>>In the source language, a function can use variables from outside its>>scope. More importantly, these variables could be declared after the>>function is. This is okay as long as this function is not called>>before the declaration of these variables.>> As long as non-local variables are transitively in the lexical scope> chain of the function that uses them you can still gather all the> declarations in one pass. If they're not, you have a language that> will be error prone and confusing to use.

They are.

I think I understand. You are proposing a breadth first traversal? We are
using the visitor pattern right now, which lends itself best to a depth
first traversal.

> The simplest way to do it is to organize your symbol "table" as a> stack of lists[*].> ...> This allows for> lexical shadowing of same-named variables in enclosing scopes.

This is pretty much what I'm doing already. :-)

>>Yes, I suppose I am stretching the definition a bit. An expression has a>>type (bool, int, etc.). But to me it also has an access type. This is>>either readonly, writeonly or readwrite. It basically specifies whether it>>is an r-value, an l-value or both.>> I believe you are overthinking the problem.>> L-value or R-value is a matter of usage, not type.

I've seen the terms used in both contexts. As in: A variable is an l-value.
A constant is an r-value. I believe the Dragon book does this.

> Obviously it> matters whether a particular variable is in an operand position or in> a result position, but that depends on the class of the expression -> unary, binary, ternary, etc. - and not on the operand or result types> or the operators involved.

Maybe I should clarify. This information decides whether an expression CAN
be used as an l/r-value or not.

If it cannot be an l-value, it is a readonly expression. You will see this
often with a simple arithmetic operation or with a constant or literal.

If it cannot be a an r-value, it is a writeonly expression. This is seen
less often, but can occur for formal parameters of the 'out' direction. (As
opposed to 'in' or 'inout'.) Or for properties that have a setter method
but no getter method.

If it can be both, it is a readwrite expression. The access-type of your
basic variable. But also of some other expressions, like properties and
array-subscriptings.

This information is stored in the symbol table and is used to check for
referencing errors. It may also help for some optimizations later.

> Since you are targeting C which already has a fairly> sophisticated understanding of complex data types, your compiler> really doesn't have to bother. If your source language says "A[X] :=> A[X] + 1", you can just say that directly in C after appropriately> defining A and X. You don't need to transform it all the way down> into address computations and dereferences.

But I'm sure our source language handles a lot of constructs a little
differently than C does. Also, we want to write our own error messages.

Anyway, the translation to C is only a temporary solution. We're focussing
on the design and proof of correctness concept right now, and do not want
to have to bother with assembly or learning to use the gcc backend until
later. Translating to C seemed like the easiest solution for now. But all
processing of the AST is completely separate from the final translation.