refactor: interpreter and type system improvements
- Parser and typechecker updates for new features - Schema evolution refinements - Type system enhancements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
100
src/parser.rs
100
src/parser.rs
@@ -479,8 +479,11 @@ impl Parser {
|
||||
self.skip_newlines();
|
||||
|
||||
if self.check(TokenKind::Pipe) {
|
||||
// Enum type - requires leading | for variants
|
||||
// Enum type - with leading | for variants
|
||||
(TypeDef::Enum(self.parse_variants()?), Vec::new())
|
||||
} else if self.is_single_line_enum() {
|
||||
// Single-line enum without leading pipe: type Status = Ok | Error
|
||||
(TypeDef::Enum(self.parse_single_line_variants()?), Vec::new())
|
||||
} else {
|
||||
// Type alias - any type expression
|
||||
(TypeDef::Alias(self.parse_type()?), Vec::new())
|
||||
@@ -1253,6 +1256,85 @@ impl Parser {
|
||||
Ok(migrations)
|
||||
}
|
||||
|
||||
/// Check if we're looking at a single-line enum (no leading pipe)
|
||||
/// e.g., type Status = Ok | Error
|
||||
fn is_single_line_enum(&self) -> bool {
|
||||
// Look for pattern: Ident (LParen|LBrace)? Pipe
|
||||
// We need to peek ahead without consuming tokens
|
||||
if !matches!(&self.peek().kind, TokenKind::Ident(_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there's a | somewhere on this logical line
|
||||
// This is a simple heuristic - look at the next few tokens
|
||||
let mut pos = self.pos;
|
||||
let mut found_ident = false;
|
||||
let mut depth = 0;
|
||||
|
||||
while pos < self.tokens.len() {
|
||||
match &self.tokens[pos].kind {
|
||||
TokenKind::Ident(_) if !found_ident => found_ident = true,
|
||||
TokenKind::LParen | TokenKind::LBrace => depth += 1,
|
||||
TokenKind::RParen | TokenKind::RBrace => {
|
||||
if depth > 0 {
|
||||
depth -= 1;
|
||||
}
|
||||
}
|
||||
TokenKind::Pipe if depth == 0 => return true,
|
||||
TokenKind::Newline | TokenKind::Eof => return false,
|
||||
_ => {}
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Parse single-line variants without leading pipe
|
||||
fn parse_single_line_variants(&mut self) -> Result<Vec<Variant>, ParseError> {
|
||||
let mut variants = Vec::new();
|
||||
|
||||
loop {
|
||||
let start = self.current_span();
|
||||
let name = self.parse_ident()?;
|
||||
|
||||
let fields = if self.check(TokenKind::LParen) {
|
||||
// Tuple variant
|
||||
self.advance();
|
||||
let mut types = Vec::new();
|
||||
while !self.check(TokenKind::RParen) {
|
||||
types.push(self.parse_type()?);
|
||||
if !self.check(TokenKind::RParen) {
|
||||
self.expect(TokenKind::Comma)?;
|
||||
}
|
||||
}
|
||||
self.expect(TokenKind::RParen)?;
|
||||
VariantFields::Tuple(types)
|
||||
} else if self.check(TokenKind::LBrace) {
|
||||
// Record variant
|
||||
self.advance();
|
||||
self.skip_newlines();
|
||||
let fields = self.parse_record_fields()?;
|
||||
self.expect(TokenKind::RBrace)?;
|
||||
VariantFields::Record(fields)
|
||||
} else {
|
||||
VariantFields::Unit
|
||||
};
|
||||
|
||||
let span = start.merge(self.previous_span());
|
||||
variants.push(Variant { name, fields, span });
|
||||
|
||||
// Check for more variants
|
||||
if self.check(TokenKind::Pipe) {
|
||||
self.advance();
|
||||
self.skip_newlines();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(variants)
|
||||
}
|
||||
|
||||
fn parse_variants(&mut self) -> Result<Vec<Variant>, ParseError> {
|
||||
let mut variants = Vec::new();
|
||||
|
||||
@@ -1660,9 +1742,19 @@ impl Parser {
|
||||
let then_branch = Box::new(self.parse_expr()?);
|
||||
|
||||
self.skip_newlines();
|
||||
self.expect(TokenKind::Else)?;
|
||||
self.skip_newlines();
|
||||
let else_branch = Box::new(self.parse_expr()?);
|
||||
|
||||
// Else is optional - if missing, synthesize a Unit value
|
||||
let else_branch = if self.check(TokenKind::Else) {
|
||||
self.expect(TokenKind::Else)?;
|
||||
self.skip_newlines();
|
||||
Box::new(self.parse_expr()?)
|
||||
} else {
|
||||
// No else clause - use Unit as the else branch
|
||||
Box::new(Expr::Literal(Literal {
|
||||
kind: LiteralKind::Unit,
|
||||
span: then_branch.span(),
|
||||
}))
|
||||
};
|
||||
|
||||
let span = start.merge(else_branch.span());
|
||||
Ok(Expr::If {
|
||||
|
||||
Reference in New Issue
Block a user