[erlang-questions] Fwd: Is there a good source for documentation on BEAM?

Richard O'Keefe ok@REDACTED
Wed May 9 01:58:44 CEST 2012


Let me illustrate the Icon approach by showing you a fragment of the
micro-BEAM I wrote to get the performance numbers in the frames proposal.
(The whole thing is fragmentary.)

...
@i
max src, snd, dst
@d
dst := max(src, snd)

This computes the maximum using the micro-Erlang term ordering.
If src and snd are tagged immediate integers the comparison is
done inline; the compare() function is called otherwise.
@c
    T = @src;
    U = @snd;
    @dst = cmp(T, >, U) ? T : U;
    @step;
@e
...
@i
check_record src, size, const
@d
Type test.

Fail unless src is tagged as a pointer to a tuple or frame,
the first word it points to is size, and the second is the
const (which must be an atom, but we don't check that).
Used for record matching.
@c
    T = @src;
    if (!is_tuple(T))                   @fail "is_record"; else
    if (FIELD(T, TUP_TAG, 0) != @size)  @fail "is_record"; else
    if (FIELD(T, TUP_TAG, 1) != @const) @fail "is_record"; else
    @step;
@e
...
There is a preprocessor written in AWK that turns this into
several C files.  One of them is the emulator cases.  For
the check_record instruction you get

#line 75 "frame.master"
        case CHECK_RECORD:
#line 76 "frame.master"
            T = reg[(int)P[1]];
#line 77 "frame.master"
            if (!is_tuple(T))
               P = failure, operation = "is_record"; else
#line 78 "frame.master"
            if (FIELD(T, TUP_TAG, 0) != 4)
	       P = failure, operation = "is_record"; else
#line 79 "frame.master"
            if (FIELD(T, TUP_TAG, 1) != P[3])
	       P = failure, operation = "is_record"; else
#line 80 "frame.master"
            P += 4;
            break;

where I've broken the long lines (the preprocessor doesn't).
The #line directives are option.

@i introduces an instruction; the next line is a template
for it saying what the operands are.
@d introduces the description for people.
@c introduces the code.  In it, various built-in @macros
are expanded.

One advantage of doing it this way is that by using
@step to update the PC I *cannot* get the offset wrong;
the preprocessor counted the operands and their sizes
for me.  Similarly, what I write has *no* operand numbers;
the preprocessor counted those, and supplies all necessary
casts as well.  I can shuffle operands around (in @i)
without revising the code (in @c), and have.

It wouldn't be too hard to write another preprocessor that
built some kind of documentation (HTML would probably be
easiest) out of this, but since this was an experiment,
it didn't seem worth while.

Why did I write the preprocessor?
Well, to be honest, the first draft didn't use one.
I got a bit sick of debugging, and wrote the preprocessor
(based on vague memories of Icon) to eliminate a class of
errors.  It turned out to be _easier_ to develop a
documented emulator than an undocumented one.




More information about the erlang-questions mailing list