simple parser bug?

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

simple parser bug?

Postby Mysoft » Jul 11, 2011 4:37

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: 5793
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Jul 12, 2011 8:32

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: 3156
Joined: Jul 28, 2005 14:45
Location: Germany

Postby dkl » Jul 12, 2011 15:34

Mysoft
Posts: 748
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Postby Mysoft » Jul 13, 2011 2:47

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: 3156
Joined: Jul 28, 2005 14:45
Location: Germany

Postby dkl » Jul 13, 2011 7:26

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: 748
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Postby Mysoft » Jul 13, 2011 19:40

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: 5793
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Jul 13, 2011 21:10

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: 748
Joined: Jul 28, 2005 13:56
Location: Brazil, Santa Catarina, Indaial (ouch!)
Contact:

Postby Mysoft » Jul 13, 2011 23:34

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: 5793
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Jul 14, 2011 9:32

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: 5317
Joined: May 27, 2005 6:42
Location: Illinois
Contact:

Postby cha0s » Jul 16, 2011 0:46

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

Postby agamemnus » Jul 16, 2011 2:33

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

Postby cha0s » Jul 25, 2011 3:22

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
Posts: 7274
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: simple parser bug?

Postby fxm » Sep 23, 2017 9:17

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: 3156
Joined: Jul 28, 2005 14:45
Location: Germany

Re: simple parser bug?

Postby dkl » Sep 24, 2017 16:33

fxm
Posts: 7274
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: simple parser bug?

Postby fxm » Sep 24, 2017 17:00

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

Return to “General”

Who is online

Users browsing this forum: No registered users and 3 guests