From: Hannu Niemistö Date: Thu, 27 Apr 2017 20:55:55 +0000 (+0300) Subject: Merge "(refs #6924) Support for record field access syntax." X-Git-Tag: v1.29.0~85 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=27d76db8786149c91b2e5a97d79c774e8c163eb0;hp=8c344e6911c8156dc3ee25e5048f8202f80e52c1;p=simantics%2Fplatform.git Merge "(refs #6924) Support for record field access syntax." --- 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