Introduce Value::Cell for mutable upvalues, allowing closures to

modify captured variables.
Implement `capture_upvalue` and `get_value`/`set_value` methods in the
`VM` to handle these mutable upvalues.

Refactor number parsing to support integers and floats

Separate the `TokenKind::Number` into `TokenKind::Integer` and
`TokenKind::Float`.
Update the lexer to distinguish between integer and float literals.
Update the parser to correctly map these new token kinds to their
respective `Value` types.

Add integration tests for parsing integers and floats, and for closure
modification of captured variables.
This commit is contained in:
Michael Schimmel
2026-02-17 12:35:39 +01:00
parent 12791a7f8f
commit ce166f39e3
6 changed files with 289 additions and 16 deletions
+16 -3
View File
@@ -11,7 +11,8 @@ pub enum TokenKind {
Quote, Backtick, Tilde, At,
Identifier(Arc<str>),
Keyword(Arc<str>),
Number(f64),
Integer(i64),
Float(f64),
String(Arc<str>),
EOF,
}
@@ -69,8 +70,20 @@ impl<'a> Lexer<'a> {
'"' => TokenKind::String(Arc::from(self.read_string()?)),
c if c.is_ascii_digit() || (c == '-' && self.input.peek().is_some_and(|p| p.is_ascii_digit())) => {
let mut num_str = String::from(c);
num_str.push_str(&self.read_while(|c| c.is_ascii_digit() || c == '.'));
TokenKind::Number(num_str.parse().map_err(|_| "Invalid number format")?)
while let Some(&next) = self.peek() {
if next.is_ascii_digit() || next == '.' {
num_str.push(self.input.next().unwrap());
self.col += 1;
} else {
break;
}
}
if num_str.contains('.') {
TokenKind::Float(num_str.parse().map_err(|_| "Invalid float format")?)
} else {
TokenKind::Integer(num_str.parse().map_err(|_| "Invalid integer format")?)
}
}
c if is_ident_start(c) => {
let mut id = String::from(c);