From 9429d1ea0d14effbf50b6ecf292ef4d6a5a98abc Mon Sep 17 00:00:00 2001 From: Robert Konrad Date: Fri, 16 Aug 2024 17:46:22 +0200 Subject: [PATCH] Support do while loops --- Sources/compiler.c | 35 +++++++++++++++++++++++++++++++++-- Sources/kong.c | 7 ++++--- Sources/parser.c | 28 ++++++++++++++++++++++++++-- Sources/parser.h | 12 ++++++++++-- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/Sources/compiler.c b/Sources/compiler.c index bdf4c1b..b394001 100644 --- a/Sources/compiler.c +++ b/Sources/compiler.c @@ -562,14 +562,45 @@ void emit_statement(opcodes *code, block *parent, statement *statement) { o.type = OPCODE_WHILE_CONDITION; o.size = OP_SIZE(o, op_while); - variable v = emit_expression(code, parent, statement->willy.test); + variable v = emit_expression(code, parent, statement->whiley.test); o.op_while.condition = v; emit_op(code, &o); } - emit_statement(code, parent, statement->willy.while_block); + emit_statement(code, parent, statement->whiley.while_block); + + { + opcode o; + o.type = OPCODE_WHILE_END; + o.size = OP_SIZE(o, op_nothing); + emit_op(code, &o); + } + + break; + } + case STATEMENT_DO_WHILE: { + { + opcode o; + o.type = OPCODE_WHILE_START; + o.size = OP_SIZE(o, op_nothing); + emit_op(code, &o); + } + + emit_statement(code, parent, statement->whiley.while_block); + + { + opcode o; + o.type = OPCODE_WHILE_CONDITION; + o.size = OP_SIZE(o, op_while); + + variable v = emit_expression(code, parent, statement->whiley.test); + + o.op_while.condition = v; + + emit_op(code, &o); + } { opcode o; diff --git a/Sources/kong.c b/Sources/kong.c index d8749e4..ebbc76e 100644 --- a/Sources/kong.c +++ b/Sources/kong.c @@ -277,9 +277,10 @@ void resolve_types_in_block(statement *parent, statement *block) { } break; } - case STATEMENT_WHILE: { - resolve_types_in_expression(block, s->willy.test); - resolve_types_in_block(block, s->willy.while_block); + case STATEMENT_WHILE: + case STATEMENT_DO_WHILE: { + resolve_types_in_expression(block, s->whiley.test); + resolve_types_in_block(block, s->whiley.while_block); break; } case STATEMENT_BLOCK: { diff --git a/Sources/parser.c b/Sources/parser.c index d2c7a8c..2a2f91e 100644 --- a/Sources/parser.c +++ b/Sources/parser.c @@ -330,8 +330,32 @@ static statement *parse_statement(state_t *state, block *parent_block) { statement *while_block = parse_statement(state, parent_block); statement *s = statement_allocate(); s->kind = STATEMENT_WHILE; - s->willy.test = test; - s->willy.while_block = while_block; + s->whiley.test = test; + s->whiley.while_block = while_block; + + return s; + } + case TOKEN_DO: { + advance_state(state); + + statement *do_block = parse_statement(state, parent_block); + statement *s = statement_allocate(); + s->kind = STATEMENT_DO_WHILE; + s->whiley.while_block = do_block; + + match_token(state, TOKEN_WHILE, "Expected \"while\""); + advance_state(state); + match_token(state, TOKEN_LEFT_PAREN, "Expected an opening bracket"); + advance_state(state); + + expression *test = parse_expression(state); + match_token(state, TOKEN_RIGHT_PAREN, "Expected a closing bracket"); + advance_state(state); + + s->whiley.test = test; + + match_token(state, TOKEN_SEMICOLON, "Expected a semicolon"); + advance_state(state); return s; } diff --git a/Sources/parser.h b/Sources/parser.h index cc9719f..6e1fc2e 100644 --- a/Sources/parser.h +++ b/Sources/parser.h @@ -88,7 +88,15 @@ typedef struct block { } block; typedef struct statement { - enum { STATEMENT_EXPRESSION, STATEMENT_RETURN_EXPRESSION, STATEMENT_IF, STATEMENT_WHILE, STATEMENT_BLOCK, STATEMENT_LOCAL_VARIABLE } kind; + enum { + STATEMENT_EXPRESSION, + STATEMENT_RETURN_EXPRESSION, + STATEMENT_IF, + STATEMENT_WHILE, + STATEMENT_DO_WHILE, + STATEMENT_BLOCK, + STATEMENT_LOCAL_VARIABLE + } kind; union { expression *expression; @@ -100,7 +108,7 @@ typedef struct statement { struct { expression *test; struct statement *while_block; - } willy; + } whiley; block block; struct { local_variable var;