]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge commit 'dazhbog/master' into lazy_jit
authorSlava Pestov <slava@factorcode.org>
Wed, 26 Sep 2007 04:36:48 +0000 (00:36 -0400)
committerSlava Pestov <slava@factorcode.org>
Wed, 26 Sep 2007 04:36:48 +0000 (00:36 -0400)
60 files changed:
Factor.app/Contents/Info.plist
Factor.app/Contents/Resources/FRaptorMix.icns [deleted file]
Factor.app/Contents/Resources/Factor.icns [new file with mode: 0644]
core/bootstrap/image/image.factor
core/bootstrap/primitives.factor
core/optimizer/debugger/debugger.factor
core/sequences/sequences.factor
extra/benchmark/dispatch4/dispatch4.factor
extra/boids/boids.factor
extra/channels/sniffer/bsd/bsd.factor
extra/concurrency/concurrency.factor
extra/cpu/8080/8080.factor
extra/furnace/furnace.factor
extra/html/elements/elements.factor
extra/html/html-tests.factor
extra/html/html.factor
extra/html/stylesheet.css [new file with mode: 0644]
extra/http/http.factor
extra/http/server/resources/prototype.js [deleted file]
extra/http/server/resources/stylesheet.css [deleted file]
extra/http/server/responders/continuation/examples/examples.factor
extra/http/server/responders/file/file.factor
extra/http/server/responders/responders.factor
extra/icfp/2006/2006.factor
extra/io/sniffer/filter/bsd/bsd.factor
extra/io/streams/null/null.factor
extra/locals/locals.factor
extra/openal/macosx/macosx.factor
extra/space-invaders/space-invaders.factor
extra/state-machine/state-machine.factor
extra/webapps/help/help.factor
extra/xml/utilities/utilities.factor
misc/icons/FRaptorMix.ico [deleted file]
misc/icons/FRaptorMix_128x128.png [deleted file]
misc/icons/FRaptorMix_16x16.png [deleted file]
misc/icons/FRaptorMix_32x32.png [deleted file]
misc/icons/FRaptorMix_48x48.png [deleted file]
misc/icons/Factor.ico [new file with mode: 0644]
misc/icons/Factor_128x128.png [new file with mode: 0644]
misc/icons/Factor_16x16.png [new file with mode: 0644]
misc/icons/Factor_32x32.png [new file with mode: 0644]
misc/icons/Factor_48x48.png [new file with mode: 0644]
misc/icons/license.txt
vm/cpu-ppc.S
vm/cpu-ppc.h
vm/cpu-x86.32.S
vm/cpu-x86.64.S
vm/cpu-x86.S
vm/data_gc.c
vm/debug.c
vm/factor.c
vm/factor.rs
vm/image.c
vm/jit.c
vm/jit.h
vm/layouts.h
vm/run.c
vm/run.h
vm/stack.c
vm/types.c

index c54acd717993258cc0b2a417589ab4de46cfa30c..ca0e6d5f8adc3e5804d714ae090dcab1d601c57e 100644 (file)
@@ -22,7 +22,7 @@
        <key>CFBundleExecutable</key>
        <string>factor</string>
        <key>CFBundleIconFile</key>
-       <string>FRaptorMix.icns</string>
+       <string>Factor.icns</string>
        <key>CFBundleIdentifier</key>
        <string>org.factorcode.Factor</string>
        <key>CFBundleInfoDictionaryVersion</key>
diff --git a/Factor.app/Contents/Resources/FRaptorMix.icns b/Factor.app/Contents/Resources/FRaptorMix.icns
deleted file mode 100644 (file)
index 5cbe894..0000000
Binary files a/Factor.app/Contents/Resources/FRaptorMix.icns and /dev/null differ
diff --git a/Factor.app/Contents/Resources/Factor.icns b/Factor.app/Contents/Resources/Factor.icns
new file mode 100644 (file)
index 0000000..ab70230
Binary files /dev/null and b/Factor.app/Contents/Resources/Factor.icns differ
index 0f61eb4c83afe643c4fbafdde2d232efac32d256..c749ec3dad9577161606bd0d47b8fabc36e41a29 100644 (file)
@@ -36,7 +36,7 @@ IN: bootstrap.image
 : wrapper@ bootstrap-cell object tag-number - ;
 : word-xt@ 8 bootstrap-cells object tag-number - ;
 : quot-array@ bootstrap-cell object tag-number - ;
-: quot-xt@ 2 bootstrap-cells object tag-number - ;
+: quot-xt@ 3 bootstrap-cells object tag-number - ;
 
 ! The image being constructed; a vector of word-size integers
 SYMBOL: image
@@ -312,6 +312,7 @@ M: quotation '
         quotation-array '
         quotation type-number object tag-number [
             emit ! array
+            f ' emit ! compiled?
             0 emit ! XT
         ] emit-object
     ] cache ;
index 5e7bc1f3386e3fe23729e6db42ffbf98d3721964..edd1d42dcf329b5f8dfa56f39709d23a1f4d98cf 100644 (file)
@@ -452,6 +452,13 @@ num-types get f <array> builtins set
         { "quotation-array" "quotations.private" }
         f
     }
+    {
+        { "object" "kernel" }
+        "compiled?"
+        2
+        { "quotation-compiled?" "quotations" }
+        f
+    }
 } define-builtin
 
 "dll" "alien" create "dll?" "alien" create
index 6c323fce1eaa01752655272901c35dc3c2adad8f..ed0358fe7f30aae681e465dd4e2e53c32d29c8ae 100644 (file)
@@ -3,7 +3,7 @@
 USING: classes inference inference.dataflow io kernel
 kernel.private math.parser namespaces optimizer prettyprint
 prettyprint.backend sequences words arrays match macros
-assocs ;
+assocs combinators.private ;
 IN: optimizer.debugger
 
 ! A simple tool for turning dataflow IR into quotations, for
index 8d883ddcbbdd1a4e368fd802e5deab243f66441c..1a8e5c956125739f9e2ee437c55741a95aea7c26 100644 (file)
@@ -191,14 +191,14 @@ TUPLE: slice from to seq ;
 TUPLE: slice-error reason ;
 : slice-error ( str -- * ) \ slice-error construct-boa throw ;
 
-: check-slice ( from to seq -- )
+: check-slice ( from to seq -- from to seq )
     pick 0 < [ "start < 0" slice-error ] when
-    length over < [ "end > sequence" slice-error ] when
-    > [ "start > end" slice-error ] when ;
+    dup length pick < [ "end > sequence" slice-error ] when
+    pick pick > [ "start > end" slice-error ] when ;
 
 : <slice> ( from to seq -- slice )
     dup slice? [ collapse-slice ] when
-    3dup check-slice
+    check-slice
     slice construct-boa ;
 
 M: slice virtual-seq slice-seq ;
@@ -259,7 +259,7 @@ INSTANCE: repetition immutable-sequence
 PRIVATE>
 
 : subseq ( from to seq -- subseq )
-    [ 3dup check-slice prepare-subseq (copy) ] keep like ;
+    [ check-slice prepare-subseq (copy) ] keep like ;
 
 : head ( seq n -- headseq ) (head) subseq ;
 
@@ -525,7 +525,7 @@ M: sequence <=>
     ] if ;
 
 : delete-slice ( from to seq -- )
-    3dup check-slice >r over >r - r> r> open-slice ;
+    check-slice >r over >r - r> r> open-slice ;
 
 : delete-nth ( n seq -- )
     >r dup 1+ r> delete-slice ;
index 3ad41337d55f68ff86ef1eb20b0cfac69e94013e..a5bb9831511e0658a96fe8cd3d56f156ec1d4a6e 100644 (file)
@@ -1,4 +1,5 @@
-USING: kernel.private kernel sequences math combinators ;
+USING: kernel.private kernel sequences math combinators
+combinators.private ;
 IN: benchmark.dispatch4
 
 : foobar-1
index 397ce6eb5a943eb7a054f572af6ab832d292702b..aa3311ada5e15fdb07fcfe126260421de44eaa89 100644 (file)
@@ -56,7 +56,7 @@ VAR: separation-radius
 ! random-boid and random-boids
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: random-range ( a b -- n ) 1 + dupd swap - random + ;
+: random-range ( a b -- n ) 1+ over - random + ;
 
 : random-pos ( -- pos ) world-size> [ random ] map ;
 
@@ -68,7 +68,7 @@ VAR: separation-radius
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: distance ( boid boid -- n ) boid-pos swap boid-pos v- norm ;
+: distance ( boid boid -- n ) [ boid-pos ] [ boid-pos ] bi* v- norm ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -79,7 +79,9 @@ VAR: separation-radius
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: relative-position ( self other -- v ) boid-pos swap boid-pos v- ;
+! : relative-position ( self other -- v ) boid-pos swap boid-pos v- ;
+
+: relative-position ( self other -- v ) swap [ boid-pos ] 2apply v- ;
 
 : relative-angle ( self other -- angle )
 over boid-vel -rot relative-position angle-between ;
@@ -88,7 +90,7 @@ over boid-vel -rot relative-position angle-between ;
 
 : vsum ( vector-of-vectors -- vec ) { 0 0 } [ v+ ] reduce ;
 
-: vaverage ( seq-of-vectors -- seq ) dup vsum swap length v/n ;
+: vaverage ( seq-of-vectors -- seq ) [ vsum ] [ length ] bi v/n ;
 
 : average-position ( boids -- pos ) [ boid-pos ] map vaverage ;
 
@@ -204,14 +206,14 @@ cond ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: new-pos ( boid -- pos ) dup boid-vel time-slice> v*n swap boid-pos v+ ;
+: new-pos ( boid -- pos ) [ boid-pos ] [ boid-vel time-slice> v*n ] bi v+ ;
 
 : new-vel ( boid -- vel )
-dup acceleration time-slice> v*n swap boid-vel v+ normalize* ;
+  [ boid-vel ] [ acceleration time-slice> v*n ] bi v+ normalize* ;
 
 : wrap-pos ( pos -- pos ) { [ wrap-x ] [ wrap-y ] } parallel-call ;
 
-: iterate-boid ( self -- self ) dup >r new-pos wrap-pos r> new-vel <boid> ;
+: iterate-boid ( self -- self ) [ new-pos wrap-pos ] [ new-vel ] bi <boid> ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
index dd72279e4b4d6a1c18a4b20dbd44df9dd01cba81..ba8e5ceeb99a572544dd73caf266710e5794562d 100644 (file)
@@ -3,7 +3,7 @@
 !
 ! Wrap a sniffer in a channel
 USING: kernel channels channels.sniffer concurrency io
-io.sniffer io.sniffer.bsd ;
+io.sniffer io.sniffer.bsd io.unix.backend ;
 
 M: unix-io sniff-channel ( -- channel ) 
   "/dev/bpf0" "en1" <sniffer-spec> <sniffer> <channel> [
index 391e6b4c4b684578599ee79ee02beed49dbd9392..32ae3e59408f40a79911559cf3f59a3b346c364f 100644 (file)
@@ -239,7 +239,7 @@ PRIVATE>
         "Exiting process: " write self process-pid print
     ] curry spawn-link ;
 
-: server-cc ( -- cc | process )
+: server-cc ( -- cc|process )
     #! Captures the current continuation and returns the value.
     #! If that CC is called with a process on the stack it will
     #! set 'self' for the current process to it. Otherwise it will
index 34666b3288d9e5d3515231b3c110f9b3a4c4bd57..87c3a235fd5f080113436db5177f43f570d387c0 100644 (file)
@@ -3,7 +3,8 @@
 !
 USING: kernel math sequences words arrays io 
        io.files namespaces math.parser kernel.private
-       assocs quotations parser parser-combinators tools.time ;
+       assocs quotations parser parser-combinators tools.time
+       combinators.private ;
 IN: cpu.8080
 
 TUPLE: cpu b c d e f h l a pc sp halted? last-interrupt cycles ram ;
index 8a475b98dbc97d1356151be2e6d4676cfa679473..330c4868178c1edaa9cd5872883981cce760a896 100644 (file)
@@ -118,18 +118,18 @@ SYMBOL: model
 
 : render-page* ( model body-template head-template -- )
     [
-        [ render-template ] [ f rot render-template ] html-document* 
+        [ render-template ] [ f rot render-template ] html-document 
     ] serve-html ;
 
 : render-titled-page* ( model body-template head-template title -- )
     [ 
-        [ render-template ] swap [ <title> write </title> f rot render-template ] curry html-document
+        [ render-template ] swap [ <title> write </title> f rot render-template ] curry html-document
     ] serve-html ;
 
 
 : render-page ( model template title -- )
     [
-        [ render-template ] html-document
+        [ render-template ] simple-html-document
     ] serve-html ;
 
 : web-app ( name default path -- )
index 09ef3a4c036b1add291b0fbaf14597417ab9bc33..0b70f5aa5ce53df7b9faf4dd42817119d102f86c 100644 (file)
@@ -152,5 +152,5 @@ SYMBOL: html
     "size" "href" "class" "border" "rows" "cols" 
     "id" "onclick" "style" "valign" "accesskey"
     "src" "language" "colspan" "onchange" "rel"
-    "width" "selected" "onsubmit"
+    "width" "selected" "onsubmit" "xmlns" "lang" "xml:lang"
 ] [ define-attribute-word ] each 
index 5beb81b29add6775eb5f2679b6c7029b715e7d1e..798d5563feb0ece150bca530272a7cee61721fec 100644 (file)
@@ -1,30 +1,39 @@
 USING: html http io io.streams.string io.styles kernel
-namespaces tools.test xml.writer ;
+namespaces tools.test xml.writer sbufs sequences html.private ;
 IN: temporary
 
-[
-    "/responder/foo?z=%20"
-] [
-    "/responder/foo" H{ { "z" " " } } build-url
+: make-html-string
+    [ with-html-stream ] string-out ;
+
+[ ] [
+    512 <sbuf> <html-stream> drop
 ] unit-test
 
-[
-    "&lt;html&gt;&amp;&apos;sgml&apos;"
-] [ "<html>&'sgml'" chars>entities ] unit-test
+[ "" ] [
+    [ "" write ] make-html-string
+] unit-test
 
-[ "" ]
-[
-    [
-        H{ } [ drop ] span-tag
-    ] string-out
+[ "a" ] [
+    [ CHAR: a write1 ] make-html-string
 ] unit-test
 
-: html-format ( string style -- string )
-    [ format ] with-html-stream ;
+[ "&lt;" ] [
+    [ "<" write ] make-html-string
+] unit-test
 
-[ "hello world" ]
-[
-    [ "hello world" H{ } html-format ] string-out
+[ "<" ] [
+    [ "<" H{ } stdio get format-html-span ] make-html-string
+] unit-test
+
+TUPLE: funky town ;
+
+M: funky browser-link-href
+    "http://www.funky-town.com/" swap funky-town append ;
+
+[ "<a href='http://www.funky-town.com/austin'>&lt;</a>" ] [
+    [
+        "<" "austin" funky construct-boa write-object
+    ] make-html-string
 ] unit-test
 
 [ "<span style='font-family: monospace; '>car</span>" ]
@@ -32,8 +41,8 @@ IN: temporary
     [
         "car"
         H{ { font "monospace" } }
-        html-format
-    ] string-out
+        format
+    ] make-html-string
 ] unit-test
 
 [ "<span style='color: #ff00ff; '>car</span>" ]
@@ -41,6 +50,14 @@ IN: temporary
     [
         "car"
         H{ { foreground { 1 0 1 1 } } }
-        html-format
-    ] string-out
+        format
+    ] make-html-string
+] unit-test
+
+[ "<div style='background-color: #ff00ff; '>cdr</div>" ]
+[
+    [
+        H{ { page-color { 1 0 1 1 } } }
+        [ "cdr" write ] with-nesting
+    ] make-html-string
 ] unit-test
index 8d151906dc14baf31b4b64fe3e538af4bd47565c..9db97957a5789f36153e620870e49b758e21c140 100644 (file)
@@ -1,10 +1,43 @@
 ! Copyright (C) 2004, 2006 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: generic assocs help http io io.styles io.files io.streams.string
-kernel math math.parser namespaces xml.writer quotations
-assocs sequences strings words html.elements ;
+USING: generic assocs help http io io.styles io.files
+io.streams.string kernel math math.parser namespaces
+quotations assocs sequences strings words html.elements
+xml.writer sbufs ;
 IN: html
 
+GENERIC: browser-link-href ( presented -- href )
+
+M: object browser-link-href drop f ;
+
+TUPLE: html-stream ;
+
+: <html-stream> ( stream -- stream )
+    html-stream construct-delegate ;
+
+<PRIVATE
+
+TUPLE: html-sub-stream style stream ;
+
+: (html-sub-stream) ( style stream -- stream )
+    html-sub-stream construct-boa
+    512 <sbuf> <html-stream> over set-delegate ;
+
+: <html-sub-stream> ( style stream class -- stream )
+    >r (html-sub-stream) r> construct-delegate ; inline
+
+: end-sub-stream ( substream -- string style stream )
+    dup delegate >string
+    over html-sub-stream-style
+    rot html-sub-stream-stream ;
+
+: delegate-write ( string -- )
+    stdio get delegate stream-write ;
+
+: object-link-tag ( style quot -- )
+    presented pick at browser-link-href
+    [ <a =href a> call </a> ] [ call ] if* ; inline
+
 : hex-color, ( triplet -- )
     3 head-slice
     [ 255 * >fixnum >hex 2 CHAR: 0 pad-left % ] each ;
@@ -28,166 +61,149 @@ IN: html
 : font-css, ( font -- )
     "font-family: " % % "; " % ;
 
-: hash-apply ( value-hash quot-hash -- )
-    #! Looks up the key of each pair in the first list in the
-    #! second list to produce a quotation. The quotation is
-    #! applied to the value of the pair. If there is no
-    #! corresponding quotation, the value is popped off the
-    #! stack.
-    [ swapd at dup [ call ] [ 2drop ] if ] curry assoc-each ;
+: apply-style ( style key quot -- style gadget )
+    >r over at r> when* ; inline
+
+: make-css ( style quot -- str )
+    "" make nip ; inline
 
 : span-css-style ( style -- str )
     [
-        H{
-            { foreground  [ fg-css,        ] }
-            { background  [ bg-css,        ] }
-            { font        [ font-css,      ] }
-            { font-style  [ style-css,     ] }
-            { font-size   [ size-css,      ] }
-        } hash-apply
-    ] "" make ;
+        foreground [ fg-css,    ] apply-style
+        background [ bg-css,    ] apply-style
+        font       [ font-css,  ] apply-style
+        font-style [ style-css, ] apply-style
+        font-size  [ size-css,  ] apply-style
+    ] make-css ;
 
 : span-tag ( style quot -- )
     over span-css-style dup empty? [
         drop call
     ] [
         <span =style span> call </span>
-    ] if ;
+    ] if ; inline
+
+: format-html-span ( string style stream -- )
+    [
+        [ [ drop delegate-write ] span-tag ] object-link-tag
+    ] with-stream* ;
+
+TUPLE: html-span-stream ;
+
+M: html-span-stream stream-close
+    end-sub-stream format-html-span ;
 
 : border-css, ( border -- )
     "border: 1px solid #" % hex-color, "; " % ;
 
 : padding-css, ( padding -- ) "padding: " % # "px; " % ;
 
-: pre-css, ( -- )
-    "white-space: pre; font-family: monospace; " % ;
+: pre-css, ( margin -- )
+    [ "white-space: pre; font-family: monospace; " % ] unless ;
 
 : div-css-style ( style -- str )
     [
-        H{
-            { page-color [ bg-css, ] }
-            { border-color [ border-css, ] }
-            { border-width [ padding-css, ] }
-            { wrap-margin [ [ pre-css, ] unless ] }
-        } hash-apply
-    ] "" make ;
+        page-color   [ bg-css,      ] apply-style
+        border-color [ border-css,  ] apply-style
+        border-width [ padding-css, ] apply-style
+        wrap-margin  [ pre-css,     ] apply-style
+    ] make-css ;
 
 : div-tag ( style quot -- )
     swap div-css-style dup empty? [
         drop call
     ] [
         <div =style div> call </div>
-    ] if ;
+    ] if ; inline
 
-: do-escaping ( string style -- string )
-    html swap at [ chars>entities ] unless ;
-
-GENERIC: browser-link-href ( presented -- href )
+: format-html-div ( string style stream -- )
+    [
+        [ [ delegate-write ] div-tag ] object-link-tag
+    ] with-stream* ;
 
-M: object browser-link-href drop f ;
+TUPLE: html-block-stream ;
 
-: object-link-tag ( style quot -- )
-    presented pick at browser-link-href
-    [ <a =href a> call </a> ] [ call ] if* ;
+M: html-block-stream stream-close ( quot style stream -- )
+    end-sub-stream format-html-div ;
 
-TUPLE: nested-stream ;
+: border-spacing-css,
+    "padding: " % first2 max 2 /i # "px; " % ;
 
-: <nested-stream> ( stream -- stream )
-    nested-stream construct-delegate ;
+: table-style ( style -- str )
+    [
+        table-border [ border-css,         ] apply-style
+        table-gap    [ border-spacing-css, ] apply-style
+    ] make-css ;
 
-M: nested-stream stream-close drop ;
+: table-attrs ( style -- )
+    table-style " border-collapse: collapse;" append =style ;
 
-TUPLE: html-stream ;
+: do-escaping ( string style -- string )
+    html swap at [ chars>entities ] unless ;
 
-: <html-stream> ( stream -- stream )
-    html-stream construct-delegate ;
+PRIVATE>
 
+! Stream protocol
 M: html-stream stream-write1 ( char stream -- )
     >r 1string r> stream-write ;
 
-: delegate-write delegate stream-write ;
-
 M: html-stream stream-write ( str stream -- )
-    >r chars>entities r> delegate-write ;
-
-: with-html-style ( quot style stream -- )
-    [ [ swap span-tag ] object-link-tag ] with-stream* ; inline
+    >r chars>entities r> delegate stream-write ;
 
-M: html-stream with-stream-style ( quot style stream -- )
-    [ drop call ] -rot with-html-style ;
+M: html-stream make-span-stream ( style stream -- stream' )
+    html-span-stream <html-sub-stream> ;
 
 M: html-stream stream-format ( str style stream -- )
-    [ do-escaping stdio get delegate-write ] -rot
-    with-html-style ;
+    >r html over at [ >r chars>entities r> ] unless r>
+    format-html-span ;
 
-: with-html-stream ( quot -- )
-    stdio get <html-stream> swap with-stream* ;
-
-M: html-stream with-nested-stream ( quot style stream -- )
-    [
-        [
-            [
-                stdio get <nested-stream> swap with-stream*
-            ] div-tag
-        ] object-link-tag
-    ] with-stream* ;
-
-: border-spacing-css,
-    "padding: " % first2 max 2 /i # "px; " % ;
-
-: table-style ( style -- str )
-    [
-        H{
-            { table-border [ border-css,         ] }
-            { table-gap    [ border-spacing-css, ] }
-        } hash-apply
-    ] "" make ;
-
-: table-attrs ( style -- )
-    table-style " border-collapse: collapse;" append =style ;
+M: html-stream make-block-stream ( style stream -- stream' )
+    html-block-stream <html-sub-stream> ;
 
 M: html-stream stream-write-table ( grid style stream -- )
     [
         <table dup table-attrs table> swap [
             <tr> [
                 <td "top" =valign swap table-style =style td>
-                    write-html
+                    >string write-html
                 </td>
             ] curry* each </tr>
         ] curry* each </table>
     ] with-stream* ;
 
-M: html-stream make-table-cell ( quot style stream -- table-cell )
-    2drop [ with-html-stream ] string-out ;
+M: html-stream make-cell-stream ( style stream -- stream' )
+    (html-sub-stream) ;
 
-M: html-stream stream-nl [ <br/> ] with-stream* ;
+M: html-stream stream-nl ( stream -- )
+    [ <br/> ] with-stream* ;
 
-: default-css ( -- )
-    <link
-    "stylesheet" =rel "text/css" =type
-    "/responder/resources/stylesheet.css" =href
-    link/> ;
+! Utilities
+: with-html-stream ( quot -- )
+    stdio get <html-stream> swap with-stream* ;
 
 : xhtml-preamble
     "<?xml version=\"1.0\"?>" write-html
     "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" write-html ;
 
-: html-document* ( body-quot head-quot -- )
+: html-document ( body-quot head-quot -- )
     #! head-quot is called to produce output to go
     #! in the html head portion of the document.
     #! body-quot is called to produce output to go
     #! in the html body portion of the document.
     xhtml-preamble
-    <html " xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"" write-html html>
+    <html "http://www.w3.org/1999/xhtml" =xmlns "en" =xml:lang "en" =lang html>
         <head> call </head>
         <body> call </body>
     </html> ;
-  
-: html-document ( title quot -- )
+
+: default-css ( -- )
+    <link
+    "stylesheet" =rel "text/css" =type
+    "/responder/resources/extra/html/stylesheet.css" =href
+    link/> ;
+
+: simple-html-document ( title quot -- )
     swap [
         <title> write </title>
         default-css
-    ] html-document* ;
-
-: simple-html-document ( title quot -- )
-    swap [ <pre> with-html-stream </pre> ] html-document ;
+    ] html-document ;
diff --git a/extra/html/stylesheet.css b/extra/html/stylesheet.css
new file mode 100644 (file)
index 0000000..a1afce7
--- /dev/null
@@ -0,0 +1,4 @@
+a:link { text-decoration: none; color: black; }
+a:visited { text-decoration: none; color: black; }
+a:active { text-decoration: none; color: black; }
+a:hover { text-decoration: underline; color: black; }
index 687fa807f5c524fedeabb6420cdfdea0a27969e1..a358c449af8a3fcf7b7074c8641c302a473c75fe 100644 (file)
@@ -7,7 +7,7 @@ IN: http
 : header-line ( line -- )
     ": " split1 dup [ swap set ] [ 2drop ] if ;
 
-: (read-header) ( hash -- hash )
+: (read-header) ( -- )
     readln dup
     empty? [ drop ] [ header-line (read-header) ] if ;
 
diff --git a/extra/http/server/resources/prototype.js b/extra/http/server/resources/prototype.js
deleted file mode 100644 (file)
index 0e85338..0000000
+++ /dev/null
@@ -1,1781 +0,0 @@
-/*  Prototype JavaScript framework, version 1.4.0
- *  (c) 2005 Sam Stephenson <sam@conio.net>
- *
- *  Prototype is freely distributable under the terms of an MIT-style license.
- *  For details, see the Prototype web site: http://prototype.conio.net/
- *
-/*--------------------------------------------------------------------------*/
-
-var Prototype = {
-  Version: '1.4.0',
-  ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
-
-  emptyFunction: function() {},
-  K: function(x) {return x}
-}
-
-var Class = {
-  create: function() {
-    return function() {
-      this.initialize.apply(this, arguments);
-    }
-  }
-}
-
-var Abstract = new Object();
-
-Object.extend = function(destination, source) {
-  for (property in source) {
-    destination[property] = source[property];
-  }
-  return destination;
-}
-
-Object.inspect = function(object) {
-  try {
-    if (object == undefined) return 'undefined';
-    if (object == null) return 'null';
-    return object.inspect ? object.inspect() : object.toString();
-  } catch (e) {
-    if (e instanceof RangeError) return '...';
-    throw e;
-  }
-}
-
-Function.prototype.bind = function() {
-  var __method = this, args = $A(arguments), object = args.shift();
-  return function() {
-    return __method.apply(object, args.concat($A(arguments)));
-  }
-}
-
-Function.prototype.bindAsEventListener = function(object) {
-  var __method = this;
-  return function(event) {
-    return __method.call(object, event || window.event);
-  }
-}
-
-Object.extend(Number.prototype, {
-  toColorPart: function() {
-    var digits = this.toString(16);
-    if (this < 16) return '0' + digits;
-    return digits;
-  },
-
-  succ: function() {
-    return this + 1;
-  },
-
-  times: function(iterator) {
-    $R(0, this, true).each(iterator);
-    return this;
-  }
-});
-
-var Try = {
-  these: function() {
-    var returnValue;
-
-    for (var i = 0; i < arguments.length; i++) {
-      var lambda = arguments[i];
-      try {
-        returnValue = lambda();
-        break;
-      } catch (e) {}
-    }
-
-    return returnValue;
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
-  initialize: function(callback, frequency) {
-    this.callback = callback;
-    this.frequency = frequency;
-    this.currentlyExecuting = false;
-
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    if (!this.currentlyExecuting) {
-      try {
-        this.currentlyExecuting = true;
-        this.callback();
-      } finally {
-        this.currentlyExecuting = false;
-      }
-    }
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-function $() {
-  var elements = new Array();
-
-  for (var i = 0; i < arguments.length; i++) {
-    var element = arguments[i];
-    if (typeof element == 'string')
-      element = document.getElementById(element);
-
-    if (arguments.length == 1)
-      return element;
-
-    elements.push(element);
-  }
-
-  return elements;
-}
-Object.extend(String.prototype, {
-  stripTags: function() {
-    return this.replace(/<\/?[^>]+>/gi, '');
-  },
-
-  stripScripts: function() {
-    return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
-  },
-
-  extractScripts: function() {
-    var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
-    var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
-    return (this.match(matchAll) || []).map(function(scriptTag) {
-      return (scriptTag.match(matchOne) || ['', ''])[1];
-    });
-  },
-
-  evalScripts: function() {
-    return this.extractScripts().map(eval);
-  },
-
-  escapeHTML: function() {
-    var div = document.createElement('div');
-    var text = document.createTextNode(this);
-    div.appendChild(text);
-    return div.innerHTML;
-  },
-
-  unescapeHTML: function() {
-    var div = document.createElement('div');
-    div.innerHTML = this.stripTags();
-    return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
-  },
-
-  toQueryParams: function() {
-    var pairs = this.match(/^\??(.*)$/)[1].split('&');
-    return pairs.inject({}, function(params, pairString) {
-      var pair = pairString.split('=');
-      params[pair[0]] = pair[1];
-      return params;
-    });
-  },
-
-  toArray: function() {
-    return this.split('');
-  },
-
-  camelize: function() {
-    var oStringList = this.split('-');
-    if (oStringList.length == 1) return oStringList[0];
-
-    var camelizedString = this.indexOf('-') == 0
-      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
-      : oStringList[0];
-
-    for (var i = 1, len = oStringList.length; i < len; i++) {
-      var s = oStringList[i];
-      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
-    }
-
-    return camelizedString;
-  },
-
-  inspect: function() {
-    return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
-  }
-});
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-var $break    = new Object();
-var $continue = new Object();
-
-var Enumerable = {
-  each: function(iterator) {
-    var index = 0;
-    try {
-      this._each(function(value) {
-        try {
-          iterator(value, index++);
-        } catch (e) {
-          if (e != $continue) throw e;
-        }
-      });
-    } catch (e) {
-      if (e != $break) throw e;
-    }
-  },
-
-  all: function(iterator) {
-    var result = true;
-    this.each(function(value, index) {
-      result = result && !!(iterator || Prototype.K)(value, index);
-      if (!result) throw $break;
-    });
-    return result;
-  },
-
-  any: function(iterator) {
-    var result = true;
-    this.each(function(value, index) {
-      if (result = !!(iterator || Prototype.K)(value, index))
-        throw $break;
-    });
-    return result;
-  },
-
-  collect: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      results.push(iterator(value, index));
-    });
-    return results;
-  },
-
-  detect: function (iterator) {
-    var result;
-    this.each(function(value, index) {
-      if (iterator(value, index)) {
-        result = value;
-        throw $break;
-      }
-    });
-    return result;
-  },
-
-  findAll: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      if (iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
-
-  grep: function(pattern, iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      var stringValue = value.toString();
-      if (stringValue.match(pattern))
-        results.push((iterator || Prototype.K)(value, index));
-    })
-    return results;
-  },
-
-  include: function(object) {
-    var found = false;
-    this.each(function(value) {
-      if (value == object) {
-        found = true;
-        throw $break;
-      }
-    });
-    return found;
-  },
-
-  inject: function(memo, iterator) {
-    this.each(function(value, index) {
-      memo = iterator(memo, value, index);
-    });
-    return memo;
-  },
-
-  invoke: function(method) {
-    var args = $A(arguments).slice(1);
-    return this.collect(function(value) {
-      return value[method].apply(value, args);
-    });
-  },
-
-  max: function(iterator) {
-    var result;
-    this.each(function(value, index) {
-      value = (iterator || Prototype.K)(value, index);
-      if (value >= (result || value))
-        result = value;
-    });
-    return result;
-  },
-
-  min: function(iterator) {
-    var result;
-    this.each(function(value, index) {
-      value = (iterator || Prototype.K)(value, index);
-      if (value <= (result || value))
-        result = value;
-    });
-    return result;
-  },
-
-  partition: function(iterator) {
-    var trues = [], falses = [];
-    this.each(function(value, index) {
-      ((iterator || Prototype.K)(value, index) ?
-        trues : falses).push(value);
-    });
-    return [trues, falses];
-  },
-
-  pluck: function(property) {
-    var results = [];
-    this.each(function(value, index) {
-      results.push(value[property]);
-    });
-    return results;
-  },
-
-  reject: function(iterator) {
-    var results = [];
-    this.each(function(value, index) {
-      if (!iterator(value, index))
-        results.push(value);
-    });
-    return results;
-  },
-
-  sortBy: function(iterator) {
-    return this.collect(function(value, index) {
-      return {value: value, criteria: iterator(value, index)};
-    }).sort(function(left, right) {
-      var a = left.criteria, b = right.criteria;
-      return a < b ? -1 : a > b ? 1 : 0;
-    }).pluck('value');
-  },
-
-  toArray: function() {
-    return this.collect(Prototype.K);
-  },
-
-  zip: function() {
-    var iterator = Prototype.K, args = $A(arguments);
-    if (typeof args.last() == 'function')
-      iterator = args.pop();
-
-    var collections = [this].concat(args).map($A);
-    return this.map(function(value, index) {
-      iterator(value = collections.pluck(index));
-      return value;
-    });
-  },
-
-  inspect: function() {
-    return '#<Enumerable:' + this.toArray().inspect() + '>';
-  }
-}
-
-Object.extend(Enumerable, {
-  map:     Enumerable.collect,
-  find:    Enumerable.detect,
-  select:  Enumerable.findAll,
-  member:  Enumerable.include,
-  entries: Enumerable.toArray
-});
-var $A = Array.from = function(iterable) {
-  if (!iterable) return [];
-  if (iterable.toArray) {
-    return iterable.toArray();
-  } else {
-    var results = [];
-    for (var i = 0; i < iterable.length; i++)
-      results.push(iterable[i]);
-    return results;
-  }
-}
-
-Object.extend(Array.prototype, Enumerable);
-
-Array.prototype._reverse = Array.prototype.reverse;
-
-Object.extend(Array.prototype, {
-  _each: function(iterator) {
-    for (var i = 0; i < this.length; i++)
-      iterator(this[i]);
-  },
-
-  clear: function() {
-    this.length = 0;
-    return this;
-  },
-
-  first: function() {
-    return this[0];
-  },
-
-  last: function() {
-    return this[this.length - 1];
-  },
-
-  compact: function() {
-    return this.select(function(value) {
-      return value != undefined || value != null;
-    });
-  },
-
-  flatten: function() {
-    return this.inject([], function(array, value) {
-      return array.concat(value.constructor == Array ?
-        value.flatten() : [value]);
-    });
-  },
-
-  without: function() {
-    var values = $A(arguments);
-    return this.select(function(value) {
-      return !values.include(value);
-    });
-  },
-
-  indexOf: function(object) {
-    for (var i = 0; i < this.length; i++)
-      if (this[i] == object) return i;
-    return -1;
-  },
-
-  reverse: function(inline) {
-    return (inline !== false ? this : this.toArray())._reverse();
-  },
-
-  shift: function() {
-    var result = this[0];
-    for (var i = 0; i < this.length - 1; i++)
-      this[i] = this[i + 1];
-    this.length--;
-    return result;
-  },
-
-  inspect: function() {
-    return '[' + this.map(Object.inspect).join(', ') + ']';
-  }
-});
-var Hash = {
-  _each: function(iterator) {
-    for (key in this) {
-      var value = this[key];
-      if (typeof value == 'function') continue;
-
-      var pair = [key, value];
-      pair.key = key;
-      pair.value = value;
-      iterator(pair);
-    }
-  },
-
-  keys: function() {
-    return this.pluck('key');
-  },
-
-  values: function() {
-    return this.pluck('value');
-  },
-
-  merge: function(hash) {
-    return $H(hash).inject($H(this), function(mergedHash, pair) {
-      mergedHash[pair.key] = pair.value;
-      return mergedHash;
-    });
-  },
-
-  toQueryString: function() {
-    return this.map(function(pair) {
-      return pair.map(encodeURIComponent).join('=');
-    }).join('&');
-  },
-
-  inspect: function() {
-    return '#<Hash:{' + this.map(function(pair) {
-      return pair.map(Object.inspect).join(': ');
-    }).join(', ') + '}>';
-  }
-}
-
-function $H(object) {
-  var hash = Object.extend({}, object || {});
-  Object.extend(hash, Enumerable);
-  Object.extend(hash, Hash);
-  return hash;
-}
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
-  initialize: function(start, end, exclusive) {
-    this.start = start;
-    this.end = end;
-    this.exclusive = exclusive;
-  },
-
-  _each: function(iterator) {
-    var value = this.start;
-    do {
-      iterator(value);
-      value = value.succ();
-    } while (this.include(value));
-  },
-
-  include: function(value) {
-    if (value < this.start)
-      return false;
-    if (this.exclusive)
-      return value < this.end;
-    return value <= this.end;
-  }
-});
-
-var $R = function(start, end, exclusive) {
-  return new ObjectRange(start, end, exclusive);
-}
-
-var Ajax = {
-  getTransport: function() {
-    return Try.these(
-      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
-      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
-      function() {return new XMLHttpRequest()}
-    ) || false;
-  },
-
-  activeRequestCount: 0
-}
-
-Ajax.Responders = {
-  responders: [],
-
-  _each: function(iterator) {
-    this.responders._each(iterator);
-  },
-
-  register: function(responderToAdd) {
-    if (!this.include(responderToAdd))
-      this.responders.push(responderToAdd);
-  },
-
-  unregister: function(responderToRemove) {
-    this.responders = this.responders.without(responderToRemove);
-  },
-
-  dispatch: function(callback, request, transport, json) {
-    this.each(function(responder) {
-      if (responder[callback] && typeof responder[callback] == 'function') {
-        try {
-          responder[callback].apply(responder, [request, transport, json]);
-        } catch (e) {}
-      }
-    });
-  }
-};
-
-Object.extend(Ajax.Responders, Enumerable);
-
-Ajax.Responders.register({
-  onCreate: function() {
-    Ajax.activeRequestCount++;
-  },
-
-  onComplete: function() {
-    Ajax.activeRequestCount--;
-  }
-});
-
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
-  setOptions: function(options) {
-    this.options = {
-      method:       'post',
-      asynchronous: true,
-      parameters:   ''
-    }
-    Object.extend(this.options, options || {});
-  },
-
-  responseIsSuccess: function() {
-    return this.transport.status == undefined
-        || this.transport.status == 0
-        || (this.transport.status >= 200 && this.transport.status < 300);
-  },
-
-  responseIsFailure: function() {
-    return !this.responseIsSuccess();
-  }
-}
-
-Ajax.Request = Class.create();
-Ajax.Request.Events =
-  ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
-  initialize: function(url, options) {
-    this.transport = Ajax.getTransport();
-    this.setOptions(options);
-    this.request(url);
-  },
-
-  request: function(url) {
-    var parameters = this.options.parameters || '';
-    if (parameters.length > 0) parameters += '&_=';
-
-    try {
-      this.url = url;
-      if (this.options.method == 'get' && parameters.length > 0)
-        this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
-
-      Ajax.Responders.dispatch('onCreate', this, this.transport);
-
-      this.transport.open(this.options.method, this.url,
-        this.options.asynchronous);
-
-      if (this.options.asynchronous) {
-        this.transport.onreadystatechange = this.onStateChange.bind(this);
-        setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
-      }
-
-      this.setRequestHeaders();
-
-      var body = this.options.postBody ? this.options.postBody : parameters;
-      this.transport.send(this.options.method == 'post' ? body : null);
-
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  setRequestHeaders: function() {
-    var requestHeaders =
-      ['X-Requested-With', 'XMLHttpRequest',
-       'X-Prototype-Version', Prototype.Version];
-
-    if (this.options.method == 'post') {
-      requestHeaders.push('Content-type',
-        'application/x-www-form-urlencoded');
-
-      /* Force "Connection: close" for Mozilla browsers to work around
-       * a bug where XMLHttpReqeuest sends an incorrect Content-length
-       * header. See Mozilla Bugzilla #246651.
-       */
-      if (this.transport.overrideMimeType)
-        requestHeaders.push('Connection', 'close');
-    }
-
-    if (this.options.requestHeaders)
-      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
-
-    for (var i = 0; i < requestHeaders.length; i += 2)
-      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
-  },
-
-  onStateChange: function() {
-    var readyState = this.transport.readyState;
-    if (readyState != 1)
-      this.respondToReadyState(this.transport.readyState);
-  },
-
-  header: function(name) {
-    try {
-      return this.transport.getResponseHeader(name);
-    } catch (e) {}
-  },
-
-  evalJSON: function() {
-    try {
-      return eval(this.header('X-JSON'));
-    } catch (e) {}
-  },
-
-  evalResponse: function() {
-    try {
-      return eval(this.transport.responseText);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-  },
-
-  respondToReadyState: function(readyState) {
-    var event = Ajax.Request.Events[readyState];
-    var transport = this.transport, json = this.evalJSON();
-
-    if (event == 'Complete') {
-      try {
-        (this.options['on' + this.transport.status]
-         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
-         || Prototype.emptyFunction)(transport, json);
-      } catch (e) {
-        this.dispatchException(e);
-      }
-
-      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
-        this.evalResponse();
-    }
-
-    try {
-      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
-      Ajax.Responders.dispatch('on' + event, this, transport, json);
-    } catch (e) {
-      this.dispatchException(e);
-    }
-
-    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
-    if (event == 'Complete')
-      this.transport.onreadystatechange = Prototype.emptyFunction;
-  },
-
-  dispatchException: function(exception) {
-    (this.options.onException || Prototype.emptyFunction)(this, exception);
-    Ajax.Responders.dispatch('onException', this, exception);
-  }
-});
-
-Ajax.Updater = Class.create();
-
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
-  initialize: function(container, url, options) {
-    this.containers = {
-      success: container.success ? $(container.success) : $(container),
-      failure: container.failure ? $(container.failure) :
-        (container.success ? null : $(container))
-    }
-
-    this.transport = Ajax.getTransport();
-    this.setOptions(options);
-
-    var onComplete = this.options.onComplete || Prototype.emptyFunction;
-    this.options.onComplete = (function(transport, object) {
-      this.updateContent();
-      onComplete(transport, object);
-    }).bind(this);
-
-    this.request(url);
-  },
-
-  updateContent: function() {
-    var receiver = this.responseIsSuccess() ?
-      this.containers.success : this.containers.failure;
-    var response = this.transport.responseText;
-
-    if (!this.options.evalScripts)
-      response = response.stripScripts();
-
-    if (receiver) {
-      if (this.options.insertion) {
-        new this.options.insertion(receiver, response);
-      } else {
-        Element.update(receiver, response);
-      }
-    }
-
-    if (this.responseIsSuccess()) {
-      if (this.onComplete)
-        setTimeout(this.onComplete.bind(this), 10);
-    }
-  }
-});
-
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
-  initialize: function(container, url, options) {
-    this.setOptions(options);
-    this.onComplete = this.options.onComplete;
-
-    this.frequency = (this.options.frequency || 2);
-    this.decay = (this.options.decay || 1);
-
-    this.updater = {};
-    this.container = container;
-    this.url = url;
-
-    this.start();
-  },
-
-  start: function() {
-    this.options.onComplete = this.updateComplete.bind(this);
-    this.onTimerEvent();
-  },
-
-  stop: function() {
-    this.updater.onComplete = undefined;
-    clearTimeout(this.timer);
-    (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
-  },
-
-  updateComplete: function(request) {
-    if (this.options.decay) {
-      this.decay = (request.responseText == this.lastText ?
-        this.decay * this.options.decay : 1);
-
-      this.lastText = request.responseText;
-    }
-    this.timer = setTimeout(this.onTimerEvent.bind(this),
-      this.decay * this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    this.updater = new Ajax.Updater(this.container, this.url, this.options);
-  }
-});
-document.getElementsByClassName = function(className, parentElement) {
-  var children = ($(parentElement) || document.body).getElementsByTagName('*');
-  return $A(children).inject([], function(elements, child) {
-    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
-      elements.push(child);
-    return elements;
-  });
-}
-
-/*--------------------------------------------------------------------------*/
-
-if (!window.Element) {
-  var Element = new Object();
-}
-
-Object.extend(Element, {
-  visible: function(element) {
-    return $(element).style.display != 'none';
-  },
-
-  toggle: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      Element[Element.visible(element) ? 'hide' : 'show'](element);
-    }
-  },
-
-  hide: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      element.style.display = 'none';
-    }
-  },
-
-  show: function() {
-    for (var i = 0; i < arguments.length; i++) {
-      var element = $(arguments[i]);
-      element.style.display = '';
-    }
-  },
-
-  remove: function(element) {
-    element = $(element);
-    element.parentNode.removeChild(element);
-  },
-
-  update: function(element, html) {
-    $(element).innerHTML = html.stripScripts();
-    setTimeout(function() {html.evalScripts()}, 10);
-  },
-
-  getHeight: function(element) {
-    element = $(element);
-    return element.offsetHeight;
-  },
-
-  classNames: function(element) {
-    return new Element.ClassNames(element);
-  },
-
-  hasClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).include(className);
-  },
-
-  addClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).add(className);
-  },
-
-  removeClassName: function(element, className) {
-    if (!(element = $(element))) return;
-    return Element.classNames(element).remove(className);
-  },
-
-  // removes whitespace-only text node children
-  cleanWhitespace: function(element) {
-    element = $(element);
-    for (var i = 0; i < element.childNodes.length; i++) {
-      var node = element.childNodes[i];
-      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
-        Element.remove(node);
-    }
-  },
-
-  empty: function(element) {
-    return $(element).innerHTML.match(/^\s*$/);
-  },
-
-  scrollTo: function(element) {
-    element = $(element);
-    var x = element.x ? element.x : element.offsetLeft,
-        y = element.y ? element.y : element.offsetTop;
-    window.scrollTo(x, y);
-  },
-
-  getStyle: function(element, style) {
-    element = $(element);
-    var value = element.style[style.camelize()];
-    if (!value) {
-      if (document.defaultView && document.defaultView.getComputedStyle) {
-        var css = document.defaultView.getComputedStyle(element, null);
-        value = css ? css.getPropertyValue(style) : null;
-      } else if (element.currentStyle) {
-        value = element.currentStyle[style.camelize()];
-      }
-    }
-
-    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
-      if (Element.getStyle(element, 'position') == 'static') value = 'auto';
-
-    return value == 'auto' ? null : value;
-  },
-
-  setStyle: function(element, style) {
-    element = $(element);
-    for (name in style)
-      element.style[name.camelize()] = style[name];
-  },
-
-  getDimensions: function(element) {
-    element = $(element);
-    if (Element.getStyle(element, 'display') != 'none')
-      return {width: element.offsetWidth, height: element.offsetHeight};
-
-    // All *Width and *Height properties give 0 on elements with display none,
-    // so enable the element temporarily
-    var els = element.style;
-    var originalVisibility = els.visibility;
-    var originalPosition = els.position;
-    els.visibility = 'hidden';
-    els.position = 'absolute';
-    els.display = '';
-    var originalWidth = element.clientWidth;
-    var originalHeight = element.clientHeight;
-    els.display = 'none';
-    els.position = originalPosition;
-    els.visibility = originalVisibility;
-    return {width: originalWidth, height: originalHeight};
-  },
-
-  makePositioned: function(element) {
-    element = $(element);
-    var pos = Element.getStyle(element, 'position');
-    if (pos == 'static' || !pos) {
-      element._madePositioned = true;
-      element.style.position = 'relative';
-      // Opera returns the offset relative to the positioning context, when an
-      // element is position relative but top and left have not been defined
-      if (window.opera) {
-        element.style.top = 0;
-        element.style.left = 0;
-      }
-    }
-  },
-
-  undoPositioned: function(element) {
-    element = $(element);
-    if (element._madePositioned) {
-      element._madePositioned = undefined;
-      element.style.position =
-        element.style.top =
-        element.style.left =
-        element.style.bottom =
-        element.style.right = '';
-    }
-  },
-
-  makeClipping: function(element) {
-    element = $(element);
-    if (element._overflow) return;
-    element._overflow = element.style.overflow;
-    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
-      element.style.overflow = 'hidden';
-  },
-
-  undoClipping: function(element) {
-    element = $(element);
-    if (element._overflow) return;
-    element.style.overflow = element._overflow;
-    element._overflow = undefined;
-  }
-});
-
-var Toggle = new Object();
-Toggle.display = Element.toggle;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.Insertion = function(adjacency) {
-  this.adjacency = adjacency;
-}
-
-Abstract.Insertion.prototype = {
-  initialize: function(element, content) {
-    this.element = $(element);
-    this.content = content.stripScripts();
-
-    if (this.adjacency && this.element.insertAdjacentHTML) {
-      try {
-        this.element.insertAdjacentHTML(this.adjacency, this.content);
-      } catch (e) {
-        if (this.element.tagName.toLowerCase() == 'tbody') {
-          this.insertContent(this.contentFromAnonymousTable());
-        } else {
-          throw e;
-        }
-      }
-    } else {
-      this.range = this.element.ownerDocument.createRange();
-      if (this.initializeRange) this.initializeRange();
-      this.insertContent([this.range.createContextualFragment(this.content)]);
-    }
-
-    setTimeout(function() {content.evalScripts()}, 10);
-  },
-
-  contentFromAnonymousTable: function() {
-    var div = document.createElement('div');
-    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
-    return $A(div.childNodes[0].childNodes[0].childNodes);
-  }
-}
-
-var Insertion = new Object();
-
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
-  initializeRange: function() {
-    this.range.setStartBefore(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.parentNode.insertBefore(fragment, this.element);
-    }).bind(this));
-  }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
-  initializeRange: function() {
-    this.range.selectNodeContents(this.element);
-    this.range.collapse(true);
-  },
-
-  insertContent: function(fragments) {
-    fragments.reverse(false).each((function(fragment) {
-      this.element.insertBefore(fragment, this.element.firstChild);
-    }).bind(this));
-  }
-});
-
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
-  initializeRange: function() {
-    this.range.selectNodeContents(this.element);
-    this.range.collapse(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.appendChild(fragment);
-    }).bind(this));
-  }
-});
-
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
-  initializeRange: function() {
-    this.range.setStartAfter(this.element);
-  },
-
-  insertContent: function(fragments) {
-    fragments.each((function(fragment) {
-      this.element.parentNode.insertBefore(fragment,
-        this.element.nextSibling);
-    }).bind(this));
-  }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
-  initialize: function(element) {
-    this.element = $(element);
-  },
-
-  _each: function(iterator) {
-    this.element.className.split(/\s+/).select(function(name) {
-      return name.length > 0;
-    })._each(iterator);
-  },
-
-  set: function(className) {
-    this.element.className = className;
-  },
-
-  add: function(classNameToAdd) {
-    if (this.include(classNameToAdd)) return;
-    this.set(this.toArray().concat(classNameToAdd).join(' '));
-  },
-
-  remove: function(classNameToRemove) {
-    if (!this.include(classNameToRemove)) return;
-    this.set(this.select(function(className) {
-      return className != classNameToRemove;
-    }).join(' '));
-  },
-
-  toString: function() {
-    return this.toArray().join(' ');
-  }
-}
-
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Field = {
-  clear: function() {
-    for (var i = 0; i < arguments.length; i++)
-      $(arguments[i]).value = '';
-  },
-
-  focus: function(element) {
-    $(element).focus();
-  },
-
-  present: function() {
-    for (var i = 0; i < arguments.length; i++)
-      if ($(arguments[i]).value == '') return false;
-    return true;
-  },
-
-  select: function(element) {
-    $(element).select();
-  },
-
-  activate: function(element) {
-    element = $(element);
-    element.focus();
-    if (element.select)
-      element.select();
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Form = {
-  serialize: function(form) {
-    var elements = Form.getElements($(form));
-    var queryComponents = new Array();
-
-    for (var i = 0; i < elements.length; i++) {
-      var queryComponent = Form.Element.serialize(elements[i]);
-      if (queryComponent)
-        queryComponents.push(queryComponent);
-    }
-
-    return queryComponents.join('&');
-  },
-
-  getElements: function(form) {
-    form = $(form);
-    var elements = new Array();
-
-    for (tagName in Form.Element.Serializers) {
-      var tagElements = form.getElementsByTagName(tagName);
-      for (var j = 0; j < tagElements.length; j++)
-        elements.push(tagElements[j]);
-    }
-    return elements;
-  },
-
-  getInputs: function(form, typeName, name) {
-    form = $(form);
-    var inputs = form.getElementsByTagName('input');
-
-    if (!typeName && !name)
-      return inputs;
-
-    var matchingInputs = new Array();
-    for (var i = 0; i < inputs.length; i++) {
-      var input = inputs[i];
-      if ((typeName && input.type != typeName) ||
-          (name && input.name != name))
-        continue;
-      matchingInputs.push(input);
-    }
-
-    return matchingInputs;
-  },
-
-  disable: function(form) {
-    var elements = Form.getElements(form);
-    for (var i = 0; i < elements.length; i++) {
-      var element = elements[i];
-      element.blur();
-      element.disabled = 'true';
-    }
-  },
-
-  enable: function(form) {
-    var elements = Form.getElements(form);
-    for (var i = 0; i < elements.length; i++) {
-      var element = elements[i];
-      element.disabled = '';
-    }
-  },
-
-  findFirstElement: function(form) {
-    return Form.getElements(form).find(function(element) {
-      return element.type != 'hidden' && !element.disabled &&
-        ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
-    });
-  },
-
-  focusFirstElement: function(form) {
-    Field.activate(Form.findFirstElement(form));
-  },
-
-  reset: function(form) {
-    $(form).reset();
-  }
-}
-
-Form.Element = {
-  serialize: function(element) {
-    element = $(element);
-    var method = element.tagName.toLowerCase();
-    var parameter = Form.Element.Serializers[method](element);
-
-    if (parameter) {
-      var key = encodeURIComponent(parameter[0]);
-      if (key.length == 0) return;
-
-      if (parameter[1].constructor != Array)
-        parameter[1] = [parameter[1]];
-
-      return parameter[1].map(function(value) {
-        return key + '=' + encodeURIComponent(value);
-      }).join('&');
-    }
-  },
-
-  getValue: function(element) {
-    element = $(element);
-    var method = element.tagName.toLowerCase();
-    var parameter = Form.Element.Serializers[method](element);
-
-    if (parameter)
-      return parameter[1];
-  }
-}
-
-Form.Element.Serializers = {
-  input: function(element) {
-    switch (element.type.toLowerCase()) {
-      case 'submit':
-      case 'hidden':
-      case 'password':
-      case 'text':
-        return Form.Element.Serializers.textarea(element);
-      case 'checkbox':
-      case 'radio':
-        return Form.Element.Serializers.inputSelector(element);
-    }
-    return false;
-  },
-
-  inputSelector: function(element) {
-    if (element.checked)
-      return [element.name, element.value];
-  },
-
-  textarea: function(element) {
-    return [element.name, element.value];
-  },
-
-  select: function(element) {
-    return Form.Element.Serializers[element.type == 'select-one' ?
-      'selectOne' : 'selectMany'](element);
-  },
-
-  selectOne: function(element) {
-    var value = '', opt, index = element.selectedIndex;
-    if (index >= 0) {
-      opt = element.options[index];
-      value = opt.value;
-      if (!value && !('value' in opt))
-        value = opt.text;
-    }
-    return [element.name, value];
-  },
-
-  selectMany: function(element) {
-    var value = new Array();
-    for (var i = 0; i < element.length; i++) {
-      var opt = element.options[i];
-      if (opt.selected) {
-        var optValue = opt.value;
-        if (!optValue && !('value' in opt))
-          optValue = opt.text;
-        value.push(optValue);
-      }
-    }
-    return [element.name, value];
-  }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
-  initialize: function(element, frequency, callback) {
-    this.frequency = frequency;
-    this.element   = $(element);
-    this.callback  = callback;
-
-    this.lastValue = this.getValue();
-    this.registerCallback();
-  },
-
-  registerCallback: function() {
-    setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
-  },
-
-  onTimerEvent: function() {
-    var value = this.getValue();
-    if (this.lastValue != value) {
-      this.callback(this.element, value);
-      this.lastValue = value;
-    }
-  }
-}
-
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
-  getValue: function() {
-    return Form.Element.getValue(this.element);
-  }
-});
-
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
-  getValue: function() {
-    return Form.serialize(this.element);
-  }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
-  initialize: function(element, callback) {
-    this.element  = $(element);
-    this.callback = callback;
-
-    this.lastValue = this.getValue();
-    if (this.element.tagName.toLowerCase() == 'form')
-      this.registerFormCallbacks();
-    else
-      this.registerCallback(this.element);
-  },
-
-  onElementEvent: function() {
-    var value = this.getValue();
-    if (this.lastValue != value) {
-      this.callback(this.element, value);
-      this.lastValue = value;
-    }
-  },
-
-  registerFormCallbacks: function() {
-    var elements = Form.getElements(this.element);
-    for (var i = 0; i < elements.length; i++)
-      this.registerCallback(elements[i]);
-  },
-
-  registerCallback: function(element) {
-    if (element.type) {
-      switch (element.type.toLowerCase()) {
-        case 'checkbox':
-        case 'radio':
-          Event.observe(element, 'click', this.onElementEvent.bind(this));
-          break;
-        case 'password':
-        case 'text':
-        case 'textarea':
-        case 'select-one':
-        case 'select-multiple':
-          Event.observe(element, 'change', this.onElementEvent.bind(this));
-          break;
-      }
-    }
-  }
-}
-
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
-  getValue: function() {
-    return Form.Element.getValue(this.element);
-  }
-});
-
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
-  getValue: function() {
-    return Form.serialize(this.element);
-  }
-});
-if (!window.Event) {
-  var Event = new Object();
-}
-
-Object.extend(Event, {
-  KEY_BACKSPACE: 8,
-  KEY_TAB:       9,
-  KEY_RETURN:   13,
-  KEY_ESC:      27,
-  KEY_LEFT:     37,
-  KEY_UP:       38,
-  KEY_RIGHT:    39,
-  KEY_DOWN:     40,
-  KEY_DELETE:   46,
-
-  element: function(event) {
-    return event.target || event.srcElement;
-  },
-
-  isLeftClick: function(event) {
-    return (((event.which) && (event.which == 1)) ||
-            ((event.button) && (event.button == 1)));
-  },
-
-  pointerX: function(event) {
-    return event.pageX || (event.clientX +
-      (document.documentElement.scrollLeft || document.body.scrollLeft));
-  },
-
-  pointerY: function(event) {
-    return event.pageY || (event.clientY +
-      (document.documentElement.scrollTop || document.body.scrollTop));
-  },
-
-  stop: function(event) {
-    if (event.preventDefault) {
-      event.preventDefault();
-      event.stopPropagation();
-    } else {
-      event.returnValue = false;
-      event.cancelBubble = true;
-    }
-  },
-
-  // find the first node with the given tagName, starting from the
-  // node the event was triggered on; traverses the DOM upwards
-  findElement: function(event, tagName) {
-    var element = Event.element(event);
-    while (element.parentNode && (!element.tagName ||
-        (element.tagName.toUpperCase() != tagName.toUpperCase())))
-      element = element.parentNode;
-    return element;
-  },
-
-  observers: false,
-
-  _observeAndCache: function(element, name, observer, useCapture) {
-    if (!this.observers) this.observers = [];
-    if (element.addEventListener) {
-      this.observers.push([element, name, observer, useCapture]);
-      element.addEventListener(name, observer, useCapture);
-    } else if (element.attachEvent) {
-      this.observers.push([element, name, observer, useCapture]);
-      element.attachEvent('on' + name, observer);
-    }
-  },
-
-  unloadCache: function() {
-    if (!Event.observers) return;
-    for (var i = 0; i < Event.observers.length; i++) {
-      Event.stopObserving.apply(this, Event.observers[i]);
-      Event.observers[i][0] = null;
-    }
-    Event.observers = false;
-  },
-
-  observe: function(element, name, observer, useCapture) {
-    var element = $(element);
-    useCapture = useCapture || false;
-
-    if (name == 'keypress' &&
-        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-        || element.attachEvent))
-      name = 'keydown';
-
-    this._observeAndCache(element, name, observer, useCapture);
-  },
-
-  stopObserving: function(element, name, observer, useCapture) {
-    var element = $(element);
-    useCapture = useCapture || false;
-
-    if (name == 'keypress' &&
-        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
-        || element.detachEvent))
-      name = 'keydown';
-
-    if (element.removeEventListener) {
-      element.removeEventListener(name, observer, useCapture);
-    } else if (element.detachEvent) {
-      element.detachEvent('on' + name, observer);
-    }
-  }
-});
-
-/* prevent memory leaks in IE */
-Event.observe(window, 'unload', Event.unloadCache, false);
-var Position = {
-  // set to true if needed, warning: firefox performance problems
-  // NOT neeeded for page scrolling, only if draggable contained in
-  // scrollable elements
-  includeScrollOffsets: false,
-
-  // must be called before calling withinIncludingScrolloffset, every time the
-  // page is scrolled
-  prepare: function() {
-    this.deltaX =  window.pageXOffset
-                || document.documentElement.scrollLeft
-                || document.body.scrollLeft
-                || 0;
-    this.deltaY =  window.pageYOffset
-                || document.documentElement.scrollTop
-                || document.body.scrollTop
-                || 0;
-  },
-
-  realOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.scrollTop  || 0;
-      valueL += element.scrollLeft || 0;
-      element = element.parentNode;
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  cumulativeOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      element = element.offsetParent;
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  positionedOffset: function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      element = element.offsetParent;
-      if (element) {
-        p = Element.getStyle(element, 'position');
-        if (p == 'relative' || p == 'absolute') break;
-      }
-    } while (element);
-    return [valueL, valueT];
-  },
-
-  offsetParent: function(element) {
-    if (element.offsetParent) return element.offsetParent;
-    if (element == document.body) return element;
-
-    while ((element = element.parentNode) && element != document.body)
-      if (Element.getStyle(element, 'position') != 'static')
-        return element;
-
-    return document.body;
-  },
-
-  // caches x/y coordinate pair to use with overlap
-  within: function(element, x, y) {
-    if (this.includeScrollOffsets)
-      return this.withinIncludingScrolloffsets(element, x, y);
-    this.xcomp = x;
-    this.ycomp = y;
-    this.offset = this.cumulativeOffset(element);
-
-    return (y >= this.offset[1] &&
-            y <  this.offset[1] + element.offsetHeight &&
-            x >= this.offset[0] &&
-            x <  this.offset[0] + element.offsetWidth);
-  },
-
-  withinIncludingScrolloffsets: function(element, x, y) {
-    var offsetcache = this.realOffset(element);
-
-    this.xcomp = x + offsetcache[0] - this.deltaX;
-    this.ycomp = y + offsetcache[1] - this.deltaY;
-    this.offset = this.cumulativeOffset(element);
-
-    return (this.ycomp >= this.offset[1] &&
-            this.ycomp <  this.offset[1] + element.offsetHeight &&
-            this.xcomp >= this.offset[0] &&
-            this.xcomp <  this.offset[0] + element.offsetWidth);
-  },
-
-  // within must be called directly before
-  overlap: function(mode, element) {
-    if (!mode) return 0;
-    if (mode == 'vertical')
-      return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
-        element.offsetHeight;
-    if (mode == 'horizontal')
-      return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
-        element.offsetWidth;
-  },
-
-  clone: function(source, target) {
-    source = $(source);
-    target = $(target);
-    target.style.position = 'absolute';
-    var offsets = this.cumulativeOffset(source);
-    target.style.top    = offsets[1] + 'px';
-    target.style.left   = offsets[0] + 'px';
-    target.style.width  = source.offsetWidth + 'px';
-    target.style.height = source.offsetHeight + 'px';
-  },
-
-  page: function(forElement) {
-    var valueT = 0, valueL = 0;
-
-    var element = forElement;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-
-      // Safari fix
-      if (element.offsetParent==document.body)
-        if (Element.getStyle(element,'position')=='absolute') break;
-
-    } while (element = element.offsetParent);
-
-    element = forElement;
-    do {
-      valueT -= element.scrollTop  || 0;
-      valueL -= element.scrollLeft || 0;
-    } while (element = element.parentNode);
-
-    return [valueL, valueT];
-  },
-
-  clone: function(source, target) {
-    var options = Object.extend({
-      setLeft:    true,
-      setTop:     true,
-      setWidth:   true,
-      setHeight:  true,
-      offsetTop:  0,
-      offsetLeft: 0
-    }, arguments[2] || {})
-
-    // find page position of source
-    source = $(source);
-    var p = Position.page(source);
-
-    // find coordinate system to use
-    target = $(target);
-    var delta = [0, 0];
-    var parent = null;
-    // delta [0,0] will do fine with position: fixed elements,
-    // position:absolute needs offsetParent deltas
-    if (Element.getStyle(target,'position') == 'absolute') {
-      parent = Position.offsetParent(target);
-      delta = Position.page(parent);
-    }
-
-    // correct by body offsets (fixes Safari)
-    if (parent == document.body) {
-      delta[0] -= document.body.offsetLeft;
-      delta[1] -= document.body.offsetTop;
-    }
-
-    // set position
-    if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + 'px';
-    if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + 'px';
-    if(options.setWidth)  target.style.width = source.offsetWidth + 'px';
-    if(options.setHeight) target.style.height = source.offsetHeight + 'px';
-  },
-
-  absolutize: function(element) {
-    element = $(element);
-    if (element.style.position == 'absolute') return;
-    Position.prepare();
-
-    var offsets = Position.positionedOffset(element);
-    var top     = offsets[1];
-    var left    = offsets[0];
-    var width   = element.clientWidth;
-    var height  = element.clientHeight;
-
-    element._originalLeft   = left - parseFloat(element.style.left  || 0);
-    element._originalTop    = top  - parseFloat(element.style.top || 0);
-    element._originalWidth  = element.style.width;
-    element._originalHeight = element.style.height;
-
-    element.style.position = 'absolute';
-    element.style.top    = top + 'px';;
-    element.style.left   = left + 'px';;
-    element.style.width  = width + 'px';;
-    element.style.height = height + 'px';;
-  },
-
-  relativize: function(element) {
-    element = $(element);
-    if (element.style.position == 'relative') return;
-    Position.prepare();
-
-    element.style.position = 'relative';
-    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
-    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
-    element.style.top    = top + 'px';
-    element.style.left   = left + 'px';
-    element.style.height = element._originalHeight;
-    element.style.width  = element._originalWidth;
-  }
-}
-
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned.  For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
-  Position.cumulativeOffset = function(element) {
-    var valueT = 0, valueL = 0;
-    do {
-      valueT += element.offsetTop  || 0;
-      valueL += element.offsetLeft || 0;
-      if (element.offsetParent == document.body)
-        if (Element.getStyle(element, 'position') == 'absolute') break;
-
-      element = element.offsetParent;
-    } while (element);
-
-    return [valueL, valueT];
-  }
-}
\ No newline at end of file
diff --git a/extra/http/server/resources/stylesheet.css b/extra/http/server/resources/stylesheet.css
deleted file mode 100644 (file)
index a1afce7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-a:link { text-decoration: none; color: black; }
-a:visited { text-decoration: none; color: black; }
-a:active { text-decoration: none; color: black; }
-a:hover { text-decoration: underline; color: black; }
index 2a2eae72d7151d5bdc82f0cc162d2f7423257a07..e6abcc7a72edbb3940570526edcbb96e04ff0f33 100644 (file)
@@ -34,7 +34,7 @@ IN: http.server.responders.continuation.examples
     <h1> over write </h1>
     swap [ 
       <a =href a> "Next" write </a>
-    ] html-document 
+    ] simple-html-document 
   ] show 2drop ;
 
 : display-get-name-page ( -- name )
@@ -47,7 +47,7 @@ IN: http.server.responders.continuation.examples
         <input "text" =type "name" =name "20" =size input/>
         <input "submit" =type "Ok" =value input/>
       </form>
-    ] html-document
+    ] simple-html-document
   ] show "name" swap at ;
 
 : test-cont-responder ( -- )
@@ -71,7 +71,7 @@ IN: http.server.responders.continuation.examples
         <li> "Test responder1" [ test-cont-responder ] quot-href </li>
         <li> "Test responder2" [ test-cont-responder2 ] quot-href </li>
       </ol>
-    ] html-document 
+    ] simple-html-document 
   ] show-final ;
 
 : counter-example ( count -- )
@@ -87,7 +87,7 @@ IN: http.server.responders.continuation.examples
       "++" over 1quotation [ f ] swap append [ 1 + counter-example ] append quot-href
       "--" over 1quotation [ f ] swap append [ 1 - counter-example ] append quot-href
       drop
-    ] html-document 
+    ] simple-html-document 
   ] show drop ;
 
 : counter-example2 ( -- )
@@ -102,7 +102,7 @@ IN: http.server.responders.continuation.examples
       <h2> "counter" get unparse write </h2>
       "++" [ "counter" get 1 + "counter" set ] quot-href
       "--" [ "counter" get 1 - "counter" set ] quot-href
-    ] html-document 
+    ] simple-html-document 
   ] show 
   drop ;
 
index e6af805462df706ae7af5611ef32a61d96f0d5e9..4f83e8fa9806ba6a6f15e13c319553801ef5a3a6 100644 (file)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2004, 2006 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: calendar html io io.files kernel math math.parser http.server.responders
-http.server.templating namespaces parser sequences strings assocs hashtables
-debugger http.mime sorting ;
+USING: calendar html io io.files kernel math math.parser
+http.server.responders http.server.templating namespaces parser
+sequences strings assocs hashtables debugger http.mime sorting
+html.elements ;
 
 IN: http.server.responders.file
 
@@ -55,19 +56,25 @@ SYMBOL: page
     dup mime-type dup "application/x-factor-server-page" =
     [ drop serving-html run-page ] [ serve-static ] if ;
 
-: file. ( path name dirp -- )
-    "[DIR] " "      " ? write
-    dup <pathname> write-object nl ;
+: file. ( name dirp -- )
+    [ "/" append ] when
+    dup <a =href a> write </a> ;
 
-: directory. ( path -- )
-    directory sort-keys [ first2 file. ] each ;
+: directory. ( path request -- )
+    dup [
+        <h1> write </h1>
+        <ul>
+            directory sort-keys
+            [ <li> file. </li> ] assoc-each
+        </ul>
+    ] simple-html-document ;
 
 : list-directory ( directory -- )
     serving-html
      "method" get "head" = [
         drop
     ] [
-        "request" get [ directory. ] simple-html-document
+        "request" get directory.
     ] if ;
 
 : find-index ( filename -- path )
@@ -98,17 +105,17 @@ SYMBOL: page
     ] if ;
 
 global [
-    ! Javascript source used by ajax libraries
+    ! Serve up our own source code
     "resources" [ 
         [
-            "extra/http/server/resources/" resource-path "doc-root" set
+            "" resource-path "doc-root" set
             file-responder
         ] with-scope
     ] add-simple-responder
     
     ! Serves files from a directory stored in the "doc-root"
-    ! variable. You can set the variable in the global namespace,
-    ! or inside the responder.
+    ! variable. You can set the variable in the global
+    ! namespace, or inside the responder.
     "file" [ file-responder ] add-simple-responder
     
     ! The root directory is served by...
index 725cb515b0f71caf5de930703202293abb4de80d..aadf513aea21c0e8032c69ab03db7352bba8b7c8 100644 (file)
@@ -16,16 +16,16 @@ SYMBOL: responders
 : response ( header msg -- )
     "HTTP/1.0 " write print print-header ;
 
-: error-body ( error -- body )
+: error-body ( error -- )
     <html> <body> <h1> write </h1> </body> </html> ;
 
 : error-head ( error -- )
     dup log-error
-    H{ { "Content-Type" "text/html" } } over response ;
+    H{ { "Content-Type" "text/html" } } swap response ;
 
 : httpd-error ( error -- )
     #! This must be run from handle-request
-    error-head
+    dup error-head
     "head" "method" get = [ drop ] [ nl error-body ] if ;
 
 : bad-request ( -- )
@@ -101,7 +101,8 @@ SYMBOL: max-post-request
     dup "request" set ;
 
 : prepare-header ( -- )
-    read-header dup "header" set
+    read-header
+    dup "header" set
     dup log-headers
     read-post-request "response" set "raw-response" set ;
 
index 317a5ae83b50c892fdc78b028515f91d9a93df53..2b42cddc6a28585a75d15e556c4792c14128ef1a 100644 (file)
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 
 USING: kernel math sequences kernel.private namespaces arrays
-io io.files splitting io.binary math.functions vectors ;
+io io.files splitting io.binary math.functions vectors
+quotations combinators.private ;
 IN: universal-machine
 
 SYMBOL: regs
index c986a096641a8e4f483b9aa35d0889a2e2a9ba5f..fc34b3448bd53633aa2470b30209eafeefc515e5 100644 (file)
@@ -1,7 +1,7 @@
 USING: alien.c-types hexdump io io.backend io.sockets.headers
 io.sockets.headers.bsd kernel io.sniffer io.sniffer.bsd
 io.sniffer.filter io.streams.string io.unix.backend math
-sequences system ;
+sequences system byte-arrays ;
 IN: io.sniffer.filter.bsd
 
 ! http://www.iana.org/assignments/ethernet-numbers
index 7c1113039768c9665a65702445e9c989cc20f8b5..12a36091ce510aee68f513de2cd50b9eab9fa6af 100644 (file)
@@ -16,7 +16,10 @@ M: null-stream stream-write 2drop ;
 M: null-stream stream-nl drop ;
 M: null-stream stream-flush drop ;
 M: null-stream stream-format 3drop ;
-M: null-stream with-nested-stream rot drop with-stream* ;
+M: null-stream make-span-stream nip ;
+M: null-stream make-block-stream nip ;
+M: null-stream make-cell-stream nip ;
+M: null-stream stream-write-table 3drop ;
 
 : with-null-stream ( quot -- )
     T{ null-stream } swap with-stream* ; inline
index ca157fa2a7c30feebf1e31942c7ffabc323e5a16..688507be78492e45ce593359aa35cf7ad0658262 100644 (file)
@@ -4,7 +4,8 @@
 USING: kernel namespaces sequences sequences.private assocs
        math inference.transforms parser words quotations debugger
        macros arrays macros splitting combinators prettyprint.backend
-       definitions prettyprint hashtables combinators.lib ;
+       definitions prettyprint hashtables combinators.lib
+       prettyprint.sections ;
 
 IN: locals
 
index 21c918e33ea997b8c2cb6505873dc043b45a3b00..77484aca74430fcd979502c9985361419aee84b9 100644 (file)
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.\r
 !\r
 IN: openal.macosx\r
-USING: openal alien.c-types kernel alien alien.syntax shuffle ;\r
+USING: openal alien.c-types kernel alien alien.syntax shuffle\r
+combinators.lib ;\r
 \r
 LIBRARY: alut\r
 \r
index 287e6eebb8c496bab583084e2a8584300264f103..3f695a4f60562e5ff017f12b3f9ed8bcf6468a83 100644 (file)
@@ -4,7 +4,8 @@
 USING: cpu.8080 openal math alien.c-types sequences kernel
        shuffle arrays io.files combinators kernel.private
        ui.gestures ui.gadgets ui.render opengl.gl system 
-       threads concurrency match ui byte-arrays combinators.lib ;
+       threads concurrency match ui byte-arrays combinators.lib
+       combinators.private ;
 IN: space-invaders
 
 TUPLE: space-invaders port1 port2i port2o port3o port4lo port4hi port5o bitmap sounds looping? ;
index 671150b10a13f61c43d1ddeb79db744e2e457f4e..85f4812d9ad5e0b364f164b680d17bc17ad1bdb6 100644 (file)
@@ -1,5 +1,5 @@
-USING: kernel parser strings math namespaces sequences words io arrays 
-quotations debugger kernel.private ;
+USING: kernel parser strings math namespaces sequences words io
+arrays quotations debugger kernel.private combinators.private ;
 IN: state-machine
 
 : STATES:
index ec0590df349abd04c96a741fb8ef5d133cbd714a..366baffcb99fe0dc1bb9567127d56c3b3b778a8c 100644 (file)
@@ -10,7 +10,7 @@ IN: webapps.help
     serving-html
     dup article-title [
         [ help ] with-html-stream
-    ] html-document ;
+    ] simple-html-document ;
 
 : string>topic ( string -- topic )
     " " split dup length 1 = [ first ] when ;
@@ -73,9 +73,10 @@ M: vocab-author browser-link-href
 "help" "show-help" "extra/webapps/help" web-app
 
 ! Hard-coding for factorcode.org
-M: pathname browser-link-href
-    pathname-string "resource:" ?head [
-        "http://factorcode.org/repos/Factor/" swap append
-    ] [
-        drop f
-    ] if ;
+PREDICATE: pathname resource-pathname
+    pathname-string "resource:" head? ;
+
+M: resource-pathname browser-link-href
+    pathname-string
+    "resource:" ?head drop
+    "/responder/resources/" swap append ;
index f88d4c586317d1e19d5835c4de95363d5590da3a..303de4295e70a9714fbe1d2e60170ce76e63b63d 100644 (file)
@@ -10,9 +10,9 @@ IN: xml.utilities
 TUPLE: process-missing process tag ;\r
 M: process-missing error.\r
     "Tag <" write\r
-    process-missing-tag print-name\r
+    dup process-missing-tag print-name\r
     "> not implemented on process process " write\r
-    dup process-missing-process word-name print ;\r
+    process-missing-process word-name print ;\r
 \r
 : run-process ( tag word -- )\r
     2dup "xtable" word-prop\r
diff --git a/misc/icons/FRaptorMix.ico b/misc/icons/FRaptorMix.ico
deleted file mode 100644 (file)
index 6d199e7..0000000
Binary files a/misc/icons/FRaptorMix.ico and /dev/null differ
diff --git a/misc/icons/FRaptorMix_128x128.png b/misc/icons/FRaptorMix_128x128.png
deleted file mode 100644 (file)
index bc08801..0000000
Binary files a/misc/icons/FRaptorMix_128x128.png and /dev/null differ
diff --git a/misc/icons/FRaptorMix_16x16.png b/misc/icons/FRaptorMix_16x16.png
deleted file mode 100644 (file)
index 1613566..0000000
Binary files a/misc/icons/FRaptorMix_16x16.png and /dev/null differ
diff --git a/misc/icons/FRaptorMix_32x32.png b/misc/icons/FRaptorMix_32x32.png
deleted file mode 100644 (file)
index d93a4a6..0000000
Binary files a/misc/icons/FRaptorMix_32x32.png and /dev/null differ
diff --git a/misc/icons/FRaptorMix_48x48.png b/misc/icons/FRaptorMix_48x48.png
deleted file mode 100644 (file)
index 1200571..0000000
Binary files a/misc/icons/FRaptorMix_48x48.png and /dev/null differ
diff --git a/misc/icons/Factor.ico b/misc/icons/Factor.ico
new file mode 100644 (file)
index 0000000..fa4baa8
Binary files /dev/null and b/misc/icons/Factor.ico differ
diff --git a/misc/icons/Factor_128x128.png b/misc/icons/Factor_128x128.png
new file mode 100644 (file)
index 0000000..1854aa6
Binary files /dev/null and b/misc/icons/Factor_128x128.png differ
diff --git a/misc/icons/Factor_16x16.png b/misc/icons/Factor_16x16.png
new file mode 100644 (file)
index 0000000..2361ef4
Binary files /dev/null and b/misc/icons/Factor_16x16.png differ
diff --git a/misc/icons/Factor_32x32.png b/misc/icons/Factor_32x32.png
new file mode 100644 (file)
index 0000000..9d6368e
Binary files /dev/null and b/misc/icons/Factor_32x32.png differ
diff --git a/misc/icons/Factor_48x48.png b/misc/icons/Factor_48x48.png
new file mode 100644 (file)
index 0000000..364bb44
Binary files /dev/null and b/misc/icons/Factor_48x48.png differ
index 3a886d770cd60c19730d393a0a9e1e09a531734e..7979a793a92985346e7de3a84e0e3bdd7f03068b 100644 (file)
@@ -1,4 +1,4 @@
 The icons/images/jackets contained in this archive are
-Copyright (C) 2007 Elie CHAFTARI. All Rights Reserved.
+Copyright (C) 2007 Elie Chaftari. All Rights Reserved.
 
 See http://factorcode.org/license.txt for BSD license.
\ No newline at end of file
index 295e16f04c1a3f564a76745b87cdcb5201a8fa51..295fffa1a5bfcc1446c3bbfa16a9a5ec7eba3ee3 100644 (file)
@@ -4,7 +4,7 @@ in the public domain. */
 
 /* Note that the XT is passed to the quotation in r11 */
 #define CALL_OR_JUMP_QUOT \
-        lwz r11,5(r3)      /* load quotation-xt slot */ XX \
+        lwz r11,9(r3)      /* load quotation-xt slot */ XX \
 
 #define CALL_QUOT \
         CALL_OR_JUMP_QUOT XX \
@@ -40,11 +40,19 @@ in the public domain. */
 
 #define RESTORE(register,offset) lwz register,SAVE_AT(offset)(r1)
 
-DEF(void,c_to_factor,(CELL quot)):
-        mflr r0            /* get caller's return address */
-        stwu r1,-FRAME(r1) /* create a stack frame to hold non-volatile registers */
+#define PROLOGUE \
+       mflr r0 XX         /* get caller's return address */ \
+        stwu r1,-FRAME(r1) XX /* create a stack frame to hold non-volatile registers */ \
         SAVE_LR(r0)
 
+#define EPILOGUE \
+       LOAD_LR(r0) XX \
+        lwz r1,0(r1) XX    /* destroy the stack frame */ \
+        mtlr r0            /* get ready to return */
+
+DEF(void,c_to_factor,(CELL quot)):
+        PROLOGUE
+
        SAVE(r13,0)        /* save GPRs */
                            /* don't save ds pointer */
                            /* don't save rs pointer */
@@ -92,9 +100,7 @@ DEF(void,c_to_factor,(CELL quot)):
                            /* don't restore ds pointer */
         RESTORE(r13,0)
 
-        LOAD_LR(r0)
-        lwz r1,0(r1)       /* destroy the stack frame */
-        mtlr r0            /* get ready to return */
+        EPILOGUE
         blr
 
 /* The JIT compiles an 'mr r4,r1' in front of every primitive call, since a
@@ -164,6 +170,13 @@ DEF(void,throw_impl,(CELL quot, F_STACK_FRAME *rewind_to)):
        mtlr r0
        JUMP_QUOT          /* call the quotation */
 
+DEF(void,lazy_jit_compile,(CELL quot)):
+       mr r4,r1           /* save stack pointer */
+       PROLOGUE
+       bl MANGLE(jit_compile)
+       EPILOGUE
+        JUMP_QUOT          /* call the quotation */
+
 /* Thanks to Joshua Grams for this code.
 
 On PowerPC processors, we must flush the instruction cache manually
index e4ff35c15c602f133d72249167157bf6ec41fa65..c74e13e68b0181db464f28d8fcdad2c3958bd861 100644 (file)
@@ -11,6 +11,7 @@ void docol(CELL word);
 void undefined(CELL word);
 void set_callstack(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, void *memcpy);
 void throw_impl(CELL quot, F_STACK_FRAME *rewind);
+void lazy_jit_compile(CELL quot);
 void flush_icache(CELL start, CELL len);
 
 #define FRAME_SUCCESSOR(frame) (frame)->previous
index 19a735ec88b21ff8b96edb6aa604ecafb29cb4f9..6233b4a14f22812af88ac9829fe9db9a650a0576 100644 (file)
@@ -9,6 +9,7 @@ and the callstack top is passed in EDX */
 #define XT_REG %ecx
 #define STACK_REG %esp
 #define DS_REG %esi
+#define RETURN_REG %eax
 
 #define CELL_SIZE 4
 
@@ -20,7 +21,7 @@ and the callstack top is passed in EDX */
        pop %ebp ; \
        pop %ebx
 
-#define QUOT_XT_OFFSET 5
+#define QUOT_XT_OFFSET 9
 #define PROFILING_OFFSET 25
 #define WORD_DEF_OFFSET 13
 #define WORD_XT_OFFSET 29
index 1725c0cbd594cc98360a7bda81eb2dd865e7f375..4e8faa18de1903baa7028dd538cd3090e3c0ebec 100644 (file)
@@ -5,6 +5,7 @@
 #define XT_REG %rcx
 #define STACK_REG %rsp
 #define DS_REG %r14
+#define RETURN_REG %rax
 
 #define CELL_SIZE 8
 
@@ -20,7 +21,7 @@
        pop %rbp ; \
        pop %rbx
 
-#define QUOT_XT_OFFSET 13
+#define QUOT_XT_OFFSET 21
 #define PROFILING_OFFSET 53
 #define WORD_DEF_OFFSET 29
 #define WORD_XT_OFFSET 61
index 3e2a97dd5cdb6246729083060aec7adc70e99a07..ec5d09291e9e43e5ae4dcf69c5842a7bfcf6501f 100644 (file)
@@ -51,3 +51,15 @@ DEF(FASTCALL void,primitive_execute,(void)):
 DEF(FASTCALL void,throw_impl,(CELL quot, F_STACK_FRAME *rewind_to)):
        mov ARG1,STACK_REG                    /* rewind_to */
        JUMP_QUOT
+
+DEF(FASTCALL void,lazy_jit_compile,(CELL quot)):
+       mov STACK_REG,ARG1           /* Save stack pointer */
+       push XT_REG                  /* Alignment */
+       push XT_REG
+       push XT_REG
+       call MANGLE(jit_compile)
+       mov RETURN_REG,ARG0          /* No-op on 32-bit */
+       pop XT_REG                   /* OK to clobber XT_REG here */
+       pop XT_REG
+       pop XT_REG
+        JUMP_QUOT                    /* Call the quotation */
index eaf88f31c5c029995d59e3913e6b4f4a54c57097..a94dcadf81ce103adcf57da81ddd2e553025a477 100644 (file)
@@ -553,7 +553,7 @@ CELL collect_next(CELL scan)
                break;
        case QUOTATION_TYPE:
                quot = (F_QUOTATION *)scan;
-               if(collecting_code && quot->xt != NULL)
+               if(collecting_code && quot->xt != lazy_jit_compile)
                        recursive_mark(quot->xt);
                break;
        case CALLSTACK_TYPE:
index b7fb4ff68f2ae9e94057624ba16d88693093b677..57d195e2ba27b0c57869977a0ab98a0083cef099 100644 (file)
@@ -3,7 +3,12 @@
 void print_word(F_WORD* word, CELL nesting)
 {
        if(type_of(word->name) == STRING_TYPE)
-               printf("%s",to_char_string(untag_string(word->name),true));
+       {
+               F_STRING *string = untag_string(word->name);
+               CELL i;
+               for(i = 0; i < string_capacity(string); i++)
+                       putchar(cget(SREF(string,i)));
+       }
        else
        {
                printf("#<not a string: ");
@@ -14,7 +19,11 @@ void print_word(F_WORD* word, CELL nesting)
 
 void print_string(F_STRING* str)
 {
-       printf("\"%s\"",to_char_string(str,true));
+       putchar('"');
+       CELL i;
+       for(i = 0; i < string_capacity(str); i++)
+               putchar(cget(SREF(str,i)));
+       putchar('"');
 }
 
 void print_array(F_ARRAY* array, CELL nesting)
index e74662a8a42aed54ae93fec144d6e73d31e6c590..3f471f87f1c0afa05752821b458b22b6964fd60e 100644 (file)
@@ -126,14 +126,6 @@ void init_factor_from_args(F_CHAR *image, int argc, F_CHAR **argv, bool embedded
        userenv[EXECUTABLE_ENV] = tag_object(from_native_string(executable_path));
        userenv[EMBEDDED_ENV] = (embedded ? T : F);
 
-       if(!untag_quotation(userenv[BOOT_ENV])->xt)
-       {
-               /* This can only happen when we're starting a stage2 bootstrap.
-               The stage1 bootstrapper doesn't attempt to compile quotations,
-               so we do it here. */
-               jit_compile_all();
-       }
-
        nest_stacks();
        c_to_factor_toplevel(userenv[BOOT_ENV]);
        unnest_stacks();
index ffe83d00ab597dfd1637b55b0b2d1abad1d510d5..5b983cacba0c2b52b095ff15ec348d52b2795305 100644 (file)
@@ -1,2 +1,2 @@
-fraptor ICON "misc/icons/FRaptorMix.ico"\r
+fraptor ICON "misc/icons/Factor.ico"\r
 \r
index 32e628f902adc909a76616a923ac9dfe7db274c7..a4fd08af003578b94bc0a755922453c4544f269c 100644 (file)
@@ -154,17 +154,17 @@ void fixup_word(F_WORD *word)
 {
        /* If this is a compiled word, relocate the code pointer. Otherwise,
        reset it based on the primitive number of the word. */
-       if(word->compiledp != F)
-               code_fixup(&word->xt);
+       if(word->compiledp == F)
+               word->xt = default_word_xt(word);
        else
-               update_xt(word);
+               code_fixup(&word->xt);
 }
 
 void fixup_quotation(F_QUOTATION *quot)
 {
-       /* quot->xt is only ever NULL at the start of stage2 bootstrap,
-       in this case the JIT compiles all quotations */
-       if(quot->xt)
+       if(quot->compiled == F)
+               quot->xt = lazy_jit_compile;
+       else
                code_fixup(&quot->xt);
 }
 
index 7cdd645683e33b956e1e89001ed5566552bf0b7e..6faf0a6a17cf16204586b400fb17f43a147505fa 100644 (file)
--- a/vm/jit.c
+++ b/vm/jit.c
@@ -34,8 +34,13 @@ bool jit_stack_frame_p(F_ARRAY *array)
        return false;
 }
 
-void jit_compile(F_QUOTATION *quot)
+FASTCALL CELL jit_compile(CELL tagged, F_STACK_FRAME *stack)
 {
+       stack_chain->callstack_top = stack;
+
+       REGISTER_ROOT(tagged);
+
+       F_QUOTATION *quot = untag_quotation(tagged);
        F_ARRAY *array = untag_object(quot->array);
 
        REGISTER_UNTAGGED(quot);
@@ -150,21 +155,10 @@ void jit_compile(F_QUOTATION *quot)
 
        UNREGISTER_UNTAGGED(quot);
        quot->xt = xt;
-}
-
-void jit_compile_all(void)
-{
-       begin_scan();
-
-       CELL obj;
-       while((obj = next_object()) != F)
-       {
-               if(type_of(obj) == QUOTATION_TYPE)
-                       jit_compile(untag_quotation(obj));
-       }
+       quot->compiled = T;
 
-       /* End the scan */
-       gc_off = false;
+       UNREGISTER_ROOT(tagged);
+       return tagged;
 }
 
 XT quot_offset_to_pc(F_QUOTATION *quot, F_FIXNUM offset)
index 1758a24ff1ed048d66db3ae71857ac9b651f4ae6..a9f1399472b714bc72ed740fc4f5bad26160680a 100644 (file)
--- a/vm/jit.h
+++ b/vm/jit.h
@@ -1,3 +1,2 @@
-void jit_compile(F_QUOTATION *quot);
-void jit_compile_all(void);
+DLLEXPORT FASTCALL CELL jit_compile(CELL tagged, F_STACK_FRAME *stack);
 XT quot_offset_to_pc(F_QUOTATION *quot, F_FIXNUM offset);
index e5419d14702b67905f3c9d61e13760179c1049d0..fc59802f3636f67854124357b53c28739d5dbb1b 100644 (file)
@@ -194,6 +194,8 @@ typedef struct {
        CELL header;
        /* tagged */
        CELL array;
+       /* tagged */
+       CELL compiled;
        /* untagged */
        XT xt;
 } F_QUOTATION;
index 2b946b0722a89aca1fd729f6b67d8298c9232205..255be845d3053eee0349c93a36ffd7ada74b2586 100644 (file)
--- a/vm/run.c
+++ b/vm/run.c
@@ -20,23 +20,21 @@ void uncurry(CELL obj)
        }
 }
 
-void update_xt(F_WORD* word)
+XT default_word_xt(F_WORD *word)
 {
-       word->compiledp = F;
-
        if(word->def == T)
-               word->xt = dosym;
+               return dosym;
        else if(type_of(word->def) == QUOTATION_TYPE)
        {
                if(profiling)
-                       word->xt = docol_profiling;
+                       return docol_profiling;
                else
-                       word->xt = docol;
+                       return docol;
        }
        else if(type_of(word->def) == FIXNUM_TYPE)
-               word->xt = primitives[to_fixnum(word->def)];
+               return primitives[to_fixnum(word->def)];
        else
-               word->xt = undefined;
+               return undefined;
 }
 
 DEFINE_PRIMITIVE(uncurry)
index 4d031350d3a5dfb0e36f6df2e320fb3b2f912545..72ee7eea173366fecc84bf44110406a448510b19 100644 (file)
--- a/vm/run.h
+++ b/vm/run.h
@@ -145,7 +145,7 @@ INLINE CELL type_of(CELL tagged)
 DEFPUSHPOP(d,ds)
 DEFPUSHPOP(r,rs)
 
-void update_xt(F_WORD* word);
+XT default_word_xt(F_WORD *word);
 
 DECLARE_PRIMITIVE(execute);
 DECLARE_PRIMITIVE(call);
index cf3c1df00a76be017ed2859602dc938e3067a7b3..b2a05b91816cbfce4e5aeb505f63eaa27bbb8fe6 100644 (file)
@@ -407,13 +407,12 @@ void stack_frame_to_array(F_STACK_FRAME *frame)
                offset = F;
 
 #ifdef CALLSTACK_UP_P
-       #define I(n) (n)
+       set_array_nth(array,frame_index++,frame_executing(frame));
+       set_array_nth(array,frame_index++,offset);
 #else
-       #define I(n) (array_capacity(array) - (n) - 1)
+       set_array_nth(array,frame_index--,offset);
+       set_array_nth(array,frame_index--,frame_executing(frame));
 #endif
-
-       set_array_nth(array,I(frame_index++),frame_executing(frame));
-       set_array_nth(array,I(frame_index++),offset);
 }
 
 DEFINE_PRIMITIVE(callstack_to_array)
@@ -429,7 +428,12 @@ DEFINE_PRIMITIVE(callstack_to_array)
 
        /* frame_count is equal to the total length now */
 
+#ifdef CALLSTACK_UP_P
        frame_index = 0;
+#else
+       frame_index = frame_count - 1;
+#endif
+
        iterate_callstack_object(stack,stack_frame_to_array);
 
        dpush(tag_object(array));
index 1b9b3513dc5a9a5d935d192bd22669571d1a23c6..d6cb96508a1f8cc4a506820a273ced91d5445b23 100644 (file)
@@ -131,12 +131,8 @@ DEFINE_PRIMITIVE(array_to_quotation)
 {
        F_QUOTATION *quot = allot_object(QUOTATION_TYPE,sizeof(F_QUOTATION));
        quot->array = dpeek();
-       quot->xt = NULL;
-
-       REGISTER_UNTAGGED(quot);
-       jit_compile(quot);
-       UNREGISTER_UNTAGGED(quot);
-
+       quot->xt = lazy_jit_compile;
+       quot->compiled = F;
        drepl(tag_object(quot));
 }
 
@@ -482,7 +478,8 @@ F_WORD *allot_word(CELL vocab, CELL name)
        word->def = F;
        word->props = F;
        word->counter = tag_fixnum(0);
-       update_xt(word);
+       word->compiledp = F;
+       word->xt = default_word_xt(word);
        return word;
 }
 
@@ -495,7 +492,9 @@ DEFINE_PRIMITIVE(word)
 
 DEFINE_PRIMITIVE(update_xt)
 {
-       update_xt(untag_word(dpop()));
+       F_WORD *word = untag_word(dpop());
+       word->compiledp = F;
+       word->xt = default_word_xt(word);
 }
 
 DEFINE_PRIMITIVE(word_xt)