(refs #6924) Support for record field access syntax. 64/464/2
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Mon, 24 Apr 2017 15:24:17 +0000 (18:24 +0300)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Wed, 26 Apr 2017 13:58:38 +0000 (16:58 +0300)
Because the record field access syntax is harder to implement when the
old Variable access syntax is also supported, this feature is only
enabled (and Variable disabled), when the following module header is
used:

module {
    fields
}

This change contains also refactoring and cleaning up of code
related to variable resolving and field handling.

Change-Id: I8e877573131d501e1a6e63bdde39e064df9ded39

41 files changed:
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CompilationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/SafeCoerce.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EEntityTypeAnnotation.java [deleted file]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVar.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/ExpressionAccessor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/FieldAccessor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/IdAccessor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/StringAccessor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/pre/QPreGuard.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/ConcreteEnvironment.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/profiling/BranchPointInjector.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidPattern3.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record2.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/RecursiveValues2.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Select3.scl [deleted file]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable2.scl

index 397e1ce4fcd306d8dbcbcd3adcbab049fe3eb997..411b93fe22eb72cb58523d62a88c4af61f6ce067 100644 (file)
@@ -11,6 +11,7 @@ import org.simantics.scl.compiler.errors.ErrorLog;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
+import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.module.ConcreteModule;
 import org.simantics.scl.compiler.types.Type;
 
@@ -22,6 +23,7 @@ public class CompilationContext implements EnvironmentalContext {
     public JavaTypeTranslator javaTypeTranslator;
     public JavaNamingPolicy namingPolicy;
     public ConcreteModule module;
+    public ModuleHeader header;
     
     private THashMap<Name, SCLValue> valueCache = new THashMap<Name, SCLValue>();
 
index c36564eda59981fef0d800fc1d4492556f7817cd..9dbd94691a82cd27bab16a4a7be498e39fee2852 100644 (file)
@@ -7,6 +7,7 @@ import java.util.List;
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.common.datatypes.Constructor;
 import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
 import org.simantics.scl.compiler.constants.SCLConstructor;
 import org.simantics.scl.compiler.constants.StringConstant;
@@ -14,12 +15,14 @@ import org.simantics.scl.compiler.constants.generic.CallJava;
 import org.simantics.scl.compiler.constants.generic.ClassRef;
 import org.simantics.scl.compiler.constants.generic.ConvertToListFilter;
 import org.simantics.scl.compiler.constants.generic.MethodRef;
+import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
 import org.simantics.scl.compiler.constants.generic.OutputFilter;
 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
 import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter;
 import org.simantics.scl.compiler.constants.generic.PopOutputFilter;
 import org.simantics.scl.compiler.constants.generic.StackItem;
 import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem;
+import org.simantics.scl.compiler.constants.singletons.SafeCoerce;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
@@ -316,6 +319,7 @@ public class Elaboration {
     }
     
     public void processDataTypes(ArrayList<DDataAst> dataTypesAst) {
+        ArrayList<Runnable> fieldAccessorGenerators = new ArrayList<Runnable>(); 
         for(DDataAst dataTypeAst : dataTypesAst) {
             TypeTranslationContext context = createTypeTranslationContext();
             TVar[] typeParameters = new TVar[dataTypeAst.parameters.length];
@@ -395,7 +399,34 @@ public class Elaboration {
                 constructors[j].fieldNames = fieldNames;
                 constructors[j].recordFieldNames = constructor.fieldNames;
             }
+            if(constructors.length == 1) {
+                Constructor constructor = constructors[0];
+                if(constructor.recordFieldNames != null) {
+                    fieldAccessorGenerators.add(new Runnable() {
+                        @Override
+                        public void run() {
+                            Type in = Types.apply(dataType.name, dataType.parameters);
+                            for(int i=0;i<constructor.recordFieldNames.length;++i) {
+                                Type out = constructor.parameterTypes[i];
+                                Constant accessor;
+                                if(trivialDataType)
+                                    accessor = new SafeCoerce(dataType.parameters, in, out);
+                                else
+                                    accessor = new CallJava(dataType.parameters, Types.NO_EFFECTS, out,
+                                            new Type[] {in}, new StackItem[] {new ParameterStackItem(0, in)},
+                                            new FieldRef(constructor.javaName, constructor.fieldNames != null ? constructor.fieldNames[i] : "c" + i,
+                                                    javaTypeTranslator.toTypeDesc(out)),
+                                            null);
+                                module.addFieldAccessor(constructor.recordFieldNames[i], accessor);
+                            }
+                        }
+                    });
+                }
+            }
         }
+        
+        for(Runnable fieldAccessorGenerator : fieldAccessorGenerators)
+            fieldAccessorGenerator.run();
     }
     
     public void processTypeClasses(ArrayList<ProcessedDClassAst> typeClassesAst) {
index 0b4d03a046775d772b17b7955876cf8a5fb6a625..fd70d368d96cb7e6fbedf004c41c58d04dbf1534 100644 (file)
@@ -2,8 +2,10 @@ package org.simantics.scl.compiler.compilation;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
@@ -40,6 +42,21 @@ public class EnvironmentOfModule implements Environment {
         else
             return base.getValue(name);
     }
+    
+    @Override
+    public List<Constant> getFieldAccessors(String name) {
+        List<Constant> r1 = base.getFieldAccessors(name);
+        List<Constant> r2 = module.getFieldAccessors(name);
+        if(r1 == null)
+            return r2;
+        if(r2 == null)
+            return r1;
+        ArrayList<Constant> result = new ArrayList<Constant>(r1.size() + r2.size());
+        result.addAll(r1);
+        result.addAll(r2);
+        return result;
+    }
+    
     @Override
     public SCLRelation getRelation(Name name) {
         if(name.module.equals(module.getName()))
index c010835e9dc1383081033c8c28da0408dfef7f7f..77e6e96df9a4390f4c7ef4ef70758f20b15d35f7 100644 (file)
@@ -5,7 +5,6 @@ import java.util.function.Consumer;
 
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
-import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
 import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
@@ -64,7 +63,7 @@ public class NamespaceOfModule implements Namespace {
             return base.getValue(name);
         }
     }
-
+    
     @Override
     public SCLRelation getRelation(String name) throws AmbiguousNameException {
         SCLRelation relation = module.getRelation(name);
index 65e89edf1bc7c26fb4e8c1563083647b6d1cf231..643513d67720537450e8c98fbd411bdd781b000e 100644 (file)
@@ -7,7 +7,6 @@ import java.util.Map;
 
 import org.simantics.scl.compiler.environment.EnvironmentFactory;
 import org.simantics.scl.compiler.errors.ErrorLog;
-import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
 import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
@@ -71,11 +70,12 @@ public class SCLCompiler {
             String moduleName) {
         try {
             if(hasErrors()) return;
+            compilationContext.header = ModuleHeader.process(compilationContext.errorLog, declarations.moduleHeader);
             Elaboration elaboration = new Elaboration(compilationContext,
                     timer,
                     localEnvironmentFactory,
                     moduleName,
-                    ModuleHeader.process(compilationContext.errorLog, declarations.moduleHeader),
+                    compilationContext.header,
                     declarations.importsAst,
                     jrvFactory,
                     declarations.valueDefinitionsAst,
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/SafeCoerce.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/SafeCoerce.java
new file mode 100644 (file)
index 0000000..8d5b00d
--- /dev/null
@@ -0,0 +1,25 @@
+package org.simantics.scl.compiler.constants.singletons;
+
+import org.simantics.scl.compiler.constants.FunctionValue;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class SafeCoerce extends FunctionValue {    
+    public SafeCoerce(TVar[] vars, Type in, Type out) {
+        super(vars, Types.NO_EFFECTS, out, in);
+    }
+    
+    @Override
+    public Type applyExact(MethodBuilder mb, Val[] parameters) {
+        parameters[0].push(mb);
+        return getReturnType();
+    }
+
+    @Override
+    public String toString() {
+        return "safeCoerce";
+    }
+}
index e5b5720ef07a005b61f3269b3ed07fc30e2737bd..203bd81d2d2bd925b9fd9ee969aa475db7b31331 100644 (file)
@@ -12,7 +12,6 @@ import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.elaboration.expressions.Case;
 import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
-import org.simantics.scl.compiler.elaboration.expressions.EEntityTypeAnnotation;
 import org.simantics.scl.compiler.elaboration.expressions.EError;
 import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess;
 import org.simantics.scl.compiler.elaboration.expressions.ELambda;
@@ -52,7 +51,6 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
     ArrayList<ArrayList<Variable>> blanksInExistentialFrame = new ArrayList<ArrayList<Variable>>();
     SCLValue bindFunction;
     
-    public EEntityTypeAnnotation currentEntityTypeAnnotation;
     public PreQuery currentPreQuery;
     
     THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>();
@@ -131,130 +129,91 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
                 return new EVariable(variable);
             }
             break;
-        case '#':
-            if(name.length() > 1 && Character.isLetter(name.charAt(1))) {
-                if(currentEntityTypeAnnotation == null) {
-                    errorLog.log(location, "Attribute references cannot be made in this context.");
-                    return new EError(location);
-                }
-                return currentEntityTypeAnnotation.resolveAttribute(this, location, name.substring(1));
-            }
-            break;
         }
         return null;
     }
     
-    private FieldAccessor createFieldAccessor(char accessSeparator, String name) {
-        IdAccessor accessor = new IdAccessor(name);
-        accessor.accessSeparator = accessSeparator;
-        return accessor;
-    }
-    
     private Expression resolveFieldAccess(Expression base, int pos, String name) {
-        ArrayList<FieldAccessor> accessors = new ArrayList<FieldAccessor>(2);
         while(pos != -1) {
             int p = findSeparator(name, pos+1);
-            accessors.add(createFieldAccessor(
+            FieldAccessor accessor = new IdAccessor(
                     name.charAt(pos),
-                    name.substring(pos+1, p==-1 ? name.length() : p-1)));
+                    name.substring(pos+1, p==-1 ? name.length() : p-1));
+            base = new EFieldAccess(base, accessor);
             pos = p;
         }
-        return new EFieldAccess(base,
-                accessors.toArray(new FieldAccessor[accessors.size()]));
+        return base;
     }
     
-    private Expression resolveIn(long location, Namespace namespace, String name) {
-        SCLValue value;
-        try {
-            value = resolveValueIn(location, namespace, name);
-        } catch (AmbiguousNameException e) {
-            if(SCLCompilerConfiguration.ALLOW_OVERLOADING) {
-                EAmbiguous.Alternative[] alternatives = new EAmbiguous.Alternative[e.conflictingModules.length];
-                //System.out.println("Overloading:");
-                for(int i=0;i<e.conflictingModules.length;++i) {
-                    Name altName = Name.create(e.conflictingModules[i], e.name);
-                    //System.out.println("    " + altName);
-                    SCLValue altValue = environment.getValue(altName);
-                    alternatives[i] = new EAmbiguous.Alternative() {
-                        @Override
-                        public Type getType() {
-                            return altValue.getType();
-                        }
-    
-                        @Override
-                        public Expression realize() {
-                            EConstant expression = new EConstant(altValue);
-                            expression.location = location;
-                            return expression;
-                        }
-                        
-                        @Override
-                        public String toString() {
-                            return altValue.getName().toString().replace('/', '.');
-                        }
-                    };
-                }
-                EAmbiguous expression = new EAmbiguous(alternatives);
-                expression.location = location;
-                return expression;
-            }
-            else {
-                errorLog.log(location, e.getMessage());
-                value = null;
-            }
+    private static int findSeparator(String name, int fromIndex) {
+        ++fromIndex; // the first character (that can be #) is never a separator
+        while(fromIndex < name.length()) {
+            char c = name.charAt(fromIndex);
+            if(c == '.' || c == '#')
+                return fromIndex;
+            ++fromIndex;
         }
-        if(value == null)
-            return new EError(location);
-        String deprecatedDescription = value.isDeprecated();
-        if(deprecatedDescription != null)
-            errorLog.logWarning(location, "Deprecated value " + value.getName().name + "." + (deprecatedDescription.isEmpty() ? "" : " " + deprecatedDescription));
-        return new EConstant(location, value);
+        return -1;
     }
     
-    private Expression resolveComplexNameIn(long location, Namespace namespace, int startPos, String name) {
-        int pos = name.length();
-        {
-            int hashPos = name.lastIndexOf('#');
-            if(hashPos >= 0)
-                pos = hashPos;
-        }
-        while(pos > startPos) {
-            SCLValue value;
-            try {
-                value = namespace.getValue(name.substring(startPos, pos));
-            } catch (AmbiguousNameException e) {
+    public Expression resolveValue(long location, Namespace namespace, String name) {
+        try {
+            SCLValue value = namespace.getValue(name);
+            if(value == null)
+                return null;
+            String deprecatedDescription = value.isDeprecated();
+            if(deprecatedDescription != null)
+                errorLog.logWarning(location, "Deprecated value " + value.getName().name + "." + (deprecatedDescription.isEmpty() ? "" : " " + deprecatedDescription));
+            return new EConstant(location, value);
+        } catch (AmbiguousNameException e) {
+            if(SCLCompilerConfiguration.ALLOW_OVERLOADING)
+               return resolveAmbigious(location, e.conflictingModules, name);
+            else {
                 errorLog.log(location, e.getMessage());
                 return new EError(location);
             }
-            if(value != null) {
-                Expression result = new EConstant(location, value);
-                if(pos < name.length())
-                    result = resolveFieldAccess(result, pos, name);
-                return result;
-            }
-            pos = name.lastIndexOf('.', pos-1);
         }
-        errorLog.log(location, "Couldn't resolve variable " + name + ".");
-        return new EError(location);
     }
     
-    private static int findSeparator(String name, int fromIndex) {
-        while(fromIndex < name.length()) {
-            char c = name.charAt(fromIndex);
-            if(c == '.' || c == '#')
-                return fromIndex;
-            ++fromIndex;
+    private Expression resolveAmbigious(long location, String[] conflictingModules, String name) {
+        EAmbiguous.Alternative[] alternatives = new EAmbiguous.Alternative[conflictingModules.length];
+        for(int i=0;i<conflictingModules.length;++i) {
+            Name altName = Name.create(conflictingModules[i], name);
+            SCLValue altValue = environment.getValue(altName);
+            alternatives[i] = new EAmbiguous.Alternative() {
+                @Override
+                public Type getType() {
+                    return altValue.getType();
+                }
+
+                @Override
+                public Expression realize() {
+                    EConstant expression = new EConstant(altValue);
+                    expression.location = location;
+                    return expression;
+                }
+
+                @Override
+                public String toString() {
+                    return altValue.getName().toString().replace('/', '.');
+                }
+            };
         }
-        return -1;
+        EAmbiguous expression = new EAmbiguous(alternatives);
+        expression.location = location;
+        return expression;
     }
     
-    public Expression resolveExpression(long location, String name) {
-        int p = findSeparator(name, 1 /* Initial # is not a separator */);
-        if(p == -1) {
-            Expression result = resolveLocalVariable(location, name);
+    public Expression resolveVariable(long location, Namespace namespace, String name, int begin) {
+        int end = findSeparator(name, begin);
+        String part = end == -1 ? (begin == 0 ? name : name.substring(begin)) : name.substring(begin, end);
+
+        if(begin == 0) {
+            Expression result = resolveLocalVariable(location, part);
             if(result != null)
-                return result;
+                return end == -1 ? result : resolveFieldAccess(result, end, name);
             
+            // FIXME.. support for records
             if(localEnvironment != null) {
                 result = localEnvironment.resolve(environment, name);
                 if(result != null) {
@@ -262,39 +221,82 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
                     return result;
                 }
             }
-            
-            return resolveIn(location, environment.getLocalNamespace(), name);
         }
-        else {
-            if(localEnvironment != null) {
-                Expression result = localEnvironment.resolve(environment, name);
-                if(result != null) {
-                    result.setLocationDeep(location);
-                    return result;
+        if(end != -1 && name.charAt(end) == '.') {
+            Namespace childNamespace = namespace.getNamespace(part);
+            if(childNamespace != null)
+                return resolveVariable(location, childNamespace, name, end+1);
+        }
+        {
+            Expression result = null;
+            if(end != -1) {
+                for(int end2 = name.length();end2 > end;end2 = name.lastIndexOf('.', end2-1)) {
+                    part = name.substring(begin, end2);
+                    result = resolveValue(location, namespace, part);
+                    if(result != null) {
+                        end = end2 == name.length() ? -1 : end2;
+                        break;
+                    }
                 }
             }
-            
-            String prefix = name.substring(0, p);
-            Expression result = resolveLocalVariable(location, prefix);
+            if(result == null)
+                result = resolveValue(location, namespace, part);
             if(result != null)
-                return resolveFieldAccess(result, p, name);
-            
-            Namespace namespace = environment.getLocalNamespace();
-            int pos = 0;
-            while(name.charAt(p)=='.') {
-                Namespace temp = namespace.getNamespace(prefix);
-                if(temp == null)
-                    break;
-                namespace = temp;
-                pos = p+1;
-                p = findSeparator(name, pos);
-                if(p < 0)
-                    return resolveIn(location, namespace, name.substring(pos));
-                prefix = name.substring(pos, p);
+                return end == -1 ? result : resolveFieldAccess(result, end, name);
+        }
+        reportResolveFailure(location, namespace, part);
+        return new EError(location);
+    }
+    
+    private void reportResolveFailure(long location, Namespace namespace, String name) {
+        StringBuilder message = new StringBuilder();
+        message.append("Couldn't resolve ").append(name).append(".");
+
+        final THashSet<String> candidateNames = new THashSet<String>(4);
+        namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE,
+                new TObjectProcedure<SCLValue>() {
+            @Override
+            public boolean execute(SCLValue value) {
+                if(value == null) {
+                    new Exception().printStackTrace();
+                    return true;
+                }
+                String valueName = value.getName().name;
+                if(name.equalsIgnoreCase(valueName))
+                    candidateNames.add(valueName);
+                return true;
             }
-            
-            return resolveComplexNameIn(location, namespace, pos, name);
+        });
+        if(localEnvironment != null)
+            localEnvironment.forNames(new TObjectProcedure<String>() {
+                @Override
+                public boolean execute(String valueName) {
+                    if(name.equalsIgnoreCase(valueName))
+                        candidateNames.add(valueName);
+                    return true;
+                }
+            });
+
+        if(candidateNames.size() > 0) {
+            message.append(" Did you mean ");
+            String[] ns = candidateNames.toArray(new String[candidateNames.size()]);
+            Arrays.sort(ns);
+            for(int i=0;i<ns.length;++i) {
+                if(i > 0) {
+                    message.append(", ");
+                    if(i == ns.length-1)
+                        message.append("or ");
+                }
+                message.append(ns[i]);
+            }
+            message.append('?');
         }
+
+        errorLog.log(location, message.toString());
+    }
+    
+    public Expression resolveVariable(long location, String name) {
+        return resolveVariable(location, environment.getLocalNamespace(), name, 0);
     }
     
     public Expression resolvePattern(EVar name) {
@@ -308,7 +310,7 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
             return new EVariable(name.location, newVariable(name.name));
         }
         else 
-            return resolveExpression(name.location, name.name);
+            return resolveVariable(name.location, name.name);
     }
 
     /**
@@ -422,58 +424,6 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
         else
             return prec;
     }
-
-    private SCLValue resolveValueIn(long location, Namespace namespace, final String name) throws AmbiguousNameException {
-        SCLValue value = namespace.getValue(name);
-        if(value == null) {
-            StringBuilder message = new StringBuilder();
-            message.append("Couldn't resolve variable ").append(name).append(".");
-
-            final THashSet<String> candidateNames = new THashSet<String>(4);
-            namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE,
-                    new TObjectProcedure<SCLValue>() {
-                @Override
-                public boolean execute(SCLValue value) {
-                    if(value == null) {
-                        new Exception().printStackTrace();
-                        return true;
-                    }
-                    String valueName = value.getName().name;
-                    if(name.equalsIgnoreCase(valueName))
-                        candidateNames.add(valueName);
-                    return true;
-                }
-            });
-            if(localEnvironment != null)
-                localEnvironment.forNames(new TObjectProcedure<String>() {
-                    @Override
-                    public boolean execute(String valueName) {
-                        if(name.equalsIgnoreCase(valueName))
-                            candidateNames.add(valueName);
-                        return true;
-                    }
-                });
-
-            if(candidateNames.size() > 0) {
-                message.append(" Did you mean ");
-                String[] ns = candidateNames.toArray(new String[candidateNames.size()]);
-                Arrays.sort(ns);
-                for(int i=0;i<ns.length;++i) {
-                    if(i > 0) {
-                        message.append(", ");
-                        if(i == ns.length-1)
-                            message.append("or ");
-                    }
-                    message.append(ns[i]);
-                }
-                message.append('?');
-            }
-
-            errorLog.log(location, message.toString());
-            return null;
-        }
-        return value;
-    }
     
     public Case translateCase(Expression lhs, Expression rhs) {        
         ArrayList<Expression> parameters = new ArrayList<Expression>(4);  
index 465c5c8ffac7f1981ccc50a42c7a09bfb94cf749..8e836d002e1dc296680ba67e8c3e634895ab14c5 100644 (file)
@@ -57,7 +57,7 @@ public class EBinary extends ASTExpression {
         output.add(left);
         for(EBinaryRightSide right : rights) {
             // Read op
-            Expression op = context.resolveExpression(right.operator.location, right.operator.name);
+            Expression op = context.resolveVariable(right.operator.location, right.operator.name);
             if(op == null)
                 return new EError(location);
             Precedence opPrec = op.getPrecedence();
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EEntityTypeAnnotation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EEntityTypeAnnotation.java
deleted file mode 100644 (file)
index f0363dc..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.simantics.scl.compiler.elaboration.expressions;
-
-import static org.simantics.scl.compiler.elaboration.expressions.Expressions.loc;
-
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
-import org.simantics.scl.compiler.elaboration.java.EqRelation;
-import org.simantics.scl.compiler.elaboration.query.QAtom;
-import org.simantics.scl.compiler.elaboration.query.Query;
-import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
-import org.simantics.scl.compiler.elaboration.relations.SCLEntityType.Attribute;
-import org.simantics.scl.compiler.elaboration.relations.SCLEntityType.AttributeBinding;
-import org.simantics.scl.compiler.environment.AmbiguousNameException;
-import org.simantics.scl.compiler.environment.Environments;
-import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.internal.parsing.Token;
-
-import gnu.trove.map.hash.THashMap;
-
-public class EEntityTypeAnnotation extends ASTExpression {
-    
-    Expression expression;
-    Token entityTypeName;
-    SCLEntityType entityType;
-    Query query; // optional
-    THashMap<String, AttributeBinding> attributeBindingMap;
-
-    public EEntityTypeAnnotation(Expression expression, Token entityTypeName,
-            Query query) {
-        this.expression = expression;
-        this.entityTypeName = entityTypeName;
-        this.query = query;
-    }
-
-    @Override
-    public Expression resolve(TranslationContext context) {
-        // Resolve a subexpression
-        expression = expression.resolve(context);
-        
-        // Check that we are inside a query
-        if(context.currentPreQuery == null) {
-            context.getErrorLog().log(location, "Entity type annotations can be used only in queries.");
-            return new EError(location);
-        }
-        
-        // Resolve entity type
-        try {
-            entityType = Environments.getEntityType(context.getEnvironment(), entityTypeName.text);
-        } catch (AmbiguousNameException e) {
-            context.getErrorLog().log(location, e.getMessage());
-            return new EError(location);
-        }
-        if(entityType == null) {
-            context.getErrorLog().log(location, "Couldn't resolve entity type " + entityTypeName.text + ".");
-            return new EError(location);
-        }
-
-        // Rewrite the subexpression as a separate query if it is not a variable
-        Variable base;
-        if(expression instanceof EVariable)
-            base = ((EVariable)expression).variable;
-        else {
-            base = new Variable("?" + entityTypeName.text);
-            context.currentPreQuery.extraVariables.add(base);
-            context.currentPreQuery.sideQueries.add(loc(expression.location,
-                    new QAtom(EqRelation.INSTANCE, new EVariable(base), expression)));
-            expression = loc(expression.location, new EVariable(base));
-        }
-        
-        // Resolve a related query if it exists
-        if(query != null) {
-            EEntityTypeAnnotation oldEntityTypeAnnotation = context.currentEntityTypeAnnotation;
-            attributeBindingMap = new THashMap<String, AttributeBinding>();
-            context.currentEntityTypeAnnotation = this;
-            query = query.resolve(context);
-            context.currentPreQuery.sideQueries.add(query);
-            context.currentEntityTypeAnnotation = oldEntityTypeAnnotation;
-            AttributeBinding[] attributeBindings;
-            if(attributeBindingMap.isEmpty())
-                attributeBindings = AttributeBinding.EMPTY_ARRAY;
-            else {
-                attributeBindings = attributeBindingMap.values().toArray(new AttributeBinding[attributeBindingMap.size()]);
-                for(AttributeBinding binding : attributeBindings)
-                    context.currentPreQuery.extraVariables.add(binding.variable);
-            }
-            context.currentPreQuery.sideQueries.add(entityType.generateQuery(context, base, attributeBindings));
-        }
-        else
-            context.currentPreQuery.sideQueries.add(entityType.generateQuery(context, base, AttributeBinding.EMPTY_ARRAY));
-        return expression;
-    }
-    
-    @Override
-    public void setLocationDeep(long loc) {
-        if(location == Locations.NO_LOCATION) {
-            location = loc;
-            expression.setLocationDeep(loc);
-            query.setLocationDeep(loc);
-        }
-    }
-
-    public Expression resolveAttribute(TranslationContext context, long location, String name) {
-        AttributeBinding binding = attributeBindingMap.get(name);
-        if(binding == null) {
-            Attribute attribute = entityType.getAttribute(name);
-            if(attribute == null) {
-                context.getErrorLog().log(location, "Attribute " + name + " is not defined in entity type " + entityTypeName.text + ".");
-                return new EError(location);
-            }
-            binding = new AttributeBinding(attribute, new Variable("#"+name));
-            attributeBindingMap.put(name, binding);
-        }
-        return new EVariable(binding.variable);
-    }
-    
-    @Override
-    public Expression accept(ExpressionTransformer transformer) {
-        return transformer.transform(this);
-    }
-
-}
index 4ebd0248d5f799d1fdfe2023cee77f93d0db7f31..c05b15409bf8976d6a95c386d7a714085c7c5d01 100644 (file)
@@ -1,12 +1,18 @@
 package org.simantics.scl.compiler.elaboration.expressions;
 
+import java.util.List;
+
 import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous.Alternative;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
+import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.Types;
 import org.simantics.scl.compiler.types.exceptions.MatchException;
@@ -20,37 +26,32 @@ public class EFieldAccess extends SimplifiableExpression {
     private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
     
     Expression parent;
-    FieldAccessor[] accessors;
+    FieldAccessor accessor;
+    boolean lastAccessor = true;
 
-    public EFieldAccess(Expression parent, FieldAccessor[] accessors) {
-        if(parent instanceof EFieldAccess) {
-            EFieldAccess parentAccess = (EFieldAccess)parent;
-            parent = parentAccess.parent;
-            accessors = concat(parentAccess.accessors, accessors);
-        }
+    public EFieldAccess(Expression parent, FieldAccessor accessor) {
         this.parent = parent;
-        this.accessors = accessors;
+        this.accessor = accessor;
+        if(parent instanceof EFieldAccess)
+               ((EFieldAccess)parent).lastAccessor = false;
     }
 
     @Override
     public void collectRefs(TObjectIntHashMap<Object> allRefs,
             TIntHashSet refs) {
         parent.collectRefs(allRefs, refs);
-        for(FieldAccessor accessor : accessors)
-            accessor.collectRefs(allRefs, refs);
+        accessor.collectRefs(allRefs, refs);
     }
 
     @Override
     public void collectVars(TObjectIntHashMap<Variable> allVars,
             TIntHashSet vars) {
         parent.collectVars(allVars, vars);
-        for(FieldAccessor accessor : accessors)
-            accessor.collectVars(allVars, vars);
+        accessor.collectVars(allVars, vars);
     }
 
     private boolean returnsValue() {
-        FieldAccessor lastAccessor = accessors[accessors.length-1];
-        return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();
+       return accessor.accessSeparator == '#' && !accessor.isVariableId();
     }
 
     @Override
@@ -58,8 +59,50 @@ public class EFieldAccess extends SimplifiableExpression {
         // Type is already updated in checkBasicType
     }
     
+    private Expression resolveAccessor(TypingContext context, Type requiredType) {
+        if(!(accessor instanceof IdAccessor))
+            return null;
+        IdAccessor idAccessor = (IdAccessor)accessor;
+        if(idAccessor.accessSeparator != '.')
+            return null;
+        List<Constant> accessors = context.getEnvironment().getFieldAccessors(idAccessor.fieldName);
+        if(accessors == null) {
+            context.getErrorLog().log("Couldn't resolve accessor ." + idAccessor.fieldName + ".");
+            return new EError(location);
+        }
+        Expression accessorExpression;
+        if(accessors.size() == 1)
+            accessorExpression = new ELiteral(accessors.get(0));
+        else {
+            Alternative[] alternatives = new Alternative[accessors.size()];
+            for(int i=0;i<alternatives.length;++i) {
+                final int index = i;
+                alternatives[i] = new Alternative() {
+                    @Override
+                    public Expression realize() {
+                        return new ELiteral(accessors.get(index));
+                    }
+                    @Override
+                    public Type getType() {
+                        return accessors.get(index).getType();
+                    }
+                };
+            }
+            accessorExpression = new EAmbiguous(alternatives);
+        }
+        return new EApply(location, accessorExpression, parent).checkType(context, requiredType);
+    }
+    
     @Override
     public Expression checkBasicType(TypingContext context, Type requiredType) {
+        ModuleHeader header = context.getCompilationContext().header;
+        if(header != null && header.fields) {
+            Expression expression = resolveAccessor(context, requiredType);
+            if(expression != null)
+                return expression;
+        }
+        
+        // Default case
         if(returnsValue())
             setType(requiredType);
         else {
@@ -67,8 +110,7 @@ public class EFieldAccess extends SimplifiableExpression {
             context.subsume(this, requiredType);
         }
         parent = parent.checkType(context, VARIABLE);
-        for(FieldAccessor accessor : accessors)
-            accessor.checkType(context);
+        accessor.checkType(context);
         context.declareEffect(getLocation(), Types.READ_GRAPH);
         return this;
     }
@@ -76,64 +118,47 @@ public class EFieldAccess extends SimplifiableExpression {
     @Override
     public void collectFreeVariables(THashSet<Variable> vars) {
         parent.collectFreeVariables(vars);
-        for(FieldAccessor accessor : accessors)
-            accessor.collectFreeVariables(vars);
+        accessor.collectFreeVariables(vars);
     }
 
     @Override
     public Expression simplify(SimplificationContext context) {
         // Simplify subexpressions
         parent = parent.simplify(context);
-        for(FieldAccessor accessor : accessors)
-            accessor.simplify(context);
+        accessor.simplify(context);
         
-        // ...
-        Expression result = parent;
-        for(int i=0;i<accessors.length;++i) {
-            FieldAccessor accessor = accessors[i];
-            if(accessor.accessSeparator == '.')
-                result = new EApply(
-                        getLocation(),
-                        Types.READ_GRAPH,
-                        context.getConstant(Names.Simantics_Variables_child_),
-                        result,
-                        accessor.asExpression()
-                        );
-            else if(i < accessors.length-1)
-                result = new EApply(
-                        getLocation(),
-                        Types.READ_GRAPH,
-                        context.getConstant(Names.Simantics_Variables_property),
-                        result,
-                        accessor.asExpression()
-                        );
-            else if(accessor.isVariableId())
-                ;
-            else
-                result = new EApply(
-                        getLocation(),
-                        Types.READ_GRAPH,
-                        context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
-                        result,
-                        accessor.asExpression()
-                        );
-        }
-        return result;
-    }
-
-    private static FieldAccessor[] concat(FieldAccessor[] accessors1,
-            FieldAccessor[] accessors2) {
-        FieldAccessor[] result = new FieldAccessor[accessors1.length + accessors2.length];
-        System.arraycopy(accessors1, 0, result, 0, accessors1.length);
-        System.arraycopy(accessors2, 0, result, accessors1.length, accessors2.length);
-        return result;
+        if(accessor.accessSeparator == '.')
+               return new EApply(
+                               getLocation(),
+                               Types.READ_GRAPH,
+                               context.getConstant(Names.Simantics_Variables_child_),
+                               parent,
+                               accessor.asExpression()
+                               );
+        else if(!lastAccessor)
+               return new EApply(
+                               getLocation(),
+                               Types.READ_GRAPH,
+                               context.getConstant(Names.Simantics_Variables_property),
+                               parent,
+                               accessor.asExpression()
+                               );
+        else if(accessor.isVariableId())
+               return parent;
+        else
+               return new EApply(
+                               getLocation(),
+                               Types.READ_GRAPH,
+                               context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
+                               parent,
+                               accessor.asExpression()
+                               );
     }
 
     @Override
     public Expression resolve(TranslationContext context) {
         parent = parent.resolve(context);
-        for(FieldAccessor accessor : accessors)
-            accessor.resolve(context);
+        accessor.resolve(context);
         return this;
     }
 
@@ -153,8 +178,7 @@ public class EFieldAccess extends SimplifiableExpression {
         if(location == Locations.NO_LOCATION) {
             location = loc;
             parent.setLocationDeep(loc);
-            for(FieldAccessor accessor : accessors)
-                accessor.setLocationDeep(loc);
+            accessor.setLocationDeep(loc);
         }
     }
     
@@ -166,8 +190,7 @@ public class EFieldAccess extends SimplifiableExpression {
     @Override
     public void forVariables(VariableProcedure procedure) {
         parent.forVariables(procedure);
-        for(FieldAccessor accessor : accessors)
-            accessor.forVariables(procedure);
+        accessor.forVariables(procedure);
     }
     
     @Override
index a47d3e0dd0a9691261d79e5b380467a98d47b4fb..fda9d37ace3971278859e75ab390de257dccee14 100644 (file)
@@ -44,7 +44,7 @@ public class EVar extends ASTExpression {
 
     @Override
     public Expression resolve(TranslationContext context) {
-        return context.resolveExpression(location, name);
+        return context.resolveVariable(location, name);
     }
     
     @Override
index 50f08149989d140099073f96674a80f274bba457..8d54d50633c7289c5311cfc03e4b7f2b48993e83 100644 (file)
@@ -13,7 +13,6 @@ public interface ExpressionTransformer {
     Expression transform(EConstant expression);
     Expression transform(ECoveringBranchPoint expression);
     Expression transform(EEnforce expression);
-    Expression transform(EEntityTypeAnnotation expression);
     Expression transform(EEquations expression);
     Expression transform(EError expression);
     Expression transform(EExternalConstant expression);
index 2fc6d1e7eb4d93ea1f224dc214650eae6c766a14..5d1d2eb9544493172ee1cb24af7085734659998c 100644 (file)
@@ -7,7 +7,6 @@ import org.simantics.scl.compiler.elaboration.equation.EqGuard;
 import org.simantics.scl.compiler.elaboration.equation.Equation;
 import org.simantics.scl.compiler.elaboration.equation.EquationVisitor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor;
-import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
@@ -143,14 +142,6 @@ EquationVisitor {
         return expression;
     }
 
-    @Override
-    public Expression transform(EEntityTypeAnnotation expression) {
-        expression.expression = expression.expression.accept(this);
-        if(expression.query != null)
-            expression.query = expression.query.accept(this);
-        return expression;
-    }
-
     @Override
     public Expression transform(EError expression) {
         return expression;
@@ -164,11 +155,10 @@ EquationVisitor {
     @Override
     public Expression transform(EFieldAccess expression) {
         expression.parent = expression.parent.accept(this);
-        for(FieldAccessor accessor : expression.accessors)
-            if(accessor instanceof ExpressionAccessor) {
-                ExpressionAccessor expAcc = (ExpressionAccessor)accessor;
-                expAcc.fieldName = expAcc.fieldName.accept(this);
-            }
+        if(expression.accessor instanceof ExpressionAccessor) {
+               ExpressionAccessor expAcc = (ExpressionAccessor)expression.accessor;
+               expAcc.fieldName = expAcc.fieldName.accept(this);
+        }
         return expression;
     }
 
index 401150db5f6bc39f7e50d6940175eb68a57c6735..ef247bf131279042292cad01a6889e0be700b378 100644 (file)
@@ -8,7 +8,6 @@ import org.simantics.scl.compiler.elaboration.equation.Equation;
 import org.simantics.scl.compiler.elaboration.equation.EquationVisitor;
 import org.simantics.scl.compiler.elaboration.expressions.ERuleset.DatalogRule;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor;
-import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessorVisitor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
@@ -85,8 +84,7 @@ EquationVisitor, StatementVisitor {
     @Override
     public void visit(EFieldAccess expression) {
         expression.parent.accept(this);
-        for(FieldAccessor accessor : expression.accessors)
-            accessor.accept(this);
+        expression.accessor.accept(this);
     }
 
     @Override
index 100d3124b27968fec89f09162a94ee3ed5d038aa..e3a1333c08de375b92397972273ea15ba2e6c10d 100644 (file)
@@ -17,7 +17,8 @@ import gnu.trove.set.hash.TIntHashSet;
 public class ExpressionAccessor extends FieldAccessor {
     public Expression fieldName;
 
-    public ExpressionAccessor(Expression fieldName) {
+    public ExpressionAccessor(char accessSeparator, Expression fieldName) {
+        super(accessSeparator);
         this.fieldName = fieldName;
     }
     
index ec9a80b2540f1f1c53a33504466679db9c25279a..ce56da39f4c827819f66ae673e581dbc35590ef8 100644 (file)
@@ -15,6 +15,10 @@ import gnu.trove.set.hash.TIntHashSet;
 
 public abstract class FieldAccessor extends Symbol {
     public char accessSeparator;
+    
+    public FieldAccessor(char accessSeparator) {
+        this.accessSeparator = accessSeparator;
+    }
 
     public void collectRefs(TObjectIntHashMap<Object> allRefs,
             TIntHashSet refs) {
index 0220a9ab859149d6be43ab8c25353f43b2bf34fe..9cb37e58ff12c610207aad0a828a7dc2a8fabd60 100644 (file)
@@ -9,7 +9,8 @@ import org.simantics.scl.compiler.errors.Locations;
 public class IdAccessor extends FieldAccessor {
     public final String fieldName;
 
-    public IdAccessor(String fieldName) {
+    public IdAccessor(char accessSeparator, String fieldName) {
+        super(accessSeparator);
         this.fieldName = fieldName;
     }
 
index 548cc9f4389b7aadeed49d9e0d7f90621fcf3b8e..d08a4383fa8816b11c641d3518586ec189b668b9 100644 (file)
@@ -9,7 +9,8 @@ import org.simantics.scl.compiler.errors.Locations;
 public class StringAccessor extends FieldAccessor {
     public final String fieldName;
 
-    public StringAccessor(String fieldName) {
+    public StringAccessor(char accessSeparator, String fieldName) {
+        super(accessSeparator);
         this.fieldName = fieldName;
     }
     
index 287f89919236559366bc50017d207974c07122df..f0caf7f370ef2e2e52ff584ef4a982c2a3956fc6 100644 (file)
@@ -2,16 +2,11 @@ package org.simantics.scl.compiler.elaboration.query.pre;
 
 import java.util.Arrays;
 
-import org.simantics.scl.compiler.constants.BooleanConstant;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.expressions.EApply;
-import org.simantics.scl.compiler.elaboration.expressions.EEntityTypeAnnotation;
-import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
-import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
 import org.simantics.scl.compiler.elaboration.expressions.EVar;
 import org.simantics.scl.compiler.elaboration.expressions.Expression;
 import org.simantics.scl.compiler.elaboration.expressions.QueryTransformer;
-import org.simantics.scl.compiler.elaboration.expressions.Variable;
 import org.simantics.scl.compiler.elaboration.java.CheckRelation;
 import org.simantics.scl.compiler.elaboration.query.QAtom;
 import org.simantics.scl.compiler.elaboration.query.QMapping;
@@ -83,9 +78,6 @@ public class QPreGuard extends PreQuery {
             if(query != null)
                 return query;
         }
-        else if(expression instanceof EEntityTypeAnnotation) {
-            expression = new ESimpleLet(new Variable("_"), expression, new ELiteral(new BooleanConstant(true)));
-        }
         return new QAtom(CheckRelation.INSTANCE,
                 new Expression[] { expression.resolve(context) });
     }
index e3280daf6e731494e40f2e968093dea2e0aae9ea..c2a16f68151995defb0f4d02d7551ecf90df5f34 100644 (file)
@@ -1,7 +1,10 @@
 package org.simantics.scl.compiler.environment;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
 import org.simantics.scl.compiler.module.Module;
 
@@ -18,6 +21,27 @@ public class ConcreteEnvironment extends AbstractEnvironment {
         this.localNamespace = localNamespace;
     }
 
+    @Override
+    public List<Constant> getFieldAccessors(String name) {
+        List<Constant> result = null;
+        boolean resultIsImmutable = true;
+        for(Module module : moduleMap.values()) {
+            List<Constant> accessors = module.getFieldAccessors(name);
+            if(accessors != null) {
+                if(result == null)
+                    result = accessors;
+                else if(resultIsImmutable) {
+                    result = new ArrayList<Constant>(result.size() + accessors.size());
+                    result.addAll(accessors);
+                    resultIsImmutable = false;
+                }   
+                else
+                    result.addAll(accessors);
+            }
+        }
+        return result;
+    }
+
     @Override
     public Namespace getLocalNamespace() {
         return localNamespace;
index b25fc72091a8bf23d0046c2901ae9bba258b72c5..545c6b82ce834af5f8cc4c58f507bcb8225db9be 100644 (file)
@@ -1,8 +1,10 @@
 package org.simantics.scl.compiler.environment;
 
 import java.util.Collection;
+import java.util.List;
 
 import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
@@ -18,6 +20,7 @@ public interface Environment extends EnvironmentalContext {
     Namespace getLocalNamespace();
     
     SCLValue getValue(Name name);
+    List<Constant> getFieldAccessors(String name);
     SCLRelation getRelation(Name name);
     SCLEntityType getEntityType(Name name);
     TypeDescriptor getTypeDescriptor(TCon type);
index 3253931feb4dcb396167418c5b07b6d89f3af5c6..9b4712c847bacd1ff049d86b0b0d31f1cd88fb1b 100644 (file)
@@ -1,7 +1,9 @@
 package org.simantics.scl.compiler.environment;
 
+import java.util.List;
 import java.util.function.Consumer;
 
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
index 6dac77acf029d54aa3dc9f641de6bd5c0fc006af..0c97d308ab680ed87ee6a2dbace1b971ea6e9d3c 100644 (file)
@@ -1,8 +1,10 @@
 package org.simantics.scl.compiler.environment;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Consumer;
 
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
@@ -73,7 +75,7 @@ public class NamespaceImpl implements Namespace {
             throw new AmbiguousNameException(conflictingModules, name);
         return result;
     }
-
+    
     @Override
     public SCLRelation getRelation(String name) throws AmbiguousNameException {
         SCLRelation result = null, temp;
index 3d7350f9f7863bc1cd7e63313d5767ab0505e269..6f3ff3be93150e8685e05495f1104173dfd865f6 100644 (file)
@@ -14,7 +14,6 @@ import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset;
 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
 import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;
 import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
-import org.simantics.scl.compiler.elaboration.expressions.EEntityTypeAnnotation;
 import org.simantics.scl.compiler.elaboration.expressions.EError;
 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
 import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess;
@@ -222,12 +221,6 @@ public class BranchPointInjector extends StandardExpressionTransformer {
         return super.transform(expression);
     }
     
-    @Override
-    public Expression transform(EEntityTypeAnnotation expression) {
-        ++codeCounter;
-        return super.transform(expression);
-    }
-    
     @Override
     public Expression transform(EError expression) {
         ++codeCounter;
index 7fec8f83ce0e3abe13b2b0fadbec83290cf5a8ba..c408b4bb6e12f01a3fe33610a072055692b958c6 100644 (file)
@@ -9,6 +9,7 @@ public class ModuleHeader {
     public String classLoader;
     public long classLoaderLocation;
     public String defaultLocalName;
+    public boolean fields;
     
     private void read(ErrorLog errorLog, DModuleHeader header) {
         for(FieldAssignment assignment : header.fields)
@@ -33,6 +34,9 @@ public class ModuleHeader {
                                errorLog.log(assignment.value.location, "Expected string here.");
                }
                break;
+            case "fields":
+                this.fields = true;
+                break;
             default:
                 errorLog.logWarning(assignment.location, "Unknown module header field was skipped.");
             }
index 8ff94fd4b8f4db278f4f79f3b57010219f362a90..7551271af416cd323ab16f89e45d6d7a2bdfe4d1 100644 (file)
@@ -120,7 +120,6 @@ ruleDeclaration
  */
  
 exp = bexp (HASTYPE type)?                                   # LocalTypeAnnotation, shift HASTYPE, shift COLON
-    | bexp COLON ID WITH? queryBlock?                        # EntityTypeAnnotation, shift LBRACE, shift WITH
     ;
 
 bexp 
index da6ec2969c2b796a91d045b6977a1de2f7b867bd..51eafba3c75c8de5febcc4628b457aa146cc94d5 100644 (file)
Binary files a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat and b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat differ
index 362bc51420da61eccbac64be9e5165a84bf88cf9..735974868ec8d4ae851d4490661b95eccf93bdd1 100644 (file)
@@ -13,18 +13,18 @@ public abstract class SCLParser {
     public static final boolean TRACE = false;
 
     private static final int INITIAL_CAPACITY = 16;
-    private static final int STATE_COUNT = 349;
+    private static final int STATE_COUNT = 345;
     private static final int TERMINAL_COUNT = 83;
     private static final int NONTERMINAL_COUNT = 51;
-    private static final int PRODUCT_COUNT = 133;
+    private static final int PRODUCT_COUNT = 132;
     
     private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];
     private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];
-    private static final short[] ACTION_TABLE = new short[6396];
-    private static final int[] ERROR_TABLE = new int[906];
+    private static final short[] ACTION_TABLE = new short[6360];
+    private static final int[] ERROR_TABLE = new int[895];
     private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];
     private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];
-    private static final short[] GOTO_TABLE = new short[1652];
+    private static final short[] GOTO_TABLE = new short[1711];
     private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT];
 
     private static final short STATE_MASK = (short)0x0fff;
@@ -72,7 +72,6 @@ public abstract class SCLParser {
         "HIDING",
         "ARROW",
         "COLON",
-        "WITH",
         "MINUS",
         "SYMBOL",
         "LESS",
@@ -103,6 +102,7 @@ public abstract class SCLParser {
         "IN",
         "THEN",
         "ELSE",
+        "WITH",
         "RBRACKET",
         "DOTDOT",
         "AT",
@@ -149,12 +149,12 @@ public abstract class SCLParser {
         "fundep",
         "ruleDeclaration",
         "query",
-        "queryBlock",
         "lexp",
         "symbol",
         "faexp",
         "accessor",
         "case",
+        "queryBlock",
         "stringLiteral",
         "symbolWithoutMinus",
         "listQualifier",
@@ -393,19 +393,19 @@ public abstract class SCLParser {
         return parse(0);
     }
     public Object parseCommands() {
-        return parse(334);
+        return parse(330);
     }
     public Object parseImport() {
-        return parse(341);
+        return parse(337);
     }
     public Object parseType() {
-        return parse(343);
+        return parse(339);
     }
     public Object parseExp() {
-        return parse(345);
+        return parse(341);
     }
     public Object parseEquationBlock() {
-        return parse(347);
+        return parse(343);
     }
 
 
@@ -425,246 +425,244 @@ public abstract class SCLParser {
         case 5:
             return reduceLocalTypeAnnotation();
         case 6:
-            return reduceEntityTypeAnnotation();
-        case 7:
             return reduceEquationBlock();
-        case 8:
+        case 7:
             return reduceModuleHeader();
-        case 9:
+        case 8:
             return reduceTypeAnnotation();
-        case 10:
+        case 9:
             return reduceValueDefinition();
-        case 11:
+        case 10:
             return reduceDataDefinition();
-        case 12:
+        case 11:
             return reduceTypeDefinition();
-        case 13:
+        case 12:
             return reduceClassDefinition();
-        case 14:
+        case 13:
             return reduceInstanceDefinition();
-        case 15:
+        case 14:
             return reduceDerivingInstanceDefinition();
-        case 16:
+        case 15:
             return reduceDocumentationString();
-        case 17:
+        case 16:
             return reduceAnnotation();
-        case 18:
+        case 17:
             return reducePrecedenceDefinition();
-        case 19:
+        case 18:
             return reduceJustImport();
-        case 20:
+        case 19:
             return reduceImportJava();
-        case 21:
+        case 20:
             return reduceEffectDefinition();
-        case 22:
+        case 21:
             return reduceRuleDefinition();
-        case 23:
+        case 22:
             return reduceMappingRelationDefinition();
-        case 24:
+        case 23:
             return reduceRelationDefinition();
-        case 25:
+        case 24:
             return reduceStatementCommand();
-        case 26:
+        case 25:
             return reduceImportCommand();
-        case 27:
+        case 26:
             return reduceGuardStatement();
-        case 28:
+        case 27:
             return reduceLetStatement();
-        case 29:
+        case 28:
             return reduceBindStatement();
-        case 30:
+        case 29:
             return reduceRuleStatement();
-        case 31:
+        case 30:
             return reduceCHRStatement();
-        case 32:
+        case 31:
             return reduceVerboseCHRStatement();
-        case 33:
+        case 32:
             return reduceConstraintStatement();
-        case 34:
+        case 33:
             return reduceDeclarations();
-        case 35:
+        case 34:
             return reduceField();
-        case 36:
+        case 35:
             return reduceFieldShorthand();
-        case 37:
+        case 36:
             return reduceVarId();
-        case 38:
+        case 37:
             return reduceEscapedSymbol();
-        case 39:
+        case 38:
             return reduceTupleConstructor();
-        case 40:
+        case 39:
             return reduceBinary();
-        case 41:
+        case 40:
             return reduceSimpleRhs();
-        case 42:
+        case 41:
             return reduceGuardedRhs();
-        case 43:
+        case 42:
             return reduceConstructor();
-        case 44:
+        case 43:
             return reduceRecordConstructor();
-        case 45:
+        case 44:
             return reduceContext();
-        case 46:
+        case 45:
             return reduceFundeps();
-        case 47:
+        case 46:
             return reduceTypeVar();
-        case 48:
+        case 47:
             return reduceTupleType();
-        case 49:
+        case 48:
             return reduceListType();
-        case 50:
+        case 49:
             return reduceListTypeConstructor();
-        case 51:
+        case 50:
             return reduceTupleTypeConstructor();
-        case 52:
+        case 51:
             return reduceLambda();
-        case 53:
+        case 52:
             return reduceLambdaMatch();
-        case 54:
+        case 53:
             return reduceLet();
-        case 55:
+        case 54:
             return reduceIf();
-        case 56:
+        case 55:
             return reduceMatch();
-        case 57:
+        case 56:
             return reduceDo();
-        case 58:
+        case 57:
             return reduceSelect();
-        case 59:
+        case 58:
             return reduceEnforce();
-        case 60:
+        case 59:
             return reduceVar();
-        case 61:
+        case 60:
             return reduceHashedId();
-        case 62:
+        case 61:
             return reduceBlank();
-        case 63:
+        case 62:
             return reduceInteger();
-        case 64:
+        case 63:
             return reduceFloat();
-        case 65:
+        case 64:
             return reduceString();
-        case 66:
+        case 65:
             return reduceChar();
-        case 67:
+        case 66:
             return reduceTuple();
-        case 68:
+        case 67:
             return reduceViewPattern();
-        case 69:
+        case 68:
             return reduceRightSection();
-        case 70:
+        case 69:
             return reduceLeftSection();
-        case 71:
+        case 70:
             return reduceListLiteral();
-        case 72:
+        case 71:
             return reduceRange();
-        case 73:
+        case 72:
             return reduceListComprehension();
-        case 74:
+        case 73:
             return reduceAs();
-        case 75:
+        case 74:
             return reduceRecord();
-        case 76:
+        case 75:
             return reduceTransformation();
-        case 77:
+        case 76:
             return reduceEq();
-        case 78:
+        case 77:
             return reduceRuleDeclarations();
-        case 79:
+        case 78:
             return reduceImportShowing();
-        case 80:
+        case 79:
             return reduceImportHiding();
-        case 81:
+        case 80:
             return reduceImportValueItem();
-        case 82:
+        case 81:
             return reduceFieldDescription();
-        case 83:
+        case 82:
             return reduceStatements();
-        case 84:
+        case 83:
             return reduceGuardedExpEq();
-        case 85:
+        case 84:
             return reduceFundep();
-        case 86:
+        case 85:
             return reduceQueryRuleDeclaration();
-        case 87:
+        case 86:
             return reduceAnnotation();
-        case 88:
+        case 87:
             return reduceGuardQuery();
-        case 89:
+        case 88:
             return reduceEqualsQuery();
-        case 90:
+        case 89:
             return reduceBindQuery();
-        case 91:
+        case 90:
             return reduceCompositeQuery();
+        case 91:
+            return reduceApply();
         case 92:
-            return reduceQueryBlock();
+            return reduceSymbol();
         case 93:
-            return reduceApply();
+            return reduceEscapedId();
         case 94:
-            return reduceSymbol();
+            return reduceMinus();
         case 95:
-            return reduceEscapedId();
+            return reduceLess();
         case 96:
-            return reduceMinus();
+            return reduceGreater();
         case 97:
-            return reduceLess();
+            return reduceDot();
         case 98:
-            return reduceGreater();
+            return reduceFieldAccess();
         case 99:
-            return reduceDot();
+            return reduceIdAccessor();
         case 100:
-            return reduceFieldAccess();
+            return reduceStringAccessor();
         case 101:
-            return reduceIdAccessor();
+            return reduceExpAccessor();
         case 102:
-            return reduceStringAccessor();
+            return reduceCase();
         case 103:
-            return reduceExpAccessor();
+            return reduceQueryBlock();
         case 104:
-            return reduceCase();
-        case 105:
             return reduceStringLiteral();
-        case 106:
+        case 105:
             return reduceSymbol();
-        case 107:
+        case 106:
             return reduceEscapedId();
-        case 108:
+        case 107:
             return reduceLess();
-        case 109:
+        case 108:
             return reduceGreater();
-        case 110:
+        case 109:
             return reduceDot();
-        case 111:
+        case 110:
             return reduceGuardQualifier();
-        case 112:
+        case 111:
             return reduceLetQualifier();
-        case 113:
+        case 112:
             return reduceBindQualifier();
-        case 114:
+        case 113:
             return reduceThenQualifier();
-        case 115:
+        case 114:
             return reduceCHRQuery();
-        case 116:
+        case 115:
             return reduceVerboseCHRQuery();
-        case 117:
+        case 116:
             return reduceSimpleCaseRhs();
-        case 118:
+        case 117:
             return reduceGuardedCaseRhs();
-        case 119:
+        case 118:
             return reduceGuardedExpArrow();
-        case 120:
+        case 119:
             return reduceGuardEquation();
-        case 121:
+        case 120:
             return reduceBasicEquation();
-        case 122:
+        case 121:
             return reduceEffect();
-        case 123:
+        case 122:
             return reduceJustEtype();
-        case 124:
+        case 123:
             return reduceForAll();
-        case 125:
+        case 124:
             return reduceApplyType();
-        case 126:
+        case 125:
             return reduceDummy();
 
         default:
@@ -709,10 +707,6 @@ public abstract class SCLParser {
      * exp ::= bexp (HASTYPE type)?
      */
     protected abstract Object reduceLocalTypeAnnotation();
-    /**
-     * exp ::= bexp COLON ID (queryBlock | WITH queryBlock?)?
-     */
-    protected abstract Object reduceEntityTypeAnnotation();
     /**
      * equationBlock ::= (equation (SEMICOLON equation)&#42;)?
      */
@@ -1049,10 +1043,6 @@ public abstract class SCLParser {
      * query ::= QUERY_OP queryBlock
      */
     protected abstract Object reduceCompositeQuery();
-    /**
-     * queryBlock ::= LBRACE (query (SEMICOLON (query SEMICOLON)&#42; query)?)? RBRACE
-     */
-    protected abstract Object reduceQueryBlock();
     /**
      * lexp ::= faexp faexp&#42;
      */
@@ -1101,6 +1091,10 @@ public abstract class SCLParser {
      * case ::= exp caseRhs
      */
     protected abstract Object reduceCase();
+    /**
+     * queryBlock ::= LBRACE (query (SEMICOLON (query SEMICOLON)&#42; query)?)? RBRACE
+     */
+    protected abstract Object reduceQueryBlock();
     /**
      * stringLiteral ::= BEGIN_STRING (SUSPEND_STRING exp CONTINUE_STRING)&#42; END_STRING
      */
index 90c801403c859ab2218b47000daf86ceb8851bd7..799e59099b924a005ff59d8a3bf048dfd3e6b3ee 100644 (file)
@@ -21,7 +21,6 @@ import org.simantics.scl.compiler.elaboration.expressions.EBinaryRightSide;
 import org.simantics.scl.compiler.elaboration.expressions.EBlock;
 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
 import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
-import org.simantics.scl.compiler.elaboration.expressions.EEntityTypeAnnotation;
 import org.simantics.scl.compiler.elaboration.expressions.EEquations;
 import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess;
 import org.simantics.scl.compiler.elaboration.expressions.EIf;
@@ -957,30 +956,30 @@ public class SCLParserImpl extends SCLParser {
 
     @Override
     protected Object reduceIdAccessor() {
-        return new IdAccessor(((Token)get(0)).text);
+        return new IdAccessor('.', ((Token)get(0)).text);
     }
 
     @Override
     protected Object reduceStringAccessor() {
-        return new StringAccessor(((Token)get(1)).text);
+        return new StringAccessor('.', ((Token)get(1)).text);
     }
 
     @Override
     protected Object reduceExpAccessor() {
-        return new ExpressionAccessor((Expression)get(1));
+        return new ExpressionAccessor('.', (Expression)get(1));
     }
 
     @Override
     protected Object reduceFieldAccess() {
         if(length() == 1)
             return get(0);
-        FieldAccessor[] accessors = new FieldAccessor[length()/2];
-        for(int i=0;i<accessors.length;++i) {
-            FieldAccessor accessor = (FieldAccessor)get(i*2+2);
-            accessor.accessSeparator = ((Token)get(i*2+1)).text.charAt(0);
-            accessors[i] = accessor;
+        Expression result = (Expression)get(0);
+        for(int i=2;i<length();i+=2) {
+            FieldAccessor accessor = (FieldAccessor)get(i);
+            accessor.accessSeparator = ((Token)get(i-1)).text.charAt(0);
+            result = new EFieldAccess(result, accessor);
         }
-        return new EFieldAccess((Expression)get(0), accessors);
+        return result;
     }
 
     @Override
@@ -1024,14 +1023,6 @@ public class SCLParserImpl extends SCLParser {
     protected Object reduceRuleStatement() {
         return new RuleStatement((Expression)get(0), new QConjunction((Query[])get(2)));
     }
-    
-    @Override
-    protected Object reduceEntityTypeAnnotation() {
-        return new EEntityTypeAnnotation((Expression)get(0), (Token)get(2), 
-                length() > 3 
-                ? new QConjunction((Query[])get(length()-1))
-                : null);
-    }
 
     @Override
     protected Object reduceHashedId() {
index 98ef910f375e417c1668d175026180fed0a9ab7f..c7723eea8e5a41f8dacab76bbecbd8a9105f97ae 100644 (file)
@@ -38,37 +38,37 @@ public interface SCLTerminals {
     public static final int HIDING = 34;
     public static final int ARROW = 35;
     public static final int COLON = 36;
-    public static final int WITH = 37;
-    public static final int MINUS = 38;
-    public static final int SYMBOL = 39;
-    public static final int LESS = 40;
-    public static final int GREATER = 41;
-    public static final int SEPARATED_DOT = 42;
-    public static final int ESCAPED_ID = 43;
-    public static final int LAMBDA = 44;
-    public static final int LAMBDA_MATCH = 45;
-    public static final int LET = 46;
-    public static final int IF = 47;
-    public static final int MATCH = 48;
-    public static final int DO = 49;
-    public static final int MDO = 50;
-    public static final int ENFORCE = 51;
-    public static final int BLANK = 52;
-    public static final int FLOAT = 53;
-    public static final int LBRACKET = 54;
-    public static final int ESCAPED_SYMBOL = 55;
-    public static final int CHAR = 56;
-    public static final int WHEN = 57;
-    public static final int ATTACHED_HASH = 58;
-    public static final int SELECT = 59;
-    public static final int SELECT_FIRST = 60;
-    public static final int SELECT_DISTINCT = 61;
-    public static final int TRANSFORMATION = 62;
-    public static final int EQ = 63;
-    public static final int ATTACHED_DOT = 64;
-    public static final int IN = 65;
-    public static final int THEN = 66;
-    public static final int ELSE = 67;
+    public static final int MINUS = 37;
+    public static final int SYMBOL = 38;
+    public static final int LESS = 39;
+    public static final int GREATER = 40;
+    public static final int SEPARATED_DOT = 41;
+    public static final int ESCAPED_ID = 42;
+    public static final int LAMBDA = 43;
+    public static final int LAMBDA_MATCH = 44;
+    public static final int LET = 45;
+    public static final int IF = 46;
+    public static final int MATCH = 47;
+    public static final int DO = 48;
+    public static final int MDO = 49;
+    public static final int ENFORCE = 50;
+    public static final int BLANK = 51;
+    public static final int FLOAT = 52;
+    public static final int LBRACKET = 53;
+    public static final int ESCAPED_SYMBOL = 54;
+    public static final int CHAR = 55;
+    public static final int WHEN = 56;
+    public static final int ATTACHED_HASH = 57;
+    public static final int SELECT = 58;
+    public static final int SELECT_FIRST = 59;
+    public static final int SELECT_DISTINCT = 60;
+    public static final int TRANSFORMATION = 61;
+    public static final int EQ = 62;
+    public static final int ATTACHED_DOT = 63;
+    public static final int IN = 64;
+    public static final int THEN = 65;
+    public static final int ELSE = 66;
+    public static final int WITH = 67;
     public static final int RBRACKET = 68;
     public static final int DOTDOT = 69;
     public static final int AT = 70;
index 55ee202f7d78d9b56f189bee8df90d96920f03b7..c6210ce49dcf99498b68e09946fb02593c06c308 100644 (file)
@@ -37,6 +37,7 @@ public class ConcreteModule implements Module {
     THashMap<String, TypeClass> typeClasses = new THashMap<String, TypeClass>();
     THashMap<TCon, ArrayList<TypeClassInstance>> typeClassInstances = new THashMap<TCon, ArrayList<TypeClassInstance>>();
     THashMap<String, SCLValue> values = new THashMap<String, SCLValue>();
+    THashMap<String, List<Constant>> fieldAccessors = new THashMap<String, List<Constant>>();
     THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>();
     THashMap<String, SCLEntityType> entityTypes = new THashMap<String, SCLEntityType>();
     THashMap<String, TransformationRule> rules = new THashMap<String, TransformationRule>();
@@ -106,6 +107,11 @@ public class ConcreteModule implements Module {
         addValue(value);
         return value;
     }
+    
+    @Override
+    public List<Constant> getFieldAccessors(String name) {
+        return fieldAccessors.get(name);
+    }
 
     public void addRelation(String name, SCLRelation relation) {
         relations.put(name, relation);
@@ -300,4 +306,13 @@ public class ConcreteModule implements Module {
             throw new NullPointerException();
         this.parentClassLoader = parentClassLoader;
     }
+    
+    public void addFieldAccessor(String name, Constant accessor) {
+        List<Constant> list = fieldAccessors.get(name);
+        if(list == null) {
+            list = new ArrayList<Constant>(2);
+            fieldAccessors.put(name, list);
+        }
+        list.add(accessor);
+    }
 }
index fe57054cc133b7fe28f6ec636ef28f4c962b4212..a53a90b916e8bb8ca7bb6e210f91e13077e54a9d 100644 (file)
@@ -2,7 +2,9 @@ package org.simantics.scl.compiler.module;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.modules.Documentation;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
@@ -70,6 +72,11 @@ public abstract class LazyModule implements Module {
         }
     }
     
+    @Override
+    public List<Constant> getFieldAccessors(String name) {
+        return null;
+    }
+    
     public SCLRelation getRelation(String name) {
         if(relations.containsKey(name))
             return relations.get(name);
index aff2e2d7f815e1ee5c7c3caa15a0fe43a5e47f40..51d39e103c96b53a7e44a13dd175ea0bf2ae349e 100644 (file)
@@ -4,6 +4,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.function.Consumer;
 
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.modules.Documentation;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
@@ -28,6 +29,7 @@ public interface Module {
     String getDefaultLocalName();
     
     SCLValue getValue(String name);
+    List<Constant> getFieldAccessors(String name);
     SCLRelation getRelation(String name);
     SCLEntityType getEntityType(String name);
     
index 93ecb2f1721adbb86b649ef58395cd5a813accad..aeb21ffa63b333a5aae9cd1b018c75aad4549e29 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.runtime;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 
 import org.simantics.scl.compiler.constants.Constant;
@@ -205,6 +206,11 @@ public class RuntimeModule {
         @Override
         public void collectRules(Collection<TransformationRule> rules) {
         }
+        @Override
+        public List<Constant> getFieldAccessors(String name) {
+            // TODO Not clear if this is needed.
+            return null;
+        }
     };
     
     public RuntimeModule(Module module, RuntimeModuleMap parentModuleMap,
index cecc93e84c7df47f9f73463697419a38c1993062..4701e2586e961465e9a9a6c95085b984eb8111a2 100644 (file)
@@ -187,6 +187,7 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void Random1() { test(); }
     @Test public void RangeSyntax() { test(); }
     @Test public void Record1() { test(); }
+    @Test public void Record2() { test(); }
     @Test public void RecordShorthand() { test(); }
     @Test public void RecursiveContext() { test(); }
     @Test public void RecursiveValues2() { test(); }
@@ -201,7 +202,6 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void Sections() { test(); }
     @Test public void Select1() { test(); }
     @Test public void Select2() { test(); }
-    @Test public void Select3() { test(); }
     @Test public void Select4() { test(); }
     @Test public void Select5() { test(); }
     @Test public void Select6() { test(); }
index cd9425658efdb7ad8b1aa8b0b8251558b0cdecd4..e5b4785aeb73095e599df9cb636de9bebfc44cee 100644 (file)
@@ -4,5 +4,5 @@ foo x = b
 
 main = "Not to be executed."
 --
-1:9-1:10: Couldn't resolve variable b.
+1:9-1:10: Couldn't resolve b.
 3:5-3:23: Pattern was expected here.
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record2.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record2.scl
new file mode 100644 (file)
index 0000000..de71cf4
--- /dev/null
@@ -0,0 +1,15 @@
+module {
+    fields
+}
+
+import "Prelude"
+
+data Foo = Foo { x :: Double }
+data Bar = Bar { x :: Double, y :: Double }
+
+main = f.x + b.x + b.y
+  where
+    f = Foo 1.0
+    b = Bar 2.0 3.0
+-- 
+6.0
\ No newline at end of file
index e81fd508b4bd4c392bf6bb3a5f4e0384ceb5de1a..252e7ccfafeaf1cc0ccd74b440cdff67cafcde26 100644 (file)
@@ -2,4 +2,4 @@ f g = a
   where 
     a = g a
 --
-3:11-3:12: Couldn't resolve variable a.
\ No newline at end of file
+3:11-3:12: Couldn't resolve a.
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Select3.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Select3.scl
deleted file mode 100644 (file)
index a3e4f44..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-import "StandardLibrary"
-import "Minigraph"
-
-main = withGraph do
-    a = resource "a"
-    b = map resource ["b0", "b1", "b2", "b3", "b4"]
-    r = map resource ["r0", "r1"]
-    
-    enforce
-        Statement a (r!0) (b!0)
-        Statement a (r!0) (b!1)
-        Statement a (r!1) (b!4)
-        Statement (b!1) (r!1) (b!3)
-        Statement (b!1) (r!0) (b!2)
-    sort $ map uriOf $ select ?x where 
-        Statement a (r!0) (_ : Resource { #r1 = ?x })
---
-[b3]
index d49b1cb8013ef150756295bb14be574fcb73e5d6..70b20b36033ea7f96167aa56e95483e3dbc2d645 100644 (file)
@@ -1,4 +1,4 @@
 a = b
 
 --
-1:5-1:6: Couldn't resolve variable b.
\ No newline at end of file
+1:5-1:6: Couldn't resolve b.
\ No newline at end of file
index 8fddcf679c2e2d1cd07a44dad3f54abd97610f6a..9e607cbe845ea82f1001b6b0e33e681ef95f9a3d 100644 (file)
@@ -4,4 +4,4 @@ b = b
 c = a + b
 
 --
-4:7-4:8: Couldn't resolve variable +.
\ No newline at end of file
+4:7-4:8: Couldn't resolve +.
\ No newline at end of file