]> gitweb.factorcode.org Git - factor.git/commitdiff
Fix conflict
authorSlava Pestov <slava@factorcode.org>
Sun, 6 Jan 2008 17:30:23 +0000 (13:30 -0400)
committerSlava Pestov <slava@factorcode.org>
Sun, 6 Jan 2008 17:30:23 +0000 (13:30 -0400)
81 files changed:
core/bootstrap/stage2.factor
core/classes/classes-docs.factor
core/heaps/heaps-tests.factor
core/heaps/heaps.factor
core/sequences/sequences.factor
core/slots/slots-docs.factor
extra/assoc-heaps/assoc-heaps-tests.factor [new file with mode: 0644]
extra/assoc-heaps/assoc-heaps.factor [new file with mode: 0755]
extra/delegate/delegate-tests.factor
extra/faq/faq.factor
extra/fjsc/fjsc-tests.factor
extra/fjsc/fjsc.factor
extra/fjsc/resources/bootstrap.factor
extra/fjsc/resources/bootstrap.js
extra/furnace/authors.txt [new file with mode: 0644]
extra/furnace/furnace-tests.factor
extra/furnace/furnace.factor
extra/furnace/sessions/sessions.factor [new file with mode: 0644]
extra/hello-world/deploy.factor
extra/http/http.factor [changed mode: 0644->0755]
extra/http/server/templating/templating.factor
extra/lazy-lists/authors.txt
extra/lazy-lists/lazy-lists-docs.factor
extra/lazy-lists/lazy-lists.factor
extra/math/erato/authors.txt [new file with mode: 0644]
extra/math/erato/erato-docs.factor [new file with mode: 0644]
extra/math/erato/erato-tests.factor [new file with mode: 0644]
extra/math/erato/erato.factor [new file with mode: 0644]
extra/math/erato/summary.txt [new file with mode: 0644]
extra/parser-combinators/replace/replace-docs.factor [deleted file]
extra/parser-combinators/replace/replace.factor [deleted file]
extra/parser-combinators/simple/simple.factor
extra/peg/ebnf/tags.txt [new file with mode: 0644]
extra/peg/peg.factor
extra/peg/pl0/tags.txt [new file with mode: 0644]
extra/peg/search/authors.txt [new file with mode: 0644]
extra/peg/search/search-docs.factor [new file with mode: 0755]
extra/peg/search/search-tests.factor [new file with mode: 0755]
extra/peg/search/search.factor [new file with mode: 0755]
extra/peg/search/summary.txt [new file with mode: 0644]
extra/peg/search/tags.txt [new file with mode: 0644]
extra/peg/tags.txt [new file with mode: 0644]
extra/project-euler/001/001.factor [new file with mode: 0644]
extra/project-euler/002/002.factor [new file with mode: 0644]
extra/project-euler/003/003.factor [new file with mode: 0644]
extra/project-euler/004/004.factor [new file with mode: 0644]
extra/project-euler/005/005.factor [new file with mode: 0644]
extra/project-euler/006/006.factor [new file with mode: 0644]
extra/project-euler/007/007.factor [new file with mode: 0644]
extra/project-euler/008/008.factor [new file with mode: 0644]
extra/project-euler/009/009.factor [new file with mode: 0644]
extra/project-euler/010/010.factor [new file with mode: 0644]
extra/project-euler/011/011.factor [new file with mode: 0644]
extra/project-euler/012/012.factor [new file with mode: 0644]
extra/project-euler/013/013.factor [new file with mode: 0644]
extra/project-euler/014/014.factor [new file with mode: 0644]
extra/project-euler/015/015.factor [new file with mode: 0644]
extra/project-euler/016/016.factor [new file with mode: 0644]
extra/project-euler/017/017.factor [new file with mode: 0644]
extra/project-euler/authors.txt [new file with mode: 0644]
extra/project-euler/ave-time/authors.txt [new file with mode: 0644]
extra/project-euler/ave-time/ave-time-docs.factor [new file with mode: 0644]
extra/project-euler/ave-time/ave-time.factor [new file with mode: 0644]
extra/project-euler/ave-time/summary.txt [new file with mode: 0644]
extra/project-euler/ave-time/tags.txt [new file with mode: 0644]
extra/project-euler/common/common.factor [new file with mode: 0644]
extra/project-euler/project-euler.factor [new file with mode: 0644]
extra/project-euler/summary.txt [new file with mode: 0644]
extra/project-euler/tags.txt [new file with mode: 0644]
extra/sequences/lib/lib.factor
extra/tools/deploy/windows/windows.factor
extra/webapps/fjsc/fjsc.factor
extra/webapps/help/help.factor
extra/webapps/pastebin/annotate-paste.furnace
extra/webapps/pastebin/modes.furnace
extra/webapps/pastebin/new-paste.furnace
extra/webapps/pastebin/pastebin.factor
extra/webapps/pastebin/style.css
extra/xml/data/data.factor
extra/xml/utilities/utilities.factor
misc/factor.sh

index 5587f54c16c33c876b254febd4dbf4895163c8c1..841f1ab280968cbc22f378a8be83a0c19f6a2bb0 100755 (executable)
@@ -59,10 +59,12 @@ IN: bootstrap.stage2
         [
             boot
             do-init-hooks
-            [ parse-command-line ] try
-            [ run-user-init ] try
-            [ "run" get run ] try
-            stdio get [ stream-flush ] when*
+            [
+                parse-command-line
+                run-user-init
+                "run" get run
+                stdio get [ stream-flush ] when*
+            ] [ print-error 1 exit ] recover
         ] set-boot-quot
 
         : count-words all-words swap subset length pprint ;
index 6cc08e9f8fc0bb8bdf88304977c90b4cf163ae91..859b6a95d5dbf594f0cd19f483d9b953e75b15f6 100755 (executable)
@@ -5,7 +5,7 @@ classes.predicate ;
 IN: classes
 
 ARTICLE: "builtin-classes" "Built-in classes"
-"Every object is an instance of to exactly one canonical " { $emphasis "built-in class" } " which defines its layout in memory and basic behavior."
+"Every object is an instance of exactly one canonical " { $emphasis "built-in class" } " which defines its layout in memory and basic behavior."
 $nl
 "Corresponding to every built-in class is a built-in type number. An object can be asked for its built-in type number:"
 { $subsection type }
index 03e0816c1911c181b126b48bfec8e4eb8029a0cd..de661fad921f04fd4b7181cef43865ad2e588116 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright 2007 Ryan Murphy
 ! See http://factorcode.org/license.txt for BSD license.
 
-USING: kernel math tools.test heaps heaps.private ;
+USING: arrays kernel math namespaces tools.test
+heaps heaps.private ;
 IN: temporary
 
 [ <min-heap> heap-pop ] unit-test-fails
@@ -33,3 +34,16 @@ IN: temporary
 
 [ 0 ] [ <max-heap> heap-length ] unit-test
 [ 1 ] [ <max-heap> t 1 pick heap-push heap-length ] unit-test
+
+[ { { 1 2 } { 3 4 } { 5 6 } } ] [
+    T{ min-heap T{ heap f V{ { 2 1 } { 4 3 } { 6 5 } } } }
+    [ [ 10 < nip ] [ 2array , ] heap-pop-while ] { } make
+] unit-test
+[ { { 1 2 } } ] [
+    T{ min-heap T{ heap f V{ { 2 1 } { 4 3 } { 6 5 } } } }
+    [ [ 3 < nip ] [ 2array , ] heap-pop-while ] { } make
+] unit-test
+[ { } ] [
+    T{ min-heap T{ heap f V{ { 2 1 } { 4 3 } { 6 5 } } } }
+    [ [ 1 < nip ] [ 2array , ] heap-pop-while ] { } make
+] unit-test
index 73a37660f67714da48da18db719c034e17fe77a5..f01b436e90a506ed7c631c835115355f19f49c72 100644 (file)
@@ -3,6 +3,19 @@
 USING: kernel math sequences arrays assocs ;
 IN: heaps
 
+MIXIN: priority-queue
+
+GENERIC: heap-push ( value key heap -- )
+GENERIC: heap-push-all ( assoc heap -- )
+GENERIC: heap-peek ( heap -- value key )
+GENERIC: heap-pop* ( heap -- )
+GENERIC: heap-pop ( heap -- value key )
+GENERIC: heap-delete ( key heap -- )
+GENERIC: heap-delete* ( key heap -- old ? )
+GENERIC: heap-empty? ( heap -- ? )
+GENERIC: heap-length ( heap -- n )
+GENERIC# heap-pop-while 2 ( heap pred quot -- )
+
 <PRIVATE
 TUPLE: heap data ;
 
@@ -19,6 +32,9 @@ TUPLE: max-heap ;
 
 : <max-heap> ( -- max-heap ) max-heap <heap> ;
 
+INSTANCE: min-heap priority-queue
+INSTANCE: max-heap priority-queue
+
 <PRIVATE
 : left ( n -- m ) 2 * 1+ ; inline
 : right ( n -- m ) 2 * 2 + ; inline
@@ -85,19 +101,19 @@ DEFER: down-heap
 
 PRIVATE>
 
-: heap-push ( value key heap -- )
+M: priority-queue heap-push ( value key heap -- )
     >r swap 2array r>
     [ heap-data push ] keep
     [ heap-data ] keep
     up-heap ;
 
-: heap-push-all ( assoc heap -- )
+M: priority-queue heap-push-all ( assoc heap -- )
     [ swapd heap-push ] curry assoc-each ;
 
-: heap-peek ( heap -- value key )
+M: priority-queue heap-peek ( heap -- value key )
     heap-data first first2 swap ;
 
-: heap-pop* ( heap -- )
+M: priority-queue heap-pop* ( heap -- )
     dup heap-data length 1 > [
         [ heap-data pop ] keep
         [ heap-data set-first ] keep
@@ -106,8 +122,19 @@ PRIVATE>
         heap-data pop*
     ] if ;
 
-: heap-pop ( heap -- value key ) dup heap-peek rot heap-pop* ;
+M: priority-queue heap-pop ( heap -- value key ) dup heap-peek rot heap-pop* ;
+
+M: priority-queue heap-empty? ( heap -- ? ) heap-data empty? ;
+
+M: priority-queue heap-length ( heap -- n ) heap-data length ;
 
-: heap-empty? ( heap -- ? ) heap-data empty? ;
+: (heap-pop-while) ( heap pred quot -- )
+    pick heap-empty? [
+        3drop
+    ] [
+        [ >r >r dup heap-peek r> call r> [ drop f ] if ] 3keep
+        roll [ (heap-pop-while) ] [ 3drop ] if
+    ] if ;
 
-: heap-length ( heap -- n ) heap-data length ;
+M: priority-queue heap-pop-while ( heap pred quot -- )
+    [ heap-pop ] swap [ t ] 3compose (heap-pop-while) ;
index b5955d01971a1a59c75d5bf87fbbb4f20c6b3374..91b4300d3253275159df1f1e6e56145da97ea302 100755 (executable)
@@ -221,7 +221,8 @@ TUPLE: column seq col ;
 C: <column> column
 
 M: column virtual-seq column-seq ;
-M: column virtual@ dup column-col -rot column-seq nth ;
+M: column virtual@
+    dup column-col -rot column-seq nth bounds-check ;
 M: column length column-seq length ;
 
 INSTANCE: column virtual-sequence
@@ -546,11 +547,6 @@ M: sequence <=>
 
 : all-eq? ( seq -- ? ) [ eq? ] monotonic? ;
 
-: flip ( matrix -- newmatrix )
-    dup empty? [
-        dup first length [ <column> dup like ] curry* map
-    ] unless ;
-
 : exchange ( m n seq -- )
     pick over bounds-check 2drop 2dup bounds-check 2drop
     exchange-unsafe ;
@@ -667,7 +663,19 @@ PRIVATE>
 : infimum ( seq -- n ) dup first [ min ] reduce ;
 : supremum ( seq -- n ) dup first [ max ] reduce ;
 
+: flip ( matrix -- newmatrix )
+    dup empty? [
+        dup [ length ] map infimum
+        [ <column> dup like ] curry* map
+    ] unless ;
+
+: sequence-hashcode-step ( oldhash newpart -- newhash )
+    swap [
+        dup -2 fixnum-shift >fixnum swap 5 fixnum-shift >fixnum
+        fixnum+fast fixnum+fast
+    ] keep bitxor ; inline
+
 : sequence-hashcode ( n seq -- x )
     0 -rot [
-        hashcode* >fixnum swap 31 fixnum*fast fixnum+fast
+        hashcode* >fixnum sequence-hashcode-step
     ] curry* each ; inline
index 04db98c9b2619d848d4ba0f97b466592aee12234..d8c8f5fbbab61c5feaf1fee8d855df413fa6b7cc 100644 (file)
@@ -9,7 +9,6 @@ ARTICLE: "slots" "Slots"
 $nl
 { $link "tuples" } " are composed entirely of slots, and instances of " { $link "builtin-classes" } " consist of slots together with intrinsic data."
 $nl
-"The " 
 "The " { $snippet "\"slots\"" } " word property of built-in and tuple classes holds an array of " { $emphasis "slot specifiers" } " describing the slot layout of each instance."
 { $subsection slot-spec }
 "Each slot has a reader word; mutable slots have an optional writer word. All tuple slots are mutable, but some slots on built-in classes are not."
diff --git a/extra/assoc-heaps/assoc-heaps-tests.factor b/extra/assoc-heaps/assoc-heaps-tests.factor
new file mode 100644 (file)
index 0000000..656e7fc
--- /dev/null
@@ -0,0 +1,46 @@
+USING: assocs assoc-heaps heaps heaps.private kernel tools.test ;
+IN: temporary
+
+[
+T{
+    assoc-heap
+    f
+    H{ { 2 1 } }
+    T{ min-heap T{ heap f V{ { 1 2 } } } }
+}
+] [ H{ } clone <assoc-min-heap> 1 2 pick heap-push ] unit-test
+
+[
+T{
+    assoc-heap
+    f
+    H{ { 1 0 } { 2 1 } }
+    T{ min-heap T{ heap f V{ { 0 1 } { 1 2 } } } }
+}
+] [  H{ } clone <assoc-min-heap> 1 2 pick heap-push 0 1 pick heap-push ] unit-test
+
+[ T{ assoc-heap f H{ } T{ min-heap T{ heap f V{ } } } } ]
+[
+    H{ } clone <assoc-min-heap>
+    1 2 pick heap-push 0 1 pick heap-push
+    dup heap-pop 2drop dup heap-pop 2drop
+] unit-test
+
+
+[ 0 1 ] [
+T{
+    assoc-heap
+    f
+    H{ { 1 0 } { 2 1 } }
+    T{ min-heap T{ heap f V{ { 0 1 } { 1 2 } } } }
+} heap-pop
+] unit-test
+
+[ 1 2 ] [
+T{
+    assoc-heap
+    f
+    H{ { 1 0 } { 2 1 } }
+    T{ max-heap T{ heap f V{ { 1 2 } { 0 1 } } } }
+} heap-pop
+] unit-test
diff --git a/extra/assoc-heaps/assoc-heaps.factor b/extra/assoc-heaps/assoc-heaps.factor
new file mode 100755 (executable)
index 0000000..a5471c2
--- /dev/null
@@ -0,0 +1,48 @@
+USING: assocs heaps kernel sequences ;
+IN: assoc-heaps
+
+TUPLE: assoc-heap assoc heap ;
+
+INSTANCE: assoc-heap assoc
+INSTANCE: assoc-heap priority-queue
+
+C: <assoc-heap> assoc-heap
+
+: <assoc-min-heap> ( assoc -- obj ) <min-heap> <assoc-heap> ;
+: <assoc-max-heap> ( assoc -- obj ) <max-heap> <assoc-heap> ;
+
+M: assoc-heap at* ( key assoc-heap -- value ? )
+    assoc-heap-assoc at* ;
+
+M: assoc-heap assoc-size ( assoc-heap -- n )
+    assoc-heap-assoc assoc-size ;
+
+TUPLE: assoc-heap-key-exists ;
+
+: check-key-exists ( key assoc-heap -- )
+    assoc-heap-assoc key?
+    [ \ assoc-heap-key-exists construct-empty throw ] when ;
+
+M: assoc-heap set-at ( value key assoc-heap -- )
+    [ check-key-exists ] 2keep
+    [ assoc-heap-assoc set-at ] 3keep
+    assoc-heap-heap swapd heap-push ;
+
+M: assoc-heap heap-empty? ( assoc-heap -- ? )
+    assoc-heap-assoc assoc-empty? ;
+
+M: assoc-heap heap-length ( assoc-heap -- n )
+    assoc-heap-assoc assoc-size ;
+
+M: assoc-heap heap-peek ( assoc-heap -- value key )
+    assoc-heap-heap heap-peek ;
+
+M: assoc-heap heap-push ( value key assoc-heap -- )
+    set-at ;
+
+M: assoc-heap heap-push-all ( assoc assoc-heap -- )
+    swap [ rot set-at ] curry* each ;
+
+M: assoc-heap heap-pop ( assoc-heap -- value key )
+    dup assoc-heap-heap heap-pop swap
+    rot dupd assoc-heap-assoc delete-at ;
index 01ef33b9221d34d598218524ca8b30be3e178597..dd9a77aa217a7575dd2b9df49f24597345a2357b 100644 (file)
@@ -1,4 +1,5 @@
 USING: delegate kernel arrays tools.test ;
+IN: temporary
 
 TUPLE: hello this that ;
 C: <hello> hello
index 9f39b33dc6fc63cda61762d83b0baa6fc0158cd2..f10e6481fa3b924c1c5d263dc791c14f075c43b1 100644 (file)
@@ -9,7 +9,7 @@ IN: faq
     over >r find r> rot 1+ tail ; inline
 
 : tag-named? ( tag name -- ? )
-    assure-name swap (get-tag) ;
+    assure-name swap tag-named? ;
 
 ! Questions
 TUPLE: q/a question answer ;
index 1c70c0c32516656739a0bf15c121818240f19a3f..ccb004581a5042671b7311161d35c22019568d2a 100755 (executable)
@@ -1,54 +1,54 @@
 ! Copyright (C) 2006 Chris Double. All Rights Reserved.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel tools.test parser-combinators lazy-lists fjsc ;
+USING: kernel tools.test peg fjsc ;
 IN: temporary
 
-{ T{ ast-expression f { T{ ast-number f 55 } T{ ast-identifier f "2abc1" } T{ ast-number f 100 } } } } [
-  "55 2abc1 100" 'expression' parse-1
+{ T{ ast-expression f V{ T{ ast-number f 55 } T{ ast-identifier f "2abc1" } T{ ast-number f 100 } } } } [
+  "55 2abc1 100" 'expression' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-quotation f { T{ ast-number f 55 } T{ ast-identifier f "2abc1" } T{ ast-number f 100 } } } } [
-  "[ 55 2abc1 100 ]" 'quotation' parse-1
+{ T{ ast-quotation f V{ T{ ast-number f 55 } T{ ast-identifier f "2abc1" } T{ ast-number f 100 } } } } [
+  "[ 55 2abc1 100 ]" 'quotation' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-array f { T{ ast-number f 55 } T{ ast-identifier f "2abc1" } T{ ast-number f 100 } } } } [
-  "{ 55 2abc1 100 }" 'array' parse-1
+{ T{ ast-array f V{ T{ ast-number f 55 } T{ ast-identifier f "2abc1" } T{ ast-number f 100 } } } } [
+  "{ 55 2abc1 100 }" 'array' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-stack-effect f { } { "d" "e" "f" } } } [
-  "( -- d e f )" 'stack-effect' parse-1
+{ T{ ast-stack-effect f V{ } V{ "d" "e" "f" } } } [
+  "( -- d e f )" 'stack-effect' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-stack-effect f { "a" "b" "c" } { "d" "e" "f" } } } [
-  "( a b c -- d e f )" 'stack-effect' parse-1
+{ T{ ast-stack-effect f V{ "a" "b" "c" } V{ "d" "e" "f" } } } [
+  "( a b c -- d e f )" 'stack-effect' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-stack-effect f { "a" "b" "c" } { } } } [
-  "( a b c -- )" 'stack-effect' parse-1
+{ T{ ast-stack-effect f V{ "a" "b" "c" } V{ } } } [
+  "( a b c -- )" 'stack-effect' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-stack-effect f { } { } } } [
-  "( -- )" 'stack-effect' parse-1
+{ T{ ast-stack-effect f V{ } V{ } } } [
+  "( -- )" 'stack-effect' parse parse-result-ast
 ] unit-test
 
-{ } [
-  ": foo ( a b -- c d ) abcdefghijklmn 123 ;" 'expression' parse car drop
+{ } [
+  ": foo ( a b -- c d ) abcdefghijklmn 123 ;" 'expression' parse not
 ] unit-test
 
 
-{ T{ ast-expression f { T{ ast-string f "abcd" } } } } [
-  "\"abcd\"" 'statement' parse-1
+{ T{ ast-expression f V{ T{ ast-string f "abcd" } } } } [
+  "\"abcd\"" 'statement' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-expression f { T{ ast-use f "foo" } } } } [
-  "USE: foo" 'statement' parse-1
+{ T{ ast-expression f V{ T{ ast-use f "foo" } } } } [
+  "USE: foo" 'statement' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-expression f { T{ ast-in f "foo" } } } } [
-  "IN: foo" 'statement' parse-1
+{ T{ ast-expression f V{ T{ ast-in f "foo" } } } } [
+  "IN: foo" 'statement' parse parse-result-ast
 ] unit-test
 
-{ T{ ast-expression f { T{ ast-using f { "foo" "bar" }  } } } } [
-  "USING: foo bar ;" 'statement' parse-1
+{ T{ ast-expression f V{ T{ ast-using f V{ "foo" "bar" }  } } } } [
+  "USING: foo bar ;" 'statement' parse parse-result-ast
 ] unit-test
 
index 22031afb25b79309ed7915e64046dfe01558ee46..fdeed339d8b376c135fe27c113445dba966bddeb 100755 (executable)
@@ -1,50 +1,38 @@
 ! Copyright (C) 2006 Chris Double. All Rights Reserved.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel lazy-lists parser-combinators  parser-combinators.simple
-       strings promises sequences math math.parser namespaces words
-       quotations arrays hashtables io io.streams.string assocs ;
+USING: kernel peg strings promises sequences math math.parser
+       namespaces words quotations arrays hashtables io
+       io.streams.string assocs memoize ;
 IN: fjsc
 
 TUPLE: ast-number value ;
-C: <ast-number> ast-number
-
 TUPLE: ast-identifier value vocab ;
-C: <ast-identifier> ast-identifier
-
 TUPLE: ast-string value ;
-C: <ast-string> ast-string
-
 TUPLE: ast-quotation values ;
-C: <ast-quotation> ast-quotation
-
 TUPLE: ast-array elements ;
-C: <ast-array> ast-array
-
 TUPLE: ast-define name stack-effect expression ;
-C: <ast-define> ast-define
-
 TUPLE: ast-expression values ;
-C: <ast-expression> ast-expression
-
 TUPLE: ast-word value vocab ;
-C: <ast-word> ast-word
-
 TUPLE: ast-comment ;
-C: <ast-comment> ast-comment
-
 TUPLE: ast-stack-effect in out ;
-C: <ast-stack-effect> ast-stack-effect
-
 TUPLE: ast-use name ;
-C: <ast-use> ast-use
-
 TUPLE: ast-using names ;
-C: <ast-using> ast-using
-
 TUPLE: ast-in name ;
-C: <ast-in> ast-in
-
 TUPLE: ast-hashtable elements ;
+
+C: <ast-number> ast-number
+C: <ast-identifier> ast-identifier
+C: <ast-string> ast-string
+C: <ast-quotation> ast-quotation
+C: <ast-array> ast-array
+C: <ast-define> ast-define
+C: <ast-expression> ast-expression
+C: <ast-word> ast-word
+C: <ast-comment> ast-comment
+C: <ast-stack-effect> ast-stack-effect
+C: <ast-use> ast-use
+C: <ast-using> ast-using
+C: <ast-in> ast-in
 C: <ast-hashtable> ast-hashtable
 
 : identifier-middle? ( ch -- bool )
@@ -56,7 +44,7 @@ C: <ast-hashtable> ast-hashtable
   digit? not
   and and and and and ;
 
-LAZY: 'identifier-ends' ( -- parser )
+MEMO: 'identifier-ends' ( -- parser )
   [
     [ blank? not ] keep
     [ CHAR: " = not ] keep
@@ -65,99 +53,137 @@ LAZY: 'identifier-ends' ( -- parser )
     [ letter? not ] keep
     identifier-middle? not
     and and and and and
-  ] satisfy <!*> ;
+  ] satisfy repeat0 ;
 
-LAZY: 'identifier-middle' ( -- parser )
-  [ identifier-middle? ] satisfy <!+> ;
+MEMO: 'identifier-middle' ( -- parser )
+  [ identifier-middle? ] satisfy repeat1 ;
 
-LAZY: 'identifier' ( -- parser )
-  'identifier-ends'
-  'identifier-middle' <&>
-  'identifier-ends' <:&>
-  [ concat >string f <ast-identifier> ] <@ ;
+MEMO: 'identifier' ( -- parser )
+  [
+    'identifier-ends' ,
+    'identifier-middle' ,
+    'identifier-ends' ,
+  ] { } make seq [
+    concat >string f <ast-identifier>
+  ] action ;
 
 
 DEFER: 'expression'
 
-LAZY: 'effect-name' ( -- parser )
+MEMO: 'effect-name' ( -- parser )
   [
     [ blank? not ] keep
+    [ CHAR: ) = not ] keep
     CHAR: - = not
-    and
-  ] satisfy <!+> [ >string ] <@ ;
-
-LAZY: 'stack-effect' ( -- parser )
-  "(" token sp
-  'effect-name' sp <*> &>
-  "--" token sp <&
-  'effect-name' sp <*> <&>
-  ")" token sp <& [ first2 <ast-stack-effect> ] <@ ;
-
-LAZY: 'define' ( -- parser )
-  ":" token sp
-  'identifier' sp [ ast-identifier-value ] <@ &>
-  'stack-effect' sp <!?> <&>
-  'expression' <:&>
-  ";" token sp <& [ first3 <ast-define> ] <@ ;
-
-LAZY: 'quotation' ( -- parser )
-  "[" token sp
-  'expression' [ ast-expression-values ] <@ &>
-  "]" token sp <& [ <ast-quotation> ] <@ ;
-
-LAZY: 'array' ( -- parser )
-  "{" token sp
-  'expression' [ ast-expression-values ] <@ &>
-  "}" token sp <& [ <ast-array> ] <@ ;
-
-LAZY: 'word' ( -- parser )
-  "\\" token sp
-  'identifier' sp &> [ ast-identifier-value f <ast-word> ] <@ ;
-
-LAZY: 'atom' ( -- parser )
-  'identifier' 'integer' [ <ast-number> ] <@ <|> 'string' [ <ast-string> ] <@ <|> ;
-
-LAZY: 'comment' ( -- parser )
-  "#!" token sp
-  "!" token sp <|> [
-    dup CHAR: \n = swap CHAR: \r = or not
-  ] satisfy <*> <&> [ drop <ast-comment> ] <@ ;
-
-LAZY: 'USE:' ( -- parser )
-  "USE:" token sp
-  'identifier' sp &> [ ast-identifier-value <ast-use> ] <@ ;
-
-LAZY: 'IN:' ( -- parser )
-  "IN:" token sp
-  'identifier' sp &> [ ast-identifier-value <ast-in> ] <@ ;
-
-LAZY: 'USING:' ( -- parser )
-  "USING:" token sp
-  'identifier' sp [ ast-identifier-value ] <@ <+> &>
-  ";" token sp <& [ <ast-using> ] <@ ;
-
-LAZY: 'hashtable' ( -- parser )
-  "H{" token sp
-  'expression' [ ast-expression-values ] <@ &>
-  "}" token sp <& [ <ast-hashtable> ] <@ ;
-
-LAZY: 'parsing-word' ( -- parser )
-  'USE:'
-  'USING:' <|>
-  'IN:' <|> ;
-
-LAZY: 'expression' ( -- parser )
-  'comment'
-  'parsing-word' sp <|>
-  'quotation' sp <|>
-  'define' sp <|>
-  'array' sp <|>
-  'hashtable' sp <|>
-  'word' sp <|>
-  'atom' sp <|>
-  <*> [ <ast-expression> ] <@ ;
-
-LAZY: 'statement' ( -- parser )
+    and and
+  ] satisfy repeat1 [ >string ] action ;
+
+MEMO: 'stack-effect' ( -- parser )
+  [
+    "(" token hide ,
+    'effect-name' sp repeat0 ,
+    "--" token sp hide ,
+    'effect-name' sp repeat0 ,
+    ")" token sp hide ,
+  ] { } make seq [
+    first2 <ast-stack-effect>
+  ] action ;
+
+MEMO: 'define' ( -- parser )
+  [
+    ":" token sp hide ,
+    'identifier' sp [ ast-identifier-value ] action ,
+    'stack-effect' sp optional ,
+    'expression' ,
+    ";" token sp hide ,
+  ] { } make seq [ first3 <ast-define> ] action ;
+
+MEMO: 'quotation' ( -- parser )
+  [
+    "[" token sp hide ,
+    'expression' [ ast-expression-values ] action ,
+    "]" token sp hide ,
+  ] { } make seq [ first <ast-quotation> ] action ;
+
+MEMO: 'array' ( -- parser )
+  [
+    "{" token sp hide ,
+    'expression' [ ast-expression-values ] action ,
+    "}" token sp hide ,
+  ] { } make seq [ first <ast-array> ] action ;
+
+MEMO: 'word' ( -- parser )
+  [
+    "\\" token sp hide ,
+    'identifier' sp ,
+  ] { } make seq [ first ast-identifier-value f <ast-word> ] action ;
+
+MEMO: 'atom' ( -- parser )
+  [
+    'identifier' ,
+    'integer' [ <ast-number> ] action ,
+    'string' [ <ast-string> ] action ,
+  ] { } make choice ;
+
+MEMO: 'comment' ( -- parser )
+  [
+    [
+      "#!" token sp ,
+      "!" token sp ,
+    ] { } make choice hide ,
+    [
+      dup CHAR: \n = swap CHAR: \r = or not
+    ] satisfy repeat0 ,
+  ] { } make seq [ drop <ast-comment> ] action ;
+
+MEMO: 'USE:' ( -- parser )
+  [
+    "USE:" token sp hide ,
+    'identifier' sp ,
+  ] { } make seq [ first ast-identifier-value <ast-use> ] action ;
+
+MEMO: 'IN:' ( -- parser )
+  [
+    "IN:" token sp hide ,
+    'identifier' sp ,
+  ] { } make seq [ first ast-identifier-value <ast-in> ] action ;
+
+MEMO: 'USING:' ( -- parser )
+  [
+    "USING:" token sp hide ,
+    'identifier' sp [ ast-identifier-value ] action repeat1 ,
+    ";" token sp hide ,
+  ] { } make seq [ first <ast-using> ] action ;
+
+MEMO: 'hashtable' ( -- parser )
+  [
+    "H{" token sp hide ,
+    'expression' [ ast-expression-values ] action ,
+    "}" token sp hide ,
+  ] { } make seq [ first <ast-hashtable> ] action ;
+
+MEMO: 'parsing-word' ( -- parser )
+  [
+    'USE:' ,
+    'USING:' ,
+    'IN:' ,
+  ] { } make choice ;
+
+MEMO: 'expression' ( -- parser )
+  [
+    [
+      'comment' ,
+      'parsing-word' sp ,
+      'quotation' sp ,
+      'define' sp ,
+      'array' sp ,
+      'hashtable' sp ,
+      'word' sp ,
+      'atom' sp ,
+    ] { } make choice repeat0 [ <ast-expression> ] action
+  ] delay ;
+
+MEMO: 'statement' ( -- parser )
   'expression' ;
 
 GENERIC: (compile) ( ast -- )
@@ -328,7 +354,7 @@ M: wrapper (parse-factor-quotation) ( object -- ast )
 GENERIC: fjsc-parse ( object -- ast )
 
 M: string fjsc-parse ( object -- ast )
-  'expression' parse-1 ;
+  'expression' parse parse-result-ast ;
 
 M: quotation fjsc-parse ( object -- ast )
   [
@@ -345,11 +371,11 @@ M: quotation fjsc-parse ( object -- ast )
   ] string-out ;
 
 : fjsc-compile* ( string -- string )
-  'statement' parse-1 fjsc-compile ;
+  'statement' parse parse-result-ast fjsc-compile ;
 
 : fc* ( string -- string )
   [
-  'statement' parse-1 ast-expression-values do-expressions
+  'statement' parse parse-result-ast ast-expression-values do-expressions
   ] { } make [ write ] each ;
 
 
index 13fef4aa57f7ee49eff34ac9c97728f9d76897a7..db63f15f1c15f3b4692701ea8de26276fd7af654 100644 (file)
@@ -3,10 +3,6 @@ USE: kernel-internals
 : bind ( ns quot -- )
   swap >n call n> drop ;
 
-: alert ( string -- )
-  #! Display the string in an alert box
-  window { } "" "alert" { "string" } alien-invoke ;
-
 "browser-dom" set-in
 
 : elements ( string -- result )
@@ -38,3 +34,6 @@ USE: kernel-internals
     drop "Click done!" alert 
   ] callcc0 ;
   
+: alert ( string -- )
+  #! Display the string in an alert box
+  window { } "" "alert" { "string" } alien-invoke ;
index 43d100ec733fcf35698fe5eb9b426ce4e121f153..032829c36318faec0b05d50ceab621bf67a4ccda 100644 (file)
@@ -513,6 +513,12 @@ factor.add_word("alien", "set-alien-property", "primitive", function(next) {
   factor.call_next(next);
 });
 
+factor.add_word("alien", "uneval", "primitive", function(next) {
+  var stack = factor.cont.data_stack;
+  stack.push(uneval(stack.pop()));
+  factor.call_next(next);
+});
+
 factor.add_word("words", "vocabs", "primitive", function(next) {   
   var stack = factor.cont.data_stack;
   var result = [];
diff --git a/extra/furnace/authors.txt b/extra/furnace/authors.txt
new file mode 100644 (file)
index 0000000..f372b57
--- /dev/null
@@ -0,0 +1,2 @@
+Slava Pestov
+Doug Coleman
index 85fc6c8727749f848b8b276ef72c92b4aa5734f5..6a14d40cde26173283db7f119b800ddd5ae9b404 100644 (file)
@@ -28,7 +28,7 @@ TUPLE: test-tuple m n ;
     [
         H{
             { "bar" "hello" }
-        } \ foo query>quot
+        } \ foo query>seq
     ] with-scope
 ] unit-test
 
index 756fa13d1c52acc5101131976389a0e58949febc..e745e28ad5d6f897e17c15d4d131dfe3416475f3 100644 (file)
@@ -1,48 +1,39 @@
-! Copyright (C) 2006 Slava Pestov
+! Copyright (C) 2006 Slava Pestov, Doug Coleman
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel vectors io assocs quotations splitting strings 
-       words sequences namespaces arrays hashtables debugger
-       continuations tuples classes io.files 
-       http http.server.templating http.basic-authentication 
-       webapps.callback html html.elements 
-       http.server.responders furnace.validator vocabs ;
+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 ;
+USING: continuations io prettyprint ;
 IN: furnace
 
-SYMBOL: default-action
+: code>quotation ( word/quot -- quot )
+    dup word? [ 1quotation ] when ;
 
+SYMBOL: default-action
 SYMBOL: template-path
 
-: define-authenticated-action ( word params realm -- )
-    pick swap "action-realm" set-word-prop
+: 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-action ( word params -- )
-    f define-authenticated-action ;
-
-: define-redirect ( word quot -- )
-    "action-redirect" set-word-prop ;
-
-: responder-vocab ( name -- vocab )
-    "webapps." swap append ;
+: define-form ( word1 word2 hash -- )
+    dupd define-action
+    swap code>quotation "form-failed" set-word-prop ;
 
-: lookup-action ( name webapp -- word )
-    responder-vocab lookup dup [
-        dup "action" word-prop [ drop f ] unless
-    ] when ;
-
-: truncate-url ( url -- action-name )
-  CHAR: / over index [ head ] when* ;
-
-: current-action ( url -- word/f )
-    dup empty? [ drop default-action get ] when
-    truncate-url "responder" get lookup-action ;
-
-PREDICATE: word action "action" word-prop ;
+: default-values ( word hash -- )
+    "default-values" set-word-prop ;
 
-: quot>query ( seq action -- hash )
-    >r >array r> "action-params" word-prop
-    [ first swap 2array ] 2map >hashtable ;
+SYMBOL: request-params
+SYMBOL: current-action
+SYMBOL: validators-errored
+SYMBOL: validation-errors
 
 : action-link ( query action -- url )
     [
@@ -52,6 +43,38 @@ PREDICATE: word action "action" word-prop ;
         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*
+    ] curry* map ;
+
+: expire-sessions ( -- )
+    sessions get-global
+    [ nip session-last-seen 20 minutes ago <=> 0 > ]
+    [ 2drop ] heap-pop-while ;
+
+: lookup-session ( hash -- session )
+    "furnace-session-id" over at sessions get-global at [
+        nip
+    ] [
+        new-session rot "furnace-session-id" swap 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 ;
 
@@ -64,62 +87,94 @@ PREDICATE: word action "action" word-prop ;
         t register-html-callback
     ] if ;
 
-: render-link ( quot name -- )
-    <a swap quot-link =href a> write </a> ;
+: replace-variables ( quot -- quot )
+    [ dup string? [ request-params session> at ] when ] map ;
 
-: action-param ( params paramspec -- obj error/f )
-    unclip rot at swap >quotation apply-validators ;
+: furnace-session-id ( -- hash )
+    "furnace-session-id" request-params session> at
+    "furnace-session-id" associate ;
 
-: query>quot ( params action -- seq )
-    "action-params" word-prop [ action-param drop ] curry* map ;
+: redirect-to-action ( -- )
+    current-action session>
+    "form-failed" word-prop replace-variables
+    quot-link furnace-session-id build-url permanent-redirect ;
 
-SYMBOL: request-params
+: if-form-page ( if then -- )
+    current-action session> "form-failed" word-prop -rot if ;
 
-: perform-redirect ( action -- )
-    "action-redirect" word-prop
-    [ dup string? [ request-params get at ] when ] map
-    [ quot-link permanent-redirect ] when* ;
+: do-action
+    current-action session> [ query>seq ] keep add >quotation call ;
 
-: (call-action) ( params action -- )
-    over request-params set
-    [ query>quot ] keep [ add >quotation call ] keep
-    perform-redirect ;
+: 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 ;
 
-: call-action ( params action -- )
-    dup "action-realm" word-prop [
-        [ (call-action) ] with-basic-authentication
-    ] [ (call-action) ] if* ;
+: 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 ;
 
-: service-request ( params url -- )
-    current-action [
+: 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 ( url -- ) "query" get swap service-request ;
-
-: service-post ( url -- ) "response" get swap service-request ;
-
-: send-resource ( name -- )
-    template-path get swap path+ resource-path <file-reader>
-    stdio get stream-copy ;
+: service-get
+    "query" get swap service-request ;
 
-: render-template ( template -- )
-    template-path get swap path+
-    ".furnace" append resource-path
-    run-template-file ;
+: service-post
+    "response" get swap service-request ;
 
-: web-app ( name default path -- )
+: web-app ( name defaul path -- )
     [
         template-path set
         default-action set
         "responder" set
         [ service-get ] "get" set
         [ service-post ] "post" set
-        ! [ service-head ] "head" set
     ] make-responder ;
 
+USING: classes html tuples vocabs ;
 : explode-tuple ( tuple -- )
     dup tuple-slots swap class "slot-names" word-prop
     [ set ] 2each ;
@@ -138,3 +193,24 @@ SYMBOL: model
     <a f >vocab-link 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/sessions.factor b/extra/furnace/sessions/sessions.factor
new file mode 100644 (file)
index 0000000..523598e
--- /dev/null
@@ -0,0 +1,40 @@
+USING: assoc-heaps assocs calendar crypto.sha2 heaps
+init kernel math.parser namespaces random ;
+IN: furnace.sessions
+
+SYMBOL: sessions
+
+[
+    H{ } clone <min-heap> <assoc-heap>
+    sessions set-global
+] "furnace.sessions" add-init-hook
+
+: new-session-id ( -- str )
+    4 big-random number>string string>sha-256-string
+    dup sessions get-global at [ drop new-session-id ] when ;
+
+TUPLE: session created last-seen user-agent namespace ;
+
+M: session <=> ( session1 session2 -- n )
+    [ session-last-seen ] 2apply <=> ;
+
+: <session> ( -- obj )
+    now dup H{ } clone
+    [ set-session-created set-session-last-seen set-session-namespace ]
+    \ session construct ;
+
+: new-session ( -- obj id )
+    <session> new-session-id [ sessions get-global set-at ] 2keep ;
+
+: get-session ( id -- obj/f )
+    sessions get-global at* [ "no session found 1" throw ] unless ;
+
+! Delete from the assoc only, the heap will timeout
+: destroy-session ( id -- )
+    sessions get-global assoc-heap-assoc delete-at ;
+
+: session> ( str -- obj )
+    session get session-namespace at ;
+
+: >session ( value key -- )
+    session get session-namespace set-at ;
index 06bad872befceaa3a763c03933033a66e743bbe6..6dee7d4be31a0c895771a865bb2c5fa5e436c3a7 100755 (executable)
@@ -1,13 +1,13 @@
 USING: tools.deploy.config ;
 H{
+    { deploy-c-types? f }
+    { deploy-ui? f }
+    { deploy-reflection 1 }
     { deploy-math? f }
-    { deploy-word-defs? f }
     { deploy-word-props? f }
+    { deploy-word-defs? f }
     { deploy-name "Hello world (console)" }
     { "stop-after-last-window?" t }
-    { deploy-c-types? f }
     { deploy-compiler? f }
     { deploy-io 2 }
-    { deploy-ui? f }
-    { deploy-reflection 1 }
 }
old mode 100644 (file)
new mode 100755 (executable)
index f6ea3d6..9e5d34f
@@ -60,11 +60,18 @@ IN: http
 : url-decode ( str -- str )
     [ 0 swap url-decode-iter ] "" make ;
 
-: build-url ( path query-params -- str )
+: hash>query ( hash -- str )
+    [ [ url-encode ] 2apply "=" swap 3append ] { } assoc>map
+    "&" join ;
+
+: build-url ( str query-params -- newstr )
     [
-        swap % dup assoc-empty? [
-            "?" % dup
-            [ [ url-encode ] 2apply "=" swap 3append ] { } assoc>map
-            "&" join %
-        ] unless drop
+        over %
+        dup assoc-empty? [
+            2drop
+        ] [
+            CHAR: ? rot member? "&" "?" ? %
+            hash>query %
+        ] if
     ] "" make ;
+
index d76e11287c5a054bab8436e390f65aca51c13344..cd587799c26bdb210f42a36c1bbd0059616422af 100755 (executable)
@@ -76,6 +76,7 @@ DEFER: <% delimiter
 : run-template-file ( filename -- )
     [
         [
+            "quiet" on
             file-vocabs
             parser-notes off
             templating-vocab use+
index 6d23bcac92115d3e04fd7e4752d4cacd9e4785d9..f6ba9ba80de7a7b51e0d2e480c95f7758fcc44a0 100644 (file)
@@ -1,2 +1,3 @@
 Chris Double
+Samuel Tardieu
 Matthew Willis
index e8acb397df319c27362e96aa19781a1e99d8f407..b66eb6367fc65973822b302a7943cbd7504acadb 100644 (file)
@@ -114,6 +114,16 @@ HELP: lsubset
 { $description "Perform a similar functionality to that of the " { $link subset } " word, but in a lazy manner. No evaluation of the list elements occurs initially but a " { $link <lazy-subset> } " object is returned which conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." } 
 { $see-also leach lmap lmap-with ltake lappend lfrom lfrom-by lconcat lcartesian-product lcartesian-product* lcomp lcomp* lmerge } ;
 
+HELP: lwhile
+{ $values { "list" "a cons object" } { "quot" "a quotation with stack effect ( X -- bool )" } { "result" "resulting cons object" } }
+{ $description "Outputs a lazy list containing the first items in the list as long as " { $snippet "quot" } " evaluates to t. No evaluation of the list elements occurs initially but a " { $link <lazy-while> } " object is returned with conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." }
+{ $see-also luntil } ;
+
+HELP: luntil
+{ $values { "list" "a cons object" } { "quot" "a quotation with stack effect ( X -- bool )" } { "result" "resulting cons object" } }
+{ $description "Outputs a lazy list containing the first items in the list until after " { $snippet "quot" } " evaluates to t. No evaluation of the list elements occurs initially but a " { $link <lazy-while> } " object is returned with conforms to the list protocol. Calling " { $link car } ", " { $link cdr } " or " { $link nil? } " on this will evaluate elements as required." }
+{ $see-also lwhile } ;
+
 HELP: list>vector
 { $values { "list" "a cons object" } { "vector" "the list converted to a vector" } }
 { $description "Convert a list to a vector. If the list is a lazy infinite list then this will enter an infinite loop." } 
index 2e3dc9154a25ab03fc1158adda9b0f38336fd1a4..1fb7a18cba1e863b31aecbe9cd3dc29a572b9e51 100644 (file)
@@ -100,11 +100,7 @@ M: lazy-cons list? ( object -- bool )
     dup car swap cdr ;
 
 : leach ( list quot -- )
-  swap dup nil? [
-    2drop
-  ] [
-    uncons swap pick call swap leach
-  ] if ;
+  swap dup nil? [ 2drop ] [ uncons swapd over 2slip leach ] if ; inline
 
 TUPLE: memoized-cons original car cdr nil? ;
 
@@ -210,6 +206,48 @@ M: lazy-take nil? ( lazy-take -- bool )
 M: lazy-take list? ( object -- bool )
   drop t ;
 
+TUPLE: lazy-until cons quot ;
+
+C: <lazy-until> lazy-until
+
+: luntil ( list quot -- result )
+  <lazy-until> ;
+
+M: lazy-until car ( lazy-until -- car )
+   lazy-until-cons car ;
+
+M: lazy-until cdr ( lazy-until -- cdr )
+   [ lazy-until-cons uncons ] keep lazy-until-quot
+   rot over call [ 2drop nil ] [ luntil ] if ;
+
+M: lazy-until nil? ( lazy-until -- bool )
+   lazy-until-cons nil? ;
+
+M: lazy-until list? ( lazy-until -- bool )
+   drop t ;
+
+TUPLE: lazy-while cons quot ;
+
+C: <lazy-while> lazy-while
+
+: lwhile ( list quot -- result )
+  <lazy-while>
+;
+
+M: lazy-while car ( lazy-while -- car )
+   lazy-while-cons car ;
+
+M: lazy-while cdr ( lazy-while -- cdr )
+   dup lazy-while-cons cdr dup nil?
+   [ 2drop nil ] [ swap lazy-while-quot lwhile ] if ;
+
+M: lazy-while nil? ( lazy-while -- bool )
+   dup lazy-while-cons nil?
+   [ nip ] [ [ car ] keep lazy-while-quot call not ] if* ;
+
+M: lazy-while list? ( lazy-while -- bool )
+   drop t ;
+
 TUPLE: lazy-subset cons quot ;
 
 C: <lazy-subset> lazy-subset
diff --git a/extra/math/erato/authors.txt b/extra/math/erato/authors.txt
new file mode 100644 (file)
index 0000000..f3b0233
--- /dev/null
@@ -0,0 +1 @@
+Samuel Tardieu
diff --git a/extra/math/erato/erato-docs.factor b/extra/math/erato/erato-docs.factor
new file mode 100644 (file)
index 0000000..6e84c84
--- /dev/null
@@ -0,0 +1,6 @@
+USING: help.markup help.syntax ;
+IN: math.erato
+
+HELP: lerato
+{ $values { "n" "a positive number" } { "lazy-list" "a lazy prime numbers generator" } }
+{ $description "Builds a lazy list containing the prime numbers between 2 and " { $snippet "n" } " (inclusive). Lazy lists are described in " { $link "lazy-lists" } "." } ;
diff --git a/extra/math/erato/erato-tests.factor b/extra/math/erato/erato-tests.factor
new file mode 100644 (file)
index 0000000..6e961b9
--- /dev/null
@@ -0,0 +1,6 @@
+! Copyright (c) 2007 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: lazy-lists math.erato tools.test ;
+IN: temporary
+
+[ { 2 3 5 7 11 13 17 19 } ] [ 20 lerato list>array ] unit-test
diff --git a/extra/math/erato/erato.factor b/extra/math/erato/erato.factor
new file mode 100644 (file)
index 0000000..4993f39
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (c) 2007 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: bit-arrays kernel lazy-lists math math.functions math.ranges sequences ;
+IN: math.erato
+
+<PRIVATE
+
+TUPLE: erato limit bits latest ;
+
+: ind ( n -- i )
+  2/ 1- ; inline
+
+: is-prime ( n erato -- bool )
+  >r ind r> erato-bits nth ; inline
+
+: indices ( n erato -- range )
+  erato-limit ind over 3 * ind swap rot <range> ;
+
+: mark-multiples ( n erato -- )
+  over sq over erato-limit <=
+  [ [ indices ] keep erato-bits [ f -rot set-nth ] curry each ] [ 2drop ] if ;
+
+: <erato> ( n -- erato )
+  dup ind 1+ <bit-array> 1 over set-bits erato construct-boa ;
+
+: next-prime ( erato -- prime/f )
+  [ erato-latest 2 + ] keep [ set-erato-latest ] 2keep
+  2dup erato-limit <=
+  [
+    2dup is-prime [ dupd mark-multiples ] [ nip next-prime ] if
+  ] [
+    2drop f
+  ] if ;
+
+PRIVATE>
+
+: lerato ( n -- lazy-list )
+  <erato> 2 [ drop next-prime ] curry* lfrom-by [ ] lwhile ;
diff --git a/extra/math/erato/summary.txt b/extra/math/erato/summary.txt
new file mode 100644 (file)
index 0000000..e8982fa
--- /dev/null
@@ -0,0 +1 @@
+Sieve of Eratosthene
diff --git a/extra/parser-combinators/replace/replace-docs.factor b/extra/parser-combinators/replace/replace-docs.factor
deleted file mode 100644 (file)
index fe73f5d..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-! Copyright (C) 2006 Chris Double.
-! See http://factorcode.org/license.txt for BSD license.
-USING: help.syntax help.markup parser-combinators
-parser-combinators.replace ;
-
-HELP: tree-write
-{ $values 
-  { "object" "an object" } }
-{ $description 
-    "Write the object to the standard output stream, unless "
-    "it is an array, in which case recurse through the array "
-    "writing each object to the stream." }
-{ $example "USE: parser-combinators" "{ 65 \"bc\" { 68 \"ef\" } } tree-write" "AbcDef" } ;
-
-HELP: search
-{ $values 
-  { "string" "a string" } 
-  { "parser" "a parser combinator based parser" } 
-  { "seq"    "a sequence" } 
-}
-{ $description 
-    "Returns a sequence containing the parse results of all substrings "
-    "from the input string that successfully parse using the "
-    "parser."
-}
-    
-{ $example "USE: parser-combinators" "\"one 123 two 456\" 'integer' search ." "{ 123 456 }" }
-{ $example "USE: parser-combinators" "\"one 123 \\\"hello\\\" two 456\" 'integer' 'string' <|> search ." "{ 123 \"hello\" 456 }" }
-{ $see-also search* replace replace* } ;
-
-HELP: search*
-{ $values 
-  { "string" "a string" } 
-  { "parsers" "a sequence of parser combinator based parsers" } 
-  { "seq"    "a sequence" } 
-}
-{ $description 
-    "Returns a sequence containing the parse results of all substrings "
-    "from the input string that successfully parse using any of the "
-    "parsers in the 'parsers' sequence."
-}
-    
-{ $example "USE: parser-combinators" "\"one 123 \\\"hello\\\" two 456\" 'integer' 'string' 2array search* ." "{ 123 \"hello\" 456 }" }
-{ $see-also search replace replace* } ;
-
-HELP: replace
-{ $values 
-  { "string" "a string" } 
-  { "parser" "a parser combinator based parser" } 
-  { "result"    "a string" } 
-}
-{ $description 
-    "Returns a copy of the original string but with all substrings that "
-    "successfully parse with the given parser replaced with "
-    "the result of that parser."
-}   
-{ $example "USING: parser-combinators math.parser ;" "\"one 123 two 456\" 'integer' [ 2 * number>string ] <@ replace ." "\"one 246 two 912\"" }
-{ $example "USE: parser-combinators" "\"hello *world* from *factor*\" 'bold' [ \"<strong>\" swap \"</strong>\" 3append ] <@ replace ." "\"hello <strong>world</strong> from <strong>factor</strong>\"" }
-{ $example "USE: parser-combinators" "\"hello *world* from _factor_\"\n 'bold' [ \"<strong>\" swap \"</strong>\" 3append ] <@\n 'italic' [ \"<emphasis>\" swap \"</emphasis>\" 3append ] <@ <|>\n replace ." "\"hello <strong>world</strong> from <emphasis>factor</emphasis>\"" }
-{ $see-also search search* replace* } ;
-
-HELP: replace*
-{ $values 
-  { "string" "a string" } 
-  { "parsers" "a sequence of parser combinator based parsers" } 
-  { "result"    "a string" } 
-}
-{ $description 
-    "Returns a copy of the original string but with all substrings that "
-    "successfully parse with the given parsers replaced with "
-    "the result of that parser. Each parser is done in sequence so that "
-    "the parse results of the first parser can be replaced by later parsers."
-}   
-{ $example "USE: parser-combinators" "\"*hello _world_*\"\n 'bold' [ \"<strong>\" swap \"</strong>\" 3append ] <@\n 'italic' [ \"<emphasis>\" swap \"</emphasis>\" 3append ] <@ 2array\n replace* ." "\"<strong>hello <emphasis>world</emphasis></strong>\"" }
-{ $see-also search search* replace* } ;
-
diff --git a/extra/parser-combinators/replace/replace.factor b/extra/parser-combinators/replace/replace.factor
deleted file mode 100755 (executable)
index 541bde7..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-! Copyright (C) 2006 Chris Double.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math io io.streams.string sequences strings
-lazy-lists combinators parser-combinators.simple ;
-IN: parser-combinators 
-
-: tree-write ( object -- )
-  { 
-    { [ dup number?   ] [ write1 ] }
-    { [ dup string?   ] [ write ] }
-    { [ dup sequence? ] [ [ tree-write ] each ] }
-    { [ t             ] [ write ] }
-  } cond ;
-
-: search ( string parser -- seq )
-  any-char-parser [ drop f ] <@ <|> <*> parse dup nil? [
-    drop { }
-  ] [
-    car parse-result-parsed [ ] subset 
-  ] if ;
-
-: search* ( string parsers -- seq )
-  unclip [ <|> ] reduce any-char-parser [ drop f ] <@ <|> <*> parse dup nil? [
-    drop { }
-  ] [
-    car parse-result-parsed [ ] subset 
-  ] if ;
-
-: (replace) ( string parser -- seq )
-  any-char-parser <|> <*> parse-1 ;
-
-: replace ( string parser -- result )
- [  (replace) [ tree-write ] each ] string-out ;
-
-: replace* ( string parsers -- result )
-  swap [ replace ] reduce ;
-
index c5b84d86c6917f151405ea3a0a70f5eef41cd29f..3b59068dd6bb9f534446f3c85925582ed9bb4fda 100755 (executable)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2006 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel strings math sequences lazy-lists words
-math.parser promises ;
-IN: parser-combinators 
+math.parser promises parser-combinators ;
+IN: parser-combinators.simple
 
 : 'digit' ( -- parser )
   [ digit? ] satisfy [ digit> ] <@ ;
diff --git a/extra/peg/ebnf/tags.txt b/extra/peg/ebnf/tags.txt
new file mode 100644 (file)
index 0000000..9da5688
--- /dev/null
@@ -0,0 +1 @@
+parsing
index 7fa1fb90e5e2eee1a379434bef364112614e7658..411a47b9bda592f0b80212aefb3cac2f71efcdce 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences strings namespaces math assocs shuffle 
-       vectors arrays combinators.lib memoize ;
+       vectors arrays combinators.lib memoize math.parser ;
 IN: peg
 
 TUPLE: parse-result remaining ast ;
@@ -265,3 +265,16 @@ MEMO: delay ( parser -- parser )
 
 MEMO: list-of ( items separator -- parser )
   hide over 2array seq repeat0 [ concat ] action 2array seq [ unclip 1vector swap first append ] action ;
+
+MEMO: 'digit' ( -- parser )
+  [ digit? ] satisfy [ digit> ] action ;
+
+MEMO: 'integer' ( -- parser )
+  'digit' repeat1 [ 10 swap digits>integer ] action ;
+
+MEMO: 'string' ( -- parser )
+  [
+    [ CHAR: " = ] satisfy hide ,
+    [ CHAR: " = not ] satisfy repeat0 ,
+    [ CHAR: " = ] satisfy hide ,
+  ] { } make seq [ first >string ] action ;
diff --git a/extra/peg/pl0/tags.txt b/extra/peg/pl0/tags.txt
new file mode 100644 (file)
index 0000000..9da5688
--- /dev/null
@@ -0,0 +1 @@
+parsing
diff --git a/extra/peg/search/authors.txt b/extra/peg/search/authors.txt
new file mode 100644 (file)
index 0000000..44b06f9
--- /dev/null
@@ -0,0 +1 @@
+Chris Double
diff --git a/extra/peg/search/search-docs.factor b/extra/peg/search/search-docs.factor
new file mode 100755 (executable)
index 0000000..244dc7f
--- /dev/null
@@ -0,0 +1,43 @@
+! Copyright (C) 2006 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.syntax help.markup peg peg.search ;
+
+HELP: tree-write
+{ $values
+  { "object" "an object" } }
+{ $description
+    "Write the object to the standard output stream, unless "
+    "it is an array, in which case recurse through the array "
+    "writing each object to the stream." }
+{ $example "{ 65 \"bc\" { 68 \"ef\" } } tree-write" "AbcDef" } ;
+
+HELP: search
+{ $values
+  { "string" "a string" }
+  { "parser" "a peg based parser" }
+  { "seq"    "a sequence" }
+}
+{ $description
+    "Returns a sequence containing the parse results of all substrings "
+    "from the input string that successfully parse using the "
+    "parser."
+}
+
+{ $example "\"one 123 two 456\" 'integer' search" "V{ 123 456 }" }
+{ $example "\"one 123 \\\"hello\\\" two 456\" 'integer' 'string' 2array choice search" "V{ 123 \"hello\" 456 }" }
+{ $see-also replace } ;
+
+HELP: replace
+{ $values
+  { "string" "a string" }
+  { "parser" "a peg based parser" }
+  { "result"    "a string" }
+}
+{ $description
+    "Returns a copy of the original string but with all substrings that "
+    "successfully parse with the given parser replaced with "
+    "the result of that parser."
+}
+{ $example "\"one 123 two 456\" 'integer' [ 2 * number>string ] action replace" "\"one 246 two 912\"" }
+{ $see-also search } ;
+
diff --git a/extra/peg/search/search-tests.factor b/extra/peg/search/search-tests.factor
new file mode 100755 (executable)
index 0000000..b33161d
--- /dev/null
@@ -0,0 +1,18 @@
+! 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 ;
+IN: temporary
+
+{ V{ 123 456 } } [
+  "abc 123 def 456" 'integer' search
+] unit-test
+
+{ V{ 123 "hello" 456 } } [
+  "one 123 \"hello\" two 456" 'integer' 'string' 2array choice search
+] unit-test
+
+{ "abc 246 def 912" } [
+  "abc 123 def 456" 'integer' [ 2 * number>string ] action replace
+] unit-test
+
diff --git a/extra/peg/search/search.factor b/extra/peg/search/search.factor
new file mode 100755 (executable)
index 0000000..6b34c03
--- /dev/null
@@ -0,0 +1,32 @@
+! Copyright (C) 2006 Chris Double.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math io io.streams.string sequences strings
+combinators peg memoize arrays ;
+IN: peg.search
+
+: tree-write ( object -- )
+  {
+    { [ dup number?   ] [ write1 ] }
+    { [ dup string?   ] [ write ] }
+    { [ dup sequence? ] [ [ tree-write ] each ] }
+    { [ t             ] [ write ] }
+  } cond ;
+
+MEMO: any-char-parser ( -- parser )
+  [ drop t ] satisfy ;
+
+: search ( string parser -- seq )
+  any-char-parser [ drop f ] action 2array choice repeat0 parse dup [
+    parse-result-ast [ ] subset
+  ] [
+    drop { }
+  ] if ;
+
+
+: (replace) ( string parser -- seq )
+  any-char-parser 2array choice repeat0 parse parse-result-ast [ ] subset ;
+
+: replace ( string parser -- result )
+ [  (replace) [ tree-write ] each ] string-out ;
+
+
diff --git a/extra/peg/search/summary.txt b/extra/peg/search/summary.txt
new file mode 100644 (file)
index 0000000..ad27ade
--- /dev/null
@@ -0,0 +1 @@
+Search and replace using parsing expression grammars
diff --git a/extra/peg/search/tags.txt b/extra/peg/search/tags.txt
new file mode 100644 (file)
index 0000000..9da5688
--- /dev/null
@@ -0,0 +1 @@
+parsing
diff --git a/extra/peg/tags.txt b/extra/peg/tags.txt
new file mode 100644 (file)
index 0000000..9da5688
--- /dev/null
@@ -0,0 +1 @@
+parsing
diff --git a/extra/project-euler/001/001.factor b/extra/project-euler/001/001.factor
new file mode 100644 (file)
index 0000000..7d77e86
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.ranges sequences ;
+IN: project-euler.001
+
+! http://projecteuler.net/index.php?section=problems&id=1
+
+! DESCRIPTION
+! -----------
+
+! If we list all the natural numbers below 10 that are multiples of 3 or 5, we
+! get 3, 5, 6 and 9. The sum of these multiples is 23.
+
+! Find the sum of all the multiples of 3 or 5 below 1000.
+
+
+! SOLUTION
+! --------
+
+! Inclusion-exclusion principle
+
+: euler001 ( -- answer )
+    0 999 3 <range> sum 0 999 5 <range> sum + 0 999 15 <range> sum - ;
+
+! [ euler001 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+
+! ALTERNATE SOLUTIONS
+! -------------------
+
+: euler001a ( -- answer )
+    1000 [ dup 5 mod swap 3 mod [ zero? ] either? ] subset sum ;
+
+! [ euler001a ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler001
diff --git a/extra/project-euler/002/002.factor b/extra/project-euler/002/002.factor
new file mode 100644 (file)
index 0000000..386d847
--- /dev/null
@@ -0,0 +1,34 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math sequences ;
+IN: project-euler.002
+
+! http://projecteuler.net/index.php?section=problems&id=2
+
+! DESCRIPTION
+! -----------
+
+! Each new term in the Fibonacci sequence is generated by adding the previous
+! two terms. By starting with 1 and 2, the first 10 terms will be:
+
+!     1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
+
+! Find the sum of all the even-valued terms in the sequence which do not exceed one million.
+
+
+! SOLUTION
+! --------
+
+: last2 ( seq -- elt last )
+    reverse first2 swap ;
+
+: fib-up-to ( n -- seq )
+    { 0 } 1 [ pick dupd < ] [ add dup last2 + ] [ ] while drop nip ;
+
+: euler002 ( -- answer )
+    1000000 fib-up-to [ even? ] subset sum ;
+
+! [ euler002 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler002
diff --git a/extra/project-euler/003/003.factor b/extra/project-euler/003/003.factor
new file mode 100644 (file)
index 0000000..87db922
--- /dev/null
@@ -0,0 +1,28 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math project-euler.common sequences ;
+IN: project-euler.003
+
+! http://projecteuler.net/index.php?section=problems&id=3
+
+! DESCRIPTION
+! -----------
+
+! The prime factors of 13195 are 5, 7, 13 and 29.
+
+! What is the largest prime factor of the number 317584931803?
+
+
+! SOLUTION
+! --------
+
+: largest-prime-factor ( n -- factor )
+    prime-factors supremum ;
+
+: euler003 ( -- answer )
+    317584931803 largest-prime-factor ;
+
+! [ euler003 ] 100 ave-time
+! 404 ms run / 9 ms GC ave time - 100 trials
+
+MAIN: euler003
diff --git a/extra/project-euler/004/004.factor b/extra/project-euler/004/004.factor
new file mode 100644 (file)
index 0000000..dadde25
--- /dev/null
@@ -0,0 +1,41 @@
+! Copyright (c) 2007 Aaron Schaefer, Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays combinators.lib hashtables kernel math math.parser math.ranges
+    sequences sorting ;
+IN: project-euler.004
+
+! http://projecteuler.net/index.php?section=problems&id=4
+
+! DESCRIPTION
+! -----------
+
+! A palindromic number reads the same both ways. The largest palindrome made
+! from the product of two 2-digit numbers is 9009 = 91 * 99.
+
+! Find the largest palindrome made from the product of two 3-digit numbers.
+
+
+! SOLUTION
+! --------
+
+: palindrome? ( n -- ? )
+    number>string dup reverse = ;
+
+: cartesian-product ( seq1 seq2 -- seq1xseq2 )
+    swap [ swap [ 2array ] map-with ] map-with concat ;
+
+<PRIVATE
+
+: max-palindrome ( seq -- palindrome )
+    natural-sort [ palindrome? ] find-last nip ;
+
+PRIVATE>
+
+: euler004 ( -- answer )
+    100 999 [a,b] [ 10 mod zero? not ] subset dup
+    cartesian-product [ product ] map prune max-palindrome ;
+
+! [ euler004 ] 100 ave-time
+! 1608 ms run / 102 ms GC ave time - 100 trials
+
+MAIN: euler004
diff --git a/extra/project-euler/005/005.factor b/extra/project-euler/005/005.factor
new file mode 100644 (file)
index 0000000..ff627e4
--- /dev/null
@@ -0,0 +1,26 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions sequences ;
+IN: project-euler.005
+
+! http://projecteuler.net/index.php?section=problems&id=5
+
+! DESCRIPTION
+! -----------
+
+! 2520 is the smallest number that can be divided by each of the numbers from 1
+! to 10 without any remainder.
+
+! What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?
+
+
+! SOLUTION
+! --------
+
+: euler005 ( -- answer )
+    20 1 [ 1+ lcm ] reduce ;
+
+! [ euler005 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler005
diff --git a/extra/project-euler/006/006.factor b/extra/project-euler/006/006.factor
new file mode 100644 (file)
index 0000000..2f09912
--- /dev/null
@@ -0,0 +1,39 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions math.ranges sequences ;
+IN: project-euler.006
+
+! http://projecteuler.net/index.php?section=problems&id=6
+
+! DESCRIPTION
+! -----------
+
+! The sum of the squares of the first ten natural numbers is,
+!     1² + 2² + ... + 10² = 385
+
+! The square of the sum of the first ten natural numbers is,
+!    (1 + 2 + ... + 10)² = 55² = 3025
+
+! Hence the difference between the sum of the squares of the first ten natural
+! numbers and the square of the sum is 3025 385 = 2640.
+
+! Find the difference between the sum of the squares of the first one hundred
+! natural numbers and the square of the sum.
+
+
+! SOLUTION
+! --------
+
+: sum-of-squares ( seq -- n )
+    0 [ sq + ] reduce ;
+
+: square-of-sums ( seq -- n )
+    0 [ + ] reduce sq ;
+
+: euler006 ( -- answer )
+    1 100 [a,b] dup sum-of-squares swap square-of-sums - abs ;
+
+! [ euler006 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler006
diff --git a/extra/project-euler/007/007.factor b/extra/project-euler/007/007.factor
new file mode 100644 (file)
index 0000000..0a9cd98
--- /dev/null
@@ -0,0 +1,29 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.miller-rabin ;
+IN: project-euler.007
+
+! http://projecteuler.net/index.php?section=problems&id=7
+
+! DESCRIPTION
+! -----------
+
+! By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see
+! that the 6th prime is 13.
+
+! What is the 10001st prime number?
+
+
+! SOLUTION
+! --------
+
+: nth-prime ( n -- n )
+    2 swap 1- [ next-prime ] times ;
+
+: euler007 ( -- answer )
+    10001 nth-prime ;
+
+! [ euler007 ] time
+! 19230 ms run / 487 ms GC time
+
+MAIN: euler007
diff --git a/extra/project-euler/008/008.factor b/extra/project-euler/008/008.factor
new file mode 100644 (file)
index 0000000..d76f344
--- /dev/null
@@ -0,0 +1,72 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math.parser project-euler.common sequences ;
+IN: project-euler.008
+
+! http://projecteuler.net/index.php?section=problems&id=8
+
+! DESCRIPTION
+! -----------
+
+! Find the greatest product of five consecutive digits in the 1000-digit number.
+
+!     73167176531330624919225119674426574742355349194934
+!     96983520312774506326239578318016984801869478851843
+!     85861560789112949495459501737958331952853208805511
+!     12540698747158523863050715693290963295227443043557
+!     66896648950445244523161731856403098711121722383113
+!     62229893423380308135336276614282806444486645238749
+!     30358907296290491560440772390713810515859307960866
+!     70172427121883998797908792274921901699720888093776
+!     65727333001053367881220235421809751254540594752243
+!     52584907711670556013604839586446706324415722155397
+!     53697817977846174064955149290862569321978468622482
+!     83972241375657056057490261407972968652414535100474
+!     82166370484403199890008895243450658541227588666881
+!     16427171479924442928230863465674813919123162824586
+!     17866458359124566529476545682848912883142607690042
+!     24219022671055626321111109370544217506941658960408
+!     07198403850962455444362981230987879927244284909188
+!     84580156166097919133875499200524063689912560717606
+!     05886116467109405077541002256983155200055935729725
+!     71636269561882670428252483600823257530420752963450
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: source-008 ( -- str )
+    {
+        "73167176531330624919225119674426574742355349194934"
+        "96983520312774506326239578318016984801869478851843"
+        "85861560789112949495459501737958331952853208805511"
+        "12540698747158523863050715693290963295227443043557"
+        "66896648950445244523161731856403098711121722383113"
+        "62229893423380308135336276614282806444486645238749"
+        "30358907296290491560440772390713810515859307960866"
+        "70172427121883998797908792274921901699720888093776"
+        "65727333001053367881220235421809751254540594752243"
+        "52584907711670556013604839586446706324415722155397"
+        "53697817977846174064955149290862569321978468622482"
+        "83972241375657056057490261407972968652414535100474"
+        "82166370484403199890008895243450658541227588666881"
+        "16427171479924442928230863465674813919123162824586"
+        "17866458359124566529476545682848912883142607690042"
+        "24219022671055626321111109370544217506941658960408"
+        "07198403850962455444362981230987879927244284909188"
+        "84580156166097919133875499200524063689912560717606"
+        "05886116467109405077541002256983155200055935729725"
+        "71636269561882670428252483600823257530420752963450"
+    } concat ;
+
+PRIVATE>
+
+: euler008 ( -- answer )
+    source-008 5 collect-consecutive [ string>digits product ] map supremum ;
+
+! [ euler008 ] 100 ave-time
+! 11 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler008
diff --git a/extra/project-euler/009/009.factor b/extra/project-euler/009/009.factor
new file mode 100644 (file)
index 0000000..4456914
--- /dev/null
@@ -0,0 +1,55 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions namespaces sequences sorting ;
+IN: project-euler.009
+
+! http://projecteuler.net/index.php?section=problems&id=9
+
+! DESCRIPTION
+! -----------
+
+! A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
+!     a² + b² = c²
+
+! For example, 3² + 4² = 9 + 16 = 25 = 5².
+
+! There exists exactly one Pythagorean triplet for which a + b + c = 1000.
+! Find the product abc.
+
+
+! SOLUTION
+! --------
+
+! Algorithm adapted from http://www.friesian.com/pythag.com
+
+<PRIVATE
+
+: next-pq ( p1 q1 -- p2 q2 )
+    ! p > q and both are odd integers
+    dup 1 = [ swap 2 + nip dup 2 - ] [ 2 - ] if ;
+
+: abc ( p q -- triplet )
+    [
+        2dup * ,                      ! a = p * q
+        2dup sq swap sq swap - 2 / ,  ! b = (p² - q²) / 2
+        sq swap sq swap + 2 / ,       ! c = (p² + q²) / 2
+    ] { } make natural-sort ;
+
+: (ptriplet) ( target p q triplet -- target p q )
+    roll dup >r swap sum = r> -roll
+    [
+        next-pq 2dup abc (ptriplet)
+    ] unless ;
+
+: ptriplet ( target -- triplet )
+   3 1 { 3 4 5 } (ptriplet) abc nip ;
+
+PRIVATE>
+
+: euler009 ( -- answer )
+    1000 ptriplet product ;
+
+! [ euler009 ] 100 ave-time
+! 1 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler009
diff --git a/extra/project-euler/010/010.factor b/extra/project-euler/010/010.factor
new file mode 100644 (file)
index 0000000..7518eb2
--- /dev/null
@@ -0,0 +1,31 @@
+! Copyright (c) 2007 Aaron Schaefer, Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays kernel lazy-lists math math.erato math.functions math.ranges
+       namespaces sequences ;
+IN: project-euler.010
+
+! http://projecteuler.net/index.php?section=problems&id=10
+
+! DESCRIPTION
+! -----------
+
+! The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
+
+! Find the sum of all the primes below one million.
+
+
+! SOLUTION
+! --------
+
+! Sieve of Eratosthenes and lazy summing
+
+: euler010 ( -- answer )
+    0 1000000 lerato [ + ] leach ;
+
+! TODO: solution is still too slow for 1000000, probably due to seq-diff
+! calling member? for each number that we want to remove
+
+! [ euler010 ] time
+! 765 ms run / 7 ms GC time
+
+MAIN: euler010
diff --git a/extra/project-euler/011/011.factor b/extra/project-euler/011/011.factor
new file mode 100644 (file)
index 0000000..9739ee9
--- /dev/null
@@ -0,0 +1,107 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel namespaces project-euler.common sequences ;
+IN: project-euler.011
+
+! http://projecteuler.net/index.php?section=problems&id=11
+
+! DESCRIPTION
+! -----------
+
+! In the 20x20 grid below, four numbers along a diagonal line have been marked
+! in red.
+
+!     08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
+!     49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
+!     81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
+!     52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
+!     22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
+!     24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
+!     32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
+!     67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
+!     24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
+!     21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
+!     78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
+!     16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
+!     86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
+!     19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
+!     04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
+!     88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
+!     04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
+!     20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
+!     20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
+!     01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
+
+! The product of these numbers is 26 * 63 * 78 * 14 = 1788696.
+
+! What is the greatest product of four numbers in any direction (up, down,
+! left, right, or diagonally) in the 20x20 grid?
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: horizontal ( -- matrix )
+    {
+        { 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 }
+        { 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 }
+        { 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 }
+        { 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 }
+        { 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 }
+        { 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 }
+        { 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 }
+        { 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 }
+        { 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 }
+        { 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 }
+        { 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 }
+        { 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 }
+        { 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 }
+        { 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 }
+        { 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 }
+        { 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 }
+        { 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 }
+        { 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 }
+        { 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 }
+        { 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48 }
+    } ;
+
+: vertical ( -- matrix )
+    horizontal flip ;
+
+: pad-front ( matrix -- matrix )
+    [
+        length [ 0 <repetition> ] each
+    ] keep [ append ] map ;
+
+: pad-back ( matrix -- matrix )
+    <reversed> [
+        length [ 0 <repetition> ] each
+    ] keep [ <reversed> append ] map ;
+
+: diagonal/ ( -- matrix )
+    horizontal reverse pad-front pad-back flip ;
+
+: diagonal\ ( -- matrix )
+    horizontal pad-front pad-back flip ;
+
+: max-product ( matrix width -- n )
+    [ collect-consecutive ] curry map concat
+    [ product ] map supremum ; inline
+
+PRIVATE>
+
+: euler011 ( -- answer )
+    [
+        { [ horizontal ] [ vertical ] [ diagonal/ ] [ diagonal\ ] }
+        [ call 4 max-product , ] each
+    ] { } make supremum ;
+
+! TODO: solution works but doesn't completely compile due to the creation of
+! the diagonal matrices, there must be a cleaner way to generate those
+
+! [ euler011 ] 100 ave-time
+! 4 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler011
diff --git a/extra/project-euler/012/012.factor b/extra/project-euler/012/012.factor
new file mode 100644 (file)
index 0000000..0d0d416
--- /dev/null
@@ -0,0 +1,45 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math project-euler.common ;
+IN: project-euler.012
+
+! http://projecteuler.net/index.php?section=problems&id=12
+
+! DESCRIPTION
+! -----------
+
+! The sequence of triangle numbers is generated by adding the natural numbers.
+! So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first
+! ten terms would be:
+
+!     1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
+
+! Let us list the factors of the first seven triangle numbers:
+
+!      1: 1
+!      3: 1,3
+!      6: 1,2,3,6
+!     10: 1,2,5,10
+!     15: 1,3,5,15
+!     21: 1,3,7,21
+!     28: 1,2,4,7,14,28
+
+! We can see that the 7th triangle number, 28, is the first triangle number to
+! have over five divisors.
+
+! Which is the first triangle number to have over five-hundred divisors?
+
+
+! SOLUTION
+! --------
+
+: nth-triangle ( n -- n )
+    dup 1+ * 2 / ;
+
+: euler012 ( -- answer )
+    2 [ dup nth-triangle tau* 500 < ] [ 1+ ] [ ] while nth-triangle ;
+
+! [ euler012 ] 10 ave-time
+! 5413 ms run / 1 ms GC ave time - 10 trials
+
+MAIN: euler012
diff --git a/extra/project-euler/013/013.factor b/extra/project-euler/013/013.factor
new file mode 100644 (file)
index 0000000..be968fc
--- /dev/null
@@ -0,0 +1,233 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math.parser sequences ;
+IN: project-euler.013
+
+! http://projecteuler.net/index.php?section=problems&id=13
+
+! DESCRIPTION
+! -----------
+
+! Work out the first ten digits of the sum of the following one-hundred
+! 50-digit numbers.
+
+!     37107287533902102798797998220837590246510135740250
+!     46376937677490009712648124896970078050417018260538
+!     74324986199524741059474233309513058123726617309629
+!     91942213363574161572522430563301811072406154908250
+!     23067588207539346171171980310421047513778063246676
+!     89261670696623633820136378418383684178734361726757
+!     28112879812849979408065481931592621691275889832738
+!     44274228917432520321923589422876796487670272189318
+!     47451445736001306439091167216856844588711603153276
+!     70386486105843025439939619828917593665686757934951
+!     62176457141856560629502157223196586755079324193331
+!     64906352462741904929101432445813822663347944758178
+!     92575867718337217661963751590579239728245598838407
+!     58203565325359399008402633568948830189458628227828
+!     80181199384826282014278194139940567587151170094390
+!     35398664372827112653829987240784473053190104293586
+!     86515506006295864861532075273371959191420517255829
+!     71693888707715466499115593487603532921714970056938
+!     54370070576826684624621495650076471787294438377604
+!     53282654108756828443191190634694037855217779295145
+!     36123272525000296071075082563815656710885258350721
+!     45876576172410976447339110607218265236877223636045
+!     17423706905851860660448207621209813287860733969412
+!     81142660418086830619328460811191061556940512689692
+!     51934325451728388641918047049293215058642563049483
+!     62467221648435076201727918039944693004732956340691
+!     15732444386908125794514089057706229429197107928209
+!     55037687525678773091862540744969844508330393682126
+!     18336384825330154686196124348767681297534375946515
+!     80386287592878490201521685554828717201219257766954
+!     78182833757993103614740356856449095527097864797581
+!     16726320100436897842553539920931837441497806860984
+!     48403098129077791799088218795327364475675590848030
+!     87086987551392711854517078544161852424320693150332
+!     59959406895756536782107074926966537676326235447210
+!     69793950679652694742597709739166693763042633987085
+!     41052684708299085211399427365734116182760315001271
+!     65378607361501080857009149939512557028198746004375
+!     35829035317434717326932123578154982629742552737307
+!     94953759765105305946966067683156574377167401875275
+!     88902802571733229619176668713819931811048770190271
+!     25267680276078003013678680992525463401061632866526
+!     36270218540497705585629946580636237993140746255962
+!     24074486908231174977792365466257246923322810917141
+!     91430288197103288597806669760892938638285025333403
+!     34413065578016127815921815005561868836468420090470
+!     23053081172816430487623791969842487255036638784583
+!     11487696932154902810424020138335124462181441773470
+!     63783299490636259666498587618221225225512486764533
+!     67720186971698544312419572409913959008952310058822
+!     95548255300263520781532296796249481641953868218774
+!     76085327132285723110424803456124867697064507995236
+!     37774242535411291684276865538926205024910326572967
+!     23701913275725675285653248258265463092207058596522
+!     29798860272258331913126375147341994889534765745501
+!     18495701454879288984856827726077713721403798879715
+!     38298203783031473527721580348144513491373226651381
+!     34829543829199918180278916522431027392251122869539
+!     40957953066405232632538044100059654939159879593635
+!     29746152185502371307642255121183693803580388584903
+!     41698116222072977186158236678424689157993532961922
+!     62467957194401269043877107275048102390895523597457
+!     23189706772547915061505504953922979530901129967519
+!     86188088225875314529584099251203829009407770775672
+!     11306739708304724483816533873502340845647058077308
+!     82959174767140363198008187129011875491310547126581
+!     97623331044818386269515456334926366572897563400500
+!     42846280183517070527831839425882145521227251250327
+!     55121603546981200581762165212827652751691296897789
+!     32238195734329339946437501907836945765883352399886
+!     75506164965184775180738168837861091527357929701337
+!     62177842752192623401942399639168044983993173312731
+!     32924185707147349566916674687634660915035914677504
+!     99518671430235219628894890102423325116913619626622
+!     73267460800591547471830798392868535206946944540724
+!     76841822524674417161514036427982273348055556214818
+!     97142617910342598647204516893989422179826088076852
+!     87783646182799346313767754307809363333018982642090
+!     10848802521674670883215120185883543223812876952786
+!     71329612474782464538636993009049310363619763878039
+!     62184073572399794223406235393808339651327408011116
+!     66627891981488087797941876876144230030984490851411
+!     60661826293682836764744779239180335110989069790714
+!     85786944089552990653640447425576083659976645795096
+!     66024396409905389607120198219976047599490197230297
+!     64913982680032973156037120041377903785566085089252
+!     16730939319872750275468906903707539413042652315011
+!     94809377245048795150954100921645863754710598436791
+!     78639167021187492431995700641917969777599028300699
+!     15368713711936614952811305876380278410754449733078
+!     40789923115535562561142322423255033685442488917353
+!     44889911501440648020369068063960672322193204149535
+!     41503128880339536053299340368006977710650566631954
+!     81234880673210146739058568557934581403627822703280
+!     82616570773948327592232845941706525094512325230608
+!     22918802058777319719839450180888072429661980811197
+!     77158542502016545090413245809786882778948721859617
+!     72107838435069186155435662884062257473692284509516
+!     20849603980134001723930671666823555245252804609722
+!     53503534226472524250874054075591789781264330331690
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: source-013 ( -- seq )
+    {
+        37107287533902102798797998220837590246510135740250
+        46376937677490009712648124896970078050417018260538
+        74324986199524741059474233309513058123726617309629
+        91942213363574161572522430563301811072406154908250
+        23067588207539346171171980310421047513778063246676
+        89261670696623633820136378418383684178734361726757
+        28112879812849979408065481931592621691275889832738
+        44274228917432520321923589422876796487670272189318
+        47451445736001306439091167216856844588711603153276
+        70386486105843025439939619828917593665686757934951
+        62176457141856560629502157223196586755079324193331
+        64906352462741904929101432445813822663347944758178
+        92575867718337217661963751590579239728245598838407
+        58203565325359399008402633568948830189458628227828
+        80181199384826282014278194139940567587151170094390
+        35398664372827112653829987240784473053190104293586
+        86515506006295864861532075273371959191420517255829
+        71693888707715466499115593487603532921714970056938
+        54370070576826684624621495650076471787294438377604
+        53282654108756828443191190634694037855217779295145
+        36123272525000296071075082563815656710885258350721
+        45876576172410976447339110607218265236877223636045
+        17423706905851860660448207621209813287860733969412
+        81142660418086830619328460811191061556940512689692
+        51934325451728388641918047049293215058642563049483
+        62467221648435076201727918039944693004732956340691
+        15732444386908125794514089057706229429197107928209
+        55037687525678773091862540744969844508330393682126
+        18336384825330154686196124348767681297534375946515
+        80386287592878490201521685554828717201219257766954
+        78182833757993103614740356856449095527097864797581
+        16726320100436897842553539920931837441497806860984
+        48403098129077791799088218795327364475675590848030
+        87086987551392711854517078544161852424320693150332
+        59959406895756536782107074926966537676326235447210
+        69793950679652694742597709739166693763042633987085
+        41052684708299085211399427365734116182760315001271
+        65378607361501080857009149939512557028198746004375
+        35829035317434717326932123578154982629742552737307
+        94953759765105305946966067683156574377167401875275
+        88902802571733229619176668713819931811048770190271
+        25267680276078003013678680992525463401061632866526
+        36270218540497705585629946580636237993140746255962
+        24074486908231174977792365466257246923322810917141
+        91430288197103288597806669760892938638285025333403
+        34413065578016127815921815005561868836468420090470
+        23053081172816430487623791969842487255036638784583
+        11487696932154902810424020138335124462181441773470
+        63783299490636259666498587618221225225512486764533
+        67720186971698544312419572409913959008952310058822
+        95548255300263520781532296796249481641953868218774
+        76085327132285723110424803456124867697064507995236
+        37774242535411291684276865538926205024910326572967
+        23701913275725675285653248258265463092207058596522
+        29798860272258331913126375147341994889534765745501
+        18495701454879288984856827726077713721403798879715
+        38298203783031473527721580348144513491373226651381
+        34829543829199918180278916522431027392251122869539
+        40957953066405232632538044100059654939159879593635
+        29746152185502371307642255121183693803580388584903
+        41698116222072977186158236678424689157993532961922
+        62467957194401269043877107275048102390895523597457
+        23189706772547915061505504953922979530901129967519
+        86188088225875314529584099251203829009407770775672
+        11306739708304724483816533873502340845647058077308
+        82959174767140363198008187129011875491310547126581
+        97623331044818386269515456334926366572897563400500
+        42846280183517070527831839425882145521227251250327
+        55121603546981200581762165212827652751691296897789
+        32238195734329339946437501907836945765883352399886
+        75506164965184775180738168837861091527357929701337
+        62177842752192623401942399639168044983993173312731
+        32924185707147349566916674687634660915035914677504
+        99518671430235219628894890102423325116913619626622
+        73267460800591547471830798392868535206946944540724
+        76841822524674417161514036427982273348055556214818
+        97142617910342598647204516893989422179826088076852
+        87783646182799346313767754307809363333018982642090
+        10848802521674670883215120185883543223812876952786
+        71329612474782464538636993009049310363619763878039
+        62184073572399794223406235393808339651327408011116
+        66627891981488087797941876876144230030984490851411
+        60661826293682836764744779239180335110989069790714
+        85786944089552990653640447425576083659976645795096
+        66024396409905389607120198219976047599490197230297
+        64913982680032973156037120041377903785566085089252
+        16730939319872750275468906903707539413042652315011
+        94809377245048795150954100921645863754710598436791
+        78639167021187492431995700641917969777599028300699
+        15368713711936614952811305876380278410754449733078
+        40789923115535562561142322423255033685442488917353
+        44889911501440648020369068063960672322193204149535
+        41503128880339536053299340368006977710650566631954
+        81234880673210146739058568557934581403627822703280
+        82616570773948327592232845941706525094512325230608
+        22918802058777319719839450180888072429661980811197
+        77158542502016545090413245809786882778948721859617
+        72107838435069186155435662884062257473692284509516
+        20849603980134001723930671666823555245252804609722
+        53503534226472524250874054075591789781264330331690
+    } ;
+
+PRIVATE>
+
+: euler013 ( -- answer )
+    source-013 sum number>string 10 head string>number ;
+
+! [ euler013 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler013
diff --git a/extra/project-euler/014/014.factor b/extra/project-euler/014/014.factor
new file mode 100644 (file)
index 0000000..7c1f0d4
--- /dev/null
@@ -0,0 +1,79 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays combinators.lib kernel math math.ranges namespaces sequences
+    sorting ;
+IN: project-euler.014
+
+! http://projecteuler.net/index.php?section=problems&id=14
+
+! DESCRIPTION
+! -----------
+
+! The following iterative sequence is defined for the set of positive integers:
+
+!     n -> n / 2  (n is even)
+!     n -> 3n + 1 (n is odd)
+
+! Using the rule above and starting with 13, we generate the following
+! sequence:
+
+!     13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
+
+! It can be seen that this sequence (starting at 13 and finishing at 1)
+! contains 10 terms. Although it has not been proved yet (Collatz Problem), it
+! is thought that all starting numbers finish at 1.
+
+! Which starting number, under one million, produces the longest chain?
+
+! NOTE: Once the chain starts the terms are allowed to go above one million.
+
+
+! SOLUTION
+! --------
+
+! Brute force
+
+<PRIVATE
+
+: next-collatz ( n -- n )
+    dup even? [ 2 / ] [ 3 * 1+ ] if ;
+
+: longest ( seq seq -- seq )
+    2dup length swap length > [ nip ] [ drop ] if ;
+
+PRIVATE>
+
+: collatz ( n -- seq )
+    [ [ dup 1 > ] [ dup , next-collatz ] [ ] while , ] { } make ;
+
+: euler014 ( -- answer )
+    1000000 0 [ 1+ collatz longest ] reduce first ;
+
+! [ euler014 ] time
+! 52868 ms run / 483 ms GC time
+
+
+! ALTERNATE SOLUTIONS
+! -------------------
+
+<PRIVATE
+
+: worth-calculating? ( n -- ? )
+    {
+        [ dup 1- 3 mod zero? ]
+        [ dup 1- 3 / even? ]
+    } && nip ;
+
+PRIVATE>
+
+: euler014a ( -- answer )
+    500000 1000000 [a,b] 1 [
+        dup worth-calculating? [ collatz longest ] [ drop ] if
+    ] reduce first ;
+
+! [ euler014a ] 10 ave-time
+! 5109 ms run / 44 ms GC time
+
+! TODO: try using memoization
+
+MAIN: euler014a
diff --git a/extra/project-euler/015/015.factor b/extra/project-euler/015/015.factor
new file mode 100644 (file)
index 0000000..3054269
--- /dev/null
@@ -0,0 +1,33 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.combinatorics ;
+IN: project-euler.015
+
+! http://projecteuler.net/index.php?section=problems&id=15
+
+! DESCRIPTION
+! -----------
+
+! Starting in the top left corner of a 2x2 grid, there are 6 routes (without
+! backtracking) to the bottom right corner.
+
+! How many routes are there through a 20x20 grid?
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: grid-paths ( n -- n )
+    dup 2 * swap nCk ;
+
+PRIVATE>
+
+: euler015 ( -- answer )
+    20 grid-paths ;
+
+! [ euler015 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler015
diff --git a/extra/project-euler/016/016.factor b/extra/project-euler/016/016.factor
new file mode 100644 (file)
index 0000000..a8b2aea
--- /dev/null
@@ -0,0 +1,28 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math.functions math.parser sequences ;
+IN: project-euler.016
+
+! http://projecteuler.net/index.php?section=problems&id=16
+
+! DESCRIPTION
+! -----------
+
+! 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
+
+! What is the sum of the digits of the number 2^1000?
+
+
+! SOLUTION
+! --------
+
+: number>digits ( n -- seq )
+    number>string string>digits ;
+
+: euler016 ( -- answer )
+    2 1000 ^ number>digits sum ;
+
+! [ euler016 ] 100 ave-time
+! 0 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler016
diff --git a/extra/project-euler/017/017.factor b/extra/project-euler/017/017.factor
new file mode 100644 (file)
index 0000000..7568872
--- /dev/null
@@ -0,0 +1,65 @@
+! Copyright (c) 2007 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math namespaces sequences strings ;
+IN: project-euler.017
+
+! http://projecteuler.net/index.php?section=problems&id=17
+
+! DESCRIPTION
+! -----------
+
+! If the numbers 1 to 5 are written out in words: one, two, three, four, five;
+! there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.
+
+! If all the numbers from 1 to 1000 (one thousand) inclusive were written out
+! in words, how many letters would be used?
+
+! NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and
+! forty-two) contains 23 letters and 115 (one hundred and fifteen) contains
+! 20 letters.
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: units ( n -- )
+  {
+    "zero" "one" "two" "three" "four" "five" "six" "seven" "eight" "nine"
+    "ten" "eleven" "twelve" "thirteen" "fourteen" "fifteen" "sixteen"
+    "seventeen" "eighteen" "nineteen"
+  } nth % ;
+
+: tenths ( n -- )
+  {
+    f f "twenty" "thirty" "fourty" "fifty" "sixty" "seventy" "eighty" "ninety"
+  } nth % ;
+
+DEFER: make-english
+
+: maybe-add ( n sep -- )
+  over 0 = [ 2drop ] [ % make-english ] if ;
+
+: 0-99 ( n -- )
+  dup 20 < [ units ] [ 10 /mod swap tenths "-" maybe-add ] if ;
+
+: 0-999 ( n -- )
+  100 /mod swap
+  dup 0 = [ drop 0-99 ] [ units " hundred" % " and " maybe-add ] if ;
+
+: make-english ( n -- )
+  1000 /mod swap
+  dup 0 = [ drop 0-999 ] [ 0-999 " thousand" % " and " maybe-add ] if ;
+
+PRIVATE>
+
+: >english ( n -- str )
+  [ make-english ] "" make ;
+
+: euler017 ( -- answer )
+  1000 [ 1 + >english [ letter? ] subset length ] map sum ;
+
+! [ euler017 ] 100 ave-time
+! 9 ms run / 0 ms GC ave time - 100 trials
+
+MAIN: euler017
diff --git a/extra/project-euler/authors.txt b/extra/project-euler/authors.txt
new file mode 100644 (file)
index 0000000..4eec9c9
--- /dev/null
@@ -0,0 +1 @@
+Aaron Schaefer
diff --git a/extra/project-euler/ave-time/authors.txt b/extra/project-euler/ave-time/authors.txt
new file mode 100644 (file)
index 0000000..4eec9c9
--- /dev/null
@@ -0,0 +1 @@
+Aaron Schaefer
diff --git a/extra/project-euler/ave-time/ave-time-docs.factor b/extra/project-euler/ave-time/ave-time-docs.factor
new file mode 100644 (file)
index 0000000..cc40ae4
--- /dev/null
@@ -0,0 +1,24 @@
+USING: arrays help.markup help.syntax math memory quotations sequences system tools.time ;
+IN: project-euler.ave-time
+
+HELP: collect-benchmarks
+{ $values { "quot" quotation } { "n" integer } { "seq" sequence } }
+{ $description "Runs a quotation " { $snippet "n" } " times, collecting the wall clock time and the time spent in the garbage collector into pairs inside of a sequence." }
+{ $notes "The stack effect of " { $snippet "quot" } " is inferred and only one set of outputs will remain on the stack no matter how many trials are run."
+    $nl
+    "A nicer word for interactive use is " { $link ave-time } "." } ;
+
+HELP: ave-time
+{ $values { "quot" quotation } { "n" integer } }
+{ $description "Runs a quotation " { $snippet "n" } " times, then prints the average run time and the average time spent in the garbage collector." }
+{ $notes "The stack effect of " { $snippet "quot" } " is inferred and only one set of outputs will remain on the stack no matter how many trials are run." }
+{ $examples
+    "This word can be used to compare performance of the non-optimizing and optimizing compilers."
+    $nl
+    "First, we time a quotation directly; quotations are compiled by the non-optimizing quotation compiler:"
+    { $unchecked-example "[ 1000000 0 [ + ] reduce drop ] 10 ave-time" "1116 ms run / 6 ms GC ave time - 10 trials" }
+    "Now we define a word and compile it with the optimizing word compiler. This results is faster execution:"
+    { $unchecked-example ": foo 1000000 0 [ + ] reduce ;" "\\ foo compile" "[ foo drop ] 10 ave-time" "202 ms run / 13 ms GC ave time - 10 trials" }
+} ;
+
+{ benchmark collect-benchmarks gc-time millis time ave-time } related-words
diff --git a/extra/project-euler/ave-time/ave-time.factor b/extra/project-euler/ave-time/ave-time.factor
new file mode 100644 (file)
index 0000000..d481b30
--- /dev/null
@@ -0,0 +1,25 @@
+! Copyright (c) 2007 Aaron Schaefer
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays effects inference io kernel math math.functions math.parser
+    math.statistics namespaces sequences tools.time ;
+IN: project-euler.ave-time
+
+<PRIVATE
+
+: clean-stack ( quot -- )
+    infer dup effect-out swap effect-in - [ drop ] times ;
+
+: ave-benchmarks ( seq -- pair )
+    flip [ mean round ] map ;
+
+PRIVATE>
+
+: collect-benchmarks ( quot n -- seq )
+    [
+        1- [ [ benchmark ] keep -rot 2array , [ clean-stack ] keep ] times
+    ] curry { } make >r benchmark 2array r> swap add ; inline
+
+: ave-time ( quot n -- )
+    [ collect-benchmarks ] keep swap ave-benchmarks [
+        dup second # " ms run / " % first # " ms GC ave time - " % # " trials" %
+    ] "" make print flush ; inline
diff --git a/extra/project-euler/ave-time/summary.txt b/extra/project-euler/ave-time/summary.txt
new file mode 100644 (file)
index 0000000..5fadfa9
--- /dev/null
@@ -0,0 +1 @@
+Averaging code execution times
diff --git a/extra/project-euler/ave-time/tags.txt b/extra/project-euler/ave-time/tags.txt
new file mode 100644 (file)
index 0000000..ef1aab0
--- /dev/null
@@ -0,0 +1 @@
+tools
diff --git a/extra/project-euler/common/common.factor b/extra/project-euler/common/common.factor
new file mode 100644 (file)
index 0000000..73de3a7
--- /dev/null
@@ -0,0 +1,61 @@
+USING: arrays kernel hashtables math math.functions math.miller-rabin
+    math.ranges namespaces sequences combinators.lib ;
+IN: project-euler.common
+
+! A collection of words used by more than one Project Euler solution.
+
+<PRIVATE
+
+: count-shifts ( seq width -- n )
+    >r length 1+ r> - ;
+
+: shift-3rd ( seq obj obj -- seq obj obj )
+    rot 1 tail -rot ;
+
+: >multiplicity ( seq -- seq )
+    dup prune [
+        [ 2dup [ = ] curry count 2array , ] each
+    ] { } make nip ; inline
+
+: reduce-2s ( n -- r s )
+    dup even? [ factor-2s >r 1+ r> ] [ 1 swap ] if ;
+
+: tau-limit ( n -- n )
+    sqrt floor >fixnum ;
+
+PRIVATE>
+
+
+: divisor? ( n m -- ? )
+    mod zero? ;
+
+: perfect-square? ( n -- ? )
+    dup sqrt mod zero? ;
+
+: collect-consecutive ( seq width -- seq )
+    [
+        2dup count-shifts [ 2dup head shift-3rd , ] times
+    ] { } make 2nip ;
+
+: prime-factorization ( n -- seq )
+    [
+        2 [ over 1 > ]
+        [ 2dup divisor? [ dup , [ / ] keep ] [ next-prime ] if ]
+        [ ] while 2drop
+    ] { } make ;
+
+: prime-factorization* ( n -- seq )
+    prime-factorization >multiplicity ;
+
+: prime-factors ( n -- seq )
+    prime-factorization prune >array ;
+
+! The divisor function, counts the number of divisors
+: tau ( n -- n )
+    prime-factorization* flip second 1 [ 1+ * ] reduce ;
+
+! Optimized brute-force, is often faster than prime factorization
+: tau* ( n -- n )
+    reduce-2s [ perfect-square? -1 0 ? ] keep dup tau-limit [1,b] [
+        dupd divisor? [ >r 2 + r> ] when
+    ] each drop * ;
diff --git a/extra/project-euler/project-euler.factor b/extra/project-euler/project-euler.factor
new file mode 100644 (file)
index 0000000..c351017
--- /dev/null
@@ -0,0 +1,44 @@
+! Copyright (c) 2007 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: io io.files kernel math.parser namespaces sequences strings
+    vocabs vocabs.loader system project-euler.ave-time
+    project-euler.001 project-euler.002 project-euler.003 project-euler.004
+    project-euler.005 project-euler.006 project-euler.007 project-euler.008
+    project-euler.009 project-euler.010 project-euler.011 project-euler.012
+    project-euler.013 project-euler.014 project-euler.015 project-euler.016 ;
+IN: project-euler
+
+<PRIVATE
+
+: problem-prompt ( -- n )
+    "Which problem number from Project Euler would you like to solve?"
+    print readln string>number ;
+
+: number>euler ( n -- str )
+    number>string string>digits 3 0 pad-left [ number>string ] map concat ;
+
+: solution-path ( n -- str )
+    number>euler dup [
+        "project-euler" vocab-root ?resource-path %
+        os "windows" = [
+            "\\project-euler\\" % % "\\" % % ".factor" %
+        ] [
+            "/project-euler/" % % "/" % % ".factor" %
+        ] if
+    ] "" make ;
+
+PRIVATE>
+
+: problem-solved? ( n -- ? )
+    solution-path exists? ;
+
+: run-project-euler ( -- )
+    problem-prompt dup problem-solved? [
+        dup number>euler "project-euler." swap append run
+        "Answer: " swap number>string append print
+        "Source: " swap solution-path append print
+    ] [
+        drop "That problem has not been solved yet..." print
+    ] if ;
+
+MAIN: run-project-euler
diff --git a/extra/project-euler/summary.txt b/extra/project-euler/summary.txt
new file mode 100644 (file)
index 0000000..add3da5
--- /dev/null
@@ -0,0 +1 @@
+Project Euler example solutions
diff --git a/extra/project-euler/tags.txt b/extra/project-euler/tags.txt
new file mode 100644 (file)
index 0000000..1e107f5
--- /dev/null
@@ -0,0 +1 @@
+examples
index a28fe32818384c0c4741a8e0572883a2bc415e4b..269c22e81138c908df03a9efc564781d5bd6a824 100755 (executable)
@@ -1,5 +1,6 @@
 USING: combinators.lib kernel sequences math namespaces assocs 
 random sequences.private shuffle math.functions mirrors ;
+USING: arrays math.parser sorting strings ;
 IN: sequences.lib
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -113,3 +114,20 @@ PRIVATE>
 
 : partition ( seq quot -- trueseq falseseq )
     over >r 2pusher >r >r each r> r> r> drop ; inline
+
+: cut-find ( seq pred -- before after )
+    dupd find drop dup [ cut ] when ;
+
+: cut3 ( seq pred -- first mid last )
+    [ cut-find ] keep [ not ] compose cut-find ;
+
+: (cut-all) ( seq pred quot -- )
+    [ >r cut3 r> dip >r >r , r> [ , ] when* r> ] 2keep
+    pick [ (cut-all) ] [ 3drop ] if ;
+
+: cut-all ( seq pred quot -- first mid last )
+    [ (cut-all) ] { } make ;
+
+: human-sort ( seq -- newseq )
+    [ dup [ digit? ] [ string>number ] cut-all ] { } map>assoc
+    sort-values keys ;
index 89dc0d8cc3f74a4c591ac0a86d09c88d583837a7..59e446af34558fea8ced17966e26622da2c18136 100755 (executable)
@@ -40,6 +40,5 @@ M: windows-deploy-implementation deploy*
         [
             [ deploy-name get create-exe-dir ] keep
             [ deploy-name get image-name ] keep
-            deploy-name get
         ] bind
     ] keep stage2 open-in-explorer ;
index b21e91bc8fb1bd5a872032a3b9e641dd4e49f3de..19dab4ed1b03b7ce9fbba9722b2ff584d060463b 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2006 Chris Double. All Rights Reserved.
 ! See http://factorcode.org/license.txt for BSD license.
 !
-USING: kernel furnace fjsc  parser-combinators namespaces
+USING: kernel furnace fjsc  peg namespaces
        lazy-lists io io.files furnace.validator sequences
        http.client http.server http.server.responders
        webapps.file html ;
@@ -11,7 +11,7 @@ IN: webapps.fjsc
   #! Compile the factor code as a string, outputting the http
   #! response containing the javascript.
   serving-text
-  'expression' parse-1 fjsc-compile
+  'expression' parse parse-result-ast fjsc-compile
   write flush ;
 
 ! The 'compile' action results in an URL that looks like
@@ -25,7 +25,7 @@ IN: webapps.fjsc
 : compile-url ( url -- )
   #! Compile the factor code at the given url, return the javascript.
   dup "http:" head? [ "Unable to access remote sites." throw ] when
-  "http://" host rot 3append http-get 2nip compile "();" write flush ;
+  "http://" "Host" header-param rot 3append http-get 2nip compile "();" write flush ;
 
 \ compile-url {
   { "url" v-required }
index 145df4119a131329dd69b05d6a5ab87499618acb..28d73607bac3132a935e00eabb9f7d73c94f2562 100644 (file)
@@ -6,18 +6,19 @@ USING: kernel furnace furnace.validator http.server.responders
        arrays io.files ;
 IN: webapps.help 
 
+! : string>topic ( string -- topic )
+    ! " " split dup length 1 = [ first ] when ;
+
 : show-help ( topic -- )
     serving-html
     dup article-title [
         [ help ] with-html-stream
     ] simple-html-document ;
 
-: string>topic ( string -- topic )
-    " " split dup length 1 = [ first ] when ;
-
 \ show-help {
-    { "topic" "handbook" v-default string>topic }
+    { "topic" }
 } define-action
+\ show-help { { "topic" "handbook" } } default-values
 
 M: link browser-link-href
     link-name
@@ -32,9 +33,10 @@ M: link browser-link-href
     lookup show-help ;
 
 \ show-word {
-    { "word" "call" v-default }
-    { "vocab" "kernel" v-default }
+    { "word" }
+    { "vocab" }
 } define-action
+\ show-word { { "word" "call" } { "vocab" "kernel" } } default-values
 
 M: f browser-link-href
     drop \ f browser-link-href ;
@@ -47,9 +49,11 @@ M: word browser-link-href
     f >vocab-link show-help ;
 
 \ show-vocab {
-    { "vocab" "kernel" v-default }
+    { "vocab" }
 } define-action
 
+\ show-vocab { { "vocab" "kernel" } } default-values
+
 M: vocab-spec browser-link-href
     vocab-name [ show-vocab ] curry quot-link ;
 
index abb5cc3d07d49742961ccb4d06237685de555a1a..14a424f77636085a0c79530ed1898f2d1083a8b4 100755 (executable)
@@ -6,16 +6,16 @@
 
 <table>
 
-<input type="hidden" name="n" value="<% "n" get number>string write %>" />
-
 <tr>
 <th align="right">Summary:</th>
-<td><input type="TEXT" name="summary" value="" /></td>
+<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
+<td align="left" class="error"><% "summary" "*Required" render-error %></td>
 </tr>
 
 <tr>
 <th align="right">Your name:</th>
-<td><input type="TEXT" name="author" value="" /></td>
+<td><input type="TEXT" name="author" value="<% "author" render  %>" /></td>
+<td class="error"><% "author" "*Required" render-error %></td>
 </tr>
 
 <tr>
 <td><% "modes" render-template %></td>
 </tr>
 
+<!--
+<tr>
+<th align="right">Channel:</th>
+<td><input type="TEXT" name="channel" value="#concatenative" /></td>
+</tr>
+-->
+
+<tr>
+<td></td>
+<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
+</tr>
+
 <tr>
 <th align="right" valign="top">Content:</th>
-<td><textarea rows="24" cols="60" name="contents"></textarea></td>
+<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
 </tr>
 </table>
 
+<input type="hidden" name="n" value="<% "n" get number>string write %>" />
+<input type="hidden" name="furnace-form-submitted" value="annotate-paste"/>
 <input type="SUBMIT" value="Annotate" />
 </form>
index 960b7d4e2735408f2acba5b596842ebd0f16e0c7..18bbec180af5b816e8044fd7805329749a49ea47 100644 (file)
@@ -1,7 +1,7 @@
-<% USING: xmode.catalog sequences kernel html.elements assocs io sorting ; %>
+<% USING: furnace xmode.catalog sequences kernel html.elements assocs io sorting continuations ; %>
 
 <select name="mode">
     <% modes keys natural-sort [
-        <option dup "factor" = [ "true" =selected ] when option> write </option>
+        <option dup "mode" session-var = [ "true" =selected ] when option> write </option>
     ] each %>
 </select>
index 8f48f670d3fa6c8d379673e80458e1a370fd352a..b21e19734d53e05cdfe0b2278b34b59a94973295 100755 (executable)
@@ -1,4 +1,4 @@
-<% USING: furnace namespaces ; %>
+<% USING: continuations furnace namespaces ; %>
 
 <%
     "New paste" "title" set
 
 <tr>
 <th align="right">Summary:</th>
-<td><input type="TEXT" name="summary" value="" /></td>
+<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
+<td align="left" class="error"><% "summary" "*Required" render-error %></td>
 </tr>
 
 <tr>
 <th align="right">Your name:</th>
-<td><input type="TEXT" name="author" value="" /></td>
+<td><input type="TEXT" name="author" value="<% "author" render  %>" /></td>
+<td class="error"><% "author" "*Required" render-error %></td>
 </tr>
 
 <tr>
 </tr>
 -->
 
+<tr>
+<td></td>
+<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
+</tr>
+
 <tr>
 <th align="right" valign="top">Content:</th>
-<td><textarea rows="24" cols="60" name="contents"></textarea></td>
+<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
 </tr>
 </table>
 
+<input type="hidden" name="furnace-form-submitted" value="new-paste"/>
 <input type="SUBMIT" value="Submit paste" />
 </form>
 
index 8e4c0a5be9dc9df6494b00b684a8b4a8d2d28aa4..0a7dc559c3938ae1fbb76a27268947b7a33a7e38 100755 (executable)
@@ -1,6 +1,6 @@
 USING: calendar furnace furnace.validator io.files kernel
 namespaces sequences store http.server.responders html
-math.parser rss xml.writer ;
+math.parser rss xml.writer xmode.code2html ;
 IN: webapps.pastebin
 
 TUPLE: pastebin pastes ;
@@ -84,28 +84,37 @@ C: <annotation> annotation
         store save-store
     ] keep paste-link permanent-redirect ;
 
+\ new-paste
 \ submit-paste {
-    { "summary" "- no summary -" v-default }
-    { "author" "- no author -" v-default }
-    { "channel" "#concatenative" v-default }
-    { "mode" "factor" v-default }
+    { "summary" v-required }
+    { "author" v-required }
+    { "channel" }
+    { "mode" v-required }
     { "contents" v-required }
-} define-action
+} define-form
+
+\ new-paste {
+    { "channel" "#concatenative" }
+    { "mode" "factor" }
+} default-values
 
 : annotate-paste ( n summary author mode contents -- )
     <annotation> swap get-paste
-    paste-annotations push
-    store save-store ;
+    [ paste-annotations push store save-store ] keep
+    paste-link permanent-redirect ;
 
+[ "n" show-paste ]
 \ annotate-paste {
     { "n" v-required v-number }
-    { "summary" "- no summary -" v-default }
-    { "author" "- no author -" v-default }
-    { "mode" "factor" v-default }
+    { "summary" v-required }
+    { "author" v-required }
+    { "mode" v-required }
     { "contents" v-required }
-} define-action
+} define-form
 
-\ annotate-paste [ "n" show-paste ] define-redirect
+\ show-paste {
+    { "mode" "factor" }
+} default-values
 
 : style.css ( -- )
     "text/css" serving-content
index e3c7c19fc5a7d381378d58216b77f66cade121e2..4a469f92cb0c167d265d616d1a9fbca8003fd0dc 100644 (file)
@@ -35,3 +35,7 @@ pre.code {
        border: 1px solid #C1DAD7;
        padding: 10px;
 }
+
+.error {
+       color: red;
+}
index 58ff2a3f6c90618adca81ea2db6d13d2f587f053..725d6da3cc7c819bb0d8beaf7945f5b78d19a72e 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2005, 2006 Daniel Ehrenberg
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences sequences.private assocs arrays ;
+USING: kernel sequences sequences.private assocs arrays vectors ;
 IN: xml.data
 
 TUPLE: name space tag url ;
@@ -60,7 +60,8 @@ M: attrs set-at
     2dup attr@ nip [
         2nip set-second
     ] [
-        >r assure-name swap 2array r> push
+        [ >r assure-name swap 2array r> ?push ] keep
+        set-delegate
     ] if* ;
 
 M: attrs assoc-size length ;
@@ -68,14 +69,15 @@ M: attrs new-assoc drop V{ } new <attrs> ;
 M: attrs >alist delegate >alist ;
 
 : >attrs ( assoc -- attrs )
-    V{ } assoc-clone-like
-    [ >r assure-name r> ] assoc-map
-    <attrs> ;
+    dup [
+        V{ } assoc-clone-like
+        [ >r assure-name r> ] assoc-map
+    ] when <attrs> ;
 M: attrs assoc-like
     drop dup attrs? [ >attrs ] unless ;
 
 M: attrs clear-assoc
-    delete-all ;
+    f swap set-delegate ;
 M: attrs delete-at
     tuck attr@ drop [ swap delete-nth ] [ drop ] if* ;
 
index e64b9591a555fefe129b5e257d5c2fcdea625649..798b7f571aed925766b567463e99886e91410cf8 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces sequences words io assocs
 quotations strings parser arrays xml.data xml.writer debugger
-splitting ;
+splitting vectors ;
 IN: xml.utilities
 
 ! * System for words specialized on tag names
@@ -36,14 +36,16 @@ M: process-missing error.
 ! * Common utility functions
 
 : build-tag* ( items name -- tag )
-    "" swap "" <name>
-    swap >r { } r> <tag> ;
+    assure-name swap >r f r> <tag> ;
 
 : build-tag ( item name -- tag )
     >r 1array r> build-tag* ;
 
+: standard-prolog ( -- prolog )
+    T{ prolog f "1.0" "iso-8859-1" f } ;
+
 : build-xml ( tag -- xml )
-    T{ prolog f "1.0" "iso-8859-1" f } { } rot { } <xml> ;
+    standard-prolog { } rot { } <xml> ;
 
 : children>string ( tag -- string )
     tag-children
@@ -91,7 +93,7 @@ M: xml xml-map
 
 GENERIC# xml-find 1 ( quot tag -- tag ) inline
 M: tag xml-find
-    [ call ] 2keep spin [
+    [ call ] 2keep swap rot [
         f swap
         [ nip over >r swap xml-find r> swap dup ] find
         2drop ! leaves result of quot
@@ -111,30 +113,53 @@ M: object xml-inject 2drop ;
 M: xml xml-inject >r delegate >r xml-inject ;
 
 ! * Accessing part of an XML document
+! for tag- words, a start means that it searches all children
+! and no star searches only direct children
 
-: get-id ( tag id -- elem ) ! elem=tag.getElementById(id)
-    swap [
-        dup tag?
-        [ "id" swap at over = ]
-        [ drop f ] if
-    ] xml-find nip ;
-
-: (get-tag) ( name elem -- ? )
+: tag-named? ( name elem -- ? )
     dup tag? [ names-match? ] [ 2drop f ] if ;
 
 : tag-named* ( tag name/string -- matching-tag )
-    assure-name swap [ dupd (get-tag) ] xml-find nip ;
+    assure-name swap [ dupd tag-named? ] xml-find nip ;
 
 : tags-named* ( tag name/string -- tags-seq )
-    assure-name swap [ dupd (get-tag) ] xml-subset nip ;
+    assure-name swap [ dupd tag-named? ] xml-subset nip ;
 
 : tag-named ( tag name/string -- matching-tag )
     ! like get-name-tag but only looks at direct children,
     ! not all the children down the tree.
-    assure-name swap [ (get-tag) ] curry* find nip ;
+    assure-name swap [ tag-named? ] curry* find nip ;
 
 : tags-named ( tag name/string -- tags-seq )
-    assure-name swap [ (get-tag) ] curry* subset ;
+    assure-name swap [ tag-named? ] curry* subset ;
 
 : assert-tag ( name name -- )
     names-match? [ "Unexpected XML tag found" throw ] unless ;
+
+: insert-children ( children tag -- )
+    dup tag-children [ push-all ]
+    [ >r V{ } like r> set-tag-children ] if ;
+
+: insert-child ( child tag -- )
+    >r 1vector r> insert-children ;
+
+: tag-with-attr? ( elem attr-value attr-name -- ? )
+    rot dup tag? [ at = ] [ drop f ] if ;
+
+: tag-with-attr ( tag attr-value attr-name -- matching-tag )
+    assure-name [ tag-with-attr? ] 2curry find nip ;
+
+: tags-with-attr ( tag attr-value attr-name -- tags-seq )
+    assure-name [ tag-with-attr? ] 2curry subset ;
+
+: tag-with-attr* ( tag attr-value attr-name -- matching-tag )
+    assure-name [ tag-with-attr? ] 2curry xml-find nip ;
+
+: tags-with-attr* ( tag attr-value attr-name -- tags-seq )
+    assure-name [ tag-with-attr? ] 2curry xml-subset ;
+
+: get-id ( tag id -- elem ) ! elem=tag.getElementById(id)
+    "id" tag-with-attr ;
+
+: tags-named-with-attr* ( tag tag-name attr-value attr-name -- tags )
+    >r >r tags-named* r> r> tags-with-attr ;
index 11ea2a9cdffc9e4005d12e880902076539ddaf57..b2cbb836e65c20920ea89b5ccbc7a845d855357e 100755 (executable)
@@ -152,6 +152,7 @@ echo_build_info() {
        echo FACTOR_BINARY=$FACTOR_BINARY
        echo MAKE_TARGET=$MAKE_TARGET
        echo BOOT_IMAGE=$BOOT_IMAGE
+       echo MAKE_IMAGE_TARGET=$MAKE_IMAGE_TARGET
 }
 
 set_build_info() {
@@ -162,13 +163,20 @@ set_build_info() {
                echo "OS, ARCH, or WORD is empty.  Please report this"
                exit 5
        fi
-       
+
        MAKE_TARGET=$OS-$ARCH-$WORD
+       MAKE_IMAGE_TARGET=$ARCH.$WORD
        BOOT_IMAGE=boot.$ARCH.$WORD.image
        if [[ $OS == macosx && $ARCH == ppc ]] ; then
+               MAKE_IMAGE_TARGET=$OS-$ARCH
                MAKE_TARGET=$OS-$ARCH
                BOOT_IMAGE=boot.macosx-ppc.image
        fi
+       if [[ $OS == linux && $ARCH == ppc ]] ; then
+               MAKE_IMAGE_TARGET=$OS-$ARCH
+               MAKE_TARGET=$OS-$ARCH
+               BOOT_IMAGE=boot.linux-ppc.image
+       fi
 }
 
 find_build_info() {
@@ -266,16 +274,24 @@ update_bootstrap() {
 }
 
 refresh_image() {
-       ./$FACTOR_BINARY -e="refresh-all save 0 USE: system exit"
+       ./$FACTOR_BINARY -script -e="refresh-all save 0 USE: system exit"
+       check_ret factor
+}
+
+make_boot_image() {
+       ./$FACTOR_BINARY -script -e="\"$MAKE_IMAGE_TARGET\" USE: bootstrap.image make-image save 0 USE: system exit"
+       check_ret factor
+
 }
 
 install_libraries() {
-       sudo apt-get install libc6-dev libfreetype6-dev wget git-core git-doc libx11-dev glutg3-dev rlwrap
+       sudo apt-get install libc6-dev libfreetype6-dev libx11-dev xorg-dev glutg3-dev wget git-core git-doc rlwrap
 }
 
 case "$1" in
        install) install ;;
        install-x11) install_libraries; install ;;
+       self-update) update; make_boot_image; bootstrap;;
        quick-update) update; refresh_image ;;
        update) update; update_bootstrap ;;
        *) usage ;;