doing a bit of cleaning up

This commit is contained in:
SpookyDervish
2025-09-07 20:00:35 +10:00
parent 35ee183768
commit be2cfdf9c8
4 changed files with 59 additions and 123 deletions

View File

@@ -1,5 +1,6 @@
from ground_ast import RootNode from ground_ast import RootNode
from typing import Any from typing import Any
from ground_ast import *
class Generator: class Generator:
@@ -22,6 +23,12 @@ class Generator:
self.constant_counter += 1 self.constant_counter += 1
return "[.LC" + str(self.constant_counter-1) + "]" return "[.LC" + str(self.constant_counter-1) + "]"
def clamp_instruction_args(self, instruction: InstructionNode, min_args: int, max_args: int):
if len(instruction.arguments) < min_args:
traceback(self.code, "TypeError", f"{instruction.instruction} expects at least {min_args} arguments.")
elif len(instruction.arguments) > max_args:
traceback(self.code, "TypeError", f"{instruction.instruction} expects at most {max_args} arguments.")
def init(self): def init(self):
pass pass

View File

@@ -179,10 +179,7 @@ class X86_64Generator(Generator):
### VARIABLE INSTRUCTIONS ### ### VARIABLE INSTRUCTIONS ###
elif node.instruction == "set": elif node.instruction == "set":
if len(node.arguments) < 2: # example: "set" or "set &hi" self.clamp_instruction_args(node, 2, 2)
traceback(self.code, "TypeError", "set expects atleast 2 arguments.")
elif len(node.arguments) > 2: # example: "set &hi 0 123"
traceback(self.code, "TypeError", "set expects only 2 arguments.")
if not isinstance(node.arguments[0], VarPointerNode): if not isinstance(node.arguments[0], VarPointerNode):
traceback(self.code, "TypeError", f"the first argument of set should be a variable pointer, not \"{node.arguments[0]}\"") traceback(self.code, "TypeError", f"the first argument of set should be a variable pointer, not \"{node.arguments[0]}\"")
if type(node.arguments[1]) not in [IntNode, VarRefNode, FloatNode, StringNode, BoolNode]: if type(node.arguments[1]) not in [IntNode, VarRefNode, FloatNode, StringNode, BoolNode]:
@@ -196,13 +193,10 @@ class X86_64Generator(Generator):
self.change_variable(node.arguments[0].var_name, node.arguments[1]) self.change_variable(node.arguments[0].var_name, node.arguments[1])
### MATH INSTRUCTIONS ### ### MATH INSTRUCTIONS ###
elif node.instruction == "add": elif node.instruction in ["add", "subtract", "multiply"]:
if len(node.arguments) < 3: # example: "add" or "add 1" or "add 1 2" self.clamp_instruction_args(node, 3, 3)
traceback(self.code, "TypeError", "add expects atleast 3 arguments.") if type(node.arguments[2]) != VarPointerNode:
elif len(node.arguments) > 3: # example: "add 1 2 3 4" traceback(self.code, "TypeError", f"the destination of the {node.instruction} command must be a variable pointer, not \"{node.arguments[2]}\"")
traceback(self.code, "TypeError", "add expects only 3 arguments.")
elif type(node.arguments[2]) != VarPointerNode:
traceback(self.code, "TypeError", f"the destination of the add command must be a variable pointer, not \"{node.arguments[2]}\"")
# bro this entire god damn instruction is just error handling 😔 # bro this entire god damn instruction is just error handling 😔
number1_type = None number1_type = None
@@ -236,12 +230,22 @@ class X86_64Generator(Generator):
# TODO: numbers can be added to numbers, but numbers cant be added to strings. but strings can be added to strings, etc... # TODO: numbers can be added to numbers, but numbers cant be added to strings. but strings can be added to strings, etc...
if number1_type not in [IntNode, FloatNode] or number2_type not in [IntNode, FloatNode]: if number1_type not in [IntNode, FloatNode] or number2_type not in [IntNode, FloatNode]:
traceback(self.code, "TypeError", f"Unsupported operation \"add\" for \"{node.arguments[0]}\" and \"{node.arguments[1]}\".") traceback(self.code, "TypeError", f"Unsupported operation \"f{node.instruction}\" for \"{node.arguments[0]}\" and \"{node.arguments[1]}\".")
if number1_type == IntNode and number2_type == IntNode: if number1_type == IntNode and number2_type == IntNode:
self.lines.append(f"add rax, {arg2}\n\t") if node.instruction == "add":
self.lines.append(f"add rax, {arg2}\n\t")
elif node.instruction == "subtract":
self.lines.append(f"sub rax, {arg2}\n\t")
elif node.instruction == "multiply":
self.lines.append(f"imul rax, {arg2}\n\t")
else: else:
self.lines.append(f"addsd xmm0, xmm1\n\t") if node.instruction == "add":
self.lines.append(f"addsd xmm0, xmm1\n\t")
elif node.instruction == "subtract":
self.lines.append(f"subsd xmm0, xmm1\n\t")
elif node.instruction == "multiply":
self.lines.append(f"mulsd xmm0, xmm1\n\t")
is_integer = number1_type == IntNode and number2_type == IntNode is_integer = number1_type == IntNode and number2_type == IntNode
starting_reg = "rax" if is_integer else "xmm0" starting_reg = "rax" if is_integer else "xmm0"
@@ -250,114 +254,7 @@ class X86_64Generator(Generator):
self.create_variable(node.arguments[2].var_name, starting_reg, IntNode if is_integer else FloatNode) self.create_variable(node.arguments[2].var_name, starting_reg, IntNode if is_integer else FloatNode)
else: else:
self.change_variable(node.arguments[2].var_name, starting_reg) self.change_variable(node.arguments[2].var_name, starting_reg)
elif node.instruction == "subtract":
if len(node.arguments) < 3: # example: "subtract" or "subtract 1" or "subtract 1 2"
traceback(self.code, "TypeError", "subtract expects atleast 3 arguments.")
elif len(node.arguments) > 3: # example: "subtract 1 2 3 4"
traceback(self.code, "TypeError", "subtract expects only 3 arguments.")
elif type(node.arguments[2]) != VarPointerNode:
traceback(self.code, "TypeError", f"the destination of the subtract command must be a variable pointer, not \"{node.arguments[2]}\"")
# bro this entire god damn instruction is just error handling 😔
number1_type = None
number2_type = None
arg2 = "rbx"
if isinstance(node.arguments[0], VarRefNode):
number1_type = self.get_variable(node.arguments[0].var_name, "rax", isinstance(node.arguments[1], FloatNode))
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")
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")
else:
traceback(self.code, "TypeError", f"expected a variable reference or number for argument 1 of subtract, got {node.arguments[0]}")
if isinstance(node.arguments[1], VarRefNode):
number2_type = self.get_variable(node.arguments[1].var_name, "rbx", number1_type == FloatNode)
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")
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")
else:
traceback(self.code, "TypeError", f"expected a variable reference or number for argument 2 of subtract, got {node.arguments[1]}")
# TODO: numbers can be added to numbers, but numbers cant be added to strings. but strings can be added to strings, etc...
if number1_type not in [IntNode, FloatNode] or number2_type not in [IntNode, FloatNode]:
traceback(self.code, "TypeError", f"Unsupported operation \"subtract\" for \"{node.arguments[0]}\" and \"{node.arguments[1]}\".")
if number1_type == IntNode and number2_type == IntNode:
self.lines.append(f"sub rax, {arg2}\n\t")
else:
self.lines.append(f"subsd 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)
else:
self.change_variable(node.arguments[2].var_name, starting_reg)
elif node.instruction == "multiply":
if len(node.arguments) < 3: # example: "multiply" or "multiply 1" or "multiply 1 2"
traceback(self.code, "TypeError", "multiply expects atleast 3 arguments.")
elif len(node.arguments) > 3: # example: "multiply 1 2 3 4"
traceback(self.code, "TypeError", "multiply expects only 3 arguments.")
elif type(node.arguments[2]) != VarPointerNode:
traceback(self.code, "TypeError", f"the destination of the multiply command must be a variable pointer, not \"{node.arguments[2]}\"")
# bro this entire god damn instruction is just error handling 😔
number1_type = None
number2_type = None
arg2 = "rbx"
if isinstance(node.arguments[0], VarRefNode):
number1_type = self.get_variable(node.arguments[0].var_name, "rax", isinstance(node.arguments[1], FloatNode))
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")
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")
else:
traceback(self.code, "TypeError", f"expected a variable reference or number for argument 1 of multiply, got {node.arguments[0]}")
if isinstance(node.arguments[1], VarRefNode):
number2_type = self.get_variable(node.arguments[1].var_name, "rbx", number1_type == FloatNode)
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")
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")
else:
traceback(self.code, "TypeError", f"expected a variable reference or number for argument 2 of multiply, got {node.arguments[1]}")
# TODO: numbers can be added to numbers, but numbers cant be added to strings. but strings can be added to strings, etc...
if number1_type not in [IntNode, FloatNode] or number2_type not in [IntNode, FloatNode]:
traceback(self.code, "TypeError", f"Unsupported operation \"multiply\" for \"{node.arguments[0]}\" and \"{node.arguments[1]}\".")
if number1_type == IntNode and number2_type == IntNode:
self.lines.append(f"imul rax, {arg2}\n\t")
else:
self.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)
else:
self.change_variable(node.arguments[2].var_name, starting_reg)
elif node.instruction == "divide": elif node.instruction == "divide":
if len(node.arguments) < 3: # example: "divide" or "divide 1" or "divide 1 2" if len(node.arguments) < 3: # example: "divide" or "divide 1" or "divide 1 2"
traceback(self.code, "TypeError", "divide expects atleast 3 arguments.") traceback(self.code, "TypeError", "divide expects atleast 3 arguments.")

View File

@@ -98,8 +98,7 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
current_node_type = None current_node_type = None
scope = root_node scope = root_node
# todo: this is the absolute WORST way i could do this, but i could not care less lmao # todo: this is the absolute WORST way i could do this, but i could not care less lmao, its not even performant......
# its not even performant......
for token in tokens: for token in tokens:
if token.type == TokenType.INSTRUCTION: if token.type == TokenType.INSTRUCTION:

33
test.o Normal file
View File

@@ -0,0 +1,33 @@
.file "test.c"
.text
.section .text.startup,"ax",@progbits
.p2align 4
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
movl $100000000, %eax
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: