1 (* P0SymBuild.mod pass 0 symbol creation.
3 Copyright (C) 2011-2021 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. *)
22 IMPLEMENTATION MODULE P0SymBuild ;
24 FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
25 FROM M2Printf IMPORT printf0, printf1, printf2 ;
26 FROM Lists IMPORT List, InitList, KillList, IncludeItemIntoList, RemoveItemFromList, NoOfItemsInList, GetItemFromList, IsItemInList ;
27 FROM M2Batch IMPORT MakeDefinitionSource, MakeProgramSource, MakeImplementationSource ;
28 FROM SymbolTable IMPORT NulSym, MakeInnerModule, SetCurrentModule, SetFileModule, MakeError ;
29 FROM NameKey IMPORT Name, NulName ;
30 FROM M2Quads IMPORT PushT, PushTF, PopT, PopTF, PopN, OperandT, PopTtok, PushTtok ;
31 FROM M2Reserved IMPORT ImportTok ;
32 FROM M2Debug IMPORT Assert ;
33 FROM M2MetaError IMPORT MetaErrorT1, MetaErrorT2, MetaError1, MetaError2 ;
34 FROM M2LexBuf IMPORT GetTokenNo, UnknownTokenNo ;
42 Kind = (module, program, defimp, inner, procedure, universe, unknown) ;
44 BlockInfoPtr = POINTER TO RECORD
49 token : CARDINAL ; (* where the block starts. *)
50 LocalModules, (* locally declared modules at the current level *)
51 ImportedModules: List ; (* current list of imports for the scanned module *)
54 toNext, (* next in same level *)
55 toUp, (* return to outer level *)
56 toDown : BlockInfoPtr ; (* first of the inner level *)
61 curBP : BlockInfoPtr ;
69 PROCEDURE nSpaces (n: CARDINAL) ;
82 PROCEDURE DisplayB (b: BlockInfoPtr) ;
86 program : printf1("MODULE %a ;\n", b^.name) |
87 defimp : printf1("DEFIMP %a ;\n", b^.name) |
88 inner : printf1("INNER MODULE %a ;\n", b^.name) |
89 procedure: printf1("PROCEDURE %a ;\n", b^.name)
101 PROCEDURE DisplayBlock (b: BlockInfoPtr; l: CARDINAL) ;
115 printf1("END %a\n", b^.name)
120 pc - an interactive debugging aid callable from gdb.
139 printf0("Universe of Modula-2 modules\n") ;
142 b := headBP^.toDown ;
152 addDown - adds, b, to the down link of, a.
155 PROCEDURE addDown (a, b: BlockInfoPtr) ;
162 WHILE a^.toNext#NIL DO
171 GraftBlock - add a new block, b, into the tree in the correct order.
174 PROCEDURE GraftBlock (b: BlockInfoPtr) ;
177 Assert(ABS(Level-curBP^.level)<=1) ;
178 CASE Level-curBP^.level OF
180 -1: (* returning up to the outer scope *)
181 curBP := curBP^.toUp ;
182 Assert(curBP^.toNext=NIL) ;
185 Assert(curBP^.toNext=NIL) ;
187 b^.toUp := curBP^.toUp |
188 +1: (* insert down a level *)
189 b^.toUp := curBP ; (* save return value *)
200 BeginBlock - denotes the start of the next block. We remember all imports and
201 local modules and procedures created in this block.
204 PROCEDURE BeginBlock (n: Name; k: Kind; s: CARDINAL; tok: CARDINAL) ;
213 InitList(LocalModules) ;
214 InitList(ImportedModules) ;
231 PROCEDURE InitUniverse ;
238 InitList(LocalModules) ;
239 InitList(ImportedModules) ;
253 PROCEDURE FlushImports (b: BlockInfoPtr) ;
260 n := NoOfItemsInList (ImportedModules) ;
262 modname := GetItemFromList (ImportedModules, i) ;
263 sym := MakeDefinitionSource (GetTokenNo (), modname) ;
264 Assert (sym # NulSym) ;
272 EndBlock - shutdown the module and create definition symbols for all imported
278 FlushImports(curBP) ;
279 curBP := curBP^.toUp ;
289 RegisterLocalModule - register, n, as a local module.
292 PROCEDURE RegisterLocalModule (n: Name) ;
294 (* printf1('seen local module %a\n', n) ; *)
296 IncludeItemIntoList(LocalModules, n) ;
297 RemoveItemFromList(ImportedModules, n)
299 END RegisterLocalModule ;
303 RegisterImport - register, n, as a module imported from either a local scope or definition module.
306 PROCEDURE RegisterImport (n: Name) ;
310 (* printf1('register import from module %a\n', n) ; *)
312 Assert(curBP^.toUp#NIL) ;
313 bp := curBP^.toUp ; (* skip over current module *)
315 IF NOT IsItemInList(LocalModules, n)
317 IncludeItemIntoList(ImportedModules, n)
327 PROCEDURE RegisterImports ;
331 PopT(n) ; (* n = # of the Ident List *)
332 IF OperandT(n+1)=ImportTok
334 (* Ident list contains Module Names *)
337 RegisterImport(OperandT(n+1-i)) ;
341 (* Ident List contains list of objects *)
342 RegisterImport(OperandT(n+1))
344 PopN(n+1) (* clear stack *)
345 END RegisterImports ;
349 RegisterInnerImports -
352 PROCEDURE RegisterInnerImports ;
356 PopT(n) ; (* n = # of the Ident List *)
357 IF OperandT(n+1)=ImportTok
359 (* Ident list contains list of objects, which will be seen outside the scope of this module *)
363 RegisterImport(OperandT(n+1-i)) ;
368 (* Ident List contains list of objects, but we are importing directly from a module OperandT(n+1) *)
369 RegisterImport(OperandT(n+1))
371 PopN(n+1) (* clear stack *)
372 END RegisterInnerImports ;
376 RegisterProgramModule - register the top of stack as a program module.
379 PROCEDURE RegisterProgramModule ;
389 sym := MakeProgramSource (tok, n) ;
390 SetCurrentModule (sym) ;
391 SetFileModule (sym) ;
392 BeginBlock (n, program, sym, tok) ;
393 M2Error.EnterProgramScope (n)
394 END RegisterProgramModule ;
398 RegisterImplementationModule - register the top of stack as an implementation module.
401 PROCEDURE RegisterImplementationModule ;
411 sym := MakeImplementationSource (tok, n) ;
412 SetCurrentModule (sym) ;
413 SetFileModule (sym) ;
414 BeginBlock (n, defimp, sym, tok) ;
415 M2Error.EnterImplementationScope (n)
416 END RegisterImplementationModule ;
420 RegisterDefinitionModule - register the top of stack as a definition module.
423 PROCEDURE RegisterDefinitionModule ;
433 sym := MakeDefinitionSource (tok, n) ;
434 SetCurrentModule (sym) ;
435 SetFileModule (sym) ;
436 BeginBlock (n, defimp, sym, tok) ;
437 M2Error.EnterDefinitionScope (n)
438 END RegisterDefinitionModule ;
442 RegisterInnerModule - register the top of stack as an inner module, this module name
443 will be removed from the list of outstanding imports in the
444 current module block.
447 PROCEDURE RegisterInnerModule ;
455 RegisterLocalModule (n) ;
456 BeginBlock (n, inner, NulSym, tok) ;
457 M2Error.EnterModuleScope (n)
458 END RegisterInnerModule ;
462 RegisterProcedure - register the top of stack as a procedure.
465 PROCEDURE RegisterProcedure ;
473 BeginBlock (n, procedure, NulSym, tok) ;
474 M2Error.EnterProcedureScope (n)
475 END RegisterProcedure ;
479 EndBuildProcedure - ends building a Procedure.
482 PROCEDURE EndProcedure ;
484 NameEnd, NameStart: Name ;
485 end, start : CARDINAL ;
487 PopTtok (NameEnd, end) ;
488 PopTtok (NameStart, start) ;
489 Assert (start # UnknownTokenNo) ;
490 Assert (end # UnknownTokenNo) ;
491 IF NameEnd # NameStart
496 'procedure name at beginning {%1Ea} does not match the name at end',
497 MakeError (start, NameStart)) ;
498 MetaError1 ('procedure name at end does not match the name at beginning {%1Ea}',
499 MakeError (start, NameStart))
502 'procedure name at beginning {%1Ea} does not match the name at end {%2a}',
503 MakeError (start, curBP^.name), MakeError (end, NameEnd)) ;
505 'procedure name at end {%1Ea} does not match the name at beginning {%2Ea}',
506 MakeError (end, NameEnd), MakeError (start, curBP^.name))
510 M2Error.LeaveErrorScope
518 PROCEDURE EndModule ;
520 NameEnd, NameStart: Name ;
521 end, start : CARDINAL ;
523 PopTtok (NameEnd, end) ;
524 PopTtok (NameStart, start) ;
525 Assert (start # UnknownTokenNo) ;
526 Assert (end # UnknownTokenNo) ;
527 IF NameEnd # NameStart
532 'module name at beginning {%1Ea} does not match the name at end',
533 MakeError (start, NameStart)) ;
534 MetaError1 ('module name at end does not match the name at beginning {%1Ea}',
535 MakeError (start, NameStart))
538 'module name at beginning {%1Ea} does not match the name at end {%2a}',
539 MakeError (start, curBP^.name), MakeError (end, NameEnd)) ;
541 'module name at end {%1Ea} does not match the name at beginning {%2Ea}',
542 MakeError (end, NameEnd), MakeError (start, curBP^.name))
546 M2Error.LeaveErrorScope
551 DeclareModules - declare all inner modules seen at the current block level.
554 PROCEDURE DeclareModules ;
565 printf1 ("*** declaring inner module %a\n", b^.name)
567 s := MakeInnerModule (curBP^.token, b^.name) ;
588 curBP := curBP^.toNext ;
589 (* remember our return *)
603 (* move down a level *)
604 (* remember where we came from *)
606 curBP := curBP^.toDown ;
617 (* move up to the outer scope *)
618 curBP := curBP^.toUp ;
631 IF Level=curBP^.level
633 b := curBP^.toReturn ;
635 curBP := curBP^.toNext ;
636 (* remember our return *)
639 WHILE Level#curBP^.level DO
640 IF Level<curBP^.level
642 (* move up to the outer scope *)
644 curBP := curBP^.toReturn ;
645 curBP^.toPC := b^.toNext (* remember where we reached *)
647 (* move down a level *)
648 (* remember where we came from *)
652 Assert(curBP^.toDown#NIL) ;
653 curBP^.toPC := curBP^.toDown
655 Assert(curBP^.toPC#NIL) ;
656 curBP := curBP^.toPC ;
668 PROCEDURE EnterBlock (n: Name) ;
678 printf1('block %a\n', n)
680 printf2('seen block %a but tree has recorded %a\n', n, curBP^.name)
683 Assert((n=curBP^.name) OR (curBP^.name=NulName)) ;
692 PROCEDURE LeaveBlock ;
696 printf1('leaving block %a ', curBP^.name)
726 (* curBP := headBP^.toDown ; *)
729 curBP^.toPC := curBP^.toDown ;
730 curBP^.toReturn := curBP ;