def applies(self, element: Element):
     next = element.next
     return (is_identifier(element.code) and next is not None
             and is_identifier(next.code)
             and (element.code.name, next.code.name) in self.sym_vals
             and  # FIXME
             not element.is_first() and not next.is_last())
Ejemplo n.º 2
0
 def applies(self, y: Element):
     c = y.next if y is not None else None
     b = y.prev if y is not None else None
     x = b.prev if b is not None else None
     a = x.prev if x is not None else None
     return (x is not None and is_identifier(y.code)
             and is_identifier(x.code) and a is not None and b is not None
             and c is not None and (x.code.name, y.code.name) in self.set)
 def applies(self, element:Element):
     next = element.next
     return (
         is_identifier(element.code) and
         next is not None and
         is_identifier(next.code) and
         (element.code.name, next.code.name) in self.sym_vals and # FIXME
         not element.is_first() and
         not next.is_last()
     )
Ejemplo n.º 4
0
 def applies(self, y:Element):
     c = y.next if y is not None else None
     b = y.prev if y is not None else None
     x = b.prev if b is not None else None
     a = x.prev if x is not None else None
     return (
         x is not None and
         is_identifier(y.code) and
         is_identifier(x.code) and
         a is not None and
         b is not None and
         c is not None and
         (x.code.name, y.code.name) in self.set
     )
    def apply(self, element):
        # p < n
        form = element.parent
        ops = [element]
        p = element.prev
        n = element.next
        args = [p, n]
        form.remove(p) # < n
        form.remove(n) # <
        new_form = Form(Identifier(self.head_symbol_name))
        new_form_element = form.replace(element, new_form) # (head_symbol)

        while True: # while we find + e
            e1 = new_form_element.next
            if e1 is None: break
            e2 = e1.next
            if e2 is None: break
            if is_identifier(e1.code) and e1.code.name in self.sym_vals: # if e1 is the same symbol as e, then it is the same operator
                form.remove(e1)
                form.remove(e2)
                ops.append(e1)
                args.append(e2)
            else: break

        for op in ops:
            new_form.append(op)

        new_form.append(Seq(*args))

        return new_form_element.next
Ejemplo n.º 6
0
    def apply(self, element):
        # p + n
        # + p n
        # (+ p n)
        form = element.parent
        head = element.code
        p = element.prev
        n = element.next
        form.remove(p) # + n
        form.remove(n) # +
        new_form = Form(head, p, n) # +      (+ p n)
        new_form_element = form.replace(element, new_form) # (+ p n)

        while True: # while we find + e
            e1 = new_form_element.next
            if e1 is None: break
            e2 = e1.next
            if e2 is None: break
            if is_identifier(e1.code, head.name): # if e1 is the same symbol as e, then it is the same operator
                form.remove(e1)
                form.remove(e2)
                new_form.append(e2) # so we add the next element as an operand
            else: break

        return new_form_element.next
 def applies(self, element: Element):
     return ((not isinstance(element.parent, Form)
              or not element.is_first()) and is_identifier(element.code)
             and identifier_in(element.code, self.sym_vals)
             and element.next is not None and element.next.code is not None
             and element.code.range.position_after.index
             == element.next.code.range.first_position.index)
Ejemplo n.º 8
0
    def apply(self, element: Element):
        form = element.code
        elm = form[1]
        in_elm = None
        colon_elm = None
        ind_elm = None
        while elm is not None:
            if is_identifier(elm, 'in'):
                in_elm = elm
            elif is_token(elm, PUNCTUATION, ':'):
                colon_elm = elm
                break
            elm = elm.next

        if colon_elm is None or in_elm is None:
            raise ArrangementError(element.range, "`for` form must be punctuated by `in` and `:`.")
        if in_elm.prev is form[0]:
            raise ArrangementError(element.range, "No element before `in` in `for` form.")
        if in_elm.next is colon_elm:
            raise ArrangementError(element.range, "No element between `in` and `:` in `for` form.")

        form.wrap(form[1], in_elm.prev, PreSeq)
        form.wrap(in_elm.next, colon_elm.prev, PreSeq)
        form.remove(in_elm)

        return DefaultPunctuation.apply(self, element)
Ejemplo n.º 9
0
    def apply(self, element):
        form = element.parent

        if is_identifier(element, '=') and \
                not ( form.first.next is element or
                      is_token(form.first.next, Tokens.PUNCTUATION, ',')):
            return

        form.wrap(form.first, element.prev, PreSeq)
        if element.next is not None:
            first_indent = element.next
            while first_indent is not None and not is_token(
                    first_indent, Tokens.INDENT):
                first_indent = first_indent.next
            if first_indent is not None:
                if is_token(first_indent.prev, Tokens.PUNCTUATION, ':'):
                    form.wrap(element.next, form.last, PreForm)
                else:
                    form.replace(first_indent, Tokens.ARGBREAK())
                    form.wrap(element.next, form.last, PreSeq)
        form.remove(element)
        if isinstance(form, PreForm):
            form.prepend(Identifier("="))
        else:
            new_form = form.wrap(form.first, form.last, Form).code
            new_form.prepend(element)
        return None
 def applies(self, element:Element):
     #  p [ + ] n
     return (is_identifier(element.code) and
             identifier_in(element.code, self.sym_vals) and
             not element.is_first() and
             not element.is_last() and
             not is_form(element.parent, self.head_symbol_name))
Ejemplo n.º 11
0
    def expand(self, element: Element, EC: ExpansionContext):

        acode = element.code

        for import_element in acode[1:]:

            if is_identifier(import_element):
                to_import_name = import_element.code.full_name
                try:
                    module = importlib.import_module(to_import_name)
                    macros = module.__macros__
                    EC.macros.update(macros)
                    id_macros = module.__id_macros__
                    EC.id_macros.update(id_macros)
                    special_forms = module.__special_forms__
                    EC.special_forms.update(special_forms)
                except Exception as e:
                    traceback.print_exc()
                    raise CodeGenerationError(
                        import_element.range,
                        "Failed to meta-import module `%s`." % to_import_name)

            else:
                raise CodeGenerationError(
                    import_element.range,
                    "Special form `meta-import` expected a module pathbut found `%s`."
                    % succinct_lisp_printer(import_element))

        return
Ejemplo n.º 12
0
    def apply(self, element):
        form = element.parent

        if is_identifier(element, '=') and \
                not ( form.first.next is element or
                      is_token(form.first.next, Tokens.PUNCTUATION, ',')):
                return


        form.wrap(form.first, element.prev, PreSeq)
        if element.next is not None:
            first_indent = element.next
            while first_indent is not None and not is_token(first_indent, Tokens.INDENT):
                first_indent = first_indent.next
            if first_indent is not None:
                if is_token(first_indent.prev, Tokens.PUNCTUATION, ':'):
                    form.wrap(element.next, form.last, PreForm)
                else:
                    form.replace(first_indent, Tokens.ARGBREAK())
                    form.wrap(element.next, form.last, PreSeq)
        form.remove(element)
        if isinstance(form, PreForm):
            form.prepend(Identifier("="))
        else:
            new_form = form.wrap(form.first, form.last, Form).code
            new_form.prepend(element)
        return None
Ejemplo n.º 13
0
def _get_module_path(element:Element) -> str:
    if not _is_module_path(element):
            raise CodeGenerationError(element.range, "Expected a module path (`a.b.c`) , but found `%s`." % succinct_lisp_printer(element))
    elif is_identifier(element):
        return element.code.full_name # TODO: name mangling?
    elif is_form(element, '.'):
        return _get_module_path(element.code[1]) + "." + _get_module_path(element.code[2])
Ejemplo n.º 14
0
    def generate_quote_ast(element:Element, GC:GenerationContext):

        # allow passing code instead of element?

        acode = element.code


        if isinstance(acode, Form) and is_identifier(acode[0], "~"):

            assert len(acode) == 2

            with GC.let(domain=ExpressionDomain):
                literal_value = GC.generate(acode[1])

            a = ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                            attr="force_literal",
                                            ctx=ast.Load()),
                         args=[literal_value],
                         keywords=[])

            return a


        elif isinstance(acode, Form) or isinstance(acode, Seq):

            #return __aky__.Form(*[akycode_to_ast(e) for e in acode])

            children_ast = [Quote.generate_quote_ast(e, GC) for e in acode]

            a = ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                            attr="Form" if isinstance(acode, Form) else "Seq",
                                            ctx=ast.Load()),
                         args=children_ast,
                         keywords=[])

            return a


        elif isinstance(acode, Identifier):

            return ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                            attr="Identifier", ctx=ast.Load()),
                            args=[ast.Str(acode.full_name)],
                            keywords=[])

        else:

            assert isinstance(acode, Literal)

            if acode.type is str:
                value_code = ast.Str(acode.value)
            else:
                assert acode.type in [int, float]
                value_code = ast.Num(acode.value)

            return ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()),
                                            attr="Literal", ctx=ast.Load()),
                            args=[value_code,
                                  ast.Name(id=acode.type.__name__, ctx=ast.Load())],
                            keywords=[])
Ejemplo n.º 15
0
    def apply(self, element):
        # p < n
        form = element.parent
        ops = [element]
        p = element.prev
        n = element.next
        args = [p, n]
        form.remove(p)  # < n
        form.remove(n)  # <
        new_form = Form(Identifier(self.head_symbol_name))
        new_form_element = form.replace(element, new_form)  # (head_symbol)

        while True:  # while we find + e
            e1 = new_form_element.next
            if e1 is None: break
            e2 = e1.next
            if e2 is None: break
            if is_identifier(
                    e1.code
            ) and e1.code.name in self.sym_vals:  # if e1 is the same symbol as e, then it is the same operator
                form.remove(e1)
                form.remove(e2)
                ops.append(e1)
                args.append(e2)
            else:
                break

        for op in ops:
            new_form.append(op)

        new_form.append(Seq(*args))

        return new_form_element.next
 def applies(self, element:Element):
     return (
         is_identifier(element.code) and
         identifier_in(element.code, self.sym_vals) and
         not is_head(element) and
         not element.is_last()
     )
Ejemplo n.º 17
0
    def expand(self, element:Element, EC:ExpansionContext):

        acode = element.code

        for import_element in acode[1:]:

            if is_identifier(import_element):
                to_import_name = import_element.code.full_name
                try:
                    module = importlib.import_module(to_import_name)
                    macros = module.__macros__
                    EC.macros.update(macros)
                    id_macros = module.__id_macros__
                    EC.id_macros.update(id_macros)
                    special_forms = module.__special_forms__
                    EC.special_forms.update(special_forms)
                except Exception as e:
                    traceback.print_exc()
                    raise CodeGenerationError(import_element.range,
                                              "Failed to meta-import module `%s`." % to_import_name)

            else:
                raise CodeGenerationError(import_element.range,
                                          "Special form `meta-import` expected a module pathbut found `%s`." % succinct_lisp_printer(
                                              import_element))

        return
 def applies(self, element:Element):
     return (
         not element.is_first() and
         is_identifier(element.code) and
         identifier_in(element.code, self.sym_vals) and
         element.prev is not None and
         element.prev.code is not None and
         element.prev.code.range.position_after.index == element.code.range.first_position.index
     )
 def applies(self, element:Element):
     return (
         (not isinstance(element.parent, Form) or not element.is_first()) and
         is_identifier(element.code) and
         identifier_in(element.code, self.sym_vals) and
         element.next is not None and
         element.next.code is not None and
         element.code.range.position_after.index == element.next.code.range.first_position.index
     )
Ejemplo n.º 20
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=[]
                            )
 def applies(self, element:Element):
     next = element.next
     return (
         next is not None and
         (not (element.is_first() and is_form(element.parent)) or not next.is_last()) and
         is_identifier(element) and
         element.code.name in self.token_vals and
         is_not_none(element, ".range.position_after.index", next, ".range.first_position.index") and
         element.code.range.position_after.index == next.code.range.first_position.index
     )
 def applies(self, element: Element):
     next = element.next
     return (next is not None
             and (not (element.is_first() and is_form(element.parent))
                  or not next.is_last()) and is_identifier(element)
             and element.code.name in self.token_vals
             and is_not_none(element, ".range.position_after.index", next,
                             ".range.first_position.index")
             and element.code.range.position_after.index
             == next.code.range.first_position.index)
Ejemplo n.º 23
0
def _get_module_path(element: Element) -> str:
    if not _is_module_path(element):
        raise CodeGenerationError(
            element.range,
            "Expected a module path (`a.b.c`) , but found `%s`." %
            succinct_lisp_printer(element))
    elif is_identifier(element):
        return element.code.full_name  # TODO: name mangling?
    elif is_form(element, '.'):
        return _get_module_path(element.code[1]) + "." + _get_module_path(
            element.code[2])
Ejemplo n.º 24
0
    def generate(self, element:Element, GC:GenerationContext):


        acode = element.code

        if len(acode) is 2 and is_form(acode[1], "for"):

            for_form = acode[1].code

            # list comprehension

            # («[]» (for (in i lst) (f i))) # list compr

            in_el = for_form[1]
            in_el_code = in_el.code

            #with GC.let(domain=ExDom):

            assert is_identifier(in_el, "in")

            target_element = in_el_code[1]
            iter_element = in_el_code[2]

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

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



            generators = [ ast.comprehension(target=target_code,
                                             iter=iter_code,
                                             ifs=[]) ]


            to_evaluate_element = for_form[2]

            with GC.let(domain=ExDom):

                to_evaluate_code = GC.generate(to_evaluate_element)


            return ast.ListComp(to_evaluate_code, generators)


        else:

            els = self.generate_as_expressions(GC, *acode[1:])

            if GC.domain == LVDom:
                return ast.List(els, ast.Store())
            return expr_wrap(ast.List(els, ast.Load()), GC)
 def apply(self, element):
     form = element.parent
     next = element.next
     if is_identifier(next) or is_literal(next):
         new_form_element = form.wrap(element, next, Form)
     elif is_token(next, Tokens.BEGIN_MACRO):
         new_form_element = form.wrap(element, next.end, Form)
     else:
         raise ArrangementError(next.range.first_position, "Expected identifier, literal or begin-macro-token after '%s' identifier in position %s." %(element.value, element.range.first_position.nameless_str))
     new_form = new_form_element.code
     new_form.remove(element)
     new_form.prepend(element)
     return new_form_element.next
Ejemplo n.º 26
0
    def expand(self, element: Element, EC: ExpansionContext):

        code = element.code

        # expand downwards by cases

        if isinstance(code, Form):

            head = code.first
            headcode = head.code

            # check if any macros apply

            if is_identifier(headcode):
                if headcode.full_name in EC.macros:
                    EC.macros[headcode.full_name].expand(element, EC)
                elif headcode.full_name in EC.special_forms:
                    EC.special_forms[headcode.full_name].expand(element, EC)
            # otherwise expand recursively
            else:

                for item in code:
                    EC.expand(item)

        elif isinstance(code, Seq):
            # expand all elements in the seq

            for item in code:

                EC.expand(item)

        elif isinstance(code, Literal):

            pass

        elif isinstance(code, Identifier):

            # IDENTIFIER MACROS
            if code.full_name in EC.id_macros:

                idmac = EC.id_macros[code.full_name]

                idmac.expand(element, EC)


#                element.parent.replace(element, idmac.expand(element, context))
            elif code.full_name in EC.macros:
                raise MacroExpansionError(
                    code.range,
                    "Refering to macro `%s` by name requires the use of `the`."
                    % code.full_name)
Ejemplo n.º 27
0
    def generate(self, element:Element, GC:GenerationContext):

        acode = element.code

        imports_list = []
        import_statements = []

        with GC.let(domain=ExDom):

            for import_element in acode[1:]:

                if _is_module_path(import_element):
                    to_import_name = _get_module_path(import_element)
                    imports_list.append(ast.alias(name=to_import_name, asname=None))

                elif is_form(import_element.code, "as"):
                    to_import_name = _get_module_path(import_element.code[1])
                    to_import_asname = _get_name(import_element.code[2])

                    imports_list.append(ast.alias(name=to_import_name,
                                                  asname=to_import_asname))
                elif is_form(import_element.code) or is_seq(import_element.code):
                    to_import_module_name = _get_module_path(import_element.code[0])
                    imported_names_from_module = []

                    for to_import_item_element in import_element.code[1:]:

                        if is_identifier(to_import_item_element):
                            to_import_name = _get_name(to_import_item_element)
                            imported_names_from_module.append(ast.alias(name=to_import_name, asname=None))

                        elif is_form(to_import_item_element.code, "as"):
                            to_import_name = _get_name(to_import_item_element.code[1])
                            to_import_asname = _get_name(to_import_item_element.code[2])
                            imported_names_from_module.append(ast.alias(name=to_import_name,
                                                          asname=to_import_asname))
                    import_statements.append(ast.ImportFrom(to_import_module_name, imported_names_from_module, 0))
                else:
                    raise CodeGenerationError(import_element.range, "Special form `import` expected an import specifier but found `%s`."
                                                                    "For example:"
                                                                    "```"
                                                                    "import"
                                                                    "   a.b.c"
                                                                    "   x.y.z as name"
                                                                    "   u.v.w( var1, var2 as v )"
                                                                    "```" % succinct_lisp_printer(import_element))

        if len(imports_list) > 0:
            import_statements.append(ast.Import(imports_list))
        return import_statements
Ejemplo n.º 28
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=[])
 def apply(self, element):
     form = element.parent
     next = element.next
     if is_identifier(next) or is_literal(next):
         new_form_element = form.wrap(element, next, Form)
     elif is_token(next, Tokens.BEGIN_MACRO):
         new_form_element = form.wrap(element, next.end, Form)
     else:
         raise ArrangementError(
             next.range.first_position,
             "Expected identifier, literal or begin-macro-token after '%s' identifier in position %s."
             % (element.value, element.range.first_position.nameless_str))
     new_form = new_form_element.code
     new_form.remove(element)
     new_form.prepend(element)
     return new_form_element.next
Ejemplo n.º 30
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)
    def applies(self, element:Element):
        def _is_identifier_or_literal_immediately_after(next, element):
            return ((is_identifier(next) or is_literal(next)) and
                is_not_none(next, ".code.range.first_position.index") and
                element.code.range.position_after.index == next.code.range.first_position.index)

        def _is_begin_macro_token_immediately_after(next, element):
            return (is_token(next, Tokens.BEGIN_MACRO) and
                is_not_none(next, ".range.first_position.index") and
                element.code.range.position_after.index == next.range.first_position.index)

        next = element.next
        return (
            next is not None and
            (not (element.is_first() and is_form(element.parent)) or not next.is_last()) and
            is_identifier(element) and
            identifier_in(element.code, self.sym_vals) and
            is_not_none(element, ".code.range.position_after.index") and
            (_is_identifier_or_literal_immediately_after(next, element) or
             _is_begin_macro_token_immediately_after(next, element))
        )
    def applies(self, element: Element):
        def _is_identifier_or_literal_immediately_after(next, element):
            return ((is_identifier(next) or is_literal(next))
                    and is_not_none(next, ".code.range.first_position.index")
                    and element.code.range.position_after.index
                    == next.code.range.first_position.index)

        def _is_begin_macro_token_immediately_after(next, element):
            return (is_token(next, Tokens.BEGIN_MACRO)
                    and is_not_none(next, ".range.first_position.index")
                    and element.code.range.position_after.index
                    == next.range.first_position.index)

        next = element.next
        return (next is not None
                and (not (element.is_first() and is_form(element.parent))
                     or not next.is_last()) and is_identifier(element)
                and identifier_in(element.code, self.sym_vals)
                and is_not_none(element, ".code.range.position_after.index")
                and
                (_is_identifier_or_literal_immediately_after(next, element)
                 or _is_begin_macro_token_immediately_after(next, element)))
Ejemplo n.º 33
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)
Ejemplo n.º 34
0
    def _single_indented_segment_apply(self, begin_token) -> Element:
        # BEGIN  = INDENT  END
        new_form_element = begin_token.parent.wrap(begin_token,
                                                   begin_token.end, Form)
        # (BEGIN  = INDENT  END)
        new_form = new_form_element.code

        indent = begin_token.indents[0]
        assignment_symbol_elm = indent.prev

        has_colon = begin_token.find_punctuation(':', indent) is not None
        if has_colon:
            raise ArrangementError(has_colon.range,
                                   "Unexpected `:` in assignment segment.")

        new_form.wrap(begin_token.next, assignment_symbol_elm.prev, PreSeq)
        # (BEGIN ⟅,⟆ = INDENT  END)
        new_form.remove(new_form.first)
        # (⟅,⟆ = INDENT  END)
        new_form.remove(new_form.last)
        # (⟅,⟆ = INDENT  )
        new_form.remove(assignment_symbol_elm)
        # (⟅,⟆ INDENT  )
        new_form.prepend(Identifier("="))
        # (= ⟅,⟆ INDENT  )

        if is_identifier(assignment_symbol_elm, '='):
            first_begin_after_indentation = indent.next
            # remove BEGIN/END pairs of non-indented, non-colon-having segments
            Util.explode_list_of_args(first_begin_after_indentation)

        rvalue_elm = new_form.wrap(indent.next, new_form.last, PreSeq)
        # (= ⟅,⟆ INDENT ⟅,⟆ )
        new_form.remove(indent)
        # (= ⟅,⟆ ⟅,⟆ )

        return new_form_element.next
Ejemplo n.º 35
0
 def apply(self, element):
     form = element.parent
     next = element.next  # this is 'b'
     prev = element.prev  # this is 'a'
     if is_identifier(next) or is_literal(next) or is_form(next):
         new_form_element = form.wrap(prev, next, Form)
     elif is_token(next, Tokens.BEGIN_MACRO):
         # a . BEGIN_MACRO something END_MACRO dont want => (. a BEGIN_MACRO) something END_MACRO
         # actually want
         # a . BEGIN_MACRO something END_MACRO => (. a BEGIN_MACRO something END_MACRO)
         new_form_element = form.wrap(prev, next.end, Form)
     else:
         raise ArrangementError(
             element.range.position_after,
             "Expected identifier, literal, form or begin-macro-token after '%s' in position %s."
             %
             (element.code.name, element.range.first_position.nameless_str))
     new_form = new_form_element.code
     # at this point new_form = ⦅a X b⦆
     new_form.remove(element)
     # at this point new_form = ⦅a b⦆
     new_form.prepend(element)
     # at this point new_form = ⦅X a b⦆
     return new_form_element.next  # return the next position to be read
Ejemplo n.º 36
0
 def applies(self, element: Element):
     return (is_identifier(element.code) and element.code.name in self.names
             and not is_forced_head(element))
Ejemplo n.º 37
0
 def applies(self, element: Element):
     return is_identifier(element.code) and element.code.name in self.names and not is_forced_head(element)
Ejemplo n.º 38
0
 def applies(self, element:Element):
     return isinstance(element.code, Form) and is_identifier(element.code.head, self.head_name)
Ejemplo n.º 39
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
Ejemplo n.º 40
0
 def applies(self, element):
     return is_token(element, Tokens.BEGIN) and \
            len(element.indents) > 0 and \
            (is_identifier(element.indents[0].prev, "=") or
             is_identifier(element.indents[0].prev, ":=")) and \
             element.next is not element.indents[0].prev
Ejemplo n.º 41
0
def _get_name(element:Element):
    if not is_identifier(element):
        raise SyntaxError(element.range, "Expected a module name , but found `%s`." % succinct_lisp_printer(element))
    return element.code.full_name
 def _is_identifier_or_literal_immediately_after(next, element):
     return ((is_identifier(next) or is_literal(next))
             and is_not_none(next, ".code.range.first_position.index")
             and element.code.range.position_after.index
             == next.code.range.first_position.index)
Ejemplo n.º 43
0
 def applies(self, element: Element):
     return (is_identifier(element, ':=') or is_identifier(element, '=')) and \
            not element.is_first() and \
            ( isinstance(element.parent, PreForm) or isinstance(element.parent, PreSeq) )
Ejemplo n.º 44
0
def _get_name(element: Element):
    if not is_identifier(element):
        raise SyntaxError(
            element.range, "Expected a module name , but found `%s`." %
            succinct_lisp_printer(element))
    return element.code.full_name
Ejemplo n.º 45
0
def _is_module_path(element: Element) -> bool:
    return is_identifier(element) or \
               is_form(element, ".") and \
               len(element.code) == 3 and \
               _is_module_path(element.code[1]) and \
               is_identifier(element.code[2])
Ejemplo n.º 46
0
 def applies(self, element: Element):
     return (is_identifier(element.code) and element.code.name in self.names
             and (element.parent.__class__ is not Form
                  or not element.is_first() or len(element.parent) > 2))
Ejemplo n.º 47
0
 def applies(self, element:Element):
     return (is_identifier(element, ':=') or is_identifier(element, '=')) and \
            not element.is_first() and \
            ( isinstance(element.parent, PreForm) or isinstance(element.parent, PreSeq) )
Ejemplo n.º 48
0
    def generate(self, element: Element, GC: GenerationContext):

        acode = element.code

        imports_list = []
        import_statements = []

        with GC.let(domain=ExDom):

            for import_element in acode[1:]:

                if _is_module_path(import_element):
                    to_import_name = _get_module_path(import_element)
                    imports_list.append(
                        ast.alias(name=to_import_name, asname=None))

                elif is_form(import_element.code, "as"):
                    to_import_name = _get_module_path(import_element.code[1])
                    to_import_asname = _get_name(import_element.code[2])

                    imports_list.append(
                        ast.alias(name=to_import_name,
                                  asname=to_import_asname))
                elif is_form(import_element.code) or is_seq(
                        import_element.code):
                    to_import_module_name = _get_module_path(
                        import_element.code[0])
                    imported_names_from_module = []

                    for to_import_item_element in import_element.code[1:]:

                        if is_identifier(to_import_item_element):
                            to_import_name = _get_name(to_import_item_element)
                            imported_names_from_module.append(
                                ast.alias(name=to_import_name, asname=None))

                        elif is_form(to_import_item_element.code, "as"):
                            to_import_name = _get_name(
                                to_import_item_element.code[1])
                            to_import_asname = _get_name(
                                to_import_item_element.code[2])
                            imported_names_from_module.append(
                                ast.alias(name=to_import_name,
                                          asname=to_import_asname))
                    import_statements.append(
                        ast.ImportFrom(to_import_module_name,
                                       imported_names_from_module, 0))
                else:
                    raise CodeGenerationError(
                        import_element.range,
                        "Special form `import` expected an import specifier but found `%s`."
                        "For example:"
                        "```"
                        "import"
                        "   a.b.c"
                        "   x.y.z as name"
                        "   u.v.w( var1, var2 as v )"
                        "```" % succinct_lisp_printer(import_element))

        if len(imports_list) > 0:
            import_statements.append(ast.Import(imports_list))
        return import_statements
Ejemplo n.º 49
0
 def applies(self, element: Element):
     return is_identifier(
         element.code
     ) and element.code.name in self.arrows and not element.is_first()
Ejemplo n.º 50
0
    def generate_quote_ast(element: Element, GC: GenerationContext):

        # allow passing code instead of element?

        acode = element.code

        if isinstance(acode, Form) and is_identifier(acode[0], "~"):

            assert len(acode) == 2

            with GC.let(domain=ExpressionDomain):
                literal_value = GC.generate(acode[1])

            a = ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__",
                                                           ctx=ast.Load()),
                                            attr="force_literal",
                                            ctx=ast.Load()),
                         args=[literal_value],
                         keywords=[])

            return a

        elif isinstance(acode, Form) or isinstance(acode, Seq):

            #return __aky__.Form(*[akycode_to_ast(e) for e in acode])

            children_ast = [Quote.generate_quote_ast(e, GC) for e in acode]

            a = ast.Call(func=ast.Attribute(
                value=ast.Name(id="__aky__", ctx=ast.Load()),
                attr="Form" if isinstance(acode, Form) else "Seq",
                ctx=ast.Load()),
                         args=children_ast,
                         keywords=[])

            return a

        elif isinstance(acode, Identifier):

            return ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__",
                                                              ctx=ast.Load()),
                                               attr="Identifier",
                                               ctx=ast.Load()),
                            args=[ast.Str(acode.full_name)],
                            keywords=[])

        else:

            assert isinstance(acode, Literal)

            if acode.type is str:
                value_code = ast.Str(acode.value)
            else:
                assert acode.type in [int, float]
                value_code = ast.Num(acode.value)

            return ast.Call(func=ast.Attribute(value=ast.Name(id="__aky__",
                                                              ctx=ast.Load()),
                                               attr="Literal",
                                               ctx=ast.Load()),
                            args=[
                                value_code,
                                ast.Name(id=acode.type.__name__,
                                         ctx=ast.Load())
                            ],
                            keywords=[])
Ejemplo n.º 51
0
 def applies(self, element: Element):
     return isinstance(element.code, Form) and is_identifier(
         element.code.head, self.head_name)
Ejemplo n.º 52
0
def _is_module_path(element:Element) -> bool:
    return is_identifier(element) or \
               is_form(element, ".") and \
               len(element.code) == 3 and \
               _is_module_path(element.code[1]) and \
               is_identifier(element.code[2])
Ejemplo n.º 53
0
 def applies(self, element:Element):
     #  p [ + ] n
     return (is_identifier(element.code) and
             identifier_in(element.code, self.sym_vals) and
             not element.is_first() and
             not element.is_last())
 def applies(self, element: Element):
     return (is_identifier(element.code)
             and identifier_in(element.code, self.sym_vals)
             and not element.is_first() and not element.is_last())
Ejemplo n.º 55
0
 def applies(self, element:Element):
     return is_identifier(element.code) and element.code.name in self.arrows and not element.is_first()
 def _is_identifier_or_literal_immediately_after(next, element):
     return ((is_identifier(next) or is_literal(next)) and
         is_not_none(next, ".code.range.first_position.index") and
         element.code.range.position_after.index == next.code.range.first_position.index)
Ejemplo n.º 57
0
 def applies(self, element:Element):
     return (is_identifier(element.code) and
             element.code.name in self.names and
             (element.parent.__class__ is not Form or not element.is_first() or len(element.parent) > 2))