Skip to content
Merged
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
75 changes: 75 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//go:build go1.24 && cache
Copy link

Copilot AI Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build constraint 'go1.24' may not work as expected. Go build tags typically use version formats like 'go1.24.0' or semantic versioning. Consider using a more standard build tag format.

Suggested change
//go:build go1.24 && cache
//go:build go1.24.0 && cache

Copilot uses AI. Check for mistakes.

package govaluate

import (
"sync"
"weak"
)

var (
paramMap = sync.Map{}

constMap = sync.Map{}
)

func getParameterStage(name string) (*evaluationStage, error) {
stage, ok := getParamFromMap(name)
if ok {
return stage, nil
}

operator := makeParameterStage(name)
ret := &evaluationStage{
operator: operator,
}
storeVal := weak.Make(ret)
paramMap.Store(name, storeVal)
return ret, nil
}

func getParamFromMap(name string) (*evaluationStage, bool) {
stage, ok := paramMap.Load(name)
if ok {
ptr, ok := stage.(weak.Pointer[evaluationStage])
if ok {
ret := ptr.Value()
if ret != nil {
return ret, true
}
paramMap.Delete(name)
}
}
return nil, false
}

func getConstantStage(value any) (*evaluationStage, error) {
stage, ok := getConstantFromMap(value)
if ok {
return stage, nil
}

operator := makeLiteralStage(value)
ret := &evaluationStage{
symbol: LITERAL,
operator: operator,
}
storeVal := weak.Make(ret)
constMap.Store(value, storeVal)
return ret, nil
}

func getConstantFromMap(value any) (*evaluationStage, bool) {
stage, ok := constMap.Load(value)
if ok {
ptr, ok := stage.(weak.Pointer[evaluationStage])
if ok {
ret := ptr.Value()
if ret != nil {
return ret, true
}
constMap.Delete(value)
}
}
return nil, false
}
18 changes: 18 additions & 0 deletions noCache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//go:build !go1.24 || !cache
Copy link

Copilot AI Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build constraint '!go1.24' should match the format used in cache.go. If cache.go uses 'go1.24', this constraint should be '!go1.24', but consider using a more standard build tag format consistently.

Suggested change
//go:build !go1.24 || !cache
//go:build !(go1.24 && cache)

Copilot uses AI. Check for mistakes.

package govaluate

func getParameterStage(name string) (*evaluationStage, error) {
operator := makeParameterStage(name)
return &evaluationStage{
operator: operator,
}, nil
}

func getConstantStage(value interface{}) (*evaluationStage, error) {
operator := makeLiteralStage(value)
return &evaluationStage{
symbol: LITERAL,
operator: operator,
}, nil
}
13 changes: 7 additions & 6 deletions stagePlanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,10 @@ func planValue(stream *tokenStream) (*evaluationStage, error) {
// clauses with single elements don't trigger SEPARATE stage planner
// this ensures that when used as part of an "in" comparison, the array requirement passes
if prev.Kind == COMPARATOR && prev.Value == "in" && ret.symbol == LITERAL {
ret.operator = ensureSliceStage(ret.operator)
// We need to copy this in case we are using the cached value...
tmp := *ret
tmp.operator = ensureSliceStage(ret.operator)
ret = &tmp
}

// advance past the CLAUSE_CLOSE token. We know that it's a CLAUSE_CLOSE, because at parse-time we check for unbalanced parens.
Expand All @@ -428,7 +431,7 @@ func planValue(stream *tokenStream) (*evaluationStage, error) {
return nil, nil

case VARIABLE:
operator = makeParameterStage(token.Value.(string))
return getParameterStage(token.Value.(string))

case NUMERIC:
fallthrough
Expand All @@ -437,11 +440,9 @@ func planValue(stream *tokenStream) (*evaluationStage, error) {
case PATTERN:
fallthrough
case BOOLEAN:
symbol = LITERAL
operator = makeLiteralStage(token.Value)
return getConstantStage(token.Value)
case TIME:
symbol = LITERAL
operator = makeLiteralStage(float64(token.Value.(time.Time).Unix()))
return getConstantStage(float64(token.Value.(time.Time).Unix()))

case PREFIX:
stream.rewind()
Expand Down
Loading