]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/OrdDeriver.java
Merge "Ensure GetElementClassRequest is not constructed without elementFactory"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / deriving / OrdDeriver.java
1 package org.simantics.scl.compiler.internal.deriving;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.common.datatypes.Constructor;
6 import org.simantics.scl.compiler.constants.IntegerConstant;
7 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
8 import org.simantics.scl.compiler.elaboration.expressions.EApply;
9 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
10 import org.simantics.scl.compiler.elaboration.expressions.EVar;
11 import org.simantics.scl.compiler.elaboration.expressions.Expression;
12 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
13 import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
14 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
15 import org.simantics.scl.compiler.environment.AmbiguousNameException;
16 import org.simantics.scl.compiler.environment.Environment;
17 import org.simantics.scl.compiler.environment.Environments;
18 import org.simantics.scl.compiler.errors.ErrorLog;
19 import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
20 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
21 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
22 import org.simantics.scl.compiler.internal.parsing.expressions.Expressions;
23 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
24 import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
25 import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
26 import org.simantics.scl.compiler.types.TCon;
27
28 class OrdDeriver implements InstanceDeriver {
29
30     @Override
31     public void derive(
32             ErrorLog errorLog,
33             Environment environment,
34             ArrayList<ProcessedDInstanceAst> instancesAst,
35             DDerivingInstanceAst der) {
36      // Analyze
37         if(der.types.length != 1) {
38             errorLog.log(der.location, "Invalid number of parameters to " + der.name);
39             return;
40         }
41         TVarAst headType = DerivingUtils.getHeadType(der.types[0]);
42         if(headType == null) {
43             errorLog.log(der.types[0].location, "Cannot derive Ord instance for the type " + headType + ".");
44             return;
45         }
46         TCon con;
47         try {
48             con = Environments.getTypeDescriptorName(environment, headType.name);
49         } catch (AmbiguousNameException e1) {
50             errorLog.log(headType.location, e1.getMessage());
51             return;
52         }
53         if(con == null) {
54             errorLog.log(headType.location, "Couldn't resolve " + headType.name);
55             return;
56         }
57         TypeDescriptor tdesc = environment.getTypeDescriptor(con);
58         if(tdesc == null) {
59             errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
60             return;
61         }
62         if(tdesc instanceof TypeAlias) {
63             errorLog.log(headType.location, "Cannot derive instance for a type alias.");
64             return;
65         }
66         TypeConstructor tcon = (TypeConstructor)tdesc;
67         if(tcon.isOpen) {
68             errorLog.log(headType.location, "Cannot derive instance for open data types.");
69             return;
70         }
71         
72         // Generate
73         DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
74         ValueRepository valueDefs = new ValueRepository();
75         int cCount = tcon.constructors.length;
76         for(int a=0;a<cCount;++a) {
77             Constructor consA = tcon.constructors[a];
78             int lA = consA.parameterTypes.length;
79             String[] parA = new String[lA];            
80             for(int i=0;i<lA;++i) {
81                 parA[i] = "a" + i;
82             }
83             for(int b=0;b<cCount;++b) {
84                 if(a != b) {
85                     Constructor consB = tcon.constructors[b];
86                     int lB = consB.parameterTypes.length;
87                     String[] parB = new String[lB];            
88                     for(int i=0;i<lB;++i) {
89                         parB[i] = "b" + i;
90                     }
91                     Expression lhs = new EApply(
92                             new EVar("compare"),
93                             new EApply(new EVar(consA.name.name), Expressions.vars(parA)),
94                             new EApply(new EVar(consB.name.name), Expressions.vars(parB))
95                             );
96                     Expression value = new ELiteral(a < b ? IntegerConstant.MINUS_ONE : IntegerConstant.ONE);
97                     try {
98                         DValueAst valueAst = new DValueAst(lhs, value);
99                         valueAst.setLocationDeep(der.location);
100                         valueDefs.add(valueAst);
101                         /*valueDefs.addAnnotation("compare", new DAnnotationAst(new EVar("@private"), 
102                                 Collections.<Expression>emptyList()));*/
103                     } catch (NotPatternException e) {
104                         errorLog.log(e.getExpression().location, "Not a pattern.");
105                     }
106                 }
107                 else {
108                     String[] parB = new String[lA];            
109                     for(int i=0;i<lA;++i) {
110                         parB[i] = "b" + i;
111                     }
112                     Expression lhs = new EApply(
113                             new EVar("compare"),
114                             new EApply(new EVar(consA.name.name), Expressions.vars(parA)),
115                             new EApply(new EVar(consA.name.name), Expressions.vars(parB))
116                             );
117                     Expression value = new ELiteral(IntegerConstant.ZERO);
118                     for(int i=lA-1;i>=0;--i)
119                         value = new EApply(
120                                 new EVar("&<&"),
121                                 new EApply(
122                                         new EVar("compare"), 
123                                         new EVar(parA[i]), 
124                                         new EVar(parB[i])),
125                                 value);
126                     try {
127                         DValueAst valueAst = new DValueAst(lhs, value);
128                         valueAst.setLocationDeep(der.location);
129                         valueDefs.add(valueAst);
130                         /*valueDefs.addAnnotation("&<&", new DAnnotationAst(new EVar("@private"), 
131                                 Collections.<Expression>emptyList()));*/
132                     } catch (NotPatternException e) {
133                         errorLog.log(e.getExpression().location, "Not a pattern.");
134                     }
135                 }
136             }
137         }
138         instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
139     }
140
141 }