From cf0c081da0e1327f2fc2d28c764672da5133c8cd Mon Sep 17 00:00:00 2001 From: Robert Konrad Date: Thu, 15 Aug 2024 20:31:09 +0200 Subject: [PATCH] Support limitless while loops --- Sources/backends/cstyle.c | 4 ++++ Sources/compiler.c | 17 +++++++++++++++++ Sources/compiler.h | 4 ++++ Sources/kong.c | 5 +++++ Sources/parser.c | 17 +++++++++++++++++ Sources/parser.h | 6 +++++- Sources/tokenizer.c | 9 +++++++++ Sources/tokenizer.h | 3 +++ 8 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Sources/backends/cstyle.c b/Sources/backends/cstyle.c index bb5df25..9d45cea 100644 --- a/Sources/backends/cstyle.c +++ b/Sources/backends/cstyle.c @@ -165,6 +165,10 @@ void cstyle_write_opcode(char *code, size_t *offset, opcode *o, type_string_func *offset += sprintf(&code[*offset], "\telse\n"); break; } + case OPCODE_WHILE: { + *offset += sprintf(&code[*offset], "\twhile (_%" PRIu64 ")\n", o->op_if.condition.index); + break; + } case OPCODE_BLOCK_START: { *offset += sprintf(&code[*offset], "\t{\n"); break; diff --git a/Sources/compiler.c b/Sources/compiler.c index 2e235bf..c2cbbd3 100644 --- a/Sources/compiler.c +++ b/Sources/compiler.c @@ -549,6 +549,23 @@ void emit_statement(opcodes *code, block *parent, statement *statement) { break; } + case STATEMENT_WHILE: { + { + opcode o; + o.type = OPCODE_WHILE; + o.size = OP_SIZE(o, op_while); + + variable v = emit_expression(code, parent, statement->willy.test); + + o.op_while.condition = v; + + emit_op(code, &o); + } + + emit_statement(code, parent, statement->willy.while_block); + + break; + } case STATEMENT_BLOCK: { { opcode o; diff --git a/Sources/compiler.h b/Sources/compiler.h index 6c41041..df82dc0 100644 --- a/Sources/compiler.h +++ b/Sources/compiler.h @@ -42,6 +42,7 @@ typedef struct opcode { OPCODE_OR, OPCODE_IF, OPCODE_ELSE, + OPCODE_WHILE, OPCODE_BLOCK_START, OPCODE_BLOCK_END } type; @@ -95,6 +96,9 @@ typedef struct opcode { struct { variable condition; } op_if; + struct { + variable condition; + } op_while; struct { uint8_t nothing; } op_nothing; diff --git a/Sources/kong.c b/Sources/kong.c index b67cec9..d8749e4 100644 --- a/Sources/kong.c +++ b/Sources/kong.c @@ -277,6 +277,11 @@ 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); + break; + } case STATEMENT_BLOCK: { resolve_types_in_block(block, s); break; diff --git a/Sources/parser.c b/Sources/parser.c index ff65b57..d2c7a8c 100644 --- a/Sources/parser.c +++ b/Sources/parser.c @@ -318,6 +318,23 @@ static statement *parse_statement(state_t *state, block *parent_block) { return s; } + case TOKEN_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); + + 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; + + return s; + } case TOKEN_LEFT_CURLY: { return parse_block(state, parent_block); } diff --git a/Sources/parser.h b/Sources/parser.h index bf18415..cc9719f 100644 --- a/Sources/parser.h +++ b/Sources/parser.h @@ -88,7 +88,7 @@ typedef struct block { } block; typedef struct statement { - enum { STATEMENT_EXPRESSION, STATEMENT_RETURN_EXPRESSION, STATEMENT_IF, STATEMENT_BLOCK, STATEMENT_LOCAL_VARIABLE } kind; + enum { STATEMENT_EXPRESSION, STATEMENT_RETURN_EXPRESSION, STATEMENT_IF, STATEMENT_WHILE, STATEMENT_BLOCK, STATEMENT_LOCAL_VARIABLE } kind; union { expression *expression; @@ -97,6 +97,10 @@ typedef struct statement { struct statement *if_block; struct statement *else_block; } iffy; + struct { + expression *test; + struct statement *while_block; + } willy; block block; struct { local_variable var; diff --git a/Sources/tokenizer.c b/Sources/tokenizer.c index 7148ea7..d76127a 100644 --- a/Sources/tokenizer.c +++ b/Sources/tokenizer.c @@ -164,6 +164,15 @@ static void tokens_add_identifier(tokenizer_state *state, tokens *tokens, tokeni else if (tokenizer_buffer_equals(buffer, "else")) { token = token_create(TOKEN_ELSE, state); } + else if (tokenizer_buffer_equals(buffer, "while")) { + token = token_create(TOKEN_WHILE, state); + } + else if (tokenizer_buffer_equals(buffer, "do")) { + token = token_create(TOKEN_DO, state); + } + else if (tokenizer_buffer_equals(buffer, "for")) { + token = token_create(TOKEN_FOR, state); + } else if (tokenizer_buffer_equals(buffer, "in")) { token = token_create(TOKEN_IN, state); } diff --git a/Sources/tokenizer.h b/Sources/tokenizer.h index 429da93..22f6715 100644 --- a/Sources/tokenizer.h +++ b/Sources/tokenizer.h @@ -45,6 +45,9 @@ typedef struct token { TOKEN_RIGHT_SQUARE, TOKEN_IF, TOKEN_ELSE, + TOKEN_WHILE, + TOKEN_DO, + TOKEN_FOR, TOKEN_SEMICOLON, TOKEN_COLON, TOKEN_DOT,