Files
Argon/argon.py
T

1028 lines
38 KiB
Python

import copy
import re
from typing import Any, Tuple
import sys
import time
import math
import random
import json
import pathlib
version = "ARGON Beta 2.4.2"
# make a function that clears the screen
def clear():
print("\033c", end='')
# make a function that takes in 2 params, colour and text and outputs a coloured text
def colourify(colour, text):
text = valToArgonString(text, colour=False, pretty=None)
if colour == None:
return text
if type(colour) == int:
return f"\033[38;5;{colour}m{text}\033[0m"
elif colour == "red":
return f"\033[31m{text}\033[0m"
elif colour == "green":
return f"\033[32m{text}\033[0m"
elif colour == "yellow":
return f"\033[33m{text}\033[0m"
elif colour == "blue":
return f"\033[34m{text}\033[0m"
elif colour == "purple":
return f"\033[35m{text}\033[0m"
elif colour == "cyan":
return f"\033[36m{text}\033[0m"
elif colour == "white":
return f"\033[37m{text}\033[0m"
elif colour == "black":
return f"\033[30m{text}\033[0m"
elif colour == "grey":
return f"\033[90m{text}\033[0m"
elif colour == "orange":
return f"\033[33m{text}\033[0m"
elif colour == "grey":
return f"\033[90m{text}\033[0m"
elif colour == "lightred":
return f"\033[91m{text}\033[0m"
elif colour == "lightgreen":
return f"\033[92m{text}\033[0m"
elif colour == "lightyellow":
return f"\033[93m{text}\033[0m"
elif colour == "lightblue":
return f"\033[94m{text}\033[0m"
elif colour == "lightcyan":
return f"\033[96m{text}\033[0m"
elif colour == "lightwhite":
return f"\033[97m{text}\033[0m"
elif colour == "pink" or colour == "purple":
return f"\033[95m{text}\033[0m"
else:
raise ValueError("colour must be one of the following: red, green, yellow, blue, purple, cyan, white, black, grey, orange, lightred, lightgreen, lightyellow, lightblue, lightcyan, lightwhite, pink, purple")
# make a function that takes in a param of any type and returns it as a number
def number(value: Any):
try:
inted = int(value)
floated = float(value)
if inted == floated:
return inted
return floated
except:
return float(value)
def Atype(value):
return {
int: "number",
float: "number",
str: "string",
bool: "logic",
list: "items",
tuple: "items",
dict: "book",
}[type(value)]
def code_Aexec(string):
Aexec(string, False)
def code_Aeval(string):
return Aexec(string, True)[1]
def logSF(*args):
newargs = []
for i in range(len(args)):
newargs.append(valToArgonString(args[i], speach=True, colour=False))
print(*newargs, end='')
def logSCF(*args):
newargs = []
for i in range(len(args)):
newargs.append(valToArgonString(args[i], speach=True))
print(*newargs, end='')
def logS(*args):
newargs = []
for i in range(len(args)):
newargs.append(valToArgonString(args[i], speach=True, colour=False))
print(*newargs)
def logSC(*args):
newargs = []
for i in range(len(args)):
newargs.append(valToArgonString(args[i], speach=True))
print(*newargs)
def logF(*args):
newargs = []
for i in range(len(args)):
newargs.append(valToArgonString(args[i]))
print(*newargs, end='')
def log(*args):
newargs = []
for i in range(len(args)):
newargs.append(valToArgonString(args[i]))
print(*newargs)
def rand(seed=None):
resetseed = random.random()
if seed != None:
random.seed(seed)
randomresult = random.random()
if seed != None:
random.seed(resetseed)
return randomresult
def quadraticFormula(a, b, c):
if a == 0:
return None
else:
return (-b + math.sqrt(b**2 - 4*a*c)) / (2*a), (-b - math.sqrt(b**2 - 4*a*c)) / (2*a)
def substring(string, start=None, end=None, step=None):
return string[start:end:step]
# make a function that takes in a string and an array of strings, and returns the value in the array of string that looks the most similar to the string
def find(string, array):
best = None
bestscore = None
for i in range(len(array)):
score = 0
for j in range(len(array[i])):
if array[i][j] in string:
score += 1
else:
score -= 1
if (bestscore == None or score > bestscore) and score > len(string)/4:
best = array[i]
bestscore = score
return best
def boxify(text, length=0, align="left"):
if align not in ['left', 'right', 'center']:
raise SyntaxError(f"invalid alignment")
textsplit = text.split("\n")
for i in range(len(textsplit)):
if len(textsplit[i]) > length:
length = len(textsplit[i])
processed = []
for i in range(len(textsplit)):
processed.append('║ ' + (" "*(length-len(textsplit[i]) if align == 'right' else math.ceil((length-len(textsplit[i]))/2) if align == 'center' else 0)) +
textsplit[i] + (" "*(length-len(textsplit[i]) if align == 'left' else math.floor((length-len(textsplit[i]))/2) if align == 'center' else 0)) + ' ║')
return ('╔'+((length+2)*'═')+'╗\n'+("\n".join(processed))+'\n╚'+((length+2)*'═')+'╝')
def valToArgonString(value, speach=False, pretty=1, colour=True):
if type(value) == int or type(value) == float:
return colourify('cyan' if colour else None, str(number(value)))
elif value == None:
return colourify('grey' if colour else None, "unknown")
elif value == True:
return colourify('green' if colour else None, "yes")
elif value == False:
return colourify('red' if colour else None, "no")
elif type(value) == dict:
return "{" + ", ".join(("\n"+(' '*pretty) if pretty != None and len(list(value)) > 0 else '')+f"{colourify('lightgreen' if colour else None,key) if noSpaceVarTest.fullmatch(str(key)) else valToArgonString(key, speach=True, colour=colour, pretty=pretty+1 if pretty != None else None )}: {valToArgonString(value[key], speach=True, pretty=pretty+1 if pretty != None else None, colour=colour)}" for key in value) + ('\n'+(' '*(pretty-1))if pretty != None and len(list(value)) > 0 else '') + "}"
elif type(value) in [list, tuple]:
return "[" + ", ".join(('\n'+(' '*(pretty))if pretty != None and len(list(value)) > 0 else '')+valToArgonString(i, speach=True, pretty=pretty+1 if pretty != None else None, colour=colour) for i in value) + ('\n'+(' '*(pretty-1))if pretty != None and len(list(value)) > 0 else '') + "]"
elif speach == True and type(value) == str:
return colourify('yellow' if colour else None, f'\'{value}\'')
return str(value)
def Arange(start, stop=None, step=1):
if stop == None:
stop = start
start = 0
if step == 0:
raise ValueError("step cannot be 0")
if step > 0:
return list(range(start, stop + 1, step))
else:
return list(range(start, stop - 1, step))
builtins = {
'log': {'type': 'init', 'py': log},
'logF': {'type': 'init', 'py': logF},
'logS': {'type': 'init', 'py': logS},
'logSC': {'type': 'init', 'py': logSC},
'logSF': {'type': 'init', 'py': logSF},
'logSCF': {'type': 'init', 'py': logSCF},
'input': {'type': 'init', 'py': input},
'PYeval': {'type': 'init', 'py': eval},
'colourify': {'type': 'init', 'py': colourify},
'colorify': {'type': 'init', 'py': colourify},
'clear': {'type': 'init', 'py': clear},
'PYexec': {'type': 'init', 'py': exec},
'abs': {'type': 'init', 'py': abs},
'round': {'type': 'init', 'py': round},
'length': {'type': 'init', 'py': len},
'sub': {'type': 'init', 'py': substring},
'upper': {'type': 'init', 'py': lambda x: x.upper()},
'lower': {'type': 'init', 'py': lambda x: x.lower()},
'append': {'type': 'init', 'py': lambda list, value: list.append(value)},
'insert': {'type': 'init', 'py': lambda list, to, value: list.insert(to, value)},
'extend': {'type': 'init', 'py': lambda list, values: list.extend(values)},
'pop': {'type': 'init', 'py': lambda list, i=-1: list.pop(i)},
'number': {'type': 'init', 'py': number},
'char': {'type': 'init', 'py': chr},
'ord': {'type': 'init', 'py': ord},
'numberToBinary': {'type': 'init', 'py': lambda x: bin(x)[2:]},
'numberToHex': {'type': 'init', 'py': lambda x: hex(x)[2:]},
'numberToOctal': {'type': 'init', 'py': lambda x: oct(x)[2:]},
'binaryToNumber': {'type': 'init', 'py': lambda x: int(x, 2)},
'hexToNumber': {'type': 'init', 'py': lambda x: int(x, 16)},
'octalToNumber': {'type': 'init', 'py': lambda x: int(x, 8)},
'string': {'type': 'init', 'py': lambda x: valToArgonString(x, colour=False, pretty=None)},
'logic': {'type': 'init', 'py': bool},
'yes': {'type': 'init', 'value': True},
'no': {'type': 'init', 'value': False},
'unknown': {'type': 'init', 'value': None},
'snooze': {'type': 'init', 'py': time.sleep},
'time': {'type': 'init', 'py': time.time},
'exit': {'type': 'init', 'py': sys.exit},
'boxify': {'type': 'init', 'py': boxify},
'whole': {'type': 'init', 'py': int},
'book': {'type': 'init', 'py': dict},
'items': {'type': 'init', 'py': list},
'quadraticFormula': {'type': 'init', 'py': quadraticFormula},
'exec': {"type": "init", "py": code_Aexec},
'eval': {"type": "init", "py": code_Aeval},
'range': {'type': 'init', 'py': Arange},
'type': {'type': 'init', 'py': Atype},
'random': {'type': 'init', 'py': rand},
'join': {'type': 'init', 'py': lambda by, list: by.join(list)},
'split': {'type': 'init', 'py': lambda by, string: string.split(by)},
'replace': {'type': 'init', 'py': lambda from_, to, string: string.replace(from_, to)},
'readFile': {'type': 'init', 'py': lambda filename: open(filename, 'r').read()},
'writeFile': {'type': 'init', 'py': lambda filename, text: open(filename, 'w').write(text)},
'appendFile': {'type': 'init', 'py': lambda filename, text: open(filename, 'a').write(text)},
'readLines': {'type': 'init', 'py': lambda filename: open(filename, 'r').readlines()},
'writeLines': {'type': 'init', 'py': lambda filename, lines: open(filename, 'w').writelines(lines)},
'appendLines': {'type': 'init', 'py': lambda filename, lines: open(filename, 'a').writelines(lines)},
'JSONparse': {'type': 'init', 'py': json.loads},
'JSONstringify': {'type': 'init', 'py': json.dumps},
'pi': {'type': 'init', 'value': math.pi},
'e': {'type': 'init', 'value': math.e},
'sin': {'type': 'init', 'py': lambda x: math.sin(math.radians(x))},
'cos': {'type': 'init', 'py': lambda x: math.cos(math.radians(x))},
'tan': {'type': 'init', 'py': lambda x: math.tan(math.radians(x))},
'rsin': {'type': 'init', 'py': math.sin},
'rcos': {'type': 'init', 'py': math.cos},
'rtan': {'type': 'init', 'py': math.tan},
'asin': {'type': 'init', 'py': math.asin},
'acos': {'type': 'init', 'py': math.acos},
'atan': {'type': 'init', 'py': math.atan},
'atan2': {'type': 'init', 'py': math.atan2},
'sinh': {'type': 'init', 'py': math.sinh},
'cosh': {'type': 'init', 'py': math.cosh},
'tanh': {'type': 'init', 'py': math.tanh},
'asinh': {'type': 'init', 'py': math.asinh},
'acosh': {'type': 'init', 'py': math.acosh},
'atanh': {'type': 'init', 'py': math.atanh},
'exp': {'type': 'init', 'py': math.exp},
'logarithm': {'type': 'init', 'py': math.log},
'logarithm10': {'type': 'init', 'py': math.log10},
'logarithm2': {'type': 'init', 'py': math.log2},
'sqrt': {'type': 'init', 'py': math.sqrt},
'ceil': {'type': 'init', 'py': math.ceil},
'floor': {'type': 'init', 'py': math.floor},
'round': {'type': 'init', 'py': round},
'pow': {'type': 'init', 'py': math.pow},
'hypot': {'type': 'init', 'py': math.hypot},
'degrees': {'type': 'init', 'py': math.degrees},
'radians': {'type': 'init', 'py': math.radians},
'mol': {'type': 'init', 'value': 6.02214076e+23},
}
vars = copy.copy(builtins)
stringTextREGEX = r"( *)((((\')((\\([a-z\\\"\']))|[^\\\'])*(\'))|((\")((\\([a-z\\\"\']))|[^\\\"])*(\"))))( *)"
numberTextREGEX = r"( *)(\-)?([0-9]*(\.[0-9]*)?((\+|-|)e[0-9]+)?)( *)"
varOnly = r'[a-zA-Z_][a-zA-Z0-9_]*'
varNoSpace = fr'{varOnly}(\[([^\[\]]|\[.*\])*\])*'
varTextREGEX = fr"( *){varNoSpace}( *)"
bookTextREGEX = r"( *)\{(((( *).+( *):( *).+( *))|("+varTextREGEX+r"))(( *)\,(( *).+( *):( *).+( *))|("+varTextREGEX+r")))*\}( *)"
bracketsTextREGEX = r"( *)\(.*\)( *)"
commentTextREGEX = r'( *)\#(.*)( *)'
functionTextREGEX = r"( *)(([a-zA-Z_])([a-zA-Z0-9_]*))\(.*\)( *)"
varAdd1 = fr"( *){varNoSpace}\+\+( *)"
switchTextREGEX = r"( *).+\?.+\:.+( *)"
itemsTextREGEX = r"( *)\[.*\]( *)"
remTextREGEX = fr"( *)del( +)({varTextREGEX})( *)"
cobined = fr"{stringTextREGEX}|{numberTextREGEX}|{varTextREGEX}|{functionTextREGEX}|{switchTextREGEX}|{itemsTextREGEX}|{commentTextREGEX}|{bookTextREGEX}|{varAdd1}|{bracketsTextREGEX}"
commentTest = re.compile(commentTextREGEX)
cobinedcompiled = re.compile(cobined)
noSpaceVarTest = re.compile(varNoSpace)
bookcompiled = re.compile(bookTextREGEX)
bracketsTest = re.compile(bracketsTextREGEX)
varAdd1compiled = re.compile(varAdd1)
stringTest = re.compile(stringTextREGEX)
itemscompiled = re.compile(itemsTextREGEX)
remcompiled = re.compile(remTextREGEX)
functionTest = re.compile(functionTextREGEX)
switchcompiled = re.compile(switchTextREGEX)
numberTest = re.compile(numberTextREGEX)
setVarREGEX = fr"( *)(((const|var) ({varTextREGEX})(( +)=( +).+)?)|({varTextREGEX})(( +)=( +).+))( *)"
setVar = re.compile(
setVarREGEX
)
cobinedevalcompiled = re.compile(fr"{cobined}|{setVarREGEX}|{remTextREGEX}")
evalcompiled = re.compile(r"( *)( *)")
varTest = re.compile(varTextREGEX)
def findclosestvarname(varname, vars):
return find(varname, list(vars))
# make a function that takes an input of a string that represents a string and convert all the \ commands to their actual character
# make is decode unicode encoding (eg '\u0041' to A)
def convert_backslash(string):
string = string.strip()
if string[0] == "'":
string = string[1:-1]
elif string[0] == '"':
string = string[1:-1]
string = re.sub(r"\\([a-z\"\'\\])",
lambda x: eval(f"'\\{x.group(1)}'"), string)
string = re.sub(r"\\u([a-fA-F0-9]{4})",
lambda x: chr(int(x.group(1), 16)), string)
return string
# make a function that takes in variable and outputs 2 things, the variable name and the itterable indexes
# e.g. variable: 'my2DList[1][4]' will output name: "my2DList" and indexes: [1, 4]
# to get the true value of the indexes the Aexec function
def get_var_name_and_indexes(variable):
bracketSplit = variable.strip().split("[")
varName = bracketSplit[0]
indexes = []
if len(bracketSplit) > 1:
brackets = "["+('['.join(bracketSplit[1:]))
process = []
inbracket = 0
for i in range(len(brackets)):
char = brackets[i]
if inbracket == 0 and char == "[":
inbracket += 1
elif inbracket >= 1 and char == "]":
inbracket -= 1
if inbracket == 0:
indexes.append(Aexec("".join(process), True, vars=vars)[1])
process = []
else:
process.append(char)
else:
process.append(char)
return varName, indexes
# make a function takes takes in 2 values, a mathermatical operator and 2 values and returns the result
# the mathermatical operators are +, -, *, /, %, **, //, and access boolian operators and their nots such as ==, !=, >, <, >=, <=, and in, not in
processes = [
"&&",
' and ',
"||",
' or ',
"!@",
' not in ',
' is not in ',
' isnt in ',
"@",
' in ',
' is in ',
"<=",
' is less than or equal to ',
' is smaller than or equal to ',
">=",
' is bigger than or equal to ',
' is more than or equal to ',
'<',
' is less than ',
' is smaller than ',
'>',
' is bigger than ',
' is more than ',
"!=",
' is not ',
' is not equal to ',
' isnt equal to ',
' isnt ',
'!==',
"==",
' equals ',
' is equal to ',
' is ',
'===',
' minus ',
' subtract ',
'-',
' plus ',
' add ','+',
'!**',
'!^',
' root ',
'√',
' to the power of ',
'^',
'**',
'*',
' x ',
' times ',
' multiplied by ',
' div ',
' floor division of ',
' floor divistion ',
'//', '$',
' mod ', ' modulo ',
'%', ' over ',
' divided by ', '/'
]
def math_exec(operator, value1, value2):
if operator in ["+", ' add ', ' plus ']:
if type(value1) == str or type(value2) == str:
return valToArgonString(value1, colour=False, pretty=None)+valToArgonString(value2, colour=False, pretty=None)
return value1+value2
elif operator in ["-", ' subtract ', ' minus ']:
output = value1-value2
return output
elif operator in ["*", ' multiplied by ', ' times ', ' x ']:
output = value1*value2
return output
elif operator in ["/", ' divided by ', ' over ']:
output = value1 / value2
return output
elif operator in ["%", ' modulo ', ' mod ']:
return value1 % value2
elif operator in ["^", '**', ' to the power of ']:
output = value1 ** value2
return output
elif operator in [' root ', '!**', '!^']:
output = value1 ** (1/value2)
return output
elif operator == '√':
output = value2 ** (1/value1)
return output
elif operator in ["//", '$', ' floor division ', ' floor division of ', ' div ']:
return value1 // value2
elif operator in ["==", ' equals ', ' is equal to ']:
return value1 == value2
elif operator in [' is ']:
return value1 is value2
elif operator in ["!=", ' isnt equal to ', ' is not equal to ']:
return value1 != value2
elif operator in [' isnt ', ' is not ']:
return value1 is not value2
elif operator == "===":
if isinstance(value2, type(value1)):
return value1 == value2
return False
elif operator == "!==":
if isinstance(value2, type(value1)):
return value1 != value2
return False
elif operator in [">", ' is bigger than ', ' is more than ']:
return value1 > value2
elif operator in ["<", ' is less than ', ' is smaller than ']:
return value1 < value2
elif operator in [">=", ' is bigger than or equal to ', ' is more than or equal to ']:
return value1 >= value2
elif operator in ["<=", ' is less then or equal to ', ' is smaller than or equal to ']:
return value1 <= value2
elif operator in ["@", ' in ', ' is in ']:
return value1 in value2
elif operator in ["!@", ' not in ', ' is not in ', ' isnt in ']:
return value1 not in value2
elif operator in ["||", ' or ']:
return value1 or value2
elif operator in ["&&", ' and ']:
return value1 and value2
else:
raise SyntaxError(f"invalid syntax")
def runSub(subname, args):
if len(vars[subname]['f']['prams']) != len(args):
raise SyntaxError(
f"{subname} requires {len(vars[subname]['f']['prams'])} arguments, but {len(args)} were given")
kwargs = copy.copy(builtins)
for i in range(len(args)):
if vars[subname]['f']['prams'][i] in kwargs and kwargs[vars[subname]['f']['prams'][i]]['type'] == 'init':
raise RuntimeError(
f"{vars[subname]['f']['prams'][i]} is an initialized variable / function")
kwargs[vars[subname]['f']['prams'][i]] = {
'type': 'var', 'value': args[i]}
return run(vars[subname]['f']['code'], kwargs, True)[1]
# value Argon executer takes in a string and runs it through the parser
# returns a tuple of a bool and a value
def val_Aexec(string, eval=False, vars=vars) -> Tuple[bool, Any]:
didprocess = False # did the string get processed
output = None # the output of the string
if commentTest.fullmatch(string) or string.strip() == "":
pass
elif not eval and setVar.fullmatch(string):
string = string.strip()
typeAndVar = re.split(r"( +)", string)
varname = []
varnamearray = []
aftertype = string[5:] if string[0:5] == "const" else string[3:
] if string[0:3] == "var" else string
value = None
type = typeAndVar[0]
if type not in ["const", "var"]:
varname = type
type = "var"
for i in range(len(aftertype)):
char = aftertype[i]
joined = "".join(varnamearray)
if i == len(aftertype)-1 and varTest.fullmatch(joined):
varnamearray.append(char)
joined = "".join(varnamearray)
varname = joined.strip()
break
elif char == "=" and varTest.fullmatch(joined):
value = Aexec(aftertype[len(joined)+1:],
eval=True, vars=vars)[1]
varname = joined.strip()
break
else:
varnamearray.append(char)
varname, brackets = get_var_name_and_indexes(varname)
if varname in vars:
if vars[varname]["type"] == "init":
raise Exception(
f'Variable {varname} is an initialized variable')
elif vars[varname]["type"] == "const" and len(brackets) == 0:
raise Exception(f"Variable {varname} is already a constant")
if len(brackets) == 0:
vars[varname] = {"type": type, "value": value}
else:
val = vars[varname]["value"]
for i in range(len(brackets)-1):
val = val[brackets[i]]
val[brackets[-1]] = value
elif not eval and remcompiled.fullmatch(string):
var = re.split(r"( +)", string)[2]
bracketSplit = var.strip().split("[")
varname = bracketSplit[0]
if varname in vars:
if vars[varname]["type"] == "init":
raise Exception(f'Cannot delete initialized variable')
if len(bracketSplit) > 1:
brackets = "["+('['.join(bracketSplit[1:]))
bracketslist = []
process = []
inbracket = 0
for i in range(len(brackets)):
char = brackets[i]
if inbracket == 0 and char == "[":
inbracket += 1
elif inbracket >= 1 and char == "]":
inbracket -= 1
if inbracket == 0:
bracketslist.append(
Aexec("".join(process), True, vars=vars)[1])
process = []
else:
process.append(char)
else:
process.append(char)
val = vars[varname]['value']
for i in range(len(bracketslist)-1):
val = val[bracketslist[i]]
del val[bracketslist[-1]]
else:
del vars[varname]
else:
closest = findclosestvarname(varname, vars)
if closest == None:
raise Exception(f'Variable {varname} does not exist')
else:
raise Exception(
f'Variable {varname} does not exist, did you mean \'{closest}\'?')
elif bracketsTest.fullmatch(string):
output = Aexec(string.strip()[1:-1], True, vars=vars)
didprocess = True
elif stringTest.match(string):
didprocess = True
output = convert_backslash(string)
elif numberTest.fullmatch(string):
didprocess = True
output = number(string)
elif varTest.fullmatch(string):
didprocess = True
bracketSplit = string.strip().split("[")
var = bracketSplit[0]
if var in vars:
if 'f' in vars[var] or 'py' in vars[var]:
output = f'function({var})'
else:
if len(bracketSplit) > 1:
brackets = "["+('['.join(bracketSplit[1:]))
bracketslist = []
process = []
inbracket = 0
for i in range(len(brackets)):
char = brackets[i]
if inbracket == 0 and char == "[":
inbracket += 1
elif inbracket >= 1 and char == "]":
inbracket -= 1
if inbracket == 0:
bracketslist.append(
Aexec("".join(process), True, vars=vars)[1])
process = []
else:
process.append(char)
else:
process.append(char)
output = vars[var]['value']
for i in range(len(bracketslist)):
output = output[bracketslist[i]]
else:
output = vars[var]["value"]
else:
closest = findclosestvarname(var, vars)
if closest == None:
raise Exception(f'Variable {var} does not exist')
else:
raise Exception(
f'Variable {var} does not exist, did you mean \'{closest}\'?')
elif functionTest.fullmatch(string):
function = string.strip().split("(")
funcname = function[0]
funcpramsTEXT = "(".join(function[1:])[:-1]
funcprams = []
process = []
for i in range(len(funcpramsTEXT)):
process.append(funcpramsTEXT[i])
if funcpramsTEXT[i] == ",":
try:
funcprams.append(
Aexec("".join(process)[:-1], True, vars=vars)[1])
process = []
except SyntaxError:
pass
if len(process) > 0:
funcprams.append(Aexec("".join(process), True, vars=vars)[1])
if funcname in vars:
if 'f' in vars[funcname] or 'py' in vars[funcname]:
if 'py' in vars[funcname]:
didprocess = True
output = vars[funcname]["py"](*funcprams)
else:
didprocess = False
output = runSub(funcname, funcprams)
else:
raise Exception(f"Variable {funcname} is not a function")
else:
closest = findclosestvarname(funcname, vars)
if closest == None:
raise Exception(f"Function {funcname} does not exist")
else:
raise Exception(
f"Function {funcname} does not exist, did you mean \'{closest}\'?")
elif varAdd1compiled.fullmatch(string):
didprocess = True
string = string.strip()
var = string[:-2]
varname, brackets = get_var_name_and_indexes(var)
if varname in vars:
if vars[varname]["type"] == "init":
raise Exception(f'Cannot add to initialized variable')
if brackets:
val = vars[varname]['value']
for i in range(len(brackets)):
val = val[brackets[i]]
val += 1
output = val
else:
vars[varname]["value"] += 1
output = vars[varname]["value"]
else:
raise Exception(f"Variable {varname} does not exist")
elif bookcompiled.fullmatch(string):
didprocess = True
string = string.strip()[1:-1]
output = {}
process = []
key = None
iskey = False
for i in range(len(string)):
char = string[i]
if iskey:
if char == ",":
try:
output[key] = Aexec(
"".join(process), True, vars=vars)[1]
process = []
iskey = False
key = None
except SyntaxError:
process.append(char)
else:
process.append(char)
else:
if char == ":":
try:
key = convert_backslash("".join(process))
if key in output:
raise Exception(f'Key \'{key}\' already exists')
iskey = True
process = []
except SyntaxError:
process.append(char)
elif char == ",":
try:
key = "".join(process).strip()
if key not in vars:
closest = findclosestvarname(key, vars)
if closest == None:
raise Exception(
f'Variable {key} does not exist')
else:
raise Exception(
f'Variable {key} does not exist, did you mean \'{closest}\'?')
value = Aexec("".join(process),
eval=True, vars=vars)[1]
if key in output:
raise Exception(f'Key \'{key}\' already exists')
output[key] = value
key = None
process = []
except SyntaxError:
process.append(char)
else:
process.append(char)
if iskey and len(process) > 0:
output[key] = Aexec("".join(process), True, vars=vars)[1]
elif len(process) > 0:
key = "".join(process).strip()
output[key] = Aexec(key, True, vars=vars)[1]
elif itemscompiled.fullmatch(string):
itemsText = string.strip()[1:-1]
items = []
process = []
for i in range(len(itemsText)):
process.append(itemsText[i])
if itemsText[i] == ",":
try:
items.append(
Aexec("".join(process)[:-1], True, vars=vars)[1])
process = []
except SyntaxError:
pass
if len(process) > 0:
items.append(Aexec("".join(process), True, vars=vars)[1])
didprocess = True
output = items
elif switchcompiled.fullmatch(string):
process = []
switchlen = 0
switchval = None
breaks = False
for i in range(len(string)):
switchlen += 1
if string[i] == "?":
try:
switchval = Aexec("".join(process), True, vars=vars)[1]
breaks = True
break
except SyntaxError:
pass
process.append(string[i])
if not breaks:
raise Exception(f"invalid 'checker' value within switch statement")
if switchval:
process = []
for i in range(len(string[switchlen+1:])):
char = string[switchlen+1+i]
if char == ":":
try:
didprocess, output = Aexec(
"".join(process), True, vars=vars)
breaks = True
break
except SyntaxError:
pass
process.append(char)
if not breaks:
raise Exception(f"invalid 'yes' value within switch statement")
else:
process = []
for i in range(len(string)):
char = string[len(string)-i-1]
if char == ":":
try:
didprocess, output = Aexec(
"".join(process), True, vars=vars)
break
except SyntaxError:
pass
process.insert(0, char)
if not breaks:
raise Exception(f"invalid 'no' value within switch statement")
else:
raise SyntaxError(f"invalid syntax")
return didprocess, output
# bodmas stands for brackets, order of operations, division, multiplication, addition, subtraction
# Aexec stands for Argon Execution
def Aexec(string, eval=False, vars=vars) -> Tuple[bool, str]:
string = string.strip()
if bracketsTest.fullmatch(string):
try:
return Aexec(string[1:-1], True, vars=vars)
except SyntaxError:
pass
elif (eval and cobinedcompiled.fullmatch(string)) or (not eval and cobinedevalcompiled.fullmatch(string)):
return val_Aexec(string, eval, vars=vars)
didprocess = False
output = None
breaks = False
for x in range(len(processes)):
currentprocesser = processes[x]
currentsplit = string.split(currentprocesser)
if len(currentsplit) > 1:
for i in range(len(currentsplit)-1):
removed = currentprocesser.join(currentsplit[:i+1]).strip()
after = currentprocesser.join(currentsplit[i+1:]).strip()
try:
val1 = Aexec(removed, True, vars=vars)[1]
val2 = Aexec(after, True, vars=vars)[1]
didprocess = True
output = math_exec(currentprocesser, val1, val2)
breaks = True
break
except SyntaxError:
pass
if breaks:
break
if not didprocess:
raise SyntaxError(f"invalid syntax")
return didprocess, output
runnerREGEX = re.compile(
fr"( *)(while( +)\(.*\)|if( +)\(.*\)|(sub)( +)({varOnly})\((.*)\)( +))( *)\[( *)")
def run(code: list, runvars=vars, isSub=False):
Runnertype = ""
Runnercheck = None
inRunner = 0
Runnercode = []
prams = []
subname = ""
inElse = False
Elsecode = []
for line in code:
if runnerREGEX.fullmatch(line):
inRunner += 1
if inRunner == 1:
inElse = False
Runnertype = line.strip().split(' ')[0]
if Runnertype == 'sub':
subdata = "".join(line.strip().split(' ')[1:]).split('(')
subname = subdata[0]
prams = '('.join(subdata[1:]).split(')')[0].split(',')
for i in range(len(prams)):
if prams[i] == '':
prams.pop(i)
else:
Runnercheck = ''.join(line.strip().split(' ')[1:])[
:-1].strip()[1:-1]
else:
if inElse:
Elsecode.append(line)
else:
Runnercode.append(line)
elif inRunner > 0:
if re.fullmatch(r'( *)]( *)', line):
inRunner -= 1
if inRunner == 0:
if Runnertype == "while":
while Aexec(Runnercheck, True, vars=runvars)[1]:
resp = run(Runnercode, runvars, isSub)
if isSub and resp[0]:
return resp
elif Runnertype == "if":
if Aexec(Runnercheck, True, vars=runvars)[1]:
resp = run(Runnercode, runvars, isSub)
if isSub and resp[0]:
return resp
else:
resp = run(Runnercode, runvars, isSub)
if isSub and resp[0]:
return resp
elif Runnertype == "sub":
vars[subname] = {"type": "const", 'f': {
'prams': prams, 'code': Runnercode}}
Runnertype = ""
subname = ""
Runnercheck = None
Runnercode = []
prams = []
inElse = False
Elsecode = []
else:
if inElse:
Elsecode.append(line)
else:
Runnercode.append(line)
elif re.fullmatch(r'( *)(\] else \[)( *)', line) and Runnertype == "if" and inRunner == 1 and not inElse:
inElse = True
else:
if inElse:
Elsecode.append(line)
else:
Runnercode.append(line)
elif line != "":
if isSub:
if line.strip().startswith('return'):
return Aexec(line.strip()[6:], vars=runvars, eval=True)
elif line.strip().startswith('global'):
runvars[line.strip()[6:].strip()
] = vars[line.strip()[6:].strip()]
else:
Aexec(line, vars=runvars)
else:
Aexec(line, vars=runvars)
return False, None
if __name__ == "__main__":
if len(sys.argv) > 1:
filename = sys.argv[1]
split = pathlib.Path(filename)
if len(split.suffix) == 0:
filename += ".ar"
code = open(filename, "r").read().split("\n")
run(code)
else:
print(boxify(
version+'\nMIT LICENCE AGREEMENT\n(https://github.com/Ugric/Argon)', align='center'))
exitAtempt = 0
while True:
try:
code = input(">>> ")
exitAtempt = 0
if code != "":
output = (Aexec(code))
if output[0]:
log(output[1])
except KeyboardInterrupt as e:
if exitAtempt == 0:
exitAtempt += 1
print('\n(To exit, press Ctrl+C again or Ctrl+D)')
else:
break
except EOFError as e:
break
except SyntaxError as e:
exitAtempt = 0
print(e)
continue
except Exception as e:
exitAtempt = 0
print(e)
continue