1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00

Language: enum declarations

Adds \`enum Name { V1, V2, ... }\` as a top-level declaration. Each
variant is registered as a \`u8\` constant equal to its index in the
declaration. Variant names are global and must be unique across all
enums and other symbols (E0501 on collision).

- Lexer: \`enum\` keyword
- AST: \`EnumDecl { name, variants, span }\` field on \`Program\`
- Parser: top-level \`enum\` syntax with optional trailing commas
- Analyzer: \`register_enum\` flattens variants into the symbol table
- IR lowering and AST codegen: variants resolve through the existing
  \`const_values\` path
- Tests cover parsing, duplicate detection, and usage

https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
Claude 2026-04-12 11:36:44 +00:00
parent ae051f5909
commit dbfcb313bc
No known key found for this signature in database
12 changed files with 181 additions and 0 deletions

View file

@ -116,6 +116,7 @@ impl Parser {
let mut game = None;
let mut globals = Vec::new();
let mut constants = Vec::new();
let mut enums: Vec<EnumDecl> = Vec::new();
let mut functions = Vec::new();
let mut states = Vec::new();
let mut sprites = Vec::new();
@ -143,6 +144,9 @@ impl Parser {
TokenKind::KwConst => {
constants.push(self.parse_const_decl()?);
}
TokenKind::KwEnum => {
enums.push(self.parse_enum_decl()?);
}
TokenKind::KwState => {
states.push(self.parse_state_decl()?);
}
@ -216,6 +220,7 @@ impl Parser {
game,
globals,
constants,
enums,
functions,
states,
sprites,
@ -227,6 +232,41 @@ impl Parser {
})
}
fn parse_enum_decl(&mut self) -> Result<EnumDecl, Diagnostic> {
let start = self.current_span();
self.expect(&TokenKind::KwEnum)?;
let (name, _) = self.expect_ident()?;
self.expect(&TokenKind::LBrace)?;
let mut variants = Vec::new();
while *self.peek() != TokenKind::RBrace && *self.peek() != TokenKind::Eof {
let span = self.current_span();
let (vname, _) = self.expect_ident()?;
variants.push((vname, span));
if *self.peek() == TokenKind::Comma {
self.advance();
} else if *self.peek() != TokenKind::RBrace {
return Err(Diagnostic::error(
ErrorCode::E0201,
"expected ',' or '}' in enum body",
self.current_span(),
));
}
}
self.expect(&TokenKind::RBrace)?;
if variants.len() > 256 {
return Err(Diagnostic::error(
ErrorCode::E0201,
"enum has more than 256 variants (u8 overflow)",
start,
));
}
Ok(EnumDecl {
name,
variants,
span: Span::new(start.file_id, start.start, self.current_span().end),
})
}
// ── Game declaration ──
fn parse_game_decl(&mut self) -> Result<GameDecl, Diagnostic> {