converting Calc functions to jump functions

Eike Rathke erack at redhat.com
Fri Jun 3 12:41:12 UTC 2016


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/libreoffice/attachments/20160603/a69a9010/attachment.sig>


More information about the LibreOffice mailing list