Hi,
you must do it this way: Make two tables, a lable table and an adress table, both dynamic lists.
A lable table entry stores the following data: the lable's name, the lable adress and whether the lable adress is known yet or not.
plables = ^tlables;
tlables = record
name: array[0..5] of char;
adress: word;
isknown: boolean;
next: plables;
end;
(you should not make the name a string because you have much lables and few memory only; I gave it 6 chars here, you can modify that). When parsing the source, set up the lable table (--> set the name field, and isknown := false. Ignore the adress field). NOTE: The lable table contains all things that have an adress, so variables and procedures are lables, too.
I don't know how you build the compiler, but if you have a kind of designator list storing all designators parsed from the source and storing whether it's a var, a procedure et.c., you can link the lable table directly to it, which would be faster and need less memory:
plables = ^tlables;
tlables = record
item: pdesignator;
adress: word;
isknown: boolean;
next: plables;
end;
Note that you need to have the lable table complete (you should complete it during first parsing) before going to the next step (building the bytecode), as you need the lables for it.
On building the bytecode, maybe read the source again or you have stored all neccessarry data in an internal list already (that you also did set up during parsing, but I'd advice against it because of the low memory).
Whenever you need an adress in the bytecode (e.g. "call anything"), look into the lable table what adress your needed lable has (--> "anything"). If the adress is known, insert the adress. If not, leave space in the bytecode for the adress that you can fill it in later and set up an adress table entry. An adress table entry stores where what adress has to be filled in:
padresses = ^tadresses;
tadresses = record
where: word; //offset in the bytecode, where you left space to recieve the adress
what: plables; //pointer to the lable whose adress has to be filled in
next: padresses;
end;
On building the bytecode, also update the lable table permanently to determine the adresses of labels. That goes this way:
Imagine you bildet 2340 bytes of bytecode already, so your "current offset" is 2340 meaning the next thing appearing in the source will have adress 2340 (note that you need a current data offset and a current code offset if you divide the program into code and data segment). When you read in a lable declaration now (--> a lable, a variable or a procedure declaration), search the according lable table entry, set the adress field and set isnknown := true.
When ready with this step, finally work of the adress table as all lable adresses are known now. Means for all adress table entries: word(pointer(where)^) := what^.adress. Then you're ready.
Hope that'll help you
---Edit:--->
When you read in a lable declaration now, search the according lable table entryNote that this step works very very fast! Don't search it by comparing the names through the full list, but the lable list contains it's lables already in that order they appeared in the source (if you added a new lable always to the end of the list during parsing). So when youn read through the source again and want to find the matching table entry, the matching entry is always the next one.