Change-Id: Iaddc3d0536350eef85086b0a73a5c1b08055398c
public void resolve(TranslationContext context) {
context.pushExistentialFrame();
head.resolve(context);
public void resolve(TranslationContext context) {
context.pushExistentialFrame();
head.resolve(context);
+ context.disallowNewExistentials();
body.resolve(context);
existentialVariables = context.popExistentialFrame();
}
body.resolve(context);
existentialVariables = context.popExistentialFrame();
}
public class TranslationContext extends TypeTranslationContext implements EnvironmentalContext {
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);
+ boolean disallowNewExistentials;
+ }
+
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>>();
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;
SCLValue bindFunction;
public PreQuery currentPreQuery;
char c = name.charAt(0);
switch(c) {
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);
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);
return new EVariable(variable);
if(name.length()==1) {
variable = new Variable("_");
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);
}
return new EError(location);
}
- blanksInExistentialFrame.get(blanksInExistentialFrame.size()-1).add(variable);
+ existentialFrame.blanks.add(variable);
return new EVariable(variable);
}
break;
}
return new EVariable(variable);
}
break;
}
+ private 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) {
while(pos != -1) {
int p = findSeparator(name, pos+1);
private Expression resolveFieldAccess(Expression base, int pos, String name) {
while(pos != -1) {
int p = findSeparator(name, pos+1);
public void pushExistentialFrame() {
pushFrame();
public void pushExistentialFrame() {
pushFrame();
- existentialFrames.add(new THashSet<String>());
- blanksInExistentialFrame.add(new ArrayList<Variable>(2));
+ existentialFrames.add(new ExistentialFrame());
}
public Variable[] popExistentialFrame() {
popFrame();
}
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()];
+ for(String name : frame.variables)
result[i++] = variables.remove(name);
result[i++] = variables.remove(name);
- for(Variable blank : blanks)
+ for(Variable blank : frame.blanks)
result[i++] = blank;
return result;
}
result[i++] = blank;
return result;
}
public CHRRuleset resolveRuleset(String name) throws AmbiguousNameException {
return Environments.getRuleset(environment, name);
}
public CHRRuleset resolveRuleset(String name) throws AmbiguousNameException {
return Environments.getRuleset(environment, name);
}
+
+ public void disallowNewExistentials() {
+ getCurrentExistentialFrame().disallowNewExistentials = true;
+ }
if(compiler.getErrorLog().hasNoErrors())
return new Success<Module>(compiler.getModule());
else {
if(compiler.getErrorLog().hasNoErrors())
return new Success<Module>(compiler.getModule());
else {
+ if(options == null || !options.silent)
LOGGER.error("While compiling " + getModuleName() + ":\n " +
CompilationErrorFormatter.toString(getSourceReader(null), compiler.getErrorLog().getErrors()).replaceAll("\n", "\n "));
return new Failure(compiler.getErrorLog().getErrors());
}
} catch (IOException e) {
LOGGER.error("While compiling " + getModuleName() + ":\n " +
CompilationErrorFormatter.toString(getSourceReader(null), compiler.getErrorLog().getErrors()).replaceAll("\n", "\n "));
return new Failure(compiler.getErrorLog().getErrors());
}
} catch (IOException e) {
+ if(options == null || !options.silent)
LOGGER.error("Compilation of module " + moduleName + " failed.", e);
return new Failure(e);
}
LOGGER.error("Compilation of module " + moduleName + " failed.", e);
return new Failure(e);
}
@Test public void CHR3() { test(); }
@Test public void CHR4() { test(); }
@Test public void CHR5() { test(); }
@Test public void CHR3() { test(); }
@Test public void CHR4() { test(); }
@Test public void CHR5() { test(); }
- @Test public void CHR6() { test(); }
+ @Test public void CHR6() { test(); }
+ @Test public void CHR7() { test(); }
+ @Test public void CHR8() { test(); }
@Test public void ClosureRecursion() { test(); }
@Test public void Collaz() { test(); }
@Test public void Compose() { test(); }
@Test public void ClosureRecursion() { test(); }
@Test public void Collaz() { test(); }
@Test public void Compose() { test(); }
--- /dev/null
+module {
+ export = [main],
+ chr
+}
+
+import "StandardLibrary"
+
+ruleset RS where
+ constraint X Integer
+ True => X 3
+
+main = ()
+ where
+ include RS createRS
+ -X ?value, ?value < 6 => print "X \(?value)", X (?value+1)
+--
+X 3
+X 4
+X 5
+()
\ No newline at end of file
--- /dev/null
+module {
+ export = [main],
+ chr
+}
+
+import "StandardLibrary"
+
+main = ()
+ where
+ X ?x => Y ?y
+--
+10:15-10:17: New existential variables can be defined only in queries.
\ No newline at end of file