labels work im pretty sure
This commit is contained in:
8
.vscode/settings.json
vendored
Normal file
8
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.embeddedhtml": "html",
|
||||||
|
"*.spk": "code-text-binary",
|
||||||
|
"*.mem": "code-text-binary",
|
||||||
|
"stdio.h": "c"
|
||||||
|
}
|
||||||
|
}
|
@@ -10,6 +10,7 @@ class Generator:
|
|||||||
self.output_path = output_path
|
self.output_path = output_path
|
||||||
self.variables = {}
|
self.variables = {}
|
||||||
self.constants = {}
|
self.constants = {}
|
||||||
|
self.labels = []
|
||||||
self.constants_reverse = {}
|
self.constants_reverse = {}
|
||||||
self.constant_counter = 0
|
self.constant_counter = 0
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ class X86_64Generator(Generator):
|
|||||||
self.stack_size = 0
|
self.stack_size = 0
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.lines.append("global _start\n\n")
|
self.lines.append("global _start\n")
|
||||||
self.lines.append("_start:\n\t")
|
self.lines.append("_start:\n\t")
|
||||||
|
|
||||||
# generate code
|
# generate code
|
||||||
@@ -105,7 +105,6 @@ class X86_64Generator(Generator):
|
|||||||
def change_variable(self, var_name: str, new_value):
|
def change_variable(self, var_name: str, new_value):
|
||||||
var_pos = self.get_var_pos(var_name)
|
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
|
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.lines.append(f"mov QWORD [rsp + {var_pos}], {new_value.value}\n\t")
|
||||||
self.variables[var_name]["type"] = IntNode
|
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
|
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.lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t")
|
||||||
self.variables[var_name]["type"] = IntNode
|
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):
|
def generate_InstructionNode(self, node: InstructionNode):
|
||||||
### MISC ###
|
### 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("mov rdi, 1\n\t") # a file descriptor of 1 is stdout
|
||||||
self.lines.append("syscall\n\t")
|
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:
|
else:
|
||||||
self.lines.append("; FUCK\n\t")
|
self.lines.append("; FUCK\n\t")
|
||||||
#raise NotImplementedError(f"A generate method hasn't been made for the \"{node.instruction}\" instruction.")
|
#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:
|
elif value_type == float or value_type == int:
|
||||||
f.write(f"dq {float(value)}")
|
f.write(f"dq {float(value)}")
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
f.write("\nsection .text\n")
|
f.write("section .text\n")
|
||||||
f.writelines(self.lines)
|
f.writelines(self.lines)
|
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|||||||
from tokenizer import Token, TokenType
|
from tokenizer import Token, TokenType
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any
|
||||||
from error import traceback
|
from error import traceback
|
||||||
|
from console import console
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@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
|
# 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:
|
||||||
#print(token.type)
|
|
||||||
if token.type == TokenType.INSTRUCTION:
|
if token.type == TokenType.INSTRUCTION:
|
||||||
|
|
||||||
if current_node:
|
if current_node:
|
||||||
scope.statements.append(current_node)
|
scope.statements.append(current_node)
|
||||||
|
|
||||||
@@ -125,6 +126,11 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
|||||||
else:
|
else:
|
||||||
current_node = FunctionNode([], [], scope)
|
current_node = FunctionNode([], [], scope)
|
||||||
current_node_type = "func"
|
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 current_node:
|
||||||
if token.type == TokenType.STRING:
|
if token.type == TokenType.STRING:
|
||||||
@@ -200,9 +206,6 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
|
|||||||
else:
|
else:
|
||||||
traceback(code, "SyntaxError", "Expected instruction or function return type, got function reference.")
|
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:
|
elif token.type == TokenType.COMMENT:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
35
out.asm
35
out.asm
@@ -1,38 +1,11 @@
|
|||||||
; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~
|
; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~
|
||||||
|
|
||||||
section .data
|
section .data
|
||||||
.LC0: db "hiii", 0
|
|
||||||
.LC1: equ $ - .LC0
|
|
||||||
.LC2: db "", 10, 0
|
|
||||||
.LC3: equ $ - .LC2
|
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
global _start
|
global _start
|
||||||
|
|
||||||
_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])
|
; LabelDecleration
|
||||||
mov rax, 123
|
.myLabel:
|
||||||
push rax
|
; InstructionNode(instruction='jump', parent=RootNode(statements=[LabelDecleration, ...]), arguments=[LabelReference])
|
||||||
; 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])
|
jmp .myLabel
|
||||||
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
|
|
||||||
|
|
5
test.c
Normal file
5
test.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
int main() {
|
||||||
|
printf("Hello, World!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
45
test.s
Normal file
45
test.s
Normal file
@@ -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:
|
@@ -1,5 +1,2 @@
|
|||||||
set &x 123
|
@myLabel
|
||||||
set &x "hiii"
|
jump %myLabel
|
||||||
stdout $x
|
|
||||||
stdout "\n"
|
|
||||||
end 0
|
|
Reference in New Issue
Block a user