def __call__(self, forms, var_env, func_env, macro_env): """Behavior of IfSystemMacro. """ from clispy.expander import Expander # If else_form is Null, then else_form is set to Null. test_form, then_form, else_form = forms.car, forms.cdr.car, forms.cdr.cdr.car # Expands body recursively. test_form = Expander.expand(test_form, var_env, func_env, macro_env) then_form = Expander.expand(then_form, var_env, func_env, macro_env) else_form = Expander.expand(else_form, var_env, func_env, macro_env) forms = Cons(Symbol('IF'), Cons(test_form, Cons(then_form, Cons(else_form, Null())))) return forms
def testLambda_call_expand_argument(self): """Arguments are expanded before the call method is executed. """ # Makes an instance of Lambda. forms = Parser.parse('((x) (* x x x))') lambda_func = Lambda(forms, PackageManager.current_package.env['VARIABLE'], PackageManager.current_package.env['FUNCTION'], PackageManager.current_package.env['MACRO']) # Define macro. forms = Parser.parse('(defmacro cube (x) `(* ,x ,x ,x))') exp = Expander.expand(forms, PackageManager.current_package.env['VARIABLE'], PackageManager.current_package.env['FUNCTION'], PackageManager.current_package.env['MACRO']) Evaluator.eval(exp, PackageManager.current_package.env['VARIABLE'], PackageManager.current_package.env['FUNCTION'], PackageManager.current_package.env['MACRO']) # Checks call. retval = lambda_func( Parser.parse('((cube 2))'), # an argument is expression. PackageManager.current_package.env['VARIABLE'], PackageManager.current_package.env['FUNCTION'], PackageManager.current_package.env['MACRO']) # Checks return value. self.assertTrue(retval, Integer(512))
def testExpanderUnitTestCase_expand_atom(self): # Sets atom. forms = Parser.parse('3.14') # Expand forms. forms = Expander.expand(forms, PackageManager.current_package.env['VARIABLE'], PackageManager.current_package.env['FUNCTION'], PackageManager.current_package.env['MACRO']) # Checks forms. self.assertEqual(forms, SingleFloat(3.14))
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of FletSystemMacro. """ from clispy.expander import Expander bindings, body = forms.car, forms.cdr # Expands body recursively. body = Expander.expand(body, var_env, macro_env, macro_env) # The body of flet has an implicit progn. forms = Cons(Symbol('FLET'), Cons(bindings, Cons(Cons(Symbol('PROGN'), body), Null()))) return forms
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of BlockSystemMacro. """ from clispy.expander import Expander name, body = forms.car, forms.cdr # Expands body recursively. body = Expander.expand(body, var_env, func_env, macro_env) # The body of a block has an implicit progn. forms = Cons(Symbol('BLOCK'), Cons(name, Cons(Cons(Symbol('PROGN'), body), Null()))) return forms
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of LambdaSystemMacro. """ from clispy.expander import Expander params, body = forms.car, forms.cdr # Expands body recursively. body = Expander.expand(body, var_env, func_env, macro_env) # The body of a lambda has an implicit progn. forms = Cons(Symbol('LAMBDA'), Cons(params, Cons(Cons(Symbol('PROGN'), body), Null()))) return forms
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of DefmacroSystemMacro. """ from clispy.expander import Expander name, params, body = forms.car, forms.cdr.car, forms.cdr.cdr # Expands body, recursively. body = Expander.expand(body, var_env, func_env, macro_env) # The value of the last form executed is returned as the expansion of the macro. body = Cons(Cons(Symbol('PROGN'), body), Null()) # The body of a defmacro has an implicit block. forms = Cons(Symbol('DEFMACRO'), Cons(name, Cons(params, Cons(Cons(Symbol('BLOCK'), Cons(name, body)), Null())))) return forms
def __init__(self, forms, var_env, func_env, macro_env): """Initialize Lambda. """ from clispy.evaluator import Evaluator from clispy.expander import Expander params, body = forms.car, forms.cdr.car # Binds params and args. self.params = [] while params is not Null(): if isinstance(params.car, Cons): self.params.append(params.car) else: self.params.append(params.car.value) params = params.cdr ################################################## # Accesser parameters ################################################## # Finds accessor and checks index. self.accessor_index = {} # Optional parameters. self.default_optional_args = [] if '&OPTIONAL' in self.params: self.accessor_index['&OPTIONAL'] = self.params.index('&OPTIONAL') self.params.pop(self.accessor_index['&OPTIONAL']) for param in self.params[self.accessor_index['&OPTIONAL']:]: if isinstance(param, Cons): # Expands and evaluates default value. exp = Expander.expand(param.cdr.car, var_env, func_env, macro_env) x = Evaluator.eval(exp, var_env, func_env, macro_env) # Sets a default value as an arguments self.default_optional_args.append(x) else: self.default_optional_args.append(Null()) # Rest parameters. if '&REST' in self.params: self.accessor_index['&REST'] = self.params.index('&REST') self.params.pop(self.accessor_index['&REST']) # Keyword parameters. self.default_keyword_args = {} if '&KEY' in self.params: self.accessor_index['&KEY'] = self.params.index('&KEY') self.params.pop(self.accessor_index['&KEY']) for param in self.params[self.accessor_index['&KEY']:]: if isinstance(param, Cons): # Expand and evaluate default value. exp = Expander.expand(param.cdr.car, var_env, func_env, macro_env) x = Evaluator.eval(exp, var_env, func_env, macro_env) # Sets a default value as an arguments self.default_keyword_args[param.car.value] = x else: # If param is not Cons, it is already value (str) of symbol. self.default_keyword_args[param] = Null() # Remove cons objects. for i, param in enumerate(self.params): if isinstance(param, Cons): self.params[i] = param.car.value # Binds forms. self.forms = body # Lexical environments self.var_env = var_env self.func_env = func_env self.macro_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)