Previously, the loader would use directory names as top-level keys when
paths referred to directories. This meant that identical queries against
policies/data in differently named directories would return different
answers.
Now, the loader ignores the first directory name when recursing on
paths. Unfortunately this is not backwards compatible. Scripts and
workflows can be adapted as follows:
Before: opa test *
After: opa test .
Before: opa test /some/path/to/dir/*
After: opa test /some/path/to/dir
The same goes for opa run.
Previously refs like p["not"] would be represented as p.not which does
not parse because 'not' is an invalid variable name. This change ensures
that ref string operands are escape if they are keywords.
Previously, if partial evaluation encountered a ref against an unknown
term, it would attempt to evaluate the ref against the binding list and
then fail (because there would not be a binding for the unknown.)
With thes changes partial evaluation deals with unknown terms twofold:
1) When the term being dereferenced is unknown, eval saves the remainder
of the expression and continues.
2) When the ref operand is unknown, eval uses the value obtained by
enumerating the term to continue.
Previously, partial evaluation would save negated expressions and not
perform any inlining. With these changes, partial evaluation inlines
negated expressions into support rules and rewrites the original
expression to refer to the support rule.
These changes will improve the coverage of partial evaluation which
improves the applicability of rule indexing and other optimizations.
Fixes#623
Fixes#421
removed blank line
updated test
added command info documentation
wrap the error messages
used buitin URL decode method
moved verify token code in tokens module
Some buillt-in functions should not be partially evaluated because they
are not pure functions (e.g., http.send and time.now_ns are two exampels
we currently have.)
In the future, we may need to add variants of these functions that can
be evaluated during partial evaluation.
Fixes#622
Previously, partial eval was not checking call args recursively for
terms in the save set. As a result, if a call expression passed a term
that had an unknown embedded, the call would be evaluated, which could
potentially result in an internal error.
Fixes#621
The query compiler was not deep copying queries like the compiler does
for modules. As a result, the parsed query in the REPL was being
recompiled and the rewritten var mapping was not correct. E.g.,
rewritten vars were not be displayed properly.
The rego package was not checking capture vars unless the query
contained iteration. As a result, queries like a = 1; b = 2; a > b would
be return a single result when they should be undefined.
The debug form was passing the parsed input as a Go native interface{}
which caused the Rego package to attempt to treat ast.Valeu as a Go
native value (which fails.)
Fixes#571
The initial assignment support in the REPL was using the expr operand
instead of the rule name for the unset operation. As a result,
assignments to input/data would panic because the expr operand was a ref
and not a var.
With these changes, the REPL can now print expression values more
reliably. E.g., simple expressions like 3+5 just do the right thing.
Previously the REPL called topdown directly and reimplemented some of
the logic to format result sets. This was a source of issues because it
was possible for the rego package and the REPL to return different
answers. With these changes, the REPL and rego package results are
equivalent.
A few changes were required. Specifically:
* Query Compiler. Updated to accept user supplied stages. This way users
can perform their own rewriting. This is used by the rego package to
provide the query+functional semantics we want. In the future, this API
could be used to register custom optimization passes to the compiler.
* Compiler. Expose GetArity helper. This allows users to quickly lookup
the arity of a function referred to by a ref. The rego package needs
this to decide whether to capture call outputs.
* Rego package. Expose new args to set parse package, imports, etc. This
is used by the REPL which maintains state to control the currently
active module.
Previously, if callers omitted output terms from call expressions, the
result would be ignored. This was fine for most calls which would only
return true if they were defined, however, for functions could return
false this became confusing because an expression like "f(1)" where f(1)
= false would be succeed and yield a result.
With these changes, built-in functions that used to only return true
always return true or false and the eval engine takes care to check if
the result is false when the the caller omits the output term.
This provides consistent behaviour across cases like...
f(1) => undefined (previously {})
f(1,x) => {x:false} (previously {x:false})
neq(1,1,x) => {x:false} (previously undefined)
neq(1,1,false) => {} (previously undefined)
neq(1,1,true) => undefined (previously undefined)
In the next set of changes, the Rego package will be updated to capture
values for expressions like the first one above so that function calls
behave like refs (i.e., their values are returned).