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;
ArrayList<ArrayList<Variable>> blanksInExistentialFrame = new ArrayList<ArrayList<Variable>>();
SCLValue bindFunction;
- public EEntityTypeAnnotation currentEntityTypeAnnotation;
public PreQuery currentPreQuery;
THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>();
return new EVariable(variable);
}
break;
- case '#':
- if(name.length() > 1 && Character.isLetter(name.charAt(1))) {
- if(currentEntityTypeAnnotation == null) {
- errorLog.log(location, "Attribute references cannot be made in this context.");
- return new EError(location);
- }
- return currentEntityTypeAnnotation.resolveAttribute(this, location, name.substring(1));
- }
- break;
}
return null;
}
- private FieldAccessor createFieldAccessor(char accessSeparator, String name) {
- IdAccessor accessor = new IdAccessor(name);
- accessor.accessSeparator = accessSeparator;
- return accessor;
- }
-
private Expression resolveFieldAccess(Expression base, int pos, String name) {
- ArrayList<FieldAccessor> accessors = new ArrayList<FieldAccessor>(2);
while(pos != -1) {
int p = findSeparator(name, pos+1);
- accessors.add(createFieldAccessor(
+ FieldAccessor accessor = new IdAccessor(
name.charAt(pos),
- name.substring(pos+1, p==-1 ? name.length() : p-1)));
+ name.substring(pos+1, p==-1 ? name.length() : p-1));
+ base = new EFieldAccess(base, accessor);
pos = p;
}
- return new EFieldAccess(base,
- accessors.toArray(new FieldAccessor[accessors.size()]));
+ return base;
}
- private Expression resolveIn(long location, Namespace namespace, String name) {
- SCLValue value;
- try {
- value = resolveValueIn(location, namespace, name);
- } catch (AmbiguousNameException e) {
- if(SCLCompilerConfiguration.ALLOW_OVERLOADING) {
- EAmbiguous.Alternative[] alternatives = new EAmbiguous.Alternative[e.conflictingModules.length];
- //System.out.println("Overloading:");
- for(int i=0;i<e.conflictingModules.length;++i) {
- Name altName = Name.create(e.conflictingModules[i], e.name);
- //System.out.println(" " + altName);
- SCLValue altValue = environment.getValue(altName);
- alternatives[i] = new EAmbiguous.Alternative() {
- @Override
- public Type getType() {
- return altValue.getType();
- }
-
- @Override
- public Expression realize() {
- EConstant expression = new EConstant(altValue);
- expression.location = location;
- return expression;
- }
-
- @Override
- public String toString() {
- return altValue.getName().toString().replace('/', '.');
- }
- };
- }
- EAmbiguous expression = new EAmbiguous(alternatives);
- expression.location = location;
- return expression;
- }
- else {
- errorLog.log(location, e.getMessage());
- value = null;
- }
+ private static int findSeparator(String name, int fromIndex) {
+ ++fromIndex; // the first character (that can be #) is never a separator
+ while(fromIndex < name.length()) {
+ char c = name.charAt(fromIndex);
+ if(c == '.' || c == '#')
+ return fromIndex;
+ ++fromIndex;
}
- if(value == null)
- return new EError(location);
- return new EConstant(location, value);
+ return -1;
}
- private Expression resolveComplexNameIn(long location, Namespace namespace, int startPos, String name) {
- int pos = name.length();
- {
- int hashPos = name.lastIndexOf('#');
- if(hashPos >= 0)
- pos = hashPos;
- }
- while(pos > startPos) {
- SCLValue value;
- try {
- value = namespace.getValue(name.substring(startPos, pos));
- } catch (AmbiguousNameException e) {
+ public Expression resolveValue(long location, Namespace namespace, String name) {
+ try {
+ SCLValue value = namespace.getValue(name);
+ if(value == null)
+ return null;
+ String deprecatedDescription = value.isDeprecated();
+ if(deprecatedDescription != null)
+ errorLog.logWarning(location, "Deprecated value " + value.getName().name + "." + (deprecatedDescription.isEmpty() ? "" : " " + deprecatedDescription));
+ return new EConstant(location, value);
+ } catch (AmbiguousNameException e) {
+ if(SCLCompilerConfiguration.ALLOW_OVERLOADING)
+ return resolveAmbigious(location, e.conflictingModules, name);
+ else {
errorLog.log(location, e.getMessage());
return new EError(location);
}
- if(value != null) {
- Expression result = new EConstant(location, value);
- if(pos < name.length())
- result = resolveFieldAccess(result, pos, name);
- return result;
- }
- pos = name.lastIndexOf('.', pos-1);
}
- errorLog.log(location, "Couldn't resolve variable " + name + ".");
- return new EError(location);
}
- private static int findSeparator(String name, int fromIndex) {
- while(fromIndex < name.length()) {
- char c = name.charAt(fromIndex);
- if(c == '.' || c == '#')
- return fromIndex;
- ++fromIndex;
+ private Expression resolveAmbigious(long location, String[] conflictingModules, String name) {
+ EAmbiguous.Alternative[] alternatives = new EAmbiguous.Alternative[conflictingModules.length];
+ for(int i=0;i<conflictingModules.length;++i) {
+ Name altName = Name.create(conflictingModules[i], name);
+ SCLValue altValue = environment.getValue(altName);
+ alternatives[i] = new EAmbiguous.Alternative() {
+ @Override
+ public Type getType() {
+ return altValue.getType();
+ }
+
+ @Override
+ public Expression realize() {
+ EConstant expression = new EConstant(altValue);
+ expression.location = location;
+ return expression;
+ }
+
+ @Override
+ public String toString() {
+ return altValue.getName().toString().replace('/', '.');
+ }
+ };
}
- return -1;
+ EAmbiguous expression = new EAmbiguous(alternatives);
+ expression.location = location;
+ return expression;
}
- public Expression resolveExpression(long location, String name) {
- int p = findSeparator(name, 1 /* Initial # is not a separator */);
- if(p == -1) {
- Expression result = resolveLocalVariable(location, name);
+ public Expression resolveVariable(long location, Namespace namespace, String name, int begin) {
+ int end = findSeparator(name, begin);
+ String part = end == -1 ? (begin == 0 ? name : name.substring(begin)) : name.substring(begin, end);
+
+ if(begin == 0) {
+ Expression result = resolveLocalVariable(location, part);
if(result != null)
- return result;
+ return end == -1 ? result : resolveFieldAccess(result, end, name);
+ // FIXME.. support for records
if(localEnvironment != null) {
result = localEnvironment.resolve(environment, name);
if(result != null) {
return result;
}
}
-
- return resolveIn(location, environment.getLocalNamespace(), name);
}
- else {
- if(localEnvironment != null) {
- Expression result = localEnvironment.resolve(environment, name);
- if(result != null) {
- result.setLocationDeep(location);
- return result;
+ if(end != -1 && name.charAt(end) == '.') {
+ Namespace childNamespace = namespace.getNamespace(part);
+ if(childNamespace != null)
+ return resolveVariable(location, childNamespace, name, end+1);
+ }
+ {
+ Expression result = null;
+ if(end != -1) {
+ for(int end2 = name.length();end2 > end;end2 = name.lastIndexOf('.', end2-1)) {
+ part = name.substring(begin, end2);
+ result = resolveValue(location, namespace, part);
+ if(result != null) {
+ end = end2 == name.length() ? -1 : end2;
+ break;
+ }
}
}
-
- String prefix = name.substring(0, p);
- Expression result = resolveLocalVariable(location, prefix);
+ if(result == null)
+ result = resolveValue(location, namespace, part);
if(result != null)
- return resolveFieldAccess(result, p, name);
-
- Namespace namespace = environment.getLocalNamespace();
- int pos = 0;
- while(name.charAt(p)=='.') {
- Namespace temp = namespace.getNamespace(prefix);
- if(temp == null)
- break;
- namespace = temp;
- pos = p+1;
- p = findSeparator(name, pos);
- if(p < 0)
- return resolveIn(location, namespace, name.substring(pos));
- prefix = name.substring(pos, p);
+ return end == -1 ? result : resolveFieldAccess(result, end, name);
+ }
+ reportResolveFailure(location, namespace, part);
+ return new EError(location);
+ }
+
+ private void reportResolveFailure(long location, Namespace namespace, String name) {
+ StringBuilder message = new StringBuilder();
+ message.append("Couldn't resolve ").append(name).append(".");
+
+ final THashSet<String> candidateNames = new THashSet<String>(4);
+ namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE,
+ new TObjectProcedure<SCLValue>() {
+ @Override
+ public boolean execute(SCLValue value) {
+ if(value == null) {
+ new Exception().printStackTrace();
+ return true;
+ }
+ String valueName = value.getName().name;
+ if(name.equalsIgnoreCase(valueName))
+ candidateNames.add(valueName);
+ return true;
}
-
- return resolveComplexNameIn(location, namespace, pos, name);
+ });
+ if(localEnvironment != null)
+ localEnvironment.forNames(new TObjectProcedure<String>() {
+ @Override
+ public boolean execute(String valueName) {
+ if(name.equalsIgnoreCase(valueName))
+ candidateNames.add(valueName);
+ return true;
+ }
+ });
+
+ if(candidateNames.size() > 0) {
+ message.append(" Did you mean ");
+ String[] ns = candidateNames.toArray(new String[candidateNames.size()]);
+ Arrays.sort(ns);
+ for(int i=0;i<ns.length;++i) {
+ if(i > 0) {
+ message.append(", ");
+ if(i == ns.length-1)
+ message.append("or ");
+ }
+ message.append(ns[i]);
+ }
+ message.append('?');
}
+
+ errorLog.log(location, message.toString());
+ }
+
+ public Expression resolveVariable(long location, String name) {
+ return resolveVariable(location, environment.getLocalNamespace(), name, 0);
}
public Expression resolvePattern(EVar name) {
return new EVariable(name.location, newVariable(name.name));
}
else
- return resolveExpression(name.location, name.name);
+ return resolveVariable(name.location, name.name);
}
/**
else
return prec;
}
-
- private SCLValue resolveValueIn(long location, Namespace namespace, final String name) throws AmbiguousNameException {
- SCLValue value = namespace.getValue(name);
- if(value == null) {
- StringBuilder message = new StringBuilder();
- message.append("Couldn't resolve variable ").append(name).append(".");
-
- final THashSet<String> candidateNames = new THashSet<String>(4);
- namespace.findValuesForPrefix("", AcceptAllNamespaceFilter.INSTANCE,
- new TObjectProcedure<SCLValue>() {
- @Override
- public boolean execute(SCLValue value) {
- if(value == null) {
- new Exception().printStackTrace();
- return true;
- }
- String valueName = value.getName().name;
- if(name.equalsIgnoreCase(valueName))
- candidateNames.add(valueName);
- return true;
- }
- });
- if(localEnvironment != null)
- localEnvironment.forNames(new TObjectProcedure<String>() {
- @Override
- public boolean execute(String valueName) {
- if(name.equalsIgnoreCase(valueName))
- candidateNames.add(valueName);
- return true;
- }
- });
-
- if(candidateNames.size() > 0) {
- message.append(" Did you mean ");
- String[] ns = candidateNames.toArray(new String[candidateNames.size()]);
- Arrays.sort(ns);
- for(int i=0;i<ns.length;++i) {
- if(i > 0) {
- message.append(", ");
- if(i == ns.length-1)
- message.append("or ");
- }
- message.append(ns[i]);
- }
- message.append('?');
- }
-
- errorLog.log(location, message.toString());
- return null;
- }
- return value;
- }
public Case translateCase(Expression lhs, Expression rhs) {
ArrayList<Expression> parameters = new ArrayList<Expression>(4);