Introduce support for unbound variables within a Term; MPSCR-155

This commit is contained in:
Fedor Isakov 2024-08-19 21:46:50 +02:00
parent 99c3fdf9d0
commit 8d6c5add7e
3 changed files with 34 additions and 12 deletions

View File

@ -17,12 +17,16 @@
package jetbrains.mps.logic.reactor.core
import jetbrains.mps.logic.reactor.core.internal.FeedbackStatus
import jetbrains.mps.logic.reactor.core.internal.push
import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence
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.Rule
import jetbrains.mps.logic.reactor.util.Id
import jetbrains.mps.unification.Term
import java.util.LinkedList
/**
@ -56,23 +60,28 @@ class Occurrence(val constraint: Constraint,
override fun reactivate(controller: Controller) = doReactivate(controller)
fun terminate(observable: LogicalStateObservable) {
for (a in arguments) {
if (a is Logical<*>) {
observable.removeReactivatable(a, this)
}
}
forEachUnboundLogical { observable.removeReactivatable(it, this) }
alive = false
}
fun revive(observable: LogicalStateObservable) {
if (!alive) {
for (a in HashSet(arguments)) { // avoid duplicate subscriptions
if (a is Logical<*>) {
observable.addReactivatable(a, this)
}
forEachUnboundLogical { observable.addReactivatable(it, this) }
alive = true
}
private fun forEachUnboundLogical(block: (Logical<*>) -> Unit) {
val logicals = hashSetOf<Id<Logical<*>>>() // avoid duplicate subscriptions
// NB! Don't use "findRoot" for these are stored using an identity map
val queue = LinkedList(arguments)
while (queue.isNotEmpty()) {
val next = queue.removeFirst()
when (next) {
is Logical<*> -> if (next.isBound) queue.addLast(next.findRoot().value())
else logicals.add(Id(next))
is Term -> next.unboundLogicals().forEach { logicals.add(Id(it)) }
}
}
alive = true
logicals.forEach{ block(it.wrapped) }
}
private fun doReactivate(controller: Controller) {

View File

@ -50,7 +50,9 @@ class LogicalState : LogicalStateObservable, LogicalObserver
if (!observers.containsKey(logical)) {
logical.addObserver(this)
}
observers.getOrPut(logical) { arrayListOf() }.add(reactivatable)
val list = observers.getOrPut(logical) { arrayListOf() }
// TODO this check may be inefficient, but it's necessary
if (!list.contains(reactivatable)) list.add(reactivatable)
}
override fun removeReactivatable(logical: Logical<*>, reactivatable: Reactivatable) {

View File

@ -16,9 +16,12 @@
package jetbrains.mps.unification;
import jetbrains.mps.logic.reactor.logical.Logical;
import jetbrains.mps.logic.reactor.logical.LogicalOwner;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
/**
* Represents a node in a term graph. The graph may contain cycles. A node in a term
@ -45,6 +48,14 @@ public interface Term extends Comparable<Term> {
*/
Collection<? extends Term> arguments();
/**
* A collection of all instances of {@link jetbrains.mps.logic.reactor.logical.Logical}
* within this term that have not been assigned a value.
*/
default Collection<Logical<?>> unboundLogicals() {
return Collections.emptyList();
}
/**
* For a reference term, returns the term this term is referring to.
* For function and variable terms return this term.