New built-in functions for late binding interpolation (fn::template and fn::eval)#638
Open
New built-in functions for late binding interpolation (fn::template and fn::eval)#638
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces late-binding interpolation by adding two new built-in functions: fn::template (to define a deferred template) and fn::eval (to evaluate a deferred template in the consumer environment), along with a new golden test case under eval/testdata/eval/late-binding.
Changes:
- Add AST support for
fn::templateandfn::eval. - Add evaluator support to defer template evaluation and explicitly evaluate it later via
fn::eval. - Add new
late-bindingeval test fixtures + expected output.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
ast/expr.go |
Adds AST nodes + parsing hooks for fn::template / fn::eval. |
eval/eval.go |
Declares/evaluates new expr forms (templateExpr, evalExpr) to implement late-binding. |
eval/expr.go |
Updates expression exporting logic for the new expr kinds. |
eval/eval_test.go |
Modifies the golden-test runner logic (currently filtering to only late-binding). |
eval/testdata/eval/late-binding/* |
Adds new golden test case YAMLs + expected.json. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+367
to
+369
| entries = slices.DeleteFunc(entries, func(entry os.DirEntry) bool { | ||
| return entry.Name() != "late-binding" | ||
| }) |
Comment on lines
+660
to
+662
| defn := e.evaluateExpr(repr.value, schema.Always()) // deref template expr | ||
| expr := declare(e, "", defn.repr.(*templateExpr).node.Args(), nil) // clone its ast node into a new expr | ||
| val = e.evaluateExpr(expr, schema.Always()) // evaluate it |
| repr := &templateExpr{node: x, template: declare(e, "", x.Args(), nil)} | ||
| return newExpr(path, repr, schema.Never().Schema(), base) | ||
| case *ast.EvalExpr: | ||
| repr := &evalExpr{node: x, value: declare(e, "", x.Args(), base)} |
Comment on lines
+348
to
+350
| // not evaluated | ||
| case *evalExpr: | ||
| return repr.value.export(environment) |
Member
|
this really needs a design doc. do we have one? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces new built-in function to enable late binding interpolation
The
fn::templatebuilt-in function defines a template expression whose interpolations are not resolved immediately. Instead, the template is evaluated later when a consumer environment references it withfn::eval. This enables late binding — defining reusable expressions in one environment and evaluating them with different values in another.Test changes
Risk
None.
Rollback
Revert the commit