Implement if statements

This commit is contained in:
2025-04-29 00:55:20 +02:00
parent 963d32e8d1
commit 9c66cec171
7 changed files with 476 additions and 213 deletions

View File

@@ -14,6 +14,9 @@ type checking.
hexadecimal format).
- Comments are accepted only at the end of a line.
- Return can be used only as the last statement of a procedure. It
doesn't actually return, but sets a0 to the appropriate value.
*)
program
@@ -36,7 +39,7 @@ begin
end
proc _build_binary_expression()
var loca0, loca4, loca8: Word
var loca0, loca4, loca8, loca20: Word
begin
_build_expression(0)
@@ -44,8 +47,7 @@ begin
loca8 := 0x0a316120 (* _a1\n *)
_skip_spaces()
call _read_token
sw a0, 20(sp)
loca20 := _read_token()
li t0, 0x26 # &
sw t0, 16(sp)
@@ -87,6 +89,14 @@ begin
call _token_compare
beqz a0, .L_build_binary_expression_minus
li t0, 0x2a # *
sw t0, 16(sp)
mv a0, s1
lw a1, 20(sp)
addi a2, sp, 16
call _token_compare
beqz a0, .L_build_binary_expression_product
goto .Lbuild_binary_expression_end
.L_build_binary_expression_equal
@@ -146,6 +156,19 @@ begin
_write_out(@loca4, 4)
_write_out(@loca8, 4)
goto .Lbuild_binary_expression_end
.L_build_binary_expression_product
_advance(1) (* Skip *. *)
_build_expression(1)
loca0 := 0x6c756d (* mul *)
_write_out(@loca0, 3)
_write_out(@loca4, 4)
_write_out(@loca4, 4)
_write_out(@loca8, 4)
goto .Lbuild_binary_expression_end
.Lbuild_binary_expression_end
end
@@ -156,28 +179,30 @@ a0 - X in aX, the register number to save the result.
*)
proc _build_expression()
var
loca20, loca28, loca8: Word
loca24: ^Byte
loca0, loca20, loca28, loca8: Word
loca24, loca4: ^Byte
begin
addi a0, a0, '0' # Make the register number to a character.
sw a0, 28(sp) # And save it.
(* Make the register number to a character and save it. *)
loca28 := loca84 + 0x30 (* 0 *)
_skip_spaces()
loca20 := _read_token()
loca24 := _current()
addi a0, s1, 0
lbu a0, (a0)
lbu a0, (s1)
li t0, '-'
beq a0, t0, .Lbuild_expression_negate
lbu a0, (s1)
li t0, '@'
beq a0, t0, .Lbuild_expression_address
addi a0, s1, 0
lbu a0, (a0)
call _is_digit
bnez a0, .Lbuild_expression_literal
loca0 := _front()
if _is_digit(loca0) then
goto .Lbuild_expression_literal
end
addi a0, s1, 0
lbu a0, (a0)
lbu a0, (s1)
li t0, '_'
beq a0, t0, .Lbuild_expression_call
@@ -200,6 +225,19 @@ begin
goto .Lbuild_expression_advance
.Lbuild_expression_negate
_advance(1) (* Skip the -. *)
_build_expression(0)
loca8 := 0x2067656e (* neg_ *)
_write_out(@loca8, 4)
loca8 := 0x202c3061 (* a0,_ *)
_write_out(@loca8, 4)
loca8 := 0x0a3061 (* a0,_ *)
_write_out(@loca8, 3)
goto .Lbuild_expression_advance
.Lbuild_expression_address
loca8 := 0x69646461 (* addi *)
_write_out(@loca8, 4)
@@ -216,40 +254,28 @@ begin
loca24 := _current()
loca20 := _read_token()
lw a0, 24(sp)
lw a1, 20(sp)
addi a0, a0, 4 # Skip the "loca" variable prefix.
addi a1, a1, -4 # Skip the "loca" variable prefix.
call _write_out
(* Skip the "loca" variable prefix. *)
loca4 := loca24 + 4
loca0 := loca20 - 4
_write_out(loca4, loca0)
_put_char(0xa)
goto .Lbuild_expression_advance
.Lbuild_expression_identifier
lw t1, 28(sp)
li t0, 0x00202c00 # \0,_
or t0, t0, t1
sw t0, 8(sp)
li t0, 0x6120776c # lw a
sw t0, 4(sp)
addi a0, sp, 4
li a1, 7
call _write_out
loca8 := 0x6120776c (* lw a *)
_write_out(@loca8, 4)
loca8 := 0x00202c00 or loca28 # \0,_
_write_out(@loca8, 3)
lw a0, 24(sp)
lw a1, 20(sp)
addi a0, a0, 4 # Skip the "loca" variable prefix.
addi a1, a1, -4 # Skip the "loca" variable prefix.
call _write_out
loca4 := loca24 + 4
loca0 := loca20 - 4
_write_out(loca4, loca0) (* Skip the "loca" variable prefix. *)
li t0, 0x0a # \n
sw t0, 8(sp)
li t0, 0x29707328 # (sp)
sw t0, 4(sp)
addi a0, sp, 4
li a1, 5
call _write_out
loca8 := 0x29707328 (* (sp) *)
_write_out(@loca8, 4)
_put_char(0x0a) (* \n *)
goto .Lbuild_expression_advance
@@ -261,18 +287,13 @@ begin
goto .Lbuild_expression_end
.Lbuild_expression_literal
lw t1, 28(sp)
li t0, 0x00202c00 # \0,_
or t0, t0, t1
sw t0, 8(sp)
li t0, 0x6120696c # li a
sw t0, 4(sp)
addi a0, sp, 4
li a1, 7
call _write_out
loca8 := 0x6120696c (* li a *)
_write_out(@loca8, 4)
loca8 := 0x00202c00 or loca28 (* \0,_ *)
_write_out(@loca8, 3)
_write_out(loca24, loca20)
_put_char(0x0a) # \n
_put_char(0x0a) (* \n *)
goto .Lbuild_expression_advance
@@ -335,11 +356,9 @@ begin
loca0 := 0x202c30 (* 0,_ *)
_write_out(@loca0, 3)
lw a0, 20(sp)
lw a1, 16(sp)
addi a0, a0, 4 # Skip the "loca" variable prefix.
addi a1, a1, -4 # Skip the "loca" variable prefix.
call _write_out
loca20 := loca20 + 4
loca16 := loca16 - 4
_write_out(loca20, loca16)
loca0 := 0x29707328 (* (sp) *)
_write_out(@loca0, 4)
@@ -359,7 +378,7 @@ Returns the procedure result in a0.
*)
proc _compile_call(loca84: ^Byte, loca80: Word)
var
loca0, loca12: Word
loca0, loca4, loca12: Word
begin
loca12 := 0 (* Argument count for a procedure call. *)
@@ -377,49 +396,24 @@ begin
loca0 := 0x202c30 (* 0,_ *)
_write_out(@loca0, 3)
lw t0, 12(sp) # Argument count for a procedure call.
(*
Only 6 arguments are supported with a0-a5.
Save all arguments on the stack so they aren't overriden afterwards.
The offset on the stack always has two digits in this case.
*)
li t1, -4
mul t1, t0, t1
addi t1, t1, 60
li t2, 10
div t3, t1, t2
rem t4, t1, t2
addi t3, t3, '0'
addi t4, t4, '0'
loca0 := -4 * loca12
loca0 := loca0 + 60
_printi(loca0)
sw t3, 8(sp)
sw t4, 4(sp)
addi a0, sp, 8
li a1, 1
call _write_out
addi a0, sp, 4
li a1, 1
call _write_out
li t0, 0x0a # \n
sw t0, 8(sp)
li t0, 0x29707328 # (sp)
sw t0, 4(sp)
addi a0, sp, 4
li a1, 5
call _write_out
loca0 := 0x29707328 (* (sp) *)
_write_out(@loca0, 4)
_put_char(0x0a) (* \n *)
_skip_spaces()
lbu t0, (s1)
li t1, ','
bne t0, t1, .Lcompile_call_paren
lw t0, 12(sp) # Argument count for a procedure call.
addi t0, t0, 1
sw t0, 12(sp)
loca12 := loca12 + 1 (* Argument count for a procedure call. *)
_advance(1) (* Skip the comma between the arguments. *)
goto .Lcompile_call_argument
@@ -432,47 +426,62 @@ begin
Just go through all a0-a5 registers and read them from stack.
If this stack value contains garbage, the procedure just shouldn't use it.
*)
lw t0, 12(sp)
li t1, 5
bgt t0, t1, .Lcompile_call_perform
loca0 := 0x6120776c (* lw a *)
(* lw a0, 60(sp) *)
_write_out(@loca0, 4)
loca4 := 0x36202c30 (* 0, 6 *)
_write_out(@loca4, 4)
loca4 := 0x70732830 (* 0(sp *)
_write_out(@loca4, 4)
loca4 := 0x0a29 (* )\n *)
_write_out(@loca4, 2)
li t0, 0x6120776c # lw a
sw t0, 4(sp)
addi a0, sp, 4
li a1, 4
call _write_out
(* lw a1, 56(sp) *)
_write_out(@loca0, 4)
loca4 := 0x35202c31 (* 1, 5 *)
_write_out(@loca4, 4)
loca4 := 0x70732836 (* 6(sp *)
_write_out(@loca4, 4)
loca4 := 0x0a29 (* )\n *)
_write_out(@loca4, 2)
lw t0, 12(sp) # Argument count for a procedure call.
(* lw a2, 52(sp) *)
_write_out(@loca0, 4)
loca4 := 0x35202c32 (* 2, 5 *)
_write_out(@loca4, 4)
loca4 := 0x70732832 (* 2(sp *)
_write_out(@loca4, 4)
loca4 := 0x0a29 (* )\n *)
_write_out(@loca4, 2)
li t1, -4
mul t1, t0, t1
addi t1, t1, 60
li t2, 10
div t3, t1, t2
rem t4, t1, t2
addi t3, t3, '0'
addi t4, t4, '0'
addi t0, t0, '0'
(* lw a3, 48(sp) *)
_write_out(@loca0, 4)
loca4 := 0x34202c33 (* 3, 4 *)
_write_out(@loca4, 4)
loca4 := 0x70732838 (* 8(sp *)
_write_out(@loca4, 4)
loca4 := 0x0a29 (* )\n *)
_write_out(@loca4, 2)
li t5, 0x0a # \n
sb t5, 11(sp)
li t5, 0x29707328 # (sp)
sw t5, 7(sp)
sb t4, 6(sp)
sb t3, 5(sp)
li t5, 0x202c # ,_
sh t5, 3(sp)
sb t0, 2(sp)
(* lw a4, 44(sp) *)
_write_out(@loca0, 4)
loca4 := 0x34202c34 (* 4, 4 *)
_write_out(@loca4, 4)
loca4 := 0x70732834 (* 4(sp *)
_write_out(@loca4, 4)
loca4 := 0x0a29 (* )\n *)
_write_out(@loca4, 2)
addi a0, sp, 2
li a1, 10
call _write_out
(* lw a5, 40(sp) *)
_write_out(@loca0, 4)
loca4 := 0x34202c35 (* 5, 4 *)
_write_out(@loca4, 4)
loca4 := 0x70732830 (* 0(sp *)
_write_out(@loca4, 4)
loca4 := 0x0a29 (* )\n *)
_write_out(@loca4, 2)
loca12 := loca12 + 1
goto .Lcompile_call_restore
.Lcompile_call_perform
loca0 := 0x6c6c6163
loca0 := 0x6c6c6163 (* call *)
_write_out(@loca0, 4)
_put_char(0x20) (* _ *)
@@ -532,6 +541,9 @@ begin
li t1, '-'
beq t0, t1, .Ltoken_character_single
li t1, '*'
beq t0, t1, .Ltoken_character_single
li t1, '@'
beq t0, t1, .Ltoken_character_single
(* Expect an identifier or a number. *)
@@ -1125,6 +1137,61 @@ begin
_build_binary_expression()
end
proc _compile_if()
var
loca8, loca12, loca16, loca20: Word
loca4: ^Byte
begin
_advance(2) (* Skip the if. *)
_skip_spaces()
_build_binary_expression()
_skip_spaces()
_advance(4) (* Skip the then. *)
loca20 := 0x00646e65 (* if end marker and newline. *)
loca16 := 0x66694c2e (* Label prefix ".Lif". *)
loca12 := 0x7a716562 (* beqz *)
_write_out(@loca12, 4)
loca12 := 0x2c306120 (* _a0, *)
_write_out(@loca12, 4)
_put_char(0x20) (* _ *)
(* Write the label *)
_write_out(@loca16, 4)
mv a0, s2
call _printi
_put_char(0x0a) (* \n *)
.Lcompile_if_loop
_skip_spaces()
loca12 := _read_token()
loca4 := _current()
loca8 := _token_compare(loca4, loca12, @loca20)
if loca8 then
loca12 := _read_line()
_compile_line(loca12, 1)
goto .Lcompile_if_loop
end
(* Write the label *)
_write_out(@loca16, 4)
mv a0, s2
call _printi
loca12 := 0x0a3a0a3a (* :\n:\n *)
_write_out(@loca12, 2)
addi s2, s2, 1 # Increment the label counter.
_advance(4) (* Skip the end with newline. *)
end
(*
Parameters:
a0 - Line length.
@@ -1234,6 +1301,14 @@ begin
call _memcmp
beqz a0, .Lcompile_line_return
li t0, 0x6669 # if
sw t0, 12(sp)
mv a0, s1
addi a1, sp, 12
li a2, 2
call _memcmp
beqz a0, .Lcompile_line_if
lbu t0, (s1)
li t1, '.'
beq t0, t1, .Lcompile_line_label
@@ -1242,6 +1317,10 @@ begin
goto .Lcompile_line_unchanged (* Else. *)
.Lcompile_line_if:
_compile_if()
goto .Lcompile_line_section
.Lcompile_line_label
_compile_label(loca84)
goto .Lcompile_line_section
@@ -1409,7 +1488,9 @@ begin
end
proc _compile()
var loca0, loca4: Word
var
loca0, loca4: Word
loca8: Bool
begin
loca4 := 0 (* Whether the text section header was already emitted. *)
@@ -1419,15 +1500,11 @@ begin
_skip_indentation()
loca0 := _read_line()
lw a0, 0(sp)
lw a1, 4(sp)
call _compile_line
loca8 := _compile_line(loca0, loca4)
beqz a0, .Lcompile_do
(* Update whether the text section header was already emitted. *)
lw t0, 4(sp)
or t0, t0, a0
sw t0, 4(sp)
loca4 := loca4 or loca8
goto .Lcompile_do
.Lcompile_end
@@ -1460,5 +1537,6 @@ begin
call _read_file
la s1, source_code # s1 = Source code position.
li s2, 1
_compile()
end.