diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..76bf544 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "*.embeddedhtml": "html", + "*.spk": "code-text-binary", + "*.mem": "code-text-binary", + "stdio.h": "c" + } +} \ No newline at end of file diff --git a/a.out b/a.out index dd7131b..193e800 100644 Binary files a/a.out and b/a.out differ diff --git a/generators/generator.py b/generators/generator.py index 7e01c80..b3e5a96 100644 --- a/generators/generator.py +++ b/generators/generator.py @@ -10,6 +10,7 @@ class Generator: self.output_path = output_path self.variables = {} self.constants = {} + self.labels = [] self.constants_reverse = {} self.constant_counter = 0 diff --git a/generators/x86_64.py b/generators/x86_64.py index e611649..1316760 100644 --- a/generators/x86_64.py +++ b/generators/x86_64.py @@ -8,7 +8,7 @@ class X86_64Generator(Generator): self.stack_size = 0 def init(self): - self.lines.append("global _start\n\n") + self.lines.append("global _start\n") self.lines.append("_start:\n\t") # generate code @@ -105,7 +105,6 @@ class X86_64Generator(Generator): def change_variable(self, var_name: str, new_value): var_pos = self.get_var_pos(var_name) - print(self.variables[var_name]["type"]) if type(new_value) == IntNode: # we're changing a variable to a number self.lines.append(f"mov QWORD [rsp + {var_pos}], {new_value.value}\n\t") self.variables[var_name]["type"] = IntNode @@ -135,7 +134,10 @@ class X86_64Generator(Generator): elif type(new_value) == str: # we're changing a variable to the value of a register self.lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t") self.variables[var_name]["type"] = IntNode - print(self.variables[var_name]["type"]) + + def generate_LabelDecNode(self, node: LabelDecNode): + self.labels.append(node.name) + self.lines.append("." + node.name + ":\n\t") def generate_InstructionNode(self, node: InstructionNode): ### MISC ### @@ -409,6 +411,15 @@ class X86_64Generator(Generator): self.lines.append("mov rdi, 1\n\t") # a file descriptor of 1 is stdout self.lines.append("syscall\n\t") + elif node.instruction == "jump": + if len(node.arguments) < 1: # example: "jump" + traceback(self.code, "TypeError", "jump expects atleast 1 argument.") + elif len(node.arguments) > 1: # example: "jump %label 123" + traceback(self.code, "TypeError", "jump expects at most 1 argument.") + elif not isinstance(node.arguments[0], LabelRefNode): + traceback(self.code, "TypeError", f"jump expects a label reference as the first argument, not \"{node.arguments[0]}\"") + + self.lines.append(f"jmp .{node.arguments[0].name}\n\t") else: self.lines.append("; FUCK\n\t") #raise NotImplementedError(f"A generate method hasn't been made for the \"{node.instruction}\" instruction.") @@ -431,5 +442,5 @@ class X86_64Generator(Generator): elif value_type == float or value_type == int: f.write(f"dq {float(value)}") f.write("\n") - f.write("\nsection .text\n") + f.write("section .text\n") f.writelines(self.lines) \ No newline at end of file diff --git a/ground_ast.py b/ground_ast.py index ba360a8..8365373 100644 --- a/ground_ast.py +++ b/ground_ast.py @@ -3,6 +3,7 @@ from dataclasses import dataclass from tokenizer import Token, TokenType from typing import Optional, Any from error import traceback +from console import console @dataclass @@ -100,8 +101,8 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode: # todo: this is the absolute WORST way i could do this, but i could not care less lmao # its not even performant...... for token in tokens: - #print(token.type) if token.type == TokenType.INSTRUCTION: + if current_node: scope.statements.append(current_node) @@ -125,6 +126,11 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode: else: current_node = FunctionNode([], [], scope) current_node_type = "func" + elif token.type == TokenType.LABEL_DECLERATION: + if current_node: + scope.statements.append(current_node) + current_node = None + scope.statements.append(LabelDecNode(token.value)) if current_node: if token.type == TokenType.STRING: @@ -199,9 +205,6 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode: current_node.arguments.append(FunctionCallNode(token.value)) else: traceback(code, "SyntaxError", "Expected instruction or function return type, got function reference.") - - elif token.type == TokenType.LABEL_DECLERATION: - scope.statements.append(LabelDecNode(token.value)) elif token.type == TokenType.COMMENT: continue diff --git a/out b/out index 40d3a2b..e04ac58 100644 Binary files a/out and b/out differ diff --git a/out.asm b/out.asm index edd111a..ddd38ec 100644 --- a/out.asm +++ b/out.asm @@ -1,38 +1,11 @@ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ section .data -.LC0: db "hiii", 0 -.LC1: equ $ - .LC0 -.LC2: db "", 10, 0 -.LC3: equ $ - .LC2 - section .text global _start - _start: - ; InstructionNode(instruction='set', parent=RootNode(statements=[..., InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='stdout', parent=..., arguments=[String]), InstructionNode(instruction='end', parent=..., arguments=[Int])]), arguments=[VariablePointer, Int]) - mov rax, 123 - push rax - ; InstructionNode(instruction='set', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), ..., InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='stdout', parent=..., arguments=[String]), InstructionNode(instruction='end', parent=..., arguments=[Int])]), arguments=[VariablePointer, String]) - mov QWORD [rsp + 0], 0 - lea rax, [.LC0] - push rax - mov rax, .LC1 - push rax - ; InstructionNode(instruction='stdout', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), ..., InstructionNode(instruction='stdout', parent=..., arguments=[String]), InstructionNode(instruction='end', parent=..., arguments=[Int])]), arguments=[VariableReference]) - mov rsi, [rsp + 8] - mov rdx, [rsp + 0] - mov rax, 1 - mov rdi, 1 - syscall - ; InstructionNode(instruction='stdout', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), ..., InstructionNode(instruction='end', parent=..., arguments=[Int])]), arguments=[String]) - mov rsi, .LC2 - mov rdx, .LC3 - mov rax, 1 - mov rdi, 1 - syscall - ; InstructionNode(instruction='end', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='stdout', parent=..., arguments=[String]), ...]), arguments=[Int]) - mov rax, 60 - mov rdi, 0 - syscall + ; LabelDecleration + .myLabel: + ; InstructionNode(instruction='jump', parent=RootNode(statements=[LabelDecleration, ...]), arguments=[LabelReference]) + jmp .myLabel \ No newline at end of file diff --git a/test b/test new file mode 100644 index 0000000..3cd4628 Binary files /dev/null and b/test differ diff --git a/test.c b/test.c new file mode 100644 index 0000000..23704de --- /dev/null +++ b/test.c @@ -0,0 +1,5 @@ +#include +int main() { + printf("Hello, World!\n"); + return 0; +} \ No newline at end of file diff --git a/test.o b/test.o new file mode 100644 index 0000000..19dab46 Binary files /dev/null and b/test.o differ diff --git a/test.s b/test.s new file mode 100644 index 0000000..079e309 --- /dev/null +++ b/test.s @@ -0,0 +1,45 @@ + .file "test.c" + .text + .section .rodata +.LC0: + .string "Hello, World!" + .text + .globl main + .type main, @function +main: +.LFB0: + .cfi_startproc + endbr64 + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + leaq .LC0(%rip), %rax + movq %rax, %rdi + call puts@PLT + movl $0, %eax + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size main, .-main + .ident "GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0" + .section .note.GNU-stack,"",@progbits + .section .note.gnu.property,"a" + .align 8 + .long 1f - 0f + .long 4f - 1f + .long 5 +0: + .string "GNU" +1: + .align 8 + .long 0xc0000002 + .long 3f - 2f +2: + .long 0x3 +3: + .align 8 +4: diff --git a/test2.grnd b/test2.grnd index 8163406..9f706fb 100644 --- a/test2.grnd +++ b/test2.grnd @@ -1,5 +1,2 @@ -set &x 123 -set &x "hiii" -stdout $x -stdout "\n" -end 0 \ No newline at end of file +@myLabel +jump %myLabel \ No newline at end of file