diff --git a/compiler/semantic/checker.go b/compiler/semantic/checker.go index e3c9a0c883..e34cde370f 100644 --- a/compiler/semantic/checker.go +++ b/compiler/semantic/checker.go @@ -9,7 +9,6 @@ import ( "github.com/brimdata/super" "github.com/brimdata/super/compiler/ast" "github.com/brimdata/super/compiler/semantic/sem" - "github.com/brimdata/super/runtime/sam/expr/agg" "github.com/brimdata/super/sup" ) @@ -1155,11 +1154,11 @@ func (c *checker) error(loc ast.Node, err error) { func (c *checker) newFuser() *fuser { //XXX "complete" option will be true when we have dual support for fusion // and static types - return &fuser{agg.NewFuser(c.t.sctx, false), c.unknown} + return &fuser{super.NewFuser(c.t.sctx, false), c.unknown} } type fuser struct { - fuser *agg.Fuser + fuser *super.Fuser unknown super.Type } diff --git a/csup/fusedtype.go b/csup/fusedtype.go index d6fbd43d14..0487eb3913 100644 --- a/csup/fusedtype.go +++ b/csup/fusedtype.go @@ -6,7 +6,6 @@ import ( "math" "github.com/brimdata/super" - "github.com/brimdata/super/runtime/sam/expr/agg" ) func FusedType(sctx *super.Context, r io.ReaderAt) (super.Type, error) { @@ -21,7 +20,7 @@ func FusedType(sctx *super.Context, r io.ReaderAt) (super.Type, error) { if _, err := s.Seek(0, io.SeekStart); err != nil { return nil, err } - fuser := agg.NewFuser(super.NewContext(), false) + fuser := super.NewFuser(super.NewContext(), false) for size > 0 { typ, n, err := readPart(sctx, r, size) if err != nil { diff --git a/csup/writer.go b/csup/writer.go index 6c65e4a558..512e5762f0 100644 --- a/csup/writer.go +++ b/csup/writer.go @@ -6,7 +6,6 @@ import ( "io" "github.com/brimdata/super" - "github.com/brimdata/super/runtime/sam/expr/agg" "github.com/brimdata/super/sio" "github.com/brimdata/super/sio/bsupio" "github.com/brimdata/super/sup" @@ -22,7 +21,7 @@ var maxObjectSize uint32 = 120_000 type Serializer struct { writer io.WriteCloser dynamic *vbuild.DynamicBuilder - fuser *agg.Fuser + fuser *super.Fuser fuserSctx *super.Context size uint64 } @@ -118,7 +117,7 @@ func (w *Serializer) finalizeObject() error { func (w *Serializer) fuse(dynamic *vector.Dynamic) { if w.fuser == nil { w.fuserSctx = super.NewContext() - w.fuser = agg.NewFuser(w.fuserSctx, false) + w.fuser = super.NewFuser(w.fuserSctx, false) } for _, vec := range dynamic.Values { typ, err := w.fuserSctx.TranslateType(vec.Type()) diff --git a/runtime/sam/expr/agg/fuser.go b/fuser.go similarity index 64% rename from runtime/sam/expr/agg/fuser.go rename to fuser.go index d0297500c0..fcee11e3ee 100644 --- a/runtime/sam/expr/agg/fuser.go +++ b/fuser.go @@ -1,28 +1,25 @@ -package agg +package super import ( "fmt" "slices" - - "github.com/brimdata/super" - "github.com/brimdata/super/sup" ) // Fuser constructs a fused supertype for all the types passed to Fuse. type Fuser struct { - sctx *super.Context + sctx *Context complete bool - typ super.Type - types map[super.Type]struct{} + typ Type + types map[Type]struct{} } // XXX this is used by type checker but I think we can use the other one -func NewFuser(sctx *super.Context, complete bool) *Fuser { - return &Fuser{sctx: sctx, complete: complete, types: make(map[super.Type]struct{})} +func NewFuser(sctx *Context, complete bool) *Fuser { + return &Fuser{sctx: sctx, complete: complete, types: make(map[Type]struct{})} } -func (f *Fuser) Fuse(t super.Type) { +func (f *Fuser) Fuse(t Type) { if _, ok := f.types[t]; ok { return } @@ -36,26 +33,26 @@ func (f *Fuser) Fuse(t super.Type) { } // Type returns the computed supertype. -func (f *Fuser) Type() super.Type { +func (f *Fuser) Type() Type { return f.typ } -func (f *Fuser) fuse(a, b super.Type) super.Type { +func (f *Fuser) fuse(a, b Type) Type { if a == b { return a } - if typ, ok := a.(*super.TypeFusion); ok { + if typ, ok := a.(*TypeFusion); ok { return f.fusion(f.fuse(typ.Type, b)) } - if typ, ok := b.(*super.TypeFusion); ok { + if typ, ok := b.(*TypeFusion); ok { return f.fusion(f.fuse(a, typ.Type)) } if isAll(a) || isAll(b) { - return super.TypeAll + return TypeAll } switch a := a.(type) { - case *super.TypeRecord: - if b, ok := b.(*super.TypeRecord); ok { + case *TypeRecord: + if b, ok := b.(*TypeRecord); ok { fields := slices.Clone(a.Fields) // First change all fields to optional that are in "a" but not in "b". for k, field := range fields { @@ -71,7 +68,7 @@ func (f *Fuser) fuse(a, b super.Type) super.Type { fields[i].Type = f.fuse(fields[i].Type, field.Type) } else { typ := f.makeOption(field.Type) - fields = append(fields, super.NewField(field.Name, typ)) + fields = append(fields, NewField(field.Name, typ)) } } fusedRec := f.sctx.MustLookupTypeRecord(fields) @@ -80,30 +77,30 @@ func (f *Fuser) fuse(a, b super.Type) super.Type { } return fusedRec } - case *super.TypeArray: - if b, ok := b.(*super.TypeArray); ok { + case *TypeArray: + if b, ok := b.(*TypeArray); ok { return f.fusion(f.sctx.LookupTypeArray(f.fuse(a.Type, b.Type))) } - case *super.TypeSet: - if b, ok := b.(*super.TypeSet); ok { + case *TypeSet: + if b, ok := b.(*TypeSet); ok { return f.fusion(f.sctx.LookupTypeSet(f.fuse(a.Type, b.Type))) } - case *super.TypeMap: - if b, ok := b.(*super.TypeMap); ok { + case *TypeMap: + if b, ok := b.(*TypeMap); ok { keyType := f.fuse(a.KeyType, b.KeyType) valType := f.fuse(a.ValType, b.ValType) return f.fusion(f.sctx.LookupTypeMap(keyType, valType)) } - case *super.TypeUnion: + case *TypeUnion: types := f.fuseIntoUnionTypes(nil, a) types = f.fuseIntoUnionTypes(types, b) if len(types) == 1 { return types[0] } - union := f.sctx.MustLookupTypeUnion(super.Flatten(types)) + union := f.sctx.MustLookupTypeUnion(Flatten(types)) return f.fusion(union) - case *super.TypeEnum: - if b, ok := b.(*super.TypeEnum); ok { + case *TypeEnum: + if b, ok := b.(*TypeEnum); ok { var newSymbols []string for _, s := range b.Symbols { if !slices.Contains(a.Symbols, s) { @@ -116,12 +113,12 @@ func (f *Fuser) fuse(a, b super.Type) super.Type { symbols := append(slices.Clone(a.Symbols), newSymbols...) return f.fusion(f.sctx.LookupTypeEnum(symbols)) } - case *super.TypeError: - if b, ok := b.(*super.TypeError); ok { + case *TypeError: + if b, ok := b.(*TypeError); ok { return f.fusion(f.sctx.LookupTypeError(f.fuse(a.Type, b.Type))) } - case *super.TypeNamed: - if b, ok := b.(*super.TypeNamed); ok && a.Name == b.Name { + case *TypeNamed: + if b, ok := b.(*TypeNamed); ok && a.Name == b.Name { // if we got here without match a=b above, then there are // two different types with the same name, which the type // context shouldn't allow. @@ -131,61 +128,61 @@ func (f *Fuser) fuse(a, b super.Type) super.Type { // a barrier to type fusion. Instead we fall through here and , // fuse the named type with the other type. } - if _, ok := b.(*super.TypeUnion); ok { + if _, ok := b.(*TypeUnion); ok { return f.fuse(b, a) } // Neither a nor b can be an anonymous union at this point. - return f.fusion(f.sctx.MustLookupTypeUnion([]super.Type{a, b})) + return f.fusion(f.sctx.MustLookupTypeUnion([]Type{a, b})) } -func (f *Fuser) makeOption(t super.Type) super.Type { - if fusion, ok := t.(*super.TypeFusion); ok { +func (f *Fuser) makeOption(t Type) Type { + if fusion, ok := t.(*TypeFusion); ok { return f.sctx.LookupTypeFusion(f.makeOption(fusion.Type)) } return f.sctx.Option(t) } -func isAll(t super.Type) bool { - _, ok := t.(*super.TypeOfAll) +func isAll(t Type) bool { + _, ok := t.(*TypeOfAll) return ok } -func (f *Fuser) redefPanic(named *super.TypeNamed) { +func (f *Fuser) redefPanic(named *TypeNamed) { previous := f.sctx.LookupByName(named.Name) - panic(fmt.Sprintf("type %s redefined: %s to %s", named.Name, sup.String(previous), sup.String(named.Type))) + panic(fmt.Sprintf("type %s redefined: %#v to %#v", named.Name, previous, named.Type)) } -func (f *Fuser) fuseInternal(typ super.Type) super.Type { - if typ, ok := typ.(*super.TypeFusion); ok { +func (f *Fuser) fuseInternal(typ Type) Type { + if typ, ok := typ.(*TypeFusion); ok { return f.fusion(f.fuseInternal(typ.Type)) } - var out super.Type + var out Type switch typ := typ.(type) { - case *super.TypeRecord: + case *TypeRecord: fields := slices.Clone(typ.Fields) for i, field := range fields { fields[i].Type = f.fuseInternal(field.Type) } out = f.sctx.MustLookupTypeRecord(fields) - case *super.TypeArray: + case *TypeArray: out = f.sctx.LookupTypeArray(f.fuseInternal(typ.Type)) - case *super.TypeSet: + case *TypeSet: out = f.sctx.LookupTypeSet(f.fuseInternal(typ.Type)) - case *super.TypeMap: + case *TypeMap: out = f.sctx.LookupTypeMap(f.fuseInternal(typ.KeyType), f.fuseInternal(typ.ValType)) - case *super.TypeUnion: - var types []super.Type + case *TypeUnion: + var types []Type for _, t := range typ.Types { types = f.fuseIntoUnionTypes(types, f.fuseInternal(t)) } if len(types) == 1 { out = types[0] } else { - out = f.sctx.MustLookupTypeUnion(super.Flatten(types)) + out = f.sctx.MustLookupTypeUnion(Flatten(types)) } - case *super.TypeEnum: + case *TypeEnum: return typ - case *super.TypeError: + case *TypeError: out = f.sctx.LookupTypeError(f.fuseInternal(typ.Type)) default: out = typ @@ -198,16 +195,16 @@ func (f *Fuser) fuseInternal(typ super.Type) super.Type { // fuseIntoUnionTypes fuses typ into types while maintaining the invariant that // types contains at most one type of each complex kind but no unions. -func (f *Fuser) fuseIntoUnionTypes(types []super.Type, typ super.Type) []super.Type { +func (f *Fuser) fuseIntoUnionTypes(types []Type, typ Type) []Type { switch typ := typ.(type) { - case *super.TypeNamed: + case *TypeNamed: return f.addNamed(types, typ) - case *super.TypeUnion: + case *TypeUnion: for _, t := range typ.Types { types = f.fuseIntoUnionTypes(types, t) } return types - case *super.TypeFusion: + case *TypeFusion: return f.fuseIntoUnionTypes(types, typ.Type) } typKind := typ.Kind() @@ -216,7 +213,7 @@ func (f *Fuser) fuseIntoUnionTypes(types []super.Type, typ super.Type) []super.T case t == typ: // This is already in the union. return types - case typKind != super.PrimitiveKind && typKind == t.Kind() && !super.IsTypeNamed(t): + case typKind != PrimitiveKind && typKind == t.Kind() && !IsTypeNamed(t): types[i] = noFusion(f.fuse(t, typ)) return types } @@ -224,9 +221,9 @@ func (f *Fuser) fuseIntoUnionTypes(types []super.Type, typ super.Type) []super.T return append(types, noFusion(typ)) } -func (f *Fuser) addNamed(types []super.Type, named *super.TypeNamed) []super.Type { +func (f *Fuser) addNamed(types []Type, named *TypeNamed) []Type { for _, t := range types { - if existingNamed, ok := t.(*super.TypeNamed); ok && existingNamed.Name == named.Name { + if existingNamed, ok := t.(*TypeNamed); ok && existingNamed.Name == named.Name { if existingNamed.Type != named.Type { f.redefPanic(named) } @@ -236,24 +233,24 @@ func (f *Fuser) addNamed(types []super.Type, named *super.TypeNamed) []super.Typ return append(types, named) } -func noFusion(typ super.Type) super.Type { - if s, ok := typ.(*super.TypeFusion); ok { +func noFusion(typ Type) Type { + if s, ok := typ.(*TypeFusion); ok { return s.Type } return typ } -func (f *Fuser) fusion(typ super.Type) super.Type { +func (f *Fuser) fusion(typ Type) Type { if !f.complete { return typ } - if typ, ok := typ.(*super.TypeFusion); ok { + if typ, ok := typ.(*TypeFusion); ok { return typ } return f.sctx.LookupTypeFusion(typ) } -func indexOfField(fields []super.Field, name string) (int, bool) { +func indexOfField(fields []Field, name string) (int, bool) { for i, f := range fields { if f.Name == name { return i, true @@ -267,13 +264,13 @@ func indexOfField(fields []super.Field, name string) (int, bool) { // As long as all the fields names and optionality are the same, then // any type differences in the fused type of the child fields will be // captured by a fusion wrapper somewhere in the descendent type. -func recChanged(a, b *super.TypeRecord) bool { +func recChanged(a, b *TypeRecord) bool { if len(a.Fields) != len(b.Fields) { return true } for k, af := range a.Fields { bf := b.Fields[k] - if af.Name != bf.Name || super.IsOptionType(af.Type) != super.IsOptionType(bf.Type) { + if af.Name != bf.Name || IsOptionType(af.Type) != IsOptionType(bf.Type) { return true } } diff --git a/runtime/sam/expr/agg/fuser_test.go b/fuser_test.go similarity index 82% rename from runtime/sam/expr/agg/fuser_test.go rename to fuser_test.go index d210d49831..82cc3baa54 100644 --- a/runtime/sam/expr/agg/fuser_test.go +++ b/fuser_test.go @@ -1,4 +1,4 @@ -package agg +package super_test import ( "testing" @@ -8,7 +8,7 @@ import ( ) func TestFuserSamePrimitiveTypeTwice(t *testing.T) { - s := NewFuser(super.NewContext(), false) + s := super.NewFuser(super.NewContext(), false) typ := super.TypeInt64 s.Fuse(typ) s.Fuse(typ) diff --git a/runtime/sam/expr/agg/fuse.go b/runtime/sam/expr/agg/fuse.go index b6494d120d..0cabc8a2f0 100644 --- a/runtime/sam/expr/agg/fuse.go +++ b/runtime/sam/expr/agg/fuse.go @@ -31,7 +31,7 @@ func (f *fuse) Result(sctx *super.Context) super.Value { if len(f.shapes)+len(f.partials) == 0 { return super.Null } - fuser := NewFuser(sctx, f.complete) + fuser := super.NewFuser(sctx, f.complete) for _, p := range f.partials { typ, err := sctx.LookupByValue(p.Bytes()) if err != nil { diff --git a/runtime/vam/expr/agg/fuse.go b/runtime/vam/expr/agg/fuse.go index ee4f65c2a0..e655c4998f 100644 --- a/runtime/vam/expr/agg/fuse.go +++ b/runtime/vam/expr/agg/fuse.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/brimdata/super" - samagg "github.com/brimdata/super/runtime/sam/expr/agg" "github.com/brimdata/super/vector" ) @@ -54,7 +53,7 @@ func (f *fuse) Result(sctx *super.Context) vector.Any { if len(f.types)+len(f.partials) == 0 { return vector.NewNull(1) } - fuser := samagg.NewFuser(sctx, f.complete) + fuser := super.NewFuser(sctx, f.complete) for _, p := range f.partials { typ, err := sctx.LookupByValue(p.Bytes()) if err != nil { diff --git a/runtime/vam/op/fuse.go b/runtime/vam/op/fuse.go index e9cdaad6ce..0989f77dbb 100644 --- a/runtime/vam/op/fuse.go +++ b/runtime/vam/op/fuse.go @@ -2,7 +2,6 @@ package op import ( "github.com/brimdata/super" - samagg "github.com/brimdata/super/runtime/sam/expr/agg" "github.com/brimdata/super/runtime/vam/expr" "github.com/brimdata/super/runtime/vam/expr/function" "github.com/brimdata/super/sup" @@ -15,7 +14,7 @@ type Fuse struct { parent vio.Puller complete bool - fuser *samagg.Fuser + fuser *super.Fuser vecs []vector.Any upcaster *function.Upcast defuser *expr.Defuse @@ -38,7 +37,7 @@ func (f *Fuse) Pull(done bool) (vector.Any, error) { return f.parent.Pull(done) } if f.fuser == nil { - f.fuser = samagg.NewFuser(f.sctx, f.complete) + f.fuser = super.NewFuser(f.sctx, f.complete) for { vec, err := f.parent.Pull(false) if err != nil { diff --git a/sio/anyio/file.go b/sio/anyio/file.go index d664cc962a..1edffa577c 100644 --- a/sio/anyio/file.go +++ b/sio/anyio/file.go @@ -7,7 +7,6 @@ import ( "github.com/brimdata/super" "github.com/brimdata/super/pkg/storage" - "github.com/brimdata/super/runtime/sam/expr/agg" "github.com/brimdata/super/sbuf" "github.com/brimdata/super/sio" ) @@ -94,7 +93,7 @@ func FileType(ctx context.Context, sctx *super.Context, engine storage.Engine, p } // XXX this should pass super true when type checker can handle it rr := sbuf.PullerReader(sbuf.NewMaterializer(f)) - fuser := agg.NewFuser(sctx, false) + fuser := super.NewFuser(sctx, false) for range sampleSize { val, err := rr.Read() if val == nil || err != nil {