Re: interpreters/compilers in m4?

daniel daniel <[email protected]>
Newsgroups gmane.comp.gnu.m4.general
Message-ID <CAF5U=ueMcBarPbYNN3jA8LaQTKjH9dLiK07=pCvMcyPzzG79EQ@mail.gmail.com>
JHines: you can use defn() to access the
body/content of a macro definition, and
defn() allows you to access macros with
names fitting an arbitrary regexp pattern
that won't typically be expanded. So you
can create a macro, and if that macro fits
a unique pattern then it will be treated
a certain way. This way  you can
implement a sort of pseudo-type.

For example, lets create a boolean type
in m4.  In terms of how m4 understands
macros, the canonical description of a
boolean type is already implicit. What
I mean by that is ifelse($1,1,1,0) will
actually look at the byte value contained
at $1 and compare it with the value of 1
(returning 1 if true, and 0 if false).
Other m4 macros achieve macro
comparisons like regexp() and eval().

So, we can say that the closest thing
to a 'false' value in m4 is an empty
string, and the closest thing to 'true'
in m4 is a non-empty string.

CODE:
define(getboolVal,`pushdef(_boolVal,defn($))_boolVal($1)popdef(`_boolVal')')
define($,`ifelse'($`'1,`true',0,$`'1,`false',`'))
getboolVal(true)

On Mon, Aug 8, 2011 at 5:51 AM, Johnicholas Hines <
[email protected]> 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
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.