bmx-ng / bcc

A next-generation bcc parser for BlitzMax
zlib License
33 stars 12 forks source link

Incorrect 'not equal' comparator compiles and runs #559

Closed davecamp closed 3 years ago

davecamp commented 3 years ago

This code compiles and runs with incorrectly generated c code.

SuperStrict

Function TestThis:Int(f:Byte Ptr, y:Int)
    If f != y
    EndIf
EndFunction

Print TestThis(Null, 0)

The If statement becomes

if(bbt_f==((BBBYTE*)bbt_y)){
davecamp commented 3 years ago

The expectation is for the compiler to issue an error at the != token in the BMax code.

GWRon commented 3 years ago

wrapping the "f" into brackets ... and the error is detected.

SuperStrict

Function TestThis:Int(f:Byte Ptr, y:Int)
    If (f) != y
    EndIf
EndFunction

Print TestThis(Null, 0)

Also it does not need to happen in a function...

SuperStrict
Framework Brl.Standardio

Global f:Byte Ptr
Global y:Int
If f != y
EndIf
Type TBinaryCompareExpr Extends TBinaryExpr
    Method Semant:TExpr(options:Int = 0)
...
        ty=BalanceTypes( lhs.exprType,rhs.exprType )

op is = here - so somehow the exclamation mark is eaten.

Balance types ... lhs="Byte Ptr"  rhs="Int"   op="="
GWRon commented 3 years ago

Type TParser.ParseCompareExpr() already just receives = from _toke. This method then "falls back" to various other potential expressions - until it reaches "ParsePrimaryExpr"

parseandexpr "f"
ParseCompareExpr _toke="f"
ParseBitorExpr _toke="f"
ParseBitandExpr _toke="f"
ParseAddSubExpr _toke="f"
ParseMulDivExpr _toke="f"
ParsePowExpr _toke="f"
ParseUnaryExpr _toke="f"
ParsePrimaryExpr _toke="f"

inside this method there is:

        Default
            Select _tokeType
            Case TOKE_IDENT
                Local tok:TToker=New TToker.Copy( _toker )

                Local ty:TType=CParseIdentType()
                If ty
                    expr=New TIdentTypeExpr.Create( ty )
                Else
                    _toker=tok
                    _toke=_toker.Toke()

which I extended to print out some stuff

print "  default _tokeType="+_tokeType +"  _toke=~q"+_toke+"~q"
            Select _tokeType
            Case TOKE_IDENT
                Local tok:TToker=New TToker.Copy( _toker )

                Local ty:TType=CParseIdentType()
                If ty
                    expr=New TIdentTypeExpr.Create( ty )
                Else
                    _toker=tok
print "   else1: ~q"+_toke+"~q"
                    _toke=_toker.Toke()
print "   else2: ~q"+_toke+"~q"
                    _tokeType=_toker.TokeType()
                    expr=New TIdentExpr.Create( ParseIdent(),,,unknownIdentsEvalFalse )
print "   toke="+_toke
                    ty = ParseConstNumberType()
print "   toke="+_toke
print "   expr="+expr.toString()            
print "   ty="+ty.toString()            
                    If TArrayType(ty) Then
                        If Not TArrayType(ty).elemType Then
                            TArrayType(ty).elemType = New TIdentType.Create(TIdentExpr(expr).ident)
                            expr=New TIdentTypeExpr.Create( ty )
                        End If
                    End If

                EndIf
print "   toke after="+_toke

output is:

  default _tokeType=2  _toke="f"
   else1: "!"
   else2: "f"
   toke=!
   toke==
   expr=TIdentExpr("f")
   ty=Double
   toke after==

So it seems as if ParseConstNumberType is eating it ...

And of course this method is seeing ! as declaration for "Double" (hence the ty=Double output).

So the real issue seems to be that "!" is an allowed "number type shortcut" - and that these things do not need the colon as the long versions require.


'for strings this does not work :D
'If "hi":String = "hi" Then Print "hi"
'If "hi"$ = "hi" Then Print "hi"

If 1:Int = 1 Then Print "1"
If 2% = 2 Then Print "2"
If 3! = 3:Double Then Print "3"

TL / DR

In our very specific case this is not a bug ... but simply a "cast".

Local x:Int = 1
If x:Double = 1 Then Print "1"
If x! = 1 Then Print "1"
If x != 1 Then Print "1"

it is not a cast - yet ... ah I hope @HurryStarfish can find the time to write what exactly it is :D

HurryStarfish commented 3 years ago

While @GWRon has already identified what's going on here, I want to clarify two more things: