///|
pub fn Runtime::new_rule(
self : Runtime,
input_relations : Array[CellId],
output_relations : Array[CellId],
apply_delta : () -> Unit,
label? : String,
) -> @incr_types.RuleId {
for id in input_relations {
self.assert_rule_relation_id(id, "input")
}
for id in output_relations {
self.assert_rule_relation_id(id, "output")
}
let idx = self.datalog.rules.length()
let cell_id = self.alloc_cell_id(Rule(idx))
let data : RuleData = {
meta: {
cell_id,
label,
changed_at: Revision::initial(),
durability: Low,
subscribers: @hashset.HashSet([]),
push_reachable_count: 0,
},
apply_delta,
input_relations,
output_relations,
}
self.datalog.rules.push(data)
let ops : &CellOps = self.datalog.rules[idx]
self.core.cell_ops.push(ops)
let lifecycle : &CellLifecycle = self.datalog.rules[idx]
self.cell_lifecycle.push(lifecycle)
@incr_types.RuleId::{ id: cell_id }
}
///|
fn Runtime::assert_rule_relation_id(
self : Runtime,
id : CellId,
role : String,
) -> Unit {
if id.runtime_id != self.core.runtime_id {
abort(
"new_rule: " +
role +
" relation belongs to Runtime " +
id.runtime_id.to_string() +
", expected Runtime " +
self.core.runtime_id.to_string(),
)
}
if id.id < 0 || id.id >= self.core.cell_index.length() {
abort(
"new_rule: " +
role +
" relation cell_id out of bounds: " +
id.id.to_string(),
)
}
match self.core.cell_index[id.id] {
Relation(_) | FunctionalRelation(_) => ()
_ =>
abort(
"new_rule: " + role + " cell_id is not a Relation: " + id.id.to_string(),
)
}
}