Commit 65391c35 authored by Nick Coghlan's avatar Nick Coghlan

Hide list comp variables and support set comprehensions

parent 7b1dd1ee
...@@ -363,6 +363,10 @@ is the address to jump to (which should be a \code{FOR_ITER} ...@@ -363,6 +363,10 @@ is the address to jump to (which should be a \code{FOR_ITER}
instruction). instruction).
\end{opcodedesc} \end{opcodedesc}
\begin{opcodedesc}{SET_ADD}{}
Calls \code{set.add(TOS1, TOS)}. Used to implement set comprehensions.
\end{opcodedesc}
\begin{opcodedesc}{LIST_APPEND}{} \begin{opcodedesc}{LIST_APPEND}{}
Calls \code{list.append(TOS1, TOS)}. Used to implement list comprehensions. Calls \code{list.append(TOS1, TOS)}. Used to implement list comprehensions.
\end{opcodedesc} \end{opcodedesc}
......
...@@ -82,16 +82,10 @@ with_var: 'as' expr ...@@ -82,16 +82,10 @@ with_var: 'as' expr
except_clause: 'except' [test ['as' NAME]] except_clause: 'except' [test ['as' NAME]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
# Backward compatibility cruft to support:
# [ x for x in lambda: True, lambda: False if x() ]
# even while also allowing:
# lambda x: 5 if x else 2
# (But not a mix of the two)
testlist_safe: old_test [(',' old_test)+ [',']]
old_test: or_test | old_lambdef
old_lambdef: 'lambda' [varargslist] ':' old_test
test: or_test ['if' or_test 'else' test] | lambdef test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ':' test
lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
or_test: and_test ('or' and_test)* or_test: and_test ('or' and_test)*
and_test: not_test ('and' not_test)* and_test: not_test ('and' not_test)*
not_test: 'not' not_test | comparison not_test: 'not' not_test | comparison
...@@ -105,33 +99,28 @@ arith_expr: term (('+'|'-') term)* ...@@ -105,33 +99,28 @@ arith_expr: term (('+'|'-') term)*
term: factor (('*'|'/'|'%'|'//') factor)* term: factor (('*'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power factor: ('+'|'-'|'~') factor | power
power: atom trailer* ['**' factor] power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_gexp] ')' | atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [listmaker] ']' | '[' [testlist_comp] ']' |
'{' [dictsetmaker] '}' | '{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...') NAME | NUMBER | STRING+ | '...')
listmaker: test ( list_for | (',' test)* [','] ) testlist_comp: test ( comp_for | (',' test)* [','] )
testlist_gexp: test ( gen_for | (',' test)* [','] )
lambdef: 'lambda' [varargslist] ':' test
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [','] subscriptlist: subscript (',' subscript)* [',']
subscript: test | [test] ':' [test] [sliceop] subscript: test | [test] ':' [test] [sliceop]
sliceop: ':' [test] sliceop: ':' [test]
exprlist: expr (',' expr)* [','] exprlist: expr (',' expr)* [',']
testlist: test (',' test)* [','] testlist: test (',' test)* [',']
dictsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [',']) dictorsetmaker: ( (test ':' test (',' test ':' test)* [',']) |
(test (comp_for | (',' test)* [','])) )
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
argument: test [gen_for] | test '=' test # Really [keyword '='] test argument: test [comp_for] | test '=' test # Really [keyword '='] test
list_iter: list_for | list_if
list_for: 'for' exprlist 'in' testlist_safe [list_iter]
list_if: 'if' old_test [list_iter]
gen_iter: gen_for | gen_if comp_iter: comp_for | comp_if
gen_for: 'for' exprlist 'in' or_test [gen_iter] comp_for: 'for' exprlist 'in' or_test [comp_iter]
gen_if: 'if' old_test [gen_iter] comp_if: 'if' test_nocond [comp_iter]
testlist1: test (',' test)* testlist1: test (',' test)*
......
...@@ -183,10 +183,10 @@ struct _stmt { ...@@ -183,10 +183,10 @@ struct _stmt {
enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4, enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8, IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
GeneratorExp_kind=9, Yield_kind=10, Compare_kind=11, SetComp_kind=9, GeneratorExp_kind=10, Yield_kind=11,
Call_kind=12, Num_kind=13, Str_kind=14, Bytes_kind=15, Compare_kind=12, Call_kind=13, Num_kind=14, Str_kind=15,
Ellipsis_kind=16, Attribute_kind=17, Subscript_kind=18, Bytes_kind=16, Ellipsis_kind=17, Attribute_kind=18,
Name_kind=19, List_kind=20, Tuple_kind=21}; Subscript_kind=19, Name_kind=20, List_kind=21, Tuple_kind=22};
struct _expr { struct _expr {
enum _expr_kind kind; enum _expr_kind kind;
union { union {
...@@ -231,6 +231,11 @@ struct _expr { ...@@ -231,6 +231,11 @@ struct _expr {
asdl_seq *generators; asdl_seq *generators;
} ListComp; } ListComp;
struct {
expr_ty elt;
asdl_seq *generators;
} SetComp;
struct { struct {
expr_ty elt; expr_ty elt;
asdl_seq *generators; asdl_seq *generators;
...@@ -465,6 +470,9 @@ expr_ty _Py_Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena); ...@@ -465,6 +470,9 @@ expr_ty _Py_Set(asdl_seq * elts, int lineno, int col_offset, PyArena *arena);
#define ListComp(a0, a1, a2, a3, a4) _Py_ListComp(a0, a1, a2, a3, a4) #define ListComp(a0, a1, a2, a3, a4) _Py_ListComp(a0, a1, a2, a3, a4)
expr_ty _Py_ListComp(expr_ty elt, asdl_seq * generators, int lineno, int expr_ty _Py_ListComp(expr_ty elt, asdl_seq * generators, int lineno, int
col_offset, PyArena *arena); col_offset, PyArena *arena);
#define SetComp(a0, a1, a2, a3, a4) _Py_SetComp(a0, a1, a2, a3, a4)
expr_ty _Py_SetComp(expr_ty elt, asdl_seq * generators, int lineno, int
col_offset, PyArena *arena);
#define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4) #define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4)
expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int
col_offset, PyArena *arena); col_offset, PyArena *arena);
......
...@@ -46,10 +46,10 @@ ...@@ -46,10 +46,10 @@
#define with_var 301 #define with_var 301
#define except_clause 302 #define except_clause 302
#define suite 303 #define suite 303
#define testlist_safe 304 #define test 304
#define old_test 305 #define test_nocond 305
#define old_lambdef 306 #define lambdef 306
#define test 307 #define lambdef_nocond 307
#define or_test 308 #define or_test 308
#define and_test 309 #define and_test 309
#define not_test 310 #define not_test 310
...@@ -64,25 +64,20 @@ ...@@ -64,25 +64,20 @@
#define factor 319 #define factor 319
#define power 320 #define power 320
#define atom 321 #define atom 321
#define listmaker 322 #define testlist_comp 322
#define testlist_gexp 323 #define trailer 323
#define lambdef 324 #define subscriptlist 324
#define trailer 325 #define subscript 325
#define subscriptlist 326 #define sliceop 326
#define subscript 327 #define exprlist 327
#define sliceop 328 #define testlist 328
#define exprlist 329 #define dictorsetmaker 329
#define testlist 330 #define classdef 330
#define dictsetmaker 331 #define arglist 331
#define classdef 332 #define argument 332
#define arglist 333 #define comp_iter 333
#define argument 334 #define comp_for 334
#define list_iter 335 #define comp_if 335
#define list_for 336 #define testlist1 336
#define list_if 337 #define encoding_decl 337
#define gen_iter 338 #define yield_expr 338
#define gen_for 339
#define gen_if 340
#define testlist1 341
#define encoding_decl 342
#define yield_expr 343
...@@ -21,6 +21,7 @@ extern "C" { ...@@ -21,6 +21,7 @@ extern "C" {
#define UNARY_INVERT 15 #define UNARY_INVERT 15
#define SET_ADD 17
#define LIST_APPEND 18 #define LIST_APPEND 18
#define BINARY_POWER 19 #define BINARY_POWER 19
......
...@@ -5,31 +5,35 @@ ...@@ -5,31 +5,35 @@
extern "C" { extern "C" {
#endif #endif
/* XXX(ncoghlan): This is a weird mix of public names and interpreter internal
* names.
*/
typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock } typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock }
_Py_block_ty; _Py_block_ty;
struct _symtable_entry; struct _symtable_entry;
struct symtable { struct symtable {
const char *st_filename; /* name of file being compiled */ const char *st_filename; /* name of file being compiled */
struct _symtable_entry *st_cur; /* current symbol table entry */ struct _symtable_entry *st_cur; /* current symbol table entry */
struct _symtable_entry *st_top; /* module entry */ struct _symtable_entry *st_top; /* symbol table entry for module */
PyObject *st_symbols; /* dictionary of symbol table entries */ PyObject *st_blocks; /* dict: map AST node addresses
PyObject *st_stack; /* stack of namespace info */ * to symbol table entries */
PyObject *st_global; /* borrowed ref to MODULE in st_symbols */ PyObject *st_stack; /* list: stack of namespace info */
int st_nblocks; /* number of blocks */ PyObject *st_global; /* borrowed ref to st_top->st_symbols */
PyObject *st_private; /* name of current class or NULL */ int st_nblocks; /* number of blocks used */
int st_tmpname; /* temporary name counter */ PyObject *st_private; /* name of current class or NULL */
PyFutureFeatures *st_future; /* module's future features */ PyFutureFeatures *st_future; /* module's future features */
}; };
typedef struct _symtable_entry { typedef struct _symtable_entry {
PyObject_HEAD PyObject_HEAD
PyObject *ste_id; /* int: key in st_symbols */ PyObject *ste_id; /* int: key in ste_table->st_blocks */
PyObject *ste_symbols; /* dict: name to flags */ PyObject *ste_symbols; /* dict: variable names to flags */
PyObject *ste_name; /* string: name of block */ PyObject *ste_name; /* string: name of current block */
PyObject *ste_varnames; /* list of variable names */ PyObject *ste_varnames; /* list of variable names */
PyObject *ste_children; /* list of child ids */ PyObject *ste_children; /* list of child blocks */
_Py_block_ty ste_type; /* module, class, or function */ _Py_block_ty ste_type; /* module, class, or function */
int ste_unoptimized; /* false if namespace is optimized */ int ste_unoptimized; /* false if namespace is optimized */
unsigned ste_nested : 1; /* true if block is nested */ unsigned ste_nested : 1; /* true if block is nested */
...@@ -80,7 +84,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *); ...@@ -80,7 +84,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *);
table. GLOBAL is returned from PyST_GetScope() for either of them. table. GLOBAL is returned from PyST_GetScope() for either of them.
It is stored in ste_symbols at bits 12-15. It is stored in ste_symbols at bits 12-15.
*/ */
#define SCOPE_OFF 11 #define SCOPE_OFFSET 11
#define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL) #define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL)
#define LOCAL 1 #define LOCAL 1
......
...@@ -559,7 +559,7 @@ class Transformer: ...@@ -559,7 +559,7 @@ class Transformer:
testlist1 = testlist testlist1 = testlist
exprlist = testlist exprlist = testlist
def testlist_gexp(self, nodelist): def testlist_comp(self, nodelist):
if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for: if len(nodelist) == 2 and nodelist[1][0] == symbol.gen_for:
test = self.com_node(nodelist[0]) test = self.com_node(nodelist[0])
return self.com_generator_expression(test, nodelist[1]) return self.com_generator_expression(test, nodelist[1])
...@@ -1027,7 +1027,7 @@ class Transformer: ...@@ -1027,7 +1027,7 @@ class Transformer:
# loop to avoid trivial recursion # loop to avoid trivial recursion
while 1: while 1:
t = node[0] t = node[0]
if t in (symbol.exprlist, symbol.testlist, symbol.testlist_safe, symbol.testlist_gexp): if t in (symbol.exprlist, symbol.testlist, symbol.testlist_comp):
if len(node) > 2: if len(node) > 2:
return self.com_assign_tuple(node, assigning) return self.com_assign_tuple(node, assigning)
node = node[1] node = node[1]
......
...@@ -2282,10 +2282,8 @@ class Context(object): ...@@ -2282,10 +2282,8 @@ class Context(object):
_ignored_flags = [] _ignored_flags = []
if not isinstance(flags, dict): if not isinstance(flags, dict):
flags = dict([(s,s in flags) for s in _signals]) flags = dict([(s,s in flags) for s in _signals])
del s
if traps is not None and not isinstance(traps, dict): if traps is not None and not isinstance(traps, dict):
traps = dict([(s,s in traps) for s in _signals]) traps = dict([(s,s in traps) for s in _signals])
del s
for name, val in locals().items(): for name, val in locals().items():
if val is None: if val is None:
setattr(self, name, _copy.copy(getattr(DefaultContext, name))) setattr(self, name, _copy.copy(getattr(DefaultContext, name)))
......
...@@ -57,6 +57,7 @@ def_op('UNARY_NOT', 12) ...@@ -57,6 +57,7 @@ def_op('UNARY_NOT', 12)
def_op('UNARY_INVERT', 15) def_op('UNARY_INVERT', 15)
def_op('SET_ADD', 17)
def_op('LIST_APPEND', 18) def_op('LIST_APPEND', 18)
def_op('BINARY_POWER', 19) def_op('BINARY_POWER', 19)
def_op('BINARY_MULTIPLY', 20) def_op('BINARY_MULTIPLY', 20)
......
...@@ -163,7 +163,6 @@ _tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3] ...@@ -163,7 +163,6 @@ _tuplesize2code = [EMPTY_TUPLE, TUPLE1, TUPLE2, TUPLE3]
__all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)]) __all__.extend([x for x in dir() if re.match("[A-Z][A-Z0-9_]+$",x)])
del x
# Pickling machinery # Pickling machinery
......
...@@ -20,9 +20,9 @@ from datetime import time ...@@ -20,9 +20,9 @@ from datetime import time
from datetime import date, datetime from datetime import date, datetime
pickle_choices = [(pickler, unpickler, proto) pickle_choices = [(pickler, unpickler, proto)
for pickler in pickle, cPickle for pickler in (pickle, cPickle)
if pickler is not None if pickler is not None
for unpickler in pickle, cPickle for unpickler in (pickle, cPickle)
if unpickler is not None if unpickler is not None
for proto in range(3)] for proto in range(3)]
if cPickle is None: if cPickle is None:
......
...@@ -129,8 +129,12 @@ class DisTests(unittest.TestCase): ...@@ -129,8 +129,12 @@ class DisTests(unittest.TestCase):
def test_bug_1333982(self): def test_bug_1333982(self):
# This one is checking bytecodes generated for an `assert` statement, # This one is checking bytecodes generated for an `assert` statement,
# so fails if the tests are run with -O. Skip this test then. # so fails if the tests are run with -O. Skip this test then.
if __debug__: pass # Test has been disabled due to change in the way
self.do_disassembly_test(bug1333982, dis_bug1333982) # list comps are handled. The byte code now includes
# a memory address and a file location, so they change from
# run to run.
# if __debug__:
# self.do_disassembly_test(bug1333982, dis_bug1333982)
def test_big_linenos(self): def test_big_linenos(self):
def func(count): def func(count):
......
...@@ -843,7 +843,8 @@ class GrammarTests(unittest.TestCase): ...@@ -843,7 +843,8 @@ class GrammarTests(unittest.TestCase):
print(x) print(x)
return ret return ret
self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True]) # the next line is not allowed anymore
#self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True])
self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True]) self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True])
self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True]) self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True])
self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5) self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5)
......
This diff is collapsed.
This diff is collapsed.
...@@ -5,7 +5,7 @@ Here's an example of the sort of thing that is tested. ...@@ -5,7 +5,7 @@ Here's an example of the sort of thing that is tested.
>>> def f(x): >>> def f(x):
... global x ... global x
Traceback (most recent call last): Traceback (most recent call last):
SyntaxError: name 'x' is local and global SyntaxError: name 'x' is parameter and global
The tests are all raise SyntaxErrors. They were created by checking The tests are all raise SyntaxErrors. They were created by checking
each C call that raises SyntaxError. There are several modules that each C call that raises SyntaxError. There are several modules that
...@@ -373,7 +373,7 @@ Misuse of the nonlocal statement can lead to a few unique syntax errors. ...@@ -373,7 +373,7 @@ Misuse of the nonlocal statement can lead to a few unique syntax errors.
... nonlocal x ... nonlocal x
Traceback (most recent call last): Traceback (most recent call last):
... ...
SyntaxError: name 'x' is local and nonlocal SyntaxError: name 'x' is parameter and nonlocal
>>> def f(): >>> def f():
... global x ... global x
......
...@@ -28,7 +28,6 @@ DATA_CRLF = "\r\n".join(DATA_TEMPLATE) + "\r\n" ...@@ -28,7 +28,6 @@ DATA_CRLF = "\r\n".join(DATA_TEMPLATE) + "\r\n"
# before end-of-file. # before end-of-file.
DATA_MIXED = "\n".join(DATA_TEMPLATE) + "\r" DATA_MIXED = "\n".join(DATA_TEMPLATE) + "\r"
DATA_SPLIT = [x + "\n" for x in DATA_TEMPLATE] DATA_SPLIT = [x + "\n" for x in DATA_TEMPLATE]
del x
class TestGenericUnivNewlines(unittest.TestCase): class TestGenericUnivNewlines(unittest.TestCase):
# use a class variable DATA to define the data to write to the file # use a class variable DATA to define the data to write to the file
......
...@@ -32,7 +32,6 @@ from token import * ...@@ -32,7 +32,6 @@ from token import *
import token import token
__all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize", __all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize",
"generate_tokens", "NL", "untokenize"] "generate_tokens", "NL", "untokenize"]
del x
del token del token
COMMENT = N_TOKENS COMMENT = N_TOKENS
......
...@@ -28,6 +28,9 @@ TO DO ...@@ -28,6 +28,9 @@ TO DO
Core and Builtins Core and Builtins
----------------- -----------------
- Patch #1660500: hide iteration variable in list comps, add set comps
and use common code to handle compilation of iterative expressions
- By default, != returns the opposite of ==, unless the latter returns - By default, != returns the opposite of ==, unless the latter returns
NotImplemented. NotImplemented.
......
This diff is collapsed.
...@@ -33,7 +33,7 @@ symtable_symtable(PyObject *self, PyObject *args) ...@@ -33,7 +33,7 @@ symtable_symtable(PyObject *self, PyObject *args)
st = Py_SymtableString(str, filename, start); st = Py_SymtableString(str, filename, start);
if (st == NULL) if (st == NULL)
return NULL; return NULL;
t = st->st_symbols; t = st->st_blocks;
Py_INCREF(t); Py_INCREF(t);
PyMem_Free((void *)st->st_future); PyMem_Free((void *)st->st_future);
PySymtable_Free(st); PySymtable_Free(st);
......
...@@ -56,6 +56,7 @@ module Python version "$Revision$" ...@@ -56,6 +56,7 @@ module Python version "$Revision$"
| Dict(expr* keys, expr* values) | Dict(expr* keys, expr* values)
| Set(expr* elts) | Set(expr* elts)
| ListComp(expr elt, comprehension* generators) | ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators) | GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur -- the grammar constrains where yield expressions can occur
| Yield(expr? value) | Yield(expr? value)
......
...@@ -192,6 +192,11 @@ static char *ListComp_fields[]={ ...@@ -192,6 +192,11 @@ static char *ListComp_fields[]={
"elt", "elt",
"generators", "generators",
}; };
static PyTypeObject *SetComp_type;
static char *SetComp_fields[]={
"elt",
"generators",
};
static PyTypeObject *GeneratorExp_type; static PyTypeObject *GeneratorExp_type;
static char *GeneratorExp_fields[]={ static char *GeneratorExp_fields[]={
"elt", "elt",
...@@ -543,6 +548,8 @@ static int init_types(void) ...@@ -543,6 +548,8 @@ static int init_types(void)
if (!Set_type) return 0; if (!Set_type) return 0;
ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2); ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2);
if (!ListComp_type) return 0; if (!ListComp_type) return 0;
SetComp_type = make_type("SetComp", expr_type, SetComp_fields, 2);
if (!SetComp_type) return 0;
GeneratorExp_type = make_type("GeneratorExp", expr_type, GeneratorExp_type = make_type("GeneratorExp", expr_type,
GeneratorExp_fields, 2); GeneratorExp_fields, 2);
if (!GeneratorExp_type) return 0; if (!GeneratorExp_type) return 0;
...@@ -1418,6 +1425,27 @@ ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, ...@@ -1418,6 +1425,27 @@ ListComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
return p; return p;
} }
expr_ty
SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena
*arena)
{
expr_ty p;
if (!elt) {
PyErr_SetString(PyExc_ValueError,
"field elt is required for SetComp");
return NULL;
}
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = SetComp_kind;
p->v.SetComp.elt = elt;
p->v.SetComp.generators = generators;
p->lineno = lineno;
p->col_offset = col_offset;
return p;
}
expr_ty expr_ty
GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
PyArena *arena) PyArena *arena)
...@@ -2416,6 +2444,21 @@ ast2obj_expr(void* _o) ...@@ -2416,6 +2444,21 @@ ast2obj_expr(void* _o)
goto failed; goto failed;
Py_DECREF(value); Py_DECREF(value);
break; break;
case SetComp_kind:
result = PyType_GenericNew(SetComp_type, NULL, NULL);
if (!result) goto failed;
value = ast2obj_expr(o->v.SetComp.elt);
if (!value) goto failed;
if (PyObject_SetAttrString(result, "elt", value) == -1)
goto failed;
Py_DECREF(value);
value = ast2obj_list(o->v.SetComp.generators,
ast2obj_comprehension);
if (!value) goto failed;
if (PyObject_SetAttrString(result, "generators", value) == -1)
goto failed;
Py_DECREF(value);
break;
case GeneratorExp_kind: case GeneratorExp_kind:
result = PyType_GenericNew(GeneratorExp_type, NULL, NULL); result = PyType_GenericNew(GeneratorExp_type, NULL, NULL);
if (!result) goto failed; if (!result) goto failed;
...@@ -3120,6 +3163,8 @@ init_ast(void) ...@@ -3120,6 +3163,8 @@ init_ast(void)
if (PyDict_SetItemString(d, "Set", (PyObject*)Set_type) < 0) return; if (PyDict_SetItemString(d, "Set", (PyObject*)Set_type) < 0) return;
if (PyDict_SetItemString(d, "ListComp", (PyObject*)ListComp_type) < 0) if (PyDict_SetItemString(d, "ListComp", (PyObject*)ListComp_type) < 0)
return; return;
if (PyDict_SetItemString(d, "SetComp", (PyObject*)SetComp_type) < 0)
return;
if (PyDict_SetItemString(d, "GeneratorExp", if (PyDict_SetItemString(d, "GeneratorExp",
(PyObject*)GeneratorExp_type) < 0) return; (PyObject*)GeneratorExp_type) < 0) return;
if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return; if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return;
......
This diff is collapsed.
...@@ -1241,6 +1241,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) ...@@ -1241,6 +1241,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
} }
break; break;
case SET_ADD:
w = POP();
v = POP();
err = PySet_Add(v, w);
Py_DECREF(v);
Py_DECREF(w);
if (err == 0) {
PREDICT(JUMP_ABSOLUTE);
continue;
}
break;
case INPLACE_POWER: case INPLACE_POWER:
w = POP(); w = POP();
v = TOP(); v = TOP();
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -1175,8 +1175,8 @@ class PyBuildExt(build_ext): ...@@ -1175,8 +1175,8 @@ class PyBuildExt(build_ext):
# #
include_dirs = [ include_dirs = [
join(F, fw + '.framework', H) join(F, fw + '.framework', H)
for fw in 'Tcl', 'Tk' for fw in ('Tcl', 'Tk')
for H in 'Headers', 'Versions/Current/PrivateHeaders' for H in ('Headers', 'Versions/Current/PrivateHeaders')
] ]
# For 8.4a2, the X11 headers are not included. Rather than include a # For 8.4a2, the X11 headers are not included. Rather than include a
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment