X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fcontexts%2FTranslationContext.java;h=757aca8b5e272880e7c6526048f1b20837709f82;hp=41f807592b7ad1de8c0b28d20183a3d4c80a3948;hb=e12e3ad357853a07b24923b341c4732962a94623;hpb=4bf8562ab7cbb3747f9c5844a07469291d43e905 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 41f807592..757aca8b5 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 @@ -4,15 +4,14 @@ import java.util.ArrayList; import java.util.Arrays; import org.simantics.scl.compiler.common.names.Name; -import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.common.precedence.Associativity; import org.simantics.scl.compiler.common.precedence.Precedence; import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; 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; @@ -33,6 +32,8 @@ import org.simantics.scl.compiler.environment.Namespace; import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst; +import org.simantics.scl.compiler.module.debug.ModuleDebugInfo; +import org.simantics.scl.compiler.module.debug.SymbolReference; import org.simantics.scl.compiler.top.SCLCompilerConfiguration; import org.simantics.scl.compiler.types.Type; @@ -43,16 +44,28 @@ import gnu.trove.set.hash.THashSet; public class TranslationContext extends TypeTranslationContext implements EnvironmentalContext { + public static class ExistentialFrame { + THashSet variables = new THashSet(4); + ArrayList blanks = new ArrayList(2); + public boolean disallowNewExistentials; + + public EVariable createBlank(long location) { + Variable variable = new Variable("_"); + blanks.add(variable); + EVariable result = new EVariable(variable); + result.location = location; + return result; + } + } + THashMap variables = new THashMap(); ArrayList variableEntries = new ArrayList(); LocalEnvironment localEnvironment; TIntArrayList frames = new TIntArrayList(); ArrayList> frameNameSets = new ArrayList>(); - ArrayList> existentialFrames = new ArrayList>(); - ArrayList> blanksInExistentialFrame = new ArrayList>(); + ArrayList existentialFrames = new ArrayList(2); SCLValue bindFunction; - public EEntityTypeAnnotation currentEntityTypeAnnotation; public PreQuery currentPreQuery; THashMap relations = new THashMap(); @@ -63,6 +76,12 @@ public class TranslationContext extends TypeTranslationContext implements Enviro TIntArrayList chrConstraintFrames = new TIntArrayList(); ArrayList chrConstraintEntries = new ArrayList(); + public CHRRuleset currentRuleset; + + public ModuleDebugInfo moduleDebugInfo; + + private String definitionName; + static class Entry { String name; Variable variable; @@ -90,15 +109,17 @@ public class TranslationContext extends TypeTranslationContext implements Enviro } } - public TranslationContext(CompilationContext compilationContext, LocalEnvironment localEnvironment) { + public TranslationContext(CompilationContext compilationContext, LocalEnvironment localEnvironment, String definitionName) { super(compilationContext); this.localEnvironment = localEnvironment; + this.moduleDebugInfo = compilationContext.moduleDebugInfo; + this.definitionName = definitionName; } public static boolean isConstructorName(String name) { int p = name.lastIndexOf('.'); char firstChar = name.charAt(p<0 ? 0 : p+1); - return Character.isUpperCase(firstChar); + return Character.isUpperCase(firstChar) || firstChar == '('; } /* Tries to resolve name as a local variable. It is assumed @@ -111,147 +132,128 @@ public class TranslationContext extends TypeTranslationContext implements Enviro char c = name.charAt(0); switch(c) { - case '?': - if(existentialFrames.isEmpty()) { - errorLog.log(location, "Existential variables can be used only in queries."); + case '?': { + ExistentialFrame existentialFrame = getCurrentExistentialFrame(); + if(existentialFrame == null || existentialFrame.disallowNewExistentials) { + errorLog.log(location, "New existential variables can be defined only in queries."); return new EError(location); } variable = new Variable(name); variables.put(name, variable); - existentialFrames.get(existentialFrames.size()-1).add(name); + existentialFrame.variables.add(name); return new EVariable(variable); - case '_': + } + case '_': { if(name.length()==1) { - variable = new Variable("_"); - if(blanksInExistentialFrame.isEmpty()) { - errorLog.log(location, "Cannot use blank variables in this context."); + ExistentialFrame existentialFrame = getCurrentExistentialFrame(); + if(existentialFrame == null || existentialFrame.disallowNewExistentials) { + errorLog.log(location, "Blank variables can be used only in queries."); return new EError(location); } - blanksInExistentialFrame.get(blanksInExistentialFrame.size()-1).add(variable); - 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)); + return existentialFrame.createBlank(location); } break; } + } return null; } - private FieldAccessor createFieldAccessor(char accessSeparator, String name) { - IdAccessor accessor = new IdAccessor(name); - accessor.accessSeparator = accessSeparator; - return accessor; + public ExistentialFrame getCurrentExistentialFrame() { + int size = existentialFrames.size(); + if(size == 0) + return null; + else + return existentialFrames.get(size-1); } - private Expression resolveFieldAccess(Expression base, int pos, String name) { - ArrayList accessors = new ArrayList(2); + private Expression resolveFieldAccess(long location, Expression base, int pos, String name) { while(pos != -1) { int p = findSeparator(name, pos+1); - accessors.add(createFieldAccessor( + int endPos = p==-1 ? name.length() : p; + FieldAccessor accessor = new IdAccessor( name.charAt(pos), - name.substring(pos+1, p==-1 ? name.length() : p-1))); + name.substring(pos+1, endPos)); + accessor.location = Locations.sublocation(location, pos+1, endPos); + base = new EFieldAccess(base, accessor); + base.location = Locations.sublocation(location, 0, endPos); 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)); + if(moduleDebugInfo != null) + moduleDebugInfo.symbolReferences.add(new SymbolReference(value.getName(), Name.create(compilationContext.module.getName(), definitionName), location)); + 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(location, 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) { @@ -305,7 +350,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); } /** @@ -356,7 +401,7 @@ public class TranslationContext extends TypeTranslationContext implements Enviro chrConstraintFrames.add(chrConstraintEntries.size()); } - public void popCHRConstraintFrame(ArrayList constraints) { + public void popCHRConstraintFrame(CHRRuleset ruleset) { int frame = chrConstraintFrames.removeAt(chrConstraintFrames.size()-1); int i = chrConstraintEntries.size(); while(i > frame) { @@ -368,25 +413,23 @@ public class TranslationContext extends TypeTranslationContext implements Enviro else newConstraint = chrConstraints.put(entry.name, entry.constraint); if(newConstraint.implicitlyDeclared) - constraints.add(newConstraint); + ruleset.addConstraint(newConstraint); } } public void pushExistentialFrame() { pushFrame(); - existentialFrames.add(new THashSet()); - blanksInExistentialFrame.add(new ArrayList(2)); + existentialFrames.add(new ExistentialFrame()); } public Variable[] popExistentialFrame() { popFrame(); - THashSet set = existentialFrames.remove(existentialFrames.size()-1); - ArrayList blanks = blanksInExistentialFrame.remove(blanksInExistentialFrame.size()-1); - Variable[] result = new Variable[set.size() + blanks.size()]; + ExistentialFrame frame = existentialFrames.remove(existentialFrames.size()-1); + Variable[] result = new Variable[frame.variables.size() + frame.blanks.size()]; int i=0; - for(String name : set) + for(String name : frame.variables) result[i++] = variables.remove(name); - for(Variable blank : blanks) + for(Variable blank : frame.blanks) result[i++] = blank; return result; } @@ -419,58 +462,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); @@ -534,13 +525,6 @@ public class TranslationContext extends TypeTranslationContext implements Enviro Locations.combine(definitions.get(0).location, definitions.get(definitions.size()-1).location), cases); } - - public SCLValue getBindFunction() { - if(bindFunction == null) { - bindFunction = getEnvironment().getValue(Names.Prelude_bind); - } - return bindFunction; - } public SCLRelation resolveRelation(long location, String name) { SCLRelation relation = relations.get(name); @@ -568,4 +552,12 @@ public class TranslationContext extends TypeTranslationContext implements Enviro public SCLValue getValue(Name name) { return environment.getValue(name); } + + public CHRRuleset resolveRuleset(String name) throws AmbiguousNameException { + return Environments.getRuleset(environment, name); + } + + public void disallowNewExistentials() { + getCurrentExistentialFrame().disallowNewExistentials = true; + } }