]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "(refs #6924) Support for record field access syntax."
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 27 Apr 2017 20:55:55 +0000 (23:55 +0300)
committerGerrit Code Review <gerrit2@www.simantics.org>
Thu, 27 Apr 2017 20:55:55 +0000 (23:55 +0300)
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