diff --git a/compiler/kernel/vop.go b/compiler/kernel/vop.go index 876febe5dd..341d559f8b 100644 --- a/compiler/kernel/vop.go +++ b/compiler/kernel/vop.go @@ -5,6 +5,7 @@ import ( "github.com/brimdata/zed/compiler/ast/dag" "github.com/brimdata/zed/compiler/optimizer" + "github.com/brimdata/zed/runtime/vam/expr" vamop "github.com/brimdata/zed/runtime/vam/op" "github.com/brimdata/zed/vector" "github.com/brimdata/zed/zbuf" @@ -81,6 +82,8 @@ func (b *Builder) compileVamLeaf(o dag.Op, parent vector.Puller) (vector.Puller, } else { return nil, fmt.Errorf("internal error: unhandled dag.Summarize: %#v", o) } + case *dag.Put: + return b.compileVamPut(o, parent) case *dag.Yield: exprs, err := b.compileVamExprs(o.Exprs) if err != nil { @@ -95,6 +98,36 @@ func (b *Builder) compileVamLeaf(o dag.Op, parent vector.Puller) (vector.Puller, } } +func (b *Builder) compileVamPut(put *dag.Put, parent vector.Puller) (vector.Puller, error) { + elems := []dag.RecordElem{ + &dag.Spread{Kind: "Spread", Expr: &dag.This{Kind: "This"}}, + } + for _, a := range put.Args { + lhs, ok := a.LHS.(*dag.This) + if !ok { + return nil, fmt.Errorf("internal error: dynamic field name not yet supported in vector runtime: %#v", a.LHS) + } + elems = append(elems, newDagRecordExprForPath(lhs.Path, a.RHS).Elems...) + } + e, err := b.compileVamRecordExpr(&dag.RecordExpr{Kind: "RecordExpr", Elems: elems}) + if err != nil { + return nil, err + } + return vamop.NewYield(b.rctx.Zctx, parent, []expr.Evaluator{expr.NewPutter(b.zctx(), e)}), nil +} + +func newDagRecordExprForPath(path []string, expr dag.Expr) *dag.RecordExpr { + if len(path) > 1 { + expr = newDagRecordExprForPath(path[1:], expr) + } + return &dag.RecordExpr{ + Kind: "RecordExpr", + Elems: []dag.RecordElem{ + &dag.Field{Kind: "Field", Name: path[0], Value: expr}, + }, + } +} + func (b *Builder) compileVamSeq(seq dag.Seq, parents []vector.Puller) ([]vector.Puller, error) { for _, o := range seq { var err error diff --git a/runtime/vam/expr/coerce.go b/runtime/vam/expr/coerce.go index 8156ac26bd..c2da7450c4 100644 --- a/runtime/vam/expr/coerce.go +++ b/runtime/vam/expr/coerce.go @@ -91,8 +91,6 @@ func coerceVals(zctx *zed.Context, a, b vector.Any) (vector.Any, vector.Any, vec //return id, ok } -//XXX need to handle const here - func promoteWider(id int, val vector.Any) vector.Any { typ, err := zed.LookupPrimitiveByID(id) if err != nil { @@ -103,6 +101,14 @@ func promoteWider(id int, val vector.Any) vector.Any { return val.Promote(typ) case *vector.Uint: return val.Promote(typ) + case *vector.Const: + var zedVal zed.Value + if zed.IsSigned(id) { + zedVal = zed.NewInt(typ, val.Value().Int()) + } else { + zedVal = zed.NewUint(typ, val.Value().Uint()) + } + return vector.NewConst(zedVal, val.Len(), val.Nulls) case *vector.Dict: promoted := val.Any.(vector.Promotable).Promote(typ) return vector.NewDict(promoted, val.Index, val.Counts, val.Nulls) diff --git a/runtime/vam/expr/putter.go b/runtime/vam/expr/putter.go new file mode 100644 index 0000000000..c5f91daf07 --- /dev/null +++ b/runtime/vam/expr/putter.go @@ -0,0 +1,30 @@ +package expr + +import ( + "github.com/brimdata/zed" + "github.com/brimdata/zed/vector" +) + +// Putter adapts the behavior of recordExpr (obtained from NewRecordExpr) to +// match that of the put operator, which emits an error when an input value is +// not a record. +type Putter struct { + zctx *zed.Context + recordExpr Evaluator +} + +func NewPutter(zctx *zed.Context, recordExpr Evaluator) *Putter { + return &Putter{zctx, recordExpr} +} + +func (p *Putter) Eval(vec vector.Any) vector.Any { + return vector.Apply(false, p.eval, vec) +} + +func (p *Putter) eval(vecs ...vector.Any) vector.Any { + vec := vecs[0] + if vec.Type().Kind() != zed.RecordKind { + return vector.NewWrappedError(p.zctx, "put: not a record", vec) + } + return p.recordExpr.Eval(vec) +} diff --git a/runtime/sam/op/ztests/put-1.yaml b/runtime/ztests/op/put-1.yaml similarity index 92% rename from runtime/sam/op/ztests/put-1.yaml rename to runtime/ztests/op/put-1.yaml index 33c8f8f497..f56758a973 100644 --- a/runtime/sam/op/ztests/put-1.yaml +++ b/runtime/ztests/op/put-1.yaml @@ -1,6 +1,8 @@ # Tests a simple expression written into a new field zed: put y := x + 1 +vector: true + input: | {x:1(int32)} {x:2(int32)} diff --git a/runtime/sam/op/ztests/put-2.yaml b/runtime/ztests/op/put-2.yaml similarity index 91% rename from runtime/sam/op/ztests/put-2.yaml rename to runtime/ztests/op/put-2.yaml index cb6338b9fc..ea4e6de1c3 100644 --- a/runtime/sam/op/ztests/put-2.yaml +++ b/runtime/ztests/op/put-2.yaml @@ -1,6 +1,8 @@ # Tests a simple expression written into an existing field zed: put x := x + 1 +vector: true + input: | {x:1(int32)} {x:2(int32)} diff --git a/runtime/sam/op/ztests/put-3.yaml b/runtime/ztests/op/put-3.yaml similarity index 92% rename from runtime/sam/op/ztests/put-3.yaml rename to runtime/ztests/op/put-3.yaml index 9e25d04f49..e1259333a8 100644 --- a/runtime/sam/op/ztests/put-3.yaml +++ b/runtime/ztests/op/put-3.yaml @@ -1,6 +1,8 @@ # Tests writing a new record zed: put r2 := r +vector: true + input: | {r:{s:"hello"}} {r:{s:"world"}} diff --git a/runtime/sam/op/ztests/put-4.yaml b/runtime/ztests/op/put-4.yaml similarity index 93% rename from runtime/sam/op/ztests/put-4.yaml rename to runtime/ztests/op/put-4.yaml index 7ce5cec097..814576f593 100644 --- a/runtime/sam/op/ztests/put-4.yaml +++ b/runtime/ztests/op/put-4.yaml @@ -1,6 +1,8 @@ # Tests overwriting a primitive value with a record zed: put x := r +vector: true + input: | {x:1(int32),r:{s:"hello"}} {x:2(int32),r:{s:"world"}} diff --git a/runtime/sam/op/ztests/put-5.yaml b/runtime/ztests/op/put-5.yaml similarity index 93% rename from runtime/sam/op/ztests/put-5.yaml rename to runtime/ztests/op/put-5.yaml index 721b7f768a..b555f43300 100644 --- a/runtime/sam/op/ztests/put-5.yaml +++ b/runtime/ztests/op/put-5.yaml @@ -1,6 +1,8 @@ # Tests overwriting a record with a primitive value zed: put r := x +vector: true + input: | {x:1(int32),r:{s:"hello"}} {x:2(int32),r:{s:"world"}} diff --git a/runtime/sam/op/ztests/put-implied-1.yaml b/runtime/ztests/op/put-implied-1.yaml similarity index 88% rename from runtime/sam/op/ztests/put-implied-1.yaml rename to runtime/ztests/op/put-implied-1.yaml index 0e6b19b194..d8bb09495a 100644 --- a/runtime/sam/op/ztests/put-implied-1.yaml +++ b/runtime/ztests/op/put-implied-1.yaml @@ -1,5 +1,7 @@ zed: y := x + 1 +vector: true + input: | {x:1(int32)} {x:2(int32)} diff --git a/runtime/sam/op/ztests/put-implied-2.yaml b/runtime/ztests/op/put-implied-2.yaml similarity index 87% rename from runtime/sam/op/ztests/put-implied-2.yaml rename to runtime/ztests/op/put-implied-2.yaml index 88580f3710..fbb46f72e4 100644 --- a/runtime/sam/op/ztests/put-implied-2.yaml +++ b/runtime/ztests/op/put-implied-2.yaml @@ -1,5 +1,7 @@ zed: 'x:=upper(x), y:=lower(x)' +vector: true + input: | {x:"vAlUe1"} diff --git a/runtime/sam/op/ztests/put-multi-1.yaml b/runtime/ztests/op/put-multi-1.yaml similarity index 91% rename from runtime/sam/op/ztests/put-multi-1.yaml rename to runtime/ztests/op/put-multi-1.yaml index 8219baa8cc..c52508c041 100644 --- a/runtime/sam/op/ztests/put-multi-1.yaml +++ b/runtime/ztests/op/put-multi-1.yaml @@ -1,6 +1,8 @@ # Tests multiple output expressions zed: put a:=1, b:=2 +vector: true + input: | {x:1(int32)} {x:2(int32)} diff --git a/runtime/sam/op/ztests/put-multi-2.yaml b/runtime/ztests/op/put-multi-2.yaml similarity index 93% rename from runtime/sam/op/ztests/put-multi-2.yaml rename to runtime/ztests/op/put-multi-2.yaml index 154a775572..ac87b8f811 100644 --- a/runtime/sam/op/ztests/put-multi-2.yaml +++ b/runtime/ztests/op/put-multi-2.yaml @@ -1,6 +1,8 @@ # Test overwriting multiple fields in-order zed: put a:=b, b:=a +vector: true + input: | {a:1(int32),b:2(int32)} {a:3(int32),b:4(int32)} diff --git a/runtime/sam/op/ztests/put-multi-3.yaml b/runtime/ztests/op/put-multi-3.yaml similarity index 93% rename from runtime/sam/op/ztests/put-multi-3.yaml rename to runtime/ztests/op/put-multi-3.yaml index 241e0d18c0..51cb1d0511 100644 --- a/runtime/sam/op/ztests/put-multi-3.yaml +++ b/runtime/ztests/op/put-multi-3.yaml @@ -1,6 +1,8 @@ # Test overwriting multiple fields out of order zed: put b:=a, a:=b +vector: true + input: | {a:1(int32),b:2(int32)} {a:3(int32),b:4(int32)} diff --git a/runtime/sam/op/ztests/put-multi-4.yaml b/runtime/ztests/op/put-multi-4.yaml similarity index 93% rename from runtime/sam/op/ztests/put-multi-4.yaml rename to runtime/ztests/op/put-multi-4.yaml index ecbf12fe76..048f26a5e9 100644 --- a/runtime/sam/op/ztests/put-multi-4.yaml +++ b/runtime/ztests/op/put-multi-4.yaml @@ -2,6 +2,8 @@ # creates a new field zed: put new:=1, x:=x+1 +vector: true + input: | {x:1(int32)} {x:2(int32)} diff --git a/runtime/ztests/op/put-non-record.yaml b/runtime/ztests/op/put-non-record.yaml new file mode 100644 index 0000000000..f205713ce4 --- /dev/null +++ b/runtime/ztests/op/put-non-record.yaml @@ -0,0 +1,9 @@ +zed: put a:=1 + +vector: true + +input: | + 0 + +output: | + error({message:"put: not a record",on:0}) diff --git a/runtime/sam/op/ztests/put-null.yaml b/runtime/ztests/op/put-null.yaml similarity index 84% rename from runtime/sam/op/ztests/put-null.yaml rename to runtime/ztests/op/put-null.yaml index eda752b78e..b249a217a1 100644 --- a/runtime/sam/op/ztests/put-null.yaml +++ b/runtime/ztests/op/put-null.yaml @@ -1,5 +1,7 @@ zed: put b:=null +vector: true + input: | {a:1(int32)} diff --git a/runtime/sam/op/ztests/put-overwrite-132.yaml b/runtime/ztests/op/put-overwrite-132.yaml similarity index 95% rename from runtime/sam/op/ztests/put-overwrite-132.yaml rename to runtime/ztests/op/put-overwrite-132.yaml index b2882db857..968846da4e 100644 --- a/runtime/sam/op/ztests/put-overwrite-132.yaml +++ b/runtime/ztests/op/put-overwrite-132.yaml @@ -4,6 +4,8 @@ # and this test will need to be updated. zed: put c:=1,a:=3,b:=2 +vector: true + input: | {a:1(int32),b:2(int32),c:3(int32)} diff --git a/runtime/sam/op/ztests/put-overwrite-321.yaml b/runtime/ztests/op/put-overwrite-321.yaml similarity index 86% rename from runtime/sam/op/ztests/put-overwrite-321.yaml rename to runtime/ztests/op/put-overwrite-321.yaml index fc0b352250..0bd2cecb58 100644 --- a/runtime/sam/op/ztests/put-overwrite-321.yaml +++ b/runtime/ztests/op/put-overwrite-321.yaml @@ -1,5 +1,7 @@ zed: put a:=3,b:=2,c:=1 +vector: true + input: | {a:1(int32),b:2(int32)} diff --git a/runtime/sam/op/ztests/put-root.yaml b/runtime/ztests/op/put-root.yaml similarity index 86% rename from runtime/sam/op/ztests/put-root.yaml rename to runtime/ztests/op/put-root.yaml index b3f7add23c..1d630b5f56 100644 --- a/runtime/sam/op/ztests/put-root.yaml +++ b/runtime/ztests/op/put-root.yaml @@ -1,5 +1,7 @@ zed: yield a +vector: true + input: | {"a": {"a": "a", "b": "b"}, "b": "b"}