154 lines
3.3 KiB
Rust
154 lines
3.3 KiB
Rust
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<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
|
|
},
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Expression {
|
|
Literal(Literal),
|
|
Tuple(Vec<Expression>),
|
|
Lookup(Lookup),
|
|
Assign {
|
|
lval: DefId,
|
|
rval: 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>,
|
|
},
|
|
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,
|
|
arity: u32,
|
|
tag: u32
|
|
},
|
|
}
|
|
|
|
#[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>,
|
|
},
|
|
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 }
|
|
}
|
|
}
|