* [PATCH olang v1] parser: add support for parsing while-statements
@ 2024-10-08 21:33 Johnny Richard
2024-10-08 19:34 ` [olang/patches/.build.yml] build success builds.sr.ht
2024-10-08 22:49 ` [PATCH olang v1] parser: add support for parsing while-statements Carlos Maniero
0 siblings, 2 replies; 4+ messages in thread
From: Johnny Richard @ 2024-10-08 21:33 UTC (permalink / raw)
To: ~johnnyrichard/olang-devel; +Cc: Johnny Richard
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
---
src/ast.c | 14 +++++++++++
src/ast.h | 12 ++++++++++
src/checker.c | 7 ++++++
src/codegen_linux_x86_64.c | 25 ++++++++++++++++++++
src/parser.c | 39 +++++++++++++++++++++++++++++++
src/pretty_print_ast.c | 14 +++++++++++
tests/olc/0030_while_statement.ol | 20 ++++++++++++----
7 files changed, 127 insertions(+), 4 deletions(-)
diff --git a/src/ast.c b/src/ast.c
index 531415c..d6ec70c 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -186,6 +186,20 @@ ast_new_node_if_stmt(arena_t *arena, token_loc_t loc, ast_node_t *cond, ast_node
return node_if_stmt;
}
+ast_node_t *
+ast_new_node_while_stmt(arena_t *arena, token_loc_t loc, ast_node_t *cond, ast_node_t *then)
+{
+ ast_node_t *node_while_stmt = arena_alloc(arena, sizeof(ast_node_t));
+ assert(node_while_stmt);
+
+ node_while_stmt->kind = AST_NODE_WHILE_STMT;
+ node_while_stmt->loc = loc;
+ node_while_stmt->as_while_stmt.cond = cond;
+ node_while_stmt->as_while_stmt.then = then;
+
+ return node_while_stmt;
+}
+
ast_node_t *
ast_new_node_block(arena_t *arena)
{
diff --git a/src/ast.h b/src/ast.h
index dce7cd8..238435e 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -39,6 +39,7 @@ typedef enum
AST_NODE_VAR_ASSIGN_STMT,
AST_NODE_RETURN_STMT,
AST_NODE_IF_STMT,
+ AST_NODE_WHILE_STMT,
AST_NODE_LITERAL,
AST_NODE_REF,
AST_NODE_UNKNOWN
@@ -168,6 +169,13 @@ typedef struct ast_if_stmt
ast_node_t *_else;
} ast_if_stmt_t;
+typedef struct ast_while_stmt
+{
+ ast_node_meta_t meta;
+ ast_node_t *cond;
+ ast_node_t *then;
+} ast_while_stmt_t;
+
typedef union ast_node
{
// inlined ast_node_meta_t struct.
@@ -187,6 +195,7 @@ typedef union ast_node
ast_var_assign_stmt_t as_var_assign_stmt;
ast_return_stmt_t as_return_stmt;
ast_if_stmt_t as_if_stmt;
+ ast_while_stmt_t as_while_stmt;
} ast_node_t;
ast_node_t *
@@ -224,6 +233,9 @@ ast_new_node_return_stmt(arena_t *arena, token_loc_t loc, ast_node_t *expr);
ast_node_t *
ast_new_node_if_stmt(arena_t *arena, token_loc_t loc, ast_node_t *cond, ast_node_t *then, ast_node_t *_else);
+ast_node_t *
+ast_new_node_while_stmt(arena_t *arena, token_loc_t loc, ast_node_t *cond, ast_node_t *then);
+
ast_node_t *
ast_new_node_block(arena_t *arena);
diff --git a/src/checker.c b/src/checker.c
index 4523b79..36202bd 100644
--- a/src/checker.c
+++ b/src/checker.c
@@ -109,6 +109,13 @@ populate_scope(checker_t *checker, scope_t *scope, ast_node_t *ast)
return;
}
+ case AST_NODE_WHILE_STMT: {
+ populate_scope(checker, scope, ast->as_while_stmt.cond);
+ populate_scope(checker, scope, ast->as_while_stmt.then);
+
+ return;
+ }
+
case AST_NODE_BINARY_OP: {
ast_binary_op_t bin_op = ast->as_bin_op;
diff --git a/src/codegen_linux_x86_64.c b/src/codegen_linux_x86_64.c
index ebda8eb..5749e65 100644
--- a/src/codegen_linux_x86_64.c
+++ b/src/codegen_linux_x86_64.c
@@ -627,6 +627,31 @@ codegen_linux_x86_64_emit_block(codegen_x86_64_t *codegen, ast_block_t *block)
break;
}
+
+ case AST_NODE_WHILE_STMT: {
+ ast_while_stmt_t while_stmt = node->as_while_stmt;
+
+ ast_node_t *cond = while_stmt.cond;
+ ast_node_t *then = while_stmt.then;
+
+ size_t begin_label = codegen_linux_x86_64_get_next_label(codegen);
+ size_t end_label = codegen_linux_x86_64_get_next_label(codegen);
+
+ fprintf(codegen->out, ".L%ld:\n", begin_label);
+ codegen_linux_x86_64_emit_expression(codegen, cond);
+ fprintf(codegen->out, " cmp $1, %%rax\n");
+ fprintf(codegen->out, " jnz .L%ld\n", end_label);
+
+ assert(then->kind == AST_NODE_BLOCK && "invalid while-then block");
+ ast_block_t then_block = then->as_block;
+
+ codegen_linux_x86_64_emit_block(codegen, &then_block);
+
+ fprintf(codegen->out, " jmp .L%ld\n", begin_label);
+ fprintf(codegen->out, ".L%ld:\n", end_label);
+
+ break;
+ }
default: {
// FIXME: improve error: replace the node->kind to a string representation
fprintf(stderr, "node kind %d not supported\n", node->kind);
diff --git a/src/parser.c b/src/parser.c
index 94e8a1e..d498ea5 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -46,6 +46,9 @@ parser_parse_return_stmt(parser_t *parser);
static ast_node_t *
parser_parse_if_stmt(parser_t *parser);
+static ast_node_t *
+parser_parse_while_stmt(parser_t *parser);
+
static ast_node_t *
parser_parse_var_def(parser_t *parser);
@@ -471,6 +474,10 @@ StartLoop:
node = parser_parse_if_stmt(parser);
break;
}
+ case TOKEN_WHILE: {
+ node = parser_parse_while_stmt(parser);
+ break;
+ }
case TOKEN_VAR: {
node = parser_parse_var_def(parser);
break;
@@ -580,6 +587,38 @@ parser_parse_if_stmt(parser_t *parser)
return node_if_stmt;
}
+static ast_node_t *
+parser_parse_while_stmt(parser_t *parser)
+{
+ token_t token_while;
+ if (!expected_next_token(parser, &token_while, TOKEN_WHILE)) {
+ return NULL;
+ }
+
+ ast_node_t *cond = parser_parse_expr(parser);
+
+ if (cond == NULL) {
+ return NULL;
+ }
+
+ skip_line_feeds(parser->lexer);
+
+ ast_node_t *then = parser_parse_block(parser);
+
+ if (then == NULL) {
+ return NULL;
+ }
+
+ token_t next_token;
+ peek_next_non_lf_token(parser->lexer, &next_token);
+
+ ast_node_t *node_while_stmt = ast_new_node_while_stmt(parser->arena, token_while.loc, cond, then);
+
+ assert(node_while_stmt);
+
+ return node_while_stmt;
+}
+
static ast_node_t *
parser_parse_var_def(parser_t *parser)
{
diff --git a/src/pretty_print_ast.c b/src/pretty_print_ast.c
index 3282166..0c5d2d5 100644
--- a/src/pretty_print_ast.c
+++ b/src/pretty_print_ast.c
@@ -237,6 +237,20 @@ ast_node_to_pretty_print_node(ast_node_t *ast, arena_t *arena)
return node;
}
+ case AST_NODE_WHILE_STMT: {
+ pretty_print_node_t *node = pretty_print_node_new(arena);
+ ast_while_stmt_t while_stmt = ast->as_while_stmt;
+
+ node->name = "While_Statement";
+
+ pretty_print_node_t *child = ast_node_to_pretty_print_node(while_stmt.cond, arena);
+ list_append(node->children, child);
+
+ child = ast_node_to_pretty_print_node(while_stmt.then, arena);
+ list_append(node->children, child);
+
+ return node;
+ }
case AST_NODE_LITERAL: {
pretty_print_node_t *node = pretty_print_node_new(arena);
ast_literal_t literal = ast->as_literal;
diff --git a/tests/olc/0030_while_statement.ol b/tests/olc/0030_while_statement.ol
index 1ebdc5a..0eca528 100644
--- a/tests/olc/0030_while_statement.ol
+++ b/tests/olc/0030_while_statement.ol
@@ -23,16 +23,28 @@ fn main(): u32 {
return i
}
-# XTEST test_compile(exit_code=0)
+# TEST test_compile(exit_code=0)
#
-# XTEST test_run_binary(exit_code=9)
+# TEST test_run_binary(exit_code=10)
#
-# XTEST test_ast WITH
+# TEST test_ast WITH
# Translation_Unit
# `-Function_Definition <name:main> <return:u32>
# `-Block
+# |-Var_Definition <name:i> <kind:u32>
+# | `-Literal <kind:u32> <value:0>
+# |-While_Statement
+# | |-Binary_Operation (<)
+# | | |-Reference <name:i>
+# | | `-Literal <kind:u32> <value:10>
+# | `-Block
+# | `-Var_Assigment
+# | |-Reference <name:i>
+# | `-Binary_Operation (+)
+# | |-Reference <name:i>
+# | `-Literal <kind:u32> <value:1>
# `-Return_Statement
-# `-Literal <kind:u32> <value:0>
+# `-Reference <name:i>
# END
#
# TEST test_contains_tokens WITH
base-commit: f0a565d7d551df220c7b8ae0b924245dd70c9468
--
2.46.0
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-10-09 12:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-08 21:33 [PATCH olang v1] parser: add support for parsing while-statements Johnny Richard
2024-10-08 19:34 ` [olang/patches/.build.yml] build success builds.sr.ht
2024-10-08 22:49 ` [PATCH olang v1] parser: add support for parsing while-statements Carlos Maniero
2024-10-09 14:55 ` Johnny Richard
Code repositories for project(s) associated with this public inbox
https://git.johnnyrichard.com/olang.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox