[ to-lowercase new-slice [ dup letter? [ $a :n - #13 + #26 rem $a :n + ] if-true slice-store ] for-each-character current-slice :s ] 'rot13' define
: rot13 ^strings'toLower here ^buffer'set [ @ dup 'a 'z within [ 'a - 13 + 26 mod 'a + ] ifTrue ^buffer'add ] ^types'STRING each@ here ;
These are using basically the same approach, but differ slightly due to the underlying language and standard library. In breaking this down, I'll put Parable code on the top line and Retro code on the following one.
Each starts by converting a string to lowercase:
Then it sets up a buffer for the encoded string:
new-slice here ^buffer'set
Then we have a quotation that processes each character in the string. We'll look at the overall form first, and then the internals.
[ ] for-each-character [ ] ^types'STRING each@
Inside these is where all the real work is being done. First, we check to see if the character is a letter:
dup letter? @ 'a 'z within
This illustrates one important difference: Parable's combinator for iterating over the characters passes each character to the quotation, but Retro's passes a pointer to the character. We then have a conditional block:
[ $a :n - #13 + #26 rem $a :n + ] if-true [ 'a - 13 + 26 mod 'a + ] ifTrue
Retro is a little shorter here, since it's untyped (so can avoid the character to number conversions) and does not require prefixes for numbers. But the overall logic is identical. The final bit in each of these quotations is appending the possibly altered character to the buffer we created:
And the final step is to return the newly created string:
current-slice :s here
Most of the code is identical, apart from function names and prefixes. The biggest difference is that Parable's combinator for iterating over characters returns the character, whereas Retro's returns a pointer. This is a subtle difference that could cause issues in translations. I'll likely add an equivalent to for-each-character to future Retro releases to help smooth this out. The other big difference is that Parable's addressing model keeps the newly created string separate in memory. If you don't want to risk corruption of the one Retro returns, you'll need to pass it to tempString or keepString.
I'm working on some updates to Apologue. The first of these will be submitted for review on Monday, and the second will follow be a couple of weeks later.
In the first update Apologue will become a universal application. The introduction of larger screen sizes for iPhone has convinced me that it's worth adapting the UI to work on a wider array of devices. So 1.1 will add support for all current (4S, 5/5S, 6, 6+, iPad) screen sizes in both portrait and landscape.
The second update is more focused on the backend. I have several API endpoints depending on the configuration selected. Going forward this is going to be a problem. So I'm rewriting it to use a single endpoint, passing in the options instead of having a separate endpoint for each possible combination. This will take a few weeks to finish implementing and testing, but will make it significantly easier to add in new features and update to the latest Parable.
Additionally, starting with 1.1, Apologue will require iOS 8 or higher.
This has some relevance for Retro on iOS. I've been doing some experiments which look promising, merging Ngaro into a UI that reuses some pieces of code from Apologue. I'd still like to find a way to do a full terminal emulation, but accept that this is still beyond my abilities and knowledge of the API's.
Once I finish these update to Apologue I will finish adding in the layouts for each size class, create the necessary artwork assets, and then submit the first implementation of Retro for iOS for review. More on this soon.
Going slightly further than yesterday, I've implemented code to capture the output and display it below the editor. It still needs a lot of work, but is now functional on both the simulator and my iPad Mini. (I've tested 11.4 - 11.6 images with it).
I'll likely try to build a UI similar to Apologue for this, though some things will be different due to the underlying VM differences.
For those curious, I'm using a modified version of libretro.c with a thin ViewController for UI. I've removed the TTY setup in the rxPrepareOutput() and replaced the character display with code writing to a character array. The ViewController copies out the latest changes and adds them to the output area, then resets the output buffer. This is done every second or so. The stack display is updated after an evaluation completes.
I think that I'll clean up the ViewController a bit and add a tabbed controller so that additional screens will be more readily doable. And then I'll work to flesh out functionality to make it more useful.
This is all pretty early, but I'm making a little headway on getting Retro running under iOS. As of today I can:
- load the retroImage
- evaluate strings from an editor window
- display resulting stack contents
Now to capture output and display it, and then find better ways to handle input...