I've written about the Self programming language before and still occasionally fire up the GUI environment to explore prototype object development. The Self implementation is JIT based and doesn't have an interpreter. I've wanted to have the Self environment running on a mobile device but most tablets and phones are ARM based and Self doesn't have an ARM backend.
Intel based mobile devices are starting to appear however so I decided to try and get Self running on one. The GUI backend for Self on Linux uses X11 and it's a bit too large a project to do an Android GUI backend so I just tried getting the console REPL of Self working.
Building on Linux
My first step was to revive my port of the Self build system that uses Tup instead of the original custom shell scripts. By doing this I'd gain a better understanding of how Self is built and then move to using Android tools. My rebased version of Self that uses
tup to build is in the
tup branch of my Self github fork. With
tup installed this can be built with (probably works on Linux only, sorry):
$ git clone https://github.com/doublec/self $ cd self $ git checkout -b tup origin/tup $ tup init $ tup upd
This creates a
Self executable in the root of the Self checkout. A bootstrapped snapshot can be created with:
$ cd objects $ ../Self Self Virtual Machine Version 4.1.13 Copyright 1989-2003: The Self Group (type _Credits for credits) for I386: LogVMMessages = true for I386: PrintScriptName = true for I386: Inline = true for I386: SICDeferUncommonBranches = false (not implemented) for I386: SICReplaceOnStack = false (not implemented) for I386: SaveOutgoingArgumentsOfPatchedFrames = true VM# 'worldBuilder.self' _RunScript
'worldBuilder.self' _RunScript command loads a script that loads the code for the standard Self runtime. It prompts if you want
UI2, which you do if you want the GUI, and
UI1, which you don't unless you want to explore the old gui.
Once loaded you can run some basic commands:
"Self 0" 'hello world' print hello world'hello world' "Self 1" 100 factorial. a bigInt(9332621544394415...00000000000000000000) "Self 2" [ 1000 factorial ] time. 1552 "Self 3" desktop open.
The last comand,
desktop open, runs the Self GUI. You can see a screencast of me using the GUI in my displaying images with Self post.
Android Standalone Toolchain
To build Self for Android we need to generate a standalone toolchain from the Android NDK. To generate an x86 toolchain:
$ cd $NDK_HOME $ ./build/tools/make-standalone-toolchain.sh \ --arch=x86 \ --install-dir=/somewhere/stk
This generates the toolchain and copies it to the
/somewhere/stk directory. That should be changed to where you want it installed and it needs to be added to the path:
$ export PATH=/somewhere/stk/bin:$PATH
termlib from the ncurses library. This can be built from source and installed using the standalone toolchain:
$ wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz $ tar xvf ncurses-5.9.tar.gz $ cd ../ncurses-5.9 $ ./configure --host=i686-android-linux \ --prefix=/somewhere/stk \ --with-termlib $ make $ make install
prefix in the configure line above will install it in the location of the standalone toolchain so it can be found easily when building Self.
I've generated a patch file that allows building Self in Android. It's pretty rough but gets the console REPL working and can then be fixed up later. To apply and build:
$ git clone https://github.com/doublec/self $ cd self $ git checkout -b tup origin/tup $ curl http://bluishcoder.co.nz/self/android.patch | patch -p1 $ tup init $ tup upd
The resulting executable should be pushed to a directory on the Android device. Pushing the
objects directory will provide the files to allow bootstrapping the Self runtime system:
$ adb push Self /data/local/tmp $ adb push objects /data/local/tmp $ adb shell device$ cd /data/local/tmp device$ chmod 0755 Self device$ ./Self VM# 'worldBuilder.self' _RunScript
Running the benchmark suite on my laptop gives about 2 seconds elapsed time. On the Asus Fonepad it's 10 seconds, so approximately 5x slower. The benchmark can be run with:
"Self 0" [ benchmarks run ] time
A precompiled binary is available at i686-android-linux-Self.bz2. Uncompress it before copying it to the device. You'll need the
objects directory from the git source to boostrap the runtime environment:
$ wget http://bluishcoder.co.nz/self/i686-android-linux-Self.bz2 $ bunzip2 i686-android-linux-Self.bz2 $ mv i686-android-linux-Self.bz2 Self $ adb push Self /data/local/tmp $ git clone https://github.com/doublec/self $ cd self $ git checkout -b tup origin/tup $ adb push objects /data/local/tmp ...as previously to run...
This provides basic console Self usage. It requires knowing how to program in Self without using the GUI, which is not the most common way of writing Self programs. An interesting next exercise would be trying to get a GUI working.
The images below show Self running on two x86 Android devices. On the left is a screenshot of running on a Samsung Galaxy Tab 3 10.1 and on the right running on an Asus Fonepad with bluetooth keyboard. Click on the images for the larger version.
Unfortunately this build doesn't work on ARM as mentioned previously. I suspect an ARM backend would be a significant amount of work.
For more reading on Self: