forked from AbleOS/holey-bytes
on the journey twards struct destruct
This commit is contained in:
parent
fa41c56cb3
commit
880cd66c66
|
@ -173,7 +173,8 @@ main := fn(): int {
|
||||||
}
|
}
|
||||||
|
|
||||||
pass := fn(t: ^Ty): int {
|
pass := fn(t: ^Ty): int {
|
||||||
return t.a - t.b;
|
.{ a, b } := *t;
|
||||||
|
return a - b;
|
||||||
}
|
}
|
||||||
|
|
||||||
odher_pass := fn(t: Ty2): Ty2 {
|
odher_pass := fn(t: Ty2): Ty2 {
|
||||||
|
|
|
@ -1584,34 +1584,38 @@ impl Codegen {
|
||||||
E::Ctor {
|
E::Ctor {
|
||||||
pos, ty, fields, ..
|
pos, ty, fields, ..
|
||||||
} => {
|
} => {
|
||||||
let Some(ty) = ty.map(|ty| self.ty(ty)).or(ctx.ty) else {
|
let (stuct, loc) = self.prepare_struct_ctor(pos, ctx, ty, fields.len());
|
||||||
self.report(pos, "expected type, (it cannot be inferred)");
|
for (name, field) in fields {
|
||||||
};
|
let Some((offset, ty)) = self.tys.offset_of(stuct, Ok(name)) else {
|
||||||
let size = self.tys.size_of(ty);
|
|
||||||
|
|
||||||
let loc = ctx
|
|
||||||
.loc
|
|
||||||
.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size)));
|
|
||||||
let ty::Kind::Struct(stuct) = ty.expand() else {
|
|
||||||
self.report(pos, "expected expression to evaluate to struct")
|
|
||||||
};
|
|
||||||
let field_count = self.tys.structs[stuct as usize].fields.len();
|
|
||||||
if field_count != fields.len() {
|
|
||||||
self.report(
|
|
||||||
pos,
|
|
||||||
format_args!("expected {} fields, got {}", field_count, fields.len()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, (name, field)) in fields.iter().enumerate() {
|
|
||||||
let Some((offset, ty)) = self.tys.offset_of(stuct, name.ok_or(i)) else {
|
|
||||||
self.report(pos, format_args!("field not found: {name:?}"));
|
self.report(pos, format_args!("field not found: {name:?}"));
|
||||||
};
|
};
|
||||||
let loc = loc.as_ref().offset(offset);
|
let loc = loc.as_ref().offset(offset);
|
||||||
let value = self.expr_ctx(field, Ctx::default().with_loc(loc).with_ty(ty))?;
|
let value = self.expr_ctx(
|
||||||
|
field.as_ref().expect("TODO"),
|
||||||
|
Ctx::default().with_loc(loc).with_ty(ty),
|
||||||
|
)?;
|
||||||
self.ci.free_loc(value.loc);
|
self.ci.free_loc(value.loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ty = ty::Kind::Struct(stuct).compress();
|
||||||
|
return Some(Value { ty, loc });
|
||||||
|
}
|
||||||
|
E::Tupl {
|
||||||
|
pos, ty, fields, ..
|
||||||
|
} => {
|
||||||
|
let (stuct, loc) = self.prepare_struct_ctor(pos, ctx, ty, fields.len());
|
||||||
|
let mut offset = 0;
|
||||||
|
let sfields = self.tys.structs[stuct as usize].fields.clone();
|
||||||
|
for (sfield, field) in sfields.iter().zip(fields) {
|
||||||
|
let loc = loc.as_ref().offset(offset);
|
||||||
|
let ctx = Ctx::default().with_loc(loc).with_ty(sfield.ty);
|
||||||
|
let value = self.expr_ctx(field, ctx)?;
|
||||||
|
self.ci.free_loc(value.loc);
|
||||||
|
offset += self.tys.size_of(sfield.ty);
|
||||||
|
offset = Types::align_up(offset, self.tys.align_of(sfield.ty));
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty = ty::Kind::Struct(stuct).compress();
|
||||||
return Some(Value { ty, loc });
|
return Some(Value { ty, loc });
|
||||||
}
|
}
|
||||||
E::Field { target, field } => {
|
E::Field { target, field } => {
|
||||||
|
@ -2138,6 +2142,36 @@ impl Codegen {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_struct_ctor(
|
||||||
|
&mut self,
|
||||||
|
pos: Pos,
|
||||||
|
ctx: Ctx,
|
||||||
|
ty: Option<&Expr>,
|
||||||
|
field_len: usize,
|
||||||
|
) -> (ty::Struct, Loc) {
|
||||||
|
let Some(ty) = ty.map(|ty| self.ty(ty)).or(ctx.ty) else {
|
||||||
|
self.report(pos, "expected type, (it cannot be inferred)");
|
||||||
|
};
|
||||||
|
|
||||||
|
let size = self.tys.size_of(ty);
|
||||||
|
let loc = ctx
|
||||||
|
.loc
|
||||||
|
.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size)));
|
||||||
|
let ty::Kind::Struct(stuct) = ty.expand() else {
|
||||||
|
self.report(pos, "expected expression to evaluate to struct")
|
||||||
|
};
|
||||||
|
|
||||||
|
let field_count = self.tys.structs[stuct as usize].fields.len();
|
||||||
|
if field_count != field_len {
|
||||||
|
self.report(
|
||||||
|
pos,
|
||||||
|
format_args!("expected {field_count} fields, got {field_len}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(stuct, loc)
|
||||||
|
}
|
||||||
|
|
||||||
fn struct_op(
|
fn struct_op(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: TokenKind,
|
op: TokenKind,
|
||||||
|
@ -2743,13 +2777,13 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_ecall(&mut self) {
|
fn handle_ecall(&mut self) {
|
||||||
let local_pc = (self.ct.vm.pc.get() as usize - self.output.code.as_ptr() as usize)
|
|
||||||
.checked_sub(self.ci.snap.code);
|
|
||||||
|
|
||||||
let arr = self.ct.vm.pc.get() as *const Trap;
|
let arr = self.ct.vm.pc.get() as *const Trap;
|
||||||
let trap = unsafe { std::ptr::read_unaligned(arr) };
|
let trap = unsafe { std::ptr::read_unaligned(arr) };
|
||||||
self.ct.vm.pc = self.ct.vm.pc.wrapping_add(std::mem::size_of::<Trap>());
|
self.ct.vm.pc = self.ct.vm.pc.wrapping_add(std::mem::size_of::<Trap>());
|
||||||
|
|
||||||
|
let local_pc = (self.ct.vm.pc.get() as usize - self.output.code.as_ptr() as usize)
|
||||||
|
.checked_sub(self.ci.snap.code);
|
||||||
|
|
||||||
match trap {
|
match trap {
|
||||||
Trap::MakeStruct { file, struct_expr } => {
|
Trap::MakeStruct { file, struct_expr } => {
|
||||||
let cfile = self.files[file as usize].clone();
|
let cfile = self.files[file as usize].clone();
|
||||||
|
@ -2783,10 +2817,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(lpc) = local_pc {
|
if let Some(lpc) = local_pc {
|
||||||
let offset = std::mem::size_of::<Trap>()
|
let offset = lpc + self.ci.snap.code + self.output.code.as_ptr() as usize;
|
||||||
+ lpc
|
|
||||||
+ self.ci.snap.code
|
|
||||||
+ self.output.code.as_ptr() as usize;
|
|
||||||
self.ct.vm.pc = hbvm::mem::Address::new(offset as _);
|
self.ct.vm.pc = hbvm::mem::Address::new(offset as _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,6 +341,8 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
},
|
},
|
||||||
body: self.ptr_expr(),
|
body: self.ptr_expr(),
|
||||||
},
|
},
|
||||||
|
T::Ctor => self.ctor(token.start, None),
|
||||||
|
T::Tupl => self.tupl(token.start, None),
|
||||||
T::Band | T::Mul | T::Xor => E::UnOp {
|
T::Band | T::Mul | T::Xor => E::UnOp {
|
||||||
pos: token.start,
|
pos: token.start,
|
||||||
op: token.kind,
|
op: token.kind,
|
||||||
|
@ -392,23 +394,8 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
args: self.collect_list(T::Comma, T::RParen, Self::expr),
|
args: self.collect_list(T::Comma, T::RParen, Self::expr),
|
||||||
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
||||||
},
|
},
|
||||||
T::Ctor => E::Ctor {
|
T::Ctor => self.ctor(token.start, Some(expr)),
|
||||||
pos: token.start,
|
T::Tupl => self.tupl(token.start, Some(expr)),
|
||||||
ty: Some(self.arena.alloc(expr)),
|
|
||||||
fields: self.collect_list(T::Comma, T::RBrace, |s| {
|
|
||||||
let name = s.expect_advance(T::Ident);
|
|
||||||
s.expect_advance(T::Colon);
|
|
||||||
let val = s.expr();
|
|
||||||
(Some(s.move_str(name)), val)
|
|
||||||
}),
|
|
||||||
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
|
||||||
},
|
|
||||||
T::Tupl => E::Ctor {
|
|
||||||
pos: token.start,
|
|
||||||
ty: Some(self.arena.alloc(expr)),
|
|
||||||
fields: self.collect_list(T::Comma, T::RParen, |s| (None, s.expr())),
|
|
||||||
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
|
||||||
},
|
|
||||||
T::Dot => E::Field {
|
T::Dot => E::Field {
|
||||||
target: self.arena.alloc(expr),
|
target: self.arena.alloc(expr),
|
||||||
field: {
|
field: {
|
||||||
|
@ -431,6 +418,28 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>) -> Expr<'a> {
|
||||||
|
Expr::Tupl {
|
||||||
|
pos,
|
||||||
|
ty: ty.map(|ty| self.arena.alloc(ty)),
|
||||||
|
fields: self.collect_list(TokenKind::Comma, TokenKind::RParen, Self::expr),
|
||||||
|
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ctor(&mut self, pos: Pos, ty: Option<Expr<'a>>) -> Expr<'a> {
|
||||||
|
Expr::Ctor {
|
||||||
|
pos,
|
||||||
|
ty: ty.map(|ty| self.arena.alloc(ty)),
|
||||||
|
fields: self.collect_list(TokenKind::Comma, TokenKind::RBrace, |s| {
|
||||||
|
let name = s.advance_ident();
|
||||||
|
let value = s.advance_if(TokenKind::Colon).then(|| s.expr());
|
||||||
|
(s.move_str(name), value)
|
||||||
|
}),
|
||||||
|
trailing_comma: std::mem::take(&mut self.trailing_sep),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn advance_ident(&mut self) -> Token {
|
fn advance_ident(&mut self) -> Token {
|
||||||
if matches!(self.token.kind, TokenKind::Ident | TokenKind::CtIdent) {
|
if matches!(self.token.kind, TokenKind::Ident | TokenKind::CtIdent) {
|
||||||
self.next()
|
self.next()
|
||||||
|
@ -661,7 +670,13 @@ generate_expr! {
|
||||||
Ctor {
|
Ctor {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
ty: Option<&'a Self>,
|
ty: Option<&'a Self>,
|
||||||
fields: &'a [(Option<&'a str>, Self)],
|
fields: &'a [(&'a str, Option<Self>)],
|
||||||
|
trailing_comma: bool,
|
||||||
|
},
|
||||||
|
Tupl {
|
||||||
|
pos: Pos,
|
||||||
|
ty: Option<&'a Self>,
|
||||||
|
fields: &'a [Self],
|
||||||
trailing_comma: bool,
|
trailing_comma: bool,
|
||||||
},
|
},
|
||||||
Field {
|
Field {
|
||||||
|
@ -720,26 +735,22 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
|
|
||||||
fn fmt_list<T>(
|
fn fmt_list<T>(
|
||||||
f: &mut std::fmt::Formatter,
|
f: &mut std::fmt::Formatter,
|
||||||
|
trailing: bool,
|
||||||
end: &str,
|
end: &str,
|
||||||
list: &[T],
|
list: &[T],
|
||||||
fmt: impl Fn(&T, &mut std::fmt::Formatter) -> std::fmt::Result,
|
fmt: impl Fn(&T, &mut std::fmt::Formatter) -> std::fmt::Result,
|
||||||
) -> std::fmt::Result {
|
) -> std::fmt::Result {
|
||||||
let first = &mut true;
|
if !trailing {
|
||||||
for expr in list {
|
let first = &mut true;
|
||||||
if !std::mem::take(first) {
|
for expr in list {
|
||||||
write!(f, ", ")?;
|
if !std::mem::take(first) {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
fmt(expr, f)?;
|
||||||
}
|
}
|
||||||
fmt(expr, f)?;
|
return write!(f, "{end}");
|
||||||
}
|
}
|
||||||
write!(f, "{end}")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_trailing_list<T>(
|
|
||||||
f: &mut std::fmt::Formatter,
|
|
||||||
end: &str,
|
|
||||||
list: &[T],
|
|
||||||
fmt: impl Fn(&T, &mut std::fmt::Formatter) -> std::fmt::Result,
|
|
||||||
) -> std::fmt::Result {
|
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
INDENT.with(|i| i.set(i.get() + 1));
|
INDENT.with(|i| i.set(i.get() + 1));
|
||||||
let res = (|| {
|
let res = (|| {
|
||||||
|
@ -805,11 +816,13 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
Self::Field { target, field } => write!(f, "{}.{field}", Postfix(target)),
|
Self::Field { target, field } => write!(f, "{}.{field}", Postfix(target)),
|
||||||
Self::Directive { name, args, .. } => {
|
Self::Directive { name, args, .. } => {
|
||||||
write!(f, "@{name}(")?;
|
write!(f, "@{name}(")?;
|
||||||
fmt_list(f, ")", args, std::fmt::Display::fmt)
|
fmt_list(f, false, ")", args, std::fmt::Display::fmt)
|
||||||
}
|
}
|
||||||
Self::Struct { fields, .. } => {
|
Self::Struct { fields, .. } => {
|
||||||
write!(f, "struct {{")?;
|
write!(f, "struct {{")?;
|
||||||
fmt_list(f, "}", fields, |(name, val), f| write!(f, "{name}: {val}",))
|
fmt_list(f, true, "}", fields, |(name, val), f| {
|
||||||
|
write!(f, "{name}: {val}",)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
Self::Ctor {
|
Self::Ctor {
|
||||||
ty,
|
ty,
|
||||||
|
@ -817,27 +830,30 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
trailing_comma,
|
trailing_comma,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let (left, rith) = if fields.iter().any(|(name, _)| name.is_some()) {
|
|
||||||
('{', "}")
|
|
||||||
} else {
|
|
||||||
('(', ")")
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(ty) = ty {
|
if let Some(ty) = ty {
|
||||||
write!(f, "{}", Unary(ty))?;
|
write!(f, "{}", Unary(ty))?;
|
||||||
}
|
}
|
||||||
write!(f, ".{left}")?;
|
write!(f, ".{{")?;
|
||||||
let fmt_field = |(name, val): &_, f: &mut std::fmt::Formatter| {
|
let fmt_field = |(name, val): &_, f: &mut std::fmt::Formatter| {
|
||||||
if let Some(name) = name {
|
if let Some(val) = val {
|
||||||
write!(f, "{name}: ")?;
|
write!(f, "{name}: {val}")
|
||||||
|
} else {
|
||||||
|
write!(f, "{name}")
|
||||||
}
|
}
|
||||||
write!(f, "{val}")
|
|
||||||
};
|
};
|
||||||
if trailing_comma {
|
fmt_list(f, trailing_comma, "}", fields, fmt_field)
|
||||||
fmt_trailing_list(f, rith, fields, fmt_field)
|
}
|
||||||
} else {
|
Self::Tupl {
|
||||||
fmt_list(f, rith, fields, fmt_field)
|
ty,
|
||||||
|
fields,
|
||||||
|
trailing_comma,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if let Some(ty) = ty {
|
||||||
|
write!(f, "{}", Unary(ty))?;
|
||||||
}
|
}
|
||||||
|
write!(f, ".(")?;
|
||||||
|
fmt_list(f, trailing_comma, ")", fields, std::fmt::Display::fmt)
|
||||||
}
|
}
|
||||||
Self::UnOp { op, val, .. } => write!(f, "{op}{}", Unary(val)),
|
Self::UnOp { op, val, .. } => write!(f, "{op}{}", Unary(val)),
|
||||||
Self::Break { .. } => write!(f, "break"),
|
Self::Break { .. } => write!(f, "break"),
|
||||||
|
@ -856,7 +872,9 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
ret, body, args, ..
|
ret, body, args, ..
|
||||||
} => {
|
} => {
|
||||||
write!(f, "fn(")?;
|
write!(f, "fn(")?;
|
||||||
fmt_list(f, "", args, |arg, f| write!(f, "{}: {}", arg.name, arg.ty))?;
|
fmt_list(f, false, "", args, |arg, f| {
|
||||||
|
write!(f, "{}: {}", arg.name, arg.ty)
|
||||||
|
})?;
|
||||||
write!(f, "): {ret} {body}")?;
|
write!(f, "): {ret} {body}")?;
|
||||||
if !matches!(body, Self::Block { .. }) {
|
if !matches!(body, Self::Block { .. }) {
|
||||||
write!(f, ";")?;
|
write!(f, ";")?;
|
||||||
|
@ -869,11 +887,7 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
trailing_comma,
|
trailing_comma,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "{}(", Postfix(func))?;
|
write!(f, "{}(", Postfix(func))?;
|
||||||
if trailing_comma {
|
fmt_list(f, trailing_comma, ")", args, std::fmt::Display::fmt)
|
||||||
fmt_trailing_list(f, ")", args, std::fmt::Display::fmt)
|
|
||||||
} else {
|
|
||||||
fmt_list(f, ")", args, std::fmt::Display::fmt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Self::Return { val: Some(val), .. } => write!(f, "return {val}"),
|
Self::Return { val: Some(val), .. } => write!(f, "return {val}"),
|
||||||
Self::Return { val: None, .. } => write!(f, "return"),
|
Self::Return { val: None, .. } => write!(f, "return"),
|
||||||
|
|
Loading…
Reference in a new issue