From 59bef834c4bb9493a6c6d6fab3c36c957a99c557 Mon Sep 17 00:00:00 2001 From: SpookyDervish <78246495+SpookyDervish@users.noreply.github.com> Date: Wed, 10 Sep 2025 07:30:58 +1000 Subject: [PATCH] VERY basic functions implementation --- a.out | Bin 15776 -> 0 bytes generators/generator.py | 2 +- generators/x86_64.py | 241 ++++++++++++++++++++++------------------ ground_ast.py | 2 +- out | Bin 4712 -> 8928 bytes out.asm | 23 ++-- test.c | 7 -- test.s | 47 -------- test2.grnd | 17 +-- 9 files changed, 162 insertions(+), 177 deletions(-) delete mode 100644 a.out delete mode 100644 test.c delete mode 100644 test.s diff --git a/a.out b/a.out deleted file mode 100644 index 43fbe8b854ae40c2f609c3057062b333dfa29e82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15776 zcmeHOYit}>6~4QU6SqnHN<&N%nh`V*(|Y2!(t^o4_Bw0iJet_N)G&;_V|%52xVy8| zu1HBRltv+_R22vbq^d%Igg_u6fdqoBTv8PQBEJa#!lP0U(71x41%iij=ALgo9<7N~ zkoYs#+WGGJ?)mP$bMD>QJDxiqPfm=*V=;x)px&d{O0;SwAq5{9lng;a9Z@^!_!hNa zZ6$k)&*}1n1}fF*dVC``3Ex1-x(?3N!Tp-17IZ=n8CkbkT5Z%NKqcqFI=@J4@IXfz z0D`ZzXGn`7d{Jm%P{*-Z?a~gbLmSbMxEvCMj!o7nQ~T3!=p@5t`tY1OesW4tH5KM0j4FOX z+o+Gr?vZl#?;QBh4}Nz3n{8M3u1tNpaQ7qC+^zxk;eNA*eK>J_m?CU*p4(&}9gmBY zletZJ&G|*nCpI~-uDwp#2ysRo-r9uEZ^G{){;hTDQIpF4-WB#8WsTkSZU(A>C-ppMbb)J9BefM*pr!dFqil-C4$N2sjZJMvj z_Z$2Tsjw-b%fZ9GepK^3hCC)nHv)Wc+;0YW%rVxi26&!7NYwz(^Ce1A1fmE;5r`rX zMIeem6oDuLQ3N;we`&e*AF1U(HKi^${`#;|sZUkhxcAG{@{3I?et^7z=ZW?Xeua)L z2NJ%&ckoAK&9)pE)%u=4k6*g>;nbzyrj~!ddU`V1Q|Wm*b!F(MRDrj7ntGwy zkcwSRU0ZYSp$ZO41x?-!-7o0*{4NY}u`1s`m0BK(b2fG96?aGK^3YZ?ZgzT}cQZ|g ztBwDnyYARI($?B%{U08qLe5N)?xkdv`}b1vHp3sAmXp=ka`JZU;`!U^H?KFAZ(UAS z&#kP-wH8Tsk5UwYC<0Lgq6kD0h$0Y0Ac{Z~fhYn|1fmE;5%~W^fS-TG_BFig5H-)w zkM^&6-Xnw$5b_=Sy9wzwUmbkS^S(sL&oDW~9zUaEi>@d2`e*$(NW&7##ed2whxpl0$h*A`RC<0Lgq6kD0h$0Y0Ac{Z~fhYn|1fmGkjR5v5Vt*p` z9%9et4ya`R;!d$YAp0EOEH?H*?h_mLVtd8Len`H5rxnT8>FNGboP26c zY=09j`O=eN|9lWfx=r=%RXLx(i;aFs_5VA-{_y{@M(j&HJ~Hx7*o3x=0EtaQKnx1 zH#@Iy`SrA`ih&x|v0gnt^!;hJhsOISzN}4cG1m2*yH1~&dXvKU0Hv=|rr!SV?Gz9L zP5~VB`8`S{0wiVML42#)Q;R1`P2$_*Eeh8Q@crT+u4mY{l5@;c z%gWGF(05hFaDi!z4QO)M1`Lqp8FH_ z|19wa!~y&|@wlc2XthFodz`Lfp?Ry$&J^7qvp_r9?dgo=+H;DCl3SjgHD}cNu6N7L zSu?!vy+oerf;E>dOxsy2?G}n9%PudfnL=(M>$pzZ?5^*@JMJ@*wQlpP3VyWc z#hubp&b6lr-J-^MrfeP%3jFs}JT}fikYMNJpLz5?{Jt30 z7gFr|BG33X`tTY6`pw>pVqZ@9-Pe{<{MuVkAAUcI|GynfxE_Jy-<_Zyzk5Ifj)GzR z`-%S>ts&5Vteb#nAM2)Y|83IqnhAQWtAI~SyWB^PGxS&wWr*XSYUr^}1M=@-FmWBh z^e7p;MuHyeA|TeA=s)~`PmrG1T(Gh30(MJd;r^o!S17|Vg&ylbU_~6!e)#;qK;?W+ zD6d_&<@$~FuTv$fO|p%1|91A zPDqd6bs+8!;2)m9-xGap&0&bAVAvlv@W-OZ_+gy`>U=z&!#3hHZuZmmH(r~x|IYm{LQ?PLAaD*CX$ zoDSrwfe7Zry~aa-e~r-@=!1x{54t9#!jyE3zsEdB(H~s@_aZFH=se|SK9?YM*f-x6e|h5!Hn diff --git a/generators/generator.py b/generators/generator.py index e42d218..ffe3497 100644 --- a/generators/generator.py +++ b/generators/generator.py @@ -37,7 +37,7 @@ class Generator: node_type = str(type(node))[19:-2] if not hasattr(self, f"generate_{node_type}"): raise NotImplementedError(f"Generator has no generate method for {node_type}.") - getattr(self, f"generate_{node_type}")(node) + getattr(self, f"generate_{node_type}")(node, self.lines) def generate(self): for statement in self.ast.statements: diff --git a/generators/x86_64.py b/generators/x86_64.py index b587227..9a26988 100644 --- a/generators/x86_64.py +++ b/generators/x86_64.py @@ -7,6 +7,7 @@ class X86_64Generator(Generator): def __init__(self, ast, code, output_path): super().__init__(ast, code, output_path) self.stack_size = 0 + self.function_lines = [] def init(self): self.lines.append("global _start\n") @@ -16,15 +17,15 @@ class X86_64Generator(Generator): self.generate() self.write() - def push(self, reg: str): - self.lines.append("push " + reg + "\n\t") + def push(self, reg: str, lines): + lines.append("push " + reg + "\n\t") self.stack_size += 1 - def pop(self, reg: str): - self.lines.append("pop " + reg + "\n\t") + def pop(self, reg: str, lines): + lines.append("pop " + reg + "\n\t") self.stack_size -= 1 - def get_variable(self, var_name: str, reg: str, float: bool = False, offset: int = 0, no_stack_pop: bool = True): + def get_variable(self, lines, var_name: str, reg: str, float: bool = False, offset: int = 0, no_stack_pop: bool = True): var = self.variables.get(var_name, None) var_pos = self.get_var_pos(var_name) try: @@ -37,25 +38,27 @@ class X86_64Generator(Generator): # ... } - self.lines.append(f"movsd {conversion[reg]}, [rsp + {var_pos + offset}]\n\t") - self.lines.append("add rsp, 8\n\t") + lines.append(f"movsd {conversion[reg]}, [rsp + {var_pos + offset}]\n\t") + lines.append("add rsp, 8\n\t") self.stack_size += 1 elif var["type"] in [IntNode,StringNode]: if no_stack_pop: - self.lines.append(f"mov {reg}, [rsp + {var_pos + offset}]\n\t") + lines.append(f"mov {reg}, [rsp + {var_pos + offset}]\n\t") else: self.push( - f"QWORD [rsp + {var_pos + offset}]" + f"QWORD [rsp + {var_pos + offset}]", + lines ) - self.pop(reg) + self.pop(reg, lines) elif var["type"] == BoolNode: if no_stack_pop: - self.lines.append(f"mov {reg}, [rsp + {var_pos + offset}]\n\t") + lines.append(f"mov {reg}, [rsp + {var_pos + offset}]\n\t") else: self.push( - f"QWORD [rsp + {var_pos + offset}]" + f"QWORD [rsp + {var_pos + offset}]", + lines ) - self.pop(reg) + self.pop(reg, lines) except TypeError: # variable doesnt exist traceback(self.code, "NameError", f"\"{var_name}\" is not defined.") @@ -68,28 +71,28 @@ class X86_64Generator(Generator): except TypeError: # not defined traceback(self.code, "TypeError", f"\"{var_name}\" is not defined.") - def create_variable(self, var_name: str, starting_value, var_type: Any = None): + def create_variable(self, lines, var_name: str, starting_value, var_type: Any = None): if var_type == None: var_type = type(starting_value) stack_location = self.stack_size if type(starting_value) == IntNode: - self.lines.append(f"mov rax, {starting_value.value}\n\t") - self.push("rax") + lines.append(f"mov rax, {starting_value.value}\n\t") + self.push("rax", lines) elif type(starting_value) == VarRefNode: - var_type = self.get_variable(starting_value.var_name, "rax") + var_type = self.get_variable(lines, starting_value.var_name, "rax") if var_type == FloatNode: - self.lines.append("sub rsp, 8\n\t") - self.lines.append("movsd [rsp], xmm0\n\t") + lines.append("sub rsp, 8\n\t") + lines.append("movsd [rsp], xmm0\n\t") else: - self.push("rax") + self.push("rax", lines) elif type(starting_value) == FloatNode: name = self.add_constant(starting_value.value) - self.lines.append("sub rsp, 8\n\t") # make space on the stack - self.lines.append(f"movsd xmm0, {name}\n\t") - self.lines.append("movsd [rsp], xmm0\n\t") + lines.append("sub rsp, 8\n\t") # make space on the stack + lines.append(f"movsd xmm0, {name}\n\t") + lines.append("movsd [rsp], xmm0\n\t") self.stack_size += 1 elif type(starting_value) == StringNode: @@ -97,83 +100,96 @@ class X86_64Generator(Generator): starting_value.value ) string_len = self.add_constant(f"equ $ - {string_pointer[1:-1]}", no_string=True) - self.lines.append(f"lea rax, {string_pointer}\n\t") - self.push("rax") - self.lines.append(f"mov rax, {string_len[1:-1]}\n\t") - self.push("rax") + lines.append(f"lea rax, {string_pointer}\n\t") + self.push("rax", lines) + lines.append(f"mov rax, {string_len[1:-1]}\n\t") + self.push("rax", lines) elif type(starting_value) == BoolNode: - self.push("1" if starting_value.value else "0") + self.push("1" if starting_value.value else "0", lines) elif type(starting_value) == str: if starting_value.startswith("xmm"): # floating point stuff - self.lines.append("sub rsp, 8\n\t") # make space - self.lines.append(f"movsd [rsp], {starting_value}\n\t") + lines.append("sub rsp, 8\n\t") # make space + lines.append(f"movsd [rsp], {starting_value}\n\t") self.stack_size += 1 else: - self.push(starting_value) + self.push(starting_value, lines) self.variables[var_name] = {"stack_loc": stack_location, "type": var_type} - def change_variable(self, var_name: str, new_value): + def change_variable(self, lines, var_name: str, new_value): var_pos = self.get_var_pos(var_name) 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") + lines.append(f"mov QWORD [rsp + {var_pos}], {new_value.value}\n\t") self.variables[var_name]["type"] = IntNode elif type(new_value) == VarRefNode: # we're changing a variable to the value of another variable - var_type = self.get_variable(new_value.var_name, "rax") - self.lines.append(f"mov QWORD [rsp + {var_pos}], rax\n\t") + var_type = self.get_variable(lines, new_value.var_name, "rax") + lines.append(f"mov QWORD [rsp + {var_pos}], rax\n\t") self.variables[var_name]["type"] = var_type elif type(new_value) == StringNode: # we're changing a variable to a string - self.lines.append(f"mov QWORD [rsp + {var_pos}], 0\n\t") + lines.append(f"mov QWORD [rsp + {var_pos}], 0\n\t") string_pointer = self.add_constant(new_value.value) string_len = self.add_constant(f"equ $ - {string_pointer[1:-1]}", no_string=True) - #self.lines.append(f"lea QWORD [rsp + {var_pos}], {string_pointer}\n\t") - ##self.lines.append(f"mov QWORD [rsp + {var_pos + 8}], {string_len[1:-1]}\n\t") + #lines.append(f"lea QWORD [rsp + {var_pos}], {string_pointer}\n\t") + ##lines.append(f"mov QWORD [rsp + {var_pos + 8}], {string_len[1:-1]}\n\t") self.variables[var_name]["stack_loc"] = self.stack_size - self.lines.append(f"lea rax, {string_pointer}\n\t") - self.push("rax") - self.lines.append(f"mov rax, {string_len[1:-1]}\n\t") - self.push("rax") + lines.append(f"lea rax, {string_pointer}\n\t") + self.push("rax", lines) + lines.append(f"mov rax, {string_len[1:-1]}\n\t") + self.push("rax", lines) self.variables[var_name]["type"] = StringNode elif type(new_value) == BoolNode: - self.lines.append(f"mov QWORD [rsp + {var_pos}], {"1" if new_value.value else "0"}\n\t") + lines.append(f"mov QWORD [rsp + {var_pos}], {'1' if new_value.value else '0'}\n\t") self.variables[var_name]["type"] = BoolNode 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") + lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t") self.variables[var_name]["type"] = IntNode - def generate_LabelDecNode(self, node: LabelDecNode): + def generate_LabelDecNode(self, node: LabelDecNode, lines): self.labels.append(node.name) - self.lines.append("." + node.name + ":\n\t") + lines.append("." + node.name + ":\n\t") + + def generate_FunctionNode(self, node: FunctionNode, lines): + if node.return_type == None: + traceback(self.code, "SyntaxError", "Functions require a return type.") + if node.name == None: + traceback(self.code, "SyntaxError", "Functions require a name.") + + self.function_lines.append(node.name + ":") + for inst in node.statements: + self.generate_InstructionNode(inst, self.function_lines) + + def generate_InstructionNode(self, node: InstructionNode, lines = None): + if lines == None: + lines = self.lines - def generate_InstructionNode(self, node: InstructionNode): ### MISC ### if node.instruction == "end": self.clamp_instruction_args(node, 1, 1) if not type(node.arguments[0]) in [IntNode, VarRefNode]: # example: "end true" traceback(self.code, "TypeError", f"end expects an integer, not {node.arguments[0]}") - self.lines.append("mov rax, 60\n\t") + lines.append("mov rax, 60\n\t") if type(node.arguments[0]) in [IntNode,BoolNode]: - self.lines.append("mov rdi, " + str(node.arguments[0].value) + "\n\t") + lines.append("mov rdi, " + str(node.arguments[0].value) + "\n\t") elif isinstance(node.arguments[0], VarRefNode): - var_type = self.get_variable(node.arguments[0].var_name, "rdi", no_stack_pop=True) + var_type = self.get_variable(lines, node.arguments[0].var_name, "rdi", no_stack_pop=True) if var_type == FloatNode: - self.lines.append("cvttsd2si rdi, xmm0\n\t") + lines.append("cvttsd2si rdi, xmm0\n\t") else: if var_type not in [IntNode,BoolNode]: traceback(self.code, "TypeError", f"end expects an integer, not \"{var_type}\"") - #self.lines.append("mov rdi, " + str(self.get_variable(node.arguments[0].var_name)) + "\n\t") - self.lines.append("syscall\n\t") + #lines.append("mov rdi, " + str(self.get_variable(lines, node.arguments[0].var_name)) + "\n\t") + lines.append("syscall\n\t") ### VARIABLE INSTRUCTIONS ### elif node.instruction == "set": @@ -186,9 +202,9 @@ class X86_64Generator(Generator): variable_exists = self.variables.get(node.arguments[0].var_name, None) != None if not variable_exists: # create a new variable - self.create_variable(node.arguments[0].var_name, node.arguments[1]) + self.create_variable(lines, node.arguments[0].var_name, node.arguments[1]) else: # modify the existing one - self.change_variable(node.arguments[0].var_name, node.arguments[1]) + self.change_variable(lines, node.arguments[0].var_name, node.arguments[1]) ### MATH INSTRUCTIONS ### elif node.instruction in ["add", "subtract", "multiply"]: @@ -201,28 +217,28 @@ class X86_64Generator(Generator): number2_type = None arg2 = "rbx" if isinstance(node.arguments[0], VarRefNode): - number1_type = self.get_variable(node.arguments[0].var_name, "rax") + number1_type = self.get_variable(lines, node.arguments[0].var_name, "rax") elif isinstance(node.arguments[0], FloatNode) or isinstance(node.arguments[1], FloatNode): number1_type = FloatNode constant_name = self.add_constant(node.arguments[0].value) - self.lines.append(f"movsd xmm0, {constant_name}\n\t") + lines.append(f"movsd xmm0, {constant_name}\n\t") elif isinstance(node.arguments[0], IntNode): number1_type = IntNode #arg1 = node.arguments[0].value - self.lines.append(f"mov rax, {node.arguments[0].value}\n\t") + lines.append(f"mov rax, {node.arguments[0].value}\n\t") else: traceback(self.code, "TypeError", f"expected a variable reference or number for argument 1 of add, got {node.arguments[0]}") if isinstance(node.arguments[1], VarRefNode): - number2_type = self.get_variable(node.arguments[1].var_name, "rbx") + number2_type = self.get_variable(lines, node.arguments[1].var_name, "rbx") elif number1_type == FloatNode or isinstance(node.arguments[1], FloatNode): number2_type = FloatNode constant_name = self.add_constant(node.arguments[1].value) - self.lines.append(f"movsd xmm1, {constant_name}\n\t") + lines.append(f"movsd xmm1, {constant_name}\n\t") elif isinstance(node.arguments[1], IntNode): number2_type = IntNode arg2 = node.arguments[1].value - #self.lines.append(f"mov rbx, {node.arguments[1].value}\n\t") + #lines.append(f"mov rbx, {node.arguments[1].value}\n\t") else: traceback(self.code, "TypeError", f"expected a variable reference or number for argument 2 of add, got {node.arguments[1]}") @@ -232,26 +248,26 @@ class X86_64Generator(Generator): if number1_type == IntNode and number2_type == IntNode: if node.instruction == "add": - self.lines.append(f"add rax, {arg2}\n\t") + lines.append(f"add rax, {arg2}\n\t") elif node.instruction == "subtract": - self.lines.append(f"sub rax, {arg2}\n\t") + lines.append(f"sub rax, {arg2}\n\t") elif node.instruction == "multiply": - self.lines.append(f"imul rax, {arg2}\n\t") + lines.append(f"imul rax, {arg2}\n\t") else: if node.instruction == "add": - self.lines.append(f"addsd xmm0, xmm1\n\t") + lines.append(f"addsd xmm0, xmm1\n\t") elif node.instruction == "subtract": - self.lines.append(f"subsd xmm0, xmm1\n\t") + lines.append(f"subsd xmm0, xmm1\n\t") elif node.instruction == "multiply": - self.lines.append(f"mulsd xmm0, xmm1\n\t") + lines.append(f"mulsd xmm0, xmm1\n\t") is_integer = number1_type == IntNode and number2_type == IntNode starting_reg = "rax" if is_integer else "xmm0" if self.variables.get(node.arguments[2].var_name, None) == None: # we need to create a variable for the destination - self.create_variable(node.arguments[2].var_name, starting_reg, IntNode if is_integer else FloatNode) + self.create_variable(lines, node.arguments[2].var_name, starting_reg, IntNode if is_integer else FloatNode) else: - self.change_variable(node.arguments[2].var_name, starting_reg) + self.change_variable(lines, node.arguments[2].var_name, starting_reg) elif node.instruction == "divide": self.clamp_instruction_args(node, 3, 3) @@ -264,20 +280,20 @@ class X86_64Generator(Generator): number2_type = None if isinstance(node.arguments[0], VarRefNode): - number1_type = self.get_variable(node.arguments[0].var_name, "rax", True) + number1_type = self.get_variable(lines, node.arguments[0].var_name, "rax", True) elif type(node.arguments[0]) in [IntNode, FloatNode]: number1_type = FloatNode constant_name = self.add_constant(node.arguments[0].value) - self.lines.append(f"movsd xmm0, {constant_name}\n\t") + lines.append(f"movsd xmm0, {constant_name}\n\t") else: traceback(self.code, "TypeError", f"expected a variable reference or number for argument 1 of divide, got {node.arguments[0]}") if isinstance(node.arguments[1], VarRefNode): - number2_type = self.get_variable(node.arguments[1].var_name, "rbx", True) + number2_type = self.get_variable(lines, node.arguments[1].var_name, "rbx", True) elif type(node.arguments[1]) in [IntNode, FloatNode]: number2_type = FloatNode constant_name = self.add_constant(node.arguments[1].value) - self.lines.append(f"movsd xmm1, {constant_name}\n\t") + lines.append(f"movsd xmm1, {constant_name}\n\t") else: traceback(self.code, "TypeError", f"expected a variable reference or number for argument 2 of divide, got {node.arguments[1]}") @@ -285,12 +301,12 @@ class X86_64Generator(Generator): if number1_type not in [IntNode, FloatNode] or number2_type not in [IntNode, FloatNode]: traceback(self.code, "TypeError", f"Unsupported operation \"divide\" for \"{node.arguments[0]}\" and \"{node.arguments[1]}\".") - self.lines.append(f"divsd xmm0, xmm1\n\t") + lines.append(f"divsd xmm0, xmm1\n\t") if self.variables.get(node.arguments[2].var_name, None) == None: # we need to create a variable for the destination - self.create_variable(node.arguments[2].var_name, "xmm0", FloatNode) + self.create_variable(lines, node.arguments[2].var_name, "xmm0", FloatNode) else: - self.change_variable(node.arguments[2].var_name, "xmm0") + self.change_variable(lines, node.arguments[2].var_name, "xmm0") elif node.instruction == "stdout": self.clamp_instruction_args(node, 1, 1) @@ -300,27 +316,27 @@ class X86_64Generator(Generator): printed_value = arg.__str__() if isinstance(arg, VarRefNode): - var_type = self.get_variable(arg.var_name, "rsi", offset=0, no_stack_pop=True) + var_type = self.get_variable(lines, arg.var_name, "rsi", offset=0, no_stack_pop=True) if var_type == StringNode: - self.get_variable(arg.var_name, "rdx", offset=-8, no_stack_pop=True) + self.get_variable(lines, arg.var_name, "rdx", offset=-8, no_stack_pop=True) else: traceback(self.code, "TypeError", f"You can't print \"{var_type(None).__repr__()}\", try converting it to a string first.") else: string_pointer = self.add_constant(printed_value)[1:-1] string_len = self.add_constant(f"equ $ - {string_pointer}", True)[1:-1] - self.lines.append(f"mov rsi, {string_pointer}\n\t") - self.lines.append(f"mov rdx, {string_len}\n\t") # length + lines.append(f"mov rsi, {string_pointer}\n\t") + lines.append(f"mov rdx, {string_len}\n\t") # length - self.lines.append("mov rax, 1\n\t") # sys_write syscall - self.lines.append("mov rdi, 1\n\t") # a file descriptor of 1 is stdout - self.lines.append("syscall\n\t") + lines.append("mov rax, 1\n\t") # sys_write syscall + lines.append("mov rdi, 1\n\t") # a file descriptor of 1 is stdout + lines.append("syscall\n\t") elif node.instruction == "jump": self.clamp_instruction_args(node, 1, 1) if 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") + lines.append(f"jmp .{node.arguments[0].name}\n\t") elif node.instruction == "if": self.clamp_instruction_args(node, 2, 2) @@ -332,16 +348,16 @@ class X86_64Generator(Generator): if isinstance(node.arguments[0], BoolNode): if node.arguments[0].value: - self.lines.append(f"jmp .{node.arguments[1].name}\n\t") - #self.lines.append("mov eax, 1") - #self.lines.append(f"cmp eax, {1 if node.arguments[0].value else 0}") + lines.append(f"jmp .{node.arguments[1].name}\n\t") + #lines.append("mov eax, 1") + #lines.append(f"cmp eax, {1 if node.arguments[0].value else 0}") elif type(node.arguments[0]) in [IntNode,FloatNode]: if node.arguments[0].value != 0: - self.lines.append(f"jmp .{node.arguments[1].name}\n\t") + lines.append(f"jmp .{node.arguments[1].name}\n\t") elif isinstance(node.arguments[0], VarRefNode): - self.get_variable(node.arguments[0].var_name, "eax") - self.lines.append(f"test eax, eax\n\t") - self.lines.append(f"jnz .{node.arguments[1].name}\n\t") + self.get_variable(lines, node.arguments[0].var_name, "eax") + lines.append(f"test eax, eax\n\t") + lines.append(f"jnz .{node.arguments[1].name}\n\t") elif node.instruction in ["equal", "inequal", "greater", "lesser"]: self.clamp_instruction_args(node, 3, 3) @@ -356,34 +372,34 @@ class X86_64Generator(Generator): arg2 = None if isinstance(node.arguments[0], BoolNode): - self.lines.append(f"mov rax, {int(node.arguments[0].value)}\n\t") + lines.append(f"mov rax, {int(node.arguments[0].value)}\n\t") arg1 = "rax" elif isinstance(node.arguments[0], IntNode): - self.lines.append(f"mov rax, {node.arguments[0].value}\n\t") + lines.append(f"mov rax, {node.arguments[0].value}\n\t") arg1 = "rax" elif isinstance(node.arguments[0], FloatNode): const_name = self.add_constant(node.arguments[0].value) - self.lines.append(f"movsd xmm0, {const_name}\n\t") + lines.append(f"movsd xmm0, {const_name}\n\t") arg1 = "xmm0" elif isinstance(node.arguments[0], VarRefNode): - self.get_variable(node.arguments[0].var_name, "rax") + self.get_variable(lines, node.arguments[0].var_name, "rax") arg1 = "rax" if isinstance(node.arguments[1], BoolNode): - self.lines.append(f"mov rbx, {int(node.arguments[1].value)}\n\t") + lines.append(f"mov rbx, {int(node.arguments[1].value)}\n\t") arg2 = "rbx" elif isinstance(node.arguments[1], IntNode): - self.lines.append(f"mov rbx, {node.arguments[1].value}\n\t") + lines.append(f"mov rbx, {node.arguments[1].value}\n\t") arg2 = "rbx" elif isinstance(node.arguments[1], FloatNode): const_name = self.add_constant(node.arguments[1].value) - self.lines.append(f"movsd xmm1, {const_name}\n\t") + lines.append(f"movsd xmm1, {const_name}\n\t") arg2 = "xmm1" elif isinstance(node.arguments[1], VarRefNode): - self.get_variable(node.arguments[1].var_name, "rbx") + self.get_variable(lines, node.arguments[1].var_name, "rbx") arg2 = "rbx" - self.lines.append(f"cmp {arg1}, {arg2}\n\t") + lines.append(f"cmp {arg1}, {arg2}\n\t") instructions = { "equal": "sete", @@ -391,15 +407,26 @@ class X86_64Generator(Generator): "greater": "setg", "lesser": "setl" } - self.lines.append(f"{instructions[node.instruction]} al\n\t") - self.lines.append("movzx rax, al\n\t") + lines.append(f"{instructions[node.instruction]} al\n\t") + lines.append("movzx rax, al\n\t") var_name = node.arguments[2].var_name if self.variables.get(var_name, None) == None: - self.create_variable(var_name, "rax", BoolNode) + self.create_variable(lines, var_name, "rax", BoolNode) else: - self.change_variable(var_name, "rax") + self.change_variable(lines, var_name, "rax") + + elif node.instruction == "endfun": + return + elif node.instruction == "return": + lines.append("ret\n\t") + elif node.instruction == "call": + self.clamp_instruction_args(node, 1, 1) + if not isinstance(node.arguments[0], FunctionCallNode): + traceback(self.code, "TypeError", "Argument 1 of call needs to be a function reference.") + + lines.append(f"call {node.arguments[0].func_name}\n\t") else: raise NotImplementedError(f"A generate method hasn't been made for the \"{node.instruction}\" instruction.") @@ -419,7 +446,9 @@ class X86_64Generator(Generator): value_type = type(value) if value_type == str: if not const["no_string"]: - f.write(f"db \"{value.replace("\\n","\", 10, \"")}\", 0".replace(", \"\", ", ", ")) + final = f'db "' + value.replace("\\n", "\", 10, \"") + "\", 0" + final = final.replace(", \"\", ", ", ") + f.write(final) else: f.write(value) elif value_type == float or value_type == int: @@ -427,5 +456,5 @@ class X86_64Generator(Generator): f.write("\n") f.write("section .text\n") - optimizer = X86_64Optimizer(self.lines) + optimizer = X86_64Optimizer(self.lines + self.function_lines) f.writelines(optimizer.optimize_until_stable()) \ No newline at end of file diff --git a/ground_ast.py b/ground_ast.py index 4cb66ce..7544839 100644 --- a/ground_ast.py +++ b/ground_ast.py @@ -119,7 +119,7 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode: scope = scope.parent # go up one scope current_node.parent = scope scope.statements.append(current_node) - current_node = scope + current_node = None else: current_node.parent = scope else: diff --git a/out b/out index 83f17b831ed301409946042b1d8269ea23dc2379..07c8fcce2a5b5c9daad60a5ebe0cc8d73c0ef043 100644 GIT binary patch literal 8928 zcmeI2zfJ-{5XOgtGiU=^nP{;@R0?y^*iaZl{Ff_y2Rz`662-(@qb4TSh8HpxTKEz? z0xeH~JG(P*Uev7jO z27Fsvm@b)&JDd(_jTOqyz-RcF(j4e{tb48uSh)`SW^hg6U_v#lu&%fnuyP;SB0@k2 z2mv7=1cZPP5CTF#2nYcoAO!v;fgzsjyIwaR_7AGXu)kalbA#~7wB=m@BgWO;~RgQ{92|Su5NS?C6}P%L)SXO5+-o}K&E%{8 NI`yxoi%p*G{{Vh9Oh*6! delta 289 zcmaFh`a)%bhPZ|x0~|OoSTHa#I54m>uuQa93YvWCI{z;4$ zT3HNPj2_)CDjXio2N*p%fs7pt55KZ{SOZ!0&vw`V)$a%C;b)!rQEsw>f}AiT1B-wI zNC*z3CNESFw-g2P1sE6^7!(}fG9ZQ`5MvY9fQe83s35@|UtE${RHB!YpIqCpRjYbFxAMLlMZ6 F2LL$uF%$p* diff --git a/out.asm b/out.asm index 58ddf61..9817ca5 100644 --- a/out.asm +++ b/out.asm @@ -1,18 +1,25 @@ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ section .data +.LC0: db "this was called by a function!!!!", 10, 0 +.LC1: equ $ - .LC0 section .text global _start _start: -push 0 -push 1 -.loop: +call test +push 2 +push 3 mov rax, [rsp + 8] -add rax, 1 +mov rbx, [rsp + 0] +add rax, rbx mov QWORD [rsp + 8], rax -mov rax, 100000000 -cmp rax, [rsp + 8] -jg .loop mov rax, 60 -mov rdi, 0 +mov rdi, [rsp + 8] syscall +test: +mov rsi, .LC0 +mov rdx, .LC1 +mov rax, 1 +mov rdi, 1 +syscall +ret diff --git a/test.c b/test.c deleted file mode 100644 index 43e6f6a..0000000 --- a/test.c +++ /dev/null @@ -1,7 +0,0 @@ -int main() { - int lol = 0; - for (int i = 0; i != 100000000; i++) { - lol++; - } - return lol; -} \ No newline at end of file diff --git a/test.s b/test.s deleted file mode 100644 index b9d8363..0000000 --- a/test.s +++ /dev/null @@ -1,47 +0,0 @@ - .file "test.c" - .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 - movl $0, -8(%rbp) - movl $0, -4(%rbp) - jmp .L2 -.L3: - addl $1, -8(%rbp) - addl $1, -4(%rbp) -.L2: - cmpl $100000000, -4(%rbp) - jne .L3 - movl -8(%rbp), %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 f44404c..7192c58 100644 --- a/test2.grnd +++ b/test2.grnd @@ -1,7 +1,10 @@ -set &counter 0 -set &cond 1 -@loop -add $counter 1 &counter -greater 100000000 $counter &cond -if $cond %loop -end 0 \ No newline at end of file +fun -string !test + stdout "this was called by a function!!!!\n" + return +endfun + +call !test +set &x 2 +set &y 3 +add $x $y &x +end $x \ No newline at end of file