Symbol table stores current program state. I separated it into three
levels, turning SymbolTable
into a kind of
manager-facade:
ClassA.someClassFunction()
is
resolved, instance of ClassA is a variableTable in current
SymbolTable
). Variable table is not a special class, it’s
either a primitive or a class instance.I created global SymbolTable globalTable
and global
imports
. It was convenient at the time. All classes,
functions and objects are added to the globalTable
during
semantic analysis. Superclasses are defined, imports too. Semantic
analysis is performed for initial file and all its dependencies (they
are files). It is handy to write imports and file contents to global
variables. But when I started writing tests, it backfired.
When running a program once, evaluation is done once. However, when running tests, evaluation runs many times. It lead to all kinds of issues:
To fix that, I added clear()
function to make global
Table a blank table and delete all imports. It is called at the end of
evaluate()
and eval()
(which is a light
version of evaluate()
). But it was treating a symptom, not
dealing with a problem. I plan to make it possible to run multiple
threads in parallel. So I need to remove these globals. Probably I can
create an array of global tables, each thread will write to a separate
table, although I would like to make stateless code, not add another
crutch.
Then I discovered same problems with tests that check failure
behavior. Particularly check whether exceptions are thrown correctly. It
appeared they did, however a clean program state wasn’t restored after.
Exception was thrown, but globalTable
and
imports
weren’t cleared after. I added clear()
on PositionalException
initialization.
Add imports
to FileTable
as a property.
Remove globalTable
and pass it as an argument.