]> gerrit.simantics Code Review - simantics/platform.git/blob
451493ba3f6764965c8ec1662b2c1a34059abe93
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions.list;
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.Expression;
7 import org.simantics.scl.compiler.elaboration.expressions.Variable;
8 import org.simantics.scl.compiler.errors.Locations;
9 import org.simantics.scl.compiler.types.TMetaVar;
10 import org.simantics.scl.compiler.types.Type;
11 import org.simantics.scl.compiler.types.Types;
12 import org.simantics.scl.compiler.types.exceptions.UnificationException;
13 import org.simantics.scl.compiler.types.kinds.Kinds;
14
15 import gnu.trove.map.hash.TObjectIntHashMap;
16 import gnu.trove.set.hash.THashSet;
17 import gnu.trove.set.hash.TIntHashSet;
18
19 public class ListThen extends ListQualifier {
20     public ListQualifier left;
21     public Expression transformer;
22     public Expression by; // optional
23     TMetaVar cType;
24     
25     public ListThen(Expression transformer, Expression by) {
26         this.transformer = transformer;
27         this.by = by;
28     }
29     
30     public void setLeft(ListQualifier inner) {
31         this.left = inner;
32     }
33     
34     @Override
35     public void checkType(TypingContext context) {
36         left.checkType(context);
37         
38         cType = Types.metaVar(Kinds.STAR);
39         Type transformerType = Types.function(Types.list(cType), Types.list(cType));
40         if(by != null) {
41             by = by.checkType(context, Types.metaVar(Kinds.STAR));
42             transformerType = Types.function(Types.function(cType, by.getType()), transformerType);
43         }
44         transformer = transformer.checkType(context, transformerType);
45         if(!(Types.canonical(cType) instanceof TMetaVar)) {
46             context.getErrorLog().log(location, "Transformation function must be generic on list elements.");
47         }
48     }
49
50     @Override
51     public void collectRefs(TObjectIntHashMap<Object> allRefs,
52             TIntHashSet refs) {
53         left.collectRefs(allRefs, refs);
54         transformer.collectRefs(allRefs, refs);
55         if(by != null)
56             by.collectRefs(allRefs, refs);
57     }
58
59     @Override
60     public void collectVars(TObjectIntHashMap<Variable> allVars,
61             TIntHashSet vars) {
62         left.collectVars(allVars, vars);
63         transformer.collectVars(allVars, vars);
64         if(by != null)
65             by.collectVars(allVars, vars);
66     }
67
68     @Override
69     public void collectFreeVariables(THashSet<Variable> vars) {
70         left.collectFreeVariables(vars);
71         transformer.collectFreeVariables(vars);
72         if(by != null)
73             by.collectFreeVariables(vars);
74     }
75
76     @Override
77     public CompiledQualifier compile(SimplificationContext context) {
78         CompiledQualifier q = left.compile(context);
79         
80         try {
81             Types.unify(cType, q.pattern.getType());
82         } catch (UnificationException e) {
83             context.getErrorLog().log(location, "Transformation function must be generic on list elements.");
84         }
85         
86         if(by == null)
87             q.value = context.apply(transformer, q.value);
88         else
89             q.value = context.apply(transformer, context.lambda(q.pattern.copy(), by), q.value);
90         return q;
91     }
92
93     @Override
94     public void resolve(TranslationContext context) {
95         transformer = transformer.resolve(context);
96         left.resolve(context);
97         if(by != null)
98             by = by.resolve(context);
99     }
100
101     @Override
102     public void collectEffects(THashSet<Type> effects) {
103         left.collectEffects(effects);
104         transformer.collectEffects(effects);
105         if(by != null)
106             by.collectEffects(effects);
107     }
108     
109     @Override
110     public void setLocationDeep(long loc) {
111         if(location == Locations.NO_LOCATION) {
112             location = loc;
113             left.setLocationDeep(loc);
114             transformer.setLocationDeep(loc);
115             if(by != null)
116                 by.setLocationDeep(loc);
117         }
118     }
119     
120     @Override
121     public void accept(ListQualifierVisitor visitor) {
122         visitor.visit(this);
123     }
124     
125     @Override
126     public ListQualifier accept(ListQualifierTransformer transformer) {
127         return transformer.transform(this);
128     }
129 }