Compare commits
3 Commits
cc82d27b03
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0e37cccd7a | ||
![]() |
f561a849c2 | ||
![]() |
9e2846962c |
@@ -30,8 +30,6 @@ class X86_64Generator(Generator):
|
||||
|
||||
var = scope.lookup(var_name)
|
||||
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
|
||||
waste = {
|
||||
@@ -50,7 +48,6 @@ class X86_64Generator(Generator):
|
||||
lines.append(f"mov {reg}, {var_pos}\n\t")
|
||||
else:
|
||||
try:
|
||||
#print(var["type"])
|
||||
if var["type"] == FloatNode:
|
||||
conversion = {
|
||||
"rax": "xmm0",
|
||||
@@ -132,7 +129,6 @@ class X86_64Generator(Generator):
|
||||
self.push("rax", lines)
|
||||
lines.append(f"mov rax, {string_len[1:-1]}\n\t")
|
||||
self.push("rax", lines)
|
||||
print(self.stack_size)
|
||||
|
||||
elif type(starting_value) == BoolNode:
|
||||
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
|
||||
#lines.append(f"mov QWORD [rsp + {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:
|
||||
@@ -231,7 +227,8 @@ class X86_64Generator(Generator):
|
||||
|
||||
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")
|
||||
scope.table[var_name]["type"] = IntNode
|
||||
#scope.table[var_name]["type"] = IntNode
|
||||
|
||||
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.")
|
||||
|
||||
@@ -268,7 +265,6 @@ class X86_64Generator(Generator):
|
||||
#self.generate_InstructionNode(inst, self.function_lines)
|
||||
|
||||
def generate_InstructionNode(self, node: InstructionNode, lines = None):
|
||||
print(node.instruction, self.stack_size)
|
||||
lines = lines or self.lines
|
||||
|
||||
### MISC ###
|
||||
@@ -538,6 +534,27 @@ class X86_64Generator(Generator):
|
||||
self.create_variable(lines, var_name, "rax", BoolNode)
|
||||
else:
|
||||
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":
|
||||
return
|
||||
@@ -681,25 +698,32 @@ class X86_64Generator(Generator):
|
||||
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("section .data\n")
|
||||
for name, const in self.constants.items():
|
||||
value = const["value"]
|
||||
f.write(name + ": ")
|
||||
value_type = type(value)
|
||||
if value_type == str:
|
||||
if not const["no_string"]:
|
||||
final = f'db "' + value.replace("\\n", "\", 10, \"") + "\", 0"
|
||||
final = final.replace(", \"\", ", ", ")
|
||||
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.constants) > 0:
|
||||
f.write("section .data\n")
|
||||
for name, const in self.constants.items():
|
||||
value = const["value"]
|
||||
f.write(name + ": ")
|
||||
value_type = type(value)
|
||||
if value_type == str:
|
||||
if not const["no_string"]:
|
||||
value = value.replace("\"", "\", 34, \"")
|
||||
value = value.replace("\r", "\", 13, \"")
|
||||
value = value.replace("\n", "\", 10, \"")
|
||||
value = value.replace("\a", "\", 7, \"")
|
||||
|
||||
f.write("section .bss\n")
|
||||
for buf, size in self.buffers.items():
|
||||
f.write(f"{buf} resb {size}\n")
|
||||
final = f'db "' + value + "\", 0"
|
||||
final = final.replace(", \"\", ", ", ")
|
||||
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")
|
||||
|
||||
|
38
out.asm
38
out.asm
@@ -1,43 +1,5 @@
|
||||
; ~~~ 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
|
||||
|
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: "
|
||||
stdin &myString
|
||||
stdout "You said: "
|
||||
stdout $myString
|
||||
set &number 4
|
||||
set &stop 0
|
||||
|
||||
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
|
33
tokenizer.py
33
tokenizer.py
@@ -379,7 +379,8 @@ def tokenize(input_string: str):
|
||||
current_char = input_string[pos]
|
||||
|
||||
while current_char != '"':
|
||||
current_token += current_char
|
||||
if current_char != "\\":
|
||||
current_token += current_char
|
||||
pos += 1
|
||||
column += 1
|
||||
if pos > len(input_string)-1:
|
||||
@@ -387,6 +388,36 @@ def tokenize(input_string: str):
|
||||
|
||||
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(
|
||||
TokenType.STRING,
|
||||
value=current_token
|
||||
|
Reference in New Issue
Block a user