diff --git a/ast/builtins.go b/ast/builtins.go index 5847df3265..7fb5c6ce41 100644 --- a/ast/builtins.go +++ b/ast/builtins.go @@ -4,7 +4,11 @@ package ast -import "github.com/open-policy-agent/opa/types" +import ( + "strings" + + "github.com/open-policy-agent/opa/types" +) // Builtins is the registry of built-in functions supported by OPA. // Call RegisterBuiltin to add a new built-in. @@ -65,7 +69,7 @@ var DefaultBuiltins = [...]*Builtin{ // BuiltinMap provides a convenient mapping of built-in names to // built-in definitions. -var BuiltinMap map[String]*Builtin +var BuiltinMap map[string]*Builtin /** * Unification @@ -73,8 +77,8 @@ var BuiltinMap map[String]*Builtin // Equality represents the "=" operator. var Equality = &Builtin{ - Name: String("eq"), - Infix: String("="), + Name: "eq", + Infix: "=", Args: []types.Type{ types.A, types.A, @@ -88,8 +92,8 @@ var Equality = &Builtin{ // GreaterThan represents the ">" comparison operator. var GreaterThan = &Builtin{ - Name: String("gt"), - Infix: String(">"), + Name: "gt", + Infix: ">", Args: []types.Type{ types.A, types.A, @@ -98,8 +102,8 @@ var GreaterThan = &Builtin{ // GreaterThanEq represents the ">=" comparison operator. var GreaterThanEq = &Builtin{ - Name: String("gte"), - Infix: String(">="), + Name: "gte", + Infix: ">=", Args: []types.Type{ types.A, types.A, @@ -108,8 +112,8 @@ var GreaterThanEq = &Builtin{ // LessThan represents the "<" comparison operator. var LessThan = &Builtin{ - Name: String("lt"), - Infix: String("<"), + Name: "lt", + Infix: "<", Args: []types.Type{ types.A, types.A, @@ -118,8 +122,8 @@ var LessThan = &Builtin{ // LessThanEq represents the "<=" comparison operator. var LessThanEq = &Builtin{ - Name: String("lte"), - Infix: String("<="), + Name: "lte", + Infix: "<=", Args: []types.Type{ types.A, types.A, @@ -128,8 +132,8 @@ var LessThanEq = &Builtin{ // NotEqual represents the "!=" comparison operator. var NotEqual = &Builtin{ - Name: String("neq"), - Infix: String("!="), + Name: "neq", + Infix: "!=", Args: []types.Type{ types.A, types.A, @@ -142,8 +146,8 @@ var NotEqual = &Builtin{ // Plus adds two numbers together. var Plus = &Builtin{ - Name: String("plus"), - Infix: String("+"), + Name: "plus", + Infix: "+", Args: []types.Type{ types.N, types.N, @@ -155,8 +159,8 @@ var Plus = &Builtin{ // Minus subtracts the second number from the first number or computes the diff // between two sets. var Minus = &Builtin{ - Name: String("minus"), - Infix: String("-"), + Name: "minus", + Infix: "-", Args: []types.Type{ types.NewAny(types.N, types.NewSet(types.A)), types.NewAny(types.N, types.NewSet(types.A)), @@ -167,8 +171,8 @@ var Minus = &Builtin{ // Multiply multiplies two numbers together. var Multiply = &Builtin{ - Name: String("mul"), - Infix: String("*"), + Name: "mul", + Infix: "*", Args: []types.Type{ types.N, types.N, @@ -179,8 +183,8 @@ var Multiply = &Builtin{ // Divide divides the first number by the second number. var Divide = &Builtin{ - Name: String("div"), - Infix: String("/"), + Name: "div", + Infix: "/", Args: []types.Type{ types.N, types.N, @@ -191,7 +195,7 @@ var Divide = &Builtin{ // Round rounds the number up to the nearest integer. var Round = &Builtin{ - Name: String("round"), + Name: "round", Args: []types.Type{ types.N, types.N, @@ -201,7 +205,7 @@ var Round = &Builtin{ // Abs returns the number without its sign. var Abs = &Builtin{ - Name: String("abs"), + Name: "abs", Args: []types.Type{ types.N, types.N, @@ -217,8 +221,8 @@ var Abs = &Builtin{ // And performs an intersection operation on sets. var And = &Builtin{ - Name: String("and"), - Infix: String("&"), + Name: "and", + Infix: "&", Args: []types.Type{ types.NewSet(types.A), types.NewSet(types.A), @@ -229,8 +233,8 @@ var And = &Builtin{ // Or performs a union operation on sets. var Or = &Builtin{ - Name: String("or"), - Infix: String("|"), + Name: "or", + Infix: "|", Args: []types.Type{ types.NewSet(types.A), types.NewSet(types.A), @@ -245,7 +249,7 @@ var Or = &Builtin{ // Count takes a collection or string and counts the number of elements in it. var Count = &Builtin{ - Name: String("count"), + Name: "count", Args: []types.Type{ types.NewAny( types.NewSet(types.A), @@ -260,7 +264,7 @@ var Count = &Builtin{ // Sum takes an array or set of numbers and sums them. var Sum = &Builtin{ - Name: String("sum"), + Name: "sum", Args: []types.Type{ types.NewAny( types.NewSet(types.N), @@ -273,7 +277,7 @@ var Sum = &Builtin{ // Max returns the maximum value in a collection. var Max = &Builtin{ - Name: String("max"), + Name: "max", Args: []types.Type{ types.NewAny( types.NewSet(types.A), @@ -286,7 +290,7 @@ var Max = &Builtin{ // Min returns the minimum value in a collection. var Min = &Builtin{ - Name: String("min"), + Name: "min", Args: []types.Type{ types.NewAny( types.NewSet(types.A), @@ -305,7 +309,7 @@ var Min = &Builtin{ // Strings are converted to numbers using strconv.Atoi. // Boolean false is converted to 0 and boolean true is converted to 1. var ToNumber = &Builtin{ - Name: String("to_number"), + Name: "to_number", Args: []types.Type{ types.NewAny( types.N, @@ -325,7 +329,7 @@ var ToNumber = &Builtin{ // RegexMatch takes two strings and evaluates to true if the string in the second // position matches the pattern in the first position. var RegexMatch = &Builtin{ - Name: String("re_match"), + Name: "re_match", Args: []types.Type{ types.S, types.S, @@ -338,7 +342,7 @@ var RegexMatch = &Builtin{ // Concat joins an array of strings with an input string. var Concat = &Builtin{ - Name: String("concat"), + Name: "concat", Args: []types.Type{ types.S, types.NewAny( @@ -352,7 +356,7 @@ var Concat = &Builtin{ // FormatInt returns the string representation of the number in the given base after converting it to an integer value. var FormatInt = &Builtin{ - Name: String("format_int"), + Name: "format_int", Args: []types.Type{ types.N, types.N, @@ -363,7 +367,7 @@ var FormatInt = &Builtin{ // IndexOf returns the index of a substring contained inside a string var IndexOf = &Builtin{ - Name: String("indexof"), + Name: "indexof", Args: []types.Type{ types.S, types.S, @@ -375,7 +379,7 @@ var IndexOf = &Builtin{ // Substring returns the portion of a string for a given start index and a length. // If the length is less than zero, then substring returns the remainder of the string. var Substring = &Builtin{ - Name: String("substring"), + Name: "substring", Args: []types.Type{ types.S, types.N, @@ -387,7 +391,7 @@ var Substring = &Builtin{ // Contains returns true if the search string is included in the base string var Contains = &Builtin{ - Name: String("contains"), + Name: "contains", Args: []types.Type{ types.S, types.S, @@ -396,7 +400,7 @@ var Contains = &Builtin{ // StartsWith returns true if the search string begins with the base string var StartsWith = &Builtin{ - Name: String("startswith"), + Name: "startswith", Args: []types.Type{ types.S, types.S, @@ -405,7 +409,7 @@ var StartsWith = &Builtin{ // EndsWith returns true if the search string begins with the base string var EndsWith = &Builtin{ - Name: String("endswith"), + Name: "endswith", Args: []types.Type{ types.S, types.S, @@ -414,7 +418,7 @@ var EndsWith = &Builtin{ // Lower returns the input string but with all characters in lower-case var Lower = &Builtin{ - Name: String("lower"), + Name: "lower", Args: []types.Type{ types.S, types.S, @@ -424,7 +428,7 @@ var Lower = &Builtin{ // Upper returns the input string but with all characters in upper-case var Upper = &Builtin{ - Name: String("upper"), + Name: "upper", Args: []types.Type{ types.S, types.S, @@ -434,7 +438,7 @@ var Upper = &Builtin{ // Split returns an array containing elements of the input string split on a delimiter. var Split = &Builtin{ - Name: String("split"), + Name: "split", Args: []types.Type{ types.S, types.S, @@ -446,7 +450,7 @@ var Split = &Builtin{ // Replace returns the given string with all instances of the second argument replaced // by the third. var Replace = &Builtin{ - Name: String("replace"), + Name: "replace", Args: []types.Type{ types.S, types.S, @@ -459,7 +463,7 @@ var Replace = &Builtin{ // Trim returns the given string will all leading or trailing instances of the second // argument removed. var Trim = &Builtin{ - Name: String("trim"), + Name: "trim", Args: []types.Type{ types.S, types.S, @@ -470,7 +474,7 @@ var Trim = &Builtin{ // Sprintf returns the given string, formatted. var Sprintf = &Builtin{ - Name: String("sprintf"), + Name: "sprintf", Args: []types.Type{ types.S, types.NewArray(nil, types.A), @@ -485,7 +489,7 @@ var Sprintf = &Builtin{ // JSONMarshal serializes the input term. var JSONMarshal = &Builtin{ - Name: String("json.marshal"), + Name: "json.marshal", Args: []types.Type{ types.A, types.S, @@ -495,7 +499,7 @@ var JSONMarshal = &Builtin{ // JSONUnmarshal deserializes the input string. var JSONUnmarshal = &Builtin{ - Name: String("json.unmarshal"), + Name: "json.unmarshal", Args: []types.Type{ types.S, types.A, @@ -505,7 +509,7 @@ var JSONUnmarshal = &Builtin{ // Base64UrlEncode serializes the input string into base64url encoding. var Base64UrlEncode = &Builtin{ - Name: String("base64url.encode"), + Name: "base64url.encode", Args: []types.Type{ types.S, types.S, @@ -515,7 +519,7 @@ var Base64UrlEncode = &Builtin{ // Base64UrlDecode deserializes the base64url encoded input string. var Base64UrlDecode = &Builtin{ - Name: String("base64url.decode"), + Name: "base64url.decode", Args: []types.Type{ types.S, types.S, @@ -525,7 +529,7 @@ var Base64UrlDecode = &Builtin{ // YAMLMarshal serializes the input term. var YAMLMarshal = &Builtin{ - Name: String("yaml.marshal"), + Name: "yaml.marshal", Args: []types.Type{ types.A, types.S, @@ -535,7 +539,7 @@ var YAMLMarshal = &Builtin{ // YAMLUnmarshal deserializes the input string. var YAMLUnmarshal = &Builtin{ - Name: String("yaml.unmarshal"), + Name: "yaml.unmarshal", Args: []types.Type{ types.S, types.A, @@ -549,7 +553,7 @@ var YAMLUnmarshal = &Builtin{ // JWTDecode decodes a JSON Web Token and outputs it as an Object. var JWTDecode = &Builtin{ - Name: String("io.jwt.decode"), + Name: "io.jwt.decode", Args: []types.Type{ types.S, types.NewObject(nil, types.NewDynamicProperty(types.A, types.A)), @@ -565,7 +569,7 @@ var JWTDecode = &Builtin{ // NowNanos returns the current time since epoch in nanoseconds. var NowNanos = &Builtin{ - Name: String("time.now_ns"), + Name: "time.now_ns", Args: []types.Type{ types.N, }, @@ -574,7 +578,7 @@ var NowNanos = &Builtin{ // ParseNanos returns the time in nanoseconds parsed from the string in the given format. var ParseNanos = &Builtin{ - Name: String("time.parse_ns"), + Name: "time.parse_ns", Args: []types.Type{ types.S, types.S, @@ -585,7 +589,7 @@ var ParseNanos = &Builtin{ // ParseRFC3339Nanos returns the time in nanoseconds parsed from the string in RFC3339 format. var ParseRFC3339Nanos = &Builtin{ - Name: String("time.parse_rfc3339_ns"), + Name: "time.parse_rfc3339_ns", Args: []types.Type{ types.S, types.N, @@ -600,7 +604,7 @@ var ParseRFC3339Nanos = &Builtin{ // WalkBuiltin generates [path, value] tuples for all nested documents // (recursively). var WalkBuiltin = &Builtin{ - Name: String("walk"), + Name: "walk", Args: []types.Type{ types.A, types.NewArray( @@ -620,7 +624,7 @@ var WalkBuiltin = &Builtin{ // SetDiff has been replaced by the minus built-in. var SetDiff = &Builtin{ - Name: String("set_diff"), + Name: "set_diff", Args: []types.Type{ types.NewSet(types.A), types.NewSet(types.A), @@ -632,23 +636,35 @@ var SetDiff = &Builtin{ // Builtin represents a built-in function supported by OPA. Every // built-in function is uniquely identified by a name. type Builtin struct { - Name String // Unique name of built-in function, e.g., name(term,term,...,term) - Infix String // Unique name of infix operator. Default should be unset. + Name string // Unique name of built-in function, e.g., (arg1,arg2,...,argN) + Infix string // Unique name of infix operator. Default should be unset. Args []types.Type // Built-in argument type declaration. TargetPos []int // Argument positions that bind outputs. Indexing is zero-based. } // Expr creates a new expression for the built-in with the given terms. func (b *Builtin) Expr(terms ...*Term) *Expr { - ts := []*Term{StringTerm(string(b.Name))} - for _, t := range terms { - ts = append(ts, t) + ts := make([]*Term, len(terms)+1) + ts[0] = NewTerm(b.Ref()) + for i := range terms { + ts[i+1] = terms[i] } return &Expr{ Terms: ts, } } +// Ref returns a Ref that refers to the built-in function. +func (b *Builtin) Ref() Ref { + parts := strings.Split(b.Name, ".") + ref := make(Ref, len(parts)) + ref[0] = VarTerm(parts[0]) + for i := 1; i < len(parts); i++ { + ref[i] = StringTerm(parts[i]) + } + return ref +} + // IsTargetPos returns true if a variable in the i-th position will be // bound when the expression is evaluated. func (b *Builtin) IsTargetPos(i int) bool { @@ -661,7 +677,7 @@ func (b *Builtin) IsTargetPos(i int) bool { } func init() { - BuiltinMap = map[String]*Builtin{} + BuiltinMap = map[string]*Builtin{} for _, b := range DefaultBuiltins { RegisterBuiltin(b) } diff --git a/ast/builtins_test.go b/ast/builtins_test.go index a6bc7321ba..da863a8816 100644 --- a/ast/builtins_test.go +++ b/ast/builtins_test.go @@ -10,7 +10,7 @@ import ( ) func TestIsTargetPos(t *testing.T) { - b := &Builtin{Name: String("dummy"), TargetPos: []int{1, 3}} + b := &Builtin{Name: "dummy", TargetPos: []int{1, 3}} expected := []int{1, 3} result := []int{} for i := 0; i < 4; i++ { diff --git a/ast/check.go b/ast/check.go index 2c2a150547..873f0e6d34 100644 --- a/ast/check.go +++ b/ast/check.go @@ -23,7 +23,7 @@ type exprChecker func(*TypeEnv, *Expr) *Error // issues. type typeChecker struct { errs Errors - exprCheckers map[String]exprChecker + exprCheckers map[string]exprChecker // When checking the types of functions, their inputs need to initially // be assumed as types.Any. In order to fill the TypeEnv with more accurate @@ -35,8 +35,8 @@ type typeChecker struct { // newTypeChecker returns a new typeChecker object that has no errors. func newTypeChecker() *typeChecker { tc := &typeChecker{} - tc.exprCheckers = map[String]exprChecker{ - Equality.Name: tc.checkExprEq, + tc.exprCheckers = map[string]exprChecker{ + "eq": tc.checkExprEq, } return tc } @@ -163,7 +163,7 @@ func (tc *typeChecker) checkFunc(env *TypeEnv, fn *Func) { if len(err) > prev { return } - name := fn.PathString() + name := fn.Path().String() // Ensure that multiple definitions of this function have consistent argument // lengths. @@ -188,7 +188,7 @@ func (tc *typeChecker) checkFunc(env *TypeEnv, fn *Func) { func (tc *typeChecker) checkLanguageBuiltins() *TypeEnv { env := NewTypeEnv() for _, bi := range Builtins { - env.PutFunc(bi.Name, bi.Args) + env.PutFunc(string(bi.Name), bi.Args) } return env @@ -236,7 +236,7 @@ func (tc *typeChecker) checkExpr(env *TypeEnv, expr *Expr) *Error { return nil } - checker := tc.exprCheckers[expr.Name()] + checker := tc.exprCheckers[expr.Name().String()] if checker != nil { return checker(env, expr) } @@ -245,7 +245,7 @@ func (tc *typeChecker) checkExpr(env *TypeEnv, expr *Expr) *Error { } func (tc *typeChecker) checkExprBuiltin(env *TypeEnv, expr *Expr) *Error { - name := expr.Name() + name := expr.Name().String() expArgs := env.GetFunc(name) if expArgs == nil { return NewError(TypeErr, expr.Location, "undefined built-in function %v", name) @@ -475,6 +475,13 @@ func (rc *refChecker) Visit(x interface{}) Visitor { switch x := x.(type) { case *ArrayComprehension, *ObjectComprehension, *SetComprehension: return nil + case *Expr: + if terms, ok := x.Terms.([]*Term); ok { + for i := 1; i < len(terms); i++ { + Walk(rc, terms[i]) + } + return nil + } case Ref: if err := rc.checkRef(rc.env, rc.env.tree, x, 0); err != nil { rc.errs = append(rc.errs, err) @@ -906,7 +913,7 @@ func newRefError(loc *Location, ref Ref) *Error { return NewError(TypeErr, loc, "undefined ref: %v", ref) } -func newArgError(loc *Location, builtinName String, msg string, have []types.Type, want []types.Type) *Error { +func newArgError(loc *Location, builtinName, msg string, have []types.Type, want []types.Type) *Error { err := NewError(TypeErr, loc, "%v: %v", builtinName, msg) err.Details = &ArgErrDetail{ Have: have, diff --git a/ast/check_test.go b/ast/check_test.go index 766d841a90..541c4bb9d0 100644 --- a/ast/check_test.go +++ b/ast/check_test.go @@ -20,7 +20,7 @@ func TestCheckInference(t *testing.T) { // fake_builtin_1([str1,str2]) RegisterBuiltin(&Builtin{ - Name: String("fake_builtin_1"), + Name: "fake_builtin_1", Args: []types.Type{ types.NewArray( []types.Type{types.S, types.S}, nil, @@ -31,7 +31,7 @@ func TestCheckInference(t *testing.T) { // fake_builtin_2({"a":str1,"b":str2}) RegisterBuiltin(&Builtin{ - Name: String("fake_builtin_2"), + Name: "fake_builtin_2", Args: []types.Type{ types.NewObject( []*types.StaticProperty{ @@ -45,7 +45,7 @@ func TestCheckInference(t *testing.T) { // fake_builtin_3({str1,str2,...}) RegisterBuiltin(&Builtin{ - Name: String("fake_builtin_3"), + Name: "fake_builtin_3", Args: []types.Type{ types.NewSet(types.S), }, @@ -549,7 +549,6 @@ func TestCheckMatchErrors(t *testing.T) { {"object-dynamic", `{ obj2 = obj1 }`}, {"set", "{{1,2,3} = null}"}, } - for _, tc := range tests { test.Subtest(t, tc.note, func(t *testing.T) { body := MustParseBody(tc.query) @@ -560,13 +559,12 @@ func TestCheckMatchErrors(t *testing.T) { } }) } - } func TestCheckBuiltinErrors(t *testing.T) { RegisterBuiltin(&Builtin{ - Name: String("fake_builtin_2"), + Name: "fake_builtin_2", Args: []types.Type{ types.NewAny(types.NewObject( []*types.StaticProperty{ diff --git a/ast/compile.go b/ast/compile.go index 1c938378ac..a993c8cfab 100644 --- a/ast/compile.go +++ b/ast/compile.go @@ -91,7 +91,7 @@ type Compiler struct { // FunctionMap is a map containing the user defined functions of this // compiler's modules. - FuncMap map[String][]*Func + FuncMap map[string][]*Func // Graph represents the dependencies between rules and funcs (lets call // them targets). An edge (u,v) is added to the graph if target "u" @@ -194,7 +194,7 @@ func NewCompiler() *Compiler { c := &Compiler{ Modules: map[string]*Module{}, TypeEnv: NewTypeEnv(), - FuncMap: map[String][]*Func{}, + FuncMap: map[string][]*Func{}, generatedVars: map[*Module]VarSet{}, ruleIndices: util.NewHashMap(func(a, b util.T) bool { r1, r2 := a.(Ref), b.(Ref) @@ -405,7 +405,7 @@ func (c *Compiler) GetRules(ref Ref) (rules []*Rule) { } // GetFunc returns the function referred to by name. -func (c *Compiler) GetFunc(name String) []*Func { +func (c *Compiler) GetFunc(name string) []*Func { if fn, ok := c.FuncMap[name]; ok { return fn } @@ -413,14 +413,14 @@ func (c *Compiler) GetFunc(name String) []*Func { } // GetAllFuncs returns a map of functions that this compiler has discovered. -func (c *Compiler) GetAllFuncs() map[String][]*Func { - cpy := map[String][]*Func{} +func (c *Compiler) GetAllFuncs() map[string][]*Func { + cpy := map[string][]*Func{} for _, fn := range c.FuncMap { var fns []*Func for _, f := range fn { fns = append(fns, f.Copy()) } - cpy[fn[0].PathString()] = fns + cpy[fn[0].Path().String()] = fns } return cpy } @@ -618,7 +618,8 @@ func (c *Compiler) checkBodySafety(safe VarSet, m *Module, b Body, l *Location) } var safetyCheckVarVisitorParams = VarVisitorParams{ - SkipClosures: true, + SkipRefCallHead: true, + SkipClosures: true, } // checkSafetyRuleHeads ensures that variables appearing in the head of a @@ -768,7 +769,7 @@ func (c *Compiler) resolveAllRefs() { }) WalkFuncs(mod, func(fn *Func) bool { resolveRefsInFunc(globals, fn) - path := fn.PathString() + path := fn.Path().String() c.FuncMap[path] = append(c.FuncMap[path], fn) return false @@ -779,14 +780,20 @@ func (c *Compiler) resolveAllRefs() { } for _, mod := range c.Modules { - visitor := NewGenericVisitor(func(x interface{}) bool { - // Walk terms in order to provide more detailed location - // information. + var visitor Visitor + visitor = NewGenericVisitor(func(x interface{}) bool { switch x := x.(type) { + case *Expr: + if terms, ok := x.Terms.([]*Term); ok { + for i := 1; i < len(terms); i++ { + Walk(visitor, terms[i]) + } + return true + } case *Term: switch v := x.Value.(type) { case Ref: - if _, ok := c.FuncMap[String(v.String())]; ok { + if _, ok := c.FuncMap[v.String()]; ok { c.err(&Error{ Code: CompileErr, Message: x.Location.Format("%v refers to a known builtin but does not call it", string(x.Location.Text)), @@ -1243,7 +1250,7 @@ type Graph struct { // NewGraph returns a new Graph based on modules. The list function // must return the rules or user functions referred to directly by the ref. -func NewGraph(modules map[string]*Module, list func(Ref) []*Rule, resolve func(String) []*Func) *Graph { +func NewGraph(modules map[string]*Module, list func(Ref) []*Rule, resolve func(string) []*Func) *Graph { graph := &Graph{ adj: map[util.T]map[util.T]struct{}{}, @@ -1264,7 +1271,7 @@ func NewGraph(modules map[string]*Module, list func(Ref) []*Rule, resolve func(S addFuncDeps := func(a util.T) func(expr *Expr) bool { return func(expr *Expr) bool { if expr.IsBuiltin() { - name := expr.Terms.([]*Term)[0].Value.(String) + name := expr.Terms.([]*Term)[0].String() // Language builtins won't be resolved. if b := resolve(name); b != nil { @@ -1766,20 +1773,27 @@ func resolveRefsInExpr(globals map[Var]Ref, expr *Expr) *Expr { case *Term: cpy.Terms = resolveRefsInTerm(globals, ts) case []*Term: - buf := []*Term{} + buf := make([]*Term, len(ts)) - // Resolve user defined functions. - v := Var(ts[0].Value.(String)) - if r, ok := globals[v]; ok { - tcpy := *ts[0] - tcpy.Value = String(r.String()) - buf = append(buf, &tcpy) - ts = ts[1:] + // Resolve refs to functions inside the package. Refs outside the + // package must be fully qualified. FIXME(tsandall): this can go away + // once functions are merged with rules. + ref := ts[0].Value.(Ref) + if path, ok := globals[ref[0].Value.(Var)]; ok && len(ref) == 1 { + refCopy := path.Copy() + for i := range refCopy { + refCopy[i].SetLocation(ts[0].Location) + } + buf[0] = NewTerm(refCopy) + } else { + buf[0] = ts[0] } - for _, t := range ts { - buf = append(buf, resolveRefsInTerm(globals, t)) + // resolve remaining terms normally + for i := 1; i < len(ts); i++ { + buf[i] = resolveRefsInTerm(globals, ts[i]) } + cpy.Terms = buf } for _, w := range cpy.With { diff --git a/ast/compile_test.go b/ast/compile_test.go index 3ec1f1ab92..898244a613 100644 --- a/ast/compile_test.go +++ b/ast/compile_test.go @@ -427,6 +427,7 @@ func TestCompilerCheckSafetyBodyReordering(t *testing.T) { contains(x, "oo") `}, {"userfunc", `split(y, ".", z); a.b.funcs.fn("...foo.bar..", y)`, `a.b.funcs.fn("...foo.bar..", y); split(y, ".", z)`}, + {"call-vars", `f.g[i](1); i = "foo"`, `i = "foo"; f.g[i](1)`}, } for i, tc := range tests { @@ -535,6 +536,7 @@ func TestCompilerCheckSafetyBodyErrors(t *testing.T) { {"with-value-2", `p { x = data.a.b.d.t with input as x }`, `{x,}`}, {"else-kw", "p { false } else { count(x, 1) }", `{x,}`}, {"userfunc", "foo(x) = [y, z] { split(x, y, z) }", `{y,z}`}, + {"call-vars", "p { f[i].g[j](1) }", `{i, j}`}, } makeErrMsg := func(varName string) string { diff --git a/ast/env.go b/ast/env.go index a5dd020bd2..d01c8f2c77 100644 --- a/ast/env.go +++ b/ast/env.go @@ -11,7 +11,7 @@ import ( // TypeEnv contains type info for static analysis such as type checking. type TypeEnv struct { - funcs map[String][]types.Type + funcs map[string][]types.Type tree *typeTreeNode next *TypeEnv } @@ -19,7 +19,7 @@ type TypeEnv struct { // NewTypeEnv returns an empty TypeEnv. func NewTypeEnv() *TypeEnv { return &TypeEnv{ - funcs: map[String][]types.Type{}, + funcs: map[string][]types.Type{}, tree: newTypeTree(), } } @@ -27,7 +27,7 @@ func NewTypeEnv() *TypeEnv { // GetFunc returns the type array corresponding to the arguments of the function // referred to by name. GetFunc returns nil if there is no function matching that // name. -func (env *TypeEnv) GetFunc(name String) []types.Type { +func (env *TypeEnv) GetFunc(name string) []types.Type { tps, ok := env.funcs[name] if !ok && env.next != nil { return env.next.GetFunc(name) @@ -37,7 +37,7 @@ func (env *TypeEnv) GetFunc(name String) []types.Type { // PutFunc inserts the type information for the function referred to by name into // this TypeEnv. -func (env *TypeEnv) PutFunc(name String, args []types.Type) { +func (env *TypeEnv) PutFunc(name string, args []types.Type) { env.funcs[name] = args } diff --git a/ast/parser.go b/ast/parser.go index 232b1c669d..943d98bdab 100644 --- a/ast/parser.go +++ b/ast/parser.go @@ -1392,42 +1392,42 @@ var g = &grammar{ }, { name: "InfixExpr", - pos: position{line: 465, col: 1, offset: 12550}, + pos: position{line: 465, col: 1, offset: 12577}, expr: &actionExpr{ - pos: position{line: 465, col: 14, offset: 12563}, + pos: position{line: 465, col: 14, offset: 12590}, run: (*parser).callonInfixExpr1, expr: &seqExpr{ - pos: position{line: 465, col: 14, offset: 12563}, + pos: position{line: 465, col: 14, offset: 12590}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 465, col: 14, offset: 12563}, + pos: position{line: 465, col: 14, offset: 12590}, label: "left", expr: &ruleRefExpr{ - pos: position{line: 465, col: 19, offset: 12568}, + pos: position{line: 465, col: 19, offset: 12595}, name: "Term", }, }, &ruleRefExpr{ - pos: position{line: 465, col: 24, offset: 12573}, + pos: position{line: 465, col: 24, offset: 12600}, name: "_", }, &labeledExpr{ - pos: position{line: 465, col: 26, offset: 12575}, + pos: position{line: 465, col: 26, offset: 12602}, label: "op", expr: &ruleRefExpr{ - pos: position{line: 465, col: 29, offset: 12578}, + pos: position{line: 465, col: 29, offset: 12605}, name: "InfixOp", }, }, &ruleRefExpr{ - pos: position{line: 465, col: 37, offset: 12586}, + pos: position{line: 465, col: 37, offset: 12613}, name: "_", }, &labeledExpr{ - pos: position{line: 465, col: 39, offset: 12588}, + pos: position{line: 465, col: 39, offset: 12615}, label: "right", expr: &ruleRefExpr{ - pos: position{line: 465, col: 45, offset: 12594}, + pos: position{line: 465, col: 45, offset: 12621}, name: "Term", }, }, @@ -1437,43 +1437,43 @@ var g = &grammar{ }, { name: "InfixOp", - pos: position{line: 469, col: 1, offset: 12669}, + pos: position{line: 469, col: 1, offset: 12696}, expr: &actionExpr{ - pos: position{line: 469, col: 12, offset: 12680}, + pos: position{line: 469, col: 12, offset: 12707}, run: (*parser).callonInfixOp1, expr: &labeledExpr{ - pos: position{line: 469, col: 12, offset: 12680}, + pos: position{line: 469, col: 12, offset: 12707}, label: "val", expr: &choiceExpr{ - pos: position{line: 469, col: 17, offset: 12685}, + pos: position{line: 469, col: 17, offset: 12712}, alternatives: []interface{}{ &litMatcher{ - pos: position{line: 469, col: 17, offset: 12685}, + pos: position{line: 469, col: 17, offset: 12712}, val: "=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 469, col: 23, offset: 12691}, + pos: position{line: 469, col: 23, offset: 12718}, val: "!=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 469, col: 30, offset: 12698}, + pos: position{line: 469, col: 30, offset: 12725}, val: "<=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 469, col: 37, offset: 12705}, + pos: position{line: 469, col: 37, offset: 12732}, val: ">=", ignoreCase: false, }, &litMatcher{ - pos: position{line: 469, col: 44, offset: 12712}, + pos: position{line: 469, col: 44, offset: 12739}, val: "<", ignoreCase: false, }, &litMatcher{ - pos: position{line: 469, col: 50, offset: 12718}, + pos: position{line: 469, col: 50, offset: 12745}, val: ">", ignoreCase: false, }, @@ -1484,81 +1484,81 @@ var g = &grammar{ }, { name: "PrefixExpr", - pos: position{line: 481, col: 1, offset: 12965}, + pos: position{line: 481, col: 1, offset: 13019}, expr: &choiceExpr{ - pos: position{line: 481, col: 15, offset: 12979}, + pos: position{line: 481, col: 15, offset: 13033}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 481, col: 15, offset: 12979}, + pos: position{line: 481, col: 15, offset: 13033}, name: "SetEmpty", }, &ruleRefExpr{ - pos: position{line: 481, col: 26, offset: 12990}, - name: "Builtin", + pos: position{line: 481, col: 26, offset: 13044}, + name: "Call", }, }, }, }, { - name: "Builtin", - pos: position{line: 483, col: 1, offset: 12999}, + name: "Call", + pos: position{line: 483, col: 1, offset: 13050}, expr: &actionExpr{ - pos: position{line: 483, col: 12, offset: 13010}, - run: (*parser).callonBuiltin1, + pos: position{line: 483, col: 9, offset: 13058}, + run: (*parser).callonCall1, expr: &seqExpr{ - pos: position{line: 483, col: 12, offset: 13010}, + pos: position{line: 483, col: 9, offset: 13058}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 483, col: 12, offset: 13010}, + pos: position{line: 483, col: 9, offset: 13058}, label: "name", expr: &ruleRefExpr{ - pos: position{line: 483, col: 17, offset: 13015}, - name: "BuiltinName", + pos: position{line: 483, col: 14, offset: 13063}, + name: "Operator", }, }, &litMatcher{ - pos: position{line: 483, col: 29, offset: 13027}, + pos: position{line: 483, col: 23, offset: 13072}, val: "(", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 483, col: 33, offset: 13031}, + pos: position{line: 483, col: 27, offset: 13076}, name: "_", }, &labeledExpr{ - pos: position{line: 483, col: 35, offset: 13033}, + pos: position{line: 483, col: 29, offset: 13078}, label: "head", expr: &zeroOrOneExpr{ - pos: position{line: 483, col: 40, offset: 13038}, + pos: position{line: 483, col: 34, offset: 13083}, expr: &ruleRefExpr{ - pos: position{line: 483, col: 40, offset: 13038}, + pos: position{line: 483, col: 34, offset: 13083}, name: "Term", }, }, }, &labeledExpr{ - pos: position{line: 483, col: 46, offset: 13044}, + pos: position{line: 483, col: 40, offset: 13089}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 483, col: 51, offset: 13049}, + pos: position{line: 483, col: 45, offset: 13094}, expr: &seqExpr{ - pos: position{line: 483, col: 53, offset: 13051}, + pos: position{line: 483, col: 47, offset: 13096}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 483, col: 53, offset: 13051}, + pos: position{line: 483, col: 47, offset: 13096}, name: "_", }, &litMatcher{ - pos: position{line: 483, col: 55, offset: 13053}, + pos: position{line: 483, col: 49, offset: 13098}, val: ",", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 483, col: 59, offset: 13057}, + pos: position{line: 483, col: 53, offset: 13102}, name: "_", }, &ruleRefExpr{ - pos: position{line: 483, col: 61, offset: 13059}, + pos: position{line: 483, col: 55, offset: 13104}, name: "Term", }, }, @@ -1566,11 +1566,11 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 483, col: 69, offset: 13067}, + pos: position{line: 483, col: 63, offset: 13112}, name: "_", }, &litMatcher{ - pos: position{line: 483, col: 72, offset: 13070}, + pos: position{line: 483, col: 66, offset: 13115}, val: ")", ignoreCase: false, }, @@ -1579,41 +1579,24 @@ var g = &grammar{ }, }, { - name: "BuiltinName", - pos: position{line: 499, col: 1, offset: 13474}, + name: "Operator", + pos: position{line: 499, col: 1, offset: 13519}, expr: &actionExpr{ - pos: position{line: 499, col: 16, offset: 13489}, - run: (*parser).callonBuiltinName1, - expr: &seqExpr{ - pos: position{line: 499, col: 16, offset: 13489}, - exprs: []interface{}{ - &labeledExpr{ - pos: position{line: 499, col: 16, offset: 13489}, - label: "head", - expr: &ruleRefExpr{ - pos: position{line: 499, col: 21, offset: 13494}, - name: "Var", + pos: position{line: 499, col: 13, offset: 13531}, + run: (*parser).callonOperator1, + expr: &labeledExpr{ + pos: position{line: 499, col: 13, offset: 13531}, + label: "val", + expr: &choiceExpr{ + pos: position{line: 499, col: 18, offset: 13536}, + alternatives: []interface{}{ + &ruleRefExpr{ + pos: position{line: 499, col: 18, offset: 13536}, + name: "Ref", }, - }, - &labeledExpr{ - pos: position{line: 499, col: 25, offset: 13498}, - label: "tail", - expr: &zeroOrMoreExpr{ - pos: position{line: 499, col: 30, offset: 13503}, - expr: &seqExpr{ - pos: position{line: 499, col: 32, offset: 13505}, - exprs: []interface{}{ - &litMatcher{ - pos: position{line: 499, col: 32, offset: 13505}, - val: ".", - ignoreCase: false, - }, - &ruleRefExpr{ - pos: position{line: 499, col: 36, offset: 13509}, - name: "Var", - }, - }, - }, + &ruleRefExpr{ + pos: position{line: 499, col: 24, offset: 13542}, + name: "Var", }, }, }, @@ -1622,34 +1605,34 @@ var g = &grammar{ }, { name: "Term", - pos: position{line: 513, col: 1, offset: 13914}, + pos: position{line: 511, col: 1, offset: 13773}, expr: &actionExpr{ - pos: position{line: 513, col: 9, offset: 13922}, + pos: position{line: 511, col: 9, offset: 13781}, run: (*parser).callonTerm1, expr: &labeledExpr{ - pos: position{line: 513, col: 9, offset: 13922}, + pos: position{line: 511, col: 9, offset: 13781}, label: "val", expr: &choiceExpr{ - pos: position{line: 513, col: 15, offset: 13928}, + pos: position{line: 511, col: 15, offset: 13787}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 513, col: 15, offset: 13928}, + pos: position{line: 511, col: 15, offset: 13787}, name: "Comprehension", }, &ruleRefExpr{ - pos: position{line: 513, col: 31, offset: 13944}, + pos: position{line: 511, col: 31, offset: 13803}, name: "Composite", }, &ruleRefExpr{ - pos: position{line: 513, col: 43, offset: 13956}, + pos: position{line: 511, col: 43, offset: 13815}, name: "Scalar", }, &ruleRefExpr{ - pos: position{line: 513, col: 52, offset: 13965}, + pos: position{line: 511, col: 52, offset: 13824}, name: "Ref", }, &ruleRefExpr{ - pos: position{line: 513, col: 58, offset: 13971}, + pos: position{line: 511, col: 58, offset: 13830}, name: "Var", }, }, @@ -1659,20 +1642,20 @@ var g = &grammar{ }, { name: "Comprehension", - pos: position{line: 517, col: 1, offset: 14002}, + pos: position{line: 515, col: 1, offset: 13861}, expr: &choiceExpr{ - pos: position{line: 517, col: 18, offset: 14019}, + pos: position{line: 515, col: 18, offset: 13878}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 517, col: 18, offset: 14019}, + pos: position{line: 515, col: 18, offset: 13878}, name: "ArrayComprehension", }, &ruleRefExpr{ - pos: position{line: 517, col: 39, offset: 14040}, + pos: position{line: 515, col: 39, offset: 13899}, name: "ObjectComprehension", }, &ruleRefExpr{ - pos: position{line: 517, col: 61, offset: 14062}, + pos: position{line: 515, col: 61, offset: 13921}, name: "SetComprehension", }, }, @@ -1680,57 +1663,57 @@ var g = &grammar{ }, { name: "ArrayComprehension", - pos: position{line: 519, col: 1, offset: 14080}, + pos: position{line: 517, col: 1, offset: 13939}, expr: &actionExpr{ - pos: position{line: 519, col: 23, offset: 14102}, + pos: position{line: 517, col: 23, offset: 13961}, run: (*parser).callonArrayComprehension1, expr: &seqExpr{ - pos: position{line: 519, col: 23, offset: 14102}, + pos: position{line: 517, col: 23, offset: 13961}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 519, col: 23, offset: 14102}, + pos: position{line: 517, col: 23, offset: 13961}, val: "[", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 519, col: 27, offset: 14106}, + pos: position{line: 517, col: 27, offset: 13965}, name: "_", }, &labeledExpr{ - pos: position{line: 519, col: 29, offset: 14108}, + pos: position{line: 517, col: 29, offset: 13967}, label: "term", expr: &ruleRefExpr{ - pos: position{line: 519, col: 34, offset: 14113}, + pos: position{line: 517, col: 34, offset: 13972}, name: "Term", }, }, &ruleRefExpr{ - pos: position{line: 519, col: 39, offset: 14118}, + pos: position{line: 517, col: 39, offset: 13977}, name: "_", }, &litMatcher{ - pos: position{line: 519, col: 41, offset: 14120}, + pos: position{line: 517, col: 41, offset: 13979}, val: "|", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 519, col: 45, offset: 14124}, + pos: position{line: 517, col: 45, offset: 13983}, name: "_", }, &labeledExpr{ - pos: position{line: 519, col: 47, offset: 14126}, + pos: position{line: 517, col: 47, offset: 13985}, label: "body", expr: &ruleRefExpr{ - pos: position{line: 519, col: 52, offset: 14131}, + pos: position{line: 517, col: 52, offset: 13990}, name: "WhitespaceBody", }, }, &ruleRefExpr{ - pos: position{line: 519, col: 67, offset: 14146}, + pos: position{line: 517, col: 67, offset: 14005}, name: "_", }, &litMatcher{ - pos: position{line: 519, col: 69, offset: 14148}, + pos: position{line: 517, col: 69, offset: 14007}, val: "]", ignoreCase: false, }, @@ -1740,78 +1723,78 @@ var g = &grammar{ }, { name: "ObjectComprehension", - pos: position{line: 525, col: 1, offset: 14273}, + pos: position{line: 523, col: 1, offset: 14132}, expr: &actionExpr{ - pos: position{line: 525, col: 24, offset: 14296}, + pos: position{line: 523, col: 24, offset: 14155}, run: (*parser).callonObjectComprehension1, expr: &seqExpr{ - pos: position{line: 525, col: 24, offset: 14296}, + pos: position{line: 523, col: 24, offset: 14155}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 525, col: 24, offset: 14296}, + pos: position{line: 523, col: 24, offset: 14155}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 525, col: 28, offset: 14300}, + pos: position{line: 523, col: 28, offset: 14159}, name: "_", }, &labeledExpr{ - pos: position{line: 525, col: 30, offset: 14302}, + pos: position{line: 523, col: 30, offset: 14161}, label: "key", expr: &ruleRefExpr{ - pos: position{line: 525, col: 34, offset: 14306}, + pos: position{line: 523, col: 34, offset: 14165}, name: "Key", }, }, &ruleRefExpr{ - pos: position{line: 525, col: 38, offset: 14310}, + pos: position{line: 523, col: 38, offset: 14169}, name: "_", }, &litMatcher{ - pos: position{line: 525, col: 40, offset: 14312}, + pos: position{line: 523, col: 40, offset: 14171}, val: ":", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 525, col: 44, offset: 14316}, + pos: position{line: 523, col: 44, offset: 14175}, name: "_", }, &labeledExpr{ - pos: position{line: 525, col: 46, offset: 14318}, + pos: position{line: 523, col: 46, offset: 14177}, label: "value", expr: &ruleRefExpr{ - pos: position{line: 525, col: 52, offset: 14324}, + pos: position{line: 523, col: 52, offset: 14183}, name: "Term", }, }, &ruleRefExpr{ - pos: position{line: 525, col: 58, offset: 14330}, + pos: position{line: 523, col: 58, offset: 14189}, name: "_", }, &litMatcher{ - pos: position{line: 525, col: 60, offset: 14332}, + pos: position{line: 523, col: 60, offset: 14191}, val: "|", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 525, col: 64, offset: 14336}, + pos: position{line: 523, col: 64, offset: 14195}, name: "_", }, &labeledExpr{ - pos: position{line: 525, col: 66, offset: 14338}, + pos: position{line: 523, col: 66, offset: 14197}, label: "body", expr: &ruleRefExpr{ - pos: position{line: 525, col: 71, offset: 14343}, + pos: position{line: 523, col: 71, offset: 14202}, name: "WhitespaceBody", }, }, &ruleRefExpr{ - pos: position{line: 525, col: 86, offset: 14358}, + pos: position{line: 523, col: 86, offset: 14217}, name: "_", }, &litMatcher{ - pos: position{line: 525, col: 88, offset: 14360}, + pos: position{line: 523, col: 88, offset: 14219}, val: "}", ignoreCase: false, }, @@ -1821,57 +1804,57 @@ var g = &grammar{ }, { name: "SetComprehension", - pos: position{line: 531, col: 1, offset: 14500}, + pos: position{line: 529, col: 1, offset: 14359}, expr: &actionExpr{ - pos: position{line: 531, col: 21, offset: 14520}, + pos: position{line: 529, col: 21, offset: 14379}, run: (*parser).callonSetComprehension1, expr: &seqExpr{ - pos: position{line: 531, col: 21, offset: 14520}, + pos: position{line: 529, col: 21, offset: 14379}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 531, col: 21, offset: 14520}, + pos: position{line: 529, col: 21, offset: 14379}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 531, col: 25, offset: 14524}, + pos: position{line: 529, col: 25, offset: 14383}, name: "_", }, &labeledExpr{ - pos: position{line: 531, col: 27, offset: 14526}, + pos: position{line: 529, col: 27, offset: 14385}, label: "term", expr: &ruleRefExpr{ - pos: position{line: 531, col: 32, offset: 14531}, + pos: position{line: 529, col: 32, offset: 14390}, name: "Term", }, }, &ruleRefExpr{ - pos: position{line: 531, col: 37, offset: 14536}, + pos: position{line: 529, col: 37, offset: 14395}, name: "_", }, &litMatcher{ - pos: position{line: 531, col: 39, offset: 14538}, + pos: position{line: 529, col: 39, offset: 14397}, val: "|", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 531, col: 43, offset: 14542}, + pos: position{line: 529, col: 43, offset: 14401}, name: "_", }, &labeledExpr{ - pos: position{line: 531, col: 45, offset: 14544}, + pos: position{line: 529, col: 45, offset: 14403}, label: "body", expr: &ruleRefExpr{ - pos: position{line: 531, col: 50, offset: 14549}, + pos: position{line: 529, col: 50, offset: 14408}, name: "WhitespaceBody", }, }, &ruleRefExpr{ - pos: position{line: 531, col: 65, offset: 14564}, + pos: position{line: 529, col: 65, offset: 14423}, name: "_", }, &litMatcher{ - pos: position{line: 531, col: 67, offset: 14566}, + pos: position{line: 529, col: 67, offset: 14425}, val: "}", ignoreCase: false, }, @@ -1881,20 +1864,20 @@ var g = &grammar{ }, { name: "Composite", - pos: position{line: 537, col: 1, offset: 14689}, + pos: position{line: 535, col: 1, offset: 14548}, expr: &choiceExpr{ - pos: position{line: 537, col: 14, offset: 14702}, + pos: position{line: 535, col: 14, offset: 14561}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 537, col: 14, offset: 14702}, + pos: position{line: 535, col: 14, offset: 14561}, name: "Object", }, &ruleRefExpr{ - pos: position{line: 537, col: 23, offset: 14711}, + pos: position{line: 535, col: 23, offset: 14570}, name: "Array", }, &ruleRefExpr{ - pos: position{line: 537, col: 31, offset: 14719}, + pos: position{line: 535, col: 31, offset: 14578}, name: "Set", }, }, @@ -1902,24 +1885,24 @@ var g = &grammar{ }, { name: "Scalar", - pos: position{line: 539, col: 1, offset: 14724}, + pos: position{line: 537, col: 1, offset: 14583}, expr: &choiceExpr{ - pos: position{line: 539, col: 11, offset: 14734}, + pos: position{line: 537, col: 11, offset: 14593}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 539, col: 11, offset: 14734}, + pos: position{line: 537, col: 11, offset: 14593}, name: "Number", }, &ruleRefExpr{ - pos: position{line: 539, col: 20, offset: 14743}, + pos: position{line: 537, col: 20, offset: 14602}, name: "String", }, &ruleRefExpr{ - pos: position{line: 539, col: 29, offset: 14752}, + pos: position{line: 537, col: 29, offset: 14611}, name: "Bool", }, &ruleRefExpr{ - pos: position{line: 539, col: 36, offset: 14759}, + pos: position{line: 537, col: 36, offset: 14618}, name: "Null", }, }, @@ -1927,20 +1910,20 @@ var g = &grammar{ }, { name: "Key", - pos: position{line: 541, col: 1, offset: 14765}, + pos: position{line: 539, col: 1, offset: 14624}, expr: &choiceExpr{ - pos: position{line: 541, col: 8, offset: 14772}, + pos: position{line: 539, col: 8, offset: 14631}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 541, col: 8, offset: 14772}, + pos: position{line: 539, col: 8, offset: 14631}, name: "Scalar", }, &ruleRefExpr{ - pos: position{line: 541, col: 17, offset: 14781}, + pos: position{line: 539, col: 17, offset: 14640}, name: "Ref", }, &ruleRefExpr{ - pos: position{line: 541, col: 23, offset: 14787}, + pos: position{line: 539, col: 23, offset: 14646}, name: "Var", }, }, @@ -1948,49 +1931,49 @@ var g = &grammar{ }, { name: "Object", - pos: position{line: 543, col: 1, offset: 14792}, + pos: position{line: 541, col: 1, offset: 14651}, expr: &actionExpr{ - pos: position{line: 543, col: 11, offset: 14802}, + pos: position{line: 541, col: 11, offset: 14661}, run: (*parser).callonObject1, expr: &seqExpr{ - pos: position{line: 543, col: 11, offset: 14802}, + pos: position{line: 541, col: 11, offset: 14661}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 543, col: 11, offset: 14802}, + pos: position{line: 541, col: 11, offset: 14661}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 543, col: 15, offset: 14806}, + pos: position{line: 541, col: 15, offset: 14665}, name: "_", }, &labeledExpr{ - pos: position{line: 543, col: 17, offset: 14808}, + pos: position{line: 541, col: 17, offset: 14667}, label: "head", expr: &zeroOrOneExpr{ - pos: position{line: 543, col: 22, offset: 14813}, + pos: position{line: 541, col: 22, offset: 14672}, expr: &seqExpr{ - pos: position{line: 543, col: 23, offset: 14814}, + pos: position{line: 541, col: 23, offset: 14673}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 543, col: 23, offset: 14814}, + pos: position{line: 541, col: 23, offset: 14673}, name: "Key", }, &ruleRefExpr{ - pos: position{line: 543, col: 27, offset: 14818}, + pos: position{line: 541, col: 27, offset: 14677}, name: "_", }, &litMatcher{ - pos: position{line: 543, col: 29, offset: 14820}, + pos: position{line: 541, col: 29, offset: 14679}, val: ":", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 543, col: 33, offset: 14824}, + pos: position{line: 541, col: 33, offset: 14683}, name: "_", }, &ruleRefExpr{ - pos: position{line: 543, col: 35, offset: 14826}, + pos: position{line: 541, col: 35, offset: 14685}, name: "Term", }, }, @@ -1998,45 +1981,45 @@ var g = &grammar{ }, }, &labeledExpr{ - pos: position{line: 543, col: 42, offset: 14833}, + pos: position{line: 541, col: 42, offset: 14692}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 543, col: 47, offset: 14838}, + pos: position{line: 541, col: 47, offset: 14697}, expr: &seqExpr{ - pos: position{line: 543, col: 49, offset: 14840}, + pos: position{line: 541, col: 49, offset: 14699}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 543, col: 49, offset: 14840}, + pos: position{line: 541, col: 49, offset: 14699}, name: "_", }, &litMatcher{ - pos: position{line: 543, col: 51, offset: 14842}, + pos: position{line: 541, col: 51, offset: 14701}, val: ",", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 543, col: 55, offset: 14846}, + pos: position{line: 541, col: 55, offset: 14705}, name: "_", }, &ruleRefExpr{ - pos: position{line: 543, col: 57, offset: 14848}, + pos: position{line: 541, col: 57, offset: 14707}, name: "Key", }, &ruleRefExpr{ - pos: position{line: 543, col: 61, offset: 14852}, + pos: position{line: 541, col: 61, offset: 14711}, name: "_", }, &litMatcher{ - pos: position{line: 543, col: 63, offset: 14854}, + pos: position{line: 541, col: 63, offset: 14713}, val: ":", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 543, col: 67, offset: 14858}, + pos: position{line: 541, col: 67, offset: 14717}, name: "_", }, &ruleRefExpr{ - pos: position{line: 543, col: 69, offset: 14860}, + pos: position{line: 541, col: 69, offset: 14719}, name: "Term", }, }, @@ -2044,23 +2027,23 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 543, col: 77, offset: 14868}, + pos: position{line: 541, col: 77, offset: 14727}, name: "_", }, &zeroOrOneExpr{ - pos: position{line: 543, col: 79, offset: 14870}, + pos: position{line: 541, col: 79, offset: 14729}, expr: &litMatcher{ - pos: position{line: 543, col: 79, offset: 14870}, + pos: position{line: 541, col: 79, offset: 14729}, val: ",", ignoreCase: false, }, }, &ruleRefExpr{ - pos: position{line: 543, col: 84, offset: 14875}, + pos: position{line: 541, col: 84, offset: 14734}, name: "_", }, &litMatcher{ - pos: position{line: 543, col: 86, offset: 14877}, + pos: position{line: 541, col: 86, offset: 14736}, val: "}", ignoreCase: false, }, @@ -2070,56 +2053,56 @@ var g = &grammar{ }, { name: "Array", - pos: position{line: 547, col: 1, offset: 14940}, + pos: position{line: 545, col: 1, offset: 14799}, expr: &actionExpr{ - pos: position{line: 547, col: 10, offset: 14949}, + pos: position{line: 545, col: 10, offset: 14808}, run: (*parser).callonArray1, expr: &seqExpr{ - pos: position{line: 547, col: 10, offset: 14949}, + pos: position{line: 545, col: 10, offset: 14808}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 547, col: 10, offset: 14949}, + pos: position{line: 545, col: 10, offset: 14808}, val: "[", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 547, col: 14, offset: 14953}, + pos: position{line: 545, col: 14, offset: 14812}, name: "_", }, &labeledExpr{ - pos: position{line: 547, col: 17, offset: 14956}, + pos: position{line: 545, col: 17, offset: 14815}, label: "head", expr: &zeroOrOneExpr{ - pos: position{line: 547, col: 22, offset: 14961}, + pos: position{line: 545, col: 22, offset: 14820}, expr: &ruleRefExpr{ - pos: position{line: 547, col: 22, offset: 14961}, + pos: position{line: 545, col: 22, offset: 14820}, name: "Term", }, }, }, &labeledExpr{ - pos: position{line: 547, col: 28, offset: 14967}, + pos: position{line: 545, col: 28, offset: 14826}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 547, col: 33, offset: 14972}, + pos: position{line: 545, col: 33, offset: 14831}, expr: &seqExpr{ - pos: position{line: 547, col: 34, offset: 14973}, + pos: position{line: 545, col: 34, offset: 14832}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 547, col: 34, offset: 14973}, + pos: position{line: 545, col: 34, offset: 14832}, name: "_", }, &litMatcher{ - pos: position{line: 547, col: 36, offset: 14975}, + pos: position{line: 545, col: 36, offset: 14834}, val: ",", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 547, col: 40, offset: 14979}, + pos: position{line: 545, col: 40, offset: 14838}, name: "_", }, &ruleRefExpr{ - pos: position{line: 547, col: 42, offset: 14981}, + pos: position{line: 545, col: 42, offset: 14840}, name: "Term", }, }, @@ -2127,23 +2110,23 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 547, col: 49, offset: 14988}, + pos: position{line: 545, col: 49, offset: 14847}, name: "_", }, &zeroOrOneExpr{ - pos: position{line: 547, col: 51, offset: 14990}, + pos: position{line: 545, col: 51, offset: 14849}, expr: &litMatcher{ - pos: position{line: 547, col: 51, offset: 14990}, + pos: position{line: 545, col: 51, offset: 14849}, val: ",", ignoreCase: false, }, }, &ruleRefExpr{ - pos: position{line: 547, col: 56, offset: 14995}, + pos: position{line: 545, col: 56, offset: 14854}, name: "_", }, &litMatcher{ - pos: position{line: 547, col: 59, offset: 14998}, + pos: position{line: 545, col: 59, offset: 14857}, val: "]", ignoreCase: false, }, @@ -2153,30 +2136,30 @@ var g = &grammar{ }, { name: "ArgTerm", - pos: position{line: 556, col: 1, offset: 15393}, + pos: position{line: 554, col: 1, offset: 15252}, expr: &actionExpr{ - pos: position{line: 556, col: 12, offset: 15404}, + pos: position{line: 554, col: 12, offset: 15263}, run: (*parser).callonArgTerm1, expr: &labeledExpr{ - pos: position{line: 556, col: 12, offset: 15404}, + pos: position{line: 554, col: 12, offset: 15263}, label: "val", expr: &choiceExpr{ - pos: position{line: 556, col: 17, offset: 15409}, + pos: position{line: 554, col: 17, offset: 15268}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 556, col: 17, offset: 15409}, + pos: position{line: 554, col: 17, offset: 15268}, name: "Scalar", }, &ruleRefExpr{ - pos: position{line: 556, col: 26, offset: 15418}, + pos: position{line: 554, col: 26, offset: 15277}, name: "Var", }, &ruleRefExpr{ - pos: position{line: 556, col: 32, offset: 15424}, + pos: position{line: 554, col: 32, offset: 15283}, name: "ArgObject", }, &ruleRefExpr{ - pos: position{line: 556, col: 44, offset: 15436}, + pos: position{line: 554, col: 44, offset: 15295}, name: "ArgArray", }, }, @@ -2186,49 +2169,49 @@ var g = &grammar{ }, { name: "ArgObject", - pos: position{line: 560, col: 1, offset: 15471}, + pos: position{line: 558, col: 1, offset: 15330}, expr: &actionExpr{ - pos: position{line: 560, col: 14, offset: 15484}, + pos: position{line: 558, col: 14, offset: 15343}, run: (*parser).callonArgObject1, expr: &seqExpr{ - pos: position{line: 560, col: 14, offset: 15484}, + pos: position{line: 558, col: 14, offset: 15343}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 560, col: 14, offset: 15484}, + pos: position{line: 558, col: 14, offset: 15343}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 560, col: 18, offset: 15488}, + pos: position{line: 558, col: 18, offset: 15347}, name: "_", }, &labeledExpr{ - pos: position{line: 560, col: 20, offset: 15490}, + pos: position{line: 558, col: 20, offset: 15349}, label: "head", expr: &zeroOrOneExpr{ - pos: position{line: 560, col: 25, offset: 15495}, + pos: position{line: 558, col: 25, offset: 15354}, expr: &seqExpr{ - pos: position{line: 560, col: 26, offset: 15496}, + pos: position{line: 558, col: 26, offset: 15355}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 560, col: 26, offset: 15496}, + pos: position{line: 558, col: 26, offset: 15355}, name: "ArgKey", }, &ruleRefExpr{ - pos: position{line: 560, col: 33, offset: 15503}, + pos: position{line: 558, col: 33, offset: 15362}, name: "_", }, &litMatcher{ - pos: position{line: 560, col: 35, offset: 15505}, + pos: position{line: 558, col: 35, offset: 15364}, val: ":", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 560, col: 39, offset: 15509}, + pos: position{line: 558, col: 39, offset: 15368}, name: "_", }, &ruleRefExpr{ - pos: position{line: 560, col: 41, offset: 15511}, + pos: position{line: 558, col: 41, offset: 15370}, name: "ArgTerm", }, }, @@ -2236,45 +2219,45 @@ var g = &grammar{ }, }, &labeledExpr{ - pos: position{line: 560, col: 51, offset: 15521}, + pos: position{line: 558, col: 51, offset: 15380}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 560, col: 56, offset: 15526}, + pos: position{line: 558, col: 56, offset: 15385}, expr: &seqExpr{ - pos: position{line: 560, col: 58, offset: 15528}, + pos: position{line: 558, col: 58, offset: 15387}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 560, col: 58, offset: 15528}, + pos: position{line: 558, col: 58, offset: 15387}, name: "_", }, &litMatcher{ - pos: position{line: 560, col: 60, offset: 15530}, + pos: position{line: 558, col: 60, offset: 15389}, val: ",", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 560, col: 64, offset: 15534}, + pos: position{line: 558, col: 64, offset: 15393}, name: "_", }, &ruleRefExpr{ - pos: position{line: 560, col: 66, offset: 15536}, + pos: position{line: 558, col: 66, offset: 15395}, name: "ArgKey", }, &ruleRefExpr{ - pos: position{line: 560, col: 73, offset: 15543}, + pos: position{line: 558, col: 73, offset: 15402}, name: "_", }, &litMatcher{ - pos: position{line: 560, col: 75, offset: 15545}, + pos: position{line: 558, col: 75, offset: 15404}, val: ":", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 560, col: 79, offset: 15549}, + pos: position{line: 558, col: 79, offset: 15408}, name: "_", }, &ruleRefExpr{ - pos: position{line: 560, col: 81, offset: 15551}, + pos: position{line: 558, col: 81, offset: 15410}, name: "ArgTerm", }, }, @@ -2282,23 +2265,23 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 560, col: 92, offset: 15562}, + pos: position{line: 558, col: 92, offset: 15421}, name: "_", }, &zeroOrOneExpr{ - pos: position{line: 560, col: 94, offset: 15564}, + pos: position{line: 558, col: 94, offset: 15423}, expr: &litMatcher{ - pos: position{line: 560, col: 94, offset: 15564}, + pos: position{line: 558, col: 94, offset: 15423}, val: ",", ignoreCase: false, }, }, &ruleRefExpr{ - pos: position{line: 560, col: 99, offset: 15569}, + pos: position{line: 558, col: 99, offset: 15428}, name: "_", }, &litMatcher{ - pos: position{line: 560, col: 101, offset: 15571}, + pos: position{line: 558, col: 101, offset: 15430}, val: "}", ignoreCase: false, }, @@ -2308,64 +2291,64 @@ var g = &grammar{ }, { name: "ArgKey", - pos: position{line: 564, col: 1, offset: 15634}, + pos: position{line: 562, col: 1, offset: 15493}, expr: &ruleRefExpr{ - pos: position{line: 564, col: 11, offset: 15644}, + pos: position{line: 562, col: 11, offset: 15503}, name: "Scalar", }, }, { name: "ArgArray", - pos: position{line: 566, col: 1, offset: 15652}, + pos: position{line: 564, col: 1, offset: 15511}, expr: &actionExpr{ - pos: position{line: 566, col: 13, offset: 15664}, + pos: position{line: 564, col: 13, offset: 15523}, run: (*parser).callonArgArray1, expr: &seqExpr{ - pos: position{line: 566, col: 13, offset: 15664}, + pos: position{line: 564, col: 13, offset: 15523}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 566, col: 13, offset: 15664}, + pos: position{line: 564, col: 13, offset: 15523}, val: "[", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 566, col: 17, offset: 15668}, + pos: position{line: 564, col: 17, offset: 15527}, name: "_", }, &labeledExpr{ - pos: position{line: 566, col: 20, offset: 15671}, + pos: position{line: 564, col: 20, offset: 15530}, label: "head", expr: &zeroOrOneExpr{ - pos: position{line: 566, col: 25, offset: 15676}, + pos: position{line: 564, col: 25, offset: 15535}, expr: &ruleRefExpr{ - pos: position{line: 566, col: 25, offset: 15676}, + pos: position{line: 564, col: 25, offset: 15535}, name: "ArgTerm", }, }, }, &labeledExpr{ - pos: position{line: 566, col: 34, offset: 15685}, + pos: position{line: 564, col: 34, offset: 15544}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 566, col: 39, offset: 15690}, + pos: position{line: 564, col: 39, offset: 15549}, expr: &seqExpr{ - pos: position{line: 566, col: 40, offset: 15691}, + pos: position{line: 564, col: 40, offset: 15550}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 566, col: 40, offset: 15691}, + pos: position{line: 564, col: 40, offset: 15550}, name: "_", }, &litMatcher{ - pos: position{line: 566, col: 42, offset: 15693}, + pos: position{line: 564, col: 42, offset: 15552}, val: ",", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 566, col: 46, offset: 15697}, + pos: position{line: 564, col: 46, offset: 15556}, name: "_", }, &ruleRefExpr{ - pos: position{line: 566, col: 48, offset: 15699}, + pos: position{line: 564, col: 48, offset: 15558}, name: "ArgTerm", }, }, @@ -2373,23 +2356,23 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 566, col: 58, offset: 15709}, + pos: position{line: 564, col: 58, offset: 15568}, name: "_", }, &zeroOrOneExpr{ - pos: position{line: 566, col: 60, offset: 15711}, + pos: position{line: 564, col: 60, offset: 15570}, expr: &litMatcher{ - pos: position{line: 566, col: 60, offset: 15711}, + pos: position{line: 564, col: 60, offset: 15570}, val: ",", ignoreCase: false, }, }, &ruleRefExpr{ - pos: position{line: 566, col: 65, offset: 15716}, + pos: position{line: 564, col: 65, offset: 15575}, name: "_", }, &litMatcher{ - pos: position{line: 566, col: 68, offset: 15719}, + pos: position{line: 564, col: 68, offset: 15578}, val: "]", ignoreCase: false, }, @@ -2399,16 +2382,16 @@ var g = &grammar{ }, { name: "Set", - pos: position{line: 570, col: 1, offset: 15781}, + pos: position{line: 568, col: 1, offset: 15640}, expr: &choiceExpr{ - pos: position{line: 570, col: 8, offset: 15788}, + pos: position{line: 568, col: 8, offset: 15647}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 570, col: 8, offset: 15788}, + pos: position{line: 568, col: 8, offset: 15647}, name: "SetEmpty", }, &ruleRefExpr{ - pos: position{line: 570, col: 19, offset: 15799}, + pos: position{line: 568, col: 19, offset: 15658}, name: "SetNonEmpty", }, }, @@ -2416,24 +2399,24 @@ var g = &grammar{ }, { name: "SetEmpty", - pos: position{line: 572, col: 1, offset: 15812}, + pos: position{line: 570, col: 1, offset: 15671}, expr: &actionExpr{ - pos: position{line: 572, col: 13, offset: 15824}, + pos: position{line: 570, col: 13, offset: 15683}, run: (*parser).callonSetEmpty1, expr: &seqExpr{ - pos: position{line: 572, col: 13, offset: 15824}, + pos: position{line: 570, col: 13, offset: 15683}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 572, col: 13, offset: 15824}, + pos: position{line: 570, col: 13, offset: 15683}, val: "set(", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 572, col: 20, offset: 15831}, + pos: position{line: 570, col: 20, offset: 15690}, name: "_", }, &litMatcher{ - pos: position{line: 572, col: 22, offset: 15833}, + pos: position{line: 570, col: 22, offset: 15692}, val: ")", ignoreCase: false, }, @@ -2443,53 +2426,53 @@ var g = &grammar{ }, { name: "SetNonEmpty", - pos: position{line: 578, col: 1, offset: 15921}, + pos: position{line: 576, col: 1, offset: 15780}, expr: &actionExpr{ - pos: position{line: 578, col: 16, offset: 15936}, + pos: position{line: 576, col: 16, offset: 15795}, run: (*parser).callonSetNonEmpty1, expr: &seqExpr{ - pos: position{line: 578, col: 16, offset: 15936}, + pos: position{line: 576, col: 16, offset: 15795}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 578, col: 16, offset: 15936}, + pos: position{line: 576, col: 16, offset: 15795}, val: "{", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 578, col: 20, offset: 15940}, + pos: position{line: 576, col: 20, offset: 15799}, name: "_", }, &labeledExpr{ - pos: position{line: 578, col: 22, offset: 15942}, + pos: position{line: 576, col: 22, offset: 15801}, label: "head", expr: &ruleRefExpr{ - pos: position{line: 578, col: 27, offset: 15947}, + pos: position{line: 576, col: 27, offset: 15806}, name: "Term", }, }, &labeledExpr{ - pos: position{line: 578, col: 32, offset: 15952}, + pos: position{line: 576, col: 32, offset: 15811}, label: "tail", expr: &zeroOrMoreExpr{ - pos: position{line: 578, col: 37, offset: 15957}, + pos: position{line: 576, col: 37, offset: 15816}, expr: &seqExpr{ - pos: position{line: 578, col: 38, offset: 15958}, + pos: position{line: 576, col: 38, offset: 15817}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 578, col: 38, offset: 15958}, + pos: position{line: 576, col: 38, offset: 15817}, name: "_", }, &litMatcher{ - pos: position{line: 578, col: 40, offset: 15960}, + pos: position{line: 576, col: 40, offset: 15819}, val: ",", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 578, col: 44, offset: 15964}, + pos: position{line: 576, col: 44, offset: 15823}, name: "_", }, &ruleRefExpr{ - pos: position{line: 578, col: 46, offset: 15966}, + pos: position{line: 576, col: 46, offset: 15825}, name: "Term", }, }, @@ -2497,23 +2480,23 @@ var g = &grammar{ }, }, &ruleRefExpr{ - pos: position{line: 578, col: 53, offset: 15973}, + pos: position{line: 576, col: 53, offset: 15832}, name: "_", }, &zeroOrOneExpr{ - pos: position{line: 578, col: 55, offset: 15975}, + pos: position{line: 576, col: 55, offset: 15834}, expr: &litMatcher{ - pos: position{line: 578, col: 55, offset: 15975}, + pos: position{line: 576, col: 55, offset: 15834}, val: ",", ignoreCase: false, }, }, &ruleRefExpr{ - pos: position{line: 578, col: 60, offset: 15980}, + pos: position{line: 576, col: 60, offset: 15839}, name: "_", }, &litMatcher{ - pos: position{line: 578, col: 62, offset: 15982}, + pos: position{line: 576, col: 62, offset: 15841}, val: "}", ignoreCase: false, }, @@ -2523,35 +2506,35 @@ var g = &grammar{ }, { name: "Ref", - pos: position{line: 595, col: 1, offset: 16387}, + pos: position{line: 593, col: 1, offset: 16246}, expr: &actionExpr{ - pos: position{line: 595, col: 8, offset: 16394}, + pos: position{line: 593, col: 8, offset: 16253}, run: (*parser).callonRef1, expr: &seqExpr{ - pos: position{line: 595, col: 8, offset: 16394}, + pos: position{line: 593, col: 8, offset: 16253}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 595, col: 8, offset: 16394}, + pos: position{line: 593, col: 8, offset: 16253}, label: "head", expr: &ruleRefExpr{ - pos: position{line: 595, col: 13, offset: 16399}, + pos: position{line: 593, col: 13, offset: 16258}, name: "Var", }, }, &labeledExpr{ - pos: position{line: 595, col: 17, offset: 16403}, + pos: position{line: 593, col: 17, offset: 16262}, label: "tail", expr: &oneOrMoreExpr{ - pos: position{line: 595, col: 22, offset: 16408}, + pos: position{line: 593, col: 22, offset: 16267}, expr: &choiceExpr{ - pos: position{line: 595, col: 24, offset: 16410}, + pos: position{line: 593, col: 24, offset: 16269}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 595, col: 24, offset: 16410}, + pos: position{line: 593, col: 24, offset: 16269}, name: "RefDot", }, &ruleRefExpr{ - pos: position{line: 595, col: 33, offset: 16419}, + pos: position{line: 593, col: 33, offset: 16278}, name: "RefBracket", }, }, @@ -2564,23 +2547,23 @@ var g = &grammar{ }, { name: "RefDot", - pos: position{line: 608, col: 1, offset: 16658}, + pos: position{line: 606, col: 1, offset: 16517}, expr: &actionExpr{ - pos: position{line: 608, col: 11, offset: 16668}, + pos: position{line: 606, col: 11, offset: 16527}, run: (*parser).callonRefDot1, expr: &seqExpr{ - pos: position{line: 608, col: 11, offset: 16668}, + pos: position{line: 606, col: 11, offset: 16527}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 608, col: 11, offset: 16668}, + pos: position{line: 606, col: 11, offset: 16527}, val: ".", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 608, col: 15, offset: 16672}, + pos: position{line: 606, col: 15, offset: 16531}, label: "val", expr: &ruleRefExpr{ - pos: position{line: 608, col: 19, offset: 16676}, + pos: position{line: 606, col: 19, offset: 16535}, name: "Var", }, }, @@ -2590,45 +2573,45 @@ var g = &grammar{ }, { name: "RefBracket", - pos: position{line: 615, col: 1, offset: 16895}, + pos: position{line: 613, col: 1, offset: 16754}, expr: &actionExpr{ - pos: position{line: 615, col: 15, offset: 16909}, + pos: position{line: 613, col: 15, offset: 16768}, run: (*parser).callonRefBracket1, expr: &seqExpr{ - pos: position{line: 615, col: 15, offset: 16909}, + pos: position{line: 613, col: 15, offset: 16768}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 615, col: 15, offset: 16909}, + pos: position{line: 613, col: 15, offset: 16768}, val: "[", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 615, col: 19, offset: 16913}, + pos: position{line: 613, col: 19, offset: 16772}, label: "val", expr: &choiceExpr{ - pos: position{line: 615, col: 24, offset: 16918}, + pos: position{line: 613, col: 24, offset: 16777}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 615, col: 24, offset: 16918}, + pos: position{line: 613, col: 24, offset: 16777}, name: "Composite", }, &ruleRefExpr{ - pos: position{line: 615, col: 36, offset: 16930}, + pos: position{line: 613, col: 36, offset: 16789}, name: "Ref", }, &ruleRefExpr{ - pos: position{line: 615, col: 42, offset: 16936}, + pos: position{line: 613, col: 42, offset: 16795}, name: "Scalar", }, &ruleRefExpr{ - pos: position{line: 615, col: 51, offset: 16945}, + pos: position{line: 613, col: 51, offset: 16804}, name: "Var", }, }, }, }, &litMatcher{ - pos: position{line: 615, col: 56, offset: 16950}, + pos: position{line: 613, col: 56, offset: 16809}, val: "]", ignoreCase: false, }, @@ -2638,15 +2621,15 @@ var g = &grammar{ }, { name: "Var", - pos: position{line: 619, col: 1, offset: 16979}, + pos: position{line: 617, col: 1, offset: 16838}, expr: &actionExpr{ - pos: position{line: 619, col: 8, offset: 16986}, + pos: position{line: 617, col: 8, offset: 16845}, run: (*parser).callonVar1, expr: &labeledExpr{ - pos: position{line: 619, col: 8, offset: 16986}, + pos: position{line: 617, col: 8, offset: 16845}, label: "val", expr: &ruleRefExpr{ - pos: position{line: 619, col: 12, offset: 16990}, + pos: position{line: 617, col: 12, offset: 16849}, name: "VarChecked", }, }, @@ -2654,20 +2637,20 @@ var g = &grammar{ }, { name: "VarChecked", - pos: position{line: 624, col: 1, offset: 17112}, + pos: position{line: 622, col: 1, offset: 16971}, expr: &seqExpr{ - pos: position{line: 624, col: 15, offset: 17126}, + pos: position{line: 622, col: 15, offset: 16985}, exprs: []interface{}{ &labeledExpr{ - pos: position{line: 624, col: 15, offset: 17126}, + pos: position{line: 622, col: 15, offset: 16985}, label: "val", expr: &ruleRefExpr{ - pos: position{line: 624, col: 19, offset: 17130}, + pos: position{line: 622, col: 19, offset: 16989}, name: "VarUnchecked", }, }, ¬CodeExpr{ - pos: position{line: 624, col: 32, offset: 17143}, + pos: position{line: 622, col: 32, offset: 17002}, run: (*parser).callonVarChecked4, }, }, @@ -2675,28 +2658,28 @@ var g = &grammar{ }, { name: "VarUnchecked", - pos: position{line: 628, col: 1, offset: 17208}, + pos: position{line: 626, col: 1, offset: 17067}, expr: &actionExpr{ - pos: position{line: 628, col: 17, offset: 17224}, + pos: position{line: 626, col: 17, offset: 17083}, run: (*parser).callonVarUnchecked1, expr: &seqExpr{ - pos: position{line: 628, col: 17, offset: 17224}, + pos: position{line: 626, col: 17, offset: 17083}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 628, col: 17, offset: 17224}, + pos: position{line: 626, col: 17, offset: 17083}, name: "AsciiLetter", }, &zeroOrMoreExpr{ - pos: position{line: 628, col: 29, offset: 17236}, + pos: position{line: 626, col: 29, offset: 17095}, expr: &choiceExpr{ - pos: position{line: 628, col: 30, offset: 17237}, + pos: position{line: 626, col: 30, offset: 17096}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 628, col: 30, offset: 17237}, + pos: position{line: 626, col: 30, offset: 17096}, name: "AsciiLetter", }, &ruleRefExpr{ - pos: position{line: 628, col: 44, offset: 17251}, + pos: position{line: 626, col: 44, offset: 17110}, name: "DecimalDigit", }, }, @@ -2708,30 +2691,30 @@ var g = &grammar{ }, { name: "Number", - pos: position{line: 635, col: 1, offset: 17394}, + pos: position{line: 633, col: 1, offset: 17253}, expr: &actionExpr{ - pos: position{line: 635, col: 11, offset: 17404}, + pos: position{line: 633, col: 11, offset: 17263}, run: (*parser).callonNumber1, expr: &seqExpr{ - pos: position{line: 635, col: 11, offset: 17404}, + pos: position{line: 633, col: 11, offset: 17263}, exprs: []interface{}{ &zeroOrOneExpr{ - pos: position{line: 635, col: 11, offset: 17404}, + pos: position{line: 633, col: 11, offset: 17263}, expr: &litMatcher{ - pos: position{line: 635, col: 11, offset: 17404}, + pos: position{line: 633, col: 11, offset: 17263}, val: "-", ignoreCase: false, }, }, &choiceExpr{ - pos: position{line: 635, col: 18, offset: 17411}, + pos: position{line: 633, col: 18, offset: 17270}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 635, col: 18, offset: 17411}, + pos: position{line: 633, col: 18, offset: 17270}, name: "Float", }, &ruleRefExpr{ - pos: position{line: 635, col: 26, offset: 17419}, + pos: position{line: 633, col: 26, offset: 17278}, name: "Integer", }, }, @@ -2742,16 +2725,16 @@ var g = &grammar{ }, { name: "Float", - pos: position{line: 648, col: 1, offset: 17810}, + pos: position{line: 646, col: 1, offset: 17669}, expr: &choiceExpr{ - pos: position{line: 648, col: 10, offset: 17819}, + pos: position{line: 646, col: 10, offset: 17678}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 648, col: 10, offset: 17819}, + pos: position{line: 646, col: 10, offset: 17678}, name: "ExponentFloat", }, &ruleRefExpr{ - pos: position{line: 648, col: 26, offset: 17835}, + pos: position{line: 646, col: 26, offset: 17694}, name: "PointFloat", }, }, @@ -2759,25 +2742,25 @@ var g = &grammar{ }, { name: "ExponentFloat", - pos: position{line: 650, col: 1, offset: 17847}, + pos: position{line: 648, col: 1, offset: 17706}, expr: &seqExpr{ - pos: position{line: 650, col: 18, offset: 17864}, + pos: position{line: 648, col: 18, offset: 17723}, exprs: []interface{}{ &choiceExpr{ - pos: position{line: 650, col: 20, offset: 17866}, + pos: position{line: 648, col: 20, offset: 17725}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 650, col: 20, offset: 17866}, + pos: position{line: 648, col: 20, offset: 17725}, name: "PointFloat", }, &ruleRefExpr{ - pos: position{line: 650, col: 33, offset: 17879}, + pos: position{line: 648, col: 33, offset: 17738}, name: "Integer", }, }, }, &ruleRefExpr{ - pos: position{line: 650, col: 43, offset: 17889}, + pos: position{line: 648, col: 43, offset: 17748}, name: "Exponent", }, }, @@ -2785,19 +2768,19 @@ var g = &grammar{ }, { name: "PointFloat", - pos: position{line: 652, col: 1, offset: 17899}, + pos: position{line: 650, col: 1, offset: 17758}, expr: &seqExpr{ - pos: position{line: 652, col: 15, offset: 17913}, + pos: position{line: 650, col: 15, offset: 17772}, exprs: []interface{}{ &zeroOrOneExpr{ - pos: position{line: 652, col: 15, offset: 17913}, + pos: position{line: 650, col: 15, offset: 17772}, expr: &ruleRefExpr{ - pos: position{line: 652, col: 15, offset: 17913}, + pos: position{line: 650, col: 15, offset: 17772}, name: "Integer", }, }, &ruleRefExpr{ - pos: position{line: 652, col: 24, offset: 17922}, + pos: position{line: 650, col: 24, offset: 17781}, name: "Fraction", }, }, @@ -2805,19 +2788,19 @@ var g = &grammar{ }, { name: "Fraction", - pos: position{line: 654, col: 1, offset: 17932}, + pos: position{line: 652, col: 1, offset: 17791}, expr: &seqExpr{ - pos: position{line: 654, col: 13, offset: 17944}, + pos: position{line: 652, col: 13, offset: 17803}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 654, col: 13, offset: 17944}, + pos: position{line: 652, col: 13, offset: 17803}, val: ".", ignoreCase: false, }, &oneOrMoreExpr{ - pos: position{line: 654, col: 17, offset: 17948}, + pos: position{line: 652, col: 17, offset: 17807}, expr: &ruleRefExpr{ - pos: position{line: 654, col: 17, offset: 17948}, + pos: position{line: 652, col: 17, offset: 17807}, name: "DecimalDigit", }, }, @@ -2826,19 +2809,19 @@ var g = &grammar{ }, { name: "Exponent", - pos: position{line: 656, col: 1, offset: 17963}, + pos: position{line: 654, col: 1, offset: 17822}, expr: &seqExpr{ - pos: position{line: 656, col: 13, offset: 17975}, + pos: position{line: 654, col: 13, offset: 17834}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 656, col: 13, offset: 17975}, + pos: position{line: 654, col: 13, offset: 17834}, val: "e", ignoreCase: true, }, &zeroOrOneExpr{ - pos: position{line: 656, col: 18, offset: 17980}, + pos: position{line: 654, col: 18, offset: 17839}, expr: &charClassMatcher{ - pos: position{line: 656, col: 18, offset: 17980}, + pos: position{line: 654, col: 18, offset: 17839}, val: "[+-]", chars: []rune{'+', '-'}, ignoreCase: false, @@ -2846,9 +2829,9 @@ var g = &grammar{ }, }, &oneOrMoreExpr{ - pos: position{line: 656, col: 24, offset: 17986}, + pos: position{line: 654, col: 24, offset: 17845}, expr: &ruleRefExpr{ - pos: position{line: 656, col: 24, offset: 17986}, + pos: position{line: 654, col: 24, offset: 17845}, name: "DecimalDigit", }, }, @@ -2857,26 +2840,26 @@ var g = &grammar{ }, { name: "Integer", - pos: position{line: 658, col: 1, offset: 18001}, + pos: position{line: 656, col: 1, offset: 17860}, expr: &choiceExpr{ - pos: position{line: 658, col: 12, offset: 18012}, + pos: position{line: 656, col: 12, offset: 17871}, alternatives: []interface{}{ &litMatcher{ - pos: position{line: 658, col: 12, offset: 18012}, + pos: position{line: 656, col: 12, offset: 17871}, val: "0", ignoreCase: false, }, &seqExpr{ - pos: position{line: 658, col: 20, offset: 18020}, + pos: position{line: 656, col: 20, offset: 17879}, exprs: []interface{}{ &ruleRefExpr{ - pos: position{line: 658, col: 20, offset: 18020}, + pos: position{line: 656, col: 20, offset: 17879}, name: "NonZeroDecimalDigit", }, &zeroOrMoreExpr{ - pos: position{line: 658, col: 40, offset: 18040}, + pos: position{line: 656, col: 40, offset: 17899}, expr: &ruleRefExpr{ - pos: position{line: 658, col: 40, offset: 18040}, + pos: position{line: 656, col: 40, offset: 17899}, name: "DecimalDigit", }, }, @@ -2887,16 +2870,16 @@ var g = &grammar{ }, { name: "String", - pos: position{line: 660, col: 1, offset: 18057}, + pos: position{line: 658, col: 1, offset: 17916}, expr: &choiceExpr{ - pos: position{line: 660, col: 11, offset: 18067}, + pos: position{line: 658, col: 11, offset: 17926}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 660, col: 11, offset: 18067}, + pos: position{line: 658, col: 11, offset: 17926}, name: "QuotedString", }, &ruleRefExpr{ - pos: position{line: 660, col: 26, offset: 18082}, + pos: position{line: 658, col: 26, offset: 17941}, name: "RawString", }, }, @@ -2904,27 +2887,27 @@ var g = &grammar{ }, { name: "QuotedString", - pos: position{line: 662, col: 1, offset: 18093}, + pos: position{line: 660, col: 1, offset: 17952}, expr: &actionExpr{ - pos: position{line: 662, col: 17, offset: 18109}, + pos: position{line: 660, col: 17, offset: 17968}, run: (*parser).callonQuotedString1, expr: &seqExpr{ - pos: position{line: 662, col: 17, offset: 18109}, + pos: position{line: 660, col: 17, offset: 17968}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 662, col: 17, offset: 18109}, + pos: position{line: 660, col: 17, offset: 17968}, val: "\"", ignoreCase: false, }, &zeroOrMoreExpr{ - pos: position{line: 662, col: 21, offset: 18113}, + pos: position{line: 660, col: 21, offset: 17972}, expr: &ruleRefExpr{ - pos: position{line: 662, col: 21, offset: 18113}, + pos: position{line: 660, col: 21, offset: 17972}, name: "Char", }, }, &litMatcher{ - pos: position{line: 662, col: 27, offset: 18119}, + pos: position{line: 660, col: 27, offset: 17978}, val: "\"", ignoreCase: false, }, @@ -2934,22 +2917,22 @@ var g = &grammar{ }, { name: "RawString", - pos: position{line: 670, col: 1, offset: 18274}, + pos: position{line: 668, col: 1, offset: 18133}, expr: &actionExpr{ - pos: position{line: 670, col: 14, offset: 18287}, + pos: position{line: 668, col: 14, offset: 18146}, run: (*parser).callonRawString1, expr: &seqExpr{ - pos: position{line: 670, col: 14, offset: 18287}, + pos: position{line: 668, col: 14, offset: 18146}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 670, col: 14, offset: 18287}, + pos: position{line: 668, col: 14, offset: 18146}, val: "`", ignoreCase: false, }, &zeroOrMoreExpr{ - pos: position{line: 670, col: 18, offset: 18291}, + pos: position{line: 668, col: 18, offset: 18150}, expr: &charClassMatcher{ - pos: position{line: 670, col: 18, offset: 18291}, + pos: position{line: 668, col: 18, offset: 18150}, val: "[^`]", chars: []rune{'`'}, ignoreCase: false, @@ -2957,7 +2940,7 @@ var g = &grammar{ }, }, &litMatcher{ - pos: position{line: 670, col: 24, offset: 18297}, + pos: position{line: 668, col: 24, offset: 18156}, val: "`", ignoreCase: false, }, @@ -2967,24 +2950,24 @@ var g = &grammar{ }, { name: "Bool", - pos: position{line: 679, col: 1, offset: 18464}, + pos: position{line: 677, col: 1, offset: 18323}, expr: &choiceExpr{ - pos: position{line: 679, col: 9, offset: 18472}, + pos: position{line: 677, col: 9, offset: 18331}, alternatives: []interface{}{ &actionExpr{ - pos: position{line: 679, col: 9, offset: 18472}, + pos: position{line: 677, col: 9, offset: 18331}, run: (*parser).callonBool2, expr: &litMatcher{ - pos: position{line: 679, col: 9, offset: 18472}, + pos: position{line: 677, col: 9, offset: 18331}, val: "true", ignoreCase: false, }, }, &actionExpr{ - pos: position{line: 683, col: 5, offset: 18572}, + pos: position{line: 681, col: 5, offset: 18431}, run: (*parser).callonBool4, expr: &litMatcher{ - pos: position{line: 683, col: 5, offset: 18572}, + pos: position{line: 681, col: 5, offset: 18431}, val: "false", ignoreCase: false, }, @@ -2994,12 +2977,12 @@ var g = &grammar{ }, { name: "Null", - pos: position{line: 689, col: 1, offset: 18673}, + pos: position{line: 687, col: 1, offset: 18532}, expr: &actionExpr{ - pos: position{line: 689, col: 9, offset: 18681}, + pos: position{line: 687, col: 9, offset: 18540}, run: (*parser).callonNull1, expr: &litMatcher{ - pos: position{line: 689, col: 9, offset: 18681}, + pos: position{line: 687, col: 9, offset: 18540}, val: "null", ignoreCase: false, }, @@ -3007,9 +2990,9 @@ var g = &grammar{ }, { name: "AsciiLetter", - pos: position{line: 695, col: 1, offset: 18776}, + pos: position{line: 693, col: 1, offset: 18635}, expr: &charClassMatcher{ - pos: position{line: 695, col: 16, offset: 18791}, + pos: position{line: 693, col: 16, offset: 18650}, val: "[A-Za-z_]", chars: []rune{'_'}, ranges: []rune{'A', 'Z', 'a', 'z'}, @@ -3019,35 +3002,35 @@ var g = &grammar{ }, { name: "Char", - pos: position{line: 697, col: 1, offset: 18802}, + pos: position{line: 695, col: 1, offset: 18661}, expr: &choiceExpr{ - pos: position{line: 697, col: 9, offset: 18810}, + pos: position{line: 695, col: 9, offset: 18669}, alternatives: []interface{}{ &seqExpr{ - pos: position{line: 697, col: 11, offset: 18812}, + pos: position{line: 695, col: 11, offset: 18671}, exprs: []interface{}{ ¬Expr{ - pos: position{line: 697, col: 11, offset: 18812}, + pos: position{line: 695, col: 11, offset: 18671}, expr: &ruleRefExpr{ - pos: position{line: 697, col: 12, offset: 18813}, + pos: position{line: 695, col: 12, offset: 18672}, name: "EscapedChar", }, }, &anyMatcher{ - line: 697, col: 24, offset: 18825, + line: 695, col: 24, offset: 18684, }, }, }, &seqExpr{ - pos: position{line: 697, col: 32, offset: 18833}, + pos: position{line: 695, col: 32, offset: 18692}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 697, col: 32, offset: 18833}, + pos: position{line: 695, col: 32, offset: 18692}, val: "\\", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 697, col: 37, offset: 18838}, + pos: position{line: 695, col: 37, offset: 18697}, name: "EscapeSequence", }, }, @@ -3057,9 +3040,9 @@ var g = &grammar{ }, { name: "EscapedChar", - pos: position{line: 699, col: 1, offset: 18856}, + pos: position{line: 697, col: 1, offset: 18715}, expr: &charClassMatcher{ - pos: position{line: 699, col: 16, offset: 18871}, + pos: position{line: 697, col: 16, offset: 18730}, val: "[\\x00-\\x1f\"\\\\]", chars: []rune{'"', '\\'}, ranges: []rune{'\x00', '\x1f'}, @@ -3069,16 +3052,16 @@ var g = &grammar{ }, { name: "EscapeSequence", - pos: position{line: 701, col: 1, offset: 18887}, + pos: position{line: 699, col: 1, offset: 18746}, expr: &choiceExpr{ - pos: position{line: 701, col: 19, offset: 18905}, + pos: position{line: 699, col: 19, offset: 18764}, alternatives: []interface{}{ &ruleRefExpr{ - pos: position{line: 701, col: 19, offset: 18905}, + pos: position{line: 699, col: 19, offset: 18764}, name: "SingleCharEscape", }, &ruleRefExpr{ - pos: position{line: 701, col: 38, offset: 18924}, + pos: position{line: 699, col: 38, offset: 18783}, name: "UnicodeEscape", }, }, @@ -3086,9 +3069,9 @@ var g = &grammar{ }, { name: "SingleCharEscape", - pos: position{line: 703, col: 1, offset: 18939}, + pos: position{line: 701, col: 1, offset: 18798}, expr: &charClassMatcher{ - pos: position{line: 703, col: 21, offset: 18959}, + pos: position{line: 701, col: 21, offset: 18818}, val: "[ \" \\\\ / b f n r t ]", chars: []rune{' ', '"', ' ', '\\', ' ', '/', ' ', 'b', ' ', 'f', ' ', 'n', ' ', 'r', ' ', 't', ' '}, ignoreCase: false, @@ -3097,29 +3080,29 @@ var g = &grammar{ }, { name: "UnicodeEscape", - pos: position{line: 705, col: 1, offset: 18981}, + pos: position{line: 703, col: 1, offset: 18840}, expr: &seqExpr{ - pos: position{line: 705, col: 18, offset: 18998}, + pos: position{line: 703, col: 18, offset: 18857}, exprs: []interface{}{ &litMatcher{ - pos: position{line: 705, col: 18, offset: 18998}, + pos: position{line: 703, col: 18, offset: 18857}, val: "u", ignoreCase: false, }, &ruleRefExpr{ - pos: position{line: 705, col: 22, offset: 19002}, + pos: position{line: 703, col: 22, offset: 18861}, name: "HexDigit", }, &ruleRefExpr{ - pos: position{line: 705, col: 31, offset: 19011}, + pos: position{line: 703, col: 31, offset: 18870}, name: "HexDigit", }, &ruleRefExpr{ - pos: position{line: 705, col: 40, offset: 19020}, + pos: position{line: 703, col: 40, offset: 18879}, name: "HexDigit", }, &ruleRefExpr{ - pos: position{line: 705, col: 49, offset: 19029}, + pos: position{line: 703, col: 49, offset: 18888}, name: "HexDigit", }, }, @@ -3127,9 +3110,9 @@ var g = &grammar{ }, { name: "DecimalDigit", - pos: position{line: 707, col: 1, offset: 19039}, + pos: position{line: 705, col: 1, offset: 18898}, expr: &charClassMatcher{ - pos: position{line: 707, col: 17, offset: 19055}, + pos: position{line: 705, col: 17, offset: 18914}, val: "[0-9]", ranges: []rune{'0', '9'}, ignoreCase: false, @@ -3138,9 +3121,9 @@ var g = &grammar{ }, { name: "NonZeroDecimalDigit", - pos: position{line: 709, col: 1, offset: 19062}, + pos: position{line: 707, col: 1, offset: 18921}, expr: &charClassMatcher{ - pos: position{line: 709, col: 24, offset: 19085}, + pos: position{line: 707, col: 24, offset: 18944}, val: "[1-9]", ranges: []rune{'1', '9'}, ignoreCase: false, @@ -3149,9 +3132,9 @@ var g = &grammar{ }, { name: "HexDigit", - pos: position{line: 711, col: 1, offset: 19092}, + pos: position{line: 709, col: 1, offset: 18951}, expr: &charClassMatcher{ - pos: position{line: 711, col: 13, offset: 19104}, + pos: position{line: 709, col: 13, offset: 18963}, val: "[0-9a-fA-F]", ranges: []rune{'0', '9', 'a', 'f', 'A', 'F'}, ignoreCase: false, @@ -3161,11 +3144,11 @@ var g = &grammar{ { name: "ws", displayName: "\"whitespace\"", - pos: position{line: 713, col: 1, offset: 19117}, + pos: position{line: 711, col: 1, offset: 18976}, expr: &oneOrMoreExpr{ - pos: position{line: 713, col: 20, offset: 19136}, + pos: position{line: 711, col: 20, offset: 18995}, expr: &charClassMatcher{ - pos: position{line: 713, col: 20, offset: 19136}, + pos: position{line: 711, col: 20, offset: 18995}, val: "[ \\t\\r\\n]", chars: []rune{' ', '\t', '\r', '\n'}, ignoreCase: false, @@ -3176,21 +3159,21 @@ var g = &grammar{ { name: "_", displayName: "\"whitespace\"", - pos: position{line: 715, col: 1, offset: 19148}, + pos: position{line: 713, col: 1, offset: 19007}, expr: &zeroOrMoreExpr{ - pos: position{line: 715, col: 19, offset: 19166}, + pos: position{line: 713, col: 19, offset: 19025}, expr: &choiceExpr{ - pos: position{line: 715, col: 21, offset: 19168}, + pos: position{line: 713, col: 21, offset: 19027}, alternatives: []interface{}{ &charClassMatcher{ - pos: position{line: 715, col: 21, offset: 19168}, + pos: position{line: 713, col: 21, offset: 19027}, val: "[ \\t\\r\\n]", chars: []rune{' ', '\t', '\r', '\n'}, ignoreCase: false, inverted: false, }, &ruleRefExpr{ - pos: position{line: 715, col: 33, offset: 19180}, + pos: position{line: 713, col: 33, offset: 19039}, name: "Comment", }, }, @@ -3199,17 +3182,17 @@ var g = &grammar{ }, { name: "Comment", - pos: position{line: 717, col: 1, offset: 19192}, + pos: position{line: 715, col: 1, offset: 19051}, expr: &actionExpr{ - pos: position{line: 717, col: 12, offset: 19203}, + pos: position{line: 715, col: 12, offset: 19062}, run: (*parser).callonComment1, expr: &seqExpr{ - pos: position{line: 717, col: 12, offset: 19203}, + pos: position{line: 715, col: 12, offset: 19062}, exprs: []interface{}{ &zeroOrMoreExpr{ - pos: position{line: 717, col: 12, offset: 19203}, + pos: position{line: 715, col: 12, offset: 19062}, expr: &charClassMatcher{ - pos: position{line: 717, col: 12, offset: 19203}, + pos: position{line: 715, col: 12, offset: 19062}, val: "[ \\t]", chars: []rune{' ', '\t'}, ignoreCase: false, @@ -3217,17 +3200,17 @@ var g = &grammar{ }, }, &litMatcher{ - pos: position{line: 717, col: 19, offset: 19210}, + pos: position{line: 715, col: 19, offset: 19069}, val: "#", ignoreCase: false, }, &labeledExpr{ - pos: position{line: 717, col: 23, offset: 19214}, + pos: position{line: 715, col: 23, offset: 19073}, label: "text", expr: &zeroOrMoreExpr{ - pos: position{line: 717, col: 28, offset: 19219}, + pos: position{line: 715, col: 28, offset: 19078}, expr: &charClassMatcher{ - pos: position{line: 717, col: 28, offset: 19219}, + pos: position{line: 715, col: 28, offset: 19078}, val: "[^\\r\\n]", chars: []rune{'\r', '\n'}, ignoreCase: false, @@ -3241,11 +3224,11 @@ var g = &grammar{ }, { name: "EOF", - pos: position{line: 728, col: 1, offset: 19495}, + pos: position{line: 726, col: 1, offset: 19354}, expr: ¬Expr{ - pos: position{line: 728, col: 8, offset: 19502}, + pos: position{line: 726, col: 8, offset: 19361}, expr: &anyMatcher{ - line: 728, col: 9, offset: 19503, + line: 726, col: 9, offset: 19362, }, }, }, @@ -3724,8 +3707,8 @@ func (c *current) onArithInfixOp1(val interface{}) (interface{}, error) { op = string(b.Name) } } - operator := StringTerm(op) - operator.Location = currentLocation(c) + loc := currentLocation(c) + operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) return operator, nil } @@ -3752,8 +3735,8 @@ func (c *current) onInfixOp1(val interface{}) (interface{}, error) { op = string(b.Name) } } - operator := StringTerm(op) - operator.Location = currentLocation(c) + loc := currentLocation(c) + operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) return operator, nil } @@ -3763,7 +3746,7 @@ func (p *parser) callonInfixOp1() (interface{}, error) { return p.cur.onInfixOp1(stack["val"]) } -func (c *current) onBuiltin1(name, head, tail interface{}) (interface{}, error) { +func (c *current) onCall1(name, head, tail interface{}) (interface{}, error) { buf := []*Term{name.(*Term)} if head == nil { return buf, nil @@ -3779,30 +3762,28 @@ func (c *current) onBuiltin1(name, head, tail interface{}) (interface{}, error) return buf, nil } -func (p *parser) callonBuiltin1() (interface{}, error) { +func (p *parser) callonCall1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onBuiltin1(stack["name"], stack["head"], stack["tail"]) + return p.cur.onCall1(stack["name"], stack["head"], stack["tail"]) } -func (c *current) onBuiltinName1(head, tail interface{}) (interface{}, error) { - tailSlice := tail.([]interface{}) - buf := make([]string, 1+len(tailSlice)) - buf[0] = string(head.(*Term).Value.(Var)) - for i := range tailSlice { - elem := tailSlice[i] - part := elem.([]interface{})[1].(*Term).Value.(Var) - buf[i+1] = string(part) +func (c *current) onOperator1(val interface{}) (interface{}, error) { + term := val.(*Term) + switch term.Value.(type) { + case Ref: + return val, nil + case Var: + return RefTerm(term).SetLocation(currentLocation(c)), nil + default: + panic("unreachable") } - name := StringTerm(strings.Join(buf, ".")) - name.Location = currentLocation(c) - return name, nil } -func (p *parser) callonBuiltinName1() (interface{}, error) { +func (p *parser) callonOperator1() (interface{}, error) { stack := p.vstack[len(p.vstack)-1] _ = stack - return p.cur.onBuiltinName1(stack["head"], stack["tail"]) + return p.cur.onOperator1(stack["val"]) } func (c *current) onTerm1(val interface{}) (interface{}, error) { diff --git a/ast/parser_test.go b/ast/parser_test.go index 411c6d60b6..44adf59950 100644 --- a/ast/parser_test.go +++ b/ast/parser_test.go @@ -415,7 +415,7 @@ func TestInfixArithExpr(t *testing.T) { } func TestMiscBuiltinExpr(t *testing.T) { - xyz := StringTerm("xyz") + xyz := RefTerm(VarTerm("xyz")) assertParseOneExpr(t, "empty", "xyz()", NewBuiltinExpr(xyz)) assertParseOneExpr(t, "single", "xyz(abc)", NewBuiltinExpr(xyz, VarTerm("abc"))) assertParseOneExpr(t, "multiple", "xyz(abc, {\"one\": [1,2,3]})", NewBuiltinExpr(xyz, VarTerm("abc"), ObjectTerm(Item(StringTerm("one"), ArrayTerm(IntNumberTerm(1), IntNumberTerm(2), IntNumberTerm(3)))))) @@ -433,7 +433,7 @@ func TestNegatedExpr(t *testing.T) { ref1 := RefTerm(VarTerm("x"), VarTerm("y"), StringTerm("z"), VarTerm("a")) assertParseOneExprNegated(t, "membership", "not x[y].z[a] = \"b\"", Equality.Expr(ref1, StringTerm("b"))) - assertParseOneExprNegated(t, "misc. builtin", "not sorted(x[y].z[a])", NewBuiltinExpr(StringTerm("sorted"), ref1)) + assertParseOneExprNegated(t, "misc. builtin", "not sorted(x[y].z[a])", NewBuiltinExpr(RefTerm(VarTerm("sorted")), ref1)) } func TestExprWith(t *testing.T) { @@ -578,21 +578,21 @@ func TestUserFunctions(t *testing.T) { assertParseFunc(t, "term input", `f([x, y]) = z { split(x, y, z) }`, &Func{ Head: NewFuncHead(Var("f"), VarTerm("z"), ArrayTerm(VarTerm("x"), VarTerm("y"))), Body: NewBody( - &Expr{Terms: []*Term{StringTerm("split"), VarTerm("x"), VarTerm("y"), VarTerm("z")}}, + Split.Expr(VarTerm("x"), VarTerm("y"), VarTerm("z")), ), }) assertParseFunc(t, "term output", `f() = [x, y] { split("foo.bar", x, y) }`, &Func{ Head: NewFuncHead(Var("f"), ArrayTerm(VarTerm("x"), VarTerm("y"))), Body: NewBody( - &Expr{Terms: []*Term{StringTerm("split"), StringTerm("foo.bar"), VarTerm("x"), VarTerm("y")}}, + Split.Expr(StringTerm("foo.bar"), VarTerm("x"), VarTerm("y")), ), }) assertParseFunc(t, "comprehension", `f(x) = y { count([1 | x[_]], y) }`, &Func{ Head: NewFuncHead(Var("f"), VarTerm("y"), VarTerm("x")), Body: NewBody( - &Expr{Terms: []*Term{StringTerm("count"), MustParseTerm("[1 | x[_]]"), VarTerm("y")}}, + Count.Expr(MustParseTerm("[1 | x[_]]"), VarTerm("y")), ), }) @@ -1225,7 +1225,7 @@ func TestNamespacedBuiltins(t *testing.T) { expected *Term wantErr bool }{ - {`foo.bar.baz(1, 2)`, StringTerm("foo.bar.baz"), false}, + {`foo.bar.baz(1, 2)`, MustParseTerm("foo.bar.baz"), false}, {`foo.(1,2)`, nil, true}, {`foo.#.bar(1,2)`, nil, true}, {`foo(1,2,3).bar`, nil, true}, diff --git a/ast/policy.go b/ast/policy.go index 2f34018666..cddcbee7d6 100644 --- a/ast/policy.go +++ b/ast/policy.go @@ -541,11 +541,6 @@ func (f *Func) Path() Ref { return global } -// PathString returns a String type representing the full path of this Func. -func (f *Func) PathString() String { - return String(f.Path().String()) -} - func (f *Func) String() string { return f.Head.String() + " { " + f.Body.String() + " }" } @@ -999,10 +994,7 @@ func (expr *Expr) IsEquality() bool { if !ok { return false } - if len(terms) != 3 { - return false - } - return terms[0].Value.Compare(Equality.Name) == 0 + return terms[0].Value.Compare(Equality.Ref()) == 0 } // IsBuiltin returns true if this expression refers to a function. @@ -1011,14 +1003,14 @@ func (expr *Expr) IsBuiltin() bool { return ok } -// Name returns the name of the user function or built-in this expression refers to. If -// this expression is not a function call, returns the empty string. -func (expr *Expr) Name() String { +// Name returns the name of the user function or built-in this expression +// refers to. If this expression is not a function call, returns nil. +func (expr *Expr) Name() Ref { terms, ok := expr.Terms.([]*Term) if !ok || len(terms) == 0 { - return "" + return nil } - return terms[0].Value.(String) + return terms[0].Value.(Ref) } // Operand returns the term at the zero-based pos. If the expr does not include @@ -1075,9 +1067,9 @@ func (expr *Expr) OutputVars(safe VarSet) VarSet { case *Term: return expr.outputVarsRefs(safe) case []*Term: - name := terms[0].Value.(String) + name := terms[0].String() if b := BuiltinMap[name]; b != nil { - if b.Name.Equal(Equality.Name) { + if b.Name == Equality.Name { return expr.outputVarsEquality(safe) } return expr.outputVarsBuiltins(b, safe) @@ -1108,7 +1100,7 @@ func (expr *Expr) String() string { } switch t := expr.Terms.(type) { case []*Term: - name := t[0].Value.(String) + name := t[0].String() bi := BuiltinMap[name] var s string if bi != nil && len(bi.Infix) > 0 { @@ -1127,7 +1119,7 @@ func (expr *Expr) String() string { for _, v := range t[1:] { args = append(args, v.String()) } - name := string(t[0].Value.(String)) + name := string(t[0].String()) s = fmt.Sprintf("%s(%s)", name, strings.Join(args, ", ")) } diff --git a/ast/policy_test.go b/ast/policy_test.go index cceb06949d..2c4c16afdd 100644 --- a/ast/policy_test.go +++ b/ast/policy_test.go @@ -219,7 +219,7 @@ func TestBodyIsGround(t *testing.T) { func TestExprOutputVars(t *testing.T) { RegisterBuiltin(&Builtin{ - Name: String("test_out_array"), + Name: "test_out_array", Args: []types.Type{ types.NewArray(nil, types.N), }, @@ -227,7 +227,7 @@ func TestExprOutputVars(t *testing.T) { }) RegisterBuiltin(&Builtin{ - Name: String("test_out_set"), + Name: "test_out_set", Args: []types.Type{ types.NewArray(nil, types.N), }, @@ -235,7 +235,7 @@ func TestExprOutputVars(t *testing.T) { }) RegisterBuiltin(&Builtin{ - Name: String("foo"), + Name: "foo", Args: []types.Type{ types.A, types.A, @@ -292,18 +292,13 @@ func TestExprString(t *testing.T) { Negated: true, Terms: RefTerm(VarTerm("q"), StringTerm("r"), VarTerm("x")), } - expr3 := &Expr{ - Terms: []*Term{StringTerm("="), StringTerm("a"), FloatNumberTerm(17.1)}, - } - expr4 := &Expr{ - Terms: []*Term{ - StringTerm("!="), - ObjectTerm(Item(VarTerm("foo"), ArrayTerm( - IntNumberTerm(1), RefTerm(VarTerm("a"), StringTerm("b")), - ))), - BooleanTerm(false), - }, - } + expr3 := Equality.Expr(StringTerm("a"), FloatNumberTerm(17.1)) + expr4 := NotEqual.Expr( + ObjectTerm(Item(VarTerm("foo"), ArrayTerm( + IntNumberTerm(1), RefTerm(VarTerm("a"), StringTerm("b")), + ))), + BooleanTerm(false), + ) expr5 := &Expr{ Terms: BooleanTerm(true), With: []*With{ @@ -317,21 +312,15 @@ func TestExprString(t *testing.T) { }, }, } - expr6 := &Expr{ - Terms: []*Term{ - StringTerm("+"), - IntNumberTerm(1), - IntNumberTerm(2), - IntNumberTerm(3), - }, - } - expr7 := &Expr{ - Terms: []*Term{ - StringTerm("count"), - StringTerm("foo"), - VarTerm("x"), - }, - } + expr6 := Plus.Expr( + IntNumberTerm(1), + IntNumberTerm(2), + IntNumberTerm(3), + ) + expr7 := Count.Expr( + StringTerm("foo"), + VarTerm("x"), + ) assertExprString(t, expr1, "q.r[x]") assertExprString(t, expr2, "not q.r[x]") assertExprString(t, expr3, "\"a\" = 17.1") diff --git a/ast/rego.peg b/ast/rego.peg index 78fcb98072..657e776754 100644 --- a/ast/rego.peg +++ b/ast/rego.peg @@ -457,8 +457,8 @@ ArithInfixOp <- val:("+" / "-" / "*" / "/" / "&" / "|" / "-") { op = string(b.Name) } } - operator := StringTerm(op) - operator.Location = currentLocation(c) + loc := currentLocation(c) + operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) return operator, nil } @@ -473,14 +473,14 @@ InfixOp <- val:("=" / "!=" / "<=" / ">=" / "<" / ">") { op = string(b.Name) } } - operator := StringTerm(op) - operator.Location = currentLocation(c) + loc := currentLocation(c) + operator := RefTerm(VarTerm(op).SetLocation(loc)).SetLocation(loc) return operator, nil } -PrefixExpr <- SetEmpty / Builtin +PrefixExpr <- SetEmpty / Call -Builtin <- name:BuiltinName "(" _ head:Term? tail:( _ "," _ Term )* _ ")" { +Call <- name:Operator "(" _ head:Term? tail:( _ "," _ Term )* _ ")" { buf := []*Term{name.(*Term)} if head == nil { return buf, nil @@ -496,18 +496,16 @@ Builtin <- name:BuiltinName "(" _ head:Term? tail:( _ "," _ Term )* _ ")" { return buf, nil } -BuiltinName <- head:Var tail:( "." Var )* { - tailSlice := tail.([]interface{}) - buf := make([]string, 1+len(tailSlice)) - buf[0] = string(head.(*Term).Value.(Var)) - for i := range tailSlice { - elem := tailSlice[i] - part := elem.([]interface{})[1].(*Term).Value.(Var) - buf[i+1] = string(part) +Operator <- val:(Ref / Var) { + term := val.(*Term) + switch term.Value.(type) { + case Ref: + return val, nil + case Var: + return RefTerm(term).SetLocation(currentLocation(c)), nil + default: + panic("unreachable") } - name := StringTerm(strings.Join(buf, ".")) - name.Location = currentLocation(c) - return name, nil } Term <- val:( Comprehension / Composite / Scalar / Ref / Var ) { diff --git a/ast/unify_test.go b/ast/unify_test.go index cb6accf8ef..da022cd84f 100644 --- a/ast/unify_test.go +++ b/ast/unify_test.go @@ -53,8 +53,8 @@ func TestUnify(t *testing.T) { } terms := expr.Terms.([]*Term) - if terms[0].Value.Compare(Equality.Name) != 0 { - panic(terms) + if !expr.IsEquality() { + panic(expr) } a, b := terms[1], terms[2] diff --git a/ast/visit.go b/ast/visit.go index 0af38fe00b..035c4d91ce 100644 --- a/ast/visit.go +++ b/ast/visit.go @@ -243,12 +243,13 @@ type VarVisitor struct { // VarVisitorParams contains settings for a VarVisitor. type VarVisitorParams struct { - SkipRefHead bool - SkipObjectKeys bool - SkipClosures bool - SkipWithTarget bool - SkipSets bool - SkipFuncVars bool + SkipRefHead bool + SkipRefCallHead bool + SkipObjectKeys bool + SkipClosures bool + SkipWithTarget bool + SkipSets bool + SkipFuncVars bool } // NewVarVisitor returns a new VarVisitor object. @@ -304,6 +305,22 @@ func (vis *VarVisitor) Visit(v interface{}) Visitor { return nil } } + if vis.params.SkipRefCallHead { + if expr, ok := v.(*Expr); ok { + if terms, ok := expr.Terms.([]*Term); ok { + for _, t := range terms[0].Value.(Ref)[1:] { + Walk(vis, t) + } + for i := 1; i < len(terms); i++ { + Walk(vis, terms[i]) + } + for _, w := range expr.With { + Walk(vis, w) + } + return nil + } + } + } if vis.params.SkipFuncVars { if f, ok := v.(*Func); ok { Walk(vis, f.Body) diff --git a/ast/visit_test.go b/ast/visit_test.go index 5f7de6d62d..6200a804dd 100644 --- a/ast/visit_test.go +++ b/ast/visit_test.go @@ -23,11 +23,19 @@ func TestVisitor(t *testing.T) { import input.x.y as z -t[x] = y { p[x] = {"foo": [y, 2, {"bar": 3}]}; not q[x]; y = [[x, z] | x = "x"; z = "z"]; z = {"foo": [x, z] | x = "x"; z = "z"}; s = {1 | a[i] = "foo"}; count({1, 2, 3}, n) with input.foo.bar as x } +t[x] = y { + p[x] = {"foo": [y, 2, {"bar": 3}]} + not q[x] + y = [[x, z] | x = "x"; z = "z"] + z = {"foo": [x, z] | x = "x"; z = "z"} + s = {1 | a[i] = "foo"} + count({1, 2, 3}, n) with input.foo.bar as x +} p { false } else { false } else { true } -fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) +fn([x, y]) = z { json.unmarshal(x, z); z > y } +`) vis := &testVis{} Walk(vis, rule) @@ -62,7 +70,9 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) body expr1 term - = + ref + term + = term ref1 term @@ -94,7 +104,9 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) x expr3 term - = + ref + term + = term y term @@ -108,21 +120,27 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) body expr4 term - = + ref + term + = term x term "x" expr5 term - = + ref + term + = term z term "z" expr4 term - = + ref + term + = term z term @@ -139,21 +157,27 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) body expr1 term - = + ref + term + = term x term "x" expr2 term - = + ref + term + = term z term "z" expr5 term - = + ref + term + = term s term @@ -163,7 +187,9 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) body expr1 term - = + ref + term + = term ref term @@ -175,7 +201,9 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) "foo" expr6 term - count + ref + term + count term set term @@ -241,23 +269,27 @@ fn([x, y]) = z { z = "bar"; trim(x, y, z) }`) body expr1 term - = - term - z - term - "bar" - expr2 - term - trim + ref + term + json + term + unmarshal term x term - y + z + expr2 + term + ref + term + > term z + term + y */ - if len(vis.elems) != 216 { - t.Errorf("Expected exactly 216 elements in AST but got %d: %v", len(vis.elems), vis.elems) + if len(vis.elems) != 240 { + t.Errorf("Expected exactly 240 elements in AST but got %d: %v", len(vis.elems), vis.elems) } } @@ -268,7 +300,7 @@ func TestWalkVars(t *testing.T) { found.Add(v) return false }) - expected := NewVarSet(Var("x"), Var("data"), Var("y"), Var("z"), Var("q")) + expected := NewVarSet(Var("x"), Var("data"), Var("y"), Var("z"), Var("q"), Var("eq")) if !expected.Equal(found) { t.Fatalf("Expected %v but got: %v", expected, found) } @@ -281,11 +313,11 @@ func TestVarVisitor(t *testing.T) { params VarVisitorParams expected string }{ - {"data.foo[x] = bar.baz[y]", VarVisitorParams{SkipRefHead: true}, "[x, y]"}, {"{x: y}", VarVisitorParams{SkipObjectKeys: true}, "[y]"}, - {`foo = [x | data.a[i] = x]`, VarVisitorParams{SkipClosures: true}, "[foo]"}, - {`x = 1; y = 2; z = x + y; count([x, y, z], z)`, VarVisitorParams{}, "[x, y, z]"}, {"foo with input.bar.baz as qux[corge]", VarVisitorParams{SkipWithTarget: true}, "[foo, qux, corge]"}, + {"data.foo[x] = bar.baz[y]", VarVisitorParams{SkipRefHead: true}, "[x, y]"}, + {`foo = [x | data.a[i] = x]`, VarVisitorParams{SkipClosures: true}, "[foo, eq]"}, + {`x = 1; y = 2; z = x + y; count([x, y, z], z)`, VarVisitorParams{}, "[x, y, z, eq, plus, count]"}, } for _, tc := range tests { diff --git a/format/format.go b/format/format.go index f5d1785930..16aab7b26e 100644 --- a/format/format.go +++ b/format/format.go @@ -368,7 +368,7 @@ func (w *writer) writeExpr(expr *ast.Expr, comments []*ast.Comment) []*ast.Comme } func (w *writer) writeFunctionCall(t []*ast.Term, comments []*ast.Comment) []*ast.Comment { - name := t[0].Value.(ast.String) + name := t[0].Value.String() bi := ast.BuiltinMap[name] if bi != nil && len(bi.Infix) > 0 { switch len(bi.Args) { @@ -383,7 +383,7 @@ func (w *writer) writeFunctionCall(t []*ast.Term, comments []*ast.Comment) []*as } } - w.write(string(t[0].Value.(ast.String)) + "(") + w.write(string(t[0].String()) + "(") for _, v := range t[1 : len(t)-1] { comments = w.writeTerm(v, comments) w.write(", ") diff --git a/rego/rego_test.go b/rego/rego_test.go index 078960773e..c862e1625b 100644 --- a/rego/rego_test.go +++ b/rego/rego_test.go @@ -54,7 +54,7 @@ func TestRegoCaptureTermsRewrite(t *testing.T) { func TestRegoCancellation(t *testing.T) { ast.RegisterBuiltin(&ast.Builtin{ - Name: ast.String("test.sleep"), + Name: "test.sleep", Args: []types.Type{ types.S, }, diff --git a/repl/repl.go b/repl/repl.go index 6031acd213..9d54a1875d 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -491,7 +491,7 @@ func (r *REPL) unsetFunc(ctx context.Context, v ast.Value) error { mod := r.modules[r.currentModuleID] funcs := []*ast.Func{} for _, f := range mod.Funcs { - if !f.PathString().Equal(ast.String(ref.String())) { + if f.Path().String() != ref.String() { funcs = append(funcs, f) } } diff --git a/repl/repl_test.go b/repl/repl_test.go index d7d7aea4b1..8e692a518f 100644 --- a/repl/repl_test.go +++ b/repl/repl_test.go @@ -386,7 +386,7 @@ func TestUnset(t *testing.T) { repl.OneShot(ctx, "unset repl.p") err = repl.OneShot(ctx, "repl.p(5, y)") - if err == nil || err.Error() != `1 error occurred: 1:1: rego_type_error: undefined built-in function "repl.p"` { + if err == nil || err.Error() != `1 error occurred: 1:1: rego_type_error: undefined built-in function repl.p` { t.Fatalf("Expected eval error (undefined built-in) but got err: '%v'", err) } @@ -396,7 +396,7 @@ func TestUnset(t *testing.T) { repl.OneShot(ctx, "unset repl.p") err = repl.OneShot(ctx, "repl.p(1, 2, y)") - if err == nil || err.Error() != `1 error occurred: 1:1: rego_type_error: undefined built-in function "repl.p"` { + if err == nil || err.Error() != `1 error occurred: 1:1: rego_type_error: undefined built-in function repl.p` { t.Fatalf("Expected eval error (undefined built-in) but got err: '%v'", err) } diff --git a/server/server_test.go b/server/server_test.go index 3c56f71503..11db96fc34 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -1341,8 +1341,8 @@ func TestQueryWatchMigrateInvalidate(t *testing.T) { "HTTP/1.1 200 OK\nContent-Type: application/json\nTransfer-Encoding: chunked\n\n7c", `{"result":[{"expressions":[{"value":true,"text":"a=data.z.r+data.x","location":{"row":1,"col":1}}],"bindings":{"a":-200}}]} `, - `d7`, - `{"result":null,"error":{"code":"evaluation_error","message":"watch invalidated: 1 error occurred: 1:1: rego_type_error: \"plus\": invalid argument(s)\n\thave: (string, any, ???)\n\twant: (number, number, number)"}} + `d3`, + `{"result":null,"error":{"code":"evaluation_error","message":"watch invalidated: 1 error occurred: 1:1: rego_type_error: plus: invalid argument(s)\n\thave: (string, any, ???)\n\twant: (number, number, number)"}} `, `0`, ``, diff --git a/tester/runner_test.go b/tester/runner_test.go index 7e3bfb5f1d..70e8e06010 100644 --- a/tester/runner_test.go +++ b/tester/runner_test.go @@ -71,7 +71,7 @@ func TestRun(t *testing.T) { func TestRunnerCancel(t *testing.T) { ast.RegisterBuiltin(&ast.Builtin{ - Name: ast.String("test.sleep"), + Name: "test.sleep", Args: []types.Type{ types.S, }, diff --git a/topdown/builtins.go b/topdown/builtins.go index 27bc1e8415..5819e9dacd 100644 --- a/topdown/builtins.go +++ b/topdown/builtins.go @@ -91,43 +91,43 @@ type ( ) // RegisterBuiltinFunc adds a new built-in function to the evaluation engine. -func RegisterBuiltinFunc(name ast.String, fun BuiltinFunc) { +func RegisterBuiltinFunc(name string, fun BuiltinFunc) { builtinFunctions[name] = fun } // RegisterFunctionalBuiltinVoid1 adds a new built-in function to the evaluation // engine. -func RegisterFunctionalBuiltinVoid1(name ast.String, fun FunctionalBuiltinVoid1) { +func RegisterFunctionalBuiltinVoid1(name string, fun FunctionalBuiltinVoid1) { builtinFunctions[name] = functionalWrapperVoid1(name, fun) } // RegisterFunctionalBuiltinVoid2 adds a new built-in function to the evaluation // engine. -func RegisterFunctionalBuiltinVoid2(name ast.String, fun FunctionalBuiltinVoid2) { +func RegisterFunctionalBuiltinVoid2(name string, fun FunctionalBuiltinVoid2) { builtinFunctions[name] = functionalWrapperVoid2(name, fun) } // RegisterFunctionalBuiltin1 adds a new built-in function to the evaluation // engine. -func RegisterFunctionalBuiltin1(name ast.String, fun FunctionalBuiltin1) { +func RegisterFunctionalBuiltin1(name string, fun FunctionalBuiltin1) { builtinFunctions[name] = functionalWrapper1(name, fun) } // RegisterFunctionalBuiltin2 adds a new built-in function to the evaluation // engine. -func RegisterFunctionalBuiltin2(name ast.String, fun FunctionalBuiltin2) { +func RegisterFunctionalBuiltin2(name string, fun FunctionalBuiltin2) { builtinFunctions[name] = functionalWrapper2(name, fun) } // RegisterFunctionalBuiltin3 adds a new built-in function to the evaluation // engine. -func RegisterFunctionalBuiltin3(name ast.String, fun FunctionalBuiltin3) { +func RegisterFunctionalBuiltin3(name string, fun FunctionalBuiltin3) { builtinFunctions[name] = functionalWrapper3(name, fun) } // RegisterFunctionalBuiltin1Out3 adds a new built-in function to the evaluation // engine. -func RegisterFunctionalBuiltin1Out3(name ast.String, fun FunctionalBuiltin1Out3) { +func RegisterFunctionalBuiltin1Out3(name string, fun FunctionalBuiltin1Out3) { builtinFunctions[name] = functionalWrapper1Out3(name, fun) } @@ -150,9 +150,9 @@ func (BuiltinEmpty) Error() string { return "" } -var builtinFunctions = map[ast.String]BuiltinFunc{} +var builtinFunctions = map[string]BuiltinFunc{} -func functionalWrapperVoid1(name ast.String, fn FunctionalBuiltinVoid1) BuiltinFunc { +func functionalWrapperVoid1(name string, fn FunctionalBuiltinVoid1) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, 1) @@ -167,7 +167,7 @@ func functionalWrapperVoid1(name ast.String, fn FunctionalBuiltinVoid1) BuiltinF } } -func functionalWrapperVoid2(name ast.String, fn FunctionalBuiltinVoid2) BuiltinFunc { +func functionalWrapperVoid2(name string, fn FunctionalBuiltinVoid2) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, 2) @@ -182,7 +182,7 @@ func functionalWrapperVoid2(name ast.String, fn FunctionalBuiltinVoid2) BuiltinF } } -func functionalWrapper1(name ast.String, fn FunctionalBuiltin1) BuiltinFunc { +func functionalWrapper1(name string, fn FunctionalBuiltin1) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, 1) @@ -197,7 +197,7 @@ func functionalWrapper1(name ast.String, fn FunctionalBuiltin1) BuiltinFunc { } } -func functionalWrapper2(name ast.String, fn FunctionalBuiltin2) BuiltinFunc { +func functionalWrapper2(name string, fn FunctionalBuiltin2) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, 2) @@ -212,7 +212,7 @@ func functionalWrapper2(name ast.String, fn FunctionalBuiltin2) BuiltinFunc { } } -func functionalWrapper3(name ast.String, fn FunctionalBuiltin3) BuiltinFunc { +func functionalWrapper3(name string, fn FunctionalBuiltin3) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, 3) @@ -227,7 +227,7 @@ func functionalWrapper3(name ast.String, fn FunctionalBuiltin3) BuiltinFunc { } } -func functionalWrapper1Out3(name ast.String, fn FunctionalBuiltin1Out3) BuiltinFunc { +func functionalWrapper1Out3(name string, fn FunctionalBuiltin1Out3) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, 1) @@ -244,7 +244,7 @@ func functionalWrapper1Out3(name ast.String, fn FunctionalBuiltin1Out3) BuiltinF } } -func userFunctionWrapper(name ast.String, fns []*ast.Func) BuiltinFunc { +func userFunctionWrapper(name string, fns []*ast.Func) BuiltinFunc { return func(t *Topdown, expr *ast.Expr, iter Iterator) error { operands := expr.Terms.([]*ast.Term)[1:] resolved, err := resolveN(t, name, operands, len(operands)-1) @@ -299,7 +299,7 @@ func userFunctionWrapper(name ast.String, fns []*ast.Func) BuiltinFunc { } } -func handleFunctionalBuiltinErr(name ast.String, loc *ast.Location, err error) error { +func handleFunctionalBuiltinErr(name string, loc *ast.Location, err error) error { switch err := err.(type) { case BuiltinEmpty: return nil @@ -318,7 +318,7 @@ func handleFunctionalBuiltinErr(name ast.String, loc *ast.Location, err error) e } } -func resolveN(t *Topdown, name ast.String, ops []*ast.Term, n int) ([]ast.Value, error) { +func resolveN(t *Topdown, name string, ops []*ast.Term, n int) ([]ast.Value, error) { result := make([]ast.Value, n) for i := 0; i < n; i++ { op, err := ResolveRefs(ops[i].Value, t) diff --git a/topdown/example_test.go b/topdown/example_test.go index 8883a1989c..50494f0be0 100644 --- a/topdown/example_test.go +++ b/topdown/example_test.go @@ -154,7 +154,7 @@ func ExampleRegisterFunctionalBuiltin1() { // registry to include your built-in. Otherwise, the compiler will complain // when it encounters your built-in. builtin := &ast.Builtin{ - Name: ast.String("mybuiltins.upper"), + Name: "mybuiltins.upper", Args: []types.Type{ types.S, types.S, diff --git a/topdown/topdown.go b/topdown/topdown.go index 7837860b57..8cddb891bf 100644 --- a/topdown/topdown.go +++ b/topdown/topdown.go @@ -37,7 +37,7 @@ type Topdown struct { qid uint64 redos *redoStack builtins builtins.Cache - userBuiltins map[ast.String]BuiltinFunc + userBuiltins map[string]BuiltinFunc } // ResetQueryIDs resets the query ID generator. This is only for test purposes. @@ -90,7 +90,7 @@ func New(ctx context.Context, query ast.Body, compiler *ast.Compiler, store stor qid: qidFactory.Next(), redos: &redoStack{}, builtins: builtins.Cache{}, - userBuiltins: map[ast.String]BuiltinFunc{}, + userBuiltins: map[string]BuiltinFunc{}, } t.registerUserFunctions() return t @@ -905,7 +905,7 @@ func evalExpr(t *Topdown, iter Iterator) error { expr := PlugExpr(t.Current(), t.Binding) switch tt := expr.Terms.(type) { case []*ast.Term: - name := tt[0].Value.(ast.String) + name := tt[0].String() builtin, ok := builtinFunctions[name] if !ok { builtin, ok = t.userBuiltins[name] @@ -966,7 +966,7 @@ func evalRef(t *Topdown, ref, path ast.Ref, iter Iterator) error { } // This should not be reachable. - return fmt.Errorf("unbound ref head: %v", path) + return fmt.Errorf("unbound ref head") } var n ast.Ref @@ -1882,7 +1882,7 @@ func evalTerms(t *Topdown, iter Iterator) error { var ts []*ast.Term switch t := expr.Terms.(type) { case []*ast.Term: - ts = t + ts = t[1:] case *ast.Term: ts = append(ts, t) default: diff --git a/topdown/topdown_test.go b/topdown/topdown_test.go index 9476482c0d..1c1ffa92d8 100644 --- a/topdown/topdown_test.go +++ b/topdown/topdown_test.go @@ -1492,14 +1492,14 @@ func TestTopDownJWTBuiltins(t *testing.T) { func TestTopDownTime(t *testing.T) { ast.RegisterBuiltin(&ast.Builtin{ - Name: ast.String("test_sleep"), + Name: "test_sleep", Args: []types.Type{ types.S, }, TargetPos: []int{1}, }) - RegisterFunctionalBuiltinVoid1(ast.String("test_sleep"), func(a ast.Value) error { + RegisterFunctionalBuiltinVoid1("test_sleep", func(a ast.Value) error { duration, err := time.ParseDuration(string(a.(ast.String))) if err != nil { panic(err) @@ -1783,8 +1783,7 @@ func TestTopDownPartialDocConstants(t *testing.T) { } func TestTopDownUserFunc(t *testing.T) { - compiler := compileModules([]string{ - `package ex + modules := []string{`package ex foo(x) = y { split(x, "i", y) @@ -1911,8 +1910,9 @@ func TestTopDownUserFunc(t *testing.T) { samepkg = y { foo("how do you do?", y) - }`, - }) + }`} + + compiler := compileModules(modules) store := inmem.NewFromObject(loadSmallTestData()) ctx := context.Background() txn := storage.NewTransactionOrDie(ctx, store) @@ -1985,9 +1985,9 @@ func TestUserFunctionErrors(t *testing.T) { txn := storage.NewTransactionOrDie(ctx, store) defer store.Abort(ctx, txn) - assertTopDownWithPath(t, compiler, store, "function output conflict single", []string{"test1", "r"}, "", errors.New(`eval_conflict_error: function "test1.p" produces conflicting outputs`)) + assertTopDownWithPath(t, compiler, store, "function output conflict single", []string{"test1", "r"}, "", errors.New(`eval_conflict_error: function test1.p produces conflicting outputs`)) assertTopDownWithPath(t, compiler, store, "function input no match", []string{"test2", "r"}, "", "") - assertTopDownWithPath(t, compiler, store, "function output conflict multiple", []string{"test3", "r"}, "", errors.New(`eval_conflict_error: function "test3.p" produces conflicting outputs`)) + assertTopDownWithPath(t, compiler, store, "function output conflict multiple", []string{"test3", "r"}, "", errors.New(`eval_conflict_error: function test3.p produces conflicting outputs`)) } func TestTopDownWithKeyword(t *testing.T) { @@ -2240,7 +2240,7 @@ violations[server] { server = servers[_]; server.protocols[_] = "http"; public_s func TestTopDownUnsupportedBuiltin(t *testing.T) { ast.RegisterBuiltin(&ast.Builtin{ - Name: ast.String("unsupported_builtin"), + Name: "unsupported_builtin", }) body := ast.MustParseBody(`unsupported_builtin()`) @@ -2264,7 +2264,7 @@ func TestTopDownUnsupportedBuiltin(t *testing.T) { func TestTopDownQueryCancellation(t *testing.T) { ast.RegisterBuiltin(&ast.Builtin{ - Name: ast.String("test.sleep"), + Name: "test.sleep", Args: []types.Type{ types.S, }, diff --git a/watch/watch_test.go b/watch/watch_test.go index 195a2a4743..ac44530c30 100644 --- a/watch/watch_test.go +++ b/watch/watch_test.go @@ -228,7 +228,7 @@ func TestWatchMigrateInvalidate(t *testing.T) { second := <-handle.C expSecond := Event{ Query: `x = data.y.r["foo"]+1`, - Error: errors.New(`watch invalidated: 1 error occurred: 1:1: rego_type_error: "plus": invalid argument(s) + Error: errors.New(`watch invalidated: 1 error occurred: 1:1: rego_type_error: plus: invalid argument(s) have: (string, number, ???) want: (number, number, number)`), }