package org.simantics.scl.compiler.elaboration.expressions;
+import java.util.Arrays;
+
import org.simantics.scl.compiler.constants.SCLConstructor;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext.ExistentialFrame;
public class ERecord extends ASTExpression {
+ public static final boolean DEBUG = false;
+
public final EVar constructor;
public final FieldAssignment[] fields;
public Expression resolve(TranslationContext context, boolean asPattern) {
SCLValue constructorValue;
try {
- constructorValue = context.getEnvironment().getLocalNamespace().getValue(constructor.name);
+ constructorValue = context.resolveRecordConstructor(location, constructor.name);
} catch (AmbiguousNameException e) {
context.getErrorLog().log(constructor.location, e.getMessage());
return new EError(constructor.location);
context.getErrorLog().log(constructor.location, "Couldn't resolve the record constructor " + constructor.name + ".");
return new EError(constructor.location);
}
- if(!(constructorValue.getValue() instanceof SCLConstructor)) {
- context.getErrorLog().log(constructor.location, "Value " + constructor.name + " is not a record constructor.");
- return new EError(constructor.location);
- }
- String[] fieldNames = ((SCLConstructor)constructorValue.getValue()).recordFieldNames;
- if(fieldNames == null) {
+ String[] parameterNames = constructorValue.parameterNames;
+ if(parameterNames == null) {
context.getErrorLog().log(constructor.location, "Value " + constructor.name + " is not a record constructor.");
return new EError(constructor.location);
}
- Expression[] parameters = translateFieldsToFunctionParameters(context, fields, fieldNames);
+ Expression[] parameters = translateFieldsToFunctionParameters(context, fields, parameterNames, false);
if(parameters == null)
return new EError(location);
if(asPattern)
if(parameter == null) {
ExistentialFrame frame = context.getCurrentExistentialFrame();
if(frame == null || frame.disallowNewExistentials) {
- context.getErrorLog().log(location, "Field " + fieldNames[i] + " not defined.");
+ context.getErrorLog().log(location, "Field " + parameterNames[i] + " not defined.");
error = true;
}
else
return result;
}
- public static Expression[] translateFieldsToFunctionParameters(TranslationContext context, FieldAssignment[] fields, String[] fieldNames) {
+ public static Expression[] translateFieldsToFunctionParameters(TranslationContext context, FieldAssignment[] fields, String[] fieldNames, boolean chrLiteral) {
+ if(DEBUG) {
+ System.out.println("translateFieldsToFunctionParameters");
+ System.out.println(" fieldNames = " + Arrays.toString(fieldNames));
+ System.out.print(" fields = {");
+ for(int i=0;i<fields.length;++i) {
+ FieldAssignment field = fields[i];
+ if(i > 0)
+ System.out.print(", ");
+ System.out.print(field.name);
+ if(field.value != null) {
+ System.out.print(" = ");
+ System.out.print(field.value);
+ }
+ }
+ System.out.println("}");
+ }
+
THashMap<String,FieldAssignment> recordMap = new THashMap<String,FieldAssignment>(fields.length);
boolean error = false;
+ FieldAssignment wildcardField = null;
for(FieldAssignment field : fields) {
if(field.value == null) {
String actualName = field.name;
+ if(actualName.equals(FieldAssignment.WILDCARD)) {
+ if(wildcardField != null)
+ context.getErrorLog().log(field.location, "The record has more than one wildcard.");
+ wildcardField = field;
+ continue;
+ }
if(actualName.charAt(0) == '?')
actualName = actualName.substring(1);
String bestMatch = null;
FieldAssignment assignment = recordMap.remove(fieldNames[i]);
if(assignment != null)
parameters[i] = assignment.value;
+ else if(wildcardField != null) {
+ String variableName = fieldNames[i];
+ if(chrLiteral)
+ variableName = "?" + variableName;
+ EVar expandedVar = new EVar(wildcardField.location, variableName);
+ parameters[i] = expandedVar;
+ context.addExpandedFromWildcard(expandedVar);
+ }
}
if(!recordMap.isEmpty()) {
for(FieldAssignment field : recordMap.values())
context.getErrorLog().log(field.location, "Field " + field.name + " is not defined in the constructor.");
return null;
}
+ if(DEBUG)
+ System.out.println(" => parameters = " + Arrays.toString(parameters));
return parameters;
}