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:
Fedor Isakov 2017-01-05 17:16:21 +01:00
parent ebfe680aae
commit c68d9a0bd7
25 changed files with 276 additions and 261 deletions

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -2,9 +2,8 @@ package jetbrains.mps.logic.reactor.evaluation;
/*Generated by MPS */
public interface Instructible {
void tell(PredicateInvocation invocation);
void tell(PredicateInvocation invocation);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 {
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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.

View File

@ -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);
}

View File

@ -1,10 +0,0 @@
package jetbrains.mps.logic.reactor.program;
/*Generated by MPS */
public interface PredicateFactory {
Predicate predicate(PredicateSymbol predicateSymbol, Object... args);
}

View File

@ -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);
}

View File

@ -0,0 +1,9 @@
package jetbrains.mps.logic.reactor.program;
/*Generated by MPS */
public interface Solver {
}

View File

@ -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()
}

View File

@ -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()

View File

@ -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()})"
}

View File

@ -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()})"
}

View File

@ -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

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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) {

View File

@ -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) =

View File

@ -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() {

View File

@ -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)
}

View File

@ -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