From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id 8HRPLR2JBWc9awEA62LTzQ:P1 (envelope-from ) for ; Tue, 08 Oct 2024 21:33:49 +0200 Received: from aspmx1.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1.migadu.com with LMTPS id 8HRPLR2JBWc9awEA62LTzQ (envelope-from ) for ; Tue, 08 Oct 2024 21:33:49 +0200 X-Envelope-To: patches@johnnyrichard.com Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=lists.sr.ht header.s=20240113 header.b=UKLA4ITv; dkim=pass header.d=johnnyrichard.com header.s=key1 header.b=h6MR6Qqm; dmarc=pass (policy=quarantine) header.from=johnnyrichard.com; spf=pass (aspmx1.migadu.com: domain of lists@sr.ht designates 46.23.81.152 as permitted sender) smtp.mailfrom=lists@sr.ht ARC-Seal: i=1; s=key1; d=johnnyrichard.com; t=1728416029; a=rsa-sha256; cv=none; b=13lMW+xNMWllBG99U6GlYPu2cXbEFUYwTqAAuMbF0BUM0PXoMZ5R6v4C5II5PmAe2ljnbq 30t7kWOwCJykmpn+6KMQU5JoMr/pt4nObqTCGTrjy6ktmeZ4co4QCGfxvfOaTKjrdNAHx/ S6J9/qHwfsTVQZeMK7bRzLUBpebcbdKXT5O174E98Q5XjL85obhulEMbvCfAyf3KnQ9qwS swmqfH3kOXNa8G1hIgXiefEJIL8TBKsBw8o5CcS3SQ+YWLbOjmWbl/3g5Jw/eV01aVoEGo JJUZMTaydBaRyrA7EeZTOaGeMeBW9uS4S011rZlPjlPpF5zYV50EC22flxNr9A== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=lists.sr.ht header.s=20240113 header.b=UKLA4ITv; dkim=pass header.d=johnnyrichard.com header.s=key1 header.b=h6MR6Qqm; dmarc=pass (policy=quarantine) header.from=johnnyrichard.com; spf=pass (aspmx1.migadu.com: domain of lists@sr.ht designates 46.23.81.152 as permitted sender) smtp.mailfrom=lists@sr.ht ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=johnnyrichard.com; s=key1; t=1728416029; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding:list-id: list-unsubscribe:list-subscribe:list-post:dkim-signature; bh=yeZWoic2dhru84j+GY2FWBnmlAMyMNGHg0mYOkByJ+8=; b=d5+VuS2ijtd59X75rhvygfbP/h1D28Jtfo1vDyvIxJhR4Jf1SYzQeWHrDwEqoxXbExvkqM NipO9OEFdqeghbPS8PH9Jgx0GLgyJMkWREQ+JokcQyHcaNLKytYM3cDH2YADY5Cm4SDUI8 e7peHKNzJaq/qqcw2YltLekrf41Ty2VBqINTW7S+GcJ0JhqHuqaDlcxF6Ke44lI0Fc/BaV Mv5TNir8oUUJ18OEM3biqRQJeqiPFTUSR50VhWH7geEYf7tErxH+NinpGqJuAbsXYJAe2u r8DSMwkaOq6K6LNAU2Xqc+SdtpZ4S6tXcecuIZkPvEpQK4DCdYAnRQgS+KKRNw== Received: from mail-a.sr.ht (mail-a.sr.ht [46.23.81.152]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 52F10875FD for ; Tue, 08 Oct 2024 21:33:49 +0200 (CEST) DKIM-Signature: a=rsa-sha256; bh=qmSmx6vWXZdTip/JmN1piCoUP+DDu/m2dM6T+QyaBZI=; c=simple/simple; d=lists.sr.ht; h=From:To:Cc:Subject:Date:List-Unsubscribe:List-Subscribe:List-Archive:List-Post:List-ID; q=dns/txt; s=20240113; t=1728416028; v=1; b=UKLA4ITvbAgHNr/9Z+KaQEbUg6aArXgIY/w0LaiGfhsOPcGZxG70NtM8mNEgTS8MIHyGE6Gb 6htwmQRSvIcXxPKNl44iFb8PSOFFgr+AHSMJuer/tkW7OFaC7Rdi5GI0m6umcn1eBHGvumNMLV2 7FK7eQzQnWAJoC0B9YJ6Kf3HiDcJ2pRolyCPEPavFUcJ5ZgvUpugOIlClifXWC8FsjuiKGpoMc/ X1RUK/4eu52XPBUTiKZKslbEfuip7l0GFuY0A+Zvd7jdbmrrCpaSxJpxmz3cOGIZW521oje/Vhr qObODKFr5dP8AgvMp/g8N6Qga/uUwEzVUvT7CV2efhvRA== Received: from lists.sr.ht (unknown [46.23.81.154]) by mail-a.sr.ht (Postfix) with ESMTPSA id ABFBC2019A for ; Tue, 08 Oct 2024 19:33:48 +0000 (UTC) Received: from out-187.mta1.migadu.com (out-187.mta1.migadu.com [95.215.58.187]) by mail-a.sr.ht (Postfix) with ESMTPS id F0F2E20156 for <~johnnyrichard/olang-devel@lists.sr.ht>; Tue, 08 Oct 2024 19:33:47 +0000 (UTC) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=johnnyrichard.com; s=key1; t=1728416027; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=yeZWoic2dhru84j+GY2FWBnmlAMyMNGHg0mYOkByJ+8=; b=h6MR6QqmGh5BrFTQF4N+5tVXZ2qnSw9HLpg8evBR9AbEzTVnjt40hJTV+0VU/GeAgq9y0L qMce4VyKj1M6UYlE/DVEyMyKm6KtR80dQFRduBnk4Wv/zmYAOC4LN/AjHRI4sawT7G0Nf3 eHjj/Y1ZyvWhRzJLfTzjZ+YhU1SSqK33KGJG0Zz6YI5YH2l+5+ecjObSSjfSvJaWQdPFVr Ado3WC4NjGgn6/+5vsEZ7TK0FhQPxGJP6Lv3VLCFIW6CnfMsNQOvW857Tsr/novcG8Bs1R 9xnaDjHO764yfgXXlcIExu76AkqhnT1u/zwToMuULPEPC3qCEcpPLqacFMvj/g== From: Johnny Richard To: ~johnnyrichard/olang-devel@lists.sr.ht Cc: Johnny Richard Subject: [PATCH olang v1] parser: add support for parsing while-statements Date: Tue, 8 Oct 2024 23:33:05 +0200 Message-ID: <20241008213319.239796-1-johnny@johnnyrichard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Sourcehut-Patchset-Status: PROPOSED List-Unsubscribe: List-Subscribe: List-Archive: Archived-At: List-Post: List-ID: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel.lists.sr.ht> Sender: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel@lists.sr.ht> X-Migadu-Flow: FLOW_IN X-Migadu-Country: NL X-Migadu-Spam-Score: -0.81 X-Spam-Score: -0.81 X-Migadu-Queue-Id: 52F10875FD X-Migadu-Scanner: mx12.migadu.com X-TUID: 27hxl/2rtGLM Signed-off-by: Johnny Richard --- 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 # `-Block +# |-Var_Definition +# | `-Literal +# |-While_Statement +# | |-Binary_Operation (<) +# | | |-Reference +# | | `-Literal +# | `-Block +# | `-Var_Assigment +# | |-Reference +# | `-Binary_Operation (+) +# | |-Reference +# | `-Literal # `-Return_Statement -# `-Literal +# `-Reference # END # # TEST test_contains_tokens WITH base-commit: f0a565d7d551df220c7b8ae0b924245dd70c9468 -- 2.46.0