* [olang/patches/.build.yml] build success
2024-10-09 11:28 [PATCH olang v1] parser: codegen(x86_64): docs: implement else if Johnny Richard
@ 2024-10-09 9:29 ` builds.sr.ht
2024-10-09 9:32 ` [PATCH olang v1] parser: codegen(x86_64): docs: implement else if Carlos Maniero
1 sibling, 0 replies; 3+ messages in thread
From: builds.sr.ht @ 2024-10-09 9:29 UTC (permalink / raw)
To: Johnny Richard; +Cc: ~johnnyrichard/olang-devel
olang/patches/.build.yml: SUCCESS in 22s
[parser: codegen(x86_64): docs: implement else if][0] from [Johnny Richard][1]
[0]: https://lists.sr.ht/~johnnyrichard/olang-devel/patches/55396
[1]: mailto:johnny@johnnyrichard.com
✓ #1347567 SUCCESS olang/patches/.build.yml https://builds.sr.ht/~johnnyrichard/job/1347567
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH olang v1] parser: codegen(x86_64): docs: implement else if
2024-10-09 11:28 [PATCH olang v1] parser: codegen(x86_64): docs: implement else if Johnny Richard
2024-10-09 9:29 ` [olang/patches/.build.yml] build success builds.sr.ht
@ 2024-10-09 9:32 ` Carlos Maniero
1 sibling, 0 replies; 3+ messages in thread
From: Carlos Maniero @ 2024-10-09 9:32 UTC (permalink / raw)
To: Johnny Richard, ~johnnyrichard/olang-devel
Applied! Thanks.
To git.sr.ht:~johnnyrichard/olang
55edba3..2407c81 main -> main
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH olang v1] parser: codegen(x86_64): docs: implement else if
@ 2024-10-09 11:28 Johnny Richard
2024-10-09 9:29 ` [olang/patches/.build.yml] build success builds.sr.ht
2024-10-09 9:32 ` [PATCH olang v1] parser: codegen(x86_64): docs: implement else if Carlos Maniero
0 siblings, 2 replies; 3+ messages in thread
From: Johnny Richard @ 2024-10-09 11:28 UTC (permalink / raw)
To: ~johnnyrichard/olang-devel; +Cc: Johnny Richard
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
---
docs/info/getting-started.texi | 2 +
docs/info/specification.texi | 2 +-
src/codegen_linux_x86_64.c | 67 ++++++++++++++++++++--------------
src/parser.c | 8 +++-
tests/olc/0032_else_if.ol | 50 +++++++++++++++++++++++++
5 files changed, 99 insertions(+), 30 deletions(-)
create mode 100644 tests/olc/0032_else_if.ol
diff --git a/docs/info/getting-started.texi b/docs/info/getting-started.texi
index 394b266..a68f5b1 100644
--- a/docs/info/getting-started.texi
+++ b/docs/info/getting-started.texi
@@ -71,6 +71,8 @@ Any non zero expr is true.
@verbatim
if expr {
# statement
+} else if expr {
+ # statement
} else {
# statement
}
diff --git a/docs/info/specification.texi b/docs/info/specification.texi
index 1bac50f..6caaac8 100644
--- a/docs/info/specification.texi
+++ b/docs/info/specification.texi
@@ -42,7 +42,7 @@ language.
<function-args> ::= <expression> (<ows> ',' <function-args>)*
<function-call> ::= <function-name> <ows> '(' ( <ows> | <ows> <function-args> <ows> ) ')'
<statement> ::= <common-statement> | <if-statement> | <while-statement> | <return-statement> | <function-call>
-<if-statement> ::= 'if' <ws> <expression> <ows> <block>
+<if-statement> ::= 'if' <ws> <expression> <ows> <block> ( <ows> 'else' ( <ows> <block> | <ows> <if-statement> ) )?
<while-statement> ::= 'while' <ws> <expression> <ows> <block>
<return-statement> ::= 'return' <ws> <expression>
diff --git a/src/codegen_linux_x86_64.c b/src/codegen_linux_x86_64.c
index 5749e65..10005b9 100644
--- a/src/codegen_linux_x86_64.c
+++ b/src/codegen_linux_x86_64.c
@@ -66,6 +66,9 @@ codegen_linux_x86_64_emit_start_entrypoint(codegen_x86_64_t *codegen);
static void
codegen_linux_x86_64_emit_function(codegen_x86_64_t *codegen, ast_fn_definition_t *fn);
+static void
+codegen_linux_x86_64_emit_if(codegen_x86_64_t *codegen, ast_if_stmt_t is_stmt);
+
static void
codegen_linux_x86_64_put_stack_offset(codegen_x86_64_t *codegen, symbol_t *symbol, size_t offset);
@@ -597,34 +600,7 @@ codegen_linux_x86_64_emit_block(codegen_x86_64_t *codegen, ast_block_t *block)
}
case AST_NODE_IF_STMT: {
- ast_if_stmt_t if_stmt = node->as_if_stmt;
-
- ast_node_t *cond = if_stmt.cond;
- ast_node_t *then = if_stmt.then;
- ast_node_t *_else = if_stmt._else;
-
- size_t end_if_label = codegen_linux_x86_64_get_next_label(codegen);
- size_t end_else_label = codegen_linux_x86_64_get_next_label(codegen);
-
- codegen_linux_x86_64_emit_expression(codegen, cond);
- fprintf(codegen->out, " cmp $1, %%rax\n");
- fprintf(codegen->out, " jnz .L%ld\n", end_if_label);
-
- assert(then->kind == AST_NODE_BLOCK && "invalid if-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", end_else_label);
-
- fprintf(codegen->out, ".L%ld:\n", end_if_label);
-
- if (_else != NULL) {
- ast_block_t else_block = _else->as_block;
- codegen_linux_x86_64_emit_block(codegen, &else_block);
- }
-
- fprintf(codegen->out, ".L%ld:\n", end_else_label);
-
+ codegen_linux_x86_64_emit_if(codegen, node->as_if_stmt);
break;
}
@@ -664,6 +640,41 @@ codegen_linux_x86_64_emit_block(codegen_x86_64_t *codegen, ast_block_t *block)
codegen->base_offset = block_offset;
}
+static void
+codegen_linux_x86_64_emit_if(codegen_x86_64_t *codegen, ast_if_stmt_t if_stmt)
+{
+ ast_node_t *cond = if_stmt.cond;
+ ast_node_t *then = if_stmt.then;
+ ast_node_t *_else = if_stmt._else;
+
+ size_t end_if_label = codegen_linux_x86_64_get_next_label(codegen);
+ size_t end_else_label = codegen_linux_x86_64_get_next_label(codegen);
+
+ codegen_linux_x86_64_emit_expression(codegen, cond);
+ fprintf(codegen->out, " cmp $1, %%rax\n");
+ fprintf(codegen->out, " jnz .L%ld\n", end_if_label);
+
+ assert(then->kind == AST_NODE_BLOCK && "invalid if-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", end_else_label);
+
+ fprintf(codegen->out, ".L%ld:\n", end_if_label);
+
+ if (_else != NULL) {
+ if (_else->kind == AST_NODE_IF_STMT) {
+ ast_if_stmt_t else_if = _else->as_if_stmt;
+ codegen_linux_x86_64_emit_if(codegen, else_if);
+ } else {
+ ast_block_t else_block = _else->as_block;
+ codegen_linux_x86_64_emit_block(codegen, &else_block);
+ }
+ }
+
+ fprintf(codegen->out, ".L%ld:\n", end_else_label);
+}
+
static size_t
type_to_bytes(type_t *type)
{
diff --git a/src/parser.c b/src/parser.c
index d498ea5..5d6290b 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -573,7 +573,13 @@ parser_parse_if_stmt(parser_t *parser)
lexer_next_token(parser->lexer, &next_token);
skip_line_feeds(parser->lexer);
- _else = parser_parse_block(parser);
+ lexer_peek_next(parser->lexer, &next_token);
+
+ if (next_token.kind == TOKEN_IF) {
+ _else = parser_parse_if_stmt(parser);
+ } else {
+ _else = parser_parse_block(parser);
+ }
if (_else == NULL) {
return NULL;
diff --git a/tests/olc/0032_else_if.ol b/tests/olc/0032_else_if.ol
new file mode 100644
index 0000000..6260838
--- /dev/null
+++ b/tests/olc/0032_else_if.ol
@@ -0,0 +1,50 @@
+# Copyright (C) 2024 olang mantainers
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+fn main(): u32
+{
+ if 0 != 0 {
+ return 1
+ } else if 1 == 1 {
+ return 0
+ }
+ return 1
+}
+
+# XTEST test_compile(exit_code=0)
+
+# XTEST test_run_binary(exit_code=0)
+
+# TEST test_ast WITH
+# Translation_Unit
+# `-Function_Definition <name:main> <return:u32>
+# `-Block
+# |-If_Statement
+# | |-Binary_Operation (!=)
+# | | |-Literal <kind:u32> <value:0>
+# | | `-Literal <kind:u32> <value:0>
+# | |-Block
+# | | `-Return_Statement
+# | | `-Literal <kind:u32> <value:1>
+# | `-If_Statement
+# | |-Binary_Operation (==)
+# | | |-Literal <kind:u32> <value:1>
+# | | `-Literal <kind:u32> <value:1>
+# | `-Block
+# | `-Return_Statement
+# | `-Literal <kind:u32> <value:0>
+# `-Return_Statement
+# `-Literal <kind:u32> <value:1>
+# END
base-commit: 55edba3a0a62d33556e3366c49cd7ce5beab6665
--
2.46.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-10-09 9:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-09 11:28 [PATCH olang v1] parser: codegen(x86_64): docs: implement else if Johnny Richard
2024-10-09 9:29 ` [olang/patches/.build.yml] build success builds.sr.ht
2024-10-09 9:32 ` [PATCH olang v1] parser: codegen(x86_64): docs: implement else if Carlos Maniero
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