in reactor/Core/src/jetbrains/mps/logic/reactor/core/RuleIndex.kt [209:278]
fun select(occ: ConstraintOccurrence): Pair<RuleBits, Map<Int, HeadBits>> {
if (occ.constraint().symbol() != symbol) throw IllegalArgumentException()
// by default select all rules where this constraint is in the head
var refined = false
val slotVotes = HashMap<Pair<Int, Int>, BitSet>()
val wildcardSlots = BitSet()
val selectedRuleBits = emptyRuleBits()
for ((argIdx, arg) in occ.arguments().withIndex()) {
if (arg is Logical<*> && !arg.isBound) {
// ALL values must be selected for a free logical
wildcardSlots.set(argIdx)
continue
}
val candidateRuleBits = emptyRuleBits()
val value2indices = anySelectors[argIdx]
val termIndices = termSelectors[argIdx]
val wildcardIndices = wildcardSelectors[argIdx]
// indices found from Term or Any argument are AND-ed
candidateRuleBits.clear()
candidateRuleBits.addAll(wildcardIndices)
val argVal = if (arg is Logical<*>) arg.findRoot().value() else arg
when (argVal) {
is Term ->
termIndices.forValuesWithIndex(argVal) { headPos, ruleBit ->
candidateRuleBits.add(ruleBit)
slotVotes.getOrPut(ruleBit to headPos) { BitSet() }.set(argIdx)
}
is Any ->
// ensure only rules with either matching values or wildcard arguments get selected
value2indices[argVal]?.run { forEach { (ruleBit, headPos) ->
candidateRuleBits.add(ruleBit)
slotVotes.getOrPut(ruleBit to headPos) { BitSet() }.set(argIdx)
} }
}
if (!refined) {
refined = true
selectedRuleBits.addAll(candidateRuleBits)
} else {
selectedRuleBits.retainAll(candidateRuleBits)
}
if (selectedRuleBits.isEmpty) break
}
selectedRuleBits.retainAll(symbolSelector)
val slotMasks = HashMap<Int, HeadBits>()
for ((p, votes) in slotVotes.entries) {
val (ruleBit, headPos) = p
if (!votes.isEmpty || !wildcardSlots.isEmpty) {
slotMasks.getOrPut(ruleBit) { emptyHeadBits() }.set(headPos)
}
}
return if (!refined) {
// no arguments or all arguments are wildcards
symbolSelector to slotMasks
} else {
selectedRuleBits to slotMasks
}
}