Funny compiler bug

image

Const AutoEol As Boolean = True

Const LF As String = &u10

Var StrLForNotEnded As String = If(AutoEol, LF, "")

Var StrSysOrNotEnded As String = If(AutoEol, EndOfLine, "")

It‘s the analyzer, not the compiler :wink:

1 Like

Could it be the compiler was expecting EndOfLine.some _value ?

You can invoke the linter with ^K or the compiler with ^B. Same mess.

Nope.

“Expected class EndOfLine, but got TextLiteral”

EndOfLine in Xojo translates to the equivalent TextLiteral for the current system, and that’s a valid value. The funny error is “I expected an error, but found a valid value, so I’ll consider it an error” :laughing:

In case of someone wanting a simple workaround:

Const AutoEol As Boolean = True

Const LF As String = &u10

Var StrLForNotEnded As String = If(AutoEol, LF, "")

Var StrSysOrNotEnded As String = If(AutoEol, EndOfLine+"", "")

The documentation reads:

result = EndOfLine

Part Type Description
result String The end of line String for the platform being compiled.

or
result = EndOfLine.EndOfLineType

Part Type Description
result String The end of line String specified by EndOfLineType.
EndofLineType String The end of line String being requested.

The choices are:

  • Windows
  • Unix
  • macOS|

Can it be that EndOfLine by itself does not return a string ? If so, that is a bug !

What happens if you type EndOfLine.MacOS ?

Again, everybody uses this for ages. EndOfLine by itself is the literal string equivalent EOL for the current system, as stated in your print of the manual above. The compiler itself calls it “TextLiteral” in the “Error”. Then when I add a empty string to the value, doing nothing, it works as it should.

It will return what you asked for, but not what I asked for.

So in this case the compiler does not complain. Looks like a bug.

I understand, but that does not prevent a developer, or even Apple, from breaking the code…

Out of curiosity, what are the OS and Xojo versions ?

The compiler doesn’t do the operator convert or whatever magic is needed to covert EndOfLine to text. The problem is the second argument and third argument of your if(condition, a, b) are different types and the in-line if requires them to be the same type.

2 Likes

seems EndOfLine does not return a string as the manual said.
Var s As String = If(True,CType(EndOfLine,String),"")

The destination, the left side of the attribution, is String, all the operands of an “inline” (not function) IF are strings, in case of any of those contents having some type of type selection, instead of fixed one, the selection to be tried is the destination one, the attribution, and that means, a String in this case.
The “inline” IF is not working as a real inline IF, because if

Var StrSysOrNotEnded As String = EndOfLine

Works; an inline

Var StrSysOrNotEnded As String = If (True, EndOfLine, "")

Should too.

Actually @Jason_King is right, lets clear that out.

Actually EndOfLine is an Object that returns a string, NOT a “literal string”.

When you send a OBJECT and a string to the If operator, you get exactly the behavior documented: "Having no common type results in a Type Mismatch compile error."
Kind of weird redaction but is documented, different types, you get the error.

And this is the problem, you are not understanding what the compiler is telling you.

Lets translate the “Expected class EndOfLine, but got TextLiteral” to a more verbose thing the compiler may say: "I got a string in the second parameter but I was expecting a Object of type EndOfLine in there BECAUSE you put a Object of type EndOfLine in the first parameter and both should be the same type.

In other words, the compiler first evaluates if the two passed values are of the same type (doesnt care if the object will return a string), if they are not the same type, you get the Type Mismatch error.

Of course, Xojo could change the IF behavior internally to first evaluate the expresions pased and THEN evaluate if the results of both expressions are the same type. But, that is another thing.

In this case, the + Operator forces the compiler to first evaluate the EndOfLine object to make the concatenation and then the result string is passed, so, both values passed are the same type.

2 Likes

An inline function would be forced to evaluate to the target type, it’s not the same as a function and parameter types, I know that I forced it as if it was one , because I perceived the weird way Xojo behaved, the worse of 2 worlds. :smiley:

As an Inline it should render as intended, as a function the same, but it gets confused and ends needing a conversion tip.

The other way to render as expected would be having a function with the expected signatures, so Xojo didn’t get confuse on how to solve the target type, like:

Public Function IIF(first As Boolean, s1 As String, s2 As String) As String
  If fisrt then
    Return s1
  Else
    Return s2
  End
End Function

Var StrSysOrNotEnded As String = IIf(true, EndOfLine, "") // works
2 Likes

Ivan explained how to read and understand the error message. Anyway, this is compiler-, sorry, analyzer-stupidity; we have a statement of type string, so the result of the expression has to be of type string. Therefore all types are known and IMHO there‘s nothing wrong to expect that this works.

1 Like

In line if does not do type coercion. It is an operator, not a function. If you call a function the type is coerced for you. See the notes section: https://documentation.xojo.com/api/code_execution/if.html

I suspect that if you flipped the order so the string is first it may “work” like you expect since then it is clear that the EndOfLine OBJECT has to be converted to the common type with operator convert. But the compiler can’t make that assumption since the first value of the operator is an object not a string literal.

Then you just need an infinite number of functions to acomodate all posible combinations of objects passed :rofl:

OR you can use a single function using variants:

Public Function IIF(first As Boolean, v1 As Variant, v2 As Variant) As Variant
'if you use a variant, v1 will be a EndOfLine object in here, not a String 
End Function

If you use variants, the compiler CANNOT determine the type of the value at compile time. So you will end with the OBJECT passed, it is a little more trickier than it looks like at a first glance.

Anyway, the function behaves as documented and the error message is correct. Just use it as intended.

Xojo is not smart enough to take some smart considerations, it many times does simple considerations like this one (and sometimes reports confusing messages due to its rules). In the past I discussed about some features with Joe, the last “compiler architect” about how Xojo solved some expressions, I don’t remember anymore, maybe it was something about Xojo getting wrong values due to not promoting some values to the proper superior scales to accommodate larger intermediate values. I do remember it solved different things in the same fixed way, 32 bit, even when we needed 64 resolutions, disregarding the target, it just truncated the value and done, this kind of thing.

Or just change the behavior to something like real a ternary operator, where a x = if(bool, y, z) wants y and z to solve to a compatible type x.

But no need to argue anymore. The case ended posts and posts above. And the current Xojo behavior is annotated in the manual.

EndOfLine

apart of how xojo behave.
you could make a (unhopeful) feature request with EndOfLine.Automatic
because EndOfLine.Windows in IF(,) works.