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())
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() )
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
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)
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)
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))
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 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 _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])
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=[])
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() )
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 )
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)
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])
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
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)
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
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
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)))
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 _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
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
def applies(self, element: Element): return (is_identifier(element.code) and element.code.name in self.names and not is_forced_head(element))
def applies(self, element: Element): return is_identifier(element.code) and element.code.name in self.names and not is_forced_head(element)
def applies(self, element:Element): return isinstance(element.code, Form) and is_identifier(element.code.head, self.head_name)
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
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
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)
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) )
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_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])
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))
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) )
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
def applies(self, element: Element): return is_identifier( element.code ) and element.code.name in self.arrows and not element.is_first()
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=[])
def applies(self, element: Element): return isinstance(element.code, Form) and is_identifier( element.code.head, self.head_name)
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])
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())
def applies(self, element:Element): return is_identifier(element.code) and element.code.name in self.arrows and not element.is_first()
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))