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.variables = {}
|
||||
self.constants = {}
|
||||
self.labels = []
|
||||
self.constants_reverse = {}
|
||||
self.constant_counter = 0
|
||||
|
||||
|
@@ -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)
|
@@ -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
|
||||
|
35
out.asm
35
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
|
||||
|
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
|
||||
set &x "hiii"
|
||||
stdout $x
|
||||
stdout "\n"
|
||||
end 0
|
||||
@myLabel
|
||||
jump %myLabel
|
Reference in New Issue
Block a user