Select Case in Native mode

Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
Post Reply
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Select Case in Native mode

Post by spamiam »

I have a problem with a program I am compiling in Native Mode (ZX24n)

I have the following code snippet

Code: Select all

Select Case True
            Case GetButton(UpButton)  
And other similar Cases. None of them get evaluated as true even if one of them should have been true.

The GetButton function is as follows:

Code: Select all

Public Function GetButton(ByVal ButtonNumber As Byte) As Boolean

    Const ButtonPressed As Byte = 0

    Select Case ButtonNumber
        Case 1
            GetButton = (GetPin(Button1Pin) = ButtonPressed)
        Case 2
            GetButton = (GetPin(Button2Pin) = ButtonPressed)
        Case 3
            GetButton = (GetPin(Button3Pin) = ButtonPressed)
        Case 4
            GetButton = (GetPin(Button4Pin) = ButtonPressed)
        Case Else
            GetButton = False
    End Select
End Function
This function does give correct results when used independently of a Case statement. The Select Case statements work properly when running in the ZVM mode. Is this an inconsistency in the Native Mode function, or do I have some odd software error elsewhere causing the code to fail?

-Tony
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: Select Case in Native mode

Post by dkinzer »

spamiam wrote:Is this an inconsistency in the Native Mode function?
It sounds like there is a code generation error somewhere. I tried to construct a test case similar to what you described but it worked OK.

If you can, try to produce a simplified test case that exhibits the problem. Perhaps a variation of the code below will do it.

Code: Select all

Sub Main()
  Select Case True
  Case test(3)
    Debug.Print "3"
  Case test(5)
    Debug.Print "5"
  End Select
End Sub

Function test(byval mode as byte) as Boolean
  test = (mode = 3)
End Function
Alternately, add --keep-files to your .pjt file and then send me the resulting .c file(s) containing the procedures involved. You'll find them two levels down from the directory containing the .pjt file: zxTempDir/<project-name>.
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Re: Select Case in Native mode

Post by spamiam »

dkinzer wrote:It sounds like there is a code generation error somewhere. I tried to construct a test case similar to what you described but it worked OK.
Unfortunately, this is a big, rambling project that I have been trying to update to the newest ZBasic. It was originally written for BasicX. Some of it was written by the BasicX company for some now discontinued hardware.

Since you could not reproduce the error, it is going to get a little harder to reproduce. I will have to move just the Constant declarations (for the button names, etc.) and the GetButton() function, and the Select Case into a new project.

As an attempt to debug the Select Case portion, I added a little code that has a bunch of if-then-else if statements that check all 4 buttons and then puts the button number (or zero) in a variable. I then did the Select Case based on that variable and then it worked.

So, it appears that it is something to do with using the GetButton function and doing the boolean comparison inside the Case statememts. Maybe the Select Case gets optimized away, or maybe the correct boolean value is lost and replaced by a zero. In your test code, the boolean function is effectively a constant, and the optimizer might be able to optimize the code down to something like just the Debug.Print statement, thereby not really reproducing the full complexity of my code.

I have not checked the files to see if there is excessive optimization and to see how the Select Case gets translated into C.

-Tony
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

I threw the following code together, as best as I can recall, essentially matching the functions of the real code (The actual program is not here at work). I compiled it in Native mode and looked at the C output. It looks fine to me! It ought to work. Now I have to set the Const statements to the correct values and try it again at home on the actual hardware.

-Tony

Code: Select all

Const GoButton		as byte = 1
Const StopButton	as byte = 2
Const UpButton		as byte = 3
Const DownButton	as byte = 4
	
Const Button1Pin	as byte = 5
Const Button2Pin	as byte = 6
Const Button3Pin	as byte = 7
Const Button4Pin	as byte = 8


Sub Main&#40;&#41;

	Do
	Select Case True 
            Case GetButton&#40;UpButton&#41; 
				debug.print "UpButton Pressed"
				
			Case GetButton&#40;DownButton&#41; 
				debug.print "DownButton Pressed"
				
			Case GetButton&#40;StopButton&#41; 
				debug.print "StopButton Pressed"
				
			Case GetButton&#40;GoButton&#41; 
				debug.print "GoButton Pressed"
	End Select
	Loop while &#40;Not GetButton&#40;StopButton&#41;&#41;
	
	Debug.print "Test complete"


End Sub


Public Function GetButton&#40;ByVal ButtonNumber As Byte&#41; As Boolean 

    Const ButtonPressed As Byte = 0 

    Select Case ButtonNumber 
        Case 1 
            GetButton = &#40;GetPin&#40;Button1Pin&#41; = ButtonPressed&#41; 
        Case 2 
            GetButton = &#40;GetPin&#40;Button2Pin&#41; = ButtonPressed&#41; 
        Case 3 
            GetButton = &#40;GetPin&#40;Button3Pin&#41; = ButtonPressed&#41; 
        Case 4 
            GetButton = &#40;GetPin&#40;Button4Pin&#41; = ButtonPressed&#41; 
        Case Else 
            GetButton = False 
    End Select 
End Function
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

spamiam wrote:I compiled it in Native mode and looked at the C output. It looks fine to me!
You've run into an error that was found and corrected last week (currently being tested for release). The issue arises with the code generated for the button testing code in GetButton(). An excerpt of the generated code appears below.

Code: Select all

uint8_t _zv_selectValTemp01;
_zv_selectValTemp01 = zp_ButtonNumber;
if &#40;_zv_selectValTemp01 == 1&#41;
&#123;
  zr_GetButton = !ZX_BOOL&#40;&#40;getPin&#40;7&#41;&#41;&#41;;
&#125;
else if &#40;_zv_selectValTemp01 == 2&#41;
The problem is the use of the logical negation on the result of the ZX_BOOL() macro. The macro returns either &H00 or &Hff corresponding to ZBasic's False and True values. The logical negation, unfortunately, converts these to 1 and 0, respectively. This causes the comparison with True (back in Main()) to always fail since neither of those values corresponds to True.

The GetButton() function can be rewritten to avoid the problem as shown below.

Code: Select all

Public Function GetButton&#40;ByVal ButtonNumber As Byte&#41; As Boolean
    Const ButtonPressed As Byte = 0
    GetButton = False
    Dim buttonState as Byte
    Select Case ButtonNumber
    Case 1
        buttonState = GetPin&#40;Button1Pin&#41;
    Case 2
        buttonState = GetPin&#40;Button2Pin&#41;
    Case 3
        buttonState = GetPin&#40;Button3Pin&#41;
    Case 4
        buttonState = GetPin&#40;Button4Pin&#41;
    Case Else
        Exit Function
    End Select
    If &#40;buttonState = ButtonPressed&#41; Then
      GetButton = True
    End If
End Function
If the button numbers will always begin with 1 and be sequential, the function can be simplified as shown below.

Code: Select all

Public Function GetButton&#40;ByVal ButtonNumber As Byte&#41; As Boolean
    Const ButtonPressed As Byte = 0
    Dim buttonPins as ByteVectorData&#40;&#123;
        Button1Pin, Button2Pin, Button3Pin, Button4Pin
    &#125;&#41;

    GetButton = False
    If &#40;ButtonNumber <= CByte&#40;UBound&#40;buttonPins&#41;&#41;&#41; And _
            &#40;GetPin&#40;buttonPins&#40;ButtonNumber&#41;&#41; = ButtonPressed&#41; Then
        GetButton = True
    End If
End Function
- Don Kinzer
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

dkinzer wrote:You've run into an error that was found and corrected last week (currently being tested for release).
Ah, a week or 2 too late for me to have been helpful!

The GetButton() function can be rewritten to avoid the problem as shown below.
That rewritten code looks really good. Actually it is more legible than the code as it currently exists. The GetButton() function is one of the routines that was originally written by Netmedia in their software for this hardware that I never bothered to change. If I were going to write it, it would have ended up looking like what you suggested, but probably not so good.

If the button numbers will always begin with 1 and be sequential, the function can be simplified as shown below.
There is no reason the button numbers COULDN'T be starting at 1 and sequential. I believe that they are.

I will await the update, but in the meantime, I will modify the code to work with the existing compiler.

As far as I can tell, this is the only compiler issue (other than it not complaining about an excessively small task stack as discussed in another thread) that I encountered in my conversion of a large BasicX project to Native Mode ZBasic.

-Tony
mikep
Posts: 796
Joined: 24 September 2005, 15:54 PM

Post by mikep »

spamiam wrote:
dkinzer wrote:You've run into an error that was found and corrected last week (currently being tested for release).
Ah, a week or 2 too late for me to have been helpful!
Here is the thread where I first reported this problem: http://www.zbasic.net/forum/about1031.html

I had a large body of code which made it difficult to isolate the problem. I used a simple workaround for a while. I eventually found time to narrow down the code to a 50 line test case which I sent to Don on 9/22. He was able to quickly diagnose the problem and supply a fix.

So you can blame me for not having this fix earlier :)
Mike Perks
spamiam
Posts: 739
Joined: 13 November 2005, 6:39 AM

Post by spamiam »

mikep wrote:Here is the thread where I first reported this problem: http://www.zbasic.net/forum/about1031.html
I had seen that thread. I was not at all sure I understood what it was doing wrong adn what the fix had been. I now can see that the native mode evaluation of boolean results might have played a part in your reported problem.

-Tony
Post Reply