From ea2ea9b12b4f50e8bffe53bb1e66e2d88572271e Mon Sep 17 00:00:00 2001 From: Torin Sandall Date: Tue, 3 Oct 2017 14:15:07 -0700 Subject: [PATCH] Modify AST to represent function names as refs These changes update the AST to represent function names as refs. Previously, function names were represented as strings. Representing the names as strings was fine, however, once functions and rules are merged, it will be desirable to refer to functions using references. This is a bit of preemptive refactoring to make that change easier. Instead of having functions referred to with both strings and references, all functions will be referred to with references. --- ast/builtins.go | 146 ++++--- ast/builtins_test.go | 2 +- ast/check.go | 23 +- ast/check_test.go | 10 +- ast/compile.go | 62 ++- ast/compile_test.go | 2 + ast/env.go | 8 +- ast/parser.go | 941 ++++++++++++++++++++-------------------- ast/parser_test.go | 12 +- ast/policy.go | 28 +- ast/policy_test.go | 49 +-- ast/rego.peg | 32 +- ast/unify_test.go | 4 +- ast/visit.go | 29 +- ast/visit_test.go | 86 ++-- format/format.go | 4 +- rego/rego_test.go | 2 +- repl/repl.go | 2 +- repl/repl_test.go | 4 +- server/server_test.go | 4 +- tester/runner_test.go | 2 +- topdown/builtins.go | 34 +- topdown/example_test.go | 2 +- topdown/topdown.go | 10 +- topdown/topdown_test.go | 20 +- watch/watch_test.go | 2 +- 26 files changed, 783 insertions(+), 737 deletions(-) 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)`), }