multi-line lambda expressions

Donald Beaudry (don@vicorp.com)
Mon, 14 Mar 94 09:10:25 EST

Well, I found some time to figure out why the code generated from the
multi-line lambda expressions did not work. Below is a new version of
the compile_lamdef() routine from compile.c. I also have another
slight change to the grammar to keep full backwards compatability with
existing source. Note that this is still a hack and by no means an
offical patch. To do this right would require some real changes to
the grammar. As given below, you might experience some unexpected
behavior if you try to write a one line 'if'-like statement. I would
guess that none of this stuff will ever make it into a release, so
just think of it as a test bed for experimentation.

The multi-line lamba fix:

Just change the simple_stmt and lambdef lines of the grammar to read:

#simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
simple_stmt: small_stmt (';' small_stmt)* ([';'] NEWLINE | [';'])

#lambdef: 'lambda' [varargslist] ':' test
lambdef: 'lambda' [varargslist] ':' \
(test | [NEWLINE] (INDENT | ':' '(') stmt+ (DEDENT | ':' ')' [NEWLINE]))

and install this routine in place of compile_lambdef in compile.c.

static void
compile_lambdef(c, n)
struct compiling *c;
node *n;
{
node *ch;
int i = 0;

/* lambdef: 'lambda' [parameters] ':' (test | [NEWLINE] ':' '(' stmt+ ':' ')') */
REQ(n, lambdef);
c->c_name = NULL;

ch = CHILD(n, 1);
if (TYPE(ch) == COLON) {
com_addoparg(c, UNPACK_ARG, 0);
i = 2;
}
else {
com_addoparg(c, RESERVE_FAST, com_addconst(c, None));
com_arglist(c, ch);
i = 3;
}

ch = CHILD(n, i);
if (TYPE(ch) == test)
com_node(c, ch);
else { /* suite */
c->c_infunction = 1;
for (; i < NCH(n); i++) {
ch = CHILD(n, i);
if (TYPE(ch) == stmt)
com_node(c, ch);
}
c->c_infunction = 0;
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
}

com_addbyte(c, RETURN_VALUE);
}

after changing the grammar and installing the new routine, just do the
following:

cd Parser
pgen ../Grammar/Grammer
cp graminit.h ../Include
cp graminit.c ../Python
cd ..
make

The changes mentioned above will allow you to use ':(' and ':)' in
place of INDENT and DEDENT in lambda expressions only. If you would
like to experiment with these symbols as optional block delimiters
elsewhere in the language, the following change also needs to be made
to the grammar. (This was pointed out in my previous post).

#suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
suite: simple_stmt \
| [NEWLINE] (INDENT | ':' '(') stmt+ (DEDENT | ':' ')' [NEWLINE])

Happy hacking.

--Don

______ ______
\_\_\_\ /#/#/#/
\_\_\_\ ______
\_\_\_V#/#/#/ Donald Beaudry don@vicorp.com
\_\_/#/#/#/ V. I. Corporation uunet!vicorp!don
\_/#/#/#/ 47 Pleasant Street PHONE: (413) 586-4144
V#/#/#/ Northampton, MA 01060 FAX: (413) 586-3805