def __call__(self, forms, var_env, func_env, macro_env): """Behavior of FletSpecialOperator. """ from clispy.evaluator import Evaluator bindings, body = forms.car, forms.cdr.car funcs = [] exps = [] while bindings is not Null(): func, exp = bindings.car.car, bindings.car.cdr # Interns symbol that represents function name into current package. PackageManager.intern(String(func.value)) funcs.append(func.value) exp = Cons(Symbol('LAMBDA'), exp) # The scope of the name bindings dose not encompasse the function definitions. exps.append(Evaluator.eval(exp, var_env, func_env, macro_env)) bindings = bindings.cdr # The bindings are in parallel. func_env = func_env.extend(params=funcs, args=exps) return Evaluator.eval(body, var_env, func_env, macro_env)
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of ImportModuleObjectManipulation. """ while forms is not Null(): symbol, module_name, forms = forms.car, forms.cdr.car, forms.cdr.cdr symbol_name = symbol.value module = PyObject(import_module(module_name.value)) # Interns symbol that represents module name into current package. PackageManager.intern(String(symbol_name)) # import-moduel may be used for assignment of both lexical and dynamic variables. try: var_env.find(symbol_name)[symbol_name] = module except LookupError: try: # package_name=None means finding an environment from current package. PackageManager.find( symbol_name, package_name=None, status_check=False)[symbol_name] = module except LookupError: PackageManager.current_package.env['VARIABLE'][ symbol_name] = module # the primary value of the last form return symbol
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of FletSpecialOperator. """ from clispy.evaluator import Evaluator bindings, body = forms.car, forms.cdr.car funcs = [] exps = [] # For encompassing the function definitions themselves, # a function environment is extended in advance. local_func_env = func_env.extend() while bindings is not Null(): func, exp = bindings.car.car, bindings.car.cdr # Interns symbol that represents function name into current package. PackageManager.intern(String(func.value)) funcs.append(func.value) exp = Cons(Symbol('LAMBDA'), exp) # The scope of the name bindings encompasses the function definitions # themselves as well as the body. exps.append(Evaluator.eval(exp, var_env, local_func_env, macro_env)) bindings = bindings.cdr # The bindings are in parallel. local_func_env.update(zip(funcs, exps)) return Evaluator.eval(body, var_env, local_func_env, macro_env)
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of SetqSpecialOperator. """ from clispy.evaluator import Evaluator while forms is not Null(): symbol, value, forms = forms.car, forms.cdr.car, forms.cdr.cdr symbol_name = symbol.value value = Evaluator.eval(value, var_env, func_env, macro_env) # Interns symbol that represents function name into current package. PackageManager.intern(String(symbol_name)) # setq may be used for assignment of both lexical and dynamic variables. try: var_env.find(symbol_name)[symbol_name] = value except LookupError: try: # package_name=None means finding an environment from current package. PackageManager.find( symbol_name, package_name=None, status_check=False)[symbol_name] = value except LookupError: PackageManager.current_package.env['VARIABLE'][ symbol_name] = value # the primary value of the last form return value
def testPackageManager_get_package_name(self): # PackageManager.get_package_name returns package name represented by package_designator. # IF package_designator is None, it returns None. self.assertTrue(PackageManager.get_package_name(package_designator=None) is None) # Then package_designator is String or Symbol, it returns package name. self.assertTrue(PackageManager.get_package_name(String('COMMON-LISP')) is 'COMMON-LISP') self.assertTrue(PackageManager.get_package_name(Symbol('COMMON-LISP')) is 'COMMON-LISP')
def testPackageManager_intern(self): # PackageManager.intern interns symbol_designator to Package.symbol_container. # The package_designator argument is omitted, # symbol_designator is interned to PackageManager.current_package.symbol_container. symbol, status = PackageManager.intern(symbol_designator=String('TEST-INTERN')) self.assertTrue(symbol is Symbol('TEST-INTERN')) self.assertTrue(status is Null()) self.assertTrue('TEST-INTERN' in PackageManager.current_package.symbol_container.keys()) self.assertEqual(PackageManager.current_package.symbol_container['TEST-INTERN'], [Symbol('TEST-INTERN'), Keyword(':INTERNAL'), None]) # The package_designator argument is supplied to the specified package. symbol, status = PackageManager.intern(symbol_designator=String('INTERN-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Symbol('INTERN-WITH-PACKAGE')) self.assertTrue(status is Null()) self.assertTrue('INTERN-WITH-PACKAGE' in PackageManager.package_container['COMMON-LISP-USER'].symbol_container.keys()) self.assertEqual(PackageManager.package_container['COMMON-LISP-USER'].symbol_container['INTERN-WITH-PACKAGE'], [Symbol('INTERN-WITH-PACKAGE'), Keyword(':INTERNAL'), None])
def assign_helper(symbol_name, value, package_name, env='VARIABLE', status=':INTERNAL'): """Assign helper function. Other modules use this function to assign value. Args: symbol_name: str. A symbol name. value: mix. An assigned value. package_name: str. A package name. env: str. An environment is selected from 'VARIABLE', 'FUNCTION' or 'MACRO'. status: str. A status is selected from ':INTERNAL' or ':EXTERNAL' """ PackageManager.intern(String(symbol_name), String(package_name)) PackageManager.package_container[package_name].env[env][ symbol_name] = value if status == ':EXTERNAL': PackageManager.export(Symbol(symbol_name), Symbol(package_name))
def testPackageManager_export(self): # PackageManager.export changes symbol status in symbol container to :EXTERNAL. # The package_designator argument is omitted, # status in PackageManager.current_package.symbol_container is changed. # EXPORT is interned to PackageManager.current_package in advance. PackageManager.intern(symbol_designator=String('EXPORT')) PackageManager.export(symbol_designator=Symbol('EXPORT')) symbol, status = PackageManager.find_symbol(symbol_designator=String('EXPORT')) self.assertTrue(symbol is Symbol('EXPORT')) self.assertTrue(status is Keyword(':EXTERNAL')) # The package_designator argument is supplied to the specified package. # EXPORT-WITH-PACKAGE is interned to COMMON-LISP-USER pacakge in advance. PackageManager.intern(symbol_designator=String('EXPORT-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) PackageManager.export(symbol_designator=Symbol('EXPORT-WITH-PACKAGE'), package_designator=Symbol('COMMON-LISP-USER')) symbol, status = PackageManager.find_symbol(symbol_designator=String('EXPORT-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Symbol('EXPORT-WITH-PACKAGE')) self.assertTrue(status is Keyword(':EXTERNAL'))
def testPackageManager_find_symbol(self): # PackageManager.find_symbol returns symbol represented by symbol_designator and status. # The package_designator argument is omitted, # PackageManager.current_package.symbol_container is checked. # FIND-SYMBOL is interned to PackageManager.current_package in advance. PackageManager.intern(symbol_designator=String('FIND-SYMBOL')) symbol, status = PackageManager.find_symbol(symbol_designator=String('FIND-SYMBOL')) self.assertTrue(symbol is Symbol('FIND-SYMBOL')) self.assertTrue(status, Keyword(':INTERNAL')) # If symbol_designator dose not exist in PackageManager.current_package, # it must return Null object as symbol and status. symbol, status = PackageManager.find_symbol(symbol_designator=String('FIND-SYMBOL-NOT-EXIST')) self.assertTrue(symbol is Null()) self.assertTrue(status is Null()) # The package_designator argument is supplied to the specified package. # FIND-SYMBOL-WITH-PACKAGE is interned to COMMON-LISP-USER package in advance. PackageManager.intern(symbol_designator=String('FIND-SYMBOL-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) symbol, status = PackageManager.find_symbol(symbol_designator=String('FIND-SYMBOL-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Symbol('FIND-SYMBOL-WITH-PACKAGE')) self.assertTrue(status is Keyword(':INTERNAL')) # If symbol_designator dose not exist in the specified package, # it must return Null object as symbol and status. symbol, status = PackageManager.find_symbol(symbol_designator=String('FIND-SYMBOL-WITH-PACKAGE-NOT-EXIST'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Null()) self.assertTrue(status is Null())
def testPackageManager_import(self): # PackageManager.import_ imports symbol to symbol container of the specific package. # The package_name argument is omitted, # the method imports symbol to PackageManager.current_package.symbol_container. # IMPORT is interned to PakageManager.package_container['COMMON-LISP-USER']. PackageManager.intern(symbol_designator=String('IMPORT'), package_designator=String('COMMON-LISP-USER')) # Add value to the variable space. PackageManager.package_container['COMMON-LISP-USER'].env['VARIABLE']['IMPORT'] = String('VALUE') PackageManager.import_(symbol_designator=Symbol('COMMON-LISP-USER::IMPORT')) symbol, status = PackageManager.find_symbol(symbol_designator=String('IMPORT')) self.assertTrue(symbol is Symbol('IMPORT')) self.assertTrue(status is Keyword(':INTERNAL')) self.assertTrue(PackageManager.current_package.env['VARIABLE']['IMPORT'] is String('VALUE')) # The package_designator argument is supplied to the specified package. # IMPORT-WITH-PACKAGE is interned to COMMON-LISP package. PackageManager.intern(symbol_designator=String('IMPORT-WITH-PACKAGE'), package_designator=String('COMMON-LISP')) # Add value to the variable space. PackageManager.package_container['COMMON-LISP'].env['VARIABLE']['IMPORT-WITH-PACKAGE'] = String('VALUE') PackageManager.import_(symbol_designator=Symbol('COMMON-LISP::IMPORT-WITH-PACKAGE'), package_designator=Symbol('COMMON-LISP-USER')) symbol, status = PackageManager.find_symbol(symbol_designator=String('IMPORT-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Symbol('IMPORT-WITH-PACKAGE')) self.assertTrue(status is Keyword(':INTERNAL')) self.assertTrue(PackageManager.package_container['COMMON-LISP-USER'].env['VARIABLE']['IMPORT-WITH-PACKAGE'] is String('VALUE'))
def testPackageManager_use_package(self): # PackageManager.use_package inherited symbol in package_designator_to_use. # The package_designator argument is omitted, # symbol is inherited, and interned to PackageManager.current_package.symbol_container. # USE-PACKAGE-INTERNAL and USE-PACKAGE-EXTERNAL are interned to COMMON-LISP-USER. PackageManager.intern(symbol_designator=String('USE-PACKAGE-INTERNAL'), package_designator=String('COMMON-LISP-USER')) PackageManager.intern(symbol_designator=String('USE-PACKAGE-EXTERNAL'), package_designator=String('COMMON-LISP-USER')) # Only status of USE-PACKAGE-EXTERNAL is changed to :EXTERNAL. PackageManager.export(symbol_designator=Symbol('USE-PACKAGE-EXTERNAL'), package_designator=Symbol('COMMON-LISP-USER')) PackageManager.use_package(package_designator_to_use=Symbol('COMMON-LISP-USER')) # When status is :EXTERNAL, the symbol is inherited. symbol, status = PackageManager.find_symbol(symbol_designator=String('USE-PACKAGE-EXTERNAL')) self.assertTrue(symbol is Symbol('USE-PACKAGE-EXTERNAL')) self.assertTrue(status is Keyword(':INHERITED')) # When statis is not :EXTERNAL, the symbol is not inherited. symbol, status = PackageManager.find_symbol(symbol_designator=String('USE-PACKAGE-INTERNAL')) self.assertTrue(symbol is Null()) self.assertTrue(status is Null()) # The package_designator argument is supplied to the specified package. # USE-PACKAGE-INTERNAL-WITH-PACKAGE and USE-PACKAGE-EXTERNAL-WITH-PACKAGE are interned to COMMON-LISP. PackageManager.intern(String('USE-PACKAGE-INTERNAL-WITH-PACKAGE')) PackageManager.intern(String('USE-PACKAGE-EXTERNAL-WITH-PACKAGE')) # Only status of USE-PACKAGE-EXTERNAL-WITH-PACKAGE is changed to :EXTERNAL. PackageManager.export(Symbol('USE-PACKAGE-EXTERNAL-WITH-PACKAGE')) PackageManager.use_package(package_designator_to_use=Symbol('COMMON-LISP'), package_designator=Symbol('COMMON-LISP-USER')) # When status is :EXTERNAL, the symbol is inherited. symbol, status = PackageManager.find_symbol(symbol_designator=String('USE-PACKAGE-EXTERNAL-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Symbol('USE-PACKAGE-EXTERNAL-WITH-PACKAGE')) self.assertTrue(status is Keyword(':INHERITED')) # When statis is not :EXTERNAL, the symbol is not inherited. symbol, status = PackageManager.find_symbol(symbol_designator=String('USE-PACKAGE-INTERNAL-WITH-PACKAGE'), package_designator=String('COMMON-LISP-USER')) self.assertTrue(symbol is Null()) self.assertTrue(status is Null())
def test_eval_forms(self): forms = Parser.parse("(1 'hoge \"fuga\")") # Evaluates forms args = SystemFunction.eval_forms( forms, PackageManager.current_package.env['VARIABLE'], PackageManager.current_package.env['FUNCTION'], PackageManager.current_package.env['MACRO'], ) # Checks type of args. self.assertIsInstance(args, Cons) # Checks args self.assertTrue(args.car is Integer(1)) self.assertTrue(args.cdr.car is Symbol('HOGE')) self.assertTrue(args.cdr.cdr.car is String('fuga')) self.assertTrue(args.cdr.cdr.cdr is Null())
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of LetAsterSpecialOperator. """ from clispy.evaluator import Evaluator bindings, body = forms.car, forms.cdr.car while bindings is not Null(): var, val = bindings.car.car, bindings.car.cdr.car # Interns symbol that represents function name into current package. PackageManager.intern(String(var.value)) var = var.value val = Evaluator.eval(val, var_env, func_env, macro_env) # The bindings are in sequence. var_env = var_env.extend(params=[var], args=[val]) bindings = bindings.cdr return Evaluator.eval(body, var_env, func_env, macro_env)
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of DefunSystemFunction. """ func_symbol = forms.car func_name = func_symbol.value lambda_forms = forms # Lambda function. func = Lambda(lambda_forms.cdr, var_env, func_env, macro_env) # Interns symbol that represents function name into current package. PackageManager.intern(String(func_name)) # Binds value to symbol into the global environment. try: # package_name=None means finding an environment from current package. PackageManager.find(func_name, package_name=None, status_check=False, env='FUNCTION')[func_name] = func except LookupError: PackageManager.current_package.env['FUNCTION'][func_name] = func return func_symbol
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of DefmacroSystemFunction. """ macro_symbol = forms.car macro_name = macro_symbol.value lambda_forms = forms # Lambda function. macro = Lambda(lambda_forms.cdr, var_env, func_env, macro_env) # Interns symbol that represents macro name into current package. PackageManager.intern(String(macro_name)) # Binds value to symbol into the global environment. try: # package_name=None means finding an environment from current package. PackageManager.find(macro_name, package_name=None, status_check=False, env='MACRO')[macro_name] = macro except LookupError: PackageManager.current_package.env['MACRO'][macro_name] = macro return macro_symbol
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of LetSpecialOperator. """ from clispy.evaluator import Evaluator bindings, body = forms.car, forms.cdr.car vars, vals = [], [] while bindings is not Null(): var, val = bindings.car.car, bindings.car.cdr.car # Interns symbol that represents function name into current package. PackageManager.intern(String(var.value)) vars.append(var.value) vals.append(Evaluator.eval(val, var_env, func_env, macro_env)) bindings = bindings.cdr # The bindings are in parallel. var_env = var_env.extend(params=vars, args=vals) return Evaluator.eval(body, var_env, func_env, macro_env)
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of Lambda. """ from clispy.evaluator import Evaluator from clispy.expander import Expander # # Expands and evaluates arguments. tmp_args = [] while forms is not Null(): exp = Expander.expand(forms.car, var_env, func_env, macro_env) tmp_args.append(Evaluator.eval(exp, var_env, func_env, macro_env)) forms = forms.cdr args = tmp_args ################################################## # Accesser parameters ################################################## # Optional parameters. if '&OPTIONAL' in self.accessor_index: args = tmp_args[:self.accessor_index['&OPTIONAL']] optional_args = tmp_args[self.accessor_index['&OPTIONAL']:] for i, _ in enumerate( self.params[self.accessor_index['&OPTIONAL']:]): try: args.append(optional_args[i]) except IndexError: args.append(self.default_optional_args[i]) # Rest parameters. if '&REST' in self.accessor_index: if len(args) > self.accessor_index['&REST']: args[self.accessor_index['&REST']] = args[ self.accessor_index['&REST']:] args = args[:self.accessor_index['&REST'] + 1] else: args.append(Null()) # Keyword parameters if '&KEY' in self.accessor_index: args = tmp_args[:self.accessor_index['&KEY']] keyword_args = tmp_args[self.accessor_index['&KEY']:] kargs = {} for i, karg in enumerate(keyword_args): if isinstance(karg, Keyword): # A value of Keyword has ':' at the first character. kargs[karg.value[1:]] = keyword_args[i + 1] for param in self.params[self.accessor_index['&KEY']:]: args.append( kargs.get(param, self.default_keyword_args.get(param))) # Interns symbol names of params to lexical scope. for symbol_name in self.params: PackageManager.intern(String(symbol_name)) # Binds args to lexical scope. local_var_env = self.var_env.extend(params=self.params, args=args) local_func_env = self.func_env.extend() local_macro_env = self.macro_env.extend() # Expands and evaluates lambda expression. exp = Expander.expand(self.forms, local_var_env, local_func_env, local_macro_env) retval = Evaluator.eval(exp, local_var_env, local_func_env, local_macro_env) return retval
def repl(cls, prompt='=>', inport=InPort(sys.stdin), out=sys.stdout, zen=True): PackageManager.in_package(String("COMMON-LISP-USER")) while True: try: if prompt is not None: # Set prompt. try: prompt = PackageManager.current_package.package_nicknames[ 0] + '=>' except IndexError: prompt = PackageManager.current_package.package_name + '=>' # Wait input. print(prompt, end=' ', file=out, flush=True) # Parse inport. forms = Parser.parse(inport) # Check eof. if forms is Symbol('#<EOF-OJBECT>'): return # Expand token. forms = Expander.expand( forms, var_env=PackageManager.current_package.env['VARIABLE'], func_env=PackageManager.current_package.env['FUNCTION'], macro_env=PackageManager.current_package.env['MACRO']) # Evaluate expression. retval = Evaluator.eval( forms, var_env=PackageManager.current_package.env['VARIABLE'], func_env=PackageManager.current_package.env['FUNCTION'], macro_env=PackageManager.current_package.env['MACRO']) # Print return value. if out is not None: print(retval, end="\n\n", file=out, flush=True) except Interrupt: if zen: # Print the zen of python at random. print(random.choices(cls.the_zen_of_python)[0], end="\n\n", file=out, flush=True) return except Exception as e: print( "------------------------------------------------------------" ) print("{}: {}".format(type(e).__name__, e), end="\n\n", file=out, flush=True)