]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / relations / TransitiveClosureRelation.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/relations/TransitiveClosureRelation.java
new file mode 100644 (file)
index 0000000..fb59470
--- /dev/null
@@ -0,0 +1,145 @@
+package org.simantics.scl.compiler.elaboration.relations;
+
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.if_;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.lambda;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.let;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.letRec;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.tuple;
+import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+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.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.types.TPred;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class TransitiveClosureRelation extends AbstractRelation implements CompositeRelation {
+
+    SCLRelation baseRelation;
+    
+    public TransitiveClosureRelation(SCLRelation baseRelation) {
+        this.baseRelation = baseRelation;
+    }
+
+    @Override
+    public TVar[] getTypeVariables() {
+        return baseRelation.getTypeVariables();
+    }
+
+    @Override
+    public Type[] getParameterTypes() {
+        return baseRelation.getParameterTypes();
+    }
+    
+    @Override
+    public double getSelectivity(int boundVariabes) {
+        return baseRelation.getSelectivity(boundVariabes)*5.0;
+    }
+    
+    @Override
+    public int getRequiredVariablesMask() {
+        return baseRelation.getRequiredVariablesMask();
+    }
+
+    @Override
+    public void generate(long location,
+            QueryCompilationContext context,
+            Type[] typeParameters, Variable[] parameters, int boundVariables) {
+        Variable bound, solved;
+        if(boundVariables == (1<<(parameters.length-1))-1) {
+            bound = parameters[0];
+            solved = parameters[parameters.length-1];
+        }
+        else if(boundVariables == (1<<(parameters.length))-2) {
+            bound = parameters[parameters.length-1];
+            solved = parameters[0];
+        }
+        else //if(boundVariables == 3 || boundVariables == 0)
+            throw new UnsupportedOperationException("boundVariables = " + boundVariables);
+        
+        Type type = baseRelation.getParameterTypes()[0];
+        if(typeParameters.length > 0)
+            type = type.replace(getTypeVariables(), typeParameters);
+
+        Expression continuation = context.getContinuation();
+        System.out.println("continuation = " + continuation + " :: " + continuation.getType());
+        Variable set = new Variable("set", Types.apply(Types.con("MSet", "T"), type));
+        Variable f = new Variable("f", Types.functionE(type, Types.PROC, continuation.getType()));
+        Variable innerSolved = new Variable("tcTemp", solved.getType());
+        System.out.println("set :: " + set.getType());
+        System.out.println("f :: " + f.getType());
+        System.out.println("tcTemp :: " + innerSolved.getType());
+        
+        QueryCompilationContext newContext = context.createSubcontext(new EApply(
+                new EVariable(f), new EVariable(innerSolved)
+                ));
+        Variable[] innerParameters = new Variable[parameters.length];
+        if(boundVariables == (1<<(parameters.length-1))-1) {
+            innerParameters[0] = solved;
+            innerParameters[parameters.length-1] = innerSolved;
+        }
+        else {
+            innerParameters[0] = innerSolved;
+            innerParameters[parameters.length-1] = solved;
+        }
+        for(int i=1;i<parameters.length-1;++i)
+            innerParameters[i] = parameters[i];
+        baseRelation.generate(location,
+                newContext,
+                typeParameters,
+                innerParameters, boundVariables);
+        
+        continuation = context.disjunction(continuation, newContext.getContinuation());
+        continuation = if_(apply(context, Types.PROC, Name.create("MSet", "add"), type,
+                var(set), var(solved)),
+                continuation,
+                context.failure());
+        continuation = lambda(Types.PROC, solved, continuation);
+        continuation = letRec(f, continuation, apply(var(f), var(bound)));
+        continuation = let(set, 
+                apply(context, Types.PROC, Name.create("MSet", "create"), type, tuple()), 
+                continuation);
+        context.setContinuation(continuation);
+        
+        // TODO Auto-generated method stub
+        // base :: (a -> <Proc> ()) -> a -> <Proc> ()
+        // initial :: a
+        // cont :: a -> <Proc> ()
+        /* s = MSet.create ()
+         * f cur = if MSet.add s cur
+         *         then do
+         *             cont cur
+         *             base f cur
+         *         else ()
+         * f cur = MSet.add s cur && (cont cur || base f cur)
+         * f cur = if MSet.add s cur
+         *         then match cont cur with
+         *             result @ (Just _) -> result
+         *             _ -> base f cur
+         *         else Nothing
+         */
+        
+        /* let s = MSet.new ()
+               f = \r -> if MSet.add s r
+                         then do
+                             g r
+                             rel 
+                         else ()
+           in  f init 
+         */
+    }
+
+    @Override
+    public SCLRelation[] getSubrelations() {
+        return new SCLRelation[] { baseRelation };
+    }
+
+}