Skip to content

Commit e396edc

Browse files
authored
Merge pull request #33 from philandstuff/std-v16.0.0
WIP: update to standard v16.0.0
2 parents f50488f + caad2bb commit e396edc

File tree

9 files changed

+1784
-1704
lines changed

9 files changed

+1784
-1704
lines changed

binary/cbor.go

Lines changed: 17 additions & 277 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,13 @@ import (
44
"errors"
55
"fmt"
66
"io"
7-
"math"
87
"net/url"
98
"path"
109

10+
"github.com/fxamacker/cbor/v2"
1111
. "github.com/philandstuff/dhall-golang/term"
12-
"github.com/ugorji/go/codec"
1312
)
1413

15-
var cbor = newCborHandle()
16-
1714
var nameToBuiltin = map[string]Term{
1815
"Type": Type,
1916
"Kind": Kind,
@@ -502,283 +499,26 @@ func decode(decodedCbor interface{}) (Term, error) {
502499
return nil, fmt.Errorf("unimplemented while decoding %+v", decodedCbor)
503500
}
504501

505-
// a marker type for CBOR-encoding purposes
506-
type cborBox struct{ content Term }
507-
508-
var _ codec.Selfer = &cborBox{}
509-
510-
func box(expr Term) *cborBox { return &cborBox{content: expr} }
511-
512-
func (b *cborBox) CodecEncodeSelf(e *codec.Encoder) {
513-
switch val := b.content.(type) {
514-
case Var:
515-
if val.Name == "_" {
516-
e.Encode(val.Index)
517-
} else {
518-
e.Encode([]interface{}{val.Name, val.Index})
519-
}
520-
case Universe:
521-
switch val {
522-
case Type:
523-
e.Encode("Type")
524-
case Kind:
525-
e.Encode("Kind")
526-
case Sort:
527-
e.Encode("Sort")
528-
default:
529-
panic(fmt.Sprintf("unknown type %d\n", val))
530-
}
531-
case Builtin:
532-
e.Encode(string(val))
533-
case App:
534-
fn := val.Fn
535-
args := []interface{}{box(val.Arg)}
536-
for true {
537-
parentapp, ok := fn.(App)
538-
if !ok {
539-
break
540-
}
541-
fn = parentapp.Fn
542-
args = append([]interface{}{box(parentapp.Arg)}, args...)
543-
}
544-
e.Encode(append([]interface{}{0, box(fn)}, args...))
545-
546-
case Lambda:
547-
if val.Label == "_" {
548-
e.Encode([]interface{}{1, box(val.Type), box(val.Body)})
549-
} else {
550-
e.Encode([]interface{}{1, val.Label, box(val.Type), box(val.Body)})
551-
}
552-
case Pi:
553-
if val.Label == "_" {
554-
e.Encode([]interface{}{2, box(val.Type), box(val.Body)})
555-
} else {
556-
e.Encode([]interface{}{2, val.Label, box(val.Type), box(val.Body)})
557-
}
558-
case Op:
559-
e.Encode([]interface{}{3, val.OpCode, box(val.L), box(val.R)})
560-
case EmptyList:
561-
if app, ok := val.Type.(App); ok {
562-
if app.Fn == List {
563-
e.Encode([]interface{}{4, box(app.Arg)})
564-
break
565-
}
566-
}
567-
e.Encode([]interface{}{28, box(val.Type)})
568-
case NonEmptyList:
569-
output := make([]interface{}, len(val)+2)
570-
output[0] = 4
571-
output[1] = nil
572-
for i, item := range val {
573-
output[i+2] = box(item)
574-
}
575-
e.Encode(output)
576-
case Some:
577-
e.Encode([]interface{}{5, nil, box(val.Val)})
578-
case Merge:
579-
if val.Annotation != nil {
580-
e.Encode([]interface{}{6, box(val.Handler), box(val.Union), box(val.Annotation)})
581-
} else {
582-
e.Encode([]interface{}{6, box(val.Handler), box(val.Union)})
583-
}
584-
case RecordType:
585-
items := make(map[string]*cborBox)
586-
for k, v := range val {
587-
items[k] = box(v)
588-
}
589-
// we rely on the EncodeOptions having Canonical set
590-
// so that we get sorted keys in our map
591-
e.Encode([]interface{}{7, items})
592-
case RecordLit:
593-
items := make(map[string]*cborBox)
594-
for k, v := range val {
595-
items[k] = box(v)
596-
}
597-
// we rely on the EncodeOptions having Canonical set
598-
// so that we get sorted keys in our map
599-
e.Encode([]interface{}{8, items})
600-
case ToMap:
601-
if val.Type != nil {
602-
e.Encode([]interface{}{27, box(val.Record), box(val.Type)})
603-
} else {
604-
e.Encode([]interface{}{27, box(val.Record)})
605-
}
606-
case Field:
607-
e.Encode([]interface{}{9, box(val.Record), val.FieldName})
608-
case Project:
609-
output := make([]interface{}, len(val.FieldNames)+2)
610-
output[0] = 10
611-
output[1] = box(val.Record)
612-
for i, name := range val.FieldNames {
613-
output[i+2] = name
614-
}
615-
e.Encode(output)
616-
case ProjectType:
617-
e.Encode([]interface{}{
618-
10,
619-
box(val.Record),
620-
[]interface{}{
621-
box(val.Selector),
622-
}})
623-
case UnionType:
624-
items := make(map[string]*cborBox)
625-
for k, v := range val {
626-
items[k] = box(v)
627-
}
628-
// we rely on the EncodeOptions having Canonical set
629-
// so that we get sorted keys in our map
630-
e.Encode([]interface{}{11, items})
631-
case BoolLit:
632-
e.Encode(bool(val))
633-
case If:
634-
e.Encode([]interface{}{14, box(val.Cond), box(val.T), box(val.F)})
635-
case NaturalLit:
636-
e.Encode(append([]interface{}{15}, int(val)))
637-
case IntegerLit:
638-
e.Encode(append([]interface{}{16}, int(val)))
639-
case DoubleLit:
640-
// special-case values to encode as float16
641-
if float64(val) == 0.0 { // 0.0
642-
if math.Signbit(float64(val)) {
643-
e.Encode(codec.Raw([]byte{0xf9, 0x80, 0x00}))
644-
} else {
645-
e.Encode(codec.Raw([]byte{0xf9, 0x00, 0x00}))
646-
}
647-
} else if math.IsNaN(float64(val)) { // NaN
648-
e.Encode(codec.Raw([]byte{0xf9, 0x7e, 0x00}))
649-
} else if math.IsInf(float64(val), 1) { // Infinity
650-
e.Encode(codec.Raw([]byte{0xf9, 0x7c, 0x00}))
651-
} else if math.IsInf(float64(val), -1) { // -Infinity
652-
e.Encode(codec.Raw([]byte{0xf9, 0xfc, 0x00}))
653-
} else {
654-
single := float32(val)
655-
if float64(single) == float64(val) {
656-
e.Encode(single)
657-
} else {
658-
e.Encode(float64(val))
659-
}
660-
}
661-
case TextLit:
662-
output := []interface{}{18}
663-
for _, chunk := range val.Chunks {
664-
output = append(output, chunk.Prefix, box(chunk.Expr))
665-
}
666-
output = append(output, val.Suffix)
667-
e.Encode(output)
668-
case Assert:
669-
e.Encode([]interface{}{19, box(val.Annotation)})
670-
case Import:
671-
r := val.Fetchable
672-
// we have crafted the ImportMode constants to match the expected CBOR values
673-
mode := val.ImportMode
674-
switch rr := r.(type) {
675-
case EnvVar:
676-
e.Encode([]interface{}{24, val.Hash, mode, 6, string(rr)})
677-
case LocalFile:
678-
if rr.IsAbs() {
679-
toEncode := []interface{}{24, val.Hash, mode, AbsoluteImport}
680-
for _, component := range rr.PathComponents() {
681-
toEncode = append(toEncode, component)
682-
}
683-
e.Encode(toEncode)
684-
} else if rr.IsRelativeToParent() {
685-
toEncode := []interface{}{24, val.Hash, mode, ParentImport}
686-
for _, component := range rr.PathComponents() {
687-
toEncode = append(toEncode, component)
688-
}
689-
e.Encode(toEncode)
690-
} else if rr.IsRelativeToHome() {
691-
toEncode := []interface{}{24, val.Hash, mode, HomeImport}
692-
for _, component := range rr.PathComponents() {
693-
toEncode = append(toEncode, component)
694-
}
695-
e.Encode(toEncode)
696-
} else {
697-
toEncode := []interface{}{24, val.Hash, mode, HereImport}
698-
for _, component := range rr.PathComponents() {
699-
toEncode = append(toEncode, component)
700-
}
701-
e.Encode(toEncode)
702-
}
703-
case RemoteFile:
704-
var headers interface{} // unimplemented, leave as nil for now
705-
scheme := HttpsImport
706-
if rr.IsPlainHTTP() {
707-
scheme = HttpImport
708-
}
709-
toEncode := []interface{}{24, val.Hash, mode, scheme, headers, rr.Authority()}
710-
for _, component := range rr.PathComponents() {
711-
toEncode = append(toEncode, component)
712-
}
713-
toEncode = append(toEncode, rr.Query())
714-
e.Encode(toEncode)
715-
case Missing:
716-
e.Encode([]interface{}{24, nil, mode, 7})
717-
default:
718-
panic("can't happen")
719-
}
720-
case Let:
721-
output := []interface{}{25}
722-
// flatten multiple lets into one
723-
for {
724-
for _, binding := range val.Bindings {
725-
output = append(output, binding.Variable)
726-
output = append(output, box(binding.Annotation))
727-
output = append(output, box(binding.Value))
728-
}
729-
// there's probably a nicer way to do this...
730-
nextLet, ok := val.Body.(Let)
731-
if !ok {
732-
break
733-
}
734-
val = nextLet
735-
}
736-
output = append(output, box(val.Body))
737-
e.Encode(output)
738-
case Annot:
739-
e.Encode([]interface{}{26, box(val.Expr), box(val.Annotation)})
740-
default:
741-
e.Encode(b.content)
742-
}
743-
}
744-
745-
func (b *cborBox) CodecDecodeSelf(d *codec.Decoder) {
746-
var raw interface{}
747-
d.MustDecode(&raw)
748-
expr, err := decode(raw)
749-
if err != nil {
750-
panic(err)
751-
}
752-
b.content = expr
753-
}
754-
755502
// EncodeAsCbor encodes a Term as CBOR and writes it to the io.Writer
756503
func EncodeAsCbor(w io.Writer, e Term) error {
757-
enc := codec.NewEncoder(w, cbor)
758-
return enc.Encode(box(e))
504+
em, err := cbor.CanonicalEncOptions().EncMode()
505+
if err != nil {
506+
return err
507+
}
508+
return em.NewEncoder(w).Encode(e)
759509
}
760510

761511
// DecodeAsCbor decodes CBOR from the io.Reader and returns the resulting Expr
762512
func DecodeAsCbor(r io.Reader) (Term, error) {
763-
var b cborBox
764-
dec := codec.NewDecoder(r, cbor)
765-
err := dec.Decode(&b)
766-
return b.content, err
767-
}
768-
769-
func newCborHandle() *codec.CborHandle {
770-
var h codec.CborHandle
771-
h.Canonical = true
772-
h.SkipUnexpectedTags = true
773-
h.Raw = true
774-
return &h
513+
var b interface{}
514+
dm, err := cbor.DecOptions{}.DecMode()
515+
if err != nil {
516+
return nil, err
517+
}
518+
dec := dm.NewDecoder(r)
519+
err = dec.Decode(&b)
520+
if err != nil {
521+
return nil, err
522+
}
523+
return decode(b)
775524
}
776-
777-
const (
778-
HttpImport = 0
779-
HttpsImport = 1
780-
AbsoluteImport = 2
781-
HereImport = 3
782-
ParentImport = 4
783-
HomeImport = 5
784-
)

core/typecheck.go

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -710,11 +710,7 @@ func typeWith(ctx context, t term.Term) (Value, error) {
710710
}
711711
return result, nil
712712
case term.UnionType:
713-
if len(t) == 0 {
714-
return Type, nil
715-
}
716-
var c Universe
717-
first := true
713+
universe := Type
718714
for _, typ := range t {
719715
if typ == nil {
720716
// empty alternative
@@ -724,25 +720,15 @@ func typeWith(ctx context, t term.Term) (Value, error) {
724720
if err != nil {
725721
return nil, err
726722
}
727-
if first {
728-
var ok bool
729-
c, ok = k.(Universe)
730-
if !ok {
731-
return nil, mkTypeError(invalidAlternativeType)
732-
}
733-
} else {
734-
if !AlphaEquivalent(c, k) {
735-
return nil, mkTypeError(alternativeAnnotationMismatch)
736-
}
723+
u, ok := k.(Universe)
724+
if !ok {
725+
return nil, mkTypeError(invalidAlternativeType)
737726
}
738-
if c == Sort {
739-
if Eval(typ) != Kind {
740-
return nil, mkTypeError(invalidAlternativeType)
741-
}
727+
if u > universe {
728+
universe = u
742729
}
743-
first = false
744730
}
745-
return c, nil
731+
return universe, nil
746732
case term.Merge:
747733
handlerTypeVal, err := typeWith(ctx, t.Handler)
748734
if err != nil {

dhall-lang

Submodule dhall-lang updated 97 files

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
module github.com/philandstuff/dhall-golang
22

33
require (
4+
github.com/fxamacker/cbor/v2 v2.2.0
45
github.com/kr/pretty v0.1.0 // indirect
56
github.com/leanovate/gopter v0.2.5-0.20190402064358-634a59d12406
67
github.com/onsi/ginkgo v1.7.0
78
github.com/onsi/gomega v1.4.3
89
github.com/pkg/errors v0.8.1
9-
github.com/ugorji/go v1.1.5-0.20190603013658-a2c9fa250719
1010
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
1111
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect
1212
golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
22
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
3+
github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ=
4+
github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
35
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
46
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
57
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
@@ -18,8 +20,8 @@ github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
1820
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
1921
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
2022
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
21-
github.com/ugorji/go v1.1.5-0.20190603013658-a2c9fa250719 h1:UW5IeyWBDAPQ+Qu1hT/lwtxL7pP3L+ETA8WuBvvvBWU=
22-
github.com/ugorji/go v1.1.5-0.20190603013658-a2c9fa250719/go.mod h1:RaaajvHwnCbhlqWLTIB78hyPWp24YUXhQ3YXM7Hg7os=
23+
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
24+
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
2325
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
2426
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
2527
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

0 commit comments

Comments
 (0)