use super::{
bind::Ref,
callsite::{Arg, ArgKey, CallSite},
Constant, Nop, NOP,
};
use crate::{
expr::{ExprId, ModPath, Origin},
typ::{FnType, Type},
BindId, ExecCtx, Node, Rt, Scope, UserEvent,
};
use ahash::AHashMap;
use combine::stream::position::SourcePosition;
use enumflags2::BitFlags;
use netidx::publisher::{Typ, Value};
use poolshark::local::LPooled;
use triomphe::Arc;
pub fn nop<R: Rt, E: UserEvent>(typ: Type) -> Node<R, E> {
Nop::new(typ)
}
pub fn bind<R: Rt, E: UserEvent>(
ctx: &mut ExecCtx<R, E>,
scope: &ModPath,
name: &str,
typ: Type,
top_id: ExprId,
) -> (BindId, Node<R, E>) {
let id = ctx
.env
.bind_variable(
scope,
name,
typ.clone(),
SourcePosition::default(),
Arc::new(Origin::default()),
)
.id;
ctx.rt.ref_var(id, top_id);
(id, Box::new(Ref { spec: NOP.clone(), typ, id, top_id }))
}
pub fn reference<R: Rt, E: UserEvent>(
ctx: &mut ExecCtx<R, E>,
id: BindId,
typ: Type,
top_id: ExprId,
) -> Node<R, E> {
ctx.rt.ref_var(id, top_id);
Box::new(Ref { spec: NOP.clone(), typ, id, top_id })
}
pub fn constant<R: Rt, E: UserEvent>(v: Value) -> Node<R, E> {
Box::new(Constant {
spec: NOP.clone(),
typ: Type::Primitive(Typ::get(&v).into()),
value: v,
})
}
pub fn apply<R: Rt, E: UserEvent>(
fnode: Node<R, E>,
scope: Scope,
args: Vec<Node<R, E>>,
typ: &FnType,
top_id: ExprId,
) -> Node<R, E> {
let ftype = typ.reset_tvars();
ftype.alias_tvars(&mut LPooled::take());
let args: AHashMap<ArgKey, Arg<R, E>> = args
.into_iter()
.zip(typ.args.iter())
.enumerate()
.map(|(i, (node, farg))| {
let key = match farg.label() {
Some(name) => ArgKey::Named(name.clone()),
None => ArgKey::Positional(i),
};
(key, Arg { id: BindId::new(), node: Some(node), is_default: false })
})
.collect();
Box::new(CallSite {
spec: NOP.clone(),
rtype: ftype.rtype.clone(),
ftype: Some(ftype),
resolved_ftype: None,
args,
arg_refs: Vec::new(),
scope,
flags: BitFlags::empty(),
fnode,
function: None,
top_id,
})
}