Symbol Table Confusion

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Symbol Table Confusion

Krozu
Symbol Tables have confused me a bit after reading through chapter 11. Although most of the confusion came from an outer source, it got me to look a little further than what is written in the book (which is more than plenty to understand what they are used for).
So if any of the following is incorrect, please point it out.

class Object{
    static int nObjects;
    constructor Object new(int x, bool flag) {
        var char r, g, b;
        if(flag) {
            var char a;
        }
    }

    method void inc_nObj() {
        var i;
        if(nObj < 20) {
            if(nObj < 10) {
                var j;
            }
        }
    }
}
For the above example, the Symbol Table should look like this:
[Object, Class]
   |    [ClassVars]
   |       |    [nObjects, int, static, 0]
   |    [Functions]
   |       |    [new, constructor, Object]
   |       |       |    [Scope_0]
   |       |       |       |    [x, int, arg, 0]
   |       |       |       |    [flag, bool, arg, 1]
   |       |       |       |    [r, char, var, 0]
   |       |       |       |    [g, char, var, 1]
   |       |       |       |    [b, char, var, 2]
   |       |       |       |    [Scope_0]
   |       |       |       |       |    [a, char, var, 3]
   |       |    [inc_nObj, method, void]
   |       |       |    [Scope_0]
   |       |       |       |    [i, int, var, 0]
   |       |       |       |    [Scope_0]
   |       |       |       |       |    [Scope_0]
   |       |       |       |       |       |    [j, int, var, 1]

The book only checks class and function scopes, but if it were to include all scopes, would this be correct?
Reply | Threaded
Open this post in threaded view
|

Re: Symbol Table Confusion

cadet1620
Administrator
Krozu wrote
class Object{
    static int nObjects;
    constructor Object new(int x, bool flag) {
        var char r, g, b;
        if(flag) {
            var char a;     <=====
        }
    }
}
For the above example, the Symbol Table should look like this:
[Object, Class]
   |    [ClassVars]
   |       |    [nObjects, int, static, 0]
   |    [Functions]
   |       |    [new, constructor, Object]
   |       |       |    [Scope_0]
   |       |       |       |    [x, int, arg, 0]
   |       |       |       |    [flag, bool, arg, 1]
   |       |       |       |    [r, char, var, 0]
   |       |       |       |    [g, char, var, 1]
   |       |       |       |    [b, char, var, 2]
   |       |       |       |    [Scope_0]                        <=====
   |       |       |       |       |    [a, char, var, 3]        <=====

The book only checks class and function scopes, but if it were to include all scopes, would this be correct?
The Jack language does not allow subscope declarations like you show in your example(1). If they were allowed, you would likely want to identify them as scope[0] = class scope, scope[1] = function scope, scope[n] = nested scope, etc. so that you could search for a variable by searching in scope n, then n-1, n-2, etc. down to scope[0].

Observe that the "kind" of a Jack symbol identifies whether it can occur at class or function scope. This can vastly simplify the scope handling.

As suggested in the book, create two symbol tables, one for class scope and one for function scope.  The function symbol table is destroyed and reconstructed for each function.  You can add all symbols found at class scope to the class symbol table, and add all symbols defined in a function (and its arguments) to the function symbol table.  Then when you need to look up a symbol first look in the function symbol table, and if the the symbol is not found, then look in the class symbol table.

--Mark

----------
(1)  I've thought a bit about how to implement subscopes in Jack, but it is not easy because there is no way to know how much local variable space will be needed for all the vars in the nested scope(s) when generating the 'function' VM command.  It would likely require two passes through the source, rather than the one pass design presented in the book.  Another complication is that to be consistent, the local variables need to be initialized to 0 upon every entry to the subscope that defines them.