Skip to content

Commit

Permalink
Fix for #25 (Broken lambdas due to variable scoping).
Browse files Browse the repository at this point in the history
  • Loading branch information
Aklakan committed Oct 22, 2024
1 parent 9a41a1e commit b436105
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
package org.aksw.jena_sparql_api.sparql.ext.sys;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.aksw.jenax.arq.datatype.lambda.Lambda;
import org.aksw.jenax.arq.datatype.lambda.NodeValueLambda;
import org.aksw.jenax.arq.util.binding.BindingUtils;
import org.aksw.jenax.arq.util.expr.ExprUtils;
import org.aksw.jenax.arq.util.var.VarUtils;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.ResultSet;
import org.apache.jena.query.ResultSetFormatter;
import org.apache.jena.sparql.core.DatasetGraphFactory;
import org.apache.jena.sparql.core.Substitute;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.engine.Rename;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.exec.QueryExec;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.function.FunctionBase;
import org.apache.jena.sparql.function.FunctionEnv;
import org.apache.jena.sparql.service.enhancer.impl.util.VarScopeUtils;

/**
* A function that returns an RDF term that encapsulates a lambda.
Expand Down Expand Up @@ -85,18 +91,21 @@ public NodeValue exec(Binding binding, ExprList args, String uri, FunctionEnv en
if (n == 0) {
throw new RuntimeException("At least 1 argument required which is an expression");
}
List<Expr> el = args.getList();
List<Expr> argList = el.subList(0, n - 1);
List<Expr> scopedExprs = args.getList();
List<Expr> scopedArgList = scopedExprs.subList(0, n - 1);

List<Var> argVars = argList.stream().map(e -> e.asVar()).collect(Collectors.toList());
Set<Var> argVarsSet = new HashSet<>(argVars);
Expr rawExpr = el.get(n - 1);
List<Var> scopedArgVars = scopedArgList.stream().map(e -> e.asVar()).collect(Collectors.toList());
Set<Var> scopedArgVarsSet = new HashSet<>(scopedArgVars);
Expr scopedRawExpr = scopedExprs.get(n - 1);

// Remove all argVars from the binding
Binding effBinding = BindingUtils.project(binding, binding.vars(), argVarsSet);
Expr expr = Substitute.substitute(rawExpr, effBinding);
Binding effBinding = BindingUtils.project(binding, binding.vars(), scopedArgVarsSet);
Expr scopedExpr = Substitute.substitute(scopedRawExpr, effBinding);

Lambda lambda = new Lambda(argVars, expr);
List<Var> unscopedArgVars = scopedArgVars.stream().map(v -> (Var)Rename.reverseVarRename(v)).toList();
Expr unscopedExpr = ExprUtils.reverseVarRename(scopedExpr);

Lambda lambda = new Lambda(unscopedArgVars, unscopedExpr);
NodeValue result = new NodeValueLambda(lambda);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import org.aksw.jenax.arq.functionbinder.FunctionBinder;
import org.aksw.jenax.arq.functionbinder.FunctionBinders;
import org.aksw.jenax.norse.term.core.NorseTerms;
import org.aksw.jenax.norse.term.rdf.NorseTermsLambda;
import org.aksw.jenax.norse.term.sparql.NorseTermsSparql;
import org.apache.jena.shared.PrefixMapping;
import org.apache.jena.sparql.function.FunctionRegistry;
import org.apache.jena.sparql.pfunction.PropertyFunctionRegistry;
Expand All @@ -35,9 +35,14 @@ public static void register() {
registry.put(ns + "nextLong", E_NextLong.class);
registry.put(ns + "rscmp", E_CompareResultSet.class);

registry.put(NorseTermsLambda.fnOf, FN_LambdaOf.class);
registry.put(NorseTermsLambda.fnCall, FN_LambdaCall.class);
registry.put(NorseTermsLambda.mapComputeIfAbsent, FN_MapComputeIfAbsent.class);
// Legacy registrations
// registry.put(NorseTermsLambda.fnOf, FN_LambdaOf.class);
// registry.put(NorseTermsLambda.fnCall, FN_LambdaCall.class);
// registry.put(NorseTermsLambda.mapComputeIfAbsent, FN_MapComputeIfAbsent.class);

registry.put(NorseTermsSparql.fnOf, FN_LambdaOf.class);
registry.put(NorseTermsSparql.fnCall, FN_LambdaCall.class);
registry.put(NorseTermsSparql.mapComputeIfAbsent, FN_MapComputeIfAbsent.class);

FunctionBinder binder = FunctionBinders.getDefaultFunctionBinder();
binder.register(ns + "getenv", System.class, "getenv", String.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package org.aksw.jenax.arq.datatype.lambda;

import org.aksw.jenax.norse.term.sparql.NorseTermsSparql;
import org.apache.jena.datatypes.BaseDatatype;
import org.apache.jena.datatypes.DatatypeFormatException;
import org.apache.jena.datatypes.RDFDatatype;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprEvalException;
import org.apache.jena.sparql.util.ExprUtils;

///**
// * A datatype for storing SPARQL expressions in RDF literals.
Expand All @@ -16,9 +14,12 @@
public class RDFDatatypeLambda
extends BaseDatatype
{
public static final String IRI = "http://jsa.aksw.org/dt/sparql/lambda";
public static final String IRI = NorseTermsSparql.fn;
public static final RDFDatatypeLambda INSTANCE = new RDFDatatypeLambda();

// Legacy IRI
// public static final String IRI = "http://jsa.aksw.org/dt/sparql/lambda";

public static RDFDatatype get() {
return INSTANCE;
}
Expand Down Expand Up @@ -58,4 +59,4 @@ public Lambda parse(String lexicalForm) throws DatatypeFormatException {
Lambda result = Lambdas.parse(lexicalForm);
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.core.VarAlloc;
import org.apache.jena.sparql.engine.Rename;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.expr.E_Bound;
import org.apache.jena.sparql.expr.E_Equals;
Expand Down Expand Up @@ -175,6 +176,11 @@ public static Expr applyNodeTransform(Expr expr, NodeTransform xform) {
return result;
}

/** Repeatedly reverse var naming of {@link Rename#renameVars(Expr, Set)}. */
public static Expr reverseVarRename(Expr expr) {
return applyNodeTransform(expr, Rename::reverseVarRename);
}

public static E_OneOf oneOf(Node v, Iterable<Node> args) {
ExprList el = new ExprList();
el.addAll(ExprListUtils.nodesToExprs(args));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.aksw.jenax.norse.term.sparql;

import org.aksw.jenax.norse.term.core.NorseTerms;

public class NorseTermsSparql {
public static final String NS = NorseTerms.NS + "sparql.";
public static final String fn = NorseTerms.NS + "fn";

public static final String fnOf = NorseTerms.NS + "fn.of";
public static final String fnCall = NorseTerms.NS + "fn.call";

// Move to Map
public static final String mapComputeIfAbsent = NorseTerms.NS + "map.computeIfAbsent";

}

0 comments on commit b436105

Please sign in to comment.