stdin works i think

This commit is contained in:
SpookyDervish
2025-09-13 15:48:41 +10:00
parent 983e1e8a74
commit cc82d27b03
5 changed files with 90 additions and 2 deletions

View File

@@ -31,12 +31,15 @@ class Generator:
self.global_scope = SymbolTable() self.global_scope = SymbolTable()
self.current_var_scope = self.global_scope self.current_var_scope = self.global_scope
self.constants = {} self.constants = {}
self.buffers = {}
self.structs = {} self.structs = {}
self.functions: dict[str, dict] = {} self.functions: dict[str, dict] = {}
self.labels = [] self.labels = []
self.arg_list = [] self.arg_list = []
self.constants_reverse = {} self.constants_reverse = {}
self.constant_counter = 0 self.constant_counter = 0
self.buffer_counter = 0
self.included_functions = []
def ground_type_to_node(self, ground_type: str): def ground_type_to_node(self, ground_type: str):
if ground_type == "string": if ground_type == "string":
@@ -58,6 +61,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 add_buffer(self, size: int):
buffer_name = "BUF" + str(self.buffer_counter)
self.buffers[buffer_name] = size
self.buffer_counter += 1
return buffer_name
def add_function(self, node: FunctionNode): def add_function(self, node: FunctionNode):
self.functions[node.name] = { self.functions[node.name] = {
"func": node, "func": node,

View File

@@ -31,6 +31,8 @@ class X86_64Generator(Generator):
var = scope.lookup(var_name) var = scope.lookup(var_name)
var_pos = self.get_var_pos(var_name, scope) var_pos = self.get_var_pos(var_name, scope)
print(self.stack_size, var_name, var_pos)
if isinstance(var_pos, str): # in a reg, not on the stack if isinstance(var_pos, str): # in a reg, not on the stack
waste = { waste = {
"rax": "eax", "rax": "eax",
@@ -130,6 +132,7 @@ class X86_64Generator(Generator):
self.push("rax", lines) self.push("rax", lines)
lines.append(f"mov rax, {string_len[1:-1]}\n\t") lines.append(f"mov rax, {string_len[1:-1]}\n\t")
self.push("rax", lines) self.push("rax", lines)
print(self.stack_size)
elif type(starting_value) == BoolNode: elif type(starting_value) == BoolNode:
self.push("1" if starting_value.value else "0", lines) self.push("1" if starting_value.value else "0", lines)
@@ -139,6 +142,10 @@ class X86_64Generator(Generator):
lines.append("sub rsp, 8\n\t") # make space lines.append("sub rsp, 8\n\t") # make space
lines.append(f"movsd [rsp], {starting_value}\n\t") lines.append(f"movsd [rsp], {starting_value}\n\t")
self.stack_size += 1 self.stack_size += 1
else:
if starting_value.startswith("BUF"):
self.push(starting_value, lines) # push buffer
self.push("rax", lines) # push length
else: else:
self.push(starting_value, lines) self.push(starting_value, lines)
scope.define(var_name, {"stack_loc": stack_location, "type": var_type, "used": False}) scope.define(var_name, {"stack_loc": stack_location, "type": var_type, "used": False})
@@ -261,6 +268,7 @@ class X86_64Generator(Generator):
#self.generate_InstructionNode(inst, self.function_lines) #self.generate_InstructionNode(inst, self.function_lines)
def generate_InstructionNode(self, node: InstructionNode, lines = None): def generate_InstructionNode(self, node: InstructionNode, lines = None):
print(node.instruction, self.stack_size)
lines = lines or self.lines lines = lines or self.lines
### MISC ### ### MISC ###
@@ -424,6 +432,26 @@ class X86_64Generator(Generator):
lines.append("syscall\n\t") lines.append("syscall\n\t")
self.pop("rdi", lines) # restore rdi self.pop("rdi", lines) # restore rdi
elif node.instruction == "stdin":
self.clamp_instruction_args(node, 1, 1)
arg = node.arguments[0]
if not isinstance(arg, VarPointerNode):
traceback(self.code, "TypeError", f"Argument 1 of stdin has to be a variable pointer, not \"{arg}\"")
buf_size = 255
buffer = self.add_buffer(buf_size)
lines.append("mov rax, 0\n\t") # sys_read syscall
lines.append("mov rdi, 0\n\t") # a file descriptor of 0 is stdin
lines.append(f"mov rsi, {buffer}\n\t")
lines.append(f"mov rdx, {buf_size}")
lines.append("syscall")
if not self.current_var_scope.table.get(arg.var_name):
self.create_variable(lines, arg.var_name, buffer, StringNode)
else:
self.change_variable(lines, arg.var_name, buffer)
elif node.instruction == "jump": elif node.instruction == "jump":
self.clamp_instruction_args(node, 1, 1) self.clamp_instruction_args(node, 1, 1)
if not isinstance(node.arguments[0], LabelRefNode): if not isinstance(node.arguments[0], LabelRefNode):
@@ -668,6 +696,11 @@ 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("section .bss\n")
for buf, size in self.buffers.items():
f.write(f"{buf} resb {size}\n")
f.write("section .text\n") f.write("section .text\n")
optimizer = X86_64Optimizer(self.lines + self.function_lines) optimizer = X86_64Optimizer(self.lines + self.function_lines)

BIN
out

Binary file not shown.

43
out.asm Normal file
View File

@@ -0,0 +1,43 @@
; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~
section .data
LC0: db "Type something: ", 0
LC1: equ $ - LC0
LC2: db "You said: ", 0
LC3: equ $ - LC2
section .bss
BUF0 resb 255
section .text
global _start
_start:
mov rsi, LC0
mov rdx, LC1
push rdi
mov rax, 1
mov rdi, 1
syscall
pop rdi
mov rax, 0
mov rdi, 0
mov rsi, BUF0
mov rdx, 255
syscall
push BUF0
push rax
mov rsi, LC2
mov rdx, LC3
push rdi
mov rax, 1
mov rdi, 1
syscall
pop rdi
mov rsi, [rsp + 8]
mov rdx, [rsp + 0]
push rdi
mov rax, 1
mov rdi, 1
syscall
pop rdi
mov rdi, 0
mov rax, 60
syscall

View File

@@ -1,2 +1,5 @@
stdout "Hello, World!\n" stdout "Type something: "
stdin &myString
stdout "You said: "
stdout $myString
end 0 end 0