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 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 __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 IfSpecialOperator. """ from clispy.evaluator import Evaluator # Sets test-form, then-form and else-form. test_form, then_form, else_form = forms.car, forms.cdr.car, forms.cdr.cdr.car # If-then-else if Evaluator.eval(test_form, var_env, func_env, macro_env) is Null(): return Evaluator.eval(else_form, var_env, func_env, macro_env) else: return Evaluator.eval(then_form, var_env, 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 __call__(self, forms, var_env, func_env, macro_env): """Behavior of PrognSpecialOperator. """ from clispy.evaluator import Evaluator # The values of eatch form but the last are discarded. while forms is not Null(): last = Evaluator.eval(forms.car, var_env, func_env, macro_env) forms = forms.cdr return last
def __call__(self, forms, var_env, func_env, macro_env): """Behavior of ReturnFromSpecialOperator. """ from clispy.evaluator import Evaluator block_name, body = forms.car.value, forms.cdr.car # Sets return value. retval = Evaluator.eval(body, var_env, func_env, macro_env) # name is param of lambda and have throw function as value in call/cc. return var_env.find(block_name)[block_name](retval)
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 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 eval_forms(cls, forms, var_env, func_env, macro_env): """Evaluates forms before these are given to functions as arguments. Returns: Cons. """ from clispy.evaluator import Evaluator args = [] while forms is not Null(): args.append(Evaluator.eval(forms.car, var_env, func_env, macro_env)) forms = forms.cdr return Cons.tocons(args)
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)