basic struct

This commit is contained in:
Edgar 2024-02-17 18:41:33 +01:00
parent a4ca9c2ecd
commit a9cd4eff86
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
3 changed files with 137 additions and 13 deletions

View file

@ -1160,6 +1160,21 @@ fn compile_basic_type<'ctx>(
.ptr_sized_int_type(&ctx.target_data, None)
.ptr_type(AddressSpace::default())
.as_basic_type_enum(),
ir::TypeKind::Struct(id) => {
let body = ctx.ctx.program.structs.get(id).unwrap();
let mut fields = Vec::new();
for field in &body.variants {
let ty = compile_basic_type(ctx, &field.ty);
fields.push(ty);
}
ctx.ctx
.context
.struct_type(&fields, false)
.as_basic_type_enum()
}
}
}
@ -1277,5 +1292,40 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo)
.di_builder
.create_reference_type(compile_debug_type(ctx, inner), 0x10)
.as_type(),
ir::TypeKind::Struct(id) => {
let body = ctx.ctx.program.structs.get(id).unwrap();
let mut fields = Vec::new();
for field in &body.variants {
let ty = compile_debug_type(ctx, &field.ty);
fields.push(ty);
}
let (_, line, _column) = ctx
.ctx
.session
.source
.get_offset_line(body.span.lo)
.unwrap();
let real_ty = compile_basic_type(ctx, ty);
ctx.di_builder
.create_struct_type(
ctx.di_namespace,
&body.name,
ctx.di_unit.get_file(),
(line + 1).try_into().unwrap(),
ctx.target_data.get_bit_size(&real_ty),
ctx.target_data.get_abi_alignment(&real_ty),
0,
None,
&fields,
0,
None,
&body.name,
)
.as_type()
}
}
}

View file

@ -26,6 +26,7 @@ pub struct ProgramBody {
pub modules: BTreeMap<DefId, ModuleBody>,
/// This stores all the functions from all modules
pub functions: BTreeMap<DefId, Body>,
pub structs: BTreeMap<DefId, AdtBody>,
/// The function signatures.
pub function_signatures: BTreeMap<DefId, (Vec<TypeInfo>, TypeInfo)>,
}
@ -87,6 +88,23 @@ impl Body {
}
}
#[derive(Debug, Clone)]
pub struct AdtBody {
pub def_id: DefId,
pub is_pub: bool,
pub name: String,
pub variants: Vec<AdtVariant>,
pub span: Span,
}
/// struct field or enum variant
#[derive(Debug, Clone)]
pub struct AdtVariant {
pub def_id: DefId,
pub name: String,
pub ty: TypeInfo,
}
#[derive(Debug, Clone)]
pub struct DebugInfo {
pub id: usize,
@ -205,6 +223,7 @@ pub enum TypeKind {
FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types
Ptr(Box<TypeInfo>),
Ref(bool, Box<TypeInfo>),
Struct(DefId),
}
impl TypeKind {
@ -241,6 +260,7 @@ impl TypeKind {
TypeKind::FnDef(_, _) => unreachable!(),
TypeKind::Ptr(_pointee) => todo!(),
TypeKind::Ref(_, inner) => inner.kind.get_falsy_value(),
TypeKind::Struct(_) => todo!(),
}
}
}

View file

@ -5,8 +5,8 @@ use common::{BodyBuilder, BuildCtx};
use edlang_ast as ast;
use edlang_ir as ir;
use ir::{
BasicBlock, Body, DefId, Local, LocalKind, Operand, Place, PlaceElem, ProgramBody, RValue,
Statement, StatementKind, SwitchTarget, Terminator, TypeInfo, TypeKind,
AdtBody, AdtVariant, BasicBlock, Body, DefId, Local, LocalKind, Operand, Place, PlaceElem,
ProgramBody, RValue, Statement, StatementKind, SwitchTarget, Terminator, TypeInfo, TypeKind,
};
use tracing::trace;
@ -40,6 +40,18 @@ pub fn lower_modules(modules: &[ast::Module]) -> ProgramBody {
}
fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx {
// lower first structs, constants, types
for content in &module.contents {
match content {
ModuleStatement::Constant(_) => todo!(),
ModuleStatement::Struct(info) => {
ctx = lower_struct(ctx, info, id);
}
// ModuleStatement::Type(_) => todo!(),
_ => {}
}
}
let body = ctx.body.modules.get(&id).unwrap();
// fill fn sigs
@ -51,12 +63,12 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx
let ret_type;
for arg in &fn_def.params {
let ty = lower_type(&ctx, &arg.arg_type);
let ty = lower_type(&ctx, &arg.arg_type, id);
args.push(ty);
}
if let Some(ty) = &fn_def.return_type {
ret_type = lower_type(&ctx, ty);
ret_type = lower_type(&ctx, ty, id);
} else {
ret_type = TypeInfo {
span: None,
@ -70,19 +82,43 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx
for content in &module.contents {
match content {
ModuleStatement::Constant(_) => todo!(),
ModuleStatement::Function(fn_def) => {
ctx = lower_function(ctx, fn_def, id);
}
ModuleStatement::Struct(_) => todo!(),
// ModuleStatement::Type(_) => todo!(),
ModuleStatement::Module(_mod_def) => {}
_ => {}
}
}
ctx
}
fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> BuildCtx {
let mut body = AdtBody {
def_id: {
let body = ctx.body.modules.get(&module_id).unwrap();
*body.symbols.structs.get(&info.name.name).unwrap()
},
is_pub: true, // todo struct pub
name: info.name.name.clone(),
variants: Vec::new(),
span: info.span,
};
for field in &info.fields {
let variant = AdtVariant {
def_id: ctx.gen.next_defid(),
name: field.name.name.clone(),
ty: lower_type(&ctx, &field.r#type, module_id),
};
body.variants.push(variant);
}
ctx.body.structs.insert(body.def_id, body);
ctx
}
fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> BuildCtx {
let mut builder = BodyBuilder {
body: Body {
@ -141,7 +177,7 @@ fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> Buil
// Get all user defined locals
for stmt in &func.body.body {
if let ast::Statement::Let(info) = stmt {
let ty = lower_type(&builder.ctx, &info.r#type);
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module);
builder
.name_to_local
.insert(info.name.name.clone(), builder.body.locals.len());
@ -360,7 +396,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK
}
fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
let ty = lower_type(&builder.ctx, &info.r#type);
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module);
let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty.kind));
let local_idx = builder.name_to_local.get(&info.name.name).copied().unwrap();
builder.statements.push(Statement {
@ -665,10 +701,13 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand,
.get(&fn_id)
.unwrap();
let args: Vec<_> = args.iter().map(|x| lower_type(&builder.ctx, x)).collect();
let args: Vec<_> = args
.iter()
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
.collect();
let ret = ret
.as_ref()
.map(|x| lower_type(&builder.ctx, x))
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
.unwrap_or(TypeInfo {
span: None,
kind: TypeKind::Unit,
@ -904,7 +943,7 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
}
#[allow(clippy::only_used_in_recursion)]
pub fn lower_type(ctx: &BuildCtx, t: &ast::Type) -> ir::TypeInfo {
pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeInfo {
let inner_ty = match t.name.name.as_str() {
"()" => ir::TypeInfo {
span: Some(t.span),
@ -960,9 +999,24 @@ pub fn lower_type(ctx: &BuildCtx, t: &ast::Type) -> ir::TypeInfo {
},
"ptr" => ir::TypeInfo {
span: Some(t.span),
kind: ir::TypeKind::Ptr(Box::new(lower_type(ctx, t.generics.first().unwrap()))),
kind: ir::TypeKind::Ptr(Box::new(lower_type(
ctx,
t.generics.first().unwrap(),
module_id,
))),
},
x => todo!("{:?}", x),
other => {
let module = ctx.body.modules.get(&module_id).expect("module not found");
if let Some(struct_id) = module.symbols.structs.get(other) {
let struct_body = ctx.body.structs.get(struct_id).unwrap();
ir::TypeInfo {
span: Some(struct_body.span),
kind: TypeKind::Struct(*struct_id),
}
} else {
todo!("{:?}", other)
}
}
};
match t.is_ref {