1 package org.simantics.scl.compiler.elaboration.expressions.list;
\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
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
21 public class ListThen extends ListQualifier {
\r
22 public ListQualifier left;
\r
23 public Expression transformer;
\r
24 public Expression by; // optional
\r
27 public ListThen(Expression transformer, Expression by) {
\r
28 this.transformer = transformer;
\r
32 public void setLeft(ListQualifier inner) {
\r
37 public void checkType(TypingContext context) {
\r
38 left.checkType(context);
\r
40 cType = Types.metaVar(Kinds.STAR);
\r
41 Type transformerType = Types.function(Types.list(cType), Types.list(cType));
\r
43 by = by.checkType(context, Types.metaVar(Kinds.STAR));
\r
44 transformerType = Types.function(Types.function(cType, by.getType()), transformerType);
\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
53 public void collectRefs(TObjectIntHashMap<Object> allRefs,
\r
55 left.collectRefs(allRefs, refs);
\r
56 transformer.collectRefs(allRefs, refs);
\r
58 by.collectRefs(allRefs, refs);
\r
62 public void collectVars(TObjectIntHashMap<Variable> allVars,
\r
64 left.collectVars(allVars, vars);
\r
65 transformer.collectVars(allVars, vars);
\r
67 by.collectVars(allVars, vars);
\r
71 public void collectFreeVariables(THashSet<Variable> vars) {
\r
72 left.collectFreeVariables(vars);
\r
73 transformer.collectFreeVariables(vars);
\r
75 by.collectFreeVariables(vars);
\r
79 public CompiledQualifier compile(SimplificationContext context) {
\r
80 CompiledQualifier q = left.compile(context);
\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
89 q.value = context.apply(transformer, q.value);
\r
91 q.value = context.apply(transformer, context.lambda(q.pattern.copy(), by), q.value);
\r
96 public void resolve(TranslationContext context) {
\r
97 transformer = transformer.resolve(context);
\r
98 left.resolve(context);
\r
100 by = by.resolve(context);
\r
104 public void decorate(ExpressionDecorator decorator) {
\r
105 transformer = transformer.decorate(decorator);
\r
107 by = by.decorate(decorator);
\r
108 left.decorate(decorator);
\r
112 public void collectEffects(THashSet<Type> effects) {
\r
113 left.collectEffects(effects);
\r
114 transformer.collectEffects(effects);
\r
116 by.collectEffects(effects);
\r
120 public void setLocationDeep(long loc) {
\r
121 if(location == Locations.NO_LOCATION) {
\r
123 left.setLocationDeep(loc);
\r
124 transformer.setLocationDeep(loc);
\r
126 by.setLocationDeep(loc);
\r
131 public void accept(ListQualifierVisitor visitor) {
\r
132 visitor.visit(this);
\r
136 public void forVariables(VariableProcedure procedure) {
\r
137 left.forVariables(procedure);
\r
138 transformer.forVariables(procedure);
\r
140 by.forVariables(procedure);
\r
144 public ListQualifier accept(ListQualifierTransformer transformer) {
\r
145 return transformer.transform(this);
\r