Apologue: Parable on iOS

I recently began working on an interface for Parable using a native iOS UI. At present it's still really rough in terms of UI, but it has finally reached a point where the core functionality is working.

I have considered running code on the device, but for now will use the server-side implementation of Parable instead. The Python implementation is already working nicely and is much better tested than the C implementation. And this avoids a bunch of battery drain, memory, and onboard performance issues. (Though it does present some issues with regards to bandwidth. A typical response set is around 500KiB in size).

So at this point I can launch it, enter code, and get a resulting stack. But there's a lot more that can be done. The server side response set includes a lot of other things (like the symbol table, memory maps, and a memory dump) that should be exposed via the client UI. My intention now is to finish the client side data parsing, refactor the view and model implementations, and then refine the interface into something that's substantially more pleasing to work with. Then I can start adding in other useful things, like a dictionary and memory view.

It also gives me a motivation to improve the server side. I really should cache the stuff that's not immediately needed (raw memory dump), and maybe allow for incremental modifications to a session so that each evaluation doesn't have to start from scratch.

An Overview of Function Classes in Retro

For the past few generations, the interpreter and compiler for Retro have been built around a concept I refer to as a function class. Specifically, the behavior of the system is determined by functions that handle the named symbols in the dictionary as they are encountered. For instance, things that are always run when encountered are handled by one function. Things that get compiled during a definition, but run when interpreting are handled by a separate function. And so forth.

This is a little different than in a classical Forth approach. A classical Forth will have a bit field in the header, with a bit for "immediate" functions, and maybe others for "compile only" or other special cases. Retro instead has a pointer to the class handler function for the entry.

When a function is found, a pointer to its definition (xt) is pushed to the stack. Then a pointer to the class handler is pushed. And finally the class handler is invoked (normally via withClass). The handler will look at the xt on the stack, and any internal system states it cares about, then do the proper action with the xt.

So a simple interpreter-only system basically just a simple class handler something like:

: .always-run( Xt - )
do ;

If we want to allow for compiling, this is easy enough to add. We could simply add a compiler variable to tell us if the compiler is on or off and then do:

: .compile-or-run( Xt - )
compiler @ [ , ] [ do ] if ;

There are no defined limits on the number of possible class handlers, or the amount of state they can process. We could easily define class handlers for different data types, functions that can only be invoked at compile time, optimizing definitions, inlining functions, or other behaviors with ease.

This has many benefits to me. It keeps the main processing loop simple, allows easy expansion and customization going forward, and neatly folds a lotion functionality  into a simple conceptual model.

Pen Review: Cross Classic Century, Lustrous Chrome

Having recently completed ten years with my current employer, I was given a fountain pen. This is the Cross Classic Century, Lustrous Chrome. 

The box.

Packaging

The packaging is pretty basic. It comes in a brown box, which says Cross in silver lettering. There's a pull tab at one end, which slides out to revel the pen and a couple of ink cartridges. Nothing too fancy, but it's sufficient.

Body and Build

It's almost all shiny chrome. It has thin lines embedded down the whole length (in groups of three), which helps to hide fingerprints. I do worry that it'll show scratches/scuffs pretty quickly though.

Just a nice, plain pen

Just a nice, plain pen

The cap is metal, with the exception of a small black plastic cap on the end. The clip is pretty much unremarkable. It's plain, except for the word Cross embedded into it. It's not spring loaded, but holds ok on my shirt pocket. The cap screws onto the pen for closing and posting.

The body is pretty plain as well. It's all metal, including the section. The threads for the cap aren't annoying, and it feels pretty good to hold.

Nib

I like broad nibs, so received this in the widest size available, which is a medium. It writes pretty smoothly, with no adjustments needed. It's pretty plain. Shiny metal, just like the rest of the pen, with the word Cross at the base, an M on one side, and some horizontal lines for decoration.

It's ok. Not as nice as some of my pens (I find my Kaweco Liliput's broad nib and the medium nib on my Lamy Joy to be smoother), but it's definitely usable. 

Ink

This pen apparently only works with Cross slim cartridges. Along with the two black cartridges included in the pen, I was given twelve additional ones separately. I'll probably try refilling them with something other than black once I use up a few of them.

The Cross black is plain, satisfactorily dark, and works decently on the cheap paper we have at work. It's just not inspiring.

Closing Thoughts

This isn't a bad pen. It writes pretty well, and has a decent overall build quality. The biggest downside this is the cap. It screws on, but is not secure. When fully tightened, it still wiggles slightly, and it has an alarming tendency to work its way loose. I can't feel comfortable keeping it in my pocket, so it'll end up being a desk use pen and not part of my EDC.

NSUserDefaults

After working my way through the use of property list files on iOS, it turns out that I could have just used NSUserDefaults, which would have been much simpler for storing simple data sets. Oh well, live and learn.

Here's a snippet from a prototype of my blood glucose recording app (in Swift):

    var results = NSUserDefaults.standardUserDefaults()

    var tbd: NSMutableArray
    tbd = []
    if let measures = results.arrayForKey("records") {
        tbd.addObjectsFromArray(measures)
    }

    var these: NSMutableArray
    these = []
    if let dates = results.arrayForKey("dates") {
        these.addObjectsFromArray(dates)
    }

    println(tbd.lastObject)

    tbd.addObject(sugar)
    these.addObject("\(stamp)")

    // set the values for the keys
    results.setObject(tbd, forKey: "records")
    results.setObject(these, forKey: "dates")

    // update the data store
    results.synchronize()

With this, I've begun factoring the logging and analysis functions into a separate class, and simplifying my view controller. So I guess this makes headway towards actually building something using a proper MVC approach.

Update on Parable via HTTP

I'm getting closer to having a fully functional interface to Parable for use over an HTTP connection. Presently the interface takes a single parameter (code) and returns a JSON structure containing the original code, a formatted stack (with Parable-style prefixes, etc), the raw stack (and corresponding types), the dictionary symbols (and a map to the slices containing them), a memory map, and a dump of the slices.

Presently the output is too big. Depending on the memory configuration, it's ranging from around five hundred kilobytes (500K) to just under nine megabytes (9MB). This is ok on my test infrastructure (running on a Mac Mini, with the client application on my MacBook Air on the same LAN), but too much to be practical over the internet as a whole.

I'll be dealing with this by splitting the memory dump into a temporarily cached record that can be retrieved as needed, and only transmitting the relevant bits as they are requested. I still need to implement some things for this, but some early prototypes look promising. I want to add an API key and rate limiting, and then support for passing in JSON as an input.

Eventually it should be possible to setup a reloadable session on the server, and execute code, receive results, and continue without needing to restart a fresh instance each time. This will take a while to work out, but it'll finally let me accomplish one of my early goals of having a programming environment that's easily used across devices.