From: Hannu Niemistö Date: Wed, 19 Jul 2017 10:42:20 +0000 (+0300) Subject: (refs #7371) Support for select keyword for CHR constraints X-Git-Tag: v1.31.0~264^2~48^2 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=292e64ba21f8044df19884dc3e61fe5e292a82df;p=simantics%2Fplatform.git (refs #7371) Support for select keyword for CHR constraints Change-Id: Ie23a1cd698b230f9be05ff38c937cfcbd13d658b --- diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java index 50729430d..183d85796 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java @@ -20,6 +20,7 @@ public class Names { public static final Name JavaBuiltin_unsafeCoerce = Name.create("JavaBuiltin", "unsafeCoerce"); public static final Name MList_add = Name.create("MList", "add"); public static final Name MList_create = Name.create("MList", "create"); + public static final Name MList_freeze = Name.create("MList", "freeze"); public static final Name MList_removeLast = Name.create("MList", "removeLast"); public static final TCon MList_T = Types.con("MList", "T"); public static final Name MSet_add = Name.create("MSet", "add"); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRLiteral.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRLiteral.java index f44609e6c..e7b3320d7 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRLiteral.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRLiteral.java @@ -187,8 +187,10 @@ public class CHRLiteral extends Symbol { } public void collectQueryEffects(THashSet effects) { + // TODO } public void collectEnforceEffects(THashSet effects) { + // TODO } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java index 5cb0f2aee..70559d18f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRQuery.java @@ -13,6 +13,7 @@ import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure; import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.parsing.Symbol; +import org.simantics.scl.compiler.types.Type; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.THashSet; @@ -71,7 +72,7 @@ public class CHRQuery extends Symbol { else context.add(literal, i); } - if(activeLiteralId == -1) { + if(activeLiteralId == -1 && inputFact != null) { context.addInitFact(initConstraint, inputFact); } return context.createQueryPlan(); @@ -95,4 +96,14 @@ public class CHRQuery extends Symbol { visitor.visit(this); return b.toString(); } + + public void collectQueryEffects(THashSet effects) { + for(CHRLiteral literal : literals) + literal.collectQueryEffects(effects); + } + + public void collectEnforceEffects(THashSet effects) { + for(CHRLiteral literal : literals) + literal.collectEnforceEffects(effects); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanOp.java index a79225604..aa317a2b2 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanOp.java @@ -17,6 +17,6 @@ public abstract class PlanOp { return b.toString(); } - public abstract void toString(StringBuilder b); + public void toString(StringBuilder b) {} public abstract void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java index 367960dfa..d4f21a726 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.java @@ -3,7 +3,6 @@ package org.simantics.scl.compiler.elaboration.chr.translation; import java.util.ArrayList; import java.util.Arrays; -import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; import org.simantics.scl.compiler.elaboration.chr.CHRQuery; import org.simantics.scl.compiler.elaboration.chr.CHRRule; @@ -131,22 +130,20 @@ public class CHRTranslation { } } - public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) { - ArrayList head = new ArrayList(statement.head.length); - for(ListQualifier qualifier : statement.head) { - CHRLiteral literal = convertListQualifier(context, true, qualifier); - if(literal != null) - head.add(literal); - } - ArrayList body = new ArrayList(statement.body.length); - for(ListQualifier qualifier : statement.body) { - CHRLiteral literal = convertListQualifier(context, false, qualifier); + public static CHRQuery convertCHRQuery(TranslationContext context, boolean isHead, ListQualifier[] lqs) { + ArrayList query = new ArrayList(lqs.length); + for(ListQualifier qualifier : lqs) { + CHRLiteral literal = convertListQualifier(context, isHead, qualifier); if(literal != null) - body.add(literal); + query.add(literal); } + return new CHRQuery(query.toArray(new CHRLiteral[query.size()])); + } + + public static CHRRule convertCHRStatement(TranslationContext context, CHRStatement statement) { return new CHRRule(statement.location, - new CHRQuery(head.toArray(new CHRLiteral[head.size()])), - new CHRQuery(body.toArray(new CHRLiteral[body.size()])), + convertCHRQuery(context, true, statement.head), + convertCHRQuery(context, false, statement.body), null); } 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 ac9299d77..b533e922d 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 @@ -75,6 +75,8 @@ public class TranslationContext extends TypeTranslationContext implements Enviro TIntArrayList chrConstraintFrames = new TIntArrayList(); ArrayList chrConstraintEntries = new ArrayList(); + public CHRRuleset currentRuleset; + static class Entry { String name; Variable variable; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ASTExpression.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ASTExpression.java index fbc0a7901..02db9bdec 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ASTExpression.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ASTExpression.java @@ -3,6 +3,7 @@ package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; +import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.exceptions.MatchException; @@ -23,7 +24,6 @@ public abstract class ASTExpression extends SimplifiableExpression { @Override final public void collectFreeVariables(THashSet vars) { throw new InternalCompilerError(getClass().getSimpleName() + " does not support collectFreeVariables."); - } @Override @@ -58,6 +58,11 @@ public abstract class ASTExpression extends SimplifiableExpression { throw new InternalCompilerError(getClass().getSimpleName() + " does not support accept."); } + @Override + public Expression accept(ExpressionTransformer transformer) { + throw new InternalCompilerError(getClass().getSimpleName() + " does not support accept."); + } + @Override public Expression checkBasicType(TypingContext context, Type requiredType) { throw new InternalCompilerError("Class " + @@ -75,4 +80,10 @@ public abstract class ASTExpression extends SimplifiableExpression { throw new InternalCompilerError("Class " + getClass().getSimpleName() + " does not implement method forVariables."); } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) + location = loc; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRuleset.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRuleset.java index 9a8aa78b9..65ce2e2df 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRuleset.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRuleset.java @@ -58,12 +58,21 @@ public class ECHRRuleset extends Expression { } @Override public Expression resolve(TranslationContext context) { + if(context.currentRuleset != null) { + context.getErrorLog().log(location, "Current version of SCL compiler does not support nested rulesets."); + return this; + } + context.currentRuleset = ruleset; + context.pushFrame(); context.pushCHRConstraintFrame(); ruleset.resolve(context); in = in.resolve(context); context.popCHRConstraintFrame(ruleset.constraints); context.popFrame(); + + context.currentRuleset = null; + return this; } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRSelect.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRSelect.java new file mode 100644 index 000000000..47c007d7f --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRSelect.java @@ -0,0 +1,152 @@ +package org.simantics.scl.compiler.elaboration.expressions; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.constants.NoRepConstant; +import org.simantics.scl.compiler.elaboration.chr.CHRQuery; +import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanContext; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanRealizer; +import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext; +import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.contexts.TypingContext; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; +import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; +import org.simantics.scl.compiler.types.exceptions.MatchException; +import org.simantics.scl.compiler.types.kinds.Kinds; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class ECHRSelect extends Expression { + CHRQuery query; + Variable[] existentialVariables; + Expression expression; + private ArrayList planOps; + private CHRRuleset currentRuleset; + + public ECHRSelect(Expression expression, CHRQuery query) { + this.expression = expression; + this.query = query; + } + + @Override + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + query.collectRefs(allRefs, refs); + expression.collectRefs(allRefs, refs); + } + + @Override + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + query.collectVars(allVars, vars); + expression.collectVars(allVars, vars); + } + + @Override + public void forVariables(VariableProcedure procedure) { + query.forVariables(procedure); + expression.forVariables(procedure); + } + + @Override + protected void updateType() throws MatchException { + setType(Types.list(expression.getType())); + } + + @Override + public Expression inferType(TypingContext context) { + for(Variable variable : existentialVariables) + variable.setType(Types.metaVar(Kinds.STAR)); + query.checkType(context); + expression = expression.inferType(context); + return this; + } + + @Override + public Expression simplify(SimplificationContext simplificationContext) { + this.expression = expression.simplify(simplificationContext); + query.simplify(simplificationContext); + + CompilationContext compilationContext = simplificationContext.getCompilationContext(); + QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables); + if(query.createQueryPlan(context, null, -1, null)) + planOps = context.getPlanOps(); + + return this; + } + + @Override + public IVal toVal(CompilationContext context, CodeWriter w) { + IVal list = w.apply(location, context.getValue(Names.MList_create).getValue(), NoRepConstant.UNIT); + planOps.add(new PlanOp(location) { + @Override + public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) { + w.apply(location, context.getValue(Names.MList_add).getValue(), list, expression.toVal(context, w)); + } + }); + PlanRealizer realizer = new PlanRealizer(context, currentRuleset, currentRuleset != null ? currentRuleset.runtimeRulesetVariable : null, null, planOps); + realizer.nextOp(w); + return w.apply(location, context.getValue(Names.MList_freeze).getValue(), list); + } + + @Override + public void collectFreeVariables(THashSet vars) { + query.collectFreeVariables(vars); + expression.collectFreeVariables(vars); + if(existentialVariables != null) + for(Variable variable : existentialVariables) + vars.remove(variable); + } + + @Override + public Expression resolve(TranslationContext context) { + currentRuleset = context.currentRuleset; + + context.pushExistentialFrame(); + query.resolve(context); + context.disallowNewExistentials(); + expression = expression.resolve(context); + existentialVariables = context.popExistentialFrame(); + return this; + } + + @Override + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + query.setLocationDeep(loc); + expression.setLocationDeep(loc); + } + } + + @Override + public Expression decorate(ExpressionDecorator decorator) { + this.expression = decorator.decorate(expression); + return this; + } + + @Override + public void collectEffects(THashSet effects) { + expression.collectEffects(effects); + query.collectQueryEffects(effects); + effects.add(Types.PROC); + } + + @Override + public void accept(ExpressionVisitor visitor) { + visitor.visit(this); + } + + @Override + public Expression accept(ExpressionTransformer transformer) { + return transformer.transform(this); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java index 2b9e8e2c0..a90c6186d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java @@ -25,6 +25,9 @@ import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.THashSet; import gnu.trove.set.hash.TIntHashSet; +/** + * Generated maily from EPreLet + */ public class ELet extends Expression { public Assignment[] assignments; public Expression in; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRSelect.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRSelect.java new file mode 100644 index 000000000..80943f7d8 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRSelect.java @@ -0,0 +1,22 @@ +package org.simantics.scl.compiler.elaboration.expressions; + +import org.simantics.scl.compiler.elaboration.chr.translation.CHRTranslation; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier; + +public class EPreCHRSelect extends ASTExpression { + ListQualifier[] query; + Expression expression; + + public EPreCHRSelect(ListQualifier[] query, Expression expression) { + this.query = query; + this.expression = expression; + } + + @Override + public Expression resolve(TranslationContext context) { + return new ECHRSelect(expression, CHRTranslation.convertCHRQuery(context, true, query)).resolve(context); + } + + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java index 035a2cadc..c7624039e 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreLet.java @@ -13,6 +13,9 @@ import org.simantics.scl.compiler.errors.Locations; import gnu.trove.map.hash.THashMap; import gnu.trove.procedure.TObjectObjectProcedure; +/** + * Generated mainly from EBlock + */ public class EPreLet extends ASTExpression { List assignments; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java index 2b75f61cd..02590273d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java @@ -252,6 +252,9 @@ public abstract class Expression extends Symbol implements Typed { return expression; } + /** + * Used during simplification and in toIExpression + */ public THashSet getFreeVariables() { THashSet result = new THashSet(); collectFreeVariables(result); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java index 4cf513c54..c0c329ba3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java @@ -9,6 +9,7 @@ public interface ExpressionTransformer { Expression transform(EBinary expression); Expression transform(EBind expression); Expression transform(EBlock expression); + Expression transform(ECHRSelect expression); Expression transform(ECHRRuleset expression); Expression transform(ECHRRulesetConstructor expression); Expression transform(EConstant expression); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java index ad32098ba..861cf48a7 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java @@ -8,6 +8,7 @@ public interface ExpressionVisitor { void visit(EBinary expression); void visit(EBind expression); void visit(EBlock expression); + void visit(ECHRSelect expression); void visit(ECHRRuleset expression); void visit(ECHRRulesetConstructor expression); void visit(EConstant expression); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java index 1bd0d22c4..97d409f15 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java @@ -1,6 +1,7 @@ package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.elaboration.chr.CHRLiteral; +import org.simantics.scl.compiler.elaboration.chr.CHRQuery; import org.simantics.scl.compiler.elaboration.chr.CHRRule; import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; import org.simantics.scl.compiler.elaboration.equation.EqBasic; @@ -125,14 +126,16 @@ EquationVisitor { statement.value = statement.value.accept(this); } + public void transform(CHRQuery query) { + for(CHRLiteral lit : query.literals) + for(int i=0;i allRefs, TIntHashSet refs); public abstract void collectVars(TObjectIntHashMap allVars, TIntHashSet vars); public abstract void collectFreeVariables(THashSet vars); + /** + * Called in simplification. + */ public abstract CompiledQualifier compile(SimplificationContext context); public abstract void resolve(TranslationContext context); public abstract void decorate(ExpressionDecorator decorator); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java index 3f6da74cb..edf951711 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java @@ -16,6 +16,7 @@ import org.simantics.scl.compiler.elaboration.expressions.EBind; import org.simantics.scl.compiler.elaboration.expressions.EBlock; import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset; import org.simantics.scl.compiler.elaboration.expressions.ECHRRulesetConstructor; +import org.simantics.scl.compiler.elaboration.expressions.ECHRSelect; import org.simantics.scl.compiler.elaboration.expressions.EConstant; import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint; import org.simantics.scl.compiler.elaboration.expressions.EEnforce; @@ -329,7 +330,12 @@ public class ExpressionToStringVisitor implements ExpressionVisitor, QueryVisito public void visit(ESelect expression) { b.append("ESelect"); } - + + @Override + public void visit(ECHRSelect expression) { + b.append("ECHRSelect"); + } + @Override public void visit(ESimpleLambda expression) { b.append('\\'); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar index f7ea1b263..ea3df9722 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar @@ -138,7 +138,7 @@ lexp shift ESCAPED_SYMBOL, shift CHAR, shift LBRACE, shift WHEN, shift ATTACHED_HASH, shift SELECT, shift SELECT_FIRST, shift SELECT_DISTINCT, - shift TRANSFORMATION, shift EQ + shift TRANSFORMATION, shift EQ, shift CHR_SELECT ; faexp @@ -161,6 +161,8 @@ aexp | (DO | MDO) statements # Do | (SELECT | SELECT_FIRST | SELECT_DISTINCT) exp WHERE queryBlock # Select + | CHR_SELECT + exp WHERE verboseChrQuery # CHRSelect | ENFORCE queryBlock # Enforce //| WHEN queryBlock SEMICOLON exp # When | var # Var diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex index 0f45c2511..1277ffe7b 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex @@ -100,7 +100,7 @@ char_literal = "'" ([^'\\\ufffd] | "\\" [^\ufffd]) "'" transformation { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.TRANSFORMATION); } select{whitespace}first { return sym(SCLTerminals.SELECT_FIRST); } select{whitespace}distinct { return sym(SCLTerminals.SELECT_DISTINCT); } - select { return sym(SCLTerminals.SELECT); } + select { return sym(supportCHR() ? SCLTerminals.CHR_SELECT : SCLTerminals.SELECT); } enforce { return sym(SCLTerminals.ENFORCE); } do { return sym(SCLTerminals.DO); } eq { return sym(options.supportEq ? SCLTerminals.EQ : SCLTerminals.ID); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.java index 5944d12e1..e3efc28dd 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.java @@ -1276,7 +1276,7 @@ public class SCLLexer { } case 175: break; case 81: - { return sym(SCLTerminals.SELECT); + { return sym(supportCHR() ? SCLTerminals.CHR_SELECT : SCLTerminals.SELECT); } case 176: break; case 82: diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat index 378013be5..e0aca1bb3 100644 Binary files a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat and b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat differ diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java index fc2242dce..612b118ad 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java @@ -13,18 +13,18 @@ public abstract class SCLParser { public static final boolean TRACE = false; private static final int INITIAL_CAPACITY = 16; - private static final int STATE_COUNT = 358; - private static final int TERMINAL_COUNT = 84; - private static final int NONTERMINAL_COUNT = 52; + private static final int STATE_COUNT = 357; + private static final int TERMINAL_COUNT = 85; + private static final int NONTERMINAL_COUNT = 51; private static final int PRODUCT_COUNT = 135; private static final int[] ACTION_ROW_ID = new int[STATE_COUNT]; private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT]; - private static final short[] ACTION_TABLE = new short[6944]; - private static final int[] ERROR_TABLE = new int[940]; + private static final short[] ACTION_TABLE = new short[6765]; + private static final int[] ERROR_TABLE = new int[949]; private static final int[] GOTO_ROW_ID = new int[STATE_COUNT]; private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT]; - private static final short[] GOTO_TABLE = new short[1708]; + private static final short[] GOTO_TABLE = new short[1647]; private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT]; private static final short STATE_MASK = (short)0x0fff; @@ -99,6 +99,7 @@ public abstract class SCLParser { "SELECT_DISTINCT", "TRANSFORMATION", "EQ", + "CHR_SELECT", "ATTACHED_DOT", "IN", "THEN", @@ -156,12 +157,11 @@ public abstract class SCLParser { "accessor", "case", "queryBlock", + "verboseChrQuery", "stringLiteral", "symbolWithoutMinus", "listQualifier", "chrQuery", - "verboseChrQuery", - "constraintSpec", "caseRhs", "guardedExpArrow", "equation", @@ -395,19 +395,19 @@ public abstract class SCLParser { return parse(0); } public Object parseCommands() { - return parse(342); + return parse(341); } public Object parseImport() { - return parse(350); + return parse(349); } public Object parseType() { - return parse(352); + return parse(351); } public Object parseExp() { - return parse(354); + return parse(353); } public Object parseEquationBlock() { - return parse(356); + return parse(355); } @@ -535,123 +535,123 @@ public abstract class SCLParser { case 59: return reduceSelect(); case 60: - return reduceEnforce(); + return reduceCHRSelect(); case 61: - return reduceVar(); + return reduceEnforce(); case 62: - return reduceHashedId(); + return reduceVar(); case 63: - return reduceBlank(); + return reduceHashedId(); case 64: - return reduceInteger(); + return reduceBlank(); case 65: - return reduceFloat(); + return reduceInteger(); case 66: - return reduceString(); + return reduceFloat(); case 67: - return reduceChar(); + return reduceString(); case 68: - return reduceTuple(); + return reduceChar(); case 69: - return reduceViewPattern(); + return reduceTuple(); case 70: - return reduceRightSection(); + return reduceViewPattern(); case 71: - return reduceLeftSection(); + return reduceRightSection(); case 72: - return reduceListLiteral(); + return reduceLeftSection(); case 73: - return reduceRange(); + return reduceListLiteral(); case 74: - return reduceListComprehension(); + return reduceRange(); case 75: - return reduceAs(); + return reduceListComprehension(); case 76: - return reduceRecord(); + return reduceAs(); case 77: - return reduceTransformation(); + return reduceRecord(); case 78: - return reduceEq(); + return reduceTransformation(); case 79: - return reduceRuleDeclarations(); + return reduceEq(); case 80: - return reduceStatements(); + return reduceRuleDeclarations(); case 81: - return reduceImportShowing(); + return reduceStatements(); case 82: - return reduceImportHiding(); + return reduceImportShowing(); case 83: - return reduceImportValueItem(); + return reduceImportHiding(); case 84: - return reduceFieldDescription(); + return reduceImportValueItem(); case 85: - return reduceGuardedExpEq(); + return reduceFieldDescription(); case 86: - return reduceFundep(); + return reduceGuardedExpEq(); case 87: - return reduceQueryRuleDeclaration(); + return reduceFundep(); case 88: - return reduceAnnotation(); + return reduceQueryRuleDeclaration(); case 89: - return reduceGuardQuery(); + return reduceAnnotation(); case 90: - return reduceEqualsQuery(); + return reduceGuardQuery(); case 91: - return reduceBindQuery(); + return reduceEqualsQuery(); case 92: - return reduceCompositeQuery(); + return reduceBindQuery(); case 93: - return reduceApply(); + return reduceCompositeQuery(); case 94: - return reduceSymbol(); + return reduceApply(); case 95: - return reduceEscapedId(); + return reduceSymbol(); case 96: - return reduceMinus(); + return reduceEscapedId(); case 97: - return reduceLess(); + return reduceMinus(); case 98: - return reduceGreater(); + return reduceLess(); case 99: - return reduceDot(); + return reduceGreater(); case 100: - return reduceFieldAccess(); + return reduceDot(); case 101: - return reduceIdAccessor(); + return reduceFieldAccess(); case 102: - return reduceStringAccessor(); + return reduceIdAccessor(); case 103: - return reduceExpAccessor(); + return reduceStringAccessor(); case 104: - return reduceCase(); + return reduceExpAccessor(); case 105: - return reduceQueryBlock(); + return reduceCase(); case 106: - return reduceStringLiteral(); + return reduceQueryBlock(); case 107: - return reduceSymbol(); + return reduceVerboseCHRQuery(); case 108: - return reduceEscapedId(); + return reduceStringLiteral(); case 109: - return reduceLess(); + return reduceSymbol(); case 110: - return reduceGreater(); + return reduceEscapedId(); case 111: - return reduceDot(); + return reduceLess(); case 112: - return reduceGuardQualifier(); + return reduceGreater(); case 113: - return reduceLetQualifier(); + return reduceDot(); case 114: - return reduceBindQualifier(); + return reduceGuardQualifier(); case 115: - return reduceThenQualifier(); + return reduceLetQualifier(); case 116: - return reduceCHRQuery(); + return reduceBindQualifier(); case 117: - return reduceVerboseCHRQuery(); + return reduceThenQualifier(); case 118: - return reduceConstraintSpec(); + return reduceCHRQuery(); case 119: return reduceSimpleCaseRhs(); case 120: @@ -824,7 +824,7 @@ public abstract class SCLParser { */ protected abstract Object reduceVerboseCHRStatement(); /** - * statement ::= CONSTRAINT constructor (WHERE constraintSpec)? + * statement ::= CONSTRAINT constructor */ protected abstract Object reduceConstraintStatement(); /** @@ -931,6 +931,10 @@ public abstract class SCLParser { * aexp ::= (SELECT | SELECT_FIRST | SELECT_DISTINCT) exp WHERE queryBlock */ protected abstract Object reduceSelect(); + /** + * aexp ::= CHR_SELECT exp WHERE verboseChrQuery + */ + protected abstract Object reduceCHRSelect(); /** * aexp ::= ENFORCE queryBlock */ @@ -1111,6 +1115,10 @@ public abstract class SCLParser { * queryBlock ::= LBRACE (query (SEMICOLON (query SEMICOLON)* query)?)? RBRACE */ protected abstract Object reduceQueryBlock(); + /** + * verboseChrQuery ::= LBRACE listQualifier (SEMICOLON listQualifier)* RBRACE + */ + protected abstract Object reduceVerboseCHRQuery(); /** * stringLiteral ::= BEGIN_STRING (SUSPEND_STRING exp CONTINUE_STRING)* END_STRING */ @@ -1135,14 +1143,6 @@ public abstract class SCLParser { * chrQuery ::= (listQualifier COMMA)* listQualifier */ protected abstract Object reduceCHRQuery(); - /** - * verboseChrQuery ::= LBRACE listQualifier (SEMICOLON listQualifier)* RBRACE - */ - protected abstract Object reduceVerboseCHRQuery(); - /** - * constraintSpec ::= LBRACE exp (SEMICOLON exp)* RBRACE - */ - protected abstract Object reduceConstraintSpec(); /** * caseRhs ::= ARROW exp (WHERE statements)? */ diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java index 34f8d6a9f..dd614f964 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java @@ -31,6 +31,7 @@ import org.simantics.scl.compiler.elaboration.expressions.EListComprehension; import org.simantics.scl.compiler.elaboration.expressions.EListLiteral; import org.simantics.scl.compiler.elaboration.expressions.ELiteral; import org.simantics.scl.compiler.elaboration.expressions.EMatch; +import org.simantics.scl.compiler.elaboration.expressions.EPreCHRSelect; import org.simantics.scl.compiler.elaboration.expressions.ERange; import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral; import org.simantics.scl.compiler.elaboration.expressions.ERecord; @@ -1305,12 +1306,17 @@ public class SCLParserImpl extends SCLParser { return new IncludeStatement(name, value); } - @Override + /*@Override protected Object reduceConstraintSpec() { Expression[] expressions = new Expression[length()/2-1]; for(int i=0;i Foo 1 + True => Foo 2 + + True => Bar 3 + True => Bar 4 +-- +[(2,4), (2,3), (1,4), (1,3)] \ No newline at end of file diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHRSelect3.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHRSelect3.scl new file mode 100644 index 000000000..2be9b98c5 --- /dev/null +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHRSelect3.scl @@ -0,0 +1,21 @@ +module { + features = [chr] +} +import "StandardLibrary" + +main = () + where + constraint Edge Integer Integer + + True => Edge 2 3 + True => Edge 1 2 + True => Edge 3 4 + + when -Edge ?x ?y + [] = select ?z where + Edge ?z ?x + then print "removed \(?x) \(?y)" +-- +removed 1 2 +removed 2 3 +() \ No newline at end of file diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidLambda.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidLambda.scl index 95d8b03da..3cf6ed74b 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidLambda.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/InvalidLambda.scl @@ -1,4 +1,4 @@ main = \ /* no parameters */ -> 3 -- -2:30-2:32: Unexpected token '->' (ARROW). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LAMBDA_MATCH, LBRACKET, LET, LPAREN, MATCH, MDO, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION. \ No newline at end of file +2:30-2:32: Unexpected token '->' (ARROW). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, CHR_SELECT, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LAMBDA_MATCH, LBRACKET, LET, LPAREN, MATCH, MDO, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION. \ No newline at end of file diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnexpectedToken.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnexpectedToken.scl index 85637b16b..45f6b0853 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnexpectedToken.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/UnexpectedToken.scl @@ -1,4 +1,4 @@ a = = b = 4 -- -1:5-1:6: Unexpected token '=' (EQUALS). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LAMBDA_MATCH, LBRACKET, LET, LPAREN, MATCH, MDO, MINUS, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION. \ No newline at end of file +1:5-1:6: Unexpected token '=' (EQUALS). Expected one of ATTACHED_HASH, BEGIN_STRING, BLANK, CHAR, CHR_SELECT, DO, ENFORCE, EQ, ESCAPED_SYMBOL, FLOAT, ID, IF, INTEGER, LAMBDA, LAMBDA_MATCH, LBRACKET, LET, LPAREN, MATCH, MDO, MINUS, SELECT, SELECT_DISTINCT, SELECT_FIRST, TRANSFORMATION. \ No newline at end of file