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