]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/OrdDeriver.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / deriving / OrdDeriver.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/OrdDeriver.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/OrdDeriver.java
new file mode 100644 (file)
index 0000000..de9f088
--- /dev/null
@@ -0,0 +1,134 @@
+package org.simantics.scl.compiler.internal.deriving;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.datatypes.Constructor;
+import org.simantics.scl.compiler.constants.IntegerConstant;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EVar;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.environment.AmbiguousNameException;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
+import org.simantics.scl.compiler.internal.parsing.expressions.Expressions;
+import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
+import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
+import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
+import org.simantics.scl.compiler.types.TCon;
+
+class OrdDeriver implements InstanceDeriver {
+
+    @Override
+    public void derive(
+            ErrorLog errorLog,
+            Environment environment,
+            ArrayList<ProcessedDInstanceAst> instancesAst,
+            DDerivingInstanceAst der) {
+     // Analyze
+        if(der.types.length != 1) {
+            errorLog.log(der.location, "Invalid number of parameters to " + der.name);
+            return;
+        }
+        TVarAst headType = DerivingUtils.getHeadType(der.types[0]);
+        if(headType == null) {
+            errorLog.log(der.types[0].location, "Cannot derive Ord instance for the type " + headType + ".");
+            return;
+        }
+        TCon con;
+        try {
+            con = Environments.getTypeConstructorName(environment, headType.name);
+        } catch (AmbiguousNameException e1) {
+            errorLog.log(headType.location, e1.getMessage());
+            return;
+        }
+        if(con == null) {
+            errorLog.log(headType.location, "Couldn't resolve " + headType.name);
+            return;
+        }
+        TypeConstructor tcon = environment.getTypeConstructor(con);
+        if(tcon == null) {
+            errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
+            return;
+        }
+        if(tcon.isOpen) {
+            errorLog.log(headType.location, "Cannot derive instance for open data types.");
+            return;
+        }
+        
+        // Generate
+        DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
+        ValueRepository valueDefs = new ValueRepository();
+        int cCount = tcon.constructors.length;
+        for(int a=0;a<cCount;++a) {
+            Constructor consA = tcon.constructors[a];
+            int lA = consA.parameterTypes.length;
+            String[] parA = new String[lA];            
+            for(int i=0;i<lA;++i) {
+                parA[i] = "a" + i;
+            }
+            for(int b=0;b<cCount;++b) {
+                if(a != b) {
+                    Constructor consB = tcon.constructors[b];
+                    int lB = consB.parameterTypes.length;
+                    String[] parB = new String[lB];            
+                    for(int i=0;i<lB;++i) {
+                        parB[i] = "b" + i;
+                    }
+                    Expression lhs = new EApply(
+                            new EVar("compare"),
+                            new EApply(new EVar(consA.name.name), Expressions.vars(parA)),
+                            new EApply(new EVar(consB.name.name), Expressions.vars(parB))
+                            );
+                    Expression value = new ELiteral(a < b ? IntegerConstant.MINUS_ONE : IntegerConstant.ONE);
+                    try {
+                        DValueAst valueAst = new DValueAst(lhs, value);
+                        valueAst.setLocationDeep(der.location);
+                        valueDefs.add(valueAst);
+                        /*valueDefs.addAnnotation("compare", new DAnnotationAst(new EVar("@private"), 
+                                Collections.<Expression>emptyList()));*/
+                    } catch (NotPatternException e) {
+                        errorLog.log(e.getExpression().location, "Not a pattern.");
+                    }
+                }
+                else {
+                    String[] parB = new String[lA];            
+                    for(int i=0;i<lA;++i) {
+                        parB[i] = "b" + i;
+                    }
+                    Expression lhs = new EApply(
+                            new EVar("compare"),
+                            new EApply(new EVar(consA.name.name), Expressions.vars(parA)),
+                            new EApply(new EVar(consA.name.name), Expressions.vars(parB))
+                            );
+                    Expression value = new ELiteral(IntegerConstant.ZERO);
+                    for(int i=lA-1;i>=0;--i)
+                        value = new EApply(
+                                new EVar("&<&"),
+                                new EApply(
+                                        new EVar("compare"), 
+                                        new EVar(parA[i]), 
+                                        new EVar(parB[i])),
+                                value);
+                    try {
+                        DValueAst valueAst = new DValueAst(lhs, value);
+                        valueAst.setLocationDeep(der.location);
+                        valueDefs.add(valueAst);
+                        /*valueDefs.addAnnotation("&<&", new DAnnotationAst(new EVar("@private"), 
+                                Collections.<Expression>emptyList()));*/
+                    } catch (NotPatternException e) {
+                        errorLog.log(e.getExpression().location, "Not a pattern.");
+                    }
+                }
+            }
+        }
+        instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
+    }
+
+}