This commit is contained in:
Edgar 2024-02-03 14:33:42 +01:00
parent 40d71d6b83
commit cdc52cef39
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
4 changed files with 214 additions and 31 deletions

View file

@ -85,7 +85,7 @@ pub fn main() -> Result<(), Box<dyn Error>> {
return Ok(()); return Ok(());
} }
let module_irs = lower_modules(&[module.clone()]); let (_symbols, module_irs) = lower_modules(&[module.clone()]);
if args.ir { if args.ir {
println!("{:#?}", module_irs); println!("{:#?}", module_irs);

View file

@ -9,14 +9,14 @@ pub mod scalar_int;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ModuleBody { pub struct ModuleBody {
pub module_id: usize, pub module_id: DefId,
pub functions: BTreeMap<DefId, Body>, pub functions: BTreeMap<DefId, Body>,
pub modules: BTreeMap<DefId, Self>, pub modules: BTreeMap<DefId, Self>,
pub span: Span, pub span: Span,
} }
/// Definition id. /// Definition id.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct DefId { pub struct DefId {
pub module_id: usize, pub module_id: usize,
pub id: usize, pub id: usize,
@ -105,6 +105,34 @@ pub enum TypeKind {
FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types
} }
impl TypeKind {
pub fn get_falsy_value(&self) -> ValueTree {
match self {
Self::Bool => ValueTree::Leaf(ConstValue::Bool(false)),
Self::Char => todo!(),
Self::Int(ty) => match ty {
IntTy::I8 => ValueTree::Leaf(ConstValue::I8(0)),
IntTy::I16 => ValueTree::Leaf(ConstValue::I16(0)),
IntTy::I32 => ValueTree::Leaf(ConstValue::I32(0)),
IntTy::I64 => ValueTree::Leaf(ConstValue::I64(0)),
IntTy::I128 => ValueTree::Leaf(ConstValue::I128(0)),
IntTy::Isize => todo!(),
},
Self::Uint(ty) => match ty {
UintTy::U8 => ValueTree::Leaf(ConstValue::U8(0)),
UintTy::U16 => ValueTree::Leaf(ConstValue::U16(0)),
UintTy::U32 => ValueTree::Leaf(ConstValue::U32(0)),
UintTy::U64 => ValueTree::Leaf(ConstValue::U64(0)),
UintTy::U128 => ValueTree::Leaf(ConstValue::U128(0)),
UintTy::Usize => todo!(),
},
Self::Float(_) => todo!(),
TypeKind::Unit => unreachable!(),
TypeKind::FnDef(_, _) => unreachable!(),
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum IntTy { pub enum IntTy {
I128, I128,
@ -153,7 +181,9 @@ pub enum ValueTree {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum RValue { pub enum RValue {
Use(Operand), Use(Operand),
Ref(bool, Operand),
BinOp(BinOp, Operand, Operand), BinOp(BinOp, Operand, Operand),
LogicOp(LogicalOp, Operand, Operand),
UnOp(UnOp, Operand), UnOp(UnOp, Operand),
} }
@ -256,6 +286,13 @@ pub enum BinOp {
Offset, Offset,
} }
// Diferent than BinOp because operands needs to be lazily evaluated.
#[derive(Debug, Clone, Copy)]
pub enum LogicalOp {
And,
Or,
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum UnOp { pub enum UnOp {
Not, Not,

View file

@ -21,6 +21,13 @@ impl IdGenerator {
self.current_id self.current_id
} }
pub fn module_defid(&self) -> DefId {
DefId {
module_id: self.module_id,
id: 0,
}
}
pub fn next_defid(&mut self) -> DefId { pub fn next_defid(&mut self) -> DefId {
let id = self.next_id(); let id = self.next_id();
@ -29,19 +36,27 @@ impl IdGenerator {
id, id,
} }
} }
pub fn next_module_defid(&mut self) -> DefId {
self.module_id += 1;
self.current_id = 0;
self.module_defid()
}
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct BuildCtx { pub struct BuildCtx {
pub module_name_to_id: HashMap<String, usize>, pub module_name_to_id: HashMap<String, DefId>,
pub modules: HashMap<usize, ModuleCtx>, pub modules: HashMap<DefId, ModuleCtx>,
pub functions: HashMap<DefId, Body>, pub functions: HashMap<DefId, Body>,
pub module_id_counter: usize, pub gen: IdGenerator,
pub symbol_names: HashMap<DefId, String>,
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct ModuleCtx { pub struct ModuleCtx {
pub id: usize, pub id: DefId,
pub func_name_to_id: HashMap<String, DefId>, pub func_name_to_id: HashMap<String, DefId>,
pub functions: HashMap<DefId, (Vec<TypeInfo>, TypeInfo)>, pub functions: HashMap<DefId, (Vec<TypeInfo>, TypeInfo)>,
pub gen: IdGenerator, pub gen: IdGenerator,
@ -49,7 +64,7 @@ pub struct ModuleCtx {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BodyBuilder { pub struct BodyBuilder {
pub local_module: usize, pub local_module: DefId,
pub body: Body, pub body: Body,
pub statements: Vec<Statement>, pub statements: Vec<Statement>,
pub locals: HashMap<String, usize>, pub locals: HashMap<String, usize>,

View file

@ -3,17 +3,29 @@ use std::collections::HashMap;
use common::{BodyBuilder, BuildCtx, IdGenerator, ModuleCtx}; use common::{BodyBuilder, BuildCtx, IdGenerator, ModuleCtx};
use edlang_ast as ast; use edlang_ast as ast;
use edlang_ir as ir; use edlang_ir as ir;
use ir::{ConstData, ConstKind, Local, Operand, Place, Statement, Terminator, TypeInfo}; use ir::{ConstData, ConstKind, DefId, Local, Operand, Place, Statement, Terminator, TypeInfo};
mod common; mod common;
pub fn lower_modules(modules: &[ast::Module]) -> Vec<ir::ModuleBody> { pub fn lower_modules(modules: &[ast::Module]) -> (HashMap<DefId, String>, Vec<ir::ModuleBody>) {
let mut ctx = BuildCtx::default(); let mut ctx = BuildCtx::default();
for m in modules { for m in modules {
let module_id = ctx.gen.module_defid();
ctx.module_name_to_id ctx.module_name_to_id
.insert(m.name.name.clone(), ctx.module_id_counter); .insert(m.name.name.clone(), ctx.gen.module_defid());
ctx.module_id_counter += 1; ctx.symbol_names.insert(module_id, m.name.name.clone());
ctx.modules.insert(
module_id,
ModuleCtx {
id: module_id,
gen: IdGenerator::new(module_id.module_id),
..Default::default()
},
);
ctx.gen.next_module_defid();
} }
let mut lowered_modules = Vec::with_capacity(modules.len()); let mut lowered_modules = Vec::with_capacity(modules.len());
@ -26,7 +38,7 @@ pub fn lower_modules(modules: &[ast::Module]) -> Vec<ir::ModuleBody> {
lowered_modules.push(ir); lowered_modules.push(ir);
} }
lowered_modules (ctx.symbol_names, lowered_modules)
} }
fn lower_module(mut ctx: BuildCtx, module: &ast::Module) -> (BuildCtx, ir::ModuleBody) { fn lower_module(mut ctx: BuildCtx, module: &ast::Module) -> (BuildCtx, ir::ModuleBody) {
@ -38,19 +50,18 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module) -> (BuildCtx, ir::Modul
span: module.span, span: module.span,
}; };
let mut module_ctx = ModuleCtx {
id: body.module_id,
gen: IdGenerator::new(body.module_id),
..Default::default()
};
for stmt in &module.contents { for stmt in &module.contents {
match stmt { match stmt {
ast::ModuleStatement::Function(func) => { ast::ModuleStatement::Function(func) => {
let next_id = {
let module_ctx = ctx.modules.get_mut(&module_id).unwrap();
let next_id = module_ctx.gen.next_defid(); let next_id = module_ctx.gen.next_defid();
module_ctx module_ctx
.func_name_to_id .func_name_to_id
.insert(func.name.name.clone(), next_id); .insert(func.name.name.clone(), next_id);
ctx.symbol_names.insert(next_id, func.name.name.clone());
next_id
};
let mut args = Vec::new(); let mut args = Vec::new();
let ret_type; let ret_type;
@ -69,18 +80,15 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module) -> (BuildCtx, ir::Modul
args.push(ty); args.push(ty);
} }
let module_ctx = ctx.modules.get_mut(&module_id).unwrap();
module_ctx.functions.insert(next_id, (args, ret_type)); module_ctx.functions.insert(next_id, (args, ret_type));
} }
ast::ModuleStatement::Constant(_) => todo!(), ast::ModuleStatement::Constant(_) => todo!(),
ast::ModuleStatement::Struct(_) => todo!(), ast::ModuleStatement::Struct(_) => todo!(),
ast::ModuleStatement::Module(_) => todo!(), ast::ModuleStatement::Module(_) => {}
} }
} }
ctx.module_name_to_id
.insert(module.name.name.clone(), body.module_id);
ctx.modules.insert(body.module_id, module_ctx);
for stmt in &module.contents { for stmt in &module.contents {
match stmt { match stmt {
ast::ModuleStatement::Function(func) => { ast::ModuleStatement::Function(func) => {
@ -100,7 +108,7 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module) -> (BuildCtx, ir::Modul
fn lower_function( fn lower_function(
mut ctx: BuildCtx, mut ctx: BuildCtx,
func: &ast::Function, func: &ast::Function,
module_id: usize, module_id: DefId,
) -> (ir::Body, BuildCtx) { ) -> (ir::Body, BuildCtx) {
let def_id = *ctx let def_id = *ctx
.modules .modules
@ -226,7 +234,130 @@ fn lower_expr(
ast::Expression::Value(info) => ir::RValue::Use(lower_value(builder, info, type_hint)), ast::Expression::Value(info) => ir::RValue::Use(lower_value(builder, info, type_hint)),
ast::Expression::FnCall(info) => ir::RValue::Use(lower_fn_call(builder, info)), ast::Expression::FnCall(info) => ir::RValue::Use(lower_fn_call(builder, info)),
ast::Expression::Unary(_, _) => todo!(), ast::Expression::Unary(_, _) => todo!(),
ast::Expression::Binary(_, _, _) => todo!(), ast::Expression::Binary(lhs, op, rhs) => {
lower_binary_expr(builder, lhs, op, rhs, type_hint)
}
}
}
fn lower_binary_expr(
builder: &mut BodyBuilder,
lhs: &ast::Expression,
op: &ast::BinaryOp,
rhs: &ast::Expression,
type_hint: Option<&TypeInfo>,
) -> ir::RValue {
let expr_type = type_hint.expect("type hint needed");
let lhs = {
let rvalue = lower_expr(builder, lhs, type_hint);
let local = builder.add_local(Local {
mutable: false,
span: None,
ty: expr_type.clone(),
kind: ir::LocalKind::Temp,
});
builder.statements.push(Statement {
span: None,
kind: ir::StatementKind::StorageLive(local),
});
let place = Place {
local,
projection: Default::default(),
};
builder.statements.push(Statement {
span: None,
kind: ir::StatementKind::Assign(place.clone(), rvalue),
});
place
};
let rhs = {
let rvalue = lower_expr(builder, rhs, type_hint);
let local = builder.add_local(Local {
mutable: false,
span: None,
ty: expr_type.clone(),
kind: ir::LocalKind::Temp,
});
builder.statements.push(Statement {
span: None,
kind: ir::StatementKind::StorageLive(local),
});
let place = Place {
local,
projection: Default::default(),
};
builder.statements.push(Statement {
span: None,
kind: ir::StatementKind::Assign(place.clone(), rvalue),
});
place
};
match op {
ast::BinaryOp::Arith(op, _) => match op {
ast::ArithOp::Add => {
ir::RValue::BinOp(ir::BinOp::Add, Operand::Move(lhs), Operand::Move(rhs))
}
ast::ArithOp::Sub => {
ir::RValue::BinOp(ir::BinOp::Sub, Operand::Move(lhs), Operand::Move(rhs))
}
ast::ArithOp::Mul => {
ir::RValue::BinOp(ir::BinOp::Mul, Operand::Move(lhs), Operand::Move(rhs))
}
ast::ArithOp::Div => {
ir::RValue::BinOp(ir::BinOp::Div, Operand::Move(lhs), Operand::Move(rhs))
}
ast::ArithOp::Mod => {
ir::RValue::BinOp(ir::BinOp::Rem, Operand::Move(lhs), Operand::Move(rhs))
}
},
ast::BinaryOp::Logic(op, _) => match op {
ast::LogicOp::And => {
ir::RValue::LogicOp(ir::LogicalOp::And, Operand::Move(lhs), Operand::Move(rhs))
}
ast::LogicOp::Or => {
ir::RValue::LogicOp(ir::LogicalOp::Or, Operand::Move(lhs), Operand::Move(rhs))
}
},
ast::BinaryOp::Compare(op, _) => match op {
ast::CmpOp::Eq => {
ir::RValue::BinOp(ir::BinOp::Eq, Operand::Move(lhs), Operand::Move(rhs))
}
ast::CmpOp::NotEq => {
ir::RValue::BinOp(ir::BinOp::Ne, Operand::Move(lhs), Operand::Move(rhs))
}
ast::CmpOp::Lt => {
ir::RValue::BinOp(ir::BinOp::Lt, Operand::Move(lhs), Operand::Move(rhs))
}
ast::CmpOp::LtEq => {
ir::RValue::BinOp(ir::BinOp::Le, Operand::Move(lhs), Operand::Move(rhs))
}
ast::CmpOp::Gt => {
ir::RValue::BinOp(ir::BinOp::Gt, Operand::Move(lhs), Operand::Move(rhs))
}
ast::CmpOp::GtEq => {
ir::RValue::BinOp(ir::BinOp::Ge, Operand::Move(lhs), Operand::Move(rhs))
}
},
ast::BinaryOp::Bitwise(op, _) => match op {
ast::BitwiseOp::And => {
ir::RValue::BinOp(ir::BinOp::BitAnd, Operand::Move(lhs), Operand::Move(rhs))
}
ast::BitwiseOp::Or => {
ir::RValue::BinOp(ir::BinOp::BitOr, Operand::Move(lhs), Operand::Move(rhs))
}
ast::BitwiseOp::Xor => {
ir::RValue::BinOp(ir::BinOp::BitXor, Operand::Move(lhs), Operand::Move(rhs))
}
},
} }
} }
@ -446,7 +577,7 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> ir::Place {
} }
} }
pub fn lower_type(ctx: &mut BuildCtx, t: &ast::Type) -> ir::TypeInfo { pub fn lower_type(_ctx: &mut BuildCtx, t: &ast::Type) -> ir::TypeInfo {
match t.name.name.as_str() { match t.name.name.as_str() {
"()" => ir::TypeInfo { "()" => ir::TypeInfo {
span: Some(t.span), span: Some(t.span),