Scheme REPL on Android Part 1

These are not instructions. These are rather my notes on what I had to do to get a remote Scheme REPL running on Android.

Patch Kawa

Use default classloader instead of the android specific one. There are preprocessors involved, so the only way is to modify ifdef Android to ifdef xxAndroid.

  /* #ifdef JAVA2 */
  public static ClassLoader getContextClassLoader ()
  {
    try
      {
        /* #ifdef xxAndroid */
        //return ClassLoader.getSystemClassLoader();
        /* #else */
        return Thread.currentThread().getContextClassLoader();
        /* #endif */
      }
    catch (java.lang.SecurityException ex)
      {
        /* The .class syntax below also works for JDK 1.4, but it's just
           syntactic sugar, so there is no benefit in using it. */
        /* #ifdef JAVA5 */
        return ObjectType.class.getClassLoader();
        /* #else */
        // return thisClassLoader;
        /* #endif */
      }
  }
  /* #endif */

Set up Scheme project

Set up a Scheme-based Android project as per Per Bothner’s instructions.

Source for repl.scm (don’t use hello.scm)


(module-static #t)

(module-compile-options
 warn-unknown-member: #t
 warn-undefined-variable: #t
 )

(require 'android-defs)

(define (msg (fstring string) #!rest args)
  (android.util.Log:v "kawa-hello" (apply format fstring args)))

(define (start-repl port)
  (begin
    ; required! otherwise the getLanguage() call will fail
    (kawa.standard.Scheme:registerEnvironment)
    ; required! as Android cannot compile to java
    (set! gnu.expr.ModuleExp:alwaysCompile #f)
    (let* ((server (java.net.ServerSocket port)))
      (msg "listing on ~a (~a)" port server)
      (let ((socket (server:accept)))
        (msg "connected ~a " socket)
        (let ((in (gnu.mapping.InPort (socket:getInputStream)))
              (out (gnu.mapping.OutPort (socket:getOutputStream))))
          (parameterize ((current-input-port in)
                         (current-output-port out))
            (do () (#f)
              (try-catch
               (begin
                 (format #t "\n> " )
                 (force-output)
                 (let ((form (read)))
                   (format #t "form: ~s\n" form)
                   (format #t "~s" (eval form (interaction-environment)))))
               (e java.lang.Exception
                  (e:printStackTrace out))))))))))

(activity hello
  (on-create-view
    (begin
      (java.lang.Thread:run (java.lang.Thread:new (runnable (start-repl 4444))))
      (android.widget.TextView (this)
         text: "Hello, Android REPL from Kawa Scheme!"))))

Modify the start up file

In build.xml

   <arg value="-C"/>
   <arg file="src/kawa/android/repl.scm"/>

Deploy

Deploy and view the logs

ant debug; adb uninstall kawa.android; adb install bin/KawaHello-debug.apk; adb logcat

Test

; Do this if you are running on physical hardware
adb forward tcp:4444 tcp:4444

telnet localhost 4444
(+ 1 1)

Still to be resolved

  • Text label doesn’t show up
  • Compiling classes and libraries quite slow, why is it being repeated?
  • Start repl after showing text label?
  • How do I make UI calls back on the main thread?

Troubleshooting

unable to resolve static field 9 (Lit0)

Rename your scheme file from hello.scm to hello2.scm as there is a name-clash – I’m not sure why yet.


About this entry