diff --git a/Python/compile.c b/Python/compile.c index a83f9296386..07c514ccf12 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -446,21 +446,14 @@ com_addname(c, v) } static void -com_addopname(c, op, n) +com_addopnamestr(c, op, name) struct compiling *c; int op; - node *n; + char *name; { object *v; int i; - char *name; - if (TYPE(n) == STAR) - name = "*"; - else { - REQ(n, NAME); - name = STR(n); - } - if ((v = newstringobject(name)) == NULL) { + if (name == NULL || (v = newstringobject(name)) == NULL) { c->c_errors++; i = 255; } @@ -484,6 +477,45 @@ com_addopname(c, op, n) com_addoparg(c, op, i); } +static void +com_addopname(c, op, n) + struct compiling *c; + int op; + node *n; +{ + object *v; + char *name; + char buffer[1000]; + /* XXX it is possible to write this code without the 1000 + chars on the total length of dotted names, I just can't be + bothered right now */ + if (TYPE(n) == STAR) + name = "*"; + else if (TYPE(n) == dotted_name) { + char *p = buffer; + int i; + name = buffer; + for (i = 0; i < NCH(n); i += 2) { + char *s = STR(CHILD(n, i)); + if (p + strlen(s) > buffer + (sizeof buffer) - 2) { + err_setstr(MemoryError, + "dotted_name too long"); + name == NULL; + break; + } + if (p != buffer) + *p++ = '.'; + strcpy(p, s); + p = strchr(p, '\0'); + } + } + else { + REQ(n, NAME); + name = STR(n); + } + com_addopnamestr(c, op, name); +} + static object * parsenumber(s) char *s; @@ -593,6 +625,22 @@ parsestr(s) return v; } +static object * +parsestrplus(n) + node *n; +{ + object *v; + int i; + REQ(CHILD(n, 0), STRING); + if ((v = parsestr(STR(CHILD(n, 0)))) != NULL) { + /* String literal concatenation */ + for (i = 1; i < NCH(n) && v != NULL; i++) { + joinstring_decref(&v, parsestr(STR(CHILD(n, i)))); + } + } + return v; +} + static void com_list_constructor(c, n) struct compiling *c; @@ -671,13 +719,7 @@ com_atom(c, n) com_addoparg(c, LOAD_CONST, i); break; case STRING: - if ((v = parsestr(STR(ch))) != NULL) { - /* String literal concatenation */ - for (i = 1; i < NCH(n) && v != NULL; i++) { - joinstring_decref(&v, - parsestr(STR(CHILD(n, i)))); - } - } + v = parsestrplus(n); if (v == NULL) { c->c_errors++; i = 255; @@ -1457,11 +1499,11 @@ com_import_stmt(c, n) { int i; REQ(n, import_stmt); - /* 'import' NAME (',' NAME)* | - 'from' NAME 'import' ('*' | NAME (',' NAME)*) */ + /* 'import' dotted_name (',' dotted_name)* | + 'from' dotted_name 'import' ('*' | NAME (',' NAME)*) */ if (STR(CHILD(n, 0))[0] == 'f') { - /* 'from' NAME 'import' ... */ - REQ(CHILD(n, 1), NAME); + /* 'from' dotted_name 'import' ... */ + REQ(CHILD(n, 1), dotted_name); com_addopname(c, IMPORT_NAME, CHILD(n, 1)); for (i = 3; i < NCH(n); i += 2) com_addopname(c, IMPORT_FROM, CHILD(n, i)); @@ -1470,8 +1512,9 @@ com_import_stmt(c, n) else { /* 'import' ... */ for (i = 1; i < NCH(n); i += 2) { + REQ(CHILD(n, i), dotted_name); com_addopname(c, IMPORT_NAME, CHILD(n, i)); - com_addopname(c, STORE_NAME, CHILD(n, i)); + com_addopname(c, STORE_NAME, CHILD(CHILD(n, i), 0)); } } } @@ -1821,6 +1864,56 @@ com_try_stmt(c, n) com_try_except(c, n); } +static object * +get_docstring(n) + node *n; +{ + switch (TYPE(n)) { + + case suite: + if (NCH(n) == 1) + return get_docstring(CHILD(n, 0)); + else { + int i; + for (i = 0; i < NCH(n); i++) { + node *ch = CHILD(n, i); + if (TYPE(ch) == stmt) + return get_docstring(ch); + } + } + break; + + case stmt: + case simple_stmt: + case small_stmt: + return get_docstring(CHILD(n, 0)); + + case expr_stmt: + case testlist: + 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) + return get_docstring(CHILD(n, 0)); + break; + + case atom: + if (TYPE(CHILD(n, 0)) == STRING) + return parsestrplus(n); + break; + + } + return NULL; +} + static void com_suite(c, n) struct compiling *c; @@ -2235,7 +2328,15 @@ com_file_input(c, n) node *n; { int i; + object *doc; REQ(n, file_input); /* (NEWLINE | stmt)* ENDMARKER */ + doc = get_docstring(n); + if (doc != NULL) { + int i = com_addconst(c, doc); + DECREF(doc); + com_addoparg(c, LOAD_CONST, i); + com_addopnamestr(c, STORE_NAME, "__doc__"); + } for (i = 0; i < NCH(n); i++) { node *ch = CHILD(n, i); if (TYPE(ch) != ENDMARKER && TYPE(ch) != NEWLINE) @@ -2250,9 +2351,15 @@ compile_funcdef(c, n) struct compiling *c; node *n; { + object *doc; node *ch; REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */ c->c_name = STR(CHILD(n, 1)); + doc = get_docstring(CHILD(n, 4)); + if (doc != NULL) { + (void) com_addconst(c, doc); + DECREF(doc); + } com_addoparg(c, RESERVE_FAST, com_addconst(c, None)); /* Patched! */ ch = CHILD(n, 2); /* parameters: '(' [varargslist] ')' */ ch = CHILD(ch, 1); /* ')' | varargslist */ @@ -2277,6 +2384,7 @@ compile_lambdef(c, n) c->c_name = ""; ch = CHILD(n, 1); + (void) com_addconst(c, None); if (TYPE(ch) == COLON) { com_addoparg(c, UNPACK_ARG, 0); com_node(c, CHILD(n, 2)); @@ -2290,6 +2398,31 @@ compile_lambdef(c, n) com_addbyte(c, RETURN_VALUE); } +static void +compile_classdef(c, n) + struct compiling *c; + node *n; +{ + node *ch; + object *doc; + REQ(n, classdef); + /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ + c->c_name = STR(CHILD(n, 1)); + ch = CHILD(n, NCH(n)-1); /* The suite */ + doc = get_docstring(ch); + if (doc != NULL) { + int i = com_addconst(c, doc); + DECREF(doc); + com_addoparg(c, LOAD_CONST, i); + com_addopnamestr(c, STORE_NAME, "__doc__"); + } + else + (void) com_addconst(c, None); + com_node(c, ch); + com_addbyte(c, LOAD_LOCALS); + com_addbyte(c, RETURN_VALUE); +} + static void compile_node(c, n) struct compiling *c; @@ -2330,11 +2463,7 @@ compile_node(c, n) break; case classdef: /* A class definition */ - /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ - c->c_name = STR(CHILD(n, 1)); - com_node(c, CHILD(n, NCH(n)-1)); /* The suite */ - com_addbyte(c, LOAD_LOCALS); - com_addbyte(c, RETURN_VALUE); + compile_classdef(c, n); break; default: