mod dead_code;
mod lower;
mod print;
use crate::{
ast::{BinOp, Identifier, Literal},
label::LabelRef,
runtime,
typechecker::{
scope::{ResolvedName, ScopeRef},
types::{EnumVariant, Signature, Type},
},
};
pub use lower::lower_to_mir;
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[must_use]
pub struct Var {
pub scope: ScopeRef,
pub kind: VarKind,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum VarKind {
Explicit(Identifier),
Tmp(usize),
}
#[derive(Clone, Debug)]
pub struct Mir {
pub functions: Vec<Function>,
}
#[derive(Clone, Debug)]
pub struct Function {
pub name: Identifier,
pub scope: ScopeRef,
pub variables: Vec<(Var, Type)>,
pub parameters: Vec<Var>,
pub signature: Signature,
pub blocks: Vec<Block>,
pub tmp_idx: usize,
}
#[derive(Clone, Debug)]
pub struct Block {
pub label: LabelRef,
pub instructions: Vec<Instruction>,
}
#[derive(Clone, Debug)]
pub struct Place {
pub var: Var,
pub root_ty: Type,
pub projection: Vec<Projection>,
}
impl Place {
pub fn new(value: Var, ty: Type) -> Self {
Self {
var: value,
root_ty: ty,
projection: Vec::new(),
}
}
}
#[derive(Clone, Debug)]
pub enum Projection {
VariantField(Identifier, usize),
Field(Identifier),
}
#[derive(Clone, Debug)]
#[must_use]
pub enum Value {
Const(Literal, Type),
Constant(ResolvedName, Type),
Context(usize),
Clone(Place),
Discriminant(Var),
Not(Var),
Negate(Var, Type),
Move(Var),
BinOp {
left: Var,
binop: BinOp,
ty: Type,
right: Var,
},
Call {
func: ResolvedName,
args: Vec<Var>,
},
CallRuntime {
func_ref: runtime::RuntimeFunctionRef,
args: Vec<Var>,
type_params: Vec<Type>,
},
}
#[derive(Clone, Debug)]
pub enum Instruction {
Jump(LabelRef),
Switch {
examinee: Var,
branches: Vec<(usize, LabelRef)>,
default: Option<LabelRef>,
},
Assign {
to: Place,
ty: Type,
value: Value,
},
SetDiscriminant {
to: Var,
ty: Type,
variant: EnumVariant,
},
Return {
var: Var,
},
Drop {
val: Place,
ty: Type,
},
}