Skip to content

Commit

Permalink
fbc: fixed / changed symbol lookups to search the entire symbol hash …
Browse files Browse the repository at this point in the history
…list

- fixed sf.net #871 & #730 but altering the symbol lookup algorithm
- sf.net #871: Inherited methods without this shadowed by global functions
- sf.net #730: Using quirk keywords as identifier leads to parsing problems later
- symb.bas:symbLookup() now makes multiple passes on the symbol hash list to find the symbol
- previously, symbLookup() was exiting out early and not finding the correct symbol
  • Loading branch information
jayrm committed Oct 3, 2021
1 parent b617194 commit c2f08a6
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 42 deletions.
2 changes: 2 additions & 0 deletions changelog.txt
Expand Up @@ -74,6 +74,8 @@ Version 1.09.0
- sf.net #645: throw compile time error if scoped REDIM variable shadows a variable of the same name
- sf.net #939: __FB_ARG_EXTRACT__ causes compiler abort; was NULL pointer use on empty argument list.
- sf.net #581: Locals break/override THIS access to inherited members
- sf.net #871: Inherited methods without this shadowed by global functions
- sf.net #730: Using quirk keywords as identifier leads to parsing problems later


Version 1.08.0
Expand Down
75 changes: 49 additions & 26 deletions src/compiler/symb.bas
Expand Up @@ -888,58 +888,81 @@ function symbLookup _
id = @sname

dim as uinteger index = hashHash( id )
dim as FBSYMCHAIN ptr chain_ = NULL

'' for each nested hash tb, starting from last
dim as FBHASHTB ptr hashtb = symb.hashlist.tail
dim as FBHASHTB ptr hashtb = any

'' symbLookup() is used where we don't have an explicit namespace
'' and we need to use the context of the lexer to start our search
''
'' Make multiple passes on the hash lists to find the symbol.
'' Because symbols are added in the order that they are defined,
'' in some cases we can't just take the first symbol we find.
'' !!!TODO!!! optimize the cases where we can exit early with
'' the result

'' keyword?
hashtb = symb.hashlist.tail
do
dim as FBSYMBOL ptr sym = hashLookupEx( @hashtb->tb, id, index )
if( sym <> NULL ) then
chain_ = chainpoolNext()

chain_->sym = sym
chain_->next = NULL
chain_->isimport = FALSE

while( sym )
if( sym->class = FB_SYMBCLASS_KEYWORD ) then
tk = sym->key.id
tk_class = sym->key.tkclass
'' return if it's a KEYWORD or a OPERATOR token, they
'' can't never be redefined, even inside namespaces
if( tk_class <> FB_TKCLASS_QUIRKWD ) then
return chain_
return symbNewChainpool( sym )
end if
end if
sym = sym->hash.next
wend
hashtb = hashtb->prev
loop while( hashtb <> NULL )

'' any symbol not in the global namespace or we are already in the global namespace?
'' check the whole list before we check the imports
hashtb = symb.hashlist.tail
do
dim as FBSYMBOL ptr sym = hashLookupEx( @hashtb->tb, id, index )
while( sym )
'' return if it's not the global ns (as in C++, any nested
'' symbol has precedence over any imported one, even if the
'' latter was imported in the current ns)
if( hashtb->owner <> @symbGetGlobalNamespc( ) ) then
return chain_
return symbNewChainpool( sym )
else
'' also if we are at the global ns, no need to check the imports
if( symbGetCurrentNamespc( ) = @symbGetGlobalNamespc( ) ) then
return chain_
return symbNewChainpool( sym )
end if

'' check (and add) the imports..
exit do
end if
end if

sym = sym->hash.next
wend
hashtb = hashtb->prev
loop while( hashtb <> NULL )

'' now try the imported namespaces..
'' imports?
dim as FBSYMCHAIN ptr imp_chain = hashLookupEx( @symb.imphashtb, id, index )
if( chain_ = NULL ) then
if( imp_chain <> NULL ) then
return imp_chain
end if
endif

chain_->next = imp_chain
'' global?
hashtb = symb.hashlist.tail
do
dim as FBSYMBOL ptr sym = hashLookupEx( @hashtb->tb, id, index )
while( sym )
if( hashtb->owner = @symbGetGlobalNamespc( ) ) then
return symbNewChainpool( sym )
end if
sym = sym->hash.next
wend
hashtb = hashtb->prev
loop while( hashtb <> NULL )

return chain_
'' never found
return NULL

end function

Expand Down Expand Up @@ -1006,10 +1029,10 @@ private function hLookupImportList _
dim as FBSYMBOL ptr imp_ = symbGetCompImportHead( ns )
do while( imp_ <> NULL )
dim as FBSYMBOL ptr sym = hashLookupEx( _
@symbGetCompHashTb( _
symbGetImportNamespc( imp_ ) ).tb, _
id, _
index )
@symbGetCompHashTb( _
symbGetImportNamespc( imp_ ) ).tb, _
id, _
index )
if( sym <> NULL ) then
dim as FBSYMCHAIN ptr chain_ = chainpoolNext()

Expand Down
9 changes: 9 additions & 0 deletions tests/quirk/keyword-shadow-1.bas
@@ -0,0 +1,9 @@
' TEST_MODE : COMPILE_ONLY_OK

type preserve
i as integer
end type

redim array(0 to 1) as integer
redim preserve array(0 to 2)

11 changes: 11 additions & 0 deletions tests/quirk/keyword-shadow-2.bas
@@ -0,0 +1,11 @@
' TEST_MODE : COMPILE_ONLY_OK

namespace aaa
enum explicit
A
end enum

enum E explicit
B
end enum
end namespace
11 changes: 11 additions & 0 deletions tests/quirk/keyword-shadow-3.bas
@@ -0,0 +1,11 @@
' TEST_MODE : COMPILE_ONLY_OK

'' Create enum named "explicit" (not an unnamed enum with EXPLICIT access)
enum explicit
A
end enum

'' should be no syntax error ("explicit" not recognized as keyword)
enum E explicit
B
end enum
64 changes: 64 additions & 0 deletions tests/structs/member-proc-shadow.bas
@@ -0,0 +1,64 @@
#include "fbcunit.bi"

'' inherited methods called without 'this' should be preferred over the globally defined procedure

dim shared f_count as integer = 0
dim shared af_count as integer = 0

private sub f()
f_count += 1
end sub

type A
i as integer
declare sub f()
end type

sub A.f()
af_count += 1
end sub

type B extends A
declare sub test_proc()
end type

sub B.test_proc()
CU_ASSERT( f_count = 0 )
CU_ASSERT( af_count = 0 )

f()

CU_ASSERT( f_count = 0 )
CU_ASSERT( af_count = 1 )

.f()

CU_ASSERT( f_count = 1 )
CU_ASSERT( af_count = 1 )

..f()

CU_ASSERT( f_count = 2 )
CU_ASSERT( af_count = 1 )

this.f()

CU_ASSERT( f_count = 2 )
CU_ASSERT( af_count = 2 )

base.f()

CU_ASSERT( f_count = 2 )
CU_ASSERT( af_count = 3 )

end sub


SUITE( fbc_tests.structs.member_proc_shadow )
TEST( default )
dim x as B
x.test_proc()
END_TEST

END_SUITE

0 comments on commit c2f08a6

Please sign in to comment.