diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationTrace.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationTrace.java index f92a5b17..9643421e 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationTrace.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationTrace.java @@ -2,11 +2,24 @@ package jetbrains.mps.logic.reactor.evaluation; /*Generated by MPS */ +import jetbrains.mps.logic.reactor.program.Rule; import jetbrains.mps.logic.reactor.program.PredicateSymbol; import jetbrains.mps.logic.reactor.program.Symbol; public interface EvaluationTrace { + public void activate(ConstraintOccurrence occurrence); + + public void reactivate(ConstraintOccurrence occurrence); + + public void suspend(ConstraintOccurrence occurrence); + + public void discard(ConstraintOccurrence occurrence); + + public void trigger(MatchRule matchRule); + + public void exit(Rule rule); + public void askSuccess(PredicateSymbol predicateSymbol, Object... args); public void askFailure(PredicateSymbol predicateSymbol, Object... args); @@ -18,6 +31,19 @@ public interface EvaluationTrace { public void reportFailure(String message); public static final EvaluationTrace NULL = new EvaluationTrace() { + + public void activate(ConstraintOccurrence occurrence) { + } + public void reactivate(ConstraintOccurrence occurrence) { + } + public void suspend(ConstraintOccurrence occurrence) { + } + public void discard(ConstraintOccurrence occurrence) { + } + public void trigger(MatchRule matchRule) { + } + public void exit(Rule rule) { + } public void askSuccess(PredicateSymbol predicateSymbol, Object... args) { } public void askFailure(PredicateSymbol predicateSymbol, Object... args) { diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/MatchRule.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/MatchRule.java new file mode 100644 index 00000000..c848a4b0 --- /dev/null +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/MatchRule.java @@ -0,0 +1,15 @@ +package jetbrains.mps.logic.reactor.evaluation; + +/*Generated by MPS */ + +import jetbrains.mps.logic.reactor.program.Rule; + +public interface MatchRule { + + public Rule rule(); + + public Iterable matchHeadKept(); + + public Iterable matchHeadReplaced(); + +} diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/trace.info b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/trace.info index af89e1fe..a39cdcc0 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/trace.info +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/trace.info @@ -12,62 +12,116 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + - + - + - + - + - - + + @@ -161,6 +215,17 @@ + + + + + + + + + + + diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt index 175f552f..765d415d 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Handler.kt @@ -1,6 +1,7 @@ package jetbrains.mps.logic.reactor.core import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence +import jetbrains.mps.logic.reactor.evaluation.EvaluationTrace import jetbrains.mps.logic.reactor.evaluation.PredicateInvocation import jetbrains.mps.logic.reactor.evaluation.SessionSolver import jetbrains.mps.logic.reactor.logical.Logical @@ -17,19 +18,25 @@ class Handler { val sessionSolver: SessionSolver - private val rules : MutableList = ArrayList() + val trace: EvaluationTrace - private val stored : MutableList = ArrayList() + private val rules = ArrayList() - private val activeQueue : Queue = LinkedList() + private val stored = ArrayList() + + private val activeQueue = LinkedList() + + private val activationStack = LinkedList() constructor( sessionSolver: SessionSolver, programRules: Iterable, + trace: EvaluationTrace = EvaluationTrace.NULL, // for testing purposes only occurrences: Iterable? = null) { this.sessionSolver = sessionSolver + this.trace = trace this.rules.addAll(programRules) if (occurrences != null) { this.stored.addAll(occurrences) @@ -38,6 +45,18 @@ class Handler { fun occurrences(): Set = stored.toSet() + fun tell(constraint: Constraint) { + try { + queue(constraint.occurrence(this, noLogicalContext)) + } + catch (t: Throwable) { + for (pm in activationStack) { + trace.trigger(pm) + } + throw t + } + } + fun queue(occurrence: ConstraintOccurrence) { activeQueue.add(occurrence) while (activeQueue.isNotEmpty()) { @@ -48,6 +67,10 @@ class Handler { private fun process(active: ConstraintOccurrence) { if (!active.isStored()) { store(active) + trace.activate(active) + } + else { + trace.reactivate(active) } val matcher = object : Matcher(rules) { @@ -57,16 +80,27 @@ class Handler { } for (match in matcher.lookupMatches(active).filter { pm -> pm.rule.checkGuard(pm.logicalContext()) }) { - if (!active.isStored()) return + if (!active.isStored()) break if (match.occurrences().any{ co -> !co.isStored() }) continue + activationStack.push(match) + trace.trigger(match) + for ((cst, occ) in match.discarded) { discard(occ) + trace.discard(occ) } for (item in match.rule.body()) { activate(item, match.logicalContext()) } + + trace.exit(match.rule) + activationStack.pop() + } + + if (active.isStored()) { + trace.suspend(active) } } @@ -109,6 +143,10 @@ private fun AndItem.argumentValues(context: LogicalContext): List = private fun Constraint.occurrence(handler: Handler, context: LogicalContext): ConstraintOccurrence = MemConstraintOccurrence(handler, this, argumentValues(context)) +private val noLogicalContext: LogicalContext = object: LogicalContext { + override fun valueFor(logicalPattern: LogicalPattern): V? = null +} + private fun Predicate.invocation(logicalContext: LogicalContext): PredicateInvocation { return object: PredicateInvocation { diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Logical.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Logical.kt index 4442a3c4..b42a4822 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Logical.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Logical.kt @@ -77,7 +77,7 @@ class MemLogical : SolverLogical { override fun union(other: SolverLogical, reconciler: SolverLogical.ValueReconciler) { val leftRepr = this.find() - val rightRepr = (other as MemLogical).find() + val rightRepr = (other as MemLogical).find() // invariant: leftRepr.rank > rightRepr.rank if (leftRepr.rank() < rightRepr.rank()) { diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Matcher.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Matcher.kt index 90ca517b..b488cd35 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Matcher.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Matcher.kt @@ -2,6 +2,7 @@ package jetbrains.mps.logic.reactor.core import com.github.andrewoma.dexx.collection.ConsList import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence +import jetbrains.mps.logic.reactor.evaluation.MatchRule import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.logical.LogicalContext import jetbrains.mps.logic.reactor.logical.LogicalPattern @@ -50,7 +51,7 @@ abstract class Matcher(val rules: Collection) { } -class PartialMatch(val rule: Rule) { +class PartialMatch(val rule: Rule) : MatchRule { var kept = ConsList.empty>() private set @@ -110,6 +111,13 @@ class PartialMatch(val rule: Rule) { } fun logicalContext(): LogicalContext = logicalContext + + override fun rule(): Rule = rule + + override fun matchHeadKept(): Iterable = kept.map { p -> p.second } + + override fun matchHeadReplaced(): Iterable = discarded.map { p -> p.second } + } diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/MemEvaluationSession.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/MemEvaluationSession.kt index eaa29df1..bc27fb9f 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/MemEvaluationSession.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/MemEvaluationSession.kt @@ -7,6 +7,7 @@ import jetbrains.mps.logic.reactor.evaluation.EvaluationTrace import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence import jetbrains.mps.logic.reactor.evaluation.EvaluationSession import jetbrains.mps.logic.reactor.evaluation.SessionSolver +import jetbrains.mps.logic.reactor.program.Constraint import jetbrains.mps.logic.reactor.program.ConstraintSymbol import jetbrains.mps.logic.reactor.program.PredicateSymbol import jetbrains.mps.logic.reactor.program.Program @@ -48,11 +49,11 @@ class MemEvaluationSession : EvaluationSession { val sessionSolver = program.sessionSolver() sessionSolver.init(myEvaluationTrace, * predicateSymbols) - session = MemEvaluationSession(program) + session = MemEvaluationSession(program, myEvaluationTrace) ourBackend.ourSession.set(session) try { - session.launch(myParameters["main"] as ConstraintOccurrence) + session.launch(myParameters["main"] as Constraint) } finally { ourBackend.ourSession.set(null) @@ -64,15 +65,18 @@ class MemEvaluationSession : EvaluationSession { val program: Program + val trace: EvaluationTrace + lateinit var handler: Handler - private constructor(program: Program): super() { + private constructor(program: Program, trace: EvaluationTrace): super() { this.program = program + this.trace = trace } - fun launch(main: ConstraintOccurrence) { - this.handler = Handler(sessionSolver(), program.rules()) - handler.queue(main) + fun launch(main: Constraint) { + this.handler = Handler(sessionSolver(), program.rules(), trace) + handler.tell(main) // FIXME: shutdown the session properly ourBackend.ourSession.set(null) } diff --git a/reactor/Test/test/TestHandler.kt b/reactor/Test/test/TestHandler.kt index eeb96506..33ccd4c4 100644 --- a/reactor/Test/test/TestHandler.kt +++ b/reactor/Test/test/TestHandler.kt @@ -25,7 +25,7 @@ class TestHandler { init(PredicateSymbol("equals", 2), JavaPredicateSymbol.EXPRESSION0, JavaPredicateSymbol.EXPRESSION1, JavaPredicateSymbol.EXPRESSION2, JavaPredicateSymbol.EXPRESSION3) } private fun Builder.handler(vararg occurrences: ConstraintOccurrence): Handler = - Handler(sessionSolver(env.expressionSolver, env.equalsSolver), rules, listOf(* occurrences)) + Handler(sessionSolver(env.expressionSolver, env.equalsSolver), rules, occurrences = listOf(* occurrences)) private fun Handler.eq(left: Logical, right: Logical) { sessionSolver.tell(PredicateSymbol("equals", 2), left, right) diff --git a/reactor/Test/test/TestProgram.kt b/reactor/Test/test/TestProgram.kt index f45d2ea8..d965dc07 100644 --- a/reactor/Test/test/TestProgram.kt +++ b/reactor/Test/test/TestProgram.kt @@ -7,6 +7,7 @@ import jetbrains.mps.logic.reactor.program.JavaPredicateSymbol import jetbrains.mps.logic.reactor.program.PredicateSymbol import org.junit.* import org.junit.Assert.* +import program.MemConstraint import solver.eq /** @@ -30,7 +31,7 @@ class TestProgram { rules.forEach { r -> programBuilder.addRule(r) } return EvaluationSession.newSession(programBuilder.program(name, sessionSolver)). withPredicates(PredicateSymbol("equals", 2), JavaPredicateSymbol.EXPRESSION0, JavaPredicateSymbol.EXPRESSION1, JavaPredicateSymbol.EXPRESSION2, JavaPredicateSymbol.EXPRESSION3). - withParam("main", occurrence("main")).start() + withParam("main", MemConstraint(ConstraintSymbol("main", 0))).start() } @Test