}
public void resolve(TranslationContext context) {
+ if(relation == SpecialCHRRelation.ASSIGN) {
+ parameters[1] = parameters[1].resolve(context);
+ parameters[0] = parameters[0].resolveAsPattern(context);
+ return;
+ }
if(parameters != null) {
for(int i=0;i<parameters.length;++i)
parameters[i] = parameters[i].resolve(context);
parameters[0] = parameters[0].checkIgnoredType(context);
typeConstraintEvidenceParameters = Expression.EMPTY_ARRAY;
}
+ else if(relation == SpecialCHRRelation.ASSIGN) {
+ parameters[1] = parameters[1].inferType(context);
+ parameters[0] = parameters[0].checkTypeAsPattern(context, parameters[1].getType());
+ typeConstraintEvidenceParameters = Expression.EMPTY_ARRAY;
+ }
else {
TVar[] typeVariables = relation.getTypeVariables();
typeParameters = typeVariables.length == 0 ? Type.EMPTY_ARRAY : new Type[typeVariables.length];
}
public void collectFreeVariables(THashSet<Variable> vars) {
- for(Expression parameter : parameters)
- parameter.collectFreeVariables(vars);
- if(typeConstraintEvidenceParameters != null)
- for(Expression parameter : typeConstraintEvidenceParameters)
+ if(relation == SpecialCHRRelation.ASSIGN) {
+ parameters[1].collectFreeVariables(vars);
+ }
+ else {
+ for(Expression parameter : parameters)
parameter.collectFreeVariables(vars);
+ if(typeConstraintEvidenceParameters != null)
+ for(Expression parameter : typeConstraintEvidenceParameters)
+ parameter.collectFreeVariables(vars);
+ }
}
public void setLocationDeep(long loc) {
import org.simantics.scl.compiler.elaboration.chr.plan.PreCommitOp;
import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
public void collectFreeVariables(THashSet<Variable> vars) {
for(CHRLiteral literal : literals)
literal.collectFreeVariables(vars);
+ for(CHRLiteral literal : literals)
+ if(literal.relation == SpecialCHRRelation.ASSIGN)
+ literal.parameters[0].removeFreeVariables(vars);
}
public void setLocationDeep(long loc) {
}
@Override
- protected void translate(TranslationContext context, boolean isHead, ArrayList<CHRLiteral> literals) {
- literals.add(
- isConstraint(context, expression) ?
- convertConstraint(remove, expression) :
- convertExpression(isHead, expression));
+ protected void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals) {
+ if(isConstraint(context, expression)) {
+ literals.add(convertConstraint(remove, expression));
+ }
+ else {
+ if(remove)
+ context.getErrorLog().log(location, "Only constraints can be marked for removal");
+ else
+ literals.add(convertExpression(mode, expression));
+ }
}
private static boolean isConstraint(TranslationContext context, Expression expression) {
}
}
- private static CHRLiteral convertExpression(boolean isHead, Expression expression) {
- if(isHead)
+ private static CHRLiteral convertExpression(CHRQueryTranslationMode mode, Expression expression) {
+ if(mode.isHead)
return new CHRLiteral(expression.location, SpecialCHRRelation.CHECK, new Expression[] {expression}, false, false);
else
return new CHRLiteral(expression.location, SpecialCHRRelation.EXECUTE, new Expression[] {expression}, false, false);
}
@Override
- protected void translate(TranslationContext context, boolean isHead, ArrayList<CHRLiteral> literals) {
+ protected void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals) {
literals.add(new CHRLiteral(location, SpecialCHRRelation.MEMBER,
new Expression[] { left, right }, false, false));
}
}
@Override
- protected void translate(TranslationContext context, boolean isHead, ArrayList<CHRLiteral> literals) {
+ protected void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals) {
for(CHRAstQuery conjunct : conjuncts)
- conjunct.translate(context, isHead, literals);
+ conjunct.translate(context, mode, literals);
}
}
}
@Override
- protected void translate(TranslationContext context, boolean isHead, ArrayList<CHRLiteral> literals) {
- literals.add(new CHRLiteral(location, SpecialCHRRelation.EQUALS,
+ protected void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals) {
+ literals.add(new CHRLiteral(location, mode.isHead ? SpecialCHRRelation.EQUALS : SpecialCHRRelation.ASSIGN,
new Expression[] { left, right }, false, false));
}
}
}
@Override
- protected void translate(TranslationContext context, boolean isHead, ArrayList<CHRLiteral> literals) {
+ protected void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals) {
context.getCompilationContext().errorLog.log(location, "CHR negation is not yet supported.");
}
}
import org.simantics.scl.compiler.internal.parsing.Symbol;
public abstract class CHRAstQuery extends Symbol {
- public CHRQuery translateAsHead(TranslationContext context) {
- return translate(context, true);
- }
-
- public CHRQuery translateAsBody(TranslationContext context) {
- return translate(context, false);
- }
-
- private CHRQuery translate(TranslationContext context, boolean isHead) {
+ public CHRQuery translate(TranslationContext context, CHRQueryTranslationMode mode) {
ArrayList<CHRLiteral> literals = new ArrayList<CHRLiteral>();
- translate(context, isHead, literals);
+ translate(context, mode, literals);
return new CHRQuery(literals.toArray(new CHRLiteral[literals.size()]));
}
- protected abstract void translate(TranslationContext context, boolean isHead, ArrayList<CHRLiteral> literals);
+ protected abstract void translate(TranslationContext context, CHRQueryTranslationMode mode, ArrayList<CHRLiteral> literals);
public abstract void accept(CHRAstQueryVisitor visitor);
}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.ast;
+
+public enum CHRQueryTranslationMode {
+ RULE_HEAD(true),
+ QUERY_HEAD(true),
+ RULE_BODY(false);
+
+ public final boolean isHead;
+
+ private CHRQueryTranslationMode(boolean isHead) {
+ this.isHead = isHead;
+ }
+}
import org.simantics.scl.compiler.elaboration.chr.plan.AccessFactOp;
import org.simantics.scl.compiler.elaboration.chr.plan.ClaimOp;
import org.simantics.scl.compiler.elaboration.chr.plan.ExecuteOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.MatchOp;
import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;
import org.simantics.scl.compiler.elaboration.chr.planning.items.CheckPrePlanItem;
import org.simantics.scl.compiler.elaboration.chr.planning.items.EqualsPrePlanItem;
case MEMBER:
addMember(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);
return;
+ case ASSIGN:
+ throw new InternalCompilerError(literal.location, "ASSIGN constraint is not allowed in query compilation.");
case EXECUTE:
throw new InternalCompilerError(literal.location, "EXECUTE constraint is not allowed in query compilation.");
}
case EXECUTE:
addPlanOp(new ExecuteOp(literal.location, literal.parameters[0]));
break;
+ case ASSIGN:
+ addPlanOp(new MatchOp(literal.location, literal.parameters[1], literal.parameters[0]));
+ break;
default:
context.getCompilationContext().errorLog.log(
literal.location,
import org.simantics.scl.compiler.types.Types;
public enum SpecialCHRRelation implements CHRRelation {
- EQUALS(A, A),
- MEMBER(A, Types.list(A)),
- CHECK(Types.BOOLEAN),
- EXECUTE(Types.UNIT);
+ EQUALS(A, A), // only in head
+ ASSIGN(A, A), // only in body
+ MEMBER(A, Types.list(A)), // only in head
+ CHECK(Types.BOOLEAN), // only in head
+ EXECUTE(Types.UNIT); // only in body
private final TVar[] typeVariables;
private final Type[] parameterTypes;
import org.simantics.scl.compiler.elaboration.chr.CHRRule;
import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.chr.ast.CHRQueryTranslationMode;
import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
Statement statement = statements.get(i);
if(statement instanceof CHRStatement) {
CHRStatement chrStatement = (CHRStatement)statement;
- ruleset.addRule(new CHRRule(chrStatement.location, chrStatement.head.translateAsHead(context), chrStatement.body.translateAsBody(context)));
+ ruleset.addRule(new CHRRule(chrStatement.location,
+ chrStatement.head.translate(context, CHRQueryTranslationMode.RULE_HEAD),
+ chrStatement.body.translate(context, CHRQueryTranslationMode.RULE_BODY)));
}
else if(statement instanceof ConstraintStatement)
ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
package org.simantics.scl.compiler.elaboration.expressions;
import org.simantics.scl.compiler.elaboration.chr.ast.CHRAstQuery;
+import org.simantics.scl.compiler.elaboration.chr.ast.CHRQueryTranslationMode;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
public class EPreCHRSelect extends ASTExpression {
@Override
public Expression resolve(TranslationContext context) {
- return new ECHRSelect(expression, query.translateAsHead(context)).resolve(context);
+ return new ECHRSelect(expression, query.translate(context, CHRQueryTranslationMode.QUERY_HEAD)).resolve(context);
}
}
@Test public void CHR10() { test(); }
@Test public void CHR11() { test(); }
@Test public void CHR12() { test(); }
+ @Test public void CHR13() { test(); }
@Test public void CHRSelect1() { test(); }
@Test public void CHRSelect2() { test(); }
@Test public void CHRSelect3() { test(); }
--- /dev/null
+module { export = [main], features = [chr] }
+import "Prelude"
+
+main = ()
+ where
+ when Foo ?x
+ then y = ?x + 1 :: Integer
+ print y
+
+ when True
+ then Foo 1
+ Foo 2
+--
+3
+2
+()
\ No newline at end of file