1
0
Fork 0
mirror of https://gitlab.com/niansa/pilang.git synced 2025-03-06 20:48:26 +01:00

Initial commit

This commit is contained in:
niansa 2020-04-09 23:44:06 +02:00
commit f1f1743ddb
13 changed files with 385 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

25
cli.py Executable file
View file

@ -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)

4
errors.py Normal file
View file

@ -0,0 +1,4 @@
class nochsuchcmd: pass
class badarguments: pass
class nosuchmodule: pass
class nosuchvariable: pass

127
intern.py Normal file
View file

@ -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)

Binary file not shown.

122
modules/builtin.py Normal file
View file

@ -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)

81
modules/math.py Normal file
View file

@ -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)

8
rstrings.py Normal file
View file

@ -0,0 +1,8 @@
rstrings = {
"success": "Success",
"fail": "Failed",
"nochsuchcmd": "No such command",
"nosuchmodule": "No such module",
"nosuchvariable": "No such variable",
"badarguments": "Bad arguments"
}

2
rtypes.py Normal file
View file

@ -0,0 +1,2 @@
class success: pass
class fail: pass

16
test.pil Normal file
View file

@ -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!