From c68d9a0bd7aecb58a264a83c89a117328a751652 Mon Sep 17 00:00:00 2001 From: Fedor Isakov Date: Thu, 5 Jan 2017 17:16:21 +0100 Subject: [PATCH] Refactoring the reactor API. Extract StoreView. Get rid of obsolete calls to SessionSolver, cleanup the interface. Introduce AbstractSolver. Move instantiation arguments to solver/program. Cleaning up the code. --- .../reactor/evaluation/AbstractSolver.java | 43 +++++ .../reactor/evaluation/EvaluationSession.java | 4 - .../reactor/evaluation/Instructible.java | 3 +- .../logic/reactor/evaluation/Queryable.java | 3 +- .../reactor/evaluation/SessionSolver.java | 158 ++++++++---------- .../mps/logic/reactor/evaluation/Solver.java | 8 - .../logic/reactor/logical/LogicalContext.java | 5 +- .../mps/logic/reactor/program/AndItem.java | 4 +- .../mps/logic/reactor/program/Constraint.java | 2 - .../mps/logic/reactor/program/Predicate.java | 5 +- .../reactor/program/PredicateFactory.java | 10 -- .../mps/logic/reactor/program/Program.java | 4 + .../mps/logic/reactor/program/Solver.java | 9 + .../mps/logic/reactor/core/Controller.kt | 42 ++--- .../reactor/core/MemEvaluationSession.kt | 6 +- .../mps/logic/reactor/core/Occurrence.kt | 63 +++++++ .../jetbrains/mps/logic/reactor/core/Store.kt | 50 ------ reactor/Test/src/program/MockConstraint.kt | 5 - reactor/Test/src/program/MockProgram.kt | 20 ++- reactor/Test/src/solver/EqualsSolver.kt | 30 ++-- reactor/Test/src/solver/MockSessionSolver.kt | 11 +- reactor/Test/test/JavaExpressionHelper.kt | 16 +- reactor/Test/test/TestController.kt | 24 +-- reactor/Test/test/TestProgram.kt | 2 +- reactor/Test/test/TestProgramBuilder.kt | 10 +- 25 files changed, 276 insertions(+), 261 deletions(-) create mode 100644 reactor/API/src/jetbrains/mps/logic/reactor/evaluation/AbstractSolver.java delete mode 100644 reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Solver.java delete mode 100644 reactor/API/src/jetbrains/mps/logic/reactor/program/PredicateFactory.java create mode 100644 reactor/API/src/jetbrains/mps/logic/reactor/program/Solver.java create mode 100644 reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/AbstractSolver.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/AbstractSolver.java new file mode 100644 index 00000000..6126e275 --- /dev/null +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/AbstractSolver.java @@ -0,0 +1,43 @@ +package jetbrains.mps.logic.reactor.evaluation; + +import jetbrains.mps.logic.reactor.logical.LogicalContext; +import jetbrains.mps.logic.reactor.program.AndItem; +import jetbrains.mps.logic.reactor.program.Predicate; + +import java.util.Collections; +import java.util.List; + +/** + * @author Fedor Isakov + */ +public abstract class AbstractSolver implements Instructible, Queryable { + + protected abstract List invocationArguments(Predicate predicate, LogicalContext logicalContext); + + protected PredicateInvocation invocation(Predicate predicate, LogicalContext logicalContext) { + return new Invocation(predicate, invocationArguments(predicate, logicalContext)); + } + + protected static class Invocation implements PredicateInvocation { + + public Invocation(Predicate predicate, List invocationArguments) { + this.predicate = predicate; + this.invocationArguments = Collections.unmodifiableList(invocationArguments); + } + + @Override + public Predicate predicate() { + return predicate; + } + + @Override + public List arguments() { + return invocationArguments; + } + + private final Predicate predicate; + + private final List invocationArguments; + } + +} diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java index da4d230f..0988fd22 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/EvaluationSession.java @@ -39,10 +39,6 @@ public abstract class EvaluationSession { public abstract SessionSolver sessionSolver(); - public abstract Instructible sessionInstructible(); - - public abstract Queryable sessionQueryable(); - public abstract StoreView storeView(); protected static void setBackend(EvaluationSession.Backend backend) { diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Instructible.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Instructible.java index 0feafd56..4d8ac65d 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Instructible.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Instructible.java @@ -2,9 +2,8 @@ package jetbrains.mps.logic.reactor.evaluation; /*Generated by MPS */ - public interface Instructible { - void tell(PredicateInvocation invocation); + void tell(PredicateInvocation invocation); } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Queryable.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Queryable.java index ee387efc..f5112b9d 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Queryable.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Queryable.java @@ -2,9 +2,8 @@ package jetbrains.mps.logic.reactor.evaluation; /*Generated by MPS */ - public interface Queryable extends Instructible { - boolean ask(PredicateInvocation invocation); + boolean ask(PredicateInvocation invocation); } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/SessionSolver.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/SessionSolver.java index d1e676b3..e366121d 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/SessionSolver.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/SessionSolver.java @@ -2,109 +2,87 @@ package jetbrains.mps.logic.reactor.evaluation; /*Generated by MPS */ -import jetbrains.mps.logic.reactor.program.PredicateSymbol; -import jetbrains.mps.logic.reactor.program.Predicate; -import java.util.Arrays; -import jetbrains.mps.logic.reactor.program.Symbol; +import jetbrains.mps.logic.reactor.logical.LogicalContext; +import jetbrains.mps.logic.reactor.program.*; + import java.util.Map; -import java.util.List; import java.util.HashMap; /** * Is used to provide an interface for handlers and solvers working together in a single session. */ -public abstract class SessionSolver implements Instructible, Queryable { +public abstract class SessionSolver implements Queryable, Instructible { - public void init(PredicateSymbol... predicateSymbols) { - registerSymbols(predicateSymbols); - } - - public void init(EvaluationTrace evaluationTrace, PredicateSymbol... predicateSymbols) { - tracer = evaluationTrace; - init(predicateSymbols); - } - - @Override - public boolean ask(PredicateInvocation invocation) { - boolean result = solver(invocation.predicate().symbol()).ask(invocation); - tracer.ask(result, invocation); - return result; - } - - /** - * To be used internally. For testing pupposes. - */ - public boolean ask(PredicateSymbol predicateSymbol, Object... args) { - Solver solver = solver(predicateSymbol); - Predicate predicate = solver.predicate(predicateSymbol, args); - SessionSolver.Invocation invocation = new SessionSolver.Invocation(predicate, Arrays.asList(args)); - - return solver(predicateSymbol).ask(invocation); - } - - @Override - public void tell(PredicateInvocation invocation) { - tracer.tell(invocation); - handler(invocation.predicate().symbol()).tell(invocation); - } - - /** - * To be used internally. For testing pupposes. - */ - public void tell(Symbol symbol, Object... args) { - Solver solver = solver((PredicateSymbol) symbol); - Predicate predicate = solver.predicate((PredicateSymbol) symbol, args); - SessionSolver.Invocation invocation = new SessionSolver.Invocation(predicate, Arrays.asList(args)); - - solver.tell(invocation); - } - - @Deprecated - public abstract Class solverClass(PredicateSymbol predicateSymbol); - - protected abstract void registerSymbol(PredicateSymbol predicateSymbol, EvaluationTrace computingTracer); - - protected void registerSolver(PredicateSymbol constraint, Solver solver) { - solvers.put(constraint, solver); - } - - private Instructible handler(Symbol symbol) { - return solver((PredicateSymbol) symbol); - } - - private void registerSymbols(PredicateSymbol... predicateSymbols) { - for (PredicateSymbol symbol : predicateSymbols) { - registerSymbol(symbol, tracer); - } - } - - private Solver solver(PredicateSymbol predicateSymbol) { - if (!(solvers.containsKey(predicateSymbol))) { - throw new IllegalStateException("no handler: " + predicateSymbol); - } - return solvers.get(predicateSymbol); - } - - private static class Invocation implements PredicateInvocation { - - public Invocation(Predicate predicate, List args) { - this.predicate = predicate; - this.args = args; + public void init(PredicateSymbol... predicateSymbols) { + registerSymbols(predicateSymbols); } - public Predicate predicate() { - return predicate; + public void init(EvaluationTrace evaluationTrace, PredicateSymbol... predicateSymbols) { + tracer = evaluationTrace; + init(predicateSymbols); } - public List arguments() { - return args; + @Override + public boolean ask(PredicateInvocation invocation) { + AbstractSolver solver = solver(invocation.predicate().symbol()); + boolean result = solver.ask(invocation); + tracer.ask(result, invocation); + return result; } - private Predicate predicate; - private List args; - } + @Override + public void tell(PredicateInvocation invocation) { + AbstractSolver handler = handler(invocation.predicate().symbol()); + tracer.tell(invocation); + handler.tell(invocation); + } - private Map solvers = new HashMap(); - private EvaluationTrace tracer = EvaluationTrace.NULL; + public boolean ask(Predicate predicate, LogicalContext logicalContext) { + AbstractSolver solver = solver(predicate.symbol()); + PredicateInvocation invocation = solver.invocation(predicate, logicalContext); + boolean result = solver.ask(invocation); + tracer.ask(result, invocation); + return result; + } + + public void tell(AndItem item, LogicalContext logicalContext) { + if (item instanceof Predicate) { + AbstractSolver handler = handler(item.symbol()); + PredicateInvocation invocation = handler.invocation((Predicate) item, logicalContext); + tracer.tell(invocation); + handler.tell(invocation); + + } + else { + throw new UnsupportedOperationException("not implemented"); + } + } + + protected abstract void registerSymbol(PredicateSymbol predicateSymbol, EvaluationTrace computingTracer); + + protected void registerSolver(PredicateSymbol constraint, AbstractSolver solver) { + solvers.put(constraint, solver); + } + + private AbstractSolver solver(PredicateSymbol predicateSymbol) { + if (!(solvers.containsKey(predicateSymbol))) { + throw new IllegalStateException("no handler: " + predicateSymbol); + } + return solvers.get(predicateSymbol); + } + + private AbstractSolver handler(Symbol symbol) { + return solver((PredicateSymbol) symbol); + } + + private void registerSymbols(PredicateSymbol... predicateSymbols) { + for (PredicateSymbol symbol : predicateSymbols) { + registerSymbol(symbol, tracer); + } + } + + private Map solvers = new HashMap(); + + private EvaluationTrace tracer = EvaluationTrace.NULL; } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Solver.java b/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Solver.java deleted file mode 100644 index 8acd45ca..00000000 --- a/reactor/API/src/jetbrains/mps/logic/reactor/evaluation/Solver.java +++ /dev/null @@ -1,8 +0,0 @@ -package jetbrains.mps.logic.reactor.evaluation; - -/*Generated by MPS */ - -import jetbrains.mps.logic.reactor.program.PredicateFactory; - -public interface Solver extends Queryable, PredicateFactory { -} diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/logical/LogicalContext.java b/reactor/API/src/jetbrains/mps/logic/reactor/logical/LogicalContext.java index 90298fa0..547f7446 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/logical/LogicalContext.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/logical/LogicalContext.java @@ -2,9 +2,12 @@ package jetbrains.mps.logic.reactor.logical; /*Generated by MPS */ - +/** + * Substitution of logicals for meta-logicals. + */ public interface LogicalContext { + Logical variable(MetaLogical metaLogical); } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/program/AndItem.java b/reactor/API/src/jetbrains/mps/logic/reactor/program/AndItem.java index 8f16f05c..5e414398 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/program/AndItem.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/program/AndItem.java @@ -2,12 +2,12 @@ package jetbrains.mps.logic.reactor.program; /*Generated by MPS */ -import java.util.Collection; +import java.util.List; public interface AndItem { Symbol symbol(); - Collection arguments(); + List arguments(); } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/program/Constraint.java b/reactor/API/src/jetbrains/mps/logic/reactor/program/Constraint.java index aeaa5f63..0f68c9d0 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/program/Constraint.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/program/Constraint.java @@ -15,8 +15,6 @@ public interface Constraint extends AndItem { List> argumentTypes(); - Collection occurrenceArguments(LogicalContext logicalContext); - /** * Returns the collection of predicates that need to be applied after a successful match of this collection by a * rule's head. diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/program/Predicate.java b/reactor/API/src/jetbrains/mps/logic/reactor/program/Predicate.java index 9dc9757b..5835f656 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/program/Predicate.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/program/Predicate.java @@ -3,6 +3,8 @@ package jetbrains.mps.logic.reactor.program; /*Generated by MPS */ import java.util.Collection; +import java.util.List; + import jetbrains.mps.logic.reactor.logical.LogicalContext; /** @@ -12,7 +14,4 @@ public interface Predicate extends AndItem { PredicateSymbol symbol(); - Collection invocationArguments(LogicalContext logicalContext); - - } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/program/PredicateFactory.java b/reactor/API/src/jetbrains/mps/logic/reactor/program/PredicateFactory.java deleted file mode 100644 index fc8cb0bb..00000000 --- a/reactor/API/src/jetbrains/mps/logic/reactor/program/PredicateFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package jetbrains.mps.logic.reactor.program; - -/*Generated by MPS */ - - -public interface PredicateFactory { - - Predicate predicate(PredicateSymbol predicateSymbol, Object... args); - -} diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/program/Program.java b/reactor/API/src/jetbrains/mps/logic/reactor/program/Program.java index a6376a0d..60985ebf 100644 --- a/reactor/API/src/jetbrains/mps/logic/reactor/program/Program.java +++ b/reactor/API/src/jetbrains/mps/logic/reactor/program/Program.java @@ -2,6 +2,8 @@ package jetbrains.mps.logic.reactor.program; /*Generated by MPS */ +import jetbrains.mps.logic.reactor.logical.LogicalContext; + import java.util.List; public abstract class Program { @@ -23,4 +25,6 @@ public abstract class Program { public abstract Iterable handlers(); + public abstract List occurrenceArguments(Constraint constraint, LogicalContext logicalContext); + } diff --git a/reactor/API/src/jetbrains/mps/logic/reactor/program/Solver.java b/reactor/API/src/jetbrains/mps/logic/reactor/program/Solver.java new file mode 100644 index 00000000..1cd71896 --- /dev/null +++ b/reactor/API/src/jetbrains/mps/logic/reactor/program/Solver.java @@ -0,0 +1,9 @@ +package jetbrains.mps.logic.reactor.program; + +/*Generated by MPS */ + +public interface Solver { + + + +} 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 985548b9..4c33b61e 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Controller.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Controller.kt @@ -133,6 +133,8 @@ class Controller { // persistent (functional) object. reassigned on update private var propHistory = PropagationHistory() + val program: Program + val ruleIndex: RuleIndex private val trace: EvaluationTrace @@ -140,13 +142,14 @@ class Controller { private val profiler: Profiler? constructor( - handlers: Iterable, + program: Program, trace: EvaluationTrace = EvaluationTrace.NULL, profiler: Profiler? = null, // for testing purposes only occurrences: Iterable? = null) { - this.ruleIndex = RuleIndex(handlers) + this.program = program + this.ruleIndex = RuleIndex(program.handlers()) this.trace = trace this.profiler = profiler if (occurrences != null) { @@ -159,7 +162,7 @@ class Controller { fun activate(constraint: Constraint) { try { - process(constraint.occurrence({ frameStack.current }, noLogicalContext)) + process(constraint.occurrence({ frameStack.current }, program, noLogicalContext)) } catch (t: Throwable) { throw t @@ -204,7 +207,7 @@ class Controller { trace.trying(match) for (prd in match.patternPredicates) { - tellPredicate(prd.invocation(match.logicalContext), trace) + tellPredicate(prd, match.logicalContext, trace) } if (!match.rule.checkGuard(match.logicalContext, trace)) { @@ -239,8 +242,8 @@ class Controller { try { for (item in body) { when (item) { - is Constraint -> process(item.occurrence({ frameStack.current }, match.logicalContext)) - is Predicate -> tellPredicate(item.invocation(match.logicalContext), trace) + is Constraint -> process(item.occurrence({ frameStack.current }, program, match.logicalContext)) + is Predicate -> tellPredicate(item, match.logicalContext, trace) else -> throw IllegalArgumentException("unknown item ${item}") } } @@ -278,39 +281,26 @@ class Controller { private fun Rule.checkGuard(logicalContext: LogicalContext, trace: EvaluationTrace): Boolean = profiler.profile("checkGuard") { - return guard().all { prd -> askPredicate(prd.invocation(logicalContext), trace) } + return guard().all { prd -> askPredicate(prd, logicalContext, trace) } } - private fun askPredicate(invocation: PredicateInvocation, trace: EvaluationTrace): Boolean = - profiler.profile("ask_${invocation.predicate().symbol()}", { + private fun askPredicate(predicate: Predicate, logicalContext: LogicalContext, trace: EvaluationTrace): Boolean = + profiler.profile("ask_${predicate.symbol()}", { - // TODO: provide SessionSolver as part of evaluation session - val result = EvaluationSession.current().sessionQueryable().ask(invocation) -// trace.ask(result, invocation) - return result + EvaluationSession.current().sessionSolver().ask(predicate, logicalContext) }) - private fun tellPredicate(invocation: PredicateInvocation, trace: EvaluationTrace) { - profiler.profile("tell_${invocation.predicate().symbol()}") { + private fun tellPredicate(predicate: Predicate, logicalContext: LogicalContext, trace: EvaluationTrace) = + profiler.profile("tell_${predicate.symbol()}") { - // TODO: provide SessionSolver as part of evaluation session -// trace.tell(invocation) - EvaluationSession.current().sessionInstructible().tell(invocation) + EvaluationSession.current().sessionSolver().tell(predicate, logicalContext) } - } } private val noLogicalContext: LogicalContext = object: LogicalContext { override fun variable(metaLogical: MetaLogical): Logical = TODO() } - -private fun Predicate.invocation(logicalContext: LogicalContext): PredicateInvocation = object: PredicateInvocation { - - override fun predicate(): Predicate = this@invocation - - override fun arguments(): List<*> = invocationArguments(logicalContext).toList() - } 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 527dd21c..63f04d96 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/MemEvaluationSession.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/MemEvaluationSession.kt @@ -89,7 +89,7 @@ class MemEvaluationSession : EvaluationSession, SessionObjects { } fun launch(main: Constraint, profiler: Profiler?) { - this.controller = Controller(program.handlers(), trace, profiler) + this.controller = Controller(program, trace, profiler) controller.activate(main) } @@ -97,10 +97,6 @@ class MemEvaluationSession : EvaluationSession, SessionObjects { override fun sessionSolver(): SessionSolver = sessionSolver - override fun sessionInstructible(): Instructible = sessionSolver - - override fun sessionQueryable(): Queryable = sessionSolver - override fun storeView(): StoreView = controller.storeView() diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt new file mode 100644 index 00000000..0e75cbf8 --- /dev/null +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Occurrence.kt @@ -0,0 +1,63 @@ +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.program.Constraint +import jetbrains.mps.logic.reactor.program.Program +import java.util.* + +/** + * @author Fedor Isakov + */ + + +fun Constraint.occurrence(currentFrame: () -> Frame, program: Program, context: LogicalContext): ConstraintOccurrence = + Occurrence(currentFrame, this, program.occurrenceArguments(this, context)) + +private data class Occurrence (val currentFrame: () -> Frame, val constraint: Constraint, val arguments: List<*>) : + ConstraintOccurrence, + LogicalObserver, + StoreItem +{ + override var alive = true + override var stored = false + + init { + for (a in arguments) { + if (a is Logical<*>) { + currentFrame().addObserver(a) { this } + } + } + } + + override fun constraint(): Constraint = constraint + + override fun arguments(): List<*> = arguments + + override fun valueUpdated(logical: Logical<*>) { + if (alive) { + (EvaluationSession.current() as SessionObjects).handler().reactivate(this) + } + } + + override fun parentUpdated(logical: Logical<*>) { + if (alive) { + (EvaluationSession.current() as SessionObjects).handler().reactivate(this) + } + } + + override fun terminate() { + for (a in arguments) { + if (a is Logical<*>) { + currentFrame().removeObserver(a) { this } + } + } + alive = false + } + + override fun toString(): String = "${constraint().symbol()}(${arguments().joinToString()})" + +} + diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Store.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Store.kt index d67480a0..6417af4b 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/Store.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/Store.kt @@ -22,9 +22,6 @@ import com.github.andrewoma.dexx.collection.Vector as PersVector * @author Fedor Isakov */ -fun Constraint.occurrence(currentFrame: () -> Frame, context: LogicalContext): ConstraintOccurrence = - Occurrence(currentFrame, this, occurrenceArguments(context)) - fun ConstraintOccurrence.isStored(): Boolean = // TODO: superfluous cast (this as StoreItem).stored @@ -271,52 +268,5 @@ class StoreViewImpl(occurrences: Sequence) : StoreView { } -private data class Occurrence(val currentFrame: () -> Frame, val constraint: Constraint, val arguments: List<*>) : - ConstraintOccurrence, - LogicalObserver, - StoreItem -{ - override var alive = true - - override var stored = false - - constructor(currentFrame: () -> Frame, constraint: Constraint, arguments: Collection<*>) : - this(currentFrame, constraint, ArrayList(arguments)) - { - for (a in arguments) { - if (a is Logical<*>) { - currentFrame().addObserver(a) { this } - } - } - } - - override fun constraint(): Constraint = constraint - - override fun arguments(): List<*> = arguments - - override fun valueUpdated(logical: Logical<*>) { - if (alive) { - (EvaluationSession.current() as SessionObjects).handler().reactivate(this) - } - } - - override fun parentUpdated(logical: Logical<*>) { - if (alive) { - (EvaluationSession.current() as SessionObjects).handler().reactivate(this) - } - } - - override fun terminate() { - for (a in arguments) { - if (a is Logical<*>) { - currentFrame().removeObserver(a) { this } - } - } - alive = false - } - - override fun toString(): String = "${constraint().symbol()}(${arguments().joinToString()})" - -} diff --git a/reactor/Test/src/program/MockConstraint.kt b/reactor/Test/src/program/MockConstraint.kt index 55f91604..94d7a3e3 100644 --- a/reactor/Test/src/program/MockConstraint.kt +++ b/reactor/Test/src/program/MockConstraint.kt @@ -18,11 +18,6 @@ data class MockConstraint(val symbol: ConstraintSymbol, val arguments: List override fun arguments(): List = arguments - override fun occurrenceArguments(logicalContext: LogicalContext): Collection<*> = arguments.map { a -> - if (a is MetaLogical<*>) logicalContext.variable(a) - else a - } - override fun patternPredicates(args: Collection<*>): Collection = emptyList() override fun symbol(): ConstraintSymbol = symbol diff --git a/reactor/Test/src/program/MockProgram.kt b/reactor/Test/src/program/MockProgram.kt index 11f8c426..78e204cf 100644 --- a/reactor/Test/src/program/MockProgram.kt +++ b/reactor/Test/src/program/MockProgram.kt @@ -4,13 +4,15 @@ import jetbrains.mps.logic.reactor.evaluation.Queryable import jetbrains.mps.logic.reactor.evaluation.SessionSolver +import jetbrains.mps.logic.reactor.logical.LogicalContext +import jetbrains.mps.logic.reactor.logical.MetaLogical import jetbrains.mps.logic.reactor.program.* import org.omg.CORBA.Environment import program.MockConstraint import java.util.* import java.util.Collections.* -class ProgramBuilder(val registry: ConstraintRegistry) { +class ProgramBuilder(val registry: MockConstraintRegistry) { private val handlers = ArrayList() @@ -97,7 +99,7 @@ class MockRule( else (kept + replaced).map { it as AndItem } + guard + body.flatten() } -class MockProgram(val name: String, val handlers: List, val registry: ConstraintRegistry) : Program() { +class MockProgram(val name: String, val handlers: List, val registry: MockConstraintRegistry) : Program() { override fun name(): String = name @@ -110,17 +112,23 @@ class MockProgram(val name: String, val handlers: List, val registry: C override fun predicateSymbols(): Iterable = registry.predicateSymbols() + override fun occurrenceArguments(constraint: Constraint, logicalContext: LogicalContext): List<*> = + constraint.arguments().map { a -> + if (a is MetaLogical<*>) logicalContext.variable(a) + else a + } + override fun rules(): Iterable = handlers.flatMap { it.rules() } override fun handlers(): Iterable = unmodifiableCollection(handlers) } -class ConstraintRegistry(val sessionSolver: SessionSolver) { +class MockConstraintRegistry(val sessionSolver: SessionSolver) { private val myConstraintArgTypes = HashMap>>().withDefault { Collections.emptyList() } - private val myPredicateSolvers = HashMap>() + private val myPredicateSymbols = HashSet() fun update(rule: Rule) { for(item in rule.all()) { @@ -156,7 +164,7 @@ class ConstraintRegistry(val sessionSolver: SessionSolver) { fun introduce(item: AndItem) { when(item) { is Constraint -> myConstraintArgTypes.put(item.symbol(), item.argumentTypes()) - is Predicate -> myPredicateSolvers.put(item.symbol(), sessionSolver.solverClass(item.symbol())) + is Predicate -> myPredicateSymbols.add(item.symbol()) else -> throw InvalidConstraintException("unknown item: ${item}") } } @@ -168,7 +176,7 @@ class ConstraintRegistry(val sessionSolver: SessionSolver) { unmodifiableList(myConstraintArgTypes.getOrPut(symbol, { emptyList() })) fun predicateSymbols(): Iterable = - unmodifiableSet(myPredicateSolvers.keys) + unmodifiableSet(myPredicateSymbols) } diff --git a/reactor/Test/src/solver/EqualsSolver.kt b/reactor/Test/src/solver/EqualsSolver.kt index 0e265711..e7e6bc12 100644 --- a/reactor/Test/src/solver/EqualsSolver.kt +++ b/reactor/Test/src/solver/EqualsSolver.kt @@ -9,10 +9,17 @@ import jetbrains.mps.logic.reactor.program.Predicate import jetbrains.mps.logic.reactor.program.PredicateSymbol import jetbrains.mps.logic.reactor.program.Symbol -class EqualsSolver : Solver { +class EqualsSolver : AbstractSolver() { - override fun predicate(predicateSymbol: PredicateSymbol, vararg args: Any): Predicate = - TestEqPredicate(args[0], args[1]) + companion object { + fun eq(left: Any, right: Any): TestEqPredicate = TestEqPredicate(left, right) + } + + override fun invocationArguments(predicate: Predicate, logicalContext: LogicalContext): List<*> = + predicate.arguments().map { a -> + if (a is MetaLogical<*>) logicalContext.variable(a) + else a + } override fun ask(invocation: PredicateInvocation): Boolean { return _ask(invocation.arguments().get(0), invocation.arguments().get(1)) @@ -102,9 +109,15 @@ class EqualsSolver : Solver { } -infix fun Logical.eq(value: T) { - EvaluationSession.current().sessionSolver().tell(PredicateSymbol("equals", 2), this, value) -} +infix fun T.is_eq(value: T): Boolean = + EvaluationSession.current().sessionSolver().ask(EqualsSolver.eq(this, value), object : LogicalContext{ + override fun variable(metaLogical: MetaLogical?): Logical = TODO() + }) + +infix fun T.eq(value: T) = + EvaluationSession.current().sessionSolver().tell(EqualsSolver.eq(this, value), object : LogicalContext{ + override fun variable(metaLogical: MetaLogical?): Logical = TODO() + }) data class TestEqPredicate(val left: Any, val right: Any) : Predicate { @@ -112,9 +125,4 @@ data class TestEqPredicate(val left: Any, val right: Any) : Predicate { override fun symbol(): PredicateSymbol = PredicateSymbol("equals", 2) - override fun invocationArguments(logicalContext: LogicalContext): Collection<*> = listOf(left, right).map { a -> - if (a is MetaLogical<*>) logicalContext.variable(a) - else a - } - } \ No newline at end of file diff --git a/reactor/Test/src/solver/MockSessionSolver.kt b/reactor/Test/src/solver/MockSessionSolver.kt index c90a7f2c..9cf3a16d 100644 --- a/reactor/Test/src/solver/MockSessionSolver.kt +++ b/reactor/Test/src/solver/MockSessionSolver.kt @@ -3,20 +3,13 @@ package solver import jetbrains.mps.logic.reactor.evaluation.* import jetbrains.mps.logic.reactor.program.JavaPredicateSymbol import jetbrains.mps.logic.reactor.program.PredicateSymbol +import jetbrains.mps.logic.reactor.program.Solver /** * @author Fedor Isakov */ -open class MockSessionSolver(val expressionSolver: Solver, val equalsSolver: Solver) : SessionSolver() { - - override fun solverClass(predicateSymbol: PredicateSymbol): Class { - return when (predicateSymbol) { - is JavaPredicateSymbol -> expressionSolver.javaClass - PredicateSymbol("equals", 2) -> equalsSolver.javaClass - else -> throw UnsupportedOperationException("not implemented") - } - } +open class MockSessionSolver(val expressionSolver: AbstractSolver, val equalsSolver: AbstractSolver) : SessionSolver() { override fun registerSymbol(predicateSymbol: PredicateSymbol, computingTracer: EvaluationTrace?) { when (predicateSymbol) { diff --git a/reactor/Test/test/JavaExpressionHelper.kt b/reactor/Test/test/JavaExpressionHelper.kt index 5e09009c..2a86282e 100644 --- a/reactor/Test/test/JavaExpressionHelper.kt +++ b/reactor/Test/test/JavaExpressionHelper.kt @@ -1,6 +1,7 @@ +import jetbrains.mps.logic.reactor.evaluation.AbstractSolver import jetbrains.mps.logic.reactor.evaluation.PredicateInvocation import jetbrains.mps.logic.reactor.evaluation.Queryable -import jetbrains.mps.logic.reactor.evaluation.Solver +import jetbrains.mps.logic.reactor.program.Solver import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.logical.LogicalContext import jetbrains.mps.logic.reactor.logical.MetaLogical @@ -57,10 +58,13 @@ fun , add(JavaPredicateSymbol.withArity(3).withCode({ x, y, z -> body.invoke(x, y, z); true }, x, y, z)) } -class ExpressionSolver : Solver { +class ExpressionSolver : AbstractSolver() { - override fun predicate(predicateSymbol: PredicateSymbol, vararg args: Any): Predicate = - TODO() + override fun invocationArguments(predicate: Predicate, logicalContext: LogicalContext): List<*> = + predicate.arguments().map { a -> + if (a is MetaLogical<*>) logicalContext.variable(a) + else a + } override fun ask(invocation: PredicateInvocation): Boolean { return javaPredicates[invocation.arguments().get(0)]?.expr?.invoke(invocation.arguments().drop(1)) ?: @@ -99,10 +103,6 @@ data class TestJavaPredicate(val symbol: JavaPredicateSymbol, val expr: JavaExpr override fun symbol(): PredicateSymbol = symbol - override fun invocationArguments(logicalContext: LogicalContext): Collection<*> = args.map { a -> - if (a is MetaLogical<*>) logicalContext.variable(a) - else a - } } private fun JavaPredicateSymbol.withCode(code: () -> Boolean) = diff --git a/reactor/Test/test/TestController.kt b/reactor/Test/test/TestController.kt index d5a5fcf5..d21398a0 100644 --- a/reactor/Test/test/TestController.kt +++ b/reactor/Test/test/TestController.kt @@ -2,12 +2,16 @@ import jetbrains.mps.logic.reactor.core.Controller import jetbrains.mps.logic.reactor.core.SessionObjects import jetbrains.mps.logic.reactor.evaluation.* import jetbrains.mps.logic.reactor.logical.Logical +import jetbrains.mps.logic.reactor.logical.LogicalContext +import jetbrains.mps.logic.reactor.logical.MetaLogical import jetbrains.mps.logic.reactor.program.* import org.junit.* import org.junit.Assert.* import solver.EqualsSolver import solver.MockSessionSolver import solver.TestEqPredicate +import solver.eq +import solver.is_eq /** * @author Fedor Isakov @@ -27,8 +31,6 @@ class TestController { lateinit var controller: Controller override fun handler(): Controller = controller override fun sessionSolver(): SessionSolver = solver - override fun sessionInstructible(): Instructible = solver - override fun sessionQueryable(): Queryable = solver override fun storeView(): StoreView = TODO() class MockBackend(val session: MockSession) : Backend { @@ -55,19 +57,17 @@ class TestController { init(PredicateSymbol("equals", 2), JavaPredicateSymbol.EXPRESSION0, JavaPredicateSymbol.EXPRESSION1, JavaPredicateSymbol.EXPRESSION2, JavaPredicateSymbol.EXPRESSION3) } private fun Builder.controller(vararg occurrences: ConstraintOccurrence): Controller { - MockSession.init(sessionSolver(env.expressionSolver, env.equalsSolver)) - val handler = Controller(handlers, occurrences = listOf(* occurrences)) - MockSession.ourBackend.session.controller = handler - return handler + val solver = sessionSolver(env.expressionSolver, env.equalsSolver) + MockSession.init(solver) + val program = MockProgram("test", handlers, registry = MockConstraintRegistry(solver)) + val controller = Controller(program, occurrences = listOf(* occurrences)) + MockSession.ourBackend.session.controller = controller + return controller } - private fun eq(left: Logical, right: Logical) { - EvaluationSession.current().sessionSolver().tell(PredicateSymbol("equals", 2), left, right) - } + private fun eq(left: T, right: T) = left eq right - private fun is_eq(left: Logical, right: Logical): Boolean { - return EvaluationSession.current().sessionSolver().ask(PredicateSymbol("equals", 2), left, right) - } + private fun is_eq(left: T, right: T): Boolean = left is_eq right @Test fun processSingle() { diff --git a/reactor/Test/test/TestProgram.kt b/reactor/Test/test/TestProgram.kt index f3210eb4..86089fc7 100644 --- a/reactor/Test/test/TestProgram.kt +++ b/reactor/Test/test/TestProgram.kt @@ -28,7 +28,7 @@ class TestProgram { private fun Builder.session(name: String): StoreView { val sessionSolver = MockSessionSolver(env.expressionSolver, env.equalsSolver) - val programBuilder = ProgramBuilder(ConstraintRegistry(sessionSolver)) + val programBuilder = ProgramBuilder(MockConstraintRegistry(sessionSolver)) for (h in handlers) { programBuilder.addHandler(h) } diff --git a/reactor/Test/test/TestProgramBuilder.kt b/reactor/Test/test/TestProgramBuilder.kt index fb8fb878..840db840 100644 --- a/reactor/Test/test/TestProgramBuilder.kt +++ b/reactor/Test/test/TestProgramBuilder.kt @@ -1,6 +1,8 @@ +import jetbrains.mps.logic.reactor.evaluation.AbstractSolver import jetbrains.mps.logic.reactor.evaluation.PredicateInvocation import jetbrains.mps.logic.reactor.evaluation.Queryable -import jetbrains.mps.logic.reactor.evaluation.Solver +import jetbrains.mps.logic.reactor.logical.LogicalContext +import jetbrains.mps.logic.reactor.program.Solver import solver.MockSessionSolver import jetbrains.mps.logic.reactor.program.* import org.junit.AfterClass @@ -17,8 +19,8 @@ import kotlin.reflect.KClass class TestProgramBuilder { - val dummySolver = object : Solver { - override fun predicate(predicateSymbol: PredicateSymbol?, vararg args: Any?): Predicate? = TODO() + val dummySolver = object : AbstractSolver() { + override fun invocationArguments(predicate: Predicate?, logicalContext: LogicalContext?): MutableList<*> = TODO() override fun ask(invocation: PredicateInvocation?): Boolean = TODO() override fun tell(invocation: PredicateInvocation?) = TODO() } @@ -26,7 +28,7 @@ class TestProgramBuilder { val sessionSolver = MockSessionSolver(dummySolver, dummySolver) @Before fun beforeTest() { - programBuilder = ProgramBuilder(ConstraintRegistry(sessionSolver)) + programBuilder = ProgramBuilder(MockConstraintRegistry(sessionSolver)) } lateinit var programBuilder: ProgramBuilder