Skip to content

Commit

Permalink
[FIX] XQuery, inspect:functions: compile closures. #1194
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianGruen committed Mar 3, 2016
1 parent 8c8acfa commit d30d765
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ boolean parse(final HTTPContext http) throws Exception {
try(final QueryContext qc = qc(ctx)) {
// loop through all functions
final String name = file.name();
for(final StaticFunc uf : qc.funcs.funcs()) {
for(final StaticFunc sf : qc.funcs.funcs()) {
// only add functions that are defined in the same module (file)
if(name.equals(new IOFile(uf.info.path()).name())) {
final RestXqFunction rxf = new RestXqFunction(uf, qc, this);
if(name.equals(new IOFile(sf.info.path()).name())) {
final RestXqFunction rxf = new RestXqFunction(sf, qc, this);
if(rxf.parse(ctx)) functions.add(rxf);
}
}
Expand Down
12 changes: 6 additions & 6 deletions basex-core/src/main/java/org/basex/query/func/Closure.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ public Expr compile(final QueryContext qc, final VarScope scp) throws QueryExcep

@Override
public Expr optimize(final QueryContext qc, final VarScope scp) throws QueryException {
final SeqType r = expr.seqType();
final SeqType rt = type == null || r.instanceOf(type) ? r : type;
final SeqType r = expr.seqType(), rt = type == null || r.instanceOf(type) ? r : type;
seqType = FuncType.get(anns, rt, args).seqType();
size = 1;

Expand Down Expand Up @@ -211,16 +210,17 @@ public Expr optimize(final QueryContext qc, final VarScope scp) throws QueryExce
@Override
public VarUsage count(final Var var) {
VarUsage all = VarUsage.NEVER;
for(final Entry<Var, Expr> e : global.entrySet())
for(final Entry<Var, Expr> e : global.entrySet()) {
if((all = all.plus(e.getValue().count(var))) == VarUsage.MORE_THAN_ONCE) break;
}
return all;
}

@Override
public Expr inline(final QueryContext qc, final VarScope scp,
final Var var, final Expr ex) throws QueryException {
boolean change = false;
public Expr inline(final QueryContext qc, final VarScope scp, final Var var, final Expr ex)
throws QueryException {

boolean change = false;
for(final Entry<Var, Expr> entry : global.entrySet()) {
final Expr e = entry.getValue().inline(qc, scp, var, ex);
if(e != null) {
Expand Down
8 changes: 5 additions & 3 deletions basex-core/src/main/java/org/basex/query/func/Function.java
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ ITEM_ZM, flag(HOF)),
FUNCTION_ARITY(FnFunctionArity.class, "function-arity(function)", arg(FUN_O), ITR),
/** XQuery function. */
FUNCTION_LOOKUP(FnFunctionLookup.class, "function-lookup(name,arity)",
arg(QNM, ITR), FUN_OZ, flag(CTX, Flag.POS, NDT)),
arg(QNM, ITR), FUN_OZ, flag(CTX, Flag.POS, NDT, HOF)),
/** XQuery function. */
FUNCTION_NAME(FnFunctionName.class, "function-name(function)", arg(FUN_O), QNM_ZO),
/** XQuery function. */
Expand Down Expand Up @@ -1061,13 +1061,15 @@ ITEM_ZM, flag(HOF)),
/* Inspection Module. */

/** XQuery function. */
_INSPECT_FUNCTION(InspectFunction.class, "function(function)", arg(STR), ELM, INSPECT_URI),
_INSPECT_FUNCTION(InspectFunction.class, "function(function)",
arg(STR), ELM, flag(HOF), INSPECT_URI),
/** XQuery function. */
_INSPECT_MODULE(InspectModule.class, "module(uri)", arg(STR), ELM, INSPECT_URI),
/** XQuery function. */
_INSPECT_CONTEXT(InspectContext.class, "context()", arg(), ELM, INSPECT_URI),
/** XQuery function. */
_INSPECT_FUNCTIONS(InspectFunctions.class, "functions([uri])", arg(STR), FUN_ZM, INSPECT_URI),
_INSPECT_FUNCTIONS(InspectFunctions.class, "functions([uri])",
arg(STR), FUN_ZM, flag(HOF), INSPECT_URI),
/** XQuery function. */
_INSPECT_XQDOC(InspectXqdoc.class, "xqdoc(uri)", arg(STR), ELM, INSPECT_URI),

Expand Down
13 changes: 11 additions & 2 deletions basex-core/src/main/java/org/basex/query/func/StaticFuncs.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,22 @@ public void checkUp() throws QueryException {
}

/**
* Compiles the functions.
* Compiles the used functions.
* @param qc query context
*/
public void compile(final QueryContext qc) {
compile(qc, false);
}

/**
* Compiles all functions.
* @param qc query context
* @param all compile all functions (not only used ones)
*/
public void compile(final QueryContext qc, final boolean all) {
// only compile those functions that are used
for(final FuncCache fc : funcs.values()) {
if(!fc.calls.isEmpty()) fc.func.compile(qc);
if(all || !fc.calls.isEmpty()) fc.func.compile(qc);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Item item(final QueryContext qc, final InputInfo ii) throws QueryExceptio

@Override
protected Expr opt(final QueryContext qc, final VarScope scp) {
for(final StaticFunc sf : qc.funcs.funcs()) sf.compile(qc);
qc.funcs.compile(qc, true);
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Value value(final QueryContext qc) throws QueryException {
try {
final IO io = checkPath(exprs[0], qc);
qc.parse(Token.string(io.read()), io.path(), sc);
qc.compile();
qc.funcs.compile(qc, true);
} catch(final IOException ex) {
throw IOERR_X.get(info, ex);
}
Expand All @@ -56,10 +56,7 @@ public Value value(final QueryContext qc) throws QueryException {

@Override
protected Expr opt(final QueryContext qc, final VarScope scp) throws QueryException {
if(exprs.length == 0) {
for(final StaticFunc sf : qc.funcs.funcs()) sf.compile(qc);
return iter(qc).value();
}
if(exprs.length == 0) qc.funcs.compile(qc, true);
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,20 @@ public void context() {
/** Test method. */
@Test
public void functions() {
final String url = "src/test/resources/hello.xqm";
query("declare function local:x() { 1 }; " + COUNT.args(_INSPECT_FUNCTIONS.args()), "1");
query("declare function local:x() { 2 }; " + _INSPECT_FUNCTIONS.args() + "()", "2");
query("import module namespace hello='world' at 'src/test/resources/hello.xqm';" +
"inspect:functions()[last()] instance of function(*)", "true");
query("import module namespace hello='world' at '" + url + "';" +
_INSPECT_FUNCTIONS.args() + "[last()] instance of function(*)", "true");

query("for $f in " + _INSPECT_FUNCTIONS.args("src/test/resources/hello.xqm")
query("for $f in " + _INSPECT_FUNCTIONS.args(url)
+ "where local-name-from-QName(function-name($f)) = 'world' "
+ "return $f()", "hello world");

// ensure that closures will be compiled (GH-1194)
query(_INSPECT_FUNCTIONS.args(url)
+ "[function-name(.) = QName('world','closure')]()", "1");
query("import module namespace hello='world' at '" + url + "';"
+ _INSPECT_FUNCTIONS.args() + "[function-name(.) = xs:QName('hello:closure')]()", "1");
}
}
5 changes: 5 additions & 0 deletions basex-core/src/test/resources/hello.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ declare %public function hello:world() as xs:string {
declare %private %Q{ns}ignored function hello:internal() as xs:string {
"hello world"
};

(:~ Closure. :)
declare function hello:closure() {
count#1(1)
};

0 comments on commit d30d765

Please sign in to comment.