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
180180static 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
256249static 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
10701073static 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+
12001289static void
12011290com_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+
12991413static void
13001414com_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
13141443static 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+
14871632static void
14881633compile_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