Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion v1/ast/interning.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ var (
"internal": Var("internal"),
"else": Var("else"),

"i": Var("i"), "j": Var("j"), "k": Var("k"), "v": Var("v"), "x": Var("x"), "y": Var("y"), "z": Var("z"),
"a": Var("a"), "b": Var("b"), "c": Var("c"),
"i": Var("i"), "j": Var("j"),
"k": Var("k"), "v": Var("v"),
"x": Var("x"), "y": Var("y"), "z": Var("z"),

"allow": Var("allow"), "deny": Var("deny"),
}
)

Expand Down
46 changes: 22 additions & 24 deletions v1/ast/parser_ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ func MustParseTerm(input string) *Term {
// ParseRuleFromBody returns a rule if the body can be interpreted as a rule
// definition. Otherwise, an error is returned.
func ParseRuleFromBody(module *Module, body Body) (*Rule, error) {

if len(body) != 1 {
return nil, errors.New("multiple expressions cannot be used for rule head")
}
Expand All @@ -174,7 +173,6 @@ func ParseRuleFromBody(module *Module, body Body) (*Rule, error) {
// ParseRuleFromExpr returns a rule if the expression can be interpreted as a
// rule definition.
func ParseRuleFromExpr(module *Module, expr *Expr) (*Rule, error) {

if len(expr.With) > 0 {
return nil, errors.New("expressions using with keyword cannot be used for rule head")
}
Expand Down Expand Up @@ -224,7 +222,6 @@ func ParseRuleFromExpr(module *Module, expr *Expr) (*Rule, error) {
}

func parseCompleteRuleFromEq(module *Module, expr *Expr) (rule *Rule, err error) {

// ensure the rule location is set to the expr location
// the helper functions called below try to set the location based
// on the terms they've been provided but that is not as accurate.
Expand Down Expand Up @@ -257,15 +254,11 @@ func parseCompleteRuleFromEq(module *Module, expr *Expr) (rule *Rule, err error)
// be interpreted as a complete document definition declared with the assignment
// operator.
func ParseCompleteDocRuleFromAssignmentExpr(module *Module, lhs, rhs *Term) (*Rule, error) {

rule, err := ParseCompleteDocRuleFromEqExpr(module, lhs, rhs)
if err != nil {
return nil, err
if err == nil {
rule.Head.Assign = true
}

rule.Head.Assign = true

return rule, nil
return rule, err
}

// ParseCompleteDocRuleFromEqExpr returns a rule if the expression can be
Expand Down Expand Up @@ -458,7 +451,7 @@ func ParseImports(input string) ([]*Import, error) {
if err != nil {
return nil, err
}
result := []*Import{}
result := make([]*Import, 0, len(stmts))
for _, stmt := range stmts {
if imp, ok := stmt.(*Import); ok {
result = append(result, imp)
Expand Down Expand Up @@ -496,12 +489,17 @@ func ParseBody(input string) (Body, error) {
// ParseBodyWithOpts returns exactly one body. It does _not_ set SkipRules: true on its own,
// but respects whatever ParserOptions it's been given.
func ParseBodyWithOpts(input string, popts ParserOptions) (Body, error) {

stmts, _, err := ParseStatementsWithOpts("", input, popts)
if err != nil {
return nil, err
}

if len(stmts) == 1 {
if body, ok := stmts[0].(Body); ok {
return body, nil
}
}

result := Body{}

for _, stmt := range stmts {
Expand Down Expand Up @@ -619,14 +617,7 @@ func ParseRule(input string) (*Rule, error) {
// this function expects *exactly* one statement. If multiple
// statements are parsed, an error is returned.
func ParseStatement(input string) (Statement, error) {
stmts, _, err := ParseStatements("", input)
if err != nil {
return nil, err
}
if len(stmts) != 1 {
return nil, errors.New("expected exactly one statement")
}
return stmts[0], nil
return ParseStatementWithOpts(input, ParserOptions{})
}

func ParseStatementWithOpts(input string, popts ParserOptions) (Statement, error) {
Expand All @@ -640,17 +631,24 @@ func ParseStatementWithOpts(input string, popts ParserOptions) (Statement, error
return stmts[0], nil
}

// ParseStatements is deprecated. Use ParseStatementWithOpts instead.
// ParseStatements returns a slice of parsed statements.
//
// Deprecated: Use [ParseStatementsWithOpts] instead.
func ParseStatements(filename, input string) ([]Statement, []*Comment, error) {
return ParseStatementsWithOpts(filename, input, ParserOptions{})
}

// ParseStatementsWithOpts returns a slice of parsed statements. This is the
// default return value from the parser.
// ParseStatementsWithOpts returns a slice of parsed statements.
// This is the default return value from [*Parser.Parse].
func ParseStatementsWithOpts(filename, input string, popts ParserOptions) ([]Statement, []*Comment, error) {
sr := StringReaderPool.Get()
defer StringReaderPool.Put(sr)

sr.Reset(input)

parser := NewParser().
WithFilename(filename).
WithReader(strings.NewReader(input)).
WithReader(sr).
WithProcessAnnotation(popts.ProcessAnnotation).
WithFutureKeywords(popts.FutureKeywords...).
WithAllFutureKeywords(popts.AllFutureKeywords).
Expand Down
8 changes: 5 additions & 3 deletions v1/ast/syncpools.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package ast

import (
"bytes"
"strings"
"sync"

"github.com/open-policy-agent/opa/v1/util"
)

var (
TermPtrPool = util.NewSyncPool[Term]()
BytesReaderPool = util.NewSyncPool[bytes.Reader]()
IndexResultPool = util.NewSyncPool[IndexResult]()
TermPtrPool = util.NewSyncPool[Term]()
BytesReaderPool = util.NewSyncPool[bytes.Reader]()
StringReaderPool = util.NewSyncPool[strings.Reader]()
IndexResultPool = util.NewSyncPool[IndexResult]()

// Needs custom pool because of custom Put logic.
varVisitorPool = &vvPool{
Expand Down
7 changes: 6 additions & 1 deletion v1/ast/term.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ func ValueFromReader(r io.Reader) (Value, error) {

// As converts v into a Go native type referred to by x.
func As(v Value, x any) error {
return util.NewJSONDecoder(strings.NewReader(v.String())).Decode(x)
sr := StringReaderPool.Get()
defer StringReaderPool.Put(sr)

sr.Reset(v.String())

return util.NewJSONDecoder(sr).Decode(x)
}

// Resolver defines the interface for resolving references to native Go values.
Expand Down