adding struct syntax

This commit is contained in:
mlokr 2024-05-12 12:16:40 +02:00
parent 2aa315a863
commit 4bb5ec1953
5 changed files with 111 additions and 31 deletions

View file

@ -0,0 +1,9 @@
Ty := struct {
a: int
b: int
}
main := fn(): int {
inst := Ty.{ a: 1, b: 2 };
return inst.a + inst.b;
}

View file

@ -915,5 +915,6 @@ mod tests {
loops => include_str!("../examples/loops.hb"); loops => include_str!("../examples/loops.hb");
fb_driver => include_str!("../examples/fb_driver.hb"); fb_driver => include_str!("../examples/fb_driver.hb");
pointers => include_str!("../examples/pointers.hb"); pointers => include_str!("../examples/pointers.hb");
structs => include_str!("../examples/structs.hb");
} }
} }

View file

@ -91,14 +91,17 @@ gen_token_kind! {
Break = b"break", Break = b"break",
Continue = b"continue", Continue = b"continue",
Fn = b"fn", Fn = b"fn",
Struct = b"struct",
#[punkt] #[punkt]
LParen = b'(', LParen = "(",
RParen = b')', RParen = ")",
LBrace = b'{', LBrace = "{",
RBrace = b'}', RBrace = "}",
Semi = b';', Semi = ";",
Colon = b':', Colon = ":",
Comma = b',', Comma = ",",
Dot = ".",
Ctor = ".{",
#[ops] #[ops]
#[prec = 1] #[prec = 1]
Decl = ":=", Decl = ":=",
@ -202,6 +205,8 @@ impl<'a> Iterator for Lexer<'a> {
b':' if self.advance_if(b'=') => T::Decl, b':' if self.advance_if(b'=') => T::Decl,
b':' => T::Colon, b':' => T::Colon,
b',' => T::Comma, b',' => T::Comma,
b'.' if self.advance_if(b'{') => T::Ctor,
b'.' => T::Dot,
b';' => T::Semi, b';' => T::Semi,
b'=' if self.advance_if(b'=') => T::Eq, b'=' if self.advance_if(b'=') => T::Eq,
b'=' => T::Assign, b'=' => T::Assign,

View file

@ -139,6 +139,18 @@ impl<'a, 'b> Parser<'a, 'b> {
let frame = self.idents.len(); let frame = self.idents.len();
let token = self.next(); let token = self.next();
let mut expr = match token.kind { let mut expr = match token.kind {
T::Struct => E::Struct {
pos: token.start,
fields: {
self.expect_advance(T::LBrace);
self.collect_list(T::Comma, T::RBrace, |s| {
let name = s.expect_advance(T::Ident);
s.expect_advance(T::Colon);
let ty = s.expr();
(s.lexer.slice(name.range()), ty)
})
},
},
T::Ident => { T::Ident => {
let (id, last) = self.resolve_ident(token, self.token.kind == T::Decl); let (id, last) = self.resolve_ident(token, self.token.kind == T::Decl);
let name = self.lexer.slice(token.range()); let name = self.lexer.slice(token.range());
@ -207,14 +219,32 @@ impl<'a, 'b> Parser<'a, 'b> {
}; };
loop { loop {
expr = match self.token.kind { let token = self.token.kind;
T::LParen => { if matches!(token, T::LParen | T::Ctor | T::Dot) {
self.next(); self.next();
Expr::Call { }
expr = match token {
T::LParen => Expr::Call {
func: self.arena.alloc(expr), func: self.arena.alloc(expr),
args: self.collect_list(T::Comma, T::RParen, Self::expr), args: self.collect_list(T::Comma, T::RParen, Self::expr),
} },
} T::Ctor => E::Ctor {
ty: 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();
(s.lexer.slice(name.range()), val)
}),
},
T::Dot => E::Field {
ty: self.arena.alloc(expr),
field: {
let token = self.expect_advance(T::Ident);
self.lexer.slice(token.range())
},
},
_ => break, _ => break,
} }
} }
@ -313,16 +343,16 @@ pub enum Expr<'a> {
Closure { Closure {
pos: u32, pos: u32,
args: &'a [Arg<'a>], args: &'a [Arg<'a>],
ret: &'a Expr<'a>, ret: &'a Self,
body: &'a Expr<'a>, body: &'a Self,
}, },
Call { Call {
func: &'a Expr<'a>, func: &'a Self,
args: &'a [Expr<'a>], args: &'a [Self],
}, },
Return { Return {
pos: u32, pos: u32,
val: Option<&'a Expr<'a>>, val: Option<&'a Self>,
}, },
Ident { Ident {
name: &'a str, name: &'a str,
@ -331,31 +361,43 @@ pub enum Expr<'a> {
}, },
Block { Block {
pos: u32, pos: u32,
stmts: &'a [Expr<'a>], stmts: &'a [Self],
}, },
Number { Number {
pos: u32, pos: u32,
value: u64, value: u64,
}, },
BinOp { BinOp {
left: &'a Expr<'a>, left: &'a Self,
op: TokenKind, op: TokenKind,
right: &'a Expr<'a>, right: &'a Self,
}, },
If { If {
pos: u32, pos: u32,
cond: &'a Expr<'a>, cond: &'a Self,
then: &'a Expr<'a>, then: &'a Self,
else_: Option<&'a Expr<'a>>, else_: Option<&'a Self>,
}, },
Loop { Loop {
pos: u32, pos: u32,
body: &'a Expr<'a>, body: &'a Self,
}, },
UnOp { UnOp {
pos: u32, pos: u32,
op: TokenKind, op: TokenKind,
val: &'a Expr<'a>, val: &'a Self,
},
Struct {
pos: u32,
fields: &'a [(&'a str, Self)],
},
Ctor {
ty: &'a Self,
fields: &'a [(&'a str, Self)],
},
Field {
ty: &'a Self,
field: &'a str,
}, },
} }
@ -366,6 +408,29 @@ impl<'a> std::fmt::Display for Expr<'a> {
} }
match *self { match *self {
Self::Field { ty, field } => write!(f, "{}.{}", ty, field),
Self::Struct { fields, .. } => {
write!(f, "struct {{")?;
let first = &mut true;
for (name, ty) in fields {
if !std::mem::take(first) {
write!(f, ", ")?;
}
write!(f, "{}: {}", name, ty)?;
}
write!(f, "}}")
}
Self::Ctor { ty, fields } => {
write!(f, "{} {{", ty)?;
let first = &mut true;
for (name, val) in fields {
if !std::mem::take(first) {
write!(f, ", ")?;
}
write!(f, "{}: {}", name, val)?;
}
write!(f, "}}")
}
Self::UnOp { op, val, .. } => write!(f, "{}{}", op, val), Self::UnOp { op, val, .. } => write!(f, "{}{}", op, val),
Self::Break { .. } => write!(f, "break;"), Self::Break { .. } => write!(f, "break;"),
Self::Continue { .. } => write!(f, "continue;"), Self::Continue { .. } => write!(f, "continue;"),

Binary file not shown.