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;
public class TranslationContext extends TypeTranslationContext implements EnvironmentalContext {
+ public static class ExistentialFrame {
+ THashSet<String> variables = new THashSet<String>(4);
+ ArrayList<Variable> blanks = new ArrayList<Variable>(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<String, Variable> variables = new THashMap<String, Variable>();
ArrayList<Entry> variableEntries = new ArrayList<Entry>();
LocalEnvironment localEnvironment;
TIntArrayList frames = new TIntArrayList();
ArrayList<THashSet<String>> frameNameSets = new ArrayList<THashSet<String>>();
- ArrayList<THashSet<String>> existentialFrames = new ArrayList<THashSet<String>>();
- ArrayList<ArrayList<Variable>> blanksInExistentialFrame = new ArrayList<ArrayList<Variable>>();
+ ArrayList<ExistentialFrame> existentialFrames = new ArrayList<ExistentialFrame>(2);
SCLValue bindFunction;
public PreQuery currentPreQuery;
TIntArrayList chrConstraintFrames = new TIntArrayList();
ArrayList<CHRConstraintEntry> chrConstraintEntries = new ArrayList<CHRConstraintEntry>();
+ public CHRRuleset currentRuleset;
+
static class Entry {
String name;
Variable variable;
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);
+ return existentialFrame.createBlank(location);
}
break;
}
+ }
return null;
}
- private Expression resolveFieldAccess(Expression base, int pos, String name) {
+ public ExistentialFrame getCurrentExistentialFrame() {
+ int size = existentialFrames.size();
+ if(size == 0)
+ return null;
+ else
+ return existentialFrames.get(size-1);
+ }
+
+ private Expression resolveFieldAccess(long location, Expression base, int pos, String name) {
while(pos != -1) {
int p = findSeparator(name, pos+1);
+ 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 base;
if(begin == 0) {
Expression result = resolveLocalVariable(location, part);
if(result != null)
- return end == -1 ? result : resolveFieldAccess(result, end, name);
+ return end == -1 ? result : resolveFieldAccess(location, result, end, name);
// FIXME.. support for records
if(localEnvironment != null) {
if(result == null)
result = resolveValue(location, namespace, part);
if(result != null)
- return end == -1 ? result : resolveFieldAccess(result, end, name);
+ return end == -1 ? result : resolveFieldAccess(location, result, end, name);
}
reportResolveFailure(location, namespace, part);
return new EError(location);
public void pushExistentialFrame() {
pushFrame();
- existentialFrames.add(new THashSet<String>());
- blanksInExistentialFrame.add(new ArrayList<Variable>(2));
+ existentialFrames.add(new ExistentialFrame());
}
public Variable[] popExistentialFrame() {
popFrame();
- THashSet<String> set = existentialFrames.remove(existentialFrames.size()-1);
- ArrayList<Variable> 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;
}
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);
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;
+ }
}