simple enums

This commit is contained in:
2026-06-08 19:46:29 +02:00
parent 2864548daf
commit 7259f13191
7 changed files with 51 additions and 9 deletions

View File

@@ -351,7 +351,8 @@ _builtin_environ:
if self.emit_debug || *exported || name == "main" {
emit!(
&mut self.output,
"global {name}:function (__end_{name} - {name})",
"global {0}:function ({0}.end - {0})",
name
);
}
emit!(&mut self.output, "section .text.{}", name);
@@ -405,9 +406,7 @@ _builtin_environ:
emit!(&mut self.output, " ret");
}
if self.emit_debug || *exported || name == "main" {
emit!(&mut self.output, "__end_{}:", name);
}
emit!(&mut self.output, ".end:");
// patch the stack size after we know how much we actually need
let patch = format!(" sub rsp, {:<10}", (env.next_offset + 15) & !15);
@@ -481,7 +480,10 @@ _builtin_environ:
Stmt::Extern(name) => {
emit!(&mut self.output, "extern {}", name.lexeme);
}
Stmt::Struct { name: _, fields: _ } => {
Stmt::Struct { .. } => {
// handled in SymbolTable
}
Stmt::Enum { .. } => {
// handled in SymbolTable
}
}

View File

@@ -77,6 +77,10 @@ pub enum Stmt {
name: Token,
fields: Vec<Param>,
},
Enum {
name: Token,
variants: Vec<Token>,
},
}
pub static NEXT_EXPR_ID: AtomicUsize = AtomicUsize::new(0);
@@ -191,6 +195,9 @@ impl Parser {
if self.match_token(&[TokenType::KeywordStruct]) {
return self.struct_declaration();
}
if self.match_token(&[TokenType::KeywordEnum]) {
return self.enum_declaration();
}
return error!(
self.peek().loc,
"statements not allowed outside function body"
@@ -269,11 +276,26 @@ impl Parser {
fields.push(Param { var_type, var_name });
}
self.consume(TokenType::Dedent, "expected dedent after the struct fields")?;
self.consume(TokenType::Dedent, "expected dedent after struct fields")?;
Ok(Stmt::Struct { name, fields })
}
fn enum_declaration(&mut self) -> Result<Stmt, ZernError> {
let name = self.consume(TokenType::Identifier, "expected enum name")?;
self.consume(TokenType::Indent, "expected indent after enum name")?;
let mut variants = vec![];
while !self.eof() && !self.check(&TokenType::Dedent) {
variants.push(self.consume(TokenType::Identifier, "expected variant name")?);
}
self.consume(TokenType::Dedent, "expected dedent after enum variants")?;
Ok(Stmt::Enum { name, variants })
}
fn const_declaration(&mut self) -> Result<Stmt, ZernError> {
let name = self.consume(TokenType::Identifier, "expected const name")?;
self.consume(TokenType::Equal, "expected '=' after const name")?;

View File

@@ -140,6 +140,16 @@ impl SymbolTable {
self.structs.insert(name.lexeme.clone(), fields_map);
}
Stmt::Enum { name, variants } => {
// TODO: distinct enum types
for (i, v) in variants.iter().enumerate() {
let variant = format!("{}.{}", name.lexeme, v.lexeme);
if self.is_name_defined(&variant) {
return error!(name.loc, format!("tried to redefine '{}'", variant));
}
self.constants.insert(variant, i as i64);
}
}
_ => {}
}
Ok(())

View File

@@ -57,6 +57,7 @@ pub enum TokenType {
KeywordStruct,
KeywordNew,
KeywordAs,
KeywordEnum,
Indent,
Dedent,
@@ -376,6 +377,7 @@ impl Tokenizer {
"struct" => TokenType::KeywordStruct,
"new" => TokenType::KeywordNew,
"as" => TokenType::KeywordAs,
"enum" => TokenType::KeywordEnum,
"true" => TokenType::True,
"false" => TokenType::False,
_ => TokenType::Identifier,

View File

@@ -355,6 +355,7 @@ impl<'a> TypeChecker<'a> {
}
}
}
Stmt::Enum { .. } => {}
}
Ok(())
}