From f59c0c10922fb330d43b944a5bfcaa1021ecffe3 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Fri, 20 Dec 2024 11:32:18 +0100 Subject: [PATCH] some syntax changes mainly added the explicit type for declarations Signed-off-by: Jakub Doka --- lang/README.md | 36 ++++++++++----------- lang/src/fmt.rs | 4 ++- lang/src/parser.rs | 80 ++++++++++++++++++++++++++++------------------ lang/src/son.rs | 43 ++++++++++++++++++++----- lang/src/ty.rs | 17 +++++++--- 5 files changed, 117 insertions(+), 63 deletions(-) diff --git a/lang/README.md b/lang/README.md index ef8a60b..e12d062 100644 --- a/lang/README.md +++ b/lang/README.md @@ -299,17 +299,17 @@ main := fn(): uint { main := fn(): uint { a := &1 - b := @as(?^uint, null) + b: ?^uint = null if decide() b = a if b == null return 9001 - c := @as(?uint, *b) + c: ?uint = *b if decide() c = null if c != null return 42 - d := @as(?u16, null) + d: ?u16 = null if decide() d = 1 if d == null return 69 @@ -331,7 +331,7 @@ main := fn(): uint { if bar != null return 420 - g := @as(?^uint, null) + g: ?^uint = null g = a _rd := *g @@ -452,8 +452,8 @@ main := fn(): uint { hardcoded_pointer := @as(^u8, @bitcast(10)) ecall_that_returns_uint := @as(uint, @eca(1, foo.Type.(10, 20), 5, 6)) embedded_array := @as([15]u8, @embed("text.txt")) - two_fields := @len(foo.Type) - string_length := @len("foo\0") + two_fields := @lenof(foo.Type) + string_length := @lenof("foo\0") the_struct_kind := @kindof(foo.Type) return @inline(foo.foo) } @@ -482,7 +482,7 @@ arbitrary text - `@eca(...)`: invoke `eca` instruction, where return type is inferred and `...` are arguments passed to the call in the standard call convention - `@embed()`: include relative file as an array of bytes - `@inline(, ...)`: equivalent to `(...)` but function is guaranteed to inline, compiler will otherwise never inline -- `@len()`: reports a length of the type of indexing purposes or length ot a string constant +- `@lenof()`: reports a length of the type of indexing purposes or length ot a string constant - `@kindof()`: gives an u8 integer describing the kind of type as an index to array `[Builtin, Struct, Tuple, Enum, Union, Ptr, Slice, Opt, Func, Template, Global, Const, Module]` - `@Any()`: generic parameter based on inference, TBD: this will ake arguments in the future that restrict what is accepted - `@error(...)`: emit compiler error, if reachable, and use arguments to construct a message, can display strings and types @@ -544,7 +544,7 @@ fib_iter := fn(n: uint): uint { #### arrays ```hb main := fn(): uint { - addr := @as(u16, 0x1FF) + addr: u16 = 0x1FF msg := u8.[0, 0, @intcast(addr), @intcast(addr >> 8)] _force_stack := &msg @@ -579,10 +579,10 @@ foo := fn(a: uint, b: uint, c: uint): uint { #### idk ```hb -_edge_case := @as(uint, idk) +_edge_case: uint = idk main := fn(): uint { - big_array := @as([128]u8, idk) + big_array: [128]u8 = idk i := 0 loop if i >= 128 break else { big_array[i] = 69 @@ -637,11 +637,11 @@ Vec := fn($Elem: type): type return struct { vec.cap *= 2 } - new_alloc := @as(?^Elem, @bitcast(malloc(vec.cap * @sizeof(Elem), @alignof(Elem)))) + new_alloc: ?^Elem = @bitcast(malloc(vec.cap * @sizeof(Elem), @alignof(Elem))) if new_alloc == null return null src_cursor := vec.data - dst_cursor := @as(^Elem, new_alloc) + dst_cursor: ^Elem = new_alloc end := vec.data + vec.len loop if src_cursor == end break else { @@ -711,7 +711,7 @@ main := fn(): uint { nums := Nums.(1, 2, 3, 4) i := 0 sum := 0 - $loop if i == @len(Nums) break else { + $loop if i == @lenof(Nums) break else { sum += nums[i] i += 1 } @@ -837,7 +837,7 @@ main := fn(): int { Color := struct {b: u8} main := fn(): void { color := Color.(0) - n := @as(u8, 1) + n: u8 = 1 loop { if color.b == 255 | color.b == 0 { n = -n @@ -913,12 +913,12 @@ $H := 3 $W := 3 main := fn(): int { - y := @as(int, 0) + y: int = 0 loop if y == H break else { - x := @as(int, 0) + x: int = 0 loop if x == W break else { - c_r := @as(f64, @itf(x)) - c_i := @as(f64, @itf(y)) + c_r: f64 = @itf(x) + c_i: f64 = @itf(y) if c_i * c_r >= 10.0 return 0 x += 1 } diff --git a/lang/src/fmt.rs b/lang/src/fmt.rs index b6be8a9..7bf14a9 100644 --- a/lang/src/fmt.rs +++ b/lang/src/fmt.rs @@ -558,7 +558,9 @@ impl<'a> Formatter<'a> { f.write_str(op.name())?; f.write_str(" ")?; } else { - f.write_str(" ")?; + if op != TokenKind::Colon { + f.write_str(" ")?; + } f.write_str(op.name())?; f.write_str(" ")?; } diff --git a/lang/src/parser.rs b/lang/src/parser.rs index 93919a9..38371ab 100644 --- a/lang/src/parser.rs +++ b/lang/src/parser.rs @@ -287,6 +287,10 @@ impl<'a, 'b> Parser<'a, 'b> { } fn unit_expr(&mut self) -> Option> { + self.unit_expr_low(true) + } + + fn unit_expr_low(&mut self, eat_tail: bool) -> Option> { use {Expr as E, TokenKind as T}; if matches!( @@ -498,7 +502,7 @@ impl<'a, 'b> Parser<'a, 'b> { Some(adv) } }, - item: self.ptr_unit_expr()?, + item: self.arena.alloc(self.unit_expr_low(false)?), pos, }, T::Band | T::Mul | T::Xor | T::Sub | T::Que | T::Not | T::Dot => E::UnOp { @@ -551,38 +555,52 @@ impl<'a, 'b> Parser<'a, 'b> { tok => self.report(token.start, format_args!("unexpected token: {tok}"))?, }; - loop { - let token = self.token; - if matches!(token.kind, T::LParen | T::Ctor | T::Dot | T::Tupl | T::Arr | T::LBrack) { - self.next(); - } + if eat_tail { + loop { + let token = self.token; + if matches!( + token.kind, + T::LParen | T::Ctor | T::Dot | T::Tupl | T::Arr | T::LBrack | T::Colon + ) { + self.next(); + } - expr = match token.kind { - T::LParen => Expr::Call { - func: self.arena.alloc(expr), - args: self.collect_list(T::Comma, T::RParen, Self::expr), - trailing_comma: core::mem::take(&mut self.trailing_sep), - }, - T::Ctor => self.ctor(token.start, Some(expr)), - T::Tupl => self.tupl(token.start, Some(expr), ListKind::Tuple), - T::Arr => self.tupl(token.start, Some(expr), ListKind::Array), - T::LBrack => E::Index { - base: self.arena.alloc(expr), - index: { - let index = self.expr()?; - self.expect_advance(T::RBrack)?; - self.arena.alloc(index) + expr = match token.kind { + T::LParen => Expr::Call { + func: self.arena.alloc(expr), + args: self.collect_list(T::Comma, T::RParen, Self::expr), + trailing_comma: core::mem::take(&mut self.trailing_sep), }, - }, - T::Dot => E::Field { - target: self.arena.alloc(expr), - pos: token.start, - name: { - let token = self.expect_advance(T::Ident)?; - self.tok_str(token) + T::Ctor => self.ctor(token.start, Some(expr)), + T::Tupl => self.tupl(token.start, Some(expr), ListKind::Tuple), + T::Arr => self.tupl(token.start, Some(expr), ListKind::Array), + T::LBrack => E::Index { + base: self.arena.alloc(expr), + index: { + let index = self.expr()?; + self.expect_advance(T::RBrack)?; + self.arena.alloc(index) + }, }, - }, - _ => break, + T::Colon => E::BinOp { + left: { + self.declare_rec(&expr, false); + self.arena.alloc(expr) + }, + pos, + op: T::Colon, + right: self.ptr_expr()?, + }, + T::Dot => E::Field { + target: self.arena.alloc(expr), + pos: token.start, + name: { + let token = self.expect_advance(T::Ident)?; + self.tok_str(token) + }, + }, + _ => break, + } } } @@ -1456,7 +1474,7 @@ pub fn find_decl<'a>( id: DeclId, ) -> Option<(&'a Expr<'a>, Ident)> { exprs.iter().find_map(|expr| match expr { - Expr::BinOp { left, op: TokenKind::Decl, .. } => { + Expr::BinOp { left, op: TokenKind::Decl | TokenKind::Colon, .. } => { left.declares(id, file).map(|id| (expr, id)) } _ => None, diff --git a/lang/src/son.rs b/lang/src/son.rs index f6386ce..9e361e9 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -1081,6 +1081,21 @@ impl<'a> Codegen<'a> { self.error(pos, fa!("cant logically negate '{}'", self.ty_display(val.ty))) } } + Expr::BinOp { + left, + op: TokenKind::Colon, + right: &Expr::BinOp { left: ty, op: TokenKind::Assign, right, pos }, + .. + } => { + let ty = self.ty(ty); + let mut right = self.checked_expr(right, ty, "declaration")?; + + if right.ty.loc(self.tys) == Loc::Stack { + self.spill(pos, &mut right); + } + self.assign_pattern(left, right); + Some(Value::VOID) + } Expr::BinOp { left, op: TokenKind::Decl, right, pos } => { let mut right = self.expr(right)?; @@ -1342,14 +1357,21 @@ impl<'a> Codegen<'a> { let align = self.tys.align_of(ty); self.gen_inferred_const(ctx, ty::Id::DINT, align) } - Expr::Directive { name: "len", args: [ety], .. } => { + Expr::Directive { name: "lenof", args: [ety], .. } => { let ty = self.expr(ety)?; let len = match self.ci.nodes[ty.id].kind { - Kind::CInt { value } - if let Some(len) = self.tys.len_of(ty::Id::from(value as u64)) => - { - len - } + Kind::CInt { value } => match self.tys.len_of(ty::Id::from(value as u64)) { + Some(len) => len, + None => { + return self.error( + ety.pos(), + fa!( + "'@len' only supports structs and arrays or strings. got {}", + self.ty_display(ty::Id::from(value as u64)) + ), + ) + } + }, Kind::Global { global } => self.tys.ins.globals[global].data.len() as u32 - 1, _ => { return self @@ -2839,7 +2861,10 @@ impl<'a> Codegen<'a> { let prev_parent = mem::replace(&mut self.ci.parent, c.parent); let f = &self.files[c.file]; let value = match c.ast.get(f) { - Expr::BinOp { left, op: TokenKind::Decl, right, .. } => left + &Expr::BinOp { left, op: TokenKind::Decl, right, .. } + | &Expr::BinOp { + left, op: TokenKind::Colon, right: &Expr::BinOp { right, .. }, .. + } => left .find_pattern_path(c.name, right, |expr, is_ct| { debug_assert!(is_ct); self.ptr_expr_ctx(expr, ctx) @@ -3945,7 +3970,9 @@ impl<'a> Codegen<'a> { Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr), Expr::Directive { name: "ChildOf", args: [aty], .. } => { let ty = self.parse_ty(sc.anon(), aty); - let Some(ty) = self.tys.base_of(ty).or(self.tys.inner_of(ty)) else { + let Some(ty) = + self.tys.base_of(ty).or(self.tys.inner_of(ty)).or(self.tys.elem_of(ty)) + else { return self.error_low( sc.file, aty.pos(), diff --git a/lang/src/ty.rs b/lang/src/ty.rs index 2d4a61e..91bfa35 100644 --- a/lang/src/ty.rs +++ b/lang/src/ty.rs @@ -616,12 +616,11 @@ impl core::fmt::Display for Display<'_> { K::Slice(idx) => { let array = self.tys.ins.slices[idx]; f.write_str("[")?; - self.rety(array.elem).fmt(f)?; - if array.len != ArrayLen::MAX { - f.write_str("; ")?; - array.len.fmt(f)?; + if let Some(len) = array.len() { + len.fmt(f)?; } - f.write_str("]") + f.write_str("]")?; + self.rety(array.elem).fmt(f) } K::Const(idx) => { let cnst = &self.tys.ins.consts[idx]; @@ -1260,6 +1259,7 @@ impl Types { pub fn len_of(&self, ty: Id) -> Option { Some(match ty.expand() { Kind::Struct(s) => self.struct_field_range(s).len() as _, + Kind::Tuple(s) => self.ins.tuples[s].fields.len() as _, Kind::Slice(s) => self.ins.slices[s].len()? as _, _ => return None, }) @@ -1274,6 +1274,13 @@ impl Types { pub fn tuple_fields(&self, tuple: Tuple) -> &[Id] { &self.ins.args[self.ins.tuples[tuple].fields.range()] } + + pub fn elem_of(&self, ty: Id) -> Option { + match ty.expand() { + Kind::Slice(s) => Some(self.ins.slices[s].elem), + _ => None, + } + } } pub struct OptLayout {