Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d6f3bc2

Browse files
committed
Compile class definitions.
Document and fix code generation for try statements. Use two bytes for all arguments. Avoid duplicate entries in lists of constants and names.
1 parent e9736fc commit d6f3bc2

1 file changed

Lines changed: 176 additions & 27 deletions

File tree

Python/compile.c

Lines changed: 176 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#define DEBUG
21
/* Compile an expression node to intermediate code */
32

43
#include <stdio.h>
@@ -174,7 +173,8 @@ com_addint(c, x)
174173
struct compiling *c;
175174
int x;
176175
{
177-
com_addbyte(c, x);
176+
com_addbyte(c, x & 0xff);
177+
com_addbyte(c, x >> 8); /* XXX x should be positive */
178178
}
179179

180180
static void
@@ -215,22 +215,10 @@ com_backpatch(c, anchor)
215215
int prev;
216216
for (;;) {
217217
/* Make the JUMP instruction at anchor point to target */
218-
prev = code[anchor];
219-
dist = target - (anchor+1);
220-
if (dist > 255 && lastanchor &&
221-
code[lastanchor-1] == code[anchor-1]) {
222-
/* Attempt to jump to a similar jump closer by */
223-
/* XXX Show that it works */
224-
fprintf(stderr, "com_backpatch: huge jump rescued (?)\n");
225-
target = lastanchor-1;
226-
dist = target - (anchor+1);
227-
lastanchor = 0;
228-
}
229-
if (dist > 255) {
230-
err_setstr(SystemError, "relative jump > 255 bytes");
231-
c->c_errors++;
232-
}
233-
code[anchor] = dist;
218+
prev = code[anchor] + (code[anchor+1] << 8);
219+
dist = target - (anchor+2);
220+
code[anchor] = dist & 0xff;
221+
code[anchor+1] = dist >> 8;
234222
if (!prev)
235223
break;
236224
lastanchor = anchor;
@@ -246,11 +234,16 @@ com_add(c, list, v)
246234
object *list;
247235
object *v;
248236
{
249-
/* XXX Should look through list for object with same value */
250-
int i = getlistsize(list);
237+
int n = getlistsize(list);
238+
int i;
239+
for (i = n; --i >= 0; ) {
240+
object *w = getlistitem(list, i);
241+
if (cmpobject(v, w) == 0)
242+
return i;
243+
}
251244
if (addlistitem(list, v) != 0)
252245
c->c_errors++;
253-
return i;
246+
return n;
254247
}
255248

256249
static int
@@ -926,6 +919,7 @@ com_assign(c, n, assigning)
926919
/* Loop to avoid trivial recursion */
927920
for (;;) {
928921
switch (TYPE(n)) {
922+
929923
case exprlist:
930924
case testlist:
931925
if (NCH(n) > 1) {
@@ -934,6 +928,7 @@ com_assign(c, n, assigning)
934928
}
935929
n = CHILD(n, 0);
936930
break;
931+
937932
case test:
938933
case and_test:
939934
case not_test:
@@ -945,6 +940,7 @@ com_assign(c, n, assigning)
945940
}
946941
n = CHILD(n, 0);
947942
break;
943+
948944
case comparison:
949945
if (NCH(n) > 1) {
950946
err_setstr(TypeError,
@@ -954,6 +950,7 @@ com_assign(c, n, assigning)
954950
}
955951
n = CHILD(n, 0);
956952
break;
953+
957954
case expr:
958955
if (NCH(n) > 1) {
959956
err_setstr(TypeError,
@@ -963,6 +960,7 @@ com_assign(c, n, assigning)
963960
}
964961
n = CHILD(n, 0);
965962
break;
963+
966964
case term:
967965
if (NCH(n) > 1) {
968966
err_setstr(TypeError,
@@ -972,6 +970,7 @@ com_assign(c, n, assigning)
972970
}
973971
n = CHILD(n, 0);
974972
break;
973+
975974
case factor: /* ('+'|'-') factor | atom trailer* */
976975
if (TYPE(CHILD(n, 0)) != atom) { /* '+' | '-' */
977976
err_setstr(TypeError,
@@ -991,6 +990,7 @@ com_assign(c, n, assigning)
991990
}
992991
n = CHILD(n, 0);
993992
break;
993+
994994
case atom:
995995
switch (TYPE(CHILD(n, 0))) {
996996
case LPAR:
@@ -1023,11 +1023,13 @@ com_assign(c, n, assigning)
10231023
return;
10241024
}
10251025
break;
1026+
10261027
default:
10271028
fprintf(stderr, "node type %d\n", TYPE(n));
10281029
err_setstr(SystemError, "com_assign: bad node");
10291030
c->c_errors++;
10301031
return;
1032+
10311033
}
10321034
}
10331035
}
@@ -1065,6 +1067,7 @@ com_print_stmt(c, n)
10651067
}
10661068
if (TYPE(CHILD(n, NCH(n)-2)) != COMMA)
10671069
com_addbyte(c, PRINT_NEWLINE);
1070+
/* XXX Alternatively, LOAD_CONST '\n' and then PRINT_ITEM */
10681071
}
10691072

10701073
static void
@@ -1112,6 +1115,7 @@ com_import_stmt(c, n)
11121115
com_addbyte(c, POP_TOP);
11131116
}
11141117
else {
1118+
/* 'import' ... */
11151119
for (i = 1; i < NCH(n); i += 2) {
11161120
com_addopname(c, IMPORT_NAME, CHILD(n, i));
11171121
com_addopname(c, STORE_NAME, CHILD(n, i));
@@ -1197,6 +1201,91 @@ com_for_stmt(c, n)
11971201
com_backpatch(c, break_anchor);
11981202
}
11991203

1204+
/* Although 'execpt' and 'finally' clauses can be combined
1205+
syntactically, they are compiled separately. In fact,
1206+
try: S
1207+
except E1: S1
1208+
except E2: S2
1209+
...
1210+
finally: Sf
1211+
is equivalent to
1212+
try:
1213+
try: S
1214+
except E1: S1
1215+
except E2: S2
1216+
...
1217+
finally: Sf
1218+
meaning that the 'finally' clause is entered even if things
1219+
go wrong again in an exception handler. Note that this is
1220+
not the case for exception handlers: at most one is entered.
1221+
1222+
Code generated for "try: S finally: Sf" is as follows:
1223+
1224+
SETUP_FINALLY L
1225+
<code for S>
1226+
POP_BLOCK
1227+
LOAD_CONST <nil>
1228+
LOAD_CONST <nil>
1229+
L: <code for Sf>
1230+
END_FINALLY
1231+
1232+
The special instructions use the block stack. Each block
1233+
stack entry contains the instruction that created it (here
1234+
SETUP_FINALLY), the level of the value stack at the time the
1235+
block stack entry was created, and a label (here L).
1236+
1237+
SETUP_FINALLY:
1238+
Pushes the current value stack level and the label
1239+
onto the block stack.
1240+
POP_BLOCK:
1241+
Pops en entry from the block stack, and pops the value
1242+
stack until its level is the same as indicated on the
1243+
block stack. (The label is ignored.)
1244+
END_FINALLY:
1245+
Pops two entries from the *value* stack and re-raises
1246+
the exception they specify. If the top entry is nil,
1247+
no exception is raised. If it is a number, a pseudo
1248+
exception is raised ('return' or 'break'). Otherwise,
1249+
a real exception (specified by a string) is raised.
1250+
The second entry popped from the is the value that goes
1251+
with the exception (or the return value).
1252+
1253+
The block stack is unwound when an exception is raised:
1254+
when a SETUP_FINALLY entry is found, the exception is pushed
1255+
onto the value stack (and the exception condition is cleared),
1256+
and the interpreter jumps to the label gotten from the block
1257+
stack.
1258+
1259+
Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":
1260+
1261+
Value stack Label Instruction Argument
1262+
[] SETUP_EXCEPT L1
1263+
[] <code for S>
1264+
[] POP_BLOCK
1265+
[] JUMP_FORWARD L0
1266+
1267+
[val, exc] L1: DUP
1268+
[val, exc, exc] <evaluate E1>
1269+
[val, exc, exc, E1] COMPARE_OP EXC_MATCH
1270+
[val, exc, 1-or-0] JUMP_IF_FALSE L2
1271+
[val, exc, 1] POP
1272+
[val, exc] POP
1273+
[val] <assign to V1>
1274+
[] <code for S1>
1275+
JUMP_FORWARD L0
1276+
1277+
[val, exc, 0] L2: POP
1278+
[val, exc] DUP
1279+
.............................etc.......................
1280+
1281+
[val, exc, 0] Ln+1: POP
1282+
[val, exc] END_FINALLY # re-raise exception
1283+
1284+
[] L0: <next statement>
1285+
1286+
Of course, parts are not generated if Vi or Ei is not present.
1287+
*/
1288+
12001289
static void
12011290
com_try_stmt(c, n)
12021291
struct compiling *c;
@@ -1206,6 +1295,7 @@ com_try_stmt(c, n)
12061295
int except_anchor = 0;
12071296
REQ(n, try_stmt);
12081297
/* 'try' ':' suite (except_clause ':' suite)* ['finally' ':' suite] */
1298+
12091299
if (NCH(n) > 3 && TYPE(CHILD(n, NCH(n)-3)) != except_clause) {
12101300
/* Have a 'finally' clause */
12111301
com_addfwref(c, SETUP_FINALLY, &finally_anchor);
@@ -1226,12 +1316,18 @@ com_try_stmt(c, n)
12261316
i < NCH(n) && TYPE(ch = CHILD(n, i)) == except_clause;
12271317
i += 3) {
12281318
/* except_clause: 'except' [expr [',' expr]] */
1229-
int next_anchor = 0;
1319+
if (except_anchor == 0) {
1320+
err_setstr(TypeError,
1321+
"default 'except:' must be last");
1322+
c->c_errors++;
1323+
break;
1324+
}
1325+
except_anchor = 0;
12301326
if (NCH(ch) > 1) {
12311327
com_addbyte(c, DUP_TOP);
12321328
com_node(c, CHILD(ch, 1));
12331329
com_addoparg(c, COMPARE_OP, EXC_MATCH);
1234-
com_addfwref(c, JUMP_IF_FALSE, &next_anchor);
1330+
com_addfwref(c, JUMP_IF_FALSE, &except_anchor);
12351331
com_addbyte(c, POP_TOP);
12361332
}
12371333
com_addbyte(c, POP_TOP);
@@ -1241,8 +1337,10 @@ com_try_stmt(c, n)
12411337
com_addbyte(c, POP_TOP);
12421338
com_node(c, CHILD(n, i+2));
12431339
com_addfwref(c, JUMP_FORWARD, &end_anchor);
1244-
if (next_anchor)
1245-
com_backpatch(c, next_anchor);
1340+
if (except_anchor) {
1341+
com_backpatch(c, except_anchor);
1342+
com_addbyte(c, POP_TOP);
1343+
}
12461344
}
12471345
com_addbyte(c, END_FINALLY);
12481346
com_backpatch(c, end_anchor);
@@ -1296,19 +1394,50 @@ com_funcdef(c, n)
12961394
}
12971395
}
12981396

1397+
static void
1398+
com_bases(c, n)
1399+
struct compiling *c;
1400+
node *n;
1401+
{
1402+
int i, nbases;
1403+
REQ(n, baselist);
1404+
/*
1405+
baselist: atom arguments (',' atom arguments)*
1406+
arguments: '(' [testlist] ')'
1407+
*/
1408+
for (i = 0; i < NCH(n); i += 3)
1409+
com_node(c, CHILD(n, i));
1410+
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3);
1411+
}
1412+
12991413
static void
13001414
com_classdef(c, n)
13011415
struct compiling *c;
13021416
node *n;
13031417
{
1418+
object *v;
13041419
REQ(n, classdef);
13051420
/*
13061421
classdef: 'class' NAME parameters ['=' baselist] ':' suite
13071422
baselist: atom arguments (',' atom arguments)*
13081423
arguments: '(' [testlist] ')'
13091424
*/
1310-
err_setstr(SystemError, "can't compile 'class' yet");
1311-
c->c_errors++;
1425+
if (NCH(n) == 7)
1426+
com_bases(c, CHILD(n, 4));
1427+
else
1428+
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
1429+
v = (object *)compile(n);
1430+
if (v == NULL)
1431+
c->c_errors++;
1432+
else {
1433+
int i = com_addconst(c, v);
1434+
com_addoparg(c, LOAD_CONST, i);
1435+
com_addbyte(c, BUILD_FUNCTION);
1436+
com_addbyte(c, UNARY_CALL);
1437+
com_addbyte(c, BUILD_CLASS);
1438+
com_addopname(c, STORE_NAME, CHILD(n, 1));
1439+
DECREF(v);
1440+
}
13121441
}
13131442

13141443
static void
@@ -1484,6 +1613,22 @@ compile_funcdef(c, n)
14841613
com_addbyte(c, RETURN_VALUE);
14851614
}
14861615

1616+
static void
1617+
compile_classdef(c, n)
1618+
struct compiling *c;
1619+
node *n;
1620+
{
1621+
node *ch;
1622+
REQ(n, classdef);
1623+
/*
1624+
classdef: 'class' NAME parameters ['=' baselist] ':' suite
1625+
*/
1626+
com_addbyte(c, REFUSE_ARGS);
1627+
com_node(c, CHILD(n, NCH(n)-1));
1628+
com_addbyte(c, LOAD_LOCALS);
1629+
com_addbyte(c, RETURN_VALUE);
1630+
}
1631+
14871632
static void
14881633
compile_node(c, n)
14891634
struct compiling *c;
@@ -1511,6 +1656,10 @@ compile_node(c, n)
15111656
compile_funcdef(c, n);
15121657
break;
15131658

1659+
case classdef:
1660+
compile_classdef(c, n);
1661+
break;
1662+
15141663
default:
15151664
fprintf(stderr, "node type %d\n", TYPE(n));
15161665
err_setstr(SystemError, "compile_node: unexpected node type");

0 commit comments

Comments
 (0)