Skip to content
Open
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
11 changes: 1 addition & 10 deletions exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g
Original file line number Diff line number Diff line change
Expand Up @@ -3506,16 +3506,7 @@ throws PermissionDeniedException, EXistException, XPathException
)*
)
{
step = FunctionFactory.createFunction(context, fn, path, params);
if (isPartial) {
if (!(step instanceof FunctionCall)) {
if (step instanceof CastExpression) {
step = ((CastExpression)step).toFunction();
}
step = FunctionFactory.wrap(context, (Function)step);
}
step = new PartialFunctionApplication(context, (FunctionCall) step);
}
step = FunctionFactory.createFunctionCall(context, fn, path, params, isPartial);
}
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@ public abstract class AbstractInternalModule implements InternalModule {
protected final Map<QName, Variable> mGlobalVariables = new HashMap<>();
private final Map<String, List<?>> parameters;

public static class FunctionComparator implements Comparator<FunctionDef> {
@Override
public int compare(final FunctionDef o1, final FunctionDef o2) {
return o1.getSignature().getFunctionId().compareTo(o2.getSignature().getFunctionId());
}
}

public AbstractInternalModule(final FunctionDef[] functions, final Map<String, List<?>> parameters) {
// Defensive-copy + sort so the caller's static final array is left intact
// and getFunctionDef() can binary-search regardless of declaration order.
Expand All @@ -78,12 +71,11 @@ public AbstractInternalModule(final FunctionDef[] functions, final Map<String, L
* eXist 7 without source changes; call sites should migrate to
* {@link #AbstractInternalModule(FunctionDef[], Map)}.
*
* @param functions the array of functions
* @param parameters configuration parameters
* @param functionsOrdered ignored as of #6378
*
* @param functions the array of functions
* @param parameters configuration parameters
* @param functionsOrdered ignored as of #6378
* @deprecated since 7.0.0; the {@code functionsOrdered} parameter has no effect.
* Use {@link #AbstractInternalModule(FunctionDef[], Map)}.
* Use {@link #AbstractInternalModule(FunctionDef[], Map)}.
*/
@Deprecated(since = "7.0.0", forRemoval = true)
public AbstractInternalModule(final FunctionDef[] functions, final Map<String, List<?>> parameters,
Expand All @@ -100,7 +92,7 @@ public boolean isInternalModule() {
* Get a parameter.
*
* @param paramName the name of the parameter
* @return the value of tyhe parameter
* @return the value of type parameter
*/
protected List<?> getParameter(final String paramName) {
return parameters.get(paramName);
Expand Down Expand Up @@ -142,6 +134,7 @@ public FunctionDef getFunctionDef(QName qname, int arity) {
return binarySearch(new FunctionId(qname, arity));
}

@Nullable
private FunctionDef binarySearch(final FunctionId id) {
int low = 0;
int high = mFunctions.length - 1;
Expand All @@ -163,16 +156,17 @@ private FunctionDef binarySearch(final FunctionId id) {

@Override
public List<FunctionSignature> getFunctionsByName(final QName qname) {
final List<FunctionSignature> funcs = new ArrayList<>();
final List<FunctionSignature> matchingFunctions = new ArrayList<>();
for (FunctionDef mFunction : mFunctions) {
final FunctionSignature sig = mFunction.getSignature();
if (sig.getName().compareTo(qname) == 0) {
funcs.add(sig);
matchingFunctions.add(sig);
}
}
return funcs;
return matchingFunctions;
}

@Override
public Iterator<QName> getGlobalVariables() {
return mGlobalVariables.keySet().iterator();
}
Expand Down Expand Up @@ -228,7 +222,7 @@ public Variable resolveVariable(final QName qname) throws XPathException {

@Override
@Nullable
public Variable resolveVariable(@Nullable final AnalyzeContextInfo contextInfo, final QName qname) throws XPathException {
public Variable resolveVariable(@Nullable final AnalyzeContextInfo contextInfo, final QName qname) {
return mGlobalVariables.get(qname);
}

Expand All @@ -251,4 +245,11 @@ public void reset(final XQueryContext xqueryContext, final boolean keepGlobals)
mGlobalVariables.clear();
}
}

public static class FunctionComparator implements Comparator<FunctionDef> {
@Override
public int compare(final FunctionDef o1, final FunctionDef o2) {
return o1.getSignature().getFunctionId().compareTo(o2.getSignature().getFunctionId());
}
}
}
43 changes: 19 additions & 24 deletions exist-core/src/main/java/org/exist/xquery/ArrowOperator.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,30 +70,37 @@ public void setArrowFunction(final PathExpr funcSpec, final List<Expression> par

@Override
public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException {
if(getContext().getXQueryVersion() < 31) {
if (getContext().getXQueryVersion() < 31) {
throw new XPathException(this,
ErrorCodes.EXXQDY0003,
"arrow operator is not available before XQuery 3.1");
}
this.cachedContextInfo = contextInfo;
if (qname == null) {
// Dynamic (higher-order) right-hand side: analyze the operands as they are. The function
// to call is resolved at evaluation time by evaluating funcSpec.
// The function call on the right hand side is resolved at evaluation time by evaluating funcSpec.
leftExpr.analyze(contextInfo);
funcSpec.analyze(contextInfo);
return;
}

// Statically-named function: compile the arrow to the equivalent call
// f(leftExpr, parameters...), exactly as the parser builds a normal function call (the
// functionCall rule in XQueryTree.g). The left-hand side becomes a real argument
// expression — so it keeps its static context (fixing the lost-variable-scope bug, e.g.
// EXPR => util:eval()) — and a '?' placeholder yields a partial function application
// (fixing the placeholder arity bug). This replaces the previous dynamic FunctionReference
// dispatch, which pre-evaluated the left-hand side and modelled it as a placeholder.
namedCall = getNamedFunctionCall();
namedCall.analyze(contextInfo);
}

/**
* Statically-named function: compile the arrow to the equivalent call f(leftExpr, parameters...),
* exactly as the parser builds a normal function call (the functionCall rule in XQueryTree.g).
* The left-hand side becomes a real argument expression
* — so it keeps its static context (fixing the lost-variable-scope bug, e.g. EXPR => util:eval())
* — and a '?' placeholder yields a partial function application (fixing the placeholder arity bug).
* This replaces the previous dynamic FunctionReference dispatch, which pre-evaluated the left-hand side and
* modeled it as a placeholder.
*/
private Expression getNamedFunctionCall() throws XPathException {
final XQueryAST ast = new XQueryAST();
ast.setLine(getLine());
ast.setColumn(getColumn());

final List<Expression> callArgs = new ArrayList<>(parameters.size() + 1);
callArgs.add(toArgument(leftExpr));
boolean partial = false;
Expand All @@ -105,20 +112,8 @@ public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException
callArgs.add(toArgument(param));
}
}
Expression call = FunctionFactory.createFunction(context, qname, ast, null, callArgs);
if (partial) {
// mirror the functionCall rule: a '?' placeholder turns the call into a partial
// function application yielding a function item of the remaining arity.
if (!(call instanceof FunctionCall)) {
if (call instanceof CastExpression) {
call = ((CastExpression) call).toFunction();
}
call = FunctionFactory.wrap(context, (Function) call);
}
call = new PartialFunctionApplication(context, (FunctionCall) call);
}
namedCall = call;
namedCall.analyze(contextInfo);

return FunctionFactory.createFunctionCall(context, qname, ast, null, callArgs, partial);
}

/**
Expand Down
54 changes: 28 additions & 26 deletions exist-core/src/main/java/org/exist/xquery/ExternalModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,88 +30,90 @@
/**
* An external library module implemented in XQuery and loaded
* through the "import module" directive.
*
*
* @author <a href="mailto:wolfgang@exist-db.org">Wolfgang Meier</a>
*/
public interface ExternalModule extends Module {

public void setNamespace(String prefix, String namespace);
void setNamespace(String prefix, String namespace);

public void setDescription(String desc);
void setDescription(String desc);

public void addMetadata(String key, String value);
void addMetadata(String key, String value);

public Map<String, String> getMetadata();
Map<String, String> getMetadata();

/**
* Declare a new function. Called by the XQuery compiler
* when parsing a library module for every function declaration.
*
*
* @param func the function to add
*/
public void declareFunction(UserDefinedFunction func) throws XPathException;
void declareFunction(UserDefinedFunction func) throws XPathException;

/**
* Try to find the function identified by qname. Returns null
* if the function is undefined.
*
* @param qname the name of the function to look for
* @param arity arity of the function to look for
*
* @param qname the name of the function to look for
* @param arity arity of the function to look for
* @param callerContext context of the caller - needed to check if
* found function should be visible
* @throws XPathException in case of a dynamic error
* @return the function found
* @throws XPathException in case of a dynamic error
*/
public UserDefinedFunction getFunction(QName qname, int arity, XQueryContext callerContext) throws XPathException;
UserDefinedFunction getFunction(QName qname, int arity, XQueryContext callerContext) throws XPathException;

public void declareVariable(QName qname, VariableDeclaration decl) throws XPathException;
void declareVariable(QName qname, VariableDeclaration decl) throws XPathException;

/**
* Analyze declared variables. Needs to be called when the module was imported dynamically.
*
* @throws XPathException in case of static errors
*/
public void analyzeGlobalVars() throws XPathException;
void analyzeGlobalVars() throws XPathException;

public Collection<VariableDeclaration> getVariableDeclarations();
Collection<VariableDeclaration> getVariableDeclarations();

/**
* Get the source object this module has been read from.
*
* <p>
* This is required for query access control.
*
* @return The source object this module has been read from.
*/
public Source getSource();
Source getSource();

/**
* Set the source object this module has been read from.
*
* <p>
* This is required to check the validity of a compiled expression.
*
* @param source the source instance
*/
public void setSource(Source source);
void setSource(Source source);

public XQueryContext getContext();
XQueryContext getContext();

/**
* Set the XQueryContext of this module. This will be a sub-context
* of the main context as parts of the static context are shared.
*
* of the main context as parts of the static context are shared.
*
* @param context the context to set
*/
public void setContext(XQueryContext context);
void setContext(XQueryContext context);

/**
* Is this module still valid or should it be reloaded from its source?
*
* @return true if module should be reloaded
*/
public boolean moduleIsValid();
boolean moduleIsValid();

/**
* Returns the root expression associated with this context.
*
* @return root expression
* @return root expression
*/
public Expression getRootExpression();
Expression getRootExpression();
}
Loading