Well, I gave it a shot! but I still couldn't come up with anything good enough. I tried two separate approaches. The first one I tried was to try checking the ID while still in cSymbolType, but I couldn't make it work. Perhaps someone could fill in the missing pieces, but I tried for a while and couldn't get it. Patch:
Code: Select all
diff --git a/FreeBASIC/src/compiler/inc/parser.bi b/FreeBASIC/src/compiler/inc/parser.bi
index 43e8c1b..ca1b703 100644
--- a/FreeBASIC/src/compiler/inc/parser.bi
+++ b/FreeBASIC/src/compiler/inc/parser.bi
@@ -215,6 +215,7 @@ enum FB_SYMBTYPEOPT
FB_SYMBTYPEOPT_CHECKSTRPTR = &h00000001
FB_SYMBTYPEOPT_ALLOWFORWARD = &h00000002
+ FB_SYMBTYPEOPT_ALLOWID = &h00000004
FB_SYMBTYPEOPT_DEFAULT = FB_SYMBTYPEOPT_CHECKSTRPTR
end enum
diff --git a/FreeBASIC/src/compiler/parser-decl-symbtype.bas b/FreeBASIC/src/compiler/parser-decl-symbtype.bas
index e08a134..c14d59c 100644
--- a/FreeBASIC/src/compiler/parser-decl-symbtype.bas
+++ b/FreeBASIC/src/compiler/parser-decl-symbtype.bas
@@ -186,7 +186,7 @@ function cTypeOf _
'' (note: can't check periods here, because it could be a namespace resolution, or '*' because it could be STRING * n)
is_type = FALSE
else
- is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE )
+ is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_ALLOWID )
end if
'' is it a normal type?
@@ -227,10 +227,11 @@ function cTypeOf _
dim as integer derefs = 0
dim as ASTNODE ptr walk = expr
dim as FBSYMBOL ptr sym = astGetSymbol( expr )
+
if( sym = NULL ) then
dtype = astGetFullType( expr )
subtype = astGetSubtype( expr )
- lgt = symbCalcLen( dtype, subtype )
+ lgt = symbCalcLen( dtype, subtype )
else
while( walk <> NULL )
select case as const astGetClass( walk )
@@ -492,6 +493,31 @@ function cSymbolType _
lgt = symbGetLen( sym )
ptr_cnt += typeGetPtrCnt( dtype )
exit do, do
+
+ case else
+
+ '' Certain special cases will allow IDs, and that's all we'll get back from
+ '' cIdentifier() in the case of a namespaced var; we have to use it now.
+ if ( FB_SYMBTYPEOPT_ALLOWID AND options ) then
+
+ '' This symbol's hash table a namespace,
+ if( FB_SYMBCLASS_NAMESPACE = symbGetClass( symbGetParent( sym ) ) ) then
+
+ '' but not the top-level namespace?
+ if( symbGetParent( sym )->symtb ) then
+
+ '' Eat the symbol.
+ lexSkipToken()
+
+ dtype = symbGetType( sym )
+ subtype = symbGetSubtype( sym )
+ lgt = symbGetLen( sym )
+
+ exit do, do
+ end if
+ end if
+ end if
+
end select
sym = sym->hash.next
diff --git a/FreeBASIC/src/compiler/parser-quirk-math.bas b/FreeBASIC/src/compiler/parser-quirk-math.bas
index 727c7f2..9389a42 100644
--- a/FreeBASIC/src/compiler/parser-quirk-math.bas
+++ b/FreeBASIC/src/compiler/parser-quirk-math.bas
@@ -120,10 +120,10 @@ private function hLenSizeof _
is_type = FALSE
else
'' SIZEOF()
- is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE )
+ is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_ALLOWID )
end if
else
- is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE )
+ is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_ALLOWID )
end if
''
The second approach I tried, which seemed to get a lot closer was allowing an expression parse in cSymbolType, but the problem is that it failed on len(TYPE_NAME). It only works on expressions. Again, maybe someone can fill in the parts I'm missing, but I think this may have other problems due to quirks in LEN. Patch:
Code: Select all
diff --git a/FreeBASIC/src/compiler/ast.bas b/FreeBASIC/src/compiler/ast.bas
index 3b8a616..59db4fd 100644
--- a/FreeBASIC/src/compiler/ast.bas
+++ b/FreeBASIC/src/compiler/ast.bas
@@ -1259,3 +1259,30 @@ function astLoad _
end function
+sub astTypeInfo _
+ ( _
+ byval expr as ASTNODE ptr, _
+ byref dtype as integer, _
+ byref subtype as FBSYMBOL ptr, _
+ byref lgt as integer, _
+ byref ptr_cnt as integer _
+ )
+
+ '' Extract the type information out of the expression.
+ dtype = astGetFullType( expr )
+ subtype = astGetSubType( expr )
+
+ '' Get the length from the expression.
+ dim as FBSYMBOL ptr sym = astGetSymbol( expr )
+ if( subtype ) then
+ lgt = symbGetLen( subtype )
+ elseif( sym ) then
+ lgt = symbGetLen( sym )
+ else
+ lgt = symbGetDataSize( dtype )
+ end if
+
+ '' Pointer nesting.
+ ptr_cnt += typeGetPtrCnt( dtype )
+
+end sub
diff --git a/FreeBASIC/src/compiler/inc/ast.bi b/FreeBASIC/src/compiler/inc/ast.bi
index b62a9bc..db86a33 100644
--- a/FreeBASIC/src/compiler/inc/ast.bi
+++ b/FreeBASIC/src/compiler/inc/ast.bi
@@ -860,6 +860,15 @@ declare function astLoad _
byval n as ASTNODE ptr _
) as IRVREG ptr
+declare sub astTypeInfo _
+ ( _
+ byval expr as ASTNODE ptr, _
+ byref dtype as integer, _
+ byref subtype as FBSYMBOL ptr, _
+ byref lgt as integer, _
+ byref ptr_cnt as integer _
+ )
+
declare function astOptimizeTree _
( _
byval n as ASTNODE ptr _
diff --git a/FreeBASIC/src/compiler/inc/parser.bi b/FreeBASIC/src/compiler/inc/parser.bi
index 43e8c1b..3b1cecf 100644
--- a/FreeBASIC/src/compiler/inc/parser.bi
+++ b/FreeBASIC/src/compiler/inc/parser.bi
@@ -215,6 +215,7 @@ enum FB_SYMBTYPEOPT
FB_SYMBTYPEOPT_CHECKSTRPTR = &h00000001
FB_SYMBTYPEOPT_ALLOWFORWARD = &h00000002
+ FB_SYMBTYPEOPT_EXPRCHECK = &h00000004
FB_SYMBTYPEOPT_DEFAULT = FB_SYMBTYPEOPT_CHECKSTRPTR
end enum
diff --git a/FreeBASIC/src/compiler/parser-decl-symbtype.bas b/FreeBASIC/src/compiler/parser-decl-symbtype.bas
index e08a134..80765d0 100644
--- a/FreeBASIC/src/compiler/parser-decl-symbtype.bas
+++ b/FreeBASIC/src/compiler/parser-decl-symbtype.bas
@@ -186,7 +186,7 @@ function cTypeOf _
'' (note: can't check periods here, because it could be a namespace resolution, or '*' because it could be STRING * n)
is_type = FALSE
else
- is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE )
+ is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_EXPRCHECK )
end if
'' is it a normal type?
@@ -230,7 +230,7 @@ function cTypeOf _
if( sym = NULL ) then
dtype = astGetFullType( expr )
subtype = astGetSubtype( expr )
- lgt = symbCalcLen( dtype, subtype )
+ lgt = symbCalcLen( dtype, subtype )
else
while( walk <> NULL )
select case as const astGetClass( walk )
@@ -456,9 +456,34 @@ function cSymbolType _
check_id = (lexGetLookAhead( 1, LEXCHECK_NOPERIOD ) = CHAR_DOT)
end if
end if
+
+ if( options and FB_SYMBTYPEOPT_EXPRCHECK ) then
+
+ '' Watch out for non-idx array expressions...
+ dim as integer check_array = fbGetCheckArray( )
+ fbSetCheckArray( FALSE )
+
+ dim as ASTNODE ptr expr = cExpression( )
+
+ '' Restore previous array checking status.
+ fbSetCheckArray( check_array )
+
+ '' ugly hack to deal with arrays w/o indexes
+ if( astIsNIDXARRAY( expr ) ) then
+ dim as ASTNODE ptr temp_node = expr
+ expr = astGetLeft( expr )
+ astDelNode( temp_node )
+ end if
- if( check_id = TRUE ) then
+ '' Get the type information from the expression.
+ astTypeInfo( expr, dtype, subtype, lgt, ptr_cnt )
+
+ '' Delete the expression.
+ astDelTree( expr )
+
+ elseif( check_id = TRUE ) then
chain_ = cIdentifier( base_parent, id_options )
+
end if
if( chain_ = NULL ) then
@@ -492,6 +517,7 @@ function cSymbolType _
lgt = symbGetLen( sym )
ptr_cnt += typeGetPtrCnt( dtype )
exit do, do
+
end select
sym = sym->hash.next
diff --git a/FreeBASIC/src/compiler/parser-quirk-math.bas b/FreeBASIC/src/compiler/parser-quirk-math.bas
index 727c7f2..16a9a81 100644
--- a/FreeBASIC/src/compiler/parser-quirk-math.bas
+++ b/FreeBASIC/src/compiler/parser-quirk-math.bas
@@ -120,10 +120,10 @@ private function hLenSizeof _
is_type = FALSE
else
'' SIZEOF()
- is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE )
+ is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_EXPRCHECK )
end if
else
- is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE )
+ is_type = cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_EXPRCHECK )
end if
''