aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/rosa/azalea/evaluate.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-05-17 23:44:00 +0900
committerOphestra <cat@gensokyo.uk>2026-05-17 23:49:19 +0900
commitf24ae21af111e0ce34f62a37ddb4a9fc18166ae6 (patch)
treeaf7325047441c592bbdfeccf17753eea82d8ee6e /internal/rosa/azalea/evaluate.go
parent99b324fb174fbbf069bf0db39ee280590aad1f4f (diff)
internal/rosa/azalea: package special case
This is more efficient for the inputs array and packages in general. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/rosa/azalea/evaluate.go')
-rw-r--r--internal/rosa/azalea/evaluate.go95
1 files changed, 69 insertions, 26 deletions
diff --git a/internal/rosa/azalea/evaluate.go b/internal/rosa/azalea/evaluate.go
index 431d6944..daf38849 100644
--- a/internal/rosa/azalea/evaluate.go
+++ b/internal/rosa/azalea/evaluate.go
@@ -5,6 +5,7 @@ import (
"fmt"
"maps"
"reflect"
+ "slices"
"unique"
)
@@ -23,9 +24,12 @@ type (
// FArgs are arguments passed to [F].
FArgs []FArg
+ // PF implements the package declaration function.
+ PF func(name Ident, args FArgs) (v any, set bool, err error)
+
// F is the implementation of a [Func].
F struct {
- F func(isPackage bool, args FArgs) (v any, set bool, err error)
+ F func(args FArgs) (v any, set bool, err error)
V map[unique.Handle[Ident]]any
}
)
@@ -77,8 +81,8 @@ func (e UndefinedError) Error() string {
}
// evaluate is evaluateAny with a type parameter.
-func evaluate[T Value](s []Frame, expr any, rp *T) bool {
- return evaluateAny(s, expr, rp)
+func evaluate[T Value](d PF, s []Frame, expr any, rp *T) bool {
+ return evaluateAny(d, s, expr, rp)
}
// TypeError is an unexpected type during evaluation.
@@ -132,8 +136,18 @@ func (e EvaluationError) Error() string {
return fmt.Sprintf("expression %#v: %v", e.Expr, e.Err)
}
+var (
+ // IdentInputs is a special array argument in a package declaration whose
+ // values of [Ident] are kept as is when passed to a [PF].
+ IdentInputs = unique.Make(Ident("inputs"))
+
+ // ErrInvalidInputs is panicked for an [IdentInputs] argument to [PF]
+ // sharing its value or set for R.
+ ErrInvalidInputs = errors.New("inputs must not be common or bound to scope")
+)
+
// evaluateAny implements [Evaluate].
-func evaluateAny(s []Frame, expr, rp any) bool {
+func evaluateAny(d PF, s []Frame, expr, rp any) bool {
defer func() {
r := recover()
if r == nil {
@@ -193,17 +207,17 @@ func evaluateAny(s []Frame, expr, rp any) bool {
store(rp, false)
return true
default:
- return evaluateAny(s, v, rp)
+ return evaluateAny(d, s, v, rp)
}
default:
- return evaluateAny(s, e[0], rp)
+ return evaluateAny(d, s, e[0], rp)
}
}
var v string
for i := range e {
var _r string
- if evaluate(s, e[i], &_r) {
+ if evaluate(d, s, e[i], &_r) {
v += _r
}
}
@@ -214,7 +228,7 @@ func evaluateAny(s []Frame, expr, rp any) bool {
r := make([]string, 0, len(e))
for i := range e {
var _r string
- if evaluate(s, e[i], &_r) {
+ if evaluate(d, s, e[i], &_r) {
r = append(r, _r)
}
}
@@ -225,7 +239,7 @@ func evaluateAny(s []Frame, expr, rp any) bool {
r := make([][2]string, 0, len(e))
for i := range e {
var _r string
- if e[i].V == nil || evaluate(s, e[i].V, &_r) {
+ if e[i].V == nil || evaluate(d, s, e[i].V, &_r) {
r = append(r, [2]string{string(e[i].K), _r})
}
}
@@ -237,14 +251,16 @@ func evaluateAny(s []Frame, expr, rp any) bool {
f F
ok bool
)
- for i := range s {
- f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
- if ok {
- break
+ if !e.Package {
+ for i := range s {
+ f, ok = s[len(s)-1-i].Func[unique.Make(e.Ident)]
+ if ok {
+ break
+ }
+ }
+ if !ok {
+ panic(UndefinedError(e.Ident))
}
- }
- if !ok {
- panic(UndefinedError(e.Ident))
}
argc := len(e.Args)
@@ -252,29 +268,56 @@ func evaluateAny(s []Frame, expr, rp any) bool {
argc += len(arg.K) - 1
}
fargs := make([]FArg, 0, len(e.Args))
- s = append(s, Frame{Val: maps.Clone(f.V)})
+ s = append(s, Frame{})
fp := &s[len(s)-1]
+ if !e.Package {
+ fp.Val = maps.Clone(f.V)
+ }
for _, arg := range e.Args {
+ names := make([]unique.Handle[Ident], len(arg.K))
+ for i, name := range arg.K {
+ names[i] = unique.Make(name)
+ }
+
farg := FArg{R: arg.R}
- if !evaluateAny(s, arg.V, &farg.V) {
+ if e.Package && slices.Contains(names, IdentInputs) {
+ if len(names) != 1 || len(arg.V) != 1 || arg.R {
+ panic(ErrInvalidInputs)
+ }
+ farg.K = names[0]
+ if err := storeE(&farg.V, arg.V[0]); err != nil {
+ panic(err)
+ }
+ fargs = append(fargs, farg)
+ continue
+ }
+
+ if !evaluateAny(d, s, arg.V, &farg.V) {
farg.V = nil
}
- for _, name := range arg.K {
- h := unique.Make(name)
- farg.K = h
+ for _, name := range names {
+ farg.K = name
fargs = append(fargs, farg)
if arg.R && farg.V != nil {
if fp.Val == nil {
fp.Val = make(map[unique.Handle[Ident]]any)
}
- (*fp).Val[h] = farg.V
+ (*fp).Val[name] = farg.V
}
}
}
- v, set, err := f.F(e.Package, fargs)
+ var (
+ v any
+ err error
+ )
+ if !e.Package {
+ v, ok, err = f.F(fargs)
+ } else {
+ v, ok, err = d(e.Ident, fargs)
+ }
if err != nil {
panic(err)
} else if v != nil {
@@ -282,7 +325,7 @@ func evaluateAny(s []Frame, expr, rp any) bool {
panic(err)
}
}
- return set
+ return ok
default:
panic(UnsupportedExprError{expr})
@@ -290,7 +333,7 @@ func evaluateAny(s []Frame, expr, rp any) bool {
}
// Evaluate evaluates a statement and returns its value.
-func Evaluate[T Value](s []Frame, expr any) (v T, set bool, err error) {
+func Evaluate[T Value](d PF, s []Frame, expr any) (v T, set bool, err error) {
defer func() {
r := recover()
if r == nil {
@@ -303,6 +346,6 @@ func Evaluate[T Value](s []Frame, expr any) (v T, set bool, err error) {
}
err = _err
}()
- set = evaluate[T](s, expr, &v)
+ set = evaluate[T](d, s, expr, &v)
return
}