package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.constants.SCLConstructor; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.environment.AmbiguousNameException; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.parsing.Token; import gnu.trove.map.hash.THashMap; public class ERecord extends ASTExpression { Token constructor; FieldAssignment[] fields; public ERecord(Token constructor, FieldAssignment[] fields) { this.constructor = constructor; this.fields = fields; } @Override public Expression resolve(TranslationContext context) { return resolve(context, false); } @Override public Expression resolveAsPattern(TranslationContext context) { return resolve(context, true); } public Expression resolve(TranslationContext context, boolean asPattern) { SCLValue constructorValue; try { constructorValue = context.getEnvironment().getLocalNamespace().getValue(constructor.text); } catch (AmbiguousNameException e) { context.getErrorLog().log(constructor.location, e.getMessage()); return new EError(constructor.location); } if(constructorValue == null) { context.getErrorLog().log(constructor.location, "Couldn't resolve the record constructor " + constructor.text + "."); return new EError(constructor.location); } if(!(constructorValue.getValue() instanceof SCLConstructor)) { context.getErrorLog().log(constructor.location, "Value " + constructor.text + " is not a record constructor."); return new EError(constructor.location); } String[] fieldNames = ((SCLConstructor)constructorValue.getValue()).recordFieldNames; if(fieldNames == null) { context.getErrorLog().log(constructor.location, "Value " + constructor.text + " is not a record constructor."); return new EError(constructor.location); } THashMap recordMap = new THashMap(fields.length); for(FieldAssignment field : fields) { if(field.value == null) { String actualName = field.name; if(actualName.charAt(0) == '?') actualName = actualName.substring(1); String bestMatch = null; int bestMatchLength = 0; for(int i=0;i bestMatchLength) { bestMatch = fieldName; bestMatchLength = fieldName.length(); } } if(bestMatch == null) { context.getErrorLog().log(field.location, "Invalid shorthand field " + field.name + " is defined twice."); return new EError(location); } field.value = new EVar(field.location, field.name); field.name = bestMatch; } if(recordMap.put(field.name, field) != null) { context.getErrorLog().log(field.location, "Field " + field.name + " is defined more than once."); return new EError(location); } } Expression[] parameters = new Expression[fieldNames.length]; boolean error = false; for(int i=0;i