mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-23 00:18:24 +00:00
nice
This commit is contained in:
parent
40d71d6b83
commit
cdc52cef39
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in a new issue