]> gerrit.simantics Code Review - simantics/platform.git/blob
d8d5f76658e4c6947edb11a6302bf974ba763987
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.expressions;
2
3 import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext;
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
7 import org.simantics.scl.compiler.elaboration.java.Builtins;
8 import org.simantics.scl.compiler.elaboration.java.ListConstructor;
9 import org.simantics.scl.compiler.errors.Locations;
10 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
11 import org.simantics.scl.compiler.internal.interpreted.IExpression;
12 import org.simantics.scl.compiler.internal.interpreted.IListLiteral;
13 import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
14 import org.simantics.scl.compiler.types.Type;
15 import org.simantics.scl.compiler.types.Types;
16 import org.simantics.scl.compiler.types.exceptions.MatchException;
17
18 import gnu.trove.map.hash.TObjectIntHashMap;
19 import gnu.trove.set.hash.THashSet;
20 import gnu.trove.set.hash.TIntHashSet;
21
22 public class EListLiteral extends SimplifiableExpression {
23
24     Expression[] components;
25     Type componentType;
26
27     public EListLiteral(Expression[] components) {
28         this.components = components;
29     }
30
31     private EListLiteral(Expression[] components, Type componentType) {
32         this.components = components;
33         this.componentType = componentType;
34     }
35
36     public Expression[] getComponents() {
37         return components;
38     }
39     
40     @Override
41     public void collectRefs(TObjectIntHashMap<Object> allRefs,
42             TIntHashSet refs) {
43         for(Expression component : components)
44             component.collectRefs(allRefs, refs);
45     }
46
47     @Override
48     public void collectVars(TObjectIntHashMap<Variable> allVars,
49             TIntHashSet vars) {
50         for(Expression component : components)
51             component.collectVars(allVars, vars);
52     }
53     
54     @Override
55     public void collectFreeVariables(THashSet<Variable> vars) {
56         for(Expression component : components)
57             component.collectFreeVariables(vars);
58     }
59     
60     @Override
61     public Expression simplify(SimplificationContext context) {
62         context.pushLocation(location);
63         try {
64             for(int i=0;i<components.length;++i)
65                 components[i] = components[i].simplify(context);
66             
67             if(components.length <= Constants.MAX_LIST_LITERAL_LENGTH) {
68                 Expression result = new EConstant(location, Builtins.LIST_CONSTRUCTORS[components.length], 
69                         componentType);
70                 if(components.length > 0)
71                     result = new EApply(location, result, components);
72                 return result;
73             }
74             else {
75                 Expression result = new EApplyType(new ELiteral(location, new ListConstructor(components.length)), componentType);
76                 result = new EApply(location, result, components);
77                 return result;
78             }
79         } finally {
80             context.popLocation();
81         }
82     }
83
84     @Override
85     public Expression resolve(TranslationContext context) {
86         for(int i=0;i<components.length;++i)
87             components[i] = components[i].resolve(context);
88         return this;
89     }
90     
91     @Override
92     public Expression resolveAsPattern(TranslationContext context) {
93         for(int i=0;i<components.length;++i)
94             components[i] = components[i].resolveAsPattern(context);
95         return this;
96     }
97     
98     @Override
99     protected void updateType() throws MatchException {
100         setType(Types.list(componentType));
101     }
102     
103     @Override
104     public Expression checkBasicType(TypingContext context, Type requiredType) {
105         try {
106             componentType = Types.unifyApply(Types.LIST, requiredType);
107         } catch (MatchException e) {
108             context.getErrorLog().log(location, "Expected a value with type " + requiredType + " but got a list.");
109             return new EError(location);
110         }
111         for(int i=0;i<components.length;++i)
112             components[i] = components[i].checkType(context, componentType);
113         return this;
114     }
115
116     @Override
117     public void collectEffects(THashSet<Type> effects) {
118         for(Expression component : components)
119             component.collectEffects(effects);
120     }
121
122     @Override
123     public void setLocationDeep(long loc) {
124         if(location == Locations.NO_LOCATION) {
125             location = loc;
126             for(Expression component : components)
127                 component.setLocationDeep(loc);
128         }
129     }
130     
131     @Override
132     public void accept(ExpressionVisitor visitor) {
133         visitor.visit(this);
134     }
135     
136     @Override
137     public IExpression toIExpression(ExpressionInterpretationContext target) {
138         IExpression[] componentExpressions = new IExpression[components.length];
139         for(int i=0;i<components.length;++i)
140             componentExpressions[i] = components[i].toIExpression(target);
141         return new IListLiteral(componentExpressions);
142     }
143
144     @Override
145     public void forVariables(VariableProcedure procedure) {
146         for(Expression component : components)
147             component.forVariables(procedure);
148     }
149     
150     @Override
151     public Expression replace(ReplaceContext context) {
152         Expression[] newComponents = new Expression[components.length];
153         for(int i=0;i<components.length;++i)
154             newComponents[i] = components[i].replace(context);
155         return new EListLiteral(newComponents, componentType.replace(context.tvarMap));
156     }
157     
158     @Override
159     public boolean isPattern(int arity) {
160         if(arity != 0)
161             return false;
162         for(Expression component : components)
163             if(!component.isPattern(0))
164                 return false;
165         return true;
166     }
167     
168     @Override
169     public Expression accept(ExpressionTransformer transformer) {
170         return transformer.transform(this);
171     }
172
173 }