]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EListComprehension.java
a6d79e817fcdb087bde2a0276492885cd63f2537
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EListComprehension.java
1 package org.simantics.scl.compiler.elaboration.expressions;
2
3 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
4 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
6 import org.simantics.scl.compiler.elaboration.expressions.list.CompiledQualifier;
7 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
8 import org.simantics.scl.compiler.errors.Locations;
9 import org.simantics.scl.compiler.types.Type;
10 import org.simantics.scl.compiler.types.Types;
11 import org.simantics.scl.compiler.types.exceptions.MatchException;
12
13 import gnu.trove.map.hash.TObjectIntHashMap;
14 import gnu.trove.set.hash.TIntHashSet;
15
16 public class EListComprehension extends SimplifiableExpression {
17
18     public Expression head;
19     public ListQualifier qualifier;
20     
21     public EListComprehension(Expression head, ListQualifier qualifier) {
22         this.head = head;
23         this.qualifier = qualifier;
24     }
25
26     public EListComprehension(long loc, Expression head,
27             ListQualifier qualifier) {
28         super(loc);
29         this.head = head;
30         this.qualifier = qualifier;
31     }
32
33     @Override
34     public void collectVars(TObjectIntHashMap<Variable> allVars,
35             TIntHashSet vars) {
36         head.collectVars(allVars, vars);
37         qualifier.collectVars(allVars, vars);
38     }
39     
40     @Override
41     public Expression checkBasicType(TypingContext context, Type requiredType) {
42         qualifier.checkType(context);
43         Type componentType;
44         try {
45             componentType = Types.unifyApply(Types.LIST, requiredType);
46         } catch (MatchException e) {
47             context.getErrorLog().log(location, "Expected a value with type " + requiredType + " but got a list.");
48             return new EError(location);
49         }
50         head = head.checkType(context, componentType);
51         return this;
52     }
53     
54     @Override
55     protected void updateType() throws MatchException {
56         setType(Types.list(head.getType()));
57     }
58
59     @Override
60     public Expression simplify(SimplificationContext context) {
61         context.pushLocation(location);
62         try {
63             CompiledQualifier cq = qualifier.compile(context);            
64             Expression exp = context.mapList(
65                     context.lambda(cq.pattern, head), 
66                     cq.value);
67             //System.out.println("simplified: " + exp);
68             /*try {
69                 exp.validateType(context.getEnvironment());
70             } catch (TypeValidationException e) {
71                 throw new InternalCompilerError(e);
72             }*/
73             exp = exp.simplify(context);
74             return exp;
75         } finally {
76             context.popLocation();
77         }
78     }
79
80     @Override
81     public Expression resolve(TranslationContext context) {
82         context.pushFrame();
83         qualifier.resolve(context);
84         head = head.resolve(context);
85         context.popFrame();
86         return this;
87     }
88
89     @Override
90     public void setLocationDeep(long loc) {
91         if(location == Locations.NO_LOCATION) {
92             location = loc;
93             head.setLocationDeep(loc);
94             qualifier.setLocationDeep(loc);
95         }
96     }
97     
98     @Override
99     public void accept(ExpressionVisitor visitor) {
100         visitor.visit(this);
101     }
102     
103     @Override
104     public Expression accept(ExpressionTransformer transformer) {
105         return transformer.transform(this);
106     }
107
108 }