On Mon, Aug 8, 2011 at 5:51 AM, Johnicholas Hines
<address@hidden> wrote:
I'd be interested in an interactive shell also - but rather than a
code generator, I was imagining implementing another language IN m4,
just as you can write a lisp interpreter in C.
Here's a snippet - I made it as small and simple as possible, possibly
too small and simple, but extending it to have variables that are
looked up in the environment, more control flow, should be
straightforward.
divert(-1)
# a global counter used for making things unique
define(`_gensym',`0')
define(`gensym',`_gensym`'define(`_gensym',incr(_gensym))')
# exp ::= Num( int )
define(`_num',`define(`eat_Num'$1,`$'`1_num($2,shift($'`@))')Num$1')
define(`num',`_num(gensym,$1)')
# exp ::= Plus( exp , exp )
define(`_plus',`define(`eat_Plus'$1,`$'`1_plus($2,$3,shift($'`@))')Plus$1')
define(`plus',`_plus(gensym,$1,$2)')
# define print_exp by cases
# print_exp(Num(int)) => int
define(`_print_exp_num',`$1')
# print_exp(Plus(exp1,exp2)) => print_exp(exp1)+print_exp(exp2)
define(`_print_exp_plus',`print_exp($1)+print_exp($2)')
# actually dispatch
define(`print_exp',`eat_$1(_print_exp)')
# define my_eval by cases
# my_eval(Num(int)) => int
define(`_my_eval_num',`$1')
# my_eval(Plus(exp1,exp2)) => eval(my_eval(exp1)+my_eval(exp2))
define(`_my_eval_plus',`eval(my_eval($1)+my_eval($2))')
# actually dispatch
define(`my_eval',`eat_$1(_my_eval)')
divert`'dnl
# Now we can use the new "little language"
print_exp(plus(plus(num(1),num(2)),num(3)))
my_eval(plus(num(4),plus(num(5),num(6))))
Is this sort of definition-by-cases a standard m4 idiom?
What would the idiomatic way to create a new abstract datatype be?
Johnicholas