Husk, 26 25 bytes
tGF₅0hx'o
S&≠256!ë→a□?←0c
Try it online!
Explanation
The first line is the main program, the second line an helper function that computes the output of a Deadfish command that could be 'i', 'd' or 's'.
Let's start from the first line:
tGF₅0hx'o
x'o Split the string on each 'o'
h and discard the last part
(we don't care what happens after the last 'o')
G 0 Scan this list of strings using 0 as initial value
F₅ computing the result of each Deadfish subprogram
t Discard the first value (0)
What we are doing here is splitting the Deadfish code into the subprograms preceding each output 'o', and then computing the result of each subprogram.
The result of a subprogram is computed by folding the helper function over the commands: the fold will start with the value of the accumulator coming from the previous subprogram (initially 0), and will apply the helper function to the next command and the accumulator to generate the new value for the accumulator.
Lines in a Husk program are zero-indexed and modular: referring to line ₅
here is effectively the same as referring to line ₁
, but the number of times we "loop around" back to the first line determines how the called function should be modified (in order argdup
,flip
,map
,zip
,hook
); in this case we loop around 2 times, so we flip
the helper function, passing the command ('i','d',or 's') first, and the accumulator second.
We chain together the interpretations of the subprograms by scanning over the list of subprograms. A scan G
is the same thing as a fold F
, except it returns all partial results instead of only the final one. We explicitly set 0 as the initial value, but then the result of each subprogram will be passed as the accumulator to the next subprogram. The initial value is always part of the output for a scan, so we have to discard it at the end (t
).
So, how does the helper function compute the result of a Deadfish command?
S&≠256!ë→a□?←0c Takes a character (one of "ids") and an accumulator,
returns the new value for the accumulator
c Convert the character to its codepoint value
!ë and use it to index into this list of four functions:
→ Increment
a Absolute value (dummy)
□ Square
?←0 If nonzero then decrement else return 0
S&≠256 Return the result if ≠256, else 0
The trick here is that ord(c)%4 will return a different value for each c in "ids" (respectively 1,0,3). List indexing in Husk is modular so by indexing with this value into the list of functions we will get the function we need. a
is there only to pad the list to 4 elements (because otherwise 's' and 'd' would have the same value modulo 3).
We check for -1 by only decreasing the accumulator if its value is not 0, and we check for 256 explicitly after any command.
diso
tests every functionality of the code except for 256 \$\endgroup\$