use std::collections::HashMap; use std::rc::Rc; use std::convert::From; use crate::builtin::Builtin; use crate::symbol_table::{DefId, SymbolTable}; use crate::typechecking::TypeId; //TODO most of these Clone impls only exist to support function application, because the //tree-walking evaluator moves the reduced IR members. /// The reduced intermediate representation consists of a list of function definitions, and a block /// of entrypoint statements. In a repl or script context this can be an arbitrary list of /// statements, in an executable context will likely just be a pointer to the main() function. #[derive(Debug)] pub struct ReducedIR { pub functions: HashMap, pub entrypoint: Vec, } impl ReducedIR { #[allow(dead_code)] pub fn debug(&self, symbol_table: &SymbolTable) { println!("Reduced IR:"); println!("Functions:"); println!("-----------"); for (id, callable) in self.functions.iter() { let name = &symbol_table.lookup_symbol_by_def(id).unwrap().local_name(); println!("{}({}) -> {:?}", id, name, callable); } println!(""); println!("Entrypoint:"); println!("-----------"); for stmt in self.entrypoint.iter() { println!("{:?}", stmt); } println!("-----------"); } } #[derive(Debug, Clone)] pub enum Statement { Expression(Expression), Binding { id: DefId, constant: bool, expr: Expression }, } #[derive(Debug, Clone)] pub enum Expression { Literal(Literal), Tuple(Vec), Lookup(Lookup), Assign { lval: DefId, rval: Box, }, Callable(Callable), Call { f: Box, args: Vec }, Conditional { cond: Box, then_clause: Vec, else_clause: Vec, }, CaseMatch { cond: Box, alternatives: Vec, }, ReductionError(String), } impl Expression { pub fn unit() -> Self { Expression::Tuple(vec![]) } } #[derive(Debug)] pub struct FunctionDefinition { pub body: Vec } #[derive(Debug, Clone)] pub enum Callable { Builtin(Builtin), UserDefined(DefId), Lambda { arity: u8, body: Vec }, DataConstructor { type_id: TypeId, arity: u32, tag: u32 }, } #[derive(Debug, Clone)] pub enum Lookup { LocalVar(DefId), GlobalVar(DefId), Function(DefId), Param(u8), } #[derive(Debug, Clone)] pub enum Literal { Nat(u64), Int(i64), Float(f64), Bool(bool), StringLit(Rc), } #[derive(Debug, Clone)] pub struct Alternative { pub pattern: Pattern, pub item: Vec, } #[derive(Debug, Clone)] pub enum Pattern { Literal(Literal), Ignored, } /* #[derive(Debug, Clone)] pub struct Subpattern { pub tag: Option, pub subpatterns: Vec>, //pub bound_vars: BoundVars, pub guard: Option, } */ #[derive(Debug)] pub struct PatternError { msg: String, } impl From<&str> for PatternError { fn from(s: &str) -> Self { Self { msg: s.to_string() } } }