use std::{collections::HashMap, convert::From, rc::Rc}; use crate::{ builtin::Builtin, symbol_table::{DefId, SymbolTable}, type_inference::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 }, Return(Expression), Continue, Break, } #[derive(Debug, Clone)] pub enum Expression { Literal(Literal), Tuple(Vec), List(Vec), Lookup(Lookup), Assign { lval: DefId, rval: Box }, Access { name: String, expr: Box }, Callable(Callable), Call { f: Box, args: Vec }, Conditional { cond: Box, then_clause: Vec, else_clause: Vec }, CaseMatch { cond: Box, alternatives: Vec }, Loop { cond: Box, statements: Vec }, Index { indexee: Box, indexer: Box }, 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, tag: u32 }, RecordConstructor { type_id: TypeId, tag: u32, field_order: Vec }, } #[derive(Debug, Clone)] pub enum Lookup { LocalVar(DefId), GlobalVar(DefId), Function(DefId), Param(u8), } #[derive(Debug, Clone, PartialEq)] 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 { Tuple { subpatterns: Vec, tag: Option }, Record { tag: u32, subpatterns: Vec<(Rc, Pattern)> }, Literal(Literal), Ignored, Binding(DefId), } #[allow(dead_code)] #[derive(Debug)] pub struct PatternError { msg: String, } impl From<&str> for PatternError { fn from(s: &str) -> Self { Self { msg: s.to_string() } } } impl From for PatternError { fn from(msg: String) -> Self { Self { msg } } }