136 lines
3.5 KiB
Rust
136 lines
3.5 KiB
Rust
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<DefId, FunctionDefinition>,
|
|
pub entrypoint: Vec<Statement>,
|
|
}
|
|
|
|
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<Expression>),
|
|
List(Vec<Expression>),
|
|
Lookup(Lookup),
|
|
Assign { lval: DefId, rval: Box<Expression> },
|
|
Access { name: String, expr: Box<Expression> },
|
|
Callable(Callable),
|
|
Call { f: Box<Expression>, args: Vec<Expression> },
|
|
Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> },
|
|
CaseMatch { cond: Box<Expression>, alternatives: Vec<Alternative> },
|
|
Loop { cond: Box<Expression>, statements: Vec<Statement> },
|
|
Index { indexee: Box<Expression>, indexer: Box<Expression> },
|
|
ReductionError(String),
|
|
}
|
|
|
|
impl Expression {
|
|
pub fn unit() -> Self {
|
|
Expression::Tuple(vec![])
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct FunctionDefinition {
|
|
pub body: Vec<Statement>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Callable {
|
|
Builtin(Builtin),
|
|
UserDefined(DefId),
|
|
Lambda { arity: u8, body: Vec<Statement> },
|
|
DataConstructor { type_id: TypeId, tag: u32 },
|
|
RecordConstructor { type_id: TypeId, tag: u32, field_order: Vec<String> },
|
|
}
|
|
|
|
#[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<String>),
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Alternative {
|
|
pub pattern: Pattern,
|
|
pub item: Vec<Statement>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Pattern {
|
|
Tuple { subpatterns: Vec<Pattern>, tag: Option<u32> },
|
|
Record { tag: u32, subpatterns: Vec<(Rc<String>, 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<String> for PatternError {
|
|
fn from(msg: String) -> Self {
|
|
Self { msg }
|
|
}
|
|
}
|