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 --- examples/if.pipa | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/if.pipa b/examples/if.pipa index 2c5578d..b7cadcb 100644 --- a/examples/if.pipa +++ b/examples/if.pipa @@ -1,8 +1,18 @@ fn main(): i32 { - let n: i32 = 42; + let n: i32 = 11; - if n > 42 { - return 42; + if (n == 11) { + if n != 12 { + if n < 12 { + if n <= 11 { + if n > 10 { + if n >= 11 { + return 42; + } + } + } + } + } } return n; -- cgit v1.2.3 From 88630ebbea03e85119cf9795320a83cb846bdd20 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 01:43:40 -0300 Subject: gas: Implement && and || for if statements Now if statements are complete! The function %gas_assembly_generator_compile_condition% is generic and will be used for any other flow-control statment. The only requirement to it work is having two labels: One to jump when the condition is true, and another one when the condition is false. Signed-off-by: Carlos Maniero --- examples/if.pipa | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/if.pipa b/examples/if.pipa index b7cadcb..d65fc24 100644 --- a/examples/if.pipa +++ b/examples/if.pipa @@ -7,12 +7,60 @@ fn main(): i32 { if n <= 11 { if n > 10 { if n >= 11 { - return 42; + if n >= 11 || n < 11 { + if n > 11 || n < 11 { + return 199; + } + if n > 11 || n <= 11 { + if false || false { + return 199; + } + + if true || false { + if false || true { + if true && false { + return 197; + } + if false && true { + return 196; + } + if true && true { + if n >= 11 && n < 11 || n == 11 { + if false || n == 11 && n > 11 { + return 195; + } + if false || n >= 11 && n <= 11 { + if false || false && false && false || true { + if n + 1 > 11 && n - 1 < 11 { + return 42; + } + return 13; + } + return 12; + } + return 11; + } + return 10; + } + return 9; + } + return 8; + } + return 7; + } + return 6; + } + return 5; } + return 4; } + return 3; } + return 2; } + return 1; } + return 0; } return n; -- cgit v1.2.3 From a96a0cac034e16dcd7455a3b2fabf2b5b3e716bd Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 12:20:04 -0300 Subject: gas: Compile boolean variable assignment When the assignment value is a literal, it just assigns zero or one to the variable stack's location. If the value is an expression, it compiles the expression and assign zeros and ones based on expression result. --- examples/if.pipa | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/if.pipa b/examples/if.pipa index d65fc24..79f5724 100644 --- a/examples/if.pipa +++ b/examples/if.pipa @@ -1,6 +1,18 @@ fn main(): i32 { let n: i32 = 11; + let falsy: bool = false || n == 11 && n > 11; + let truth: bool = n + 1 > 11 && n - 1 < 11; + let literal_falsy: bool = false; + + if falsy { + return 201; + } + + if literal_falsy { + return 200; + } + if (n == 11) { if n != 12 { if n < 12 { @@ -15,7 +27,6 @@ fn main(): i32 { if false || false { return 199; } - if true || false { if false || true { if true && false { @@ -32,7 +43,10 @@ fn main(): i32 { if false || n >= 11 && n <= 11 { if false || false && false && false || true { if n + 1 > 11 && n - 1 < 11 { - return 42; + if truth { + return 42; + } + return 14; } return 13; } -- cgit v1.2.3 From 3129b741064c2b4f2c6c2408bd42cc83f7341ea8 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 16:53:05 -0300 Subject: gas: Generate function call This is an initial commit that enables function calls. At this point only functions with no parameters is going to work. Signed-off-by: Carlos Maniero --- examples/main.pipa | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/main.pipa b/examples/main.pipa index 2da2231..5ea0077 100644 --- a/examples/main.pipa +++ b/examples/main.pipa @@ -1,3 +1,7 @@ -fn main(): i32 { +fn give_me_the_number(): i32 { return 69; } + +fn main(): i32 { + return give_me_the_number(); +} -- 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 --- examples/function_call.pipa | 11 +++++++++++ examples/main.pipa | 6 +----- 2 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 examples/function_call.pipa (limited to 'examples') diff --git a/examples/function_call.pipa b/examples/function_call.pipa new file mode 100644 index 0000000..833c195 --- /dev/null +++ b/examples/function_call.pipa @@ -0,0 +1,11 @@ +fn add(n: i32, n2: i32): i32 { + return n + n2; +} + +fn id(n: i32): i32 { + return n; +} + +fn main(): i32 { + return id(add(40, 44)) / 2; +} diff --git a/examples/main.pipa b/examples/main.pipa index 5ea0077..2da2231 100644 --- a/examples/main.pipa +++ b/examples/main.pipa @@ -1,7 +1,3 @@ -fn give_me_the_number(): i32 { - return 69; -} - fn main(): i32 { - return give_me_the_number(); + return 69; } -- 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 --- examples/fibbonacci.pipa | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 examples/fibbonacci.pipa (limited to 'examples') diff --git a/examples/fibbonacci.pipa b/examples/fibbonacci.pipa new file mode 100644 index 0000000..c19e65d --- /dev/null +++ b/examples/fibbonacci.pipa @@ -0,0 +1,10 @@ +fn main(): i32 { + return fib(13); +} + +fn fib(n: i32): i32 { + if n <= 1 { + return n; + } + return fib(n - 1) + fib(n - 2); +} -- cgit v1.2.3