""" 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 . """ 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)