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 qEWGIh9MBmfrdwAA62LTzQ:P1 (envelope-from ) for ; Wed, 09 Oct 2024 11:25:51 +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 qEWGIh9MBmfrdwAA62LTzQ (envelope-from ) for ; Wed, 09 Oct 2024 11:25:51 +0200 X-Envelope-To: patches@johnnyrichard.com Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=lists.sr.ht header.s=20240113 header.b=mMksZV+X; dkim=pass header.d=johnnyrichard.com header.s=key1 header.b=1Ftyqcoc; 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=1728465951; a=rsa-sha256; cv=none; b=Dy427ytXkxZb9OpK8jvPwMgccmUx95dia1zASN/Ouc7fDaGDvyvJPkK+Z19g0xrnH77Usp 2/i14dWVUjd5TDShtzWNHkq4serOQsEC4/Kczr3vxdWps8w5lLx+vmT51tAgFxdYHLL0i0 bnL9uXhNQbBQwUr0jSqh2emSu8aR40MGBAdzw8nTPphN9ZxrsodeLuCjlLn32OC6QU163k DgWOXCMPEmny5HauFlwmYUSTsXzvfnz4LFpPqSabAJpDoEL3sACL6vfsgKYEYkY7MlSFOh UWUbViLW19iqmHIpWAQAR+YMQXFTnTyIaoyBa/lb0rFnBs2kIuf0E0dcf7C+fQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=lists.sr.ht header.s=20240113 header.b=mMksZV+X; dkim=pass header.d=johnnyrichard.com header.s=key1 header.b=1Ftyqcoc; 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=1728465951; 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=bLiug3TWKaaFPIj42KTPtdkhKhdNgzcIWELuP33cWXH7rc9tLFZNkIsi5oMfOR6Ctx+c5V tZEX2cyp7pBkf2O+u+gJI8wgN2Y+SlHy6ZS4xfHVRYhfbEkB/1AckrLy6AU09ViAi4OhUF 6SUg+sugGIk89/bcOcNx2jDLJF9ocBr5K7I2izhBPQEGxqrMImhCTgyekkxdGYeFIB1EG1 xU07Tt8fCg3Q1Z3kqAZwSOv8/tnwEFwTkDCsiEq/RBudHUuQAn3As7gh/jeLbdUu4/10BT OxMv6TbF+WB299UV+dGuve26rI5DK3srwIrv8h/ar5lCEVFl/BDqFQXI42oGvQ== 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 DE09D61929 for ; Wed, 09 Oct 2024 11:25:50 +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=1728465950; v=1; b=mMksZV+XR0HQJ+bwn980WXx64LZdlY3Bvr3xdorRuFw24mn0u0AjMIH4eyZhI4UCo7UtibqU 6JGrjGYCjAjzWenDlTpQ43Hp7vaM0xKXrWJ3HmuZ0uJbI6dVYAHZKihoeM1m2qW2wF42tavd6MO EJn8A0Vft/TzI+9HeHv0bmZNWNkjv608Nwi8RBufa7sY3Oac+1GHnpTOk3t0tRCONr3pgFKgScC DRi2P0hP4e5skwiTKk+Y1Q2JJayooKJEtuLGZfh8aBJwz6x0d6eWWmVWik8FbnZ3hhq4m8ZvrpR vfNZnyd28mwhz9J7VnX+K21aCu8FtmtxItLkagRPMU2Rg== Received: from lists.sr.ht (unknown [46.23.81.154]) by mail-a.sr.ht (Postfix) with ESMTPSA id 279CF201FA for ; Wed, 09 Oct 2024 09:25:50 +0000 (UTC) Received: from out-180.mta1.migadu.com (out-180.mta1.migadu.com [95.215.58.180]) by mail-a.sr.ht (Postfix) with ESMTPS id 7E55F201E6 for <~johnnyrichard/olang-devel@lists.sr.ht>; Wed, 09 Oct 2024 09:25:49 +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=1728465949; 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=1FtyqcocgkB+omeDMzReddOApGgKPDGdf6ZJyUIvP6MDf3VQnHBxr5aK6hCGNjGiFwIh0w 2VIjK9dfb2tbugH8PTj3OO01Zo3VkvwJyAa3p3rlswYx+BmyP7Fq7lXeeZMJnj1wXEiKfF w1R7splWRjf29NOr/45WvYYhh+FinjaccaxmL5twbmHiZ0jnW2b4EFMP63w65nwW2A+dUz Ecw16ecYdwTq9P9qTfwEaiAlp1+D2dvGQ2W0s3ro/7PKnbYNu3cosD932rkJUp/vkctURQ DuqwV0lpKnmaFjPBMa3be5YvG4pvFR+h059EPeaVFAz6YrVfpmttaEaItYY9rQ== From: Johnny Richard To: ~johnnyrichard/olang-devel@lists.sr.ht Cc: Johnny Richard Subject: [PATCH olang v1 1/2] parser: add support for parsing while-statements Date: Wed, 9 Oct 2024 13:24:52 +0200 Message-ID: <20241009112516.294219-2-johnny@johnnyrichard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Sourcehut-Patchset-Status: UNKNOWN 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.80 X-Spam-Score: -0.80 X-Migadu-Queue-Id: DE09D61929 X-Migadu-Scanner: mx12.migadu.com X-TUID: mXH7d+Qbhchj 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