MemLogicalPattern. Switch to using MemLogical in tests.

This commit is contained in:
Fedor Isakov 2016-01-07 12:56:13 +01:00
parent 8aa6b04c70
commit b90bdc84c4
11 changed files with 99 additions and 122 deletions

View File

@ -15,6 +15,6 @@ public interface Logical<T> {
public boolean isWildcard();
public LogicalPattern<Logical<T>> pattern();
public LogicalPattern<T> pattern();
}

View File

@ -99,7 +99,7 @@ class PartialMatch(val rule: Rule) {
return var2val[logicalPattern] as V
}
else {
val logical = logicalPattern.instance()
val logical = logicalPattern.logical()
var2val.put(logicalPattern, logical)
return logical as V
}

View File

@ -1,5 +1,5 @@
package jetbrains.mps.logic.reactor.predicate
package jetbrains.mps.logic.reactor.core
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalPattern
@ -9,6 +9,8 @@ import jetbrains.mps.logic.reactor.logical.SolverLogical
* @author Fedor Isakov
*/
fun <V> LogicalPattern<V>.logical(): Logical<V> = MemLogical<V>(name())
class MemLogical<T> : SolverLogical<T> {
companion object {
@ -17,6 +19,8 @@ class MemLogical<T> : SolverLogical<T> {
val name: String
var pattern: LogicalPattern<T>? = null
var _parent: MemLogical<T>? = null
var _value: T? = null
@ -32,6 +36,11 @@ class MemLogical<T> : SolverLogical<T> {
this.name = name
}
constructor(pattern: LogicalPattern<T>) {
this.pattern = pattern
this.name = pattern.name()
}
override fun name(): String = name
override fun value(): T? = _value
@ -40,11 +49,13 @@ class MemLogical<T> : SolverLogical<T> {
override fun isWildcard(): Boolean = TODO()
override fun pattern(): LogicalPattern<Logical<T>> = TODO()
override fun pattern(): LogicalPattern<T>? = pattern
override fun findRoot(): SolverLogical<T> = find()
override fun setParent(parent: SolverLogical<T>) { this._parent = parent as MemLogical<T> }
override fun setParent(parent: SolverLogical<T>) {
this._parent = parent as MemLogical<T>
}
override fun setValue(newValue: T) { this._value = newValue }

View File

@ -0,0 +1,28 @@
package program
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalPattern
import jetbrains.mps.logic.reactor.logical.NamingContext
/**
* @author Fedor Isakov
*/
data class MemLogicalPattern<V>(val name: String, val type: Class<V>, val wildcard: Boolean) : LogicalPattern<V> {
constructor(name: String, type: Class<V>) : this(name, type, false) {}
override fun name(): String = name
override fun name(namingContext: NamingContext): String = TODO()
override fun isWildcard(): Boolean = wildcard
override fun type(): Class<V> = type
override fun instance(): Logical<V> {
// FIXME wrong
throw UnsupportedOperationException("fixme")
}
}

View File

@ -1,4 +1,4 @@
package jetbrains.mps.logic.reactor.predicate
package solver
import jetbrains.mps.logic.reactor.evaluation.EvaluationTrace
import jetbrains.mps.logic.reactor.evaluation.Queryable
@ -15,15 +15,15 @@ open class MemSessionSolver(val expressionSolver: Queryable, val equalsSolver: Q
override fun solverClass(predicateSymbol: PredicateSymbol): Class<out Queryable> {
return when (predicateSymbol) {
is JavaPredicateSymbol -> expressionSolver.javaClass
PredicateSymbol("equals", 2) -> equalsSolver.javaClass
PredicateSymbol("equals", 2) -> equalsSolver.javaClass
else -> throw UnsupportedOperationException("not implemented")
}
}
override fun registerSymbol(predicateSymbol: PredicateSymbol, computingTracer: EvaluationTrace?) {
when (predicateSymbol) {
is JavaPredicateSymbol -> registerSolver(predicateSymbol, expressionSolver)
PredicateSymbol("equals", 2) -> registerSolver(predicateSymbol, equalsSolver)
is JavaPredicateSymbol -> registerSolver(predicateSymbol, expressionSolver)
PredicateSymbol("equals", 2) -> registerSolver(predicateSymbol, equalsSolver)
else -> throw UnsupportedOperationException("not implemented")
}
}

View File

@ -1,6 +1,7 @@
import jetbrains.mps.logic.reactor.evaluation.EvaluationSession
import jetbrains.mps.logic.reactor.evaluation.Queryable
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.SolverLogical
import jetbrains.mps.logic.reactor.program.PredicateSymbol
import jetbrains.mps.logic.reactor.program.Symbol
@ -11,13 +12,13 @@ class EqualsSolver : Queryable {
val left = args[0]
val right = args[1]
return if (left is TestLogical<*> && right is TestLogical<*>) {
return if (left is SolverLogical<*> && right is SolverLogical<*>) {
ask_logical_logical(left, right)
}
else if (left is TestLogical<*>) {
else if (left is SolverLogical<*>) {
ask_logical_value(left, right)
}
else if (right is TestLogical<*>) {
else if (right is SolverLogical<*>) {
ask_value_logical(left, right)
}
else {
@ -29,29 +30,29 @@ class EqualsSolver : Queryable {
if (args.size != 2) ERROR("arity mismatch")
val left = args[0]
val right = args[1]
if (left is TestLogical<*> && right is TestLogical<*>) {
if (left is SolverLogical<*> && right is SolverLogical<*>) {
tell_logical_logical(left, right)
}
else if (left is TestLogical<*>) {
tell_logical_value(left, right)
else if (left is SolverLogical<*>) {
tell_logical_value(left as SolverLogical<Any>, right)
}
else if (right is TestLogical<*>) {
tell_value_logical(left, right)
else if (right is SolverLogical<*>) {
tell_value_logical(left, right as SolverLogical<Any>)
}
else {
tell_value_value(left, right)
}
}
fun ask_logical_logical(left: TestLogical<*>, right: TestLogical<*>): Boolean {
fun ask_logical_logical(left: SolverLogical<*>, right: SolverLogical<*>): Boolean {
return left.isBound && right.isBound && left.findRoot().value() == right.findRoot().value()
}
fun ask_logical_value(left: TestLogical<*>, right: Any?): Boolean {
fun ask_logical_value(left: SolverLogical<*>, right: Any?): Boolean {
return left.isBound && left.findRoot().value() == right
}
fun ask_value_logical(left: Any?, right: TestLogical<*>): Boolean {
fun ask_value_logical(left: Any?, right: SolverLogical<*>): Boolean {
return right.isBound && right.findRoot().value() == left
}
@ -59,39 +60,38 @@ class EqualsSolver : Queryable {
return left == right
}
fun tell_logical_logical(left: TestLogical<*>, right: TestLogical<*>) {
fun tell_logical_logical(left: SolverLogical<*>, right: SolverLogical<*>) {
if (left.isBound && right.isBound) {
check (left.find().value == right.find().value)
left.union(right)
check (left.findRoot().value() == right.findRoot().value())
// FIXME: use rank!!!
left.setParent(right)
}
else if (left.isBound) {
right.union(left)
right.setParent(left)
}
else if (right.isBound) {
left.union(right)
left.setParent(right)
}
else {
left.union(right)
left.setParent(right)
}
}
fun tell_logical_value(left: TestLogical<*>, right: Any?) {
fun <T> tell_logical_value(left: SolverLogical<T>, right: T) {
if (left.isBound) {
check(left.find().value == right)
check(left.findRoot().value() == right)
}
else {
// TODO hack!
(left.find() as TestLogical<Any>).value = right
left.findRoot().setValue(right)
}
}
fun tell_value_logical(left: Any?, right: TestLogical<*>) {
fun <T> tell_value_logical(left: T, right: SolverLogical<T>) {
if (right.isBound) {
check(right.find().value == left)
check(right.findRoot().value() == left)
}
else {
// TODO: hack!
(right.find() as TestLogical<Any>).value = left
right.findRoot().setValue(left)
}
}
fun tell_value_value(left: Any?, right: Any?) {

View File

@ -1,10 +1,9 @@
import jetbrains.mps.logic.reactor.core.MemLogical
import jetbrains.mps.logic.reactor.evaluation.PredicateInvocation
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalContext
import jetbrains.mps.logic.reactor.logical.LogicalPattern
import jetbrains.mps.logic.reactor.logical.NamingContext
import jetbrains.mps.logic.reactor.logical.*
import jetbrains.mps.logic.reactor.program.Predicate
import jetbrains.mps.logic.reactor.program.PredicateSymbol
import program.MemLogicalPattern
import java.util.*
/**
@ -12,100 +11,35 @@ import java.util.*
*/
fun <T: Any> anon(value: T) = TestLogical(value)
fun <T: Any> anon(value: T) = MemLogical(value)
fun <T: Any> logical(name: String) = TestLogical<T>(name)
fun <T: Any> logical(name: String) = MemLogical<T>(name)
fun <T: Any> logical(name1: String, name2: String) = Pair(TestLogical<T>(name1), TestLogical<T>(name2))
fun <T: Any> logical(name1: String, name2: String) = Pair(MemLogical<T>(name1), MemLogical<T>(name2))
fun <T: Any> logical(name1: String, name2: String, name3: String) =
Triple(TestLogical<T>(name1), TestLogical<T>(name2), TestLogical<T>(name3))
Triple(MemLogical<T>(name1), MemLogical<T>(name2), MemLogical<T>(name3))
inline fun <reified T: Any> logicalPattern(name: String) = TestLogicalPattern<T>(name, T::class.java)
inline fun <reified T: Any> logicalPattern(name: String) = MemLogicalPattern<T>(name, T::class.java)
inline fun <reified T: Any> logicalPattern(name1: String, name2: String) =
Pair(TestLogicalPattern<T>(name1, T::class.java), TestLogicalPattern<T>(name2, T::class.java))
Pair(MemLogicalPattern<T>(name1, T::class.java), MemLogicalPattern<T>(name2, T::class.java))
inline fun <reified T: Any> logicalPattern(name1: String, name2: String, name3: String) =
Triple(
TestLogicalPattern<T>(name1, T::class.java),
TestLogicalPattern<T>(name2, T::class.java),
TestLogicalPattern<T>(name3, T::class.java))
MemLogicalPattern<T>(name1, T::class.java),
MemLogicalPattern<T>(name2, T::class.java),
MemLogicalPattern<T>(name3, T::class.java))
fun <T: Any> Logical<T>.get(): T = findRoot().value()
fun <T: Any> Logical<T>.set(t: T) {
if (this is TestLogical<T>)
find().value = t
if (this is SolverLogical<T>)
findRoot().setValue(t)
else
throw IllegalStateException("unexpected receiver $this")
}
data class TestLogical<T>(val name: String, var value: T?, var parent: TestLogical<T>?) : Logical<T> {
companion object {
var anonIdx = 0
}
constructor(value: T) : this("$${anonIdx++}", value, null)
constructor(name: String) : this(name, null, null) {}
override fun name(): String = name
override fun pattern(): LogicalPattern<Logical<T>> = TODO()
override fun findRoot(): Logical<T> = find()
override fun value(): T? = value
override fun isBound(): Boolean = find().value != null
override fun isWildcard(): Boolean {
throw UnsupportedOperationException()
}
fun find(): TestLogical<T> {
val tmp = parent
if (tmp == null) return this
else {
val root = tmp.find()
this.parent = root
return root
}
}
fun union(other: TestLogical<T>) {
if (find() != other.find()) find().parent = other
}
override fun toString(): String = "$name(^${parent?.name ?: null})=$value"
}
data class TestLogicalPattern<T>(val name: String, val type: Class<T>) : LogicalPattern<T> {
companion object {
val random = Random()
}
var wildcard = false
constructor(type: Class<T>) : this("_${random.nextInt()}", type) {
wildcard = true
}
override fun name(): String = name
override fun name(namingContext: NamingContext?): String? = TODO()
override fun isWildcard(): Boolean = wildcard
override fun type(): Class<T> = type
override fun instance(): Logical<T> = TestLogical<T>(name)
}
data class TestEqPredicate(val left: Any, val right: Any) : Predicate {

View File

@ -4,7 +4,7 @@ import jetbrains.mps.logic.reactor.evaluation.Queryable
import jetbrains.mps.logic.reactor.evaluation.SessionSolver
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.logical.LogicalPattern
import jetbrains.mps.logic.reactor.predicate.MemSessionSolver
import solver.MemSessionSolver
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
import jetbrains.mps.logic.reactor.program.JavaPredicateSymbol
import jetbrains.mps.logic.reactor.program.PredicateSymbol
@ -124,7 +124,7 @@ class TestHandler {
fun basicLogical() {
var test : String? = "not initialized"
val x = logical<String>("x")
x.value = "expected"
x.setValue("expected")
program(
rule("main",
headKept(
@ -143,7 +143,7 @@ class TestHandler {
fun logicalCopy() {
var test : String? = "not initialized"
val (x,y) = logical<String>("x", "y")
x.value = "expected"
x.setValue("expected")
program(
rule("main",
headKept(

View File

@ -1,6 +1,8 @@
import jetbrains.mps.logic.reactor.core.Matcher
import jetbrains.mps.logic.reactor.core.logical
import jetbrains.mps.logic.reactor.core.matches
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.program.Constraint
import org.junit.Assert.*
import org.junit.Test
@ -180,7 +182,7 @@ class TestMatcher {
@Test
fun logicalPattern() {
val (A, B, C) = logicalPattern<String>("A", "B", "C")
val b = B.instance()
val b = B.logical()
program(
rule("main",
@ -194,7 +196,8 @@ class TestMatcher {
).matcher().lookupMatches(occurrence("foo", "blah", b)).first().run {
assertEquals("blah", logicalContext().valueFor(A))
assertSame(b, logicalContext().valueFor(B))
assertEquals(C.instance(), logicalContext().valueFor(C))
assertEquals(C.logical().name(), (logicalContext().valueFor(C) as Logical<*>).name())
assertEquals(C.logical().pattern(), (logicalContext().valueFor(C) as Logical<*>).pattern())
}
}
@ -255,7 +258,8 @@ class TestMatcher {
}
val (v, w) = logical<Int>("v", "w")
w.find().union(v)
// FIXME: use rank!!!
w.findRoot().setParent(v)
matcher(occurrence("foo", v)).lookupMatches(occurrence("foo", w)).let { matches ->
assertEquals(4, matches.count())

View File

@ -1,7 +1,7 @@
import jetbrains.mps.logic.reactor.core.MemEvaluationSession
import jetbrains.mps.logic.reactor.evaluation.EvaluationSession
import jetbrains.mps.logic.reactor.logical.Logical
import jetbrains.mps.logic.reactor.predicate.MemSessionSolver
import solver.MemSessionSolver
import jetbrains.mps.logic.reactor.program.ConstraintSymbol
import jetbrains.mps.logic.reactor.program.JavaPredicateSymbol
import jetbrains.mps.logic.reactor.program.PredicateSymbol

View File

@ -1,5 +1,5 @@
import jetbrains.mps.logic.reactor.evaluation.Queryable
import jetbrains.mps.logic.reactor.predicate.MemSessionSolver
import solver.MemSessionSolver
import jetbrains.mps.logic.reactor.program.*
import org.junit.AfterClass
import org.junit.Assert.*