From b6d8521c8ceec6d2dec2906435823100399d853e Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Fri, 2 May 2008 17:11:51 -0500 Subject: [PATCH 01/10] refactor state parser --- extra/state-parser/state-parser.factor | 117 ++++++++++++++----------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/extra/state-parser/state-parser.factor b/extra/state-parser/state-parser.factor index 96ad4ca0b4..17d5377259 100644 --- a/extra/state-parser/state-parser.factor +++ b/extra/state-parser/state-parser.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2005, 2006 Daniel Ehrenberg ! See http://factorcode.org/license.txt for BSD license. USING: io io.streams.string kernel math namespaces sequences -strings circular prettyprint debugger ascii ; +strings circular prettyprint debugger ascii sbufs fry inspector +accessors sequences.lib ; IN: state-parser ! * Basic underlying words @@ -11,50 +12,56 @@ TUPLE: spot char line column next ; C: spot -: get-char ( -- char ) spot get spot-char ; -: set-char ( char -- ) spot get set-spot-char ; -: get-line ( -- line ) spot get spot-line ; -: set-line ( line -- ) spot get set-spot-line ; -: get-column ( -- column ) spot get spot-column ; -: set-column ( column -- ) spot get set-spot-column ; -: get-next ( -- char ) spot get spot-next ; -: set-next ( char -- ) spot get set-spot-next ; +: get-char ( -- char ) spot get char>> ; +: set-char ( char -- ) spot get swap >>char drop ; +: get-line ( -- line ) spot get line>> ; +: set-line ( line -- ) spot get swap >>line drop ; +: get-column ( -- column ) spot get column>> ; +: set-column ( column -- ) spot get swap >>column drop ; +: get-next ( -- char ) spot get next>> ; +: set-next ( char -- ) spot get swap >>next drop ; ! * Errors TUPLE: parsing-error line column ; -: ( -- parsing-error ) - get-line get-column parsing-error boa ; -: construct-parsing-error ( ... slots class -- error ) - construct over set-delegate ; inline +: parsing-error ( class -- obj ) + new + get-line >>line + get-column >>column ; +M: parsing-error summary ( obj -- str ) + [ + "Parsing error" print + "Line: " write dup line>> . + "Column: " write column>> . + ] with-string-writer ; -: parsing-error. ( parsing-error -- ) - "Parsing error" print - "Line: " write dup parsing-error-line . - "Column: " write parsing-error-column . ; +TUPLE: expected < parsing-error should-be was ; +: expected ( should-be was -- * ) + \ expected parsing-error + swap >>was + swap >>should-be throw ; +M: expected summary ( obj -- str ) + [ + dup call-next-method write + "Token expected: " write dup should-be>> print + "Token present: " write was>> print + ] with-string-writer ; -TUPLE: expected should-be was ; -: ( should-be was -- error ) - { set-expected-should-be set-expected-was } - expected construct-parsing-error ; -M: expected error. - dup parsing-error. - "Token expected: " write dup expected-should-be print - "Token present: " write expected-was print ; +TUPLE: unexpected-end < parsing-error ; +: unexpected-end \ unexpected-end parsing-error throw ; +M: unexpected-end summary ( obj -- str ) + [ + call-next-method write + "File unexpectedly ended." print + ] with-string-writer ; -TUPLE: unexpected-end ; -: ( -- unexpected-end ) - { } unexpected-end construct-parsing-error ; -M: unexpected-end error. - parsing-error. - "File unexpectedly ended." print ; - -TUPLE: missing-close ; -: ( -- missing-close ) - { } missing-close construct-parsing-error ; -M: missing-close error. - parsing-error. - "Missing closing token." print ; +TUPLE: missing-close < parsing-error ; +: missing-close \ missing-close parsing-error throw ; +M: missing-close summary ( obj -- str ) + [ + call-next-method write + "Missing closing token." print + ] with-string-writer ; SYMBOL: prolog-data @@ -65,7 +72,8 @@ SYMBOL: prolog-data [ 0 get-line 1+ set-line ] [ get-column 1+ ] if set-column ; -: (next) ( -- char ) ! this normalizes \r\n and \r +! (next) normalizes \r\n and \r +: (next) ( -- char ) get-next read1 2dup swap CHAR: \r = [ CHAR: \n = @@ -75,10 +83,7 @@ SYMBOL: prolog-data : next ( -- ) #! Increment spot. - get-char [ - throw - ] unless - (next) record ; + get-char [ unexpected-end ] unless (next) record ; : next* ( -- ) get-char [ (next) record ] when ; @@ -95,9 +100,9 @@ SYMBOL: prolog-data #! Take the substring of a string starting at spot #! from code until the quotation given is true and #! advance spot to after the substring. - [ [ - dup slip swap dup [ get-char , ] unless - ] skip-until ] "" make nip ; inline + 10 [ + '[ @ [ t ] [ get-char , push f ] if ] skip-until + ] keep >string ; inline : take-rest ( -- string ) [ f ] take-until ; @@ -105,6 +110,20 @@ SYMBOL: prolog-data : take-char ( ch -- string ) [ dup get-char = ] take-until nip ; +TUPLE: not-enough-characters < parsing-error ; +: not-enough-characters + \ not-enough-characters parsing-error throw ; +M: not-enough-characters summary ( obj -- str ) + [ + call-next-method write + "Not enough characters" print + ] with-string-writer ; + +: take ( n -- string ) + [ 1- ] [ ] bi [ + '[ drop get-char [ next , push f ] [ t ] if* ] attempt-each drop + ] keep get-char [ over push ] when* >string ; + : pass-blank ( -- ) #! Advance code past any whitespace, including newlines [ get-char blank? not ] skip-until ; @@ -117,16 +136,16 @@ SYMBOL: prolog-data dup length [ 2dup string-matches? ] take-until nip dup length rot length 1- - head - get-char [ throw ] unless next ; + get-char [ missing-close ] unless next ; : expect ( ch -- ) get-char 2dup = [ 2drop ] [ - >r 1string r> 1string throw + >r 1string r> 1string expected ] if next ; : expect-string ( string -- ) dup [ drop get-char next ] map 2dup = - [ 2drop ] [ throw ] if ; + [ 2drop ] [ expected ] if ; : init-parser ( -- ) 0 1 0 f spot set From a77ba70706d4dc2506faefdb9f0ba8cd4420894b Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Fri, 2 May 2008 17:12:09 -0500 Subject: [PATCH 02/10] refactor xml parser --- extra/xml/backend/backend.factor | 6 + extra/xml/errors/errors.factor | 291 +++++++++++++++++-------------- extra/xml/tests/errors.factor | 28 --- extra/xml/xml.factor | 10 +- 4 files changed, 168 insertions(+), 167 deletions(-) create mode 100644 extra/xml/backend/backend.factor delete mode 100755 extra/xml/tests/errors.factor diff --git a/extra/xml/backend/backend.factor b/extra/xml/backend/backend.factor new file mode 100644 index 0000000000..5dee38695d --- /dev/null +++ b/extra/xml/backend/backend.factor @@ -0,0 +1,6 @@ +! Copyright (C) 2008 Daniel Ehrenberg +! See http://factorcode.org/license.txt for BSD license. +IN: xml.backend + +! A stack of { tag children } pairs +SYMBOL: xml-stack diff --git a/extra/xml/errors/errors.factor b/extra/xml/errors/errors.factor index 5b41a7ff9f..3e24d7e720 100644 --- a/extra/xml/errors/errors.factor +++ b/extra/xml/errors/errors.factor @@ -1,150 +1,179 @@ ! Copyright (C) 2005, 2006 Daniel Ehrenberg ! See http://factorcode.org/license.txt for BSD license. USING: xml.data xml.writer kernel generic io prettyprint math -debugger sequences state-parser ; +debugger sequences state-parser accessors inspector +namespaces io.streams.string xml.backend ; IN: xml.errors -TUPLE: no-entity thing ; -: ( string -- error ) - { set-no-entity-thing } no-entity construct-parsing-error ; -M: no-entity error. - dup parsing-error. - "Entity does not exist: &" write no-entity-thing write ";" print ; - -TUPLE: xml-string-error string ; ! this should not exist -: ( string -- xml-string-error ) - { set-xml-string-error-string } - xml-string-error construct-parsing-error ; -M: xml-string-error error. - dup parsing-error. - xml-string-error-string print ; - -TUPLE: mismatched open close ; -: - { set-mismatched-open set-mismatched-close } - mismatched construct-parsing-error ; -M: mismatched error. - dup parsing-error. - "Mismatched tags" print - "Opening tag: <" write dup mismatched-open print-name ">" print - "Closing tag: " print ; - -TUPLE: unclosed tags ; -! is ( -- unclosed ), see presentation.factor -M: unclosed error. - "Unclosed tags" print - "Tags: " print - unclosed-tags [ " <" write print-name ">" print ] each ; - -TUPLE: bad-uri string ; -: ( string -- bad-uri ) - { set-bad-uri-string } bad-uri construct-parsing-error ; -M: bad-uri error. - dup parsing-error. - "Bad URI:" print bad-uri-string . ; - -TUPLE: nonexist-ns name ; -: ( name-string -- nonexist-ns ) - { set-nonexist-ns-name } - nonexist-ns construct-parsing-error ; -M: nonexist-ns error. - dup parsing-error. - "Namespace " write nonexist-ns-name write " has not been declared" print ; - -TUPLE: unopened ; ! this should give which tag was unopened -: ( -- unopened ) - { } unopened construct-parsing-error ; -M: unopened error. - parsing-error. - "Closed an unopened tag" print ; - -TUPLE: not-yes/no text ; -: ( text -- not-yes/no ) - { set-not-yes/no-text } not-yes/no construct-parsing-error ; -M: not-yes/no error. - dup parsing-error. - "standalone must be either yes or no, not \"" write - not-yes/no-text write "\"." print ; - -TUPLE: extra-attrs attrs ; ! this should actually print the names -: ( attrs -- extra-attrs ) - { set-extra-attrs-attrs } - extra-attrs construct-parsing-error ; -M: extra-attrs error. - dup parsing-error. - "Extra attributes included in xml version declaration:" print - extra-attrs-attrs . ; - -TUPLE: bad-version num ; -: - { set-bad-version-num } - bad-version construct-parsing-error ; -M: bad-version error. - "XML version must be \"1.0\" or \"1.1\". Version here was " write - bad-version-num . ; - -TUPLE: notags ; -C: notags -M: notags error. - drop "XML document lacks a main tag" print ; - TUPLE: multitags ; C: multitags -M: multitags error. - drop "XML document contains multiple main tags" print ; - -TUPLE: bad-prolog prolog ; -: ( prolog -- bad-prolog ) - { set-bad-prolog-prolog } - bad-prolog construct-parsing-error ; -M: bad-prolog error. - dup parsing-error. - "Misplaced XML prolog" print - bad-prolog-prolog write-prolog nl ; - -TUPLE: capitalized-prolog name ; -: ( name -- capitalized-prolog ) - { set-capitalized-prolog-name } - capitalized-prolog construct-parsing-error ; -M: capitalized-prolog error. - dup parsing-error. - "XML prolog name was partially or totally capitalized, using" print - "" write - " instead of " print ; +M: multitags summary ( obj -- str ) + drop "XML document contains multiple main tags" ; TUPLE: pre/post-content string pre? ; C:
 pre/post-content
-M: pre/post-content error.
-    "The text string:" print
-    dup pre/post-content-string .
-    "was used " write
-    pre/post-content-pre? "before" "after" ? write
-    " the main tag." print ;
+M: pre/post-content summary ( obj -- str )
+    [
+        "The text string:" print
+        dup string>> .
+        "was used " write
+        pre?>> "before" "after" ? write
+        " the main tag." print
+    ] with-string-writer ;
 
-TUPLE: versionless-prolog ;
+TUPLE: no-entity < parsing-error thing ;
+:  ( string -- error )
+    \ no-entity parsing-error swap >>thing ;
+M: no-entity summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Entity does not exist: &" write thing>> write ";" print
+    ] with-string-writer ;
+
+TUPLE: xml-string-error < parsing-error string ; ! this should not exist
+:  ( string -- xml-string-error )
+    \ xml-string-error parsing-error swap >>string ;
+M: xml-string-error summary ( obj -- str )
+    [
+        dup call-next-method write
+        string>> print
+    ] with-string-writer ;
+
+TUPLE: mismatched < parsing-error open close ;
+: 
+    \ mismatched parsing-error swap >>close swap >>open ;
+M: mismatched summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Mismatched tags" print
+        "Opening tag: <" write dup open>> print-name ">" print
+        "Closing tag: > print-name ">" print
+    ] with-string-writer ;
+
+TUPLE: unclosed < parsing-error tags ;
+:  ( -- unclosed )
+    unclosed parsing-error
+        xml-stack get rest-slice [ first opener-name ] map >>tags ;
+M: unclosed summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Unclosed tags" print
+        "Tags: " print
+        tags>> [ "  <" write print-name ">" print ] each
+    ] with-string-writer ;
+
+TUPLE: bad-uri < parsing-error string ;
+:  ( string -- bad-uri )
+    \ bad-uri parsing-error swap >>string ;
+M: bad-uri summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Bad URI:" print string>> .
+    ] with-string-writer ;
+
+TUPLE: nonexist-ns < parsing-error name ;
+:  ( name-string -- nonexist-ns )
+    \ nonexist-ns parsing-error swap >>name ;
+M: nonexist-ns summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Namespace " write name>> write " has not been declared" print
+    ] with-string-writer ;
+
+TUPLE: unopened < parsing-error ; ! this should give which tag was unopened
+:  ( -- unopened )
+    \ unopened parsing-error ;
+M: unopened summary ( obj -- str )
+    [
+        call-next-method write
+        "Closed an unopened tag" print
+    ] with-string-writer ;
+
+TUPLE: not-yes/no < parsing-error text ;
+:  ( text -- not-yes/no )
+    \ not-yes/no parsing-error swap >>text ;
+M: not-yes/no summary ( obj -- str )
+    [
+        dup call-next-method write
+        "standalone must be either yes or no, not \"" write
+        text>> write "\"." print
+    ] with-string-writer ;
+
+! this should actually print the names
+TUPLE: extra-attrs < parsing-error attrs ;
+:  ( attrs -- extra-attrs )
+    \ extra-attrs parsing-error swap >>attrs ;
+M: extra-attrs summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Extra attributes included in xml version declaration:" print
+        attrs>> .
+    ] with-string-writer ;
+
+TUPLE: bad-version < parsing-error num ;
+: 
+    \ bad-version parsing-error swap >>num ;
+M: bad-version summary ( obj -- str )
+    [
+        "XML version must be \"1.0\" or \"1.1\". Version here was " write
+        num>> .
+    ] with-string-writer ;
+
+TUPLE: notags < parsing-error ;
+: 
+    \ notags parsing-error ;
+M: notags summary ( obj -- str )
+    drop "XML document lacks a main tag" ;
+
+TUPLE: bad-prolog < parsing-error prolog ;
+:  ( prolog -- bad-prolog )
+    \ bad-prolog parsing-error swap >>prolog ;
+M: bad-prolog summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Misplaced XML prolog" print
+        prolog>> write-prolog nl
+    ] with-string-writer ;
+
+TUPLE: capitalized-prolog < parsing-error name ;
+:  ( name -- capitalized-prolog )
+    \ capitalized-prolog parsing-error swap >>name ;
+M: capitalized-prolog summary ( obj -- str )
+    [
+        dup call-next-method write
+        "XML prolog name was partially or totally capitalized, using" print
+        "> write "...?>" write
+        " instead of " print
+    ] with-string-writer ;
+
+TUPLE: versionless-prolog < parsing-error ;
 :  ( -- versionless-prolog )
-    { } versionless-prolog construct-parsing-error ;
-M: versionless-prolog error.
-    parsing-error.
-    "XML prolog lacks a version declaration" print ;
+    \ versionless-prolog parsing-error ;
+M: versionless-prolog summary ( obj -- str )
+    [
+        call-next-method write
+        "XML prolog lacks a version declaration" print
+    ] with-string-writer ;
 
-TUPLE: bad-instruction inst ;
+TUPLE: bad-instruction < parsing-error instruction ;
 :  ( instruction -- bad-instruction )
-    { set-bad-instruction-inst }
-    bad-instruction construct-parsing-error ;
-M: bad-instruction error.
-    dup parsing-error.
-    "Misplaced processor instruction:" print
-    bad-instruction-inst write-item nl ;
+    \ bad-instruction parsing-error swap >>instruction ;
+M: bad-instruction summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Misplaced processor instruction:" print
+        bad-instruction-inst write-item nl
+    ] with-string-writer ;
 
-TUPLE: bad-directive dir ;
+TUPLE: bad-directive < parsing-error dir ;
 :  ( directive -- bad-directive )
-    { set-bad-directive-dir }
-    bad-directive construct-parsing-error ;
-M: bad-directive error.
-    dup parsing-error.
-    "Misplaced directive:" print
-    bad-directive-dir write-item nl ;
+    \ bad-directive parsing-error swap >>dir ;
+M: bad-directive summary ( obj -- str )
+    [
+        dup call-next-method write
+        "Misplaced directive:" print
+        bad-directive-dir write-item nl
+    ] with-string-writer ;
 
 UNION: xml-parse-error multitags notags extra-attrs nonexist-ns
        not-yes/no unclosed mismatched xml-string-error expected no-entity
diff --git a/extra/xml/tests/errors.factor b/extra/xml/tests/errors.factor
deleted file mode 100755
index 6ba0b0d560..0000000000
--- a/extra/xml/tests/errors.factor
+++ /dev/null
@@ -1,28 +0,0 @@
-USING: continuations xml xml.errors tools.test kernel arrays xml.data state-parser quotations ;
-IN: xml.tests
-
-: xml-error-test ( expected-error xml-string -- )
-    [ string>xml ] curry swap [ = ] curry must-fail-with ;
-
-T{ no-entity T{ parsing-error f 1 10 } "nbsp" } " " xml-error-test
-T{ mismatched T{ parsing-error f 1 8 } T{ name f "" "x" "" } T{ name f "" "y" "" }
-} "" xml-error-test
-T{ unclosed f V{ T{ name f "" "x" "" } } } "" xml-error-test
-T{ nonexist-ns T{ parsing-error f 1 5 } "x" } "" xml-error-test
-T{ unopened T{ parsing-error f 1 5 } } "" xml-error-test
-T{ not-yes/no T{ parsing-error f 1 41 } "maybe" } "" xml-error-test
-T{ extra-attrs T{ parsing-error f 1 32 } V{ T{ name f "" "foo" f } }
-} "" xml-error-test
-T{ bad-version T{ parsing-error f 1 28 } "5 million" } "" xml-error-test
-T{ notags f } "" xml-error-test
-T{ multitags f } "" xml-error-test
-T{ bad-prolog T{ parsing-error f 1 26 } T{ prolog f "1.0" "UTF-8" f }
-} "" xml-error-test
-T{ capitalized-prolog T{ parsing-error f 1 6 } "XmL" } ""
-xml-error-test
-T{ pre/post-content f "x" t } "x" xml-error-test
-T{ versionless-prolog T{ parsing-error f 1 8 } } "" xml-error-test
-T{ bad-instruction T{ parsing-error f 1 11 } T{ instruction f "xsl" }
-} "" xml-error-test
-T{ bad-directive T{ parsing-error f 1 15 } T{ directive f "DOCTYPE" }
-} "" xml-error-test
diff --git a/extra/xml/xml.factor b/extra/xml/xml.factor
index 2d7c8c8ff8..f45b27b030 100644
--- a/extra/xml/xml.factor
+++ b/extra/xml/xml.factor
@@ -3,18 +3,12 @@
 USING: io io.streams.string io.files kernel math namespaces
 prettyprint sequences arrays generic strings vectors
 xml.char-classes xml.data xml.errors xml.tokenize xml.writer
-xml.utilities state-parser assocs ascii io.encodings.utf8 ;
+xml.utilities state-parser assocs ascii io.encodings.utf8
+accessors xml.backend ;
 IN: xml
 
 !   -- Overall parser with data tree
 
-! A stack of { tag children } pairs
-SYMBOL: xml-stack
-
-:  ( -- unclosed )
-    xml-stack get rest-slice [ first opener-name ] map
-    { set-unclosed-tags } unclosed construct ;
-
 : add-child ( object -- )
     xml-stack get peek second push ;
 

From 9e726f40aa58516760f3fbb0f5567b7f9a709cfb Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Mon, 5 May 2008 13:27:14 -0500
Subject: [PATCH 03/10] add more unit tests

---
 extra/taxes/taxes-tests.factor | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/extra/taxes/taxes-tests.factor b/extra/taxes/taxes-tests.factor
index 6aeb5aa098..32dbd0d625 100644
--- a/extra/taxes/taxes-tests.factor
+++ b/extra/taxes/taxes-tests.factor
@@ -96,3 +96,21 @@ IN: taxes.tests
     1000000 2008 3 t   net
     dollars/cents
 ] unit-test
+
+
+[ 30 97 ] [
+    24000 2008 2 f   withholding biweekly dollars/cents
+] unit-test
+
+[ 173 66 ] [
+    78250 2008 2 f   withholding biweekly dollars/cents
+] unit-test
+
+
+[ 138 69 ] [
+    24000 2008 2 f   withholding biweekly dollars/cents
+] unit-test
+
+[ 754 22 ] [
+    78250 2008 2 f   withholding biweekly dollars/cents
+] unit-test

From 6590c60cb31abe90449142388db96733819a308c Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 11:27:13 -0500
Subject: [PATCH 04/10] fix bootstrap

---
 core/debugger/debugger-docs.factor | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/debugger/debugger-docs.factor b/core/debugger/debugger-docs.factor
index cb79597a73..3fbac64099 100755
--- a/core/debugger/debugger-docs.factor
+++ b/core/debugger/debugger-docs.factor
@@ -1,7 +1,7 @@
 USING: alien arrays generic generic.math help.markup help.syntax
 kernel math memory strings sbufs vectors io io.files classes
 help generic.standard continuations system debugger.private
-io.files.private ;
+io.files.private listener ;
 IN: debugger
 
 ARTICLE: "errors-assert" "Assertions"

From 0b21c84e75fe3ed1689c656338bf5f9d17d232dd Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 12:16:04 -0500
Subject: [PATCH 05/10] fix errors i introduced with the state-parser cleanup

---
 extra/xml/errors/errors.factor | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/extra/xml/errors/errors.factor b/extra/xml/errors/errors.factor
index 3e24d7e720..53f2046a54 100644
--- a/extra/xml/errors/errors.factor
+++ b/extra/xml/errors/errors.factor
@@ -119,9 +119,8 @@ M: bad-version summary ( obj -- str )
         num>> .
     ] with-string-writer ;
 
-TUPLE: notags < parsing-error ;
-: 
-    \ notags parsing-error ;
+TUPLE: notags ;
+C:  notags
 M: notags summary ( obj -- str )
     drop "XML document lacks a main tag" ;
 
@@ -162,7 +161,7 @@ M: bad-instruction summary ( obj -- str )
     [
         dup call-next-method write
         "Misplaced processor instruction:" print
-        bad-instruction-inst write-item nl
+        instruction>> write-item nl
     ] with-string-writer ;
 
 TUPLE: bad-directive < parsing-error dir ;

From e7713148337d2d958c40d3529836b3d2aa936a68 Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 12:36:32 -0500
Subject: [PATCH 06/10] add butlast and butlast-slice with docs

---
 core/sequences/sequences-docs.factor | 14 +++++++++++++-
 core/sequences/sequences.factor      |  8 ++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/core/sequences/sequences-docs.factor b/core/sequences/sequences-docs.factor
index 2a2fcf29cd..67d26089b0 100755
--- a/core/sequences/sequences-docs.factor
+++ b/core/sequences/sequences-docs.factor
@@ -92,6 +92,7 @@ ARTICLE: "sequences-slices" "Subsequences and slices"
 { $subsection subseq }
 { $subsection head }
 { $subsection tail }
+{ $subsection butlast }
 { $subsection rest }
 { $subsection head* }
 { $subsection tail* }
@@ -106,6 +107,7 @@ ARTICLE: "sequences-slices" "Subsequences and slices"
 { $subsection  }
 { $subsection head-slice }
 { $subsection tail-slice }
+{ $subsection butlast-slice }
 { $subsection rest-slice }
 { $subsection head-slice* }
 { $subsection tail-slice* }
@@ -836,11 +838,16 @@ HELP: tail-slice
 { $description "Outputs a virtual sequence sharing storage with all elements from the " { $snippet "n" } "th index until the end of the input sequence." }
 { $errors "Throws an error if the index is out of bounds." } ;
 
+HELP: butlast-slice
+{ $values { "seq" sequence } { "slice" "a slice" } }
+{ $description "Outputs a virtual sequence sharing storage with all but the last element of the input sequence." }
+{ $errors "Throws an error on an empty sequence." } ;
+
 HELP: rest-slice
 { $values { "seq" sequence } { "slice" "a slice" } }
 { $description "Outputs a virtual sequence sharing storage with all elements from the 1st index until the end of the input sequence." }
 { $notes "Equivalent to " { $snippet "1 tail" } }
-{ $errors "Throws an error if the index is out of bounds." } ;
+{ $errors "Throws an error on an empty sequence." } ;
 
 HELP: head-slice*
 { $values { "seq" sequence } { "n" "a non-negative integer" } { "slice" "a slice" } }
@@ -862,6 +869,11 @@ HELP: tail
 { $description "Outputs a new sequence consisting of the input sequence with the first n items removed." }
 { $errors "Throws an error if the index is out of bounds." } ;
 
+HELP: butlast
+{ $values { "seq" sequence } { "headseq" "a new sequence" } }
+{ $description "Outputs a new sequence consisting of the input sequence with the last item removed." }
+{ $errors "Throws an error on an empty sequence." } ;
+
 HELP: rest
 { $values { "seq" sequence } { "tailseq" "a new sequence" } }
 { $description "Outputs a new sequence consisting of the input sequence with the first item removed." }
diff --git a/core/sequences/sequences.factor b/core/sequences/sequences.factor
index f39bf08e58..1e9d187c2d 100755
--- a/core/sequences/sequences.factor
+++ b/core/sequences/sequences.factor
@@ -216,6 +216,8 @@ M: slice length dup slice-to swap slice-from - ;
 
 : tail-slice* ( seq n -- slice ) from-end tail-slice ;
 
+: butlast-slice ( seq -- slice ) 1 head-slice* ;
+
 INSTANCE: slice virtual-sequence
 
 ! One element repeated many times
@@ -263,6 +265,8 @@ PRIVATE>
 
 : tail* ( seq n -- tailseq ) from-end tail ;
 
+: butlast ( seq -- headseq ) 1 head* ;
+
 : copy ( src i dst -- )
     pick length >r 3dup check-copy spin 0 r>
     (copy) drop ; inline
@@ -671,13 +675,13 @@ PRIVATE>
     [ rest ] [ first ] bi ;
 
 : unclip-last ( seq -- butfirst last )
-    [ 1 head* ] [ peek ] bi ;
+    [ butlast ] [ peek ] bi ;
 
 : unclip-slice ( seq -- rest first )
     [ rest-slice ] [ first ] bi ;
 
 : unclip-last-slice ( seq -- butfirst last )
-    [ 1 head-slice* ] [ peek ] bi ;
+    [ butlast-slice ] [ peek ] bi ;
 
 :  ( seq -- slice )
     dup slice? [ { } like ] when 0 over length rot  ;

From 01f20cf32d664743d4e86a5f45e364b4dedc0cee Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 12:36:49 -0500
Subject: [PATCH 07/10] update core to use butlast, butlast-slice

---
 core/classes/tuple/tuple.factor             | 2 +-
 core/inference/transforms/transforms.factor | 2 +-
 core/prettyprint/prettyprint-tests.factor   | 2 +-
 core/prettyprint/sections/sections.factor   | 2 +-
 core/splitting/splitting.factor             | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/core/classes/tuple/tuple.factor b/core/classes/tuple/tuple.factor
index ee7ff8c608..fb6f1ffba0 100755
--- a/core/classes/tuple/tuple.factor
+++ b/core/classes/tuple/tuple.factor
@@ -102,7 +102,7 @@ ERROR: bad-superclass class ;
     dup tuple-predicate-quot define-predicate ;
 
 : superclass-size ( class -- n )
-    superclasses 1 head-slice*
+    superclasses butlast-slice
     [ slot-names length ] map sum ;
 
 : generate-tuple-slots ( class slots -- slot-specs )
diff --git a/core/inference/transforms/transforms.factor b/core/inference/transforms/transforms.factor
index 624dcbbf98..cf3dcadd75 100755
--- a/core/inference/transforms/transforms.factor
+++ b/core/inference/transforms/transforms.factor
@@ -32,7 +32,7 @@ IN: inference.transforms
         drop [ no-case ]
     ] [
         dup peek quotation? [
-            dup peek swap 1 head*
+            dup peek swap butlast
         ] [
             [ no-case ] swap
         ] if case>quot
diff --git a/core/prettyprint/prettyprint-tests.factor b/core/prettyprint/prettyprint-tests.factor
index e94670992c..834cad5b29 100755
--- a/core/prettyprint/prettyprint-tests.factor
+++ b/core/prettyprint/prettyprint-tests.factor
@@ -114,7 +114,7 @@ unit-test
             [ parse-fresh drop ] with-compilation-unit
             [
                 "prettyprint.tests" lookup see
-            ] with-string-writer "\n" split 1 head*
+            ] with-string-writer "\n" split butlast
         ] keep =
     ] with-scope ;
 
diff --git a/core/prettyprint/sections/sections.factor b/core/prettyprint/sections/sections.factor
index 5f32539115..0ce8841256 100644
--- a/core/prettyprint/sections/sections.factor
+++ b/core/prettyprint/sections/sections.factor
@@ -284,7 +284,7 @@ M: colon unindent-first-line? drop t ;
 
 ! Long section layout algorithm
 : chop-break ( seq -- seq )
-    dup peek line-break? [ 1 head-slice* chop-break ] when ;
+    dup peek line-break? [ butlast-slice chop-break ] when ;
 
 SYMBOL: prev
 SYMBOL: next
diff --git a/core/splitting/splitting.factor b/core/splitting/splitting.factor
index 62c5121e50..be0652fd98 100755
--- a/core/splitting/splitting.factor
+++ b/core/splitting/splitting.factor
@@ -104,7 +104,7 @@ M: sliced-clumps nth group@  ;
         1array
     ] [
         "\n" split [
-            1 head-slice* [
+            butlast-slice [
                 "\r" ?tail drop "\r" split
             ] map
         ] keep peek "\r" split suffix concat

From 7c09936f30ff9827335d0ffd77124f32d373bd33 Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 12:37:11 -0500
Subject: [PATCH 08/10] use butlast, butlast-slice "extra/foo" resource-path ->
 "resource:extra/foo"

---
 .../benchmark/knucleotide/knucleotide.factor  |  2 +-
 extra/combinators/lib/lib.factor              |  5 +++++
 extra/help/lint/lint.factor                   |  2 +-
 extra/html/parser/analyzer/analyzer.factor    |  2 +-
 extra/html/parser/utils/utils.factor          |  2 +-
 extra/http/http-tests.factor                  |  4 ++--
 extra/icfp/2006/2006.factor                   |  2 +-
 extra/inverse/inverse.factor                  |  2 +-
 extra/io/encodings/8-bit/8-bit.factor         |  5 ++---
 .../windows/nt/launcher/launcher-tests.factor | 14 ++++++-------
 extra/koszul/koszul.factor                    |  2 +-
 extra/locals/locals.factor                    |  2 +-
 extra/mortar/mortar.factor                    |  2 +-
 extra/multiline/multiline.factor              |  4 ++--
 extra/openssl/openssl-tests.factor            | 10 +++++-----
 .../porter-stemmer-tests.factor               |  6 ++----
 extra/porter-stemmer/porter-stemmer.factor    | 12 +++++------
 extra/project-euler/002/002.factor            |  2 +-
 extra/project-euler/022/022.factor            |  2 +-
 extra/project-euler/042/042.factor            |  2 +-
 extra/project-euler/059/059.factor            |  4 ++--
 extra/project-euler/067/067.factor            |  2 +-
 extra/project-euler/079/079.factor            |  2 +-
 extra/rss/rss-tests.factor                    |  4 ++--
 extra/space-invaders/space-invaders.factor    | 20 +++++++++----------
 extra/tangle/tangle.factor                    |  2 +-
 extra/tools/deploy/backend/backend.factor     |  4 ++--
 extra/tuple-syntax/tuple-syntax.factor        |  2 +-
 extra/ui/gestures/gestures.factor             |  2 +-
 extra/unicode/breaks/breaks.factor            |  2 +-
 extra/unicode/data/data.factor                |  4 ++--
 extra/xml/tests/soap.factor                   |  2 +-
 extra/xml/tests/test.factor                   |  2 +-
 extra/xmode/catalog/catalog.factor            |  6 +++---
 extra/xmode/code2html/code2html.factor        |  4 ++--
 extra/xmode/utilities/utilities-tests.factor  |  4 ++--
 extra/yahoo/yahoo-tests.factor                |  2 +-
 37 files changed, 76 insertions(+), 76 deletions(-)

diff --git a/extra/benchmark/knucleotide/knucleotide.factor b/extra/benchmark/knucleotide/knucleotide.factor
index e06b81f6de..6bd2d69cfa 100644
--- a/extra/benchmark/knucleotide/knucleotide.factor
+++ b/extra/benchmark/knucleotide/knucleotide.factor
@@ -56,7 +56,7 @@ IN: benchmark.knucleotide
     drop ;
 
 : knucleotide ( -- )
-    "extra/benchmark/knucleotide/knucleotide-input.txt" resource-path
+    "resource:extra/benchmark/knucleotide/knucleotide-input.txt"
     ascii [ read-input ] with-file-reader
     process-input ;
 
diff --git a/extra/combinators/lib/lib.factor b/extra/combinators/lib/lib.factor
index 84b41a91ff..5dfe8527c1 100755
--- a/extra/combinators/lib/lib.factor
+++ b/extra/combinators/lib/lib.factor
@@ -169,3 +169,8 @@ MACRO: multikeep ( word out-indexes -- ... )
 : generate ( generator predicate -- obj )
     [ dup ] swap [ dup [ nip ] unless not ] 3compose
     swap [ ] do-while ;
+
+MACRO: predicates ( seq -- quot/f )
+    dup [ 1quotation [ drop ] prepend ] map
+    >r [ [ dup ] prepend ] map r> zip [ drop f ] suffix
+    [ cond ] curry ;
diff --git a/extra/help/lint/lint.factor b/extra/help/lint/lint.factor
index fc4b7f6f25..a120d791aa 100755
--- a/extra/help/lint/lint.factor
+++ b/extra/help/lint/lint.factor
@@ -10,7 +10,7 @@ IN: help.lint
 
 : check-example ( element -- )
     rest [
-        1 head* "\n" join 1vector
+        butlast "\n" join 1vector
         [
             use [ clone ] change
             [ eval>string ] with-datastack
diff --git a/extra/html/parser/analyzer/analyzer.factor b/extra/html/parser/analyzer/analyzer.factor
index 160b95ab1d..1912cfb65c 100755
--- a/extra/html/parser/analyzer/analyzer.factor
+++ b/extra/html/parser/analyzer/analyzer.factor
@@ -99,7 +99,7 @@ IN: html.parser.analyzer
     
 : find-between ( i/f tag/f vector -- vector )
     find-between* dup length 3 >= [
-        [ rest-slice 1 head-slice* ] keep like
+        [ rest-slice butlast-slice ] keep like
     ] when ;
 
 : find-between-first ( string vector -- vector' )
diff --git a/extra/html/parser/utils/utils.factor b/extra/html/parser/utils/utils.factor
index 0ae75e41fd..c0eee57ead 100644
--- a/extra/html/parser/utils/utils.factor
+++ b/extra/html/parser/utils/utils.factor
@@ -36,7 +36,7 @@ IN: html.parser.utils
     dup quoted? [ quote ] unless ;
 
 : unquote ( str -- newstr )
-    dup quoted? [ 1 head-slice* rest-slice >string ] when ;
+    dup quoted? [ butlast-slice rest-slice >string ] when ;
 
 : quote? ( ch -- ? ) "'\"" member? ;
 
diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor
index 07b34f17c3..21eb241b84 100755
--- a/extra/http/http-tests.factor
+++ b/extra/http/http-tests.factor
@@ -166,7 +166,7 @@ test-db [
         
             add-quit-action
             
-                "extra/http/test" resource-path  >>default
+                "resource:extra/http/test"  >>default
             "nested" add-responder
             
                 [ "redirect-loop" f  ] >>display
@@ -178,7 +178,7 @@ test-db [
 ] unit-test
 
 [ t ] [
-    "extra/http/test/foo.html" resource-path ascii file-contents
+    "resource:extra/http/test/foo.html" ascii file-contents
     "http://localhost:1237/nested/foo.html" http-get =
 ] unit-test
 
diff --git a/extra/icfp/2006/2006.factor b/extra/icfp/2006/2006.factor
index e88301c7f8..ca6f9d5905 100755
--- a/extra/icfp/2006/2006.factor
+++ b/extra/icfp/2006/2006.factor
@@ -148,4 +148,4 @@ SYMBOL: open-arrays
     init f exec-loop ;
 
 : run-sand ( -- )
-    "extra/icfp/2006/sandmark.umz" resource-path run-prog ;
+    "resource:extra/icfp/2006/sandmark.umz" run-prog ;
diff --git a/extra/inverse/inverse.factor b/extra/inverse/inverse.factor
index 265675f8df..8c19ade499 100755
--- a/extra/inverse/inverse.factor
+++ b/extra/inverse/inverse.factor
@@ -197,7 +197,7 @@ DEFER: _
 
 \ prefix [ unclip ] define-inverse
 \ unclip [ prefix ] define-inverse
-\ suffix [ dup 1 head* swap peek ] define-inverse
+\ suffix [ dup butlast swap peek ] define-inverse
 
 ! Constructor inverse
 : deconstruct-pred ( class -- quot )
diff --git a/extra/io/encodings/8-bit/8-bit.factor b/extra/io/encodings/8-bit/8-bit.factor
index 3fbb3908e2..88414efd16 100755
--- a/extra/io/encodings/8-bit/8-bit.factor
+++ b/extra/io/encodings/8-bit/8-bit.factor
@@ -30,9 +30,8 @@ IN: io.encodings.8-bit
 } ;
 
 : encoding-file ( file-name -- stream )
-    "extra/io/encodings/8-bit/" ".TXT"
-    swapd 3append resource-path
-    ascii  ;
+    "resource:extra/io/encodings/8-bit/" ".TXT"
+    swapd 3append ascii  ;
 
 : tail-if ( seq n -- newseq )
     2dup swap length <= [ tail ] [ drop ] if ;
diff --git a/extra/io/windows/nt/launcher/launcher-tests.factor b/extra/io/windows/nt/launcher/launcher-tests.factor
index c5c0e6dec2..254f845c48 100755
--- a/extra/io/windows/nt/launcher/launcher-tests.factor
+++ b/extra/io/windows/nt/launcher/launcher-tests.factor
@@ -41,7 +41,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "stderr.factor" 3array >>command
             "out.txt" temp-file >>stdout
@@ -59,7 +59,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "stderr.factor" 3array >>command
             "out.txt" temp-file >>stdout
@@ -73,7 +73,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ "output" ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "stderr.factor" 3array >>command
             "err2.txt" temp-file >>stderr
@@ -86,7 +86,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ t ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "env.factor" 3array >>command
         ascii  contents
@@ -96,7 +96,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ t ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "env.factor" 3array >>command
             +replace-environment+ >>environment-mode
@@ -108,7 +108,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ "B" ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "env.factor" 3array >>command
             { { "A" "B" } } >>environment
@@ -119,7 +119,7 @@ sequences parser assocs hashtables math continuations ;
 ] unit-test
 
 [ f ] [
-    "extra/io/windows/nt/launcher/test" resource-path [
+    "resource:extra/io/windows/nt/launcher/test" [
         
             vm "-script" "env.factor" 3array >>command
             { { "HOME" "XXX" } } >>environment
diff --git a/extra/koszul/koszul.factor b/extra/koszul/koszul.factor
index e9de82ebb6..5c337f8ce7 100755
--- a/extra/koszul/koszul.factor
+++ b/extra/koszul/koszul.factor
@@ -184,7 +184,7 @@ DEFER: (d)
     [ length ] keep [ (graded-ker/im-d) ] curry map ;
 
 : graded-betti ( generators -- seq )
-    basis graded graded-ker/im-d flip first2 1 head* 0 prefix v- ;
+    basis graded graded-ker/im-d flip first2 butlast 0 prefix v- ;
 
 ! Bi-graded for two-step complexes
 : (bigraded-ker/im-d) ( u-deg z-deg bigraded-basis -- null/rank )
diff --git a/extra/locals/locals.factor b/extra/locals/locals.factor
index d18017f69b..4ad81ef00a 100755
--- a/extra/locals/locals.factor
+++ b/extra/locals/locals.factor
@@ -101,7 +101,7 @@ UNION: special local quote local-word local-reader local-writer ;
     ] if ;
 
 : point-free-body ( quot args -- newquot )
-    >r 1 head-slice* r> [ localize ] curry map concat ;
+    >r butlast-slice r> [ localize ] curry map concat ;
 
 : point-free-end ( quot args -- newquot )
     over peek special?
diff --git a/extra/mortar/mortar.factor b/extra/mortar/mortar.factor
index b7862af7ac..3d4d287ace 100644
--- a/extra/mortar/mortar.factor
+++ b/extra/mortar/mortar.factor
@@ -122,7 +122,7 @@ over class-class-methods assoc-stack call ;
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : send-message-next ( object message -- )
-over object-class class-methods 1 head* assoc-stack call ;
+over object-class class-methods butlast assoc-stack call ;
 
 : <-~ scan parsed \ send-message-next parsed ; parsing
 
diff --git a/extra/multiline/multiline.factor b/extra/multiline/multiline.factor
index e140c5227c..acff8c8669 100755
--- a/extra/multiline/multiline.factor
+++ b/extra/multiline/multiline.factor
@@ -14,7 +14,7 @@ IN: multiline
     ] [ ";" unexpected-eof ] if* ;
 
 : parse-here ( -- str )
-    [ (parse-here) ] "" make 1 head*
+    [ (parse-here) ] "" make butlast
     lexer get next-line ;
 
 : STRING:
@@ -34,7 +34,7 @@ IN: multiline
     [
         lexer get lexer-column swap (parse-multiline-string)
         lexer get set-lexer-column
-    ] "" make rest 1 head* ;
+    ] "" make rest butlast ;
 
 : <"
     "\">" parse-multiline-string parsed ; parsing
diff --git a/extra/openssl/openssl-tests.factor b/extra/openssl/openssl-tests.factor
index f42c611fc0..2b840bdb9c 100755
--- a/extra/openssl/openssl-tests.factor
+++ b/extra/openssl/openssl-tests.factor
@@ -27,7 +27,7 @@ math.parser openssl prettyprint sequences tools.test ;
 
 [ ] [ ssl-v23 new-ctx ] unit-test
 
-[ ] [ get-ctx "extra/openssl/test/server.pem" resource-path use-cert-chain ] unit-test
+[ ] [ get-ctx "resource:extra/openssl/test/server.pem" use-cert-chain ] unit-test
 
 ! TODO: debug 'Memory protection fault at address 6c'
 ! get-ctx 1024 "char" malloc-array 1024 0 f password-cb set-default-passwd
@@ -35,10 +35,10 @@ math.parser openssl prettyprint sequences tools.test ;
 [ ] [ get-ctx "password" ascii string>alien set-default-passwd-userdata ] unit-test
 
 ! Enter PEM pass phrase: password
-[ ] [ get-ctx "extra/openssl/test/server.pem" resource-path
+[ ] [ get-ctx "resource:extra/openssl/test/server.pem"
 SSL_FILETYPE_PEM use-private-key ] unit-test
 
-[ ] [ get-ctx "extra/openssl/test/root.pem" resource-path f
+[ ] [ get-ctx "resource:extra/openssl/test/root.pem" f
 verify-load-locations ] unit-test
 
 [ ] [ get-ctx 1 set-verify-depth ] unit-test
@@ -47,7 +47,7 @@ verify-load-locations ] unit-test
 ! Load Diffie-Hellman parameters
 ! =========================================================
 
-[ ] [ "extra/openssl/test/dh1024.pem" resource-path "r" bio-new-file ] unit-test
+[ ] [ "resource:extra/openssl/test/dh1024.pem" "r" bio-new-file ] unit-test
 
 [ ] [ get-bio f f f read-pem-dh-params ] unit-test
 
@@ -131,7 +131,7 @@ verify-load-locations ] unit-test
 ! Dump errors to file
 ! =========================================================
 
-[ ] [ "extra/openssl/test/errors.txt" resource-path "w" bio-new-file ] unit-test
+[ ] [ "resource:extra/openssl/test/errors.txt" "w" bio-new-file ] unit-test
 
 [ 6 ] [ get-bio "Hello\n" bio-print ] unit-test
 
diff --git a/extra/porter-stemmer/porter-stemmer-tests.factor b/extra/porter-stemmer/porter-stemmer-tests.factor
index 32386fed2b..42c358646b 100644
--- a/extra/porter-stemmer/porter-stemmer-tests.factor
+++ b/extra/porter-stemmer/porter-stemmer-tests.factor
@@ -56,11 +56,9 @@ io.files io.encodings.utf8 ;
 [ "hell" ] [ "hell" step5 "" like ] unit-test
 [ "mate" ] [ "mate" step5 "" like ] unit-test
 
-: resource-lines resource-path utf8 file-lines ;
-
 [ { } ] [
-    "extra/porter-stemmer/test/voc.txt" resource-lines
+    "resource:extra/porter-stemmer/test/voc.txt" utf8 file-lines
     [ stem ] map
-    "extra/porter-stemmer/test/output.txt" resource-lines
+    "resource:extra/porter-stemmer/test/output.txt" utf8 file-lines
     [ 2array ] 2map [ first2 = not ] filter
 ] unit-test
diff --git a/extra/porter-stemmer/porter-stemmer.factor b/extra/porter-stemmer/porter-stemmer.factor
index 81820e0152..f6975ccce7 100644
--- a/extra/porter-stemmer/porter-stemmer.factor
+++ b/extra/porter-stemmer/porter-stemmer.factor
@@ -66,8 +66,6 @@ USING: kernel math parser sequences combinators splitting ;
 : r ( str oldsuffix newsuffix -- str )
     pick consonant-seq 0 > [ nip ] [ drop ] if append ;
 
-: butlast ( seq -- seq ) 1 head-slice* ;
-
 : step1a ( str -- newstr )
     dup peek CHAR: s = [
         {
@@ -95,7 +93,7 @@ USING: kernel math parser sequences combinators splitting ;
         { [ "iz" ?tail ] [ "ize" append ] }
         {
             [ dup length 1- over double-consonant? ]
-            [ dup "lsz" last-is? [ butlast ] unless ]
+            [ dup "lsz" last-is? [ butlast-slice ] unless ]
         }
         {
             [ t ]
@@ -122,7 +120,7 @@ USING: kernel math parser sequences combinators splitting ;
     } cond ;
 
 : step1c ( str -- newstr )
-    dup butlast stem-vowel? [
+    dup butlast-slice stem-vowel? [
         "y" ?tail [ "i" append ] when
     ] when ;
 
@@ -198,18 +196,18 @@ USING: kernel math parser sequences combinators splitting ;
 : remove-e? ( str -- ? )
     dup consonant-seq dup 1 >
     [ 2drop t ]
-    [ 1 = [ butlast cvc? not ] [ drop f ] if ] if ;
+    [ 1 = [ butlast-slice cvc? not ] [ drop f ] if ] if ;
 
 : remove-e ( str -- newstr )
     dup peek CHAR: e = [
-        dup remove-e? [ butlast ] when
+        dup remove-e? [ butlast-slice ] when
     ] when ;
 
 : ll->l ( str -- newstr )
     {
         { [ dup peek CHAR: l = not ] [ ] }
         { [ dup length 1- over double-consonant? not ] [ ] }
-        { [ dup consonant-seq 1 > ] [ butlast ] }
+        { [ dup consonant-seq 1 > ] [ butlast-slice ] }
         [ ]
     } cond ;
 
diff --git a/extra/project-euler/002/002.factor b/extra/project-euler/002/002.factor
index c2def03ace..6c9d331c90 100644
--- a/extra/project-euler/002/002.factor
+++ b/extra/project-euler/002/002.factor
@@ -41,7 +41,7 @@ PRIVATE>
 
 : fib-upto* ( n -- seq )
     0 1 [ pick over >= ] [ tuck + dup ] [ ] unfold 3nip
-    1 head-slice* { 0 1 } prepend ;
+    butlast-slice { 0 1 } prepend ;
 
 : euler002a ( -- answer )
     1000000 fib-upto* [ even? ] filter sum ;
diff --git a/extra/project-euler/022/022.factor b/extra/project-euler/022/022.factor
index 452d2ec637..82054ce014 100644
--- a/extra/project-euler/022/022.factor
+++ b/extra/project-euler/022/022.factor
@@ -28,7 +28,7 @@ IN: project-euler.022
 number ] map ;
 
@@ -78,7 +78,7 @@ INSTANCE: rollover immutable-sequence
     frequency-analysis sort-values keys peek ;
 
 : crack-key ( seq key-length -- key )
-    [ " " decrypt ] dip group 1 head-slice*
+    [ " " decrypt ] dip group butlast-slice
     flip [ most-frequent ] map ;
 
 PRIVATE>
diff --git a/extra/project-euler/067/067.factor b/extra/project-euler/067/067.factor
index 436ccde776..3e16996e04 100644
--- a/extra/project-euler/067/067.factor
+++ b/extra/project-euler/067/067.factor
@@ -38,7 +38,7 @@ IN: project-euler.067
 number ] map ] map ;
 
 PRIVATE>
diff --git a/extra/project-euler/079/079.factor b/extra/project-euler/079/079.factor
index 3674804b0c..cde4dc079b 100644
--- a/extra/project-euler/079/079.factor
+++ b/extra/project-euler/079/079.factor
@@ -27,7 +27,7 @@ IN: project-euler.079
 edges ( seq -- seq )
     [
diff --git a/extra/rss/rss-tests.factor b/extra/rss/rss-tests.factor
index 252defe99b..0e6bb0b9c1 100755
--- a/extra/rss/rss-tests.factor
+++ b/extra/rss/rss-tests.factor
@@ -22,7 +22,7 @@ IN: rss.tests
             f
         }
     }
-} ] [ "extra/rss/rss1.xml" resource-path load-news-file ] unit-test
+} ] [ "resource:extra/rss/rss1.xml" load-news-file ] unit-test
 [ T{
     feed
     f
@@ -39,4 +39,4 @@ IN: rss.tests
             T{ timestamp f 2003 12 13 8 29 29 T{ duration f 0 0 0 -4 0 0 } }
         }
     }
-} ] [ "extra/rss/atom.xml" resource-path load-news-file ] unit-test
+} ] [ "resource:extra/rss/atom.xml" load-news-file ] unit-test
diff --git a/extra/space-invaders/space-invaders.factor b/extra/space-invaders/space-invaders.factor
index 200257b31c..f773d331b1 100755
--- a/extra/space-invaders/space-invaders.factor
+++ b/extra/space-invaders/space-invaders.factor
@@ -45,21 +45,21 @@ TUPLE: space-invaders port1 port2i port2o port3o port4lo port4hi port5o bitmap s
 
 : init-sound ( index cpu filename  -- )
   swapd >r space-invaders-sounds nth AL_BUFFER r> 
-  resource-path create-buffer-from-wav set-source-param ; 
+  create-buffer-from-wav set-source-param ; 
 
 : init-sounds ( cpu -- )
   init-openal
   [ 9 gen-sources swap set-space-invaders-sounds ] keep
-  [ SOUND-SHOT        "extra/space-invaders/resources/Shot.wav" init-sound ] keep 
-  [ SOUND-UFO         "extra/space-invaders/resources/Ufo.wav" init-sound ] keep 
+  [ SOUND-SHOT        "resource:extra/space-invaders/resources/Shot.wav" init-sound ] keep 
+  [ SOUND-UFO         "resource:extra/space-invaders/resources/Ufo.wav" init-sound ] keep 
   [ space-invaders-sounds SOUND-UFO swap nth AL_LOOPING AL_TRUE set-source-param ] keep
-  [ SOUND-BASE-HIT    "extra/space-invaders/resources/BaseHit.wav" init-sound ] keep 
-  [ SOUND-INVADER-HIT "extra/space-invaders/resources/InvHit.wav" init-sound ] keep 
-  [ SOUND-WALK1       "extra/space-invaders/resources/Walk1.wav" init-sound ] keep 
-  [ SOUND-WALK2       "extra/space-invaders/resources/Walk2.wav" init-sound ] keep 
-  [ SOUND-WALK3       "extra/space-invaders/resources/Walk3.wav" init-sound ] keep 
-  [ SOUND-WALK4       "extra/space-invaders/resources/Walk4.wav" init-sound ] keep 
-  [ SOUND-UFO-HIT    "extra/space-invaders/resources/UfoHit.wav" init-sound ] keep
+  [ SOUND-BASE-HIT    "resource:extra/space-invaders/resources/BaseHit.wav" init-sound ] keep 
+  [ SOUND-INVADER-HIT "resource:extra/space-invaders/resources/InvHit.wav" init-sound ] keep 
+  [ SOUND-WALK1       "resource:extra/space-invaders/resources/Walk1.wav" init-sound ] keep 
+  [ SOUND-WALK2       "resource:extra/space-invaders/resources/Walk2.wav" init-sound ] keep 
+  [ SOUND-WALK3       "resource:extra/space-invaders/resources/Walk3.wav" init-sound ] keep 
+  [ SOUND-WALK4       "resource:extra/space-invaders/resources/Walk4.wav" init-sound ] keep 
+  [ SOUND-UFO-HIT    "resource:extra/space-invaders/resources/UfoHit.wav" init-sound ] keep
   f swap set-space-invaders-looping? ;
 
 :  ( -- cpu )
diff --git a/extra/tangle/tangle.factor b/extra/tangle/tangle.factor
index afaf3da3cd..52c454f97f 100644
--- a/extra/tangle/tangle.factor
+++ b/extra/tangle/tangle.factor
@@ -65,7 +65,7 @@ TUPLE: tangle-dispatcher < dispatcher tangle ;
 :  ( tangle -- dispatcher )
     tangle-dispatcher new-dispatcher swap >>tangle
      >>default
-    "extra/tangle/resources" resource-path  "resources" add-responder
+    "resource:extra/tangle/resources"  "resources" add-responder
      "node" add-responder
      [ all-node-ids  ] >>display "all" add-responder ;
 
diff --git a/extra/tools/deploy/backend/backend.factor b/extra/tools/deploy/backend/backend.factor
index ed466b6965..60d66e89cd 100755
--- a/extra/tools/deploy/backend/backend.factor
+++ b/extra/tools/deploy/backend/backend.factor
@@ -63,11 +63,11 @@ DEFER: ?make-staging-image
         dup empty? [
             "-i=" my-boot-image-name append ,
         ] [
-            dup 1 head* ?make-staging-image
+            dup butlast ?make-staging-image
 
             "-resource-path=" "" resource-path append ,
 
-            "-i=" over 1 head* staging-image-name append ,
+            "-i=" over butlast staging-image-name append ,
 
             "-run=tools.deploy.restage" ,
         ] if
diff --git a/extra/tuple-syntax/tuple-syntax.factor b/extra/tuple-syntax/tuple-syntax.factor
index 219df5197c..2b9b2c3fb4 100755
--- a/extra/tuple-syntax/tuple-syntax.factor
+++ b/extra/tuple-syntax/tuple-syntax.factor
@@ -7,7 +7,7 @@ IN: tuple-syntax
 
 : parse-slot-writer ( tuple -- slot# )
     scan dup "}" = [ 2drop f ] [
-        1 head* swap object-slots slot-named slot-spec-offset
+        butlast swap object-slots slot-named slot-spec-offset
     ] if ;
 
 : parse-slots ( accum tuple -- accum tuple )
diff --git a/extra/ui/gestures/gestures.factor b/extra/ui/gestures/gestures.factor
index 0970bd6027..d13e284160 100755
--- a/extra/ui/gestures/gestures.factor
+++ b/extra/ui/gestures/gestures.factor
@@ -54,7 +54,7 @@ TUPLE: zoom-in-action ;  C:  zoom-in-action
 TUPLE: zoom-out-action ; C:  zoom-out-action
 
 : generalize-gesture ( gesture -- newgesture )
-    tuple>array 1 head* >tuple ;
+    tuple>array butlast >tuple ;
 
 ! Modifiers
 SYMBOLS: C+ A+ M+ S+ ;
diff --git a/extra/unicode/breaks/breaks.factor b/extra/unicode/breaks/breaks.factor
index 9ee65c0018..9635a62e49 100644
--- a/extra/unicode/breaks/breaks.factor
+++ b/extra/unicode/breaks/breaks.factor
@@ -30,7 +30,7 @@ CATEGORY: grapheme-control Zl Zp Cc Cf ;
     concat [ dup ] H{ } map>assoc ;
 
 : other-extend-lines ( -- lines )
-    "extra/unicode/PropList.txt" resource-path ascii file-lines ;
+    "resource:extra/unicode/PropList.txt" ascii file-lines ;
 
 VALUE: other-extend
 
diff --git a/extra/unicode/data/data.factor b/extra/unicode/data/data.factor
index 85ce50acb9..f33338137a 100755
--- a/extra/unicode/data/data.factor
+++ b/extra/unicode/data/data.factor
@@ -14,7 +14,7 @@ IN: unicode.data
     ascii file-lines [ ";" split ] map ;
 
 : load-data ( -- data )
-    "extra/unicode/UnicodeData.txt" resource-path data ;
+    "resource:extra/unicode/UnicodeData.txt" data ;
 
 : (process-data) ( index data -- newdata )
     [ [ nth ] keep first swap 2array ] with map
@@ -120,7 +120,7 @@ VALUE: special-casing
 
 ! Special casing data
 : load-special-casing ( -- special-casing )
-    "extra/unicode/SpecialCasing.txt" resource-path data
+    "resource:extra/unicode/SpecialCasing.txt" data
     [ length 5 = ] filter
     [ [ set-code-point ] each ] H{ } make-assoc ;
 
diff --git a/extra/xml/tests/soap.factor b/extra/xml/tests/soap.factor
index 775930025f..c7452bb079 100755
--- a/extra/xml/tests/soap.factor
+++ b/extra/xml/tests/soap.factor
@@ -10,6 +10,6 @@ IN: xml.tests
     [ assemble-data ] map ;
 
 [ "http://www.foxnews.com/oreilly/" ] [
-    "extra/xml/tests/soap.xml" resource-path file>xml
+    "resource:extra/xml/tests/soap.xml" file>xml
     parse-result first first
 ] unit-test
diff --git a/extra/xml/tests/test.factor b/extra/xml/tests/test.factor
index d85345b3c7..7794930144 100644
--- a/extra/xml/tests/test.factor
+++ b/extra/xml/tests/test.factor
@@ -9,7 +9,7 @@ USING: kernel xml tools.test io namespaces sequences xml.errors xml.entities
 \ read-xml must-infer
 
 SYMBOL: xml-file
-[ ] [ "extra/xml/tests/test.xml" resource-path
+[ ] [ "resource:extra/xml/tests/test.xml"
     [ file>xml ] with-html-entities xml-file set ] unit-test
 [ "1.0" ] [ xml-file get xml-prolog prolog-version ] unit-test
 [ f ] [ xml-file get xml-prolog prolog-standalone ] unit-test
diff --git a/extra/xmode/catalog/catalog.factor b/extra/xmode/catalog/catalog.factor
index 22d3217ee6..277439c0cd 100755
--- a/extra/xmode/catalog/catalog.factor
+++ b/extra/xmode/catalog/catalog.factor
@@ -24,7 +24,7 @@ TAGS>
     ] keep ;
 
 : load-catalog ( -- modes )
-    "extra/xmode/modes/catalog" resource-path
+    "resource:extra/xmode/modes/catalog"
     file>xml parse-modes-tag ;
 
 : modes ( -- assoc )
@@ -38,8 +38,8 @@ TAGS>
 MEMO: (load-mode) ( name -- rule-sets )
     modes at [
         mode-file
-        "extra/xmode/modes/" prepend
-        resource-path utf8  parse-mode
+        "resource:extra/xmode/modes/" prepend
+        utf8  parse-mode
     ] [
         "text" (load-mode)
     ] if* ;
diff --git a/extra/xmode/code2html/code2html.factor b/extra/xmode/code2html/code2html.factor
index f6df23b9b2..3977f4277c 100755
--- a/extra/xmode/code2html/code2html.factor
+++ b/extra/xmode/code2html/code2html.factor
@@ -20,8 +20,8 @@ IN: xmode.code2html
 
 : default-stylesheet ( -- )
      ;
 
 : htmlize-stream ( path stream -- )
diff --git a/extra/xmode/utilities/utilities-tests.factor b/extra/xmode/utilities/utilities-tests.factor
index 99689d8819..a2183edbc9 100755
--- a/extra/xmode/utilities/utilities-tests.factor
+++ b/extra/xmode/utilities/utilities-tests.factor
@@ -48,6 +48,6 @@ TAGS>
         "This is a great company"
     }
 ] [
-    "extra/xmode/utilities/test.xml"
-    resource-path file>xml parse-company-tag
+    "resource:extra/xmode/utilities/test.xml"
+    file>xml parse-company-tag
 ] unit-test
diff --git a/extra/yahoo/yahoo-tests.factor b/extra/yahoo/yahoo-tests.factor
index 197fa4900b..46d05ce720 100644
--- a/extra/yahoo/yahoo-tests.factor
+++ b/extra/yahoo/yahoo-tests.factor
@@ -6,6 +6,6 @@ USING: tools.test yahoo kernel io.files xml sequences ;
     "Official Foo Fighters"
     "http://www.foofighters.com/"
     "Official site with news, tour dates, discography, store, community, and more."
-} ] [ "extra/yahoo/test-results.xml" resource-path file>xml parse-yahoo first ] unit-test
+} ] [ "resource:extra/yahoo/test-results.xml" file>xml parse-yahoo first ] unit-test
 
 [ "http://search.yahooapis.com/WebSearchService/V1/webSearch?appid=Factor-search&query=hi&results=1" ] [ "hi" 1 query ] unit-test

From 0cd8023a251e8f9015e10778b0e58450bacf5c6d Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 14:41:59 -0500
Subject: [PATCH 09/10] use resource: instead of resource-path

---
 core/io/io-tests.factor | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/core/io/io-tests.factor b/core/io/io-tests.factor
index 7204bde6fb..50a798d290 100755
--- a/core/io/io-tests.factor
+++ b/core/io/io-tests.factor
@@ -8,20 +8,17 @@ IN: io.tests
     "foo" "io.tests" lookup
 ] unit-test
 
-:  ( resource -- stream )
-    resource-path latin1  ;
-
 [
     "This is a line.\rThis is another line.\r"
 ] [
-    "core/io/test/mac-os-eol.txt" 
+    "resource:core/io/test/mac-os-eol.txt" latin1 
     [ 500 read ] with-input-stream
 ] unit-test
 
 [
     255
 ] [
-    "core/io/test/binary.txt" 
+    "resource:core/io/test/binary.txt" latin1 
     [ read1 ] with-input-stream >fixnum
 ] unit-test
 
@@ -36,7 +33,8 @@ IN: io.tests
     }
 ] [
     [
-        "core/io/test/separator-test.txt"  [
+        "resource:core/io/test/separator-test.txt"
+        latin1  [
             "J" read-until 2array ,
             "i" read-until 2array ,
             "X" read-until 2array ,

From 0acbdcdcc64eab65f108aee59a27937315d1e303 Mon Sep 17 00:00:00 2001
From: Doug Coleman 
Date: Tue, 6 May 2008 14:45:28 -0500
Subject: [PATCH 10/10] remove 

---
 core/io/encodings/encodings-tests.factor | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/core/io/encodings/encodings-tests.factor b/core/io/encodings/encodings-tests.factor
index 79922b019c..e6b180fde2 100755
--- a/core/io/encodings/encodings-tests.factor
+++ b/core/io/encodings/encodings-tests.factor
@@ -2,11 +2,8 @@ USING: io.files io.streams.string io
 tools.test kernel io.encodings.ascii ;
 IN: io.streams.encodings.tests
 
-:  ( resource -- stream )
-    resource-path ascii  ;
-    
 [ { } ]
-[ "core/io/test/empty-file.txt"  lines ]
+[ "resource:core/io/test/empty-file.txt" ascii  lines ]
 unit-test
 
 : lines-test ( stream -- line1 line2 )
@@ -16,21 +13,24 @@ unit-test
     "This is a line."
     "This is another line."
 ] [
-    "core/io/test/windows-eol.txt"  lines-test
+    "resource:core/io/test/windows-eol.txt"
+    ascii  lines-test
 ] unit-test
 
 [
     "This is a line."
     "This is another line."
 ] [
-    "core/io/test/mac-os-eol.txt"  lines-test
+    "resource:core/io/test/mac-os-eol.txt"
+    ascii  lines-test
 ] unit-test
 
 [
     "This is a line."
     "This is another line."
 ] [
-    "core/io/test/unix-eol.txt"  lines-test
+    "resource:core/io/test/unix-eol.txt"
+    ascii  lines-test
 ] unit-test
 
 [