diff --git a/book/src/super-sql/declarations/pragmas.md b/book/src/super-sql/declarations/pragmas.md index 2e5762c6ed..94da860103 100644 --- a/book/src/super-sql/declarations/pragmas.md +++ b/book/src/super-sql/declarations/pragmas.md @@ -46,7 +46,7 @@ values { "bar" [1,2,3] # expected output -{a:"a",b:error("missing")} +{a:"a",b:error({message:"value cannot be indexed",on:"bar"})} {a:[2],b:1} ``` diff --git a/book/src/super-sql/expressions/index.md b/book/src/super-sql/expressions/index.md index 699fd9deb1..d5c87330f9 100644 --- a/book/src/super-sql/expressions/index.md +++ b/book/src/super-sql/expressions/index.md @@ -32,7 +32,7 @@ value in the set of that index ordered by total order of values. If `` is a map, then the `` operand is presumed to be a key and the corresponding value for that key is the result of the operation. If no such key exists in the map, then -the result is `error("missing")`. +the result is `none`. If `` is a string, then the `` operand must be coercible to an integer and the result is an integer representing @@ -75,8 +75,8 @@ values a[2] # expected output 3 3 -error("missing") -error("missing") +error({message:"value cannot be indexed",on:"1234"}) +error({message:"value cannot be indexed",on:0x01020304}) ``` --- @@ -95,8 +95,8 @@ values a[2] # expected output 2 2 -error("missing") -error("missing") +error({message:"value cannot be indexed",on:"1234"}) +error({message:"value cannot be indexed",on:0x01020304}) ``` --- @@ -114,6 +114,6 @@ values a[-1] # expected output 4 4 -error("missing") -error("missing") +error({message:"value cannot be indexed",on:"1234"}) +error({message:"value cannot be indexed",on:0x01020304}) ``` diff --git a/book/src/super-sql/functions/types/nameof.md b/book/src/super-sql/functions/types/nameof.md index ce2b3111d9..37387f55be 100644 --- a/book/src/super-sql/functions/types/nameof.md +++ b/book/src/super-sql/functions/types/nameof.md @@ -11,7 +11,7 @@ nameof(val: any) -> string ## Description The `nameof` function returns the type name of `val` as a string if `val` is a named type. -Otherwise, it returns `error("missing")`. +Otherwise, it returns an error. ## Examples @@ -28,5 +28,5 @@ type port=int16 80 # expected output "port" -error("missing") +error({message:"nameof: not a type",on:80}) ``` diff --git a/book/src/super-sql/functions/types/typename.md b/book/src/super-sql/functions/types/typename.md index c11cbcea68..2945147907 100644 --- a/book/src/super-sql/functions/types/typename.md +++ b/book/src/super-sql/functions/types/typename.md @@ -12,7 +12,7 @@ typename(name: string) -> type The `typename` function returns the [type](../../types/intro.md) of the [named type](../../types/named.md) given by `name` if it exists. Otherwise, -`error("missing")` is returned. +an error is returned. ## Examples @@ -48,7 +48,7 @@ type port=int16 --- -_The result is `error("missing")` if the type name does not exist_ +_The result is an error if the type name does not exist_ ```mdtest-spq # spq @@ -56,5 +56,5 @@ values typename("port") # input 80 # expected output -error("missing") +error({message:"typename: unknown type name",on:"port"}) ``` diff --git a/compiler/rungen/op.go b/compiler/rungen/op.go index e371fe606a..88ee710adf 100644 --- a/compiler/rungen/op.go +++ b/compiler/rungen/op.go @@ -306,11 +306,10 @@ func (b *Builder) evalAtCompileTime(in dag.Expr) (val super.Value, err error) { // reference to a var not in scope, a field access null this, etc. defer func() { if recover() != nil { - val = b.sctx().Missing() + val = b.sctx().NewErrorf("evalAtCompileTime") } }() - missingVec := vector.NewMissing(b.sctx(), 1) - vec := e.Eval(missingVec) + vec := e.Eval(vector.NewStringError(b.sctx(), "evalAtCompileTime", 1)) if vec.Len() != 1 { panic(vector.Format(vec)) } diff --git a/compiler/semantic/op.go b/compiler/semantic/op.go index dc62c1ccc2..1894e22b91 100644 --- a/compiler/semantic/op.go +++ b/compiler/semantic/op.go @@ -241,7 +241,7 @@ func (t *translator) fromConst(val super.Value, entity *ast.FromEval, args []ast } names := make([]string, 0, len(vals)) for _, val := range vals { - if super.TypeUnder(val.Type()) != super.TypeString { + if !hasString(val.Type()) { t.error(entity.Expr, fmt.Errorf("from expression requires a string but encountered %s", sup.String(val))) return sem.Seq{badOp}, "" } diff --git a/runtime/vam/expr/dot.go b/runtime/vam/expr/dot.go index 6db9cb32b1..0c53fdb8de 100644 --- a/runtime/vam/expr/dot.go +++ b/runtime/vam/expr/dot.go @@ -70,8 +70,7 @@ func (d *DotExpr) eval(vecs ...vector.Any) vector.Any { errs = append(errs, i) } if len(errs) > 0 { - //XXX need to build error vector above with each field-missing message - return vector.Combine(typvals, errs, vector.NewMissing(d.sctx, uint32(len(errs)))) + return vector.NewCombinedError(d.sctx, fmt.Sprintf("no such field %s", sup.QuotedName(d.field)), typvals, val, errs) } return typvals case *vector.Map: diff --git a/runtime/vam/expr/function/types.go b/runtime/vam/expr/function/types.go index 695c7b9535..2eb9699ce2 100644 --- a/runtime/vam/expr/function/types.go +++ b/runtime/vam/expr/function/types.go @@ -132,7 +132,7 @@ func (n *NameOf) Call(args ...vector.Any) vector.Any { return vector.NewConstString(named.Name, vec.Len()) } if typ.ID() != super.IDType { - return vector.NewMissing(n.sctx, vec.Len()) + return vector.NewWrappedError(n.sctx, "nameof: not a type", vec) } out := vector.NewStringEmpty(vec.Len()) var errs []uint32 @@ -145,7 +145,7 @@ func (n *NameOf) Call(args ...vector.Any) vector.Any { } } if len(errs) > 0 { - return vector.Combine(out, errs, vector.NewMissing(n.sctx, uint32(len(errs)))) + return vector.NewCombinedError(n.sctx, "nameof: not a named type", out, vec, errs) } return out } @@ -180,7 +180,7 @@ func (t *TypeName) Call(args ...vector.Any) vector.Any { } } if len(errs) > 0 { - return vector.Combine(out, errs, vector.NewMissing(t.sctx, uint32(len(errs)))) + return vector.NewCombinedError(t.sctx, "typename: unknown type name", out, vec, errs) } return out } diff --git a/runtime/vam/expr/index.go b/runtime/vam/expr/index.go index 058cf9a24d..241f221b0d 100644 --- a/runtime/vam/expr/index.go +++ b/runtime/vam/expr/index.go @@ -35,7 +35,7 @@ func (i *Index) eval(args ...vector.Any) vector.Any { case vector.KindMap: return indexMap(i.sctx, container, index) default: - return vector.NewMissing(i.sctx, container.Len()) + return vector.NewWrappedError(i.sctx, "value cannot be indexed", container) } } @@ -78,7 +78,7 @@ func indexArrayOrSet(sctx *super.Context, vec, indexVec vector.Any, base1 bool) } out := vector.Pick(vector.Deunion(vals), viewIndexes) if len(errs) > 0 { - return vector.Combine(out, errs, vector.NewMissing(sctx, uint32(len(errs)))) + return vector.NewCombinedError(sctx, "index out of range", out, indexVec, errs) } return out } @@ -109,7 +109,7 @@ func indexRecord(sctx *super.Context, vec, indexVec vector.Any, base1 bool) vect default: panic(vec) } - var errcnt uint32 + var errs []uint32 tags := make([]uint32, vec.Len()) n := len(rec.Typ.Fields) viewIndexes := make([][]uint32, n) @@ -131,7 +131,7 @@ func indexRecord(sctx *super.Context, vec, indexVec vector.Any, base1 bool) vect } if k < 0 || k >= n { tags[i] = uint32(n) - errcnt++ + errs = append(errs, i) continue } idx := i @@ -142,9 +142,9 @@ func indexRecord(sctx *super.Context, vec, indexVec vector.Any, base1 bool) vect viewIndexes[k] = append(viewIndexes[k], idx) } out := make([]vector.Any, n+1) - out[n] = vector.NewMissing(sctx, errcnt) + out[n] = vector.NewWrappedError(sctx, "invalid record index", vector.NewView(indexVec, errs)) for i, field := range rec.Fields { - out[i] = vector.DeoptionWithNone(sctx, vector.Pick(field, viewIndexes[i])) + out[i] = vector.Pick(field, viewIndexes[i]) } return vector.NewDynamic(tags, out) } @@ -161,7 +161,7 @@ func indexMap(sctx *super.Context, vec, indexVec vector.Any) vector.Any { pick = append(pick, i) } } - var valIndexes, errs []uint32 + var valIndexes, nones []uint32 cmp := NewCompare(sctx, "==", nil, nil).eval hits := vector.Apply(vector.ApplyRipFusions|vector.ApplyRipUnions, cmp, vector.Pick(indexVec, pick), m.Keys) bits := FlattenBool(hits).Bits @@ -176,12 +176,12 @@ func indexMap(sctx *super.Context, vec, indexVec vector.Any) vector.Any { if selected != -1 { valIndexes = append(valIndexes, uint32(selected)) } else { - errs = append(errs, i) + nones = append(nones, i) } } vals := vector.Pick(vector.Deunion(m.Values), valIndexes) - if len(errs) > 0 { - return vector.Combine(vals, errs, vector.NewMissing(sctx, uint32(len(errs)))) + if len(nones) > 0 { + return vector.Combine(vals, nones, vector.NewNone(uint32(len(nones)))) } return vals } diff --git a/runtime/vcache/bool.go b/runtime/vcache/bool.go index a734c860c4..f2657e8265 100644 --- a/runtime/vcache/bool.go +++ b/runtime/vcache/bool.go @@ -27,10 +27,11 @@ func (b *bool_) length() uint32 { func (*bool_) unmarshal(*csup.Context, field.Projection) {} func (b *bool_) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewBool(b.load(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, b.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewBool(b.load(loader)) + return vec } func (b *bool_) load(loader *loader) bitvec.Bits { diff --git a/runtime/vcache/bytes.go b/runtime/vcache/bytes.go index 80b1dd02ba..72603b8b1d 100644 --- a/runtime/vcache/bytes.go +++ b/runtime/vcache/bytes.go @@ -27,18 +27,20 @@ func (b *bytes) length() uint32 { func (*bytes) unmarshal(*csup.Context, field.Projection) {} func (b *bytes) project(loader *loader, projection field.Projection) vector.Any { - if len(projection) > 0 { - return vector.NewMissing(loader.sctx, b.length()) - } + var vec vector.Any table := b.load(loader) switch b.meta.Typ.ID() { case super.IDString: - return vector.NewString(table) + vec = vector.NewString(table) case super.IDBytes: - return vector.NewBytes(table) + vec = vector.NewBytes(table) default: panic(b.meta.Typ) } + if len(projection) > 0 { + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) + } + return vec } func (b *bytes) load(loader *loader) vector.BytesTable { diff --git a/runtime/vcache/const.go b/runtime/vcache/const.go index c3933f6160..a46c78f936 100644 --- a/runtime/vcache/const.go +++ b/runtime/vcache/const.go @@ -23,9 +23,6 @@ func (c *const_) length() uint32 { func (*const_) unmarshal(*csup.Context, field.Projection) {} func (c *const_) project(loader *loader, projection field.Projection) vector.Any { - if len(projection) > 0 { - return vector.NewMissing(loader.sctx, c.length()) - } // Map the const super.Value in the csup's type context to // a new one in the query type context. val := c.meta.Value @@ -36,5 +33,9 @@ func (c *const_) project(loader *loader, projection field.Projection) vector.Any if err != nil { panic(err) } - return vector.NewConstFromValue(loader.sctx, super.NewValue(typ, val.Bytes()), c.length()) + vec := vector.NewConstFromValue(loader.sctx, super.NewValue(typ, val.Bytes()), c.length()) + if len(projection) > 0 { + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) + } + return vec } diff --git a/runtime/vcache/dict.go b/runtime/vcache/dict.go index 3bef2d7968..06cc57f6a3 100644 --- a/runtime/vcache/dict.go +++ b/runtime/vcache/dict.go @@ -35,11 +35,12 @@ func (d *dict) unmarshal(cctx *csup.Context, projection field.Projection) { } func (d *dict) project(loader *loader, projection field.Projection) vector.Any { + index, counts := d.load(loader) + vec := vector.NewDict(d.values.project(loader, projection), index, counts) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, d.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - index, counts := d.load(loader) - return vector.NewDict(d.values.project(loader, projection), index, counts) + return vec } func (d *dict) load(loader *loader) ([]byte, []uint32) { diff --git a/runtime/vcache/float.go b/runtime/vcache/float.go index d5e10b52aa..e3a6aa2fe8 100644 --- a/runtime/vcache/float.go +++ b/runtime/vcache/float.go @@ -27,10 +27,11 @@ func (f *float) length() uint32 { func (*float) unmarshal(*csup.Context, field.Projection) {} func (f *float) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewFloat(f.meta.Typ, f.load(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, f.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewFloat(f.meta.Typ, f.load(loader)) + return vec } func (f *float) load(loader *loader) []float64 { diff --git a/runtime/vcache/int.go b/runtime/vcache/int.go index 2ab8509d5d..c68b3fd989 100644 --- a/runtime/vcache/int.go +++ b/runtime/vcache/int.go @@ -28,10 +28,11 @@ func (i *int_) length() uint32 { func (*int_) unmarshal(*csup.Context, field.Projection) {} func (i *int_) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewInt(i.meta.Typ, i.load(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, i.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewInt(i.meta.Typ, i.load(loader)) + return vec } func (i *int_) load(loader *loader) []int64 { diff --git a/runtime/vcache/ip.go b/runtime/vcache/ip.go index aaafb1d034..8bbc82eeeb 100644 --- a/runtime/vcache/ip.go +++ b/runtime/vcache/ip.go @@ -26,10 +26,11 @@ func (i *ip) length() uint32 { func (*ip) unmarshal(*csup.Context, field.Projection) {} func (i *ip) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewIP(i.load(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, i.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewIP(i.load(loader)) + return vec } func (i *ip) load(loader *loader) []netip.Addr { diff --git a/runtime/vcache/net.go b/runtime/vcache/net.go index 52af85a28e..0361f3a0d6 100644 --- a/runtime/vcache/net.go +++ b/runtime/vcache/net.go @@ -26,10 +26,11 @@ func (n *net) length() uint32 { func (*net) unmarshal(*csup.Context, field.Projection) {} func (n *net) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewNet(n.load(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, n.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewNet(n.load(loader)) + return vec } func (n *net) load(loader *loader) []netip.Prefix { diff --git a/runtime/vcache/none.go b/runtime/vcache/none.go index 513ea4c4db..4a9e80161d 100644 --- a/runtime/vcache/none.go +++ b/runtime/vcache/none.go @@ -21,8 +21,9 @@ func (n *none) length() uint32 { func (*none) unmarshal(*csup.Context, field.Projection) {} func (n *none) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewNone(n.meta.Count) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, n.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewNone(n.meta.Count) + return vec } diff --git a/runtime/vcache/null.go b/runtime/vcache/null.go index b4f05bc79c..661ab6c6d7 100644 --- a/runtime/vcache/null.go +++ b/runtime/vcache/null.go @@ -21,8 +21,9 @@ func (n *null) length() uint32 { func (*null) unmarshal(*csup.Context, field.Projection) {} func (n *null) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewNull(n.meta.Count) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, n.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewNull(n.meta.Count) + return vec } diff --git a/runtime/vcache/record.go b/runtime/vcache/record.go index d895a44c0d..e284d0ccc0 100644 --- a/runtime/vcache/record.go +++ b/runtime/vcache/record.go @@ -1,12 +1,14 @@ package vcache import ( + "fmt" "slices" "sync" "github.com/brimdata/super" "github.com/brimdata/super/csup" "github.com/brimdata/super/pkg/field" + "github.com/brimdata/super/sup" "github.com/brimdata/super/vector" ) @@ -74,7 +76,7 @@ func (r *record) project(loader *loader, projection field.Projection) vector.Any if k := indexOfField(node.Name, r.meta); k >= 0 && r.fields[k] != nil { val = r.fields[k].project(loader, node.Proj) } else { - val = vector.NewMissing(loader.sctx, r.length()) + val = vector.NewStringError(loader.sctx, fmt.Sprintf("no such field %s", sup.QuotedName(node.Name)), r.length()) } valFields = append(valFields, val) fields = append(fields, super.NewField(node.Name, val.Type())) diff --git a/runtime/vcache/type.go b/runtime/vcache/type.go index 9b6c5aed38..7853ca0625 100644 --- a/runtime/vcache/type.go +++ b/runtime/vcache/type.go @@ -33,10 +33,11 @@ func (t *typevalue) length() uint32 { func (*typevalue) unmarshal(*csup.Context, field.Projection) {} func (t *typevalue) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewTypeValueWithLoader(loader.sctx, t.newLoader(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, t.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewTypeValueWithLoader(loader.sctx, t.newLoader(loader)) + return vec } func (t *typevalue) newLoader(loader *loader) *typesLoader { diff --git a/runtime/vcache/uint.go b/runtime/vcache/uint.go index 910fbcf128..b64d7faca9 100644 --- a/runtime/vcache/uint.go +++ b/runtime/vcache/uint.go @@ -28,10 +28,11 @@ func (u *uint_) length() uint32 { func (*uint_) unmarshal(*csup.Context, field.Projection) {} func (u *uint_) project(loader *loader, projection field.Projection) vector.Any { + vec := vector.NewUint(u.meta.Typ, u.load(loader)) if len(projection) > 0 { - return vector.NewMissing(loader.sctx, u.length()) + return vector.NewWrappedError(loader.sctx, "'.': applied to non-record", vec) } - return vector.NewUint(u.meta.Typ, u.load(loader)) + return vec } func (u *uint_) load(loader *loader) []uint64 { diff --git a/runtime/vcache/ztests/projection.yaml b/runtime/vcache/ztests/projection.yaml index 3b63ac4d8a..2294e05b9d 100644 --- a/runtime/vcache/ztests/projection.yaml +++ b/runtime/vcache/ztests/projection.yaml @@ -9,6 +9,9 @@ script: | super dev vector project -s test.csup s x echo === super dev vector project -s test.csup y w.y + echo === + echo '1 2 3' | super -f csup -o test2.csup - + super dev vector project -s test2.csup x inputs: - name: stdin data: | @@ -20,32 +23,36 @@ inputs: outputs: - name: stdout data: | - {x:1,y:2,z:error("missing")} - {x:3,y:4,z:error("missing")} - {x:3,y:4,z:error("missing")} - {x:3,y:4,z:error("missing")} - {x:error("missing"),y:error("missing"),z:error("missing")} + {x:1,y:2,z:error("no such field z")} + {x:3,y:4,z:error("no such field z")} + {x:3,y:4,z:error("no such field z")} + {x:3,y:4,z:error("no such field z")} + {x:error("no such field x"),y:error("no such field y"),z:error("no such field z")} === {s:"foo"} - {s:error("missing")} + {s:error("no such field s")} {s:"bar"} - {s:error("missing")} + {s:error("no such field s")} {s:"baz"} === {x:1,s:"foo"} - {x:3,s:error("missing")} + {x:3,s:error("no such field s")} {x:3,s:"bar"} - {x:3,s:error("missing")} - {x:error("missing"),s:"baz"} + {x:3,s:error("no such field s")} + {x:error("no such field x"),s:"baz"} === {s:"foo",x:1} - {s:error("missing"),x:3} + {s:error("no such field s"),x:3} {s:"bar",x:3} - {s:error("missing"),x:3} - {s:"baz",x:error("missing")} + {s:error("no such field s"),x:3} + {s:"baz",x:error("no such field x")} + === + {y:2,w:error("no such field w")} + {y:4,w:error("no such field w")} + {y:4,w:error("no such field w")} + {y:4,w:error("no such field w")} + {y:error("no such field y"),w:{y:5}} === - {y:2,w:error("missing")} - {y:4,w:error("missing")} - {y:4,w:error("missing")} - {y:4,w:error("missing")} - {y:error("missing"),w:{y:5}} + error({message:"'.': applied to non-record",on:1}) + error({message:"'.': applied to non-record",on:2}) + error({message:"'.': applied to non-record",on:3}) diff --git a/runtime/ztests/expr/dot-record-type.yaml b/runtime/ztests/expr/dot-record-type.yaml index 0a56b53b0c..24e0cb5ed0 100644 --- a/runtime/ztests/expr/dot-record-type.yaml +++ b/runtime/ztests/expr/dot-record-type.yaml @@ -9,9 +9,9 @@ input: | output: | <{bar:int64}> - error("missing") - error({message:"'.': applied to non-record",on:error("missing")}) + error({message:"no such field foo",on:}) + error({message:"'.': applied to non-record",on:error({message:"no such field foo",on:})}) - error("missing") + error({message:"no such field bar",on:}) error({message:"'.': applied to non-record",on:null}) error({message:"'.': applied to non-record",on:error({message:"'.': applied to non-record",on:null})}) diff --git a/runtime/ztests/expr/function/nameof.yaml b/runtime/ztests/expr/function/nameof.yaml index eda05c4d44..6e971161aa 100644 --- a/runtime/ztests/expr/function/nameof.yaml +++ b/runtime/ztests/expr/function/nameof.yaml @@ -20,15 +20,15 @@ input: | null::(int64|null) output: | - error("missing") + error({message:"nameof: not a type",on:{x:1}}) "foo1" "foo2" "foo3" "bar1" - error("missing") - error("missing") + error({message:"nameof: not a type",on:{y:1}}) + error({message:"nameof: not a type",on:{x:"foo",y:1,z:2}}) "bar2" - error("missing") - error("missing") - error("missing") - error("missing") + error({message:"nameof: not a named type",on:<{x:string,y:int64,z:int64}>}) + error({message:"nameof: not a type",on:null}) + error({message:"nameof: not a type",on:1}) + error({message:"nameof: not a type",on:null}) diff --git a/runtime/ztests/expr/function/typename.yaml b/runtime/ztests/expr/function/typename.yaml index 4a4d0574bf..c5876fc9b4 100644 --- a/runtime/ztests/expr/function/typename.yaml +++ b/runtime/ztests/expr/function/typename.yaml @@ -9,5 +9,5 @@ input: | output: | type port=int16 - error("missing") + error({message:"typename: unknown type name",on:"doesnotexit"}) error({message:"typename: argument must be a string",on:1}) diff --git a/runtime/ztests/expr/index.yaml b/runtime/ztests/expr/index.yaml index 44acea3f59..0c34afd208 100644 --- a/runtime/ztests/expr/index.yaml +++ b/runtime/ztests/expr/index.yaml @@ -38,8 +38,8 @@ output: | 2 1 null - error("missing") - error("missing") + error({message:"index out of range",on:-5}) + error({message:"value cannot be indexed",on:null}) error({message:"index is not an integer",on:null}) error({message:"index is not an integer",on:"hi"}) error({message:"cannot cast to int64",on:9223372036854775808::uint64}) @@ -47,7 +47,7 @@ output: | 2 1 null - error("missing") + error({message:"index out of range",on:-5}) error({message:"index is not an integer",on:"hi"}) "foo" "baz" @@ -55,11 +55,11 @@ output: | "foo" "bar" error({message:"invalid value for record index",on:1.}) - error("missing") + error({message:"invalid record index",on:"doesnotexist"}) 1 2 1 - error("missing") + none 127.0.0.1 --- @@ -107,8 +107,8 @@ output: | type bar=set[int64] error({message:"'.': applied to non-record",on:set[4,5,6]::bar}) "foo" - error("missing") - error("missing") + none + error({message:"invalid record index",on:1}) 123 --- @@ -120,8 +120,6 @@ input: | {val:fusion(2::(int64|[int64|{r:int64}]),)} {val:fusion([1,{r:3}]::(int64|[int64|{r:int64}]),<[int64|{r:int64}]>)} -# XXX fix this should not be error missing... should be structured - output: | - error({message:"'.': applied to non-record",on:error("missing")}) + error({message:"'.': applied to non-record",on:error({message:"value cannot be indexed",on:2})}) 3 diff --git a/runtime/ztests/expr/optional-fields.yaml b/runtime/ztests/expr/optional-fields.yaml index 6c07f48395..83d5e37162 100644 --- a/runtime/ztests/expr/optional-fields.yaml +++ b/runtime/ztests/expr/optional-fields.yaml @@ -80,8 +80,8 @@ output: | 1 2 3 - "foo" - none + "foo"::(string|none) + none::(string|none) --- diff --git a/runtime/ztests/expr/slice.yaml b/runtime/ztests/expr/slice.yaml index 962cd8ab37..1dc6e665b0 100644 --- a/runtime/ztests/expr/slice.yaml +++ b/runtime/ztests/expr/slice.yaml @@ -17,10 +17,10 @@ output: | {a1:0x,a2:0x,a3:0x,a4:0x,a5:0x,a6:0x,a7:0x,a8:null} {a1:"",a2:"",a3:"",a4:"",a5:"",a6:"",a7:"",a8:null} {a1:[]::[int32],a2:[]::[int32],a3:[]::[int32],a4:[]::[int32],a5:[]::[int32],a6:[]::[int32],a7:[]::[int32],a8:null} - {a1:0x1122,a2:0x112233,a3:0x00,a4:0x001122,a5:0x,a6:0x33,a7:0x22,a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error("missing")})})} - {a1:"12",a2:"123",a3:"0",a4:"012",a5:"",a6:"3",a7:"2",a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error("missing")})})} - {a1:"ⁱ⁲",a2:"ⁱ⁲3",a3:"0",a4:"0ⁱ⁲",a5:"",a6:"3",a7:"⁲",a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error("missing")})})} - {a1:"ⁱ⁲",a2:"ⁱ⁲⁳",a3:"⁰",a4:"⁰ⁱ⁲",a5:"",a6:"⁳",a7:"⁲",a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error("missing")})})} + {a1:0x1122,a2:0x112233,a3:0x00,a4:0x001122,a5:0x,a6:0x33,a7:0x22,a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error({message:"value cannot be indexed",on:0x00112233})})})} + {a1:"12",a2:"123",a3:"0",a4:"012",a5:"",a6:"3",a7:"2",a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error({message:"value cannot be indexed",on:"0123"})})})} + {a1:"ⁱ⁲",a2:"ⁱ⁲3",a3:"0",a4:"0ⁱ⁲",a5:"",a6:"3",a7:"⁲",a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error({message:"value cannot be indexed",on:"0ⁱ⁲3"})})})} + {a1:"ⁱ⁲",a2:"ⁱ⁲⁳",a3:"⁰",a4:"⁰ⁱ⁲",a5:"",a6:"⁳",a7:"⁲",a8:error({message:"slice expression: error value encountered",on:error({message:"-: error value encountered",on:error({message:"value cannot be indexed",on:"⁰ⁱ⁲⁳"})})})} {a1:[11::int32,12::int32],a2:[11::int32,12::int32,13::int32],a3:[10::int32],a4:[10::int32,11::int32,12::int32],a5:[]::[int32],a6:[13::int32],a7:[12::int32],a8:[10::int32,11::int32]} {a1:set[11::int32,12::int32],a2:set[11::int32,12::int32,13::int32],a3:set[10::int32],a4:set[10::int32,11::int32,12::int32],a5:set[]::set[int32],a6:set[13::int32],a7:set[12::int32],a8:set[10::int32,11::int32]} diff --git a/runtime/ztests/op/aggregate/missing.yaml b/runtime/ztests/op/aggregate/missing.yaml index 4a05e40142..f29681945f 100644 --- a/runtime/ztests/op/aggregate/missing.yaml +++ b/runtime/ztests/op/aggregate/missing.yaml @@ -8,5 +8,5 @@ input: | output: | {a:0,b:1} - {a:error("missing"),b:1} - {a:error("missing"),b:error({message:"'.': applied to non-record",on:"b"})} + {a:error({message:"index out of range",on:0}),b:1} + {a:error({message:"value cannot be indexed",on:"a"}),b:error({message:"'.': applied to non-record",on:"b"})} diff --git a/vector/error.go b/vector/error.go index 180bbe96b0..24b1775c4d 100644 --- a/vector/error.go +++ b/vector/error.go @@ -39,15 +39,15 @@ func NewStringError(sctx *super.Context, msg string, len uint32) *Error { return &Error{Typ: sctx.LookupTypeError(super.TypeString), Vals: vals} } -func NewMissing(sctx *super.Context, len uint32) *Error { - return NewStringError(sctx, "missing", len) -} - func NewWrappedError(sctx *super.Context, msg string, val Any) *Error { msgVec := NewConstString(msg, val.Len()) return NewVecWrappedError(sctx, msgVec, val) } +func NewCombinedError(sctx *super.Context, msg string, vec, on Any, index []uint32) Any { + return Combine(vec, index, NewWrappedError(sctx, msg, NewView(on, index))) +} + func NewVecWrappedError(sctx *super.Context, msg Any, val Any) *Error { recType := sctx.MustLookupTypeRecord([]super.Field{ {Name: "message", Type: msg.Type()},