in progress of adding methods
This commit is contained in:
parent
9dfb2eb606
commit
58ee5c0a56
|
@ -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
|
#### enums
|
||||||
```hb
|
```hb
|
||||||
Enum := enum {A, B, C}
|
Enum := enum {A, B, C}
|
||||||
|
|
|
@ -3,7 +3,10 @@ use {
|
||||||
lexer::{self, Lexer, TokenKind},
|
lexer::{self, Lexer, TokenKind},
|
||||||
parser::{self, CommentOr, CtorField, EnumField, Expr, Poser, Radix, StructField},
|
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 {
|
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
|
Decl | Assign | BorAss | XorAss | BandAss | AddAss | SubAss | MulAss | DivAss | ModAss
|
||||||
| ShrAss | ShlAss => TG::Assign,
|
| ShrAss | ShlAss => TG::Assign,
|
||||||
DQuote | Quote => TG::String,
|
DQuote | Quote => TG::String,
|
||||||
Return | If | Else | Loop | Break | Continue | Fn | Idk | Die | Struct | Packed | True
|
Slf | Return | If | Else | Loop | Break | Continue | Fn | Idk | Die | Struct | Packed
|
||||||
| False | Null | Match | Enum => TG::Keyword,
|
| True | False | Null | Match | Enum => TG::Keyword,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,12 +201,18 @@ impl<'a> Formatter<'a> {
|
||||||
return f.write_str(end);
|
return f.write_str(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(f)?;
|
if !end.is_empty() {
|
||||||
self.depth += 1;
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.depth += !end.is_empty() as usize;
|
||||||
|
let mut already_indented = end.is_empty();
|
||||||
let res = (|| {
|
let res = (|| {
|
||||||
for (i, stmt) in list.iter().enumerate() {
|
for (i, stmt) in list.iter().enumerate() {
|
||||||
for _ in 0..self.depth {
|
if !mem::take(&mut already_indented) {
|
||||||
f.write_str("\t")?;
|
for _ in 0..self.depth {
|
||||||
|
f.write_str("\t")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let add_sep = fmt(self, stmt, f)?;
|
let add_sep = fmt(self, stmt, f)?;
|
||||||
if add_sep {
|
if add_sep {
|
||||||
|
@ -225,12 +234,14 @@ impl<'a> Formatter<'a> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})();
|
})();
|
||||||
self.depth -= 1;
|
self.depth -= !end.is_empty() as usize;
|
||||||
|
|
||||||
for _ in 0..self.depth {
|
if !end.is_empty() {
|
||||||
f.write_str("\t")?;
|
for _ in 0..self.depth {
|
||||||
|
f.write_str("\t")?;
|
||||||
|
}
|
||||||
|
f.write_str(end)?;
|
||||||
}
|
}
|
||||||
f.write_str(end)?;
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +280,7 @@ impl<'a> Formatter<'a> {
|
||||||
f.write_str("$: ")?;
|
f.write_str("$: ")?;
|
||||||
self.fmt(value, f)
|
self.fmt(value, f)
|
||||||
}
|
}
|
||||||
|
Expr::Slf { .. } => f.write_str("Self"),
|
||||||
Expr::String { literal, .. } => f.write_str(literal),
|
Expr::String { literal, .. } => f.write_str(literal),
|
||||||
Expr::Comment { literal, .. } => f.write_str(literal),
|
Expr::Comment { literal, .. } => f.write_str(literal),
|
||||||
Expr::Mod { path, .. } => write!(f, "@use(\"{path}\")"),
|
Expr::Mod { path, .. } => write!(f, "@use(\"{path}\")"),
|
||||||
|
@ -292,11 +304,15 @@ impl<'a> Formatter<'a> {
|
||||||
f.write_str("struct {")?;
|
f.write_str("struct {")?;
|
||||||
self.fmt_list_low(f, trailing_comma, "}", ",", fields, |s, field, f| {
|
self.fmt_list_low(f, trailing_comma, "}", ",", fields, |s, field, f| {
|
||||||
match field {
|
match field {
|
||||||
CommentOr::Or(StructField { name, ty, .. }) => {
|
CommentOr::Or(Ok(StructField { name, ty, .. })) => {
|
||||||
f.write_str(name)?;
|
f.write_str(name)?;
|
||||||
f.write_str(": ")?;
|
f.write_str(": ")?;
|
||||||
s.fmt(ty, f)?
|
s.fmt(ty, f)?
|
||||||
}
|
}
|
||||||
|
CommentOr::Or(Err(scope)) => {
|
||||||
|
s.fmt_list(f, true, "", "", scope, Self::fmt)?;
|
||||||
|
return Ok(false);
|
||||||
|
}
|
||||||
CommentOr::Comment { literal, .. } => {
|
CommentOr::Comment { literal, .. } => {
|
||||||
f.write_str(literal)?;
|
f.write_str(literal)?;
|
||||||
f.write_str("\n")?;
|
f.write_str("\n")?;
|
||||||
|
@ -570,6 +586,7 @@ pub mod test {
|
||||||
|
|
||||||
let mut ctx = Ctx::default();
|
let mut ctx = Ctx::default();
|
||||||
let ast = parser::Ast::new(ident, minned, &mut ctx, &mut parser::no_loader);
|
let ast = parser::Ast::new(ident, minned, &mut ctx, &mut parser::no_loader);
|
||||||
|
log::info!("{}", ctx.errors.borrow());
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
write!(output, "{ast}").unwrap();
|
write!(output, "{ast}").unwrap();
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ pub enum TokenKind {
|
||||||
Under = b'_',
|
Under = b'_',
|
||||||
Tick = b'`',
|
Tick = b'`',
|
||||||
|
|
||||||
|
Slf,
|
||||||
Return,
|
Return,
|
||||||
If,
|
If,
|
||||||
Match,
|
Match,
|
||||||
|
@ -302,6 +303,7 @@ gen_token_kind! {
|
||||||
Eof,
|
Eof,
|
||||||
Directive,
|
Directive,
|
||||||
#[keywords]
|
#[keywords]
|
||||||
|
Slf = b"Self",
|
||||||
Return = b"return",
|
Return = b"return",
|
||||||
If = b"if",
|
If = b"if",
|
||||||
Match = b"match",
|
Match = b"match",
|
||||||
|
@ -401,6 +403,10 @@ impl<'a> Lexer<'a> {
|
||||||
unsafe { core::str::from_utf8_unchecked(&self.source[tok]) }
|
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> {
|
fn peek(&self) -> Option<u8> {
|
||||||
if core::intrinsics::unlikely(self.pos >= self.source.len() as u32) {
|
if core::intrinsics::unlikely(self.pos >= self.source.len() as u32) {
|
||||||
None
|
None
|
||||||
|
|
|
@ -503,8 +503,8 @@ pub mod ty {
|
||||||
Kind::Ptr(_) | Kind::Enum(_) | Kind::Builtin(_) => Loc::Reg,
|
Kind::Ptr(_) | Kind::Enum(_) | Kind::Builtin(_) => Loc::Reg,
|
||||||
Kind::Struct(_) if tys.size_of(*self) == 0 => Loc::Reg,
|
Kind::Struct(_) if tys.size_of(*self) == 0 => Loc::Reg,
|
||||||
Kind::Struct(_) | Kind::Slice(_) | Kind::Opt(_) => Loc::Stack,
|
Kind::Struct(_) | Kind::Slice(_) | Kind::Opt(_) => Loc::Stack,
|
||||||
Kind::Func(_) | Kind::Global(_) | Kind::Module(_) | Kind::Const(_) => {
|
c @ (Kind::Func(_) | Kind::Global(_) | Kind::Module(_) | Kind::Const(_)) => {
|
||||||
unreachable!()
|
unreachable!("{c:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -823,6 +823,7 @@ pub struct Sig {
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
struct Func {
|
struct Func {
|
||||||
file: Module,
|
file: Module,
|
||||||
|
parent: ty::Id,
|
||||||
name: Ident,
|
name: Ident,
|
||||||
base: Option<ty::Func>,
|
base: Option<ty::Func>,
|
||||||
expr: ExprRef,
|
expr: ExprRef,
|
||||||
|
@ -859,6 +860,7 @@ pub struct Const {
|
||||||
ast: ExprRef,
|
ast: ExprRef,
|
||||||
name: Ident,
|
name: Ident,
|
||||||
file: Module,
|
file: Module,
|
||||||
|
parent: ty::Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make into bit struct (width: u2, sub_offset: u3, offset: u27)
|
// TODO: make into bit struct (width: u2, sub_offset: u3, offset: u27)
|
||||||
|
@ -915,6 +917,7 @@ struct Struct {
|
||||||
captures: ty::Tuple,
|
captures: ty::Tuple,
|
||||||
explicit_alignment: Option<u8>,
|
explicit_alignment: Option<u8>,
|
||||||
field_start: u32,
|
field_start: u32,
|
||||||
|
ast: ExprRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
|
|
@ -300,8 +300,10 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let token @ Token { start: pos, .. } = self.next();
|
let token @ Token { start: pos, .. } = self.next();
|
||||||
let prev_boundary = self.ns_bound;
|
let prev_boundary = self.ns_bound;
|
||||||
let prev_captured = self.ctx.captured.len();
|
let prev_captured = self.ctx.captured.len();
|
||||||
|
let mut must_trail = false;
|
||||||
let mut expr = match token.kind {
|
let mut expr = match token.kind {
|
||||||
T::Ct => E::Ct { pos, value: self.ptr_expr()? },
|
T::Ct => E::Ct { pos, value: self.ptr_expr()? },
|
||||||
|
T::Slf => E::Slf { pos },
|
||||||
T::Directive if self.lexer.slice(token.range()) == "use" => {
|
T::Directive if self.lexer.slice(token.range()) == "use" => {
|
||||||
self.expect_advance(TokenKind::LParen)?;
|
self.expect_advance(TokenKind::LParen)?;
|
||||||
let str = self.expect_advance(TokenKind::DQuote)?;
|
let str = self.expect_advance(TokenKind::DQuote)?;
|
||||||
|
@ -374,14 +376,19 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let tok = s.token;
|
let tok = s.token;
|
||||||
Some(if s.advance_if(T::Comment) {
|
Some(if s.advance_if(T::Comment) {
|
||||||
CommentOr::Comment { literal: s.tok_str(tok), pos: tok.start }
|
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)?;
|
let name = s.expect_advance(T::Ident)?;
|
||||||
s.expect_advance(T::Colon)?;
|
s.expect_advance(T::Colon)?;
|
||||||
CommentOr::Or(StructField {
|
CommentOr::Or(Ok(StructField {
|
||||||
pos: name.start,
|
pos: name.start,
|
||||||
name: s.tok_str(name),
|
name: s.tok_str(name),
|
||||||
ty: s.expr()?,
|
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
|
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 {
|
T::Enum => E::Enum {
|
||||||
pos,
|
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);
|
self.pop_scope(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,11 +658,21 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
&mut self,
|
&mut self,
|
||||||
delim: TokenKind,
|
delim: TokenKind,
|
||||||
end: 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>,
|
mut f: impl FnMut(&mut Self) -> Option<T>,
|
||||||
) -> &'a [T] {
|
) -> &'a [T] {
|
||||||
let mut trailing_sep = false;
|
let mut trailing_sep = false;
|
||||||
let mut view = self.ctx.stack.view();
|
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) {
|
let val = match f(self) {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
None => {
|
None => {
|
||||||
|
@ -833,6 +850,10 @@ generate_expr! {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
value: &'a Self,
|
value: &'a Self,
|
||||||
},
|
},
|
||||||
|
/// `'Self'`
|
||||||
|
Slf {
|
||||||
|
pos: Pos,
|
||||||
|
},
|
||||||
/// `'"([^"]|\\")"'`
|
/// `'"([^"]|\\")"'`
|
||||||
String {
|
String {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
|
@ -931,7 +952,7 @@ generate_expr! {
|
||||||
/// `'struct' LIST('{', ',', '}', Ident ':' Expr)`
|
/// `'struct' LIST('{', ',', '}', Ident ':' Expr)`
|
||||||
Struct {
|
Struct {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
fields: &'a [CommentOr<'a, StructField<'a>>],
|
fields: &'a [CommentOr<'a, Result<StructField<'a>, &'a[Self]>>],
|
||||||
captured: &'a [Ident],
|
captured: &'a [Ident],
|
||||||
trailing_comma: bool,
|
trailing_comma: bool,
|
||||||
packed: bool,
|
packed: bool,
|
||||||
|
@ -1112,6 +1133,18 @@ pub trait Poser {
|
||||||
fn posi(&self) -> Pos;
|
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 {
|
impl Poser for Pos {
|
||||||
fn posi(&self) -> Pos {
|
fn posi(&self) -> Pos {
|
||||||
*self
|
*self
|
||||||
|
@ -1312,12 +1345,7 @@ impl Ast {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_decl(&self, id: Result<Ident, &str>) -> Option<(&Expr, Ident)> {
|
pub fn find_decl(&self, id: Result<Ident, &str>) -> Option<(&Expr, Ident)> {
|
||||||
self.exprs().iter().find_map(|expr| match expr {
|
find_decl(self.exprs(), &self.file, id)
|
||||||
Expr::BinOp { left, op: TokenKind::Decl, .. } => {
|
|
||||||
left.declares(id, &self.file).map(|id| (expr, id))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ident_str(&self, ident: Ident) -> &str {
|
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 {
|
impl Default for Ast {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(AstInner::new("".into(), "".into(), &mut Ctx::default(), &mut no_loader))
|
Self(AstInner::new("".into(), "".into(), &mut Ctx::default(), &mut no_loader))
|
||||||
|
|
239
lang/src/son.rs
239
lang/src/son.rs
|
@ -2342,6 +2342,7 @@ impl Scope {
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct ItemCtx {
|
pub struct ItemCtx {
|
||||||
file: Module,
|
file: Module,
|
||||||
|
parent: ty::Id,
|
||||||
pos: Vec<Pos>,
|
pos: Vec<Pos>,
|
||||||
ret: Option<ty::Id>,
|
ret: Option<ty::Id>,
|
||||||
task_base: usize,
|
task_base: usize,
|
||||||
|
@ -2356,7 +2357,7 @@ pub struct ItemCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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.loops.len(), 0);
|
||||||
debug_assert_eq!(self.scope.vars.len(), 0);
|
debug_assert_eq!(self.scope.vars.len(), 0);
|
||||||
debug_assert_eq!(self.scope.aclasses.len(), 0);
|
debug_assert_eq!(self.scope.aclasses.len(), 0);
|
||||||
|
@ -2366,6 +2367,7 @@ impl ItemCtx {
|
||||||
debug_assert_eq!(self.inline_aclass_base, 0);
|
debug_assert_eq!(self.inline_aclass_base, 0);
|
||||||
|
|
||||||
self.file = file;
|
self.file = file;
|
||||||
|
self.parent = parent;
|
||||||
self.ret = ret;
|
self.ret = ret;
|
||||||
self.task_base = task_base;
|
self.task_base = task_base;
|
||||||
|
|
||||||
|
@ -2433,6 +2435,7 @@ impl Pool {
|
||||||
fn push_ci(
|
fn push_ci(
|
||||||
&mut self,
|
&mut self,
|
||||||
file: Module,
|
file: Module,
|
||||||
|
parent: ty::Id,
|
||||||
ret: Option<ty::Id>,
|
ret: Option<ty::Id>,
|
||||||
task_base: usize,
|
task_base: usize,
|
||||||
target: &mut ItemCtx,
|
target: &mut ItemCtx,
|
||||||
|
@ -2443,7 +2446,7 @@ impl Pool {
|
||||||
self.cis.push(ItemCtx::default());
|
self.cis.push(ItemCtx::default());
|
||||||
mem::swap(self.cis.last_mut().unwrap(), target);
|
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;
|
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::Load
|
||||||
|| self.ci.nodes[region].kind == Kind::Stck
|
|| self.ci.nodes[region].kind == Kind::Stck
|
||||||
|| self.ci.nodes[region].ty.is_pointer(),
|
|| self.ci.nodes[region].ty.is_pointer(),
|
||||||
"{:?} {} {}",
|
"{:?} {} {} {:?}",
|
||||||
self.ci.nodes.graphviz_in_browser(self.ty_display(ty::Id::VOID)),
|
self.ci.nodes.graphviz_in_browser(self.ty_display(ty::Id::VOID)),
|
||||||
self.file().path,
|
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);
|
debug_assert!(self.ci.nodes[region].kind != Kind::Stre);
|
||||||
let (index, _) = self.ci.nodes.aclass_index(region);
|
let (index, _) = self.ci.nodes.aclass_index(region);
|
||||||
|
@ -2820,7 +2824,7 @@ impl<'a> Codegen<'a> {
|
||||||
ty::Kind::NEVER => Value::NEVER,
|
ty::Kind::NEVER => Value::NEVER,
|
||||||
ty::Kind::Global(global) => self.gen_global(global),
|
ty::Kind::Global(global) => self.gen_global(global),
|
||||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
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),
|
Expr::Comment { .. } => Some(Value::VOID),
|
||||||
|
@ -2863,9 +2867,9 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
let expected = *self.ci.ret.get_or_insert(value.ty);
|
let expected = *self.ci.ret.get_or_insert(value.ty);
|
||||||
self.assert_ty(pos, &mut value, expected, "return value");
|
self.assert_ty(pos, &mut value, expected, "return value");
|
||||||
self.strip_ptr(&mut value);
|
|
||||||
|
|
||||||
if self.ci.inline_depth == 0 {
|
if self.ci.inline_depth == 0 {
|
||||||
|
self.strip_ptr(&mut value);
|
||||||
debug_assert_ne!(self.ci.ctrl.get(), VOID);
|
debug_assert_ne!(self.ci.ctrl.get(), VOID);
|
||||||
let mut inps = Vc::from([self.ci.ctrl.get(), value.id]);
|
let mut inps = Vc::from([self.ci.ctrl.get(), value.id]);
|
||||||
for (i, aclass) in self.ci.scope.aclasses.iter_mut().enumerate() {
|
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));
|
.for_each(|v| v.remove(&mut self.ci.nodes));
|
||||||
|
|
||||||
let repl = StrongRef::new(NEVER, &mut self.ci.nodes);
|
let repl = StrongRef::new(NEVER, &mut self.ci.nodes);
|
||||||
let (index, _) = self
|
let (index, _) = self.ci.nodes.aclass_index(value.id);
|
||||||
.ci
|
|
||||||
.nodes
|
|
||||||
.aclass_index(*self.ci.nodes[value.id].inputs.get(1).unwrap_or(&VOID));
|
|
||||||
let aclass = (self.ci.inline_aclass_base <= index)
|
let aclass = (self.ci.inline_aclass_base <= index)
|
||||||
.then(|| self.ci.scope.aclasses[index].dup(&mut self.ci.nodes));
|
.then(|| self.ci.scope.aclasses[index].dup(&mut self.ci.nodes));
|
||||||
self.ci.inline_ret =
|
self.ci.inline_ret =
|
||||||
|
@ -2964,7 +2965,7 @@ impl<'a> Codegen<'a> {
|
||||||
ty::Kind::NEVER => Value::NEVER,
|
ty::Kind::NEVER => Value::NEVER,
|
||||||
ty::Kind::Global(global) => self.gen_global(global),
|
ty::Kind::Global(global) => self.gen_global(global),
|
||||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
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) => {
|
ty::Kind::Enum(e) => {
|
||||||
|
@ -2972,7 +2973,23 @@ impl<'a> Codegen<'a> {
|
||||||
self.gen_enum_variant(pos, e, intrnd)
|
self.gen_enum_variant(pos, e, intrnd)
|
||||||
}
|
}
|
||||||
ty::Kind::Struct(s) => {
|
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
|
let field_list = self
|
||||||
.tys
|
.tys
|
||||||
.struct_fields(s)
|
.struct_fields(s)
|
||||||
|
@ -2984,15 +3001,66 @@ impl<'a> Codegen<'a> {
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"the '{}' does not have this field, \
|
"the '{}' does not have this field, \
|
||||||
but it does have '{field_list}'",
|
but it does have '{field_list}'",
|
||||||
self.ty_display(tty)
|
self.ty_display(tty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
Value::NEVER
|
||||||
};
|
}
|
||||||
|
|
||||||
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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(
|
self.error(
|
||||||
pos,
|
pos,
|
||||||
|
@ -3203,11 +3271,13 @@ impl<'a> Codegen<'a> {
|
||||||
Some(bop)
|
Some(bop)
|
||||||
}
|
}
|
||||||
ty::Kind::Struct(s) if op.is_homogenous() => {
|
ty::Kind::Struct(s) if op.is_homogenous() => {
|
||||||
|
debug_assert!(lhs.ptr);
|
||||||
self.ci.nodes.lock(lhs.id);
|
self.ci.nodes.lock(lhs.id);
|
||||||
let rhs = self.raw_expr_ctx(right, Ctx::default().with_ty(lhs.ty));
|
let rhs = self.raw_expr_ctx(right, Ctx::default().with_ty(lhs.ty));
|
||||||
self.ci.nodes.unlock(lhs.id);
|
self.ci.nodes.unlock(lhs.id);
|
||||||
let mut rhs = rhs?;
|
let mut rhs = rhs?;
|
||||||
self.strip_var(&mut rhs);
|
self.strip_var(&mut rhs);
|
||||||
|
debug_assert!(rhs.ptr);
|
||||||
self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand");
|
self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand");
|
||||||
let dst = self.new_stack(pos, lhs.ty);
|
let dst = self.new_stack(pos, lhs.ty);
|
||||||
self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id);
|
self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id);
|
||||||
|
@ -4082,8 +4152,8 @@ impl<'a> Codegen<'a> {
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
ref e => {
|
ref e => {
|
||||||
self.error_unhandled_ast(e, "bruh");
|
let ty = self.ty(e);
|
||||||
Value::NEVER
|
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> {
|
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 {
|
let ty::Kind::Func(mut fu) = ty.expand() else {
|
||||||
self.error(func.pos(), fa!("compiler cant (yet) call '{}'", self.ty_display(ty)));
|
self.error(func.pos(), fa!("compiler cant (yet) call '{}'", self.ty_display(ty)));
|
||||||
return Value::NEVER;
|
return Value::NEVER;
|
||||||
|
@ -4333,7 +4408,8 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
fn gen_const(&mut self, cnst: ty::Const, ctx: Ctx) -> Option<Value> {
|
fn gen_const(&mut self, cnst: ty::Const, ctx: Ctx) -> Option<Value> {
|
||||||
let c = &self.tys.ins.consts[cnst];
|
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 f = &self.files[c.file.index()];
|
||||||
let Expr::BinOp { left, right, .. } = c.ast.get(f) else { unreachable!() };
|
let Expr::BinOp { left, right, .. } = c.ast.get(f) else { unreachable!() };
|
||||||
|
|
||||||
|
@ -4344,7 +4420,8 @@ impl<'a> Codegen<'a> {
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|_| unreachable!())?;
|
.unwrap_or_else(|_| unreachable!())?;
|
||||||
self.strip_var(&mut value);
|
self.strip_var(&mut value);
|
||||||
self.ci.file = prev;
|
self.ci.file = prev_file;
|
||||||
|
self.ci.parent = prev_parent;
|
||||||
Some(value)
|
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> {
|
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 fast = &self.files[file.index()];
|
||||||
let &Expr::Closure { args: cargs, ret, .. } = expr.get(fast) else {
|
let &Expr::Closure { args: cargs, ret, .. } = expr.get(fast) else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
|
@ -4488,7 +4565,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
let base = self.ci.scope.vars.len();
|
let base = self.ci.scope.vars.len();
|
||||||
for (arg, carg) in args.iter().zip(cargs) {
|
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);
|
self.tys.tmp.args.push(ty);
|
||||||
let sym = parser::find_symbol(&fast.symbols, carg.id);
|
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");
|
self.error(pos, "function instance has too many arguments");
|
||||||
return None;
|
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));
|
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 ast = &self.files[file.index()];
|
||||||
let expr = func.expr.get(ast);
|
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();
|
let prev_err_len = self.errors.borrow().len();
|
||||||
|
|
||||||
log::info!("{}", self.ast_display(expr));
|
log::info!("{}", self.ast_display(expr));
|
||||||
|
@ -4852,11 +4929,11 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty(&mut self, expr: &Expr) -> ty::Id {
|
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 {
|
fn ty_in(&mut self, file: Module, parent: ty::Id, expr: &Expr) -> ty::Id {
|
||||||
self.parse_ty(file, expr, None)
|
self.parse_ty(TyScope { file, parent, name: None }, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_display(&self, ty: ty::Id) -> ty::Display {
|
fn ty_display(&self, ty: ty::Id) -> ty::Display {
|
||||||
|
@ -5117,7 +5194,7 @@ impl<'a> Codegen<'a> {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.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
|
self.ci.scope.vars = scope
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(v, id)| {
|
.map(|(v, id)| {
|
||||||
|
@ -5170,7 +5247,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
let gid = self.tys.ins.globals.push(Global { file, name, ..Default::default() });
|
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();
|
let prev_err_len = self.errors.borrow().len();
|
||||||
|
|
||||||
self.expr(&(Expr::Return { pos: expr.pos(), val: Some(expr) }));
|
self.expr(&(Expr::Return { pos: expr.pos(), val: Some(expr) }));
|
||||||
|
@ -5216,6 +5293,17 @@ impl<'a> Codegen<'a> {
|
||||||
from_file: Module,
|
from_file: Module,
|
||||||
file: Module,
|
file: Module,
|
||||||
id: Result<Ident, &str>,
|
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 {
|
) -> ty::Id {
|
||||||
let ty = if let Ok(id) = id
|
let ty = if let Ok(id) = id
|
||||||
&& let Some(ty) = self.find_local_ty(id)
|
&& let Some(ty) = self.find_local_ty(id)
|
||||||
|
@ -5229,7 +5317,9 @@ impl<'a> Codegen<'a> {
|
||||||
} else {
|
} else {
|
||||||
let f = &self.files[file.index()];
|
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 {
|
return match id {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
debug_assert_eq!(from_file, file);
|
debug_assert_eq!(from_file, file);
|
||||||
|
@ -5264,10 +5354,22 @@ impl<'a> Codegen<'a> {
|
||||||
self.tys
|
self.tys
|
||||||
.ins
|
.ins
|
||||||
.consts
|
.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()
|
.into()
|
||||||
} else {
|
} 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
|
/// 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 {
|
match *expr {
|
||||||
|
Expr::Slf { .. } => sc.parent,
|
||||||
Expr::Mod { id, .. } => id.into(),
|
Expr::Mod { id, .. } => id.into(),
|
||||||
Expr::UnOp { op: TokenKind::Xor, val, .. } => {
|
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)
|
self.tys.make_ptr(base)
|
||||||
}
|
}
|
||||||
Expr::UnOp { op: TokenKind::Que, val, .. } => {
|
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)
|
self.tys.make_opt(base)
|
||||||
}
|
}
|
||||||
Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => bt.into(),
|
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 }
|
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::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);
|
let ty = self.parse_ty(sc.anon(), item);
|
||||||
self.tys.make_array(ty, ArrayLen::MAX)
|
self.tys.make_array(ty, ArrayLen::MAX)
|
||||||
}
|
}
|
||||||
Expr::Slice { size: Some(&Expr::Number { value, .. }), item, .. } => {
|
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 _)
|
self.tys.make_array(ty, value as _)
|
||||||
}
|
}
|
||||||
Expr::Slice { size, item, .. } => {
|
Expr::Slice { size, item, .. } => {
|
||||||
let ty = self.parse_ty(file, item, None);
|
let ty = self.parse_ty(sc.anon(), item);
|
||||||
let len = size
|
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)
|
self.tys.make_array(ty, len)
|
||||||
}
|
}
|
||||||
Expr::Struct { pos, fields, packed, captured, .. } => {
|
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 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) {
|
if let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
let prev_tmp = self.tys.tmp.struct_fields.len();
|
let prev_tmp = self.tys.tmp.struct_fields.len();
|
||||||
for field in fields.iter().filter_map(CommentOr::or) {
|
for field in fields.iter().filter_map(CommentOr::or).filter_map(Result::ok) {
|
||||||
let ty = self.parse_ty(file, &field.ty, None);
|
let ty = self.parse_ty(sc.anon(), &field.ty);
|
||||||
let field = StructField { name: self.tys.names.intern(field.name), ty };
|
let field = StructField { name: self.tys.names.intern(field.name), ty };
|
||||||
self.tys.tmp.struct_fields.push(field);
|
self.tys.tmp.struct_fields.push(field);
|
||||||
}
|
}
|
||||||
|
@ -5367,11 +5470,12 @@ impl<'a> Codegen<'a> {
|
||||||
.ins
|
.ins
|
||||||
.structs
|
.structs
|
||||||
.push(Struct {
|
.push(Struct {
|
||||||
file,
|
file: sc.file,
|
||||||
pos,
|
pos,
|
||||||
name: name.unwrap_or_default(),
|
name: sc.name.unwrap_or_default(),
|
||||||
field_start: self.tys.ins.struct_fields.len() as _,
|
field_start: self.tys.ins.struct_fields.len() as _,
|
||||||
explicit_alignment: packed.then_some(1),
|
explicit_alignment: packed.then_some(1),
|
||||||
|
ast: ExprRef::new(expr),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.into();
|
.into();
|
||||||
|
@ -5382,7 +5486,7 @@ impl<'a> Codegen<'a> {
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
Expr::Enum { pos, variants, .. } => {
|
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) {
|
if let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
@ -5398,9 +5502,9 @@ impl<'a> Codegen<'a> {
|
||||||
.ins
|
.ins
|
||||||
.enums
|
.enums
|
||||||
.push(Enum {
|
.push(Enum {
|
||||||
file,
|
file: sc.file,
|
||||||
pos,
|
pos,
|
||||||
name: name.unwrap_or_default(),
|
name: sc.name.unwrap_or_default(),
|
||||||
field_start: self.tys.ins.enum_fields.len() as _,
|
field_start: self.tys.ins.enum_fields.len() as _,
|
||||||
})
|
})
|
||||||
.into();
|
.into();
|
||||||
|
@ -5410,27 +5514,28 @@ impl<'a> Codegen<'a> {
|
||||||
self.tys.syms.insert(sym, ty, &self.tys.ins);
|
self.tys.syms.insert(sym, ty, &self.tys.ins);
|
||||||
ty
|
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 {
|
let func = Func {
|
||||||
file,
|
file: sc.file,
|
||||||
|
parent: sc.parent,
|
||||||
name,
|
name,
|
||||||
sig: 'b: {
|
sig: 'b: {
|
||||||
let arg_base = self.tys.tmp.args.len();
|
let arg_base = self.tys.tmp.args.len();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let sym =
|
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 {
|
if sym.flags & idfl::COMPTIME != 0 {
|
||||||
self.tys.tmp.args.truncate(arg_base);
|
self.tys.tmp.args.truncate(arg_base);
|
||||||
break 'b None;
|
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);
|
self.tys.tmp.args.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(args) = self.tys.pack_args(arg_base) else {
|
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 })
|
Some(Sig { args, ret })
|
||||||
},
|
},
|
||||||
|
@ -5441,12 +5546,25 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
self.tys.ins.funcs.push(func).into()
|
self.tys.ins.funcs.push(func).into()
|
||||||
}
|
}
|
||||||
_ if let Some(name) = name => self.eval_global(file, name, expr),
|
_ if let Some(name) = sc.name => self.eval_global(sc.file, name, expr),
|
||||||
_ => ty::Id::from(self.eval_const(file, expr, ty::Id::TYPE)),
|
_ => 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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use {
|
use {
|
||||||
|
@ -5503,6 +5621,7 @@ mod tests {
|
||||||
loops;
|
loops;
|
||||||
pointers;
|
pointers;
|
||||||
structs;
|
structs;
|
||||||
|
struct_scopes;
|
||||||
enums;
|
enums;
|
||||||
nullable_types;
|
nullable_types;
|
||||||
struct_operators;
|
struct_operators;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -136d
|
ADDI64 r254, r254, -104d
|
||||||
ST r31, r254, 80a, 56h
|
ST r31, r254, 48a, 56h
|
||||||
LRA r32, r0, :glob_stru
|
LRA r32, r0, :glob_stru
|
||||||
JAL r31, r0, :new_stru
|
JAL r31, r0, :new_stru
|
||||||
ST r1, r32, 0a, 16h
|
ST r1, r32, 0a, 16h
|
||||||
|
@ -19,33 +19,29 @@ main:
|
||||||
2: LI64 r34, 1d
|
2: LI64 r34, 1d
|
||||||
ST r34, r32, 0a, 8h
|
ST r34, r32, 0a, 8h
|
||||||
ST r34, r32, 8a, 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, 32a, 8h
|
||||||
ST r34, r254, 40a, 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
|
LI64 r36, 3d
|
||||||
CP r32, r33
|
CP r32, r33
|
||||||
8: JNE r32, r36, :3
|
8: JNE r32, r36, :3
|
||||||
LD r32, r254, 64a, 8h
|
LD r32, r254, 32a, 8h
|
||||||
JEQ r32, r33, :4
|
JEQ r32, r33, :4
|
||||||
LI64 r32, 100d
|
LI64 r32, 100d
|
||||||
CP r1, r32
|
CP r1, r32
|
||||||
JMP :1
|
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, 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
|
CP r32, r33
|
||||||
7: LD r37, r254, 64a, 8h
|
7: LD r37, r254, 32a, 8h
|
||||||
JNE r32, r36, :5
|
JNE r32, r36, :5
|
||||||
JEQ r37, r33, :6
|
JEQ r37, r33, :6
|
||||||
LI64 r32, 10d
|
LI64 r32, 10d
|
||||||
|
@ -65,8 +61,8 @@ main:
|
||||||
ST r1, r37, 0a, 16h
|
ST r1, r37, 0a, 16h
|
||||||
ADD64 r32, r32, r34
|
ADD64 r32, r32, r34
|
||||||
JMP :8
|
JMP :8
|
||||||
1: LD r31, r254, 80a, 56h
|
1: LD r31, r254, 48a, 56h
|
||||||
ADDI64 r254, r254, 136d
|
ADDI64 r254, r254, 104d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
new_stru:
|
new_stru:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -16d
|
||||||
|
@ -76,6 +72,6 @@ new_stru:
|
||||||
LD r1, r13, 0a, 16h
|
LD r1, r13, 0a, 16h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 736
|
code size: 684
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
0
lang/tests/son_tests_struct_scopes.txt
Normal file
0
lang/tests/son_tests_struct_scopes.txt
Normal file
Loading…
Reference in a new issue