Beispiel #1
0
    def resume_compilation(self):
        lambda_walker = SkeletonWalker(self.walker)
        w_formals = self.expr_list[0]
        lambda_body = self.expr_list[1:]

        # decoding lambda arguments and test them
        arg_list = []
        w_rest = scmlist2py(w_formals, arg_list)
        for w_argname in arg_list:
            if not w_argname.is_symbol():
                raise SchemeSyntaxError('lambda -- formal varargs should be '
                    'nothing but a symbol, got %s' % w_argname.to_string())

        lambda_walker.nb_args = len(arg_list) # set positional argcount
        if w_rest.is_null():
            lambda_walker.varargs_p = False
        else:
            if not w_rest.is_symbol():
                raise SchemeSyntaxError('lambda -- formal varargs should be '
                        'nothing but a symbol, got %s' % w_rest.to_string())
            else:
                lambda_walker.varargs_p = True

        # fill in the frame slots using those arguments
        for w_argname in arg_list:
            frame_slot_repr = FrameValueRepr(lambda_walker.alloc_frame_slot())
            lambda_walker.local_variables[w_argname.to_string()] \
                    = frame_slot_repr

        # if vararg
        if lambda_walker.varargs_p:
            frame_slot_repr = FrameValueRepr(lambda_walker.alloc_frame_slot())
            lambda_walker.local_variables[w_rest.to_string()] \
                    = frame_slot_repr

        # compile the body. XXX: create a global skeleton table like lua?
        lambda_walker.visit_list_of_expr(lambda_body)
        w_lambda_skeleton = lambda_walker.to_closure_skeleton()
        self.walker.instrs[self.instrindex] = BuildClosure(
            self.dest_val_repr.to_index(),
            self.walker.new_skel_slot(w_lambda_skeleton))
Beispiel #2
0
    def visit_application(self, w_proc, w_args, flag):
        lst = []
        w_rest = scmlist2py(w_args, lst)
        if not w_rest.is_null():
            raise SchemeSyntaxError('application -- not a well-formed list')
        # allocate len(lst) + 1 frame slots
        # XXX: ensure they sit together.
        proc_slot = FrameValueRepr(self.alloc_frame_slot())
        arg_slots = [FrameValueRepr(self.alloc_frame_slot())
                for i in xrange(len(lst))]

        # evaluate the proc and the args
        proc_visit_flag = CompilationFlag(0, desired_destination=proc_slot)
        proc_val_repr = self.visit(w_proc, proc_visit_flag)
        self.set_frame_slot(proc_slot, proc_val_repr) # could be no-op

        for i in xrange(len(lst)):
            # since enumerate is not supported in RPython...
            w_expr = lst[i]
            dest_slot = arg_slots[i]
            arg_visit_flag = CompilationFlag(0, desired_destination=dest_slot)
            arg_val_repr = self.visit(w_expr, arg_visit_flag)
            self.set_frame_slot(dest_slot, arg_val_repr)

        if flag.has_dest():
            result_value_repr = flag.get_dest()
        else:
            result_value_repr = FrameValueRepr(self.alloc_frame_slot())
        # call and return
        if flag.has_tco():
            self.emit(TailCall(result_value_repr.to_index(),
                    proc_slot.to_index(), len(lst)))
        else:
            self.emit(Call(result_value_repr.to_index(),
                    proc_slot.to_index(), len(lst)))
        return result_value_repr
Beispiel #3
0
    def visit_special_form(self, w_proc, w_args, flag):
        sval = w_proc.to_string()
        if sval == 'define':
            # @see visit_binding
            lst = []
            w_rest = scmlist2py(w_args, lst)
            if len(lst) != 2 or not w_rest.is_null(): # (define name expr)
                raise SchemeSyntaxError, 'define require 2 args'

            w_name = lst[0]
            if not w_name.is_symbol():
                raise SchemeSyntaxError, ('define require the first arg '
                        'to be symbol -- got %s' % w_name.to_string())
            w_expr = lst[1]
            value_repr = self.visit(w_expr)
            self.visit_binding(w_name, value_repr) # create binding for define
            return ConstValueRepr(self.new_const_slot(w_unspecified))

        elif sval == 'set!':
            lst = []
            w_rest = scmlist2py(w_args, lst)
            if len(lst) != 2 or not w_rest.is_null(): # (define name expr)
                raise SchemeSyntaxError, 'set! require 2 args'

            w_name = lst[0]
            if not w_name.is_symbol():
                raise SchemeSyntaxError, ('set! require the first arg '
                        'to be symbol -- got %s' % w_name.to_string())
            w_expr = lst[1]
            value_repr = self.visit(w_expr)
            self.visit_rebind(w_name, value_repr) # change binding for define
            return ConstValueRepr(self.new_const_slot(w_unspecified))

        elif sval == 'if':
            # (if pred iftrue [else])
            if flag.has_dest():
                result_value_repr = flag.get_dest()
            else:
                result_value_repr = FrameValueRepr(self.alloc_frame_slot())

            lst = []
            w_rest = scmlist2py(w_args, lst)
            if len(lst) not in (2, 3) or not w_rest.is_null():
                raise SchemeSyntaxError, 'if require 2 to 3 args'

            w_pred = lst[0]
            w_iftrue = lst[1]

            # predicate value repr
            # XXX: Note that this is a temporary variable and can be reused
            #      if we return this frame slot to the allocator.
            pred_local_val = self.cast_to_local(self.visit(w_pred))

            # saved instr index, for jump to else
            iftrue_branch_instr_index = len(self.instrs)
            self.instrs.append(None) # branch length to be calculated

            # if_true instrs
            iftrue_result_repr = self.visit(w_iftrue, flag)
            self.set_frame_slot(result_value_repr, iftrue_result_repr)
            iftrue_branch_jumpby = (len(self.instrs) -
                    iftrue_branch_instr_index)
            self.instrs[iftrue_branch_instr_index] = BranchIfFalse(
                    pred_local_val.to_index(), iftrue_branch_jumpby)

            iffalse_branch_instr_index = len(self.instrs)
            self.instrs.append(None) # branch length to be calculated
            if len(lst) == 2:
                self.set_frame_slot(result_value_repr,
                        ConstValueRepr(self.new_const_slot(w_unspecified)))
            else: # has else
                w_iffalse = lst[2]
                iffalse_result_repr = self.visit(w_iffalse, flag)
                self.set_frame_slot(result_value_repr, iffalse_result_repr)

            iffalse_branch_jumpby = (len(self.instrs) -
                    iffalse_branch_instr_index - 1)
            self.instrs[iffalse_branch_instr_index] = Branch(
                    iffalse_branch_jumpby)
            return result_value_repr

        elif sval == 'quote':
            # (quote datum)
            lst = []
            w_rest = scmlist2py(w_args, lst)
            if len(lst) != 1 or not w_rest.is_null():
                raise SchemeSyntaxError, 'quote require 1 arg'
            return ConstValueRepr(self.new_const_slot(lst[0]))

        elif sval == 'lambda':
            lst = []
            w_rest = scmlist2py(w_args, lst)
            if not w_rest.is_null():
                raise SchemeSyntaxError, 'lambda -- not a well-formed list'
            if len(lst) < 2:
                raise SchemeSyntaxError, 'lambda -- missing expression'
            if flag.has_dest():
                frame_val_repr = flag.get_dest()
            else:
                frame_val_repr = FrameValueRepr(self.alloc_frame_slot())
            current_instr_pos = len(self.instrs)
            self.instrs.append(None)
            # compile the lambdas in the end
            self.deferred_lambdas.append(DeferredLambdaCompilation(
                self, lst, current_instr_pos, frame_val_repr))
            return frame_val_repr

        elif sval == 'begin':
            lst = []
            w_rest = scmlist2py(w_args, lst)
            if not w_rest.is_null():
                raise SchemeSyntaxError, 'begin -- not a well-formed list'
            for i, w_expr in enumerate(lst):
                if i != len(lst) - 1:
                    self.visit(w_expr)
                else:
                    return self.visit(w_expr, flag)
            # when there is no args: return unspecified
            return ConstValueRepr(self.new_const_slot(w_unspecified))

        else:
            raise ValueError, 'not a special form'