Announcement

Collapse
No announcement yet.

PB9 Problems

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

  • Paul Johnson
    replied
    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?

    Leave a comment:


  • Paul Johnson
    replied
    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.

    Leave a comment:


  • Jeff Blakeney
    replied
    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.

    Leave a comment:


  • Bob Zale
    replied
    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.

    Leave a comment:


  • Jeff Blakeney
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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.

    Leave a comment:


  • Paul Squires
    replied
    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

    Leave a comment:


  • Paul Johnson
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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

    Leave a comment:


  • Steve Rossell
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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.

    Leave a comment:


  • Walt Decker
    replied
    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.

    Leave a comment:


  • Scott Hauser
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    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

    Leave a comment:


  • Walt Thompson
    replied
    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.

    Leave a comment:


  • Michael Mattias
    replied
    1. A local array should not produce the compile error "array not dimensioned" regardless of where it is dimensioned and/or initialized.

    2. A global array should not produce the compile error "array not dimensioned" regardless of where it is dimensioned and/or initialized.
    I agree. Any "not dimensioned" errors should occur only at runtime.

    But they do.
    I was not in the room when the design decision was made.

    MCM

    Leave a comment:


  • Kev Peel
    replied
    Walt,

    I understand. In that situation, I tend to use a counter and return it as a separate parameter or as the actual function return value. I don't rely on the UBOUND of an array as it could be ambiguous if the array already contains data or such. I've just accepted that the additional DIM/REDIM is what is needed by the compiler, and the overhead is really negligible since the initial DIM is only required once for each array

    It is as it is, as they say

    Leave a comment:


  • Walt Decker
    replied
    Kev:


    I don't get it, how is adding one line of code (REDIM x(0)) troublesome? Using DIM/REDIM before the array is first used is what the compiler is expecting, nothing more and nothing less. I can't see the problem unless this behaviour has changed since older versions (PB/DOS, PB/DLL, etc) and broken a lot of code.
    The problem is: the array is DIMed, REDIMed, REDIM PRESERVEd before it is used. The compiler should recognize that. To do it again, unless one actually wants to change the size, adds a spurious statement that is not needed and reduces execution time. It can also produce confusion, especially in a large app, and, to get an "array not dimensioned" compile-time error when one knows that the array has been dimensioned, is frustrating.

    Another thing, assume that you "DIM A(1 TO 1)" in one procedure then pass A() to a procedure that opens a file and reads the contents into A(). Assume further that as the file is read it REDIM PRESERVEs "A()", but there is no data in the file. When the app returns to the procedure that DIMed it, "A()" will still have a size of 1, but with nothing in it. Figuring out what happened can be a real bugger.

    Leave a comment:


  • Walt Decker
    replied
    Walter:
    I believe the problem is due to the fact that the Fruit array was never dimensioned.
    Fruit$() is dimensioned in SUB A_Sub. It is passed to A_Sub in PBMAIN. If Fruit$() was not dimensioned then PRINT UBOUND(Fruit$) would not be the same as "Cnt". Since it is a global it should be usable in PBMAIN without a compiler error, but it is not.

    Leave a comment:


  • Walt Thompson
    replied
    The Array was not Dimensioned

    After making a couple of changes to allow your example to run under PB 9, I indeed got the "array not dimensioned" error.

    I believe the problem is due to the fact that the Fruit array was never dimensioned.

    Code:
    #COMPILE EXE
    DEFLNG A - Z
    
    GLOBAL Fruit() AS STRING
    
    FUNCTION PBMAIN()
    
    CALL A_Sub(Fruit$(), Cnt)
    
    PRINT UBOUND(Fruit$), Cnt
    
    'Adding:
    DIM Fruit$(1 to Cnt)
    'Solves the problem.
    
    FOR I = 1 TO Cnt
       PRINT Fruit$(I)           '<--- compiler error "array not dimensioned"
    NEXT I
    
    WAITKEY$
    END FUNCTION
    
    SUB A_SUB(B$(), Ubnd)
    
    DATA "APPLES", "ORANGES", "GRAPES", "PINEAPPLES", "PEARS", "PAPAYA", "MANGO", "LEMONS"
    
    Ubnd = DATACOUNT
    DIM B$(1 TO Ubnd)
    
    FOR I = 1 TO Ubnd
       B$(I) = READ$(I)
    NEXT I
    
    END SUB

    Leave a comment:

Working...
X