doing a bit of cleaning up
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from ground_ast import RootNode
|
||||
from typing import Any
|
||||
from ground_ast import *
|
||||
|
||||
|
||||
class Generator:
|
||||
@@ -22,6 +23,12 @@ class Generator:
|
||||
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):
|
||||
pass
|
||||
|
||||
|
@@ -179,10 +179,7 @@ class X86_64Generator(Generator):
|
||||
|
||||
### VARIABLE INSTRUCTIONS ###
|
||||
elif node.instruction == "set":
|
||||
if len(node.arguments) < 2: # example: "set" or "set &hi"
|
||||
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.")
|
||||
self.clamp_instruction_args(node, 2, 2)
|
||||
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]}\"")
|
||||
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])
|
||||
|
||||
### MATH INSTRUCTIONS ###
|
||||
elif node.instruction == "add":
|
||||
if len(node.arguments) < 3: # example: "add" or "add 1" or "add 1 2"
|
||||
traceback(self.code, "TypeError", "add expects atleast 3 arguments.")
|
||||
elif len(node.arguments) > 3: # example: "add 1 2 3 4"
|
||||
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]}\"")
|
||||
elif node.instruction in ["add", "subtract", "multiply"]:
|
||||
self.clamp_instruction_args(node, 3, 3)
|
||||
if type(node.arguments[2]) != VarPointerNode:
|
||||
traceback(self.code, "TypeError", f"the destination of the {node.instruction} command must be a variable pointer, not \"{node.arguments[2]}\"")
|
||||
|
||||
# bro this entire god damn instruction is just error handling 😔
|
||||
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...
|
||||
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:
|
||||
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:
|
||||
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
|
||||
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)
|
||||
else:
|
||||
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":
|
||||
if len(node.arguments) < 3: # example: "divide" or "divide 1" or "divide 1 2"
|
||||
traceback(self.code, "TypeError", "divide expects atleast 3 arguments.")
|
||||
|
@@ -98,8 +98,7 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
||||
current_node_type = None
|
||||
scope = root_node
|
||||
|
||||
# todo: this is the absolute WORST way i could do this, but i could not care less lmao
|
||||
# its not even performant......
|
||||
# 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:
|
||||
if token.type == TokenType.INSTRUCTION:
|
||||
|
||||
|
33
test.o
Normal file
33
test.o
Normal 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:
|
Reference in New Issue
Block a user