package org.simantics.document.server.request;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.simantics.db.Resource;
import org.simantics.db.common.procedure.adapter.TransientCacheListener;
import org.simantics.db.common.request.IndexRoot;
-import org.simantics.db.common.request.PossibleTypedParent;
import org.simantics.db.common.request.UnaryRead;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
-import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
import org.simantics.db.layer0.variable.Variable;
-import org.simantics.document.base.ontology.DocumentationResource;
-import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext;
import org.simantics.layer0.Layer0;
import org.simantics.scl.compiler.elaboration.expressions.EApply;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.MultiFunction;
import org.simantics.scl.runtime.SCLContext;
import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.FunctionImpl1;
import org.simantics.structural2.scl.ComponentTypeProperty;
import org.simantics.structural2.scl.FindPossibleComponentTypeRequest;
import org.simantics.structural2.scl.ReadComponentTypeInterfaceRequest;
import org.simantics.utils.datastructures.Pair;
-public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Object> {
-
- private final Pair<Resource,Resource> componentTypeAndRoot;
- private final Resource literal;
- protected String possibleExpectedValueType;
-
- public static class CompilationContext extends AbstractExpressionCompilationContext {
- public final Map<String, ComponentTypeProperty> propertyMap;
-
- public CompilationContext(RuntimeEnvironment runtimeEnvironment,
- Map<String, ComponentTypeProperty> propertyMap) {
- super(runtimeEnvironment);
- this.propertyMap = propertyMap;
- }
- }
-
- private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
- assert(literal != null);
- this.literal = literal;
- this.componentTypeAndRoot = componentTypeAndRoot;
- this.possibleExpectedValueType = possibleExpectedValueType;
- }
-
- public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
- this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
- }
-
- public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
- this(getComponentTypeAndRoot(graph, s, o), o, resolveExpectedValueType(graph, p));
- }
-
- private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException {
- Variable parent = property.getParent(graph);
- Resource represents = parent.getRepresents(graph);
- if(represents != null) {
- Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents));
- if(type != null) {
- Resource root = graph.syncRequest(new IndexRoot(type));
- return Pair.make(type, root);
- }
- }
- parent = parent.getParent(graph);
- Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));
- return Pair.make(parent.getType(graph), root);
- }
-
- private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component, Resource literal) throws DatabaseException {
- if(component != null) {
- Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
- if(type != null) {
- Resource root = graph.syncRequest(new IndexRoot(type));
- return Pair.make(type, root);
- } else {
- Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
- Resource componentType = graph.getSingleType(doc);
- Resource root = graph.syncRequest(new IndexRoot(doc));
- return Pair.make(componentType, root);
- }
- // TODO: For Antti to consider and fix later
- // Introduced to handle procedural user components where component == null
- } else if (literal != null) {
- Resource root = graph.syncRequest(new IndexRoot(literal));
- return Pair.make(null, root);
- } else {
- throw new DatabaseException("Couldn't resolve component type and root for component == null && literal == null");
- }
- //throw new IllegalStateException();
- }
+public class ServerSCLHandlerValueRequest extends ServerSCLValueRequestBase<org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext> {
+
+ private final Pair<Resource,Resource> componentTypeAndRoot;
+ private final Resource literal;
+ protected String possibleExpectedValueType;
+
+ public static class CompilationContext extends AbstractExpressionCompilationContext {
+ public final Map<String, ComponentTypeProperty> propertyMap;
+
+ public CompilationContext(RuntimeEnvironment runtimeEnvironment,
+ Map<String, ComponentTypeProperty> propertyMap) {
+ super(runtimeEnvironment);
+ this.propertyMap = propertyMap;
+ }
+ }
+
+ private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
+ assert(literal != null);
+ this.literal = literal;
+ this.componentTypeAndRoot = componentTypeAndRoot;
+ this.possibleExpectedValueType = possibleExpectedValueType;
+ }
+
+ public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
+ this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
+ }
+
+ public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+ this(getComponentTypeAndRoot(graph, s, o), o, resolveExpectedValueType(graph, p));
+ }
+
+ private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property) throws DatabaseException {
+ Variable parent = property.getParent(graph);
+ Resource represents = parent.getRepresents(graph);
+ if(represents != null) {
+ Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(represents));
+ if(type != null) {
+ Resource root = graph.syncRequest(new IndexRoot(type));
+ return Pair.make(type, root);
+ }
+ }
+ parent = parent.getParent(graph);
+ Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));
+ return Pair.make(parent.getType(graph), root);
+ }
+
public static List<TCon> getEffects(ReadGraph graph, Variable context) throws DatabaseException {
+ HandlerFn fn = (HandlerFn)compile(graph, context);
+ return fn.effects;
+ }
+
+ public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.get("graph");
try {
- ServerSCLHandlerValueRequest req = new ServerSCLHandlerValueRequest(graph, context);
- return req.getExpressionEffects(graph);
+ Function1<Object,Object> exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context),
+ TransientCacheListener.instance());
+ sclContext.put("graph", graph);
+ return exp.apply(context);
} catch (DatabaseException e) {
throw (DatabaseException)e;
} catch (Throwable t) {
throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
}
}
- public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
- SCLContext sclContext = SCLContext.getCurrent();
- Object oldGraph = sclContext.get("graph");
- try {
- Function1<Object,Object> exp = graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context),
- TransientCacheListener.instance());
- sclContext.put("graph", graph);
- return exp.apply(context);
- } catch (DatabaseException e) {
- throw (DatabaseException)e;
- } catch (Throwable t) {
- throw new DatabaseException(t);
- } finally {
- sclContext.put("graph", oldGraph);
- }
- }
-
- public static Function1<Object, Object> compile(ReadGraph graph, Variable context) throws DatabaseException {
- return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance());
- }
-
- public static Function1<Object, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
- return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.<Function1<Object,Object>>instance());
- }
-
- @Override
- protected String getExpressionText(ReadGraph graph)
- throws DatabaseException {
- Layer0 L0 = Layer0.getInstance(graph);
- String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
- return "\\context -> " + exp;
- }
-
- protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) {
- return new RuntimeEnvironmentRequest2(componentType, indexRoot) {
- @Override
- protected void fillEnvironmentSpecification(
- EnvironmentSpecification environmentSpecification) {
- }
- };
- }
-
- @Override
- protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {
- return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
- @Override
- public CompilationContext perform(ReadGraph graph) throws DatabaseException {
- RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
+ public static Function1<Object, Object> compile(ReadGraph graph, Variable context) throws DatabaseException {
+ return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance());
+ }
+
+ public static Function1<Object, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+ return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, s, o, p), TransientCacheListener.instance());
+ }
+
+ public static class HandlerFn extends FunctionImpl1<Object,Object> {
+
+ Function1<Object,Object> handler;
+ ArrayList<TCon> effects;
+
+ HandlerFn(Function1<Object,Object> handler, Type type) {
+ try {
+ this.handler = handler;
+ this.effects = new ArrayList<TCon>();
+ MultiFunction mfun = Types.matchFunction(type, 1);
+ mfun.effect.collectConcreteEffects(this.effects);
+ } catch(MatchException e) {
+ // Should not happen!
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public Object apply(Object p0) {
+ return handler.apply(p0);
+ }
+
+ }
+
+ @Override
+ public Function1<Object, Object> perform(ReadGraph graph) throws DatabaseException {
+
+ CompilationContext context = getCompilationContext(graph);
+ Type expectedType = getExpectedType(graph, context);
+ Function1<Object,Object> handler = eval(prepareEvaluator(graph, context, expectedType), graph);
+ return new HandlerFn(handler, expectedType);
+
+ }
+
+ @Override
+ protected String getExpressionText(ReadGraph graph)
+ throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ String exp = graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
+ return "\\context -> " + exp;
+ }
+
+ protected RuntimeEnvironmentRequest2 getRuntimeEnvironmentRequest(Resource componentType, Resource indexRoot) {
+ return new RuntimeEnvironmentRequest2(componentType, indexRoot) {
+ @Override
+ protected void fillEnvironmentSpecification(
+ EnvironmentSpecification environmentSpecification) {
+ }
+ };
+ }
+
+ @Override
+ protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {
+ return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
+ @Override
+ public CompilationContext perform(ReadGraph graph) throws DatabaseException {
+ RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
Map<String, ComponentTypeProperty> propertyMap;
if (parameter.first != null) {
propertyMap =
- graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
- TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
+ graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
+ TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
} else {
// TODO: Antti to consider
// To handle procedural user components
propertyMap = Collections.emptyMap();
}
-// Map<String, ComponentTypeProperty> propertyMap =
-// graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
-// TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
- return new CompilationContext(runtimeEnvironment, propertyMap);
- }
- });
- }
-
- @Override
- protected Type getContextVariableType() {
- return VARIABLE;
- }
-
- private static Expression accessInputVariable(Environment environment,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {
- SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);
- return new EApply(new EConstant(variableParentFunction),
- new EApply(new EConstant(variableParentFunction),
- new EVariable(contextVariable)));
- }
-
- protected static Expression standardGetProperty(
- Environment environment,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
- String name,
- Type type) {
- return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);
- }
-
- @Override
- protected Expression getVariableAccessExpression(
- ReadGraph graph,
- CompilationContext context,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
- String name) throws DatabaseException {
- ComponentTypeProperty property = context.propertyMap.get(name);
- if(property != null)
- return standardGetProperty(
- context.runtimeEnvironment.getEnvironment(),
- contextVariable,
- name,
- property.type == null ? Types.metaVar(Kinds.STAR) : property.type);
- else {
-
-// if(context.propertyMap.containsKey(name)) {
-//
-// org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT);
-//
-// Environment environment = context.runtimeEnvironment.getEnvironment();
-//
-//// return new EApply(
-//// new EConstant(environment.getValue(FROM_DYNAMIC), Types.STRING),
-// return new EApply(
-// new EConstant(environment.getValue(CONTEXT_VARIABLE), Types.DYNAMIC),
-// new EVariable(parametersVariable),
-// new ELiteral(new StringConstant(name)));
-//
-// }
-
- return getSpecialVariableAccessExpression(graph, context, contextVariable, name);
-
- }
- }
-
- protected Expression getSpecialVariableAccessExpression(ReadGraph graph,
- CompilationContext context,
- org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
- String name) throws DatabaseException {
- if(name.equals("input")) {
- Environment environment = context.runtimeEnvironment.getEnvironment();
- return accessInputVariable(environment, contextVariable);
- } else if(name.equals("self"))
- return new EVariable(contextVariable);
- else
- return null;
- }
+// Map<String, ComponentTypeProperty> propertyMap =
+// graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
+// TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
+ return new CompilationContext(runtimeEnvironment, propertyMap);
+ }
+ });
+ }
+
+ @Override
+ protected Type getContextVariableType() {
+ return VARIABLE;
+ }
+
+ private static Expression accessInputVariable(Environment environment,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {
+ SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);
+ return new EApply(new EConstant(variableParentFunction),
+ new EApply(new EConstant(variableParentFunction),
+ new EVariable(contextVariable)));
+ }
+
+ protected static Expression standardGetProperty(
+ Environment environment,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+ String name,
+ Type type) {
+ return getPropertyFlexible(environment, accessInputVariable(environment, contextVariable), name, type);
+ }
+
+ @Override
+ protected Expression getVariableAccessExpression(
+ ReadGraph graph,
+ CompilationContext context,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+ String name) throws DatabaseException {
+ ComponentTypeProperty property = context.propertyMap.get(name);
+ if(property != null)
+ return standardGetProperty(
+ context.runtimeEnvironment.getEnvironment(),
+ contextVariable,
+ name,
+ property.type == null ? Types.metaVar(Kinds.STAR) : property.type);
+ else {
+
+// if(context.propertyMap.containsKey(name)) {
+//
+// org.simantics.scl.compiler.elaboration.expressions.Variable parametersVariable = new org.simantics.scl.compiler.elaboration.expressions.Variable("context", COMMAND_CONTEXT);
+//
+// Environment environment = context.runtimeEnvironment.getEnvironment();
+//
+//// return new EApply(
+//// new EConstant(environment.getValue(FROM_DYNAMIC), Types.STRING),
+// return new EApply(
+// new EConstant(environment.getValue(CONTEXT_VARIABLE), Types.DYNAMIC),
+// new EVariable(parametersVariable),
+// new ELiteral(new StringConstant(name)));
+//
+// }
+
+ return getSpecialVariableAccessExpression(graph, context, contextVariable, name);
+
+ }
+ }
+
+ protected Expression getSpecialVariableAccessExpression(ReadGraph graph,
+ CompilationContext context,
+ org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+ String name) throws DatabaseException {
+ if(name.equals("input")) {
+ Environment environment = context.runtimeEnvironment.getEnvironment();
+ return accessInputVariable(environment, contextVariable);
+ } else if(name.equals("self"))
+ return new EVariable(contextVariable);
+ else
+ return null;
+ }
@Override
protected Type getExpectedType(ReadGraph graph, CompilationContext context) throws DatabaseException {
return super.getExpectedType(graph, context);
}
- @Override
- public int hashCode() {
- return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
- return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
- }
+ @Override
+ public int hashCode() {
+ return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
+ return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
+ }
}