From 3aff6fc00640a4a223cf25485f6b2b33808b17fd Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Sun, 20 Oct 2024 16:43:25 +0200 Subject: [PATCH] reorganizing the type parser trait --- lang/src/codegen.rs | 116 ++++++++++++++-------------------- lang/src/lib.rs | 30 ++++----- lang/src/son.rs | 149 ++++++++++++++++++++++---------------------- 3 files changed, 135 insertions(+), 160 deletions(-) diff --git a/lang/src/codegen.rs b/lang/src/codegen.rs index ad9b24e..48d18eb 100644 --- a/lang/src/codegen.rs +++ b/lang/src/codegen.rs @@ -708,6 +708,44 @@ impl TypeParser for Codegen { &mut self.tys } + fn infer_type(&mut self, expr: &Expr) -> ty::Id { + let mut ci = ItemCtx { + file: self.ci.file, + ret: self.ci.ret, + task_base: self.ci.task_base, + ..self.pool.cis.pop().unwrap_or_default() + }; + ci.loops.extend(self.ci.loops.iter()); + ci.vars.extend(self.ci.vars.iter().map(|v| Variable { + id: v.id, + value: Value { ty: v.value.ty, loc: v.value.loc.as_ref() }, + })); + ci.stack_relocs.extend(self.ci.stack_relocs.iter()); + ci.ret_relocs.extend(self.ci.ret_relocs.iter()); + ci.loop_relocs.extend(self.ci.loop_relocs.iter()); + ci.regs.init(); + + core::mem::swap(&mut self.ci, &mut ci); + let value = self.expr(expr).unwrap(); + self.ci.free_loc(value.loc); + core::mem::swap(&mut self.ci, &mut ci); + + ci.loops.clear(); + ci.vars.clear(); + ci.stack_relocs.clear(); + ci.ret_relocs.clear(); + ci.loop_relocs.clear(); + ci.code.clear(); + ci.relocs.clear(); + self.pool.cis.push(ci); + + value.ty + } + + fn eval_const(&mut self, file: FileId, expr: &Expr, ty: ty::Id) -> u64 { + self.eval_const_low(file, expr, Some(ty)).0 + } + fn on_reuse(&mut self, existing: ty::Id) { if let ty::Kind::Func(id) = existing.expand() && let func = &mut self.tys.ins.funcs[id as usize] @@ -720,39 +758,16 @@ impl TypeParser for Codegen { } } - fn eval_ty( - &mut self, - file: FileId, - name: Option, - expr: &Expr, - _: &[parser::Ast], - ) -> ty::Id { - let prev_file = core::mem::replace(&mut self.ci.file, file); - let sym = match *expr { - Expr::Slice { size, item, .. } => { - let ty = self.ty(item); - let len = size.map_or(ArrayLen::MAX, |expr| { - self.eval_const(self.ci.file, expr, ty::U32) as _ - }); - self.tys.make_array(ty, len).expand() - } - Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr).expand(), - _ if let Some(name) = name => { - let gid = self.tys.ins.globals.len() as ty::Global; - self.tys.ins.globals.push(Global { file, name, ..Default::default() }); + fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id { + let gid = self.tys.ins.globals.len() as ty::Global; + self.tys.ins.globals.push(Global { file, name, ..Default::default() }); - let ci = ItemCtx { file, ..self.pool.cis.pop().unwrap_or_default() }; + let ci = ItemCtx { file, ..self.pool.cis.pop().unwrap_or_default() }; - self.tys.ins.globals[gid as usize] = self - .ct_eval(ci, |s, _| Ok::<_, !>(s.generate_global(expr, file, name))) - .into_ok(); + self.tys.ins.globals[gid as usize] = + self.ct_eval(ci, |s, _| Ok::<_, !>(s.generate_global(expr, file, name))).into_ok(); - ty::Kind::Global(gid) - } - _ => ty::Id::from(self.eval_const(file, expr, ty::Id::TYPE)).expand(), - }; - self.ci.file = prev_file; - sym.compress() + ty::Kind::Global(gid).compress() } fn report(&self, pos: Pos, msg: impl Display) -> ty::Id { @@ -882,7 +897,7 @@ impl Codegen { E::Slice { size, item, .. } => { let ty = self.ty(item); let len = size.map_or(ArrayLen::MAX, |expr| { - self.eval_const(self.ci.file, expr, ty::U32) as _ + self.eval_const(self.ci.file, expr, ty::Id::U32) as _ }); Some(Value::ty(self.tys.make_array(ty, len))) } @@ -1853,45 +1868,6 @@ impl Codegen { expr.has_ct(&self.cfile().symbols) } - fn infer_type(&mut self, expr: &Expr) -> ty::Id { - // FIXME: very inneficient - let mut ci = ItemCtx { - file: self.ci.file, - ret: self.ci.ret, - task_base: self.ci.task_base, - ..self.pool.cis.pop().unwrap_or_default() - }; - ci.loops.extend(self.ci.loops.iter()); - ci.vars.extend(self.ci.vars.iter().map(|v| Variable { - id: v.id, - value: Value { ty: v.value.ty, loc: v.value.loc.as_ref() }, - })); - ci.stack_relocs.extend(self.ci.stack_relocs.iter()); - ci.ret_relocs.extend(self.ci.ret_relocs.iter()); - ci.loop_relocs.extend(self.ci.loop_relocs.iter()); - ci.regs.init(); - - core::mem::swap(&mut self.ci, &mut ci); - let value = self.expr(expr).unwrap(); - self.ci.free_loc(value.loc); - core::mem::swap(&mut self.ci, &mut ci); - - ci.loops.clear(); - ci.vars.clear(); - ci.stack_relocs.clear(); - ci.ret_relocs.clear(); - ci.loop_relocs.clear(); - ci.code.clear(); - ci.relocs.clear(); - self.pool.cis.push(ci); - - value.ty - } - - fn eval_const(&mut self, file: FileId, expr: &Expr, ty: impl Into) -> u64 { - self.eval_const_low(file, expr, Some(ty.into())).0 - } - fn eval_const_low( &mut self, file: FileId, diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 647b0cb..5234b1f 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -844,14 +844,10 @@ trait TypeParser { fn tys(&mut self) -> &mut Types; fn on_reuse(&mut self, existing: ty::Id); fn find_local_ty(&mut self, name: Ident) -> Option; + fn eval_const(&mut self, file: FileId, expr: &Expr, ty: ty::Id) -> u64; + fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id; + fn infer_type(&mut self, expr: &Expr) -> ty::Id; fn report(&self, pos: Pos, msg: impl Display) -> ty::Id; - fn eval_ty( - &mut self, - file: FileId, - name: Option, - expr: &Expr, - files: &[parser::Ast], - ) -> ty::Id; fn find_type( &mut self, @@ -943,14 +939,13 @@ trait TypeParser { } Expr::Ident { id, .. } if ident::is_null(id) => id.into(), Expr::Ident { id, pos, .. } => self.find_type(pos, file, Ok(id), files), - Expr::Field { target, pos, name } => { - let ty::Kind::Module(file) = self.parse_ty(file, target, None, files).expand() - else { - return self.eval_ty(file, None, expr, files); - }; - + Expr::Field { target, pos, name } + if let ty::Kind::Module(file) = + self.parse_ty(file, target, None, files).expand() => + { self.find_type(pos, file, Err(name), files) } + Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr), Expr::Slice { size: None, item, .. } => { let ty = self.parse_ty(file, item, None, files); self.tys().make_array(ty, ArrayLen::MAX) @@ -959,6 +954,12 @@ trait TypeParser { let ty = self.parse_ty(file, item, None, files); self.tys().make_array(ty, value as _) } + Expr::Slice { size, item, .. } => { + let ty = self.parse_ty(file, item, None, files); + let len = size + .map_or(ArrayLen::MAX, |expr| self.eval_const(file, expr, ty::Id::U32) as _); + self.tys().make_array(ty, len) + } Expr::Struct { pos, fields, packed, .. } => { let sym = SymKey::Struct(file, pos); let tys = self.tys(); @@ -1021,7 +1022,8 @@ trait TypeParser { ty::Kind::Func(id).compress() } - _ => self.eval_ty(file, name, expr, files), + _ if let Some(name) = name => self.eval_global(file, name, expr), + _ => ty::Id::from(self.eval_const(file, expr, ty::Id::TYPE)), } } } diff --git a/lang/src/son.rs b/lang/src/son.rs index 9e5c380..fd07095 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -1422,6 +1422,16 @@ impl TypeParser for Codegen<'_> { &mut self.tys } + #[expect(unused)] + fn eval_const(&mut self, file: FileId, expr: &Expr, ty: ty::Id) -> u64 { + todo!() + } + + #[expect(unused)] + fn infer_type(&mut self, expr: &Expr) -> ty::Id { + todo!() + } + fn on_reuse(&mut self, existing: ty::Id) { if let ty::Kind::Func(id) = existing.expand() && let func = &mut self.tys.ins.funcs[id as usize] @@ -1434,94 +1444,81 @@ impl TypeParser for Codegen<'_> { } } - #[expect(unused)] - fn eval_ty( - &mut self, - file: FileId, - name: Option, - expr: &Expr, - files: &[parser::Ast], - ) -> ty::Id { - let sym = match expr { - right if let Some(name) = name => { - let gid = self.tys.ins.globals.len() as ty::Global; - self.tys.ins.globals.push(Global { file, name, ..Default::default() }); + fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id { + let gid = self.tys.ins.globals.len() as ty::Global; + self.tys.ins.globals.push(Global { file, name, ..Default::default() }); - let ty = ty::Kind::Global(gid); - self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci); + let ty = ty::Kind::Global(gid); + self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci); - let ret = Expr::Return { pos: right.pos(), val: Some(right) }; - self.expr(&ret); + let ret = Expr::Return { pos: expr.pos(), val: Some(expr) }; + self.expr(&ret); - self.ci.finalize(); + self.ci.finalize(); - let ret = self.ci.ret.expect("for return type to be infered"); - if self.errors.borrow().is_empty() { - self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret }); - self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0); - self.ci.emit(instrs::tx()); + let ret = self.ci.ret.expect("for return type to be infered"); + if self.errors.borrow().is_empty() { + self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret }); + self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0); + self.ci.emit(instrs::tx()); - let func = Func { - file, - name, - expr: ExprRef::new(expr), - relocs: core::mem::take(&mut self.ci.relocs), - code: core::mem::take(&mut self.ci.code), - ..Default::default() - }; - self.pool.pop_ci(&mut self.ci); - self.complete_call_graph(); + let func = Func { + file, + name, + expr: ExprRef::new(expr), + relocs: core::mem::take(&mut self.ci.relocs), + code: core::mem::take(&mut self.ci.code), + ..Default::default() + }; + self.pool.pop_ci(&mut self.ci); + self.complete_call_graph(); - let mut mem = vec![0u8; self.tys.size_of(ret) as usize]; + let mut mem = vec![0u8; self.tys.size_of(ret) as usize]; - // TODO: return them back - let fuc = self.tys.ins.funcs.len() as ty::Func; - self.tys.ins.funcs.push(func); + // TODO: return them back + let fuc = self.tys.ins.funcs.len() as ty::Func; + self.tys.ins.funcs.push(func); - self.tys.dump_reachable(fuc, &mut self.ct.code); + self.tys.dump_reachable(fuc, &mut self.ct.code); - #[cfg(debug_assertions)] - { - let mut vc = String::new(); - if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) - { - panic!("{e} {}", vc); - } else { - log::trace!("{}", vc); - } - } - - self.ct.vm.write_reg(reg::RET, mem.as_mut_ptr() as u64); - let prev_pc = self.ct.push_pc(self.tys.ins.funcs[fuc as usize].offset); - loop { - match self.ct.vm.run().expect("TODO") { - hbvm::VmRunOk::End => break, - hbvm::VmRunOk::Timer => todo!(), - hbvm::VmRunOk::Ecall => todo!(), - hbvm::VmRunOk::Breakpoint => todo!(), - } - } - self.ct.pop_pc(prev_pc); - - match mem.len() { - 0 => unreachable!(), - len @ 1..=8 => mem - .copy_from_slice(&self.ct.vm.read_reg(reg::RET).0.to_ne_bytes()[..len]), - 9..=16 => todo!(), - _ => {} - } - - self.tys.ins.globals[gid as usize].data = mem; + #[cfg(debug_assertions)] + { + let mut vc = String::new(); + if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) { + panic!("{e} {}", vc); } else { - self.pool.pop_ci(&mut self.ci); + log::trace!("{}", vc); } - self.tys.ins.globals[gid as usize].ty = ret; - - ty } - e => self.report_unhandled_ast(expr, "type"), - }; - sym.compress() + + self.ct.vm.write_reg(reg::RET, mem.as_mut_ptr() as u64); + let prev_pc = self.ct.push_pc(self.tys.ins.funcs[fuc as usize].offset); + loop { + match self.ct.vm.run().expect("TODO") { + hbvm::VmRunOk::End => break, + hbvm::VmRunOk::Timer => todo!(), + hbvm::VmRunOk::Ecall => todo!(), + hbvm::VmRunOk::Breakpoint => todo!(), + } + } + self.ct.pop_pc(prev_pc); + + match mem.len() { + 0 => unreachable!(), + len @ 1..=8 => { + mem.copy_from_slice(&self.ct.vm.read_reg(reg::RET).0.to_ne_bytes()[..len]) + } + 9..=16 => todo!(), + _ => {} + } + + self.tys.ins.globals[gid as usize].data = mem; + } else { + self.pool.pop_ci(&mut self.ci); + } + self.tys.ins.globals[gid as usize].ty = ret; + + ty.compress() } fn report(&self, pos: Pos, msg: impl Display) -> ty::Id {