cinap_lenrekadd hg and python4bb9e2215 years agoHistory
4570 lines · 109.1 KB · C
RawDownload
		default:			PyErr_SetString(PyExc_SystemError,					"param invalid for global variable");			return 0;		}		break;	case OP_NAME:		switch (ctx) {		case Load: op = LOAD_NAME; break;		case Store: op = STORE_NAME; break;		case Del: op = DELETE_NAME; break;		case AugLoad:		case AugStore:			break;		case Param:		default:			PyErr_SetString(PyExc_SystemError,					"param invalid for name variable");			return 0;		}		break;	} 	assert(op);	arg = compiler_add_o(c, dict, mangled);	Py_DECREF(mangled);	if (arg < 0)		return 0;	return compiler_addop_i(c, op, arg);} static intcompiler_boolop(struct compiler *c, expr_ty e){	basicblock *end;	int jumpi, i, n;	asdl_seq *s; 	assert(e->kind == BoolOp_kind);	if (e->v.BoolOp.op == And)		jumpi = JUMP_IF_FALSE;	else		jumpi = JUMP_IF_TRUE;	end = compiler_new_block(c);	if (end == NULL)		return 0;	s = e->v.BoolOp.values;	n = asdl_seq_LEN(s) - 1;	assert(n >= 0);	for (i = 0; i < n; ++i) {		VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));		ADDOP_JREL(c, jumpi, end);		ADDOP(c, POP_TOP)	}	VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n));	compiler_use_next_block(c, end);	return 1;} static intcompiler_list(struct compiler *c, expr_ty e){	int n = asdl_seq_LEN(e->v.List.elts);	if (e->v.List.ctx == Store) {		ADDOP_I(c, UNPACK_SEQUENCE, n);	}	VISIT_SEQ(c, expr, e->v.List.elts);	if (e->v.List.ctx == Load) {		ADDOP_I(c, BUILD_LIST, n);	}	return 1;} static intcompiler_tuple(struct compiler *c, expr_ty e){	int n = asdl_seq_LEN(e->v.Tuple.elts);	if (e->v.Tuple.ctx == Store) {		ADDOP_I(c, UNPACK_SEQUENCE, n);	}	VISIT_SEQ(c, expr, e->v.Tuple.elts);	if (e->v.Tuple.ctx == Load) {		ADDOP_I(c, BUILD_TUPLE, n);	}	return 1;} static intcompiler_compare(struct compiler *c, expr_ty e){	int i, n;	basicblock *cleanup = NULL; 	/* XXX the logic can be cleaned up for 1 or multiple comparisons */	VISIT(c, expr, e->v.Compare.left);	n = asdl_seq_LEN(e->v.Compare.ops);	assert(n > 0);	if (n > 1) {		cleanup = compiler_new_block(c);		if (cleanup == NULL)		    return 0;		VISIT(c, expr,                         (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0));	}	for (i = 1; i < n; i++) {		ADDOP(c, DUP_TOP);		ADDOP(c, ROT_THREE);		ADDOP_I(c, COMPARE_OP,			cmpop((cmpop_ty)(asdl_seq_GET(                                                  e->v.Compare.ops, i - 1))));		ADDOP_JREL(c, JUMP_IF_FALSE, cleanup);		NEXT_BLOCK(c);		ADDOP(c, POP_TOP);		if (i < (n - 1))		    VISIT(c, expr,                             (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));	}	VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n - 1));	ADDOP_I(c, COMPARE_OP,	       cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n - 1))));	if (n > 1) {		basicblock *end = compiler_new_block(c);		if (end == NULL)		    return 0;		ADDOP_JREL(c, JUMP_FORWARD, end);		compiler_use_next_block(c, cleanup);		ADDOP(c, ROT_TWO);		ADDOP(c, POP_TOP);		compiler_use_next_block(c, end);	}	return 1;}#undef CMPCAST static intcompiler_call(struct compiler *c, expr_ty e){	int n, code = 0; 	VISIT(c, expr, e->v.Call.func);	n = asdl_seq_LEN(e->v.Call.args);	VISIT_SEQ(c, expr, e->v.Call.args);	if (e->v.Call.keywords) {		VISIT_SEQ(c, keyword, e->v.Call.keywords);		n |= asdl_seq_LEN(e->v.Call.keywords) << 8;	}	if (e->v.Call.starargs) {		VISIT(c, expr, e->v.Call.starargs);		code |= 1;	}	if (e->v.Call.kwargs) {		VISIT(c, expr, e->v.Call.kwargs);		code |= 2;	}	switch (code) {	case 0:		ADDOP_I(c, CALL_FUNCTION, n);		break;	case 1:		ADDOP_I(c, CALL_FUNCTION_VAR, n);		break;	case 2:		ADDOP_I(c, CALL_FUNCTION_KW, n);		break;	case 3:		ADDOP_I(c, CALL_FUNCTION_VAR_KW, n);		break;	}	return 1;} static intcompiler_listcomp_generator(struct compiler *c, PyObject *tmpname,			    asdl_seq *generators, int gen_index, 			    expr_ty elt){	/* generate code for the iterator, then each of the ifs,	   and then write to the element */ 	comprehension_ty l;	basicblock *start, *anchor, *skip, *if_cleanup;	int i, n; 	start = compiler_new_block(c);	skip = compiler_new_block(c);	if_cleanup = compiler_new_block(c);	anchor = compiler_new_block(c); 	if (start == NULL || skip == NULL || if_cleanup == NULL ||		anchor == NULL)	    return 0; 	l = (comprehension_ty)asdl_seq_GET(generators, gen_index);	VISIT(c, expr, l->iter);	ADDOP(c, GET_ITER);	compiler_use_next_block(c, start);	ADDOP_JREL(c, FOR_ITER, anchor);	NEXT_BLOCK(c);	VISIT(c, expr, l->target); 	/* XXX this needs to be cleaned up...a lot! */	n = asdl_seq_LEN(l->ifs);	for (i = 0; i < n; i++) {		expr_ty e = (expr_ty)asdl_seq_GET(l->ifs, i);		VISIT(c, expr, e);		ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);		NEXT_BLOCK(c);		ADDOP(c, POP_TOP);	}  	if (++gen_index < asdl_seq_LEN(generators))	    if (!compiler_listcomp_generator(c, tmpname, 					     generators, gen_index, elt))		return 0; 	/* only append after the last for generator */	if (gen_index >= asdl_seq_LEN(generators)) {	    if (!compiler_nameop(c, tmpname, Load))		return 0;	    VISIT(c, expr, elt);	    ADDOP(c, LIST_APPEND); 	    compiler_use_next_block(c, skip);	}	for (i = 0; i < n; i++) {		ADDOP_I(c, JUMP_FORWARD, 1);		if (i == 0)		    compiler_use_next_block(c, if_cleanup);		ADDOP(c, POP_TOP);	} 	ADDOP_JABS(c, JUMP_ABSOLUTE, start);	compiler_use_next_block(c, anchor);	/* delete the append method added to locals */	if (gen_index == 1)	    if (!compiler_nameop(c, tmpname, Del))		return 0;		return 1;} static intcompiler_listcomp(struct compiler *c, expr_ty e){	identifier tmp;	int rc = 0;	static identifier append;	asdl_seq *generators = e->v.ListComp.generators; 	assert(e->kind == ListComp_kind);	if (!append) {		append = PyString_InternFromString("append");		if (!append)			return 0;	}	tmp = compiler_new_tmpname(c);	if (!tmp)		return 0;	ADDOP_I(c, BUILD_LIST, 0);	ADDOP(c, DUP_TOP);	if (compiler_nameop(c, tmp, Store))	    rc = compiler_listcomp_generator(c, tmp, generators, 0, 					     e->v.ListComp.elt);	Py_DECREF(tmp);	return rc;} static intcompiler_genexp_generator(struct compiler *c,			  asdl_seq *generators, int gen_index, 			  expr_ty elt){	/* generate code for the iterator, then each of the ifs,	   and then write to the element */ 	comprehension_ty ge;	basicblock *start, *anchor, *skip, *if_cleanup, *end;	int i, n; 	start = compiler_new_block(c);	skip = compiler_new_block(c);	if_cleanup = compiler_new_block(c);	anchor = compiler_new_block(c);	end = compiler_new_block(c); 	if (start == NULL || skip == NULL || if_cleanup == NULL ||	    anchor == NULL || end == NULL)		return 0; 	ge = (comprehension_ty)asdl_seq_GET(generators, gen_index);	ADDOP_JREL(c, SETUP_LOOP, end);	if (!compiler_push_fblock(c, LOOP, start))		return 0; 	if (gen_index == 0) {		/* Receive outermost iter as an implicit argument */		c->u->u_argcount = 1;		ADDOP_I(c, LOAD_FAST, 0);	}	else {		/* Sub-iter - calculate on the fly */		VISIT(c, expr, ge->iter);		ADDOP(c, GET_ITER);	}	compiler_use_next_block(c, start);	ADDOP_JREL(c, FOR_ITER, anchor);	NEXT_BLOCK(c);	VISIT(c, expr, ge->target); 	/* XXX this needs to be cleaned up...a lot! */	n = asdl_seq_LEN(ge->ifs);	for (i = 0; i < n; i++) {		expr_ty e = (expr_ty)asdl_seq_GET(ge->ifs, i);		VISIT(c, expr, e);		ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);		NEXT_BLOCK(c);		ADDOP(c, POP_TOP);	}  	if (++gen_index < asdl_seq_LEN(generators))		if (!compiler_genexp_generator(c, generators, gen_index, elt))			return 0; 	/* only append after the last 'for' generator */	if (gen_index >= asdl_seq_LEN(generators)) {		VISIT(c, expr, elt);		ADDOP(c, YIELD_VALUE);		ADDOP(c, POP_TOP); 		compiler_use_next_block(c, skip);	}	for (i = 0; i < n; i++) {		ADDOP_I(c, JUMP_FORWARD, 1);		if (i == 0)			compiler_use_next_block(c, if_cleanup); 		ADDOP(c, POP_TOP);	} 	ADDOP_JABS(c, JUMP_ABSOLUTE, start);	compiler_use_next_block(c, anchor);	ADDOP(c, POP_BLOCK);	compiler_pop_fblock(c, LOOP, start);	compiler_use_next_block(c, end); 	return 1;} static intcompiler_genexp(struct compiler *c, expr_ty e){	static identifier name;	PyCodeObject *co;	expr_ty outermost_iter = ((comprehension_ty)				 (asdl_seq_GET(e->v.GeneratorExp.generators,					       0)))->iter; 	if (!name) {		name = PyString_FromString("<genexpr>");		if (!name)			return 0;	} 	if (!compiler_enter_scope(c, name, (void *)e, e->lineno))		return 0;	compiler_genexp_generator(c, e->v.GeneratorExp.generators, 0,				  e->v.GeneratorExp.elt);	co = assemble(c, 1);	compiler_exit_scope(c);	if (co == NULL)		return 0; 	compiler_make_closure(c, co, 0);	Py_DECREF(co); 	VISIT(c, expr, outermost_iter);	ADDOP(c, GET_ITER);	ADDOP_I(c, CALL_FUNCTION, 1); 	return 1;} static intcompiler_visit_keyword(struct compiler *c, keyword_ty k){	ADDOP_O(c, LOAD_CONST, k->arg, consts);	VISIT(c, expr, k->value);	return 1;} /* Test whether expression is constant.	 For constants, report   whether they are true or false.    Return values: 1 for true, 0 for false, -1 for non-constant. */ static intexpr_constant(expr_ty e){	switch (e->kind) {	case Num_kind:		return PyObject_IsTrue(e->v.Num.n);	case Str_kind:		return PyObject_IsTrue(e->v.Str.s);	case Name_kind:		/* __debug__ is not assignable, so we can optimize		 * it away in if and while statements */		if (strcmp(PyString_AS_STRING(e->v.Name.id),		           "__debug__") == 0)			   return ! Py_OptimizeFlag;		/* fall through */	default:		return -1;	}} /*   Implements the with statement from PEP 343.    The semantics outlined in that PEP are as follows:      with EXPR as VAR:       BLOCK     It is implemented roughly as:     context = EXPR   exit = context.__exit__  # not calling it   value = context.__enter__()   try:       VAR = value  # if VAR present in the syntax       BLOCK   finally:       if an exception was raised:	   exc = copy of (exception, instance, traceback)       else:	   exc = (None, None, None)       exit(*exc) */static intcompiler_with(struct compiler *c, stmt_ty s){    static identifier enter_attr, exit_attr;    basicblock *block, *finally;    identifier tmpexit, tmpvalue = NULL;     assert(s->kind == With_kind);     if (!enter_attr) {	enter_attr = PyString_InternFromString("__enter__");	if (!enter_attr)	    return 0;    }    if (!exit_attr) {	exit_attr = PyString_InternFromString("__exit__");	if (!exit_attr)	    return 0;    }     block = compiler_new_block(c);    finally = compiler_new_block(c);    if (!block || !finally)	return 0;     /* Create a temporary variable to hold context.__exit__ */    tmpexit = compiler_new_tmpname(c);    if (tmpexit == NULL)	return 0;    PyArena_AddPyObject(c->c_arena, tmpexit);     if (s->v.With.optional_vars) {	/* Create a temporary variable to hold context.__enter__().	   We need to do this rather than preserving it on the stack	   because SETUP_FINALLY remembers the stack level.	   We need to do the assignment *inside* the try/finally	   so that context.__exit__() is called when the assignment	   fails.  But we need to call context.__enter__() *before*	   the try/finally so that if it fails we won't call	   context.__exit__().	*/	tmpvalue = compiler_new_tmpname(c);	if (tmpvalue == NULL)	    return 0;	PyArena_AddPyObject(c->c_arena, tmpvalue);    }     /* Evaluate EXPR */    VISIT(c, expr, s->v.With.context_expr);     /* Squirrel away context.__exit__  */    ADDOP(c, DUP_TOP);    ADDOP_O(c, LOAD_ATTR, exit_attr, names);    if (!compiler_nameop(c, tmpexit, Store))	return 0;     /* Call context.__enter__() */    ADDOP_O(c, LOAD_ATTR, enter_attr, names);    ADDOP_I(c, CALL_FUNCTION, 0);     if (s->v.With.optional_vars) {	/* Store it in tmpvalue */	if (!compiler_nameop(c, tmpvalue, Store))

Lines 3001–3500 of 4570. Previous lines