Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
    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)