Bug? [ABMaterial][B4J] Found a debilitating bug thats driving me nuts

techknight

Well-Known Member
Licensed User
Longtime User
I found a compiler bug that is driving me nutso. I do not know if it is related to B4J, or ABMaterial so I posted under both tags.

Its debilitating because I have to write a super huge select case statement. Otherwise it doesn't work unless its in Debug mode.

Here is a working subroutine:
B4X:
Sub myCanvas_ObjectDown(objectID As String)
    If Buttonpressed = True Then Return
    Buttonpressed = True
    Dim myCanvas As ABMCanvas = page.Component("myCanvas")
    Select Case objectID
        Case "mnupower"
            If EngineMS05.Connected = False Then
                page.Pause
                CallSub2(EngineMS05, "Connect", Me)
            Else
                CallSub(EngineMS05, "Disconnect")
            End If
        Case "mnucleargame"
            page.Msgbox2("ConfirmClearGame","Are you sure you wish to clear the game?","Clear Game","YES","NO",False,ABM.MSGBOX_TYPE_QUESTION,False,ABM.MSGBOX_POS_CENTER_CENTER,"")
        Case "mnusetclock"
            If EngineShared.ClockStopped = True Then SetClock
        Case "mnutimeofday"
      
'        Case "cmdhomeup"
'            CallSub(EngineShared,"cmdHomeUp")
        Case "cmdhomedown"
            CallSub(EngineShared,"cmdHomeDown")
        Case "cmdguestup"
            CallSub(EngineShared,"cmdGuestUp")
        Case "cmdguestdown"
            CallSub(EngineShared,"cmdGuestDown")
        Case "cmdstartstopclock"
            CallSub2(EngineShared,"cmdStartStopClock",Me)
        Case "cmdperiodup"
            CallSub(EngineShared,"cmdPeriodUp")
        Case "cmdperioddown"
            CallSub(EngineShared,"cmdPeriodDown")
    End Select
    Sleep(150)
    Buttonpressed = False
    myCanvas.Refresh
    'Log("ObjectD: " & objectID)
End Sub

That code works fine. However, noticed I commented out the "cmdhomeup" function. I figured it would get picked up by the Case Else, and then forward cmdhomeup through the CallSub function. You think it would work, right? Well....

However, I said, why not shorten it to just this:
B4X:
Sub myCanvas_ObjectDown(objectID As String)
    If Buttonpressed = True Then Return
    Buttonpressed = True
    Dim myCanvas As ABMCanvas = page.Component("myCanvas")
    Select Case objectID
        Case "mnupower"
            If EngineMS05.Connected = False Then
                page.Pause
                CallSub2(EngineMS05, "Connect", Me)
            Else
                CallSub(EngineMS05, "Disconnect")
            End If
        Case "mnucleargame"
            page.Msgbox2("ConfirmClearGame","Are you sure you wish to clear the game?","Clear Game","YES","NO",False,ABM.MSGBOX_TYPE_QUESTION,False,ABM.MSGBOX_POS_CENTER_CENTER,"")
        Case "mnusetclock"
            If EngineShared.ClockStopped = True Then SetClock
        Case "mnutimeofday"
      
        Case "cmdstartstopclock"
            CallSub2(EngineShared,"cmdStartStopClock",Me)
        Case "cmdsetyards"
            SetYards
        Case Else
            Log("hi")
            CallSub(EngineShared,objectID)
    End Select
    Sleep(150)
    Buttonpressed = False
    myCanvas.Refresh
'    Log("Object: " & objectID)
End Sub

This way, all strings that contain the ObjectID just gets forwarded to the appropriate function in the EngineShared code module. This way I dont have to write a huge select case statement for each and every function.

This introduces a bug. All the subroutines in the EngineShared module go into purple squigly iines saying cmdhomeup is not used, or such and such is not used.

So, in Release mode. NONE of my "Case Else" subroutines will fire. If I run in Debug mode, it all works fine!

Why??
 

alwaysbusy

Expert
Licensed User
Longtime User
I don't think it is ABM related as this looks like normal B4J code. Just to try, instead of using your inline if - thens, change them using end if.

e.g.
B4X:
If EngineShared.ClockStopped = True Then SetClock

becomes:

B4X:
If EngineShared.ClockStopped = True Then
   SetClock
End if

and in your Case "mnutimeofday", set something like log("empty")

EDIT: I also just noticed your sleep() call. what happens if you comment this line?
 

techknight

Well-Known Member
Licensed User
Longtime User
Those events work fine.

The trouble is "Case Else"

Anything that falls under that, fails to run unless its in Debug mode.
 

mindful

Active Member
Licensed User
Maybe EngineShared can't handle data from other thread, if this is the case maybe you should switch to CallSubDelayed ...

Another thing that is possible is that the objectID you receive from abmaterile are lower case and your subs name are camelcased ... i don't think that callsub ignores casing.. you should transfrom your subs into lowercased ...

Also in your EngineShared where it says it that some subs aren't used anywhere you should place an 'ignore after the End Sub declaration. It provides this warnings because b4j doesn't know what will be the outcome of ObjectId received from AbMaterial therefore can't decide if that sub is used.
 

techknight

Well-Known Member
Licensed User
Longtime User
I put the Sleep there because I was having issues with "bouncing" of the buttons. a single tap on the display could fire that puppy 3 or 4 times in a row.
 

mindful

Active Member
Licensed User
. i don't think that callsub ignores casing..
On second thought it does igone casing :| sorry for the confusing ... you can see in ABMaterial page_parseevents that it ignores casing as that method uses kind of the same thing...

I saw that you placed a Log("hi") in Case Else ... does that fire ?
 

techknight

Well-Known Member
Licensed User
Longtime User
No as I am not sure what it does?

Edit: Yes I just did, and no it doesnt work. Works in Debug build, but not Release build.
 

techknight

Well-Known Member
Licensed User
Longtime User
Definitely a bug guys. Even tried 'ignore which makes the error go away, but doesnt fix the problem.
 

techknight

Well-Known Member
Licensed User
Longtime User
B4X:
Sub cmdHomeUp
    If Home = 199 Then 
        Return
    Else
        Home = Home + 1
    End If
    RefreshDisplays(0)
End Sub
 

techknight

Well-Known Member
Licensed User
Longtime User
Yep. If I do a Case "Subroutine here" and then callsub(EngineShared "Subroutine") everything is fine as I said before.

It only breaks if if I do Case Else Callsub(Engineshared, objectid) This basically makes the subroutine to be called held in a variable.

Works perfectly in Debug mode like i said. but it does not work at all in Release mode.
 

mindful

Active Member
Licensed User
Like I said ABMaterial parseEvents event uses case else ... how do you know he sub isn't called ? Have you put a Log as the first line in that sub which isn't called ? Are there any errors ? - beause if you use callsub on a sub that doesn't exists an error willbe thrown

I asking because i use callsub and callsubdelayed with variables and it works vey well ...
 

techknight

Well-Known Member
Licensed User
Longtime User
Yes I have. And no errors. Guy, I wouldn't be posting here if I didn't try all of this.
 

mindful

Active Member
Licensed User
Didn't mean to offend you ... just was trying to figure it out why it doesn't work ... because like I said I use callsub and callsubdelayed with variables (whitout the hardwritten strings) and never failed ...
 

techknight

Well-Known Member
Licensed User
Longtime User
I use variables all the time, the one thing I havent used as a variable was the physical name of the subroutine itself. Thats where things break.
 
Top