Compare commits
3 Commits
cc82d27b03
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0e37cccd7a | ||
![]() |
f561a849c2 | ||
![]() |
9e2846962c |
@@ -31,8 +31,6 @@ 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",
|
||||||
@@ -50,7 +48,6 @@ class X86_64Generator(Generator):
|
|||||||
lines.append(f"mov {reg}, {var_pos}\n\t")
|
lines.append(f"mov {reg}, {var_pos}\n\t")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
#print(var["type"])
|
|
||||||
if var["type"] == FloatNode:
|
if var["type"] == FloatNode:
|
||||||
conversion = {
|
conversion = {
|
||||||
"rax": "xmm0",
|
"rax": "xmm0",
|
||||||
@@ -132,7 +129,6 @@ 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)
|
||||||
@@ -193,7 +189,7 @@ 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
|
||||||
#lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t")
|
#lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t")
|
||||||
lines.append(f"mov {var_pos}, {new_value}\n\t")
|
lines.append(f"mov {var_pos}, {new_value}\n\t")
|
||||||
scope.table[var_name]["type"] = IntNode
|
#scope.table[var_name]["type"] = IntNode
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@@ -231,7 +227,8 @@ 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
|
||||||
lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t")
|
lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t")
|
||||||
scope.table[var_name]["type"] = IntNode
|
#scope.table[var_name]["type"] = IntNode
|
||||||
|
|
||||||
if scope.table[var_name]["type"] != old_var_type:
|
if scope.table[var_name]["type"] != old_var_type:
|
||||||
warning(self.code, f"Changing the type of \"{var_name}\" at runtime is considered bad practice.")
|
warning(self.code, f"Changing the type of \"{var_name}\" at runtime is considered bad practice.")
|
||||||
|
|
||||||
@@ -268,7 +265,6 @@ 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 ###
|
||||||
@@ -538,6 +534,27 @@ class X86_64Generator(Generator):
|
|||||||
self.create_variable(lines, var_name, "rax", BoolNode)
|
self.create_variable(lines, var_name, "rax", BoolNode)
|
||||||
else:
|
else:
|
||||||
self.change_variable(lines, var_name, "rax")
|
self.change_variable(lines, var_name, "rax")
|
||||||
|
elif node.instruction == "not":
|
||||||
|
self.clamp_instruction_args(node, 2, 2)
|
||||||
|
if type(node.arguments[0]) not in [VarRefNode,BoolNode]:
|
||||||
|
traceback(self.code, "TypeError", f"Argument 1 of \"not\" must be a boolean or variable reference, not \"{node.arguments[0]}\"")
|
||||||
|
elif not isinstance(node.arguments[1], VarPointerNode):
|
||||||
|
traceback(self.code, "TypeError", f"Argument 2 of \"not\" must be a variable pointer, not \"{node.arguments[1]}\"")
|
||||||
|
|
||||||
|
result = ""
|
||||||
|
if isinstance(node.arguments[0], BoolNode):
|
||||||
|
result = BoolNode(not node.arguments[0].value)
|
||||||
|
elif isinstance(node.arguments[0], VarRefNode):
|
||||||
|
var_type = self.get_variable(lines, node.arguments[0].var_name, "rax")
|
||||||
|
if var_type != BoolNode:
|
||||||
|
traceback(self.code, "TypeError", f"Argument 1 of \"not\" must be a boolean or variable reference, not \"{var_type(0).__repr__()}\"")
|
||||||
|
result = "rax"
|
||||||
|
lines.append("xor rax, 1\n\t")
|
||||||
|
|
||||||
|
if self.current_var_scope.table.get(node.arguments[1].var_name):
|
||||||
|
self.change_variable(lines, node.arguments[1].var_name, result)
|
||||||
|
else:
|
||||||
|
self.create_variable(lines, node.arguments[1].var_name, result, BoolNode)
|
||||||
|
|
||||||
elif node.instruction == "endfun":
|
elif node.instruction == "endfun":
|
||||||
return
|
return
|
||||||
@@ -681,25 +698,32 @@ class X86_64Generator(Generator):
|
|||||||
with open(self.output_path + ".asm", "w") as f:
|
with open(self.output_path + ".asm", "w") as f:
|
||||||
f.write("; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~\n\n")
|
f.write("; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~\n\n")
|
||||||
|
|
||||||
f.write("section .data\n")
|
if len(self.constants) > 0:
|
||||||
for name, const in self.constants.items():
|
f.write("section .data\n")
|
||||||
value = const["value"]
|
for name, const in self.constants.items():
|
||||||
f.write(name + ": ")
|
value = const["value"]
|
||||||
value_type = type(value)
|
f.write(name + ": ")
|
||||||
if value_type == str:
|
value_type = type(value)
|
||||||
if not const["no_string"]:
|
if value_type == str:
|
||||||
final = f'db "' + value.replace("\\n", "\", 10, \"") + "\", 0"
|
if not const["no_string"]:
|
||||||
final = final.replace(", \"\", ", ", ")
|
value = value.replace("\"", "\", 34, \"")
|
||||||
f.write(final)
|
value = value.replace("\r", "\", 13, \"")
|
||||||
else:
|
value = value.replace("\n", "\", 10, \"")
|
||||||
f.write(value)
|
value = value.replace("\a", "\", 7, \"")
|
||||||
elif value_type == float or value_type == int:
|
|
||||||
f.write(f"dq {float(value)}")
|
|
||||||
f.write("\n")
|
|
||||||
|
|
||||||
f.write("section .bss\n")
|
final = f'db "' + value + "\", 0"
|
||||||
for buf, size in self.buffers.items():
|
final = final.replace(", \"\", ", ", ")
|
||||||
f.write(f"{buf} resb {size}\n")
|
f.write(final)
|
||||||
|
else:
|
||||||
|
f.write(value)
|
||||||
|
elif value_type == float or value_type == int:
|
||||||
|
f.write(f"dq {float(value)}")
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
|
if len(self.buffers) > 0:
|
||||||
|
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")
|
||||||
|
|
||||||
|
38
out.asm
38
out.asm
@@ -1,43 +1,5 @@
|
|||||||
; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~
|
; ~~~ 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
|
section .text
|
||||||
global _start
|
global _start
|
||||||
_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
|
|
||||||
|
79
test.grnd
79
test.grnd
@@ -1,79 +0,0 @@
|
|||||||
# checks if the current index in the determiner matches the current index in the target string
|
|
||||||
fun -bool !currentCharsMatch -string &str -string &determiner -int &counter -int &detIndex
|
|
||||||
getstrcharat $str $counter ¤tChar
|
|
||||||
getstrcharat $determiner $detIndex ¤tDetChar
|
|
||||||
equal $currentChar $currentDetChar &equals
|
|
||||||
return $equals
|
|
||||||
endfun
|
|
||||||
|
|
||||||
fun -list !split -string &str -string &determiner
|
|
||||||
# create an empty list
|
|
||||||
setlist *output ""
|
|
||||||
set &counter 0
|
|
||||||
set &detIndex 0
|
|
||||||
set ¤tLoop "" # basically we build out the current token until we reach the determiner
|
|
||||||
getstrsize $str &length
|
|
||||||
getstrsize $determiner &determinerLength
|
|
||||||
|
|
||||||
# go through each char in the string, does it match the first char in our determiner?
|
|
||||||
#@loop
|
|
||||||
# we are technically getting the current char twice
|
|
||||||
# 1. inside the currentCharsMatch function
|
|
||||||
# 2. here
|
|
||||||
# but oh well, it wont be that bad (i hope)
|
|
||||||
getstrcharat $str $counter ¤tChar
|
|
||||||
|
|
||||||
pusharg $str
|
|
||||||
pusharg $determiner
|
|
||||||
pusharg $counter
|
|
||||||
pusharg $detIndex
|
|
||||||
call !currentCharsMatch &equals
|
|
||||||
not $equals &doesntMatch
|
|
||||||
if $doesntMatch %next
|
|
||||||
|
|
||||||
stdlnout "WE HAVE A MATCH"
|
|
||||||
set &detIndex 0
|
|
||||||
# WE HAVE A MATCH BABY, we gotta make sure it matches the whole determiner tho
|
|
||||||
@innerLoop
|
|
||||||
|
|
||||||
pusharg $str
|
|
||||||
pusharg $determiner
|
|
||||||
pusharg $counter
|
|
||||||
pusharg $detIndex
|
|
||||||
call !currentCharsMatch &equals
|
|
||||||
add $detIndex 1 &detIndex
|
|
||||||
equal $detIndex $determinerLength &endOfDet
|
|
||||||
if $endOfDet %append
|
|
||||||
if $equals %innerLoop
|
|
||||||
|
|
||||||
@append
|
|
||||||
listappend *output $currentLoop
|
|
||||||
set ¤tLoop ""
|
|
||||||
set &detIndex 0
|
|
||||||
|
|
||||||
@next
|
|
||||||
add $currentLoop $currentChar ¤tLoop
|
|
||||||
# next character in the string
|
|
||||||
add $counter 1 &counter
|
|
||||||
inequal $length $counter ¬AtEnd
|
|
||||||
stdlnout $notAtEnd
|
|
||||||
if $notAtEnd %loop
|
|
||||||
|
|
||||||
return *output
|
|
||||||
endfun
|
|
||||||
|
|
||||||
pusharg "split this string"
|
|
||||||
pusharg " "
|
|
||||||
call !split *listOut
|
|
||||||
#getlistsize *listOut &length
|
|
||||||
#stdlnout $length
|
|
||||||
|
|
||||||
set &counter 0
|
|
||||||
|
|
||||||
@loopOverList
|
|
||||||
getlistat *listOut $counter ¤tItem
|
|
||||||
stdlnout $currentItem
|
|
||||||
add $counter 1 &counter
|
|
||||||
getlistsize *listOut &length
|
|
||||||
inequal $counter $length ¬Done
|
|
||||||
if $notDone %loopOverList
|
|
42
test2.grnd
42
test2.grnd
@@ -1,5 +1,39 @@
|
|||||||
stdout "Type something: "
|
set &number 4
|
||||||
stdin &myString
|
set &stop 0
|
||||||
stdout "You said: "
|
|
||||||
stdout $myString
|
fun -double !mod -double &in -double &modulus
|
||||||
|
lesser $in $modulus &store
|
||||||
|
not $store &store
|
||||||
|
if $store %downloop
|
||||||
|
|
||||||
|
lesser $in 0 &store
|
||||||
|
if $store %uploop
|
||||||
|
|
||||||
|
jump %end
|
||||||
|
|
||||||
|
@downloop
|
||||||
|
subtract $in $modulus &in
|
||||||
|
lesser $in $modulus &store
|
||||||
|
not $store &store
|
||||||
|
if $store %downloop
|
||||||
|
jump %end
|
||||||
|
|
||||||
|
@uploop
|
||||||
|
add $in $modulus &in
|
||||||
|
lesser $in 0 &store
|
||||||
|
if $store %uploop
|
||||||
|
jump %end
|
||||||
|
|
||||||
|
@end
|
||||||
|
return $in
|
||||||
|
endfun
|
||||||
|
|
||||||
|
@loop
|
||||||
|
equal $number 1 &stop
|
||||||
|
if $stop %end
|
||||||
|
|
||||||
|
|
||||||
|
jump %loop
|
||||||
|
|
||||||
|
@end
|
||||||
end 0
|
end 0
|
33
tokenizer.py
33
tokenizer.py
@@ -379,7 +379,8 @@ def tokenize(input_string: str):
|
|||||||
current_char = input_string[pos]
|
current_char = input_string[pos]
|
||||||
|
|
||||||
while current_char != '"':
|
while current_char != '"':
|
||||||
current_token += current_char
|
if current_char != "\\":
|
||||||
|
current_token += current_char
|
||||||
pos += 1
|
pos += 1
|
||||||
column += 1
|
column += 1
|
||||||
if pos > len(input_string)-1:
|
if pos > len(input_string)-1:
|
||||||
@@ -387,6 +388,36 @@ def tokenize(input_string: str):
|
|||||||
|
|
||||||
current_char = input_string[pos]
|
current_char = input_string[pos]
|
||||||
|
|
||||||
|
if current_char == "\\":
|
||||||
|
escape = ""
|
||||||
|
pos += 1
|
||||||
|
column += 1
|
||||||
|
while pos <= len(input_string)-1:
|
||||||
|
escape += input_string[pos]
|
||||||
|
|
||||||
|
valid_escapes = ['"', 'n', 't', 'a', 'r', '\\']
|
||||||
|
|
||||||
|
if escape == '"':
|
||||||
|
current_token += '"'
|
||||||
|
elif escape == "n":
|
||||||
|
current_token += '\n'
|
||||||
|
elif escape == "t":
|
||||||
|
current_token += '\t'
|
||||||
|
elif escape == "a":
|
||||||
|
current_token += "\a"
|
||||||
|
elif escape == "r":
|
||||||
|
current_token += "\r"
|
||||||
|
elif escape == "\\":
|
||||||
|
current_token += "\\"
|
||||||
|
|
||||||
|
if escape in valid_escapes:
|
||||||
|
break
|
||||||
|
|
||||||
|
pos += 1
|
||||||
|
column += 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
tokens.append(Token(
|
tokens.append(Token(
|
||||||
TokenType.STRING,
|
TokenType.STRING,
|
||||||
value=current_token
|
value=current_token
|
||||||
|
Reference in New Issue
Block a user