diff options
| author | Eugen Wissner <belka@caraus.de> | 2025-09-13 21:15:09 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2025-09-13 21:15:09 +0200 |
| commit | ee3b733a81f3136494e612a0d748f4d029064845 (patch) | |
| tree | 10a6d7534dc3efd11562f28ce9b1a581530ebb5e /boot/stage9.elna | |
| parent | 216dc59f0b1507a7529ce34332463f9443a05cd4 (diff) | |
| download | elna-ee3b733a81f3136494e612a0d748f4d029064845.tar.gz | |
Implement if-else
Diffstat (limited to 'boot/stage9.elna')
| -rw-r--r-- | boot/stage9.elna | 191 |
1 files changed, 120 insertions, 71 deletions
diff --git a/boot/stage9.elna b/boot/stage9.elna index ebeb467..9f5e4d5 100644 --- a/boot/stage9.elna +++ b/boot/stage9.elna @@ -2,11 +2,12 @@ (* v. 2.0. If a copy of the MPL was not distributed with this file, You can *) (* obtain one at https://mozilla.org/MPL/2.0/. *) -(* Stage 8 compiler. *) +(* Stage 9 compiler. *) (* - Procedure calls in expressions. *) (* - Comments between (* and *) are supported. These are still single line *) (* comments and they should be on a separate line. *) +(* - if-else statements. *) const symbol_builtin_name_int := "Int"; symbol_builtin_name_word := "Word"; @@ -45,6 +46,7 @@ var compiler_strings_position: Pointer := @compiler_strings; compiler_strings_length: Word := 0; + label_counter: Word := 0; source_code_position: Pointer := @source_code; (* Calculates and returns the string token length between quotes, including the *) @@ -93,16 +95,12 @@ begin beq t1, t2, .add_string_end - la t2, compiler_strings_position - lw t3, (t2) - sb t1, (t3) - - addi t3, t3, 1 - sw t3, (t2) - - addi t0, t0, 1 - sw t0, 0(sp) + v8 := _load_byte(v0); + _store_byte(v8, compiler_strings_position); + _store_word(compiler_strings_position + 1, @compiler_strings_position); + v0 := v0 + 1; + lb t1, 8(sp) li t2, '\\' bne t1, t2, .add_string_increment @@ -127,13 +125,7 @@ end; (* Returns the amount of bytes written in a0. *) proc _read_file(); begin - mv a2, a1 - mv a1, a0 - (* STDIN. *) - li a0, 0 - (* SYS_READ. *) - li a7, 63 - ecall + _syscall(0, v88, v84, 0, 0, 0, 63); end; (* Writes to the standard output. *) @@ -143,13 +135,7 @@ end; (* a1 - Buffer length. *) proc _write_s(); begin - mv a2, a1 - mv a1, a0 - (* STDOUT. *) - li a0, 1 - (* SYS_WRITE. *) - li a7, 64 - ecall + _syscall(1, v88, v84, 0, 0, 0, 64); end; (* Writes a number to a string buffer. *) @@ -317,9 +303,8 @@ begin li t1, '.' beq t0, t1, .read_token_next - lw a0, 0(sp) - lb a0, (a0) - _is_alnum(); + v8 := _load_byte(v0); + _is_alnum(v8); bnez a0, .read_token_next goto .read_token_end; @@ -464,10 +449,8 @@ begin _advance_token(1); .compile_character_literal_end: - la t0, source_code_position - lw t0, (t0) - lb a0, (t0) - _write_c(); + v0 := _load_byte(source_code_position); + _write_c(v0); _write_c('\''); _write_c('\n'); @@ -523,10 +506,8 @@ end; proc _compile_term(); begin - la t0, source_code_position - lw t0, (t0) - lb a0, (t0) - sw a0, 0(sp) + v0 := _load_byte(source_code_position); + lb a0, 0(sp) li t1, '\'' beq a0, t1, .compile_term_character_literal @@ -925,13 +906,72 @@ begin _write_z("mv a0, t0\n\0"); end; +(* Writes a label, .Ln, where n is a unique number. *) + +(* Parameters: *) +(* a0 - Label counter. *) +proc _write_label(); +begin + _write_z(".L\0"); + _write_i(v88); +end; + +proc _compile_if(); +begin + (* Skip "if ". *) + _advance_token(3); + (* Compile condition. *) + _compile_expression(); + (* Skip " then" with newline. *) + _advance_token(6); + + (* v0 is the label after the if statement. *) + v0 := label_counter; + _store_word(label_counter + 1, @label_counter); + (* v4 is the label in front of the next elsif condition or end. *) + v4 := label_counter; + _store_word(label_counter + 1, @label_counter); + + _write_z("\tbeqz t0, \0"); + _write_label(v4); + _write_c('\n'); + + _compile_procedure_body(); + + _write_z("\tj \0"); + _write_label(v0); + _write_c('\n'); + + _write_label(v4); + _write_z(":\n\0"); + + _memcmp(source_code_position, "end", 3); + beqz a0, .compile_if_end + + _memcmp(source_code_position, "else", 3); + beqz a0, .compile_if_else + +.compile_if_else: + (* Skip "else" and newline. *) + _advance_token(5); + _compile_procedure_body(); + +.compile_if_end: + (* Skip "end". *) + _advance_token(3); + + _write_label(v0); + _write_z(":\n\0"); +end; + proc _compile_statement(); begin + _skip_spaces(); (* This is a call if the statement starts with an underscore. *) la t0, source_code_position lw t0, (t0) (* First character after alignment tab. *) - addi t0, t0, 1 + (* addi t0, t0, 1 *) lb t0, (t0) li t1, '_' @@ -943,33 +983,42 @@ begin li t1, 'v' beq t0, t1, .compile_statement_assignment + li t1, 'i' + beq t0, t1, .compile_statement_if + (* keyword_ret contains "\tret", so it's 4 bytes long. *) - _memcmp(source_code_position, "\treturn", 7); + _memcmp(source_code_position, "return", 6); beqz a0, .compile_statement_return _compile_line(); goto .compile_statement_end; .compile_statement_call: - _advance_token(1); + (* _advance_token(1); *) _compile_call(); goto .compile_statement_semicolon; .compile_statement_goto: - _advance_token(1); + (* _advance_token(1); *) _compile_goto(); goto .compile_statement_semicolon; .compile_statement_assignment: - _advance_token(1); + (* _advance_token(1); *) _compile_assignment(); goto .compile_statement_semicolon; +.compile_statement_if: + (* _advance_token(1); *) + _compile_if(); + + goto .compile_statement_semicolon; + .compile_statement_return: - _advance_token(1); + (* _advance_token(1); *) _compile_return_statement(); _write_c('\n'); @@ -986,10 +1035,12 @@ proc _compile_procedure_body(); begin .compile_procedure_body_loop: _skip_empty_lines(); + _skip_spaces(); - (* 3 is "end" length. *) _memcmp(source_code_position, "end", 3); + beqz a0, .compile_procedure_body_epilogue + _memcmp(source_code_position, "else", 4); beqz a0, .compile_procedure_body_epilogue _compile_statement(); @@ -1065,24 +1116,24 @@ begin _advance_token(5); end; -proc _skip_newlines(); +proc _skip_spaces(); begin (* Skip newlines. *) la t0, source_code_position lw t1, (t0) -.skip_newlines_loop: +.skip_spaces_loop: lb t2, (t1) - li t3, '\n' - bne t2, t3, .skip_newlines_end - beqz t2, .skip_newlines_end + li t3, '\t' + bne t2, t3, .skip_spaces_end + beqz t2, .skip_spaces_end addi t1, t1, 1 sw t1, (t0) - goto .skip_newlines_loop; + goto .skip_spaces_loop; -.skip_newlines_end: +.skip_spaces_end: end; (* Prints and skips a line. *) @@ -1121,9 +1172,6 @@ begin lw t2, 0(sp) lb t0, (t2) - li t1, '#' - beq t0, t1, .skip_empty_lines_comment - li t1, '\n' beq t0, t1, .skip_empty_lines_newline @@ -1175,10 +1223,8 @@ begin li t1, '@' beq t0, t1, .compile_global_initializer_pointer - la a0, source_code_position - lw a0, (a0) - lb a0, (a0) - _is_digit(); + v0 := _load_byte(source_code_position); + _is_digit(v0); bnez a0, .compile_global_initializer_number unimp @@ -1373,7 +1419,13 @@ begin _skip_empty_lines(); _compile_var_part(); - _write_z(".section .text\n\0"); + _write_z(".section .text\n\n\0"); + _write_z(".type _syscall, @function\n_syscall:\n\tmv a7, a6\n\tecall\n\tret\n\n\0"); + _write_z(".type _load_byte, @function\n_load_byte:\n\tlb a0, (a0)\nret\n\n\0"); + _write_z(".type _load_word, @function\n_load_word:\n\tlw a0, (a0)\nret\n\n\0"); + _write_z(".type _store_byte, @function\n_store_byte:\n\tsb a0, (a1)\nret\n\n\0"); + _write_z(".type _store_word, @function\n_store_word:\n\tsw a0, (a1)\nret\n\n\0"); + .compile_module_loop: _skip_empty_lines(); @@ -1413,10 +1465,9 @@ begin lw t1, 4(sp) bge t0, t1, .compile_end - lb a0, (t0) - addi t0, t0, 1 - sw t0, 0(sp) - _write_c(); + v8 := _load_byte(v0); + v0 := v0 + 1; + _write_c(v8); j .compile_loop @@ -1431,8 +1482,7 @@ end; (* a0 - Status code. *) proc _exit(); begin - li a7, 93 # SYS_EXIT - ecall + _syscall(0, 0, 0, 0, 0, 0, 93); end; (* Inserts a symbol into the table. *) @@ -1554,7 +1604,7 @@ begin sw t1, (t0) end; -proc _initialize_classification(); +proc _create_classification(); begin _assign_at(@classification, 1, 15); _assign_at(@classification, 2, 1); @@ -1688,13 +1738,13 @@ begin v0 := 129; (* Set the remaining 129 - 256 bytes to transitionClassOther. *) -.initialize_classification_loop: +.create_classification_loop: _assign_at(@classification, v0, 22); v0 := v0 + 1; lw t0, 0(sp) li t1, 257 - blt t0, t1, .initialize_classification_loop + blt t0, t1, .create_classification_loop end; (* Parameters: *) @@ -1772,7 +1822,7 @@ end; (* - The next byte is the action that should be performed when transitioning. *) (* For the meaning of actions see labels in the lex_next function, which *) (* handles each action. *) -proc _initialize_transitions(); +proc _create_transitions(); begin (* Start state. *) _set_transition(1, 1, 1, 16); @@ -1896,8 +1946,7 @@ end; (* Gets pointer to the current source text. *) proc _lexer_get_current(); begin - _lexer_get_state(); - sw a0, 0(sp) + v0 := _lexer_get_state(); return v0 + 4 end; @@ -1925,8 +1974,8 @@ end; (* One time lexer initialization. *) proc _lexer_initialize(); begin - _initialize_classification(); - _initialize_transitions(); + _create_classification(); + _create_transitions(); end; (* Entry point. *) |
