summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1990-11-18 17:33:06 (GMT)
committerGuido van Rossum <guido@python.org>1990-11-18 17:33:06 (GMT)
commite9736fc8a1e7b53f92e1616980b25de9db695ed3 (patch)
tree8ed80ebef86dea0f3f4badd547cf92590aaed251
parent921842f2c2a4f4124ff80f95e3f613c3f0dcc8d5 (diff)
downloadcpython-e9736fc8a1e7b53f92e1616980b25de9db695ed3.zip
cpython-e9736fc8a1e7b53f92e1616980b25de9db695ed3.tar.gz
cpython-e9736fc8a1e7b53f92e1616980b25de9db695ed3.tar.bz2
Free parse tree after compiling.
Added support for class definitions. Reorganized main interpreter loop to fetch op and arg once at the head. Use two bytes for arguments (see ceval.c).
-rw-r--r--Python/ceval.c340
1 files changed, 171 insertions, 169 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 6a303ca..0074cd0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -134,14 +134,19 @@ newframeobject(back, code, locals, globals, nvalues, nblocks)
return f;
}
+#define GETUSTRINGVALUE(s) ((unsigned char *)GETSTRINGVALUE(s))
+
#define Push(f, v) ((f)->f_valuestack[(f)->f_ivalue++] = (v))
#define Pop(f) ((f)->f_valuestack[--(f)->f_ivalue])
#define Top(f) ((f)->f_valuestack[(f)->f_ivalue-1])
#define Empty(f) ((f)->f_ivalue == 0)
#define Full(f) ((f)->f_ivalue == (f)->f_nvalues)
-#define Nextbyte(f) (GETSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti++])
-#define Peekbyte(f) (GETSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti])
-#define Prevbyte(f) (GETSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti-1])
+#define Nextbyte(f) (GETUSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti++])
+#define Peekbyte(f) (GETUSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti])
+#define Peekint(f) \
+ (GETUSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti] + \
+ GETUSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti+1])
+#define Prevbyte(f) (GETUSTRINGVALUE((f)->f_code->co_code)[(f)->f_nexti-1])
#define Jumpto(f, x) ((f)->f_nexti = (x))
#define Jumpby(f, x) ((f)->f_nexti += (x))
#define Getconst(f, i) (GETITEM((f)->f_code->co_consts, (i)))
@@ -192,7 +197,22 @@ nextbyte(f)
printf("ran off end of instructions\n");
abort();
}
- return GETSTRINGVALUE(code)[f->f_nexti++];
+ return GETUSTRINGVALUE(code)[f->f_nexti++];
+}
+
+static int
+nextint(f)
+ frameobject *f;
+{
+ int a, b;
+#ifdef NDEBUG
+ a = Nextbyte(f);
+ b = Nextbyte(f);
+#else
+ a = nextbyte(f);
+ b = nextbyte(f);
+#endif
+ return a + (b << 8);
}
/* Tracing versions */
@@ -244,8 +264,8 @@ trace_nextop(f)
if (op < HAVE_ARGUMENT)
printf("op %3d\n", op);
else {
- arg = Peekbyte(f);
- printf("op %3d arg %3d\n", op, arg);
+ arg = Peekint(f);
+ printf("op %d arg %d\n", op, arg);
}
return op;
}
@@ -720,6 +740,68 @@ cmp_outcome(ctx, op, v, w)
return v;
}
+static void
+import_from(ctx, v, name)
+ context *ctx;
+ object *v;
+ char *name;
+{
+ object *w, *x;
+ w = getmoduledict(v);
+ if (name[0] == '*') {
+ int i;
+ int n = getdictsize(w);
+ for (i = 0; i < n; i++) {
+ name = getdictkey(w, i);
+ if (name == NULL || name[0] == '_')
+ continue;
+ x = dictlookup(w, name);
+ if (x == NULL) {
+ /* XXX can't happen? */
+ name_error(ctx, name);
+ break;
+ }
+ if (dictinsert(ctx->ctx_locals, name, x) != 0) {
+ puterrno(ctx);
+ break;
+ }
+ }
+ }
+ else {
+ x = dictlookup(w, name);
+ if (x == NULL)
+ name_error(ctx, name);
+ else if (dictinsert(ctx->ctx_locals, name, x) != 0)
+ puterrno(ctx);
+ }
+}
+
+static object *
+build_class(ctx, v, w)
+ context *ctx;
+ object *v; /* None or tuple containing base classes */
+ object *w; /* dictionary */
+{
+ if (is_tupleobject(v)) {
+ int i;
+ for (i = gettuplesize(v); --i >= 0; ) {
+ object *x = gettupleitem(v, i);
+ if (!is_classobject(x)) {
+ type_error(ctx, "base is not a class object");
+ return NULL;
+ }
+ }
+ }
+ else {
+ v = NULL;
+ }
+ if (!is_dictobject(w)) {
+ sys_error(ctx, "build_class with non-dictionary");
+ return NULL;
+ }
+ return checkerror(ctx, newclassobject(v, w));
+}
+
static object *
eval_compiled(ctx, co, arg, needvalue)
context *ctx;
@@ -733,8 +815,7 @@ eval_compiled(ctx, co, arg, needvalue)
register object *u;
register object *x;
char *name;
- int n, i;
- enum cmp_op op;
+ int i, op;
FILE *fp;
#ifndef NDEBUG
int trace = dictlookup(ctx->ctx_globals, "__trace") != NULL;
@@ -764,16 +845,12 @@ eval_compiled(ctx, co, arg, needvalue)
#define PUSH(v) Push(f, v)
#define TOP() Top(f)
#define POP() Pop(f)
-#define NEXTOP() Nextbyte(f)
-#define NEXTI() Nextbyte(f)
#else
#define PUSH(v) if(trace) trace_push(f, v); else push(f, v)
#define TOP() (trace ? trace_top(f) : top(f))
#define POP() (trace ? trace_pop(f) : pop(f))
-#define NEXTOP() (trace ? trace_nextop(f) : nextbyte(f))
-#define NEXTI() (nextbyte(f))
#endif
@@ -784,8 +861,14 @@ eval_compiled(ctx, co, arg, needvalue)
while (f->f_nexti < getstringsize((object *)f->f_code->co_code) &&
!ctx->ctx_exception) {
-
- switch (NEXTOP()) {
+#ifdef NDEBUG
+ op = Nextbyte(f);
+#else
+ op = trace ? trace_nextop(f) : nextbyte(f);
+#endif
+ if (op >= HAVE_ARGUMENT)
+ i = nextint(f);
+ switch (op) {
case DUP_TOP:
v = TOP();
@@ -844,7 +927,7 @@ eval_compiled(ctx, co, arg, needvalue)
case UNARY_CALL:
v = POP();
- if (is_classmemberobject(v) || is_funcobject(v))
+ if (is_classmethodobject(v) || is_funcobject(v))
u = call_function(ctx, v, (object *)NULL);
else
u = call_builtin(ctx, v, (object *)NULL);
@@ -909,7 +992,7 @@ eval_compiled(ctx, co, arg, needvalue)
case BINARY_CALL:
w = POP();
v = POP();
- if (is_classmemberobject(v) || is_funcobject(v))
+ if (is_classmethodobject(v) || is_funcobject(v))
u = call_function(ctx, v, w);
else
u = call_builtin(ctx, v, w);
@@ -918,128 +1001,68 @@ eval_compiled(ctx, co, arg, needvalue)
PUSH(u);
break;
- case SLICE:
- w = NULL;
- v = NULL;
- u = POP();
- x = apply_slice(ctx, u, v, w);
- DECREF(u);
- PUSH(x);
- break;
-
+ case SLICE+0:
case SLICE+1:
- w = NULL;
- v = POP();
- u = POP();
- x = apply_slice(ctx, u, v, w);
- DECREF(u);
- DECREF(v);
- PUSH(x);
- break;
-
case SLICE+2:
- w = POP();
- v = NULL;
- u = POP();
- x = apply_slice(ctx, u, v, w);
- DECREF(u);
- DECREF(w);
- PUSH(x);
- break;
-
case SLICE+3:
- w = POP();
- v = POP();
+ op -= SLICE;
+ if (op & 2)
+ w = POP();
+ else
+ w = NULL;
+ if (op & 1)
+ v = POP();
+ else
+ v = NULL;
u = POP();
x = apply_slice(ctx, u, v, w);
DECREF(u);
- DECREF(v);
- DECREF(w);
+ XDECREF(v);
+ XDECREF(w);
PUSH(x);
break;
- case STORE_SLICE:
- w = NULL;
- v = NULL;
- u = POP();
- x = POP();
- assign_slice(ctx, u, v, w, x); /* u[:] = x */
- DECREF(x);
- DECREF(u);
- break;
-
+ case STORE_SLICE+0:
case STORE_SLICE+1:
- w = NULL;
- v = POP();
- u = POP();
- x = POP();
- assign_slice(ctx, u, v, w, x); /* u[v:] = x */
- DECREF(x);
- DECREF(u);
- DECREF(v);
- break;
-
case STORE_SLICE+2:
- w = POP();
- v = NULL;
- u = POP();
- x = POP();
- assign_slice(ctx, u, v, w, x); /* u[:w] = x */
- DECREF(x);
- DECREF(u);
- DECREF(w);
- break;
-
case STORE_SLICE+3:
- w = POP();
- v = POP();
+ op -= SLICE;
+ if (op & 2)
+ w = POP();
+ else
+ w = NULL;
+ if (op & 1)
+ v = POP();
+ else
+ v = NULL;
u = POP();
x = POP();
assign_slice(ctx, u, v, w, x); /* u[v:w] = x */
DECREF(x);
DECREF(u);
- DECREF(v);
- DECREF(w);
- break;
-
- case DELETE_SLICE:
- w = NULL;
- v = NULL;
- u = POP();
- x = NULL;
- assign_slice(ctx, u, v, w, x); /* del u[:] */
- DECREF(u);
+ XDECREF(v);
+ XDECREF(w);
break;
+ case DELETE_SLICE+0:
case DELETE_SLICE+1:
- w = NULL;
- v = POP();
- u = POP();
- x = NULL;
- assign_slice(ctx, u, v, w, x); /* del u[v:] */
- DECREF(u);
- DECREF(v);
- break;
-
case DELETE_SLICE+2:
- w = POP();
- v = NULL;
- u = POP();
- x = NULL;
- assign_slice(ctx, u, v, w, x); /* del u[:w] */
- DECREF(u);
- DECREF(w);
- break;
-
case DELETE_SLICE+3:
- w = POP();
- v = POP();
+ op -= SLICE;
+ if (op & 2)
+ w = POP();
+ else
+ w = NULL;
+ if (op & 1)
+ v = POP();
+ else
+ v = NULL;
u = POP();
x = NULL;
assign_slice(ctx, u, v, w, x); /* del u[v:w] */
DECREF(u);
- DECREF(v);
- DECREF(w);
+ XDECREF(v);
+ XDECREF(w);
break;
case STORE_SUBSCR:
@@ -1118,6 +1141,12 @@ eval_compiled(ctx, co, arg, needvalue)
}
break;
+ case LOAD_LOCALS:
+ v = ctx->ctx_locals;
+ INCREF(v);
+ PUSH(v);
+ break;
+
case RETURN_VALUE:
v = POP();
raise_pseudo(ctx, RETURN_PSEUDO);
@@ -1169,8 +1198,16 @@ eval_compiled(ctx, co, arg, needvalue)
}
break;
+ case BUILD_CLASS:
+ w = POP();
+ v = POP();
+ x = build_class(ctx, v, w);
+ PUSH(x);
+ DECREF(v);
+ DECREF(w);
+ break;
+
case STORE_NAME:
- i = NEXTI();
name = GETNAME(i);
v = POP();
if (dictinsert(ctx->ctx_locals, name, v) != 0)
@@ -1179,23 +1216,21 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case DELETE_NAME:
- i = NEXTI();
name = GETNAME(i);
if (dictremove(ctx->ctx_locals, name) != 0)
name_error(ctx, name);
break;
case UNPACK_TUPLE:
- n = NEXTI();
v = POP();
if (!is_tupleobject(v)) {
type_error(ctx, "unpack non-tuple");
}
- else if (gettuplesize(v) != n) {
+ else if (gettuplesize(v) != i) {
error(ctx, "unpack tuple of wrong size");
}
else {
- for (i = n; --i >= 0; ) {
+ for (; --i >= 0; ) {
w = gettupleitem(v, i);
INCREF(w);
PUSH(w);
@@ -1205,16 +1240,15 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case UNPACK_LIST:
- n = NEXTI();
v = POP();
if (!is_listobject(v)) {
type_error(ctx, "unpack non-list");
}
- else if (getlistsize(v) != n) {
+ else if (getlistsize(v) != i) {
error(ctx, "unpack tuple of wrong size");
}
else {
- for (i = n; --i >= 0; ) {
+ for (; --i >= 0; ) {
w = getlistitem(v, i);
INCREF(w);
PUSH(w);
@@ -1224,7 +1258,6 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case STORE_ATTR:
- i = NEXTI();
name = GETNAME(i);
v = POP();
u = POP();
@@ -1241,7 +1274,6 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case DELETE_ATTR:
- i = NEXTI();
name = GETNAME(i);
v = POP();
/* del v.name */
@@ -1258,14 +1290,12 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case LOAD_CONST:
- i = NEXTI();
v = GETCONST(i);
INCREF(v);
PUSH(v);
break;
case LOAD_NAME:
- i = NEXTI();
name = GETNAME(i);
v = dictlookup(ctx->ctx_locals, name);
if (v == NULL) {
@@ -1282,10 +1312,9 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case BUILD_TUPLE:
- n = NEXTI();
- v = checkerror(ctx, newtupleobject(n));
+ v = checkerror(ctx, newtupleobject(i));
if (v != NULL) {
- for (i = n; --i >= 0;) {
+ for (; --i >= 0;) {
w = POP();
settupleitem(v, i, w);
}
@@ -1294,10 +1323,9 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case BUILD_LIST:
- n = NEXTI();
- v = checkerror(ctx, newlistobject(n));
+ v = checkerror(ctx, newlistobject(i));
if (v != NULL) {
- for (i = n; --i >= 0;) {
+ for (; --i >= 0;) {
w = POP();
setlistitem(v, i, w);
}
@@ -1306,13 +1334,11 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case BUILD_MAP:
- (void) NEXTI();
v = checkerror(ctx, newdictobject());
PUSH(v);
break;
case LOAD_ATTR:
- i = NEXTI();
name = GETNAME(i);
v = POP();
if (v->ob_type->tp_getattr == NULL) {
@@ -1328,17 +1354,15 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case COMPARE_OP:
- op = NEXTI();
w = POP();
v = POP();
- u = cmp_outcome(ctx, op, v, w);
+ u = cmp_outcome(ctx, (enum cmp_op)i, v, w);
DECREF(v);
DECREF(w);
PUSH(u);
break;
case IMPORT_NAME:
- i = NEXTI();
name = GETNAME(i);
u = import_module(ctx, name);
if (u != NULL) {
@@ -1348,44 +1372,27 @@ eval_compiled(ctx, co, arg, needvalue)
break;
case IMPORT_FROM:
- i = NEXTI();
name = GETNAME(i);
v = TOP();
- w = getmoduledict(v);
- x = dictlookup(w, name);
- if (x == NULL)
- name_error(ctx, name);
- else if (dictinsert(ctx->ctx_locals, name, x) != 0)
- puterrno(ctx);
+ import_from(ctx, v, name);
break;
- /* WARNING!
- Don't assign an expression containing NEXTI() directly
- to nexti. This expands to "nexti = ... + *nexti++"
- which has undefined evaluation order. On some machines
- (e.g., mips!) the nexti++ is done after the assignment
- to nexti. */
-
case JUMP_FORWARD:
- n = NEXTI();
- JUMPBY(n);
+ JUMPBY(i);
break;
case JUMP_IF_FALSE:
- n = NEXTI();
if (!testbool(ctx, TOP()))
- JUMPBY(n);
+ JUMPBY(i);
break;
case JUMP_IF_TRUE:
- n = NEXTI();
if (testbool(ctx, TOP()))
- JUMPBY(n);
+ JUMPBY(i);
break;
case JUMP_ABSOLUTE:
- n = NEXTI();
- JUMPTO(n);
+ JUMPTO(i);
/* XXX Should check for interrupts more often? */
if (intrcheck())
intr_error(ctx);
@@ -1396,8 +1403,7 @@ eval_compiled(ctx, co, arg, needvalue)
On entry: stack contains s, i.
On exit: stack contains s, i+1, s[i];
but if loop exhausted:
- s, i are popped, and we jump n bytes */
- n = NEXTI();
+ s, i are popped, and we jump */
w = POP(); /* Loop index */
v = POP(); /* Sequence object */
x = loop_subscript(ctx, v, w);
@@ -1412,27 +1418,24 @@ eval_compiled(ctx, co, arg, needvalue)
else {
DECREF(v);
DECREF(w);
- JUMPBY(n);
+ JUMPBY(i);
}
break;
case SETUP_LOOP:
- n = NEXTI();
- setup_block(f, SETUP_LOOP, n);
+ setup_block(f, SETUP_LOOP, i);
break;
case SETUP_EXCEPT:
- n = NEXTI();
- setup_block(f, SETUP_EXCEPT, n);
+ setup_block(f, SETUP_EXCEPT, i);
break;
case SETUP_FINALLY:
- n = NEXTI();
- setup_block(f, SETUP_FINALLY, n);
+ setup_block(f, SETUP_FINALLY, i);
break;
default:
- printf("opcode %d\n", Prevbyte(f));
+ printf("opcode %d\n", op);
sys_error(ctx, "eval_compiled: unknown opcode");
break;
@@ -1510,8 +1513,6 @@ eval_compiled(ctx, co, arg, needvalue)
#undef JUMPTO
#undef JUMPBY
-#undef NEXTOP
-#undef NEXTI
#undef POP
#undef TOP
#undef PUSH
@@ -1534,6 +1535,7 @@ eval_or_exec(ctx, n, arg, needvalue)
{
object *v;
codeobject *co = compile(n);
+ freenode(n); /* XXX A rather strange place to do this! */
if (co == NULL) {
puterrno(ctx);
return NULL;