示例#1
0
    def compile_apply(self, source_obj: pair, tc, cont):
        """
        Compile a runtime function apply expression.
        """

        tc = tc and self.tco_enabled and not self.generator

        head, tail = source_obj

        if tc and self.self_ref and \
           is_symbol(head) and (str(head) == self.name):
            return tcf(self.compile_tcr_apply, source_obj, tc, cont)

        pos = source_obj.get_position()

        if is_pair(head):
            # @trampoline
            def ccp(new_head, tc):
                # Continue Compiling Pair. This is how we finish
                # compiling a function invocation after first
                # compiling the head

                if new_head is None:
                    # the original head pair compiled down to a None,
                    # which means it pushed bytecode and left a value
                    # on the stack. Complete the apply based on that.
                    return tcf(self.complete_apply, tail, pos, tc, cont)
                else:
                    # the original head pair was transformed, so now
                    # we need to start over in a new compile_pair call
                    # using a newly assembled expression.
                    expr = pair(new_head, tail)
                    expr.set_position(pos)
                    return tcf(self.compile_pair, expr, tc, cont)

            # we need to compile the head first, to figure out if it
            # expands into a symbolic reference or something. We'll
            # use ccp as a temporary continuation. Note that the
            # evaluation of the head of the pair is never a tailcall
            # itself, even if it would be a tailcall to apply it as a
            # function afterwards.
            return tcf(self.compile_pair, head, False, ccp)

        elif tc:
            self.declare_tailcall()
            self.pseudop_get_global(_symbol_tailcall_full)
            return tcf(self.complete_apply, source_obj, pos, False, cont)

        else:
            self.add_expression(head)
            return tcf(self.complete_apply, tail, pos, tc, cont)
示例#2
0
    def compile_apply(self, source_obj: pair, tc, cont):
        """
        Compile a runtime function apply expression.
        """

        tc = tc and self.tco_enabled and not self.generator

        head, tail = source_obj

        if tc and self.self_ref and \
           is_symbol(head) and (str(head) == self.name):
            return tcf(self.compile_tcr_apply, source_obj, tc, cont)

        pos = source_obj.get_position()

        if is_pair(head):
            # @trampoline
            def ccp(new_head, tc):
                # Continue Compiling Pair. This is how we finish
                # compiling a function invocation after first
                # compiling the head

                if new_head is None:
                    # the original head pair compiled down to a None,
                    # which means it pushed bytecode and left a value
                    # on the stack. Complete the apply based on that.
                    return tcf(self.complete_apply, tail, pos, tc, cont)
                else:
                    # the original head pair was transformed, so now
                    # we need to start over in a new compile_pair call
                    # using a newly assembled expression.
                    expr = pair(new_head, tail)
                    expr.set_position(pos)
                    return tcf(self.compile_pair, expr, tc, cont)

            # we need to compile the head first, to figure out if it
            # expands into a symbolic reference or something. We'll
            # use ccp as a temporary continuation. Note that the
            # evaluation of the head of the pair is never a tailcall
            # itself, even if it would be a tailcall to apply it as a
            # function afterwards.
            return tcf(self.compile_pair, head, False, ccp)

        elif tc:
            self.declare_tailcall()
            self.pseudop_get_global(_symbol_tailcall_full)
            return tcf(self.complete_apply, source_obj, pos, False, cont)

        else:
            self.add_expression(head)
            return tcf(self.complete_apply, tail, pos, tc, cont)
示例#3
0
    def compile_keyword(self, kwd: keyword, tc, cont):
        """
        Compile a keyword expression
        """

        source = cons(_symbol_keyword, str(kwd), nil)
        return tcf(self.compile, source, False, cont)
示例#4
0
    def compile_keyword(self, kwd: keyword, tc, cont):
        """
        Compile a keyword expression
        """

        source = cons(_symbol_keyword, str(kwd), nil)
        return tcf(self.compile, source, False, cont)
示例#5
0
            def ccp(new_head, tc):
                # Continue Compiling Pair. This is how we finish
                # compiling a function invocation after first
                # compiling the head

                if new_head is None:
                    # the original head pair compiled down to a None,
                    # which means it pushed bytecode and left a value
                    # on the stack. Complete the apply based on that.
                    return tcf(self.complete_apply, tail, pos, tc, cont)
                else:
                    # the original head pair was transformed, so now
                    # we need to start over in a new compile_pair call
                    # using a newly assembled expression.
                    expr = pair(new_head, tail)
                    expr.set_position(pos)
                    return tcf(self.compile_pair, expr, tc, cont)
示例#6
0
            def ccp(new_head, tc):
                # Continue Compiling Pair. This is how we finish
                # compiling a function invocation after first
                # compiling the head

                if new_head is None:
                    # the original head pair compiled down to a None,
                    # which means it pushed bytecode and left a value
                    # on the stack. Complete the apply based on that.
                    return tcf(self.complete_apply, tail, pos, tc, cont)
                else:
                    # the original head pair was transformed, so now
                    # we need to start over in a new compile_pair call
                    # using a newly assembled expression.
                    expr = pair(new_head, tail)
                    expr.set_position(pos)
                    return tcf(self.compile_pair, expr, tc, cont)
示例#7
0
    def compile(self, compiler, source_obj, tc, cont):
        expanded = self.expand()
        expanded = _symbol_None if expanded is None else expanded

        if is_pair(source_obj):
            called_by, source = source_obj
            res = cons(expanded, source)
            fill_position(res, source_obj.get_position())
            expanded = res

        return tcf(cont, expanded, tc)
示例#8
0
    def compile(self, compiler, source_obj, tc, cont):
        expanded = self.expand()
        expanded = _symbol_None if expanded is None else expanded

        if is_pair(source_obj):
            called_by, source = source_obj
            res = cons(expanded, source)
            fill_position(res, source_obj.get_position())
            expanded = res

        return tcf(cont, expanded, tc)
示例#9
0
    def complete_tcr_apply(self, cont):
        # print("completing a tcr apply")

        non_tcr = self.gen_label()

        self.pseudop_jump_if_true_or_pop(non_tcr)
        self.pseudop_jump(0)

        self.pseudop_label(non_tcr)
        self.pseudop_unpack_sequence(1)
        self.declare_tailcall()

        return tcf(cont, None, False)
示例#10
0
    def compile_tcr_apply(self, source_obj: pair, tc, cont):
        assert tc

        # print("compiling a tcr apply", source_obj)

        pos = source_obj.get_position()

        maybe = self.helper_inline_tcr(source_obj)
        if maybe:
            fun, args = source_obj
            return tcf(self.complete_apply, args, pos, True, cont)

        else:
            def ccp(done_source, tc):
                assert done_source is None
                return tcf(self.complete_tcr_apply, cont)

            tcr_source = cons(self.self_ref, source_obj)
            tcr_source.set_position(pos)

            self.pseudop_get_global(_symbol_tcr_frame)
            return tcf(self.complete_apply, tcr_source, pos, False, ccp)
示例#11
0
    def complete_tcr_apply(self, cont):
        # print("completing a tcr apply")

        non_tcr = self.gen_label()

        self.pseudop_jump_if_true_or_pop(non_tcr)
        self.pseudop_jump(0)

        self.pseudop_label(non_tcr)
        self.pseudop_unpack_sequence(1)
        self.declare_tailcall()

        return tcf(cont, None, False)
示例#12
0
    def compile_pair(self, source_obj: pair, tc, cont):
        """
        Compile a pair expression. This will become either a literal nil,
        a macro expansion, a special invocation, or a runtime function
        application.
        """

        if is_nil(source_obj):
            return tcf(self.compile_nil, source_obj, tc, cont)

        if not is_proper(source_obj):
            # print("** WUT", self, source_obj, tc, cont)
            msg = "cannot evaluate improper lists as expressions"
            raise self.error(msg, source_obj)

        self.pseudop_position_of(source_obj)

        head, tail = source_obj

        if is_symbol(head) or is_lazygensym(head):
            comp = self.find_compiled(head)
            if comp:
                # the head of the pair is a symbolic reference which
                # resolved to a compile-time object. Invoke that.
                return tcf(comp.compile, self, source_obj, tc, cont)

            else:
                return tcf(self.compile_apply, source_obj, tc, cont)

        elif is_pair(head):
            return tcf(self.compile_apply, source_obj, tc, cont)

        else:
            # TODO: should this be a compile-time error? If we have
            # something that isn't a symbolic reference or isn't a
            # pair, then WTF else would it be? Let's just let it break
            # at runtime, for now.
            return tcf(self.compile_apply, source_obj, tc, cont)
示例#13
0
    def compile_pair(self, source_obj: pair, tc, cont):
        """
        Compile a pair expression. This will become either a literal nil,
        a macro expansion, a special invocation, or a runtime function
        application.
        """

        if is_nil(source_obj):
            return tcf(self.compile_nil, source_obj, tc, cont)

        if not is_proper(source_obj):
            # print("** WUT", self, source_obj, tc, cont)
            msg = "cannot evaluate improper lists as expressions"
            raise self.error(msg, source_obj)

        self.pseudop_position_of(source_obj)

        head, tail = source_obj

        if is_symbol(head) or is_lazygensym(head):
            comp = self.find_compiled(head)
            if comp:
                # the head of the pair is a symbolic reference which
                # resolved to a compile-time object. Invoke that.
                return tcf(comp.compile, self, source_obj, tc, cont)

            else:
                return tcf(self.compile_apply, source_obj, tc, cont)

        elif is_pair(head):
            return tcf(self.compile_apply, source_obj, tc, cont)

        else:
            # TODO: should this be a compile-time error? If we have
            # something that isn't a symbolic reference or isn't a
            # pair, then WTF else would it be? Let's just let it break
            # at runtime, for now.
            return tcf(self.compile_apply, source_obj, tc, cont)
示例#14
0
    def compile_tcr_apply(self, source_obj: pair, tc, cont):
        assert tc

        # print("compiling a tcr apply", source_obj)

        pos = source_obj.get_position()

        maybe = self.helper_inline_tcr(source_obj)
        if maybe:
            fun, args = source_obj
            return tcf(self.complete_apply, args, pos, True, cont)

        else:

            def ccp(done_source, tc):
                assert done_source is None
                return tcf(self.complete_tcr_apply, cont)

            tcr_source = cons(self.self_ref, source_obj)
            tcr_source.set_position(pos)

            self.pseudop_get_global(_symbol_tcr_frame)
            return tcf(self.complete_apply, tcr_source, pos, False, ccp)
示例#15
0
    def _compile_cont(self, source_obj, tc):
        """
        The default continuation for compile. If the result was a new
        source object (anything other than None), will restart the
        compile.
        """

        if source_obj is None:
            # None explicitly means that the compilation resulted in
            # no new forms, so we're done.
            return None
        else:
            # anything else is a transformation, and needs to be
            # compiled.
            return tcf(self.compile, source_obj, tc, None)
示例#16
0
    def compile(self, compiler, source_obj, tc, cont):
        called_by, source = source_obj

        if self._proper:
            position = source_obj.get_position()
            args, kwargs = simple_parameters(source, position)
            expr = self.expand(*args, **kwargs)

        else:
            expr = self.expand(*source.unpack())

        expr = _symbol_None if expr is None else expr

        fill_position(expr, source_obj.get_position())
        return tcf(cont, expr, tc)
示例#17
0
    def _compile_cont(self, source_obj, tc):
        """
        The default continuation for compile. If the result was a new
        source object (anything other than None), will restart the
        compile.
        """

        if source_obj is None:
            # None explicitly means that the compilation resulted in
            # no new forms, so we're done.
            return None
        else:
            # anything else is a transformation, and needs to be
            # compiled.
            return tcf(self.compile, source_obj, tc, None)
示例#18
0
    def compile_symbol(self, sym: Symbol, tc, cont):
        """
        Compile a symbol expression. This can result in a constant for
        certain specialty Python values (None, True, False, and ...)

        Dotted symbols will be compiled into attr calls. Non-dotted
        symbols will be compiled into variable references.

        If a symbol correlates to an Alias in the module namespace,
        then that alias will be expanded and compilation will continue
        from the expanded form.
        """

        comp = self.find_compiled(sym)
        if comp and is_alias(comp):
            return tcf(comp.compile, self, sym, tc, cont)

        elif sym is _symbol_None:
            return tcf(self.compile_constant, None, tc, cont)

        elif sym is _symbol_True:
            return tcf(self.compile_constant, True, tc, cont)

        elif sym is _symbol_False:
            return tcf(self.compile_constant, False, tc, cont)

        elif sym is _symbol_ellipsis:
            return tcf(self.compile_constant, ..., tc, cont)

        elif is_lazygensym(sym):
            return tcf(cont, self.pseudop_get_var(sym), tc)

        else:
            ex = sym.rsplit(".", 1)
            if len(ex) == 1:
                return tcf(cont, self.pseudop_get_var(sym), None)
            else:
                source = cons(_symbol_attr, *ex, nil)
                return tcf(self.compile, source, tc, cont)
示例#19
0
    def compile_symbol(self, sym: Symbol, tc, cont):
        """
        Compile a symbol expression. This can result in a constant for
        certain specialty Python values (None, True, False, and ...)

        Dotted symbols will be compiled into attr calls. Non-dotted
        symbols will be compiled into variable references.

        If a symbol correlates to an Alias in the module namespace,
        then that alias will be expanded and compilation will continue
        from the expanded form.
        """

        comp = self.find_compiled(sym)
        if comp and is_alias(comp):
            return tcf(comp.compile, self, sym, tc, cont)

        elif sym is _symbol_None:
            return tcf(self.compile_constant, None, tc, cont)

        elif sym is _symbol_True:
            return tcf(self.compile_constant, True, tc, cont)

        elif sym is _symbol_False:
            return tcf(self.compile_constant, False, tc, cont)

        elif sym is _symbol_ellipsis:
            return tcf(self.compile_constant, ..., tc, cont)

        elif is_lazygensym(sym):
            return tcf(cont, self.pseudop_get_var(sym), tc)

        else:
            ex = sym.rsplit(".", 1)
            if len(ex) == 1:
                return tcf(cont, self.pseudop_get_var(sym), None)
            else:
                source = cons(_symbol_attr, *ex, nil)
                return tcf(self.compile, source, tc, cont)
示例#20
0
    def compile(self, compiler, source_obj, tc, cont):
        called_by, source = source_obj

        if self._proper:
            position = source_obj.get_position()
            args, kwargs = simple_parameters(source, position)
            try:
                expr = self.expand(*args, **kwargs)
            except Exception as exc:
                work = MacroException(self.__name__, exc)
                work = work.with_traceback(exc.__traceback__)
                raise work from None

        else:
            expr = self.expand(*source.unpack())

        expr = _symbol_None if expr is None else expr

        fill_position(expr, source_obj.get_position())
        return tcf(cont, expr, tc)
示例#21
0
    def compile(self, source_obj, tc, cont):
        """
        Compile a supported source object into an expression.

        pair, symbol, keyword, and the pythonic constant types are
        valid source obj types.
        """

        tc = self.tco_enabled and tc

        if is_pair(source_obj):
            dispatch = self.compile_pair
        elif is_symbol(source_obj) or is_lazygensym(source_obj):
            dispatch = self.compile_symbol
        elif is_keyword(source_obj):
            dispatch = self.compile_keyword
        elif isinstance(source_obj, CONST_TYPES):
            dispatch = self.compile_constant
        else:
            msg = "Unsupported source object %r" % source_obj
            raise self.error(msg, source_obj)

        return tcf(dispatch, source_obj, tc, cont or self._compile_cont)
示例#22
0
    def compile_constant(self, value: Constant, tc, cont):
        """
        Compile a constant value expression
        """

        return tcf(cont, self.pseudop_const(value), tc)
示例#23
0
 def compile(self, compiler, source_obj, tc, cont):
     result = self.compile_impl(compiler, source_obj, tc)
     return tcf(cont, result, tc)
示例#24
0
 def ccp(done_source, tc):
     assert done_source is None
     return tcf(self.complete_tcr_apply, cont)
示例#25
0
 def ccp(done_source, tc):
     assert done_source is None
     return tcf(self.complete_tcr_apply, cont)
示例#26
0
    def compile_constant(self, value: Constant, tc, cont):
        """
        Compile a constant value expression
        """

        return tcf(cont, self.pseudop_const(value), tc)
示例#27
0
 def compile(self, compiler, source_obj, tc, cont):
     result = self.compile_impl(compiler, source_obj, tc)
     return tcf(cont, result, tc)
示例#28
0
    def compile_nil(self, nilv: nil, tc, cont):
        """
        Compile a literal nil expression
        """

        return tcf(cont, self.pseudop_get_global(_symbol_nil), tc)
示例#29
0
    def compile_nil(self, nilv: nil, tc, cont):
        """
        Compile a literal nil expression
        """

        return tcf(cont, self.pseudop_get_global(_symbol_nil), tc)