UDT: Dynamic Type

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

UDT: Dynamic Type

Post by fxm »

In the world of UDTs, conversions can be controlled by means of three member procedures:
  • Single-argument constructor: allow conversion from a particular type to initialize an object.
  • Assignment operator: allow conversion from a particular type on assignment.
  • Type-cast operator: allow conversion to a particular type.
Using such conversions allows to defined a simplistic dynamic type (DT) for user:
  • For a construction with implicit initialization ('Dim As DT u = v'), the compiler uses the matched constructor (for DT type / v type).
  • For an implicit assignment ('u = v'), the compiler uses the matched let operator (for DT type / v type).
  • For an implicit addition ('u = u0 + v' or 'u += v'), the compiler uses firstly the matched cast operator (for DT type / v type), then the matched let operator (for DT type / v type).
Example of simplistic Dynamic Type among the 3 Integer / Single / String types:

Code: Select all

Type DT  '' Dynamic Type
    Public:
        Declare Constructor ()
        Declare Constructor (Byval rhs As Integer)
        Declare Constructor (Byval rhs As Single)
        Declare Constructor (Byref rhs As String)
        Declare Operator Let (Byval rhs As Integer)
        Declare Operator Let (Byval rhs As Single)
        Declare Operator Let (Byref rhs As String)
        Declare Operator Cast () As Integer
        Declare Operator Cast () As Single
        Declare Operator Cast () As String
        Declare Property myType () As String
    Private:
        Dim As String _type
        Union
            Dim As Integer _integer
            Dim As Single _single
        End Union
        Dim As String _string  '' Var-len strings cannot be part of UNION
End Type

Constructor DT ()
End Constructor

Constructor DT (Byval rhs As Integer)
    This._type = "INTEGER"
    This._integer = rhs
End Constructor

Constructor DT (Byval rhs As Single)
    This._type = "SINGLE"
    This._single = rhs
End Constructor

Constructor DT (Byref rhs As String)
    This._type = "STRING"
    This._string = rhs
End Constructor

Operator DT.Let (Byval rhs As Integer)
    This._type = "INTEGER"
    This._string = ""
    This._integer = rhs
End Operator

Operator DT.Let (Byval rhs As Single)
    This._type = "SINGLE"
    This._string = ""
    This._single = rhs
End Operator

Operator DT.Let (Byref rhs As String)
    This._type = "STRING"
    This._string = rhs
End Operator

Operator DT.Cast () As Integer
    Return This._integer
End Operator

Operator DT.Cast () As Single
    Return This._single
End Operator

Operator DT.Cast () As String
    If This._type = "INTEGER" Then Return Str(This._integer)
    If This._type = "SINGLE" Then Return Str(This._single)
    If This._type = "STRING" Then Return This._string
End Operator

Property DT.myType () As String
    Return This._type
End Property


Dim As DT u

u = 100  ''
u = u + 20
u += 3
Print u.myType, u
Dim As Integer vinteger = u
Print vinteger
Print

u = 456.7
u = u + 0.08
u += 0.009
Print u.myType, u
Dim As Single vsingle = u
Print vsingle
Print

u = "a user "
u = u + "Dynamic "
u += "Type"
Print u.myType, u
Dim As String vstring = u
Print vstring
Print

Sleep
Last edited by fxm on Feb 28, 2020 21:15, edited 1 time in total.
srvaldez
Posts: 3383
Joined: Sep 25, 2005 21:54

Re: UDT: Dynamic Type

Post by srvaldez »

beautiful fxm :-)
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

It works just as well without the constructors or the union.
What are the reasons for the constructors and the union?
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT: Dynamic Type

Post by fxm »

- Union: just to save a little memory (in case of many different types).

- Conversion-constructors: to allow construction with implicit initialization, like:
Dim As DT u = 100
instead of
Dim As DT u
u = 100
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

Well fxm, you are usually the first to tell me (and others) about redundant code, and have done so over the years.
You don't use
Dim As DT u = 100
So the constructors are redundant (or in your colourful style - useless)
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT: Dynamic Type

Post by fxm »

For me, it is rather my example of application which is not exhaustive compared to the proposed DT structure.
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT: Dynamic Type

Post by fxm »

fxm wrote:In the world of UDTs, conversions can be controlled by means of three member procedures:
  • Single-argument constructor: allow conversion from a particular type to initialize an object.
  • Assignment operator: allow conversion from a particular type on assignment.
  • Type-cast operator: allow conversion to a particular type.
Using such conversions allows to defined a simplistic dynamic type (DT) for user:
  • For a construction with implicit initialization ('Dim As DT u = v'), the compiler uses the matched constructor (for DT type / v type).
  • For an implicit assignment ('u = v'), the compiler uses the matched let operator (for DT type / v type).
  • For an implicit addition ('u = u0 + v' or 'u += v'), the compiler uses firstly the matched cast operator (for DT type / v type), then the matched let operator (for DT type / v type).
Example of simplistic Dynamic Type among the 3 Integer / Single / String types:

Code: Select all

Type DT  '' Dynamic Type
    Public:
        Declare Constructor ()
        Declare Constructor (Byval rhs As Integer)
        Declare Constructor (Byval rhs As Single)
        Declare Constructor (Byref rhs As String)
        Declare Operator Let (Byval rhs As Integer)
        Declare Operator Let (Byval rhs As Single)
        Declare Operator Let (Byref rhs As String)
        Declare Operator Cast () As Integer
        Declare Operator Cast () As Single
        Declare Operator Cast () As String
        Declare Property myType () As String
    Private:
        Dim As String _type
        Union
            Dim As Integer _integer
            Dim As Single _single
        End Union
        Dim As String _string  '' Var-len strings cannot be part of UNION
End Type

Constructor DT ()
End Constructor

Constructor DT (Byval rhs As Integer)
    This._type = "INTEGER"
    This._integer = rhs
End Constructor

Constructor DT (Byval rhs As Single)
    This._type = "SINGLE"
    This._single = rhs
End Constructor

Constructor DT (Byref rhs As String)
    This._type = "STRING"
    This._string = rhs
End Constructor

Operator DT.Let (Byval rhs As Integer)
    This._type = "INTEGER"
    This._string = ""
    This._integer = rhs
End Operator

Operator DT.Let (Byval rhs As Single)
    This._type = "SINGLE"
    This._string = ""
    This._single = rhs
End Operator

Operator DT.Let (Byref rhs As String)
    This._type = "STRING"
    This._string = rhs
End Operator

Operator DT.Cast () As Integer
    Return This._integer
End Operator

Operator DT.Cast () As Single
    Return This._single
End Operator

Operator DT.Cast () As String
    If This._type = "INTEGER" Then Return Str(This._integer)
    If This._type = "SINGLE" Then Return Str(This._single)
    If This._type = "STRING" Then Return This._string
End Operator

Property DT.myType () As String
    Return This._type
End Property


Dim As DT u

u = 100  ''
u = u + 20
u += 3
Print u.myType, u
Dim As Integer vinteger = u
Print vinteger
Print

u = 456.7
u = u + 0.08
u += 0.009
Print u.myType, u
Dim As Single vsingle = u
Print vsingle
Print

u = "a user "
u = u + "Dynamic "
u += "Type"
Print u.myType, u
Dim As String vstring = u
Print vstring
Print

Sleep
Variant of DT using a single pointer to a dynamic variable matching to the dynamic type assigned:

Code: Select all

Type DT  '' Dynamic Type
    Public:
        Declare Constructor ()
        Declare Constructor (Byval rhs As Integer)
        Declare Constructor (Byval rhs As Single)
        Declare Constructor (Byref rhs As String)
        Declare Operator Let (Byval rhs As Integer)
        Declare Operator Let (Byval rhs As Single)
        Declare Operator Let (Byref rhs As String)
        Declare Operator Cast () As Integer
        Declare Operator Cast () As Single
        Declare Operator Cast () As String
        Declare Property myType () As String
        Declare Destructor ()
    Private:
        Dim As String _type
        Dim As Any Ptr _pointer
End Type

Constructor DT ()
End Constructor

Constructor DT (Byval rhs As Integer)
    This._type = "INTEGER"
    This._pointer = New Integer
    *Cptr(Integer Ptr, This._pointer) = rhs
End Constructor

Constructor DT (Byval rhs As Single)
    This._type = "SINGLE"
    This._pointer = New Single
    *Cptr(Single Ptr, This._pointer) = rhs
End Constructor

Constructor DT (Byref rhs As String)
    This._type = "STRING"
    This._pointer = New String
    *Cptr(String Ptr, This._pointer) = rhs
End Constructor

Operator DT.Let (Byval rhs As Integer)
    If This._type <> "INTEGER" Then
        If This._type = "SINGLE" Then Delete Cptr(Single Ptr, This._pointer)
        If This._type = "STRING" Then Delete Cptr(String Ptr, This._pointer)
        This._type = "INTEGER"
        This._pointer = New Integer
    End If
    *Cptr(Integer Ptr, This._pointer) = rhs
End Operator

Operator DT.Let (Byval rhs As Single)
    If This._type <> "SINGLE" Then
        If This._type = "INTEGER" Then Delete Cptr(Integer Ptr, This._pointer)
        If This._type = "STRING" Then Delete Cptr(String Ptr, This._pointer)
        This._type = "SINGLE"
        This._pointer = New Single
    End If
    *Cptr(Single Ptr, This._pointer) = rhs
End Operator

Operator DT.Let (Byref rhs As String)
    If This._type <> "STRING" Then
        If This._type = "INTEGER" Then Delete Cptr(Integer Ptr, This._pointer)
        If This._type = "SINGLE" Then Delete Cptr(Single Ptr, This._pointer)
        This._type = "STRING"
        This._pointer = New String
    End If
    *Cptr(String Ptr, This._pointer) = rhs
End Operator

Operator DT.Cast () As Integer
    If This._type = "INTEGER" Then Return *Cptr(Integer Ptr, This._pointer)
End Operator

Operator DT.Cast () As Single
    If This._type = "SINGLE" Then Return *Cptr(Single Ptr, This._pointer)
End Operator

Operator DT.Cast () As String
    If This._type = "INTEGER" Then Return Str(*Cptr(Integer Ptr, This._pointer))
    If This._type = "SINGLE" Then Return Str(*Cptr(Single Ptr, This._pointer))
    If This._type = "STRING" Then Return *Cptr(String Ptr, This._pointer)
End Operator

Property DT.myType () As String
    Return This._type
End Property

Destructor DT ()
    If This._type = "INTEGER" Then Delete Cptr(Integer Ptr, This._pointer)
    If This._type = "SINGLE" Then Delete Cptr(Single Ptr, This._pointer)
    If This._type = "STRING" Then Delete Cptr(String Ptr, This._pointer)
End Destructor


Dim As DT u

u = 100  ''
u = u + 20
u += 3
Print u.myType, u
Dim As Integer vinteger = u
Print vinteger
Print

u = 456.7
u = u + 0.08
u += 0.009
Print u.myType, u
Dim As Single vsingle = u
Print vsingle
Print

u = "a user "
u = u + "Dynamic "
u += "Type"
Print u.myType, u
Dim As String vstring = u
Print vstring
Print

Sleep
Last edited by fxm on Mar 01, 2020 14:53, edited 2 times in total.
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

Try without using new or delete.

Code: Select all


Type udt
    Declare Operator Let (Byval rhs As Integer)
    Declare Operator Let (Byval rhs As Double)
    Declare Operator Let (Byval rhs As String)
    Declare Operator Cast () As Integer
    Declare Operator Cast () As Double
    Declare Operator Cast() As String
    As Any Ptr p(1 To 4)
    #define datatype(u) *Cast(String Ptr,u.p(4))
End Type

Operator udt.Cast () As Integer
static as string s:s="Integer"
p(4)=@s:p(2)=0:p(3)=0
Return *Cast(Integer Ptr,p(1))    
End Operator

Operator udt.Cast () As Double
static as string s:s="Double"
p(4)=@s:p(1)=0:p(3)=0
Return *Cast(Double Ptr,p(2))
End Operator

Operator udt.cast As String
Dim As String s
If p(1) Then s+=Str(*Cast(Integer Ptr,p(1)))
If p(2) Then s+=Str(*Cast(Double Ptr,p(2)))
If p(3) Then s+=Str(*Cast(String Ptr,p(3)))
Operator= s
End Operator

Operator UDT.Let (Byval rhs As Integer)
static as string s:s="Integer"
p(4)=@s:p(2)=0:p(3)=0
Static As Integer g:g=rhs
p(1)=@g
End Operator

Operator UDT.Let (Byval rhs As Double)
static as string s:s="double"
p(4)=@s:p(1)=0:p(3)=0
Static As Double g:g=rhs
p(2)=@g
End Operator

Operator UDT.Let (Byval rhs As String)
static as string s:s="string"
p(4)=@s:p(1)=0:p(2)=0
Static As String g:g=rhs
p(3)=@g
End Operator


'============

Dim As udt u
u = 100
u = u + 20
u += 3
Print datatype(u),u
u = 456.7
u = u + 0.08
u += 0.009
Print datatype(u),u
u="a user "
u = u + "Dynamic "
u += "Type"
Print datatype(u),u
u="Done."
Print datatype(u),u,datatype(u),u
u="All "+u
print u
Sleep

 
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT: Dynamic Type

Post by fxm »

With your code above, only one variable of the same type can be used at any given time!

Code: Select all

Dim As UDT u1
u1 = 100  ''
u1 = u1 + 20
u1 += 3
Print u1

Dim As UDT u2
u2 = 400  ''
u2 = u2 + 50
u2 += 6
Print u2

Print u1, u2

Sleep
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

thanks fxm.
I am forced to use new and delete to carve out new memory slots, and a destructor.

Code: Select all

Type udt
    Declare Operator Let (Byref rhs As Integer)
    Declare Operator Let (Byref rhs As Double)
    Declare Operator Let (Byval rhs As String)
    Declare Operator Cast () As Integer
    Declare Operator Cast () As Double
    Declare Operator Cast() As String
    declare destructor
    As Any Ptr p(1 to 4)
    #define datatype(u) *Cast(String Ptr,u.p(4))
End Type

Operator udt.Cast () As Integer
static as string s:s="Integer"
p(4)=@s:p(2)=0:p(3)=0
return *Cast(Integer Ptr,p(1))   
End Operator

Operator udt.Cast () As Double
static as string s:s="Double"
p(4)=@s:p(1)=0:p(3)=0
Return *Cast(Double Ptr,p(2))
End Operator

Operator udt.cast As String
dim As String s
If p(1) Then s=Str(*Cast(Integer Ptr,p(1)))
If p(2) Then s=Str(*Cast(Double Ptr,p(2)))
If p(3) Then s+=Str(*Cast(String Ptr,p(3)))
Operator= s
End Operator

Operator UDT.Let (Byref rhs As Integer)
static as string s:s="Integer"
if p(2) then delete  Cast(double Ptr,p(2))
if p(3) then delete  Cast(string Ptr,p(3))
p(4)=@s:p(2)=0:p(3)=0
p(1)=new integer
*Cast(Integer Ptr,p(1))=rhs
End Operator

Operator UDT.Let (Byref rhs As Double)
static as string s:s="double"
if p(1) then delete  Cast(Integer Ptr,p(1))
if p(3) then delete  Cast(string Ptr,p(3))
p(4)=@s:p(1)=0:p(3)=0
p(2)=new double
*Cast(double Ptr,p(2))=rhs
End Operator

Operator UDT.Let (Byval rhs As String)
static as string s:s="string"
if p(1) then delete  Cast(Integer Ptr,p(1))
if p(2) then delete  Cast(double Ptr,p(2))
p(4)=@s:p(1)=0:p(2)=0
p(3)=new string
*Cast(string Ptr,p(3))=rhs
End Operator

destructor udt
if p(1) then delete  Cast(Integer Ptr,p(1))
if p(2) then delete  Cast(double Ptr,p(2))
if p(3) then delete  Cast(string Ptr,p(3))
erase p
end destructor

dim as long counter
'============
do
    counter+=1
    locate 3,,0
Dim As udt u
u = 100
u = u + 20
u += 3
Print datatype(u),u
u = 456.7
u = u + 0.08
u += 0.009
Print datatype(u),u
u="a user "
u = u + "Dynamic "
u += "Type"
Print datatype(u),u
u="Done."
Print datatype(u),u,datatype(u),u
u="All "+u
print u


Dim As UDT u1
u1 = 100  
u1 = u1 + 20
u1 += 3
Print u1

Dim As UDT u2
u2 = 400  ''
u2 = u2 + 50
u2 += 6
Print u2

Print u1, u2,datatype(u1),datatype(u2),u
print
print
print counter
loop until inkey=chr(27)
Sleep

 
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT: Dynamic Type

Post by fxm »

To avoid memory leak (check with the task manager):

Code: Select all

Operator UDT.Let (Byref rhs As Integer)
static as string s:s="Integer"
if p(2) then delete  Cast(double Ptr,p(2))
if p(3) then delete  Cast(string Ptr,p(3))
p(4)=@s:p(2)=0:p(3)=0
if p(1)=0 then p(1) =new integer  '' <<<<<<<<<<
*Cast(Integer Ptr,p(1))=rhs
End Operator

Operator UDT.Let (Byref rhs As Double)
static as string s:s="double"
if p(1) then delete  Cast(Integer Ptr,p(1))
if p(3) then delete  Cast(string Ptr,p(3))
p(4)=@s:p(1)=0:p(3)=0
if p(2)=0 then p(2)=new double  '' <<<<<<<<<<
*Cast(double Ptr,p(2))=rhs
End Operator

Operator UDT.Let (Byval rhs As String)
static as string s:s="string"
if p(1) then delete  Cast(Integer Ptr,p(1))
if p(2) then delete  Cast(double Ptr,p(2))
p(4)=@s:p(1)=0:p(2)=0
if p(3)=0 then p(3)=new string  '' <<<<<<<<<<
*Cast(string Ptr,p(3))=rhs
End Operator
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

The help file says for every new there should be a delete.
Things get a bit convoluted sometimes, so with your amendment to my code I apply a counter.

Code: Select all

Type udt
    Declare Operator Let (Byref rhs As Integer)
    Declare Operator Let (Byref rhs As Double)
    Declare Operator Let (Byval rhs As String)
    Declare Operator Cast () As Integer
    Declare Operator Cast () As Double
    Declare Operator Cast() As String
    declare destructor
    As Any Ptr p(1 to 4)
    #define datatype(u) *Cast(String Ptr,u.p(4))
End Type
dim shared as long newinteger,deleteinteger,newdouble,deletedouble,newstring,deletestring

Operator udt.Cast () As Integer
static as string s:s="Integer"
p(4)=@s:p(2)=0:p(3)=0
return *Cast(Integer Ptr,p(1))   
End Operator

Operator udt.Cast () As Double
static as string s:s="Double"
p(4)=@s:p(1)=0:p(3)=0
Return *Cast(Double Ptr,p(2))
End Operator

Operator udt.cast As String
dim As String s
If p(1) Then s=Str(*Cast(Integer Ptr,p(1)))
If p(2) Then s=Str(*Cast(Double Ptr,p(2)))
If p(3) Then s=Str(*Cast(String Ptr,p(3)))
Operator= s
'p(1)=0:p(2)=0
End Operator

Operator UDT.Let (Byref rhs As Integer)
static as string s:s="Integer"
if p(2) then delete  Cast(double Ptr,p(2)):deletedouble+=1
if p(3) then delete  Cast(string Ptr,p(3)):deletestring+=1
p(4)=@s:p(2)=0:p(3)=0
if p(1)=0 then p(1)=new integer:newinteger+=1
*Cast(Integer Ptr,p(1))=rhs
End Operator

Operator UDT.Let (Byref rhs As Double)
static as string s:s="double"
if p(1) then delete  Cast(Integer Ptr,p(1)):deleteinteger+=1
if p(3) then delete  Cast(string Ptr,p(3)):deletestring+=1
p(4)=@s:p(1)=0:p(3)=0
if p(2)=0 then p(2)=new double:newdouble+=1
*Cast(double Ptr,p(2))=rhs
End Operator

Operator UDT.Let (Byval rhs As String)
static as string s:s="string"
if p(1) then delete  Cast(Integer Ptr,p(1)):deleteinteger+=1
if p(2) then delete  Cast(double Ptr,p(2)):deletedouble+=1
p(4)=@s:p(1)=0:p(2)=0
if p(3)=0 then p(3)=new string:newstring+=1
*Cast(string Ptr,p(3))=rhs
End Operator

destructor udt
if p(1) then delete  Cast(Integer Ptr,p(1)):deleteinteger+=1
if p(2) then delete  Cast(double Ptr,p(2)):deletedouble+=1
if p(3) then delete  Cast(string Ptr,p(3)):deletestring+=1
erase p
end destructor

'============
do
    locate 3,,0
Dim As udt u
u = 100
u = u + 20
u += 3
Print datatype(u),u
u = 456.7
u = u + 0.08
u += 0.009
Print datatype(u),u
u="a user "
u = u + "Dynamic "
u += "Type"
Print datatype(u),u
u="Done."
Print datatype(u),u,datatype(u),u
u="All "+u
print u


Dim As UDT u1
u1 = 100  
u1 = u1 + 20
u1 += 3
Print u1

Dim As UDT u2
u2 = 400  ''
u2 = u2 + 50
u2 += 6
Print u2

Print u1, u2,datatype(u1),datatype(u2),u
print
print
print "integer","double","string"
print newinteger,newdouble,newstring,"New"
print deleteinteger,deletedouble,deletestring,"delete"
loop until inkey=chr(27)
Sleep

 
fxm
Moderator
Posts: 12159
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: UDT: Dynamic Type

Post by fxm »

The [Do...Loop] block has a local scope.
So the objects 'u', 'u1', 'u2' will be destroyed just at the loop exit. It is why when <escape> is entered, counters of 'new' and 'delete' show a difference of '1' for strings (corresponding to 'u') and '2' for integers (corresponding to 'u1' and 'u2').
If all counters are again displayed below the 'loop' exit (just before 'sleep'), all difference values are properly null.
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

I looped yours as well.
OK
dodicat
Posts: 7987
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: UDT: Dynamic Type

Post by dodicat »

Here is a great big looper cheat out of using new/delete.

Code: Select all


Type udt
    Declare Operator Let (Byval rhs As Integer)
    Declare Operator Let (Byval rhs As Double)
    Declare Operator Let (Byval rhs As String)
    Declare Operator Cast () As Integer
    Declare Operator Cast () As Double
    Declare Operator Cast() As String
    As Any Ptr p(1 To 4)
    #define datatype(u) *Cast(String Ptr,u.p(4))
End Type

dim shared as long lim=50
dim shared as integer i(1 to lim)
dim shared as double d(1 to lim)
dim shared as string s(1 to lim)
dim shared as long ik,dk,sk

Operator udt.Cast () As Integer
static as string s:s="Integer"
p(4)=@s:p(2)=0:p(3)=0
if p(1) then Return *Cast(Integer Ptr,p(1))   
End Operator

Operator udt.Cast () As Double
static as string s:s="Double"
p(4)=@s:p(1)=0:p(3)=0
if p(2) then Return *Cast(Double Ptr,p(2))
End Operator

Operator udt.cast As String
Dim As String s
If p(1) Then s+=Str(*Cast(Integer Ptr,p(1)))
If p(2) Then s+=Str(*Cast(Double Ptr,p(2)))
If p(3) Then s+=Str(*Cast(String Ptr,p(3)))
Operator= s
End Operator

Operator UDT.Let (Byval rhs As Integer)
ik+=1
i(ik)=rhs
static as string s:s="Integer"
p(4)=@s:p(2)=0:p(3)=0
p(1)=@i(ik)
if ik>=lim then ik=1
End Operator

Operator UDT.Let (Byval rhs As Double)
dk+=1
d(dk)=rhs
static as string s:s="double"
p(4)=@s:p(1)=0:p(3)=0
p(2)=@d(dk)
if dk>=lim then dk=1
End Operator

Operator UDT.Let (Byval rhs As String)
sk+=1
s(sk)=rhs
static as string ss:ss="string"
p(4)=@ss:p(1)=0:p(2)=0
p(3)= @s(sk)
if sk>=lim then sk=1
End Operator

operator =(n1 as udt,n2 as udt) as boolean
if n1.p(1)<>n2.p(1) then return 0
if n1.p(2)<>n2.p(2) then return 0
if n1.p(3)<>n2.p(3) then return 0
return 1
end operator


'============
dim as long ctr
do
    ctr+=1
    locate 5,,0
Dim As udt u
u = 100
u = u + 20
u += 3
Print datatype(u),u
u = 456.7
u = u + 0.08
u += 0.009
Print datatype(u),u
u="a user "
u = u + "Dynamic "
u += "Type"
Print datatype(u),u
u="Done."
Print datatype(u),u,datatype(u),u
u="All "+u
print u
Dim As UDT u1
u1 = 100  ''
u1 = u1 + 20
u1 += 3
Print u1

Dim As UDT u2
u2 = 400  ''
u2 = u2 + 50
u2 += 6
Print u2

Print u1, u2
print "Test if equal --> "; u1=u2 
if u1=u2 then beep
print

dim as udt v
v="Hello"
v+=" "
v+="world"
print v

dim as udt v2
v2="Free"
v2+=" "
v2+="world"
print v2
print v,v2
print "Test if equal --> "; v=v2 
if v=v2 then beep
dim as udt z
z+="End of tests"
print  z,datatype(z)
print
print ctr
loop until inkey=chr(27)

Sleep

 

   
Post Reply