lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

> > -- in user script
> > #macro_define \
> > 	squares (x)	\
> > 		local t = "{"
> > 		for i = 1,x do t=t.."{"..i..","..i*i.."}," end \
> > 		return t.."}" \
> > 	end
> Eeek. :-(  Crafting the textual representation lies somewhere between
> hair-raising and appallingly dreadful. :-)  More importantly though,
> it's not very powerful in an engineering sense, because the parts being
> manipulated are dead text instead of active objects with introspection.
> Before even considering that approach, I'd think seriously about defining
> an unofficial syntax tree and creating a front-end to the current parser
> to accept the tree form as input.  Then macro processing becomes a very
> clear 2nd stage in a 3-stage but still single-pass process of parsing Lua
> text into a tree, applying macros, and finally compiling the output tree.
> Rich Artym.

Just on a lark, after reading some of the recent posts on extending Lua with
this and that and another bit of sugar, I added a CLua interface into my
Lua-hosted $-grammars, so that lua programs could be compiled and translated
from within grammar reductions in their own lua_State.

The idea was that I could implement some kind of #macro functionality in a
"super-Lua", parse that super-Lua in the $-grammar, then, in the final
stage, using the _visit event, traverse the tree, expand the macros, and
then feed that expanded version into the CLua object for interpretation.

After some initial proof-of-concept bit-twiddling, it appears that it just
may work.

OK, to translate that into English:

Suppose we want variables in functions to default to local, and only be
"global" if a global keyword occurs before the variable:

	function foo()
		global a = 1; -- global
		b = 2; -- local

We write a grammar that accepts that above, and in the tree traversal after
the first parse, "real" Lua is generated:

	function foo()
		a = 1;
		local b = 2;

This could also be used for simple type checking:

	function foo() returns string
		return "10";

	function foobar() returns number
		return foo(); // illegal, since foo returns string

This would be caught in the first pass, never reaching the second pass.
This, however, would be legal:

	function foo() returns string
		return "10";

	function foobar() returns number
		return cast<number>(foo()); -- OK, because presumably, cast<N>(expr) casts
the expression to type N

I don't know if this is worthwhile -- but I'll keep experimenting and see
what I come up with.

Quinn Tyler Jackson