in progress of adding methods

This commit is contained in:
Jakub Doka 2024-11-24 14:47:38 +01:00
parent 9dfb2eb606
commit 58ee5c0a56
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
8 changed files with 319 additions and 108 deletions

View file

@ -212,6 +212,35 @@ odher_pass := fn(t: Ty2): Ty2 {
}
```
#### struct_scopes
```hb
$zr := 0
Struct := struct {
a: uint,
b: uint,
$zero := Self.(zr, zr)
$new := fn(a: uint, b: uint): Self return .(a, b)
$swap := fn(s: ^Self): void {
t := s.a
s.a = s.b
s.b = t
}
$diff := fn(s: Self): uint return s.a - s.b
}
main := fn(): uint {
z := Struct.zero
z += Struct.new(1, 2)
z.swap()
return z.diff()
}
```
#### enums
```hb
Enum := enum {A, B, C}

View file

@ -3,7 +3,10 @@ use {
lexer::{self, Lexer, TokenKind},
parser::{self, CommentOr, CtorField, EnumField, Expr, Poser, Radix, StructField},
},
core::fmt::{self},
core::{
fmt::{self},
mem,
},
};
pub fn display_radix(radix: Radix, mut value: u64, buf: &mut [u8; 64]) -> &str {
@ -64,8 +67,8 @@ fn token_group(kind: TokenKind) -> TokenGroup {
Decl | Assign | BorAss | XorAss | BandAss | AddAss | SubAss | MulAss | DivAss | ModAss
| ShrAss | ShlAss => TG::Assign,
DQuote | Quote => TG::String,
Return | If | Else | Loop | Break | Continue | Fn | Idk | Die | Struct | Packed | True
| False | Null | Match | Enum => TG::Keyword,
Slf | Return | If | Else | Loop | Break | Continue | Fn | Idk | Die | Struct | Packed
| True | False | Null | Match | Enum => TG::Keyword,
}
}
@ -198,13 +201,19 @@ impl<'a> Formatter<'a> {
return f.write_str(end);
}
if !end.is_empty() {
writeln!(f)?;
self.depth += 1;
}
self.depth += !end.is_empty() as usize;
let mut already_indented = end.is_empty();
let res = (|| {
for (i, stmt) in list.iter().enumerate() {
if !mem::take(&mut already_indented) {
for _ in 0..self.depth {
f.write_str("\t")?;
}
}
let add_sep = fmt(self, stmt, f)?;
if add_sep {
f.write_str(sep)?;
@ -225,12 +234,14 @@ impl<'a> Formatter<'a> {
}
Ok(())
})();
self.depth -= 1;
self.depth -= !end.is_empty() as usize;
if !end.is_empty() {
for _ in 0..self.depth {
f.write_str("\t")?;
}
f.write_str(end)?;
}
res
}
@ -269,6 +280,7 @@ impl<'a> Formatter<'a> {
f.write_str("$: ")?;
self.fmt(value, f)
}
Expr::Slf { .. } => f.write_str("Self"),
Expr::String { literal, .. } => f.write_str(literal),
Expr::Comment { literal, .. } => f.write_str(literal),
Expr::Mod { path, .. } => write!(f, "@use(\"{path}\")"),
@ -292,11 +304,15 @@ impl<'a> Formatter<'a> {
f.write_str("struct {")?;
self.fmt_list_low(f, trailing_comma, "}", ",", fields, |s, field, f| {
match field {
CommentOr::Or(StructField { name, ty, .. }) => {
CommentOr::Or(Ok(StructField { name, ty, .. })) => {
f.write_str(name)?;
f.write_str(": ")?;
s.fmt(ty, f)?
}
CommentOr::Or(Err(scope)) => {
s.fmt_list(f, true, "", "", scope, Self::fmt)?;
return Ok(false);
}
CommentOr::Comment { literal, .. } => {
f.write_str(literal)?;
f.write_str("\n")?;
@ -570,6 +586,7 @@ pub mod test {
let mut ctx = Ctx::default();
let ast = parser::Ast::new(ident, minned, &mut ctx, &mut parser::no_loader);
log::info!("{}", ctx.errors.borrow());
let mut output = String::new();
write!(output, "{ast}").unwrap();

View file

@ -136,6 +136,7 @@ pub enum TokenKind {
Under = b'_',
Tick = b'`',
Slf,
Return,
If,
Match,
@ -302,6 +303,7 @@ gen_token_kind! {
Eof,
Directive,
#[keywords]
Slf = b"Self",
Return = b"return",
If = b"if",
Match = b"match",
@ -401,6 +403,10 @@ impl<'a> Lexer<'a> {
unsafe { core::str::from_utf8_unchecked(&self.source[tok]) }
}
pub fn taste(&self) -> Token {
Lexer { pos: self.pos, source: self.source }.eat()
}
fn peek(&self) -> Option<u8> {
if core::intrinsics::unlikely(self.pos >= self.source.len() as u32) {
None

View file

@ -503,8 +503,8 @@ pub mod ty {
Kind::Ptr(_) | Kind::Enum(_) | Kind::Builtin(_) => Loc::Reg,
Kind::Struct(_) if tys.size_of(*self) == 0 => Loc::Reg,
Kind::Struct(_) | Kind::Slice(_) | Kind::Opt(_) => Loc::Stack,
Kind::Func(_) | Kind::Global(_) | Kind::Module(_) | Kind::Const(_) => {
unreachable!()
c @ (Kind::Func(_) | Kind::Global(_) | Kind::Module(_) | Kind::Const(_)) => {
unreachable!("{c:?}")
}
}
}
@ -823,6 +823,7 @@ pub struct Sig {
#[derive(Default, Clone, Copy)]
struct Func {
file: Module,
parent: ty::Id,
name: Ident,
base: Option<ty::Func>,
expr: ExprRef,
@ -859,6 +860,7 @@ pub struct Const {
ast: ExprRef,
name: Ident,
file: Module,
parent: ty::Id,
}
// TODO: make into bit struct (width: u2, sub_offset: u3, offset: u27)
@ -915,6 +917,7 @@ struct Struct {
captures: ty::Tuple,
explicit_alignment: Option<u8>,
field_start: u32,
ast: ExprRef,
}
#[derive(PartialEq, Eq, Hash, Clone, Copy)]

View file

@ -300,8 +300,10 @@ impl<'a, 'b> Parser<'a, 'b> {
let token @ Token { start: pos, .. } = self.next();
let prev_boundary = self.ns_bound;
let prev_captured = self.ctx.captured.len();
let mut must_trail = false;
let mut expr = match token.kind {
T::Ct => E::Ct { pos, value: self.ptr_expr()? },
T::Slf => E::Slf { pos },
T::Directive if self.lexer.slice(token.range()) == "use" => {
self.expect_advance(TokenKind::LParen)?;
let str = self.expect_advance(TokenKind::DQuote)?;
@ -374,14 +376,19 @@ impl<'a, 'b> Parser<'a, 'b> {
let tok = s.token;
Some(if s.advance_if(T::Comment) {
CommentOr::Comment { literal: s.tok_str(tok), pos: tok.start }
} else {
} else if s.lexer.taste().kind == T::Colon {
let name = s.expect_advance(T::Ident)?;
s.expect_advance(T::Colon)?;
CommentOr::Or(StructField {
CommentOr::Or(Ok(StructField {
pos: name.start,
name: s.tok_str(name),
ty: s.expr()?,
})
}))
} else {
must_trail = true;
CommentOr::Or(Err(
s.collect_list_low(T::Semi, T::RBrace, true, |s| s.expr_low(true))
))
})
})
},
@ -400,7 +407,7 @@ impl<'a, 'b> Parser<'a, 'b> {
}
pos
},
trailing_comma: core::mem::take(&mut self.trailing_sep),
trailing_comma: core::mem::take(&mut self.trailing_sep) || must_trail,
},
T::Enum => E::Enum {
pos,
@ -578,7 +585,7 @@ impl<'a, 'b> Parser<'a, 'b> {
}
}
if matches!(token.kind, T::Loop | T::LBrace | T::Fn) {
if matches!(token.kind, T::Loop | T::LBrace | T::Fn | T::Struct) {
self.pop_scope(frame);
}
@ -651,11 +658,21 @@ impl<'a, 'b> Parser<'a, 'b> {
&mut self,
delim: TokenKind,
end: TokenKind,
f: impl FnMut(&mut Self) -> Option<T>,
) -> &'a [T] {
self.collect_list_low(delim, end, false, f)
}
fn collect_list_low<T: Copy>(
&mut self,
delim: TokenKind,
end: TokenKind,
keep_end: bool,
mut f: impl FnMut(&mut Self) -> Option<T>,
) -> &'a [T] {
let mut trailing_sep = false;
let mut view = self.ctx.stack.view();
'o: while !self.advance_if(end) {
'o: while (keep_end && self.token.kind != end) || (!keep_end && !self.advance_if(end)) {
let val = match f(self) {
Some(val) => val,
None => {
@ -833,6 +850,10 @@ generate_expr! {
pos: Pos,
value: &'a Self,
},
/// `'Self'`
Slf {
pos: Pos,
},
/// `'"([^"]|\\")"'`
String {
pos: Pos,
@ -931,7 +952,7 @@ generate_expr! {
/// `'struct' LIST('{', ',', '}', Ident ':' Expr)`
Struct {
pos: Pos,
fields: &'a [CommentOr<'a, StructField<'a>>],
fields: &'a [CommentOr<'a, Result<StructField<'a>, &'a[Self]>>],
captured: &'a [Ident],
trailing_comma: bool,
packed: bool,
@ -1112,6 +1133,18 @@ pub trait Poser {
fn posi(&self) -> Pos;
}
impl<O: Poser, E: Poser> Poser for Result<O, E> {
fn posi(&self) -> Pos {
self.as_ref().map_or_else(Poser::posi, Poser::posi)
}
}
impl<T: Poser> Poser for &[T] {
fn posi(&self) -> Pos {
self[0].posi()
}
}
impl Poser for Pos {
fn posi(&self) -> Pos {
*self
@ -1312,12 +1345,7 @@ impl Ast {
}
pub fn find_decl(&self, id: Result<Ident, &str>) -> Option<(&Expr, Ident)> {
self.exprs().iter().find_map(|expr| match expr {
Expr::BinOp { left, op: TokenKind::Decl, .. } => {
left.declares(id, &self.file).map(|id| (expr, id))
}
_ => None,
})
find_decl(self.exprs(), &self.file, id)
}
pub fn ident_str(&self, ident: Ident) -> &str {
@ -1325,6 +1353,19 @@ impl Ast {
}
}
pub fn find_decl<'a>(
exprs: &'a [Expr<'a>],
file: &str,
id: Result<Ident, &str>,
) -> Option<(&'a Expr<'a>, Ident)> {
exprs.iter().find_map(|expr| match expr {
Expr::BinOp { left, op: TokenKind::Decl, .. } => {
left.declares(id, file).map(|id| (expr, id))
}
_ => None,
})
}
impl Default for Ast {
fn default() -> Self {
Self(AstInner::new("".into(), "".into(), &mut Ctx::default(), &mut no_loader))

View file

@ -2342,6 +2342,7 @@ impl Scope {
#[derive(Default, Clone)]
pub struct ItemCtx {
file: Module,
parent: ty::Id,
pos: Vec<Pos>,
ret: Option<ty::Id>,
task_base: usize,
@ -2356,7 +2357,7 @@ pub struct ItemCtx {
}
impl ItemCtx {
fn init(&mut self, file: Module, ret: Option<ty::Id>, task_base: usize) {
fn init(&mut self, file: Module, parent: ty::Id, ret: Option<ty::Id>, task_base: usize) {
debug_assert_eq!(self.loops.len(), 0);
debug_assert_eq!(self.scope.vars.len(), 0);
debug_assert_eq!(self.scope.aclasses.len(), 0);
@ -2366,6 +2367,7 @@ impl ItemCtx {
debug_assert_eq!(self.inline_aclass_base, 0);
self.file = file;
self.parent = parent;
self.ret = ret;
self.task_base = task_base;
@ -2433,6 +2435,7 @@ impl Pool {
fn push_ci(
&mut self,
file: Module,
parent: ty::Id,
ret: Option<ty::Id>,
task_base: usize,
target: &mut ItemCtx,
@ -2443,7 +2446,7 @@ impl Pool {
self.cis.push(ItemCtx::default());
mem::swap(self.cis.last_mut().unwrap(), target);
}
target.init(file, ret, task_base);
target.init(file, parent, ret, task_base);
self.used_cis += 1;
}
@ -2718,10 +2721,11 @@ impl<'a> Codegen<'a> {
self.ci.nodes[region].kind != Kind::Load
|| self.ci.nodes[region].kind == Kind::Stck
|| self.ci.nodes[region].ty.is_pointer(),
"{:?} {} {}",
"{:?} {} {} {:?}",
self.ci.nodes.graphviz_in_browser(self.ty_display(ty::Id::VOID)),
self.file().path,
self.ty_display(self.ci.nodes[region].ty)
self.ty_display(self.ci.nodes[region].ty),
self.ci.nodes[region],
);
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
let (index, _) = self.ci.nodes.aclass_index(region);
@ -2820,7 +2824,7 @@ impl<'a> Codegen<'a> {
ty::Kind::NEVER => Value::NEVER,
ty::Kind::Global(global) => self.gen_global(global),
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
_ => Some(Value::new(Nid::MAX).ty(decl)),
_ => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, decl)),
}
}
Expr::Comment { .. } => Some(Value::VOID),
@ -2863,9 +2867,9 @@ impl<'a> Codegen<'a> {
let expected = *self.ci.ret.get_or_insert(value.ty);
self.assert_ty(pos, &mut value, expected, "return value");
self.strip_ptr(&mut value);
if self.ci.inline_depth == 0 {
self.strip_ptr(&mut value);
debug_assert_ne!(self.ci.ctrl.get(), VOID);
let mut inps = Vc::from([self.ci.ctrl.get(), value.id]);
for (i, aclass) in self.ci.scope.aclasses.iter_mut().enumerate() {
@ -2930,10 +2934,7 @@ impl<'a> Codegen<'a> {
.for_each(|v| v.remove(&mut self.ci.nodes));
let repl = StrongRef::new(NEVER, &mut self.ci.nodes);
let (index, _) = self
.ci
.nodes
.aclass_index(*self.ci.nodes[value.id].inputs.get(1).unwrap_or(&VOID));
let (index, _) = self.ci.nodes.aclass_index(value.id);
let aclass = (self.ci.inline_aclass_base <= index)
.then(|| self.ci.scope.aclasses[index].dup(&mut self.ci.nodes));
self.ci.inline_ret =
@ -2964,7 +2965,7 @@ impl<'a> Codegen<'a> {
ty::Kind::NEVER => Value::NEVER,
ty::Kind::Global(global) => self.gen_global(global),
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
v => Some(Value::new(Nid::MAX).ty(v.compress())),
v => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, v.compress())),
}
}
ty::Kind::Enum(e) => {
@ -2972,7 +2973,23 @@ impl<'a> Codegen<'a> {
self.gen_enum_variant(pos, e, intrnd)
}
ty::Kind::Struct(s) => {
let Some((offset, ty)) = OffsetIter::offset_of(self.tys, s, name) else {
let Struct { ast, file, .. } = self.tys.ins.structs[s];
if let Some((offset, ty)) = OffsetIter::offset_of(self.tys, s, name) {
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
} else if let Expr::Struct {
fields: [.., CommentOr::Or(Err(scope))], ..
} = ast.get(&self.files[file.index()])
&& let ty = self.find_type_low(
pos,
self.ci.file,
file,
Some((s.into(), scope)),
Err(name),
)
&& ty != ty::Id::NEVER
{
todo!()
} else {
let field_list = self
.tys
.struct_fields(s)
@ -2988,11 +3005,62 @@ impl<'a> Codegen<'a> {
self.ty_display(tty)
),
);
Value::NEVER
}
}
ty::Kind::TYPE => match ty::Id::from(match self.ci.nodes[vtarget.id].kind {
Kind::CInt { value } => value as u64,
_ => unreachable!(),
})
.expand()
{
ty::Kind::Struct(s) => {
let Struct { ast, file, .. } = self.tys.ins.structs[s];
let Expr::Struct { fields: &[.., CommentOr::Or(Err(scope))], .. } =
ast.get(&self.files[file.index()])
else {
self.error(
pos,
fa!("'{}' has not declarations", self.ty_display(s.into())),
);
return Value::NEVER;
};
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
match self
.find_type_low(
pos,
self.ci.file,
file,
Some((s.into(), scope)),
Err(name),
)
.expand()
{
ty::Kind::NEVER => Value::NEVER,
ty::Kind::Global(global) => self.gen_global(global),
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
v => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, v.compress())),
}
}
ty::Kind::Module(m) => {
match self.find_type(pos, self.ci.file, m, Err(name)).expand() {
ty::Kind::NEVER => Value::NEVER,
ty::Kind::Global(global) => self.gen_global(global),
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
v => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, v.compress())),
}
}
ty => {
self.error(
pos,
fa!(
"accesing scope on '{}' is not supported yet",
self.ty_display(ty.compress())
),
);
Value::NEVER
}
},
_ => {
self.error(
pos,
@ -3203,11 +3271,13 @@ impl<'a> Codegen<'a> {
Some(bop)
}
ty::Kind::Struct(s) if op.is_homogenous() => {
debug_assert!(lhs.ptr);
self.ci.nodes.lock(lhs.id);
let rhs = self.raw_expr_ctx(right, Ctx::default().with_ty(lhs.ty));
self.ci.nodes.unlock(lhs.id);
let mut rhs = rhs?;
self.strip_var(&mut rhs);
debug_assert!(rhs.ptr);
self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand");
let dst = self.new_stack(pos, lhs.ty);
self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id);
@ -4082,8 +4152,8 @@ impl<'a> Codegen<'a> {
Some(Value::VOID)
}
ref e => {
self.error_unhandled_ast(e, "bruh");
Value::NEVER
let ty = self.ty(e);
Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, ty))
}
}
}
@ -4161,7 +4231,12 @@ impl<'a> Codegen<'a> {
}
fn gen_call(&mut self, func: &Expr, args: &[Expr], inline: bool) -> Option<Value> {
let ty = self.ty(func);
let mut ty = self.expr(func)?;
self.assert_ty(func.pos(), &mut ty, ty::Id::TYPE, "function");
let ty = ty::Id::from(match self.ci.nodes[ty.id].kind {
Kind::CInt { value } => value as u64,
_ => unreachable!(),
});
let ty::Kind::Func(mut fu) = ty.expand() else {
self.error(func.pos(), fa!("compiler cant (yet) call '{}'", self.ty_display(ty)));
return Value::NEVER;
@ -4333,7 +4408,8 @@ impl<'a> Codegen<'a> {
fn gen_const(&mut self, cnst: ty::Const, ctx: Ctx) -> Option<Value> {
let c = &self.tys.ins.consts[cnst];
let prev = mem::replace(&mut self.ci.file, c.file);
let prev_file = mem::replace(&mut self.ci.file, c.file);
let prev_parent = mem::replace(&mut self.ci.parent, c.parent);
let f = &self.files[c.file.index()];
let Expr::BinOp { left, right, .. } = c.ast.get(f) else { unreachable!() };
@ -4344,7 +4420,8 @@ impl<'a> Codegen<'a> {
})
.unwrap_or_else(|_| unreachable!())?;
self.strip_var(&mut value);
self.ci.file = prev;
self.ci.file = prev_file;
self.ci.parent = prev_parent;
Some(value)
}
@ -4475,7 +4552,7 @@ impl<'a> Codegen<'a> {
}
fn compute_signature(&mut self, func: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option<Sig> {
let Func { file, expr, sig, .. } = self.tys.ins.funcs[*func];
let Func { file, expr, sig, parent, .. } = self.tys.ins.funcs[*func];
let fast = &self.files[file.index()];
let &Expr::Closure { args: cargs, ret, .. } = expr.get(fast) else {
unreachable!();
@ -4488,7 +4565,7 @@ impl<'a> Codegen<'a> {
let base = self.ci.scope.vars.len();
for (arg, carg) in args.iter().zip(cargs) {
let ty = self.ty_in(file, &carg.ty);
let ty = self.ty_in(file, parent, &carg.ty);
self.tys.tmp.args.push(ty);
let sym = parser::find_symbol(&fast.symbols, carg.id);
@ -4526,7 +4603,7 @@ impl<'a> Codegen<'a> {
self.error(pos, "function instance has too many arguments");
return None;
};
let ret = self.ty_in(file, ret);
let ret = self.ty_in(file, parent, ret);
self.ci.scope.vars.drain(base..).for_each(|v| v.remove(&mut self.ci.nodes));
@ -4695,7 +4772,7 @@ impl<'a> Codegen<'a> {
let ast = &self.files[file.index()];
let expr = func.expr.get(ast);
self.pool.push_ci(file, Some(sig.ret), 0, &mut self.ci);
self.pool.push_ci(file, func.parent, Some(sig.ret), 0, &mut self.ci);
let prev_err_len = self.errors.borrow().len();
log::info!("{}", self.ast_display(expr));
@ -4852,11 +4929,11 @@ impl<'a> Codegen<'a> {
}
fn ty(&mut self, expr: &Expr) -> ty::Id {
self.ty_in(self.ci.file, expr)
self.ty_in(self.ci.file, self.ci.parent, expr)
}
fn ty_in(&mut self, file: Module, expr: &Expr) -> ty::Id {
self.parse_ty(file, expr, None)
fn ty_in(&mut self, file: Module, parent: ty::Id, expr: &Expr) -> ty::Id {
self.parse_ty(TyScope { file, parent, name: None }, expr)
}
fn ty_display(&self, ty: ty::Id) -> ty::Display {
@ -5117,7 +5194,7 @@ impl<'a> Codegen<'a> {
_ => unreachable!(),
})
.collect::<Vec<_>>();
self.pool.push_ci(file, Some(ret), self.tys.tasks.len(), &mut self.ci);
self.pool.push_ci(file, self.ci.parent, Some(ret), self.tys.tasks.len(), &mut self.ci);
self.ci.scope.vars = scope
.into_iter()
.map(|(v, id)| {
@ -5170,7 +5247,7 @@ impl<'a> Codegen<'a> {
let gid = self.tys.ins.globals.push(Global { file, name, ..Default::default() });
self.pool.push_ci(file, None, self.tys.tasks.len(), &mut self.ci);
self.pool.push_ci(file, self.ci.parent, None, self.tys.tasks.len(), &mut self.ci);
let prev_err_len = self.errors.borrow().len();
self.expr(&(Expr::Return { pos: expr.pos(), val: Some(expr) }));
@ -5216,6 +5293,17 @@ impl<'a> Codegen<'a> {
from_file: Module,
file: Module,
id: Result<Ident, &str>,
) -> ty::Id {
self.find_type_low(pos, from_file, file, None, id)
}
fn find_type_low(
&mut self,
pos: Pos,
from_file: Module,
file: Module,
subscope: Option<(ty::Id, &[Expr])>,
id: Result<Ident, &str>,
) -> ty::Id {
let ty = if let Ok(id) = id
&& let Some(ty) = self.find_local_ty(id)
@ -5229,7 +5317,9 @@ impl<'a> Codegen<'a> {
} else {
let f = &self.files[file.index()];
let Some((expr @ Expr::BinOp { left, right, .. }, name)) = f.find_decl(id) else {
let Some((expr @ Expr::BinOp { left, right, .. }, name)) =
parser::find_decl(subscope.map(|(_, s)| s).unwrap_or(f.exprs()), &f.file, id)
else {
return match id {
Ok(_) => {
debug_assert_eq!(from_file, file);
@ -5264,10 +5354,22 @@ impl<'a> Codegen<'a> {
self.tys
.ins
.consts
.push(Const { ast: ExprRef::new(expr), name, file })
.push(Const {
ast: ExprRef::new(expr),
name,
file,
parent: subscope.map(|(p, _)| p).unwrap_or(file.into()),
})
.into()
} else {
self.parse_ty(file, right, Some(name))
self.parse_ty(
TyScope {
file,
parent: subscope.map(|(p, _)| p).unwrap_or(file.into()),
name: Some(name),
},
right,
)
},
)
})
@ -5309,37 +5411,38 @@ impl<'a> Codegen<'a> {
}
/// returns none if comptime eval is required
fn parse_ty(&mut self, file: Module, expr: &Expr, name: Option<Ident>) -> ty::Id {
fn parse_ty(&mut self, sc: TyScope, expr: &Expr) -> ty::Id {
match *expr {
Expr::Slf { .. } => sc.parent,
Expr::Mod { id, .. } => id.into(),
Expr::UnOp { op: TokenKind::Xor, val, .. } => {
let base = self.parse_ty(file, val, None);
let base = self.parse_ty(sc.anon(), val);
self.tys.make_ptr(base)
}
Expr::UnOp { op: TokenKind::Que, val, .. } => {
let base = self.parse_ty(file, val, None);
let base = self.parse_ty(sc.anon(), val);
self.tys.make_opt(base)
}
Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => bt.into(),
Expr::Ident { id, pos, .. } => self.find_type(pos, file, file, Ok(id)),
Expr::Ident { id, pos, .. } => self.find_type(pos, sc.file, sc.file, Ok(id)),
Expr::Field { target, pos, name }
if let ty::Kind::Module(inside) = self.parse_ty(file, target, None).expand() =>
if let ty::Kind::Module(inside) = self.parse_ty(sc.anon(), target).expand() =>
{
self.find_type(pos, file, inside, Err(name))
self.find_type(pos, sc.file, inside, Err(name))
}
Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr),
Expr::Slice { size: None, item, .. } => {
let ty = self.parse_ty(file, item, None);
let ty = self.parse_ty(sc.anon(), item);
self.tys.make_array(ty, ArrayLen::MAX)
}
Expr::Slice { size: Some(&Expr::Number { value, .. }), item, .. } => {
let ty = self.parse_ty(file, item, None);
let ty = self.parse_ty(sc.anon(), item);
self.tys.make_array(ty, value as _)
}
Expr::Slice { size, item, .. } => {
let ty = self.parse_ty(file, item, None);
let ty = self.parse_ty(sc.anon(), item);
let len = size
.map_or(ArrayLen::MAX, |expr| self.eval_const(file, expr, ty::Id::U32) as _);
.map_or(ArrayLen::MAX, |expr| self.eval_const(sc.file, expr, ty::Id::U32) as _);
self.tys.make_array(ty, len)
}
Expr::Struct { pos, fields, packed, captured, .. } => {
@ -5350,14 +5453,14 @@ impl<'a> Codegen<'a> {
}
let captured = self.tys.pack_args(captures_start).expect("TODO");
let sym = SymKey::Struct(file, pos, captured);
let sym = SymKey::Struct(sc.file, pos, captured);
if let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins) {
return ty;
}
let prev_tmp = self.tys.tmp.struct_fields.len();
for field in fields.iter().filter_map(CommentOr::or) {
let ty = self.parse_ty(file, &field.ty, None);
for field in fields.iter().filter_map(CommentOr::or).filter_map(Result::ok) {
let ty = self.parse_ty(sc.anon(), &field.ty);
let field = StructField { name: self.tys.names.intern(field.name), ty };
self.tys.tmp.struct_fields.push(field);
}
@ -5367,11 +5470,12 @@ impl<'a> Codegen<'a> {
.ins
.structs
.push(Struct {
file,
file: sc.file,
pos,
name: name.unwrap_or_default(),
name: sc.name.unwrap_or_default(),
field_start: self.tys.ins.struct_fields.len() as _,
explicit_alignment: packed.then_some(1),
ast: ExprRef::new(expr),
..Default::default()
})
.into();
@ -5382,7 +5486,7 @@ impl<'a> Codegen<'a> {
ty
}
Expr::Enum { pos, variants, .. } => {
let sym = SymKey::Enum(file, pos);
let sym = SymKey::Enum(sc.file, pos);
if let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins) {
return ty;
}
@ -5398,9 +5502,9 @@ impl<'a> Codegen<'a> {
.ins
.enums
.push(Enum {
file,
file: sc.file,
pos,
name: name.unwrap_or_default(),
name: sc.name.unwrap_or_default(),
field_start: self.tys.ins.enum_fields.len() as _,
})
.into();
@ -5410,27 +5514,28 @@ impl<'a> Codegen<'a> {
self.tys.syms.insert(sym, ty, &self.tys.ins);
ty
}
Expr::Closure { pos, args, ret, .. } if let Some(name) = name => {
Expr::Closure { pos, args, ret, .. } if let Some(name) = sc.name => {
let func = Func {
file,
file: sc.file,
parent: sc.parent,
name,
sig: 'b: {
let arg_base = self.tys.tmp.args.len();
for arg in args {
let sym =
parser::find_symbol(&self.files[file.index()].symbols, arg.id);
parser::find_symbol(&self.files[sc.file.index()].symbols, arg.id);
if sym.flags & idfl::COMPTIME != 0 {
self.tys.tmp.args.truncate(arg_base);
break 'b None;
}
let ty = self.parse_ty(file, &arg.ty, None);
let ty = self.parse_ty(sc.anon(), &arg.ty);
self.tys.tmp.args.push(ty);
}
let Some(args) = self.tys.pack_args(arg_base) else {
return self.error_low(file, pos, "function has too many argumnets");
return self.error_low(sc.file, pos, "function has too many argumnets");
};
let ret = self.parse_ty(file, ret, None);
let ret = self.parse_ty(sc.anon(), ret);
Some(Sig { args, ret })
},
@ -5441,12 +5546,25 @@ impl<'a> Codegen<'a> {
self.tys.ins.funcs.push(func).into()
}
_ if let Some(name) = name => self.eval_global(file, name, expr),
_ => ty::Id::from(self.eval_const(file, expr, ty::Id::TYPE)),
_ if let Some(name) = sc.name => self.eval_global(sc.file, name, expr),
_ => ty::Id::from(self.eval_const(sc.file, expr, ty::Id::TYPE)),
}
}
}
#[derive(Clone, Copy)]
struct TyScope {
file: Module,
parent: ty::Id,
name: Option<Ident>,
}
impl TyScope {
fn anon(self) -> Self {
Self { name: None, ..self }
}
}
#[cfg(test)]
mod tests {
use {
@ -5503,6 +5621,7 @@ mod tests {
loops;
pointers;
structs;
struct_scopes;
enums;
nullable_types;
struct_operators;

View file

@ -1,6 +1,6 @@
main:
ADDI64 r254, r254, -136d
ST r31, r254, 80a, 56h
ADDI64 r254, r254, -104d
ST r31, r254, 48a, 56h
LRA r32, r0, :glob_stru
JAL r31, r0, :new_stru
ST r1, r32, 0a, 16h
@ -19,33 +19,29 @@ main:
2: LI64 r34, 1d
ST r34, r32, 0a, 8h
ST r34, r32, 8a, 8h
ADDI64 r35, r254, 32d
ADDI64 r35, r254, 0d
ST r34, r254, 0a, 8h
ST r34, r254, 8a, 8h
ST r34, r254, 16a, 8h
ST r34, r254, 24a, 8h
ST r34, r254, 32a, 8h
ST r34, r254, 40a, 8h
ST r34, r254, 48a, 8h
ST r34, r254, 56a, 8h
ST r34, r254, 64a, 8h
ST r34, r254, 72a, 8h
LI64 r36, 3d
CP r32, r33
8: JNE r32, r36, :3
LD r32, r254, 64a, 8h
LD r32, r254, 32a, 8h
JEQ r32, r33, :4
LI64 r32, 100d
CP r1, r32
JMP :1
4: ST r34, r254, 32a, 8h
4: ST r34, r254, 0a, 8h
ST r34, r254, 8a, 8h
ST r34, r254, 16a, 8h
ST r34, r254, 24a, 8h
ST r34, r254, 32a, 8h
ST r34, r254, 40a, 8h
ST r34, r254, 48a, 8h
ST r34, r254, 56a, 8h
ST r34, r254, 64a, 8h
ST r34, r254, 72a, 8h
ST r33, r254, 0a, 8h
ST r33, r254, 8a, 8h
ST r33, r254, 16a, 8h
ST r33, r254, 24a, 8h
CP r32, r33
7: LD r37, r254, 64a, 8h
7: LD r37, r254, 32a, 8h
JNE r32, r36, :5
JEQ r37, r33, :6
LI64 r32, 10d
@ -65,8 +61,8 @@ main:
ST r1, r37, 0a, 16h
ADD64 r32, r32, r34
JMP :8
1: LD r31, r254, 80a, 56h
ADDI64 r254, r254, 136d
1: LD r31, r254, 48a, 56h
ADDI64 r254, r254, 104d
JALA r0, r31, 0a
new_stru:
ADDI64 r254, r254, -16d
@ -76,6 +72,6 @@ new_stru:
LD r1, r13, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 736
code size: 684
ret: 0
status: Ok(())

View file