Example #1
0
    def program(self):
        e = SetupEnvironment()
        e = e.env_extend()
        tree = self.opt_form_list(e)

        if len(self.delays) > 0:
            raise ParseError("Variables used, but never defined: %s" % str(self.delays))

        return tree
Example #2
0
 def __init__(self, args=None):
     self.args = args
     self.global_env = SetupEnvironment(args)
     self.repl_env = self.global_env.env_extend()
Example #3
0
class Evaluator:
    def __init__(self, args=None):
        self.args = args
        self.global_env = SetupEnvironment(args)
        self.repl_env = self.global_env.env_extend()

    def eval_swndl(self, text):
        l = Lexer(StringIO(text))
        p = Parser(l)
        tree = p.program()
        return self.eval(tree, self.repl_env)

    def eval(self, tree, env):
        if tree is None:
            return

        t = tree.val_type

        if t == Types.kw_def:
            return self.eval_def(tree, env)
        elif t == Types.kw_lambda:
            return self.eval_lambda(tree, env)
        elif t == Types.kw_set:
            return self.eval_set(tree, env)
        elif t == Types.kw_if:
            return self.eval_if(tree, env)
        elif t == Types.kw_elif:
            return self.eval_if(tree, env)
        elif t == Types.kw_else:
            return self.eval_else(tree, env)
        elif t == Types.colon:
            return self.eval(tree.right, env)
        elif t == Types.form_list:
            return self.eval_form_list(tree, env)
        elif t == Types.obracket:
            return self.eval_tuple(tree, env)
        elif t == Types.quote:
            return self.eval_quote(tree, env)
        elif t == Types.newline:
            pass
        elif t == Types.integer:
            return int(tree.val)
        elif t == Types.string:
            return str(tree.val)[1:-1]
        elif t == Types.symbol:
            return str(tree.val)
        elif t == Types.variable:
            # proc_call
            if tree.left and tree.left.val_type == Types.oparen:
                return self.eval_proc_call(tree, env)

            if tree.left and tree.left.val_type == Types.dot:
                return self.eval_dot_call(tree, env)

            return self.eval_variable(tree, env)
        elif t == Types.form:
            return self.eval(tree.left, env)
        else:
            raise Exception("Bad expression!")

    def eval_def(self, tree, env):
        var = tree.left.val
        val = self.eval(tree.right, env)
        env.env_insert(var, val)

    def eval_lambda(self, tree, env):
        return Closure(parameters=self.get_params(tree.left), body=tree.right, env=env)

    def get_params(self, tree):
        p = list()
        # sometimes the tree can be empty
        if tree:
            t = tree
            while t:
                p.append(t.left.val)
                t = t.right

        return p

    def eval_set(self, tree, env):
        var = tree.left.val
        val = self.eval(tree.right, env)
        env.env_update(var, val)

    def eval_if(self, tree, env):
        if self.eval(tree.left, env):
            return self.eval(tree.right.left, env)
        else:
            return self.eval(tree.right.right, env)

    def eval_else(self, tree, env):
        return self.eval(tree.right, env)

    def eval_form_list(self, tree, env):
        result = None

        t = tree
        while t:
            result = self.eval(t.left, env)
            t = t.right

        return result

    def get_expr_list(self, tree):
        # not sure about this
        # expr_list is really a list of args for proc_call
        e = list()
        # sometimes the tree can be empty
        if tree:
            t = tree.right

            while t:
                e.append(t.left)
                t = t.right

        return e

    def eval_datum_list(self, tree, env):
        # not sure about this
        d = list()

        # sometimes the tree can be empty
        if tree:
            t = tree.right

            while t:
                d.append(self.eval(t.left, env))
                t = t.right

        return d

    def eval_quote(self, tree, env):
        return self.eval(tree.right, env)

    def eval_tuple(self, tree, env):
        # maybe convert this to a list structure of cons?
        return list(self.eval_datum_list(tree, env))

    def eval_variable(self, tree, env):
        return env.env_lookup(tree.val)

    def eval_args(self, args, env):
        e = list()
        for arg in args:
            e.append(self.eval(arg, env))
        return e

    def eval_proc_call(self, tree, env):
        #    closure = self.eval(getFuncCallName(t),env);
        #    args = getFuncCallArgs(t);
        #    params = getClosureParams(closure);
        #    body = getClosureBody(closure);
        #    senv = getClosureEnvironment(closure);
        #    eargs = evalArgs(args,env);
        #    xenv = EnvExtend(senv,params,eargs);

        closure = env.env_lookup(tree.val)
        args = self.get_expr_list(tree)
        eargs = self.eval_args(args, env)
        if type(closure) == Plosure:
            # this star is very important since Guido is an idiot.
            # it's the equivalent of using apply(procedure, args) in Py2
            return closure.procedure(*eargs)
        elif type(closure) == Closure:
            params = closure.parameters
            body = closure.body
            senv = closure.env

            pairs = list()
            if len(params) > len(eargs):
                raise EvalError("Not enough arguments to call %s" % tree.val, tree)
            elif len(params) < len(eargs):
                raise EvalError("Too many arguments to call %s" % tree.val, tree)

            for i in range(0, len(params)):
                pairs.append((params[i], eargs[i]))

            xenv = senv.env_extend(pairs)
            xenv.env_insert("self", xenv)

            return self.eval(body, xenv)

    def eval_dot_call(self, tree, env):
        obj = env.env_lookup(tree.val)
        return self.eval(tree.right, obj)