1 (* P1SymBuild.mod pass 1 symbol creation.
3 Copyright (C) 2001-2024 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 P1SymBuild ;
25 FROM ASCII IMPORT nul ;
26 FROM NameKey IMPORT Name, WriteKey, MakeKey, KeyToCharStar, NulName ;
27 FROM M2Debug IMPORT Assert, WriteDebug ;
28 FROM M2LexBuf IMPORT GetFileName, GetTokenNo, UnknownTokenNo ;
29 FROM M2MetaError IMPORT MetaErrorString2, MetaError0, MetaError1, MetaError2, MetaErrorT1, MetaErrorT2 ;
30 FROM DynamicStrings IMPORT String, Slice, InitString, KillString, EqualCharStar, RIndex, Mark, ConCat ;
31 FROM M2Printf IMPORT printf0, printf1, printf2 ;
32 FROM M2Options IMPORT Iso ;
34 FROM M2Reserved IMPORT ImportTok, ExportTok, QualifiedTok, UnQualifiedTok,
35 NulTok, VarTok, ArrayTok, BuiltinTok, InlineTok ;
37 FROM FifoQueue IMPORT PutEnumerationIntoFifoQueue ;
38 FROM P0SymBuild IMPORT EnterBlock, LeaveBlock ;
40 FROM SymbolTable IMPORT NulSym,
42 AppendModuleOnImportStatement,
43 AppendModuleImportStatement,
44 MakeImportStatement, MakeImport,
46 StartScope, EndScope, PseudoScope,
47 GetScope, GetCurrentScope,
49 SetCurrentModule, SetFileModule,
51 MakeEnumeration, MakeSubrange,
52 MakeVar, MakeType, PutType,
55 PutFieldEnumeration, PutSubrange, PutVar,
56 IsDefImp, IsModule, IsInnerModule, IsType,
60 GetSym, RequestSym, IsUnknown, RenameSym,
62 GetExported, IsExported,
64 PutImported, PutIncludedByDefinition,
65 PutExported, PutExportQualified, PutExportUnQualified,
66 TryMoveUndeclaredSymToInnerModule,
69 PutDoesNeedExportList, PutDoesNotNeedExportList,
70 DoesNotNeedExportList,
72 PutFunction, PutParam, PutVarParam,
74 IsProcedure, IsConstString,
75 MakePointer, PutPointer,
76 MakeRecord, PutFieldRecord,
78 MakeSubscript, PutSubscript,
79 PutArray, GetType, IsArray,
80 IsProcType, MakeProcType,
81 PutProcTypeVarParam, PutProcTypeParam,
82 PutProcedureBuiltin, PutProcedureInline,
84 ResolveImports, PutDeclared,
85 MakeError, MakeErrorS,
88 FROM M2Batch IMPORT MakeDefinitionSource,
89 MakeImplementationSource,
91 LookupModule, LookupOuterModule ;
93 FROM M2Quads IMPORT PushT, PopT, PushTF, PopTF, OperandT, PopN, OperandTok,
94 PopTtok, PushTtok, PushTFtok, PopTFtok ;
96 FROM M2Comp IMPORT CompilingDefinitionModule,
97 CompilingImplementationModule,
98 CompilingProgramModule ;
104 importStatementCount: CARDINAL ;
108 CheckFileName - checks to see that the module name matches the file name.
112 PROCEDURE CheckFileName (tok: CARDINAL; name: Name; ModuleType: ARRAY OF CHAR) ;
119 FileName := GetFileName() ;
120 basename := RIndex(FileName, '/', 0) ;
125 ext := RIndex(FileName, '.', 0) ;
130 FileName := Slice(FileName, basename, ext) ;
131 IF EqualCharStar(FileName, KeyToCharStar(name))
133 FileName := KillString(FileName)
135 s := ConCat (InitString (ModuleType),
136 Mark (InitString (" module name {%1Ea} is inconsistant with the filename {%F{%2a}}"))) ;
137 MetaErrorString2 (s, MakeError (tok, name), MakeErrorS (tok, FileName))
144 StartBuildDefinitionModule - Creates a definition module and starts
147 he Stack is expected:
154 |------------| +------------+
155 | NulName/"C"| | NameStart |
156 |------------| |------------|
159 PROCEDURE P1StartBuildDefinitionModule ;
163 ModuleSym: CARDINAL ;
165 importStatementCount := 0 ;
167 (* CheckFileName(name, 'definition') ; *)
168 ModuleSym := MakeDefinitionSource(GetTokenNo(), name) ;
169 PutDoesNotNeedExportList(ModuleSym) ;
170 SetCurrentModule(ModuleSym) ;
171 SetFileModule(ModuleSym) ;
172 StartScope(ModuleSym) ;
173 Assert(IsDefImp(ModuleSym)) ;
174 Assert(CompilingDefinitionModule()) ;
176 IF (language#NulSym) AND IsConstString(language)
178 IF GetSymName(language)=MakeKey('C')
180 PutDefinitionForC(ModuleSym)
181 ELSIF GetSymName(language)=NulName
183 MetaError0 ('{%E}currently a non modula-2 definition module can only be declared as DEFINITION FOR {%k"C"}')
185 MetaError1 ('unknown definition module language {%1Ea}, currently a non modula-2 definition module can only be declared as DEFINITION FOR {%k"C"}', language)
190 END P1StartBuildDefinitionModule ;
194 EndBuildDefinitionModule - Destroys the definition module scope and
195 checks for correct name.
197 The Stack is expected:
202 +------------+ +-----------+
204 |------------| |-----------|
205 | NameStart | | | <- Ptr
206 |------------| |-----------|
209 PROCEDURE P1EndBuildDefinitionModule ;
215 Assert(CompilingDefinitionModule()) ;
217 PopTtok(NameStart, start) ;
221 printf0('pass 1: ') ;
222 DisplayTrees(GetCurrentModule())
226 MetaError1 ('inconsistant definition module name {%1Wa}', MakeError (start, NameStart))
229 END P1EndBuildDefinitionModule ;
233 StartBuildImplementationModule - Creates an implementation module and starts
236 The Stack is expected:
241 +------------+ +-----------+
242 | NameStart | | NameStart |
243 |------------| |-----------|
247 PROCEDURE P1StartBuildImplementationModule ;
251 ModuleSym: CARDINAL ;
253 importStatementCount := 0 ;
254 PopTtok (name, tok) ;
255 (* CheckFileName(name, 'implementation') ; *)
256 ModuleSym := MakeImplementationSource (tok, name) ;
257 SetCurrentModule (ModuleSym) ;
258 SetFileModule (ModuleSym) ;
259 StartScope (ModuleSym) ;
260 IF NOT IsDefImp (ModuleSym)
262 MetaError1 ('cannot find corresponding definition module for {%1Ea}', ModuleSym)
264 Assert (CompilingImplementationModule()) ;
265 PushTtok (name, tok) ;
267 END P1StartBuildImplementationModule ;
271 EndBuildImplementationModule - Destroys the implementation module scope and
272 checks for correct name.
274 The Stack is expected:
279 +------------+ +-----------+
281 |------------| |-----------|
282 | NameStart | | | <- Ptr
283 |------------| |-----------|
286 PROCEDURE P1EndBuildImplementationModule ;
288 start, end: CARDINAL ;
293 Assert(CompilingImplementationModule()) ;
295 PopTtok(NameStart, start) ;
296 PopTtok(NameEnd, end) ;
300 'inconsistant implementation module name {%1Wa}', MakeError (start, NameStart))
303 END P1EndBuildImplementationModule ;
307 StartBuildProgramModule - Creates a program module and starts
310 The Stack is expected:
315 +------------+ +-----------+
316 | NameStart | | NameStart |
317 |------------| |-----------|
321 PROCEDURE P1StartBuildProgramModule ;
325 ModuleSym: CARDINAL ;
327 importStatementCount := 0 ;
329 (* CheckFileName(name, 'main') ; *)
330 ModuleSym := MakeProgramSource(tok, name) ;
331 SetCurrentModule(ModuleSym) ;
332 SetFileModule(ModuleSym) ;
333 StartScope(ModuleSym) ;
334 IF (NOT CompilingProgramModule()) OR IsDefImp(ModuleSym)
337 'module {%1Ea} has a corresponding DEFINITION MODULE but no IMPLEMENTATION keyword in the main module', ModuleSym)
339 PushTtok(name, tok) ;
341 END P1StartBuildProgramModule ;
345 EndBuildProgramModule - Destroys the program module scope and
346 checks for correct name.
348 The Stack is expected:
353 +------------+ +-----------+
355 |------------| |-----------|
356 | NameStart | | | <- Ptr
357 |------------| |-----------|
360 PROCEDURE P1EndBuildProgramModule ;
368 Assert(CompilingProgramModule()) ;
370 PopTtok(NameStart, start) ;
371 PopTtok(NameEnd, end) ;
374 printf0('pass 1: ') ;
375 DisplayTrees(GetCurrentModule())
380 'inconsistant program module name {%1Wa}', MakeError (start, NameStart))
383 END P1EndBuildProgramModule ;
387 StartBuildInnerModule - Creates an Inner module and starts
390 The Stack is expected:
395 +------------+ +-----------+
396 | NameStart | | NameStart |
397 |------------| |-----------|
401 PROCEDURE StartBuildInnerModule ;
405 ModuleSym: CARDINAL ;
408 ModuleSym := GetSym(name) ;
409 Assert(ModuleSym#NulSym) ;
410 StartScope(ModuleSym) ;
411 Assert(NOT IsDefImp(ModuleSym)) ;
412 PushTtok(name, tok) ;
414 END StartBuildInnerModule ;
418 EndBuildInnerModule - Destroys the Inner module scope and
419 checks for correct name.
421 The Stack is expected:
426 +------------+ +-----------+
428 |------------| |-----------|
429 | NameStart | | | <- Ptr
430 |------------| |-----------|
433 PROCEDURE EndBuildInnerModule ;
435 start, end: CARDINAL ;
440 PopTtok(NameStart, start) ;
441 PopTtok(NameEnd, end) ;
445 'inconsistant inner module name {%1Wa}', MakeError (start, NameStart))
448 END EndBuildInnerModule ;
452 BuildImportOuterModule - Builds imported identifiers into an outer module
453 from a definition module.
455 The Stack is expected:
460 +------------+ +-----------+
462 |------------| |-----------|
464 |------------| |-----------|
468 |------------| |-----------|
470 |------------| |-----------|
471 | ImportTok | | Ident |
472 |------------| |-----------|
474 IMPORT Id1, .. Id# ; FROM Ident IMPORT Id1 .. Id# ;
479 All above stack discarded
482 PROCEDURE BuildImportOuterModule (definition: BOOLEAN) ;
487 PopT(n) ; (* n = # of the Ident List *)
488 IF OperandT(n+1)=ImportTok
490 (* Ident list contains Module Names *)
493 ModSym := LookupModule(OperandTok(n+1-i),
495 PutImported(ModSym) ;
498 PutIncludedByDefinition(ModSym)
503 (* Ident List contains list of objects *)
504 ModSym := LookupModule(OperandTok(n+1),
509 WriteString('Importing ') ; WriteKey(Operand(j)) ; WriteString(' from ') ; WriteKey(GetSymName(ModSym)) ; WriteLn ;
511 Sym := GetExported (OperandTok (n+1-i),
512 ModSym, OperandT (n+1-i)) ;
517 PopN (n+1) (* clear stack *)
518 END BuildImportOuterModule ;
522 BuildExportOuterModule - Builds exported identifiers from an outer module
523 to the outside world of library modules.
525 The Stack is expected:
530 +------------+ +--------------+
532 |------------| |--------------|
534 |------------| |--------------|
538 |------------| |--------------|
540 |------------| |--------------|
541 | ExportTok | | QualifiedTok |
542 |------------| |--------------|
544 EXPORT Id1, .. Id# ; EXPORT QUALIFIED Id1 .. Id# ;
551 All above stack discarded
554 PROCEDURE BuildExportOuterModule ;
558 PopT (n) ; (* n = # of the Ident List *)
559 IF (OperandT(n+1)=QualifiedTok) AND CompilingDefinitionModule()
561 PutDoesNeedExportList(GetCurrentModule()) ;
562 (* Ident List contains list of export qualified objects *)
565 PutExportQualified (OperandTok (i), OperandT (i)) ;
568 ELSIF (OperandT(n+1)=UnQualifiedTok) AND CompilingDefinitionModule()
570 PutDoesNeedExportList(GetCurrentModule()) ;
571 (* Ident List contains list of export unqualified objects *)
574 PutExportUnQualified (OperandTok (i), OperandT(i)) ;
577 ELSIF CompilingDefinitionModule()
579 MetaError0 ('the {%EkEXPORT} must be either {%kQUALIFIED} or {%kUNQUALIFIED} in a definition module')
581 MetaError0 ('{%E}only allowed inter module exports in a definition module')
583 PopN (n+1) (* clear stack *)
584 END BuildExportOuterModule ;
588 CheckExplicitExported - checks to see whether we are compiling
589 a definition module and whether the ident
590 is implicitly export qualified or unqualified.
593 The Stack is expected:
598 +------------+ +-----------+
599 | Identname | | Identname |
600 |------------| |-----------|
604 PROCEDURE CheckExplicitExported ;
606 IF CompilingDefinitionModule() AND DoesNotNeedExportList(GetCurrentModule())
608 (* printf1('exporting identifier %a\n', OperandT(1)) ; *)
609 PutExportQualified (OperandTok (1), OperandT(1))
611 END CheckExplicitExported ;
615 BuildImportInnerModule - Builds imported identifiers into an inner module
616 from the last level of module.
618 The Stack is expected:
623 +------------+ +-----------+
625 |------------| |-----------|
627 |------------| |-----------|
631 |------------| |-----------|
633 |------------| |-----------|
634 | ImportTok | | Ident |
635 |------------| |-----------|
637 IMPORT Id1, .. Id# ; FROM Ident IMPORT Id1 .. Id# ;
641 All above stack discarded
644 PROCEDURE BuildImportInnerModule ;
649 PopT (n) ; (* n = # of the Ident List *)
650 IF OperandT (n+1) = ImportTok
652 (* Ident List contains list of objects *)
655 AddNameToImportList (OperandT (i)) ;
659 (* Ident List contains list of objects *)
660 ModSym := LookupOuterModule (OperandTok(n+1),
664 Sym := GetExported (OperandTok (n+1-i), ModSym, OperandT (n+1-i)) ;
669 PopN (n+1) (* clear stack *)
670 END BuildImportInnerModule ;
674 BuildExportInnerModule - Builds exported identifiers from an inner module
675 to the next layer module.
677 The Stack is expected:
682 +------------+ +--------------+
684 |------------| |--------------|
686 |------------| |--------------|
690 |------------| |--------------|
692 |------------| |--------------|
693 | ExportTok | | QualifiedTok |
694 |------------| |--------------|
696 EXPORT Id1, .. Id# ; EXPORT QUALIFIED Id1 .. Id# ;
702 All above stack discarded
705 PROCEDURE BuildExportInnerModule ;
712 PopT (n) ; (* n = # of the Ident List *)
713 IF OperandT (n+1) = ExportTok
715 (* Ident List contains list of objects *)
717 PrevMod := GetScope (GetCurrentScope ()) ;
719 tok := OperandTok (i) ;
720 IF (PrevMod#NulSym) AND (IsModule(PrevMod) OR IsDefImp(PrevMod))
722 Sym := GetLocalSym (PrevMod, OperandT(i)) ;
725 Sym := TryMoveUndeclaredSymToInnerModule (PrevMod, GetCurrentScope (), OperandT (i)) ;
728 Sym := RequestSym (tok, OperandT(i)) ;
732 (* use Sym which has already been created in outer scope *)
733 AddSymToModuleScope (GetCurrentScope (), Sym)
736 Sym := RequestSym (tok, OperandT(i)) ;
742 MetaError0 ('{%EkQUALIFIED} not allowed in an inner module')
744 PopN(n+1) (* clear stack *)
745 END BuildExportInnerModule ;
749 StartBuildEnumeration - Builds an Enumeration type Type.
767 |------------| +------------+
769 |------------| |------------|
771 |------------| |------------|
774 PROCEDURE StartBuildEnumeration ;
781 PopT(n) ; (* No := # *)
782 name := OperandT(n+1) ;
783 tokno := OperandTok(n+1) ;
784 Type := MakeEnumeration(tokno, name) ;
787 PutFieldEnumeration(OperandTok(n-i+1), Type, OperandT(n-i+1)) ;
790 PutEnumerationIntoFifoQueue(Type) ; (* store enumeration away for pass 2 *)
792 PushTtok(name, tokno) ;
793 PushTtok(Type, tokno)
794 END StartBuildEnumeration ;
798 EndBuildEnumeration - completes the construction of the enumeration type.
808 |------------| +---------------+
809 | Name | | Type | Name |
810 |------------| |---------------|
815 PROCEDURE EndBuildEnumeration ;
826 - the type name the same as Name, or the name is nul. - do nothing.
827 - when type with a name that is different to Name. In which case
828 we create a new type.
830 PopTtok(Type, tokno) ;
835 n1 := GetSymName(GetCurrentModule()) ;
836 printf2('inside module %a declaring type name %a\n',
838 IF (NOT IsUnknown(Type))
840 n1 := GetSymName(GetScope(Type)) ;
841 n2 := GetSymName(Type) ;
842 printf2('type was created inside scope %a as name %a\n',
846 IF (name=NulName) OR (GetSymName(Type)=name)
849 Typically the declaration that causes this case is:
852 a: (blue, green, red) ;
855 +---- type has no name.
857 in which case the constructed from StartBuildEnumeration is complete
859 PushTFtok(Type, name, tokno)
861 (* in this case we are seeing:
864 name = (blue, green, red)
866 so we construct the type name and define it to have the previously
867 created enumeration type
869 Sym := MakeType(tokno, name) ;
871 PushTFtok(Sym, name, tokno)
873 END EndBuildEnumeration ;
877 BuildHiddenType - Builds a Hidden Type.
890 PROCEDURE BuildHiddenType ;
895 PopTtok (name, tokno) ;
896 (* WriteString('Hidden type encountered: ') ; *)
897 (* WriteKey(Name) ; WriteLn ; *)
898 Assert (MakeHiddenType (tokno, name) # NulSym)
899 END BuildHiddenType ;
903 StartBuildProcedure - Builds a Procedure.
910 +------------+ +------------+
912 |------------| |------------|
916 | or name or | | Name |
918 |------------| |------------|
921 PROCEDURE StartBuildProcedure ;
928 PopTtok (name, tokno) ;
929 PopT (builtin) ; (* was this procedure defined as a builtin? *)
930 PushTtok (name, tokno) ; (* Name saved for the EndBuildProcedure name check *)
931 ProcSym := RequestSym (tokno, name) ;
932 IF IsUnknown (ProcSym)
935 May have been compiled in DEF or IMP module, remember that IMP maybe
936 compiled before corresponding DEF module.
938 ProcSym := MakeProcedure (tokno, name)
939 ELSIF IsProcedure (ProcSym)
941 (* declared in the other module, we record declaration here as well *)
942 PutDeclared (tokno, ProcSym)
944 MetaError1 ('expecting a procedure name and symbol {%1Ea} has been declared as a {%1d}', ProcSym) ;
950 IF builtin=BuiltinTok
952 PutProcedureBuiltin (ProcSym, name)
953 ELSIF builtin=InlineTok
955 PutProcedureInline (ProcSym)
957 PutProcedureBuiltin (ProcSym, builtin)
961 StartScope (ProcSym) ;
962 IF NOT CompilingDefinitionModule ()
966 END StartBuildProcedure ;
970 EndBuildProcedure - Ends building a Procedure.
971 It checks the start procedure name matches the end
976 (Procedure Not Defined in definition module)
991 PROCEDURE EndBuildProcedure ;
993 start, end: CARDINAL ;
998 PopTtok(NameEnd, end) ;
1000 PopTtok(NameStart, start) ;
1001 IF NameEnd#NameStart
1003 IF end # UnknownTokenNo
1006 'procedure name at end does not match name at beginning {%1EDa}', ProcSym)
1007 ELSIF start # UnknownTokenNo
1010 'procedure name at end {%1EDa} does not match name at beginning {%2a}',
1011 MakeError (end, NameEnd), ProcSym)
1013 MetaError1 ('procedure name at end does not match name at beginning {%1EDa}', ProcSym)
1017 Assert (NOT CompilingDefinitionModule()) ;
1019 END EndBuildProcedure ;
1023 BuildProcedureHeading - Builds a procedure heading for the definition
1026 Operation only performed if compiling a
1043 PROCEDURE BuildProcedureHeading ;
1045 ProcSym : CARDINAL ;
1048 IF CompilingDefinitionModule()
1054 END BuildProcedureHeading ;
1058 BuildNulName - Pushes a NulName onto the top of the stack.
1065 Empty +------------+
1070 PROCEDURE BuildNulName ;
1077 BuildTypeEnd - Pops the type Type and Name.
1086 | Type | Name | Empty
1090 PROCEDURE BuildTypeEnd ;
1100 BuildImportStatement - create a new import statement in the current module.
1101 It ignores local modules.
1103 The quadruple stack is not used.
1106 PROCEDURE BuildImportStatement (tok: CARDINAL) ;
1110 scope := GetCurrentScope () ;
1111 IF IsDefImp (scope) OR (IsModule (scope) AND (NOT IsInnerModule (scope)))
1113 IF CompilingDefinitionModule () AND (NOT IsDefImp (scope))
1115 MetaError1 ('module scope should be a definition module rather than {%1EDa}', scope)
1117 INC (importStatementCount) ;
1118 AppendModuleImportStatement (scope, MakeImportStatement (tok, importStatementCount))
1121 END BuildImportStatement ;
1125 AddImportToImportStatement - the top of stack is expected to be a module name.
1126 This is looked up from the module universe and
1127 wrapped in an import symbol and placed into the
1128 current import statement.
1130 The quadruple stack is unchanged.
1136 +---------------------+ +---------------------+
1137 | ImportedModuleName | | ImportedModuleName |
1138 |---------------------| |---------------------|
1141 PROCEDURE AddImportToImportStatement (qualified: BOOLEAN) ;
1145 scope := GetCurrentScope () ;
1146 IF IsDefImp (scope) OR (IsModule (scope) AND (NOT IsInnerModule (scope)))
1148 IF CompilingDefinitionModule () AND (NOT IsDefImp (scope))
1150 MetaError1 ('module scope should be a definition module rather than {%1EDa}', scope) ;
1152 AppendModuleOnImportStatement (scope, MakeImport (OperandTok (1),
1153 LookupModule (OperandTok (1), OperandT (1)),
1154 importStatementCount, qualified))
1157 END AddImportToImportStatement ;