X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2Frequest%2FServerSCLHandlerValueRequest.java;h=44e2ceeee8283a9d29bc9fb0793920dba7d3c9e4;hp=12a4e017a3bffc3ff60253befba71b98ddd7fc8c;hb=ae2e31aa5eb35410e5b2ce222d42421154f3fecc;hpb=06718abb2b3cc780748553811c4857c165499809 diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java index 12a4e017a..44e2ceeee 100644 --- a/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java @@ -1,269 +1,284 @@ -package org.simantics.document.server.request; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.simantics.databoard.Bindings; -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.procedure.adapter.TransientCacheListener; -import org.simantics.db.common.request.IndexRoot; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.request.VariableRead; -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.server.Functions; -import org.simantics.document.server.bean.DataDefinition; -import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext; -import org.simantics.layer0.Layer0; -import org.simantics.scl.compiler.constants.StringConstant; -import org.simantics.scl.compiler.elaboration.expressions.EApply; -import org.simantics.scl.compiler.elaboration.expressions.EConstant; -import org.simantics.scl.compiler.elaboration.expressions.ELiteral; -import org.simantics.scl.compiler.elaboration.expressions.EVar; -import org.simantics.scl.compiler.elaboration.expressions.EVariable; -import org.simantics.scl.compiler.elaboration.expressions.Expression; -import org.simantics.scl.compiler.elaboration.modules.SCLValue; -import org.simantics.scl.compiler.environment.Environment; -import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification; -import org.simantics.scl.compiler.runtime.RuntimeEnvironment; -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.kinds.Kinds; -import org.simantics.scl.runtime.SCLContext; -import org.simantics.scl.runtime.function.Function1; -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 { - - private final Variable context; - private final Pair componentTypeAndRoot; - private final Resource literal; - - public static class CompilationContext extends AbstractExpressionCompilationContext { - public final Map propertyMap; - - public CompilationContext(RuntimeEnvironment runtimeEnvironment, - Map propertyMap) { - super(runtimeEnvironment); - this.propertyMap = propertyMap; - } - } - - private ServerSCLHandlerValueRequest(Variable context, Pair componentTypeAndRoot, Resource literal) { - assert(literal != null); - this.context = context; - this.literal = literal; - this.componentTypeAndRoot = componentTypeAndRoot; - } - - public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException { - this(context, getComponentTypeAndRoot(graph, context), context.getRepresents(graph)); - } - - private static Pair 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 getEffects(ReadGraph graph, Variable context) throws DatabaseException { - try { - ServerSCLHandlerValueRequest req = new ServerSCLHandlerValueRequest(graph, context); - return req.getExpressionEffects(graph); - } catch (DatabaseException e) { - throw (DatabaseException)e; - } catch (Throwable t) { - throw new DatabaseException(t); - } - } - - public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException { - SCLContext sclContext = SCLContext.getCurrent(); - Object oldGraph = sclContext.get("graph"); - try { - Function1 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); - } - } - - @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 VariableRead(context) { - - @Override - public CompilationContext perform(ReadGraph graph) throws DatabaseException { - - Pair parameter = getComponentTypeAndRoot(graph, variable); - RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second)); - - Map propertyMap = - graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), - TransientCacheListener.>instance()); - -// Map result = new HashMap(propertyMap); -// for(DataDefinition dd : Functions.dataDefinitions(graph, variable)) { -// result.put(dd.target, null); -// } - - 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 - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((context == null) ? 0 : context.hashCode()); - return result; - } - - @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; - if (context == null) { - if (other.context != null) - return false; - } else if (!context.equals(other.context)) - return false; - return true; - } - -// @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 || obj.getClass() != getClass()) -// return false; -// ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest)obj; -// return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot); -// } - -} +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.databoard.Bindings; +import org.simantics.db.ReadGraph; +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.UnaryRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext; +import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2; +import org.simantics.db.layer0.variable.Variable; +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.elaboration.expressions.EVariable; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.modules.SCLValue; +import org.simantics.scl.compiler.environment.Environment; +import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification; +import org.simantics.scl.compiler.runtime.RuntimeEnvironment; +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 ServerSCLValueRequestBase { + + private final Pair componentTypeAndRoot; + private final Resource literal; + protected String possibleExpectedValueType; + + public static class CompilationContext extends AbstractExpressionCompilationContext { + public final Map propertyMap; + + public CompilationContext(RuntimeEnvironment runtimeEnvironment, + Map propertyMap) { + super(runtimeEnvironment); + this.propertyMap = propertyMap; + } + } + + private ServerSCLHandlerValueRequest(Pair 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 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 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 { + Function1 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 compile(ReadGraph graph, Variable context) throws DatabaseException { + return graph.syncRequest(new ServerSCLHandlerValueRequest(graph, context), TransientCacheListener.instance()); + } + + public static Function1 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 { + + Function1 handler; + ArrayList effects; + + HandlerFn(Function1 handler, Type type) { + try { + this.handler = handler; + this.effects = new ArrayList(); + 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 perform(ReadGraph graph) throws DatabaseException { + + CompilationContext context = getCompilationContext(graph); + Type expectedType = getExpectedType(graph, context); + Function1 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,CompilationContext>(componentTypeAndRoot) { + @Override + public CompilationContext perform(ReadGraph graph) throws DatabaseException { + RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second)); + Map propertyMap; + if (parameter.first != null) { + propertyMap = + graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), + TransientCacheListener.>instance()); + } else { + // TODO: Antti to consider + // To handle procedural user components + propertyMap = Collections.emptyMap(); + } +// Map propertyMap = +// graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()), +// TransientCacheListener.>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); + } + +}