Announcement

Collapse
No announcement yet.

PB9 Problems

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #41
    The Array was not Dimensioned ptII

    From Programming Reference:
    "You must DIM all arrays before you can use them. This is a different approach then that used by some BASIC dialects, which assume that an array contains 10 elements (0 to 9) if the array is not explicitly dimensioned."

    The foregoing suggests that an array must be explicitly dimensioned before you can use it.

    I ran a couple of tests and found:
    1. When an array is declared locally, it must be explicitly dimensioned or redimensioned in the sub or function where it is declared.

    2. When an array is declared globally, it may be dimensioned or re-dimensioned within any sub or function that references it.

    Comment


    • #42
      A program can't compile if there is no "DIM/REDIM" or "[scope] ARRAYNAME() AS datatype" physically preceding the use of the array in an executable statement.

      At least it was like that in 8x. I am not testing 9x for this because the style I use now still works in 9x. If it ain't broke I ain't fixin' it.

      I always use [SCOPE] Arrayname() AS DATATYPE

      If the program won't compile on an 'array not dimensioned' error, I move some stuff around OR just add a REDIM arrayname(0) statement early, since I always REDIM to the correct size before I use an array "for real" anyway.

      MCM
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #43
        Walt,

        Gosta's post and sample illustrated to me the point you are trying to make. Stepping through his sample in the debugger surprised me. I expected at least an error, because the array wasn't explicitly dimensioned and/or initialized before the REDIM PRESERVE. It didn't produce the error and the array bounds were correct. Out of curiosity, I compiled the code under PB/DLL 6.11 and 7.04 and stepped through it in their debuggers. The results were identical to what I saw in PB/WIN 9.0. Removing the comment from the offending call likewise produced the expected compiler error. I included the output from the log files below.

        Because of this, I am convinced the compiler is behaving it has always done. I don't feel this is a PB/WIN 9 issue, but rather an opportunity for you to make a feature request.

        Scott

        Code:
        'PowerBasic DLL/32 Compiler
        
        'PB/DLL  Version 6.11
        
        'Copyright (c) 1996-2002 PowerBasic Inc.
        
        'Carmel, California, USA
        
        'All Rights Reserved
        
        
        
        'Error 461 in C:\Documents and Settings\Administrator\Desktop\gostawaltd_array.bas(22:21):  Array not dimensioned
        
        'Line 22:      B$ = B$ + STR$(A(I) + ", "     '<--- "Array not dimensioned" compiler  _
        
        
        
        'PowerBASIC Compiler for Windows
        
        'PB/Win  Version 7.04
        
        'Copyright (c) 1996-2004 PowerBasic Inc.
        
        'Venice, Florida USA
        
        'All Rights Reserved
        
        
        
        'Error 461 in C:\DOCUME~1\ADMINI~1\Desktop\gostawaltd_array.bas(31:21):  Array not dimensioned
        
        'Line 31:      B$ = B$ + STR$(A(I) + ", "     '<--- "Array not dimensioned" compiler  _
        
        
        
        
        
        #Compile Exe
        
        DefLng A - z
        
        
        
        Sub A_Sub(B(), Ubnd)
        
            For I = 1 To 10
        
               ReDim Preserve B(1 To I)
        
                  B(I) = I
        
            Next I
        
             MsgBox "Ubound B() =" & Str$(UBound(b())),,FuncName$
        
             Cnt = 10
        
        End Sub
        
        
        
        Function PBMain()
        
            Static A() As Long
        
        Local B As String
        
        
        
        Call A_Sub(A(), Cnt)
        
        ' ? "Cnt = " & Str$(cnt),,FuncName$
        
         MsgBox "Ubound A() =" & Str$(UBound(A())),,FuncName$
        
            For I = 1 To 10 'Cnt
        
               B$ = B$ + Str$(A(I) + ", "     '<--- "Array not dimensioned" compiler ERROR here
        
            Next I                                    ' yet the array is dimensioned
        
            MsgBox "i = " & Str$(i),,FuncName$
        
            MsgBox B$
        
        End Function
        Last edited by Scott Hauser; 17 Dec 2008, 08:27 PM.
        The most exasperating part of the "rat race" is how often the rats are in the lead!

        Comment


        • #44
          Here's one other point:

          If one declares a global/local/static array in one procedure, pass it to another procedure for dimensioning and initializing, then pass it to a third procedure for processing, error 461 "array not dimensioned" does not occur.

          For example, and this is not compilable:

          Proc 1:
          Code:
          GLOBAL A() AS LONG
          
          PROC_1
          
          CALL PROC_2(A(), Cnt)
          
          CALL PROC_3(A(), Cnt)
          
          END PROC_1
          Proc 2:
          Code:
          PROC_2(B(), Ubnd)
          
          SomeNumber = 10
          
          DIM B(1 TO SomeNumber
          
          FOR I = 1 to SomeNumber
            B(I) = I
          NEXT I
          
          END PROC_2
          Proc 3:
          Code:
          PROC_3(C(), Ubnd)
          
          FOR I = 1 TO Ubnd
            PRINT C(I)
          NEXT I
          END PROC_3
          The above pseudo-code illustrates that the global array is dimensioned and is populated. However, if one tries to do anything with it in proc 1 compiler error 461 "array not dimensioned" will appear.
          Walt Decker

          Comment


          • #45
            Mr Zale posted here once that you can only get the compile-time "array not dimensioned" error if, given the current source code, there is absolutely no chance that array is the object of a DIM or REDIM statement SOMEWHERE in that module.

            I don't agree with the philosophy which issues this compile-time error, but as I said, I was not in the room when the decision was made.
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #46
              PowerBASIC recommends that you dimension arrays in the same procedure that they are referenced. This is how it has been done since the first PowerBASIC Compiler. If you have a better idea, please send an explicit description of your desires to support. Thank you.
              Sincerely,

              Steve Rossell
              PowerBASIC Staff

              Comment


              • #47
                I still think there is confusion about how the the DIM keyword works with arrays.

                AFAIK DIM is the only statement which is BOTH a compiler directive AND an executable statement, except when it is ignored completely because a DIM already appeared in the procedure.

                Just don't DIM. Instead use a scope and type definition...
                Code:
                GLOBAL    A() AS SOMETHING   ' scope outside all procedures for GLOBAL
                FUNCTION Foo
                    LOCAL|STATIC   X() AS anything     ' scope in procedure for LOCAL or STATIC
                ...
                And to actually allocate elements, use REDIM.

                This has kept me out of trouble, like, forever.

                MCM
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #48
                  Yes, pretty sure this is a PB9 bug -Especially with classes

                  This is a bug. Walt's code is not using objects, so maybe I'll give an object based example...

                  I'm also having this same issue, and for me it's severe enough that I will have to use a different compiler if not fixed. Here's the gist of what's going on...

                  'A stripped down version of my class, for this example's sake:

                  Code:
                  CLASS CallManagerClass 
                       INSTANCE CallTime()         AS DWORD                  
                  
                       CLASS METHOD CREATE()
                            'This is where these arrays should be dimmed...
                            'They should not need to be dimmed/redimmed in every individual
                            'method that uses them - would destroy performance!
                            DIM CallTime( %MAX_CALL_IDS ) AS DWORD
                            DIM CallInfos( %MAX_CALL_IDS ) AS OUTGOINGCALLINFO
                       END METHOD
                  
                       INTERFACE CallStatusManagerObj
                            INHERIT IUNKNOWN            
                  
                            METHOD GetCallID(BYVAL AnArg AS DWORD) AS DWORD
                                 'Arrays were ALREADY FOR SURE dimmed in constructor
                  
                                 CallTime(SomeIndex)  = AnArg  'compiler error - not dimensioned!   
                  
                            END METHOD
                  
                       END INTERFACE
                  END CLASS

                  Again, the above code is stripped down, but in essence, the help file indicates that an instance variable that is an array should be declared at the class level with empty parens, as I did here, then dimensioned, which I'm doing in the constructor, which would be the ONLY possible or reasonable place to do it (doing it in each method would be silly, and horribly anti-performant, as it would require a redim preserve in every method to keep from destroying the data in the array). In this circumstance, the only proper place for dimensioning it would be in the constructor, which would ensure it is dimensioned before use by the methods. The attempted access to the array element in the GetCallID method above could be assured that it would never encounter an undimensioned array, and therefore shouldn't cause the compiler error in question.

                  The help simply states:
                  To declare an array as an instance variable, use an empty set of parentheses in the variable list: You can then use the DIM statement to dimension the array.
                  That's exacly what's being done, and it causes a compiler error. Any other way of coding it would make no sense. I can't be expected to try a redim preserve in every method that wants to read these class-level variables, can I? I'm firmly of the opinion that this is a compiler error. Maybe it's missing the check to see if the constructor is initializing/dimensioning the array.

                  Comment


                  • #49
                    I haven't read this whole thread but I expect the following is the proper declaration:
                    Code:
                    DIM CallTime( %MAX_CALL_IDS ) AS INSTANCE DWORD
                    DIM CallInfos( %MAX_CALL_IDS ) AS INSTANCE OUTGOINGCALLINFO
                    Paul Squires
                    FireFly Visual Designer (for PowerBASIC Windows 10+)
                    Version 3 now available.
                    http://www.planetsquires.com

                    Comment


                    • #50
                      Try REDIM instead of DIM as in
                      Code:
                      CLASS CallManagerClass 
                           INSTANCE CallTime()         AS DWORD                  
                      
                           CLASS METHOD CREATE()
                                'This is where these arrays should be dimmed...
                                'They should not need to be dimmed/redimmed in every individual
                                'method that uses them - would destroy performance!
                                [COLOR="Red"]RE[/COLOR]DIM CallTime( %MAX_CALL_IDS )  [COLOR="Red"] ' NO 'AS TYPE' here [/COLOR]
                                [COLOR="Red"]RE[/COLOR]DIM CallInfos( %MAX_CALL_IDS ) AS OUTGOINGCALLINFO [COLOR="Red"]' See note[/COLOR]
                      That works with regular procedures when you use the...
                      Code:
                         scope   ArrayName() AS datatype
                      ...syntax.

                      I don't see a scope for "CallInfos()" but I think it needs one somewhere; however, the REDIM syntax does not support a "scope" clause so I don't know where it has to go. Upon further review, I can't tell what the scope is supposed to be from your code.

                      MCM
                      Last edited by Michael Mattias; 26 Jul 2009, 10:04 AM.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #51
                        I posted an example program in the Programming with Objects forum the other day that uses instance variable arrays and it works just fine. My post can be found here.

                        Perhaps the compiler is getting confused by you specifying the data type in both the INSTANCE declaration and in the DIM in your constructor method? In my example, I use:
                        Code:
                        INSTANCE sName() AS STRING
                        and in the constructor I use:
                        Code:
                        DIM sName(0)
                        and it the my addRecord method I use:
                        Code:
                        REDIM PRESERVE sName(dNumRecords)
                        and it all works fine.
                        Jeff Blakeney

                        Comment


                        • #52
                          Originally posted by Paul Johnson View Post
                          This is a bug...
                          This is a bug in the code in your CREATE method. When you dimension an array without an explicit scope, it defaults to LOCAL scope. So, you actually created two local arrays in that method. As Paul mentioned, the correct syntax would be to DIM xxx(numrexpr) AS INSTANCE datatype. Using REDIM won't correct this coding error.

                          Best regards,

                          Bob Zale
                          PowerBASIC Inc.

                          Comment


                          • #53
                            Originally posted by Bob Zale View Post
                            When you dimension an array without an explicit scope, it defaults to LOCAL scope.
                            This is why I never use DIM to set the data type or scope of a variable. I only use DIM to set the dimensions of an array and always use the GLOBAL, STATIC, LOCAL, THREADED and INSTANCE statements to set the scope of my variables.
                            Jeff Blakeney

                            Comment


                            • #54
                              Thanks

                              This is a bug in the code in your CREATE method. When you dimension an array without an explicit scope, it defaults to LOCAL scope. So, you actually created two local arrays in that method. As Paul mentioned, the correct syntax would be to DIM xxx(numrexpr) AS INSTANCE datatype. Using REDIM won't correct this coding error.
                              Thanks Bob! You saved me a bunch of trouble. The redim is what I tried first, which didn't work, so I had switched to dim. The problem was in the CREATE method where I needed to specify AS INSTANCE datatype in my dim/redim statement. I had left the 'INSTANCE' out of the dim statement. I was under the impression that it would get the scope from the declaration. Adding INSTANCE between the AS and the datatype in the dim/redim seems to allow the code to compile.

                              In the help file, for regular scalar (non-array) variables, it says that:

                              When a DIM statement is used (without an explicit scope clause), to declare a variable in a procedure, and an identical variable has already been declared as GLOBAL, the variable in the procedure will be given GLOBAL scope. For example:
                              So I kind of assumed this would hold true for arrays, but I should have looked at the array portion of the help file that says:

                              It is recommended that an explicit variable scope clause (GLOBAL/LOCAL/STATIC) be added to each DIM statement that uses an explicit type clause.
                              I would suggest that maybe the help file could use just a tweek on this topic (the Dim statement), and/or an example to clarify this syntax and how to use it properly.

                              Comment


                              • #55
                                Another question

                                Also, another note:

                                Removing the "AS datatype" and changing the dims to redims in the create seems to work as well. Is it the "AS datatype" on the dim in the CREATE method what is causing it to consider this a new array, rather than the one dimensioned at the class level?

                                Comment

                                Working...
                                X