diff options
Diffstat (limited to 'Python')
| -rw-r--r-- | Python/Python-ast.c | 57 | ||||
| -rw-r--r-- | Python/ast.c | 125 | ||||
| -rw-r--r-- | Python/compile.c | 64 | ||||
| -rw-r--r-- | Python/graminit.c | 20 | ||||
| -rw-r--r-- | Python/symtable.c | 28 | 
5 files changed, 230 insertions, 64 deletions
| diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 18c2eb5d31..d5250a42f9 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -198,6 +198,12 @@ static char *SetComp_fields[]={          "elt",          "generators",  }; +static PyTypeObject *DictComp_type; +static char *DictComp_fields[]={ +        "key", +        "value", +        "generators", +};  static PyTypeObject *GeneratorExp_type;  static char *GeneratorExp_fields[]={          "elt", @@ -551,6 +557,8 @@ static int init_types(void)          if (!ListComp_type) return 0;          SetComp_type = make_type("SetComp", expr_type, SetComp_fields, 2);          if (!SetComp_type) return 0; +        DictComp_type = make_type("DictComp", expr_type, DictComp_fields, 3); +        if (!DictComp_type) return 0;          GeneratorExp_type = make_type("GeneratorExp", expr_type,                                        GeneratorExp_fields, 2);          if (!GeneratorExp_type) return 0; @@ -1445,6 +1453,33 @@ SetComp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, PyArena  }  expr_ty +DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int lineno, int +         col_offset, PyArena *arena) +{ +        expr_ty p; +        if (!key) { +                PyErr_SetString(PyExc_ValueError, +                                "field key is required for DictComp"); +                return NULL; +        } +        if (!value) { +                PyErr_SetString(PyExc_ValueError, +                                "field value is required for DictComp"); +                return NULL; +        } +        p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); +        if (!p) +                return NULL; +        p->kind = DictComp_kind; +        p->v.DictComp.key = key; +        p->v.DictComp.value = value; +        p->v.DictComp.generators = generators; +        p->lineno = lineno; +        p->col_offset = col_offset; +        return p; +} + +expr_ty  GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,               PyArena *arena)  { @@ -2479,6 +2514,26 @@ ast2obj_expr(void* _o)                          goto failed;                  Py_DECREF(value);                  break; +        case DictComp_kind: +                result = PyType_GenericNew(DictComp_type, NULL, NULL); +                if (!result) goto failed; +                value = ast2obj_expr(o->v.DictComp.key); +                if (!value) goto failed; +                if (PyObject_SetAttrString(result, "key", value) == -1) +                        goto failed; +                Py_DECREF(value); +                value = ast2obj_expr(o->v.DictComp.value); +                if (!value) goto failed; +                if (PyObject_SetAttrString(result, "value", value) == -1) +                        goto failed; +                Py_DECREF(value); +                value = ast2obj_list(o->v.DictComp.generators, +                                     ast2obj_comprehension); +                if (!value) goto failed; +                if (PyObject_SetAttrString(result, "generators", value) == -1) +                        goto failed; +                Py_DECREF(value); +                break;          case GeneratorExp_kind:                  result = PyType_GenericNew(GeneratorExp_type, NULL, NULL);                  if (!result) goto failed; @@ -3186,6 +3241,8 @@ init_ast(void)              return;          if (PyDict_SetItemString(d, "SetComp", (PyObject*)SetComp_type) < 0)              return; +        if (PyDict_SetItemString(d, "DictComp", (PyObject*)DictComp_type) < 0) +            return;          if (PyDict_SetItemString(d, "GeneratorExp",              (PyObject*)GeneratorExp_type) < 0) return;          if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return; diff --git a/Python/ast.c b/Python/ast.c index c611436f6d..23df29fc13 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -426,6 +426,9 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n)          case SetComp_kind:              expr_name = "set comprehension";              break; +        case DictComp_kind: +            expr_name = "dict comprehension"; +            break;          case Dict_kind:          case Set_kind:          case Num_kind: @@ -1047,23 +1050,22 @@ static int  count_comp_fors(const node *n)  {      int n_fors = 0; -    node *ch = CHILD(n, 1);    count_comp_for:      n_fors++; -    REQ(ch, comp_for); -    if (NCH(ch) == 5) -        ch = CHILD(ch, 4); +    REQ(n, comp_for); +    if (NCH(n) == 5) +        n = CHILD(n, 4);      else          return n_fors;    count_comp_iter: -    REQ(ch, comp_iter); -    ch = CHILD(ch, 0); -    if (TYPE(ch) == comp_for) +    REQ(n, comp_iter); +    n = CHILD(n, 0); +    if (TYPE(n) == comp_for)          goto count_comp_for; -    else if (TYPE(ch) == comp_if) { -        if (NCH(ch) == 3) { -            ch = CHILD(ch, 2); +    else if (TYPE(n) == comp_if) { +        if (NCH(n) == 3) { +            n = CHILD(n, 2);              goto count_comp_iter;          }          else @@ -1099,22 +1101,12 @@ count_comp_ifs(const node *n)      }  } -static expr_ty -ast_for_comprehension(struct compiling *c, const node *n, int type) +static asdl_seq * +ast_for_comprehension(struct compiling *c, const node *n)  { -    /* testlist_comp: test ( comp_for | (',' test)* [','] ) -       argument: [test '='] test [comp_for]       # Really [keyword '='] test */ -    expr_ty elt; -    asdl_seq *comps;      int i, n_fors; -    node *ch; -     -    assert(NCH(n) > 1); -     -    elt = ast_for_expr(c, CHILD(n, 0)); -    if (!elt) -        return NULL; -     +    asdl_seq *comps; +      n_fors = count_comp_fors(n);      if (n_fors == -1)          return NULL; @@ -1123,20 +1115,19 @@ ast_for_comprehension(struct compiling *c, const node *n, int type)      if (!comps)          return NULL; -    ch = CHILD(n, 1);      for (i = 0; i < n_fors; i++) {          comprehension_ty comp;          asdl_seq *t;          expr_ty expression;          node *for_ch; -        REQ(ch, comp_for); +        REQ(n, comp_for); -        for_ch = CHILD(ch, 1); +        for_ch = CHILD(n, 1);          t = ast_for_exprlist(c, for_ch, Store);          if (!t)              return NULL; -        expression = ast_for_expr(c, CHILD(ch, 3)); +        expression = ast_for_expr(c, CHILD(n, 3));          if (!expression)              return NULL; @@ -1146,19 +1137,19 @@ ast_for_comprehension(struct compiling *c, const node *n, int type)              comp = comprehension((expr_ty)asdl_seq_GET(t, 0), expression,                                   NULL, c->c_arena);          else -            comp = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, +            comp = comprehension(Tuple(t, Store, LINENO(n), n->n_col_offset,                                         c->c_arena),                                   expression, NULL, c->c_arena);          if (!comp)              return NULL; -        if (NCH(ch) == 5) { +        if (NCH(n) == 5) {              int j, n_ifs;              asdl_seq *ifs; -            ch = CHILD(ch, 4); -            n_ifs = count_comp_ifs(ch); +            n = CHILD(n, 4); +            n_ifs = count_comp_ifs(n);              if (n_ifs == -1)                  return NULL; @@ -1167,24 +1158,44 @@ ast_for_comprehension(struct compiling *c, const node *n, int type)                  return NULL;              for (j = 0; j < n_ifs; j++) { -                REQ(ch, comp_iter); -                ch = CHILD(ch, 0); -                REQ(ch, comp_if); +                REQ(n, comp_iter); +                n = CHILD(n, 0); +                REQ(n, comp_if); -                expression = ast_for_expr(c, CHILD(ch, 1)); +                expression = ast_for_expr(c, CHILD(n, 1));                  if (!expression)                      return NULL;                  asdl_seq_SET(ifs, j, expression); -                if (NCH(ch) == 3) -                    ch = CHILD(ch, 2); +                if (NCH(n) == 3) +                    n = CHILD(n, 2);              } -            /* on exit, must guarantee that ch is a comp_for */ -            if (TYPE(ch) == comp_iter) -                ch = CHILD(ch, 0); +            /* on exit, must guarantee that n is a comp_for */ +            if (TYPE(n) == comp_iter) +                n = CHILD(n, 0);              comp->ifs = ifs;          }          asdl_seq_SET(comps, i, comp);      } +    return comps; +} + +static expr_ty +ast_for_itercomp(struct compiling *c, const node *n, int type) +{ +    /* testlist_comp: test ( comp_for | (',' test)* [','] ) +       argument: [test '='] test [comp_for]       # Really [keyword '='] test */ +    expr_ty elt; +    asdl_seq *comps; +     +    assert(NCH(n) > 1); +     +    elt = ast_for_expr(c, CHILD(n, 0)); +    if (!elt) +        return NULL; +     +    comps = ast_for_comprehension(c, CHILD(n, 1)); +    if (!comps) +        return NULL;      if (type == COMP_GENEXP)          return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena); @@ -1198,24 +1209,48 @@ ast_for_comprehension(struct compiling *c, const node *n, int type)  }  static expr_ty +ast_for_dictcomp(struct compiling *c, const node *n) +{ +    expr_ty key, value; +    asdl_seq *comps; +     +    assert(NCH(n) > 3); +    REQ(CHILD(n, 1), COLON); +     +    key = ast_for_expr(c, CHILD(n, 0)); +    if (!key) +        return NULL; + +    value = ast_for_expr(c, CHILD(n, 2)); +    if (!value) +        return NULL; +     +    comps = ast_for_comprehension(c, CHILD(n, 3)); +    if (!comps) +        return NULL; +     +    return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena); +} + +static expr_ty  ast_for_genexp(struct compiling *c, const node *n)  {      assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument)); -    return ast_for_comprehension(c, n, COMP_GENEXP); +    return ast_for_itercomp(c, n, COMP_GENEXP);  }  static expr_ty  ast_for_listcomp(struct compiling *c, const node *n)  {      assert(TYPE(n) == (testlist_comp)); -    return ast_for_comprehension(c, n, COMP_LISTCOMP); +    return ast_for_itercomp(c, n, COMP_LISTCOMP);  }  static expr_ty  ast_for_setcomp(struct compiling *c, const node *n)  {      assert(TYPE(n) == (dictorsetmaker)); -    return ast_for_comprehension(c, n, COMP_SETCOMP); +    return ast_for_itercomp(c, n, COMP_SETCOMP);  } @@ -1313,6 +1348,8 @@ ast_for_atom(struct compiling *c, const node *n)          } else if (TYPE(CHILD(ch, 1)) == comp_for) {              /* it's a set comprehension */              return ast_for_setcomp(c, ch); +        } else if (NCH(ch) > 3 && TYPE(CHILD(ch, 3)) == comp_for) { +            return ast_for_dictcomp(c, ch);          } else {              /* it's a dict */              size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ diff --git a/Python/compile.c b/Python/compile.c index cbb6b4d61a..77c6a775b7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -42,6 +42,7 @@ int Py_OptimizeFlag = 0;  #define COMP_GENEXP   0  #define COMP_LISTCOMP 1  #define COMP_SETCOMP  2 +#define COMP_DICTCOMP 3  struct instr {  	unsigned i_jabs : 1; @@ -2753,7 +2754,7 @@ compiler_call_helper(struct compiler *c,  static int  compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,  				 asdl_seq *generators, int gen_index,  -				 expr_ty elt, int type) +				 expr_ty elt, expr_ty val, int type)  {  	/* generate code for the iterator, then each of the ifs,  	   and then write to the element */ @@ -2801,7 +2802,7 @@ compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,  	if (++gen_index < asdl_seq_LEN(generators))  		if (!compiler_comprehension_generator(c, tmpname,   						      generators, gen_index, -						      elt, type)) +						      elt, val, type))  		return 0;  	/* only append after the last for generator */ @@ -2825,6 +2826,17 @@ compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,  			VISIT(c, expr, elt);  			ADDOP(c, SET_ADD);  			break; +		case COMP_DICTCOMP: +			if (!compiler_nameop(c, tmpname, Load)) +				return 0; +			/* With 'd[k] = v', v is evaluated before k, so we do +			   the same. STORE_SUBSCR requires (item, map, key), +			   so we still end up ROTing once. */ +			VISIT(c, expr, val); +			ADDOP(c, ROT_TWO); +			VISIT(c, expr, elt); +			ADDOP(c, STORE_SUBSCR); +			break;  		default:  			return 0;  		} @@ -2846,7 +2858,7 @@ compiler_comprehension_generator(struct compiler *c, PyObject *tmpname,  static int  compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, -		       asdl_seq *generators, expr_ty elt) +		       asdl_seq *generators, expr_ty elt, expr_ty val)  {  	PyCodeObject *co = NULL;  	identifier tmp = NULL; @@ -2859,18 +2871,34 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,  		goto error;  	if (type != COMP_GENEXP) { +		int op;  		tmp = compiler_new_tmpname(c);  		if (!tmp)  			goto error_in_scope; +		switch (type) { +		case COMP_LISTCOMP: +			op = BUILD_LIST; +			break; +		case COMP_SETCOMP: +			op = BUILD_SET; +			break; +		case COMP_DICTCOMP: +			op = BUILD_MAP; +			break; +		default: +			PyErr_Format(PyExc_SystemError, +				     "unknown comprehension type %d", type); +			goto error_in_scope; +		} -		ADDOP_I(c, (type == COMP_LISTCOMP ? -			    BUILD_LIST : BUILD_SET), 0); +		ADDOP_I(c, op, 0);  		ADDOP(c, DUP_TOP);  		if (!compiler_nameop(c, tmp, Store))  			goto error_in_scope;  	} -	if (!compiler_comprehension_generator(c, tmp, generators, 0, elt, type)) +	if (!compiler_comprehension_generator(c, tmp, generators, 0, elt, +					      val, type))  		goto error_in_scope;  	if (type != COMP_GENEXP) { @@ -2911,7 +2939,7 @@ compiler_genexp(struct compiler *c, expr_ty e)  	assert(e->kind == GeneratorExp_kind);  	return compiler_comprehension(c, e, COMP_GENEXP, name,  				      e->v.GeneratorExp.generators, -				      e->v.GeneratorExp.elt); +				      e->v.GeneratorExp.elt, NULL);  }  static int @@ -2926,7 +2954,7 @@ compiler_listcomp(struct compiler *c, expr_ty e)  	assert(e->kind == ListComp_kind);  	return compiler_comprehension(c, e, COMP_LISTCOMP, name,  				      e->v.ListComp.generators, -				      e->v.ListComp.elt); +				      e->v.ListComp.elt, NULL);  }  static int @@ -2941,7 +2969,23 @@ compiler_setcomp(struct compiler *c, expr_ty e)  	assert(e->kind == SetComp_kind);  	return compiler_comprehension(c, e, COMP_SETCOMP, name,  				      e->v.SetComp.generators, -				      e->v.SetComp.elt); +				      e->v.SetComp.elt, NULL); +} + + +static int +compiler_dictcomp(struct compiler *c, expr_ty e) +{ +	static identifier name; +	if (!name) { +		name = PyString_FromString("<dictcomp>"); +		if (!name) +			return 0; +	} +	assert(e->kind == DictComp_kind); +	return compiler_comprehension(c, e, COMP_DICTCOMP, name, +				      e->v.DictComp.generators, +				      e->v.DictComp.key, e->v.DictComp.value);  } @@ -3173,6 +3217,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e)  		return compiler_listcomp(c, e);  	case SetComp_kind:  		return compiler_setcomp(c, e); +	case DictComp_kind: +		return compiler_dictcomp(c, e);  	case Yield_kind:  		if (c->u->u_ste->ste_type != FunctionBlock)  			return compiler_error(c, "'yield' outside function"); diff --git a/Python/graminit.c b/Python/graminit.c index c1c070b36e..95905d7f59 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1505,7 +1505,8 @@ static arc arcs_71_4[2] = {  	{24, 6},  	{0, 4},  }; -static arc arcs_71_5[2] = { +static arc arcs_71_5[3] = { +	{156, 3},  	{30, 7},  	{0, 5},  }; @@ -1518,18 +1519,27 @@ static arc arcs_71_7[2] = {  	{0, 7},  };  static arc arcs_71_8[1] = { -	{25, 2}, +	{25, 9}, +}; +static arc arcs_71_9[1] = { +	{24, 10}, +}; +static arc arcs_71_10[2] = { +	{30, 7}, +	{0, 10},  }; -static state states_71[9] = { +static state states_71[11] = {  	{1, arcs_71_0},  	{4, arcs_71_1},  	{1, arcs_71_2},  	{1, arcs_71_3},  	{2, arcs_71_4}, -	{2, arcs_71_5}, +	{3, arcs_71_5},  	{2, arcs_71_6},  	{2, arcs_71_7},  	{1, arcs_71_8}, +	{1, arcs_71_9}, +	{2, arcs_71_10},  };  static arc arcs_72_0[1] = {  	{160, 1}, @@ -1864,7 +1874,7 @@ static dfa dfas[81] = {  	 "\000\040\040\200\000\000\000\000\000\040\000\000\000\000\000\000\200\041\224\017\000"},  	{326, "testlist", 0, 3, states_70,  	 "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\200\041\224\017\000"}, -	{327, "dictorsetmaker", 0, 9, states_71, +	{327, "dictorsetmaker", 0, 11, states_71,  	 "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\200\041\224\017\000"},  	{328, "classdef", 0, 8, states_72,  	 "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001"}, diff --git a/Python/symtable.c b/Python/symtable.c index 30e97d6f5a..121f3eeafe 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -170,6 +170,7 @@ static int symtable_visit_expr(struct symtable *st, expr_ty s);  static int symtable_visit_genexp(struct symtable *st, expr_ty s);  static int symtable_visit_listcomp(struct symtable *st, expr_ty s);  static int symtable_visit_setcomp(struct symtable *st, expr_ty s); +static int symtable_visit_dictcomp(struct symtable *st, expr_ty s);  static int symtable_visit_arguments(struct symtable *st, arguments_ty);  static int symtable_visit_excepthandler(struct symtable *st, excepthandler_ty);  static int symtable_visit_alias(struct symtable *st, alias_ty); @@ -183,7 +184,7 @@ static int symtable_visit_annotations(struct symtable *st, stmt_ty s);  static identifier top = NULL, lambda = NULL, genexpr = NULL, -    listcomp = NULL, setcomp = NULL, __class__ = NULL; +    listcomp = NULL, setcomp = NULL, dictcomp = NULL, __class__ = NULL;  #define GET_IDENTIFIER(VAR) \  	((VAR) ? (VAR) : ((VAR) = PyUnicode_InternFromString(# VAR))) @@ -1270,6 +1271,10 @@ symtable_visit_expr(struct symtable *st, expr_ty e)  		if (!symtable_visit_setcomp(st, e))  			return 0;  		break; +	case DictComp_kind: +		if (!symtable_visit_dictcomp(st, e)) +			return 0; +		break;          case Yield_kind:  		if (e->v.Yield.value)  			VISIT(st, expr, e->v.Yield.value); @@ -1521,8 +1526,8 @@ symtable_visit_slice(struct symtable *st, slice_ty s)  static int   symtable_handle_comprehension(struct symtable *st, expr_ty e, -                              identifier scope_name, -                              asdl_seq *generators, expr_ty elt) +                              identifier scope_name, asdl_seq *generators, +                              expr_ty elt, expr_ty value)  {  	int is_generator = (e->kind == GeneratorExp_kind);  	int needs_tmp = !is_generator; @@ -1550,6 +1555,8 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e,  	VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e);  	VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension,  				generators, 1, (void*)e); +	if (value) +		VISIT_IN_BLOCK(st, expr, value, (void*)e);  	VISIT_IN_BLOCK(st, expr, elt, (void*)e);  	return symtable_exit_block(st, (void *)e);  } @@ -1559,7 +1566,7 @@ symtable_visit_genexp(struct symtable *st, expr_ty e)  {  	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(genexpr),                                               e->v.GeneratorExp.generators, -                                             e->v.GeneratorExp.elt); +                                             e->v.GeneratorExp.elt, NULL);  }  static int  @@ -1567,7 +1574,7 @@ symtable_visit_listcomp(struct symtable *st, expr_ty e)  {  	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(listcomp),                                               e->v.ListComp.generators, -                                             e->v.ListComp.elt); +                                             e->v.ListComp.elt, NULL);  }  static int @@ -1575,5 +1582,14 @@ symtable_visit_setcomp(struct symtable *st, expr_ty e)  {  	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(setcomp),  					     e->v.SetComp.generators, -					     e->v.SetComp.elt); +					     e->v.SetComp.elt, NULL); +} + +static int +symtable_visit_dictcomp(struct symtable *st, expr_ty e) +{ +	return symtable_handle_comprehension(st, e, GET_IDENTIFIER(dictcomp), +					     e->v.DictComp.generators, +					     e->v.DictComp.key, +					     e->v.DictComp.value);  } | 
