Skip to content

Undefined behaviour and known bugs

Thomas Jollans edited this page Aug 27, 2021 · 3 revisions

What happens when you cross the edge?

One area of undefined behaviour noted in the Mycology test suite is the question of what happens when you cross the edge fungespace with a command that operates on the ‘next character’ (not the next instruction), such as #, " or '.

RFunge takes the view that the program is in theory surrounded by an infinite amount of spaces, and should act that way whether these spaces were ever physically present in the file or not. This means # over the edge skips nothing (other than a maybe-fictional space), and '/" over the edge pick up a space. In this, it follows the behaviour of (e.g.) CCBI, cfunge and pyfunge.

An alternative approach is to imagine the rightmost column to be directly adjacent to left leftmost column, and skip (#) or read ('/") it accordingly. RcFunge 2 and Funge++ take this approach, and define ‘rightmost column’ to be the rightmost column of the file, not of the line. I think this is an unfortunate choice as it changes the behaviour of instructions depending on whether they’re on the longest line (globally) or not.

FBBI and jsFunge-98 make the curious choice of having # and ' behave like in CCBI, but having " behave like in rcFunge.

Edge cases of k

k (iterate) is a tragically misunderstood instruction. Or rather, it’s poorly defined in the spec. The spec says:

Then it finds the next instruction in Funge-space in the path of the IP (note that this cannot be a marker such as space or ;), treats it as an instruction, executing it n times. (…) However, you may pass a zero count to k, and the [next] instruction will not be executed; this can be a valuable behaviour.

So... what happens when k encounters a ; marker? Does it pretend the ; is a space? (probably not) Does it skip over the ; ... ; section? (this is more common) And what exactly does k do with a zero argument? Does it act like #? Even when it's followed by a space or ;? Does it scan to the next instruction and skip that? What if that instruction is a ;? Does it skip the ; like # would, or does it skip over the ; ... ; region as it would with a positive argument?

And what happens when k’s argument is negative? Does it reflect, act like 0k, or do nothing?

Let's do a survey of what various interpreters do right now:

rfunge and cfunge

0k skips over cmd after ;...;
3k executes cmd after ;...; thrice
02-k reflects
0k skips next command
0k ;v;vv acts like ;v;#vv

CCBI

0k skips over single ;
3k executes cmd after ;...; thrice
02-k acts like 0k
0k acts like #
0k ;v;vv acts like # ;v;vv

FBBI

0k skips over cmd after ;...;
3k executes cmd after ;...; thrice
02-k acts like 0k
0k skips next command
0k ;v;vv acts like ;v;#vv

RCFunge 2

0k skips over single ;
3k executes cmd after ;...; thrice
02-k reflects
0k acts like #
0k ;v;vv acts like # ;v;vv

PyFunge

0k skips over cmd after ;...;
3k executes cmd after ;...; thrice
02-k does nothing
0k skips next command
0k ;v;vv acts like ;v;#vv

Funge++ and jsFunge-98

0k skips over single ;
3k executes cmd between ;...;! (BAD)
02-k does nothing
0k acts like #
0k ;v;vv acts like # ;v;vv

As you can see, there’s clearly no agreement (and far be it from me to suggest that rfunge is correct here).

k and t

What happens when you iterate over a t instruction using k? It's actually fairly clear what should happen, but it requires some care to get right. Some interpreters (rfunge, cfunge, pyfunge, funge++) do the right thing. RCFunge 2 and CCBI are examples of interpreters that get it wrong, with RCFunge sending some of the child IPs in the wrong direction and CCBI sending then in wrong directions and not creating enough in the first place.

k followed by k

See the discussion here — if the instruction k is supposed to iterate on is another k, (e.g. 32kk'......>:#._@), the behaviour, both in fact and in theory, becomes very dependent on where exactly the IP’s location is deemed to be at various points during the execution of a k instruction. Undefined behaviour par excellence, if there is a correct answer to this problem, it’s possible nobody has ever implemented it.

Clone this wiki locally