Hi Winfried, On Thursday, 2016-06-02 09:18:51 +0200, Winfried Donkers wrote:
I started converting the new Calc functions IFS and SWITCH to jump functions. I experience a problem where the functions IFS and SWITCH differ from the other jump functions (IF, CHOOSE, IFERROR, IFNA). The other jump functions do 1 evaluation (of the first argument) and then jump to an argument that is to be the output. The new jump functions need to evaluate at least 2 arguments. And that is where I get stuck.
I can imagine..
The first argument is on the stack, i.e. GetStackType() returns a type and ScInterpreter::sp is 1. When I jump to the next argument to be evaluated, with aCode.Jump( pJump[ nIdx ], pJump[ pJump[ 0 ] ] ), ScInterpreter::sp is 0 afterwards.
Apart from that, aCode.Jump( pJump[ nIdx ], pJump[ pJump[ 0 ] ] ) looks wrong to me, pJump[0] returns an offset into the RPN array, which can't be used as an index for another pJump. See also the description of formula::FormulaTokenIterator::Jump() in include/formula/tokenarray.hxx For understanding it helps to step into such Jump() and see what it does to the counters and on the subsequent iteration of the while loop in ScInterpreter::Interpret() step into its condition where aCode.Next() is executed and analyze what happens to the token array and counters.
How do I get the argument I jumped to (that part works) on the stack to be evaluated?
I'm not sure at the moment. That might be a case for pushing a token array (or rather the same token array with the corresponding jump locations in this case) to execute a subroutine as result and then execute the ocIfs again. Some time ago I prepared something in interpr4.cxx Interpret(), look for ocCall, but that's not ready yet. I'd have to further work on it. It wouldn't be too hard, right now I'm just stuck with another thing. Another possibility and maybe more straight forward would be to look, for example, at IFS(x,1,a,2,b,3,c,else) as an equivalent sequence of IF(x=1,a,IF(x=2,b,IF(x=3,c,else))). So when evaluating the IFS(x,1,...) and that is not a match then discard the 'a', push the 'x' again and the next code path (jump) would be IFS(x,2,b,3,c,else). I'm not sure how feasible that is though.. it would likely mean having to calculate the jumps such that they exclude the previous two parameters and include the ocIfs OpCode when creating the jumps in the RPN compile step, except for the 'else' part. Basically both approaches would work, the latter might be even "easier" (I know it's not easy at all) to code with what is already implemented. But maybe I'm complicating things and you found some other approach and it already helps to push the original 'x' token (remembered as a FormulaTokenRef before popping the value) again and correct the pJump[pJump[0]]? Eike -- LibreOffice Calc developer. Number formatter stricken i18n transpositionizer. GPG key "ID" 0x65632D3A - 2265 D7F3 A7B0 95CC 3918 630B 6A6C D5B7 6563 2D3A Better use 64-bit 0x6A6CD5B765632D3A here is why: https://evil32.com/ Care about Free Software, support the FSFE https://fsfe.org/support/?erack
Attachment:
signature.asc
Description: PGP signature