X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fexpressions%2FERecord.java;h=47ef205df17cbce0d9ff1d74dd8f1154adc1bcfa;hp=e1f444d8220a12801d3ad430c55c11065a4edef8;hb=dce0962e9a3220b7cc5e4e7d782dd565ab817104;hpb=1ec0193a5a5b8f368b03adb24acd762838ddf8ea diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERecord.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERecord.java index e1f444d82..47ef205df 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERecord.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERecord.java @@ -1,5 +1,7 @@ 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; @@ -12,6 +14,8 @@ import gnu.trove.map.hash.THashMap; public class ERecord extends ASTExpression { + public static final boolean DEBUG = false; + public final EVar constructor; public final FieldAssignment[] fields; @@ -33,7 +37,7 @@ public class ERecord extends ASTExpression { 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); @@ -42,16 +46,12 @@ public class ERecord extends ASTExpression { 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) @@ -69,7 +69,7 @@ public class ERecord extends ASTExpression { 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 @@ -86,12 +86,36 @@ public class ERecord extends ASTExpression { 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 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 recordMap = new THashMap(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; @@ -122,12 +146,20 @@ public class ERecord extends ASTExpression { 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; + parameters[i] = new EVar(wildcardField.location, variableName); + } } 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; }