//! ClosureNode — the executable IR produced from typed ASTs.
//!
//! Adapted from the platform evaluator. Dependencies stripped to pfcl-catalog only.

use std::sync::Arc;
use pfcl_types::{Hash, Value};
use pfcl_catalog::{NativeFn, Intrinsic};

/// An executable node in the closure graph.
#[derive(Clone)]
pub enum ClosureNode {
    Literal(Value),
    Var(usize),
    Primitive { func: NativeFn, name: String },
    Apply { func: Box<ClosureNode>, args: Vec<ClosureNode> },
    Lambda { arity: usize, body: Box<ClosureNode> },
    Let { value: Box<ClosureNode>, body: Box<ClosureNode> },
    Match { scrutinee: Box<ClosureNode>, arms: Vec<ClosureArm> },
    ListLit(Vec<ClosureNode>),
    RecordLit(Vec<(String, ClosureNode)>),
    TupleLit(Vec<ClosureNode>),
    Constructor { name: String, args: Vec<ClosureNode> },
    FieldAccess { expr: Box<ClosureNode>, fields: Vec<String> },
    ComposedRef { hash: Hash, name: String },
    Intrinsic { id: Intrinsic, name: String },
}

#[derive(Clone)]
pub struct ClosureArm {
    pub pattern: ClosurePattern,
    pub body: ClosureNode,
}

#[derive(Debug, Clone)]
pub enum ClosurePattern {
    Wildcard,
    Var,
    IntPat(i64),
    StringPat(String),
    BoolPat(bool),
    NothingPat,
    Constructor { name: String, args: Vec<ClosurePattern> },
    TuplePat(Vec<ClosurePattern>),
}

impl core::fmt::Debug for ClosureNode {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            ClosureNode::Literal(v)          => write!(f, "Lit({:?})", v),
            ClosureNode::Var(i)              => write!(f, "Var({})", i),
            ClosureNode::Primitive{name,..}  => write!(f, "Prim({})", name),
            ClosureNode::Apply{func,args}    => write!(f, "Apply({:?}, {} args)", func, args.len()),
            ClosureNode::Lambda{arity,..}    => write!(f, "Lam({})", arity),
            ClosureNode::Let{..}             => write!(f, "Let"),
            ClosureNode::Match{arms,..}      => write!(f, "Match({} arms)", arms.len()),
            ClosureNode::ListLit(e)          => write!(f, "List({})", e.len()),
            ClosureNode::RecordLit(fields)   => write!(f, "Rec({})", fields.len()),
            ClosureNode::TupleLit(e)         => write!(f, "Tuple({})", e.len()),
            ClosureNode::Constructor{name,..}=> write!(f, "Ctor({})", name),
            ClosureNode::FieldAccess{fields,..} => write!(f, "Field(.{})", fields.join(".")),
            ClosureNode::ComposedRef{name,..}=> write!(f, "Composed({})", name),
            ClosureNode::Intrinsic{id,..}    => write!(f, "Intrinsic({:?})", id),
        }
    }
}

impl core::fmt::Debug for ClosureArm {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{:?} => {:?}", self.pattern, self.body)
    }
}
