]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge git://factorcode.org/git/littledan into unicode
authorSlava Pestov <slava@factorcode.org>
Thu, 6 Mar 2008 19:51:33 +0000 (13:51 -0600)
committerSlava Pestov <slava@factorcode.org>
Thu, 6 Mar 2008 19:51:33 +0000 (13:51 -0600)
93 files changed:
core/hashtables/hashtables.factor
core/io/files/files.factor
core/words/words-tests.factor
extra/builder/builder.factor
extra/calendar/format/format.factor
extra/db/db.factor
extra/db/sqlite/lib/lib.factor
extra/db/sqlite/sqlite-tests.factor
extra/db/sqlite/sqlite.factor
extra/db/sqlite/test.db [deleted file]
extra/db/tuples/tuples-tests.factor
extra/db/tuples/tuples.factor
extra/db/types/types.factor
extra/destructors/destructors-docs.factor
extra/destructors/destructors-tests.factor
extra/destructors/destructors.factor
extra/farkup/farkup-tests.factor
extra/furnace/authors.txt [deleted file]
extra/furnace/furnace-tests.factor [deleted file]
extra/furnace/furnace.factor [deleted file]
extra/furnace/sessions/authors.txt [deleted file]
extra/furnace/sessions/sessions.factor [deleted file]
extra/furnace/summary.txt [deleted file]
extra/furnace/tags.txt [deleted file]
extra/furnace/validator/authors.txt [deleted file]
extra/furnace/validator/validator-tests.factor [deleted file]
extra/furnace/validator/validator.factor [deleted file]
extra/html/parser/analyzer/analyzer.factor
extra/http/server/actions/actions-tests.factor
extra/http/server/actions/actions.factor
extra/http/server/auth/basic/basic.factor [new file with mode: 0755]
extra/http/server/auth/login/login.factor [new file with mode: 0755]
extra/http/server/auth/login/login.fhtml [new file with mode: 0755]
extra/http/server/auth/providers/assoc/assoc-tests.factor [new file with mode: 0755]
extra/http/server/auth/providers/assoc/assoc.factor [new file with mode: 0755]
extra/http/server/auth/providers/db/db-tests.factor [new file with mode: 0755]
extra/http/server/auth/providers/db/db.factor [new file with mode: 0755]
extra/http/server/auth/providers/null/null.factor [new file with mode: 0755]
extra/http/server/auth/providers/providers.factor [new file with mode: 0755]
extra/http/server/components/components.factor [new file with mode: 0644]
extra/http/server/crud/crud.factor [new file with mode: 0644]
extra/http/server/db/db.factor
extra/http/server/server.factor
extra/http/server/sessions/sessions-tests.factor
extra/http/server/sessions/sessions.factor
extra/http/server/templating/authors.txt [deleted file]
extra/http/server/templating/fhtml/authors.txt [new file with mode: 0644]
extra/http/server/templating/fhtml/fhtml-tests.factor [new file with mode: 0644]
extra/http/server/templating/fhtml/fhtml.factor [new file with mode: 0755]
extra/http/server/templating/fhtml/test/bug.fhtml [new file with mode: 0644]
extra/http/server/templating/fhtml/test/bug.html [new file with mode: 0644]
extra/http/server/templating/fhtml/test/example.fhtml [new file with mode: 0644]
extra/http/server/templating/fhtml/test/example.html [new file with mode: 0644]
extra/http/server/templating/fhtml/test/stack.fhtml [new file with mode: 0644]
extra/http/server/templating/fhtml/test/stack.html [new file with mode: 0644]
extra/http/server/templating/templating-tests.factor [deleted file]
extra/http/server/templating/templating.factor [deleted file]
extra/http/server/templating/test/bug.fhtml [deleted file]
extra/http/server/templating/test/bug.html [deleted file]
extra/http/server/templating/test/example.fhtml [deleted file]
extra/http/server/templating/test/example.html [deleted file]
extra/http/server/templating/test/stack.fhtml [deleted file]
extra/http/server/templating/test/stack.html [deleted file]
extra/http/server/validators/validators-tests.factor [new file with mode: 0644]
extra/http/server/validators/validators.factor [new file with mode: 0644]
extra/io/sniffer/bsd/bsd.factor
extra/io/unix/files/files.factor
extra/io/unix/kqueue/kqueue.factor
extra/ldap/ldap-tests.factor
extra/ldap/libldap/libldap.factor
extra/namespaces/lib/lib.factor
extra/openssl/libssl/libssl.factor
extra/pdf/libhpdf/libhpdf.factor
extra/pdf/pdf-tests.factor
extra/pdf/test/font_test.pdf [deleted file]
extra/peg/peg-docs.factor
extra/peg/peg.factor
extra/peg/search/search-tests.factor
extra/random-tester/safe-words/safe-words.factor
extra/regexp2/regexp2-tests.factor [new file with mode: 0644]
extra/regexp2/regexp2.factor [new file with mode: 0644]
extra/singleton/authors.txt [new file with mode: 0644]
extra/singleton/singleton-docs.factor [new file with mode: 0644]
extra/singleton/singleton.factor [new file with mode: 0644]
extra/smtp/smtp-tests.factor
extra/unix/stat/stat.factor
extra/unix/unix.factor
extra/webapps/callback/authors.txt [deleted file]
extra/webapps/callback/callback.factor [deleted file]
extra/webapps/continuation/authors.txt [deleted file]
extra/webapps/continuation/continuation.factor [deleted file]
extra/webapps/continuation/examples/authors.txt [deleted file]
extra/webapps/continuation/examples/examples.factor [deleted file]

index 359bedd0416b06cceacfacdf223bdd2e3663b3ed..7d8c6f0b5f85299491fcb27e430b61efcf095ff5 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays kernel kernel.private slots.private math assocs
-math.private sequences sequences.private vectors ;
+       math.private sequences sequences.private vectors ;
 IN: hashtables
 
 <PRIVATE
@@ -16,15 +16,16 @@ IN: hashtables
     2 fixnum+fast over wrap ; inline
 
 : (key@) ( key keys i -- array n ? )
-    3dup swap array-nth dup ((tombstone)) eq? [
-        2drop probe (key@)
-    ] [
-        dup ((empty)) eq? [
-            3drop nip f f
-        ] [
-            = [ rot drop t ] [ probe (key@) ] if
-        ] if
-    ] if ; inline
+    3dup swap array-nth
+    dup ((empty)) eq?
+      [ 3drop nip f f ]
+      [
+        =
+          [ rot drop t ]
+          [ probe (key@) ]
+        if
+      ]
+    if ; inline
 
 : key@ ( key hash -- array n ? )
     hash-array 2dup hash@ (key@) ; inline
index b51d7670693dba2b9964517090eccb5f2116cfcc..899a1be006b808c870b03382d504ea90c20fa218 100755 (executable)
@@ -54,6 +54,7 @@ TUPLE: no-parent-directory path ;
 TUPLE: file-info type size permissions modified ;
 
 HOOK: file-info io-backend ( path -- info )
+HOOK: link-info io-backend ( path -- info )
 
 SYMBOL: +regular-file+
 SYMBOL: +directory+
index 06f3c7a7827d713d1649aef9f9081c43c3c2dfaa..4d9933147b970885313121612958a78e69b1fed4 100755 (executable)
@@ -141,7 +141,11 @@ SYMBOL: quot-uses-b
 
 [ { + } ] [ \ quot-uses-b uses ] unit-test
 
-[ "IN: words.tests FORGET: undef-test : undef-test ; << undef-test >>" eval ]
+"undef-test" "words.tests" lookup [
+    [ forget ] with-compilation-unit
+] when*
+
+[ "IN: words.tests : undef-test ; << undef-test >>" eval ]
 [ [ undefined? ] is? ] must-fail-with
 
 [ ] [
index 92cd5f5241d26397b86426b199e888fe0cbfd259..41096e863cbf6feb5ef1595075c05ce436efe469 100644 (file)
@@ -39,7 +39,7 @@ IN: builder
 
 : record-git-id ( -- ) git-id "../git-id" [ . ] with-file-writer ;
 
-: do-make-clean ( -- desc ) { "make" "clean" } try-process ;
+: do-make-clean ( -- ) { "make" "clean" } try-process ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
index 75ceea8ea2cd08f30aab7a9be5ad2003a946a1c7..89e09e0d0cd3003cdd3aab2168cf3fbd11d886a7 100755 (executable)
@@ -36,8 +36,12 @@ M: timestamp year. ( timestamp -- )
 \r
 : pad-00 number>string 2 CHAR: 0 pad-left ;\r
 \r
+: pad-0000 number>string 4 CHAR: 0 pad-left ;\r
+\r
 : write-00 pad-00 write ;\r
 \r
+: write-0000 pad-0000 write ;\r
+\r
 : (timestamp>string) ( timestamp -- )\r
     dup day-of-week day-abbreviations3 nth write ", " write\r
     dup day>> number>string write bl\r
@@ -107,24 +111,68 @@ M: timestamp year. ( timestamp -- )
         60 / + *\r
     ] if ;\r
 \r
+: read-ymd ( -- y m d )\r
+    read-0000 "-" expect read-00 "-" expect read-00 ;\r
+\r
+: read-hms ( -- h m s )\r
+    read-00 ":" expect read-00 ":" expect read-00 ;\r
+\r
 : (rfc3339>timestamp) ( -- timestamp )\r
-    read-0000 ! year\r
-    "-" expect\r
-    read-00 ! month\r
-    "-" expect\r
-    read-00 ! day\r
+    read-ymd\r
     "Tt" expect\r
-    read-00 ! hour\r
-    ":" expect\r
-    read-00 ! minute\r
-    ":" expect\r
-    read-00 ! second\r
+    read-hms\r
     read-rfc3339-gmt-offset ! timezone\r
     <timestamp> ;\r
 \r
 : rfc3339>timestamp ( str -- timestamp )\r
     [ (rfc3339>timestamp) ] with-string-reader ;\r
 \r
+: (ymdhms>timestamp) ( -- timestamp )\r
+    read-ymd " " expect read-hms 0 <timestamp> ;\r
+\r
+: ymdhms>timestamp ( str -- timestamp )\r
+    [ (ymdhms>timestamp) ] with-string-reader ;\r
+\r
+: (hms>timestamp) ( -- timestamp )\r
+    f f f read-hms f <timestamp> ;\r
+\r
+: hms>timestamp ( str -- timestamp )\r
+    [ (hms>timestamp) ] with-string-reader ;\r
+\r
+: (ymd>timestamp) ( -- timestamp )\r
+    read-ymd f f f f <timestamp> ;\r
+\r
+: ymd>timestamp ( str -- timestamp )\r
+    [ (ymd>timestamp) ] with-string-reader ;\r
+\r
+: (timestamp>ymd) ( timestamp -- )\r
+    dup timestamp-year write-0000\r
+    "-" write\r
+    dup timestamp-month write-00\r
+    "-" write\r
+    timestamp-day write-00 ;\r
+\r
+: timestamp>ymd ( timestamp -- str )\r
+    [ (timestamp>ymd) ] with-string-writer ;\r
+\r
+: (timestamp>hms)\r
+    dup timestamp-hour write-00\r
+    ":" write\r
+    dup timestamp-minute write-00\r
+    ":" write\r
+    timestamp-second >integer write-00 ;\r
+\r
+: timestamp>hms ( timestamp -- str )\r
+    [ (timestamp>hms) ] with-string-writer ;\r
+\r
+: timestamp>ymdhms ( timestamp -- str )\r
+    >gmt\r
+    [\r
+        dup (timestamp>ymd)\r
+        " " write\r
+        (timestamp>hms)\r
+    ] with-string-writer ;\r
+\r
 : file-time-string ( timestamp -- string )\r
     [\r
         [ month>> month-abbreviations nth write ] keep bl\r
index e834144d0c2d603603f30e66a85587c4cc6ea993..170d9a60f12f1723fa08b3b850e2814b7225f403 100755 (executable)
@@ -34,7 +34,7 @@ HOOK: db-close db ( handle -- )
 TUPLE: statement handle sql in-params out-params bind-params bound? ;
 TUPLE: simple-statement ;
 TUPLE: prepared-statement ;
-TUPLE: result-set sql params handle n max ;
+TUPLE: result-set sql in-params out-params handle n max ;
 : <statement> ( sql in out -- statement )
     { (>>sql) (>>in-params) (>>out-params) } statement construct ;
 
@@ -47,6 +47,7 @@ GENERIC: query-results ( query -- result-set )
 GENERIC: #rows ( result-set -- n )
 GENERIC: #columns ( result-set -- n )
 GENERIC# row-column 1 ( result-set n -- obj )
+GENERIC# row-column-typed 1 ( result-set n -- sql )
 GENERIC: advance-row ( result-set -- )
 GENERIC: more-rows? ( result-set -- ? )
 
@@ -67,13 +68,16 @@ GENERIC: more-rows? ( result-set -- ? )
     0 >>n drop ;
 
 : <result-set> ( query handle tuple -- result-set )
-    >r >r { sql>> in-params>> } get-slots r>
-    { (>>sql) (>>params) (>>handle) } result-set
+    >r >r { sql>> in-params>> out-params>> } get-slots r>
+    { (>>sql) (>>in-params) (>>out-params) (>>handle) } result-set
     construct r> construct-delegate ;
 
 : sql-row ( result-set -- seq )
     dup #columns [ row-column ] with map ;
 
+: sql-row-typed ( result-set -- seq )
+    dup #columns [ row-column-typed ] with map ;
+
 : query-each ( statement quot -- )
     over more-rows? [
         [ call ] 2keep over advance-row query-each
index 648d8493dcb64925176ae3f07e8fcc46472261de..f11f1e2ba634722579e5033061c4d544b62e5994 100755 (executable)
@@ -2,7 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien.c-types arrays assocs kernel math math.parser
 namespaces sequences db.sqlite.ffi db combinators
-continuations db.types ;
+continuations db.types calendar.format serialize
+io.streams.string byte-arrays ;
+USE: tools.walker
 IN: db.sqlite.lib
 
 : sqlite-error ( n -- * )
@@ -55,6 +57,10 @@ IN: db.sqlite.lib
 : sqlite-bind-null ( handle i -- )
     sqlite3_bind_null sqlite-check-result ;
 
+: sqlite-bind-blob ( handle i byte-array -- )
+    dup length SQLITE_TRANSIENT
+    sqlite3_bind_blob sqlite-check-result ;
+
 : sqlite-bind-text-by-name ( handle name text -- )
     parameter-index sqlite-bind-text ;
 
@@ -67,20 +73,32 @@ IN: db.sqlite.lib
 : sqlite-bind-double-by-name ( handle name double -- )
     parameter-index sqlite-bind-double ;
 
+: sqlite-bind-blob-by-name ( handle name blob -- )
+    parameter-index sqlite-bind-blob ;
+
 : sqlite-bind-null-by-name ( handle name obj -- )
     parameter-index drop sqlite-bind-null ;
 
 : sqlite-bind-type ( handle key value type -- )
+    over [ drop NULL ] unless
     dup array? [ first ] when
     {
         { INTEGER [ sqlite-bind-int-by-name ] }
-        { BIG_INTEGER [ sqlite-bind-int64-by-name ] }
+        { BIG-INTEGER [ sqlite-bind-int64-by-name ] }
         { TEXT [ sqlite-bind-text-by-name ] }
         { VARCHAR [ sqlite-bind-text-by-name ] }
         { DOUBLE [ sqlite-bind-double-by-name ] }
-        { TIMESTAMP [ sqlite-bind-double-by-name ] }
+        { DATE [ sqlite-bind-text-by-name ] }
+        { TIME [ sqlite-bind-text-by-name ] }
+        { DATETIME [ sqlite-bind-text-by-name ] }
+        { TIMESTAMP [ sqlite-bind-text-by-name ] }
+        { BLOB [ sqlite-bind-blob-by-name ] }
+        { FACTOR-BLOB [
+            [ serialize ] with-string-writer >byte-array
+            sqlite-bind-blob-by-name
+        ] }
         { +native-id+ [ sqlite-bind-int-by-name ] }
-        { NULL [ sqlite-bind-null-by-name ] }
+        { NULL [ sqlite-bind-null-by-name ] }
         [ no-sql-type ]
     } case ;
 
@@ -93,21 +111,38 @@ IN: db.sqlite.lib
 : sqlite-#columns ( query -- int )
     sqlite3_column_count ;
 
-! TODO
 : sqlite-column ( handle index -- string )
     sqlite3_column_text ;
 
+: sqlite-column-blob ( handle index -- byte-array/f )
+    [ sqlite3_column_bytes ] 2keep
+    pick zero? [
+        3drop f
+    ] [
+        sqlite3_column_blob swap memory>byte-array
+    ] if ;
+
 : sqlite-column-typed ( handle index type -- obj )
+    dup array? [ first ] when
     {
+        { +native-id+ [ sqlite3_column_int64 ] }
         { INTEGER [ sqlite3_column_int ] }
-        { BIG_INTEGER [ sqlite3_column_int64 ] }
+        { BIG-INTEGER [ sqlite3_column_int64 ] }
         { TEXT [ sqlite3_column_text ] }
+        { VARCHAR [ sqlite3_column_text ] }
         { DOUBLE [ sqlite3_column_double ] }
-        { TIMESTAMP [ sqlite3_column_double ] }
+        { DATE [ sqlite3_column_text dup [ ymd>timestamp ] when ] }
+        { TIME [ sqlite3_column_text dup [ hms>timestamp ] when ] }
+        { TIMESTAMP [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
+        { DATETIME [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
+        { BLOB [ sqlite-column-blob ] }
+        { FACTOR-BLOB [
+            sqlite-column-blob [ deserialize ] with-string-reader
+        ] }
+        ! { NULL [ 2drop f ] }
         [ no-sql-type ]
     } case ;
 
-! TODO
 : sqlite-row ( handle -- seq )
     dup sqlite-#columns [ sqlite-column ] with map ;
 
index 08139610a05d2a9e69e0d06075931ce18a885108..b30cb4ba80f3d7bb1fb528db68cfa669f74706f9 100755 (executable)
@@ -3,7 +3,7 @@ prettyprint tools.test db.sqlite db sequences
 continuations db.types db.tuples unicode.case ;
 IN: db.sqlite.tests
 
-: db-path "extra/db/sqlite/test.db" resource-path ;
+: db-path "test.db" temp-file ;
 : test.db db-path sqlite-db ;
 
 [ ] [ [ db-path delete-file ] ignore-errors ] unit-test
index 62f5717c84e494996d01feb09c2c8233b9845d0d..643b42165da22d17bbeddb5fdce2b74e7395c44b 100755 (executable)
@@ -80,8 +80,9 @@ M: sqlite-result-set #columns ( result-set -- n )
 M: sqlite-result-set row-column ( result-set n -- obj )
     >r result-set-handle r> sqlite-column ;
 
-M: sqlite-result-set row-column-typed ( result-set n type -- obj )
-    >r result-set-handle r> sqlite-column-typed ;
+M: sqlite-result-set row-column-typed ( result-set n -- obj )
+    dup pick result-set-out-params nth sql-spec-type
+    >r >r result-set-handle r> r> sqlite-column-typed ;
 
 M: sqlite-result-set advance-row ( result-set -- )
     [ result-set-handle sqlite-next ] keep
@@ -141,6 +142,10 @@ M: sqlite-db <insert-assigned-statement> ( tuple -- statement )
     " where " 0%
     find-primary-key dup sql-spec-column-name 0% " = " 0% bind% ;
 
+: where-clause ( specs -- )
+    " where " 0%
+    [ " and " 0% ] [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave ;
+
 M: sqlite-db <update-tuple-statement> ( class -- statement )
     [
         "update " 0%
@@ -173,14 +178,7 @@ M: sqlite-db <select-by-slots-statement> ( tuple class -- statement )
 
         " from " 0% 0%
         [ sql-spec-slot-name swap get-slot-named ] with subset
-        dup empty? [
-            drop
-        ] [
-            " where " 0%
-            [ ", " 0% ]
-            [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
-        ] if
-        ";" 0%
+        dup empty? [ drop ] [ where-clause ] if ";" 0%
     ] sqlite-make ;
 
 M: sqlite-db modifier-table ( -- hashtable )
@@ -209,8 +207,13 @@ M: sqlite-db type-table ( -- assoc )
         { INTEGER "integer" }
         { TEXT "text" }
         { VARCHAR "text" }
+        { DATE "date" }
+        { TIME "time" }
+        { DATETIME "datetime" }
         { TIMESTAMP "timestamp" }
         { DOUBLE "real" }
+        { BLOB "blob" }
+        { FACTOR-BLOB "blob" }
     } ;
 
 M: sqlite-db create-type-table
diff --git a/extra/db/sqlite/test.db b/extra/db/sqlite/test.db
deleted file mode 100644 (file)
index e483c47..0000000
Binary files a/extra/db/sqlite/test.db and /dev/null differ
index 517f8bcc36a60ca0f9048072fcb531bcc679c462..5913f053da1cc417cd3b9928eab98e54c74238f8 100755 (executable)
@@ -1,40 +1,47 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: io.files kernel tools.test db db.tuples
-db.types continuations namespaces db.postgresql math
-prettyprint tools.walker db.sqlite ;
+db.types continuations namespaces math
+prettyprint tools.walker db.sqlite calendar
+math.intervals ;
 IN: db.tuples.tests
 
-TUPLE: person the-id the-name the-number the-real ;
-: <person> ( name age real -- person )
+TUPLE: person the-id the-name the-number the-real ts date time blob ;
+: <person> ( name age real ts date time blob -- person )
     {
         set-person-the-name
         set-person-the-number
         set-person-the-real
+        set-person-ts
+        set-person-date
+        set-person-time
+        set-person-blob
     } person construct ;
 
-: <assigned-person> ( id name number the-real -- obj )
+: <assigned-person> ( id name age real ts date time blob -- person )
     <person> [ set-person-the-id ] keep ;
 
-SYMBOL: the-person1
-SYMBOL: the-person2
+SYMBOL: person1
+SYMBOL: person2
+SYMBOL: person3
+SYMBOL: person4
 
 : test-tuples ( -- )
     [ person drop-table ] [ drop ] recover
     [ ] [ person create-table ] unit-test
     [ person create-table ] must-fail
     
-    [ ] [ the-person1 get insert-tuple ] unit-test
+    [ ] [ person1 get insert-tuple ] unit-test
 
-    [ 1 ] [ the-person1 get person-the-id ] unit-test
+    [ 1 ] [ person1 get person-the-id ] unit-test
 
-    200 the-person1 get set-person-the-number
+    200 person1 get set-person-the-number
 
-    [ ] [ the-person1 get update-tuple ] unit-test
+    [ ] [ person1 get update-tuple ] unit-test
 
     [ T{ person f 1 "billy" 200 3.14 } ]
     [ T{ person f 1 } select-tuple ] unit-test
-    [ ] [ the-person2 get insert-tuple ] unit-test
+    [ ] [ person2 get insert-tuple ] unit-test
     [
         {
             T{ person f 1 "billy" 200 3.14 }
@@ -48,9 +55,33 @@ SYMBOL: the-person2
         }
     ] [ T{ person f } select-tuples ] unit-test
 
+    [
+        {
+            T{ person f 2 "johnny" 10 3.14 }
+        }
+    ] [ T{ person f f f 10 3.14 } select-tuples ] unit-test
 
-    [ ] [ the-person1 get delete-tuple ] unit-test
+
+    [ ] [ person1 get delete-tuple ] unit-test
     [ f ] [ T{ person f 1 } select-tuple ] unit-test
+
+    [ ] [ person3 get insert-tuple ] unit-test
+
+    [
+        T{
+            person
+            f
+            3
+            "teddy"
+            10
+            3.14
+            T{ timestamp f 2008 3 5 16 24 11 0 }
+            T{ timestamp f 2008 11 22 f f f f }
+            T{ timestamp f f f f 12 34 56 f }
+            B{ 115 116 111 114 101 105 110 97 98 108 111 98 }
+        }
+    ] [ T{ person f 3 } select-tuple ] unit-test
+
     [ ] [ person drop-table ] unit-test ;
 
 : make-native-person-table ( -- )
@@ -67,9 +98,14 @@ SYMBOL: the-person2
         { "the-name" "NAME" { VARCHAR 256 } +not-null+ }
         { "the-number" "AGE" INTEGER { +default+ 0 } }
         { "the-real" "REAL" DOUBLE { +default+ 0.3 } }
+        { "ts" "TS" TIMESTAMP }
+        { "date" "D" DATE }
+        { "time" "T" TIME }
+        { "blob" "B" BLOB }
     } define-persistent
-    "billy" 10 3.14 <person> the-person1 set
-    "johnny" 10 3.14 <person> the-person2 set ;
+    "billy" 10 3.14 f f f f <person> person1 set
+    "johnny" 10 3.14 f f f f <person> person2 set
+    "teddy" 10 3.14 "2008-03-05 16:24:11" "2008-11-22" "12:34:56" B{ 115 116 111 114 101 105 110 97 98 108 111 98 } <person> person3 set ;
 
 : assigned-person-schema ( -- )
     person "PERSON"
@@ -78,10 +114,14 @@ SYMBOL: the-person2
         { "the-name" "NAME" { VARCHAR 256 } +not-null+ }
         { "the-number" "AGE" INTEGER { +default+ 0 } }
         { "the-real" "REAL" DOUBLE { +default+ 0.3 } }
+        { "ts" "TS" TIMESTAMP }
+        { "date" "D" DATE }
+        { "time" "T" TIME }
+        { "blob" "B" BLOB }
     } define-persistent
-    1 "billy" 10 3.14 <assigned-person> the-person1 set
-    2 "johnny" 10 3.14 <assigned-person> the-person2 set ;
-
+    1 "billy" 10 3.14 f f f f <assigned-person> person1 set
+    2 "johnny" 10 3.14 f f f f <assigned-person> person2 set
+    3 "teddy" 10 3.14 "2008-03-05 16:24:11" "2008-11-22" "12:34:56" B{ 115 116 111 114 101 105 110 97 98 108 111 98 } <assigned-person> person3 set ;
 
 TUPLE: paste n summary author channel mode contents timestamp annotations ;
 TUPLE: annotation n paste-id summary author mode contents ;
@@ -118,14 +158,54 @@ TUPLE: annotation n paste-id summary author mode contents ;
     ! [ ] [ annotation create-table ] unit-test
 ! ] with-db
 
-
 : test-sqlite ( quot -- )
-    >r "tuples-test.db" resource-path sqlite-db r> with-db ;
+    >r "tuples-test.db" temp-file sqlite-db r> with-db ;
 
-: test-postgresql ( -- )
-    >r { "localhost" "postgres" "" "factor-test" } postgresql-db r> with-db ;
+: test-postgresql ( -- )
+!    >r { "localhost" "postgres" "" "factor-test" } postgresql-db r> with-db ;
 
 [ native-person-schema test-tuples ] test-sqlite
 [ assigned-person-schema test-tuples ] test-sqlite
 
-! [ make-native-person-table ] test-sqlite
+TUPLE: serialize-me id data ;
+
+: test-serialize ( -- )
+    serialize-me "SERIALIZED"
+    {
+        { "id" "ID" +native-id+ }
+        { "data" "DATA" FACTOR-BLOB }
+    } define-persistent
+    [ serialize-me drop-table ] [ drop ] recover
+    [ ] [ serialize-me create-table ] unit-test
+
+    [ ] [ T{ serialize-me f f H{ { 1 2 } } } insert-tuple ] unit-test
+    [
+        { T{ serialize-me f 1 H{ { 1 2 } } } }
+    ] [ T{ serialize-me f 1 } select-tuples ] unit-test ;
+
+! [ test-serialize ] test-sqlite
+
+TUPLE: exam id name score ; 
+
+: test-ranges ( -- )
+    exam "EXAM"
+    {
+        { "id" "ID" +native-id+ }
+        { "name" "NAME" TEXT }
+        { "score" "SCORE" INTEGER }
+    } define-persistent
+    [ exam drop-table ] [ drop ] recover
+    [ ] [ exam create-table ] unit-test
+
+    [ ] [ T{ exam f f "Kyle" 100 } insert-tuple ] unit-test
+    [ ] [ T{ exam f f "Stan" 80 } insert-tuple ] unit-test
+    [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test
+    [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test
+
+    [
+        T{ exam f 3 "Kenny" 60 }
+        T{ exam f 4 "Cartman" 41 }
+    ] [ T{ exam f 4 f T{ interval f { 0 t } { 70 t } } } select-tuples ] unit-test
+    ;
+
+! [ test-ranges ] test-sqlite
index d61fe8135ee97a71c47b3dd4d8103bedcb73187b..32055ccedc35b84795238362e3f6678cbc709ce2 100755 (executable)
@@ -37,27 +37,24 @@ HOOK: <delete-tuples-statement> db ( class -- obj )
 
 HOOK: <select-by-slots-statement> db ( tuple -- tuple )
 
-HOOK: row-column-typed db ( result-set n type -- sql )
 HOOK: insert-tuple* db ( tuple statement -- )
 
 : resulting-tuple ( row out-params -- tuple )
     dup first sql-spec-class construct-empty [
         [
-            >r [ sql-spec-type sql-type>factor-type ] keep
-            sql-spec-slot-name r> set-slot-named
+            >r sql-spec-slot-name r> set-slot-named
         ] curry 2each
     ] keep ;
 
 : query-tuples ( statement -- seq )
     [ statement-out-params ] keep query-results [
-        [ sql-row swap resulting-tuple ] with query-map
+        [ sql-row-typed swap resulting-tuple ] with query-map
     ] with-disposal ;
  
 : query-modify-tuple ( tuple statement -- )
-    [ query-results [ sql-row ] with-disposal ] keep
+    [ query-results [ sql-row-typed ] with-disposal ] keep
     statement-out-params rot [
-        >r [ sql-spec-type sql-type>factor-type ] keep
-        sql-spec-slot-name r> set-slot-named
+        >r sql-spec-slot-name r> set-slot-named
     ] curry 2each ;
 
 : sql-props ( class -- columns table )
index c84b23c50f274794837f3c36014f5cb9c2f2b283..c2aa825db8479290e839d479678f18e17cdb04db 100755 (executable)
@@ -3,7 +3,8 @@
 USING: arrays assocs db kernel math math.parser
 sequences continuations sequences.deep sequences.lib
 words namespaces tools.walker slots slots.private classes
-mirrors tuples combinators ;
+mirrors tuples combinators calendar.format serialize
+io.streams.string ;
 IN: db.types
 
 HOOK: modifier-table db ( -- hash )
@@ -60,14 +61,19 @@ SYMBOL: +has-many+
 : relation? ( spec -- ? ) [ +has-many+ = ] deep-find ;
 
 SYMBOL: INTEGER
-SYMBOL: BIG_INTEGER
+SYMBOL: BIG-INTEGER
 SYMBOL: DOUBLE
 SYMBOL: REAL
 SYMBOL: BOOLEAN
 SYMBOL: TEXT
 SYMBOL: VARCHAR
-SYMBOL: TIMESTAMP
 SYMBOL: DATE
+SYMBOL: TIME
+SYMBOL: DATETIME
+SYMBOL: TIMESTAMP
+SYMBOL: BLOB
+SYMBOL: FACTOR-BLOB
+SYMBOL: NULL
 
 : spec>tuple ( class spec -- tuple )
     [ ?first3 ] keep 3 ?tail*
@@ -80,15 +86,6 @@ SYMBOL: DATE
     } sql-spec construct
     dup normalize-spec ;
 
-: sql-type-hash ( -- assoc )
-    H{
-        { INTEGER "integer" }
-        { TEXT "text" }
-        { VARCHAR "varchar" }
-        { DOUBLE "real" }
-        { TIMESTAMP "timestamp" }
-    } ;
-
 TUPLE: no-sql-type ;
 : no-sql-type ( -- * ) T{ no-sql-type } throw ;
 
@@ -210,15 +207,3 @@ TUPLE: no-slot-named ;
         >r dup sql-spec-type swap sql-spec-slot-name r>
         get-slot-named swap
     ] curry { } map>assoc ;
-
-: sql-type>factor-type ( obj type -- obj )
-    dup array? [ first ] when
-    {
-        { +native-id+ [ string>number ] }
-        { INTEGER [ string>number ] }
-        { DOUBLE [ string>number ] }
-        { REAL [ string>number ] }
-        { TEXT [ ] }
-        { VARCHAR [ ] }
-        [ "no conversion from sql type to factor type" throw ]
-    } case ;
index 4c51e7ddfbc72ff9265c570da6093e22b5801cf6..f96931c412920ad5f255b2045242e2f8918aef2b 100755 (executable)
@@ -1,4 +1,4 @@
-USING: help.markup help.syntax libc kernel ;
+USING: help.markup help.syntax libc kernel continuations ;
 IN: destructors
 
 HELP: free-always
@@ -23,7 +23,7 @@ HELP: close-later
 
 HELP: with-destructors
 { $values { "quot" "a quotation" } }
-{ $description "Calls a quotation within a new dynamic scope.  This quotation may register destructors, on any object, by wrapping the object in a destructor and implementing " { $link destruct } " on that object type.  After the quotation finishes, if an error was thrown, all destructors are called and the error is then rethrown.  However, if the quotation was successful, only those destructors created with an 'always cleanup' flag will be destroyed." }
+{ $description "Calls a quotation within a new dynamic scope.  This quotation may register destructors, on any object, by wrapping the object in a destructor and implementing " { $link dispose } " on that object type.  After the quotation finishes, if an error was thrown, all destructors are called and the error is then rethrown.  However, if the quotation was successful, only those destructors created with an 'always cleanup' flag will be destroyed." }
 { $notes "Destructors are not allowed to throw exceptions.  No exceptions." }
 { $examples
     { $code "[ 10 malloc free-always ] with-destructors" }
index 09b4ccc35757c792f296aeea86aa9c634e1f70b9..147e1836881585f978b55a6b3a0b9b60005c3374 100755 (executable)
@@ -9,7 +9,7 @@ TUPLE: dummy-destructor obj ;
 
 C: <dummy-destructor> dummy-destructor
 
-M: dummy-destructor destruct ( obj -- )
+M: dummy-destructor dispose ( obj -- )
     dummy-destructor-obj t swap set-dummy-obj-destroyed? ;
 
 : destroy-always
index 0f8ec3af84939c67d9145952864e9bfd9c1cad9a..b2561c74395af64d16c2392b2c43da1ea36cdf10 100755 (executable)
@@ -4,18 +4,16 @@ USING: continuations io.backend libc kernel namespaces
 sequences system vectors ;
 IN: destructors
 
-GENERIC: destruct ( obj -- )
-
 SYMBOL: error-destructors
 SYMBOL: always-destructors
 
 TUPLE: destructor object destroyed? ;
 
-M: destructor destruct
+M: destructor dispose
     dup destructor-destroyed? [
         drop
     ] [
-        dup destructor-object destruct
+        dup destructor-object dispose 
         t swap set-destructor-destroyed?
     ] if ;
 
@@ -29,10 +27,10 @@ M: destructor destruct
     <destructor> always-destructors get push ;
 
 : do-always-destructors ( -- )
-    always-destructors get [ destruct ] each ;
+    always-destructors get [ dispose ] each ;
 
 : do-error-destructors ( -- )
-    error-destructors get [ destruct ] each ;
+    error-destructors get [ dispose ] each ;
 
 : with-destructors ( quot -- )
     [
@@ -47,7 +45,7 @@ TUPLE: memory-destructor alien ;
 
 C: <memory-destructor> memory-destructor
 
-M: memory-destructor destruct ( obj -- )
+M: memory-destructor dispose ( obj -- )
     memory-destructor-alien free ;
 
 : free-always ( alien -- )
@@ -63,7 +61,7 @@ C: <handle-destructor> handle-destructor
 
 HOOK: destruct-handle io-backend ( obj -- )
 
-M: handle-destructor destruct ( obj -- )
+M: handle-destructor dispose ( obj -- )
     handle-destructor-alien destruct-handle ;
 
 : close-always ( handle -- )
@@ -79,7 +77,7 @@ C: <socket-destructor> socket-destructor
 
 HOOK: destruct-socket io-backend ( obj -- )
 
-M: socket-destructor destruct ( obj -- )
+M: socket-destructor dispose ( obj -- )
     socket-destructor-alien destruct-socket ;
 
 : close-socket-always ( handle -- )
index 2e0d9832b0f6f594d85c20ee3f45f89d6bea83cf..f4b3025fcd2b93eebb306871f2b5aa6c6c0bffdf 100755 (executable)
@@ -42,3 +42,7 @@ IN: farkup.tests
 
 [ "<p><strong>foo</strong>\n</p><h1>aheading</h1>\n<p>adfasd</p>" ]
 [ "*foo*\n=aheading=\nadfasd" convert-farkup ] unit-test
+
+[ "<p>=foo\n</p>" ] [ "=foo\n" convert-farkup ] unit-test
+[ "<h1>foo</h1>\n" ] [ "=foo=\n" convert-farkup ] unit-test
+[ "<p>lol</p><h1>foo</h1>\n" ] [ "lol=foo=\n" convert-farkup ] unit-test
diff --git a/extra/furnace/authors.txt b/extra/furnace/authors.txt
deleted file mode 100644 (file)
index f372b57..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Slava Pestov
-Doug Coleman
diff --git a/extra/furnace/furnace-tests.factor b/extra/furnace/furnace-tests.factor
deleted file mode 100755 (executable)
index d8124d1..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-USING: kernel sequences namespaces math tools.test furnace furnace.validator ;
-IN: furnace.tests
-
-TUPLE: test-tuple m n ;
-
-[ H{ { "m" 3 } { "n" 2 } } ]
-[
-    [ T{ test-tuple f 3 2 } explode-tuple ] H{ } make-assoc
-] unit-test
-
-[
-    { 3 }
-] [
-    H{ { "n" "3" } } { { "n" v-number } }
-    [ action-param drop ] with map
-] unit-test
-
-: foo ;
-
-\ foo { { "foo" "2" v-default } { "bar" v-required } } define-action
-
-[ t ] [ [ 1 2 foo ] action-call? ] unit-test
-[ f ] [ [ 2 + ] action-call? ] unit-test
-
-[
-    { "2" "hello" }
-] [
-    [
-        H{
-            { "bar" "hello" }
-        } \ foo query>seq
-    ] with-scope
-] unit-test
-
-[
-    H{ { "foo" "1" } { "bar" "2" } }
-] [
-    { "1" "2" } \ foo quot>query
-] unit-test
-
-[
-    "/responder/furnace.tests/foo?foo=3"
-] [
-    [
-        [ "3" foo ] quot-link
-    ] with-scope
-] unit-test
diff --git a/extra/furnace/furnace.factor b/extra/furnace/furnace.factor
deleted file mode 100755 (executable)
index 3bbd2d0..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-! Copyright (C) 2006, 2008 Slava Pestov, Doug Coleman
-! See http://factorcode.org/license.txt for BSD license.
-USING: arrays assocs calendar debugger furnace.sessions
-furnace.validator hashtables heaps html.elements http
-http.server.responders http.server.templating io.files kernel
-math namespaces quotations sequences splitting words strings
-vectors webapps.callback continuations tuples classes vocabs
-html io ;
-IN: furnace
-
-: code>quotation ( word/quot -- quot )
-    dup word? [ 1quotation ] when ;
-
-SYMBOL: default-action
-SYMBOL: template-path
-
-: render-template ( template -- )
-    template-path get swap path+
-    ".furnace" append resource-path
-    run-template-file ;
-
-: define-action ( word hash -- )
-    over t "action" set-word-prop
-    "action-params" set-word-prop ;
-
-: define-form ( word1 word2 hash -- )
-    dupd define-action
-    swap code>quotation "form-failed" set-word-prop ;
-
-: default-values ( word hash -- )
-    "default-values" set-word-prop ;
-
-SYMBOL: request-params
-SYMBOL: current-action
-SYMBOL: validators-errored
-SYMBOL: validation-errors
-
-: build-url ( str query-params -- newstr )
-    [
-        over %
-        dup assoc-empty? [
-            2drop
-        ] [
-            CHAR: ? rot member? "&" "?" ? %
-            assoc>query %
-        ] if
-    ] "" make ;
-
-: action-link ( query action -- url )
-    [
-        "/responder/" %
-        dup word-vocabulary "webapps." ?head drop %
-        "/" %
-        word-name %
-    ] "" make swap build-url ;
-
-: action-param ( hash paramsepc -- obj error/f )
-    unclip rot at swap >quotation apply-validators ;
-
-: query>seq ( hash word -- seq )
-    "action-params" word-prop [
-        dup first -rot
-        action-param [
-            t validators-errored >session
-            rot validation-errors session> set-at
-        ] [
-            nip
-        ] if*
-    ] with map ;
-
-: lookup-session ( hash -- session )
-    "furnace-session-id" over at get-session
-    [ ] [ new-session "furnace-session-id" roll set-at ] ?if ;
-
-: quot>query ( seq action -- hash )
-    >r >array r> "action-params" word-prop
-    [ first swap 2array ] 2map >hashtable ;
-
-PREDICATE: word action "action" word-prop ;
-
-: action-call? ( quot -- ? )
-    >vector dup pop action? >r [ word? not ] all? r> and ;
-
-: unclip* dup 1 head* swap peek ;
-
-: quot-link ( quot -- url )
-    dup action-call? [
-        unclip* [ quot>query ] keep action-link
-    ] [
-        t register-html-callback
-    ] if ;
-
-: replace-variables ( quot -- quot )
-    [ dup string? [ request-params session> at ] when ] map ;
-
-: furnace-session-id ( -- hash )
-    "furnace-session-id" request-params session> at
-    "furnace-session-id" associate ;
-
-: redirect-to-action ( -- )
-    current-action session>
-    "form-failed" word-prop replace-variables
-    quot-link furnace-session-id build-url permanent-redirect ;
-
-: if-form-page ( if then -- )
-    current-action session> "form-failed" word-prop -rot if ;
-
-: do-action
-    current-action session> [ query>seq ] keep add >quotation call ;
-
-: process-form ( -- )
-    H{ } clone validation-errors >session
-    request-params session> current-action session> query>seq
-    validators-errored session> [
-        drop redirect-to-action
-    ] [
-        current-action session> add >quotation call
-    ] if ;
-
-: page-submitted ( -- )
-    [ process-form ] [ request-params session> do-action ] if-form-page ;
-
-: action-first-time ( -- )
-    request-params session> current-action session>
-    [ "default-values" word-prop swap union request-params >session ] keep
-    request-params session> do-action ;
-
-: page-not-submitted ( -- )
-    [ redirect-to-action ] [ action-first-time ] if-form-page ;
-
-: setup-call-action ( hash word -- )
-    over lookup-session session set
-    current-action >session
-    request-params session> swap union
-    request-params >session
-    f validators-errored >session ;
-
-: call-action ( hash word -- )
-    setup-call-action
-    "furnace-form-submitted" request-params session> at
-    [ page-submitted ] [ page-not-submitted ] if ;
-
-: responder-vocab ( str -- newstr )
-    "webapps." swap append ;
-
-: lookup-action ( str webapp -- word )
-    responder-vocab lookup dup [
-        dup "action" word-prop [ drop f ] unless
-    ] when ;
-
-: truncate-url ( str -- newstr )
-    CHAR: / over index [ head ] when* ;
-
-: parse-action ( str -- word/f )
-    dup empty? [ drop default-action get ] when
-    truncate-url "responder" get lookup-action ;
-
-: service-request ( hash str -- )
-    parse-action [
-        [ call-action ] [ <pre> print-error </pre> ] recover
-    ] [
-        "404 no such action: " "argument" get append httpd-error
-    ] if* ;
-
-: service-get
-    "query" get swap service-request ;
-
-: service-post
-    "response" get swap service-request ;
-
-: web-app ( name defaul path -- )
-    [
-        template-path set
-        default-action set
-        "responder" set
-        [ service-get ] "get" set
-        [ service-post ] "post" set
-    ] make-responder ;
-
-: explode-tuple ( tuple -- )
-    dup tuple-slots swap class "slot-names" word-prop
-    [ set ] 2each ;
-
-SYMBOL: model
-
-: with-slots ( model quot -- )
-    [
-        >r [ dup model set explode-tuple ] when* r> call
-    ] with-scope ;
-
-: render-component ( model template -- )
-    swap [ render-template ] with-slots ;
-
-: browse-webapp-source ( vocab -- )
-    <a vocab browser-link-href =href a>
-        "Browse source" write
-    </a> ;
-
-: send-resource ( name -- )
-    template-path get swap path+ resource-path <file-reader>
-    stdio get stream-copy ;
-
-: render-link ( quot name -- )
-    <a swap quot-link =href a> write </a> ;
-
-: session-var ( str -- newstr )
-    request-params session> at ;
-
-: render ( str -- )
-    request-params session> at [ write ] when* ;
-
-: render-error ( str error-str -- )
-    swap validation-errors session> at validation-error? [
-        write
-    ] [
-        drop
-    ] if ;
diff --git a/extra/furnace/sessions/authors.txt b/extra/furnace/sessions/authors.txt
deleted file mode 100755 (executable)
index 7c1b2f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
diff --git a/extra/furnace/sessions/sessions.factor b/extra/furnace/sessions/sessions.factor
deleted file mode 100755 (executable)
index cf03fee..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-USING: assocs calendar init kernel math.parser
-namespaces random boxes alarms combinators.lib ;
-IN: furnace.sessions
-
-SYMBOL: sessions
-
-: timeout ( -- dt ) 20 minutes ;
-
-[
-    H{ } clone sessions set-global
-] "furnace.sessions" add-init-hook
-
-: new-session-id ( -- str )
-    [ 4 big-random >hex ]
-    [ sessions get-global key? not ] generate ;
-
-TUPLE: session id namespace alarm user-agent ;
-
-: cancel-timeout ( session -- )
-    session-alarm ?box [ cancel-alarm ] [ drop ] if ;
-
-: delete-session ( session -- )
-    sessions get-global delete-at*
-    [ cancel-timeout ] [ drop ] if ;
-
-: touch-session ( session -- )
-    dup cancel-timeout
-    dup [ session-id delete-session ] curry timeout later
-    swap session-alarm >box ;
-
-: <session> ( id -- session )
-    H{ } clone <box> f session construct-boa ;
-
-: new-session ( -- session id )
-    new-session-id [
-        dup <session> [
-            [ sessions get-global set-at ] keep
-            touch-session
-        ] keep
-    ] keep ;
-
-: get-session ( id -- session/f )
-    sessions get-global at*
-    [ dup touch-session ] when ;
-
-: session> ( str -- obj )
-    session get session-namespace at ;
-
-: >session ( value key -- )
-    session get session-namespace set-at ;
diff --git a/extra/furnace/summary.txt b/extra/furnace/summary.txt
deleted file mode 100755 (executable)
index 5696506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Action-based web framework
diff --git a/extra/furnace/tags.txt b/extra/furnace/tags.txt
deleted file mode 100644 (file)
index 0aef4fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-enterprise
diff --git a/extra/furnace/validator/authors.txt b/extra/furnace/validator/authors.txt
deleted file mode 100755 (executable)
index 7c1b2f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
diff --git a/extra/furnace/validator/validator-tests.factor b/extra/furnace/validator/validator-tests.factor
deleted file mode 100644 (file)
index e84e57b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-IN: furnace.validator.tests
-USING: kernel sequences tools.test furnace.validator furnace ;
-
-[
-    123 f
-] [
-    H{ { "foo" "123" } } { "foo" v-number } action-param
-] unit-test
-
-: validation-fails
-    [ action-param nip not ] append [ f ] swap unit-test ;
-
-[ H{ { "foo" "12X3" } } { "foo" v-number } ] validation-fails
-
-[ H{ { "foo" "" } } { "foo" 4 v-min-length } ] validation-fails
-
-[ "ABCD" f ]
-[ H{ { "foo" "ABCD" } } { "foo" 4 v-min-length } action-param ]
-unit-test
-
-[ H{ { "foo" "ABCD" } } { "foo" 2 v-max-length } ]
-validation-fails
-
-[ "AB" f ]
-[ H{ { "foo" "AB" } } { "foo" 2 v-max-length } action-param ]
-unit-test
-
-[ "AB" f ]
-[ H{ { "foo" f } } { "foo" "AB" v-default } action-param ]
-unit-test
diff --git a/extra/furnace/validator/validator.factor b/extra/furnace/validator/validator.factor
deleted file mode 100644 (file)
index 698c77f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-! Copyright (C) 2006 Slava Pestov
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel continuations sequences math namespaces math.parser ;
-IN: furnace.validator
-
-TUPLE: validation-error reason ;
-
-: apply-validators ( string quot -- obj error/f )
-    [
-        call f
-    ] [
-        dup validation-error? [ >r 2drop f r> ] [ rethrow ] if
-    ] recover ;
-
-: validation-error ( msg -- * )
-    \ validation-error construct-boa throw ;
-
-: v-default ( obj value -- obj )
-    over empty? [ nip ] [ drop ] if ;
-
-: v-required ( str -- str )
-    dup empty? [ "required" validation-error ] when ;
-
-: v-min-length ( str n -- str )
-    over length over < [
-        [ "must be at least " % # " characters" % ] "" make
-        validation-error
-    ] [
-        drop
-    ] if ;
-
-: v-max-length ( str n -- str )
-    over length over > [
-        [ "must be no more than " % # " characters" % ] "" make
-        validation-error
-    ] [
-        drop
-    ] if ;
-
-: v-number ( str -- n )
-    string>number [
-        "must be a number" validation-error
-    ] unless* ;
index fca15d9b07c3be4dffa1cc075a0780688c0cce5d..8fc45ec486590d441a11d16c3d94b7aa548613f8 100755 (executable)
@@ -1,6 +1,5 @@
 USING: assocs html.parser kernel math sequences strings ascii
-arrays shuffle unicode.case namespaces splitting
-http.server.responders ;
+arrays shuffle unicode.case namespaces splitting http ;
 IN: html.parser.analyzer
 
 : remove-blank-text ( vector -- vector' )
@@ -82,8 +81,8 @@ IN: html.parser.analyzer
 : href-contains? ( str tag -- ? )
     tag-attributes "href" swap at* [ subseq? ] [ 2drop f ] if ;
 
-: query>hash* ( str -- hash )
-    "?" split1 nip query>hash ;
+: query>assoc* ( str -- hash )
+    "?" split1 nip query>assoc ;
 
 ! clear "http://fark.com" http-get parse-html find-links [ "go.pl" swap start ] subset [ "=" split peek ] map
 
@@ -91,5 +90,5 @@ IN: html.parser.analyzer
 ! "a" over find-opening-tags-by-name
 ! [ nip "shipposition.phtml?call=GBTT" swap href-contains? ] assoc-subset
 ! first first 8 + over nth
-! tag-attributes "href" swap at query>hash*
+! tag-attributes "href" swap at query>assoc*
 ! "lat" over at "lon" rot at
index 2d74e92e861120491fb1744340b112c67c697760..13089ae6e83adc06e2e2b344cb4f19b8420f01e7 100644 (file)
@@ -1,11 +1,12 @@
 IN: http.server.actions.tests
 USING: http.server.actions tools.test math math.parser
 multiline namespaces http io.streams.string http.server
-sequences ;
+sequences accessors ;
 
-[ + ]
-{ { "a" [ string>number ] } { "b" [ string>number ] } }
-"GET" <action> "action-1" set
+<action>
+    [ "a" get "b" get + ] >>get
+    { { "a" [ string>number ] } { "b" [ string>number ] } } >>get-params
+"action-1" set
 
 STRING: action-request-test-1
 GET http://foo/bar?a=12&b=13 HTTP/1.1
@@ -19,9 +20,10 @@ blah
     "action-1" get call-responder
 ] unit-test
 
-[ "X" <repetition> concat append ]
-{ { +path+ [ ] } { "xxx" [ string>number ] } }
-"POST" <action> "action-2" set
+<action>
+    [ +path+ get "xxx" get "X" <repetition> concat append ] >>post
+    { { +path+ [ ] } { "xxx" [ string>number ] } } >>post-params
+"action-2" set
 
 STRING: action-request-test-2
 POST http://foo/bar/baz HTTP/1.1
index feb16a4488c13edb4c94f2ae35c75afd83f2cacd..5e5b7a956303a87f9d1cf1ab038f9dd90e43007e 100755 (executable)
@@ -1,14 +1,18 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: accessors new-slots sequences kernel assocs combinators\r
-http.server http hashtables namespaces ;\r
+http.server http.server.validators http hashtables namespaces ;\r
 IN: http.server.actions\r
 \r
 SYMBOL: +path+\r
 \r
-TUPLE: action quot params method ;\r
+TUPLE: action get get-params post post-params revalidate ;\r
 \r
-C: <action> action\r
+: <action>\r
+    action construct-empty\r
+    [ <400> ] >>get\r
+    [ <400> ] >>post\r
+    [ <400> ] >>revalidate ;\r
 \r
 : extract-params ( request path -- assoc )\r
     >r dup method>> {\r
@@ -16,15 +20,22 @@ C: <action> action
         { "POST" [ post-data>> query>assoc ] }\r
     } case r> +path+ associate union ;\r
 \r
-: push-params ( assoc action -- ... )\r
-    params>> [ first2 >r swap at r> call ] with each ;\r
+: action-params ( request path param -- error? )\r
+    -rot extract-params validate-params ;\r
+\r
+: get-action ( request path -- response )\r
+    action get get-params>> action-params\r
+    [ <400> ] [ action get get>> call ] if ;\r
+\r
+: post-action ( request path -- response )\r
+    action get post-params>> action-params\r
+    [ action get revalidate>> ] [ action get post>> ] if call ;\r
 \r
 M: action call-responder ( request path action -- response )\r
-    pick request set\r
-    pick method>> over method>> = [\r
-        >r extract-params r>\r
-        [ push-params ] keep\r
-        quot>> call\r
-    ] [\r
-        3drop <400>\r
-    ] if ;\r
+    action set\r
+    over request set\r
+    over method>>\r
+    {\r
+        { "GET" [ get-action ] }\r
+        { "POST" [ post-action ] }\r
+    } case ;\r
diff --git a/extra/http/server/auth/basic/basic.factor b/extra/http/server/auth/basic/basic.factor
new file mode 100755 (executable)
index 0000000..2ea74fe
--- /dev/null
@@ -0,0 +1,41 @@
+! Copyright (c) 2007 Chris Double.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: accessors new-slots quotations assocs kernel splitting\r
+base64 html.elements io combinators http.server\r
+http.server.auth.providers http.server.auth.providers.null\r
+http sequences ;\r
+IN: http.server.auth.basic\r
+\r
+TUPLE: basic-auth responder realm provider ;\r
+\r
+C: <basic-auth> basic-auth\r
+\r
+: authorization-ok? ( provider header -- ? )\r
+    #! Given the realm and the 'Authorization' header,\r
+    #! authenticate the user.\r
+    dup [\r
+        " " split1 swap "Basic" = [\r
+            base64> ":" split1 spin check-login\r
+        ] [\r
+            2drop f\r
+        ] if\r
+    ] [\r
+        2drop f\r
+    ] if ;\r
+\r
+: <401> ( realm -- response )\r
+    401 "Unauthorized" <trivial-response>\r
+    "Basic realm=\"" rot "\"" 3append\r
+    "WWW-Authenticate" set-header\r
+    [\r
+        <html> <body>\r
+            "Username or Password is invalid" write\r
+        </body> </html>\r
+    ] >>body ;\r
+\r
+: logged-in? ( request responder -- ? )\r
+    provider>> swap "authorization" header authorization-ok? ;\r
+\r
+M: basic-auth call-responder ( request path responder -- response )\r
+    pick over logged-in?\r
+    [ responder>> call-responder ] [ 2nip realm>> <401> ] if ;\r
diff --git a/extra/http/server/auth/login/login.factor b/extra/http/server/auth/login/login.factor
new file mode 100755 (executable)
index 0000000..e2f9a36
--- /dev/null
@@ -0,0 +1,69 @@
+! Copyright (c) 2008 Slava Pestov\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: accessors new-slots quotations assocs kernel splitting\r
+base64 html.elements io combinators http.server\r
+http.server.auth.providers http.server.actions\r
+http.server.sessions http.server.templating.fhtml http sequences\r
+io.files namespaces ;\r
+IN: http.server.auth.login\r
+\r
+TUPLE: login-auth responder provider ;\r
+\r
+C: (login-auth) login-auth\r
+\r
+SYMBOL: logged-in?\r
+SYMBOL: provider\r
+SYMBOL: post-login-url\r
+\r
+: login-page ( -- response )\r
+    "text/html" <content> [\r
+        "extra/http/server/auth/login/login.fhtml"\r
+        resource-path run-template-file\r
+    ] >>body ;\r
+\r
+: <login-action>\r
+    <action>\r
+        [ login-page ] >>get\r
+\r
+        {\r
+            { "name" [ ] }\r
+            { "password" [ ] }\r
+        } >>post-params\r
+        [\r
+            "password" get\r
+            "name" get\r
+            provider sget check-login [\r
+                t logged-in? sset\r
+                post-login-url sget <permanent-redirect>\r
+            ] [\r
+                login-page\r
+            ] if\r
+        ] >>post ;\r
+\r
+: <logout-action>\r
+    <action>\r
+        [\r
+            f logged-in? sset\r
+            request get "login" <permanent-redirect>\r
+        ] >>post ;\r
+\r
+M: login-auth call-responder ( request path responder -- response )\r
+    logged-in? sget\r
+    [ responder>> call-responder ] [\r
+        pick method>> "GET" = [\r
+            nip\r
+            provider>> provider sset\r
+            dup request-url post-login-url sset\r
+            "login" f session-link <permanent-redirect>\r
+        ] [\r
+            3drop <400>\r
+        ] if\r
+    ] if ;\r
+\r
+: <login-auth> ( responder provider -- auth )\r
+        (login-auth)\r
+        <dispatcher>\r
+            swap >>default\r
+            <login-action> "login" add-responder\r
+            <logout-action> "logout" add-responder\r
+    <cookie-sessions> ;\r
diff --git a/extra/http/server/auth/login/login.fhtml b/extra/http/server/auth/login/login.fhtml
new file mode 100755 (executable)
index 0000000..9bb1438
--- /dev/null
@@ -0,0 +1,25 @@
+<html>\r
+<body>\r
+<h1>Login required</h1>\r
+\r
+<form method="POST" action="login">\r
+<table>\r
+\r
+<tr>\r
+<td>User name:</td>\r
+<td><input name="name" /></td>\r
+</tr>\r
+\r
+<tr>\r
+<td>Password:</td>\r
+<td><input type="password" name="password" /></td>\r
+</tr>\r
+\r
+</table>\r
+\r
+<input type="submit" value="Log in" />\r
+\r
+</form>\r
+\r
+</body>\r
+</html>\r
diff --git a/extra/http/server/auth/providers/assoc/assoc-tests.factor b/extra/http/server/auth/providers/assoc/assoc-tests.factor
new file mode 100755 (executable)
index 0000000..3270fe0
--- /dev/null
@@ -0,0 +1,18 @@
+IN: http.server.auth.providers.assoc.tests\r
+USING: http.server.auth.providers \r
+http.server.auth.providers.assoc tools.test\r
+namespaces ;\r
+\r
+<assoc-auth-provider> "provider" set\r
+\r
+"slava" "provider" get new-user\r
+\r
+[ "slava" "provider" get new-user ] [ user-exists? ] must-fail-with\r
+\r
+[ f ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
+\r
+[ "xx" "blah" "provider" get set-password ] [ no-such-user? ] must-fail-with\r
+\r
+"fdasf" "slava" "provider" get set-password\r
+\r
+[ t ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
diff --git a/extra/http/server/auth/providers/assoc/assoc.factor b/extra/http/server/auth/providers/assoc/assoc.factor
new file mode 100755 (executable)
index 0000000..d57be62
--- /dev/null
@@ -0,0 +1,23 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+IN: http.server.auth.providers.assoc\r
+USING: new-slots accessors assocs kernel\r
+http.server.auth.providers ;\r
+\r
+TUPLE: assoc-auth-provider assoc ;\r
+\r
+: <assoc-auth-provider> ( -- provider )\r
+    H{ } clone assoc-auth-provider construct-boa ;\r
+\r
+M: assoc-auth-provider check-login\r
+    assoc>> at = ;\r
+\r
+M: assoc-auth-provider new-user\r
+    assoc>>\r
+    2dup key? [ drop user-exists ] when\r
+    t -rot set-at ;\r
+\r
+M: assoc-auth-provider set-password\r
+    assoc>>\r
+    2dup key? [ drop no-such-user ] unless\r
+    set-at ;\r
diff --git a/extra/http/server/auth/providers/db/db-tests.factor b/extra/http/server/auth/providers/db/db-tests.factor
new file mode 100755 (executable)
index 0000000..c4682c2
--- /dev/null
@@ -0,0 +1,25 @@
+IN: http.server.auth.providers.db.tests\r
+USING: http.server.auth.providers\r
+http.server.auth.providers.db tools.test\r
+namespaces db db.sqlite db.tuples continuations\r
+io.files ;\r
+\r
+db-auth-provider "provider" set\r
+\r
+"auth-test.db" temp-file sqlite-db [\r
+    \r
+    [ user drop-table ] ignore-errors\r
+    [ user create-table ] ignore-errors\r
+\r
+    "slava" "provider" get new-user\r
+\r
+    [ "slava" "provider" get new-user ] [ user-exists? ] must-fail-with\r
+\r
+    [ f ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
+\r
+    [ "xx" "blah" "provider" get set-password ] [ no-such-user? ] must-fail-with\r
+\r
+    "fdasf" "slava" "provider" get set-password\r
+\r
+    [ t ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
+] with-db\r
diff --git a/extra/http/server/auth/providers/db/db.factor b/extra/http/server/auth/providers/db/db.factor
new file mode 100755 (executable)
index 0000000..9583122
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: db db.tuples db.types new-slots accessors\r
+http.server.auth.providers kernel ;\r
+IN: http.server.auth.providers.db\r
+\r
+TUPLE: user name password ;\r
+\r
+: <user> user construct-empty ;\r
+\r
+user "USERS"\r
+{\r
+    { "name" "NAME" { VARCHAR 256 } +assigned-id+ }\r
+    { "password" "PASSWORD" { VARCHAR 256 } +not-null+ }\r
+} define-persistent\r
+\r
+: init-users-table ( -- )\r
+    user create-table ;\r
+\r
+TUPLE: db-auth-provider ;\r
+\r
+: db-auth-provider T{ db-auth-provider } ;\r
+\r
+M: db-auth-provider check-login\r
+    drop\r
+    <user>\r
+    swap >>name\r
+    swap >>password\r
+    select-tuple >boolean ;\r
+\r
+M: db-auth-provider new-user\r
+    drop\r
+    [\r
+        <user>\r
+        swap >>name\r
+\r
+        dup select-tuple [ name>> user-exists ] when\r
+\r
+        "unassigned" >>password\r
+\r
+        insert-tuple\r
+    ] with-transaction ;\r
+\r
+M: db-auth-provider set-password\r
+    drop\r
+    [\r
+        <user>\r
+        swap >>name\r
+\r
+        dup select-tuple [ ] [ no-such-user ] ?if\r
+\r
+        swap >>password update-tuple\r
+    ] with-transaction ;\r
diff --git a/extra/http/server/auth/providers/null/null.factor b/extra/http/server/auth/providers/null/null.factor
new file mode 100755 (executable)
index 0000000..7021119
--- /dev/null
@@ -0,0 +1,14 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: http.server.auth.providers kernel ;\r
+IN: http.server.auth.providers.null\r
+\r
+TUPLE: null-auth-provider ;\r
+\r
+: null-auth-provider T{ null-auth-provider } ;\r
+\r
+M: null-auth-provider check-login 3drop f ;\r
+\r
+M: null-auth-provider new-user 3drop f ;\r
+\r
+M: null-auth-provider set-password 3drop f ;\r
diff --git a/extra/http/server/auth/providers/providers.factor b/extra/http/server/auth/providers/providers.factor
new file mode 100755 (executable)
index 0000000..1e0fd33
--- /dev/null
@@ -0,0 +1,18 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: kernel ;\r
+IN: http.server.auth.providers\r
+\r
+GENERIC: check-login ( password user provider -- ? )\r
+\r
+GENERIC: new-user ( user provider -- )\r
+\r
+GENERIC: set-password ( password user provider -- )\r
+\r
+TUPLE: user-exists name ;\r
+\r
+: user-exists ( name -- * ) \ user-exists construct-boa throw ;\r
+\r
+TUPLE: no-such-user name ;\r
+\r
+: no-such-user ( name -- * ) \ no-such-user construct-boa throw ;\r
diff --git a/extra/http/server/components/components.factor b/extra/http/server/components/components.factor
new file mode 100644 (file)
index 0000000..6fefb1b
--- /dev/null
@@ -0,0 +1,129 @@
+! Copyright (C) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: new-slots html.elements http.server.validators
+accessors namespaces kernel io farkup math.parser assocs
+classes words tuples arrays sequences io.files
+http.server.templating.fhtml splitting ;
+IN: http.server.components
+
+SYMBOL: components
+
+TUPLE: component id ;
+
+: component ( name -- component )
+    dup components get at
+    [ ] [ "No such component: " swap append throw ] ?if ;
+
+GENERIC: validate* ( string component -- result )
+GENERIC: render-view* ( value component -- )
+GENERIC: render-edit* ( value component -- )
+GENERIC: render-error* ( reason value component -- )
+
+SYMBOL: values
+
+: value values get at ;
+
+: render-view ( component -- )
+    dup id>> value swap render-view* ;
+
+: render-error ( error -- )
+    <span "error" =class span> write </span> ;
+
+: render-edit ( component -- )
+    dup id>> value dup validation-error? [
+        dup reason>> swap value>> rot render-error*
+    ] [
+        swap render-edit*
+    ] if ;
+
+: <component> ( id string -- component )
+    >r \ component construct-boa r> construct-delegate ; inline
+
+TUPLE: string min max ;
+
+: <string> ( id -- component ) string <component> ;
+
+M: string validate*
+    [ min>> v-min-length ] keep max>> v-max-length ;
+
+M: string render-view*
+    drop write ;
+
+: render-input
+    <input "text" =type id>> dup =id =name =value input/> ;
+
+M: string render-edit*
+    render-input ;
+
+M: string render-error*
+    render-input render-error ;
+
+TUPLE: text ;
+
+: <text> ( id -- component ) <string> text construct-delegate ;
+
+: render-textarea
+    <textarea id>> dup =id =name textarea> write </textarea> ;
+
+M: text render-edit*
+    render-textarea ;
+
+M: text render-error*
+    render-textarea render-error ;
+
+TUPLE: farkup ;
+
+: <farkup> ( id -- component ) <text> farkup construct-delegate ;
+
+M: farkup render-view*
+    drop string-lines "\n" join convert-farkup write ;
+
+TUPLE: number min max ;
+
+: <number> ( id -- component ) number <component> ;
+
+M: number validate*
+    >r v-number r> [ min>> v-min-value ] keep max>> v-max-value ;
+
+M: number render-view*
+    drop number>string write ;
+
+M: number render-edit*
+    >r number>string r> render-input ;
+
+M: number render-error*
+    render-input render-error ;
+
+: tuple>slots ( tuple -- alist )
+    dup class "slot-names" word-prop swap tuple-slots
+    2array flip ;
+
+: with-components ( tuple components quot -- )
+    [
+        >r components set
+        dup tuple>slots values set
+        tuple set
+        r> call
+    ] with-scope ; inline
+
+TUPLE: form view-template edit-template components ;
+
+: <form> ( id view-template edit-template -- form )
+    V{ } clone form construct-boa
+    swap \ component construct-boa
+    over set-delegate ;
+
+: add-field ( form component -- form )
+    dup id>> pick components>> set-at ;
+
+M: form render-view* ( value form -- )
+    dup components>>
+    swap view-template>>
+    [ resource-path run-template-file ] curry
+    with-components ;
+
+M: form render-edit* ( value form -- )
+    dup components>>
+    swap edit-template>>
+    [ resource-path run-template-file ] curry
+    with-components ;
diff --git a/extra/http/server/crud/crud.factor b/extra/http/server/crud/crud.factor
new file mode 100644 (file)
index 0000000..099ded2
--- /dev/null
@@ -0,0 +1,13 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: http.server.crud
+USING: kernel namespaces db.tuples math.parser
+http.server.actions accessors ;
+
+: by-id ( class -- tuple )
+    construct-empty "id" get >>id ;
+
+: <delete-action> ( class -- action )
+    <action>
+        { { "id" [ string>number ] } } >>post-params
+        swap [ by-id delete-tuple f ] curry >>post ;
index 4baee5f02b21f09c58b9dca99162f98bb80195a4..511921ce06dcc33c7f57a6af40bb85e8ba6ae904 100755 (executable)
@@ -1,14 +1,18 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: db http.server kernel new-slots accessors\r
-continuations namespaces ;\r
+continuations namespaces destructors ;\r
 IN: http.server.db\r
 \r
 TUPLE: db-persistence responder db params ;\r
 \r
 C: <db-persistence> db-persistence\r
 \r
+: connect-db ( db-persistence -- )\r
+    dup db>> swap params>> make-db\r
+    dup db set\r
+    dup db-open\r
+    add-always-destructor ;\r
+\r
 M: db-persistence call-responder\r
-    dup db>> over params>> make-db dup db-open [\r
-        db set responder>> call-responder\r
-    ] with-disposal ;\r
+    dup connect-db responder>> call-responder ;\r
index f397b280d038b2b58512676d487a106baf952b15..990c77f71ee5a288b71282327dc8ce70e3225cdd 100755 (executable)
@@ -3,7 +3,8 @@
 USING: assocs kernel namespaces io io.timeouts strings splitting
 threads http sequences prettyprint io.server logging calendar
 new-slots html.elements accessors math.parser combinators.lib
-vocabs.loader debugger html continuations random combinators ;
+vocabs.loader debugger html continuations random combinators
+destructors ;
 IN: http.server
 
 GENERIC: call-responder ( request path responder -- response )
@@ -135,7 +136,7 @@ SYMBOL: development-mode
     swap method>> "HEAD" =
     [ drop ] [ write-response-body ] if ;
 
-: do-request ( request -- request )
+: do-request ( request -- response )
     [
         dup dup path>> over host>>
         find-virtual-host call-responder
@@ -149,13 +150,18 @@ LOG: httpd-hit NOTICE
 : log-request ( request -- )
     { method>> host>> path>> } map-exec-with httpd-hit ;
 
-: handle-client ( -- )
-    default-timeout
+: ?refresh-all ( -- )
     development-mode get-global
-    [ global [ refresh-all ] bind ] when
-    read-request
-    dup log-request
-    do-request do-response ;
+    [ global [ refresh-all ] bind ] when ;
+
+: handle-client ( -- )
+    [
+        default-timeout
+        ?refresh-all
+        read-request
+        dup log-request
+        do-request do-response
+    ] with-destructors ;
 
 : httpd ( port -- )
     internet-server "http.server"
index 4c21ba3c8d7fd979a5c3f8c81f77ccec131f5fa4..d771737c73e62e0cdac06ffdd240516f0295b711 100755 (executable)
@@ -4,6 +4,12 @@ kernel accessors ;
 \r
 : with-session \ session swap with-variable ; inline\r
 \r
+TUPLE: foo ;\r
+\r
+C: <foo> foo\r
+\r
+M: foo init-session drop 0 "x" sset ;\r
+\r
 "1234" f <session> [\r
     [ ] [ 3 "x" sset ] unit-test\r
     \r
@@ -18,8 +24,7 @@ kernel accessors ;
 [ t ] [ f <cookie-sessions> cookie-sessions? ] unit-test\r
 \r
 [ ] [\r
-    f <url-sessions>\r
-        [ 0 "x" sset ] >>init\r
+    <foo> <url-sessions>\r
     "manager" set\r
 ] unit-test\r
 \r
index 2977e5938d7ef45a1972853e153dc9fc00aaab98..d7fed6bb64568a5676d82ec511a1700014c60360 100755 (executable)
@@ -11,6 +11,8 @@ IN: http.server.sessions
 
 GENERIC: init-session ( responder -- )
 
+M: dispatcher init-session drop ;
+
 TUPLE: session-manager responder sessions ;
 
 : <session-manager> ( responder class -- responder' )
diff --git a/extra/http/server/templating/authors.txt b/extra/http/server/templating/authors.txt
deleted file mode 100644 (file)
index b47eafb..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Slava Pestov
-Matthew Willis
diff --git a/extra/http/server/templating/fhtml/authors.txt b/extra/http/server/templating/fhtml/authors.txt
new file mode 100644 (file)
index 0000000..b47eafb
--- /dev/null
@@ -0,0 +1,2 @@
+Slava Pestov
+Matthew Willis
diff --git a/extra/http/server/templating/fhtml/fhtml-tests.factor b/extra/http/server/templating/fhtml/fhtml-tests.factor
new file mode 100644 (file)
index 0000000..0ae3b41
--- /dev/null
@@ -0,0 +1,17 @@
+USING: io io.files io.streams.string
+http.server.templating.fhtml kernel tools.test sequences ;
+IN: http.server.templating.fhtml.tests
+
+: test-template ( path -- ? )
+    "extra/http/server/templating/fhtml/test/" swap append
+    [
+        ".fhtml" append resource-path
+        [ run-template-file ] with-string-writer
+    ] keep
+    ".html" append resource-path file-contents = ;
+
+[ t ] [ "example" test-template ] unit-test
+[ t ] [ "bug" test-template ] unit-test
+[ t ] [ "stack" test-template ] unit-test
+
+[ ] [ "<%\n%>" parse-template drop ] unit-test
diff --git a/extra/http/server/templating/fhtml/fhtml.factor b/extra/http/server/templating/fhtml/fhtml.factor
new file mode 100755 (executable)
index 0000000..e5770af
--- /dev/null
@@ -0,0 +1,106 @@
+! Copyright (C) 2005 Alex Chapman
+! Copyright (C) 2006, 2007 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: continuations sequences kernel parser namespaces io
+io.files io.streams.lines io.streams.string html html.elements
+source-files debugger combinators math quotations generic
+strings splitting accessors http.server.static http.server
+assocs ;
+
+IN: http.server.templating.fhtml
+
+: templating-vocab ( -- vocab-name ) "http.server.templating.fhtml" ;
+
+! See apps/http-server/test/ or libs/furnace/ for template usage
+! examples
+
+! We use a custom lexer so that %> ends a token even if not
+! followed by whitespace
+TUPLE: template-lexer ;
+
+: <template-lexer> ( lines -- lexer )
+    <lexer> template-lexer construct-delegate ;
+
+M: template-lexer skip-word
+    [
+        {
+            { [ 2dup nth CHAR: " = ] [ drop 1+ ] }
+            { [ 2dup swap tail-slice "%>" head? ] [ drop 2 + ] }
+            { [ t ] [ f skip ] }
+        } cond
+    ] change-column ;
+
+DEFER: <% delimiter
+
+: check-<% ( lexer -- col )
+    "<%" over lexer-line-text rot lexer-column start* ;
+
+: found-<% ( accum lexer col -- accum )
+    [
+        over lexer-line-text
+        >r >r lexer-column r> r> subseq parsed
+        \ write-html parsed
+    ] 2keep 2 + swap set-lexer-column ;
+
+: still-looking ( accum lexer -- accum )
+    [
+        dup lexer-line-text swap lexer-column tail
+        parsed \ print-html parsed
+    ] keep next-line ;
+
+: parse-%> ( accum lexer -- accum )
+    dup still-parsing? [
+        dup check-<%
+        [ found-<% ] [ [ still-looking ] keep parse-%> ] if*
+    ] [
+        drop
+    ] if ;
+
+: %> lexer get parse-%> ; parsing
+
+: parse-template-lines ( lines -- quot )
+    <template-lexer> [
+        V{ } clone lexer get parse-%> f (parse-until)
+    ] with-parser ;
+
+: parse-template ( string -- quot )
+    [
+        use [ clone ] change
+        templating-vocab use+
+        string-lines parse-template-lines
+    ] with-scope ;
+
+: eval-template ( string -- ) parse-template call ;
+
+: html-error. ( error -- )
+    <pre> error. </pre> ;
+
+: run-template-file ( filename -- )
+    [
+        [
+            "quiet" on
+            parser-notes off
+            templating-vocab use+
+            ! so that reload works properly
+            dup source-file file set
+            ?resource-path file-contents
+            [ eval-template ] [ html-error. drop ] recover
+        ] with-file-vocabs
+    ] curry assert-depth ;
+
+: run-relative-template-file ( filename -- )
+    file get source-file-path parent-directory
+    swap path+ run-template-file ;
+
+: template-convert ( infile outfile -- )
+    [ run-template-file ] with-file-writer ;
+
+! file responder integration
+: serve-fhtml ( filename -- response )
+    "text/html" <content>
+    swap [ run-template-file ] curry >>body ;
+
+: enable-fhtml ( responder -- responder )
+    [ serve-fhtml ]
+    "application/x-factor-server-page"
+    pick special>> set-at ;
diff --git a/extra/http/server/templating/fhtml/test/bug.fhtml b/extra/http/server/templating/fhtml/test/bug.fhtml
new file mode 100644 (file)
index 0000000..cb66599
--- /dev/null
@@ -0,0 +1,5 @@
+<%
+    USING: prettyprint ;
+    ! Hello world
+    5 pprint
+%>
diff --git a/extra/http/server/templating/fhtml/test/bug.html b/extra/http/server/templating/fhtml/test/bug.html
new file mode 100644 (file)
index 0000000..51d7b8d
--- /dev/null
@@ -0,0 +1,2 @@
+5
+
diff --git a/extra/http/server/templating/fhtml/test/example.fhtml b/extra/http/server/templating/fhtml/test/example.fhtml
new file mode 100644 (file)
index 0000000..211f44a
--- /dev/null
@@ -0,0 +1,8 @@
+<% USING: math ; %>
+
+<html>
+    <head><title>Simple Embedded Factor Example</title></head>
+    <body>
+        <% 5 [ %><p>I like repetition</p><% ] times %>
+    </body>
+</html>
diff --git a/extra/http/server/templating/fhtml/test/example.html b/extra/http/server/templating/fhtml/test/example.html
new file mode 100644 (file)
index 0000000..9bf4a08
--- /dev/null
@@ -0,0 +1,9 @@
+
+
+<html>
+    <head><title>Simple Embedded Factor Example</title></head>
+    <body>
+        <p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p>
+    </body>
+</html>
+
diff --git a/extra/http/server/templating/fhtml/test/stack.fhtml b/extra/http/server/templating/fhtml/test/stack.fhtml
new file mode 100644 (file)
index 0000000..399711a
--- /dev/null
@@ -0,0 +1 @@
+The stack: <% USING: prettyprint ;  .s %>
diff --git a/extra/http/server/templating/fhtml/test/stack.html b/extra/http/server/templating/fhtml/test/stack.html
new file mode 100644 (file)
index 0000000..ee923a6
--- /dev/null
@@ -0,0 +1,2 @@
+The stack: 
+
diff --git a/extra/http/server/templating/templating-tests.factor b/extra/http/server/templating/templating-tests.factor
deleted file mode 100644 (file)
index ceb2ed9..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-USING: io io.files io.streams.string http.server.templating kernel tools.test
-    sequences ;
-IN: http.server.templating.tests
-
-: test-template ( path -- ? )
-    "extra/http/server/templating/test/" swap append
-    [
-        ".fhtml" append resource-path
-        [ run-template-file ] with-string-writer
-    ] keep
-    ".html" append resource-path file-contents = ;
-
-[ t ] [ "example" test-template ] unit-test
-[ t ] [ "bug" test-template ] unit-test
-[ t ] [ "stack" test-template ] unit-test
-
-[ ] [ "<%\n%>" parse-template drop ] unit-test
diff --git a/extra/http/server/templating/templating.factor b/extra/http/server/templating/templating.factor
deleted file mode 100755 (executable)
index b298fac..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-! Copyright (C) 2005 Alex Chapman
-! Copyright (C) 2006, 2007 Slava Pestov
-! See http://factorcode.org/license.txt for BSD license.
-USING: continuations sequences kernel parser namespaces io
-io.files io.streams.lines io.streams.string html html.elements
-source-files debugger combinators math quotations generic
-strings splitting accessors http.server.static http.server
-assocs ;
-
-IN: http.server.templating
-
-: templating-vocab ( -- vocab-name ) "http.server.templating" ;
-
-! See apps/http-server/test/ or libs/furnace/ for template usage
-! examples
-
-! We use a custom lexer so that %> ends a token even if not
-! followed by whitespace
-TUPLE: template-lexer ;
-
-: <template-lexer> ( lines -- lexer )
-    <lexer> template-lexer construct-delegate ;
-
-M: template-lexer skip-word
-    [
-        {
-            { [ 2dup nth CHAR: " = ] [ drop 1+ ] }
-            { [ 2dup swap tail-slice "%>" head? ] [ drop 2 + ] }
-            { [ t ] [ f skip ] }
-        } cond
-    ] change-column ;
-
-DEFER: <% delimiter
-
-: check-<% ( lexer -- col )
-    "<%" over lexer-line-text rot lexer-column start* ;
-
-: found-<% ( accum lexer col -- accum )
-    [
-        over lexer-line-text
-        >r >r lexer-column r> r> subseq parsed
-        \ write-html parsed
-    ] 2keep 2 + swap set-lexer-column ;
-
-: still-looking ( accum lexer -- accum )
-    [
-        dup lexer-line-text swap lexer-column tail
-        parsed \ print-html parsed
-    ] keep next-line ;
-
-: parse-%> ( accum lexer -- accum )
-    dup still-parsing? [
-        dup check-<%
-        [ found-<% ] [ [ still-looking ] keep parse-%> ] if*
-    ] [
-        drop
-    ] if ;
-
-: %> lexer get parse-%> ; parsing
-
-: parse-template-lines ( lines -- quot )
-    <template-lexer> [
-        V{ } clone lexer get parse-%> f (parse-until)
-    ] with-parser ;
-
-: parse-template ( string -- quot )
-    [
-        use [ clone ] change
-        templating-vocab use+
-        string-lines parse-template-lines
-    ] with-scope ;
-
-: eval-template ( string -- ) parse-template call ;
-
-: html-error. ( error -- )
-    <pre> error. </pre> ;
-
-: run-template-file ( filename -- )
-    [
-        [
-            "quiet" on
-            parser-notes off
-            templating-vocab use+
-            ! so that reload works properly
-            dup source-file file set
-            ?resource-path file-contents
-            [ eval-template ] [ html-error. drop ] recover
-        ] with-file-vocabs
-    ] curry assert-depth ;
-
-: run-relative-template-file ( filename -- )
-    file get source-file-path parent-directory
-    swap path+ run-template-file ;
-
-: template-convert ( infile outfile -- )
-    [ run-template-file ] with-file-writer ;
-
-! file responder integration
-: serve-fhtml ( filename -- response )
-    "text/html" <content>
-    swap [ run-template-file ] curry >>body ;
-
-: enable-fhtml ( responder -- responder )
-    [ serve-fhtml ]
-    "application/x-factor-server-page"
-    pick special>> set-at ;
diff --git a/extra/http/server/templating/test/bug.fhtml b/extra/http/server/templating/test/bug.fhtml
deleted file mode 100644 (file)
index cb66599..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<%
-    USING: prettyprint ;
-    ! Hello world
-    5 pprint
-%>
diff --git a/extra/http/server/templating/test/bug.html b/extra/http/server/templating/test/bug.html
deleted file mode 100644 (file)
index 51d7b8d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-5
-
diff --git a/extra/http/server/templating/test/example.fhtml b/extra/http/server/templating/test/example.fhtml
deleted file mode 100644 (file)
index 211f44a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<% USING: math ; %>
-
-<html>
-    <head><title>Simple Embedded Factor Example</title></head>
-    <body>
-        <% 5 [ %><p>I like repetition</p><% ] times %>
-    </body>
-</html>
diff --git a/extra/http/server/templating/test/example.html b/extra/http/server/templating/test/example.html
deleted file mode 100644 (file)
index 9bf4a08..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-<html>
-    <head><title>Simple Embedded Factor Example</title></head>
-    <body>
-        <p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p>
-    </body>
-</html>
-
diff --git a/extra/http/server/templating/test/stack.fhtml b/extra/http/server/templating/test/stack.fhtml
deleted file mode 100644 (file)
index 399711a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-The stack: <% USING: prettyprint ;  .s %>
diff --git a/extra/http/server/templating/test/stack.html b/extra/http/server/templating/test/stack.html
deleted file mode 100644 (file)
index ee923a6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-The stack: 
-
diff --git a/extra/http/server/validators/validators-tests.factor b/extra/http/server/validators/validators-tests.factor
new file mode 100644 (file)
index 0000000..ff68dcf
--- /dev/null
@@ -0,0 +1,4 @@
+IN: http.server.validators.tests
+USING: kernel sequences tools.test http.server.validators ;
+
+[ t t ] [ "foo" [ v-number ] with-validator >r validation-error? r> ] unit-test
diff --git a/extra/http/server/validators/validators.factor b/extra/http/server/validators/validators.factor
new file mode 100644 (file)
index 0000000..03beb8c
--- /dev/null
@@ -0,0 +1,64 @@
+! Copyright (C) 2006, 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel continuations sequences math namespaces
+math.parser assocs new-slots ;
+IN: http.server.validators
+
+TUPLE: validation-error value reason ;
+
+: validation-error ( value reason -- * )
+    \ validation-error construct-boa throw ;
+
+: with-validator ( string quot -- result error? )
+    [ f ] compose curry
+    [ dup validation-error? [ t ] [ rethrow ] if ] recover ; inline
+
+: validate-param ( name validator assoc -- error? )
+    swap pick
+    >r >r at r> with-validator swap r> set ;
+
+: validate-params ( validators assoc -- error? )
+    [ validate-param ] curry { } assoc>map [ ] contains? ;
+
+: v-default ( str def -- str )
+    over empty? spin ? ;
+
+: v-required ( str -- str )
+    dup empty? [ "required" validation-error ] when ;
+
+: v-min-length ( str n -- str )
+    over length over < [
+        [ "must be at least " % # " characters" % ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
+
+: v-max-length ( str n -- str )
+    over length over > [
+        [ "must be no more than " % # " characters" % ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
+
+: v-number ( str -- n )
+    dup string>number [ ] [
+        "must be a number" validation-error
+    ] ?if ;
+
+: v-min-value ( str n -- str )
+    2dup < [
+        [ "must be at least " % # ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
+
+: v-max-value ( str n -- str )
+    2dup > [
+        [ "must be no more than " % # ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
index 1c72a4780c9135f0b5ef0e844d16c9c8ca3de643..1456965858013ef0be29ca01b2a601c8e052670f 100644 (file)
@@ -7,7 +7,7 @@ sequences io.sniffer.backend ;
 QUALIFIED: unix
 IN: io.sniffer.bsd
 
-M: unix-io destruct-handle ( obj -- ) unix:close drop ;
+M: unix-io destruct-handle ( obj -- ) unix:close ;
 
 C-UNION: ifreq_props "sockaddr-in" "short" "int" "caddr_t" ;
 C-STRUCT: ifreq { { "char" 16 } "name" } { "ifreq_props" "props" } ;
index db3cf674c7a2de2b40f3c491ec4d1231548cdb19..4142c4be77591d8b7a2a721652bc543d46d4621d 100755 (executable)
@@ -89,3 +89,12 @@ M: unix-io file-info ( path -- info )
         [ stat-st_mtim timespec-sec seconds unix-1970 time+ ]
     } cleave
     \ file-info construct-boa ;
+
+M: unix-io link-info ( path -- info )
+    lstat* {
+        [ stat>type ]
+        [ stat-st_size ]
+        [ stat-st_mode ]
+        [ stat-st_mtim timespec-sec seconds unix-1970 time+ ]
+    } cleave
+    \ file-info construct-boa ;
index 60e3754ec6a4fee8910ce033a82dbb3989ced79d..c5dc964a7a4f4c8df43c47ae98d45e2eef7ac9a5 100755 (executable)
@@ -31,7 +31,8 @@ M: output-task io-task-filter drop EVFILT_WRITE ;
     swap io-task-filter over set-kevent-filter ;
 
 : register-kevent ( kevent mx -- )
-    mx-fd swap 1 f 0 f kevent io-error ;
+    mx-fd swap 1 f 0 f kevent
+    0 < [ err_no ESRCH = [ (io-error) ] unless ] when ;
 
 M: kqueue-mx register-io-task ( task mx -- )
     over EV_ADD make-kevent over register-kevent
index e4338615cedadf6aecac2f23b64eaf095cb5327a..42e51c782a7d2a127e53041181448ebeae1a181d 100644 (file)
@@ -5,10 +5,12 @@ tools.test ;
 
 get-ldp LDAP_OPT_PROTOCOL_VERSION LDAP_VERSION3 <int> set-option
 
-[ B{ 0 0 0 3 } ] [ 
+[ 3 ] [ 
     get-ldp LDAP_OPT_PROTOCOL_VERSION "int*" <c-object> [ get-option ] keep
+    *int
 ] unit-test
 
+[
 get-ldp "cn=jimbob,dc=example,dc=com" "secret" [
 
     ! get-ldp "dc=example,dc=com" LDAP_SCOPE_ONELEVEL "(objectclass=*)" f 0
@@ -52,3 +54,4 @@ get-ldp "cn=jimbob,dc=example,dc=com" "secret" [
     get-ldp get-message next-message msgtype result-type
 
 ] with-bind
+] drop
index 492aed1a546c3a1d83f147d6d533405ac8da3925..ae613bd461009fab3b25a29a0d6c96af8bbc102f 100755 (executable)
@@ -9,11 +9,11 @@ USING: alien alien.syntax combinators kernel system ;
 
 IN: ldap.libldap
 
-"libldap" {
+<< "libldap" {
     { [ win32? ] [ "libldap.dll" "stdcall" ] }
     { [ macosx? ] [ "libldap.dylib" "cdecl" ] }
     { [ unix? ] [ "$LD_LIBRARY_PATH/libldap.so" "cdecl" ] }
-} cond add-library
+} cond add-library >>
  
 : LDAP_VERSION1     1 ; inline
 : LDAP_VERSION2     2 ; inline 
index 528e770558d12ecfa51814eaf34d6e33a2a0af3f..8e7af02597bb0699fdd062ed437738dda0cd59f2 100644 (file)
@@ -2,7 +2,7 @@
 ! USING: kernel quotations namespaces sequences assocs.lib ;
 
 USING: kernel namespaces namespaces.private quotations sequences
-       assocs.lib ;
+       assocs.lib math.parser math sequences.lib ;
 
 IN: namespaces.lib
 
@@ -17,3 +17,30 @@ IN: namespaces.lib
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : set* ( val var -- ) namestack* set-assoc-stack ;
+
+SYMBOL: building-seq 
+: get-building-seq ( n -- seq )
+    building-seq get nth ;
+
+: n, get-building-seq push ;
+: n% get-building-seq push-all ;
+: n# >r number>string r> n% ;
+
+: 0, 0 n, ;
+: 0% 0 n% ;
+: 0# 0 n# ;
+: 1, 1 n, ;
+: 1% 1 n% ;
+: 1# 1 n# ;
+: 2, 2 n, ;
+: 2% 2 n% ;
+: 2# 2 n# ;
+
+: nmake ( quot exemplars -- seqs )
+    dup length dup zero? [ 1+ ] when
+    [
+        [
+            [ drop 1024 swap new-resizable ] 2map
+            [ building-seq set call ] keep
+        ] 2keep >r [ like ] 2map r> firstn 
+    ] with-scope ;
index 29016f6d57046c40b0a4e5c52138775a4c19b508..8d1b3b524704364f8f6ac8d0aa756d9bbfe07daa 100644 (file)
@@ -9,11 +9,11 @@ USING: alien alien.syntax combinators kernel system ;
 
 IN: openssl.libssl
 
-"libssl" {
+<< "libssl" {
     { [ win32? ] [ "ssleay32.dll" "stdcall" ] }
     { [ macosx? ] [ "libssl.dylib" "cdecl" ] }
     { [ unix? ] [ "$LD_LIBRARY_PATH/libssl.so" "cdecl" ] }
-} cond add-library
+} cond add-library >>
 
 : X509_FILETYPE_PEM       1 ; inline
 : X509_FILETYPE_ASN1      2 ; inline
index 85ccc70c25a86567bb4b741f5988b2c6e76b0eda..a40b7cddeed165c3c81d51c7bb0f44a3fd5be0b8 100644 (file)
@@ -9,11 +9,11 @@ USING: alien alien.syntax combinators system ;
 
 IN: pdf.libhpdf
 
-"libhpdf" {
+<< "libhpdf" {
     { [ win32? ] [ "libhpdf.dll" "stdcall" ] }
     { [ macosx? ] [ "libhpdf.dylib" "cdecl" ] }
     { [ unix? ] [ "$LD_LIBRARY_PATH/libhpdf.so" "cdecl" ] }
-} cond add-library
+} cond add-library >>
 
 ! compression mode
 : HPDF_COMP_NONE      HEX: 00 ; inline ! No contents are compressed
index dc42874d2a6c1a71c1a5bf9c0d1b28ad6bde0e55..097f671d9af67ad6d565782c3db2f6136a688c02 100644 (file)
@@ -92,6 +92,6 @@ SYMBOL: twidth
 
     ] with-text
 
-    "extra/pdf/test/font_test.pdf" resource-path save-to-file
+    "font_test.pdf" temp-file save-to-file
 
 ] with-pdf
diff --git a/extra/pdf/test/font_test.pdf b/extra/pdf/test/font_test.pdf
deleted file mode 100644 (file)
index 4360cf3..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-%PDF-1.3
-%·¾­ª
-1 0 obj
-<<
-/Type /Catalog
-/Pages 2 0 R
->>
-endobj
-2 0 obj
-<<
-/Type /Pages
-/Kids [ 4 0 R ]
-/Count 1
->>
-endobj
-3 0 obj
-<<
-/Producer (Haru\040Free\040PDF\040Library\0402.0.8)
->>
-endobj
-4 0 obj
-<<
-/Type /Page
-/MediaBox [ 0 0 595 841 ]
-/Contents 5 0 R
-/Resources <<
-/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
-/Font <<
-/F1 7 0 R
-/F2 8 0 R
-/F3 9 0 R
-/F4 10 0 R
-/F5 11 0 R
-/F6 12 0 R
-/F7 13 0 R
-/F8 14 0 R
-/F9 15 0 R
-/F10 16 0 R
-/F11 17 0 R
-/F12 18 0 R
-/F13 19 0 R
-/F14 20 0 R
->>
->>
-/Parent 2 0 R
->>
-endobj
-5 0 obj
-<<
-/Length 6 0 R
->>
-stream\r
-1 w
-50 50 495 731 re
-S
-/F1 24 Tf
-BT
-238.148 791 Td
-(Font\040Demo) Tj
-ET
-BT
-/F1 16 Tf
-60 761 Td
-(\074Standard\040Type1\040font\040samples\076) Tj
-ET
-BT
-60 736 Td
-/F2 9 Tf
-(Courier) Tj
-0 -18 Td
-/F2 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F3 9 Tf
-(Courier-Bold) Tj
-0 -18 Td
-/F3 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F4 9 Tf
-(Courier-Oblique) Tj
-0 -18 Td
-/F4 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F5 9 Tf
-(Courier-BoldOblique) Tj
-0 -18 Td
-/F5 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F1 9 Tf
-(Helvetica) Tj
-0 -18 Td
-/F1 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F6 9 Tf
-(Helvetica-Bold) Tj
-0 -18 Td
-/F6 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F7 9 Tf
-(Helvetica-Oblique) Tj
-0 -18 Td
-/F7 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F8 9 Tf
-(Helvetica-BoldOblique) Tj
-0 -18 Td
-/F8 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F9 9 Tf
-(Times-Roman) Tj
-0 -18 Td
-/F9 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F10 9 Tf
-(Times-Bold) Tj
-0 -18 Td
-/F10 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F11 9 Tf
-(Times-Italic) Tj
-0 -18 Td
-/F11 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F12 9 Tf
-(Times-BoldItalic) Tj
-0 -18 Td
-/F12 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F13 9 Tf
-(Symbol) Tj
-0 -18 Td
-/F13 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F14 9 Tf
-(ZapfDingbats) Tj
-0 -18 Td
-/F14 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-ET
-
-endstream
-endobj
-6 0 obj
-1517
-endobj
-7 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-8 0 obj
-<<
-/Type /Font
-/BaseFont /Courier
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-9 0 obj
-<<
-/Type /Font
-/BaseFont /Courier-Bold
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-10 0 obj
-<<
-/Type /Font
-/BaseFont /Courier-Oblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-11 0 obj
-<<
-/Type /Font
-/BaseFont /Courier-BoldOblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-12 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica-Bold
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-13 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica-Oblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-14 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica-BoldOblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-15 0 obj
-<<
-/Type /Font
-/BaseFont /Times-Roman
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-16 0 obj
-<<
-/Type /Font
-/BaseFont /Times-Bold
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-17 0 obj
-<<
-/Type /Font
-/BaseFont /Times-Italic
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-18 0 obj
-<<
-/Type /Font
-/BaseFont /Times-BoldItalic
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-19 0 obj
-<<
-/Type /Font
-/BaseFont /Symbol
-/Subtype /Type1
->>
-endobj
-20 0 obj
-<<
-/Type /Font
-/BaseFont /ZapfDingbats
-/Subtype /Type1
->>
-endobj
-xref
-0 21
-0000000000 65535 f\r
-0000000015 00000 n\r
-0000000064 00000 n\r
-0000000123 00000 n\r
-0000000196 00000 n\r
-0000000518 00000 n\r
-0000002089 00000 n\r
-0000002109 00000 n\r
-0000002207 00000 n\r
-0000002303 00000 n\r
-0000002404 00000 n\r
-0000002509 00000 n\r
-0000002618 00000 n\r
-0000002722 00000 n\r
-0000002829 00000 n\r
-0000002940 00000 n\r
-0000003041 00000 n\r
-0000003141 00000 n\r
-0000003243 00000 n\r
-0000003349 00000 n\r
-0000003417 00000 n\r
-trailer
-<<
-/Root 1 0 R
-/Info 3 0 R
-/Size 21
->>
-startxref
-3491
-%%EOF
index 6dff95c8293c93f9c19d321a46b850a12853f5d5..9ad375ea042912373ea8770ca1dd575d175c4a60 100644 (file)
@@ -135,9 +135,10 @@ HELP: hide
 \r
 HELP: delay\r
 { $values \r
+  { "quot" "a quotation" } \r
   { "parser" "a parser" } \r
 }\r
 { $description \r
     "Delays the construction of a parser until it is actually required to parse. This " \r
     "allows for calling a parser that results in a recursive call to itself. The quotation "\r
-    "should return the constructed parser." } ;
\ No newline at end of file
+    "should return the constructed parser." } ;\r
index 01decc2c8118d5c6be0422f47ee18720ad311d09..16cf40f8842a7e8c6cbead7015ec3d89d08de3f3 100755 (executable)
@@ -358,7 +358,7 @@ MEMO: sp ( parser -- parser )
 MEMO: hide ( parser -- parser )
   [ drop ignore ] action ;
 
-MEMO: delay ( parser -- parser )
+MEMO: delay ( quot -- parser )
   delay-parser construct-boa init-parser ;
 
 : PEG:
index c65001be098dfaf07cdd3cecc4e7694941e9dbb9..b22a5ef0d0da6a0f258ac48e142948e616680099 100755 (executable)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2007 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 !
-USING: kernel math math.parser arrays tools.test peg peg.search ;
+USING: kernel math math.parser arrays tools.test peg peg.parsers
+peg.search ;
 IN: peg.search.tests
 
 { V{ 123 456 } } [
index ab528786bbd7658b85b2f10a3093ea27206145f7..f7eac4c32db6f603d7c48327b7cbaa4e09a1c08c 100755 (executable)
@@ -54,7 +54,6 @@ IN: random-tester.safe-words
 
 : method-words
     {
-        method-def
         forget-word
     } ;
 
diff --git a/extra/regexp2/regexp2-tests.factor b/extra/regexp2/regexp2-tests.factor
new file mode 100644 (file)
index 0000000..1fb3f61
--- /dev/null
@@ -0,0 +1,5 @@
+USING: kernel peg regexp2 sequences tools.test ;
+IN: regexp2.tests
+
+[ T{ parse-result f T{ slice f 3 3 "056" } 46 } ]
+    [ "056" 'octal' parse ] unit-test
diff --git a/extra/regexp2/regexp2.factor b/extra/regexp2/regexp2.factor
new file mode 100644 (file)
index 0000000..e62eb76
--- /dev/null
@@ -0,0 +1,262 @@
+USING: assocs combinators.lib kernel math math.parser
+namespaces peg unicode.case sequences unicode.categories
+memoize peg.parsers ;
+USE: io
+USE: tools.walker
+IN: regexp2
+
+<PRIVATE
+    
+SYMBOL: ignore-case?
+
+: char=-quot ( ch -- quot )
+    ignore-case? get
+    [ ch>upper [ swap ch>upper = ] ] [ [ = ] ] if
+    curry ;
+    
+: char-between?-quot ( ch1 ch2 -- quot )
+    ignore-case? get
+    [ [ ch>upper ] 2apply [ >r >r ch>upper r> r> between? ] ]
+    [ [ between? ] ]
+    if 2curry ;
+    
+: or-predicates ( quots -- quot )
+    [ \ dup add* ] map [ [ t ] ] f short-circuit \ nip add ;
+
+: literal-action [ nip ] curry action ;
+
+: delay-action [ curry ] curry action ;
+    
+PRIVATE>
+
+: ascii? ( n -- ? )
+    0 HEX: 7f between? ;
+    
+: octal-digit? ( n -- ? ) 
+    CHAR: 0 CHAR: 7 between? ;
+
+: hex-digit? ( n -- ? )
+    {
+        [ dup digit? ]
+        [ dup CHAR: a CHAR: f between? ]
+        [ dup CHAR: A CHAR: F between? ]
+    } || nip ;
+
+: control-char? ( n -- ? )
+    { [ dup 0 HEX: 1f between? ] [ dup HEX: 7f = ] } || nip ;
+
+: punct? ( n -- ? )
+    "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" member? ;
+
+: c-identifier-char? ( ch -- ? )
+    { [ dup alpha? ] [ dup CHAR: _ = ] } || nip ;
+
+: java-blank? ( n -- ? )
+    {
+        CHAR: \s
+        CHAR: \t CHAR: \n CHAR: \r
+        HEX: c HEX: 7 HEX: 1b
+    } member? ;
+
+: java-printable? ( n -- ? )
+    { [ dup alpha? ] [ dup punct? ] } || nip ;
+
+MEMO: 'ordinary-char' ( -- parser )
+    [ "\\^*+?|(){}[$" member? not ] satisfy
+    [ char=-quot ] action ;
+
+MEMO: 'octal-digit' ( -- parser ) [ octal-digit? ] satisfy ;
+
+MEMO: 'octal' ( -- parser )
+    "0" token hide 'octal-digit' 1 3 from-m-to-n 2seq
+    [ first oct> ] action ;
+
+MEMO: 'hex-digit' ( -- parser ) [ hex-digit? ] satisfy ;
+
+MEMO: 'hex' ( -- parser )
+    "x" token hide 'hex-digit' 2 exactly-n 2seq
+    "u" token hide 'hex-digit' 6 exactly-n 2seq 2choice
+    [ first hex> ] action ;
+
+: satisfy-tokens ( assoc -- parser )
+    [ >r token r> literal-action ] { } assoc>map choice ;
+
+MEMO: 'simple-escape-char' ( -- parser )
+    {
+        { "\\" CHAR: \\ }
+        { "t"  CHAR: \t }
+        { "n"  CHAR: \n }
+        { "r"  CHAR: \r }
+        { "f"  HEX: c   }
+        { "a"  HEX: 7   }
+        { "e"  HEX: 1b  }
+    } [ char=-quot ] assoc-map satisfy-tokens ;
+
+MEMO: 'predefined-char-class' ( -- parser )
+    {   
+        { "d" [ digit? ] } 
+        { "D" [ digit? not ] }
+        { "s" [ java-blank? ] } 
+        { "S" [ java-blank? not ] }
+        { "w" [ c-identifier-char? ] } 
+        { "W" [ c-identifier-char? not ] }
+    } satisfy-tokens ;
+
+MEMO: 'posix-character-class' ( -- parser )
+    {   
+        { "Lower" [ letter? ] }
+        { "Upper" [ LETTER? ] }
+        { "ASCII" [ ascii? ] }
+        { "Alpha" [ Letter? ] }
+        { "Digit" [ digit? ] }
+        { "Alnum" [ alpha? ] }
+        { "Punct" [ punct? ] }
+        { "Graph" [ java-printable? ] }
+        { "Print" [ java-printable? ] }
+        { "Blank" [ " \t" member? ] }
+        { "Cntrl" [ control-char? ] }
+        { "XDigit" [ hex-digit? ] }
+        { "Space" [ java-blank? ] }
+    } satisfy-tokens "p{" "}" surrounded-by ;
+
+MEMO: 'simple-escape' ( -- parser )
+    [
+        'octal' ,
+        'hex' ,
+        "c" token hide [ LETTER? ] satisfy 2seq ,
+        any-char ,
+    ] choice* [ char=-quot ] action ;
+
+MEMO: 'escape' ( -- parser )
+    "\\" token hide [
+        'simple-escape-char' ,
+        'predefined-char-class' ,
+        'posix-character-class' ,
+        'simple-escape' ,
+    ] choice* 2seq ;
+
+MEMO: 'any-char' ( -- parser )
+    "." token [ drop t ] literal-action ;
+
+MEMO: 'char' ( -- parser )
+    'any-char' 'escape' 'ordinary-char' 3choice [ satisfy ] action ;
+
+DEFER: 'regexp'
+
+TUPLE: group-result str ;
+
+C: <group-result> group-result
+
+MEMO: 'non-capturing-group' ( -- parser )
+    "?:" token hide 'regexp' ;
+
+MEMO: 'positive-lookahead-group' ( -- parser )
+    "?=" token hide 'regexp' [ ensure ] action ;
+
+MEMO: 'negative-lookahead-group' ( -- parser )
+    "?!" token hide 'regexp' [ ensure-not ] action ;
+
+MEMO: 'simple-group' ( -- parser )
+    'regexp' [ [ <group-result> ] action ] action ;
+
+MEMO: 'group' ( -- parser )
+    [
+        'non-capturing-group' ,
+        'positive-lookahead-group' ,
+        'negative-lookahead-group' ,
+        'simple-group' ,
+    ] choice* "(" ")" surrounded-by ;
+
+MEMO: 'range' ( -- parser )
+    any-char "-" token hide any-char 3seq
+    [ first2 char-between?-quot ] action ;
+
+MEMO: 'character-class-term' ( -- parser )
+    'range'
+    'escape'
+    [ "\\]" member? not ] satisfy [ char=-quot ] action
+    3choice ;
+
+MEMO: 'positive-character-class' ( -- parser )
+    ! todo
+    "]" token [ CHAR: ] = ] literal-action 'character-class-term' repeat0 2seq 
+    'character-class-term' repeat1 2choice [ or-predicates ] action ;
+
+MEMO: 'negative-character-class' ( -- parser )
+    "^" token hide 'positive-character-class' 2seq
+    [ [ not ] append ] action ;
+
+MEMO: 'character-class' ( -- parser )
+    'negative-character-class' 'positive-character-class' 2choice
+    "[" "]" surrounded-by [ satisfy ] action ;
+
+MEMO: 'escaped-seq' ( -- parser )
+    any-char repeat1
+    [ ignore-case? get token ] action "\\Q" "\\E" surrounded-by ;
+    
+MEMO: 'break' ( quot -- parser )
+    satisfy ensure
+    epsilon just 2choice ;
+    
+MEMO: 'break-escape' ( -- parser )
+    "$" token [ "\r\n" member? ] 'break' literal-action
+    "\\b" token [ blank? ] 'break' literal-action
+    "\\B" token [ blank? not ] 'break' literal-action
+    "\\z" token epsilon just literal-action 4choice ;
+    
+MEMO: 'simple' ( -- parser )
+    [
+        'escaped-seq' ,
+        'break-escape' ,
+        'group' ,
+        'character-class' ,
+        'char' ,
+    ] choice* ;
+
+MEMO: 'exactly-n' ( -- parser )
+    'integer' [ exactly-n ] delay-action ;
+
+MEMO: 'at-least-n' ( -- parser )
+    'integer' "," token hide 2seq [ at-least-n ] delay-action ;
+
+MEMO: 'at-most-n' ( -- parser )
+    "," token hide 'integer' 2seq [ at-most-n ] delay-action ;
+
+MEMO: 'from-m-to-n' ( -- parser )
+    'integer' "," token hide 'integer' 3seq
+    [ first2 from-m-to-n ] delay-action ;
+
+MEMO: 'greedy-interval' ( -- parser )
+    'exactly-n' 'at-least-n' 'at-most-n' 'from-m-to-n' 4choice ;
+
+MEMO: 'interval' ( -- parser )
+    'greedy-interval'
+    'greedy-interval' "?" token hide 2seq [ "reluctant {}" print ] action
+    'greedy-interval' "+" token hide 2seq [ "possessive {}" print ] action
+    3choice "{" "}" surrounded-by ;
+
+MEMO: 'repetition' ( -- parser )
+    [
+        ! Possessive
+        ! "*+" token [ <!*> ] literal-action ,
+        ! "++" token [ <!+> ] literal-action ,
+        ! "?+" token [ <!?> ] literal-action ,
+        ! Reluctant
+        ! "*?" token [ <(*)> ] literal-action ,
+        ! "+?" token [ <(+)> ] literal-action ,
+        ! "??" token [ <(?)> ] literal-action ,
+        ! Greedy
+        "*" token [ repeat0 ] literal-action ,
+        "+" token [ repeat1 ] literal-action ,
+        "?" token [ optional ] literal-action ,
+    ] choice* ;
+
+MEMO: 'dummy' ( -- parser )
+    epsilon [ ] literal-action ;
+
+! todo -- check the action
+! MEMO: 'term' ( -- parser )
+    ! 'simple'
+    ! 'repetition' 'interval' 'dummy' 3choice 2seq [ first2 call ] action
+    ! <!+> [ <and-parser> ] action ;
+
diff --git a/extra/singleton/authors.txt b/extra/singleton/authors.txt
new file mode 100644 (file)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/extra/singleton/singleton-docs.factor b/extra/singleton/singleton-docs.factor
new file mode 100644 (file)
index 0000000..b87c557
--- /dev/null
@@ -0,0 +1,14 @@
+USING: help.markup help.syntax ;
+IN: singleton
+
+HELP: SINGLETON:
+{ $syntax "SINGLETON: class"
+} { $values
+    { "class" "a new tuple class to define" }
+} { $description
+    "Defines a new tuple class with membership predicate name? and a default empty constructor that is the class name itself."
+} { $examples
+    { $example "SINGLETON: foo\nfoo ." "T{ foo f }" }
+} { $see-also
+    POSTPONE: TUPLE:
+} ;
diff --git a/extra/singleton/singleton.factor b/extra/singleton/singleton.factor
new file mode 100644 (file)
index 0000000..b745e8f
--- /dev/null
@@ -0,0 +1,10 @@
+! Copyright (C) 2007 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel parser quotations prettyprint tuples words ;
+IN: singleton
+
+: SINGLETON:
+    CREATE-CLASS
+    dup { } define-tuple-class
+    dup unparse create-in reset-generic
+    dup construct-empty 1quotation define ; parsing
index c1afeced3d8f314b7a004be185d0b022febe7382..32b2f3be14c394b6d745e64297c347403e544e4c 100755 (executable)
@@ -84,6 +84,7 @@ IN: smtp.tests
 
 [ ] [
     [
+        "localhost" smtp-host set
         4321 smtp-port set
 
         "Hi guys\nBye guys"
@@ -96,4 +97,4 @@ IN: smtp.tests
 
         send-simple-message
     ] with-scope
-] unit-test
\ No newline at end of file
+] unit-test
index 204321f30cbe097876c995edf74fdfeb580cef0e..6d60caf9872546bb71fdce3585210b0815a2ba62 100644 (file)
@@ -74,3 +74,8 @@ FUNCTION: int mkdir ( char* path, mode_t mode ) ;
   "stat" <c-object> dup >r
     stat check-status
   r> ;
+
+: lstat* ( pathname -- stat )
+  "stat" <c-object> dup >r
+    lstat check-status
+  r> ;
index 9cc8552f986ef868bc0dfcf4ce9a0f79846b7b3a..e1d49b8c6cf2af2af80c1f9005a021c0769ec0ba 100755 (executable)
@@ -21,6 +21,7 @@ TYPEDEF: ulong size_t
 
 : MAP_FAILED -1 <alien> ; inline
 
+: ESRCH 3 ; inline
 : EEXIST 17 ; inline
 
 ! ! ! Unix functions
diff --git a/extra/webapps/callback/authors.txt b/extra/webapps/callback/authors.txt
deleted file mode 100755 (executable)
index a8fb961..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Chris Double
-Slava Pestov
diff --git a/extra/webapps/callback/callback.factor b/extra/webapps/callback/callback.factor
deleted file mode 100644 (file)
index 6bdc84b..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-! Copyright (C) 2004 Chris Double.
-! Copyright (C) 2006 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: html http http.server.responders io kernel math
-namespaces prettyprint continuations random system sequences
-assocs ;
-IN: webapps.callback
-
-#! Name of the variable holding the continuation used to exit
-#! back to the httpd responder.
-SYMBOL: exit-continuation 
-
-#! Tuple to hold global request data. This gets passed to
-#! the continuation when resumed so it can restore things
-#! like 'stdio' so it writes to the correct socket. 
-TUPLE: request stream exitcc method url raw-query query header response ;
-
-: <request> ( -- request )
-  stdio get
-  exit-continuation get
-  "method" get
-  "request" get
-  "raw-query" get
-  "query" get
-  "header" get
-  "response" get
-  request construct-boa ;
-
-: restore-request ( -- )
-  request get 
-  dup request-stream stdio set 
-  dup request-method "method" set 
-  dup request-raw-query "raw-query" set 
-  dup request-query "query" set 
-  dup request-header "header" set 
-  dup request-response "response" set 
-  request-exitcc exit-continuation set ;
-
-: update-request ( request new-request -- )
-  [ request-stream over set-request-stream ] keep 
-  [ request-method over set-request-method ] keep 
-  [ request-url over set-request-url ] keep 
-  [ request-raw-query over set-request-raw-query ] keep 
-  [ request-query over set-request-query ] keep 
-  [ request-header over set-request-header ] keep 
-  [ request-response over set-request-response ] keep 
-  request-exitcc swap set-request-exitcc ;
-  
-: with-exit-continuation ( quot -- ) 
-    #! Call the quotation with the variable exit-continuation bound 
-    #! such that when the exit continuation is called, computation 
-    #! will resume from the end of this 'with-exit-continuation' call. 
-    [ 
-        exit-continuation set call exit-continuation get continue
-    ] callcc0 drop ;
-
-: expiry-timeout ( -- ms ) 900 1000 * ;
-
-: get-random-id ( -- id ) 
-    #! Generate a random id to use for continuation URL's
-    4 big-random unparse ;
-
-: callback-table ( -- <hashtable> ) 
-    #! Return the global table of continuations
-    \ callback-table get-global ;
-
-: reset-callback-table ( -- ) 
-    #! Create the initial global table
-    H{ } clone \ callback-table set-global ;
-
-reset-callback-table
-
-#! Tuple for holding data related to a callback.
-TUPLE: item quot expire? request id  time-added ;
-
-: <item> ( quot expire? request id -- item )
-    millis item construct-boa ;
-
-: expired? ( item -- ? )
-    #! Return true if the callback item is expirable
-    #! and has expired (ie. was added to the table more than
-    #! timeout milliseconds ago).
-    [ item-time-added expiry-timeout + millis < ] keep
-    item-expire? and ;
-
-: expire-callbacks ( -- )
-    #! Expire all continuations in the continuation table
-    #! if they are 'timeout-seconds' old (ie. were added
-    #! more than 'timeout-seconds' ago.
-    callback-table clone [
-        expired? [ callback-table delete-at ] [ drop ] if
-    ] assoc-each ;
-
-: id>url ( id -- string )
-    #! Convert the continuation id to an URL suitable for
-    #! embedding in an HREF or other HTML.
-    "/responder/callback/?id=" swap url-encode append ;
-
-: register-callback ( quot expire? -- url ) 
-    #! Store a continuation in the table and associate it with
-    #! a random id. That continuation will be expired after
-    #! a certain period of time if 'expire?' is true.  
-    request get get-random-id [ <item> ] keep
-    [ callback-table set-at ] keep
-    id>url ;
-
-: register-html-callback ( quot expire? -- url )
-    >r [ serving-html ] swap append r> register-callback ;
-
-: callback-responder ( -- )   
-    expire-callbacks
-    "id" query-param callback-table at [
-        [
-          dup item-request [
-            <request> update-request
-          ] when*
-          item-quot call 
-          exit-continuation get continue 
-        ] with-exit-continuation drop
-    ] [
-        "404 Callback not available" httpd-error
-    ] if* ;
-
-global [
-    "callback" [ callback-responder ] add-simple-responder
-] bind
diff --git a/extra/webapps/continuation/authors.txt b/extra/webapps/continuation/authors.txt
deleted file mode 100755 (executable)
index 44b06f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chris Double
diff --git a/extra/webapps/continuation/continuation.factor b/extra/webapps/continuation/continuation.factor
deleted file mode 100644 (file)
index 6b6838d..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-! Copyright (C) 2004 Chris Double.
-! See http://factorcode.org/license.txt for BSD license.
-
-USING: http math namespaces io strings kernel html html.elements
-hashtables continuations quotations parser generic sequences
-webapps.callback http.server.responders ;
-IN: webapps.continuation
-
-#! Used inside the session state of responders to indicate whether the
-#! next request should use the post-refresh-get pattern. It is set to
-#! true after each request.
-SYMBOL: post-refresh-get?
-
-: >callable ( quot|interp|f -- interp )
-    dup continuation? [
-        [ continue ] curry
-    ] when ;
-
-: forward-to-url ( url -- )
-    #! When executed inside a 'show' call, this will force a
-    #! HTTP 302 to occur to instruct the browser to forward to
-    #! the request URL.
-    [
-        "HTTP/1.1 302 Document Moved\nLocation: " % %
-        "\nContent-Length: 0\nContent-Type: text/plain\n\n" %
-    ] "" make write exit-continuation get continue ;
-
-: forward-to-id ( id -- )
-    #! When executed inside a 'show' call, this will force a
-    #! HTTP 302 to occur to instruct the browser to forward to
-    #! the request URL.
-    >r "request" get r> id>url append forward-to-url ;
-
-SYMBOL: current-show
-
-: store-current-show ( -- )
-  #! Store the current continuation in the variable 'current-show'
-  #! so it can be returned to later by href callbacks. Note that it
-  #! recalls itself when the continuation is called to ensure that
-  #! it resets its value back to the most recent show call.
-  [  ( 0 -- )
-      [ ( 0 1 -- )
-          current-show set ( 0 -- )
-          continue
-      ] callcc1
-      nip
-      restore-request
-      call
-      store-current-show
-  ] callcc0 restore-request ;
-
-: redirect-to-here ( -- )
-    #! Force a redirect to the client browser so that the browser
-    #! goes to the current point in the code. This forces an URL
-    #! change on the browser so that refreshing that URL will
-    #! immediately run from this code point. This prevents the
-    #! "this request will issue a POST" warning from the browser
-    #! and prevents re-running the previous POST logic. This is
-    #! known as the 'post-refresh-get' pattern.
-    post-refresh-get? get [
-        [
-            >callable t register-callback forward-to-url
-        ] callcc0  restore-request
-    ] [
-        t post-refresh-get? set
-    ] if ;
-
-: (show) ( quot -- hashtable )
-    #! See comments for show. The difference is the
-    #! quotation MUST set the content-type using 'serving-html'
-    #! or similar.
-    store-current-show redirect-to-here
-    [
-        >callable t register-callback swap with-scope
-        exit-continuation get  continue
-    ] callcc0 drop restore-request "response" get ;
-
-: show ( quot -- namespace )
-    #! Call the quotation with the URL associated with the current
-    #! continuation. All output from the quotation goes to the client
-    #! browser. When the URL is later referenced then
-    #! computation will resume from this 'show' call with a hashtable on
-    #! the stack containing any query or post parameters.
-    #! 'quot' has stack effect ( url -- )
-    #! NOTE: On return from 'show' the stack is exactly the same as
-    #! initial entry with 'quot' popped off and the hashtable pushed on. Even
-    #! if the quotation consumes items on the stack.
-    [ serving-html ] swap append (show) ;
-
-: (show-final) ( quot -- namespace )
-    #! See comments for show-final. The difference is the
-    #! quotation MUST set the content-type using 'serving-html'
-    #! or similar.
-    store-current-show redirect-to-here
-    with-scope exit-continuation get continue ;
-
-: show-final ( quot -- namespace )
-    #! Similar to 'show', except the quotation does not receive the URL
-    #! to resume computation following 'show-final'. No continuation is
-    #! stored for this resumption. As a result, 'show-final' is for use
-    #! when a page is to be displayed with no further action to occur. Its
-    #! use is an optimisation to save having to generate and save a continuation
-    #! in that special case.
-    #! 'quot' has stack effect ( -- ).
-    [ serving-html ] swap compose (show-final) ;
-
-#! Name of variable for holding initial continuation id that starts
-#! the responder.
-SYMBOL: root-callback
-
-: cont-get/post-responder ( id-or-f -- )
-    #! httpd responder that handles the root continuation request.
-    #! The requests for actual continuation are processed by the
-    #! 'callback-responder'.
-    [
-        [ f post-refresh-get? set <request> request set root-callback get call ] with-scope
-        exit-continuation get continue
-    ] with-exit-continuation  drop ;
-
-: quot-url ( quot -- url )
-    current-show get [ continue-with ] 2curry t register-callback ;
-
-: quot-href ( text quot -- )
-    #! Write to standard output an HTML HREF where the href,
-    #! when referenced, will call the quotation and then return
-    #! back to the most recent 'show' call (via the callback-cc).
-    #! The text of the link will be the 'text' argument on the
-    #! stack.
-    <a quot-url =href a> write </a> ;
-
-: install-cont-responder ( name quot -- )
-    #! Install a cont-responder with the given name
-    #! that will initially run the given quotation.
-    #!
-    #! Convert the quotation so it is run within a session namespace
-    #! and that namespace is initialized first.
-    [
-        [ cont-get/post-responder ] "get" set
-        [ cont-get/post-responder ] "post" set
-        swap "responder" set
-        root-callback set
-    ] make-responder ;
-
-: show-message-page ( message -- )
-    #! Display the message in an HTML page with an OK button.
-    [
-        "Press OK to Continue" [
-            swap paragraph
-            <a =href a> "OK" write </a>
-        ] simple-page
-    ] show 2drop ;
diff --git a/extra/webapps/continuation/examples/authors.txt b/extra/webapps/continuation/examples/authors.txt
deleted file mode 100755 (executable)
index 44b06f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chris Double
diff --git a/extra/webapps/continuation/examples/examples.factor b/extra/webapps/continuation/examples/examples.factor
deleted file mode 100644 (file)
index 2899562..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-! Copyright (C) 2004 Chris Double.
-! 
-! Redistribution and use in source and binary forms, with or without
-! modification, are permitted provided that the following conditions are met:
-! 
-! 1. Redistributions of source code must retain the above copyright notice,
-!    this list of conditions and the following disclaimer.
-! 
-! 2. Redistributions in binary form must reproduce the above copyright notice,
-!    this list of conditions and the following disclaimer in the documentation
-!    and/or other materials provided with the distribution.
-! 
-! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-!
-! Simple test applications
-USING: hashtables html kernel io html html.elements strings math
-assocs quotations webapps.continuation namespaces prettyprint
-sequences ;
-
-IN: webapps.continuation.examples
-
-: display-page ( title -- ) 
-  #! Display a page with some text to test the cont-responder.
-  #! The page has a link to the 'next' continuation.
-  [ 
-    <h1> over write </h1>
-    swap [ 
-      <a =href a> "Next" write </a>
-    ] simple-html-document 
-  ] show 2drop ;
-
-: display-get-name-page ( -- name )
-  #! Display a page prompting for input of a name and return that name.
-  [ 
-    "Enter your name" [
-      <h1> swap write </h1>
-      <form "post" =method =action form> 
-        "Name: " write
-        <input "text" =type "name" =name "20" =size input/>
-        <input "submit" =type "Ok" =value input/>
-      </form>
-    ] simple-html-document
-  ] show "name" swap at ;
-
-: test-cont-responder ( -- )
-  #! Test the cont-responder responder by displaying a few pages in a row.
-  "Page one" display-page 
-  "Hello " display-get-name-page append display-page
-  "Page three" display-page ;
-
-: test-cont-responder2 ( -- )
-  #! Test the cont-responder responder by displaying a few pages in a loop.
-  [ "one" "two" "three" "four" ] [ display-page ]  each 
-  "Done!" display-page  ;
-
-: test-cont-responder3 ( -- )
-  #! Test the quot-href word by displaying a menu of the current
-  #! test words. Note that we use show-final as we don't link to a 'next' page.
-  [ 
-    "Menu" [ 
-      <h1> "Menu" write </h1>
-      <ol> 
-        <li> "Test responder1" [ test-cont-responder ] quot-href </li>
-        <li> "Test responder2" [ test-cont-responder2 ] quot-href </li>
-      </ol>
-    ] simple-html-document 
-  ] show-final ;
-
-: counter-example ( count -- )
-  #! Display a counter which can be incremented or decremented
-  #! using anchors.
-  #!
-  #! Don't need the original alist
-  [ 
-    #! And we don't need the 'url' argument
-    drop         
-    "Counter: " over unparse append [ 
-      dup <h2> unparse write </h2>
-      "++" over 1quotation [ f ] swap append [ 1 + counter-example ] append quot-href
-      "--" over 1quotation [ f ] swap append [ 1 - counter-example ] append quot-href
-      drop
-    ] simple-html-document 
-  ] show drop ;
-
-: counter-example2 ( -- )
-  #! Display a counter which can be incremented or decremented
-  #! using anchors.
-  #!
-  0 "counter" set
-  [ 
-    #! We don't need the 'url' argument
-    drop   
-    "Counter: " "counter" get unparse append [ 
-      <h2> "counter" get unparse write </h2>
-      "++" [ "counter" get 1 + "counter" set ] quot-href
-      "--" [ "counter" get 1 - "counter" set ] quot-href
-    ] simple-html-document 
-  ] show 
-  drop ;
-
-! Install the examples
-"counter1" [ drop 0 counter-example ] install-cont-responder
-"counter2" [ drop counter-example2 ] install-cont-responder
-"test1" [ test-cont-responder ] install-cont-responder
-"test2" [ drop test-cont-responder2 ] install-cont-responder
-"test3" [ drop test-cont-responder3 ] install-cont-responder