Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/anonymous functions #266

Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -216,6 +217,16 @@ public IItemType getItemTypeByItemClass(Class<? extends IItem> clazz) {
return itemTypeByItemClass.get(clazz);
}

/**
* Get the collection of data type adapters provided by this service.
*
* @return the data type adapters
*/
@NonNull
public Collection<? extends IDataTypeAdapter<?>> getDataTypes() {
return ObjectUtils.notNull(atomicTypeByAdapterClass.values());
}

/**
* Lookup a specific {@link IDataTypeAdapter} by its adapter class.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import gov.nist.secauto.metaschema.core.configuration.DefaultConfiguration;
import gov.nist.secauto.metaschema.core.configuration.IConfiguration;
import gov.nist.secauto.metaschema.core.configuration.IMutableConfiguration;
import gov.nist.secauto.metaschema.core.metapath.function.DefaultFunction.CallingContext;
import gov.nist.secauto.metaschema.core.metapath.function.CallingContext;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction.FunctionProperty;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem;
import gov.nist.secauto.metaschema.core.model.IUriResolver;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* The implementation of a Metapath
* <a href="https://www.w3.org/TR/xpath-31/#static_context">static context</a>.
*/
// FIXME: refactor well-known into a new class
public final class StaticContext {
@NonNull
private static final Map<String, String> WELL_KNOWN_NAMESPACES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,40 @@ public R visitArgument(Metapath10.ArgumentContext ctx) {
throw new IllegalStateException(ERR_NO_DELEGATION);
}

// ============================================================
// https://www.w3.org/TR/xpath-31/#doc-xpath31-NamedFunctionRef
// ============================================================

@Override
public R visitNamedfunctionref(Metapath10.NamedfunctionrefContext ctx) {
throw new UnsupportedOperationException("expression not supported");
}
david-waltermire marked this conversation as resolved.
Show resolved Hide resolved

// ==============================================
// https://www.w3.org/TR/xpath-31/#id-inline-func
// ==============================================

@Override
public R visitFunctionitemexpr(Metapath10.FunctionitemexprContext ctx) {
assert ctx != null;
return delegateToChild(ctx);
}

/**
* Handle the provided expression.
*
* @param ctx
* the provided expression context
* @return the result
*/
protected abstract R handleInlinefunctionexpr(@NonNull Metapath10.InlinefunctionexprContext ctx);

@Override
public R visitInlinefunctionexpr(Metapath10.InlinefunctionexprContext ctx) {
assert ctx != null;
return handle(ctx, this::handleInlinefunctionexpr);
}

// =======================================================================
// Enclosed Expressions - https://www.w3.org/TR/xpath-31/#id-enclosed-expr
// =======================================================================
Expand Down Expand Up @@ -1018,16 +1052,6 @@ public R visitArrowfunctionspecifier(Metapath10.ArrowfunctionspecifierContext ct
throw new IllegalStateException(ERR_NO_DELEGATION);
}

@Override
public R visitNamedfunctionref(Metapath10.NamedfunctionrefContext ctx) {
throw new UnsupportedOperationException("expression not supported");
}

@Override
public R visitInlinefunctionexpr(Metapath10.InlinefunctionexprContext ctx) {
throw new UnsupportedOperationException("expression not supported");
}

/*
* ==========================================================
* The following are handled inline by other expression types
Expand Down Expand Up @@ -1225,12 +1249,6 @@ public R visitFunctionbody(Metapath10.FunctionbodyContext ctx) {
throw new IllegalStateException(ERR_NO_DELEGATION);
}

@Override
public R visitFunctionitemexpr(Metapath10.FunctionitemexprContext ctx) {
// should never be called, since this is handled by the parent expression
throw new IllegalStateException(ERR_NO_DELEGATION);
}

@Override
public R visitTypedeclaration(Metapath10.TypedeclarationContext ctx) {
// should never be called, since this is handled by the parent expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,48 @@ public IExpression visit(ParseTree tree) {
* @return the outer expression or {@code null} if no children exist to parse
*/
@Nullable
protected <CONTEXT extends ParserRuleContext, T extends IExpression, R extends IExpression>
protected <CONTEXT extends ParserRuleContext, T, R, S extends List<R>>
List<R> nairyToList(
@NonNull CONTEXT context,
int startIndex,
int step,
@NonNull BiFunction<CONTEXT, Integer, R> parser) {
int numChildren = context.getChildCount();

List<R> retval = null;
if (startIndex < numChildren) {
retval = new ArrayList<>((numChildren - startIndex) / step);
for (int idx = startIndex; idx < numChildren; idx += step) {
R result = parser.apply(context, idx);
retval.add(result);
}
}
return retval;
}

/**
* Parse the provided context as an n-ary phrase.
*
* @param <CONTEXT>
* the Java type of the antlr context to parse
* @param <T>
* the Java type of the child expressions produced by this parser
* @param <R>
* the Java type of the outer expression produced by the parser
* @param context
* the antlr context to parse
* @param startIndex
* the child index to start parsing on
* @param step
* the increment to advance while parsing child expressions
* @param parser
* a binary function used to produce child expressions
* @param supplier
* a function used to produce the other expression
* @return the outer expression or {@code null} if no children exist to parse
*/
@Nullable
protected <CONTEXT extends ParserRuleContext, T, R>
R nairyToCollection(
@NonNull CONTEXT context,
int startIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,17 @@ public RESULT visitFlag(Flag expr, CONTEXT context) {
}

@Override
public RESULT visitFunctionCall(StaticFunctionCall expr, CONTEXT context) {
public RESULT visitStaticFunctionCall(StaticFunctionCall expr, CONTEXT context) {
return visitChildren(expr, context);
}

@Override
public RESULT visitDynamicFunctionCall(DynamicFunctionCall expr, CONTEXT context) {
return visitChildren(expr, context);
}

@Override
public RESULT visitAnonymousFunctionCall(AnonymousFunctionCall expr, CONTEXT context) {
return visitChildren(expr, context);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/

package gov.nist.secauto.metaschema.core.metapath.cst;

import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.ISequence;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
import gov.nist.secauto.metaschema.core.metapath.function.impl.AbstractFunction;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.type.ISequenceType;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

/**
* Executes a function call based on a specifier expression that is used to
* dtermine the function and multiple argument expressions that are used to
* determine the function arguments.
*/
public class AnonymousFunctionCall
extends AbstractFunction
implements IExpression, IFunction {
@NonNull
private static final Set<FunctionProperty> PROPERTIES = ObjectUtils.notNull(EnumSet.of(
// FunctionProperty.CONTEXT_DEPENDENT,
// FunctionProperty.FOCUS_DEPENDENT,
david-waltermire marked this conversation as resolved.
Show resolved Hide resolved
FunctionProperty.DETERMINISTIC));
@NonNull
private final ISequenceType result;
@NonNull
private final IExpression body;

/**
* Construct a new function call expression.
*
* @param arguments
*/
public AnonymousFunctionCall(
@NonNull List<IArgument> arguments,
@NonNull ISequenceType result,
@NonNull IExpression body) {
super("(anonymous)-" + UUID.randomUUID().toString(), "", arguments);
this.result = result;
this.body = body;
}

@Override
public List<IExpression> getChildren() {
return ObjectUtils.notNull(List.of(body));
}

@Override
public Class<? extends IItem> getBaseResultType() {
return IFunction.class;
}

@Override
public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
return visitor.visitAnonymousFunctionCall(this, context);
}

@Override
public ISequence<?> accept(DynamicContext dynamicContext, ISequence<?> focus) {
return ISequence.of(this);
}

@SuppressWarnings("null")
@Override
public String toASTString() {
return String.format("%s[arguments=%s,return=%s]",
getClass().getName(), getName(),
getArguments(),
result.toSignature());
}
david-waltermire marked this conversation as resolved.
Show resolved Hide resolved

@Override
public Set<FunctionProperty> getProperties() {
return PROPERTIES;
}

@Override
public ISequenceType getResult() {
return result;
}

@Override
@NonNull
protected ISequence<?> executeInternal(
@NonNull List<ISequence<?>> arguments,
@NonNull DynamicContext dynamicContext,
@Nullable IItem focus) {

DynamicContext subContext = dynamicContext.subContext();
Iterator<? extends ISequence<?>> args = arguments.iterator();
Iterator<IArgument> params = getArguments().iterator();
while (args.hasNext() && params.hasNext()) {
ISequence<?> sequence = args.next();
IArgument param = params.next();

subContext.bindVariableValue(param.getName(), ObjectUtils.notNull(sequence));
}
david-waltermire marked this conversation as resolved.
Show resolved Hide resolved

return body.accept(subContext, ISequence.of(focus));
}
}
Loading