Skip to content
Draft
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
1 change: 1 addition & 0 deletions sjsonnet/src/sjsonnet/Evaluator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ class Evaluator(
scope: ValScope): Val.Func =
new Val.Func(outerPos, scope, params) {
override def functionName: String = name
override val bodyExpr: Expr = rhs
def evalRhs(vs: ValScope, es: EvalScope, fs: FileScope, pos: Position): Val =
visitExprWithTailCallSupport(rhs)(vs)
override def evalDefault(expr: Expr, vs: ValScope, es: EvalScope): Val = {
Expand Down
6 changes: 6 additions & 0 deletions sjsonnet/src/sjsonnet/Val.scala
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,12 @@ object Val {

def evalRhs(scope: ValScope, ev: EvalScope, fs: FileScope, pos: Position): Val

/**
* Override to expose the function's body AST for pattern detection (e.g. constant-body
* makeArray optimization). Returns null by default.
*/
def bodyExpr: Expr = null

// Convenience wrapper: evaluates the function body and resolves any TailCall sentinel.
// Use this instead of raw `evalRhs` at call sites that bypass `apply*` and consume
// the result directly (e.g. stdlib scope-reuse fast paths).
Expand Down
18 changes: 13 additions & 5 deletions sjsonnet/src/sjsonnet/stdlib/ArrayModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,19 @@ object ArrayModule extends AbstractFunctionModule {
pos, {
val sz = size.cast[Val.Num].asPositiveInt
val a = new Array[Eval](sz)
val noOff = pos.noOffset
var i = 0
while (i < sz) {
a(i) = new LazyApply1(func, Val.Num(pos, i), noOff, ev)
i += 1
val body = func.bodyExpr
if (func.params.names.length == 1 && body != null && body.isInstanceOf[Val.Literal]) {
// Function body is a constant (e.g. `function(_) 'x'`).
// Skip lazy thunk + Val.Num(index) allocation per element.
val constVal = body.asInstanceOf[Val]
java.util.Arrays.fill(a.asInstanceOf[Array[AnyRef]], constVal)
} else {
val noOff = pos.noOffset
var i = 0
while (i < sz) {
a(i) = new LazyApply1(func, Val.Num(pos, i), noOff, ev)
i += 1
}
}
a
}
Expand Down