Created
March 16, 2022 00:49
-
-
Save matyklug18/1f8130c4022815a680ae135fd487aae7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExitError(Exception): | |
def __init__(self, trace=False): | |
self.trace = trace | |
def error(msg, trace=True): | |
print(msg) | |
raise ExitError(trace=trace) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import re | |
from errpy import ExitError, error | |
import traceback | |
digexpr = r'-?\d+(?:\.\d+)?' | |
strexpr = r'(?:".*?")|(?:\'.*?\')' | |
symexpr = r'(?:\\\s|\\\(|\\\)|\\\[|\\\]|[^\s()\[\]])+' | |
regx = fr'\(|\)|\[|\]|{digexpr}|{strexpr}|{symexpr}' | |
def parse_list(lst, end): | |
if len(lst) == 0: error(f"Parsing error, expected an expression or {end}") | |
res = [] | |
e = lst[0] | |
if e == end: | |
lst.pop(0) | |
return res | |
else: res.append(parse_expr(lst)) | |
while True: | |
if len(lst) == 0: error(f"Parsing error, expected an expression or {end}") | |
e = lst[0] | |
if e == end: | |
lst.pop(0) | |
return res | |
res.append(parse_expr(lst)) | |
return res | |
def parse_expr(lst): | |
if len(lst) == 0: error("Parsing error, exected an expression") | |
e = lst.pop(0) | |
if e == '(': | |
return {"type": "list", "eval": True, "value": parse_list(lst, ')')} | |
if e == '[': | |
return {"type": "list", "eval": False, "value": parse_list(lst, ']')} | |
elif re.match(strexpr, e): | |
return {"type": "string", "value": e[1:-1]} | |
elif re.match(digexpr, e): | |
return {"type": "number", "value": e} | |
elif re.match(symexpr, e): | |
return {"type": "symbol", "value": e} | |
from infloats import Float | |
from infloats import Fraction | |
def g_add(args): | |
res = args[0]["value"] | |
for a in args[1:]: | |
res += a["value"] | |
if type(res) == Float or type(res) == Fraction: | |
return {"type":"number", "value": res} | |
elif type(res) == str: | |
return {"type":"string", "value": res} | |
def g_sub(args): | |
res = args[0]["value"] | |
for a in args[1:]: | |
res -= a["value"] | |
return {"type":"number", "value": res} | |
def g_mul(args): | |
res = args[0]["value"] | |
for a in args[1:]: | |
res *= a["value"] | |
return {"type":"number", "value": res} | |
def g_div(args): | |
res = args[0]["value"] | |
for a in args[1:]: | |
res /= a["value"] | |
return {"type":"number", "value": res} | |
def do_if(a, b, c): | |
return eval_expr(b) if eval_expr(a)["value"] else eval_expr(c) | |
def do_fn(args): | |
return {"type": "function", "eval": True, "value": lambda: eval_expr(args) } | |
prompt = "-> " | |
prompt_exec_raw = lambda: {"type":"string", "value":prompt} | |
prompt_exec = lambda: deal_exec_arg(prompt_exec_raw()).encode("utf-8").decode("unicode_escape") | |
def set_prompt(a): | |
global prompt, prompt_exec_raw | |
if a["type"] == "function": | |
prompt_exec_raw = a["value"] | |
else: | |
prompt = deal_exec_arg(a) | |
import os | |
import sys | |
from os.path import expanduser | |
import pathlib | |
import getpass | |
os.environ["SHELL"] = str(pathlib.Path(__file__)) | |
os.environ["PATH"] += ':'+str(pathlib.Path(__file__).parent.absolute()) | |
def g_set_env(v, e): | |
os.environ[v["value"]] = str(e["value"]) | |
def g_add_env(v, e): | |
os.environ[v["value"]] += (":"+str(e["value"])) | |
return {"type":"string", "value":os.environ[v["value"]]} | |
def g_path(v): | |
os.environ["PATH"] += (":"+expanduser(v["value"])) | |
return {"type":"string", "value":os.environ["PATH"]} | |
def parse_pipe(args): | |
res = [[]] | |
i = 0 | |
remov_stdout = False | |
is_file = False | |
filedesc = '0' | |
mode = "r" | |
if deal_exec_arg(args[-1]) == '!>': | |
remov_stdout = True | |
filedesc = '2' | |
a_args = args[:-1] | |
elif deal_exec_arg(args[-2]) == '>' or deal_exec_arg(args[-2]) == '>>': | |
is_file = True | |
if deal_exec_arg(args[-2]) == '>': | |
mode = "w" | |
elif deal_exec_arg(args[-2]) == '>>': | |
mode = "a" | |
a_args = args[:-2] | |
else: | |
a_args = args | |
for a in a_args: | |
if deal_exec_arg(a) == '|': | |
i+=1 | |
res.append([]) | |
else: | |
res[i].append(deal_exec_arg(a)) | |
return res, is_file, deal_exec_arg(args[-1]), mode, remov_stdout, filedesc | |
def argv_to_arg(arg): | |
return arg | |
def g_pipe_top(*arg): | |
args, is_file, filename, mode, remov_stdout, filedesc = parse_pipe(arg) | |
if len(args) > 1: | |
fst = subprocess.Popen(args[0], stdout=subprocess.PIPE).stdout | |
lst_a = fst | |
else: | |
lst_a = None | |
for a in args[1:-1]: | |
lst_a = subprocess.Popen(a, stdin=lst_a, stdout=subprocess.PIPE).stdout | |
if remov_stdout: | |
if filedesc == '1': | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=subprocess.DEVNULL) | |
if filedesc == '2': | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stderr=subprocess.DEVNULL) | |
if filedesc == '3': | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
lst.wait() | |
if is_file: | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=subprocess.PIPE) | |
lst.wait() | |
fff = open(filename, mode+'b') | |
fff.write(lst.stdout.read()) | |
fff.close() | |
else: | |
lst = subprocess.Popen(args[-1], stdin=lst_a) | |
lst.wait() | |
return lst.returncode | |
def is_number(s): | |
return s.strip('\n').strip(' ').lstrip('-').replace('.', '', 1).isdigit() | |
def g_pipe(*arg): | |
args, is_file, filename, mode, remov_stdout, filedesc = parse_pipe(arg) | |
fst = subprocess.Popen(args[0], stdout=subprocess.PIPE).stdout | |
lst_a = fst | |
for a in args[1:-1]: | |
lst_a = subprocess.Popen(a, stdin=lst_a, stdout=subprocess.PIPE).stdout | |
if remov_stdout: | |
if filedesc == '1': | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=None) | |
lst.wait() | |
return lst.returncode | |
if filedesc == '2': | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stderr=None) | |
sout = lst.stdout.read().decode("utf-8") | |
lst.wait() | |
if is_number(sout): | |
return {"type":"number", "value":Float(sout)} | |
else: | |
return {"type":"raw_string", "value":sout} | |
if filedesc == '3': | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=None, stderr=None) | |
lst.wait() | |
return lst.returncode | |
elif is_file: | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=subprocess.PIPE) | |
lst.wait() | |
fff = open(filename, mode+'b') | |
fff.write(lst.stdout.read()) | |
fff.close() | |
return None | |
else: | |
lst = subprocess.Popen(args[-1], stdin=lst_a, stdout=subprocess.PIPE) | |
sout = lst.stdout.read().decode("utf-8") | |
lst.wait() | |
if is_number(sout): | |
return {"type":"number", "value":Float(sout)} | |
else: | |
return {"type":"raw_string", "value":sout} | |
def g_ex(*args): | |
fnc = find_sym(args[0]["value"]) | |
arg = deal_exec_list(args[1:]) | |
return {"type":"number", "value":Float(spawn_proc(fnc, arg))} | |
def g_alias(a, *rest): | |
ex = find_sym(rest[0]["value"]) | |
gsyms[a["value"]] = {"type": "function", "eval": True, "value": lambda *ag: g_ex(*([ex]+list(rest[1:])+list(ag)))} | |
def g_unfree(*args): | |
fnc = find_sym(args[0]["value"]) | |
arg = deal_exec_list(args[1:]) | |
return {"type":"number", "value":Float(spawn_proc_env(fnc, arg, {"NIXPKGS_ALLOW_UNFREE": "1"}))} | |
import glob | |
toplevel_sym = { | |
'pipe': {"type": "function", "eval": True, "value": g_pipe_top} | |
} | |
gsyms = { | |
"println": {"type": "function", "eval": True, "value": lambda *a: print(*[e["value"] for e in a])}, | |
"+": {"type": "function", "eval": True, "value": lambda *a: g_add(a) }, | |
"-": {"type": "function", "eval": True, "value": lambda *a: g_sub(a) }, | |
"*": {"type": "function", "eval": True, "value": lambda *a: g_mul(a) }, | |
"/": {"type": "function", "eval": True, "value": lambda *a: g_div(a) }, | |
"==": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"]==b["value"]} }, | |
">": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"]>b["value"]} }, | |
"<": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"]<b["value"]} }, | |
">=": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"]>=b["value"]} }, | |
"<=": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"]<=b["value"]} }, | |
"!=": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"]!=b["value"]} }, | |
"!": {"type": "function", "eval": True, "value": lambda a: {"type":"boolean", "value":not a["value"]} }, | |
"&&": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"] and b["value"]} }, | |
"||": {"type": "function", "eval": True, "value": lambda a,b: {"type":"boolean", "value":a["value"] or b["value"]} }, | |
'if': {"type": "function", "eval": False, "value": do_if }, | |
'sh-if': {"type": "function", "eval": False, "value": lambda a,b,c: eval_expr(b) if eval_expr(a)["value"] == Float(0) else eval_expr(c) }, | |
'fn': {"type": "function", "eval": False, "value": do_fn }, | |
'prompt': {"type": "function", "eval": True, "value": set_prompt }, | |
'cd': {"type": "function", "eval": True, "value": lambda dir={"value":expanduser("~")}: os.chdir(expanduser(dir["value"])) }, | |
'pwd': {"type": "function", "eval": True, "value": lambda: {"type":"string", "value":os.getcwd()} }, | |
'user': {"type": "function", "eval": True, "value": lambda: {"type":"string", "value":getpass.getuser()} }, | |
'set-env': {"type": "function", "eval": True, "value": g_set_env }, | |
'add-env': {"type": "function", "eval": True, "value": g_add_env }, | |
'get-env': {"type": "function", "eval": True, "value": lambda v: {"type":"string", "value":os.environ[v["value"]]} }, | |
'is-env': {"type": "function", "eval": True, "value": lambda v: {"type":"boolean", "value":v["value"] in os.environ} }, | |
'path': {"type": "function", "eval": True, "value": g_path }, | |
'pipe': {"type": "function", "eval": False, "value": g_pipe }, | |
'glob': {"type": "function", "eval": False, "value": lambda s: {"type":"string", "value":' '.join(glob.glob(expanduser(s["value"])))} }, | |
'ex': {"type": "function", "eval": False, "value": g_ex }, | |
'unfree': {"type": "function", "eval": False, "value": g_unfree }, | |
'alias': {"type": "function", "eval": False, "value": g_alias }, | |
'do': {"type": "function", "eval": True, "value": lambda *a: a[-1]}, | |
#'startswith': {"type": "function", "eval": True, "value": lambda a, b: {"type":"boolean", "value":a["value"].startswith(b["value"])} }, | |
#'replace': {"type": "function", "eval": True, "value": lambda src, what, with: {"type":"string", "value":src["value"].replace(what["value"], with["value"])} }, | |
'replace': {"type": "function", "eval": True, "value": lambda s,w,i: {"type":"string", "value":re.sub(w["value"], i["value"], s["value"])} }, | |
} | |
import shutil | |
def path_query(sym): | |
return shutil.which(sym) != None | |
def path_get(sym): | |
return {"type":"executable", "value": shutil.which(sym), "original": sym} | |
def to_num(val): | |
return Float(val) | |
def opt_sym(sym): | |
if sym in gsyms: return gsyms[sym] | |
elif path_query(sym): return path_get(sym) | |
elif sym[0] == "$" and sym[1:] in os.environ: return {"type":"string", "value":os.getenv(sym[1:])} | |
#elif sym == '|': return {"type":"string", "value":'|'} | |
elif all([c == '.' for c in sym]): return {"type":"path-change", "value": "./" if len(sym) == 1 else (len(sym)-1)*'../'} | |
elif os.path.isdir(expanduser(sym)): return {"type":"path-change", "value": expanduser(sym)} | |
else: return None | |
def find_sym(sym): | |
ssym = opt_sym(sym) | |
if ssym: return ssym | |
else: error(f'Symbol not found: {sym}', trace=False) | |
import subprocess | |
def spawn_proc(exec, args): | |
proc = subprocess.Popen([exec["original"]]+args, executable=exec["value"]) | |
proc.wait() | |
return proc.returncode | |
def spawn_proc_env(exec, args, env): | |
proc = subprocess.Popen([exec["original"]]+args, executable=exec["value"], env=os.environ.copy() | env) | |
proc.wait() | |
return proc.returncode | |
def get_proc_out(exec, args): | |
proc = subprocess.Popen([exec["original"]]+args, executable=exec["value"], stdout=subprocess.PIPE) | |
proc.wait() | |
res = proc.stdout.read().decode("utf-8") | |
return res | |
def deal_exec_arg(e): | |
if type(e) == dict: | |
if e["type"] == "string": | |
return e["value"] | |
elif e["type"] == "boolean": | |
return "true" if e["value"] else "false" | |
elif e["type"] == "raw_string": | |
if e["value"][-1] != '\n': return e["value"] + '\n' | |
else: return e["value"] | |
elif e["type"] == "number": | |
return str(e["value"]) | |
elif e["type"] == "symbol": | |
if e["value"][0] == "$": return os.environ[e["value"][1:]] | |
else: return e["value"].replace("\\ ", " ").replace('\\_', " ").replace("\\(", "(").replace("\\)", ")").replace("\\[", "[").replace("\\]", "]") | |
elif e["type"] == "executable": | |
return e["value"] | |
else: error(f"TODO {e}") | |
else: return e | |
def deal_exec_list(lst): | |
res = [] | |
for e in lst: | |
if e["type"] == "symbol": | |
res.append(e["value"]) | |
else: | |
res.append(eval_expr(e)) | |
dres = [] | |
for e in res: | |
dres.append(deal_exec_arg(e)) | |
return dres | |
def exec_exec(func, lst): | |
fnc = find_sym(func) | |
arg = [] | |
if fnc["type"] == "executable": | |
arg = deal_exec_list(lst[1:]) | |
elif not fnc["eval"]: | |
arg = lst[1:] | |
else: | |
for e in lst[1:]: | |
arg.append(eval_expr(e)) | |
if fnc["type"] == "function": | |
return fnc["value"](*arg) | |
elif fnc["type"] == "executable": | |
return {"type":"raw_string", "value":get_proc_out(fnc, arg)} | |
else: error(f'Symbol not a function: {fnc["value"]}') | |
def eval_expr(expr): | |
if expr["type"] == "list": | |
return eval_list(expr) | |
elif expr["type"] == "symbol": | |
return find_sym(expr["value"]) | |
elif expr["type"] == "string": | |
return {"type":"string", "value": expr["value"]} | |
elif expr["type"] == "number": | |
return {"type":"number", "value": to_num(expr["value"])} | |
else: return expr # TODO | |
def eval_list(lst): | |
if lst["eval"]: | |
if len(lst["value"]) == 0: return {"type":"list", "eval": True, "value": []} | |
fst0 = lst["value"][0] | |
if fst0["type"] == "list" and fst0["eval"]: | |
fst = eval_list(fst0) | |
else: | |
fst = fst0 | |
if fst["type"] == "symbol": | |
return exec_exec(fst["value"], lst["value"]) | |
elif fst["type"] == "function": | |
if fst["eval"]: | |
argl = [eval_expr(e) for e in lst["value"][1:]] | |
else: | |
argl = lst["value"][1:] | |
return fst["value"](*argl) | |
else: error(f'Not a symbol or function: {fst["value"]}') | |
else: return lst | |
def to_string(exp): | |
if type(exp) == dict: | |
if exp["type"] == "list": | |
res = [] | |
for v in exp["value"]: | |
res.append(to_string(v)) | |
if exp["eval"]: return f"({' '.join(res)})" | |
if not exp["eval"]: return f"[{' '.join(res)}]" | |
elif exp["type"] == "string": | |
return f'"{exp["value"]}"' | |
elif exp["type"] == "number": | |
return exp["value"] | |
elif exp["type"] == "function": | |
return exp["value"] | |
elif exp["type"] == "symbol": | |
return exp["value"] | |
elif exp["type"] == "number": | |
return exp["value"] | |
elif exp["type"] == "executable": | |
return exp["value"] | |
elif exp["type"] == "raw_string": | |
return exp["value"] | |
elif exp["type"] == "boolean": | |
return "true" if exp["value"] else "false" | |
else: error("TODO") | |
elif type(exp) == float: | |
return exp | |
elif type(exp) == int: | |
return exp | |
elif type(exp) == str: | |
return f'"{exp}"' | |
import signal | |
import sys | |
from termios import tcflush, TCIFLUSH | |
def signal_handler(signal, frame): | |
pass | |
#tcflush(sys.stdin, TCIFLUSH) | |
#print(f'\n{prompt_exec()}', end='') | |
def deal_builtin_exec(a): | |
if a["type"] == "symbol": | |
sym = a["value"] | |
if sym[0] == "$" and sym[1:] in os.environ: | |
return {"type":"string", "value":os.getenv(sym[1:])} | |
else: | |
return a | |
elif a["type"] == "string": | |
return eval_expr(a) | |
else: return eval_expr(a) | |
def deal_shell_exec(args): | |
toplevel = args[0]["value"] | |
root = find_sym(toplevel) | |
if toplevel in toplevel_sym: | |
root = toplevel_sym[toplevel] | |
arg = [] | |
for a in args[1:]: | |
if a["type"] == "symbol": | |
sym = a["value"] | |
if sym[0] == "$" and sym[1:] in os.environ: | |
arg.append(os.getenv(sym[1:])) | |
else: | |
arg.append(a["value"]) | |
else: | |
arg.append(deal_exec_arg(eval_expr(a))) | |
return root["value"](*arg) | |
elif root["type"] == "path-change": | |
os.chdir(root["value"]) | |
elif root["type"] == "executable": | |
arg = [] | |
is_pipe = False | |
for a in args[1:]: | |
if a["value"] == '|' or a["value"] == '>' or a["value"] == '>>' or a["value"] == '!>': | |
is_pipe = True | |
arg.append(a["value"]) | |
elif a["type"] == "symbol": | |
sym = a["value"] | |
if sym[0] == "$" and sym[1:] in os.environ: | |
arg.append(os.getenv(sym[1:])) | |
else: | |
arg.append(a["value"].replace("\\ ", " ").replace('\\_', " ").replace("\\(", "(").replace("\\)", ")").replace("\\[", "[").replace("\\]", "]").replace("\\$", "$")) | |
else: | |
arg.append(deal_exec_arg(eval_expr(a))) | |
if is_pipe: | |
return g_pipe_top(*[root["value"]]+arg) | |
else: | |
return spawn_proc(root, arg) | |
else: | |
return root["value"](*([deal_builtin_exec(e) for e in args[1:]])) | |
#signal.signal(signal.SIGINT, signal_handler) | |
from os.path import expanduser | |
home = expanduser("~") | |
initrc = open(home+"/.config/ilisp/sh.il", 'r') | |
digexpr = r'-?\d+(?:\.\d+)?' | |
strexpr = r'(?:".*?")|(?:\'.*?\')' | |
symexpr = r'(?:\\\s|\\\(|\\\)|\\\[|\\\]|[^\s()\[\]])+' | |
regx = fr'\(|\)|\[|\]|{digexpr}|{strexpr}|{symexpr}' | |
def tokenize(inp): | |
res = [] | |
curr = "" | |
esc = False | |
strm = False | |
for c in inp: | |
if c == '\n': pass | |
elif c == '\\': # escape: begin escape | |
esc = True | |
elif esc and c == '_': | |
curr += ' ' | |
elif esc: # escaped: append unmodified | |
if strm or True: # TODO please die. | |
curr += ('\\'+c) | |
else: pass | |
# curr += c | |
esc = False | |
elif not strm and c in ['\'', '"']: # begin string: begin string, append current, begin new | |
strm = True | |
if curr != "": res.append(curr) | |
curr = c | |
elif strm and c in ['\'', '"']: # end string: end string, append current, begin new | |
strm = False | |
if curr != "": res.append(curr+c) | |
curr = "" | |
elif strm: | |
curr += c | |
elif c in ['[', ']', '(', ')']: # list: append current, append character, begin new | |
if curr != "": res.append(curr) | |
res.append(c) | |
curr = "" | |
elif (len(curr) == 0 and c in "-.0123456789") or (len(curr) > 1 and (curr[0] in "-.0123456789") and all([(ch in ".0123456789") for ch in curr[1:]]) and c in ".0123456789"): # digit: append character | |
curr += c | |
elif c == ' ' and not strm: # space: append current, begin new | |
if curr != "": res.append(curr) | |
curr = "" | |
else: | |
curr += c | |
if len(curr) > 0: res.append(curr) | |
return res | |
def exec_line(line, silent=False): | |
line_r = '\n'.join(paren_split(line)) | |
if len(line_r) == 0: return | |
lst = re.findall(regx, line_r, re.MULTILINE) | |
#lst = tokenize(line_r) | |
#print(tokenize(line_r)) | |
res = parse_expr(lst) | |
if len(lst) == 0 and type(res) == dict and res["type"] == "symbol": | |
t_str = to_string(deal_shell_exec([res])) | |
if t_str != None: | |
print(t_str) | |
elif len(lst) == 0: | |
e_res = eval_expr(res) | |
if not silent: | |
if e_res != None: | |
print(to_string(e_res)) | |
else: | |
ress = [res] | |
while True: | |
if len(lst) == 0: | |
break | |
o_len = len(lst) | |
ress.append(parse_expr(lst)) | |
if o_len == len(lst): | |
if len(lst) != 0: | |
print(f'Unexpected "{" ".join(lst)}", Expected EOF') | |
break | |
else: | |
o_len = len(lst) | |
print(to_string(deal_shell_exec(ress))) | |
def paren_split(inp): | |
pi = 0 | |
res = [""] | |
ix = 0 | |
w = False | |
e = False | |
for i,c in enumerate(inp): | |
if e: | |
e = False | |
res[ix] += c | |
continue | |
if w: | |
if c == '\n': | |
w = False | |
continue | |
else: continue | |
if c == '(': pi += 1 | |
elif c == ')': pi -= 1 | |
elif c == '\\': | |
if inp[i+1] in []: # TODO why in the actual *FUCK* does emptying this array fix escaping??? | |
e = True | |
continue | |
elif c == ';': | |
w = True | |
continue | |
res[ix] += c | |
if pi == 0: | |
if res[ix][0] == '(' and res[ix][-1] == ')': | |
ix += 1 | |
res.append("") | |
elif res[ix] == '\n': | |
res[ix] = "" | |
if len(res[ix]) == 0: res.pop() | |
return res | |
initrctxt = initrc.readlines() | |
if len(initrctxt) != 0: | |
try: | |
for l in paren_split('\n'.join(initrctxt)): | |
exec_line(l, silent=True) | |
except ExitError: | |
pass | |
except Exception as e: | |
print("Unknown Error During Startup: \n"+str(e)) | |
traceback.print_tb(e.__traceback__) | |
initrc.close() | |
import readline | |
def gsym_complete(text): | |
gsymm = [] | |
for k in gsyms.keys(): | |
if k.startswith(text): | |
gsymm.append(k) | |
gsymm.append(None) | |
return gsymm | |
def file_complete(text): | |
try: | |
t_text = text.replace('\\_', " ").replace("\\(", "(").replace("\\)", ")").replace("\\[", "[").replace("\\]", "]") | |
t_text = re.sub(r"([\[\]])", r"[\1]", t_text) | |
res_t = glob.glob(expanduser(t_text)+'*') | |
if len(res_t) > 1: | |
res = [] | |
for r in res_t: | |
res.append(r.replace(" ", "\\_").replace("(", "\\(").replace(")", "\\)").replace("[", "\\[").replace("]", "\\]")) | |
#res.append(f"'{r}'") | |
return res+[None] | |
else: | |
res = res_t[0].replace(" ", "\\_").replace("(", "\\(").replace(")", "\\)").replace("[", "\\[").replace("]", "\\]") | |
#res = f"'{res_t[0]}'" | |
return [res,None] | |
except Exception as e: | |
#traceback.print_tb(e.__traceback__) | |
pass | |
binpath = os.environ["PATH"].split(':') | |
allfiles = [] | |
for dir in binpath: | |
if os.path.exists(dir): | |
allfiles.extend([f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]) | |
def binary_complete(text): | |
res = [] | |
for f in allfiles: | |
if f.startswith(text): | |
res.append(f) | |
return res+[None] | |
def complete(text, state): | |
bc = binary_complete(text) | |
if len(bc) > 1: return bc[state] | |
fc = file_complete(text) | |
if len(fc) > 1: | |
fcp = fc[state] | |
#fcpr = os.path.basename(fcp) TODO figure out | |
fcpr = fcp | |
#if os.path.isdir(fcp.replace("\\ ", " ").replace("\\(", "(").replace("\\)", ")").replace("\\[", "[").replace("\\]", "]")): fcpr += '/' | |
if fcp[0] == "'" and fcp[-1] == "'": | |
fcppr = fcp[1:-1] | |
if os.path.isdir(fcppr): | |
fcpr = fcpr[:-1] + "/'" | |
else: | |
fcppr = fcp | |
if os.path.isdir(fcppr): | |
fcpr = fcpr + "/" | |
return fcpr | |
gc = gsym_complete(text) | |
if len(gc) > 1: return gc[state] | |
readline.set_completer_delims(' ()\t\n;') | |
readline.parse_and_bind("tab: complete") | |
readline.set_completer(complete) | |
histfile = expanduser("~/.ilisphist") | |
if not os.path.exists(histfile): | |
os.mknod(histfile) | |
readline.read_history_file(histfile) | |
# TODO WTF PYTHON | |
## import atexit | |
## def exit_handler(): | |
## readline.write_history_file(histfile) | |
## signal.signal(signal.SIGTERM, exit_handler) | |
## signal.signal(signal.SIGINT, exit_handler) | |
## atexit.register(exit_handler) | |
def f_input(prompt): | |
try: | |
return input(prompt) | |
except KeyboardInterrupt: | |
print('^C') | |
return '' | |
def repl(): | |
try: | |
while True: | |
exec_line(f_input(prompt_exec())) | |
readline.write_history_file(histfile) | |
except EOFError: | |
sys.exit("\nExit") | |
except KeyboardInterrupt: | |
pass | |
except ExitError: | |
pass | |
except Exception as e: | |
print("Unknown Error: \n"+str(e)) | |
traceback.print_tb(e.__traceback__) | |
while True: | |
repl() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
from errpy import ExitError, error | |
def simplify(val, exp): | |
tval = val | |
texp = exp | |
while (divs := math.gcd(tval, texp)) != 1: | |
tval //= divs | |
texp //= divs | |
return tval, texp | |
def prime_factors(n): | |
i = 2 | |
factors = [] | |
while i * i <= n: | |
if n % i: | |
i += 1 | |
else: | |
n //= i | |
factors.append(i) | |
if n > 1: | |
factors.append(n) | |
return factors | |
def is_float(val, exp): | |
_, den = simplify(val, exp) | |
return all((e in [2, 5]) for e in prime_factors(den)) | |
def get_float(val, exp): | |
if(is_float(val, exp)): | |
num, dem = simplify(val, exp) | |
eexp = 1 | |
while(num*(10**eexp) % dem != 0): eexp += 1 | |
return num*(10**eexp)//dem, eexp, True | |
else: return 0, 0, False | |
class Fraction: | |
def __init__(self, val, exp): | |
self.val, self.exp = simplify(val, exp) | |
def invert(self): | |
val = self.val | |
self.val = self.exp | |
self.exp = val | |
return self | |
def sign_flip(self): | |
self.val = -self.val | |
return self | |
def __mul__(self, other): | |
if type(other) == Fraction: | |
res = (self.val * other.val, self.exp * other.exp) | |
v, e, i = get_float(res[0], res[1]) | |
if i: return Float(v, e) | |
else: return Fraction(res[0], res[1]) | |
elif type(other) == Float: | |
ofrac = other.get_fraction() | |
res = (self.val * ofrac.val, self.exp * ofrac.exp) | |
v, e, i = get_float(res[0], res[1]) | |
if i: return Float(v, e) | |
else: return Fraction(res[0], res[1]) | |
def __truediv__(self, other): | |
if type(other) == Fraction: | |
return self.__mul__(other.invert()) | |
elif type(other) == Float: | |
return self.__mul__(other.get_fraction().invert()) | |
def __add__(self, other): | |
if type(other) == Fraction: | |
flcm = math.lcm(self.exp, other.exp) | |
sv = self.val * (flcm//self.exp) | |
ov = other.val * (flcm//other.exp) | |
res = (sv + ov, flcm) | |
v, e, i = get_float(res[0], res[1]) | |
if i: return Float(v, e) | |
else: return Fraction(res[0], res[1]) | |
elif type(other) == Float: | |
ofrac = other.get_fraction() | |
flcm = math.lcm(self.exp, ofrac.exp) | |
sv = self.val * (flcm//self.exp) | |
ov = ofrac.val * (flcm//ofrac.exp) | |
res = (sv + ov, flcm) | |
v, e, i = get_float(res[0], res[1]) | |
if i: return Float(v, e) | |
else: return Fraction(res[0], res[1]) | |
def __sub__(self, other): | |
if type(other) == Fraction: | |
return self.__mul__(other.sign_flip()) | |
elif type(other) == Float: | |
return self.__mul__(other.get_fraction().sign_flip()) | |
def __eq__(self, other): | |
if type(other) == Float: | |
othfr = other.get_fraction() | |
return self.val == othfr.val and self.exp == othfr.exp | |
elif type(other) == Fraction: | |
return self.val == other.val and self.exp == other.exp | |
def __gt__(self, other): | |
if type(other) == Fraction: | |
flcm = math.lcm(self.exp, other.exp) | |
sv = self.val * (flcm//self.exp) | |
ov = other.val * (flcm//other.exp) | |
return sv > ov | |
elif type(other) == Float: | |
othfr = other.get_fraction() | |
flcm = math.lcm(self.exp, othfr.exp) | |
sv = self.val * (flcm//self.exp) | |
ov = othfr.val * (flcm//othfr.exp) | |
return sv > ov | |
def __ge__(self, other): | |
if self == other: return True | |
else: return self > other | |
def __lt__(self, other): | |
if type(other) == Fraction: | |
flcm = math.lcm(self.exp, other.exp) | |
sv = self.val * (flcm//self.exp) | |
ov = other.val * (flcm//other.exp) | |
return sv < ov | |
elif type(other) == Float: | |
othfr = other.get_fraction() | |
flcm = math.lcm(self.exp, othfr.exp) | |
sv = self.val * (flcm//self.exp) | |
ov = othfr.val * (flcm//othfr.exp) | |
return sv < ov | |
def __le__(self, other): | |
if self == other: return True | |
else: return self < other | |
def __str__(self): | |
return f'{self.val}/{self.exp}' | |
def __repr__(self): | |
return self.__str__() | |
class Float: | |
def __init__(self, val, exp = 0): | |
vals = str(val).split('.') | |
if len(vals) == 1 and vals[0] == '': vals[0] = '0' | |
if len(vals) == 1: vals.append("0") | |
vals[0].lstrip('0') | |
vals[1].rstrip('0') | |
zrs = len(vals[1]) | |
iexp = int(exp) | |
ovals = ''.join(vals) | |
rvals = ''.join(vals).rstrip('0') | |
if len(rvals) == 0: rvals = '0' | |
ordif = len(ovals)-len(rvals) | |
self.exp = iexp+zrs-ordif | |
self.val = int(rvals) | |
def _frac(self): | |
if self.exp == 0: | |
sv = self.val | |
se = 1 | |
if self.exp > 0: | |
sv = self.val | |
se = 10 ** self.exp | |
if self.exp < 0: | |
sv = self.val * (10 ** (-self.exp)) | |
se = 1 | |
return sv, se | |
def get_fraction(self): | |
v, e = self._frac() | |
return Fraction(v, e) | |
def __mul__(self, other): | |
if type(other) == Float: | |
return Float(self.val * other.val, self.exp + other.exp) | |
elif type(other) == Fraction: | |
return self.get_fraction() * other | |
def __truediv__(self, other): | |
if type(other) == Float: | |
sv, se = self._frac() | |
ov, oe = other._frac() | |
rfrac = (sv * oe, se * ov) | |
val, exp, isflt = get_float(rfrac[0], rfrac[1]) | |
if isflt: | |
return Float(val, exp) | |
else: | |
return Fraction(rfrac[0], rfrac[1]) | |
elif type(other) == Fraction: | |
return self.get_fraction() / other | |
def __add__(self, other): | |
if type(other) == Float: | |
if self.exp < other.exp: | |
return Float(other.val + (self.val * (10 ** (other.exp - self.exp))), other.exp) | |
else: | |
return Float(self.val + (other.val * (10 ** (self.exp - other.exp))), self.exp) | |
elif type(other) == Fraction: | |
return self.get_fraction() + other | |
def __sub__(self, other): | |
if type(other) == Float: | |
return self.__add__(Float(-other.val, other.exp)) | |
elif type(other) == Fraction: | |
return self.get_fraction() - other | |
def __eq__(self, other): | |
if type(other) == Fraction: | |
return self.get_fraction() == other | |
elif type(other) == Float: | |
return self.val == other.val and self.exp == other.exp | |
def __gt__(self, other): | |
if type(other) == Float: | |
return self.get_fraction() > other.get_fraction() | |
elif type(other) == Fraction: | |
return self.get_fraction() > other | |
def __ge__(self, other): | |
if self == other: return True | |
else: return self > other | |
def __lt__(self, other): | |
if type(other) == Float: | |
return self.get_fraction() < other.get_fraction() | |
elif type(other) == Fraction: | |
return self.get_fraction() < other | |
def __le__(self, other): | |
if self == other: return True | |
else: return self < other | |
def __str__(self): | |
#return f'{self.val} {self.exp}' | |
sval = str(self.val) | |
iexp = len(sval)-self.exp | |
if self.exp == 0: | |
return sval | |
elif self.exp < 0: | |
return sval + ('0' * (-self.exp)) | |
elif iexp == 0: | |
return '0.' + sval | |
elif iexp < 0: | |
return '0.' + ('0'*(-iexp)) + sval | |
else: | |
return sval[:iexp]+'.'+sval[iexp:] | |
def __repr__(self): | |
return self.__str__() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment