[<<][libprim][>>][..]
Thu Aug 20 15:24:19 CEST 2009

Scheme -> EX compilation

This seems really straightforward.  It would be nice to be able to
statically check at least names and argument arity.

About writing code generators: you _really_ want to write it as a
coroutine (a `generator') that passes strings to an output port
through a `yield' function, in this case traditionally called `emit'.
Using mapping might be more elegant, but in this case due to small
differences in tree structure, decoupling the collector from the
enumerator is best.

In C, there are statements and expressions.  For EX it's simpler to
get rid of the statements early on, so one can focus on the
expressions.  Also, they don't need to be converted to statements
(CPS) since C's expression syntax will do just fine.

Then, it's simpler to use syntax-rules style pattern matching to write
the generator than an using scheme/match at runtime.

A bit of work trying to get the basic abstractions right: statements
emit a line, expressions use string substitution to be built
recursively, function/constructor names get mapped, context arguments
get added.  Everything is a function, except the language forms
themselves, which are implemented as macros (`def', `block' and `return').


(def (bar x y)
  (block ((a 123)
          (b 345))
    (block ((c (plus a b))
            (d (min a)))
       (return (foo c d x y)))))

=>
_ ex_bar(ex *ex, _ x, _ y)
{
    _ a = 123;
    _ b = 345;
    {
        _ c = ex_plus(ex, a, b);
        _ d = ex_min(ex, a);
        return ex_foo(ex, c, d, x, y);
    }
}

Translating from Scheme-like syntax (eliminating 'return') will
require automatic distinction between special forms and application
forms.

There's another thing that's really annoying: nested Scheme/lisp
expressions return values, but C's curly braces represent nested
statements.  Maybe it's best to simply target GCC's statement
expressions[1], and use the '?' condition operator.

This seems more natural.  I'm also using a direct compiler instead of
macros.  To make this look better though, the indentation needs to be
changed so statement expressions can be assigned to variables to
reduce the visual complexity of the nesting.

That's a pretty-printing exercise, so consider the real problem
solved.  The rest is play ;)

So, prettyprinting.  What you want is "newline" to indent to the
current indentation point.

--

Trying something else: rewrote it to make it more _manual_ :
essentially the code makes decisions locally about whether to "press
enter" or whether to change indentation or not.  This seems to work
quite well.

(emit-definition
 '(define (foo a b c)
    (let* ((x (plus b c))
           (y (let* ((d (min a b))
                     (e (max a b)))
                (times d e))))
      (bar x y))))
(pp-enter)

=>
_ ex_foo(ex *ex, _ a, _ b, _ c)
{
  return ({ _ x = ex_plus(ex, b, c)
            _ y = ({ _ d = ex_min(ex, a, b)
                     _ e = ex_max(ex, a, b)
                     ex_times(ex, d, e); })
            ex_bar(ex, x, y); });
}


OK..  I now see that this is not trivial because it requires
backtracking.  Better use something that's seen some thinking[3].

[1] http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
[2] http://www.iai.uni-bonn.de/~ralf/hw2001/9.html
[3] http://planet.plt-scheme.org/display.ss?package=pprint.plt&owner=dherman
[4] http://eprints.kfupm.edu.sa/69518/1/69518.pdf


[Reply][About]
[<<][libprim][>>][..]