mirror of https://github.com/python/cpython
PEP 308 implementation, including minor refdocs and some testcases. It
breaks the parser module, because it adds the if/else construct as well as two new grammar rules for backward compatibility. If no one else fixes parsermodule, I guess I'll go ahead and fix it later this week. The TeX code was checked with texcheck.py, but not rendered. There is actually a slight incompatibility: >>> (x for x in lambda:0) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: iteration over non-sequence changes into >>> (x for x in lambda: 0) File "<stdin>", line 1 (x for x in lambda: 0) ^ SyntaxError: invalid syntax Since there's no way the former version can be useful, it's probably a bugfix ;)
This commit is contained in:
parent
d3a5f53a27
commit
dca3b9c797
|
@ -155,8 +155,7 @@ square brackets:
|
||||||
|
|
||||||
\begin{productionlist}
|
\begin{productionlist}
|
||||||
\production{test}
|
\production{test}
|
||||||
{\token{and_test} ( "or" \token{and_test} )*
|
{\token{or_test} | \token{lambda_form}}
|
||||||
| \token{lambda_form}}
|
|
||||||
\production{testlist}
|
\production{testlist}
|
||||||
{\token{test} ( "," \token{test} )* [ "," ]}
|
{\token{test} ( "," \token{test} )* [ "," ]}
|
||||||
\production{list_display}
|
\production{list_display}
|
||||||
|
@ -1017,7 +1016,8 @@ Boolean operations have the lowest priority of all Python operations:
|
||||||
|
|
||||||
\begin{productionlist}
|
\begin{productionlist}
|
||||||
\production{expression}
|
\production{expression}
|
||||||
{\token{or_test} | \token{lambda_form}}
|
{\token{or_test} [\token{if} \token{or_test} \token{else}
|
||||||
|
\token{test}] | \token{lambda_form}}
|
||||||
\production{or_test}
|
\production{or_test}
|
||||||
{\token{and_test} | \token{or_test} "or" \token{and_test}}
|
{\token{and_test} | \token{or_test} "or" \token{and_test}}
|
||||||
\production{and_test}
|
\production{and_test}
|
||||||
|
@ -1036,6 +1036,11 @@ The operator \keyword{not} yields \code{True} if its argument is false,
|
||||||
\code{False} otherwise.
|
\code{False} otherwise.
|
||||||
\opindex{not}
|
\opindex{not}
|
||||||
|
|
||||||
|
The expression \code{\var{x} if \var{C} else \var{y}} first evaluates
|
||||||
|
\var{C} (\emph{not} \var{x}); if \var{C} is true, \var{x} is evaluated and
|
||||||
|
its value is returned; otherwise, \var{y} is evaluated and its value is
|
||||||
|
returned.
|
||||||
|
|
||||||
The expression \code{\var{x} and \var{y}} first evaluates \var{x}; if
|
The expression \code{\var{x} and \var{y}} first evaluates \var{x}; if
|
||||||
\var{x} is false, its value is returned; otherwise, \var{y} is
|
\var{x} is false, its value is returned; otherwise, \var{y} is
|
||||||
evaluated and the resulting value is returned.
|
evaluated and the resulting value is returned.
|
||||||
|
|
|
@ -83,7 +83,17 @@ try_stmt: ('try' ':' suite
|
||||||
except_clause: 'except' [test [',' test]]
|
except_clause: 'except' [test [',' test]]
|
||||||
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
|
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
|
||||||
|
|
||||||
test: and_test ('or' and_test)* | lambdef
|
# 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
|
||||||
|
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
|
||||||
comparison: expr (comp_op expr)*
|
comparison: expr (comp_op expr)*
|
||||||
|
@ -110,7 +120,6 @@ subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
|
||||||
sliceop: ':' [test]
|
sliceop: ':' [test]
|
||||||
exprlist: expr (',' expr)* [',']
|
exprlist: expr (',' expr)* [',']
|
||||||
testlist: test (',' test)* [',']
|
testlist: test (',' test)* [',']
|
||||||
testlist_safe: test [(',' test)+ [',']]
|
|
||||||
dictmaker: test ':' test (',' test ':' test)* [',']
|
dictmaker: test ':' test (',' test ':' test)* [',']
|
||||||
|
|
||||||
classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
|
classdef: 'class' NAME ['(' [testlist] ')'] ':' suite
|
||||||
|
@ -123,7 +132,7 @@ list_for: 'for' exprlist 'in' testlist_safe [list_iter]
|
||||||
list_if: 'if' test [list_iter]
|
list_if: 'if' test [list_iter]
|
||||||
|
|
||||||
gen_iter: gen_for | gen_if
|
gen_iter: gen_for | gen_if
|
||||||
gen_for: 'for' exprlist 'in' test [gen_iter]
|
gen_for: 'for' exprlist 'in' or_test [gen_iter]
|
||||||
gen_if: 'if' test [gen_iter]
|
gen_if: 'if' test [gen_iter]
|
||||||
|
|
||||||
testlist1: test (',' test)*
|
testlist1: test (',' test)*
|
||||||
|
|
|
@ -175,10 +175,10 @@ struct _stmt {
|
||||||
|
|
||||||
struct _expr {
|
struct _expr {
|
||||||
enum { BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
|
enum { BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
|
||||||
Dict_kind=5, ListComp_kind=6, GeneratorExp_kind=7, Yield_kind=8,
|
IfExp_kind=5, Dict_kind=6, ListComp_kind=7, GeneratorExp_kind=8,
|
||||||
Compare_kind=9, Call_kind=10, Repr_kind=11, Num_kind=12,
|
Yield_kind=9, Compare_kind=10, Call_kind=11, Repr_kind=12,
|
||||||
Str_kind=13, Attribute_kind=14, Subscript_kind=15, Name_kind=16,
|
Num_kind=13, Str_kind=14, Attribute_kind=15, Subscript_kind=16,
|
||||||
List_kind=17, Tuple_kind=18 } kind;
|
Name_kind=17, List_kind=18, Tuple_kind=19 } kind;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
boolop_ty op;
|
boolop_ty op;
|
||||||
|
@ -201,6 +201,12 @@ struct _expr {
|
||||||
expr_ty body;
|
expr_ty body;
|
||||||
} Lambda;
|
} Lambda;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
expr_ty test;
|
||||||
|
expr_ty body;
|
||||||
|
expr_ty orelse;
|
||||||
|
} IfExp;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
asdl_seq *keys;
|
asdl_seq *keys;
|
||||||
asdl_seq *values;
|
asdl_seq *values;
|
||||||
|
@ -371,6 +377,8 @@ expr_ty BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno, PyArena
|
||||||
*arena);
|
*arena);
|
||||||
expr_ty UnaryOp(unaryop_ty op, expr_ty operand, int lineno, PyArena *arena);
|
expr_ty UnaryOp(unaryop_ty op, expr_ty operand, int lineno, PyArena *arena);
|
||||||
expr_ty Lambda(arguments_ty args, expr_ty body, int lineno, PyArena *arena);
|
expr_ty Lambda(arguments_ty args, expr_ty body, int lineno, PyArena *arena);
|
||||||
|
expr_ty IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, PyArena
|
||||||
|
*arena);
|
||||||
expr_ty Dict(asdl_seq * keys, asdl_seq * values, int lineno, PyArena *arena);
|
expr_ty Dict(asdl_seq * keys, asdl_seq * values, int lineno, PyArena *arena);
|
||||||
expr_ty ListComp(expr_ty elt, asdl_seq * generators, int lineno, PyArena
|
expr_ty ListComp(expr_ty elt, asdl_seq * generators, int lineno, PyArena
|
||||||
*arena);
|
*arena);
|
||||||
|
|
|
@ -40,40 +40,43 @@
|
||||||
#define try_stmt 295
|
#define try_stmt 295
|
||||||
#define except_clause 296
|
#define except_clause 296
|
||||||
#define suite 297
|
#define suite 297
|
||||||
#define test 298
|
#define testlist_safe 298
|
||||||
#define and_test 299
|
#define old_test 299
|
||||||
#define not_test 300
|
#define old_lambdef 300
|
||||||
#define comparison 301
|
#define test 301
|
||||||
#define comp_op 302
|
#define or_test 302
|
||||||
#define expr 303
|
#define and_test 303
|
||||||
#define xor_expr 304
|
#define not_test 304
|
||||||
#define and_expr 305
|
#define comparison 305
|
||||||
#define shift_expr 306
|
#define comp_op 306
|
||||||
#define arith_expr 307
|
#define expr 307
|
||||||
#define term 308
|
#define xor_expr 308
|
||||||
#define factor 309
|
#define and_expr 309
|
||||||
#define power 310
|
#define shift_expr 310
|
||||||
#define atom 311
|
#define arith_expr 311
|
||||||
#define listmaker 312
|
#define term 312
|
||||||
#define testlist_gexp 313
|
#define factor 313
|
||||||
#define lambdef 314
|
#define power 314
|
||||||
#define trailer 315
|
#define atom 315
|
||||||
#define subscriptlist 316
|
#define listmaker 316
|
||||||
#define subscript 317
|
#define testlist_gexp 317
|
||||||
#define sliceop 318
|
#define lambdef 318
|
||||||
#define exprlist 319
|
#define trailer 319
|
||||||
#define testlist 320
|
#define subscriptlist 320
|
||||||
#define testlist_safe 321
|
#define subscript 321
|
||||||
#define dictmaker 322
|
#define sliceop 322
|
||||||
#define classdef 323
|
#define exprlist 323
|
||||||
#define arglist 324
|
#define testlist 324
|
||||||
#define argument 325
|
#define dictmaker 325
|
||||||
#define list_iter 326
|
#define classdef 326
|
||||||
#define list_for 327
|
#define arglist 327
|
||||||
#define list_if 328
|
#define argument 328
|
||||||
#define gen_iter 329
|
#define list_iter 329
|
||||||
#define gen_for 330
|
#define list_for 330
|
||||||
#define gen_if 331
|
#define list_if 331
|
||||||
#define testlist1 332
|
#define gen_iter 332
|
||||||
#define encoding_decl 333
|
#define gen_for 333
|
||||||
#define yield_expr 334
|
#define gen_if 334
|
||||||
|
#define testlist1 335
|
||||||
|
#define encoding_decl 336
|
||||||
|
#define yield_expr 337
|
||||||
|
|
|
@ -798,3 +798,28 @@ verify(len(list(g)) == 10)
|
||||||
x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x))
|
x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x))
|
||||||
x = 5; t = True;
|
x = 5; t = True;
|
||||||
verify([(i,j) for i in range(10) for j in range(5)] == list(g))
|
verify([(i,j) for i in range(10) for j in range(5)] == list(g))
|
||||||
|
|
||||||
|
# Test ifelse expressions in various cases
|
||||||
|
def _checkeval(msg, ret):
|
||||||
|
"helper to check that evaluation of expressions is done correctly"
|
||||||
|
print x
|
||||||
|
return ret
|
||||||
|
|
||||||
|
verify([ x() for x in lambda: True, lambda: False if x() ] == [True])
|
||||||
|
verify([ x() for x in (lambda: True, lambda: False) if x() ] == [True])
|
||||||
|
verify([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ] == [True])
|
||||||
|
verify((5 if 1 else _checkeval("check 1", 0)) == 5)
|
||||||
|
verify((_checkeval("check 2", 0) if 0 else 5) == 5)
|
||||||
|
verify((5 and 6 if 0 else 1) == 1)
|
||||||
|
verify(((5 and 6) if 0 else 1) == 1)
|
||||||
|
verify((5 and (6 if 1 else 1)) == 6)
|
||||||
|
verify((0 or _checkeval("check 3", 2) if 0 else 3) == 3)
|
||||||
|
verify((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)) == 1)
|
||||||
|
verify((0 or 5 if 1 else _checkeval("check 6", 3)) == 5)
|
||||||
|
verify((not 5 if 1 else 1) == False)
|
||||||
|
verify((not 5 if 0 else 1) == 1)
|
||||||
|
verify((6 + 1 if 1 else 2) == 7)
|
||||||
|
verify((6 - 1 if 1 else 2) == 5)
|
||||||
|
verify((6 * 2 if 1 else 4) == 12)
|
||||||
|
verify((6 / 2 if 1 else 3) == 3)
|
||||||
|
verify((6 < 4 if 0 else 2) == 2)
|
||||||
|
|
|
@ -52,6 +52,7 @@ module Python
|
||||||
| BinOp(expr left, operator op, expr right)
|
| BinOp(expr left, operator op, expr right)
|
||||||
| UnaryOp(unaryop op, expr operand)
|
| UnaryOp(unaryop op, expr operand)
|
||||||
| Lambda(arguments args, expr body)
|
| Lambda(arguments args, expr body)
|
||||||
|
| IfExp(expr test, expr body, expr orelse)
|
||||||
| Dict(expr* keys, expr* values)
|
| Dict(expr* keys, expr* values)
|
||||||
| ListComp(expr elt, comprehension* generators)
|
| ListComp(expr elt, comprehension* generators)
|
||||||
| GeneratorExp(expr elt, comprehension* generators)
|
| GeneratorExp(expr elt, comprehension* generators)
|
||||||
|
|
|
@ -151,6 +151,12 @@ char *Lambda_fields[]={
|
||||||
"args",
|
"args",
|
||||||
"body",
|
"body",
|
||||||
};
|
};
|
||||||
|
PyTypeObject *IfExp_type;
|
||||||
|
char *IfExp_fields[]={
|
||||||
|
"test",
|
||||||
|
"body",
|
||||||
|
"orelse",
|
||||||
|
};
|
||||||
PyTypeObject *Dict_type;
|
PyTypeObject *Dict_type;
|
||||||
char *Dict_fields[]={
|
char *Dict_fields[]={
|
||||||
"keys",
|
"keys",
|
||||||
|
@ -431,6 +437,7 @@ static int init_types(void)
|
||||||
BinOp_type = make_type("BinOp", expr_type, BinOp_fields, 3);
|
BinOp_type = make_type("BinOp", expr_type, BinOp_fields, 3);
|
||||||
UnaryOp_type = make_type("UnaryOp", expr_type, UnaryOp_fields, 2);
|
UnaryOp_type = make_type("UnaryOp", expr_type, UnaryOp_fields, 2);
|
||||||
Lambda_type = make_type("Lambda", expr_type, Lambda_fields, 2);
|
Lambda_type = make_type("Lambda", expr_type, Lambda_fields, 2);
|
||||||
|
IfExp_type = make_type("IfExp", expr_type, IfExp_fields, 3);
|
||||||
Dict_type = make_type("Dict", expr_type, Dict_fields, 2);
|
Dict_type = make_type("Dict", expr_type, Dict_fields, 2);
|
||||||
ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2);
|
ListComp_type = make_type("ListComp", expr_type, ListComp_fields, 2);
|
||||||
GeneratorExp_type = make_type("GeneratorExp", expr_type,
|
GeneratorExp_type = make_type("GeneratorExp", expr_type,
|
||||||
|
@ -1137,6 +1144,38 @@ Lambda(arguments_ty args, expr_ty body, int lineno, PyArena *arena)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_ty
|
||||||
|
IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno, PyArena *arena)
|
||||||
|
{
|
||||||
|
expr_ty p;
|
||||||
|
if (!test) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"field test is required for IfExp");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!body) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"field body is required for IfExp");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!orelse) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"field orelse is required for IfExp");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||||
|
if (!p) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
p->kind = IfExp_kind;
|
||||||
|
p->v.IfExp.test = test;
|
||||||
|
p->v.IfExp.body = body;
|
||||||
|
p->v.IfExp.orelse = orelse;
|
||||||
|
p->lineno = lineno;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
expr_ty
|
expr_ty
|
||||||
Dict(asdl_seq * keys, asdl_seq * values, int lineno, PyArena *arena)
|
Dict(asdl_seq * keys, asdl_seq * values, int lineno, PyArena *arena)
|
||||||
{
|
{
|
||||||
|
@ -2077,6 +2116,25 @@ ast2obj_expr(void* _o)
|
||||||
goto failed;
|
goto failed;
|
||||||
Py_DECREF(value);
|
Py_DECREF(value);
|
||||||
break;
|
break;
|
||||||
|
case IfExp_kind:
|
||||||
|
result = PyType_GenericNew(IfExp_type, NULL, NULL);
|
||||||
|
if (!result) goto failed;
|
||||||
|
value = ast2obj_expr(o->v.IfExp.test);
|
||||||
|
if (!value) goto failed;
|
||||||
|
if (PyObject_SetAttrString(result, "test", value) == -1)
|
||||||
|
goto failed;
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = ast2obj_expr(o->v.IfExp.body);
|
||||||
|
if (!value) goto failed;
|
||||||
|
if (PyObject_SetAttrString(result, "body", value) == -1)
|
||||||
|
goto failed;
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = ast2obj_expr(o->v.IfExp.orelse);
|
||||||
|
if (!value) goto failed;
|
||||||
|
if (PyObject_SetAttrString(result, "orelse", value) == -1)
|
||||||
|
goto failed;
|
||||||
|
Py_DECREF(value);
|
||||||
|
break;
|
||||||
case Dict_kind:
|
case Dict_kind:
|
||||||
result = PyType_GenericNew(Dict_type, NULL, NULL);
|
result = PyType_GenericNew(Dict_type, NULL, NULL);
|
||||||
if (!result) goto failed;
|
if (!result) goto failed;
|
||||||
|
|
40
Python/ast.c
40
Python/ast.c
|
@ -847,6 +847,25 @@ ast_for_lambdef(struct compiling *c, const node *n)
|
||||||
return Lambda(args, expression, LINENO(n), c->c_arena);
|
return Lambda(args, expression, LINENO(n), c->c_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static expr_ty
|
||||||
|
ast_for_ifexpr(struct compiling *c, const node *n)
|
||||||
|
{
|
||||||
|
/* test: or_test 'if' or_test 'else' test */
|
||||||
|
expr_ty expression, body, orelse;
|
||||||
|
|
||||||
|
assert(NCH(n) >= 3);
|
||||||
|
body = ast_for_expr(c, CHILD(n, 0));
|
||||||
|
if (!body)
|
||||||
|
return NULL;
|
||||||
|
expression = ast_for_expr(c, CHILD(n, 2));
|
||||||
|
if (!expression)
|
||||||
|
return NULL;
|
||||||
|
orelse = ast_for_expr(c, CHILD(n, 4));
|
||||||
|
if (!orelse)
|
||||||
|
return NULL;
|
||||||
|
return IfExp(expression, body, orelse, LINENO(n), c->c_arena);
|
||||||
|
}
|
||||||
|
|
||||||
/* Count the number of 'for' loop in a list comprehension.
|
/* Count the number of 'for' loop in a list comprehension.
|
||||||
|
|
||||||
Helper for ast_for_listcomp().
|
Helper for ast_for_listcomp().
|
||||||
|
@ -1456,7 +1475,8 @@ static expr_ty
|
||||||
ast_for_expr(struct compiling *c, const node *n)
|
ast_for_expr(struct compiling *c, const node *n)
|
||||||
{
|
{
|
||||||
/* handle the full range of simple expressions
|
/* handle the full range of simple expressions
|
||||||
test: and_test ('or' and_test)* | lambdef
|
test: or_test ['if' or_test 'else' test] | lambdef
|
||||||
|
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
|
||||||
comparison: expr (comp_op expr)*
|
comparison: expr (comp_op expr)*
|
||||||
|
@ -1468,6 +1488,15 @@ ast_for_expr(struct compiling *c, const node *n)
|
||||||
term: factor (('*'|'/'|'%'|'//') factor)*
|
term: factor (('*'|'/'|'%'|'//') factor)*
|
||||||
factor: ('+'|'-'|'~') factor | power
|
factor: ('+'|'-'|'~') factor | power
|
||||||
power: atom trailer* ('**' factor)*
|
power: atom trailer* ('**' factor)*
|
||||||
|
|
||||||
|
As well as modified versions that exist for backward compatibility,
|
||||||
|
to explicitly allow:
|
||||||
|
[ x for x in lambda: 0, lambda: 1 ]
|
||||||
|
(which would be ambiguous without these extra rules)
|
||||||
|
|
||||||
|
old_test: or_test | old_lambdef
|
||||||
|
old_lambdef: 'lambda' [vararglist] ':' old_test
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
asdl_seq *seq;
|
asdl_seq *seq;
|
||||||
|
@ -1476,9 +1505,14 @@ ast_for_expr(struct compiling *c, const node *n)
|
||||||
loop:
|
loop:
|
||||||
switch (TYPE(n)) {
|
switch (TYPE(n)) {
|
||||||
case test:
|
case test:
|
||||||
if (TYPE(CHILD(n, 0)) == lambdef)
|
case old_test:
|
||||||
|
if (TYPE(CHILD(n, 0)) == lambdef ||
|
||||||
|
TYPE(CHILD(n, 0)) == old_lambdef)
|
||||||
return ast_for_lambdef(c, CHILD(n, 0));
|
return ast_for_lambdef(c, CHILD(n, 0));
|
||||||
/* Fall through to and_test */
|
else if (NCH(n) > 1)
|
||||||
|
return ast_for_ifexpr(c, n);
|
||||||
|
/* Fallthrough */
|
||||||
|
case or_test:
|
||||||
case and_test:
|
case and_test:
|
||||||
if (NCH(n) == 1) {
|
if (NCH(n) == 1) {
|
||||||
n = CHILD(n, 0);
|
n = CHILD(n, 0);
|
||||||
|
|
|
@ -2009,6 +2009,30 @@ compiler_class(struct compiler *c, stmt_ty s)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compiler_ifexp(struct compiler *c, expr_ty e)
|
||||||
|
{
|
||||||
|
basicblock *end, *next;
|
||||||
|
|
||||||
|
assert(e->kind == IfExp_kind);
|
||||||
|
end = compiler_new_block(c);
|
||||||
|
if (end == NULL)
|
||||||
|
return 0;
|
||||||
|
next = compiler_new_block(c);
|
||||||
|
if (next == NULL)
|
||||||
|
return 0;
|
||||||
|
VISIT(c, expr, e->v.IfExp.test);
|
||||||
|
ADDOP_JREL(c, JUMP_IF_FALSE, next);
|
||||||
|
ADDOP(c, POP_TOP);
|
||||||
|
VISIT(c, expr, e->v.IfExp.body);
|
||||||
|
ADDOP_JREL(c, JUMP_FORWARD, end);
|
||||||
|
compiler_use_next_block(c, next);
|
||||||
|
ADDOP(c, POP_TOP);
|
||||||
|
VISIT(c, expr, e->v.IfExp.orelse);
|
||||||
|
compiler_use_next_block(c, end);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compiler_lambda(struct compiler *c, expr_ty e)
|
compiler_lambda(struct compiler *c, expr_ty e)
|
||||||
{
|
{
|
||||||
|
@ -3290,6 +3314,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
||||||
break;
|
break;
|
||||||
case Lambda_kind:
|
case Lambda_kind:
|
||||||
return compiler_lambda(c, e);
|
return compiler_lambda(c, e);
|
||||||
|
case IfExp_kind:
|
||||||
|
return compiler_ifexp(c, e);
|
||||||
case Dict_kind:
|
case Dict_kind:
|
||||||
/* XXX get rid of arg? */
|
/* XXX get rid of arg? */
|
||||||
ADDOP_I(c, BUILD_MAP, 0);
|
ADDOP_I(c, BUILD_MAP, 0);
|
||||||
|
|
1246
Python/graminit.c
1246
Python/graminit.c
File diff suppressed because it is too large
Load Diff
|
@ -1084,6 +1084,11 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IfExp_kind:
|
||||||
|
VISIT(st, expr, e->v.IfExp.test);
|
||||||
|
VISIT(st, expr, e->v.IfExp.body);
|
||||||
|
VISIT(st, expr, e->v.IfExp.orelse);
|
||||||
|
break;
|
||||||
case Dict_kind:
|
case Dict_kind:
|
||||||
VISIT_SEQ(st, expr, e->v.Dict.keys);
|
VISIT_SEQ(st, expr, e->v.Dict.keys);
|
||||||
VISIT_SEQ(st, expr, e->v.Dict.values);
|
VISIT_SEQ(st, expr, e->v.Dict.values);
|
||||||
|
|
Loading…
Reference in New Issue