def visit_Tuple(self, tup): """Try to turn tuple building into a constant.""" if tup.ctx != ast.Load: return tup # Don't do the rest for assignment or delete targets. # It would replace Tuple([]) with Constant('()')! if tup.elts: consts_w = [None] * len(tup.elts) for i in range(len(tup.elts)): node = tup.elts[i] w_const = node.as_constant(self.space, self.compile_info) if w_const is None: new_elts = self._optimize_constant_star_unpacks(tup.elts) if new_elts is not None: return ast.Tuple(new_elts, ast.Load, tup.lineno, tup.col_offset) return tup consts_w[i] = w_const # intern the string constants packed into the tuple here, # because assemble.py will see the result as just a tuple constant for i in range(len(consts_w)): consts_w[i] = misc.intern_if_common_string( self.space, consts_w[i]) else: consts_w = [] w_consts = self.space.newtuple(consts_w) return ast.Constant(w_consts, tup.lineno, tup.col_offset)
def _List2Tuple(self, node): if isinstance(node, ast.List): newnode = ast.Tuple(node.nodes) copy_node_fields(node, newnode) # if the resulting tuple contains only constants, we can # completely constant-fold the tuple creation itself return self.visitTuple(newnode) else: return node
def build_atom(builder, nb): atoms = get_atoms(builder, nb) top = atoms[0] if isinstance(top, TokenObject): # assert isinstance(top, TokenObject) # rtyper if top.name == builder.parser.tokens['LPAR']: if len(atoms) == 2: builder.push(ast.Tuple([], top.lineno)) else: builder.push(atoms[1]) elif top.name == builder.parser.tokens['LSQB']: if len(atoms) == 2: builder.push(ast.List([], top.lineno)) else: list_node = atoms[1] list_node.lineno = top.lineno builder.push(list_node) elif top.name == builder.parser.tokens['LBRACE']: items = [] for index in range(1, len(atoms) - 1, 4): # a : b , c : d # ^ +1 +2 +3 +4 items.append((atoms[index], atoms[index + 2])) builder.push(ast.Dict(items, top.lineno)) elif top.name == builder.parser.tokens['NAME']: val = top.get_value() builder.push(ast.Name(val, top.lineno)) elif top.name == builder.parser.tokens['NUMBER']: builder.push( ast.Const(builder.eval_number(top.get_value()), top.lineno)) elif top.name == builder.parser.tokens['STRING']: # need to concatenate strings in atoms s = '' if len(atoms) == 1: token = atoms[0] assert isinstance(token, TokenObject) builder.push( ast.Const( parsestr(builder.space, builder.source_encoding, token.get_value()), top.lineno)) else: space = builder.space empty = space.wrap('') accum = [] for token in atoms: assert isinstance(token, TokenObject) accum.append( parsestr(builder.space, builder.source_encoding, token.get_value())) w_s = space.call_method(empty, 'join', space.newlist(accum)) builder.push(ast.Const(w_s, top.lineno)) elif top.name == builder.parser.tokens['BACKQUOTE']: builder.push(ast.Backquote(atoms[1], atoms[1].lineno)) else: raise SyntaxError("unexpected tokens", top.lineno, top.col)
def build_trailer(builder, nb): """trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME """ atoms = get_atoms(builder, nb) first_token = atoms[0] # Case 1 : '(' ... if isinstance( first_token, TokenObject) and first_token.name == builder.parser.tokens['LPAR']: if len(atoms ) == 2: # and atoms[1].token == builder.parser.tokens['RPAR']: builder.push(ArglistObject([], None, None, first_token.lineno)) elif len(atoms) == 3: # '(' Arglist ')' # push arglist on the stack builder.push(atoms[1]) elif isinstance( first_token, TokenObject) and first_token.name == builder.parser.tokens['LSQB']: if len(atoms) == 3 and isinstance(atoms[1], SlicelistObject): builder.push(atoms[1]) else: # atoms is a list of, alternatively, values and comma tokens, # with '[' and ']' tokens at the end subs = [] for index in range(1, len(atoms) - 1, 2): atom = atoms[index] if isinstance(atom, SlicelistObject): num_slicevals = 3 slicevals = [] if atom.fake_rulename == 'slice': num_slicevals = 2 for val in atom.value[:num_slicevals]: if val is None: slicevals.append( ast.Const(builder.wrap_none(), atom.lineno)) else: slicevals.append(val) subs.append(ast.Sliceobj(slicevals, atom.lineno)) else: subs.append(atom) if len(atoms) > 3: # at least one comma sub = ast.Tuple(subs, first_token.lineno) else: [sub] = subs builder.push(SubscriptObject('subscript', sub, first_token.lineno)) elif len(atoms) == 2: # Attribute access: '.' NAME builder.push(atoms[0]) builder.push(atoms[1]) builder.push( TempRuleObject('pending-attr-access', 2, first_token.lineno)) else: assert False, "Trailer reducing implementation incomplete !"
def build_exprlist(builder, nb): """exprlist: expr (',' expr)* [',']""" atoms = get_atoms(builder, nb) if len(atoms) <= 2: builder.push(atoms[0]) else: names = [] values = [] isConst = True for index in range(0, len(atoms), 2): item = atoms[index] names.append(item) if isinstance(item, ast.Const): values.append(item) else: isConst = False if isConst: builder.push(ast.Const(builder.space.newtuple(values), atoms[0].lineno)) else: builder.push(ast.Tuple(names, atoms[0].lineno))
def build_testlist_gexp(builder, nb): atoms = get_atoms(builder, nb) if atoms: lineno = atoms[0].lineno else: lineno = -1 l = len(atoms) if l == 1: builder.push(atoms[0]) return items = [] token = atoms[1] if isinstance( token, TokenObject) and token.name == builder.parser.tokens['COMMA']: for i in range(0, l, 2): # this is atoms not 1 items.append(atoms[i]) else: # genfor: 'i for i in j' # GenExpr(GenExprInner(Name('i'), [GenExprFor(AssName('i', 'OP_ASSIGN'), Name('j'), [])])))])) expr = atoms[0] genexpr_for = parse_genexpr_for(atoms[1:]) genexpr_for[0].is_outmost = True builder.push( ast.GenExpr(ast.GenExprInner(expr, genexpr_for, lineno), lineno)) return isConst = True values = [] for item in items: if isinstance(item, ast.Const): values.append(item.value) else: isConst = False break if isConst: builder.push(ast.Const(builder.space.newtuple(values), lineno)) else: builder.push(ast.Tuple(items, lineno)) return
def parse_listcomp(tokens, builder): """parses 'for j in k for i in j if i %2 == 0' and returns a GenExprFor instance XXX: refactor with listmaker ? """ list_fors = [] ifs = [] index = 0 if tokens: lineno = tokens[0].lineno else: lineno = -1 while index < len(tokens): token = tokens[index] assert isinstance(token, TokenObject) # rtyper info + check if token.get_value() == 'for': index += 1 # skip 'for' ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) index += 2 # skip 'in' iterables = [tokens[index]] index += 1 while index < len(tokens): tok2 = tokens[index] if not isinstance(tok2, TokenObject): break if tok2.name != builder.parser.tokens['COMMA']: break iterables.append(tokens[index + 1]) index += 2 if len(iterables) == 1: iterable = iterables[0] else: iterable = ast.Tuple(iterables, token.lineno) while index < len(tokens): token = tokens[index] assert isinstance(token, TokenObject) # rtyper info if token.get_value() == 'if': ifs.append(ast.ListCompIf(tokens[index + 1], token.lineno)) index += 2 else: break list_fors.append(ast.ListCompFor(ass_node, iterable, ifs, lineno)) ifs = [] else: assert False, 'Unexpected token: expecting for in listcomp' # # Original implementation: # # if tokens[index].get_value() == 'for': # index += 1 # skip 'for' # ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) # index += 2 # skip 'in' # iterable = tokens[index] # index += 1 # while index < len(tokens) and tokens[index].get_value() == 'if': # ifs.append(ast.ListCompIf(tokens[index+1])) # index += 2 # list_fors.append(ast.ListCompFor(ass_node, iterable, ifs)) # ifs = [] # else: # raise ValueError('Unexpected token: %s' % tokens[index]) return list_fors