cinap_lenrekadd hg and python4bb9e2215 years agoHistory
4570 lines · 109.1 KB · C
RawDownload
	}	co = assemble(c, 1);	compiler_exit_scope(c);	if (co == NULL)		return 0; 	compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));	Py_DECREF(co); 	for (i = 0; i < asdl_seq_LEN(decos); i++) {		ADDOP_I(c, CALL_FUNCTION, 1);	} 	return compiler_nameop(c, s->v.FunctionDef.name, Store);} static intcompiler_class(struct compiler *c, stmt_ty s){	int n;	PyCodeObject *co;	PyObject *str;	/* push class name on stack, needed by BUILD_CLASS */	ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts);	/* push the tuple of base classes on the stack */	n = asdl_seq_LEN(s->v.ClassDef.bases);	if (n > 0)		VISIT_SEQ(c, expr, s->v.ClassDef.bases);	ADDOP_I(c, BUILD_TUPLE, n);	if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s,				  s->lineno))		return 0;	c->u->u_private = s->v.ClassDef.name;	Py_INCREF(c->u->u_private);	str = PyString_InternFromString("__name__");	if (!str || !compiler_nameop(c, str, Load)) {		Py_XDECREF(str);		compiler_exit_scope(c);		return 0;	}		Py_DECREF(str);	str = PyString_InternFromString("__module__");	if (!str || !compiler_nameop(c, str, Store)) {		Py_XDECREF(str);		compiler_exit_scope(c);		return 0;	}	Py_DECREF(str); 	if (!compiler_body(c, s->v.ClassDef.body)) {		compiler_exit_scope(c);		return 0;	} 	ADDOP_IN_SCOPE(c, LOAD_LOCALS);	ADDOP_IN_SCOPE(c, RETURN_VALUE);	co = assemble(c, 1);	compiler_exit_scope(c);	if (co == NULL)		return 0; 	compiler_make_closure(c, co, 0);	Py_DECREF(co); 	ADDOP_I(c, CALL_FUNCTION, 0);	ADDOP(c, BUILD_CLASS);	if (!compiler_nameop(c, s->v.ClassDef.name, Store))		return 0;	return 1;} static intcompiler_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 intcompiler_lambda(struct compiler *c, expr_ty e){	PyCodeObject *co;	static identifier name;	arguments_ty args = e->v.Lambda.args;	assert(e->kind == Lambda_kind); 	if (!name) {		name = PyString_InternFromString("<lambda>");		if (!name)			return 0;	} 	if (args->defaults)		VISIT_SEQ(c, expr, args->defaults);	if (!compiler_enter_scope(c, name, (void *)e, e->lineno))		return 0; 	/* unpack nested arguments */	compiler_arguments(c, args);		c->u->u_argcount = asdl_seq_LEN(args->args);	VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);	ADDOP_IN_SCOPE(c, RETURN_VALUE);	co = assemble(c, 1);	compiler_exit_scope(c);	if (co == NULL)		return 0; 	compiler_make_closure(c, co, asdl_seq_LEN(args->defaults));	Py_DECREF(co); 	return 1;} static intcompiler_print(struct compiler *c, stmt_ty s){	int i, n;	bool dest; 	assert(s->kind == Print_kind);	n = asdl_seq_LEN(s->v.Print.values);	dest = false;	if (s->v.Print.dest) {		VISIT(c, expr, s->v.Print.dest);		dest = true;	}	for (i = 0; i < n; i++) {		expr_ty e = (expr_ty)asdl_seq_GET(s->v.Print.values, i);		if (dest) {			ADDOP(c, DUP_TOP);			VISIT(c, expr, e);			ADDOP(c, ROT_TWO);			ADDOP(c, PRINT_ITEM_TO);		}		else {			VISIT(c, expr, e);			ADDOP(c, PRINT_ITEM);		}	}	if (s->v.Print.nl) {		if (dest)			ADDOP(c, PRINT_NEWLINE_TO)		else			ADDOP(c, PRINT_NEWLINE)	}	else if (dest)		ADDOP(c, POP_TOP);	return 1;} static intcompiler_if(struct compiler *c, stmt_ty s){	basicblock *end, *next;	int constant;	assert(s->kind == If_kind);	end = compiler_new_block(c);	if (end == NULL)		return 0;	next = compiler_new_block(c);	if (next == NULL)	    return 0;		constant = expr_constant(s->v.If.test);	/* constant = 0: "if 0"	 * constant = 1: "if 1", "if 2", ...	 * constant = -1: rest */	if (constant == 0) {		if (s->v.If.orelse)			VISIT_SEQ(c, stmt, s->v.If.orelse);	} else if (constant == 1) {		VISIT_SEQ(c, stmt, s->v.If.body);	} else {		VISIT(c, expr, s->v.If.test);		ADDOP_JREL(c, JUMP_IF_FALSE, next);		ADDOP(c, POP_TOP);		VISIT_SEQ(c, stmt, s->v.If.body);		ADDOP_JREL(c, JUMP_FORWARD, end);		compiler_use_next_block(c, next);		ADDOP(c, POP_TOP);		if (s->v.If.orelse)	    		VISIT_SEQ(c, stmt, s->v.If.orelse);	}	compiler_use_next_block(c, end);	return 1;} static intcompiler_for(struct compiler *c, stmt_ty s){	basicblock *start, *cleanup, *end; 	start = compiler_new_block(c);	cleanup = compiler_new_block(c);	end = compiler_new_block(c);	if (start == NULL || end == NULL || cleanup == NULL)		return 0;	ADDOP_JREL(c, SETUP_LOOP, end);	if (!compiler_push_fblock(c, LOOP, start))		return 0;	VISIT(c, expr, s->v.For.iter);	ADDOP(c, GET_ITER);	compiler_use_next_block(c, start);	/* XXX(nnorwitz): is there a better way to handle this?	   for loops are special, we want to be able to trace them	   each time around, so we need to set an extra line number. */	c->u->u_lineno_set = false;	ADDOP_JREL(c, FOR_ITER, cleanup);	VISIT(c, expr, s->v.For.target);	VISIT_SEQ(c, stmt, s->v.For.body);	ADDOP_JABS(c, JUMP_ABSOLUTE, start);	compiler_use_next_block(c, cleanup);	ADDOP(c, POP_BLOCK);	compiler_pop_fblock(c, LOOP, start);	VISIT_SEQ(c, stmt, s->v.For.orelse);	compiler_use_next_block(c, end);	return 1;} static intcompiler_while(struct compiler *c, stmt_ty s){	basicblock *loop, *orelse, *end, *anchor = NULL;	int constant = expr_constant(s->v.While.test); 	if (constant == 0)		return 1;	loop = compiler_new_block(c);	end = compiler_new_block(c);	if (constant == -1) {		anchor = compiler_new_block(c);		if (anchor == NULL)			return 0;	}	if (loop == NULL || end == NULL)		return 0;	if (s->v.While.orelse) {		orelse = compiler_new_block(c);		if (orelse == NULL)			return 0;	}	else		orelse = NULL; 	ADDOP_JREL(c, SETUP_LOOP, end);	compiler_use_next_block(c, loop);	if (!compiler_push_fblock(c, LOOP, loop))		return 0;	if (constant == -1) {		VISIT(c, expr, s->v.While.test);		ADDOP_JREL(c, JUMP_IF_FALSE, anchor);		ADDOP(c, POP_TOP);	}	VISIT_SEQ(c, stmt, s->v.While.body);	ADDOP_JABS(c, JUMP_ABSOLUTE, loop); 	/* XXX should the two POP instructions be in a separate block	   if there is no else clause ?	*/ 	if (constant == -1) {		compiler_use_next_block(c, anchor);		ADDOP(c, POP_TOP);		ADDOP(c, POP_BLOCK);	}	compiler_pop_fblock(c, LOOP, loop);	if (orelse != NULL) /* what if orelse is just pass? */		VISIT_SEQ(c, stmt, s->v.While.orelse);	compiler_use_next_block(c, end); 	return 1;} static intcompiler_continue(struct compiler *c){	static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop";	static const char IN_FINALLY_ERROR_MSG[] = 			"'continue' not supported inside 'finally' clause";	int i; 	if (!c->u->u_nfblocks)		return compiler_error(c, LOOP_ERROR_MSG);	i = c->u->u_nfblocks - 1;	switch (c->u->u_fblock[i].fb_type) {	case LOOP:		ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block);		break;	case EXCEPT:	case FINALLY_TRY:		while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) {			/* Prevent try: ... finally:			      try: continue ...  or			      try: ... except: continue */			if (c->u->u_fblock[i].fb_type == FINALLY_END)				return compiler_error(c, IN_FINALLY_ERROR_MSG);		}		if (i == -1)			return compiler_error(c, LOOP_ERROR_MSG);		ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block);		break;	case FINALLY_END:		return compiler_error(c, IN_FINALLY_ERROR_MSG);	} 	return 1;} /* Code generated for "try: <body> finally: <finalbody>" is as follows:   		SETUP_FINALLY	L		<code for body>		POP_BLOCK		LOAD_CONST	<None>	L:	<code for finalbody>		END_FINALLY      The special instructions use the block stack.  Each block   stack entry contains the instruction that created it (here   SETUP_FINALLY), the level of the value stack at the time the   block stack entry was created, and a label (here L).      SETUP_FINALLY:	Pushes the current value stack level and the label	onto the block stack.   POP_BLOCK:	Pops en entry from the block stack, and pops the value	stack until its level is the same as indicated on the	block stack.  (The label is ignored.)   END_FINALLY:	Pops a variable number of entries from the *value* stack	and re-raises the exception they specify.  The number of	entries popped depends on the (pseudo) exception type.      The block stack is unwound when an exception is raised:   when a SETUP_FINALLY entry is found, the exception is pushed   onto the value stack (and the exception condition is cleared),   and the interpreter jumps to the label gotten from the block   stack.*/ static intcompiler_try_finally(struct compiler *c, stmt_ty s){	basicblock *body, *end;	body = compiler_new_block(c);	end = compiler_new_block(c);	if (body == NULL || end == NULL)		return 0; 	ADDOP_JREL(c, SETUP_FINALLY, end);	compiler_use_next_block(c, body);	if (!compiler_push_fblock(c, FINALLY_TRY, body))		return 0;	VISIT_SEQ(c, stmt, s->v.TryFinally.body);	ADDOP(c, POP_BLOCK);	compiler_pop_fblock(c, FINALLY_TRY, body); 	ADDOP_O(c, LOAD_CONST, Py_None, consts);	compiler_use_next_block(c, end);	if (!compiler_push_fblock(c, FINALLY_END, end))		return 0;	VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody);	ADDOP(c, END_FINALLY);	compiler_pop_fblock(c, FINALLY_END, end); 	return 1;} /*   Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":   (The contents of the value stack is shown in [], with the top   at the right; 'tb' is trace-back info, 'val' the exception's   associated value, and 'exc' the exception.)      Value stack		Label	Instruction	Argument   []				SETUP_EXCEPT	L1   []				<code for S>   []				POP_BLOCK   []				JUMP_FORWARD	L0      [tb, val, exc]	L1:	DUP				)   [tb, val, exc, exc]		<evaluate E1>			)   [tb, val, exc, exc, E1]	COMPARE_OP	EXC_MATCH	) only if E1   [tb, val, exc, 1-or-0]	JUMP_IF_FALSE	L2		)   [tb, val, exc, 1]		POP				)   [tb, val, exc]		POP   [tb, val]			<assign to V1>	(or POP if no V1)   [tb]				POP   []				<code for S1>				JUMP_FORWARD	L0      [tb, val, exc, 0]	L2:	POP   [tb, val, exc]		DUP   .............................etc.......................    [tb, val, exc, 0]	Ln+1:	POP   [tb, val, exc]		END_FINALLY	# re-raise exception      []			L0:	<next statement>      Of course, parts are not generated if Vi or Ei is not present.*/static intcompiler_try_except(struct compiler *c, stmt_ty s){	basicblock *body, *orelse, *except, *end;	int i, n; 	body = compiler_new_block(c);	except = compiler_new_block(c);	orelse = compiler_new_block(c);	end = compiler_new_block(c);	if (body == NULL || except == NULL || orelse == NULL || end == NULL)		return 0;	ADDOP_JREL(c, SETUP_EXCEPT, except);	compiler_use_next_block(c, body);	if (!compiler_push_fblock(c, EXCEPT, body))		return 0;	VISIT_SEQ(c, stmt, s->v.TryExcept.body);	ADDOP(c, POP_BLOCK);	compiler_pop_fblock(c, EXCEPT, body);	ADDOP_JREL(c, JUMP_FORWARD, orelse);	n = asdl_seq_LEN(s->v.TryExcept.handlers);	compiler_use_next_block(c, except);	for (i = 0; i < n; i++) {		excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET(						s->v.TryExcept.handlers, i);		if (!handler->type && i < n-1)		    return compiler_error(c, "default 'except:' must be last");        c->u->u_lineno_set = false;        c->u->u_lineno = handler->lineno;		except = compiler_new_block(c);		if (except == NULL)			return 0;		if (handler->type) {			ADDOP(c, DUP_TOP);			VISIT(c, expr, handler->type);			ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH);			ADDOP_JREL(c, JUMP_IF_FALSE, except);			ADDOP(c, POP_TOP);		}		ADDOP(c, POP_TOP);		if (handler->name) {			VISIT(c, expr, handler->name);		}		else {			ADDOP(c, POP_TOP);		}		ADDOP(c, POP_TOP);		VISIT_SEQ(c, stmt, handler->body);		ADDOP_JREL(c, JUMP_FORWARD, end);		compiler_use_next_block(c, except);		if (handler->type)			ADDOP(c, POP_TOP);	}	ADDOP(c, END_FINALLY);	compiler_use_next_block(c, orelse);	VISIT_SEQ(c, stmt, s->v.TryExcept.orelse);	compiler_use_next_block(c, end);	return 1;} static intcompiler_import_as(struct compiler *c, identifier name, identifier asname){	/* The IMPORT_NAME opcode was already generated.  This function	   merely needs to bind the result to a name. 	   If there is a dot in name, we need to split it and emit a 	   LOAD_ATTR for each name.	*/	const char *src = PyString_AS_STRING(name);	const char *dot = strchr(src, '.');	if (dot) {		/* Consume the base module name to get the first attribute */		src = dot + 1;		while (dot) {			/* NB src is only defined when dot != NULL */			PyObject *attr;			dot = strchr(src, '.');

Lines 2001–2500 of 4570. Previous lines