package org.simantics.scl.compiler.elaboration.java; import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply; import static org.simantics.scl.compiler.elaboration.expressions.Expressions.constant; import static org.simantics.scl.compiler.elaboration.expressions.Expressions.string; import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var; import org.cojen.classfile.TypeDesc; import org.simantics.scl.compiler.constants.generic.CallJava; import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef; import org.simantics.scl.compiler.constants.generic.MethodRef.StaticMethodRef; import org.simantics.scl.compiler.constants.generic.ParameterStackItem; import org.simantics.scl.compiler.constants.generic.StackItem; import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.expressions.EApply; 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.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.query.QAtom; import org.simantics.scl.compiler.elaboration.query.QConjunction; import org.simantics.scl.compiler.elaboration.query.Query; import org.simantics.scl.compiler.elaboration.query.compilation.EnforcingContext; import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext; import org.simantics.scl.compiler.elaboration.relations.AbstractRelation; import org.simantics.scl.compiler.elaboration.relations.SCLEntityType; import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor; import org.simantics.scl.compiler.internal.codegen.effects.ThreadLocalVariable; import org.simantics.scl.compiler.internal.codegen.utils.Constants; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase; import org.simantics.scl.compiler.module.ConcreteModule; import org.simantics.scl.compiler.types.TCon; import org.simantics.scl.compiler.types.TVar; 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.minigraph.Minigraph; public class MinigraphModule extends ConcreteModule { public static final String MODULE = "Minigraph"; // public static final TCon RESOURCE = Types.con(MODULE, "Resource"); public static final TCon RESOURCE = Types.INTEGER; public static final TCon GRAPH = Types.con(MODULE, "Graph"); private static final String THREAD_LOCAL_VARIABLE_NAME = "graph"; private static final TypeDesc MINIGRAPH = TypeDesc.forClass(Minigraph.class); private static final CallJava CLAIM_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, Types.tupleConstructor(0), new Type[] { RESOURCE, RESOURCE, RESOURCE }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH), new ParameterStackItem(0, RESOURCE), new ParameterStackItem(1, RESOURCE), new ParameterStackItem(2, RESOURCE), }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "claim", TypeDesc.VOID, new TypeDesc[] { TypeDesc.INT, TypeDesc.INT, TypeDesc.INT }), null ); private static final CallJava HAS_STATEMENT_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, Types.BOOLEAN, new Type[] { RESOURCE, RESOURCE, RESOURCE }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH), new ParameterStackItem(0, RESOURCE), new ParameterStackItem(1, RESOURCE), new ParameterStackItem(2, RESOURCE), }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "hasStatement", TypeDesc.BOOLEAN, new TypeDesc[] { TypeDesc.INT, TypeDesc.INT, TypeDesc.INT }), null ); private static final CallJava GET_OBJECTS_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, Types.vector(RESOURCE), new Type[] { RESOURCE, RESOURCE }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH), new ParameterStackItem(0, RESOURCE), new ParameterStackItem(1, RESOURCE), }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "getObjects", TypeDesc.INT.toArrayType(), new TypeDesc[] { TypeDesc.INT, TypeDesc.INT }), null ); private static final CallJava BLANK_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, RESOURCE, new Type[] { Types.UNIT }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH) }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "blank", TypeDesc.INT, Constants.EMPTY_TYPEDESC_ARRAY), null ); private static final CallJava GET_SUBJECTS_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, Types.vector(RESOURCE), new Type[] { RESOURCE, RESOURCE }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH), new ParameterStackItem(0, RESOURCE), new ParameterStackItem(1, RESOURCE), }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "getSubjects", TypeDesc.INT.toArrayType(), new TypeDesc[] { TypeDesc.INT, TypeDesc.INT }), null ); private static final CallJava RESOURCE_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, RESOURCE, new Type[] { Types.STRING }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH), new ParameterStackItem(0, Types.STRING), }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "getResource", TypeDesc.INT, new TypeDesc[] { TypeDesc.STRING }), null ); private static final CallJava GET_URI_METHOD = new CallJava( TVar.EMPTY_ARRAY, GRAPH, Types.STRING, new Type[] { RESOURCE }, new StackItem[] { new ThreadLocalStackItem(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH), new ParameterStackItem(0, RESOURCE), }, new ObjectMethodRef(false, MethodBuilderBase.getClassName(MINIGRAPH), "getUri", TypeDesc.STRING, new TypeDesc[] { TypeDesc.INT }), null ); private static final TVar A = Types.var(Kinds.STAR); private static final TVar E = Types.var(Kinds.EFFECT); private static final Type F = Types.functionE(Types.PUNIT, Types.union(new Type[] {GRAPH, E}), A); private static final CallJava WITH_GRAPH_METHOD = new CallJava( new TVar[] { A, E }, Types.union(new Type[] {Types.PROC, E}), A, new Type[] { F }, new StackItem[] { new ParameterStackItem(0, F), }, new StaticMethodRef(MethodBuilderBase.getClassName(MINIGRAPH), "withGraph", TypeDesc.OBJECT, new TypeDesc[] { Constants.FUNCTION }), null ); public static final MinigraphModule INSTANCE = new MinigraphModule(); private MinigraphModule() { super(MODULE); //addTypeConstructor("Resource", new StandardTypeConstructor(RESOURCE, Kinds.STAR, TypeDesc.INT)); EffectConstructor effect = new EffectConstructor(Types.con(MODULE, "Graph")); effect.addThreadLocalVariable(new ThreadLocalVariable(THREAD_LOCAL_VARIABLE_NAME, MINIGRAPH)); addEffectConstructor("Graph", effect); addValue("resource", RESOURCE_METHOD); addValue("blank", BLANK_METHOD); addValue("withGraph", WITH_GRAPH_METHOD); addValue("uriOf", GET_URI_METHOD); addRelation("Statement", new AbstractRelation() { @Override public TVar[] getTypeVariables() { return TVar.EMPTY_ARRAY; } @Override public double getSelectivity(int boundVariabes) { switch(boundVariabes) { case BBF: return 10.0; case FBB: return 10.0; case BBB: return 0.95; default: return Double.POSITIVE_INFINITY; } } @Override public int getRequiredVariablesMask() { return FBF; } @Override public Type[] getParameterTypes() { return new Type[] { RESOURCE, RESOURCE, RESOURCE }; } @Override public Expression generateEnforce(long location, EnforcingContext context, Type[] typeParameters, Variable[] parameters) { return new EApply(new ELiteral(CLAIM_METHOD), new Expression[] { new EVariable(parameters[0]), new EVariable(parameters[1]), new EVariable(parameters[2]) }); } @Override public void generate(long location, QueryCompilationContext context, Type[] typeParameters, Variable[] parameters, int boundVariables) { switch(boundVariables) { case BBF: context.iterateVector(parameters[2], new EApply(new ELiteral(GET_OBJECTS_METHOD), new Expression[] { new EVariable(parameters[0]), new EVariable(parameters[1]), })); break; case FBB: context.iterateVector(parameters[0], new EApply(new ELiteral(GET_SUBJECTS_METHOD), new Expression[] { new EVariable(parameters[2]), new EVariable(parameters[1]), })); break; case BBB: context.condition( new EApply(new ELiteral(HAS_STATEMENT_METHOD), new Expression[] { new EVariable(parameters[0]), new EVariable(parameters[1]), new EVariable(parameters[2]) })); break; default: throw new IllegalArgumentException(); } } @Override public String toString() { return "Statement"; } }); addEntityType("Resource", new SCLEntityType() { @Override public Query generateQuery(TranslationContext context, Variable base, AttributeBinding[] attributeBindings) { Query[] queries = new Query[attributeBindings.length]; for(int i=0;i