• Welcome to PlanetSquires Forums.
 

FreeBASIC's equivalent to PowerBASIC's DIM AT syntax

Started by Paul Squires, February 12, 2017, 11:31:00 AM

Previous topic - Next topic

Paul Squires

I stumbled across this post today that discusses FB's for NEW (Placement) syntax. It appears to be essentially PB's DIM AT.
http://freebasic.net/forum/viewtopic.php?f=3&t=25429#p229070

I didn't think FB had an equivalent to DIM AT.... looks like I was wrong. I used DIM AT a fair bit on some programs so this is a welcomed find.

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Patrice Terrier

Paul--

DIM AT is easy to duplicate with a simple call to the low API RtlMoveMemory or RtlCopyMemory.

...

Pierre Bellisle

How about using a simple pointer...

Pierre


Type SomeType
  dw As DWORD
  w  As WORD
  d  As Double
End Type

Dim SomeTypeArray(0 TO 49) As SomeType
SomeTypeArray(33).w = 123

Dim As SomeType Pointer pSomeTypeArray = VarPtr(SomeTypeArray(0))
Print pSomeTypeArray[33].w 'Will show 123


Pierre Bellisle

Hey,

Here is a "maybe" more explicit example of what I mean.

If you feel like it, Paul and Patrice, could you give a short code example that demonstrate what you are referring to.

Pierre



#define CompilerExe "<D:\Free\64\fbc.exe>"
#define CompilerCmd "<-s console "D:\Free\bas\~~Default.rc">"

#Lang "fb"
#Define Unicode
#Include Once "Windows.bi"

Dim As String sDoubleWord = MKL(123) & MKL(234) & MKL(345) & MKL(456) & MKL(567) & MKL(789) & MKL(0)

Dim AS DWord Pointer pDoubleWord = Cast(Any Pointer, StrPtr(sDoubleWord))

Print "pDoubleWord[2] = " & pDoubleWord[2] 'Will show 345

Print : Print "Press a key or click to end"
Dim buttons As Long : Do : GetMouse(0, 0, 0, Buttons) : IF buttons Or Len(InKey) Then Exit Do : End If : Sleep 50 : Loop

Paul Squires

hmmm.... now that I've played with it for a bit, I can see that FB's ability to use dynamic arrays within TYPE structures is pretty powerful. The use of NEW basically simulates the dynamic array functionality only just in a slightly different way. Both call the newly allocated TYPE's constructors and destructors which is pretty powerful.



''
''
type EMPLOYEE
   EmpName    as string
   EmpAddress as STRING
   EmpSalary  as double
   declare constructor
   declare destructor
END TYPE

constructor EMPLOYEE
   print "Initialize EMPLOYEE type"
end constructor
DEStructor EMPLOYEE
   print "Destroy EMPLOYEE type"
end DEStructor


''
''
type APPLICATION
   pEmp as EMPLOYEE ptr
   declare constructor
   declare destructor
end type

constructor APPLICATION
   print "Initialize APPLICATION type"
   this.pEmp = new EMPLOYEE[10]
   with this.pEmp[1]
      .EmpName    = "Paul"
      .EmpAddress = "Canada"
      .EmpSalary  = 1000.00
   end with
end constructor
DEStructor APPLICATION
   print "Destroy APPLICATION type"
   delete[] this.pEmp
end DEStructor

''
''  MAIN
dim shared gApp as APPLICATION

for i as long = 0 to 9
   print i, gApp.pEmp[i].EmpName, gApp.pEmp[i].EmpAddress, gApp.pEmp[i].EmpSalary
NEXT
 

print "Done. Press any key."
sleep

' gApp's destructor will be called here as the global goes out of scope



Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Just using a plain CALLOCATE with a typed pointer results in the constructors and destructors NOT being called.




''
''
type EMPLOYEE
   EmpName    as string
   EmpAddress as STRING
   EmpSalary  as double
   declare constructor
   declare destructor
END TYPE

constructor EMPLOYEE
   print "Initialize EMPLOYEE type"
end constructor
DEStructor EMPLOYEE
   print "Destroy EMPLOYEE type"
end DEStructor



''
''  MAIN

dim pEmp as EMPLOYEE Ptr = CALLOCATE(10, len(EMPLOYEE))

with pEmp[1]
   .EmpName = "Paul"
   .EmpAddress = "Canada"
   .EmpSalary = 1000.00
end with   

for i as long = 0 to 9
   print i, pEmp[i].EmpName, pEmp[i].EmpAddress, pEmp[i].EmpSalary
NEXT
 
DEALLOCATE pEmp

print "Done. Press any key."
sleep

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

...and lastly, here is the straight forward dynamic ARRAY version. As you can see, constructors and destructors do get called.



''
''
type EMPLOYEE
   EmpName    as string
   EmpAddress as STRING
   EmpSalary  as double
   declare constructor
   declare destructor
END TYPE

constructor EMPLOYEE
   print "Initialize EMPLOYEE type"
end constructor
DEStructor EMPLOYEE
   print "Destroy EMPLOYEE type"
end DEStructor


''
''
type APPLICATION
   arrEmp(any) as EMPLOYEE
   declare constructor
   declare destructor
end type

constructor APPLICATION
   print "Initialize APPLICATION type"
   REDIM this.arrEmp(10)
   with this.arrEmp(1)
      .EmpName    = "Paul"
      .EmpAddress = "Canada"
      .EmpSalary  = 1000.00
   end with
end constructor
DEStructor APPLICATION
   print "Destroy APPLICATION type"
end DEStructor

''
''  MAIN
dim shared gApp as APPLICATION

for i as long = 0 to 9
   print i, gApp.arrEmp(i).EmpName, gApp.arrEmp(i).EmpAddress, gApp.arrEmp(i).EmpSalary
NEXT
 

print "Done. Press any key."
sleep

' gApp's destructor will be called here as the global goes out of scope



Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

This is probably closer to DIM AT. Pretty simple really given FB's ability to use ANY PTR and then convert it to a typed pointer.
I use array indexing in my code because I find it easier to visualize then incrementing memory addresses.



''
''
type EMPLOYEE
   EmpName    as string
   EmpAddress as STRING
   EmpSalary  as double
END TYPE

''
''  MAIN

dim pMem as any ptr = CALLOCATE(1024)

dim pEmp as EMPLOYEE Ptr = CPtr(EMPLOYEE Ptr, pMem)


with pEmp[1]
   .EmpName    = "Paul"
   .EmpAddress = "Canada"
   .EmpSalary  = 1000.00
end with

for i as long = 0 to 9
   print i, pEmp[i].EmpName, pEmp[i].EmpAddress, pEmp[i].EmpSalary
NEXT
 
DEALLOCATE pMem

print "Done. Press any key."
sleep




Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Pierre Bellisle

Agreed, looks pretty powerful...

Good stuff to read and learn.

Many thanks for those examples Paul.

Pierre

Patrice Terrier


Paul Squires

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Pierre Bellisle

Also what I think, they borrowed a lot from C++, and did a great job at it, I like...  :-)

José Roca

As long as they don't borrow the semi-colons and curly braces... :)

Paul Squires

Well, I totally got the DIM AT syntax a little wrong. Here is how it relates most closely to the PB DIM AT functionality.

The New (placement) operator allows to construct object(s) (no allocate memory) at an existing memory location:
New(address) datatype[ count ]


TYPE EMPLOYEE
   empName    AS STRING
   empAddress AS STRING
   empSalary  AS DOUBLE
END TYPE


' Create a generic block of memory
dim pMem as any ptr = CALLOCATE( 1024)

' Here is the DIM AT syntax. Notice the NEW(pMem) part.
' Basically 10 new employee TYPE's are overlaid on the
' existing pMem area.
DIM pEmp AS EMPLOYEE Ptr = NEW(pMem) EMPLOYEE[10]

' Assign data to our employee
pEmp->empName = "Paul"
pEmp->empAddress = "Canada"
pEmp->empSalary = 1000.00

' Deallocate our memory
DEALLOCATE(pMem)



Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Pierre Bellisle

#14
I got to read about this "New" (placement) operator...
I the mean time, what advantage do you see over the following...


#Include Once "string.bi" 'For format

TYPE Employee
  FirstName AS STRING
  Country   AS STRING
  Salary    AS DOUBLE
END TYPE

Dim pEmployeeArray As Employee Pointer = cAllocate(2048) 'Allocate memory

pEmployeeArray[0].FirstName = "Paul"
pEmployeeArray[0].Country   = "Canada"
pEmployeeArray[0].Salary    = 10000.00

pEmployeeArray[1].FirstName = "Jos" & CHR(130)
pEmployeeArray[1].Country   = "Spain"
pEmployeeArray[1].Salary    = 10000.00

Print "> " & pEmployeeArray[0].FirstName
Print "> " & pEmployeeArray[0].Country
Print "> " & Format(pEmployeeArray[0].Salary, "0,")
Print
Print "> " & pEmployeeArray[1].FirstName
Print "> " & pEmployeeArray[1].Country
Print "> " & Format(pEmployeeArray[1].Salary, "0,")

Deallocate(pEmployeeArray) 'Deallocate memory

Sleep