PDA

View Full Version : Static UDT not possible?



ReneMiner
26-03-2014, 09:02
Seems I ran into some limit again. Is not allowed to have static udt as subset of another udt?
only primitive variables (Long, String, Byte...) allowed?



' thinBasic 1.9.12.0

Uses "console"

Type t_RGB
R As Byte
G As Byte
B As Byte
End Type

Type t_myType
Static Backcolor As t_RGB ' not possible?
myCol As t_RGB ' <<< comment this line in second run to get a crash
End Type

Sub assign_shared()
Local a As t_myType

a.Backcolor.R = 64
a.Backcolor.G = 128
a.Backcolor.B = 192

End Sub

assign_shared

Dim Test As t_myType


PrintL "Test.R:" + Test.Backcolor.R
PrintL "Test.G:" + Test.Backcolor.G
PrintL "Test.B:" + Test.Backcolor.B

PrintL Repeat$(50,"-") + $CRLF
PrintL "Key to end"
WaitKey

Let run twice:
1. as is = wrong output
2.comment "myCol as t_RGB" in Type-definition to crash

ReneMiner
27-03-2014, 10:21
If not possible to use udt I simply invented a new primitive variable-type that I can use to bind anything anywhere.


- looks familiar probably though I used similar approach in a few examples already, but now I use a "Double-DWord" i.e. Quad to contain some handle to DATA and TYPE in ONE variable but uses a "Union-in-mind"-approach so my Alias Quad As Storage does not have any type-functions and can be attached to static members of UDT. I tested already - and works - but the example below does not contain any statics since I simplified a little using ByRef for better readability instead of a pointer - so this example is not working on UDT-subsets, but the approach itself does.

To have it work it needs currently constant user-made Stringpointers to the attached types-name.
To read out a string just having its pointer available is pretty simple. thinBasic offers great method Memory_Get:


String s = Memory_Get(sPtr, Peek(DWord, sPtr-4))

because
a) If have more than once to store the same strings (that never change) is mostly less memory needed when just storing the StrPtr of it.
b) a StrPtr is always 4 bytes in our world - no matter what string, so this allows something like:


' thinBasic 1.9.12.0

Uses "console"

' it's all about storing different subtypes to variables


Alias DWord As Heap
Alias DWord As ConstStrPtr

' it's in fact kind of a union
' but Union won't work with static subsets

Alias Quad As Storage ' = 2 * SizeOf(dword)

Type t_Storage
pData As HEAP
pType As ConstStrPtr
End Type

' union get's applied in untyped-functions

Function Storage_Create( ByRef hndl As Storage, _
ByVal datatype As ConstStrPtr, _
Optional ByVal sData As String _
) As Storage

' -- treat the Storage-hndl as t_Storage now:

Local Me As t_Storage At VarPtr(hndl)

' -- kill possible old data
If HEAP_Size(Me.pData) Then HEAP_Free(Me.pData)

' create data-pattern like datatype to obtain size
Local data Like Memory_Get(datatype, Peek(DWord, datatype-4))

If StrPtrLen(StrPtr(sData)) < SizeOf(data) Then
' fill optional passed data with zeros to fit the pattern
sData += Repeat$( SizeOf(data) - StrPtrLen(StrPtr(sData)), MKBYT$(0) )
EndIf

' store data to Heap and save heap-pointer + datatype to Me
Me.pData = HEAP_AllocByStr( sData )
Me.pType = datatype

' return hndl from it's position

Function = Peek( Storage, VarPtr(Me) )

End Function

Function Storage_Destroy(ByRef hndl As Storage) As Boolean

' -- treat the Storage-hndl as t_Storage now:
Local Me As t_Storage At VarPtr(hndl)

If HEAP_Size(Me.pData) Then
HEAP_Free(Me.pData)

Function = TRUE
EndIf

Me.pData = 0
Me.pType = 0

End Function

Function Storage_Delegate(ByRef hndl As Storage, ByVal sFunction As String) As Boolean

' pass a function-name to call at stored data

' -- treat the Storage-hndl as t_Storage now:
Local Me As t_Storage At VarPtr(hndl)

' -- treat the stored data like the stored type now:
Local data Like Memory_Get(Me.pType, Peek(DWord, Me.pType-4)) At Me.pData


' currently no other way nor parameters possible to call the function at data

Select Case Ucase$(sFunction)
Case "GETDATA"
Function = data.GetData
End Select

End Function

' --------------------------------------------------------------

' some different types to store

Type t_RGB
R As Byte
G As Byte
B As Byte
GetData As Function
End Type
$t_RGB = "t_RGB" : %t_RGB = StrPtr($t_RGB) As ConstStrPtr
Function t_RGB.GetData() As Boolean
If VarPtr(Me) Then
PrintL "R:" + Me.R
PrintL "G:" + Me.G
PrintL "B:" + Me.B
Function = TRUE
EndIf
End Function

Type t_Vec3d
X As Double
Y As Double
Z As Double
GetData As Function
End Type
$t_Vec3d = "t_Vec3d" : %t_vec3d = StrPtr($t_vec3d) As ConstStrPtr
Function t_Vec3d.getData() As Boolean
If VarPtr(Me) Then
PrintL "X:" + Me.X
PrintL "Y:" + Me.Y
PrintL "Z:" + Me.Z
Function = TRUE
EndIf
End Function
' --------------------------------------------------------------

Dim myArray(3) As Storage ' create simple quad-array to hold all data



Storage_Create( myArray(1), %t_RGB, MKBYT$(11,12,13) )
Storage_Create( myArray(2), %t_Vec3d, MKD$(1.11, 1.22, 1.33) )


Storage_Delegate(myArray(1), "GetData")
PrintL
Storage_Delegate(myArray(2), "GetData")


PrintL $CRLF + Repeat$(40,"-") + $CRLF + "key to end"

WaitKey


Good morning!

ReneMiner
27-03-2014, 13:08
seems to be some monologue...reminds me of the Heap_-unit once. Anyway, before trashing your minds with any more page-filling examples

- the result/the catch is currently that I have no way to call a function of an attached type in the reverse way as inheritage does:
if the function is not part of the "parenting type" it should get called from the attached type

- so that "delegate"-stuff should be done somehow like the way an extended type already works.

Since Heap is part of Core-engine already there's nothing against a variable-type - somewhat similar to string on user-side, concerning dynamics -
which could hold these 2 Dwords and have a few basic functionalities - for the interested audience I attached some example of these.

Petr Schreiber
27-03-2014, 19:59
I can confirm the static member crash :(

The HEAP way is really nice, I think it could serve as base for implementation of dynamic arrays in types - would be definitely useful to use them "natively".


Petr

ReneMiner
29-03-2014, 08:53
...it could serve as base for implementation of dynamic arrays in types...

yes it could be used to attach dynamic arrays too - but that's not the main-intention for me trying - it's not limited to sub-arrays of the same type.

I can use this to attach any variable of any available datatype (also arrays of these) to anything that has the ability to store a quad-variable.

That's why this ended up in this thread: even static members of udt can get a whole christmas-tree branched to it if desired....

Each "parent" of the same type can have a different "child-type" attached - (non-static of course then) - but all is accessable as long as we know the parent.
That's what currently already doable having the new LIKE-functionalities.

see also example here (http://www.thinbasic.com/community/showthread.php?12201-TypeOf-ideas&p=90889#post90889)
-imagine the circles and boxes being different GUI-controls or meshes all having different amount of bones, submeshes, vertex-types etc. that could be stored as members of the same parent-array, having a few type-specific and a few common functions such as ".Draw()"

There would be constrictions to store arrays of dynamic strings - but would be possible in the end too. Therefor one could attach a dictionary in Case ...() as String and put the keyptrs in an array to storage - or just some array of heap-pointers and store strings at and retrieve strings from heap using Heap_AllocByStr/Heap_Get.

If thinBasic would understand a function called at this special quad-type ("Storage") has to be called at a variable of the attached subtype and would bequeath the passed parameters to it, we could not just store anything here, but also use all functions of the attached subtype instantly - since "storage" has no own functions anyway -

Currently I'm not sure if it would be better to implement a TypeID-function which stores types-name on request and returns a pointer - or just to have use user-made ConstStrPtr's as above - or if probably a function could return the pointer to internal somewhere stored type-names.

Finally a type would decide which function gets called. Can you interpret the direction that goes?

Like-keyword, heap-memory + heap-functions, type-functions and absolute variables already offer anything else needed to go this way - now is just a small piece of bridge needed to close the gap and to have a magnificent highway
.:egg26:

ReneMiner
30-03-2014, 09:08
idea:
(see post above)
ability to call functions on "raw data" directly like this:

Syntax:



CallAt pData [As t_myType| Like "t_myType"], FunctionName ([PARAMETERS]) [To Result]


CallAt: call a type-function but data-position passed as pointer and not as variable-name

pData: pointer to current element ( =VarPtr(myVar) )

FunctionName: the name of a function as defined inside type-definition
Parameters: parameters as t_myType.FunctionName would expect

I think this could solve the current "delegate-inflexibility" and allow to call type-functions on anything that's stored somewhere in memory