Merge branch 'master' of git://factorcode.org/git/factor

db4
Slava Pestov 2008-06-12 18:59:25 -05:00
commit 078b2025b9
12 changed files with 169 additions and 88 deletions

View File

@ -35,7 +35,7 @@ HOOK: db-close db ( handle -- )
handle>> db-close handle>> db-close
] with-variable ; ] with-variable ;
TUPLE: statement handle sql in-params out-params bind-params bound? type ; TUPLE: statement handle sql in-params out-params bind-params bound? type retries ;
TUPLE: simple-statement < statement ; TUPLE: simple-statement < statement ;
TUPLE: prepared-statement < statement ; TUPLE: prepared-statement < statement ;

View File

@ -5,7 +5,7 @@ quotations sequences db.postgresql.ffi alien alien.c-types
db.types tools.walker ascii splitting math.parser combinators db.types tools.walker ascii splitting math.parser combinators
libc shuffle calendar.format byte-arrays destructors prettyprint libc shuffle calendar.format byte-arrays destructors prettyprint
accessors strings serialize io.encodings.binary io.encodings.utf8 accessors strings serialize io.encodings.binary io.encodings.utf8
alien.strings io.streams.byte-array inspector ; alien.strings io.streams.byte-array inspector present urls ;
IN: db.postgresql.lib IN: db.postgresql.lib
: postgresql-result-error-message ( res -- str/f ) : postgresql-result-error-message ( res -- str/f )
@ -84,6 +84,7 @@ M: postgresql-result-null summary ( obj -- str )
{ TIME [ dup [ timestamp>hms ] when default-param-value ] } { TIME [ dup [ timestamp>hms ] when default-param-value ] }
{ DATETIME [ dup [ timestamp>ymdhms ] when default-param-value ] } { DATETIME [ dup [ timestamp>ymdhms ] when default-param-value ] }
{ TIMESTAMP [ dup [ timestamp>ymdhms ] when default-param-value ] } { TIMESTAMP [ dup [ timestamp>ymdhms ] when default-param-value ] }
{ URL [ dup [ present ] when default-param-value ] }
[ drop default-param-value ] [ drop default-param-value ]
} case 2array } case 2array
] 2map flip dup empty? [ ] 2map flip dup empty? [
@ -164,6 +165,7 @@ M: postgresql-malloc-destructor dispose ( obj -- )
{ TIMESTAMP [ pq-get-string dup [ ymdhms>timestamp ] when ] } { TIMESTAMP [ pq-get-string dup [ ymdhms>timestamp ] when ] }
{ DATETIME [ pq-get-string dup [ ymdhms>timestamp ] when ] } { DATETIME [ pq-get-string dup [ ymdhms>timestamp ] when ] }
{ BLOB [ pq-get-blob ] } { BLOB [ pq-get-blob ] }
{ URL [ pq-get-string dup [ >url ] when ] }
{ FACTOR-BLOB [ { FACTOR-BLOB [
pq-get-blob pq-get-blob
dup [ bytes>object ] when ] } dup [ bytes>object ] when ] }

View File

@ -239,6 +239,7 @@ M: postgresql-db persistent-table ( -- hashtable )
{ TIMESTAMP { "timestamp" "timestamp" f } } { TIMESTAMP { "timestamp" "timestamp" f } }
{ BLOB { "bytea" "bytea" f } } { BLOB { "bytea" "bytea" f } }
{ FACTOR-BLOB { "bytea" "bytea" f } } { FACTOR-BLOB { "bytea" "bytea" f } }
{ URL { "varchar" "varchar" f } }
{ +foreign-id+ { f f "references" } } { +foreign-id+ { f f "references" } }
{ +autoincrement+ { f f "autoincrement" } } { +autoincrement+ { f f "autoincrement" } }
{ +unique+ { f f "unique" } } { +unique+ { f f "unique" } }

View File

@ -2,7 +2,8 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: accessors kernel math namespaces sequences random USING: accessors kernel math namespaces sequences random
strings math.parser math.intervals combinators strings math.parser math.intervals combinators
math.bitfields.lib namespaces.lib db db.tuples db.types ; math.bitfields.lib namespaces.lib db db.tuples db.types
sequences.lib db.sql classes words shuffle arrays ;
IN: db.queries IN: db.queries
GENERIC: where ( specs obj -- ) GENERIC: where ( specs obj -- )
@ -99,16 +100,15 @@ M: string where ( spec obj -- ) object-where ;
] with filter ; ] with filter ;
: where-clause ( tuple specs -- ) : where-clause ( tuple specs -- )
dupd filter-slots dupd filter-slots [
dup empty? [ drop
2drop
] [ ] [
" where " 0% [ " where " 0% [
" and " 0% " and " 0%
] [ ] [
2dup slot-name>> swap get-slot-named where 2dup slot-name>> swap get-slot-named where
] interleave drop ] interleave drop
] if ; ] if-empty ;
M: db <delete-tuples-statement> ( tuple table -- sql ) M: db <delete-tuples-statement> ( tuple table -- sql )
[ [
@ -146,15 +146,52 @@ M: db <select-by-slots-statement> ( tuple class -- statement )
number>string " limit " prepend append number>string " limit " prepend append
] curry change-sql drop ; ] curry change-sql drop ;
: make-advanced-statement ( tuple advanced -- tuple' ) : make-query ( tuple query -- tuple' )
dupd dupd
{ {
[ group>> [ do-group ] [ drop ] if* ] [ group>> [ do-group ] [ drop ] if-seq ]
[ order>> [ do-order ] [ drop ] if* ] [ order>> [ do-order ] [ drop ] if-seq ]
[ limit>> [ do-limit ] [ drop ] if* ] [ limit>> [ do-limit ] [ drop ] if* ]
[ offset>> [ do-offset ] [ drop ] if* ] [ offset>> [ do-offset ] [ drop ] if* ]
} 2cleave ; } 2cleave ;
M: db <advanced-select-statement> ( tuple class group order limit offset -- tuple ) M: db <query> ( tuple class query -- tuple )
advanced-statement boa [ <select-by-slots-statement> ] dip make-query ;
[ <select-by-slots-statement> ] dip make-advanced-statement ;
! select ID, NAME, SCORE from EXAM limit 1 offset 3
: select-tuples* ( tuple -- statement )
dup
[
select 0,
dup class db-columns [ ", " 0, ]
[ dup column-name>> 0, 2, ] interleave
from 0,
class word-name 0,
] { { } { } { } } nmake
>r >r parse-sql 4drop r> r>
<simple-statement> maybe-make-retryable do-select ;
M: db <count-statement> ( tuple class groups -- statement )
\ query new
swap >>group
[ [ "select count(*) from " 0% 0% where-clause ] query-make ]
dip make-query ;
: where-clause* ( tuple specs -- )
dupd filter-slots [
drop
] [
\ where 0,
[ 2dup slot-name>> swap get-slot-named where ] map 2array 0,
drop
] if-empty ;
: delete-tuple* ( tuple -- sql )
dup
[
delete 0, from 0, dup class db-table 0,
dup class db-columns where-clause*
] { { } { } { } } nmake
>r >r parse-sql 4drop r> r>
<simple-statement> maybe-make-retryable do-select ;

View File

@ -23,12 +23,27 @@ DEFER: sql%
: sql-function, ( seq function -- ) : sql-function, ( seq function -- )
sql% "(" sql% unclip sql% ")" sql% [ sql% ] each ; sql% "(" sql% unclip sql% ")" sql% [ sql% ] each ;
: sql-where ( seq -- )
B
[
[ second 0, ]
[ first 0, ]
[ third 1, \ ? 0, ] tri
] each ;
: sql-array% ( array -- ) : sql-array% ( array -- )
B
unclip unclip
{ {
{ \ create [ "create table" sql% ] }
{ \ drop [ "drop table" sql% ] }
{ \ insert [ "insert into" sql% ] }
{ \ update [ "update" sql% ] }
{ \ delete [ "delete" sql% ] }
{ \ select [ B "select" sql% "," (sql-interleave) ] }
{ \ columns [ "," (sql-interleave) ] } { \ columns [ "," (sql-interleave) ] }
{ \ from [ "from" "," sql-interleave ] } { \ from [ "from" "," sql-interleave ] }
{ \ where [ "where" "and" sql-interleave ] } { \ where [ B "where" 0, sql-where ] }
{ \ group-by [ "group by" "," sql-interleave ] } { \ group-by [ "group by" "," sql-interleave ] }
{ \ having [ "having" "," sql-interleave ] } { \ having [ "having" "," sql-interleave ] }
{ \ order-by [ "order by" "," sql-interleave ] } { \ order-by [ "order by" "," sql-interleave ] }
@ -49,7 +64,7 @@ DEFER: sql%
ERROR: no-sql-match ; ERROR: no-sql-match ;
: sql% ( obj -- ) : sql% ( obj -- )
{ {
{ [ dup string? ] [ " " 0% 0% ] } { [ dup string? ] [ 0, ] }
{ [ dup array? ] [ sql-array% ] } { [ dup array? ] [ sql-array% ] }
{ [ dup number? ] [ number>string sql% ] } { [ dup number? ] [ number>string sql% ] }
{ [ dup symbol? ] [ unparse sql% ] } { [ dup symbol? ] [ unparse sql% ] }
@ -59,13 +74,4 @@ ERROR: no-sql-match ;
} cond ; } cond ;
: parse-sql ( obj -- sql in-spec out-spec in out ) : parse-sql ( obj -- sql in-spec out-spec in out )
[ [ [ sql% ] each ] { { } { } { } } nmake ;
unclip {
{ \ create [ "create table" sql% ] }
{ \ drop [ "drop table" sql% ] }
{ \ insert [ "insert into" sql% ] }
{ \ update [ "update" sql% ] }
{ \ delete [ "delete" sql% ] }
{ \ select [ "select" sql% ] }
} case [ sql% ] each
] { "" { } { } { } { } } nmake ;

View File

@ -4,7 +4,7 @@ USING: alien.c-types arrays assocs kernel math math.parser
namespaces sequences db.sqlite.ffi db combinators namespaces sequences db.sqlite.ffi db combinators
continuations db.types calendar.format serialize continuations db.types calendar.format serialize
io.streams.byte-array byte-arrays io.encodings.binary io.streams.byte-array byte-arrays io.encodings.binary
io.backend db.errors ; io.backend db.errors present urls ;
IN: db.sqlite.lib IN: db.sqlite.lib
ERROR: sqlite-error < db-error n string ; ERROR: sqlite-error < db-error n string ;
@ -107,6 +107,7 @@ ERROR: sqlite-sql-error < sql-error n string ;
object>bytes object>bytes
sqlite-bind-blob-by-name sqlite-bind-blob-by-name
] } ] }
{ URL [ present sqlite-bind-text-by-name ] }
{ +db-assigned-id+ [ sqlite-bind-int-by-name ] } { +db-assigned-id+ [ sqlite-bind-int-by-name ] }
{ +random-id+ [ sqlite-bind-int64-by-name ] } { +random-id+ [ sqlite-bind-int64-by-name ] }
{ NULL [ sqlite-bind-null-by-name ] } { NULL [ sqlite-bind-null-by-name ] }
@ -147,6 +148,7 @@ ERROR: sqlite-sql-error < sql-error n string ;
{ TIMESTAMP [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] } { TIMESTAMP [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
{ DATETIME [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] } { DATETIME [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
{ BLOB [ sqlite-column-blob ] } { BLOB [ sqlite-column-blob ] }
{ URL [ sqlite3_column_text dup [ >url ] when ] }
{ FACTOR-BLOB [ { FACTOR-BLOB [
sqlite-column-blob sqlite-column-blob
dup [ bytes>object ] when dup [ bytes>object ] when

View File

@ -182,6 +182,7 @@ M: sqlite-db persistent-table ( -- assoc )
{ DOUBLE { "real" "real" } } { DOUBLE { "real" "real" } }
{ BLOB { "blob" "blob" } } { BLOB { "blob" "blob" } }
{ FACTOR-BLOB { "blob" "blob" } } { FACTOR-BLOB { "blob" "blob" } }
{ URL { "text" "text" } }
{ +autoincrement+ { f f "autoincrement" } } { +autoincrement+ { f f "autoincrement" } }
{ +unique+ { f f "unique" } } { +unique+ { f f "unique" } }
{ +default+ { f f "default" } } { +default+ { f f "default" } }

View File

@ -4,26 +4,27 @@ USING: io.files kernel tools.test db db.tuples classes
db.types continuations namespaces math math.ranges db.types continuations namespaces math math.ranges
prettyprint calendar sequences db.sqlite math.intervals prettyprint calendar sequences db.sqlite math.intervals
db.postgresql accessors random math.bitfields.lib db.postgresql accessors random math.bitfields.lib
math.ranges strings sequences.lib ; math.ranges strings sequences.lib urls ;
IN: db.tuples.tests IN: db.tuples.tests
TUPLE: person the-id the-name the-number the-real TUPLE: person the-id the-name the-number the-real
ts date time blob factor-blob ; ts date time blob factor-blob url ;
: <person> ( name age real ts date time blob factor-blob -- person ) : <person> ( name age real ts date time blob factor-blob url -- person )
{ person new
set-person-the-name swap >>url
set-person-the-number swap >>factor-blob
set-person-the-real swap >>blob
set-person-ts swap >>time
set-person-date swap >>date
set-person-time swap >>ts
set-person-blob swap >>the-real
set-person-factor-blob swap >>the-number
} person construct ; swap >>the-name ;
: <user-assigned-person> ( id name age real ts date time blob factor-blob -- person ) : <user-assigned-person> ( id name age real ts date time blob factor-blob url -- person )
<person> [ set-person-the-id ] keep ; <person>
swap >>the-id ;
SYMBOL: person1 SYMBOL: person1
SYMBOL: person2 SYMBOL: person2
@ -103,6 +104,7 @@ SYMBOL: person4
T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
f f
H{ { 1 2 } { 3 4 } { 5 "lol" } } H{ { 1 2 } { 3 4 } { 5 "lol" } }
URL" http://www.google.com/search?hl=en&q=trailer+park+boys&btnG=Google+Search"
} }
] [ T{ person f 4 } select-tuple ] unit-test ] [ T{ person f 4 } select-tuple ] unit-test
@ -120,19 +122,20 @@ SYMBOL: person4
{ "time" "T" TIME } { "time" "T" TIME }
{ "blob" "B" BLOB } { "blob" "B" BLOB }
{ "factor-blob" "FB" FACTOR-BLOB } { "factor-blob" "FB" FACTOR-BLOB }
{ "url" "U" URL }
} define-persistent } define-persistent
"billy" 10 3.14 f f f f f <person> person1 set "billy" 10 3.14 f f f f f f <person> person1 set
"johnny" 10 3.14 f f f f f <person> person2 set "johnny" 10 3.14 f f f f f f <person> person2 set
"teddy" 10 3.14 "teddy" 10 3.14
T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
B{ 115 116 111 114 101 105 110 97 98 108 111 98 } f <person> person3 set B{ 115 116 111 114 101 105 110 97 98 108 111 98 } f f <person> person3 set
"eddie" 10 3.14 "eddie" 10 3.14
T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
f H{ { 1 2 } { 3 4 } { 5 "lol" } } <person> person4 set ; f H{ { 1 2 } { 3 4 } { 5 "lol" } } URL" http://www.google.com/search?hl=en&q=trailer+park+boys&btnG=Google+Search" <person> person4 set ;
: user-assigned-person-schema ( -- ) : user-assigned-person-schema ( -- )
person "PERSON" person "PERSON"
@ -146,20 +149,21 @@ SYMBOL: person4
{ "time" "T" TIME } { "time" "T" TIME }
{ "blob" "B" BLOB } { "blob" "B" BLOB }
{ "factor-blob" "FB" FACTOR-BLOB } { "factor-blob" "FB" FACTOR-BLOB }
{ "url" "U" URL }
} define-persistent } define-persistent
1 "billy" 10 3.14 f f f f f <user-assigned-person> person1 set 1 "billy" 10 3.14 f f f f f f <user-assigned-person> person1 set
2 "johnny" 10 3.14 f f f f f <user-assigned-person> person2 set 2 "johnny" 10 3.14 f f f f f f <user-assigned-person> person2 set
3 "teddy" 10 3.14 3 "teddy" 10 3.14
T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
B{ 115 116 111 114 101 105 110 97 98 108 111 98 } B{ 115 116 111 114 101 105 110 97 98 108 111 98 }
f <user-assigned-person> person3 set f f <user-assigned-person> person3 set
4 "eddie" 10 3.14 4 "eddie" 10 3.14
T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f 2008 11 22 0 0 0 T{ duration f 0 0 0 0 0 0 } }
T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } } T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
f H{ { 1 2 } { 3 4 } { 5 "lol" } } <user-assigned-person> person4 set ; f H{ { 1 2 } { 3 4 } { 5 "lol" } } URL" http://www.google.com/search?hl=en&q=trailer+park+boys&btnG=Google+Search" <user-assigned-person> person4 set ;
TUPLE: paste n summary author channel mode contents timestamp annotations ; TUPLE: paste n summary author channel mode contents timestamp annotations ;
TUPLE: annotation n paste-id summary author mode contents ; TUPLE: annotation n paste-id summary author mode contents ;
@ -227,7 +231,7 @@ TUPLE: exam id name score ;
: random-exam ( -- exam ) : random-exam ( -- exam )
f f
6 [ CHAR: a CHAR: b [a,b] random ] replicate >string 6 [ CHAR: a CHAR: z [a,b] random ] replicate >string
100 random 100 random
exam boa ; exam boa ;
@ -340,7 +344,9 @@ TUPLE: exam id name score ;
} }
] [ ] [
T{ exam } select-tuples T{ exam } select-tuples
] unit-test ; ] unit-test
[ 4 ] [ T{ exam } f count-tuples ] unit-test ;
TUPLE: bignum-test id m n o ; TUPLE: bignum-test id m n o ;
: <bignum-test> ( m n o -- obj ) : <bignum-test> ( m n o -- obj )

View File

@ -42,8 +42,9 @@ HOOK: <insert-user-assigned-statement> db ( class -- obj )
HOOK: <update-tuple-statement> db ( class -- obj ) HOOK: <update-tuple-statement> db ( class -- obj )
HOOK: <delete-tuples-statement> db ( tuple class -- obj ) HOOK: <delete-tuples-statement> db ( tuple class -- obj )
HOOK: <select-by-slots-statement> db ( tuple class -- tuple ) HOOK: <select-by-slots-statement> db ( tuple class -- tuple )
TUPLE: advanced-statement group order offset limit ; TUPLE: query group order offset limit ;
HOOK: <advanced-select-statement> db ( tuple class group order offset limit -- tuple ) HOOK: <query> db ( tuple class query -- statement' )
HOOK: <count-statement> db ( tuple class groups -- n )
HOOK: insert-tuple* db ( tuple statement -- ) HOOK: insert-tuple* db ( tuple statement -- )
@ -55,6 +56,7 @@ SINGLETON: retryable
[ make-retryable ] map [ make-retryable ] map
] [ ] [
retryable >>type retryable >>type
10 >>retries
] if ; ] if ;
: regenerate-params ( statement -- statement ) : regenerate-params ( statement -- statement )
@ -69,12 +71,13 @@ SINGLETON: retryable
] 2map >>bind-params ; ] 2map >>bind-params ;
M: retryable execute-statement* ( statement type -- ) M: retryable execute-statement* ( statement type -- )
drop drop [
[ [
[ query-results dispose t ] [ query-results dispose t ]
[ ] [ ]
[ regenerate-params bind-statement* f ] cleanup [ regenerate-params bind-statement* f ] cleanup
] curry 10 retry drop ; ] curry
] [ retries>> ] bi retry drop ;
: resulting-tuple ( class row out-params -- tuple ) : resulting-tuple ( class row out-params -- tuple )
rot class new [ rot class new [
@ -146,12 +149,21 @@ M: retryable execute-statement* ( statement type -- )
: do-select ( exemplar-tuple statement -- tuples ) : do-select ( exemplar-tuple statement -- tuples )
[ [ bind-tuple ] [ query-tuples ] 2bi ] with-disposal ; [ [ bind-tuple ] [ query-tuples ] 2bi ] with-disposal ;
: query ( tuple query -- tuples )
>r dup dup class r> <query> do-select ;
: select-tuples ( tuple -- tuples ) : select-tuples ( tuple -- tuples )
dup dup class <select-by-slots-statement> do-select ; dup dup class <select-by-slots-statement> do-select ;
: count-tuples ( tuple -- n )
select-tuples length ;
: select-tuple ( tuple -- tuple/f ) : select-tuple ( tuple -- tuple/f )
dup dup class f f f 1 <advanced-select-statement> dup dup class \ query new 1 >>limit <query> do-select ?first ;
do-select ?first ;
: do-count ( exemplar-tuple statement -- tuples )
[
[ bind-tuple ] [ nip default-query ] 2bi
] with-disposal ;
: count-tuples ( tuple groups -- n )
>r dup dup class r> <count-statement> do-count
dup length 1 =
[ first first string>number ] [ [ first string>number ] map ] if ;

View File

@ -65,7 +65,7 @@ SYMBOLS: +autoincrement+ +serial+ +unique+ +default+ +null+ +not-null+
SYMBOLS: INTEGER BIG-INTEGER SIGNED-BIG-INTEGER UNSIGNED-BIG-INTEGER SYMBOLS: INTEGER BIG-INTEGER SIGNED-BIG-INTEGER UNSIGNED-BIG-INTEGER
DOUBLE REAL BOOLEAN TEXT VARCHAR DATE TIME DATETIME TIMESTAMP BLOB DOUBLE REAL BOOLEAN TEXT VARCHAR DATE TIME DATETIME TIMESTAMP BLOB
FACTOR-BLOB NULL ; FACTOR-BLOB NULL URL ;
: spec>tuple ( class spec -- tuple ) : spec>tuple ( class spec -- tuple )
3 f pad-right 3 f pad-right

View File

@ -2,7 +2,7 @@ USING: assocs html.parser html.parser.utils combinators
continuations hashtables continuations hashtables
hashtables.private io kernel math hashtables.private io kernel math
namespaces prettyprint quotations sequences splitting namespaces prettyprint quotations sequences splitting
state-parser strings ; strings ;
IN: html.parser.printer IN: html.parser.printer
SYMBOL: no-section SYMBOL: no-section
@ -16,7 +16,8 @@ TUPLE: state section ;
TUPLE: text-printer ; TUPLE: text-printer ;
TUPLE: ui-printer ; TUPLE: ui-printer ;
TUPLE: src-printer ; TUPLE: src-printer ;
UNION: printer text-printer ui-printer src-printer ; TUPLE: html-prettyprinter ;
UNION: printer text-printer ui-printer src-printer html-prettyprinter ;
HOOK: print-tag printer ( tag -- ) HOOK: print-tag printer ( tag -- )
HOOK: print-text-tag printer ( tag -- ) HOOK: print-text-tag printer ( tag -- )
HOOK: print-comment-tag printer ( tag -- ) HOOK: print-comment-tag printer ( tag -- )
@ -47,7 +48,7 @@ M: printer print-comment-tag ( tag -- )
tag-text write tag-text write
"-->" write ; "-->" write ;
M: printer print-dtd-tag M: printer print-dtd-tag ( tag -- )
"<!" write "<!" write
tag-text write tag-text write
">" write ; ">" write ;
@ -70,8 +71,8 @@ M: printer print-closing-named-tag ( tag -- )
M: src-printer print-opening-named-tag ( tag -- ) M: src-printer print-opening-named-tag ( tag -- )
"<" write "<" write
dup tag-name write [ tag-name write ]
tag-attributes dup assoc-empty? [ drop ] [ print-attributes ] if [ tag-attributes dup assoc-empty? [ drop ] [ print-attributes ] if ] bi
">" write ; ">" write ;
M: src-printer print-closing-named-tag ( tag -- ) M: src-printer print-closing-named-tag ( tag -- )
@ -79,9 +80,30 @@ M: src-printer print-closing-named-tag ( tag -- )
tag-name write tag-name write
">" write ; ">" write ;
TUPLE: unknown-tag-error tag ; SYMBOL: tab-width
SYMBOL: #indentations
C: <unknown-tag-error> unknown-tag-error : html-pp ( vector -- )
[
0 #indentations set
2 tab-width set
] with-scope ;
: print-tabs ( -- )
tab-width get #indentations get * CHAR: \s <repetition> write ;
M: html-prettyprinter print-opening-named-tag ( tag -- )
print-tabs "<" write
tag-name write
">\n" write ;
M: html-prettyprinter print-closing-named-tag ( tag -- )
"</" write
tag-name write
">" write ;
ERROR: unknown-tag-error tag ;
M: printer print-tag ( tag -- ) M: printer print-tag ( tag -- )
{ {
@ -92,15 +114,12 @@ M: printer print-tag ( tag -- )
[ print-closing-named-tag ] } [ print-closing-named-tag ] }
{ [ dup tag-name string? ] { [ dup tag-name string? ]
[ print-opening-named-tag ] } [ print-opening-named-tag ] }
[ <unknown-tag-error> throw ] [ unknown-tag-error ]
} cond ; } cond ;
SYMBOL: tablestack ! SYMBOL: tablestack
! : with-html-printer ( vector quot -- )
: with-html-printer ! [ V{ } clone tablestack set ] with-scope ;
[
V{ } clone tablestack set
] with-scope ;
! { { 1 2 } { 3 4 } } ! { { 1 2 } { 3 4 } }
! H{ { table-gap { 10 10 } } } [ ! H{ { table-gap { 10 10 } } } [

View File

@ -1,7 +1,7 @@
USING: assocs circular combinators continuations hashtables USING: assocs circular combinators continuations hashtables
hashtables.private io kernel math hashtables.private io kernel math
namespaces prettyprint quotations sequences splitting namespaces prettyprint quotations sequences splitting
state-parser strings ; state-parser strings sequences.lib ;
IN: html.parser.utils IN: html.parser.utils
: string-parse-end? : string-parse-end?
@ -13,7 +13,7 @@ IN: html.parser.utils
dup length rot length 1- - head next* ; dup length rot length 1- - head next* ;
: trim1 ( seq ch -- newseq ) : trim1 ( seq ch -- newseq )
[ ?head drop ] keep ?tail drop ; [ ?head drop ] [ ?tail drop ] bi ;
: single-quote ( str -- newstr ) : single-quote ( str -- newstr )
>r "'" r> "'" 3append ; >r "'" r> "'" 3append ;
@ -26,11 +26,7 @@ IN: html.parser.utils
[ double-quote ] [ single-quote ] if ; [ double-quote ] [ single-quote ] if ;
: quoted? ( str -- ? ) : quoted? ( str -- ? )
dup length 1 > [ [ [ first ] [ peek ] bi [ = ] keep "'\"" member? and ] [ f ] if-seq ;
[ first ] keep peek [ = ] keep "'\"" member? and
] [
drop f
] if ;
: ?quote ( str -- newstr ) : ?quote ( str -- newstr )
dup quoted? [ quote ] unless ; dup quoted? [ quote ] unless ;
@ -39,4 +35,3 @@ IN: html.parser.utils
dup quoted? [ but-last-slice rest-slice >string ] when ; dup quoted? [ but-last-slice rest-slice >string ] when ;
: quote? ( ch -- ? ) "'\"" member? ; : quote? ( ch -- ? ) "'\"" member? ;