Property returns incorrect object

General FreeBASIC programming questions.
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Property returns incorrect object

Post by sancho2 »

Well I didn't see that one either.
But what I meant was it shouldn't reach it based on no logic errors.

Its exactly as you stated, only safe for simple data types.

How about this instead:

Code: Select all

operator StateVar.Cast() As String
   '
   If this.init_flag = _string Then
      Return This._string_value
   ElseIf this.init_flag = _int Then
      Return Str(this._int_value)
   EndIf
   Error 10		' no point in letting the code continue
End Operator
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Property returns incorrect object

Post by sancho2 »

It seems the GetMouse is overloaded and doesn't like my statevar. It returns an ambiguous call error.
Its easy to resolve by using Getmouse(cint(mystatevarX), mystatevarY).

Code: Select all

'-----------------------------------------------------------------------------------------
' 08-22-2017 - 18:18:40 (mm/dd/yyyy)                                                      
'-----------------------------------------------------------------------------------------
'#include once "StateVar.bi"
Type StateVar
   Private:
         
      Enum _type
         _none
         _int
         _string
      End Enum

      As String _string_value
      As Integer _int_value
      
      As String _string_old_value
      As Integer _int_old_value

      As _type init_flag = _none

   Public:

      Declare Property IsChanged() As boolean   
      Declare Operator Cast() As String
      Declare Operator Cast() As Integer
   
      Declare Operator Let(ByRef txt As String)
      Declare Operator Let(ByRef value As Integer)
      
      
End Type
operator StateVar.Cast() As String
   '
   If this.init_flag = _string Then
      Return This._string_value
   ElseIf this.init_flag = _int Then
      Return Str(this._int_value)
   EndIf
   Error 10
   'Return ""	'<---------added
End Operator

operator StateVar.Cast() As Integer
   '
   Return This._int_value
End Operator

operator StateVar.Let(ByRef value As String)
'
   This._string_value = value
   If this.init_flag = _none OrElse this.init_flag = _int Then
      this.init_flag = _string
      this._string_old_value = value
   EndIf
End Operator
Operator StateVar.Let(ByRef value As Integer)
'
   This._int_value = value
   If this.init_flag = _none OrElse this.init_flag = _string Then
      this.init_flag = _int
      this._int_old_value = value
   EndIf
End Operator
Property StateVar.IsChanged() As boolean
   '
   Dim As boolean b
   
   If this.init_flag = _int Then
      If this._int_value <> this._int_old_value Then
         b = TRUE
      EndIf
      
      If b = TRUE Then
         this._int_old_value = this._int_value
      EndIf
   
   ElseIf this.init_flag = _string Then
      If this._string_value <> this._string_old_value Then
         b = TRUE
      EndIf
      
      If b = TRUE Then
         this._string_old_value = this._string_value
      EndIf
      
   EndIf
   Return b
End Property


'Dim s As StateVar
''
's = "test"
'? "test", s, s.ischanged
's = 12
'? s * 12, s, s.ischanged
's= 13
'? 13, s, s.ischanged
's= "test"
'? "test",s, s.ischanged
's= "moo"
'? "moo", s, s.ischanged
'
' 
'sleep

Type mytype
	'As Integer x
	'As Integer y
	'As Integer w
	'As Integer c	
	'As Integer b

	As statevar x
	As statevar y
	As statevar w
	As StateVar c
	As statevar b
	
	Declare Sub poll()
End Type

Sub mytype.poll()
	With This
		GetMouse(.x, .y, .w, .b, .c)
	End With
End Sub

Dim t As mytype

Do
	t.poll()
	Sleep 3

Loop While inkey <> Chr(27)

?"end"
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Property returns incorrect object

Post by fxm »

sancho2 wrote:It seems the GetMouse is overloaded and doesn't like my statevar. It returns an ambiguous call error.
Its easy to resolve by using Getmouse(cint(mystatevarX), mystatevarY).
and in addition define:
'Declare Operator Cast() Byref As Integer'
to be able to write in '_int_value'.
(the more logical is to use the syntax 'Cast(Integer, .x)' instead of 'Cint(.x)', but that works with 'Cint' because 'Cint' also calls implicitly your overload operator 'Cast')
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Property returns incorrect object

Post by sancho2 »

Can you give me an example of what writing to _int_value would look like in code?
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Property returns incorrect object

Post by fxm »

Code: Select all

Screen 12
'-----------------------------------------------------------------------------------------
' 08-22-2017 - 18:18:40 (mm/dd/yyyy)                                                     
'-----------------------------------------------------------------------------------------
'#include once "StateVar.bi"
Type StateVar
   Private:
         
      Enum _type
         _none
         _int
         _string
      End Enum

      As String _string_value
      As Integer _int_value
     
      As String _string_old_value
      As Integer _int_old_value

      As _type init_flag = _none

   Public:

      Declare Property IsChanged() As boolean   
      Declare Operator Cast() As String
      Declare Operator Cast() Byref As Integer
   
      Declare Operator Let(ByRef txt As String)
      Declare Operator Let(ByRef value As Integer)
     
End Type
operator StateVar.Cast() As String
   '
   If this.init_flag = _string Then
      Return This._string_value
   ElseIf this.init_flag = _int Then
      Return Str(this._int_value)
   EndIf
   Error 10
   'Return ""   '<---------added
End Operator

operator StateVar.Cast() Byref As Integer
   '
   Return This._int_value
End Operator

operator StateVar.Let(ByRef value As String)
'
   This._string_value = value
   If this.init_flag = _none OrElse this.init_flag = _int Then
      this.init_flag = _string
      this._string_old_value = value
   EndIf
End Operator
Operator StateVar.Let(ByRef value As Integer)
'
   This._int_value = value
   If this.init_flag = _none OrElse this.init_flag = _string Then
      this.init_flag = _int
      this._int_old_value = value
   EndIf
End Operator
Property StateVar.IsChanged() As boolean
   '
   Dim As boolean b
   
   If this.init_flag = _int Then
      If this._int_value <> this._int_old_value Then
         b = TRUE
      EndIf
     
      If b = TRUE Then
         this._int_old_value = this._int_value
      EndIf
   
   ElseIf this.init_flag = _string Then
      If this._string_value <> this._string_old_value Then
         b = TRUE
      EndIf
     
      If b = TRUE Then
         this._string_old_value = this._string_value
      EndIf
     
   EndIf
   Return b
End Property


'Dim s As StateVar
''
's = "test"
'? "test", s, s.ischanged
's = 12
'? s * 12, s, s.ischanged
's= 13
'? 13, s, s.ischanged
's= "test"
'? "test",s, s.ischanged
's= "moo"
'? "moo", s, s.ischanged
'
'
'sleep

Type mytype
'   As Integer x
'   As Integer y
'   As Integer w
'   As Integer c   
'   As Integer b

   As statevar x
   As statevar y
   As statevar w
   As StateVar c
   As statevar b
   
   Declare Sub poll()
End Type

Sub mytype.poll()
   With This
      GetMouse(Cast(Integer, .x), .y, .w, .b, .c)
      If .x.IsChanged Or .y.IsChanged Or .w.IsChanged Or .b.IsChanged Or .c.IsChanged Then
         Locate 1,1 
         Print .x & " ", .y & " ", .w & " ", .b & " ", .c & " "
      End If
   End With
End Sub

Dim t As mytype
t.x = 0  '' to avoid Error 10
t.y = 0  '' to avoid Error 10
t.w = 0  '' to avoid Error 10
t.b = 0  '' to avoid Error 10
t.c = 0  '' to avoid Error 10

Do
   t.poll()
   Sleep 3

Loop While inkey <> Chr(27)

Screen 0
?"end"
[edit]
- Added test of one instance at least '.IsChanged' to print the line.
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Property returns incorrect object

Post by sancho2 »

Of course. This is the very issue that started this thread.
Now I am looking at cast() as string. It should also return byref for the same reason.
The problem is that it also returns str(_int_value) if the object is an integer. I can't just use a procedure level variable to hold the string value because it will no longer exist after the procedure ends.
I thought about storing the _int_value in the _string_value member but this seems like a hack or clunky.
How should handle the cast() as string?
sancho2
Posts: 547
Joined: May 17, 2015 6:41

Re: Property returns incorrect object

Post by sancho2 »

The following code is a revamped version. It eliminates the initialization checks and treats the first assignment to the variable as is_changed = true. (The cls and error messages are just for me because I use FBEdit and it won't show me error 10)

Code: Select all

Type StateVar
   Private:
         
      Enum _type
         _none
         _int
         _string
      End Enum

		As String _value
		As Integer _int_value
		
		As String _last_value

      As _type init_flag = _none

   Public:

      Declare Property IsChanged() As boolean   
      Declare Operator Cast() ByRef As String
      Declare Operator Cast() ByRef As Integer
   
      Declare Operator Let(ByRef txt As String)
      Declare Operator Let(ByRef value As Integer)
      
      
End Type
operator StateVar.Cast() ByRef As String
   '
   Return This._value
End Operator

operator StateVar.Cast() ByRef  As Integer
   '
   Return This._int_value
End Operator

operator StateVar.Let(ByRef value As String)
'
   If This.init_flag = _int Then
   	Cls
   	Print "Error: StateVar integer cannot be re-initialized to string"
   	Sleep
   	Error 10 
   EndIf

   This._last_value = this._value
   This._value = value

   this._int_value = Val(value)
   This.init_flag = _string
End Operator

Operator StateVar.Let(ByRef value As Integer)
'
   If this.init_flag = _string Then
   	Cls
   	Print "Error: StateVar string cannot be re-initialized to integer"
   	sleep
   	Error 10 
   EndIf

   This._last_value = this._value
   this._value = Str(value)
   this._int_value = value
   This.init_flag = _int
End Operator

Property StateVar.IsChanged() As boolean
   '
   Return cbool(this._value <> this._last_value)
End Property


Dim As StateVar s, s2
''
's = "test"
'? "test", s, s.ischanged, s.ischanged

s = 12
? s * 12, s, s.ischanged, s.ischanged
s= 13
? s, s.ischanged
's= "test"
s2 = "test"
? s2, s2.IsChanged
Mid(s2, 3) = "e"
? s2, s2.ischanged
'? "test",s, s.ischanged
's= "moo"
'? "moo", s, s.ischanged
'
' 
sleep
Last edited by sancho2 on Aug 26, 2017 23:48, edited 1 time in total.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Property returns incorrect object

Post by dodicat »

Some of yours and some of mine.
Try the array test with yours.

Code: Select all




type statevar
    private:
    '=============
    Enum _type
         _none
         _int
         _string
    End Enum
    as string present_string,last_string
    as integer present_integer,last_integer
    as integer Sstart,Istart
     As _type init_flag = _none
    declare function  _string_value() byref as string
    declare function _int_value() byref as integer
    declare function ischanged()  as boolean
    '==============
    public:
    dim as boolean is_changed
    declare operator let(as string)
    declare operator let(as integer)
    declare operator cast() as string
    declare operator cast() as integer
end type

function statevar._string_value() byref as string
 function=present_string
 last_string=present_string
end function

function statevar._int_value() byref as integer
 function=present_integer
   last_integer=present_integer
end function

operator statevar.let(s as string)
init_flag=_string
 _string_value()=s
 if Sstart<2 then Sstart+=1 
 is_changed=ischanged
end operator

operator statevar.let(s as integer)
init_flag=_int
 _int_value()=s
 if Istart<2 then Istart+=1
 is_changed=ischanged
end operator

function statevar.ischanged()  as boolean
if init_flag=_string then function = iif(Sstart>1,last_string<>present_string,0)
if init_flag=_int    then function = iif(Istart>1,last_integer<>present_integer,0)
if init_flag=0 then  function= 0
end function

operator statevar.cast() as string
if init_flag=2 then return present_string
if init_flag=1 then return str(present_integer)
end operator

operator StateVar.Cast() As Integer
   Return present_integer
End Operator
'==============================================================================
Dim s As StateVar
'
s = "test"
? "test", s, s.is_changed
s = 12
? s * 12, s, s.is_changed

s= 13
? 13, s, s.is_changed
s= "test"
? "test",s, s.is_changed
s= "moo"
? "moo", s, s.is_changed

'=======  ARRAY TEST ========
redim as statevar x(1000000)

for n as long=0 to 1000000
    x(n)=n
    x(n)=str(-n)
next



for n as long=0 to 1000000
    if x(n).is_changed then print x(n)
next
'some changes
x(1000)="Hello"
x(500023)=10
x(10674)="New"
x(300045)=13
x(2017)="Now"
print
for n as long=0 to 1000000
    if x(n).is_changed then print n,x(n)
next
print "Press a key"
sleep
screen 12
dim as integer mx,my,mw,mb,mc
dim as statevar m(1 to 7)
do
    screenlock
    cls
    getmouse mx,my,mw,mb,mc
    m(1)=mx
    m(2)=my
    m(3)=mw
    m(4)= mb=1 and mb
    m(5)= mb=2 and mb
    m(6)= mb=4 and mb
    m(7)= mc
  '
            for n as long=1 to 7
             locate 10,9*n
            if m(n).is_changed then color 15 else color 8
            print m(n)
             next
    screenunlock
   sleep 50,1
    loop until inkey=chr(27)





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

Re: Property returns incorrect object

Post by dodicat »

An example of changed text. + a question.

I set statevar in a namespace and undefined integer to ulong for rgb()
But the new define is not contained inside the namespace, it seems permanent.
I suppose there is a reason for this, but I can't quite think of it.
Example:

Code: Select all

namespace state
#undef integer
#define integer ulong
type statevar
    private:
    as integer initflag
    as string present_string,last_string
    as integer present_integer,last_integer
    as integer Sstart,Istart
    declare function  _string_value() byref as string
    declare function _int_value() byref as integer
    declare function ischanged()  as boolean
    '==============
    public:
    as boolean is_changed
    declare operator let(as string)
    declare operator let(as integer)
    declare operator cast() as string
    declare operator cast() as integer
end type

function statevar._string_value() byref as string
 function=present_string
 last_string=present_string
end function

function statevar._int_value() byref as integer
 function=present_integer
 last_integer=present_integer
end function

operator statevar.let(s as string)
  initflag=2
 _string_value()=s
 if Sstart<2 then Sstart+=1 
 is_changed=ischanged
end operator

operator statevar.let(s as integer)
  initflag=1
 _int_value()=s
 if Istart<2 then Istart+=1
 is_changed=ischanged
end operator

function statevar.ischanged()  as boolean
if initflag=2 then function = iif(Sstart>1,last_string<>present_string,0)
if initflag=1 then function = iif(Istart>1,last_integer<>present_integer,0)
if initflag=0 then function= 0
end function

operator statevar.cast() as string
if initflag=2 then operator= present_string
if initflag=1 then operator= str(present_integer)
end operator

operator StateVar.Cast() As Integer
   operator= present_integer
End Operator

end namespace

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

''QUESTION
dim as integer i
#print typeof(i)


function contrast(c as ulong) as ulong
       #define Intrange(f,l) int(Rnd*((l+1)-(f))+(f))
       'get the rgb values
       dim as ubyte r=Cptr(Ubyte Ptr,@c)[2],g=Cptr(Ubyte Ptr,@c)[1],b=Cptr(Ubyte Ptr,@c)[0],r2,g2,b2
       do
           r2=Intrange(0,255):g2=IntRange(0,255):b2=IntRange(0,255)
           'get at least 120 byte difference
           loop until abs(r-r2)>120 andalso abs(g-g2)>120 andalso abs(b-b2)>120
          return rgb(r2,g2,b2) 
   end function
   
   
screenres 300,50,32
width 300\8,50\16
windowtitle "Every Five Seconds"
dim as state.statevar t
dim as state.statevar background,foreground
foreground=rgb(255,255,255)
randomize
    do
    t=time
    if t.is_changed then draw string(115,15),string(8,chr(219)),background:draw string(115,15),t,foreground : t+=1
    if t=5 then
            foreground=rgb(rnd*255,rnd*255,rnd*255)
            background=contrast(foreground)
            t=0
    end if
    sleep 100,1
    loop until len(inkey)
 
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Property returns incorrect object

Post by fxm »

At documentation page #DEFINE:
.....
Namespaces on the other hand do not have any effect on the visibility of a define.
.....
Post Reply