I'm delighted somebody by the name of "shadowcat-mst" has taken my Wat interpreter and reimplemented it in Perl. That really seems fitting. Wat now covers JavaScript and Perl - think of the possibilities!
Update: Piotr Kuchta ported Wat to Python.
Update: Victor Hugo Borja ported Wat to Ruby.
Showing posts with label wat. Show all posts
Showing posts with label wat. Show all posts
Wednesday, May 29, 2013
Thursday, May 9, 2013
Green threads in the browser in 20 lines of Wat
This page shows 5 independent, cooperatively scheduled Wat green threads (view source for full Wat code).
Each thread has an ID and is defined as a function that loops forever, repeatedly printing its ID, and then sleeping for a (randomly long) while.
To spawn a thread, I just wrap the call to RUN-THREAD in a prompt (which is just a unique object used as an identifier):
Then I can spawn independent threads:
Each thread has an ID and is defined as a function that loops forever, repeatedly printing its ID, and then sleeping for a (randomly long) while.
(define (run-thread (id String)) (loop (@appendChild (.body $document) (@createTextNode $document (+ "Active thread: " id " "))) (sleep (* 1000 (@random $Math)))))So, how can a Wat thread sleep inside a loop when JavaScript forbids sleeping? Why, with good ole delimited continuations:
To spawn a thread, I just wrap the call to RUN-THREAD in a prompt (which is just a unique object used as an identifier):
(define default-prompt 'default-prompt) (define (spawn-thread (id String)) (push-prompt default-prompt (run-thread id)))Where it gets interesting is the SLEEP function which captures the continuation up to the prompt, and sets up a callback with JavaScript's setTimeout that will reinstall the continuation later:
(define (sleep (ms Number)) (take-subcont default-prompt k (define (callback . #ignore) (push-prompt-subcont default-prompt k)) ($setTimeout (js-callback callback) ms)))So, first, SLEEP aborts up to and including the default prompt using TAKE-SUBCONT. It receives the continuation in the variable K. Once it has K, it defines a CALLBACK function, that will reinstall the default prompt with PUSH-PROMPT, and then continue with K again with PUSH-SUBCONT. All that's left is to give this callback to setTimeout.
Then I can spawn independent threads:
(spawn-thread "thread-1") (spawn-thread "thread-2") (spawn-thread "thread-3") (spawn-thread "thread-4") (spawn-thread "thread-5")Wat is very new, but it's already practical for adding concurrency and metaprogramming to JavaScript. Deployment is very easy. Include the single wat.js file, put some Lisp code in a <script> tag, and run it.
Wednesday, May 8, 2013
A new low in programming language design and implementation
The new Wat is the best, most lightweight way to implement a JavaScript-based programming language I have found so far.
Basically, I get away from JS as quickly and painlessly as possible, and start writing the language in itself.
So I define a very small set of primitives on the joint foundation of Kernel-like first-class lexical environments and fexprs and delimited continuations. Fexprs are a great tool for language-oriented programming, and delimited continuations allow me to escape from the browser's (and Node's) async hell and implement any concurrency and effect system I like.
To fexprs I also add macros. When a macro is used as the operator of a form, the form's code gets changed to the macro's output when the macro is first called, a technique I learned from here. I like macros because they make syntactic abstraction cost-free - with fexprs alone there is always an interpretative overhead. Still, Wat macros, like fexprs, do not work with quoted identifiers, but with first-class values, so many hygiene problems are avoided.
To delimited control I also add classic first-order control (sequential, conditional, loop, throw, catch, finally). This runs on the ordinary JS stack. Only when a continuation is captured does the stack get reified on the heap.
And last but not least, I use a JSON-based syntax for writing the language in itself. At first this was just intended as a quick way to not have to specify a parser for Wat, but I'm starting to like it. It allows Wat to truly be embedded in JavaScript.
Wat does not have a type tagging or object system. It uses the raw JavaScript values.
The whole implementation is roughly 350 lines of JavaScript. After these 350 lines, I can already write Wat in Wat, which is just great.
Subscribe to:
Posts (Atom)