Commit c5e96291 authored by Guido van Rossum's avatar Guido van Rossum

Implement 'global' and new class syntax.

parent e2966a63
...@@ -136,6 +136,7 @@ struct compiling { ...@@ -136,6 +136,7 @@ struct compiling {
object *c_code; /* string */ object *c_code; /* string */
object *c_consts; /* list of objects */ object *c_consts; /* list of objects */
object *c_names; /* list of strings (names) */ object *c_names; /* list of strings (names) */
object *c_globals; /* dictionary */
int c_nexti; /* index into c_code */ int c_nexti; /* index into c_code */
int c_errors; /* counts errors occurred */ int c_errors; /* counts errors occurred */
int c_infunction; /* set when compiling a function */ int c_infunction; /* set when compiling a function */
...@@ -204,6 +205,8 @@ com_init(c, filename) ...@@ -204,6 +205,8 @@ com_init(c, filename)
goto fail_2; goto fail_2;
if ((c->c_names = newlistobject(0)) == NULL) if ((c->c_names = newlistobject(0)) == NULL)
goto fail_1; goto fail_1;
if ((c->c_globals = newdictobject()) == NULL)
goto fail_0;
c->c_nexti = 0; c->c_nexti = 0;
c->c_errors = 0; c->c_errors = 0;
c->c_infunction = 0; c->c_infunction = 0;
...@@ -213,6 +216,8 @@ com_init(c, filename) ...@@ -213,6 +216,8 @@ com_init(c, filename)
c->c_filename = filename; c->c_filename = filename;
return 1; return 1;
fail_0:
DECREF(c->c_names);
fail_1: fail_1:
DECREF(c->c_consts); DECREF(c->c_consts);
fail_2: fail_2:
...@@ -228,6 +233,7 @@ com_free(c) ...@@ -228,6 +233,7 @@ com_free(c)
XDECREF(c->c_code); XDECREF(c->c_code);
XDECREF(c->c_consts); XDECREF(c->c_consts);
XDECREF(c->c_names); XDECREF(c->c_names);
XDECREF(c->c_globals);
} }
static void static void
...@@ -381,6 +387,19 @@ com_addopname(c, op, n) ...@@ -381,6 +387,19 @@ com_addopname(c, op, n)
i = com_addname(c, v); i = com_addname(c, v);
DECREF(v); DECREF(v);
} }
/* Hack to replace *_NAME opcodes by *_GLOBAL if necessary */
switch (op) {
case LOAD_NAME:
case STORE_NAME:
case DELETE_NAME:
if (dictlookup(c->c_globals, name) != NULL) {
switch (op) {
case LOAD_NAME: op = LOAD_GLOBAL; break;
case STORE_NAME: op = STORE_GLOBAL; break;
case DELETE_NAME: op = DELETE_GLOBAL; break;
}
}
}
com_addoparg(c, op, i); com_addoparg(c, op, i);
} }
...@@ -390,10 +409,15 @@ parsenumber(s) ...@@ -390,10 +409,15 @@ parsenumber(s)
{ {
extern long strtol(); extern long strtol();
extern double strtod(); extern double strtod();
char *end = s; char *end;
long x; long x;
double xx; double xx;
errno = 0; errno = 0;
end = s + strlen(s) - 1;
if (*end == 'l' || *end == 'L') {
extern object *long_scan();
return long_scan(s, 0);
}
x = strtol(s, &end, 0); x = strtol(s, &end, 0);
if (*end == '\0') { if (*end == '\0') {
if (errno != 0) { if (errno != 0) {
...@@ -402,10 +426,6 @@ parsenumber(s) ...@@ -402,10 +426,6 @@ parsenumber(s)
} }
return newintobject(x); return newintobject(x);
} }
if (*end == 'l' || *end == 'L') {
extern object *long_scan();
return long_scan(s, 0);
}
errno = 0; errno = 0;
xx = strtod(s, &end); xx = strtod(s, &end);
if (*end == '\0') { if (*end == '\0') {
...@@ -1341,6 +1361,21 @@ com_import_stmt(c, n) ...@@ -1341,6 +1361,21 @@ com_import_stmt(c, n)
} }
} }
static void
com_global_stmt(c, n)
struct compiling *c;
node *n;
{
int i;
object *v;
REQ(n, global_stmt);
/* 'global' NAME (',' NAME)* */
for (i = 1; i < NCH(n); i += 2) {
if (dictinsert(c->c_globals, STR(CHILD(n, i)), None) != 0)
c->c_errors++;
}
}
static void static void
com_if_stmt(c, n) com_if_stmt(c, n)
struct compiling *c; struct compiling *c;
...@@ -1654,7 +1689,7 @@ com_funcdef(c, n) ...@@ -1654,7 +1689,7 @@ com_funcdef(c, n)
} }
static void static void
com_bases(c, n) com_oldbases(c, n)
struct compiling *c; struct compiling *c;
node *n; node *n;
{ {
...@@ -1662,13 +1697,26 @@ com_bases(c, n) ...@@ -1662,13 +1697,26 @@ com_bases(c, n)
REQ(n, baselist); REQ(n, baselist);
/* /*
baselist: atom arguments (',' atom arguments)* baselist: atom arguments (',' atom arguments)*
arguments: '(' [testlist] ')' arguments: '(' ')'
*/ */
for (i = 0; i < NCH(n); i += 3) for (i = 0; i < NCH(n); i += 3)
com_node(c, CHILD(n, i)); com_node(c, CHILD(n, i));
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3); com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 3);
} }
static void
com_newbases(c, n)
struct compiling *c;
node *n;
{
int i, nbases;
REQ(n, testlist);
/* testlist: test (',' test)* [','] */
for (i = 0; i < NCH(n); i += 2)
com_node(c, CHILD(n, i));
com_addoparg(c, BUILD_TUPLE, (NCH(n)+1) / 2);
}
static void static void
com_classdef(c, n) com_classdef(c, n)
struct compiling *c; struct compiling *c;
...@@ -1677,14 +1725,38 @@ com_classdef(c, n) ...@@ -1677,14 +1725,38 @@ com_classdef(c, n)
object *v; object *v;
REQ(n, classdef); REQ(n, classdef);
/* /*
classdef: 'class' NAME parameters ['=' baselist] ':' suite classdef: 'class' NAME
['(' testlist ')' |'(' ')' ['=' baselist]] ':' suite
baselist: atom arguments (',' atom arguments)* baselist: atom arguments (',' atom arguments)*
arguments: '(' [testlist] ')' arguments: '(' ')'
*/
/* This piece of code must push a tuple on the stack (the bases) */
if (TYPE(CHILD(n, 2)) != LPAR) {
/* New syntax without base classes:
class NAME ':' suite
___________^
*/
com_addoparg(c, BUILD_TUPLE, 0);
}
else {
if (TYPE(CHILD(n, 3)) == RPAR) {
/* Old syntax with or without base classes:
class NAME '(' ')' ['=' baselist] ':' suite
_______________^....^...^
*/ */
if (NCH(n) == 7) if (TYPE(CHILD(n, 4)) == EQUAL)
com_bases(c, CHILD(n, 4)); com_oldbases(c, CHILD(n, 5));
else else
com_addoparg(c, LOAD_CONST, com_addconst(c, None)); com_addoparg(c, BUILD_TUPLE, 0);
}
else {
/* New syntax with base classes:
class NAME '(' testlist ')' ':' suite
_______________^
*/
com_newbases(c, CHILD(n, 3));
}
}
v = (object *)compile(n, c->c_filename); v = (object *)compile(n, c->c_filename);
if (v == NULL) if (v == NULL)
c->c_errors++; c->c_errors++;
...@@ -1770,6 +1842,9 @@ com_node(c, n) ...@@ -1770,6 +1842,9 @@ com_node(c, n)
case import_stmt: case import_stmt:
com_import_stmt(c, n); com_import_stmt(c, n);
break; break;
case global_stmt:
com_global_stmt(c, n);
break;
case if_stmt: case if_stmt:
com_if_stmt(c, n); com_if_stmt(c, n);
break; break;
...@@ -1950,9 +2025,11 @@ compile_node(c, n) ...@@ -1950,9 +2025,11 @@ compile_node(c, n)
break; break;
case classdef: /* A class definition */ case classdef: /* A class definition */
/* 'class' NAME parameters ['=' baselist] ':' suite */ /* classdef: 'class' NAME
['(' testlist ')' |'(' ')' ['=' baselist]]
':' suite */
com_addbyte(c, REFUSE_ARGS); com_addbyte(c, REFUSE_ARGS);
com_node(c, CHILD(n, NCH(n)-1)); com_node(c, CHILD(n, NCH(n)-1)); /* The suite */
com_addbyte(c, LOAD_LOCALS); com_addbyte(c, LOAD_LOCALS);
com_addbyte(c, RETURN_VALUE); com_addbyte(c, RETURN_VALUE);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment