(refs #7375) Replaced collectFreeVariables method by a visitor
[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.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.TIntHashSet;
17
18 public class ListThen extends ListQualifier {
19     public ListQualifier left;
20     public Expression transformer;
21     public Expression by; // optional
22     TMetaVar cType;
23     
24     public ListThen(Expression transformer, Expression by) {
25         this.transformer = transformer;
26         this.by = by;
27     }
28     
29     public void setLeft(ListQualifier inner) {
30         this.left = inner;
31     }
32     
33     @Override
34     public void checkType(TypingContext context) {
35         left.checkType(context);
36         
37         cType = Types.metaVar(Kinds.STAR);
38         Type transformerType = Types.function(Types.list(cType), Types.list(cType));
39         if(by != null) {
40             by = by.checkType(context, Types.metaVar(Kinds.STAR));
41             transformerType = Types.function(Types.function(cType, by.getType()), transformerType);
42         }
43         transformer = transformer.checkType(context, transformerType);
44         if(!(Types.canonical(cType) instanceof TMetaVar)) {
45             context.getErrorLog().log(location, "Transformation function must be generic on list elements.");
46         }
47     }
48
49     @Override
50     public void collectVars(TObjectIntHashMap<Variable> allVars,
51             TIntHashSet vars) {
52         left.collectVars(allVars, vars);
53         transformer.collectVars(allVars, vars);
54         if(by != null)
55             by.collectVars(allVars, vars);
56     }
57
58     @Override
59     public CompiledQualifier compile(SimplificationContext context) {
60         CompiledQualifier q = left.compile(context);
61         
62         try {
63             Types.unify(cType, q.pattern.getType());
64         } catch (UnificationException e) {
65             context.getErrorLog().log(location, "Transformation function must be generic on list elements.");
66         }
67         
68         if(by == null)
69             q.value = context.apply(transformer, q.value);
70         else
71             q.value = context.apply(transformer, context.lambda(q.pattern.copy(), by), q.value);
72         return q;
73     }
74
75     @Override
76     public void resolve(TranslationContext context) {
77         transformer = transformer.resolve(context);
78         left.resolve(context);
79         if(by != null)
80             by = by.resolve(context);
81     }
82
83     @Override
84     public void setLocationDeep(long loc) {
85         if(location == Locations.NO_LOCATION) {
86             location = loc;
87             left.setLocationDeep(loc);
88             transformer.setLocationDeep(loc);
89             if(by != null)
90                 by.setLocationDeep(loc);
91         }
92     }
93     
94     @Override
95     public void accept(ListQualifierVisitor visitor) {
96         visitor.visit(this);
97     }
98     
99     @Override
100     public ListQualifier accept(ListQualifierTransformer transformer) {
101         return transformer.transform(this);
102     }
103 }