diff options
author | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2023-08-18 07:15:53 +0200 |
---|---|---|
committer | Lizzy Fleckenstein <eliasfleckenstein@web.de> | 2023-08-18 07:15:53 +0200 |
commit | 2cd7a3882112436b775cc75c665a5b4247de9cd1 (patch) | |
tree | 50713445111d36cd8ccfb027996c9be11997e212 | |
parent | bccf5985e0f2cef74ff225d1bf42fe1e19a7efe6 (diff) | |
download | paradox-2cd7a3882112436b775cc75c665a5b4247de9cd1.tar.xz |
add bootstrap.lua
-rw-r--r-- | .gitignore | 6 | ||||
-rwxr-xr-x | bootstrap.lua | 345 |
2 files changed, 351 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..49fbbc0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +* +!bootstrap.lua +!README.md +!paradox.false +!.gitignore +!run.sh diff --git a/bootstrap.lua b/bootstrap.lua new file mode 100755 index 0000000..4dac57f --- /dev/null +++ b/bootstrap.lua @@ -0,0 +1,345 @@ +#!/usr/bin/env lua + +local macros = { + ["$"] = [[ +mov rax, [r12] +sub r12, 8 +mov [r12], rax +]], + ["%"] = [[ +add r12, 8 +]], + ["\\"] = [[ +mov rax, [r12] +mov rbx, [r12+8] +mov [r12], rbx +mov [r12+8], rax +]], + ["@"] = [[ +mov rax, [r12] +mov rbx, [r12+8] +mov rcx, [r12+16] +mov [r12], rcx +mov [r12+8], rax +mov [r12+16], rbx +]], + ["O"] = [[ +mov rax, [r12] +lea rax, [r12+8*rax] +mov rax, [rax+8] +mov [r12], rax +]], + ["+"] = [[ +mov eax, [r12] +add r12, 8 +add [r12], eax +]], + ["-"] = [[ +mov eax, [r12] +add r12, 8 +sub [r12], eax +]], + ["*"] = [[ +mov eax, [r12+8] +imul dword[r12] +add r12, 8 +mov [r12], eax +]], + ["/"] = [[ +xor edx, edx +mov eax, [r12+8] +idiv dword[r12] +add r12, 8 +mov [r12], eax +]], + ["_"] = [[ +neg dword[r12] +]], + ["&"] = [[ +mov eax, [r12] +and eax, [r12+8] +add r12, 8 +mov [r12], eax +]], + ["|"] = [[ +mov eax, [r12] +or eax, [r12+8] +add r12, 8 +mov [r12], eax +]], + ["~"] = [[ +not dword[r12] +]], + [">"] = [[ +mov ebx, 0 +mov ecx, -1 +add r12, 8 +mov eax, [r12] +cmp eax, [r12-8] +cmovg ebx, ecx +mov [r12], ebx +]], + ["="] = [[ +mov ebx, 0 +mov ecx, -1 +add r12, 8 +mov eax, [r12] +cmp eax, [r12-8] +cmove ebx, ecx +mov [r12], ebx +]], + ["!"] = [[ +add r12, 8 +call [r12-8] +]], + ["?"] = [[ +call conditional +]], + ["#"] = [[ +call loop +]], + [":"] = [[ +add r12, 16 +mov rax, [r12-16] +mov rbx, [r12-8] +mov [rax], rbx +]], + [";"] = [[ +mov rax, [r12] +mov rax, [rax] +mov [r12], rax +]], + [","] = [[ +mov rax, 1 +mov rdi, 1 +mov rsi, r12 +mov rdx, 1 +syscall +add r12, 8 +]], + ["^"] = [[ +sub r12, 8 +mov qword[r12], 0 +mov rax, 0 +mov rdi, 0 +mov rsi, r12 +mov rdx, 1 +syscall +mov ebx, [r12] +mov ecx, -1 +cmp rax, 0 +cmove ebx, ecx +mov [r12], ebx +]], + ["."] = [[ +call print_num +]], + ["B"] = "", +} + +local fn_counter = 0 +local str_counter = 0 +local current_int + +local line_number = 1 +local line_position = 0 + +local c + +local function read_char() + local char = io.read(1) + + if char == "\n" then + line_number = line_number + 1 + line_position = 0 + else + line_position = line_position + 1 + end + + return char +end + +local function syntax_error(msg) + error("FALSE syntax error at "..line_number..":"..line_position..": " .. msg) +end + +local function compile_fn() + local fn_id = fn_counter + fn_counter = fn_counter + 1 + + print("fun_" .. fn_id .. ":") + + local strings = "" + + c = nil + + while true do + if not c then + c = read_char() + end + + if c and c:match("%d") then + current_int = current_int or 0 + current_int = current_int * 10 + tonumber(c) + c = nil + elseif current_int then + print("sub r12, 8") + print("mov qword[r12], " .. current_int) + current_int = nil + elseif c and c:match("[a-z]") then + print("sub r12, 8") + print("mov qword[r12], var_" .. c) + c = nil + elseif c == "'" then + local x = read_char() + if not x then + syntax_error("unterminated char literal") + end + print("sub r12, 8") + print("mov qword[r12], " .. x:byte(1)) + c = nil + elseif c == "\"" then + local str = {} + while true do + local x = read_char() + if not x then + syntax_error("unterminated string literal") + end + if x == "\"" then + break + end + table.insert(str, x:byte(1)) + end + print("mov rax, 1") + print("mov rdi, 1") + print("mov rsi, str_" .. str_counter) + print("mov rdx, " .. #str) + print("syscall") + strings = "str_" .. str_counter .. ": db " .. table.concat(str, ",") .. "\n" .. strings + str_counter = str_counter + 1 + c = nil + elseif c == "[" then + local lambda = fn_counter + print("jmp end_" .. lambda) + compile_fn() + if c ~= "]" then + syntax_error("unterminated lambda") + end + print("sub r12, 8") + print("mov qword[r12], fun_" .. lambda) + c = nil + elseif c and c:match("%s") then + c = nil + elseif not c or c == "]" then + break + elseif c and c:byte(1) == 195 then + c = read_char() + + if c and c:byte(1) == 184 then + c = "O" + elseif c and c:byte(1) == 159 then + c = "B" + else + syntax_error("unknown UTF-8 character") + end + elseif c and c:byte(1) == 248 then + c = "O" + elseif c and c:byte(1) == 223 then + c = "B" + elseif c == "{" then + while read_char() ~= "}" do end + c = nil + elseif c and macros[c] then + io.write(macros[c]) + c = nil + else + syntax_error("unknown character: " .. c) + end + end + + print("ret") + + io.write(strings) + print("end_" .. fn_id .. ":") +end + +print("section .text") + +compile_fn() + +io.write([[ +conditional: +add r12, 16 +mov eax, [r12-8] +cmp eax, 0 +je .return +call [r12-16] +.return: +ret +loop: +add r12, 16 +sub rsp, 16 +mov rax, [r12-8] +mov [rsp], rax +mov rax, [r12-16] +mov [rsp+8], rax +.loop: +call [rsp] +add r12, 8 +mov eax, [r12-8] +cmp eax, 0 +je .return +call [rsp+8] +jmp .loop +.return: +add rsp, 16 +ret +print_num: +mov rcx, rsp +sub rsp, 16 +mov eax, dword[r12] +add r12, 8 +mov ebx, eax +neg ebx +cmp eax, 0 +cmovl eax, ebx +mov edi, 10 +.loop: +dec rcx +xor edx, edx +idiv edi +add dl, '0' +mov byte[rcx], dl +cmp eax, 0 +jne .loop +cmp ebx, 0 +jle .print +dec rcx +mov byte[rcx], '-' +.print: +mov rax, 1 +mov rdi, 1 +mov rsi, rcx +lea rdx, [rsp+16] +sub rdx, rcx +syscall +add rsp, 16 +ret +]]) + +io.write([[ +global _start +_start: +lea r12, [1000000+8*"$."] +call fun_0 +mov rax, 60 +mov rdi, 0 +syscall +section .bss +stack: resq 1000000 +]]) + +print("section .data") +for x = ("a"):byte(1), ("z"):byte(1) do + print("var_" .. string.char(x) .. ": dq 0") +end |