]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ERecord.java
Merge "Minor refactorings related to SCL constructors"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / ERecord.java
index e1f444d8220a12801d3ad430c55c11065a4edef8..47ef205df17cbce0d9ff1d74dd8f1154adc1bcfa 100644 (file)
@@ -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<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;
@@ -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;
     }