Beispiel #1
0
        def gen_elif_elses(elif_else_elm):
            my_code = elif_else_elm.code
            if is_form(elif_else_elm, 'elif'):
                with GC.let(domain=ExDom):
                    my_condition_gen = GC.generate(my_code[1])

                my_body_gens = []
                for body_elm in my_code.iterate_from(2):
                    extend_body(my_body_gens, GC.generate(body_elm))

                if elif_else_elm.next is None:
                    return [astIf(my_condition_gen, my_body_gens, [])]
                else:
                    else_code = gen_elif_elses(elif_else_elm.next)
                    return [astIf(my_condition_gen, my_body_gens, else_code)]
            elif is_form(elif_else_elm, 'else'):
                my_body_gens = []
                for body_elm in my_code.iterate_from(1):
                    extend_body(my_body_gens, GC.generate(body_elm))
                return my_body_gens
            else:
                raise CodeGenerationError(
                    elif_else_elm.range,
                    "Unexpected element `%s` after first `elif` or `else` form within `if` form."
                    % (succinct_lisp_printer(elif_else_elm)))
Beispiel #2
0
    def generate(self, element:Element, GC:GenerationContext):


        acode = element.code

        func_specs = acode[1].code

        assert isinstance(func_specs[0].code, Identifier)

        function_name = func_specs[0].code.full_name

        arguments = self.generate_arguments(*func_specs[1:], GC=GC)

        body_elements = acode[2:]

        body_code = []
        with GC.let(domain=SDom):
            for body_element in body_elements:
                extend_body(body_code, GC.generate(body_element))

        decorators_code = []

        returns_code = None

        return ast.FunctionDef(function_name, arguments, body_code,
                               decorators_code, returns_code)
Beispiel #3
0
    def generate(self, element: Element, GC: GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        target_iter_element = acode[1]
        target_element = target_iter_element.code[0]
        iter_element = target_iter_element.code[1]

        with GC.let(domain=LValueDomain):
            target_code = GC.generate(target_element)

        with GC.let(domain=ExpressionDomain):
            iter_code = GC.generate(iter_element)

        if is_form(acode.last, "else"):
            raise NotImplementedError()

        body_codes = []
        for e in acode[2:]:
            extend_body(body_codes, GC.generate(e))

        return ast.For(
            target=target_code,
            iter=iter_code,
            body=body_codes,
            orelse=[],
        )
Beispiel #4
0
    def generate(self, element:Element, GC:GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        target_iter_element = acode[1]
        target_element = target_iter_element.code[0]
        iter_element = target_iter_element.code[1]

        with GC.let(domain=LValueDomain):
            target_code = GC.generate(target_element)

        with GC.let(domain=ExpressionDomain):
            iter_code = GC.generate(iter_element)

        if is_form(acode.last, "else"):
            raise NotImplementedError()

        body_codes = []
        for e in acode[2:]:
            extend_body(body_codes, GC.generate(e))


        return ast.For(target=target_code,
                      iter=iter_code,
                      body=body_codes,
                      orelse=[],
                      )
Beispiel #5
0
    def generate(self, element:Element, GC:GenerationContext):

        acode = element.code


        #name
        spec = acode[1]
        if isinstance(spec.code, Form):
            assert is_identifier(spec.code[0])
            class_name = spec.code[0].code.full_name

            with GC.let(domain=ExDom):
                base_classes_codes = []

                for base_class in spec.code[1:]:
                    extend_body(base_classes_codes, GC.generate(base_class))

        elif isinstance(spec.code, Identifier):
            class_name = spec.code.full_name
            base_classes_codes = []

        #keywords

        # "class keyword(arg, value)
        #  A keyword argument to a function call or class definition.
        #  arg is a raw string of the parameter name, value is a node to pass in."

        #starargs

        #kwargs


        body_elements = acode[3:]

        assert len(body_elements) > 0

        body_codes = []

        with GC.let(domain=StatementDomain):
            for body_statement in body_elements:
                extend_body(body_codes, GC.generate(body_statement))







        return ast.ClassDef(name=class_name,
                            bases=base_classes_codes,
                            keywords=[],
                            #starargs
                            #kwargs
                            body=body_codes,
                            decorator_list=[]
                            )
Beispiel #6
0
    def generate(self, element: Element, GC: GenerationContext):

        acode = element.code

        #name
        spec = acode[1]
        if isinstance(spec.code, Form):
            assert is_identifier(spec.code[0])
            class_name = spec.code[0].code.full_name

            with GC.let(domain=ExDom):
                base_classes_codes = []

                for base_class in spec.code[1:]:
                    extend_body(base_classes_codes, GC.generate(base_class))

        elif isinstance(spec.code, Identifier):
            class_name = spec.code.full_name
            base_classes_codes = []

        #keywords

        # "class keyword(arg, value)
        #  A keyword argument to a function call or class definition.
        #  arg is a raw string of the parameter name, value is a node to pass in."

        #starargs

        #kwargs

        body_elements = acode[3:]

        assert len(body_elements) > 0

        body_codes = []

        with GC.let(domain=StatementDomain):
            for body_statement in body_elements:
                extend_body(body_codes, GC.generate(body_statement))

        return ast.ClassDef(
            name=class_name,
            bases=base_classes_codes,
            keywords=[],
            #starargs
            #kwargs
            body=body_codes,
            decorator_list=[])
Beispiel #7
0
    def generate(self, element:Element, GC:GenerationContext):

        acode = element.code

        context_element = acode[1]
        context_element_code = context_element.code
        assert len(context_element_code) > 0

        with_items = []

        with GC.let(domain=ExpressionDomain):

            for ctxel in context_element_code:


                if is_form(ctxel.code, "as"):

                    ctxelcode = ctxel.code

                    assert len(ctxel) == 3
                    ctx_expr = GC.generate(ctxelcode[1])

                    opt_var = GC.generate(ctxelcode[2])

                    with_items.append(ast.withitem(context_expr=ctx_expr,
                                                   optional_vars=opt_var))

                else:

                    ctx_expr = GC.generate(ctxel)

                    with_items.append(ast.withitem(context_expr=ctx_expr,
                                                   optional_vars=None))

            body_items = []

            with GC.let(domain=SDom):

                for bodyel in acode[2:]:
                    extend_body(body_items, GC.generate(bodyel))


        return ast.With(items=with_items,
                        body=body_items)
Beispiel #8
0
    def generate(self, element: Element, GC: GenerationContext):

        acode = element.code

        context_element = acode[1]
        context_element_code = context_element.code
        assert len(context_element_code) > 0

        with_items = []

        with GC.let(domain=ExpressionDomain):

            for ctxel in context_element_code:

                if is_form(ctxel.code, "as"):

                    ctxelcode = ctxel.code

                    assert len(ctxel) == 3
                    ctx_expr = GC.generate(ctxelcode[1])

                    opt_var = GC.generate(ctxelcode[2])

                    with_items.append(
                        ast.withitem(context_expr=ctx_expr,
                                     optional_vars=opt_var))

                else:

                    ctx_expr = GC.generate(ctxel)

                    with_items.append(
                        ast.withitem(context_expr=ctx_expr,
                                     optional_vars=None))

            body_items = []

            with GC.let(domain=SDom):

                for bodyel in acode[2:]:
                    extend_body(body_items, GC.generate(bodyel))

        return ast.With(items=with_items, body=body_items)
Beispiel #9
0
        def gen_except_handler(except_elm):
            my_code = except_elm.code
            exception_elm = my_code[1]
            name = None
            if is_form(exception_elm, 'as'):
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm.code[1])
                my_exception_name_id = exception_elm.code[2]
                if not is_identifier(my_exception_name_id):
                    raise CodeGenerationError(my_exception_name_id.range, "Expected an identifier as exception name of `except` clause in `try` special-form.")
                name = my_exception_name_id.code.name
            else:
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm)

            body_gens = []
            for my_body_elm in my_code.iterate_from(2):
                extend_body(body_gens, GC.generate(my_body_elm))

            return ast.ExceptHandler(my_exception_type, name, body_gens)
Beispiel #10
0
    def generate(self, element:Element, GC:GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        testexpr_element = acode[1]

        with GC.let(domain=ExpressionDomain):

            testexpr_code = GC.generate(testexpr_element)

        if is_form(element.next, "else"):
            raise NotImplementedError()

        body_codes = []
        for e in acode[2:]:
            extend_body(body_codes, GC.generate(e))

        return ast.While(test=testexpr_code,
                         body=body_codes,
                         orelse=[])
Beispiel #11
0
        def gen_except_handler(except_elm):
            my_code = except_elm.code
            exception_elm = my_code[1]
            name = None
            if is_form(exception_elm, 'as'):
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm.code[1])
                my_exception_name_id = exception_elm.code[2]
                if not is_identifier(my_exception_name_id):
                    raise CodeGenerationError(
                        my_exception_name_id.range,
                        "Expected an identifier as exception name of `except` clause in `try` special-form."
                    )
                name = my_exception_name_id.code.name
            else:
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm)

            body_gens = []
            for my_body_elm in my_code.iterate_from(2):
                extend_body(body_gens, GC.generate(my_body_elm))

            return ast.ExceptHandler(my_exception_type, name, body_gens)
Beispiel #12
0
        def gen_elif_elses(elif_else_elm):
            my_code = elif_else_elm.code
            if is_form(elif_else_elm, 'elif'):
                with GC.let(domain=ExDom):
                    my_condition_gen = GC.generate(my_code[1])

                my_body_gens = []
                for body_elm in my_code.iterate_from(2):
                    extend_body(my_body_gens, GC.generate(body_elm))

                if elif_else_elm.next is None:
                    return [astIf(my_condition_gen, my_body_gens, [])]
                else:
                    else_code = gen_elif_elses(elif_else_elm.next)
                    return [astIf(my_condition_gen, my_body_gens, else_code)]
            elif is_form(elif_else_elm, 'else'):
                my_body_gens = []
                for body_elm in my_code.iterate_from(1):
                    extend_body(my_body_gens, GC.generate(body_elm))
                return my_body_gens
            else:
                raise CodeGenerationError(elif_else_elm.range,
                                          "Unexpected element `%s` after first `elif` or `else` form within `if` form." % (
                                          succinct_lisp_printer(elif_else_elm)))
Beispiel #13
0
    def generate(self, element: Element, GC: GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        # "Check that form is as above"
        #assert

        def gen_except_handler(except_elm):
            my_code = except_elm.code
            exception_elm = my_code[1]
            name = None
            if is_form(exception_elm, 'as'):
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm.code[1])
                my_exception_name_id = exception_elm.code[2]
                if not is_identifier(my_exception_name_id):
                    raise CodeGenerationError(
                        my_exception_name_id.range,
                        "Expected an identifier as exception name of `except` clause in `try` special-form."
                    )
                name = my_exception_name_id.code.name
            else:
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm)

            body_gens = []
            for my_body_elm in my_code.iterate_from(2):
                extend_body(body_gens, GC.generate(my_body_elm))

            return ast.ExceptHandler(my_exception_type, name, body_gens)

        body_gens, handlers, or_else, finally_body = [], [], None, None
        stage = 0  # 0 = body, 1 = except, 2 = else, 3 = finally
        names = {1: "except", 2: "else", 3: "finally"}
        for body_elm in acode.iterate_from(1):
            if is_form(body_elm, 'except'):
                if stage > 1:
                    raise CodeGenerationError(
                        body_elm.range,
                        "Found `except` clause after first `%s` in `try` special form."
                        % names[stage])
                else:
                    stage = 1
                except_handler = gen_except_handler(body_elm)
                handlers.append(except_handler)
            elif is_form(body_elm, 'else'):
                if stage > 1:
                    raise CodeGenerationError(
                        body_elm.range,
                        "Found `except` clause after first `%s` in `try` special form."
                        % names[stage])
                else:
                    stage = 2
                or_else = [
                    GC.generate(my_body_elm)
                    for my_body_elm in body_elm.code.iterate_from(1)
                ]
            elif is_form(body_elm, 'finally'):
                if stage > 2:
                    raise CodeGenerationError(
                        body_elm.range,
                        "Found `except` clause after first `%s` in `try` special form."
                        % names[stage])
                else:
                    stage = 3
                finally_body = []
                for my_body_elm in body_elm.code.iterate_from(1):
                    extend_body(finally_body, GC.generate(my_body_elm))
            else:
                if stage > 0:
                    raise CodeGenerationError(
                        body_elm.range,
                        "Found body clause after first `%s` in `try` special form."
                        % names[stage])
                body_gen = GC.generate(body_elm)
                extend_body(body_gens, body_gen)

        return ast.Try(body_gens, handlers, or_else, finally_body)
Beispiel #14
0
    def generate(self, element:Element, GC:GenerationContext):

        acode = element.code

        rawspecs = acode[1].code

        macro_name_element = rawspecs[0]

        macro_name = rawspecs[0].code.full_name
        macro_name_safe = "__macro_"+macro_name+"__"


        rawspec_element_param = rawspecs[1].code.full_name

        rawspec_context_param = rawspecs[2].code.full_name




        expand_body_elements = acode[2:]

        expand_body_code = []
        for b in expand_body_elements:
            extend_body(expand_body_code, GC.generate(b))
        # The... second-to-last form? of the original element should be
        #  responsible for generating (i.e. should return) code that will
        #  complete the macro expansion;
        #  the final statement executed in an .expand method would actually
        #  be doing the replacing
        #
        final_body_code = expand_body_code[-1]
        # element.replace(final_body_code)
        #ast.Call( ... )


        expand_args_code = ast.arguments(
            args=[ast.arg(arg="self"),
                  ast.arg(arg=rawspec_element_param,
                          annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="Element", ctx=ast.Load())),
                  ast.arg(arg=rawspec_context_param,
                          annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="ExpansionContext", ctx=ast.Load()))],
            kwonlyargs=[], defaults=[], kw_defaults=[]
        )



        expand_method_code = ast.FunctionDef(name="expand",
                                             args=expand_args_code,
                                             body=expand_body_code,
                                             decorator_list=[]
                                             )



        class_body_code = []

        # extend_body(class_body_code, ast.Import([ast.alias(name="anoky.module", asname="__aky__")]))

        extend_body(class_body_code, ast.Assign(targets=[ast.Name(id="HEADTEXT",
                                                            ctx=ast.Store())],
                                          value=ast.Str(macro_name)))

        extend_body(class_body_code, expand_method_code)





        classdef_code = ast.ClassDef(
                name=macro_name_safe,
                bases=[ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="Macro", ctx=ast.Load())],
                keywords=[], decorator_list=[],
                body=class_body_code)


        # __macros_macro_name__()
        instantiate_macro_code = ast.Call(func=ast.Name(id=macro_name_safe, ctx=ast.Load()),
                                          args=[], keywords=[])

        # EC.macro_table[macro_name]
        context_code = ast.Subscript(
                value=ast.Attribute(value=ast.Name(id="EC", ctx=ast.Load()),
                                    attr="macro_table", ctx=ast.Load()),
                slice=ast.Index(ast.Str(macro_name)), ctx=ast.Store())


        # __macros__[macro_name] = EC.macro_table[macro_name] = __macros_macro_name__()
        register_macro_code = ast.Assign(targets=[
            ast.Subscript(value=ast.Name(id="__macros__", ctx=ast.Load()),
                          slice=ast.Index(ast.Str(macro_name)),
                          ctx=ast.Store()),
        #    context_code
        ],
                                         value=instantiate_macro_code)


        generated_code = [classdef_code, register_macro_code]

        return generated_code
Beispiel #15
0
    def generate(self, element:Element, GC:GenerationContext):

        acode = element.code



        sf_name_element = acode[1]

        sf_name = sf_name_element.code.full_name
        sf_name_safe = "__specialform_"+sf_name+"__"



        rawexpand = acode[2].code

        rawexpand_header = rawexpand[0].code
        assert is_identifier(rawexpand_header[0], "expand")

        assert is_identifier(rawexpand_header[1])
        rawexpand_element_param = rawexpand_header[1].code.full_name

        assert is_identifier(rawexpand_header[2])
        rawexpand_context_param = rawexpand_header[2].code.full_name


        expand_body_elements = rawexpand[1:]
        expand_body_code = []
        for b in expand_body_elements:
            extend_body(expand_body_code, GC.generate(b))
        # The... second-to-last form? of the original element should be
        #  responsible for generating (i.e. should return) code that will
        #  complete the macro expansion;
        #  the final statement executed in an .expand method would actually
        #  be doing the replacing


        expand_args_code = ast.arguments(
            args=[ast.arg(arg="self"),
                  ast.arg(arg=rawexpand_element_param,
                          annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="Element", ctx=ast.Load())),
                  ast.arg(arg=rawexpand_context_param,
                          annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="ExpansionContext", ctx=ast.Load()))],
            kwonlyargs=[], defaults=[], kw_defaults=[]
        )



        expand_method_code = ast.FunctionDef(name="expand",
                                             args=expand_args_code,
                                             body=expand_body_code,
                                             decorator_list=[]
                                             )





        rawgenerate = acode[3].code

        rawgenerate_header = rawgenerate[0].code
        assert is_identifier(rawgenerate_header[0], "generate")

        assert is_identifier(rawgenerate_header[1])
        rawgenerate_element_param = rawgenerate_header[1].code.full_name

        assert is_identifier(rawgenerate_header[2])
        rawgenerate_context_param = rawgenerate_header[2].code.full_name

        generate_body_elements = rawgenerate[1:]

        generate_body_code = []
        for b in generate_body_elements:
            extend_body(generate_body_code, GC.generate(b))


        generate_args_code = ast.arguments(
            args=[ast.arg(arg="self"),
                  ast.arg(arg=rawgenerate_element_param,
                          annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="Element", ctx=ast.Load())),
                  ast.arg(arg=rawgenerate_context_param,
                          annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="GenerationContext", ctx=ast.Load()))],
            kwonlyargs=[], defaults=[], kw_defaults=[]
        )



        generate_method_code = ast.FunctionDef(name="generate",
                                             args=generate_args_code,
                                             body=generate_body_code,
                                             decorator_list=[]
                                             )


        class_body_code = []

        extend_body(class_body_code,ast.Import([ast.alias(name="anoky.module", asname="__aky__")]))

        extend_body(class_body_code, ast.Assign(targets=[ast.Name(id="HEADTEXT",
                                                            ctx=ast.Store())],
                                          value=ast.Str(sf_name)))

        extend_body(class_body_code, expand_method_code)
        extend_body(class_body_code, generate_method_code)




        classdef_code = ast.ClassDef(
                name=sf_name_safe,
                bases=[ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                     attr="SpecialForm", ctx=ast.Load())],
                keywords=[], decorator_list=[],
                body=class_body_code)


        # __specialform_sf_name__()
        instantiate_macro_code = ast.Call(func=ast.Name(id=sf_name_safe, ctx=ast.Load()),
                                          args=[], keywords=[])

        # EC.macro_table[sf_name]
        expansion_context_code = ast.Subscript(
                value=ast.Attribute(value=ast.Name(id="EC", ctx=ast.Load()),
                                    attr="macro_table", ctx=ast.Load()),
                slice=ast.Index(ast.Str(sf_name)), ctx=ast.Store())

        # GC.special_forms[sf_name]
        generation_context_code = ast.Subscript(
                value=ast.Attribute(value=ast.Name(id="GC", ctx=ast.Load()),
                                    attr="special_forms", ctx=ast.Load()),
                slice=ast.Index(ast.Str(sf_name)), ctx=ast.Store())


        # __special_forms__[sf_name] = EC.macro_table[sf_name] \
        #   = GC.special_forms[sf_name] = __specialform_sf_name__()
        register_macro_code = ast.Assign(targets=[
            ast.Subscript(value=ast.Name(id="__special_forms__", ctx=ast.Load()),
                          slice=ast.Index(ast.Str(sf_name)),
                          ctx=ast.Store()),
        #    expansion_context_code,
        #    generation_context_code
        ],
                                         value=instantiate_macro_code)


        generated_code = [classdef_code, register_macro_code]

        return generated_code
Beispiel #16
0
    def generate(self, element: Element, GC: GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        # "Check that form is as above"
        #assert

        if GC.domain == ExDom:
            astIf = ast.IfExp
            if len(acode) > 3 and not (is_form(acode[3], 'elif')
                                       or is_form(acode[3], 'else')):
                raise CodeGenerationError(
                    acode.range,
                    "If expression must only have a single sub-expression (for now)."
                )
        else:
            astIf = ast.If

        def gen_elif_elses(elif_else_elm):
            my_code = elif_else_elm.code
            if is_form(elif_else_elm, 'elif'):
                with GC.let(domain=ExDom):
                    my_condition_gen = GC.generate(my_code[1])

                my_body_gens = []
                for body_elm in my_code.iterate_from(2):
                    extend_body(my_body_gens, GC.generate(body_elm))

                if elif_else_elm.next is None:
                    return [astIf(my_condition_gen, my_body_gens, [])]
                else:
                    else_code = gen_elif_elses(elif_else_elm.next)
                    return [astIf(my_condition_gen, my_body_gens, else_code)]
            elif is_form(elif_else_elm, 'else'):
                my_body_gens = []
                for body_elm in my_code.iterate_from(1):
                    extend_body(my_body_gens, GC.generate(body_elm))
                return my_body_gens
            else:
                raise CodeGenerationError(
                    elif_else_elm.range,
                    "Unexpected element `%s` after first `elif` or `else` form within `if` form."
                    % (succinct_lisp_printer(elif_else_elm)))

        with GC.let(domain=ExDom):
            condition_gen = GC.generate(acode[1])
        body_gens = []
        else_code = []

        for body_elm in acode.iterate_from(2):
            if is_form(body_elm, 'elif') or is_form(body_elm, 'else'):
                else_code = gen_elif_elses(body_elm)
                break
            else:
                body_gen = GC.generate(body_elm)
                extend_body(body_gens, body_gen)

        if len(body_gens) == 0: body_gens.append(ast.Pass())

        if GC.domain == ExDom:
            return ast.IfExp(
                condition_gen, body_gens[0],
                else_code[0] if len(else_code) > 0 else ast.NameConstant(None))
        else:
            return ast.If(condition_gen, body_gens, else_code)
Beispiel #17
0
    def generate(self, element:Element, GC:GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        # "Check that form is as above"
        #assert





        def gen_except_handler(except_elm):
            my_code = except_elm.code
            exception_elm = my_code[1]
            name = None
            if is_form(exception_elm, 'as'):
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm.code[1])
                my_exception_name_id = exception_elm.code[2]
                if not is_identifier(my_exception_name_id):
                    raise CodeGenerationError(my_exception_name_id.range, "Expected an identifier as exception name of `except` clause in `try` special-form.")
                name = my_exception_name_id.code.name
            else:
                with GC.let(domain=ExpressionDomain):
                    my_exception_type = GC.generate(exception_elm)

            body_gens = []
            for my_body_elm in my_code.iterate_from(2):
                extend_body(body_gens, GC.generate(my_body_elm))

            return ast.ExceptHandler(my_exception_type, name, body_gens)





        body_gens, handlers, or_else, finally_body = [], [], None, None
        stage = 0 # 0 = body, 1 = except, 2 = else, 3 = finally
        names = {1: "except", 2: "else", 3: "finally"}
        for body_elm in acode.iterate_from(1):
            if is_form(body_elm, 'except'):
                if stage > 1: raise CodeGenerationError(body_elm.range, "Found `except` clause after first `%s` in `try` special form." % names[stage])
                else: stage = 1
                except_handler = gen_except_handler(body_elm)
                handlers.append(except_handler)
            elif is_form(body_elm, 'else'):
                if stage > 1: raise CodeGenerationError(body_elm.range, "Found `except` clause after first `%s` in `try` special form." % names[stage])
                else: stage = 2
                or_else = [GC.generate(my_body_elm) for my_body_elm in body_elm.code.iterate_from(1)]
            elif is_form(body_elm, 'finally'):
                if stage > 2: raise CodeGenerationError(body_elm.range, "Found `except` clause after first `%s` in `try` special form." % names[stage])
                else: stage = 3
                finally_body = []
                for my_body_elm in body_elm.code.iterate_from(1):
                    extend_body(finally_body, GC.generate(my_body_elm))
            else:
                if stage > 0: raise CodeGenerationError(body_elm.range, "Found body clause after first `%s` in `try` special form." % names[stage])
                body_gen = GC.generate(body_elm)
                extend_body(body_gens, body_gen)


        return ast.Try(body_gens, handlers, or_else, finally_body)
Beispiel #18
0
    def generate(self, element:Element, GC:GenerationContext):

        self.precheck(element, GC)

        acode = element.code

        # "Check that form is as above"
        #assert


        if GC.domain == ExDom:
            astIf = ast.IfExp
            if len(acode) > 3 and not (is_form(acode[3], 'elif') or is_form(acode[3], 'else')):
                raise CodeGenerationError(acode.range, "If expression must only have a single sub-expression (for now).")
        else:
            astIf = ast.If



        def gen_elif_elses(elif_else_elm):
            my_code = elif_else_elm.code
            if is_form(elif_else_elm, 'elif'):
                with GC.let(domain=ExDom):
                    my_condition_gen = GC.generate(my_code[1])

                my_body_gens = []
                for body_elm in my_code.iterate_from(2):
                    extend_body(my_body_gens, GC.generate(body_elm))

                if elif_else_elm.next is None:
                    return [astIf(my_condition_gen, my_body_gens, [])]
                else:
                    else_code = gen_elif_elses(elif_else_elm.next)
                    return [astIf(my_condition_gen, my_body_gens, else_code)]
            elif is_form(elif_else_elm, 'else'):
                my_body_gens = []
                for body_elm in my_code.iterate_from(1):
                    extend_body(my_body_gens, GC.generate(body_elm))
                return my_body_gens
            else:
                raise CodeGenerationError(elif_else_elm.range,
                                          "Unexpected element `%s` after first `elif` or `else` form within `if` form." % (
                                          succinct_lisp_printer(elif_else_elm)))

        with GC.let(domain=ExDom):
            condition_gen = GC.generate(acode[1])
        body_gens = []
        else_code = []

        for body_elm in acode.iterate_from(2):
            if is_form(body_elm, 'elif') or is_form(body_elm, 'else'):
                else_code = gen_elif_elses(body_elm)
                break
            else:
                body_gen = GC.generate(body_elm)
                extend_body(body_gens, body_gen)

        if len(body_gens) == 0: body_gens.append(ast.Pass())


        if GC.domain == ExDom:
            return ast.IfExp(condition_gen, body_gens[0], else_code[0] if len(else_code) > 0 else ast.NameConstant(None))
        else:
            return ast.If(condition_gen, body_gens, else_code)