Skip to main content

graphix_compiler/node/
genn.rs

1use super::{
2    bind::Ref,
3    callsite::{Arg, ArgKey, CallSite},
4    Constant, Nop, NOP,
5};
6use crate::{
7    expr::{ExprId, ModPath, Origin},
8    typ::{FnType, Type},
9    BindId, ExecCtx, Node, Rt, Scope, UserEvent,
10};
11use ahash::AHashMap;
12use combine::stream::position::SourcePosition;
13use enumflags2::BitFlags;
14use netidx::publisher::{Typ, Value};
15use poolshark::local::LPooled;
16use triomphe::Arc;
17
18/// generate a no op with the specific type
19pub fn nop<R: Rt, E: UserEvent>(typ: Type) -> Node<R, E> {
20    Nop::new(typ)
21}
22
23/// bind a variable and return a node referencing it
24pub fn bind<R: Rt, E: UserEvent>(
25    ctx: &mut ExecCtx<R, E>,
26    scope: &ModPath,
27    name: &str,
28    typ: Type,
29    top_id: ExprId,
30) -> (BindId, Node<R, E>) {
31    // Generated bindings have no source position; pass defaults so IDE
32    // tooling can detect synthetic binds.
33    let id = ctx
34        .env
35        .bind_variable(
36            scope,
37            name,
38            typ.clone(),
39            SourcePosition::default(),
40            Arc::new(Origin::default()),
41        )
42        .id;
43    ctx.rt.ref_var(id, top_id);
44    (id, Box::new(Ref { spec: NOP.clone(), typ, id, top_id }))
45}
46
47/// generate a reference to a bind id
48pub fn reference<R: Rt, E: UserEvent>(
49    ctx: &mut ExecCtx<R, E>,
50    id: BindId,
51    typ: Type,
52    top_id: ExprId,
53) -> Node<R, E> {
54    ctx.rt.ref_var(id, top_id);
55    Box::new(Ref { spec: NOP.clone(), typ, id, top_id })
56}
57
58pub fn constant<R: Rt, E: UserEvent>(v: Value) -> Node<R, E> {
59    Box::new(Constant {
60        spec: NOP.clone(),
61        typ: Type::Primitive(Typ::get(&v).into()),
62        value: v,
63    })
64}
65
66/// generate and return an apply node for the given lambda
67pub fn apply<R: Rt, E: UserEvent>(
68    fnode: Node<R, E>,
69    scope: Scope,
70    args: Vec<Node<R, E>>,
71    typ: &FnType,
72    top_id: ExprId,
73) -> Node<R, E> {
74    let ftype = typ.reset_tvars();
75    ftype.alias_tvars(&mut LPooled::take());
76    let args: AHashMap<ArgKey, Arg<R, E>> = args
77        .into_iter()
78        .zip(typ.args.iter())
79        .enumerate()
80        .map(|(i, (node, farg))| {
81            let key = match farg.label() {
82                Some(name) => ArgKey::Named(name.clone()),
83                None => ArgKey::Positional(i),
84            };
85            (key, Arg { id: BindId::new(), node: Some(node), is_default: false })
86        })
87        .collect();
88    Box::new(CallSite {
89        spec: NOP.clone(),
90        rtype: ftype.rtype.clone(),
91        ftype: Some(ftype),
92        resolved_ftype: None,
93        args,
94        arg_refs: Vec::new(),
95        scope,
96        flags: BitFlags::empty(),
97        fnode,
98        function: None,
99        top_id,
100    })
101}