use std::collections::{BTreeMap, HashMap};
use polar_core::terms::{ExternalInstance, Pattern, Symbol, Term, Value};
#[derive(Default)]
pub struct MockExternal {
externals: HashMap<u64, Term>,
}
impl MockExternal {
pub fn new() -> Self {
MockExternal::default()
}
fn get_external(&self, instance_id: u64) -> &Value {
self.externals
.get(&instance_id)
.expect("Instance not constructed")
.value()
}
pub fn external_call(
&mut self,
_call_id: u64,
instance: Term,
attribute: Symbol,
args: Option<Vec<Term>>,
kwargs: Option<BTreeMap<Symbol, Term>>,
) -> Option<Term> {
assert!(
args.is_none() && kwargs.is_none(),
"Only support field lookups."
);
let instance_id = match instance.value() {
Value::ExternalInstance(ExternalInstance { instance_id, .. }) => *instance_id,
_ => panic!("expected external instance"),
};
match self.get_external(instance_id) {
Value::Call(call) => call.kwargs.clone().unwrap().get(&attribute).cloned(),
_ => panic!("expected call with kwargs"),
}
}
pub fn make_external(&mut self, instance_id: u64, constructor: Term) {
assert!(self.externals.insert(instance_id, constructor).is_none());
}
pub fn external_isa(&mut self, instance: Term, class_tag: Symbol) -> bool {
if let Value::ExternalInstance(ExternalInstance { instance_id, .. }) = instance.value() {
match self.get_external(*instance_id) {
Value::Call(call) => call.name == class_tag,
_ => panic!("expected call"),
}
} else {
false
}
}
pub fn external_is_subspecializer(
&mut self,
instance_id: u64,
left_class_tag: Symbol,
right_class_tag: Symbol,
) -> bool {
match self.get_external(instance_id) {
Value::Pattern(Pattern::Instance(literal)) => {
literal.tag == left_class_tag || literal.tag == right_class_tag
}
_ => panic!("expected instance literal"),
}
}
}