package org.simantics.structural2.scl.procedural; import java.util.List; 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.exception.DatabaseException; import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest; import org.simantics.db.layer0.variable.Variable; import org.simantics.scl.compiler.common.names.Name; 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.EExternalConstant; import org.simantics.scl.compiler.elaboration.expressions.ELiteral; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.runtime.SCLContext; import org.simantics.scl.runtime.function.Function1; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.structural2.procedural.Interface; import org.simantics.structural2.procedural.SubstructureElement; import org.simantics.structural2.scl.ComponentTypeProperty; public class CompileProceduralComponentTypeRequest extends AbstractExpressionCompilationRequest { private static final Type EXPECTED_TYPE = Types.list(Types.con("Structural/Procedural", "SubstructureElement")); private static Name PROPERTY_VALUE = Name.create("Simantics/Variables", "propertyValue"); private static final Type CONNECTION_POINT = Types.con("Structural/Procedural", "ConnectionPoint"); private final Resource componentType; public CompileProceduralComponentTypeRequest(Resource componentType) { this.componentType = componentType; } @SuppressWarnings("unchecked") public static List compileAndEvaluate(ReadGraph graph, Resource componentType, Variable context) throws DatabaseException { SCLContext sclContext = SCLContext.getCurrent(); Object oldGraph = sclContext.get("graph"); try { Function1 exp = graph.syncRequest( new CompileProceduralComponentTypeRequest(componentType), TransientCacheListener.>instance()); sclContext.put("graph", graph); return (List)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, Resource componentType) throws DatabaseException { return graph.syncRequest(new CompileProceduralComponentTypeRequest(componentType), TransientCacheListener.instance()); } @Override protected String getExpressionText(ReadGraph graph) throws DatabaseException { StructuralResource2 STR = StructuralResource2.getInstance(graph); return graph.getRelatedValue(componentType, STR.ProceduralComponentType_code, Bindings.STRING); } @Override protected ProceduralComponentTypeCompilationContext getCompilationContext( ReadGraph graph) throws DatabaseException { return graph.syncRequest(new ProceduralComponentTypeCompilationContextRequest(componentType)); } @Override protected Type getContextVariableType() { return VARIABLE; } @Override protected Expression getVariableAccessExpression( ReadGraph graph, ProceduralComponentTypeCompilationContext context, org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable, String name) throws DatabaseException { ComponentTypeProperty property = context.propertyMap.get(name); if(property != null) { Environment environment = context.runtimeEnvironment.getEnvironment(); return new EApply( new EConstant(environment.getValue(FROM_DYNAMIC), property.type), new EApply( new EConstant(environment.getValue(PROPERTY_VALUE), Types.DYNAMIC), new EVariable(contextVariable), new ELiteral(new StringConstant(name)))); } Resource connectionPoint = context.connectionPointMap.get(name); if(connectionPoint != null) return new EExternalConstant(new Interface(connectionPoint), CONNECTION_POINT); else if(name.equals("input")) return new EVariable(contextVariable); else if(name.equals("self")) return new EVariable(contextVariable); else return null; } public static Type getExpectedType() { return EXPECTED_TYPE; } @Override protected boolean parseAsBlock() { return true; } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj == null || obj.getClass() != getClass()) return false; CompileProceduralComponentTypeRequest other = (CompileProceduralComponentTypeRequest)obj; return componentType.equals(other.componentType); } @Override public int hashCode() { return componentType.hashCode(); } }