RPL stackrobatics decoder
|
07-09-2018, 04:14 PM
(This post was last modified: 07-09-2018 06:06 PM by Claudio L..)
Post: #1
|
|||
|
|||
RPL stackrobatics decoder
This thread has the repeated argument of how hard it is to read RPL code.
This brings the question: could it be possible to build an RPL converter to another language, or to pseudocode, or anything a bit more readable? With a few rules, it should be possible for a simple parser to read RPL and output something more human. This would assist people in the conversion of the vast library or RPL programs to other platforms (Prime?). The decoder would scan an RPL program and output text. It would define tons of names for functions and local variables (in the example below, I used 'lxxx' for locals, and hope they don't conflict with other variables declared within the program). The rules could be very simple: * We need to define a text output for each function/command/token we want to decode * Any objects put on the stack declare new local variables, and the local variable name gets pushed on a stack instead * Any command that takes N arguments and leaves M values on the stack, will reassign the N local variables taken as arguments with the results, and declaring new locals if M>N As an example,I took a piece of code from that same thread(which derives from this post), and "mentally" scanned it with the hypothetical decoder using the rules above: Code:
After this first scan, we'd get the following output: Code:
Is that any better than RPL? Not yet. It needs tons of cleanup. Now we need a parser that does a second pass through that source with a few more rules: * In a variable definition or an expression: Check if any of the variables in the expression is used in any statements after this one. If not, then replace the variable with its value. If being used later, or if being assigned to in this same statement, just leave it as-is * In a variable definition: If a variable name being assigned to is never used afterwards (this includes the expression being assigned and all statements after), remove the whole statement, otherwise leave it. * In a variable definition: If the previous statement assigns to the same variable name, then replace the value from previous statement into the current expression, and remove the previous statement Let's see what happens to the example above when we apply these rules, pass after pass until there are no more changes: Code:
The final result is not too bad: Code:
Any more rules or suggestions to improve on this? |
|||
07-09-2018, 05:29 PM
Post: #2
|
|||
|
|||
RE: RPL stackrobatics decoder
(07-09-2018 04:14 PM)Claudio L. Wrote: As an example, I took a piece of code from that same threadI think you should have linked to post # 52. Code: MOD --> 'l4=l4 MOD l5', DROP l4,l5, PUSH 'l4' Cheers Thomas |
|||
07-09-2018, 06:12 PM
Post: #3
|
|||
|
|||
RE: RPL stackrobatics decoder
(07-09-2018 05:29 PM)Thomas Klemm Wrote:(07-09-2018 04:14 PM)Claudio L. Wrote: As an example, I took a piece of code from that same threadI think you should have linked to post # 52. Thanks, I updated the post with your suggestion. (07-09-2018 05:29 PM)Thomas Klemm Wrote: Yes, sorry for I had very limited time, perhaps I'll fix that later. The idea is that there's a stack (only used for parsing/decoding) that carries only local variable names, functions DROP all their arguments from that stack, and PUSH all their results naming them the same name as the arguments they took when possible. Ignore the quotes, ignore the order of the PUSH/DROP which I wrote backwards in many places. In that code snippet, MOD takes l4,l5 from the stack (always names), generates the output 'l4=l4 MOD l5', and leaves l4 (the name) on the stack. The + operator of course is supposed to also DROP first, then PUSH. |
|||
07-10-2018, 07:17 AM
Post: #4
|
|||
|
|||
RE: RPL stackrobatics decoder
(07-09-2018 04:14 PM)Claudio L. Wrote: Any more rules or suggestions to improve on this? Not a suggestion but looking at Thomas Okken's program here: Code: << DUP 1 - -> n n1 I wonder how you would ever end up with something like this: Code: double[][] hilbert(int n) { Commands like DUPN, ->LIST or ->ARRY consume or produce an arbitrary number of parameters. We know their exact numbers only at runtime. Thus using local variables like in case of + or MOD wouldn't work. And then there are idiomatic ways to do something like looping through an array. C Code: const char* name = "Claudio"; Python Code: name = "Claudio" Of course we could mimic the same behaviour in Python: Code: name = "Claudio" But that would not be considered Pythonic. Thus I'm not sure if it really helps to automatically translate RPL into other languages. Most probably you end up with something that is not idiomatic and will be hard to understand. However it could be helpful to automatically create stack-diagrams, e.g. when calculating the complex arccos function. Cheers Thomas |
|||
07-10-2018, 04:42 PM
Post: #5
|
|||
|
|||
RE: RPL stackrobatics decoder
(07-10-2018 07:17 AM)Thomas Klemm Wrote: Not a suggestion but looking at Thomas Okken's program here: Yes, those commands are trouble, one way to handle them could be for this decoder to explicitly output those "push/drop" that I was doing in the background, then have special rules to cancel them out and remove them in the cleanup phase. The stack would then be used as a vector, and whatever is not removed would look like the user storing elements in a vector. Now the C code you show is not the target of this decoder, I wasn't thinking of specifically targetting constructs of a different language, but mostly to help the reader understand the algorithm by turning it into code in a language he's more familiar with. The decoder cannot rewrite an algorithm, merely try to present it in a way the programmer would be able to understand and "recode" properly in a language of choice. Back to the example you presented, with explicit stack being output for example with a vector called 'stk' and an index called 'stkidx': Code:
Which results in: Code:
Now applying the same 3 previous rules + the new "stack" rule for cleanup. * Whenever stkidx-- is found, search for a previous stk[stkidx++]=... statement, but do not cross { } boundaries. If found, remove both statements. For clarity, let's apply the new rule first: Code:
Now let's do the other rules with the cleaner output: Code:
And this leads to the following final code: Code:
It's a bit convoluted at the end, not sure if it helps as it is. To make it more like the actual code you would write, a more advanced decoder should detect that the loop 'for tmp2=0 to 1 ...' is determined at compile time, and should try to unroll the loop and simplify further, showing that l15[1]=l15[2]=n, replacing and removing it all. It would help a lot with readability in the last part, which is merely trying to fill up a matrix, the first couple of loops where the actual math is done came out pretty nice. Anyway, this was a nice experiment as a proof of concept, perhaps one day I'll actually code it for newRPL giving it the power to decompile RPL into something like Lua or Python. |
|||
07-11-2018, 11:24 AM
Post: #6
|
|||
|
|||
RE: RPL stackrobatics decoder
Nice challenge!
Wikis are great, Contribute :) |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 1 Guest(s)