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 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 generate(self, element: Element, GC: GenerationContext): acode = element.code left_element, right_element = acode[1], acode[2] with GC.let(domain=ExDom): left_code = GC.generate(left_element) right_code = GC.generate(right_element) return expr_wrap(ast.BinOp(left_code, self.OP(), right_code), GC)
def generate(self, element:Element, GC:GenerationContext): acode = element.code left_element, right_element = acode[1], acode[2] with GC.let(domain=ExDom): left_code = GC.generate(left_element) right_code = GC.generate(right_element) return expr_wrap(ast.BinOp(left_code, self.OP(), right_code), GC)
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): 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 generate(self, element:Element, GC:GenerationContext): assert GC.domain == ExDom acode = element.code #assert len(acode) == 3 with GC.let(domain=ExDom): expression_code = GC.generate(acode[2]) # INCOMPLETE: # vararg, kwarg, defaults, kw_defaults # # - This whole arg section might be way off-track # - since anything could be an argument, we might need to check # when generating any expression if we actually need to return an ast.arg object # ..or, could we convert everything (e.g. ast.Name, ast.BoolOp, anything) # to an ast.arg after it's been generated args_codes = [] #with GC.let(domain=ArgDom): # for a in acode[1]: # # args_code should be a list of ast.arg objects! # args_codes.append(GC.generate(a)) arguments_code = ast.arguments(args_codes, ) return ast.Lambda(arguments_code, expression_code)
def generate(self, element:Element, GC:GenerationContext): acode = element.code func_specs = acode[1].code assert isinstance(func_specs[0].code, Identifier) function_name = func_specs[0].code.full_name arguments = self.generate_arguments(*func_specs[1:], GC=GC) body_elements = acode[2:] body_code = [] with GC.let(domain=SDom): for body_element in body_elements: extend_body(body_code, GC.generate(body_element)) decorators_code = [] returns_code = None return ast.FunctionDef(function_name, arguments, body_code, decorators_code, returns_code)
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 generate(self, element: Element, GC: GenerationContext): self.precheck(element, GC) acode = element.code test_element = acode[1] with GC.let(domain=ExDom): test_code = GC.generate(test_element) msg_code = None if len(acode) > 2: msg_element = acode[2] msg_code = GC.generate(msg_element) return ast.Assert(test=test_code, msg=msg_code)
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 operand_element = acode[1] with GC.let(domain=ExDom): operand_code = GC.generate(operand_element) return expr_wrap(ast.UnaryOp(self.OP(), operand_code), GC)
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_as_expressions(GC:GenerationContext, *args:Element): expr_codes = [] with GC.let(domain=ExDom): for arg_element in args: expr_codes.append(GC.generate(arg_element)) return expr_codes
def generate(self, element: Element, GC: GenerationContext): acode = element.code operand_element = acode[1] with GC.let(domain=ExDom): operand_code = GC.generate(operand_element) return expr_wrap(ast.UnaryOp(self.OP(), operand_code), GC)
def generate(self, element:Element, GC:GenerationContext): self.precheck(element, GC) acode = element.code test_element = acode[1] with GC.let(domain=ExDom): test_code = GC.generate(test_element) msg_code = None if len(acode) > 2: msg_element = acode[2] msg_code = GC.generate(msg_element) return ast.Assert(test=test_code, msg=msg_code)
def generate(self, element:Element, GC:GenerationContext): acode = element.code assert len(acode) == 3 # target_element = acode[1] # augvalue_element = acode[2] with GC.let(domain=LVDom): # "target can be Name, Subscript or Attribute, # but not a Tuple or List (unlike the targets of Assign)." target_code = GC.generate(acode[1]) with GC.let(domain=ExDom): augvalue_code = GC.generate(acode[2]) return ast.AugAssign(target_code, type(self).OP(), augvalue_code)
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 generate(self, element: Element, GC: GenerationContext): acode = element.code if len(acode) == 2: arg = acode[1] with GC.let(domain=ExDom): arg_code = GC.generate(arg) return expr_wrap(ast.UnaryOp(op=ast.USub(), operand=arg_code), GC) else: assert len(acode) == 3 left_element, right_element = acode[1], acode[2] with GC.let(domain=ExDom): left_code = GC.generate(left_element) right_code = GC.generate(right_element) return expr_wrap(ast.BinOp(left_code, ast.Sub(), right_code), GC)
def generate(self, element:Element, GC:GenerationContext): acode = element.code if len(acode) == 2: arg = acode[1] with GC.let(domain=ExDom): arg_code = GC.generate(arg) return expr_wrap(ast.UnaryOp(op=ast.USub(), operand=arg_code), GC) else: assert len(acode) == 3 left_element, right_element = acode[1], acode[2] with GC.let(domain=ExDom): left_code = GC.generate(left_element) right_code = GC.generate(right_element) return expr_wrap(ast.BinOp(left_code, ast.Sub(), right_code), GC)
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 generate(self, element:Element, GC:GenerationContext): self.precheck(element, GC) acode = element.code operands_seq = acode.last.code first_operand = operands_seq[0] with GC.let(domain = ExpressionDomain): first_operand_gen = GC.generate(first_operand) ops = [self.OPERAND_DICT[e.code.name]() for e in acode[1:-1]] comparators = [GC.generate(operand) for operand in operands_seq.iterate_from(1)] return expr_wrap( ast.Compare( left = first_operand_gen, ops = ops, comparators = comparators ), GC)
def generate(self, element: Element, GC: GenerationContext): self.precheck(element, GC) acode = element.code operands_seq = acode.last.code first_operand = operands_seq[0] with GC.let(domain=ExpressionDomain): first_operand_gen = GC.generate(first_operand) ops = [self.OPERAND_DICT[e.code.name]() for e in acode[1:-1]] comparators = [ GC.generate(operand) for operand in operands_seq.iterate_from(1) ] return expr_wrap( ast.Compare(left=first_operand_gen, ops=ops, comparators=comparators), GC)
def generate(self, element:Element, GC:GenerationContext): acode = element.code #assert isinstance(acode, Form) if len(acode) > 1: with GC.let(domain=ExDom): exception_obj_code = GC.generate(acode[1]) return ast.Raise(exception_obj_code, None) # Fix none to allow raise x from y syntax else: assert len(acode) == 1 return ast.Raise()
def generate(self, element:Element, GC:GenerationContext): self.precheck(element, GC) acode = element.code targets_element = acode[1] value_element = acode.last # if not isinstance(targets, Seq): # # targets is only one target # # with GC.let(domain=LVDom): # target_code = GC.generate(targets) with GC.let(domain=LVDom): targets_code = GC.generate(targets_element) with GC.let(domain=ExDom): value_code = GC.generate(value_element) return ast.Assign(targets=[targets_code], value=value_code)
def generate(self, element:Element, GC:GenerationContext): self.precheck(element, GC) acode = element.code if len(acode) == 1: return ast.Return(None) else: assert len(acode) == 2 # TODO: return a, b, c => tuple with GC.let(domain=ExpressionDomain): expression_code = GC.generate(acode[1]) return expr_wrap(ast.Yield(expression_code), GC)
def generate(self, element: Element, GC: GenerationContext): assert GC.domain == SDom acode = element.code if len(acode) == 1: return ast.Return(None) else: assert len(acode) == 2 # TODO: return a, b, c => tuple with GC.let(domain=ExpressionDomain): expression_code = GC.generate(acode[1]) return ast.Return(expression_code)
def generate(self, element:Element, GC:GenerationContext): assert GC.domain == SDom acode = element.code if len(acode) == 1: return ast.Return(None) else: assert len(acode) == 2 # TODO: return a, b, c => tuple with GC.let(domain=ExpressionDomain): expression_code = GC.generate(acode[1]) return ast.Return(expression_code)
def generate(self, element:Element, GC:GenerationContext): acode = element.code with GC.let(domain=ExDom): base_object_code = GC.generate(acode[1]) att_name = acode[2].code.full_name if GC.domain == LValueDomain: return ast.Attribute(base_object_code, att_name, ast.Store()) elif GC.domain == DeletionDomain: return ast.Attribute(base_object_code, att_name, ast.Del()) else: return expr_wrap(ast.Attribute(base_object_code, att_name, ast.Load()), GC)
def generate(self, element: Element, GC: GenerationContext): acode = element.code with GC.let(domain=ExDom): base_object_code = GC.generate(acode[1]) att_name = acode[2].code.full_name if GC.domain == LValueDomain: return ast.Attribute(base_object_code, att_name, ast.Store()) elif GC.domain == DeletionDomain: return ast.Attribute(base_object_code, att_name, ast.Del()) else: return expr_wrap( ast.Attribute(base_object_code, att_name, ast.Load()), GC)
def generate(self, element:Element, GC:GenerationContext): acode = element.code #assert isinstance(acode, Form) # if acode[0].code.full_name == "and": # op = ast.And() # else: # assert acode[0].code.full_name == "or" # op = ast.Or() juncts_code = [] with GC.let(domain=ExDom): for e in acode[1:]: juncts_code.append(GC.generate(e)) return expr_wrap(ast.BoolOp(self.OP(), juncts_code), GC)
def generate(self, element: Element, GC: GenerationContext): acode = element.code #assert isinstance(acode, Form) # if acode[0].code.full_name == "and": # op = ast.And() # else: # assert acode[0].code.full_name == "or" # op = ast.Or() juncts_code = [] with GC.let(domain=ExDom): for e in acode[1:]: juncts_code.append(GC.generate(e)) return expr_wrap(ast.BoolOp(self.OP(), juncts_code), GC)
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_arguments(self, *params, GC:GenerationContext): poststar = False argslist = [] kwonlyargslist = [] vararg = None kwarg = None defaults = [] kw_defaults = [] for param_element in params: param_code = param_element.code if isinstance(param_code, Identifier) and param_code.full_name == '*': poststar = True elif isinstance(param_code, Identifier): # arg arg_object = ast.arg(arg=param_code.full_name, annotation=None) #if self.vararg is not None or self.kwarg is not None: if poststar: # argument is keyword-only kwonlyargslist.append(arg_object) else: assert not poststar argslist.append(arg_object) elif isinstance(param_code, Form): #assert isinstance(param_code[0].code, Identifier) and if param_code[0].code.full_name == '=': # (= arg initializer) assert len(param_code) == 3 with GC.let(domain=ExDom): initializer_code = GC.generate(param_code[2]) assert isinstance(param_code[1].code, Identifier) arg_object = ast.arg(arg=param_code[1].code.full_name, annotation=None) if poststar: kwonlyargslist.append(arg_object) kw_defaults.append(initializer_code) else: argslist.append(arg_object) defaults.append(initializer_code) elif param_code[0].code.full_name == '*': # (* arg) #assert isinstance(param_code[1].code, Identifier) starg = ast.arg(arg=param_code[1].code.full_name, annotation=None) assert vararg is None vararg = starg poststar = True else: assert param_code[0].code.full_name == '**' # (** arg) #assert isinstance(param_code[1].code, Identifier) dblstarg = ast.arg(arg=param_code[1].code.full_name, annotation=None) assert kwarg is None kwarg = dblstarg poststar = True else: # (type, arg) # (type, (= arg initializer)) # (type, (* arg)) # (type, (** arg)) #assert isinstance(param_code, Seq) annotation_element = param_code[0] # if isinstance(annotation_code, Identifier): # annotation = ast.Name(id=annotation_code.full_name, ctx=ast.Load()) # # elif isinstance(annotation_code, Literal): # annotation = with GC.let(domain=ExDom): annotation_code = GC.generate(annotation_element) # and now the arg itself.. param_code = param_code[1].code if isinstance(param_code, Identifier): #assert param_code.full_name != '*' arg_object = ast.arg(arg=param_code.full_name, annotation=annotation_code) if poststar: kwonlyargslist.append(arg_object) else: argslist.append(arg_object) else: assert isinstance(param_code, Form) #assert isinstance(param_code[0].code, Identifier) and if param_code[0].code.full_name == '=': # (= arg initializer) assert len(param_code) == 3 with GC.let(domain=ExDom): initializer_code = GC.generate(param_code[2]) assert isinstance(param_code[1].code, Identifier) arg_object = ast.arg(arg=param_code[1].full_name, annotation=annotation_code) if poststar: kwonlyargslist.append(arg_object) kw_defaults.append(initializer_code) else: argslist.append(arg_object) defaults.append(initializer_code) elif param_code[0].code.full_name == '*': # (* arg) #assert isinstance(param_code[1].code, Identifier) starg = ast.arg(arg=param_code[1].code.full_name, annotation=annotation_code) assert vararg is None vararg = starg poststar = True else: assert param_code[0].code.full_name == '**' # (** arg) #assert isinstance(param_code[1].code, Identifier) dblstarg = ast.arg(arg=param_code[1].code.full_name, annotation=annotation_code) assert kwarg is None kwarg = dblstarg poststar = True return ast.arguments(args=argslist, vararg=vararg, kwonlyargs=kwonlyargslist, kwarg=kwarg, defaults=defaults, kw_defaults=kw_defaults)
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: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, 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 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:Element, GC:GenerationContext): acode = element.code rawspecs = acode[1].code macro_name_element = rawspecs[0] macro_name = rawspecs[0].code.full_name macro_name_safe = "__macro_"+macro_name+"__" rawspec_element_param = rawspecs[1].code.full_name rawspec_context_param = rawspecs[2].code.full_name expand_body_elements = acode[2:] expand_body_code = [] for b in expand_body_elements: extend_body(expand_body_code, GC.generate(b)) # The... second-to-last form? of the original element should be # responsible for generating (i.e. should return) code that will # complete the macro expansion; # the final statement executed in an .expand method would actually # be doing the replacing # final_body_code = expand_body_code[-1] # element.replace(final_body_code) #ast.Call( ... ) expand_args_code = ast.arguments( args=[ast.arg(arg="self"), ast.arg(arg=rawspec_element_param, annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()), attr="Element", ctx=ast.Load())), ast.arg(arg=rawspec_context_param, annotation=ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()), attr="ExpansionContext", ctx=ast.Load()))], kwonlyargs=[], defaults=[], kw_defaults=[] ) expand_method_code = ast.FunctionDef(name="expand", args=expand_args_code, body=expand_body_code, decorator_list=[] ) class_body_code = [] # extend_body(class_body_code, ast.Import([ast.alias(name="anoky.module", asname="__aky__")])) extend_body(class_body_code, ast.Assign(targets=[ast.Name(id="HEADTEXT", ctx=ast.Store())], value=ast.Str(macro_name))) extend_body(class_body_code, expand_method_code) classdef_code = ast.ClassDef( name=macro_name_safe, bases=[ast.Attribute(value=ast.Name(id="__aky__", ctx=ast.Load()), attr="Macro", ctx=ast.Load())], keywords=[], decorator_list=[], body=class_body_code) # __macros_macro_name__() instantiate_macro_code = ast.Call(func=ast.Name(id=macro_name_safe, ctx=ast.Load()), args=[], keywords=[]) # EC.macro_table[macro_name] context_code = ast.Subscript( value=ast.Attribute(value=ast.Name(id="EC", ctx=ast.Load()), attr="macro_table", ctx=ast.Load()), slice=ast.Index(ast.Str(macro_name)), ctx=ast.Store()) # __macros__[macro_name] = EC.macro_table[macro_name] = __macros_macro_name__() register_macro_code = ast.Assign(targets=[ ast.Subscript(value=ast.Name(id="__macros__", ctx=ast.Load()), slice=ast.Index(ast.Str(macro_name)), ctx=ast.Store()), # context_code ], value=instantiate_macro_code) generated_code = [classdef_code, register_macro_code] return generated_code
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 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=[])