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
17 changes: 16 additions & 1 deletion basex-core/src/main/java/org/basex/query/func/Closure.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public Closure(final InputInfo info, final Expr expr, final Params params, final
this.params = params;
this.anns = anns;
this.vs = vs;
this.global = global == null ? Collections.emptyMap() : global;
this.global = global == null ? new HashMap<>() : new HashMap<>(global);
this.declType = declType == null || declType.eq(Types.ITEM_ZM) ? null : declType;
this.name = name;
}
Expand Down Expand Up @@ -128,6 +128,7 @@ public Expr compile(final CompileContext cc) throws QueryException {
compiled = true;

checkUpdating();
captureContextIfNeeded(cc);

// compile closure
for(final Entry<Var, Expr> entry : global.entrySet()) {
Expand All @@ -147,6 +148,20 @@ public Expr compile(final CompileContext cc) throws QueryException {
return optimize(cc);
}

/**
* Captures the context value if this closure wraps a static function call whose omitted default
* arguments depend on the context. This can happen for partial function applications.
* @param cc compile context
* @throws QueryException query exception
*/
private void captureContextIfNeeded(final CompileContext cc) throws QueryException {
if(!(expr instanceof StaticFuncCall sfc)) return;
final Var var = new Var(new QNm("ctx"), Types.ITEM_ZM, cc.qc, info);
final VarRef ref = new VarRef(info, var);
final InlineContext ic = new InlineContext(null, ref, cc);
if(ic.inlineOrNull(sfc) != null) global.put(vs.add(var), new ContextValue(info));
}

@Override
public Expr optimize(final CompileContext cc) {
cc.pushScope(vs);
Expand Down
12 changes: 12 additions & 0 deletions basex-core/src/test/java/org/basex/query/ast/FuncItemTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ public final class FuncItemTest extends SandboxTest {
);
}

/** Checks that partial functions can use default parameters with context value. */
@Test public void partAppContextDefault() {
query("declare function f($a, $b:= .) { $a + $b }; 1!f(?)(2)", 3);
query("declare function f($a, $b:= 3 + .) { $a + $b }; 1!f(?)(2)", 6);
query("declare function f($a, $b:= <a>3</a>/. + .) { $a + $b }; 1!f(?)(2)", 6);
query("declare function f($a, $b:= .) { $a + $b }; let $v := 1!f(?) return 2!$v(3)", 4);

error("declare function f($a, $b:= .) { $a + $b }; f(?)(2)", NOCTX_X);
error("declare function f() {.}; 1!f() ", NOCTX_X);
error("declare function g($x := .) { $x }; let $f := fn() { g() } return 1!$f()", NOCTX_X);
}

/** Checks that the Y combinator is pre-compiled. */
@Test public void yCombinatorTest() {
check("function($f) {" +
Expand Down
Loading