diff Python/compile.c @ 2089:53aa51433f7f legacy-trunk

Two independent chages: (a) support import NAME.NAME...NAME; (b) support doc strings in modules, classes and function definitions
author Guido van Rossum <guido@python.org>
date Sat, 07 Jan 1995 12:41:23 +0000
parents d0d0a69b5ca3
children cdb373f65bf3
line wrap: on
line diff
--- a/Python/compile.c	Sat Jan 07 12:40:10 1995 +0000
+++ b/Python/compile.c	Sat Jan 07 12:41:23 1995 +0000
@@ -446,21 +446,14 @@
 }
 
 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_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 @@
 	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_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 @@
 {
 	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 @@
 	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_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 @@
 	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 @@
 	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 @@
 	c->c_name = "<lambda>";
 
 	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));
@@ -2291,6 +2399,31 @@
 }
 
 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;
 	node *n;
@@ -2330,11 +2463,7 @@
 		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: