In general, you want to avoid generating multiple error messages
in response to a single mistake in the program.
It is quite easy for an error in a declaration to produce a
flood of error messages.
Consider what happens if you accidentally declare something
to be of the wrong type or mis-spell a variable' s name in
it declaration. Every reference to the variable might produce
a type error.
If you naively follow the rule that an expression is a type error
unless both of its operands have appropriate types, then a expression
that contains an error will cause a redundant error in every
level of the larger expression in which it appears
There are several ways that you can minimize the number of redundant
error message you generate.
If an error is detected in a declaration, attempt to build
an (incomplete) declaration descriptor anyway.
This can avoid a flood of "undeclared variable"
messages later.
If you can not associate a type with an object, set the type field
in its descriptor to a value indicating that an error
was detected when attempting to resolve the type. Then,
don't generate an error when you find yourself processing
an expression one of whose operands is of this "error"
type (NULL may make a good error value).
Return the "unknown type" value when you process any expression
whose type can not be determined due to an error.
Create a dummy declaration for any reference to an undefined variable
once you have produced at least one message announcing the problem
so that later references will not result in errors. To do this right,
such dummy declarations may need to be carefully exported
when you exit a scope (you don't need to do this).