@@ -48,6 +48,14 @@ declare sub symbKeywordTypeInit ( )
4848
4949declare function hGetNamespacePrefix( byval sym as FBSYMBOL ptr ) as string
5050
51+ declare function hLookupImportList _
52+ ( _
53+ byval ns as FBSYMBOL ptr, _
54+ byval id as const zstring ptr, _
55+ byval index as uinteger _
56+ ) as FBSYMCHAIN ptr
57+
58+
5159''globals
5260 dim shared as SYMBCTX symb
5361
@@ -869,6 +877,15 @@ function symbNewChainpool _
869877
870878end function
871879
880+ / '
881+ !!!TODO!!! - clean up code for lookups
882+ refactor the duplicated code in :
883+ - symbLookup108()
884+ - symbLookupNS()
885+ - symbLookupTypeNS()
886+ - symbLookup()
887+ '/
888+
872889'':::::
873890function symbLookup108 _
874891 ( _
@@ -943,15 +960,15 @@ function symbLookup108 _
943960end function
944961
945962'':::::
946- function symbLookup _
963+ function symbLookupNS _
947964 ( _
948965 byval id as zstring ptr, _
949966 byref tk as FB_TOKEN, _
950967 byref tk_class as FB_TKCLASS _
951968 ) as FBSYMCHAIN ptr
952969
953970 static as zstring * FB_MAXNAMELEN+ 1 sname
954- dim as FBSYMBOL ptr firstglobal = NULL
971+ dim as FBSYMBOL ptr first_ancestor = NULL
955972
956973 '' assume it's an unknown identifier
957974 tk = FB_TK_ID
@@ -966,7 +983,7 @@ function symbLookup _
966983 dim as FBHASHTB ptr hashtb = any
967984
968985 '' symbLookup() is used where we don't have an explicit namespace
969- '' and we need to use the context of the lexer to start our search
986+ '' and we need to use the context of the lexer/parser to start our search
970987 ''
971988 '' Make multiple passes on the hash lists to find the symbol.
972989 '' Because symbols are added in the order that they are defined,
@@ -991,10 +1008,6 @@ function symbLookup _
9911008 hashtb = hashtb->prev
9921009 loop while ( hashtb <> NULL )
9931010
994- '' use old lookup method from fbc 1.08.x and earlier?
995- if ( env.clopt.lookup108 ) then
996- return symbLookup108( id, tk, tk_class )
997- end if
9981011 '' any symbol not in the global namespace or we are already in the global namespace?
9991012 '' check the whole list before we check the imports
10001013 hashtb = symb.hashlist.tail
@@ -1011,8 +1024,8 @@ function symbLookup _
10111024 if ( symbGetCurrentNamespc( ) = @symbGetGlobalNamespc( ) ) then
10121025 return symbNewChainpool( sym )
10131026 else
1014- if ( firstglobal = NULL ) then
1015- firstglobal = sym
1027+ if ( first_ancestor = NULL ) then
1028+ first_ancestor = sym
10161029 end if
10171030 end if
10181031 end if
@@ -1025,47 +1038,190 @@ function symbLookup _
10251038 dim as FBSYMCHAIN ptr imp_chain = hashLookupEx( @symb.imphashtb, id, index )
10261039 if ( imp_chain <> NULL ) then
10271040
1028- if ( firstglobal ) then
1029- '' If we have found both imports and a global, then check the imports.
1030- '' If the import is actually a member of an enum, then we'd prefer to
1031- '' return the global instead. If the anonymous enum is not the first
1032- '' listed in the chain, then assume that the symbFindBy*() calls will
1033- '' deal with finding a suitable symbol.
1041+ '' We have both an ancestor (which was reached directly in the current
1042+ '' namespace, plus we also have imports.
1043+ '' !!!TODO!!! scoped+non-eplicit enums are going to give us trouble here
1044+ '' because the enum member is imported in to the current namespace
1045+ '' The choices are:
1046+ '' - always return the first_ancestor found
1047+ '' - return the first_ancestor + imports, and give ambiguous errors
1048+ '' - something else where we search the imports for enums
1049+ '' For now, return the first ancestor and all imports
1050+
1051+ if ( first_ancestor ) then
1052+ dim as FBSYMCHAIN ptr chain_ = symbNewChainpool( first_ancestor )
1053+ chain_-> next = imp_chain
1054+ return chain_
1055+ end if
1056+
1057+ '' No ancestor? Just return the imports.
1058+ return imp_chain
1059+ end if
1060+
1061+ '' no imports? return only the first ancestor (if we already found it)
1062+ if ( first_ancestor ) then
1063+ return symbNewChainpool( first_ancestor )
1064+ end if
1065+
1066+ '' never found
1067+ return NULL
1068+
1069+ end function
1070+
1071+ '':::::
1072+ function symbLookupTypeNS _
1073+ ( _
1074+ byval id as zstring ptr, _
1075+ byref tk as FB_TOKEN, _
1076+ byref tk_class as FB_TKCLASS _
1077+ ) as FBSYMCHAIN ptr
1078+
1079+ assert( symbGetCurrentNamespc( ) <> NULL )
1080+
1081+ static as zstring * FB_MAXNAMELEN+ 1 sname
1082+ dim as FBSYMBOL ptr first_ancestor = NULL
1083+
1084+ '' assume it's an unknown identifier
1085+ tk = FB_TK_ID
1086+ tk_class = FB_TKCLASS_IDENTIFIER
1087+
1088+ hUcase( *id, sname )
1089+ id = @sname
1090+
1091+ dim as uinteger index = hashHash( id )
1092+
1093+ '' for each nested hash tb, starting from last
1094+ dim as FBHASHTB ptr hashtb = any
1095+
1096+ '' symbLookup() is used where we don't have an explicit namespace
1097+ '' and we need to use the context of the lexer/parser to start our search
1098+ ''
1099+ '' Make multiple passes on the hash lists to find the symbol.
1100+ '' Because symbols are added in the order that they are defined,
1101+ '' in some cases we can't just take the first symbol we find.
1102+
1103+ '' keyword?
1104+ hashtb = symb.hashlist.tail
1105+ do
1106+ dim as FBSYMBOL ptr sym = hashLookupEx( @hashtb->tb, id, index )
1107+ while ( sym )
1108+ if ( sym-> class = FB_SYMBCLASS_KEYWORD ) then
1109+ tk = sym-> key .id
1110+ tk_class = sym-> key .tkclass
1111+ '' return if it's a KEYWORD or a OPERATOR token, they
1112+ '' can't never be redefined, even inside namespaces
1113+ if ( tk_class <> FB_TKCLASS_QUIRKWD ) then
1114+ return symbNewChainpool( sym )
1115+ end if
1116+ end if
1117+ sym = sym->hash.next
1118+ wend
1119+ hashtb = hashtb->prev
1120+ loop while ( hashtb <> NULL )
10341121
1035- if ( symbGetNamespace( imp_chain->sym ) <> NULL ) then
1036- if ( symbIsEnum( symbGetNamespace( imp_chain->sym ) ) ) then
1037- return symbNewChainpool( firstglobal )
1122+ '' any symbol not in the global namespace or we are already in the global namespace?
1123+ '' check the whole list before we check the imports
1124+ hashtb = symb.hashlist.tail
1125+ do
1126+ dim as FBSYMBOL ptr sym = hashLookupEx( @hashtb->tb, id, index )
1127+ while ( sym )
1128+ '' return if it's not the global ns (as in C++, any nested
1129+ '' symbol has precedence over any imported one, even if the
1130+ '' latter was imported in the current ns)
1131+ if ( hashtb->owner <> @symbGetGlobalNamespc( ) ) then
1132+ return symbNewChainpool( sym )
1133+ else
1134+ '' also if we are at the global ns, no need to check the imports
1135+ if ( symbGetCurrentNamespc( ) = @symbGetGlobalNamespc( ) ) then
1136+ return symbNewChainpool( sym )
1137+ else
1138+ if ( first_ancestor = NULL ) then
1139+ first_ancestor = sym
1140+ end if
10381141 end if
10391142 end if
1143+ sym = sym->hash.next
1144+ wend
1145+ hashtb = hashtb->prev
1146+ loop while ( hashtb <> NULL )
10401147
1041- # if 0
1042- / '
1043- not yet entirely known is if we should return a symbchain for
1044- the global plus the imports . This is what fbc < 1.09.0 did
1045- but the look-ups were also broken then . This note is left here
1046- as a hint if some future bug report is filed where we should expect
1047- ambiguous access but didn 't get it
1048- '/
1049- dim as FBSYMCHAIN ptr chain_ = symbNewChainpool( firstglobal )
1148+ dim as FBSYMBOL ptr ns = symbGetCurrentNamespc( )
1149+
1150+ '' search in UDT's (TYPE or CLASS) hash tb first
1151+ dim as FBSYMBOL ptr sym = hashLookupEx( @symbGetCompHashTb( ns ).tb, id, index )
1152+
1153+ '' don't access local variables in an explicit namespace
1154+ while ( sym )
1155+ if ( symbIsLocal( sym ) and symbIsVar( sym ) ) then
1156+ sym = sym->hash.next
1157+ else
1158+ exit while
1159+ end if
1160+ wend
1161+
1162+ '' Found the symbol in the type's namespace?
1163+ if ( sym ) then
1164+ dim as FBSYMCHAIN ptr chain_ = symbNewChainpool( sym )
1165+ return chain_
1166+ end if
1167+
1168+ '' Search the type's imports
1169+ if ( (symbGetCompExt( ns ) <> NULL) and (symbGetCompImportHead( ns ) <> NULL) ) then
1170+ dim as FBSYMCHAIN ptr chain_ = hLookupImportList( ns, id, index )
1171+ if ( chain_ ) then
1172+ '' return the first one
1173+ return symbNewChainpool( chain_->sym )
1174+ end if
1175+ end if
1176+
1177+ '' search all the imports?
1178+ dim as FBSYMCHAIN ptr imp_chain = hashLookupEx( @symb.imphashtb, id, index )
1179+ if ( imp_chain <> NULL ) then
1180+
1181+ if ( first_ancestor ) then
1182+ dim as FBSYMCHAIN ptr chain_ = symbNewChainpool( first_ancestor )
10501183 chain_-> next = imp_chain
10511184 return chain_
1052- # endif
10531185 end if
10541186
1055- '' if we didn't find any global, then return the imports
10561187 return imp_chain
1057- endif
1188+ end if
10581189
1059- '' no imports too? then return the global (if we already found it)
1060- if ( firstglobal ) then
1061- return symbNewChainpool( firstglobal )
1190+ '' no imports? return only first ancestor (if we already found it)
1191+ if ( first_ancestor ) then
1192+ return symbNewChainpool( first_ancestor )
10621193 end if
10631194
10641195 '' never found
10651196 return NULL
10661197
10671198end function
10681199
1200+ '':::::
1201+ function symbLookup _
1202+ ( _
1203+ byval id as zstring ptr, _
1204+ byref tk as FB_TOKEN, _
1205+ byref tk_class as FB_TKCLASS _
1206+ ) as FBSYMCHAIN ptr
1207+
1208+ '' use old lookup method from fbc 1.08.x and earlier?
1209+ if ( env.clopt.lookup108 ) then
1210+ return symbLookup108( id, tk, tk_class )
1211+ end if
1212+
1213+ '' In a TYPE's namespace?
1214+ if ( symbGetCurrentNamespc( ) <> NULL ) then
1215+ select case symbGetClass( symbGetCurrentNamespc( ) )
1216+ case FB_SYMBCLASS_STRUCT, FB_SYMBCLASS_CLASS
1217+ return symbLookupTypeNS( id, tk, tk_class )
1218+ end select
1219+ end if
1220+
1221+ return symbLookupNS( id, tk, tk_class )
1222+
1223+ end function
1224+
10691225'':::::
10701226private function hLookupImportHash _
10711227 ( _
0 commit comments