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

144 lines
5.3 KiB
Python

"""
This file is part of pilang.
pilang is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pilang is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pilang. If not, see <https://www.gnu.org/licenses/>.
"""
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 = {}
self.environment = environment
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
raise RuntimeError(self.get_rstring(robj))
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
#print([command] + [args])
return module.processor(command, args)