2013-09-11
Running the Self Programming Language on Android
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
The '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
Android ncurses
Self uses 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
The 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.
Android 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
You can also run Self
from within a terminal emulator. If you do this I recommend installing the Hacker's Keyboard as well.
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
Binaries
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...
Summary
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:
- Self Handbook
- Self Papers
- Prototype Based Programming Languages
- Attack of the clones
- self-interest mailing list
- Self IRC channel is #self-lang on Freenode