From f1f1743ddb7b6a5a6d5ed4e608b7cfccca287e55 Mon Sep 17 00:00:00 2001 From: niansa Date: Thu, 9 Apr 2020 23:44:06 +0200 Subject: [PATCH] Initial commit --- __pycache__/errors.cpython-37.pyc | Bin 0 -> 681 bytes __pycache__/intern.cpython-37.pyc | Bin 0 -> 3378 bytes __pycache__/rstrings.cpython-37.pyc | Bin 0 -> 322 bytes __pycache__/rtypes.cpython-37.pyc | Bin 0 -> 399 bytes cli.py | 25 ++++ errors.py | 4 + intern.py | 127 +++++++++++++++++++++ modules/__pycache__/builtin.cpython-37.pyc | Bin 0 -> 2585 bytes modules/builtin.py | 122 ++++++++++++++++++++ modules/math.py | 81 +++++++++++++ rstrings.py | 8 ++ rtypes.py | 2 + test.pil | 16 +++ 13 files changed, 385 insertions(+) create mode 100644 __pycache__/errors.cpython-37.pyc create mode 100644 __pycache__/intern.cpython-37.pyc create mode 100644 __pycache__/rstrings.cpython-37.pyc create mode 100644 __pycache__/rtypes.cpython-37.pyc create mode 100755 cli.py create mode 100644 errors.py create mode 100644 intern.py create mode 100644 modules/__pycache__/builtin.cpython-37.pyc create mode 100644 modules/builtin.py create mode 100644 modules/math.py create mode 100644 rstrings.py create mode 100644 rtypes.py create mode 100644 test.pil diff --git a/__pycache__/errors.cpython-37.pyc b/__pycache__/errors.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec7c6d23329e95a5c8d47672528f69c9e01b7681 GIT binary patch literal 681 zcma)(J#K?Q5QUdNgB|R9(1Z(Ek(DMzBqtJ`i>%fx0wjK%SraL>)8`zy5^ZjgDsMoz za>1e*=37?thPRLF^-5q}p1gj?%R#Y2m@U$i&_Y{Zh>Lw-vb6(pKo-c=9>@dP zpoR89KFHBQBBEuA4%cO&+96Dcl!=3-#lhAV&e{E4)24;#(ju+(K63g%%0|_hl>JJ| zy4799btvU~r>gPGk01|?hV&Q3MO$ZaQ&uK^r8Xy317DIPK9!Yf@;D=E$=shliO1kD zHc}u4o;_!HR9aEq)md{k7?ijPv18EjF~m4wI=~yT>y< zTnRMmAkRp7G{!*q8#NimDGDRh?a znLh0=e*%Md(99~jl#w)vP+Wh=V_euL&nm^0*I3J~X(d`d=#`HO;=|^9>;=5?3 zjV@y)>q0^FxC+O`_EtyO+OwX{dQXR`v3|c-^!Fi_Sz@@!}} zexk>Fx;Mh~$2&V4lWf?__cpS;NOk^TGPO~+o8?*2?be8?M8|l*Pwu=T<%1>RHk81r zyf;d_T^o11BWDyAPTQ5kKZl) zd7$_?e~A9X(@0{}KZzE*8=XksfHXGhk4K|ku8ghgBM4v3Z2gK?k|=%F z8y@wF)QYjO;V?6W%Cv1}qsdqo3$Jv94(Y<6;&9y+_Q|!L(iS0W0`G%)N7V5bQ9?3V9IgdmK@XOhhg{u8ct;?CUxX*&x+= ztPMqz%KC^wD-Y7Cv8_i1lI!VFk$#T|mO4m1emc0OfsHcLb=Ta+jfTRCalzZX^|A^} zs@*;X7yT#-NeZXKpD|E;=ABHGfcx2;LyJ(~DKYCJ7)oBqQ=xOX*e?+f`Wwodc@!vm zYq@5&$l24lKnM)NHH=|{2sRijY#?d<4Xi(AImSDT!lS4SVm&WCJy*P_b>pJ0eB9U| zE~kRCqB(D=fWm2Ezi@lY#+Bj5`Ea^>;!UOxPSzgf>*;YnofO$PU;n6Q)*UdU>f6r= zRXR8H9enf`sQVH+8)qiVP0`Eysg(slO}|NdWSz=6(GSz9GruM<(*YgwC&0YI*7wq) zy8uAz8F);l$63*lF4puHiJq7wer6!)HJ9lxV~d!Xd*~RK@K+0g7vnGCIhw~75i3xm<`i} zQocV{sr4|pZi6>)<=be+l{x6U!Xw_`C%3O?`cfia>Pm4-&FM-2Ntp*dc>%2`B1`d* z9p9@)Yi!^FyjH7NEdgCvhu#m_;oSu|L0joOUiq2OK%?TKR5_KBMui*|fF^M@BZ#-* z0+z1p_BEXT4%#9c1Nd@Mt`u^Bq+Me7A~6HpGO2DU!a+ny zdB*eqF1Y#&uHH<7>zfO%f2rt+k3dMxWW^ug=Rwkd&dhw!-&xTAV?poj@tI%I7PZnp zg)9f+jO*641$V@yx5j1x&fUg2$c3HwQnI>(iyur^K-nmL1z>rF`dgROO`--B91WKf zK*jSGK^g9R3_WpMDOL1MHj{g77Si~@I}>^zaE2;6tD(hcb+pFuze>w z@xxE@zn4uFJLx|w>u212R@NG9Rx2a2J#PAys?Xy5PoUzC$~r1r)AUTW5aQ<2u5kxMui1WMP z(R62b9gkgbuIG(1Dx1)qG==PkpTOp<4CX7aRCq3Sssh#8zTj`^b;P1&7yQ>3eBJT~ zno#tDe|_tM-`&07_b&L8&Q0r^$uKKy{BsoIs#e)xNDsq_je)JYFdt>bewA2+QTi?F z*3c!bd~A;T`^%S{^@eHg@-C_8E$Ho z@8k8kmxSgZoAic5D{0|629Riv(9AJ9RAjcwTMUm2{3Xy%01;ZeA*%H@_EE7}L$q8i zX!BSQMcdK0c_6A&5@)MF)di{yR5b#A%eA}wHfFL~$BBk~scu|(N8vfY+o@HcM-Ly} zq|UupT@iG~C4|-lWzNi3^dpqg?jcK+92_5`@ylnKaa{nd;q9L+2>IK=e;k9HS{s$k`1MC0* literal 0 HcmV?d00001 diff --git a/__pycache__/rstrings.cpython-37.pyc b/__pycache__/rstrings.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b04ae20b8b4d6977ae0a35713e7e46a7eb8dd72b GIT binary patch literal 322 zcmX|-!Ait15QfvbrbV}_C(peW!MuQoEaFMlh2DA)vYFThnq*0~f_({Jz!&h9aueUe zlhZA6LMHS7FyD|_7sVODczF7F`NsEW5-~C??(zC7Oh6!k6i#3Pr$9exLm;b3l{Z;E z2qC?1=p$FXgz;iyOFxLN6jp0)U|dB*TNrvdUPk@Ko#H!miZzFlyLQmh9DGHa3;{>z z;uWFc+*r{~Oraqxjh)IF7FM&0sIc5|_$O_uB;?K?oHDKdB97umj_LQBbyiDeRPWi= j+17E5^0}_rUiI9xEOy=O-$Q;o54%gJZA=SGlX(6B`50iU literal 0 HcmV?d00001 diff --git a/__pycache__/rtypes.cpython-37.pyc b/__pycache__/rtypes.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..570dfdced0d380b8b08511bebb219caaa744ec6e GIT binary patch literal 399 zcma)2yH3L}6t$hSjjEP!K%K~ff1pBD7q)_wtpk=7n>Ld3z;1@lu=5>=Kg!BqFmZ08 zX6nF|?(sdo=i0~KE|+tL_+EX!++qD8a)}7V1{rPvkIXQ`KalTYPfVByECS;u&R9Ch zp&Emu+91OMU>P)QFARrHbhFUrxeZ~LMqQ#*rAw<+H&?2xP3x#$DD~EAH*~(3pWu)l zep7j@ODn6w1^MjjgV!bKQyid+&5=W7AS)NB&_HE_87nF!oi@YVNXBd jV}jAiP)%uX1|ZqxBI3JL^cVKcYg1ja9-jL!dc5I(2G~bd literal 0 HcmV?d00001 diff --git a/cli.py b/cli.py new file mode 100755 index 0000000..ba05b9a --- /dev/null +++ b/cli.py @@ -0,0 +1,25 @@ +#! /usr/bin/env python3 +import sys +from intern import main_class + +if len(sys.argv) == 1: # CLI loop + main = main_class() + while True: + print(">>> ", end="", flush=True) + commandstr = input() + res = main.get_rstring(main.run_command(commandstr), errorsonly=False) + if res != None: + print(res) +else: # File execution loop + main = main_class() + if sys.argv[1] == "-c": + del sys.argv[1] + if len(sys.argv[1]) == 1: + sys.exit(1) + with open(sys.argv[1], mode="r") as f: + for line in f: + if line[-1] == "\n": + line = line[:-1] + cmdres = main.get_rstring(main.run_command(line), errorsonly=True) + if cmdres: + print(cmdres) diff --git a/errors.py b/errors.py new file mode 100644 index 0000000..bef5d08 --- /dev/null +++ b/errors.py @@ -0,0 +1,4 @@ +class nochsuchcmd: pass +class badarguments: pass +class nosuchmodule: pass +class nosuchvariable: pass diff --git a/intern.py b/intern.py new file mode 100644 index 0000000..df74cb6 --- /dev/null +++ b/intern.py @@ -0,0 +1,127 @@ +import sys, os +from types import ModuleType +import errors +import rtypes +from rstrings import rstrings + + +class environment_class: + def __init__(self): + self.variables = {} + self.catch = False +environment = environment_class() + +class main_class: + def __init__(self): + self.modules = {} + self.commands = {} + environment.evaluate = self.run_command + # Load and import modules + for module in os.listdir("modules"): + if module[-3:] == ".py" or module[-4:] == ".pyc": + self.import_module(f"modules/{module}") + + def is_error(self, robj): + try: + return robj.__name__ in errors.__dict__.keys() + except AttributeError: + return False + + def get_rstring(self, robj, errorsonly=True): + iserr = False + try: + if not "errorsonly" in self.__dict__.keys(): + self.errorsonly = errorsonly + if isinstance(robj,type): + if self.is_error(robj): + iserr = True + if self.errorsonly and not self.is_error(robj): + return None + try: + return rstrings[robj.__name__] + except KeyError: + return "py." + robj.__name__ + else: + return robj + finally: + if environment.catch and iserr: + environment.catch = False + print("An exception was catched:", self.get_rstring(robj)) + sys.exit(1) + + def import_module(self, path): + with open(path) as file: + modcode = file.read() + mod = ModuleType(path) + exec(modcode, mod.__dict__) + return mod.adder(self.add_module) + + def add_module(self, module_class): + modulename = module_class.__name__ + self.modules[modulename] = module_class(environment) + for command in self.modules[modulename].commands: + self.commands[command] = self.modules[modulename] + + def run_command(self, commandstr): + try: commandstr, _ = commandstr.split("#", 1) # Split off comments + except ValueError: pass + commandstr = commandstr.lstrip() + if commandstr == "": # Empty command (does nothing) + return + elif commandstr.startswith("~"): # Variable + try: + return environment.variables[commandstr[1:]] + except KeyError: + return errors.nosuchvariable + else: # Actual command + try: command, argsstr = commandstr.split(" ", 1) + except ValueError: command, argsstr = (commandstr, "") + try: commandsplit = command.split(".", 1) + except ValueError: commandsplit = [command] + # Get module to parse command + if len(commandsplit) == 1: # Non-exact command + try: + module = self.commands[command] + except KeyError: + return errors.nochsuchcmd + else: # Exact command + try: + module = self.modules[commandsplit[0]] + except KeyError: + return errors.nosuchmodule + command = commandsplit[1] + if not command in self.commands.keys(): + return errors.nochsuchcmd + # Split arguments if required + argsstr += "," + args = [] + if argsstr != ",": + currarg = "" + instring = False + arginstring = False + charig = False + skipall = False + for char in argsstr: + if skipall: + continue + elif char == '"' and not charig: + instring = not instring + if currarg == "": + arginstring = True + elif char == "#" and not charig and not instring: + skipall = True + elif char == ',' and not charig and not instring: + if len(currarg) != 0 and currarg[0] == "$" and not arginstring: + currarg = self.get_rstring(self.run_command(currarg[1:])) + args.append(currarg) + currarg = "" + arginstring = False + elif char == "\\" and not charig: + charig = True + else: + currarg += char + charig = False + else: + pass + # Run command + return module.processor(command, args) diff --git a/modules/__pycache__/builtin.cpython-37.pyc b/modules/__pycache__/builtin.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ea14af8144043e76ac5b1b1fa6e4e9d73e92d8b GIT binary patch literal 2585 zcmc&$TWcFf6rR~xtyZ!u%Z@2=A!!@Z%LWrcD6|DrLaz@6wbX_L(Pmj|HugHw%09C) zwvnEkK9>H0KC~}|{-t^CQ~pAp`km3mwkpyZ0-fc|IlFT?XTEcp{cL%;D$r=>mnVNz zg!qeJrcFV32r~E3X`y9Tw8vbw<<~-cT0Iw9oqKIh`?~a8w3U|IA_`t$zG!v0pEeJ| zLy*})mx{L30;{C<+$yDgaO|N2@RBa;5IoQoT?H@eC0zp#^|G#mSM-W*fLHaZUISm! zH=uRhmUjnPx5)AiE91sI1bq%N_t6c-0h0uIAO-S4B~YN{ujQeL%R`LDp%&QEYei*S zI;1Qw+KSS`D#Kl(HKf6=RlPwMXU>kJimh~dI(AcSnMI!N1YY6hDp~!|S)(+s(tQ zo8)`VUSAKoscBBYxPN$R!#K|Jtcc@)f#BVQ=gW(y=AAXB)2CBA?0s&`XCQJUoYn!C z7|IPX^v>aLUlj6LmF`NxPvIS?ZSfd!0sv(z@@WNYZ1_!j`Xy1HY>+ZDb}8?7_RXNP z540jht30bb!NB?n?HPCAad(49D~HtYq{j5!H^W8=>B%~tv(>5nvpKUU-~*IEE(+d* zaB_1fzYsq*MqYsu*g5?X9x}l znNvNl6^SfvgN#cAdA2eIXA+oKwE0tQZ$cPK&3=V{kt6_SLu^ev3OHU!%pmUIRgNNC zIZh}`b`frLi^o{$s|@1#`-oUG^?Is$I9`w?@Fjiq+RJ!DeyF4eL)C{@>y@i)~ z-z?$VyCB1G3t2-N)?G4I5y~7LRq2ax4j7b<#lR5u_;+9cgYzpN^yI+>a7cnHKz%$0 zYU>J6TMnpv5m3aZoxwzWEC&*CmeKp@{(%jBz(b3GsbSzl&>S!|x%LWRP=yx*^B*I| zUmP)?Tr*-`D-g>7!A1RbA_P~-Vjx~`gxvZ+Bcu*szQ1mS;A(9}HNFD#q?g9At;X^A ziiBK?R=_cBwYgqzbTn`uO)(mJICt0%Rd kHX)-tbFCWJWY*!nURryxLAW&r<5M=r@c#kqR`nnL25v#;VgLXD literal 0 HcmV?d00001 diff --git a/modules/builtin.py b/modules/builtin.py new file mode 100644 index 0000000..76ab4ad --- /dev/null +++ b/modules/builtin.py @@ -0,0 +1,122 @@ +import sys +import errors +import rtypes + + +class builtin: + def __init__(self, environ): + self.commands = { + "ret": self.cmd_ret, + "catch": self.cmd_catch, + "exit": self.cmd_exit, + "print": self.cmd_print, + "input": self.cmd_input, + "set": self.cmd_set, + "del": self.cmd_del, + "eval": self.cmd_eval, + "cmp": self.cmd_cmp, + "lower": self.cmd_lower + } + self.environ = environ + + def processor(self, command, args): + try: + return self.commands[command](args) + except KeyError: + return errors.nochsuchcmd + + def cmd_ret(self, args): + return " ".join(args) + + def cmd_catch(self, args): + if args == []: + self.environ.catch = not self.environ.catch + else: + if args[0].lower() == "true": + self.environ.catch = True + elif args[0].lower() == "false": + self.environ.catch = False + else: + return errors.badarguments + + def cmd_exit(self, args): + try: + sys.exit(int(args[0])) + except ValueError: + return errors.badarguments + except IndexError: + return errors.badarguments + + def cmd_print(self, args, nonline=False): + for arg in args: + print(arg, end="") + if not nonline: + print() + return rtypes.success + + def cmd_input(self, args): + self.cmd_print(args, nonline=True) + return input() + + def cmd_set(self, args): + if len(args) != 2: + return errors.badarguments + self.environ.variables[args[0]] = args[1] + return rtypes.success + + def cmd_del(self, args): + # Check if variable exists + for arg in args: + if not arg in self.environ.variables.keys(): + return errors.nosuchvariable + # Actually do that stuff + for arg in args: + del self.environ.variables[arg] + return rtypes.success + + def cmd_lower(self, args): + return str(args[0].lower()) + + def cmd_cmp(self, args): + # Check + try: + action, var1, var2, *commands = args + if action == "equal": + matches = str(var1) == str(var2) + elif action == "nonequal": + matches = str(var1) != str(var2) + elif action == "bigger": + matches = float(var1) > float(var2) + elif action == "smaller": + matches = float(var1) < float(var2) + elif action in ["isnum", "isnotnum"]: + try: + float(var1) + float(var2) + matches = True + except ValueError: + matches = False + if action == "isnotnum": + matches = not matches + else: + return errors.badarguments + if commands == []: + return matches + except ValueError: + return errors.badarguments + # Evaluate list of commands + if matches: + for command in commands: + lastres = self.environ.evaluate(command) + return lastres + else: + return rtypes.fail + + def cmd_eval(self, args): + for command in args: + lastres = self.environ.evaluate(command) + return lastres + + +def adder(registerer): + registerer(builtin) diff --git a/modules/math.py b/modules/math.py new file mode 100644 index 0000000..186a033 --- /dev/null +++ b/modules/math.py @@ -0,0 +1,81 @@ +import errors +import rtypes + + +class math: + def __init__(self, environ): + self.commands = { + "add": self.cmd_add, + "sub": self.cmd_sub, + "mul": self.cmd_mul, + "div": self.cmd_div + } + + def processor(self, command, args): + try: + return self.commands[command](args) + except KeyError: + return errors.nochsuchcmd + + def cmd_add(self, args): + try: + if args[0] == "asint": + asint = True + args = args[1:] + else: + asint = False + result = 0 + for arg in args: + result += float(arg) + if asint: result = int(result) + return result + except ValueError: + return errors.badarguments + + def cmd_sub(self, args): + try: + if args[0] == "asint": + asint = True + args = args[1:] + else: + asint = False + result = float(args[0]) + for arg in args[1:]: + result -= float(arg) + if asint: result = int(result) + return result + except ValueError: + return errors.badarguments + + def cmd_mul(self, args): + try: + if args[0] == "asint": + asint = True + args = args[1:] + else: + asint = False + result = 1 + for arg in args: + result *= float(arg) + if asint: result = int(result) + return result + except ValueError: + return errors.badarguments + + def cmd_div(self, args): + try: + if args[0] == "asint": + asint = True + args = args[1:] + else: + asint = False + result = float(args[0]) + for arg in args[1:]: + result /= float(arg) + if asint: result = int(result) + return result + except ValueError: + return errors.badarguments + +def adder(registerer): + registerer(math) diff --git a/rstrings.py b/rstrings.py new file mode 100644 index 0000000..2ffdcca --- /dev/null +++ b/rstrings.py @@ -0,0 +1,8 @@ +rstrings = { + "success": "Success", + "fail": "Failed", + "nochsuchcmd": "No such command", + "nosuchmodule": "No such module", + "nosuchvariable": "No such variable", + "badarguments": "Bad arguments" + } diff --git a/rtypes.py b/rtypes.py new file mode 100644 index 0000000..63de9a2 --- /dev/null +++ b/rtypes.py @@ -0,0 +1,2 @@ +class success: pass +class fail: pass diff --git a/test.pil b/test.pil new file mode 100644 index 0000000..c256a5a --- /dev/null +++ b/test.pil @@ -0,0 +1,16 @@ +# Enable error catching +catch True +# Initialise stuff +set wasword,was +# Get input from user +set errnonum,Whatever you typed in... It's definitely not a number!!! +set name,$input "Name: " +cmp equal,$~name,,"print What? That person has no name???",exit 1 +set current year,$input "Current year: " +cmp isnotnum,$~current year,0,print $~errnonum,exit 2 +set birth year,$input "Year of birth: " +cmp isnotnum,$~birth year,0,print $~errnonum,exit 3 +# Check if birth year is before current year +cmp smaller,$~current year,$~birth year,"print Will ,$~name, be born in the future?","set yesno,$input Yes/No?: ","cmp equal,$lower $~yesno,no,exit 4","cmp nonequal,$lower $~yesno,yes,print I give you up... Bye!,exit 4","set wasword,will be" +# Print result +print $~name, ,$~wasword, born in ,$~current year,",", so I guess he is ,$"sub asint,$~current year,$~birth year", Years old!