# Manfred's comments on the Joy main.c code

## John Cowan — 2006-04-12 16:35:59

    Manfred sent these to me by private mail.  Here they are:

    /* file: main.c-COMMENTS */

    I comment on the functions in main.c which are relevant to the

    symbol table management. Comments are in the same order as they

    occur in main.c.

    function enterglobal:

    Used for most definitions, except for those inside a HIDE,

    PRIVATE, PUBLIC, MODULE. Probably this should be implemented

    first.

    For a definition "foo == ...", enters identifier id

    (string "foo") into global table. For a first use of "bar" inside

    "foo == ..bar.." enters "bar" into global table. In my implementation this

    part of the table uses a hashing method, the actual hash value

    has already been computed by the scannner.

    function lookup:

    Since HIDE's and modules can be nested, there is the notion

    of level (up to 10, which is ample), level 0 means global).

    The array display contains the starting points of the local

    tables. So, to lookup identifier id (string "foo"), start

    at the current highest level (display_lookup), do a linear

    search at that local table. If not found, go down one level

    and repeat. If found on a local level, return (global variable

    location now knows where "foo" is.

    If "foo" was not found  locally, search the global table which

    is hashed: another linear search through the list for this

    particular hash value. If not found enter into global table.

    ALSO NOTE: my implementation fails to enter "foo" flagged

    as is_module = 0 in the normal case. It so happens that

    memory is automatically initialised to 0, so it worked. But

    this was bad programming. Sorry.

    function enteratom:

    If we are inside a HIDE, PRIVATE or a module and see "foo == ..."

    enter "foo" into table (with a NULL body), and add this

    entry to the current local table at the current diplay level.

    function definition:

    Remember from that a definition is either simple (of the

    form "foo == ..") or compound (HIDE, MODULE etc).

    In the body of the function the first 6 lines are just for

    parsing the compound ones, in each case calling function

    compound_def.

    The next few lines deal with empty definitions, which should

    be allowed so that ";" can be used as a terminator and not just

    as a separator between definitions (Pascal uses a similar trick

    for statement terminator/separator).

    The remainder deals with the case of atom "foo". The warning for

    overwriting inbuilt should be clear, also the parsing for "==".

    Then a term "..." is read, which readterm always leaves on the stack.

    That is term, on top of the stack, is then attached as the body

    to the part of the symbol table at here.

    function defsequence:

    This just parses definition sequences separated by ";".

    function compound_def:

    This processes in accordance with the grammar

        compound-definition :==

            ["MODULE" atomic symbol]

            ["PRIVATE" definition-sequence  ]

                                           ^   /* ERROR:

                                                  MISSING "compound_def"

                                                  SEE DISGUST BELOW */

            ["PUBLIC" definition-sequence]

            ("END" | ".")

    Each of the 3 parts is optional. Instead of "PRIVATE.. PUBLIC.."

    the combination "HIDE..IN.." can be used, and instead of

    "PUBLIC" the syntax "LIBRA.." or "DEFINE.." can be used.

    So, depending on what the symbol from the scanner is:

    If the symbol is "MODULE", the next symbol must be an atom,

      say "mymodule", enter it as an atom into the global or

      local part of the symbol table, increment two display

      indices for entering and lookup, then parse a compound definition,

      which will be at one level higher than the preceding.

      and then: set the is_module flag to 1 and the fields

      to the current value. Finally decrement these two indices.

    If the symbol is "PRIVATE" or "HIDE", the next item to be

      to be parsed has to be a definition sequence. But the details

      of what to do with the display indices depend on whether

      we are already inside something that is hidden. If we are,

      then only the display_enter is incremented before the

      definition sequence and decremented afterwards. If we are not,

      then both indices are incremented and decremented at the same

      place. In either case after all that the function calls

      itself. [NOTE: TO MY DISGUST, THE GRAMMAR IN THE MANUAL DOES

      NOT SAY THIS - VERY SORRY.]

    If the symbol is "PUBLIC" or "LIBRA" or "IN", parse and

      process a definition-sequence.

    If the symbols is anything else, warn about empty

      compound definition.

    I suppose part of the difficulty of understanding this function

    is due to the fact that I tried to squeeze the earlier "HIDE..IN.."

    into the same mould as the quite separate "PRIVATE.." and "PUBLIC..",

    and trying to use the same display mechanism for the levels of

    hiding by "HIDE" or "PRIVATE". Maybe there is a more elegant way

    of doing this, possibly by separating the cases and duplicating

    some of the code.

    --

    Dream projects long deferred             John Cowan <cowan@...>

    usually bite the wax tadpole.            http://www.ccil.org/~cowan

            --James Lileks