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.
This commit is contained in:
parent
ebfe680aae
commit
c68d9a0bd7
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ package jetbrains.mps.logic.reactor.evaluation;
|
|||
|
||||
/*Generated by MPS */
|
||||
|
||||
|
||||
public interface Instructible {
|
||||
|
||||
void tell(PredicateInvocation invocation);
|
||||
void tell(PredicateInvocation invocation);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<? extends Queryable> 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<PredicateSymbol, Solver> solvers = new HashMap<PredicateSymbol, Solver>();
|
||||
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<PredicateSymbol, AbstractSolver> solvers = new HashMap<PredicateSymbol, AbstractSolver>();
|
||||
|
||||
private EvaluationTrace tracer = EvaluationTrace.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 {
|
||||
}
|
||||
|
|
@ -2,9 +2,12 @@ package jetbrains.mps.logic.reactor.logical;
|
|||
|
||||
/*Generated by MPS */
|
||||
|
||||
|
||||
/**
|
||||
* Substitution of logicals for meta-logicals.
|
||||
*/
|
||||
public interface LogicalContext {
|
||||
|
||||
|
||||
<V> Logical<V> variable(MetaLogical<V> metaLogical);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ public interface Constraint extends AndItem {
|
|||
|
||||
List<Class<?>> 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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
package jetbrains.mps.logic.reactor.program;
|
||||
|
||||
/*Generated by MPS */
|
||||
|
||||
|
||||
public interface PredicateFactory {
|
||||
|
||||
Predicate predicate(PredicateSymbol predicateSymbol, Object... args);
|
||||
|
||||
}
|
||||
|
|
@ -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<Handler> handlers();
|
||||
|
||||
public abstract List<?> occurrenceArguments(Constraint constraint, LogicalContext logicalContext);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package jetbrains.mps.logic.reactor.program;
|
||||
|
||||
/*Generated by MPS */
|
||||
|
||||
public interface Solver {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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<Handler>,
|
||||
program: Program,
|
||||
trace: EvaluationTrace = EvaluationTrace.NULL,
|
||||
profiler: Profiler? = null,
|
||||
// for testing purposes only
|
||||
occurrences: Iterable<ConstraintOccurrence>? = 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<Boolean>("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<Boolean>("ask_${invocation.predicate().symbol()}", {
|
||||
private fun askPredicate(predicate: Predicate, logicalContext: LogicalContext, trace: EvaluationTrace): Boolean =
|
||||
profiler.profile<Boolean>("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 <V : Any> variable(metaLogical: MetaLogical<V>): Logical<V> = TODO()
|
||||
}
|
||||
|
||||
private fun Predicate.invocation(logicalContext: LogicalContext): PredicateInvocation = object: PredicateInvocation {
|
||||
|
||||
override fun predicate(): Predicate = this@invocation
|
||||
|
||||
override fun arguments(): List<*> = invocationArguments(logicalContext).toList()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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()})"
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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<ConstraintOccurrence>) : 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()})"
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@ data class MockConstraint(val symbol: ConstraintSymbol, val arguments: List<Any>
|
|||
|
||||
override fun arguments(): List<Any> = 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<Predicate> = emptyList()
|
||||
|
||||
override fun symbol(): ConstraintSymbol = symbol
|
||||
|
|
|
|||
|
|
@ -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<Handler>()
|
||||
|
||||
|
|
@ -97,7 +99,7 @@ class MockRule(
|
|||
else (kept + replaced).map { it as AndItem } + guard + body.flatten()
|
||||
}
|
||||
|
||||
class MockProgram(val name: String, val handlers: List<Handler>, val registry: ConstraintRegistry) : Program() {
|
||||
class MockProgram(val name: String, val handlers: List<Handler>, val registry: MockConstraintRegistry) : Program() {
|
||||
|
||||
override fun name(): String = name
|
||||
|
||||
|
|
@ -110,17 +112,23 @@ class MockProgram(val name: String, val handlers: List<Handler>, val registry: C
|
|||
override fun predicateSymbols(): Iterable<PredicateSymbol> =
|
||||
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<Rule> = handlers.flatMap { it.rules() }
|
||||
|
||||
override fun handlers(): Iterable<Handler> = unmodifiableCollection(handlers)
|
||||
}
|
||||
|
||||
|
||||
class ConstraintRegistry(val sessionSolver: SessionSolver) {
|
||||
class MockConstraintRegistry(val sessionSolver: SessionSolver) {
|
||||
|
||||
private val myConstraintArgTypes = HashMap<ConstraintSymbol, List<Class<*>>>().withDefault { Collections.emptyList() }
|
||||
|
||||
private val myPredicateSolvers = HashMap<PredicateSymbol, Class<out Queryable>>()
|
||||
private val myPredicateSymbols = HashSet<PredicateSymbol>()
|
||||
|
||||
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<PredicateSymbol> =
|
||||
unmodifiableSet(myPredicateSolvers.keys)
|
||||
unmodifiableSet(myPredicateSymbols)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <T : Any> Logical<T>.eq(value: T) {
|
||||
EvaluationSession.current().sessionSolver().tell(PredicateSymbol("equals", 2), this, value)
|
||||
}
|
||||
infix fun <T : Any> T.is_eq(value: T): Boolean =
|
||||
EvaluationSession.current().sessionSolver().ask(EqualsSolver.eq(this, value), object : LogicalContext{
|
||||
override fun <V : Any?> variable(metaLogical: MetaLogical<V>?): Logical<V> = TODO()
|
||||
})
|
||||
|
||||
infix fun <T : Any> T.eq(value: T) =
|
||||
EvaluationSession.current().sessionSolver().tell(EqualsSolver.eq(this, value), object : LogicalContext{
|
||||
override fun <V : Any?> variable(metaLogical: MetaLogical<V>?): Logical<V> = 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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<out Queryable> {
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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 <X, LPX: MetaLogical<X>,
|
|||
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) =
|
||||
|
|
|
|||
|
|
@ -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 <T : Any> eq(left: Logical<T>, right: Logical<T>) {
|
||||
EvaluationSession.current().sessionSolver().tell(PredicateSymbol("equals", 2), left, right)
|
||||
}
|
||||
private fun <T : Any> eq(left: T, right: T) = left eq right
|
||||
|
||||
private fun <T : Any> is_eq(left: Logical<T>, right: Logical<T>): Boolean {
|
||||
return EvaluationSession.current().sessionSolver().ask(PredicateSymbol("equals", 2), left, right)
|
||||
}
|
||||
private fun <T : Any> is_eq(left: T, right: T): Boolean = left is_eq right
|
||||
|
||||
@Test
|
||||
fun processSingle() {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue