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)))
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): 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=[], )
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=[], )
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 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 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 expand_inner_escapes(element: Element, EC: ExpansionContext): aquote = element.code # If we have a quote escape, expand sub-elements if is_form(aquote, "~"): assert len(aquote) == 2 EC.expand(aquote[1]) # otherwise, recurse on nodes, ignore the rest elif isinstance(aquote, Node): for e in aquote: Quote.expand_inner_escapes(e, EC)
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 expand_inner_escapes(element:Element, EC:ExpansionContext): aquote = element.code # If we have a quote escape, expand sub-elements if is_form(aquote, "~"): assert len(aquote) == 2 EC.expand(aquote[1]) # otherwise, recurse on nodes, ignore the rest elif isinstance(aquote, Node): for e in aquote: Quote.expand_inner_escapes(e, EC)
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 generate(self, element:Element, GC:GenerationContext): self.precheck(element, GC) head_name = element.code[0].code.name if not is_form(element.prev) or not identifier_in(element.prev.code[0], self.expected_names): raise CodeGenerationError(element.code[0].range, "`%s` form must appear after %s." % (head_name, self.expected_names)) if GC.domain == ExpressionDomain: return expr_wrap(ast.NameConstant(None), GC) else: return []
def apply(self, element:Element): form = element.parent next_form_element = element.next while next_form_element is not None: interesting_form = any( is_form(next_form_element, form_head) for form_head in self.following_names) if not interesting_form: break form.remove(next_form_element) element.code.append(next_form_element) next_form_element = element.next return element.next
def apply(self, element: Element): form = element.parent next_form_element = element.next while next_form_element is not None: interesting_form = any( is_form(next_form_element, form_head) for form_head in self.following_names) if not interesting_form: break form.remove(next_form_element) element.code.append(next_form_element) next_form_element = element.next return element.next
def generate(self, element: Element, GC: GenerationContext): self.precheck(element, GC) head_name = element.code[0].code.name if not is_form(element.prev) or not identifier_in( element.prev.code[0], self.expected_names): raise CodeGenerationError( element.code[0].range, "`%s` form must appear after %s." % (head_name, self.expected_names)) if GC.domain == ExpressionDomain: return expr_wrap(ast.NameConstant(None), GC) else: return []
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)))
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)
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)
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 generate(self, element:Element, GC:GenerationContext): acode = element.code with GC.let(domain=ExDom): base_object_code = GC.generate(acode[1]) # (.. ) if is_form(acode[2], ".."): #slice raise NotImplementedError() #if isinstance(acode[2].code, Literal): else: with GC.let(domain=ExDom): index_code = GC.generate(acode[2]) return expr_wrap(ast.Subscript(base_object_code, ast.Index(index_code), ast.Store() if GC.domain == LVDom else ast.Load()), GC)
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 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=[])
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 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): # 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 _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_form(element.code) and is_identifier(element.code.head) and element.code.head.code.full_name in self.form_heads
def generate(self, element:Element, GC:GenerationContext): acode = element.code head = acode[0].code assert isinstance(head, Identifier) headtext = head.full_name if len(acode) is 2 and is_form(acode[1].code, "for"): ccode = acode[1].code assert len(ccode) == 3 target_iter_element = ccode[1] expr_element = ccode[2] with GC.let(domain=LVDom): target_code = GC.generate(target_iter_element.code[1]) with GC.let(domain=ExDom): iter_code = GC.generate(target_iter_element.code[2]) comp_code = ast.comprehension(target=target_code, iter=iter_code, ifs=[]) if is_form(expr_element.code, "="): # dict comp key_code = GC.generate(expr_element.code[1]) value_code = GC.generate(expr_element.code[2]) return ast.DictComp(key=key_code, value=value_code, generators=[comp_code]) else: # set comp elt_code = GC.generate(expr_element) return ast.SetComp(elt=elt_code, generators=[comp_code]) else: if len(acode) is 1: return ast.Dict([], []) if all([is_form(i.code, "=") for i in acode[1:]]): #dict keys = [] values = [] with GC.let(domain=ExDom): for kvpair_el in acode[1:]: kvpair = kvpair_el.code key_code = GC.generate(kvpair[1]) value_code = GC.generate(kvpair[2]) keys.append(key_code) values.append(value_code) return expr_wrap(ast.Dict(keys, values), GC) else: #set el_codes = self.generate_as_expressions(GC, *acode[1:]) return expr_wrap(ast.Set(el_codes), GC)
def generate(self, element, GC: GenerationContext): from anoky.generation.util import expr_wrap acode = element.code if isinstance(acode, Form): head = acode.first headcode = head.code if isinstance( headcode, Identifier) and headcode.full_name in GC.special_forms: head.color = colors.SPECIAL_FORM hcname = headcode.full_name special_form = GC.special_forms[hcname] generated_code = special_form.generate(element, GC) return generated_code else: # function call # #(func arg1 arg2 arg3 ...) func_element = head #func_element_code = headcode with GC.let(domain=ExDom): func_code = GC.generate(func_element) arg_elements = acode[1:] args = [] keywords = [] for arg_element in arg_elements: arg_element_code = arg_element.code if isinstance(arg_element_code, Form): if is_form(arg_element_code, '='): # keyword argument kw_name = arg_element_code[1].code.full_name with GC.let(domain=ExDom): value_code = GC.generate(arg_element_code[2]) keywords.append(ast.keyword(kw_name, value_code)) elif is_form(arg_element_code, '*') and len(arg_element_code) == 2: # stared argument - expand as list with GC.let(domain=ExDom): arg_code = GC.generate(arg_element_code[1]) args.append(ast.Starred(arg_code, ast.Load())) elif is_form(arg_element_code, '**') and len(arg_element_code) == 2: # double starred argument - expand as kwlist assert len(arg_element_code) == 2 # verify no other dblstars already? with GC.let(domain=ExDom): arg_code = GC.generate(arg_element_code[1]) keywords.append(ast.keyword(None, arg_code)) else: # positional argument with GC.let(domain=ExDom): arg_code = GC.generate(arg_element) args.append(arg_code) else: # arg_element_code not a Form # then generate as expression with GC.let(domain=ExDom): arg_code = GC.generate(arg_element) args.append(arg_code) return expr_wrap(ast.Call(func_code, args, keywords), GC) if isinstance(acode, Seq): seq_codes = [] with GC.let(domain=ExDom): for e in acode: seq_codes.append(GC.generate(e)) if GC.domain == LVDom: return ast.Tuple(seq_codes, ast.Store()) elif GC.domain in [ExDom, SDom]: return expr_wrap(ast.Tuple(seq_codes, ast.Load()), GC) else: raise CodeGenerationError( acode.range, "Unexpected seq in domain `%s`." % str(GC.domain)) if isinstance(acode, Literal): element.color = colors.LITERAL if acode.type is str: return expr_wrap(ast.Str(acode.value), GC) elif acode.type in [int, float]: return expr_wrap(ast.Num(acode.value), GC) else: assert False if isinstance(acode, Identifier): if acode.full_name == "True": return expr_wrap(ast.NameConstant(True), GC) elif acode.full_name == "False": return expr_wrap(ast.NameConstant(False), GC) elif acode.full_name == "None": return expr_wrap(ast.NameConstant(None), GC) elif acode.full_name in GC.special_forms: element.color = colors.SPECIAL_FORM raise CodeGenerationError( acode.range, "Refering to special form `%s` by name requires the use of `the`." % acode.full_name) # elif acode.full_name in GC.macros: # raise CodeGenerationError(acode.range, # "Refering to macro `%s` by name requires the use of `the`." % acode.full_name) # elif acode.full_name in GC.id_macros: # raise CodeGenerationError(acode.range, # "Refering to identifier macro `%s` by name requires the use of `the`." % acode.full_name) elif GC.domain == LVDom: return ast.Name(acode.full_name, ast.Store()) elif GC.domain == DelDom: return ast.Name(acode.full_name, ast.Del()) else: return expr_wrap(ast.Name(acode.full_name, ast.Load()), GC)
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)
def generate(self, element, GC:GenerationContext): from anoky.generation.util import expr_wrap acode = element.code if isinstance(acode, Form): head = acode.first headcode = head.code if isinstance(headcode, Identifier) and headcode.full_name in GC.special_forms: head.color = colors.SPECIAL_FORM hcname = headcode.full_name special_form = GC.special_forms[hcname] generated_code = special_form.generate(element, GC) return generated_code else: # function call # #(func arg1 arg2 arg3 ...) func_element = head #func_element_code = headcode with GC.let(domain=ExDom): func_code = GC.generate(func_element) arg_elements = acode[1:] args = [] keywords = [] for arg_element in arg_elements: arg_element_code = arg_element.code if isinstance(arg_element_code, Form): if is_form(arg_element_code, '='): # keyword argument kw_name = arg_element_code[1].code.full_name with GC.let(domain=ExDom): value_code = GC.generate(arg_element_code[2]) keywords.append(ast.keyword(kw_name, value_code)) elif is_form(arg_element_code, '*') and len(arg_element_code) == 2: # stared argument - expand as list with GC.let(domain=ExDom): arg_code = GC.generate(arg_element_code[1]) args.append(ast.Starred(arg_code, ast.Load())) elif is_form(arg_element_code, '**') and len(arg_element_code) == 2: # double starred argument - expand as kwlist assert len(arg_element_code) == 2 # verify no other dblstars already? with GC.let(domain=ExDom): arg_code = GC.generate(arg_element_code[1]) keywords.append(ast.keyword(None, arg_code)) else: # positional argument with GC.let(domain=ExDom): arg_code = GC.generate(arg_element) args.append(arg_code) else: # arg_element_code not a Form # then generate as expression with GC.let(domain=ExDom): arg_code = GC.generate(arg_element) args.append(arg_code) return expr_wrap(ast.Call(func_code, args, keywords), GC) if isinstance(acode, Seq): seq_codes = [] with GC.let(domain=ExDom): for e in acode: seq_codes.append(GC.generate(e)) if GC.domain == LVDom: return ast.Tuple(seq_codes, ast.Store()) elif GC.domain in [ExDom, SDom]: return expr_wrap(ast.Tuple(seq_codes, ast.Load()), GC) else: raise CodeGenerationError(acode.range, "Unexpected seq in domain `%s`." % str(GC.domain)) if isinstance(acode, Literal): element.color = colors.LITERAL if acode.type is str: return expr_wrap(ast.Str(acode.value), GC) elif acode.type in [int, float]: return expr_wrap(ast.Num(acode.value), GC) else: assert False if isinstance(acode, Identifier): if acode.full_name == "True": return expr_wrap(ast.NameConstant(True), GC) elif acode.full_name == "False": return expr_wrap(ast.NameConstant(False), GC) elif acode.full_name == "None": return expr_wrap(ast.NameConstant(None), GC) elif acode.full_name in GC.special_forms: element.color = colors.SPECIAL_FORM raise CodeGenerationError(acode.range, "Refering to special form `%s` by name requires the use of `the`." % acode.full_name) # elif acode.full_name in GC.macros: # raise CodeGenerationError(acode.range, # "Refering to macro `%s` by name requires the use of `the`." % acode.full_name) # elif acode.full_name in GC.id_macros: # raise CodeGenerationError(acode.range, # "Refering to identifier macro `%s` by name requires the use of `the`." % acode.full_name) elif GC.domain == LVDom: return ast.Name(acode.full_name, ast.Store()) elif GC.domain == DelDom: return ast.Name(acode.full_name, ast.Del()) else: return expr_wrap(ast.Name(acode.full_name, ast.Load()), GC)
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)
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 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)
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): 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)
def applies(self, element: Element): return is_form(element.code, "for")