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