From 5de2e1fd9f426348127a66d2c51c300cb90cc3a4 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 00:20:00 -0300 Subject: gas: Generate code for if statement If statements are now working, the only exception is for the comparators || and && that will be addressed in a further commit. Checks tested: fn main(): i32 { let n: i32 = 11; if (n == 11) { if n != 12 { if n < 12 { if n <= 11 { if n > 10 { if n >= 11 { return 42; } } } } } } return n; } To compile the && and || a precedence issue must be addressed: they must have the highest precedence, witch is not working now: 1 == 2 || 3 != 2 The or should be the higher level of the tree in the example above. Signed-off-by: Carlos Maniero --- test/integration_test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'test/integration_test.c') diff --git a/test/integration_test.c b/test/integration_test.c index 4178b42..985e574 100644 --- a/test/integration_test.c +++ b/test/integration_test.c @@ -43,6 +43,7 @@ test_examples(const MunitParameter params[], void *user_data_or_fixture) assert_exit_status("../examples/main.pipa", 69); assert_exit_status("../examples/arithmetics.pipa", 13); assert_exit_status("../examples/variables.pipa", 28); + assert_exit_status("../examples/if.pipa", 42); return MUNIT_OK; } -- cgit v1.2.3 From 5042a4ffc1363d6f0f99a3afd79f76cf2da738d6 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 22:24:14 -0300 Subject: gas: implement function calls For now function calls are following the C's calling convention, which means they are using the following registers to pass functions' arguments: rdi, rsi, rdx, rcx, r8, r9 If a function has more then 6 parameters, the compilation will fail. To enable function with more than 6 parameters we will need to save the extra arguments on stack. Naming: parameters: function parameters are the variables a function receives. arguments: Arguments are the values passed to a function when calling it. Calling mechanism: When a function is called, all the expressions passed as argument are evaluated, after the evaluation, the result is stored on the register that represents its argument position, the first argument will be stored on rdi, the second on rsi and so on. Receiving mechanism: When a function starts, the first thing it does is store all the registers onto the stack. So rdi will be stored on -8(rbp), rsi on -16(rbp) and so on. And, a ref_entry is created making the relationship parameter-stack_offset. Signed-off-by: Carlos Maniero --- test/integration_test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'test/integration_test.c') diff --git a/test/integration_test.c b/test/integration_test.c index 985e574..608764a 100644 --- a/test/integration_test.c +++ b/test/integration_test.c @@ -44,6 +44,7 @@ test_examples(const MunitParameter params[], void *user_data_or_fixture) assert_exit_status("../examples/arithmetics.pipa", 13); assert_exit_status("../examples/variables.pipa", 28); assert_exit_status("../examples/if.pipa", 42); + assert_exit_status("../examples/function_call.pipa", 42); return MUNIT_OK; } -- cgit v1.2.3 From ea7f65fe1250be8f49edcaaedd3410aed1401648 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Thu, 11 May 2023 15:00:10 -0300 Subject: gas: implement recursion and late evaluation Until now the below code was not valid for pipac. fn main(): i32 { return fib(13); } fn fib(n: i32): i32 { if n <= 1 { return n; } return fib(n - 1) + fib(n - 2); } Pipa's parser was adding a function to scope after they were fully parsed which means that fib's self-reference would not work. Also, functions were required to follow the be called in the order they are declared for the same scope reason so, the main function was required to be defined after fib. And how it is working now? When a TOKEN_NAME is not found in the scope, instead of returning an error, an unknown token is created as placeholder. The parser stores the node reference and the token it was trying to parse. During type checks, if the parser detects an unknown node, instead of returning an error, it stores in that node what was the expected type. After the NS is fully parsed a reevaluation is made on those unknown nodes by setting the lexer back on the node's token position and parsing the TOKEN_NAME again. Ps: There is a typo on the unknown token. It will be addressed in another commit since this issue was not introduced by this change. Signed-off-by: Carlos Maniero --- test/integration_test.c | 1 + 1 file changed, 1 insertion(+) (limited to 'test/integration_test.c') diff --git a/test/integration_test.c b/test/integration_test.c index 608764a..8866f83 100644 --- a/test/integration_test.c +++ b/test/integration_test.c @@ -45,6 +45,7 @@ test_examples(const MunitParameter params[], void *user_data_or_fixture) assert_exit_status("../examples/variables.pipa", 28); assert_exit_status("../examples/if.pipa", 42); assert_exit_status("../examples/function_call.pipa", 42); + assert_exit_status("../examples/fibbonacci.pipa", 233); return MUNIT_OK; } -- cgit v1.2.3