ID:2950238
 
Resolved
Surrounding an expression with parentheses inside of a ternary operator did not correctly reset the parsing context, resulting in confusion about how to handle the : operator.
BYOND Version:515
Operating System:Windows 11 Home
Web Browser:Firefox 131.0
Applies to:Dream Maker
Status: Resolved (515.1646)

This issue has been resolved.
Descriptive Problem Summary:

The : operator has some behavioural issues when used on arrays inside of a terniary statement.

Numbered Steps to Reproduce Problem:

Attempt to compile the code provided below, which will result in a failure

Code Snippet (if applicable) to Reproduce Problem:
/datum
var/four = 4
var/five = 5

/proc/main()
var/list/d = list()
d += new /datum()
return 4 == 5 ? d[1]:four : d[1]:five


Expected Results:

Compilation success

Actual Results:

Compilation failure

Does the problem occur:
Every time? Or how often? Every time
In other games? Compilation issue
In other user accounts? Compilation issue
On other computers? Compilation issue

When does the problem NOT occur?

When not using a terniary statement:

/datum
var/four = 4
var/five = 5

/proc/main()
var/list/d = list()
d += new /datum()
return d[1]:four


When not using an array (Gives output you would expect):
/datum
var/four = 4
var/five = 5

/proc/main()
var/d = new /datum()
return 4 == 5 ? d:four : d:five


When using ?:

/datum
var/four = 4
var/five = 5

/proc/main()
var/list/d = list()
d += new /datum()
return 4 == 5 ? d[1]?:four : d[1]?:five


Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)

Tested on 514, also fails

Workarounds:

The ?: operator works correctly, and the following code will compile:

/datum
var/four = 4
var/five = 5

/proc/main()
var/list/d = list()
d += new /datum()
return 4 == 5 ? d[1]?:four : d[1]?:five
Note that compilation also fails if parenthesis are used, even if it gets confused with multiple :, we would expect it to always work when parenthesis are present:
/datum
var/four = 4
var/five = 5

/proc/main()
var/list/d = list()
d += new /datum()
return 4 == 5 ? (d[1]:four) : (d[1]:five)


This code still fails to compile.
In response to PowerfulBacon
PowerfulBacon wrote:
> /datum
> var/four = 4
> var/five = 5
>
> /proc/main()
> var/list/d = list()
> d += new /datum()
> return 4 == 5 ? (d[1]:four) : (d[1]:five)
>


This code still fails to compile.

This, at least, compiles for me.
In response to PowerfulBacon
This makes no sense, and F0lak has said it works as expected. The parsing context is completely changed by the introduction of parentheses, so as long as there's a space before the : then it should be fine.

I'll look into the : operator favoring ternary interpretation. This is very tricky thing however because the : path operator in this situation is otherwise ambiguous.
I have failures with the block of code that uses parenthesis in 514.1589 (tested locally), and 515.1634 (using a bot with the DM cog)

I get the following errors:
error: :: missing comma ',' or right-paren ')'
error: ): expected }
error: location of top-most unmatched {
It also fails to compile in 515.1644 tested using Wrench in the offical byond discord: https://discord.com/channels/725444629172060262/ 725459725012959233/1300212968004386908

I also tested it with both tab-based and space-based indentation, still getting the same issue with mismatched brackets to the same results (?: works fine, but : alone doesn't work)
Lummox JR resolved issue with message:
Surrounding an expression with parentheses inside of a ternary operator did not correctly reset the parsing context, resulting in confusion about how to handle the : operator.
I was able to confirm the parentheses case. That looks like a very very old bug, where the parser simply wasn't resetting properly inside of a ternary.

For the other case, there's a problem when it comes to legacy code, since legacy code didn't have chained . and : operators that could follow proc calls and list index operators. This is something I might be able to address in 516 with a pragma.
Thanks for taking the time to look into this