]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/macros/StandardMacroRule.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / macros / StandardMacroRule.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/macros/StandardMacroRule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/macros/StandardMacroRule.java
new file mode 100755 (executable)
index 0000000..6319e58
--- /dev/null
@@ -0,0 +1,106 @@
+package org.simantics.scl.compiler.elaboration.macros;
+
+import gnu.trove.map.hash.THashMap;
+
+import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.ELambda;
+import org.simantics.scl.compiler.elaboration.expressions.ELambdaType;
+import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+
+/**
+ * This is a macro rule that replaces an application with
+ * the definition of the function.
+ * @author Hannu Niemistö
+ */
+public class StandardMacroRule implements MacroRule {
+    Expression baseExpression;
+    int arity;
+    
+    public StandardMacroRule() {
+    }
+    
+    public void setBaseExpression(Expression baseExpression) {
+        this.baseExpression = baseExpression;
+        
+        Expression cur = baseExpression;
+        while(true) {
+            if(cur instanceof ELambdaType) {
+                cur = ((ELambdaType)cur).value;                
+            }
+            else if(cur instanceof ELambda) {
+                ELambda lambda = (ELambda)cur;
+                arity += lambda.getCases()[0].getPatterns().length;
+                break;
+            }
+            else if(cur instanceof ESimpleLambda) {
+                ESimpleLambda lambda = (ESimpleLambda)cur;
+                cur = lambda.value;
+                ++arity;
+            }
+            else
+                break;
+        }
+    }
+
+    @Override
+    public Expression apply(SimplificationContext context,
+            Type[] typeParameters, EApply apply) {
+        if(apply.getParameters().length < arity)
+            return null;
+        THashMap<TVar, Type> tvarMap = new THashMap<TVar, Type>();
+        THashMap<Variable, Expression> varMap = new THashMap<Variable, Expression>();
+        
+        Expression baseExpr = baseExpression;
+        /*System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+        TypeUnparsingContext tuc = new TypeUnparsingContext();
+        System.out.println("initial1 = " + baseExpr.toString(tuc));
+        */
+        {
+            int typeParameterId = 0;
+            while(typeParameterId < typeParameters.length) {            
+                ELambdaType lambda = (ELambdaType)baseExpr;
+                for(TVar var : lambda.parameters)                    
+                    tvarMap.put(var, typeParameters[typeParameterId++]);
+                baseExpr = lambda.value;
+            }
+        }
+        for(Expression parameter : apply.getParameters()) {
+            if(baseExpr instanceof ELambda)
+                baseExpr = ((ELambda)baseExpr).decomposeMatching();
+            ESimpleLambda lambda = (ESimpleLambda)baseExpr;
+            varMap.put(lambda.parameter, parameter);
+            baseExpr = lambda.value;
+        }
+        
+        /*
+        
+        System.out.println("initial2 = " + baseExpr.toString(tuc));
+        
+        System.out.print("tvarMap={");
+        boolean first = true;
+        for(Map.Entry<TVar, Type> entry : tvarMap.entrySet()) {
+            if(first)
+                first = false;
+            else
+                System.out.print(", ");
+            System.out.print(entry.getKey().toString(tuc));
+            System.out.print(" = ");
+            System.out.print(entry.getValue().toString(tuc));
+        }
+        System.out.println("}");
+        System.out.println("varMap = " + varMap);
+        */
+        baseExpr = baseExpr.replace(new ReplaceContext(tvarMap, varMap, null));
+        
+        //System.out.println("final = " + baseExpr.toString(tuc));
+        
+        return baseExpr;
+    }
+
+}