def eval(cls, forms, var_env, func_env, macro_env): if isinstance(forms, Null): # Returns nil. return forms elif isinstance(forms, Symbol): # Gets symbol_name, package_name, and status_check. symbol_name, package_name, status_check = PackageManager.split_symbol_name( forms.value) # Gets the value binded by the symbol. # When package_name is None, the package becomes PackageManager.current_package. try: # Tries to get the value from lexical environment in current package. return var_env.find(symbol_name)[symbol_name] except LookupError: # Tries to get the value from another package. return PackageManager.find(symbol_name, package_name, status_check, env='VARIABLE')[symbol_name] finally: # If package_name is 'KEYWORD', sets keyword represented by symbol_name. if package_name == 'KEYWORD': assign_helper(symbol_name, Keyword(symbol_name), package_name, 'VARIABLE', ':EXTERNAL') return PackageManager.find(symbol_name, package_name, status_check, env='VARIABLE')[symbol_name] elif not isinstance(forms, Cons): # If an atom is given, returns itself. return forms else: # Binds function object. if isinstance(forms.car, Cons): # If lambda expression is given, it is bound as an anonymous function. # Other than that, it is bound from predefined functions involving special func = cls.eval(forms.car, var_env, func_env, macro_env) else: # Gets symbol_name, package_name, and status_check. func_name, package_name, status_check = PackageManager.split_symbol_name( forms.car.value) # Gets the function binded by the symbol. # When package_name is None, the package becomes PackageManager.current_package. try: # Tries to get the function from lexical environment in current package. func = func_env.find(func_name)[func_name] except LookupError: # Tries to get the function from another package. func = PackageManager.find(func_name, package_name, status_check, env='FUNCTION')[func_name] return func(forms.cdr, var_env, func_env, macro_env)
def testPackageManager_find(self): # PackageManger.find results an environment that have value assigned by symbol. # The package that have the environment is shown by package_name. # symbol_name, package_name, status_check is given by PackageManger.split_symbol. # Checks an environment using *PACKAGE* in current package. symbol_name, package_name, status_check = PackageManager.split_symbol_name('COMMON-LISP::*PACKAGE*') env = PackageManager.find(symbol_name, package_name, status_check) self.assertIsInstance(env, Environment) self.assertTrue('*PACKAGE*' in env) symbol_name, package_name, status_check = PackageManager.split_symbol_name('COMMON-LISP:*PACKAGE*') env = PackageManager.find(symbol_name, package_name, status_check) self.assertIsInstance(env, Environment) self.assertTrue('*PACKAGE*' in env) symbol_name, package_name, status_check = PackageManager.split_symbol_name('*PACKAGE*') env = PackageManager.find(symbol_name, package_name, status_check) self.assertIsInstance(env, Environment) self.assertTrue('*PACKAGE*' in env) # Checks an environment using *PACKAGE* in another package. symbol_name, package_name, status_check = PackageManager.split_symbol_name('COMMON-LISP-USER::*PACKAGE*') env = PackageManager.find(symbol_name, package_name, status_check) self.assertIsInstance(env, Environment) self.assertTrue('*PACKAGE*' in env) symbol_name, package_name, status_check = PackageManager.split_symbol_name('COMMON-LISP-USER:*PACKAGE*') env = PackageManager.find(symbol_name, package_name, status_check) self.assertIsInstance(env, Environment) self.assertTrue('*PACKAGE*' in env)
def expand(cls, forms, var_env, func_env, macro_env): if not isinstance(forms, Cons): # If an atom is given, returns itself. return forms elif isinstance(forms.car, Symbol): # and forms.car.value in macro_env: # Gets symbol_name, package_name, and status_check. macro_name, package_name, status_check = PackageManager.split_symbol_name( forms.car.value) # Gets the macro binded by the symbol. # When package_name is None, the package becomes PackageManager.current_package. try: # Tries to get the function from lexical environment in current package. macro = macro_env.find(macro_name)[macro_name] except LookupError: try: macro = PackageManager.find(macro_name, package_name, status_check, env='MACRO')[macro_name] except LookupError: return Cons( forms.car, cls.recusive_expand(forms.cdr, var_env, func_env, macro_env)) return macro(forms.cdr, var_env, func_env, macro_env) else: return Cons(cls.expand(forms.car, var_env, func_env, macro_env), cls.expand(forms.cdr, var_env, func_env, macro_env))
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of FunctionSpecialOperator. """ if isinstance(forms.car, Cons) and forms.car.car is Symbol('LAMBDA'): return Lambda(forms.car.cdr, var_env, func_env, macro_env) else: # Gets symbol_name, package_name, and status_check. func_name, package_name, status_check = PackageManager.split_symbol_name( forms.car.value) # Gets the function binded by the symbol. try: # First, tries to get the value from lexical environment. return func_env.find(func_name)[func_name] except LookupError: # If LookupError is raised, tries to get from another package. return PackageManager.find(func_name, package_name, status_check, env='FUNCTION')[func_name]
def testPackageManager_split_symbol_name(self): # PackageManager.split_symbol_name splits symbol_name including package_name # and returns status_check indicating whether it needs status check or not. # When symbol_name is not KEYWORD, symbol_name, package_name, status_check = PackageManager.split_symbol_name('COMMON-LISP::CAR') self.assertEqual(symbol_name, 'CAR') self.assertEqual(package_name, 'COMMON-LISP') self.assertFalse(status_check) symbol_name, package_name, status_check = PackageManager.split_symbol_name('COMMON-LISP:CAR') self.assertEqual(symbol_name, 'CAR') self.assertEqual(package_name, 'COMMON-LISP') self.assertTrue(status_check) symbol_name, package_name, status_check = PackageManager.split_symbol_name('CAR') self.assertEqual(symbol_name, 'CAR') self.assertEqual(package_name, None) self.assertFalse(status_check) # When symbol_name is KEYWORD, sybmol_name, package_name, status_check = PackageManager.split_symbol_name('KEYWORD::EXTERNAL') self.assertEqual(sybmol_name, ':EXTERNAL') self.assertEqual(package_name, 'KEYWORD') self.assertFalse(status_check) sybmol_name, package_name, status_check = PackageManager.split_symbol_name('KEYWORD:EXTERNAL') self.assertEqual(sybmol_name, ':EXTERNAL') self.assertEqual(package_name, 'KEYWORD') self.assertFalse(status_check) sybmol_name, package_name, status_check = PackageManager.split_symbol_name(':EXTERNAL') self.assertEqual(sybmol_name, ':EXTERNAL') self.assertEqual(package_name, 'KEYWORD') self.assertFalse(status_check)