1 package org.simantics.scl.compiler.elaboration.expressions;
3 import org.simantics.scl.compiler.constants.SCLConstructor;
4 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
5 import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
6 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
7 import org.simantics.scl.compiler.environment.AmbiguousNameException;
8 import org.simantics.scl.compiler.errors.Locations;
9 import org.simantics.scl.compiler.internal.parsing.Token;
11 import gnu.trove.map.hash.THashMap;
13 public class ERecord extends ASTExpression {
16 FieldAssignment[] fields;
18 public ERecord(Token constructor, FieldAssignment[] fields) {
19 this.constructor = constructor;
24 public Expression resolve(TranslationContext context) {
25 return resolve(context, false);
29 public Expression resolveAsPattern(TranslationContext context) {
30 return resolve(context, true);
33 public Expression resolve(TranslationContext context, boolean asPattern) {
34 SCLValue constructorValue;
36 constructorValue = context.getEnvironment().getLocalNamespace().getValue(constructor.text);
37 } catch (AmbiguousNameException e) {
38 context.getErrorLog().log(constructor.location, e.getMessage());
39 return new EError(constructor.location);
41 if(constructorValue == null) {
42 context.getErrorLog().log(constructor.location, "Couldn't resolve the record constructor " + constructor.text + ".");
43 return new EError(constructor.location);
45 if(!(constructorValue.getValue() instanceof SCLConstructor)) {
46 context.getErrorLog().log(constructor.location, "Value " + constructor.text + " is not a record constructor.");
47 return new EError(constructor.location);
49 String[] fieldNames = ((SCLConstructor)constructorValue.getValue()).recordFieldNames;
50 if(fieldNames == null) {
51 context.getErrorLog().log(constructor.location, "Value " + constructor.text + " is not a record constructor.");
52 return new EError(constructor.location);
54 THashMap<String,FieldAssignment> recordMap = new THashMap<String,FieldAssignment>(fields.length);
55 for(FieldAssignment field : fields)
56 recordMap.put(field.name, field);
57 Expression[] parameters = new Expression[fieldNames.length];
58 boolean error = false;
59 for(int i=0;i<fieldNames.length;++i) {
60 FieldAssignment assignment = recordMap.remove(fieldNames[i]);
61 if(assignment == null) {
63 parameters[i] = Expressions.blank(null);
66 context.getErrorLog().log(location, "Field " + fieldNames[i] + " not defined.");
71 parameters[i] = asPattern
72 ? assignment.value.resolveAsPattern(context)
73 : assignment.value.resolve(context);
75 if(!recordMap.isEmpty()) {
76 for(FieldAssignment field : recordMap.values())
77 context.getErrorLog().log(field.location, "Field " + field.name + " is not defined in the constructor.");
81 return new EError(location);
83 EApply result = new EApply(new EConstant(constructorValue), parameters);
84 result.setLocationDeep(location);
90 public void setLocationDeep(long loc) {
91 if(location == Locations.NO_LOCATION) {
93 for(FieldAssignment field : fields)
94 field.value.setLocationDeep(loc);
99 public Expression accept(ExpressionTransformer transformer) {
100 return transformer.transform(this);