⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compile.c

📁 python s60 1.4.5版本的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (TYPE(CHILD(n, i-1)) == CIRCUMFLEX) {
			op = BINARY_XOR;
		}
		else {
			com_error(c, PyExc_SystemError,
				  "com_xor_expr: operator not ^");
			op = 255;
		}
		com_addbyte(c, op);
		com_pop(c, 1);
	}
}

static void
com_expr(struct compiling *c, node *n)
{
	int i;
	int op;
	REQ(n, expr);
	com_xor_expr(c, CHILD(n, 0));
	for (i = 2; i < NCH(n); i += 2) {
		com_xor_expr(c, CHILD(n, i));
		if (TYPE(CHILD(n, i-1)) == VBAR) {
			op = BINARY_OR;
		}
		else {
			com_error(c, PyExc_SystemError,
				  "com_expr: expr operator not |");
			op = 255;
		}
		com_addbyte(c, op);
		com_pop(c, 1);
	}
}

static enum cmp_op
cmp_type(node *n)
{
	REQ(n, comp_op);
	/* comp_op: '<' | '>' | '=' | '>=' | '<=' | '<>' | '!=' | '=='
	          | 'in' | 'not' 'in' | 'is' | 'is' not' */
	if (NCH(n) == 1) {
		n = CHILD(n, 0);
		switch (TYPE(n)) {
		case LESS:	return LT;
		case GREATER:	return GT;
		case EQEQUAL:			/* == */
		case EQUAL:	return EQ;
		case LESSEQUAL:	return LE;
		case GREATEREQUAL: return GE;
		case NOTEQUAL:	return NE;	/* <> or != */
		case NAME:	if (strcmp(STR(n), "in") == 0) return IN;
				if (strcmp(STR(n), "is") == 0) return IS;
		}
	}
	else if (NCH(n) == 2) {
		switch (TYPE(CHILD(n, 0))) {
		case NAME:	if (strcmp(STR(CHILD(n, 1)), "in") == 0)
					return NOT_IN;
				if (strcmp(STR(CHILD(n, 0)), "is") == 0)
					return IS_NOT;
		}
	}
	return BAD;
}

static void
com_comparison(struct compiling *c, node *n)
{
	int i;
	enum cmp_op op;
	int anchor;
	REQ(n, comparison); /* comparison: expr (comp_op expr)* */
	com_expr(c, CHILD(n, 0));
	if (NCH(n) == 1)
		return;

	/****************************************************************
	   The following code is generated for all but the last
	   comparison in a chain:

	   label:	on stack:	opcode:		jump to:

			a		<code to load b>
			a, b		DUP_TOP
			a, b, b		ROT_THREE
			b, a, b		COMPARE_OP
			b, 0-or-1	JUMP_IF_FALSE	L1
			b, 1		POP_TOP
			b

	   We are now ready to repeat this sequence for the next
	   comparison in the chain.

	   For the last we generate:

	   		b		<code to load c>
	   		b, c		COMPARE_OP
	   		0-or-1

	   If there were any jumps to L1 (i.e., there was more than one
	   comparison), we generate:

	   		0-or-1		JUMP_FORWARD	L2
	   L1:		b, 0		ROT_TWO
	   		0, b		POP_TOP
	   		0
	   L2:		0-or-1
	****************************************************************/

	anchor = 0;

	for (i = 2; i < NCH(n); i += 2) {
		com_expr(c, CHILD(n, i));
		if (i+2 < NCH(n)) {
			com_addbyte(c, DUP_TOP);
			com_push(c, 1);
			com_addbyte(c, ROT_THREE);
		}
		op = cmp_type(CHILD(n, i-1));
		if (op == BAD) {
			com_error(c, PyExc_SystemError,
				  "com_comparison: unknown comparison op");
		}
		com_addoparg(c, COMPARE_OP, op);
		com_pop(c, 1);
		if (i+2 < NCH(n)) {
			com_addfwref(c, JUMP_IF_FALSE, &anchor);
			com_addbyte(c, POP_TOP);
			com_pop(c, 1);
		}
	}

	if (anchor) {
		int anchor2 = 0;
		com_addfwref(c, JUMP_FORWARD, &anchor2);
		com_backpatch(c, anchor);
		com_addbyte(c, ROT_TWO);
		com_addbyte(c, POP_TOP);
		com_backpatch(c, anchor2);
	}
}

static void
com_not_test(struct compiling *c, node *n)
{
	REQ(n, not_test); /* 'not' not_test | comparison */
	if (NCH(n) == 1) {
		com_comparison(c, CHILD(n, 0));
	}
	else {
		com_not_test(c, CHILD(n, 1));
		com_addbyte(c, UNARY_NOT);
	}
}

static void
com_and_test(struct compiling *c, node *n)
{
	int i;
	int anchor;
	REQ(n, and_test); /* not_test ('and' not_test)* */
	anchor = 0;
	i = 0;
	for (;;) {
		com_not_test(c, CHILD(n, i));
		if ((i += 2) >= NCH(n))
			break;
		com_addfwref(c, JUMP_IF_FALSE, &anchor);
		com_addbyte(c, POP_TOP);
		com_pop(c, 1);
	}
	if (anchor)
		com_backpatch(c, anchor);
}

static int
com_make_closure(struct compiling *c, PyCodeObject *co)
{
	int i, free = PyCode_GetNumFree(co);
	if (free == 0)
		return 0;
	for (i = 0; i < free; ++i) {
		/* Bypass com_addop_varname because it will generate
		   LOAD_DEREF but LOAD_CLOSURE is needed.
		*/
		PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
		int arg, reftype;

		/* Special case: If a class contains a method with a
		   free variable that has the same name as a method,
		   the name will be considered free *and* local in the
		   class.  It should be handled by the closure, as
		   well as by the normal name loookup logic.
		*/
		reftype = get_ref_type(c, PyString_AS_STRING(name));
		if (reftype == CELL)
			arg = com_lookup_arg(c->c_cellvars, name);
		else /* (reftype == FREE) */
			arg = com_lookup_arg(c->c_freevars, name);
		if (arg == -1) {
			fprintf(stderr, "lookup %s in %s %d %d\n"
				"freevars of %s: %s\n",
				PyObject_REPR(name),
				c->c_name,
				reftype, arg,
				PyString_AS_STRING(co->co_name),
				PyObject_REPR(co->co_freevars));
			Py_FatalError("com_make_closure()");
		}
		com_addoparg(c, LOAD_CLOSURE, arg);

	}
	com_push(c, free);
	return 1;
}

static void
com_test(struct compiling *c, node *n)
{
	REQ(n, test); /* and_test ('or' and_test)* | lambdef */
	if (NCH(n) == 1 && TYPE(CHILD(n, 0)) == lambdef) {
		PyCodeObject *co;
		int i, closure;
		int ndefs = com_argdefs(c, CHILD(n, 0));
		symtable_enter_scope(c->c_symtable, "lambda", lambdef,
				     n->n_lineno);
		co = icompile(CHILD(n, 0), c);
		if (co == NULL) {
			c->c_errors++;
			return;
		}
		symtable_exit_scope(c->c_symtable);
		i = com_addconst(c, (PyObject *)co);
		closure = com_make_closure(c, co);
		com_addoparg(c, LOAD_CONST, i);
		com_push(c, 1);
		if (closure) {
			com_addoparg(c, MAKE_CLOSURE, ndefs);
			com_pop(c, PyCode_GetNumFree(co));
		} else
			com_addoparg(c, MAKE_FUNCTION, ndefs);
		Py_DECREF(co);
		com_pop(c, ndefs);
	}
	else {
		int anchor = 0;
		int i = 0;
		for (;;) {
			com_and_test(c, CHILD(n, i));
			if ((i += 2) >= NCH(n))
				break;
			com_addfwref(c, JUMP_IF_TRUE, &anchor);
			com_addbyte(c, POP_TOP);
			com_pop(c, 1);
		}
		if (anchor)
			com_backpatch(c, anchor);
	}
}

static void
com_list(struct compiling *c, node *n, int toplevel)
{
	/* exprlist: expr (',' expr)* [',']; likewise for testlist */
	if (NCH(n) == 1 && !toplevel) {
		com_node(c, CHILD(n, 0));
	}
	else {
		int i;
		int len;
		len = (NCH(n) + 1) / 2;
		for (i = 0; i < NCH(n); i += 2)
			com_node(c, CHILD(n, i));
		com_addoparg(c, BUILD_TUPLE, len);
		com_pop(c, len-1);
	}
}


/* Begin of assignment compilation */


static void
com_augassign_attr(struct compiling *c, node *n, int opcode, node *augn)
{
	com_addbyte(c, DUP_TOP);
	com_push(c, 1);
	com_addopname(c, LOAD_ATTR, n);
	com_node(c, augn);
	com_addbyte(c, opcode);
	com_pop(c, 1);
	com_addbyte(c, ROT_TWO);
	com_addopname(c, STORE_ATTR, n);
	com_pop(c, 2);
}

static void
com_assign_attr(struct compiling *c, node *n, int assigning)
{
	com_addopname(c, assigning ? STORE_ATTR : DELETE_ATTR, n);
	com_pop(c, assigning ? 2 : 1);
}

static void
com_assign_trailer(struct compiling *c, node *n, int assigning, node *augn)
{
	REQ(n, trailer);
	switch (TYPE(CHILD(n, 0))) {
	case LPAR: /* '(' [exprlist] ')' */
		com_error(c, PyExc_SyntaxError,
			  "can't assign to function call");
		break;
	case DOT: /* '.' NAME */
		if (assigning > OP_APPLY)
			com_augassign_attr(c, CHILD(n, 1), assigning, augn);
		else
			com_assign_attr(c, CHILD(n, 1), assigning);
		break;
	case LSQB: /* '[' subscriptlist ']' */
		com_subscriptlist(c, CHILD(n, 1), assigning, augn);
		break;
	default:
		com_error(c, PyExc_SystemError, "unknown trailer type");
	}
}

static void
com_assign_sequence(struct compiling *c, node *n, int assigning)
{
	int i;
	if (TYPE(n) != testlist && TYPE(n) != listmaker)
		REQ(n, exprlist);
	if (assigning) {
		i = (NCH(n)+1)/2;
		com_addoparg(c, UNPACK_SEQUENCE, i);
		com_push(c, i-1);
	}
	for (i = 0; i < NCH(n); i += 2)
		com_assign(c, CHILD(n, i), assigning, NULL);
}

static void
com_augassign_name(struct compiling *c, node *n, int opcode, node *augn)
{
	REQ(n, NAME);
	com_addop_varname(c, VAR_LOAD, STR(n));
	com_push(c, 1);
	com_node(c, augn);
	com_addbyte(c, opcode);
	com_pop(c, 1);
	com_assign_name(c, n, OP_ASSIGN);
}

static void
com_assign_name(struct compiling *c, node *n, int assigning)
{
	REQ(n, NAME);
	com_addop_varname(c, assigning ? VAR_STORE : VAR_DELETE, STR(n));
	if (assigning)
		com_pop(c, 1);
}

static void
com_assign(struct compiling *c, node *n, int assigning, node *augn)
{
	/* Loop to avoid trivial recursion */
	for (;;) {
		switch (TYPE(n)) {

		case exprlist:
		case testlist:
			if (NCH(n) > 1) {
				if (assigning > OP_APPLY) {
					com_error(c, PyExc_SyntaxError,
				  "augmented assign to tuple not possible");
					return;
				}
				com_assign_sequence(c, n, assigning);
				return;
			}
			n = CHILD(n, 0);
			break;

		case test:
		case and_test:
		case not_test:
		case comparison:
		case expr:
		case xor_expr:
		case and_expr:
		case shift_expr:
		case arith_expr:
		case term:
		case factor:
			if (NCH(n) > 1) {
				com_error(c, PyExc_SyntaxError,
					  "can't assign to operator");
				return;
			}
			n = CHILD(n, 0);
			break;

		case power: /* atom trailer* ('**' power)*
                              ('+'|'-'|'~') factor | atom trailer* */
			if (TYPE(CHILD(n, 0)) != atom) {
				com_error(c, PyExc_SyntaxError,
					  "can't assign to operator");
				return;
			}
			if (NCH(n) > 1) { /* trailer or exponent present */
				int i;
				com_node(c, CHILD(n, 0));
				for (i = 1; i+1 < NCH(n); i++) {
					if (TYPE(CHILD(n, i)) == DOUBLESTAR) {
						com_error(c, PyExc_SyntaxError,
						  "can't assign to operator");
						return;
					}
					com_apply_trailer(c, CHILD(n, i));
				} /* NB i is still alive */
				com_assign_trailer(c,
						CHILD(n, i), assigning, augn);
				return;
			}
			n = CHILD(n, 0);
			break;

		case atom:
			switch (TYPE(CHILD(n, 0))) {
			case LPAR:
				n = CHILD(n, 1);
				if (TYPE(n) == RPAR) {
					/* XXX Should allow () = () ??? */
					com_error(c, PyExc_SyntaxError,
						  "can't assign to ()");
					return;
				}
				if (assigning > OP_APPLY) {
					com_error(c, PyExc_SyntaxError,
				  "augmented assign to tuple not possible");
					return;
				}
				break;
			case LSQB:
				n = CHILD(n, 1);
				if (TYPE(n) == RSQB) {
					com_error(c, PyExc_SyntaxError,
						  "can't assign to []");
					return;
				}
				if (assigning > OP_APPLY) {
					com_error(c, PyExc_SyntaxError,
				  "augmented assign to list not possible");
					return;
				}
				if (NCH(n) > 1
				    && TYPE(CHILD(n, 1)) == list_for) {
					com_error(c, PyExc_SyntaxError,
				  "can't assign to list comprehension");
					return;
				}
				com_assign_sequence(c, n, assigning);
				return;
			case NAME:
				if (assigning > OP_APPLY)
					com_augassign_name(c, CHILD(n, 0),
							   assigning, augn);
				else
					com_assign_name(c, CHILD(n, 0),
							assigning);
				return;
			default:
				com_error(c, PyExc_SyntaxError,
					  "can't assign to literal");
				return;
			}
			break;

		case lambdef:
			com_error(c, PyExc_SyntaxError,
				  "can't assign to lambda");
			return;

		default:
			com_error(c, PyExc_SystemError,
				  "com_assign: bad node");
			return;

		}
	}
}

static void
com_augassign(struct compiling *c, node *n)
{
	int opcode;

	switch (STR(CHILD(CHILD(n, 1), 0))[0]) {
	case '+': opcode = INPLACE_ADD; break;
	case '-': opcode = INPLACE_SUBTRACT; break;
	case '/':
		if (STR(CHILD(CHILD(n, 1), 0))[1] == '/')
			opcode = INPLACE_FLOOR_DIVIDE;
		else if (c->c_flags & CO_FUTURE_DIVISION)
			opcode = INPLACE_TRUE_DIVIDE;
		else
			opcode = INPLACE_DIVIDE;
		break;
	case '%': opcode = INPLACE_MODULO; break;
	case '<': opcode = INPLACE_LSHIFT; break;
	case '>': opcode = INPLACE_RSHIFT; break;
	case '&': opcode = INPLACE_AND; break;
	case '^': opcode = INPLACE_XOR; break;
	case '|': opcode = INPLACE_OR; break;
	case '*':
		if (STR(CHILD(CHILD(n, 1), 0))[1] == '*')
			opcode = INPLACE_POWER;
		else
			opcode = INPLACE_MULTIPLY;
		break;
	default:
		com_error(c, PyExc_SystemError, "com_augassign: bad operator");
		return;
	}
	com_assign(c, CHILD(n, 0), opcode, CHILD(n, 2));
}

static vo

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -