reorganizing the type parser trait
This commit is contained in:
parent
ccfde6c237
commit
3aff6fc006
|
@ -708,6 +708,44 @@ impl TypeParser for Codegen {
|
||||||
&mut self.tys
|
&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) {
|
fn on_reuse(&mut self, existing: ty::Id) {
|
||||||
if let ty::Kind::Func(id) = existing.expand()
|
if let ty::Kind::Func(id) = existing.expand()
|
||||||
&& let func = &mut self.tys.ins.funcs[id as usize]
|
&& let func = &mut self.tys.ins.funcs[id as usize]
|
||||||
|
@ -720,39 +758,16 @@ impl TypeParser for Codegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_ty(
|
fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id {
|
||||||
&mut self,
|
let gid = self.tys.ins.globals.len() as ty::Global;
|
||||||
file: FileId,
|
self.tys.ins.globals.push(Global { file, name, ..Default::default() });
|
||||||
name: Option<Ident>,
|
|
||||||
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() });
|
|
||||||
|
|
||||||
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
|
self.tys.ins.globals[gid as usize] =
|
||||||
.ct_eval(ci, |s, _| Ok::<_, !>(s.generate_global(expr, file, name)))
|
self.ct_eval(ci, |s, _| Ok::<_, !>(s.generate_global(expr, file, name))).into_ok();
|
||||||
.into_ok();
|
|
||||||
|
|
||||||
ty::Kind::Global(gid)
|
ty::Kind::Global(gid).compress()
|
||||||
}
|
|
||||||
_ => ty::Id::from(self.eval_const(file, expr, ty::Id::TYPE)).expand(),
|
|
||||||
};
|
|
||||||
self.ci.file = prev_file;
|
|
||||||
sym.compress()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report(&self, pos: Pos, msg: impl Display) -> ty::Id {
|
fn report(&self, pos: Pos, msg: impl Display) -> ty::Id {
|
||||||
|
@ -882,7 +897,7 @@ impl Codegen {
|
||||||
E::Slice { size, item, .. } => {
|
E::Slice { size, item, .. } => {
|
||||||
let ty = self.ty(item);
|
let ty = self.ty(item);
|
||||||
let len = size.map_or(ArrayLen::MAX, |expr| {
|
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)))
|
Some(Value::ty(self.tys.make_array(ty, len)))
|
||||||
}
|
}
|
||||||
|
@ -1853,45 +1868,6 @@ impl Codegen {
|
||||||
expr.has_ct(&self.cfile().symbols)
|
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<ty::Id>) -> u64 {
|
|
||||||
self.eval_const_low(file, expr, Some(ty.into())).0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eval_const_low(
|
fn eval_const_low(
|
||||||
&mut self,
|
&mut self,
|
||||||
file: FileId,
|
file: FileId,
|
||||||
|
|
|
@ -844,14 +844,10 @@ trait TypeParser {
|
||||||
fn tys(&mut self) -> &mut Types;
|
fn tys(&mut self) -> &mut Types;
|
||||||
fn on_reuse(&mut self, existing: ty::Id);
|
fn on_reuse(&mut self, existing: ty::Id);
|
||||||
fn find_local_ty(&mut self, name: Ident) -> Option<ty::Id>;
|
fn find_local_ty(&mut self, name: Ident) -> Option<ty::Id>;
|
||||||
|
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 report(&self, pos: Pos, msg: impl Display) -> ty::Id;
|
||||||
fn eval_ty(
|
|
||||||
&mut self,
|
|
||||||
file: FileId,
|
|
||||||
name: Option<Ident>,
|
|
||||||
expr: &Expr,
|
|
||||||
files: &[parser::Ast],
|
|
||||||
) -> ty::Id;
|
|
||||||
|
|
||||||
fn find_type(
|
fn find_type(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -943,14 +939,13 @@ trait TypeParser {
|
||||||
}
|
}
|
||||||
Expr::Ident { id, .. } if ident::is_null(id) => id.into(),
|
Expr::Ident { id, .. } if ident::is_null(id) => id.into(),
|
||||||
Expr::Ident { id, pos, .. } => self.find_type(pos, file, Ok(id), files),
|
Expr::Ident { id, pos, .. } => self.find_type(pos, file, Ok(id), files),
|
||||||
Expr::Field { target, pos, name } => {
|
Expr::Field { target, pos, name }
|
||||||
let ty::Kind::Module(file) = self.parse_ty(file, target, None, files).expand()
|
if let ty::Kind::Module(file) =
|
||||||
else {
|
self.parse_ty(file, target, None, files).expand() =>
|
||||||
return self.eval_ty(file, None, expr, files);
|
{
|
||||||
};
|
|
||||||
|
|
||||||
self.find_type(pos, file, Err(name), files)
|
self.find_type(pos, file, Err(name), files)
|
||||||
}
|
}
|
||||||
|
Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr),
|
||||||
Expr::Slice { size: None, item, .. } => {
|
Expr::Slice { size: None, item, .. } => {
|
||||||
let ty = self.parse_ty(file, item, None, files);
|
let ty = self.parse_ty(file, item, None, files);
|
||||||
self.tys().make_array(ty, ArrayLen::MAX)
|
self.tys().make_array(ty, ArrayLen::MAX)
|
||||||
|
@ -959,6 +954,12 @@ trait TypeParser {
|
||||||
let ty = self.parse_ty(file, item, None, files);
|
let ty = self.parse_ty(file, item, None, files);
|
||||||
self.tys().make_array(ty, value as _)
|
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, .. } => {
|
Expr::Struct { pos, fields, packed, .. } => {
|
||||||
let sym = SymKey::Struct(file, pos);
|
let sym = SymKey::Struct(file, pos);
|
||||||
let tys = self.tys();
|
let tys = self.tys();
|
||||||
|
@ -1021,7 +1022,8 @@ trait TypeParser {
|
||||||
|
|
||||||
ty::Kind::Func(id).compress()
|
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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
149
lang/src/son.rs
149
lang/src/son.rs
|
@ -1422,6 +1422,16 @@ impl TypeParser for Codegen<'_> {
|
||||||
&mut self.tys
|
&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) {
|
fn on_reuse(&mut self, existing: ty::Id) {
|
||||||
if let ty::Kind::Func(id) = existing.expand()
|
if let ty::Kind::Func(id) = existing.expand()
|
||||||
&& let func = &mut self.tys.ins.funcs[id as usize]
|
&& let func = &mut self.tys.ins.funcs[id as usize]
|
||||||
|
@ -1434,94 +1444,81 @@ impl TypeParser for Codegen<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[expect(unused)]
|
fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id {
|
||||||
fn eval_ty(
|
let gid = self.tys.ins.globals.len() as ty::Global;
|
||||||
&mut self,
|
self.tys.ins.globals.push(Global { file, name, ..Default::default() });
|
||||||
file: FileId,
|
|
||||||
name: Option<Ident>,
|
|
||||||
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() });
|
|
||||||
|
|
||||||
let ty = ty::Kind::Global(gid);
|
let ty = ty::Kind::Global(gid);
|
||||||
self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci);
|
self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci);
|
||||||
|
|
||||||
let ret = Expr::Return { pos: right.pos(), val: Some(right) };
|
let ret = Expr::Return { pos: expr.pos(), val: Some(expr) };
|
||||||
self.expr(&ret);
|
self.expr(&ret);
|
||||||
|
|
||||||
self.ci.finalize();
|
self.ci.finalize();
|
||||||
|
|
||||||
let ret = self.ci.ret.expect("for return type to be infered");
|
let ret = self.ci.ret.expect("for return type to be infered");
|
||||||
if self.errors.borrow().is_empty() {
|
if self.errors.borrow().is_empty() {
|
||||||
self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret });
|
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.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0);
|
||||||
self.ci.emit(instrs::tx());
|
self.ci.emit(instrs::tx());
|
||||||
|
|
||||||
let func = Func {
|
let func = Func {
|
||||||
file,
|
file,
|
||||||
name,
|
name,
|
||||||
expr: ExprRef::new(expr),
|
expr: ExprRef::new(expr),
|
||||||
relocs: core::mem::take(&mut self.ci.relocs),
|
relocs: core::mem::take(&mut self.ci.relocs),
|
||||||
code: core::mem::take(&mut self.ci.code),
|
code: core::mem::take(&mut self.ci.code),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
self.pool.pop_ci(&mut self.ci);
|
self.pool.pop_ci(&mut self.ci);
|
||||||
self.complete_call_graph();
|
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
|
// TODO: return them back
|
||||||
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
||||||
self.tys.ins.funcs.push(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)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
let mut vc = String::new();
|
let mut vc = String::new();
|
||||||
if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {})
|
if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) {
|
||||||
{
|
panic!("{e} {}", 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;
|
|
||||||
} else {
|
} 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"),
|
|
||||||
};
|
self.ct.vm.write_reg(reg::RET, mem.as_mut_ptr() as u64);
|
||||||
sym.compress()
|
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 {
|
fn report(&self, pos: Pos, msg: impl Display) -> ty::Id {
|
||||||
|
|
Loading…
Reference in a new issue