This commit is contained in:
me 2025-12-16 17:42:48 +02:00
parent 8b544edba5
commit ff3b45352d
4 changed files with 67 additions and 14 deletions

View file

@ -17,19 +17,19 @@ let init = fn() {
return { return {
player: { position: { x: 10, y: 20 }, }, player: { position: { x: 10, y: 20 }, },
} }
} };
let update = fn(state, events) { let update = fn(state, events) {
return state'; return state';
} };
let draw = fn(frame, state) { let draw = fn(frame, state) {
frame.clear(0,0,0); frame.clear(0,0,0);
} };
let migrate = fn(state) { let migrate = fn(state) {
return { player: { pos: state.player.position } }, return { player: { pos: state.player.position } },
} };
``` ```
- dynamic software updating could occur every frame - dynamic software updating could occur every frame

View file

@ -101,8 +101,13 @@ fn parse_simple_expr(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
fn parse_fn(tokens: &mut Tokens) -> ParseResult<ast::Expr> { fn parse_fn(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
if let Some(_) = tokens.next_if(&Token::Fn) { if let Some(_) = tokens.next_if(&Token::Fn) {
if let Some(args) = parse_args(tokens)? { if let Some(args) = parse_args(tokens)? {
if let Some(body) = tokens.between(&Token::OpenCurly, &Token::CloseCurly, parse_expr)? { if let Some(body) =
Ok(Some(ast::Expr::Func(Box::new(ast::Fn { args, body })))) tokens.between(&Token::OpenCurly, &Token::CloseCurly, parse_block)?
{
Ok(Some(ast::Expr::Func(Box::new(ast::Fn {
args,
body: ast::Expr::Block(body),
}))))
} else { } else {
Err(Error::UnexpectedTokenForParser( Err(Error::UnexpectedTokenForParser(
"fn_body".into(), "fn_body".into(),
@ -120,6 +125,17 @@ fn parse_fn(tokens: &mut Tokens) -> ParseResult<ast::Expr> {
} }
} }
fn parse_block(tokens: &mut Tokens) -> ParseResult<Vec<ast::Statement>> {
tokens.many(parse_statement)
}
fn parse_statement(tokens: &mut Tokens) -> ParseResult<ast::Statement> {
tokens.one_of(vec![
|tokens| Ok(parse_expr(tokens)?.map(ast::Statement::Expr)),
|tokens| Ok(parse_definition(tokens)?.map(ast::Statement::Let)),
])
}
fn parse_args(tokens: &mut Tokens) -> ParseResult<Vec<ast::Arg>> { fn parse_args(tokens: &mut Tokens) -> ParseResult<Vec<ast::Arg>> {
tokens.between(&Token::OpenParen, &Token::CloseParen, |ts| { tokens.between(&Token::OpenParen, &Token::CloseParen, |ts| {
ts.many_sep_by(&Token::Comma, parse_identifier_arg) ts.many_sep_by(&Token::Comma, parse_identifier_arg)
@ -312,4 +328,29 @@ mod tests {
let result = parse(&mut scan(program), parse_definition); let result = parse(&mut scan(program), parse_definition);
insta::assert_debug_snapshot!(result); insta::assert_debug_snapshot!(result);
} }
#[test]
fn full_program() {
let program = "
let init = fn() {
return {
player: { position: { x: 10, y: 20 }, },
}
};
let update = fn(state, events) {
return state';
};
let draw = fn(frame, state) {
frame.clear(0,0,0);
};
let migrate = fn(state) {
return { player: { pos: state.player.position } },
};
"
.to_string();
let result = parse(&mut scan(program), parse_definitions);
insta::assert_debug_snapshot!(result);
}
} }

View file

@ -22,11 +22,17 @@ Ok(
), ),
}, },
], ],
body: Value( body: Block(
[
Expr(
Value(
Int( Int(
108, 108,
), ),
), ),
),
],
),
}, },
), ),
) )

View file

@ -23,11 +23,17 @@ Ok(
), ),
}, },
], ],
body: Value( body: Block(
[
Expr(
Value(
Int( Int(
108, 108,
), ),
), ),
),
],
),
}, },
), ),
args: [], args: [],