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