diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Controller.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Controller.kt index b8c6dcec..be969d3e 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Controller.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Controller.kt @@ -16,6 +16,7 @@ package jetbrains.mps.logic.reactor.core +import jetbrains.mps.logic.reactor.evaluation.PredicateInvocation import jetbrains.mps.logic.reactor.evaluation.StoreView /** @@ -25,8 +26,14 @@ import jetbrains.mps.logic.reactor.evaluation.StoreView */ interface Controller { + fun ask(invocation: PredicateInvocation): Boolean + + fun tell(invocation: PredicateInvocation) + fun reactivate(occ: Occurrence) + fun currentFrame(): FrameObservable + /** For tests only */ fun evaluate(occ: Occurrence): StoreView diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/EvaluationSessionEx.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/EvaluationSessionEx.kt index 7acec7c7..ec909749 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/EvaluationSessionEx.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/EvaluationSessionEx.kt @@ -41,17 +41,10 @@ abstract class EvaluationSessionEx(val program: Program, @Suppress("UNCHECKED_CAST") override fun parameter(key: ParameterKey): T? = params ?.get(key) as T - override fun ask(invocation: PredicateInvocation): Boolean { - val solver = invocation.predicate().symbol().solver() - val result = solver.ask(invocation) - trace.ask(result, invocation) - return result - } + override fun ask(invocation: PredicateInvocation): Boolean = + controller().ask(invocation) - override fun tell(invocation: PredicateInvocation) { - val solver = invocation.predicate().symbol().solver() - trace.tell(invocation) - solver.tell(invocation) - } + override fun tell(invocation: PredicateInvocation) = + controller().tell(invocation) } \ No newline at end of file diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt index 7d9e7107..0b69301b 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt @@ -18,8 +18,6 @@ package jetbrains.mps.logic.reactor.core import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence -import jetbrains.mps.logic.reactor.evaluation.EvaluationSession - import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.logical.LogicalContext import jetbrains.mps.logic.reactor.logical.MetaLogical @@ -30,10 +28,10 @@ import jetbrains.mps.logic.reactor.program.Constraint * * @author Fedor Isakov */ -data class Occurrence (val constraint: Constraint, +data class Occurrence (val controller: Controller, + val constraint: Constraint, val logicalContext: LogicalContext, - val arguments: List<*>, - val currentFrame: () -> FrameObservable) : + val arguments: List<*>) : ConstraintOccurrence, LogicalObserver { @@ -45,7 +43,7 @@ data class Occurrence (val constraint: Constraint, init { for (a in arguments) { if (a is Logical<*>) { - currentFrame().addObserver(a) { this } + controller.currentFrame().addObserver(a) { this } } } } @@ -58,20 +56,20 @@ data class Occurrence (val constraint: Constraint, override fun valueUpdated(logical: Logical<*>) { if (alive) { - EvaluationSession.current(EvaluationSessionEx::class.java).controller().reactivate(this) + controller.reactivate(this) } } override fun parentUpdated(logical: Logical<*>) { if (alive) { - EvaluationSession.current(EvaluationSessionEx::class.java).controller().reactivate(this) + controller.reactivate(this) } } fun terminate() { for (a in arguments) { if (a is Logical<*>) { - currentFrame().removeObserver(a) { this } + controller.currentFrame().removeObserver(a) { this } } } alive = false @@ -81,14 +79,14 @@ data class Occurrence (val constraint: Constraint, } -fun Constraint.occurrence(arguments: List<*>, - currentFrame: () -> FrameObservable, - logicalContext: LogicalContext): Occurrence = - Occurrence(this, logicalContext, arguments, currentFrame) +fun Constraint.occurrence(controller: Controller, + arguments: List<*>, + logicalContext: LogicalContext): Occurrence = + Occurrence(controller, this, logicalContext, arguments) -fun Constraint.occurrence(arguments: List<*>, - currentFrame: () -> FrameObservable): Occurrence = - Occurrence(this, noLogicalContext, arguments, currentFrame) +fun Constraint.occurrence(controller: Controller, + arguments: List<*>): Occurrence = + Occurrence(controller, this, noLogicalContext, arguments) private val noLogicalContext: LogicalContext = object: LogicalContext { override fun variable(metaLogical: MetaLogical): Logical? = null diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt index edefb90c..c87e2080 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ControllerImpl.kt @@ -32,18 +32,13 @@ internal class ControllerImpl ( val supervisor: Supervisor, val ruleIndex: RuleIndex, val trace: EvaluationTrace = EvaluationTrace.NULL, - val profiler: Profiler? = null, - val storeView: StoreView? = null) : Controller + val profiler: Profiler? = null) : Controller { - // FIXME move to parameter - private val session: EvaluationSession = EvaluationSession.current() - - private var dispatchFront = Dispatcher(ruleIndex).front() // FIXME move to context - private val frameStack = FrameStack(storeView) + private val frameStack = FrameStack() /** For tests only */ override fun storeView(): StoreView = frameStack.current.store.view() @@ -51,7 +46,7 @@ internal class ControllerImpl ( /** For tests only */ override fun evaluate(occ: Occurrence): StoreView { // create the internal occurrence - val active = occ.constraint().occurrence(occ.arguments(), { frameStack.current }) + val active = occ.constraint().occurrence(this, occ.arguments()) val status = process(active, NORMAL()) if (status is FAILED) { throw status.failure.failureCause() @@ -66,6 +61,21 @@ internal class ControllerImpl ( return context.currentStatus() } + override fun currentFrame(): FrameObservable = frameStack.current + + override fun ask(invocation: PredicateInvocation): Boolean { + val solver = invocation.predicate().symbol().solver() + val result = solver.ask(invocation) + trace.ask(result, invocation) + return result + } + + override fun tell(invocation: PredicateInvocation) { + val solver = invocation.predicate().symbol().solver() + trace.tell(invocation) + solver.tell(invocation) + } + override fun reactivate(occ: Occurrence) { // FIXME propagate the status further up the call stack // TODO: introduce status to solver API? @@ -148,6 +158,14 @@ internal class ControllerImpl ( trace.discard(occ) } + processBody(match, context) + + trace.finish(match) + + return context.currentStatus() + } + + private fun processBody(match: RuleMatchImpl, context: Context) { val altIt = match.rule().bodyAlternation().iterator() while (altIt.hasNext()) { val body = altIt.next() @@ -216,16 +234,12 @@ internal class ControllerImpl ( break } } - - trace.finish(match) - - return context.currentStatus() } private fun activateConstraint(constraint: Constraint, context: Context) : Boolean { val args = supervisor.instantiateArguments(constraint.arguments(), context.logicalContext, context) return context.updateStatus { status -> - val active = constraint.occurrence(args, { frameStack.current }, context.logicalContext) + val active = constraint.occurrence(this, args, context.logicalContext) process(active, status) } } @@ -235,7 +249,7 @@ internal class ControllerImpl ( context.evalSafe { status -> val args = supervisor.instantiateArguments(predicate.arguments(), context.logicalContext, context) - if (session.ask(predicate.invocation(args, context.logicalContext, context))) + if (ask(predicate.invocation(args, context.logicalContext, context))) status else status.abort(DetailedFeedback("predicate not satisfied")) @@ -248,7 +262,7 @@ internal class ControllerImpl ( context.runSafe { val args = supervisor.instantiateArguments(predicate.arguments(), context.logicalContext, context) - session.tell(predicate.invocation(args, context.logicalContext, context)) + tell(predicate.invocation(args, context.logicalContext, context)) } } @@ -264,54 +278,54 @@ internal class ControllerImpl ( private fun RuleMatch.allStored() = (matchHeadKept() + matchHeadReplaced()).all { co -> (co as Occurrence).stored } -} + private class Context(inStatus: FeedbackStatus, + val logicalContext: LogicalContext) : InvocationContext + { -private class Context(inStatus: FeedbackStatus, - val logicalContext: LogicalContext) : InvocationContext -{ + private var status = inStatus + fun currentStatus(): FeedbackStatus = status - private var status = inStatus - fun currentStatus(): FeedbackStatus = status - - override fun report(feedback: EvaluationFeedback) { - when (feedback) { - is EvaluationFailure -> this.status = status.fail(feedback) - is DetailedFeedback -> this.status = status.report(feedback) - } - } - - inline fun withStatus(block: (FeedbackStatus) -> Unit) { - block.invoke(status) - } - - inline fun updateStatus(block: (FeedbackStatus) -> FeedbackStatus) : Boolean { - this.status = block.invoke(status) - return status.operational - } - - inline fun evalSafe(block: (FeedbackStatus) -> FeedbackStatus) : Boolean { - if (status.operational) { - try { - this.status = block.invoke(status) - - } catch (ex: EvaluationFailureException) { - this.status = status.fail(EvaluationFailure(ex)) - } - } - return status.operational - } - - inline fun runSafe(block: () -> Unit) : Boolean { - if (status.operational) { - try { - block() - - } catch (ex: EvaluationFailureException) { - this.status = status.fail(EvaluationFailure(ex)) + override fun report(feedback: EvaluationFeedback) { + when (feedback) { + is EvaluationFailure -> this.status = status.fail(feedback) + is DetailedFeedback -> this.status = status.report(feedback) } } - return status.operational + inline fun withStatus(block: (FeedbackStatus) -> Unit) { + block.invoke(status) + } + + inline fun updateStatus(block: (FeedbackStatus) -> FeedbackStatus) : Boolean { + this.status = block.invoke(status) + return status.operational + } + + inline fun evalSafe(block: (FeedbackStatus) -> FeedbackStatus) : Boolean { + if (status.operational) { + try { + this.status = block.invoke(status) + + } catch (ex: EvaluationFailureException) { + this.status = status.fail(EvaluationFailure(ex)) + } + } + return status.operational + } + + inline fun runSafe(block: () -> Unit) : Boolean { + if (status.operational) { + try { + block() + + } catch (ex: EvaluationFailureException) { + this.status = status.fail(EvaluationFailure(ex)) + } + } + + return status.operational + } + } } @@ -323,4 +337,4 @@ fun createController( trace: EvaluationTrace = EvaluationTrace.NULL, profiler: Profiler? = null, storeView: StoreView? = null) : Controller = - ControllerImpl(supervisor, ruleIndex, trace, profiler, storeView) + ControllerImpl(supervisor, ruleIndex, trace, profiler) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/EvaluationSessionImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/EvaluationSessionImpl.kt index 8774d032..5b01cb87 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/EvaluationSessionImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/EvaluationSessionImpl.kt @@ -43,8 +43,8 @@ internal class EvaluationSessionImpl private constructor ( override fun controller() = controller - private fun launch(main: Constraint, profiler: Profiler?, storeView: StoreView?) : FeedbackStatus { - this.controller = ControllerImpl(supervisor, RuleIndex(program().handlers()), trace, profiler, storeView) + private fun launch(main: Constraint, profiler: Profiler?) : FeedbackStatus { + this.controller = ControllerImpl(supervisor, RuleIndex(program().handlers()), trace, profiler) return controller.activate(main) } @@ -54,15 +54,12 @@ internal class EvaluationSessionImpl private constructor ( var evaluationTrace: EvaluationTrace = EvaluationTrace.NULL - var storeView: StoreView? = null - override fun withTrace(computingTracer: EvaluationTrace): EvaluationSession.Config { this.evaluationTrace = computingTracer return this } override fun withStoreView(storeView: StoreView): EvaluationSession.Config { - this.storeView = storeView return this } @@ -85,7 +82,7 @@ internal class EvaluationSessionImpl private constructor ( var failure: Feedback? = null try { val main = parameters[ParameterKey.of("main", Constraint::class.java)] as Constraint - val status = session.launch(main, profiler, storeView) + val status = session.launch(main, profiler) if (status is FAILED) { failure = status.failure } diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Frame.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Frame.kt index 5fcc67fe..34b38601 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Frame.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Frame.kt @@ -49,12 +49,6 @@ internal class Frame: LogicalObserver, FrameObservable { this.observers = prev.observers } - constructor(stack: FrameStack, storeView: StoreView) { - this.stack = stack - this.store = Store(storeView) { stack.current } - this.observers = Maps.of() - } - override fun storeObserver() = store override fun addObserver(logical: Logical<*>, obs: (FrameObservable) -> LogicalObserver) { @@ -94,14 +88,14 @@ internal class Frame: LogicalObserver, FrameObservable { } -internal class FrameStack(storeView: StoreView?) : LogicalObserver { +internal class FrameStack : LogicalObserver { var current: Frame val observing = HashSet>>() init { - this.current = if (storeView != null) Frame(this, storeView) else Frame(this) + this.current = Frame(this) } fun push(): Frame { diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Store.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Store.kt index 756e5fa6..151e8b79 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Store.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/Store.kt @@ -53,43 +53,7 @@ internal class Store : LogicalObserver { this.symbol2occurrences = copyFrom.symbol2occurrences this.logical2occurrences = copyFrom.logical2occurrences } - - - /** - * Copy constructor that accepts a view on the store. - * This can be a view on the store from previous run of the program. - */ - constructor(copyFrom: StoreView, currentFrame: () -> FrameObservable) { - this.currentFrame = currentFrame - - var log2occs = Maps.of>, IdHashSet>() - val orig2occ = IdentityHashMap() - - // process the original data and make copies as needed - for (orig in copyFrom.allOccurrences()) { - val occ = orig.constraint().occurrence(orig.arguments(), currentFrame) - orig2occ[orig] = occ - for (arg in orig.arguments()) { - when (arg) { - is Logical<*> -> { - val key = Id(arg.findRoot()) - log2occs = log2occs.put(key, - log2occs[key]?.add(occ) ?: singletonIdSet(occ)) - currentFrame().addObserver(arg) { frame -> frame.storeObserver() } - } - } - } - occ.stored = true - } - - // set internal structures - this.logical2occurrences = log2occs - this.symbol2occurrences = copyFrom.constraintSymbols().fold(Maps.of()) { pmap, csym -> - val occs = IdHashSet(copyFrom.occurrences(csym).map { occ -> orig2occ.get(occ)!! }) - pmap.put(csym, occs) - } - } - + constructor(currentFrame: () -> FrameObservable) { this.currentFrame = currentFrame this.symbol2occurrences = Maps.of() diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java index e7ed9572..5ddd5261 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java @@ -88,6 +88,10 @@ public abstract class EvaluationSession { public abstract Config withTrace(EvaluationTrace computingTracer); + /** + * @deprecated passing store view is deprecated and doesn't have an effect + */ + @Deprecated public abstract Config withStoreView(StoreView storeView); public abstract EvaluationResult start(Supervisor supervisor); diff --git a/reactor/Test/test/RulesHelper.kt b/reactor/Test/test/RulesHelper.kt index 0a5e05a2..30ea7422 100644 --- a/reactor/Test/test/RulesHelper.kt +++ b/reactor/Test/test/RulesHelper.kt @@ -1,4 +1,6 @@ import jetbrains.mps.logic.reactor.core.* +import jetbrains.mps.logic.reactor.evaluation.PredicateInvocation +import jetbrains.mps.logic.reactor.evaluation.StoreView import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.program.* import program.MockConstraint @@ -112,7 +114,7 @@ fun equals(left: Any, right: Any): ConjBuilder.() -> Unit = { } fun occurrence(id: String, vararg args: Any): Occurrence = - MockConstraint(ConstraintSymbol.symbol(id, args.size)).occurrence(listOf(* args), { fooObservable }) + MockConstraint(ConstraintSymbol.symbol(id, args.size)).occurrence(MockController(), listOf(* args)) fun sym0(id: String): ConstraintSymbol = ConstraintSymbol(id, 0) @@ -123,15 +125,38 @@ fun sym1(id: String): ConstraintSymbol = fun sym2(id: String): ConstraintSymbol = ConstraintSymbol(id, 2) -object fooObservable : FrameObservable { - override fun storeObserver(): LogicalObserver { +class MockController : Controller { + + override fun currentFrame(): FrameObservable = object : FrameObservable { + override fun storeObserver(): LogicalObserver { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun addObserver(logical: Logical<*>, obs: (FrameObservable) -> LogicalObserver) { + } + + override fun removeObserver(logical: Logical<*>, obs: (FrameObservable) -> LogicalObserver) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + } + + override fun ask(invocation: PredicateInvocation): Boolean { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - override fun addObserver(logical: Logical<*>, obs: (FrameObservable) -> LogicalObserver) { + override fun tell(invocation: PredicateInvocation) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - override fun removeObserver(logical: Logical<*>, obs: (FrameObservable) -> LogicalObserver) { + override fun reactivate(occ: Occurrence) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun evaluate(occ: Occurrence): StoreView { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun storeView(): StoreView { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } } diff --git a/reactor/Test/test/TestController.kt b/reactor/Test/test/TestController.kt index 6e0a89a1..0b2e5fad 100644 --- a/reactor/Test/test/TestController.kt +++ b/reactor/Test/test/TestController.kt @@ -60,7 +60,7 @@ class TestController { private fun Builder.controller(vararg occurrences: ConstraintOccurrence): Controller { val program = MockProgram("test", rulesLists, registry = MockConstraintRegistry()) MockSession.init(program, MockSupervisor()) - val controller = createController(MockSupervisor(), RuleIndex(program.rulesLists), storeView = MockStoreView(listOf(* occurrences))) + val controller = createController(MockSupervisor(), RuleIndex(program.rulesLists)) MockSession.ourBackend.session.controller = controller return controller } @@ -73,7 +73,7 @@ class TestController { feedbackHandler(rule, feedback) } MockSession.init(program, supervisor) - val controller = createController(supervisor, RuleIndex(program.rulesLists), storeView = MockStoreView(listOf(* occurrences))) + val controller = createController(supervisor, RuleIndex(program.rulesLists)) MockSession.ourBackend.session.controller = controller return controller } diff --git a/reactor/Test/test/TestIncrementalProgram.kt b/reactor/Test/test/TestIncrementalProgram.kt index 9d90f8ea..3ab34ecc 100644 --- a/reactor/Test/test/TestIncrementalProgram.kt +++ b/reactor/Test/test/TestIncrementalProgram.kt @@ -4,10 +4,7 @@ import jetbrains.mps.logic.reactor.evaluation.EvaluationSession import jetbrains.mps.logic.reactor.evaluation.StoreView import jetbrains.mps.logic.reactor.program.Constraint import jetbrains.mps.logic.reactor.program.ConstraintSymbol -import org.junit.AfterClass -import org.junit.Assert -import org.junit.BeforeClass -import org.junit.Test +import org.junit.* import program.MockConstraint /* @@ -65,6 +62,7 @@ class TestIncrementalProgram { } @Test + @Ignore fun replace() { programWithRules( rule("main",