simple parser bug?

General FreeBASIC programming questions.
Mysoft
Posts: 836
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

simple parser bug?

Post by Mysoft »

Code: Select all

namespace ns
  dim as integer Var1
end namespace
dim as typeof((ns.Var1)) Works
dim as typeof(ns.Var1) DoesntWork
the code explains everything....

typeof() with a namespaced variable isnt working.... unless you use extra parenthesis.... i think since the workaround is easy i can be ok, but, so suppose to be a bug right?
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

Not sure if there'll be a simple fix, it's complicated by the fact that typeof accepts types as well as expressions. It parses for types first, but I think the first parse swallows the 'namespace.' bit, and I'm not sure if we're capable of rewinding.
I'd suggest filing a bug report, and hopefully we'll look into it sometime. It's a bit frustrating that we're finding more bugs than we're fixing atm, but it's better to keep a record of them anyway.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Post by dkl »

I think it's the same with sizeof()/len(), see here: http://sourceforge.net/tracker/index.ph ... tid=693196
Mysoft
Posts: 836
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Post by Mysoft »

hum...... ok. but why it does work with extra parenthesis? and what would block it from think that there's parenthesis there everytime...
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Post by dkl »

I suppose parentheses aren't allowed in types, so in that case the type parsing stops and doesn't swallow the namespace, and the expression parsing can work correctly.
Mysoft
Posts: 836
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Post by Mysoft »

Code: Select all

type MyType
  X as integer
  Y as short
  Z as single
end type

dim MT as MyType

namespace MyNS
 dim XX as double
 dim Z as MyType
end namespace

'dim as typeof(MyType.Y) V0 (illegal?)
dim as typeof((MT.Y)) V1
dim as typeof((MyNS.XX)) V2
dim as typeof((MyNS.Z)) V3
dim as typeof((MT)) V4

print sizeof(V1)=2
print sizeof(V2)=8
print sizeof(V3)=12
print sizeof(V4)=12
hum.... well so getting the typeof() from a type doesnt work anyway, then under such circunstances everything that i can think of worked between ()
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

I don't think Typename.elementname should really parse anyway. It's not an identifier for a type, and it's not a variable either if the type's not instantiated. I guess it has a type attached to it, but I think it would be a special case for things like typeof/sizeof.
(Given the current complications involved in type/expression disambiguating, this may not happen soon.)
Mysoft
Posts: 836
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Post by Mysoft »

yeah i think so.... but all other issues (all that i could think at least) , get resolved using (), so the compiler already know the solution...
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

Why would the compiler know how to parse typename.elementname? Getting the type of it is the only case that it makes sense. For static vars the typename could be viewed as a namespace, but I don't think FB even supports static vars in types so it's moot at this stage.
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

Hmm, looks fun. ^^ I'll give it a shot and see if I can come up with anything.
agamemnus
Posts: 1842
Joined: Jun 02, 2005 4:48

Post by agamemnus »

=D
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

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
 
 	''
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: simple parser bug?

Post by fxm »

Weird parsing!
The last code line works without any separator (without ":", neither even " "):
(working only with two methods called on any instance)

Code: Select all

Type UDT
  Declare Sub s ()
  Dim As Integer I
End Type
Sub UDT.s ()
  Print I
End Sub

Dim As UDT u1 = (1), u2 = (2)
u1.s()u2.s()
By cons, "u1.s()u2.s()u3.s()" or even "u1.s() u2.s() u3.s()" does not work.
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: simple parser bug?

Post by dkl »

fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: simple parser bug?

Post by fxm »

Thanks for the return (I had not memorized this bug report).
Post Reply