BEAM documentation (was Re: Packages in Erlang...)

Luke Gorrie luke@REDACTED
Mon Sep 8 21:25:30 CEST 2003


Thomas Lindgren <thomasl_erlang@REDACTED> writes:

> Some other options might be to write a backend for Core Erlang...

I have done a small hack in this direction, though I'm convinced that
it cannot lead to anything actually useful. (But it was fun to hack :-)

It's a compiler from Core Erlang to Common Lisp, written in Lisp. It
currently lacks concurrency completely, and much of the runtime
system. It is complete enough to compile the standard 'lists' module
and run functions like map and foreach, though.

It's in the Jungerl under lib/claw/. claw.lisp is the compiler. The
code is rather messy, but very simple. The design is a bit of fun in
that it uses a regular LALR parser which returns a Common Lisp program
as the parse tree (i.e. the compiler uses the parser for control
flow). It's there if anyone wants to play with it :-)

I don't see that it can ever be a BEAM competitor, at least with CMU
Common Lisp. Having a complete Lisp system is great for prototyping,
but would suck for a "finished product" that tries to totally hide the
Lispiness (including ~20MB memory footprint :-). Not a good base for a
"production implementation" as far as I can tell.

It also doesn't seem much good for langauge experimentation, since by
starting from core erlang you cut yourself off from the source
language. To add language constructs would require hacking the regular
Erlang compiler and its definition of Core Erlang. Probably better to
write a plain interpreter for "an Erlang-like language" with Lisp
syntax for such experimentation. (Prolog may be good for this too ;-)

I kept a little journal while hacking this, since 'tis my first
compiler. The last entry shows the basic workings and status:

  ----------------------------------------
  4th of May, 2003

  Started trying to compile lists.erl from stdlib, which flushed out a
  bunch of bugs straight away. Now it compiles without warnings, and
  some functions are working fine:

    * (|lists|:|map/2| #'1+ '(1 2 3))
    (2 3 4)
    * (|lists|:|foreach/2| #'print '(1 2 3))
    1 
    2 
    3 
    ATOM::|ok|

  though runtime support is obviously lacking in various other cases:

    * (|lists|:|flatmap/2| #'list '(1 2 3))
    Error in KERNEL:%COERCE-TO-FUNCTION:  the function ++ is undefined.

  I also have CLAW generating actual Lisp source files, and slightly
  tweaked the pretty printing. Here's the transformations of the
  standard lists:foreach/2 function, first in Erlang:

    foreach(F, [Hd|Tail]) ->
        F(Hd),
        foreach(F, Tail);
    foreach(_, []) -> ok.

  then Core Erlang:

    'foreach'/2 =
        fun (_cor1,_cor0) ->
            case <_cor1,_cor0> of
              <F,[Hd|Tail]> when 'true' ->
                  do  apply F
                          (Hd)
                      apply 'foreach'/2
                          (F, Tail)
              <_cor4,[]> when 'true' ->
                  'ok'
              <_cor3,_cor2> when 'true' ->
                  primop 'match_fail'
                      ({'function_clause',_cor3,_cor2})
            end

  and into Lisp:

    (defun |foreach/2| ($_cor1 $_cor0)
      (match-case (values $_cor1 $_cor0)
        (($F ($Hd . $Tail)) @true
         (progn (funcall $F $Hd) (|foreach/2| $F $Tail)))
        (($_cor4 nil) @true @ok)
        (($_cor3 $_cor2) @true
         (primop "match_fail" #(@function_clause $_cor3 $_cor2)))))

`match-case' is a Lisp macro that implements pattern matching. It's
the only macro-defined construct, everything else is translated
directly to regular Lisp in the parser. That is because Core Erlang
maps so easily onto Common Lisp.

(Notice that since 'fun(X) -> ... end' is compiled onto
'(lambda (x) ...)', I can pass Lisp functions like #'1+ as
fun-arguments to compiled Erlang code :-)

Cheers,
Luke




More information about the erlang-questions mailing list