improving code

This commit is contained in:
mlokr 2024-05-12 23:45:28 +02:00
parent 06e30529bf
commit c3cbd054f7

View file

@ -234,9 +234,12 @@ impl RegAlloc {
} }
} }
#[derive(Clone)]
struct FnLabel { struct FnLabel {
offset: u32, offset: u32,
name: Ident, name: Ident,
args: Rc<[Type]>,
ret: Type,
} }
struct Variable { struct Variable {
@ -351,16 +354,93 @@ impl<'a> Codegen<'a> {
self.input = input; self.input = input;
for expr in exprs { for expr in exprs {
let E::BinOp { match expr {
left: E::Ident { .. }, E::BinOp {
left: E::Ident { id, .. },
op: T::Decl, op: T::Decl,
.. right: E::Closure { args, ret, .. },
} => {
let args = args.iter().map(|arg| self.ty(&arg.ty)).collect::<Rc<[_]>>();
let ret = self.ty(ret);
self.declare_fn_label(*id, args, ret);
}
E::BinOp {
left: E::Ident { id, name, .. },
op: T::Decl,
right: E::Struct { .. },
} => {
self.records.push(Struct {
id: *id,
name: (*name).into(),
fields: Rc::from([]),
});
}
_ => self.report(expr.pos(), "expected declaration"),
}
}
for expr in exprs {
let E::BinOp {
left: E::Ident { id, name, .. },
op: T::Decl,
right,
} = expr } = expr
else { else {
self.report(expr.pos(), format_args!("expected declaration")); self.report(expr.pos(), format_args!("expected declaration"));
}; };
self.expr(expr, None); match right {
E::Struct { fields, .. } => {
let fields = fields
.iter()
.map(|&(name, ty)| (name.into(), self.ty(&ty)))
.collect();
self.records
.iter_mut()
.find(|r| r.id == *id)
.unwrap()
.fields = fields;
}
E::Closure { body, args, .. } => {
log::dbg!("fn: {}", name);
let frame = self.define_fn_label(*id);
if *name == "main" {
self.main = Some(frame.label);
}
let fn_label = self.labels[frame.label as usize].clone();
log::dbg!("fn-args");
let mut parama = 2..12;
for (arg, &ty) in args.iter().zip(fn_label.args.iter()) {
let loc = self.load_arg(ty, &mut parama);
self.vars.push(Variable {
id: arg.id,
value: Value { ty, loc },
});
}
self.gpa.init_callee();
self.ret = fn_label.ret;
log::dbg!("fn-body");
if self.expr(body, None).is_some() {
self.report(body.pos(), "expected all paths in the fucntion to return");
}
self.vars.clear();
log::dbg!("fn-prelude, stack: {:x}", self.stack_size);
log::dbg!("fn-relocs");
self.write_fn_prelude(frame);
log::dbg!("fn-ret");
self.reloc_rets();
self.ret();
self.stack_size = 0;
}
_ => unreachable!(),
}
} }
Ok(()) Ok(())
} }
@ -538,16 +618,7 @@ impl<'a> Codegen<'a> {
.position(|(n, _)| *n == name.as_ref()) .position(|(n, _)| *n == name.as_ref())
.unwrap(); .unwrap();
let (_, value) = field_values.remove(index); let (_, value) = field_values.remove(index);
if value.ty != ty { self.assert_ty(expr.pos(), ty, value.ty);
self.report(
expr.pos(),
format_args!(
"expected {}, got {}",
self.display_ty(ty),
self.display_ty(value.ty)
),
);
}
log::dbg!("ctor: {} {} {:?}", stack, offset, value.loc); log::dbg!("ctor: {} {} {:?}", stack, offset, value.loc);
self.assign( self.assign(
Value { Value {
@ -588,22 +659,6 @@ impl<'a> Codegen<'a> {
}; };
Some(Value { ty, loc }) Some(Value { ty, loc })
} }
E::BinOp {
left: E::Ident { id, name, .. },
op: T::Decl,
right: E::Struct { fields, .. },
} => {
let fields = fields
.iter()
.map(|&(name, ty)| (name.into(), self.ty(&ty)))
.collect();
self.records.push(Struct {
id: *id,
name: (*name).into(),
fields,
});
Some(Value::VOID)
}
E::UnOp { E::UnOp {
op: T::Amp, op: T::Amp,
val, val,
@ -643,50 +698,6 @@ impl<'a> Codegen<'a> {
), ),
} }
} }
E::BinOp {
left: E::Ident { name, id, .. },
op: T::Decl,
right: E::Closure {
ret, body, args, ..
},
} => {
log::dbg!("fn: {}", name);
let frame = self.add_label(*id);
if *name == "main" {
self.main = Some(frame.label);
}
log::dbg!("fn-args");
let mut parama = 2..12;
for arg in args.iter() {
let ty = self.ty(&arg.ty);
let loc = self.load_arg(ty, &mut parama);
self.vars.push(Variable {
id: arg.id,
value: Value { ty, loc },
});
}
self.gpa.init_callee();
self.ret = self.ty(ret);
log::dbg!("fn-body");
if self.expr(body, None).is_some() {
self.report(body.pos(), "expected all paths in the fucntion to return");
}
self.vars.clear();
log::dbg!("fn-prelude, stack: {:x}", self.stack_size);
log::dbg!("fn-relocs");
self.write_fn_prelude(frame);
log::dbg!("fn-ret");
self.reloc_rets();
self.ret();
self.stack_size = 0;
Some(Value::VOID)
}
E::BinOp { E::BinOp {
left: E::Ident { id, .. }, left: E::Ident { id, .. },
op: T::Decl, op: T::Decl,
@ -705,12 +716,14 @@ impl<'a> Codegen<'a> {
func: E::Ident { id, .. }, func: E::Ident { id, .. },
args, args,
} => { } => {
let func = self.get_label(*id);
let fn_label = self.labels[func as usize].clone();
let mut parama = 2..12; let mut parama = 2..12;
for arg in args.iter() { for (earg, &ty) in args.iter().zip(fn_label.args.iter()) {
let arg = self.expr(arg, None)?; let arg = self.expr(earg, Some(ty))?;
self.assert_ty(earg.pos(), ty, arg.ty);
self.pass_arg(arg, &mut parama); self.pass_arg(arg, &mut parama);
} }
let func = self.get_or_reserve_label(*id);
self.code.call(func); self.code.call(func);
let reg = self.gpa.allocate(); let reg = self.gpa.allocate();
self.code.encode(instrs::cp(reg.0, 1)); self.code.encode(instrs::cp(reg.0, 1));
@ -731,16 +744,7 @@ impl<'a> Codegen<'a> {
E::Return { val, pos } => { E::Return { val, pos } => {
if let Some(val) = val { if let Some(val) = val {
let val = self.expr(val, Some(self.ret))?; let val = self.expr(val, Some(self.ret))?;
if val.ty != self.ret { self.assert_ty(pos, self.ret, val.ty);
self.report(
pos,
format_args!(
"expected {}, got {}",
self.display_ty(self.ret),
self.display_ty(val.ty)
),
);
}
self.assign( self.assign(
Value { Value {
ty: self.ret, ty: self.ret,
@ -969,28 +973,20 @@ impl<'a> Codegen<'a> {
} }
} }
fn get_or_reserve_label(&mut self, name: Ident) -> LabelId { fn declare_fn_label(&mut self, name: Ident, args: Rc<[Type]>, ret: Type) -> LabelId {
if let Some(label) = self.labels.iter().position(|l| l.name == name) {
label as u32
} else {
self.labels.push(FnLabel { offset: 0, name });
self.labels.len() as u32 - 1
}
}
fn add_label(&mut self, name: Ident) -> Frame {
let offset = self.code.code.len() as u32;
let label = if let Some(label) = self.labels.iter().position(|l| l.name == name) {
self.labels[label].offset = offset;
label as u32
} else {
self.labels.push(FnLabel { self.labels.push(FnLabel {
offset, offset: 0,
name: name.into(), name,
args,
ret,
}); });
self.labels.len() as u32 - 1 self.labels.len() as u32 - 1
}; }
fn define_fn_label(&mut self, name: Ident) -> Frame {
let offset = self.code.code.len() as u32;
let label = self.get_label(name);
self.labels[label as usize].offset = offset;
Frame { Frame {
label, label,
prev_relocs: self.code.relocs.len(), prev_relocs: self.code.relocs.len(),
@ -1162,6 +1158,14 @@ impl<'a> Codegen<'a> {
} }
} }
fn assert_ty(&self, pos: parser::Pos, ty: Type, expected: Type) {
if ty != expected {
let ty = self.display_ty(ty);
let expected = self.display_ty(expected);
self.report(pos, format_args!("expected {ty}, got {expected}"));
}
}
fn report(&self, pos: parser::Pos, msg: impl std::fmt::Display) -> ! { fn report(&self, pos: parser::Pos, msg: impl std::fmt::Display) -> ! {
let (line, col) = lexer::line_col(self.input, pos); let (line, col) = lexer::line_col(self.input, pos);
println!("{}:{}:{}: {}", self.path.display(), line, col, msg); println!("{}:{}:{}: {}", self.path.display(), line, col, msg);