From: Hannu Niemistö Date: Mon, 24 Apr 2017 15:24:17 +0000 (+0300) Subject: (refs #6924) Support for record field access syntax. X-Git-Tag: v1.29.0~85^2 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F64%2F464%2F2;p=simantics%2Fplatform.git (refs #6924) Support for record field access syntax. 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 --- diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CompilationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CompilationContext.java index 397e1ce4f..411b93fe2 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CompilationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CompilationContext.java @@ -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 valueCache = new THashMap(); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java index c36564eda..9dbd94691 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java @@ -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 dataTypesAst) { + ArrayList fieldAccessorGenerators = new ArrayList(); 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 typeClassesAst) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java index 0b4d03a04..fd70d368d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/EnvironmentOfModule.java @@ -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 getFieldAccessors(String name) { + List r1 = base.getFieldAccessors(name); + List r2 = module.getFieldAccessors(name); + if(r1 == null) + return r2; + if(r2 == null) + return r1; + ArrayList result = new ArrayList(r1.size() + r2.size()); + result.addAll(r1); + result.addAll(r2); + return result; + } + @Override public SCLRelation getRelation(Name name) { if(name.module.equals(module.getName())) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java index c010835e9..77e6e96df 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java @@ -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); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java index 65e89edf1..643513d67 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java @@ -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 index 000000000..8d5b00dde --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/SafeCoerce.java @@ -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"; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java index e5b5720ef..203bd81d2 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java @@ -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> blanksInExistentialFrame = new ArrayList>(); SCLValue bindFunction; - public EEntityTypeAnnotation currentEntityTypeAnnotation; public PreQuery currentPreQuery; THashMap relations = new THashMap(); @@ -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 accessors = new ArrayList(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= 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 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 candidateNames = new THashSet(4); + namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, + new TObjectProcedure() { + @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() { + @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 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 candidateNames = new THashSet(4); - namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE, - new TObjectProcedure() { - @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() { - @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 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 parameters = new ArrayList(4); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java index 465c5c8ff..8e836d002 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBinary.java @@ -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 index f0363dcdf..000000000 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EEntityTypeAnnotation.java +++ /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 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(); - 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); - } - -} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java index 4ebd0248d..c05b15409 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java @@ -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 allRefs, TIntHashSet refs) { parent.collectRefs(allRefs, refs); - for(FieldAccessor accessor : accessors) - accessor.collectRefs(allRefs, refs); + accessor.collectRefs(allRefs, refs); } @Override public void collectVars(TObjectIntHashMap 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 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 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 allRefs, TIntHashSet refs) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/IdAccessor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/IdAccessor.java index 0220a9ab8..9cb37e58f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/IdAccessor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/IdAccessor.java @@ -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; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/StringAccessor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/StringAccessor.java index 548cc9f43..d08a4383f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/StringAccessor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/accessor/StringAccessor.java @@ -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; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/pre/QPreGuard.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/pre/QPreGuard.java index 287f89919..f0caf7f37 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/pre/QPreGuard.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/pre/QPreGuard.java @@ -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) }); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/ConcreteEnvironment.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/ConcreteEnvironment.java index e3280daf6..c2a16f681 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/ConcreteEnvironment.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/ConcreteEnvironment.java @@ -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 getFieldAccessors(String name) { + List result = null; + boolean resultIsImmutable = true; + for(Module module : moduleMap.values()) { + List accessors = module.getFieldAccessors(name); + if(accessors != null) { + if(result == null) + result = accessors; + else if(resultIsImmutable) { + result = new ArrayList(result.size() + accessors.size()); + result.addAll(accessors); + resultIsImmutable = false; + } + else + result.addAll(accessors); + } + } + return result; + } + @Override public Namespace getLocalNamespace() { return localNamespace; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java index b25fc7209..545c6b82c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environment.java @@ -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 getFieldAccessors(String name); SCLRelation getRelation(Name name); SCLEntityType getEntityType(Name name); TypeDescriptor getTypeDescriptor(TCon type); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java index 3253931fe..9b4712c84 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java @@ -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; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java index 6dac77acf..0c97d308a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java @@ -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; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/profiling/BranchPointInjector.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/profiling/BranchPointInjector.java index 3d7350f9f..6f3ff3be9 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/profiling/BranchPointInjector.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/profiling/BranchPointInjector.java @@ -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; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java index 7fec8f83c..c408b4bb6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java @@ -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."); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar index 8ff94fd4b..7551271af 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar @@ -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 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat index da6ec2969..51eafba3c 100644 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 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java index 362bc5142..735974868 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java @@ -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)*)? */ @@ -1049,10 +1043,6 @@ public abstract class SCLParser { * query ::= QUERY_OP queryBlock */ protected abstract Object reduceCompositeQuery(); - /** - * queryBlock ::= LBRACE (query (SEMICOLON (query SEMICOLON)* query)?)? RBRACE - */ - protected abstract Object reduceQueryBlock(); /** * lexp ::= faexp faexp* */ @@ -1101,6 +1091,10 @@ public abstract class SCLParser { * case ::= exp caseRhs */ protected abstract Object reduceCase(); + /** + * queryBlock ::= LBRACE (query (SEMICOLON (query SEMICOLON)* query)?)? RBRACE + */ + protected abstract Object reduceQueryBlock(); /** * stringLiteral ::= BEGIN_STRING (SUSPEND_STRING exp CONTINUE_STRING)* END_STRING */ diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java index 90c801403..799e59099 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java @@ -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 3 - ? new QConjunction((Query[])get(length()-1)) - : null); - } @Override protected Object reduceHashedId() { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java index 98ef910f3..c7723eea8 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java @@ -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; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java index 55ee202f7..c6210ce49 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java @@ -37,6 +37,7 @@ public class ConcreteModule implements Module { THashMap typeClasses = new THashMap(); THashMap> typeClassInstances = new THashMap>(); THashMap values = new THashMap(); + THashMap> fieldAccessors = new THashMap>(); THashMap relations = new THashMap(); THashMap entityTypes = new THashMap(); THashMap rules = new THashMap(); @@ -106,6 +107,11 @@ public class ConcreteModule implements Module { addValue(value); return value; } + + @Override + public List 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 list = fieldAccessors.get(name); + if(list == null) { + list = new ArrayList(2); + fieldAccessors.put(name, list); + } + list.add(accessor); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java index fe57054cc..a53a90b91 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java @@ -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 getFieldAccessors(String name) { + return null; + } + public SCLRelation getRelation(String name) { if(relations.containsKey(name)) return relations.get(name); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java index aff2e2d7f..51d39e103 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java @@ -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 getFieldAccessors(String name); SCLRelation getRelation(String name); SCLEntityType getEntityType(String name); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java index 93ecb2f17..aeb21ffa6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java @@ -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 rules) { } + @Override + public List getFieldAccessors(String name) { + // TODO Not clear if this is needed. + return null; + } }; public RuntimeModule(Module module, RuntimeModuleMap parentModuleMap, diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java index cecc93e84..4701e2586 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java @@ -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(); } diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidPattern3.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidPattern3.scl index cd9425658..e5b4785ae 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidPattern3.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidPattern3.scl @@ -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 index 000000000..de71cf487 --- /dev/null +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Record2.scl @@ -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 diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/RecursiveValues2.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/RecursiveValues2.scl index e81fd508b..252e7ccfa 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/RecursiveValues2.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/RecursiveValues2.scl @@ -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 index a3e4f44e8..000000000 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Select3.scl +++ /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] diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable.scl index d49b1cb80..70b20b360 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable.scl @@ -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 diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable2.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable2.scl index 8fddcf679..9e607cbe8 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable2.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnresolvedVariable2.scl @@ -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