Bluish Coder

Programming Languages, Martials Arts and Computers. The Weblog of Chris Double.


2006-05-10

Playing with HAppS

I downloaded HAppS, the Haskell Application Server, I mentioned previously to try it out.

I already had GHC installed so I could build darcs but I needed a few additional packages to install HAppS. Most of these I obtained via apt-get but I had to manually install the following two:

Once they were installed compiling and building HAppS is done using the Cabal based setup file:

runhaskell Setup.hs configure
runhaskell Setup.hs build
sudo runhaskell Setup.hs install

Once that's out of the way I tried out the 'hello' example. This is located in the 'examples' subdirectory of 'HAppS' and needs to be built and run:

make
./hello

This starts up an application server listening on port 8000. Where to go from there in terms of building apps I'm not sure as there doesn't seem to be much 'how to' style documentation. Digging through the source and examples looks to be the next thing to try.

Tags: haskell 

2006-05-07

Lightweight threads in the browser

I've made some updates to the Scheme in Javascript library. You can run it at the jsscheme page.

I've split out the example scheme source and made it loadable via Ajax. To do this I use jQuery, a very nice Javascript library. I added a Scheme wrapper around the Ajax GET call so you can do code like this:

(ajax-get "example.scm" (lambda (result) (alert result)))

The more interesting change is a simple concurrency library giving lightweight threads that run in the browser. The API loosely follows that of Termite, a concurrent Scheme. It uses '!' for sending a message to a process and '?' to receive.

To use the library click on the 'currency' button. This will load the source via Ajax. Then press 'eval'. Once loaded you can start using it. There are some examples in the concurrency.scm file.

For example, a 'logger' process:

(define logger
  (spawn
   (lambda ()
     (let loop ((msg (?)))
       (if (string? msg)
           (begin
             (process-msg msg)
             (loop (?)))))
     (process-msg "Logger exiting"))))

This loops waiting for a message in the process queue. When it appears it displays it and then waits for more messages. Any non-string message quits the process. An example of using it:

(define (logger-test)
  (spawn
   (lambda ()
     (! logger "Hello")
     (! logger "World")
     (! logger 'quit))))

I've also done an example of concurrency using Ajax. An 'ajax-process' waits for requests of the form '(FROM URL). When received it will retrieve the URL using Ajax and send the result to the FROM process:

(define ajax-process
  (spawn
   (lambda ()
     (let loop ((msg (?)))
       (let* ((from (car msg))
              (url (cadr msg)))
         (ajax-get url (lambda (result) (! from result))))
       (loop (?))))))

Using it is simple:

(alert (!? ajax-process `(,current-process "example.scm")))

This uses '!?' which sends a message and immediately waits for the result. You don't have to send to the current process. The next example instructs the Ajax process to send it to the log window:

(define (ajax-test2)
  (spawn
   (lambda ()
     (! ajax-process `(,logger "example.scm"))
     (! ajax-process `(,logger "concurrency.scm")))))

All this runs within the browser. Unfortunately it's not fast as it's interpreted. The JIT compiler does not work on Firefox and even if it did, it does not work with continuations which the concurrency system is based on. I'll look into improving this over time.

Tags: javascript 

2006-05-07

Why the Scheme->Javascript JIT doesn't work on Firefox

After doing some digging I've found a bug in the Scheme-in-Javascript implementation that seems to be the reason the JIT doesn't work on Firefox.

The system uses Javascript objects as associate arrays (hashtables), mapping symbols names to definitions. For example:

TopEnv['eval'] = function(list) { return doEval(list.car); }

There is a problem with using Javascript objects for this type of thing and that is that "TopEnv['eval']" is really syntactic sugar for 'TopEnv.eval' in Javascript. In firefox this actually returns the 'eval' standard function. You can see this by evaluating the following in a Javascript shell in Firefox:

var x = new Object()
x["eval"]
 => function eval() { [native code] }

In Internet Explorer this returns nothing. The JIT process does a lookup on 'eval' at some point and on Firefox it returns the native 'eval' function which breaks the JIT process. On IO it returns the Scheme 'eval' function.

The fix is relatively easy but finding all uses of this type of lookup in the code is time consuming. But JIT will work once I've done this.

Tags: javascript 

2006-05-07

San Francisco Bound

I'm flying out to San Francisco tomorrow to stay a week. I arrive on the 7th of May and leave on the 13th and will be at the Ajax Experience conference while I'm there. It's my first time in the US and I'm looking forward to it!

Tags: misc 

2006-05-05

Scheme Implementation in Javascript

A post on Lambda the Ultimate recently was about an Oberon interpreter written in Javascript, allowing Oberon to be embedded in the browser.

This reminded me of an near-R5RS compatible Scheme written in Javascript called jsScheme. It's a very nice implementation to play with but is IE 6 only. I've done some hacking at it and made it compatible with Firefox. I've put the modified version here.

The modified version has some changes to cater for Firefox and some things still don't work. JIT compilation for example, so I've left the checkbox for this disabled by default. This does slow things down quite a bit but I'll enable it again when I find the problem. For IE JIT works fine and you can enable it. If you find any other issues I'd be keen to get feedback. Leave a comment here or email me. I've also put the modified version in a darcs repository available with:

darcs get http://www.bluishcoder.co.nz/repos/javascript-scheme

Please send me any patches you'd like to apply.

What's nice about this system is it has most of R5RS scheme implemented, including tail recursion and first class continuations. A simple FFI for calling into Javascript is also available. For example, here's how to do some Javascript Date manipulation:

(define d  (js-eval "new Date();"))
(display (js-invoke d "toString"))
(newline)

'js-eval' will evaluate Javascript code and return the object. 'js-invoke' will invoke methods on that object. There is also 'js-call' which can call Javascript functions. Unfortunately Firefox had problem using 'js-call' on things like 'alert' and 'setTimeout' so I wrapped these built-ins with Javascript functions which can be called:

(js-call (js-eval "jsAlert") "Hello World!")

'js-call' will a Javascript function object. The 'js-eval' was required to return that function object given the function name.

Lambda the Ultimate also pointed to a Links paper recently. In this paper they describe compiling the Links language to Javascript in continuation passing style and using this to implement user level threading for client side Javascript. This should be possible using this Scheme system as well. We can create continuations using call/cc and use the 'set-timeout!' function I added which wraps 'setTimeout' to do the scheduling. Here's an example of using 'set-timeout!'.

(set-timeout! (lambda () (alert "Hello World")) 1000)

This example waits one second and displays the alert. Any Scheme function can be passed, including continuations:

(define abort #f)

(define (yield)
  (call/cc
    (lambda (k)
      (set-timeout! k 10)
      (abort))))

(define (spawn thunk)
  (call/cc
    (lambda (k)
      (set! abort k)
      (thunk))))           

(define (fib n)
  (yield)
  (if (= n 0)
    0
    (if (= n 1)
      1
      (+ (fib (- n 1)) (fib (- n 2))))))    

This code allows you to spawn a single thread which will run in the background of the browser. That thread can call 'yield' to return control back to the browser for a brief time. A simple fibonacci function is provided which calls 'yield'. For example:

(spawn (lambda () (display (fib 10))))

This will return control immediately. You can carry on using the browser and the result will be displayed when the thread completes. A simple thread scheduler implementation would be an interesting exercise.

Tags: javascript 


This site is accessable over tor as hidden service 6vp5u25g4izec5c37wv52skvecikld6kysvsivnl6sdg6q7wy25lixad.onion, or Freenet using key:
USK@1ORdIvjL2H1bZblJcP8hu2LjjKtVB-rVzp8mLty~5N4,8hL85otZBbq0geDsSKkBK4sKESL2SrNVecFZz9NxGVQ,AQACAAE/bluishcoder/-61/


Tags

Archives
Links