initial structure impl

This commit is contained in:
2025-03-26 21:39:24 -04:00
parent 0614d48fcc
commit 021434d2f1
23 changed files with 390 additions and 84 deletions

View File

@@ -1,7 +1,7 @@
use crate::common::FileSpan;
use crate::{common::FileSpan, ir::{Len, Size}};
use super::Type;
use std::fmt::Debug;
use std::{collections::HashMap, fmt::Debug};
#[derive(Clone)]
pub struct FnDef {
@@ -12,9 +12,16 @@ pub struct FnDef {
}
#[derive(Clone)]
pub struct TypeDef {
pub struct StructField {
pub ty: Type,
pub offset: Len,
}
#[derive(Clone)]
pub struct StructDef {
pub name: String,
pub args: usize,
pub fields: HashMap<String, StructField>,
pub size: Size,
pub origin: Origin,
}

View File

@@ -1,6 +1,8 @@
use std::fmt::Write;
use std::{collections::HashMap, fmt::Write};
use super::{arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, Type, VarID};
use super::{
arch::riscv64::RV64Instruction, inst::VarInst, DataID, FnID, IRUInstrInst, Type, VarID,
};
use crate::{common::FileSpan, compiler::arch::riscv::Reg, util::Padder};
pub struct IRUFunction {
@@ -31,6 +33,11 @@ pub enum IRUInstruction {
dest: VarInst,
src: FnID,
},
Access {
dest: VarInst,
src: VarInst,
field: String,
},
Call {
dest: VarInst,
f: VarInst,
@@ -43,6 +50,10 @@ pub enum IRUInstruction {
Ret {
src: VarInst,
},
Construct {
dest: VarInst,
fields: HashMap<String, VarInst>,
},
}
pub struct IRInstructions {
@@ -84,6 +95,8 @@ impl std::fmt::Debug for IRUInstruction {
} => write!(f, "{dest:?} <- {func:?}({args:?})"),
Self::AsmBlock { args, instructions } => write!(f, "asm {args:?} {instructions:#?}"),
Self::Ret { src } => f.debug_struct("Ret").field("src", src).finish(),
Self::Construct { dest, fields } => write!(f, "{dest:?} <- {fields:?}"),
Self::Access { dest, src, field } => write!(f, "{dest:?} <- {src:?}.{field}"),
}
}
}

View File

@@ -11,7 +11,7 @@ use super::{inst::VarInst, *};
pub struct IRUProgram {
pub fn_defs: Vec<FnDef>,
pub var_defs: Vec<VarDef>,
pub type_defs: Vec<TypeDef>,
pub type_defs: Vec<StructDef>,
pub data_defs: Vec<DataDef>,
pub fns: Vec<Option<IRUFunction>>,
pub data: Vec<Vec<u8>>,
@@ -59,7 +59,7 @@ impl IRUProgram {
pub fn get_fn_var(&self, id: VarID) -> Option<&FnDef> {
Some(&self.fn_defs[self.fn_map.get(&id)?.0])
}
pub fn get_type(&self, id: TypeID) -> &TypeDef {
pub fn get_struct(&self, id: TypeID) -> &StructDef {
&self.type_defs[id.0]
}
pub fn alias_fn(&mut self, name: &str, id: FnID) {
@@ -82,10 +82,7 @@ impl IRUProgram {
pub fn size_of_type(&self, ty: &Type) -> Option<Size> {
// TODO: target matters
Some(match ty {
Type::Concrete(id) => {
let def = &self.type_defs[id.0];
todo!()
}
Type::Concrete(id) => self.type_defs[id.0].size,
Type::Bits(b) => *b,
Type::Generic { base, args } => todo!(),
Type::Fn { args, ret } => todo!(),
@@ -131,7 +128,7 @@ impl IRUProgram {
id
}
pub fn def_type(&mut self, def: TypeDef) -> TypeID {
pub fn def_type(&mut self, def: StructDef) -> TypeID {
let i = self.type_defs.len();
let id = TypeID(i);
self.insert(&def.name, Ident::Type(id));
@@ -148,10 +145,10 @@ impl IRUProgram {
let mut str = String::new();
match ty {
Type::Concrete(t) => {
str += &self.get_type(*t).name;
str += &self.get_struct(*t).name;
}
Type::Generic { base, args } => {
str += &self.get_type(*base).name;
str += &self.get_struct(*base).name;
if let Some(arg) = args.first() {
str = str + "<" + &self.type_name(arg);
}

View File

@@ -1,4 +1,4 @@
use super::{IRUInstruction, IRUProgram, Len, TypeID};
use super::{IRUProgram, Len, TypeID};
#[derive(Clone, PartialEq)]
pub enum Type {
@@ -30,14 +30,7 @@ pub fn resolve_types(ns: &IRUProgram) {
for (i, f) in ns.iter_fns() {
for inst in &f.instructions {
match &inst.i {
IRUInstruction::Mv { dest, src } => todo!(),
IRUInstruction::Ref { dest, src } => todo!(),
IRUInstruction::LoadData { dest, src } => todo!(),
IRUInstruction::LoadSlice { dest, src } => todo!(),
IRUInstruction::LoadFn { dest, src } => todo!(),
IRUInstruction::Call { dest, f, args } => todo!(),
IRUInstruction::AsmBlock { instructions, args } => todo!(),
IRUInstruction::Ret { src } => todo!(),
_ => todo!(),
}
}
}

View File

@@ -1,5 +1,5 @@
// TODO: move this into ir, not parser
use super::{IRUProgram, Type};
use super::{IRUInstruction, IRUProgram, Type};
use crate::common::{CompilerMsg, CompilerOutput};
impl IRUProgram {
@@ -8,18 +8,18 @@ impl IRUProgram {
for (f, fd) in self.fns.iter().flatten().zip(&self.fn_defs) {
for i in &f.instructions {
match &i.i {
super::IRUInstruction::Mv { dest, src } => {
IRUInstruction::Mv { dest, src } => {
let dest = self.get_var(dest.id);
let src = self.get_var(src.id);
output.check_assign(self, &src.ty, &dest.ty, i.span);
}
super::IRUInstruction::Ref { dest, src } => todo!(),
super::IRUInstruction::LoadData { dest, src } => {
IRUInstruction::Ref { dest, src } => todo!(),
IRUInstruction::LoadData { dest, src } => {
let dest = self.get_var(dest.id);
let src = self.get_data(*src);
output.check_assign(self, &src.ty, &dest.ty, i.span);
}
super::IRUInstruction::LoadSlice { dest, src } => {
IRUInstruction::LoadSlice { dest, src } => {
let dest = self.get_var(dest.id);
let src = self.get_data(*src);
let Type::Array(srcty, ..) = &src.ty else {
@@ -27,8 +27,8 @@ impl IRUProgram {
};
output.check_assign(self, &Type::Slice(srcty.clone()), &dest.ty, i.span);
}
super::IRUInstruction::LoadFn { dest, src } => todo!(),
super::IRUInstruction::Call { dest, f, args } => {
IRUInstruction::LoadFn { dest, src } => todo!(),
IRUInstruction::Call { dest, f, args } => {
let destty = &self.get_var(dest.id).ty;
let f = self.get_var(f.id);
let Type::Fn { args: argtys, ret } = &f.ty else {
@@ -46,13 +46,66 @@ impl IRUProgram {
output.check_assign(self, argt, &dest.ty, argv.span);
}
}
super::IRUInstruction::AsmBlock { instructions, args } => {
IRUInstruction::AsmBlock { instructions, args } => {
// TODO
}
super::IRUInstruction::Ret { src } => {
IRUInstruction::Ret { src } => {
let srcty = &self.get_var(src.id).ty;
output.check_assign(self, srcty, &fd.ret, src.span);
},
}
IRUInstruction::Construct { dest, fields } => {
let dest_def = self.get_var(dest.id);
let tyid = match dest_def.ty {
Type::Concrete(id) => id,
_ => {
output.err(CompilerMsg {
msg: "uhh type is not struct".to_string(),
spans: vec![dest.span],
});
continue;
}
};
let def = self.get_struct(tyid);
for (name, field) in &def.fields {
if let Some(var) = fields.get(name) {
let ety = &self.get_var(var.id).ty;
output.check_assign(self, &field.ty, ety, var.span);
} else {
output.err(CompilerMsg {
msg: format!("field '{name}' missing from struct"),
spans: vec![dest.span],
});
}
}
for name in fields.keys() {
if !def.fields.contains_key(name) {
output.err(CompilerMsg {
msg: format!("field '{name}' not in struct"),
spans: vec![dest.span],
});
}
}
}
IRUInstruction::Access { dest, src, field } => {
let dest_def = self.get_var(dest.id);
let src_def = self.get_var(src.id);
let tyid = match src_def.ty {
Type::Concrete(id) => id,
_ => {
output.err(CompilerMsg {
msg: "uhh type is not struct".to_string(),
spans: vec![dest.span],
});
continue;
}
};
let def = self.get_struct(tyid);
let field = def.fields.get(field).expect(
"already validated during parse lowering... probably shouldn't be?",
);
output.check_assign(self, &field.ty, &dest_def.ty, i.span);
// TODO
}
}
}
}