Merge branch 'master' of git://factorcode.org/git/factor
commit
cc5d35e189
|
@ -270,7 +270,7 @@ M: no-such-symbol compiler-error-type
|
||||||
pop-literal nip >>library
|
pop-literal nip >>library
|
||||||
pop-literal nip >>return
|
pop-literal nip >>return
|
||||||
! Quotation which coerces parameters to required types
|
! Quotation which coerces parameters to required types
|
||||||
dup param-prep-quot f infer-quot
|
dup param-prep-quot recursive-state get infer-quot
|
||||||
! Set ABI
|
! Set ABI
|
||||||
dup library>> library [ abi>> ] [ "cdecl" ] if* >>abi
|
dup library>> library [ abi>> ] [ "cdecl" ] if* >>abi
|
||||||
! Add node to IR
|
! Add node to IR
|
||||||
|
@ -278,7 +278,7 @@ M: no-such-symbol compiler-error-type
|
||||||
! Magic #: consume exactly the number of inputs
|
! Magic #: consume exactly the number of inputs
|
||||||
dup 0 alien-invoke-stack
|
dup 0 alien-invoke-stack
|
||||||
! Quotation which coerces return value to required type
|
! Quotation which coerces return value to required type
|
||||||
return-prep-quot f infer-quot
|
return-prep-quot recursive-state get infer-quot
|
||||||
] "infer" set-word-prop
|
] "infer" set-word-prop
|
||||||
|
|
||||||
M: #alien-invoke generate-node
|
M: #alien-invoke generate-node
|
||||||
|
@ -306,13 +306,13 @@ M: alien-indirect-error summary
|
||||||
pop-parameters >>parameters
|
pop-parameters >>parameters
|
||||||
pop-literal nip >>return
|
pop-literal nip >>return
|
||||||
! Quotation which coerces parameters to required types
|
! Quotation which coerces parameters to required types
|
||||||
dup param-prep-quot [ dip ] curry f infer-quot
|
dup param-prep-quot [ dip ] curry recursive-state get infer-quot
|
||||||
! Add node to IR
|
! Add node to IR
|
||||||
dup node,
|
dup node,
|
||||||
! Magic #: consume the function pointer, too
|
! Magic #: consume the function pointer, too
|
||||||
dup 1 alien-invoke-stack
|
dup 1 alien-invoke-stack
|
||||||
! Quotation which coerces return value to required type
|
! Quotation which coerces return value to required type
|
||||||
return-prep-quot f infer-quot
|
return-prep-quot recursive-state get infer-quot
|
||||||
] "infer" set-word-prop
|
] "infer" set-word-prop
|
||||||
|
|
||||||
M: #alien-indirect generate-node
|
M: #alien-indirect generate-node
|
||||||
|
@ -345,7 +345,7 @@ M: alien-callback-error summary
|
||||||
|
|
||||||
: callback-bottom ( node -- )
|
: callback-bottom ( node -- )
|
||||||
xt>> [ word-xt drop <alien> ] curry
|
xt>> [ word-xt drop <alien> ] curry
|
||||||
f infer-quot ;
|
recursive-state get infer-quot ;
|
||||||
|
|
||||||
\ alien-callback [
|
\ alien-callback [
|
||||||
4 ensure-values
|
4 ensure-values
|
||||||
|
|
|
@ -18,6 +18,8 @@ IN: bootstrap.compiler
|
||||||
|
|
||||||
enable-compiler
|
enable-compiler
|
||||||
|
|
||||||
|
: compile-uncompiled [ compiled? not ] filter compile ;
|
||||||
|
|
||||||
nl
|
nl
|
||||||
"Compiling..." write flush
|
"Compiling..." write flush
|
||||||
|
|
||||||
|
@ -42,38 +44,38 @@ nl
|
||||||
find-pair-next namestack*
|
find-pair-next namestack*
|
||||||
|
|
||||||
bitand bitor bitxor bitnot
|
bitand bitor bitxor bitnot
|
||||||
} compile
|
} compile-uncompiled
|
||||||
|
|
||||||
"." write flush
|
"." write flush
|
||||||
|
|
||||||
{
|
{
|
||||||
+ 1+ 1- 2/ < <= > >= shift min
|
+ 1+ 1- 2/ < <= > >= shift
|
||||||
} compile
|
} compile-uncompiled
|
||||||
|
|
||||||
"." write flush
|
"." write flush
|
||||||
|
|
||||||
{
|
{
|
||||||
new-sequence nth push pop peek
|
new-sequence nth push pop peek
|
||||||
} compile
|
} compile-uncompiled
|
||||||
|
|
||||||
"." write flush
|
"." write flush
|
||||||
|
|
||||||
{
|
{
|
||||||
hashcode* = get set
|
hashcode* = get set
|
||||||
} compile
|
} compile-uncompiled
|
||||||
|
|
||||||
"." write flush
|
"." write flush
|
||||||
|
|
||||||
{
|
{
|
||||||
. lines
|
. lines
|
||||||
} compile
|
} compile-uncompiled
|
||||||
|
|
||||||
"." write flush
|
"." write flush
|
||||||
|
|
||||||
{
|
{
|
||||||
malloc calloc free memcpy
|
malloc calloc free memcpy
|
||||||
} compile
|
} compile-uncompiled
|
||||||
|
|
||||||
vocabs [ words [ compiled? not ] filter compile "." write flush ] each
|
vocabs [ words compile-uncompiled "." write flush ] each
|
||||||
|
|
||||||
" done" print flush
|
" done" print flush
|
||||||
|
|
|
@ -1,5 +1,22 @@
|
||||||
IN: bootstrap.image.tests
|
IN: bootstrap.image.tests
|
||||||
USING: bootstrap.image bootstrap.image.private tools.test ;
|
USING: bootstrap.image bootstrap.image.private tools.test
|
||||||
|
kernel math ;
|
||||||
|
|
||||||
\ ' must-infer
|
\ ' must-infer
|
||||||
\ write-image must-infer
|
\ write-image must-infer
|
||||||
|
|
||||||
|
[ f ] [ { 1 2 3 } [ 1 2 3 ] eql? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ [ 1 2 3 ] [ 1 2 3 ] eql? ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ [ 2drop 0 ] [ 2drop 0.0 ] eql? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ [ 2drop 0 ] [ 2drop 0 ] eql? ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ \ + [ 2drop 0 ] eql? ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ 3 [ 0 1 2 ] eql? ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ 3 3.0 eql? ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ 4.0 4.0 eql? ] unit-test
|
||||||
|
|
|
@ -8,7 +8,7 @@ splitting growable classes classes.builtin classes.tuple
|
||||||
classes.tuple.private words.private io.binary io.files vocabs
|
classes.tuple.private words.private io.binary io.files vocabs
|
||||||
vocabs.loader source-files definitions debugger float-arrays
|
vocabs.loader source-files definitions debugger float-arrays
|
||||||
quotations.private sequences.private combinators
|
quotations.private sequences.private combinators
|
||||||
io.encodings.binary math.order ;
|
io.encodings.binary math.order accessors ;
|
||||||
IN: bootstrap.image
|
IN: bootstrap.image
|
||||||
|
|
||||||
: my-arch ( -- arch )
|
: my-arch ( -- arch )
|
||||||
|
@ -31,6 +31,43 @@ IN: bootstrap.image
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
|
! Object cache; we only consider numbers equal if they have the
|
||||||
|
! same type
|
||||||
|
TUPLE: id obj ;
|
||||||
|
|
||||||
|
C: <id> id
|
||||||
|
|
||||||
|
M: id hashcode* obj>> hashcode* ;
|
||||||
|
|
||||||
|
GENERIC: (eql?) ( obj1 obj2 -- ? )
|
||||||
|
|
||||||
|
: eql? ( obj1 obj2 -- ? )
|
||||||
|
[ (eql?) ] [ [ class ] bi@ = ] 2bi and ;
|
||||||
|
|
||||||
|
M: integer (eql?) = ;
|
||||||
|
|
||||||
|
M: sequence (eql?)
|
||||||
|
over sequence? [
|
||||||
|
2dup [ length ] bi@ =
|
||||||
|
[ [ eql? ] 2all? ] [ 2drop f ] if
|
||||||
|
] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
M: object (eql?) = ;
|
||||||
|
|
||||||
|
M: id equal?
|
||||||
|
over id? [ [ obj>> ] bi@ eql? ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
SYMBOL: objects
|
||||||
|
|
||||||
|
: (objects) <id> objects get ; inline
|
||||||
|
|
||||||
|
: lookup-object ( obj -- n/f ) (objects) at ;
|
||||||
|
|
||||||
|
: put-object ( n obj -- ) (objects) set-at ;
|
||||||
|
|
||||||
|
: cache-object ( obj quot -- value )
|
||||||
|
>r (objects) r> [ obj>> ] prepose cache ; inline
|
||||||
|
|
||||||
! Constants
|
! Constants
|
||||||
|
|
||||||
: image-magic HEX: 0f0e0d0c ; inline
|
: image-magic HEX: 0f0e0d0c ; inline
|
||||||
|
@ -61,9 +98,6 @@ IN: bootstrap.image
|
||||||
! The image being constructed; a vector of word-size integers
|
! The image being constructed; a vector of word-size integers
|
||||||
SYMBOL: image
|
SYMBOL: image
|
||||||
|
|
||||||
! Object cache
|
|
||||||
SYMBOL: objects
|
|
||||||
|
|
||||||
! Image output format
|
! Image output format
|
||||||
SYMBOL: big-endian
|
SYMBOL: big-endian
|
||||||
|
|
||||||
|
@ -187,7 +221,9 @@ GENERIC: ' ( obj -- ptr )
|
||||||
2tri ;
|
2tri ;
|
||||||
|
|
||||||
M: bignum '
|
M: bignum '
|
||||||
bignum tag-number dup [ emit-bignum ] emit-object ;
|
[
|
||||||
|
bignum tag-number dup [ emit-bignum ] emit-object
|
||||||
|
] cache-object ;
|
||||||
|
|
||||||
! Fixnums
|
! Fixnums
|
||||||
|
|
||||||
|
@ -202,9 +238,11 @@ M: fixnum '
|
||||||
! Floats
|
! Floats
|
||||||
|
|
||||||
M: float '
|
M: float '
|
||||||
|
[
|
||||||
float tag-number dup [
|
float tag-number dup [
|
||||||
align-here double>bits emit-64
|
align-here double>bits emit-64
|
||||||
] emit-object ;
|
] emit-object
|
||||||
|
] cache-object ;
|
||||||
|
|
||||||
! Special objects
|
! Special objects
|
||||||
|
|
||||||
|
@ -243,7 +281,7 @@ M: f '
|
||||||
] bi
|
] bi
|
||||||
\ word type-number object tag-number
|
\ word type-number object tag-number
|
||||||
[ emit-seq ] emit-object
|
[ emit-seq ] emit-object
|
||||||
] keep objects get set-at ;
|
] keep put-object ;
|
||||||
|
|
||||||
: word-error ( word msg -- * )
|
: word-error ( word msg -- * )
|
||||||
[ % dup word-vocabulary % " " % word-name % ] "" make throw ;
|
[ % dup word-vocabulary % " " % word-name % ] "" make throw ;
|
||||||
|
@ -252,7 +290,7 @@ M: f '
|
||||||
[ target-word ] keep or ;
|
[ target-word ] keep or ;
|
||||||
|
|
||||||
: fixup-word ( word -- offset )
|
: fixup-word ( word -- offset )
|
||||||
transfer-word dup objects get at
|
transfer-word dup lookup-object
|
||||||
[ ] [ "Not in image: " word-error ] ?if ;
|
[ ] [ "Not in image: " word-error ] ?if ;
|
||||||
|
|
||||||
: fixup-words ( -- )
|
: fixup-words ( -- )
|
||||||
|
@ -286,7 +324,7 @@ M: wrapper '
|
||||||
M: string '
|
M: string '
|
||||||
#! We pool strings so that each string is only written once
|
#! We pool strings so that each string is only written once
|
||||||
#! to the image
|
#! to the image
|
||||||
objects get [ emit-string ] cache ;
|
[ emit-string ] cache-object ;
|
||||||
|
|
||||||
: assert-empty ( seq -- )
|
: assert-empty ( seq -- )
|
||||||
length 0 assert= ;
|
length 0 assert= ;
|
||||||
|
@ -311,12 +349,12 @@ M: float-array ' float-array emit-dummy-array ;
|
||||||
|
|
||||||
: emit-tuple ( tuple -- pointer )
|
: emit-tuple ( tuple -- pointer )
|
||||||
dup class word-name "tombstone" =
|
dup class word-name "tombstone" =
|
||||||
[ objects get [ (emit-tuple) ] cache ] [ (emit-tuple) ] if ;
|
[ [ (emit-tuple) ] cache-object ] [ (emit-tuple) ] if ;
|
||||||
|
|
||||||
M: tuple ' emit-tuple ;
|
M: tuple ' emit-tuple ;
|
||||||
|
|
||||||
M: tuple-layout '
|
M: tuple-layout '
|
||||||
objects get [
|
[
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
[ layout-hashcode , ]
|
[ layout-hashcode , ]
|
||||||
|
@ -328,12 +366,12 @@ M: tuple-layout '
|
||||||
] { } make [ ' ] map
|
] { } make [ ' ] map
|
||||||
\ tuple-layout type-number
|
\ tuple-layout type-number
|
||||||
object tag-number [ emit-seq ] emit-object
|
object tag-number [ emit-seq ] emit-object
|
||||||
] cache ;
|
] cache-object ;
|
||||||
|
|
||||||
M: tombstone '
|
M: tombstone '
|
||||||
delegate
|
delegate
|
||||||
"((tombstone))" "((empty))" ? "hashtables.private" lookup
|
"((tombstone))" "((empty))" ? "hashtables.private" lookup
|
||||||
word-def first objects get [ emit-tuple ] cache ;
|
word-def first [ emit-tuple ] cache-object ;
|
||||||
|
|
||||||
! Arrays
|
! Arrays
|
||||||
M: array '
|
M: array '
|
||||||
|
@ -343,7 +381,7 @@ M: array '
|
||||||
! Quotations
|
! Quotations
|
||||||
|
|
||||||
M: quotation '
|
M: quotation '
|
||||||
objects get [
|
[
|
||||||
quotation-array '
|
quotation-array '
|
||||||
quotation type-number object tag-number [
|
quotation type-number object tag-number [
|
||||||
emit ! array
|
emit ! array
|
||||||
|
@ -351,7 +389,7 @@ M: quotation '
|
||||||
0 emit ! xt
|
0 emit ! xt
|
||||||
0 emit ! code
|
0 emit ! code
|
||||||
] emit-object
|
] emit-object
|
||||||
] cache ;
|
] cache-object ;
|
||||||
|
|
||||||
! End of the image
|
! End of the image
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@ IN: math.floats.private
|
||||||
M: fixnum >float fixnum>float ;
|
M: fixnum >float fixnum>float ;
|
||||||
M: bignum >float bignum>float ;
|
M: bignum >float bignum>float ;
|
||||||
|
|
||||||
M: float zero? dup 0.0 float= swap -0.0 float= or ;
|
|
||||||
|
|
||||||
M: float >fixnum float>fixnum ;
|
M: float >fixnum float>fixnum ;
|
||||||
M: float >bignum float>bignum ;
|
M: float >bignum float>bignum ;
|
||||||
M: float >float ;
|
M: float >float ;
|
||||||
|
@ -22,4 +20,7 @@ M: float + float+ ;
|
||||||
M: float - float- ;
|
M: float - float- ;
|
||||||
M: float * float* ;
|
M: float * float* ;
|
||||||
M: float / float/f ;
|
M: float / float/f ;
|
||||||
|
M: float /f float/f ;
|
||||||
M: float mod float-mod ;
|
M: float mod float-mod ;
|
||||||
|
|
||||||
|
M: real abs dup 0 < [ neg ] when ;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
USING: kernel math namespaces prettyprint
|
USING: kernel math math.functions namespaces prettyprint
|
||||||
math.private continuations tools.test sequences ;
|
math.private continuations tools.test sequences random ;
|
||||||
IN: math.integers.tests
|
IN: math.integers.tests
|
||||||
|
|
||||||
[ "-8" ] [ -8 unparse ] unit-test
|
[ "-8" ] [ -8 unparse ] unit-test
|
||||||
|
@ -191,3 +191,31 @@ unit-test
|
||||||
[ f ] [ -128 power-of-2? ] unit-test
|
[ f ] [ -128 power-of-2? ] unit-test
|
||||||
[ f ] [ 0 power-of-2? ] unit-test
|
[ f ] [ 0 power-of-2? ] unit-test
|
||||||
[ t ] [ 1 power-of-2? ] unit-test
|
[ t ] [ 1 power-of-2? ] unit-test
|
||||||
|
|
||||||
|
: ratio>float [ >bignum ] bi@ /f ;
|
||||||
|
|
||||||
|
[ 5. ] [ 5 1 ratio>float ] unit-test
|
||||||
|
[ 4. ] [ 4 1 ratio>float ] unit-test
|
||||||
|
[ 2. ] [ 2 1 ratio>float ] unit-test
|
||||||
|
[ .5 ] [ 1 2 ratio>float ] unit-test
|
||||||
|
[ .75 ] [ 3 4 ratio>float ] unit-test
|
||||||
|
[ 1. ] [ 2000 2^ 2000 2^ 1+ ratio>float ] unit-test
|
||||||
|
[ -1. ] [ 2000 2^ neg 2000 2^ 1+ ratio>float ] unit-test
|
||||||
|
[ 0.4 ] [ 6 15 ratio>float ] unit-test
|
||||||
|
|
||||||
|
[ HEX: 3fe553522d230931 ]
|
||||||
|
[ 61967020039 92984792073 ratio>float double>bits ] unit-test
|
||||||
|
|
||||||
|
: random-integer
|
||||||
|
32 random-bits
|
||||||
|
1 random zero? [ neg ] when
|
||||||
|
1 random zero? [ >bignum ] when ;
|
||||||
|
|
||||||
|
[ t ] [
|
||||||
|
1000 [
|
||||||
|
drop
|
||||||
|
random-integer
|
||||||
|
random-integer
|
||||||
|
[ >float / ] [ /f ] 2bi 0.1 ~
|
||||||
|
] all?
|
||||||
|
] unit-test
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
! Copyright (C) 2004, 2007 Slava Pestov.
|
! Copyright (C) 2004, 2007 Slava Pestov.
|
||||||
|
! Copyright (C) 2008, Doug Coleman.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel kernel.private sequences
|
USING: kernel kernel.private sequences
|
||||||
sequences.private math math.private combinators ;
|
sequences.private math math.private combinators ;
|
||||||
|
@ -22,6 +23,8 @@ M: fixnum + fixnum+ ;
|
||||||
M: fixnum - fixnum- ;
|
M: fixnum - fixnum- ;
|
||||||
M: fixnum * fixnum* ;
|
M: fixnum * fixnum* ;
|
||||||
M: fixnum /i fixnum/i ;
|
M: fixnum /i fixnum/i ;
|
||||||
|
M: fixnum /f >r >float r> >float float/f ;
|
||||||
|
|
||||||
M: fixnum mod fixnum-mod ;
|
M: fixnum mod fixnum-mod ;
|
||||||
|
|
||||||
M: fixnum /mod fixnum/mod ;
|
M: fixnum /mod fixnum/mod ;
|
||||||
|
@ -67,4 +70,57 @@ M: bignum bitnot bignum-bitnot ;
|
||||||
M: bignum bit? bignum-bit? ;
|
M: bignum bit? bignum-bit? ;
|
||||||
M: bignum (log2) bignum-log2 ;
|
M: bignum (log2) bignum-log2 ;
|
||||||
|
|
||||||
M: integer zero? 0 number= ;
|
! Converting ratios to floats. Based on FLOAT-RATIO from
|
||||||
|
! sbcl/src/code/float.lisp, which has the following license:
|
||||||
|
|
||||||
|
! "The software is in the public domain and is
|
||||||
|
! provided with absolutely no warranty."
|
||||||
|
|
||||||
|
! First step: pre-scaling
|
||||||
|
: twos ( x -- y ) dup 1- bitxor log2 ; inline
|
||||||
|
|
||||||
|
: scale-denonimator ( den -- scaled-den scale' )
|
||||||
|
dup twos neg [ shift ] keep ; inline
|
||||||
|
|
||||||
|
: pre-scale ( num den -- scale shifted-num scaled-den )
|
||||||
|
2dup [ log2 ] bi@ -
|
||||||
|
tuck [ neg 54 + shift ] [ >r scale-denonimator r> + ] 2bi*
|
||||||
|
-rot ; inline
|
||||||
|
|
||||||
|
! Second step: loop
|
||||||
|
: shift-mantissa ( scale mantissa -- scale' mantissa' )
|
||||||
|
[ 1+ ] [ 2/ ] bi* ; inline
|
||||||
|
|
||||||
|
: /f-loop ( scale mantissa den -- scale' fraction-and-guard rem )
|
||||||
|
[ 2dup /i log2 53 > ]
|
||||||
|
[ >r shift-mantissa r> ]
|
||||||
|
[ ] while /mod ; inline
|
||||||
|
|
||||||
|
! Third step: post-scaling
|
||||||
|
: unscaled-float ( mantissa -- n )
|
||||||
|
52 2^ 1- bitand 1022 52 shift bitor bits>double ; inline
|
||||||
|
|
||||||
|
: scale-float ( scale mantissa -- float' )
|
||||||
|
>r dup 0 < [ neg 2^ recip ] [ 2^ ] if r> * ; inline
|
||||||
|
|
||||||
|
: post-scale ( scale mantissa -- n )
|
||||||
|
2/ dup log2 52 > [ shift-mantissa ] when
|
||||||
|
unscaled-float scale-float ; inline
|
||||||
|
|
||||||
|
! Main word
|
||||||
|
: /f-abs ( m n -- f )
|
||||||
|
over zero? [
|
||||||
|
2drop 0.0
|
||||||
|
] [
|
||||||
|
dup zero? [
|
||||||
|
2drop 1.0/0.0
|
||||||
|
] [
|
||||||
|
pre-scale
|
||||||
|
/f-loop over odd?
|
||||||
|
[ zero? [ 1+ ] unless ] [ drop ] if
|
||||||
|
post-scale
|
||||||
|
] if
|
||||||
|
] if ; inline
|
||||||
|
|
||||||
|
M: bignum /f ( m n -- f )
|
||||||
|
[ [ abs ] bi@ /f-abs ] [ [ 0 < ] bi@ xor ] 2bi [ neg ] when ;
|
||||||
|
|
|
@ -21,6 +21,7 @@ MATH: + ( x y -- z ) foldable
|
||||||
MATH: - ( x y -- z ) foldable
|
MATH: - ( x y -- z ) foldable
|
||||||
MATH: * ( x y -- z ) foldable
|
MATH: * ( x y -- z ) foldable
|
||||||
MATH: / ( x y -- z ) foldable
|
MATH: / ( x y -- z ) foldable
|
||||||
|
MATH: /f ( x y -- z ) foldable
|
||||||
MATH: /i ( x y -- z ) foldable
|
MATH: /i ( x y -- z ) foldable
|
||||||
MATH: mod ( x y -- z ) foldable
|
MATH: mod ( x y -- z ) foldable
|
||||||
|
|
||||||
|
@ -33,6 +34,8 @@ GENERIC# shift 1 ( x n -- y ) foldable
|
||||||
GENERIC: bitnot ( x -- y ) foldable
|
GENERIC: bitnot ( x -- y ) foldable
|
||||||
GENERIC# bit? 1 ( x n -- ? ) foldable
|
GENERIC# bit? 1 ( x n -- ? ) foldable
|
||||||
|
|
||||||
|
GENERIC: abs ( x -- y ) foldable
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
GENERIC: (log2) ( x -- n ) foldable
|
GENERIC: (log2) ( x -- n ) foldable
|
||||||
|
@ -46,10 +49,7 @@ PRIVATE>
|
||||||
(log2)
|
(log2)
|
||||||
] if ; foldable
|
] if ; foldable
|
||||||
|
|
||||||
GENERIC: zero? ( x -- ? ) foldable
|
: zero? ( x -- ? ) 0 number= ; inline
|
||||||
|
|
||||||
M: object zero? drop f ;
|
|
||||||
|
|
||||||
: 1+ ( x -- y ) 1 + ; inline
|
: 1+ ( x -- y ) 1 + ; inline
|
||||||
: 1- ( x -- y ) 1 - ; inline
|
: 1- ( x -- y ) 1 - ; inline
|
||||||
: 2/ ( x -- y ) -1 shift ; inline
|
: 2/ ( x -- y ) -1 shift ; inline
|
||||||
|
@ -60,8 +60,6 @@ M: object zero? drop f ;
|
||||||
|
|
||||||
: ?1+ [ 1+ ] [ 0 ] if* ; inline
|
: ?1+ [ 1+ ] [ 0 ] if* ; inline
|
||||||
|
|
||||||
: /f ( x y -- z ) >r >float r> >float float/f ; inline
|
|
||||||
|
|
||||||
: rem ( x y -- z ) tuck mod over + swap mod ; foldable
|
: rem ( x y -- z ) tuck mod over + swap mod ; foldable
|
||||||
|
|
||||||
: 2^ ( n -- 2^n ) 1 swap shift ; inline
|
: 2^ ( n -- 2^n ) 1 swap shift ; inline
|
||||||
|
|
|
@ -42,4 +42,4 @@ M: real after=? ( obj1 obj2 -- ? ) >= ;
|
||||||
|
|
||||||
: [-] ( x y -- z ) - 0 max ; inline
|
: [-] ( x y -- z ) - 0 max ; inline
|
||||||
|
|
||||||
: compare ( obj1 obj2 quot -- n ) bi@ <=> ; inline
|
: compare ( obj1 obj2 quot -- symbol ) bi@ <=> ; inline
|
||||||
|
|
|
@ -19,10 +19,10 @@ unit-test
|
||||||
|
|
||||||
[ 3 ] [ { 1 2 3 4 } midpoint ] unit-test
|
[ 3 ] [ { 1 2 3 4 } midpoint ] unit-test
|
||||||
|
|
||||||
[ f ] [ 3 { } [ - ] binsearch ] unit-test
|
[ f ] [ 3 { } [ <=> ] binsearch ] unit-test
|
||||||
[ 0 ] [ 3 { 3 } [ - ] binsearch ] unit-test
|
[ 0 ] [ 3 { 3 } [ <=> ] binsearch ] unit-test
|
||||||
[ 1 ] [ 2 { 1 2 3 } [ - ] binsearch ] unit-test
|
[ 1 ] [ 2 { 1 2 3 } [ <=> ] binsearch ] unit-test
|
||||||
[ 3 ] [ 4 { 1 2 3 4 5 6 } [ - ] binsearch ] unit-test
|
[ 3 ] [ 4 { 1 2 3 4 5 6 } [ <=> ] binsearch ] unit-test
|
||||||
[ 1 ] [ 3.5 { 1 2 3 4 5 6 7 8 } [ - ] binsearch ] unit-test
|
[ 2 ] [ 3.5 { 1 2 3 4 5 6 7 8 } [ <=> ] binsearch ] unit-test
|
||||||
[ 3 ] [ 5.5 { 1 2 3 4 5 6 7 8 } [ - ] binsearch ] unit-test
|
[ 4 ] [ 5.5 { 1 2 3 4 5 6 7 8 } [ <=> ] binsearch ] unit-test
|
||||||
[ 10 ] [ 10 20 >vector [ - ] binsearch ] unit-test
|
[ 10 ] [ 10 20 >vector [ <=> ] binsearch ] unit-test
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
! Copyright (C) 2005, 2007 Slava Pestov.
|
! Copyright (C) 2005, 2007 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: arrays kernel math sequences vectors math.order
|
USING: arrays kernel math sequences vectors math.order
|
||||||
sequences sequences.private growable ;
|
sequences sequences.private growable math.order ;
|
||||||
IN: sorting
|
IN: sorting
|
||||||
|
|
||||||
DEFER: sort
|
DEFER: sort
|
||||||
|
@ -58,13 +58,13 @@ PRIVATE>
|
||||||
[ midpoint@ ] keep nth-unsafe ; inline
|
[ midpoint@ ] keep nth-unsafe ; inline
|
||||||
|
|
||||||
: partition ( seq n -- slice )
|
: partition ( seq n -- slice )
|
||||||
1 < swap halves ? ; inline
|
+gt+ eq? not swap halves ? ; inline
|
||||||
|
|
||||||
: (binsearch) ( elt quot seq -- i )
|
: (binsearch) ( elt quot seq -- i )
|
||||||
dup length 1 <= [
|
dup length 1 <= [
|
||||||
slice-from 2nip
|
slice-from 2nip
|
||||||
] [
|
] [
|
||||||
[ midpoint swap call ] 3keep roll dup zero?
|
[ midpoint swap call ] 3keep roll dup +eq+ eq?
|
||||||
[ drop dup slice-from swap midpoint@ + 2nip ]
|
[ drop dup slice-from swap midpoint@ + 2nip ]
|
||||||
[ partition (binsearch) ] if
|
[ partition (binsearch) ] if
|
||||||
] if ; inline
|
] if ; inline
|
||||||
|
|
|
@ -21,7 +21,7 @@ IN: builder.release.branch
|
||||||
{
|
{
|
||||||
"scp"
|
"scp"
|
||||||
my-boot-image-name
|
my-boot-image-name
|
||||||
"factorcode.org:/var/www/factorcode.org/newsite/images/clean"
|
{ "factorcode.org:/var/www/factorcode.org/newsite/images/clean/" platform }
|
||||||
}
|
}
|
||||||
to-strings
|
to-strings
|
||||||
try-process ;
|
try-process ;
|
||||||
|
|
|
@ -35,7 +35,6 @@ HOOK: db-close db ( handle -- )
|
||||||
handle>> db-close
|
handle>> db-close
|
||||||
] with-variable ;
|
] with-variable ;
|
||||||
|
|
||||||
! TUPLE: sql sql in-params out-params ;
|
|
||||||
TUPLE: statement handle sql in-params out-params bind-params bound? type ;
|
TUPLE: statement handle sql in-params out-params bind-params bound? type ;
|
||||||
TUPLE: simple-statement < statement ;
|
TUPLE: simple-statement < statement ;
|
||||||
TUPLE: prepared-statement < statement ;
|
TUPLE: prepared-statement < statement ;
|
||||||
|
|
|
@ -154,7 +154,7 @@ M: postgresql-malloc-destructor dispose ( obj -- )
|
||||||
: postgresql-column-typed ( handle row column type -- obj )
|
: postgresql-column-typed ( handle row column type -- obj )
|
||||||
dup array? [ first ] when
|
dup array? [ first ] when
|
||||||
{
|
{
|
||||||
{ +native-id+ [ pq-get-number ] }
|
{ +db-assigned-id+ [ pq-get-number ] }
|
||||||
{ +random-id+ [ pq-get-number ] }
|
{ +random-id+ [ pq-get-number ] }
|
||||||
{ INTEGER [ pq-get-number ] }
|
{ INTEGER [ pq-get-number ] }
|
||||||
{ BIG-INTEGER [ pq-get-number ] }
|
{ BIG-INTEGER [ pq-get-number ] }
|
||||||
|
|
|
@ -6,6 +6,7 @@ sequences debugger db db.postgresql.lib db.postgresql.ffi
|
||||||
db.tuples db.types tools.annotations math.ranges
|
db.tuples db.types tools.annotations math.ranges
|
||||||
combinators sequences.lib classes locals words tools.walker
|
combinators sequences.lib classes locals words tools.walker
|
||||||
namespaces.lib accessors random db.queries ;
|
namespaces.lib accessors random db.queries ;
|
||||||
|
USE: tools.walker
|
||||||
IN: db.postgresql
|
IN: db.postgresql
|
||||||
|
|
||||||
TUPLE: postgresql-db < db
|
TUPLE: postgresql-db < db
|
||||||
|
@ -48,7 +49,8 @@ M: literal-bind postgresql-bind-conversion ( tuple literal-bind -- obj )
|
||||||
nip value>> <low-level-binding> ;
|
nip value>> <low-level-binding> ;
|
||||||
|
|
||||||
M: generator-bind postgresql-bind-conversion ( tuple generate-bind -- obj )
|
M: generator-bind postgresql-bind-conversion ( tuple generate-bind -- obj )
|
||||||
nip singleton>> eval-generator <low-level-binding> ;
|
dup generator-singleton>> eval-generator
|
||||||
|
[ swap slot-name>> rot set-slot-named ] [ <low-level-binding> ] bi ;
|
||||||
|
|
||||||
M: postgresql-statement bind-tuple ( tuple statement -- )
|
M: postgresql-statement bind-tuple ( tuple statement -- )
|
||||||
tuck in-params>>
|
tuck in-params>>
|
||||||
|
@ -158,7 +160,7 @@ M: postgresql-db bind# ( spec obj -- )
|
||||||
M: postgresql-db create-sql-statement ( class -- seq )
|
M: postgresql-db create-sql-statement ( class -- seq )
|
||||||
[
|
[
|
||||||
[ create-table-sql , ] keep
|
[ create-table-sql , ] keep
|
||||||
dup db-columns find-primary-key native-id?
|
dup db-columns find-primary-key db-assigned-id-spec?
|
||||||
[ create-function-sql , ] [ drop ] if
|
[ create-function-sql , ] [ drop ] if
|
||||||
] { } make ;
|
] { } make ;
|
||||||
|
|
||||||
|
@ -179,11 +181,11 @@ M: postgresql-db create-sql-statement ( class -- seq )
|
||||||
M: postgresql-db drop-sql-statement ( class -- seq )
|
M: postgresql-db drop-sql-statement ( class -- seq )
|
||||||
[
|
[
|
||||||
[ drop-table-sql , ] keep
|
[ drop-table-sql , ] keep
|
||||||
dup db-columns find-primary-key native-id?
|
dup db-columns find-primary-key db-assigned-id-spec?
|
||||||
[ drop-function-sql , ] [ drop ] if
|
[ drop-function-sql , ] [ drop ] if
|
||||||
] { } make ;
|
] { } make ;
|
||||||
|
|
||||||
M: postgresql-db <insert-native-statement> ( class -- statement )
|
M: postgresql-db <insert-db-assigned-statement> ( class -- statement )
|
||||||
[
|
[
|
||||||
"select add_" 0% 0%
|
"select add_" 0% 0%
|
||||||
"(" 0%
|
"(" 0%
|
||||||
|
@ -193,7 +195,7 @@ M: postgresql-db <insert-native-statement> ( class -- statement )
|
||||||
");" 0%
|
");" 0%
|
||||||
] query-make ;
|
] query-make ;
|
||||||
|
|
||||||
M: postgresql-db <insert-nonnative-statement> ( class -- statement )
|
M: postgresql-db <insert-user-assigned-statement> ( class -- statement )
|
||||||
[
|
[
|
||||||
"insert into " 0% 0%
|
"insert into " 0% 0%
|
||||||
"(" 0%
|
"(" 0%
|
||||||
|
@ -204,8 +206,10 @@ M: postgresql-db <insert-nonnative-statement> ( class -- statement )
|
||||||
[ ", " 0% ] [
|
[ ", " 0% ] [
|
||||||
dup type>> +random-id+ = [
|
dup type>> +random-id+ = [
|
||||||
[
|
[
|
||||||
drop bind-name%
|
bind-name%
|
||||||
f random-id-generator
|
slot-name>>
|
||||||
|
f
|
||||||
|
random-id-generator
|
||||||
] [ type>> ] bi <generator-bind> 1,
|
] [ type>> ] bi <generator-bind> 1,
|
||||||
] [
|
] [
|
||||||
bind%
|
bind%
|
||||||
|
@ -219,8 +223,8 @@ M: postgresql-db insert-tuple* ( tuple statement -- )
|
||||||
|
|
||||||
M: postgresql-db persistent-table ( -- hashtable )
|
M: postgresql-db persistent-table ( -- hashtable )
|
||||||
H{
|
H{
|
||||||
{ +native-id+ { "integer" "serial primary key" f } }
|
{ +db-assigned-id+ { "integer" "serial primary key" f } }
|
||||||
{ +assigned-id+ { f f "primary key" } }
|
{ +user-assigned-id+ { f f "primary key" } }
|
||||||
{ +random-id+ { "bigint" "bigint primary key" f } }
|
{ +random-id+ { "bigint" "bigint primary key" f } }
|
||||||
{ TEXT { "text" "text" f } }
|
{ TEXT { "text" "text" f } }
|
||||||
{ VARCHAR { "varchar" "varchar" f } }
|
{ VARCHAR { "varchar" "varchar" f } }
|
||||||
|
|
|
@ -15,7 +15,7 @@ GENERIC: where ( specs obj -- )
|
||||||
|
|
||||||
: query-make ( class quot -- )
|
: query-make ( class quot -- )
|
||||||
>r sql-props r>
|
>r sql-props r>
|
||||||
[ 0 sql-counter rot with-variable ] { "" { } { } } nmake
|
[ 0 sql-counter rot with-variable ";" 0% ] { "" { } { } } nmake
|
||||||
<simple-statement> maybe-make-retryable ; inline
|
<simple-statement> maybe-make-retryable ; inline
|
||||||
|
|
||||||
M: db begin-transaction ( -- ) "BEGIN" sql-command ;
|
M: db begin-transaction ( -- ) "BEGIN" sql-command ;
|
||||||
|
@ -35,14 +35,6 @@ M: db <update-tuple-statement> ( class -- statement )
|
||||||
where-primary-key%
|
where-primary-key%
|
||||||
] query-make ;
|
] query-make ;
|
||||||
|
|
||||||
M: db <delete-tuple-statement> ( specs table -- sql )
|
|
||||||
[
|
|
||||||
"delete from " 0% 0%
|
|
||||||
" where " 0%
|
|
||||||
find-primary-key
|
|
||||||
dup column-name>> 0% " = " 0% bind%
|
|
||||||
] query-make ;
|
|
||||||
|
|
||||||
M: random-id-generator eval-generator ( singleton -- obj )
|
M: random-id-generator eval-generator ( singleton -- obj )
|
||||||
drop
|
drop
|
||||||
system-random-generator get [
|
system-random-generator get [
|
||||||
|
@ -52,18 +44,40 @@ M: random-id-generator eval-generator ( singleton -- obj )
|
||||||
: interval-comparison ( ? str -- str )
|
: interval-comparison ( ? str -- str )
|
||||||
"from" = " >" " <" ? swap [ "= " append ] when ;
|
"from" = " >" " <" ? swap [ "= " append ] when ;
|
||||||
|
|
||||||
|
: fp-infinity? ( float -- ? )
|
||||||
|
dup float? [
|
||||||
|
double>bits -52 shift 11 2^ 1- [ bitand ] keep =
|
||||||
|
] [
|
||||||
|
drop f
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: (infinite-interval?) ( interval -- ?1 ?2 )
|
||||||
|
[ from>> ] [ to>> ] bi
|
||||||
|
[ first fp-infinity? ] bi@ ;
|
||||||
|
|
||||||
|
: double-infinite-interval? ( obj -- ? )
|
||||||
|
dup interval? [ (infinite-interval?) and ] [ drop f ] if ;
|
||||||
|
|
||||||
|
: infinite-interval? ( obj -- ? )
|
||||||
|
dup interval? [ (infinite-interval?) or ] [ drop f ] if ;
|
||||||
|
|
||||||
: where-interval ( spec obj from/to -- )
|
: where-interval ( spec obj from/to -- )
|
||||||
|
over first fp-infinity? [
|
||||||
|
3drop
|
||||||
|
] [
|
||||||
pick column-name>> 0%
|
pick column-name>> 0%
|
||||||
>r first2 r> interval-comparison 0%
|
>r first2 r> interval-comparison 0%
|
||||||
bind# ;
|
bind#
|
||||||
|
] if ;
|
||||||
|
|
||||||
: in-parens ( quot -- )
|
: in-parens ( quot -- )
|
||||||
"(" 0% call ")" 0% ; inline
|
"(" 0% call ")" 0% ; inline
|
||||||
|
|
||||||
M: interval where ( spec obj -- )
|
M: interval where ( spec obj -- )
|
||||||
[
|
[
|
||||||
[ from>> "from" where-interval " and " 0% ]
|
[ from>> "from" where-interval ] [
|
||||||
[ to>> "to" where-interval ] 2bi
|
nip infinite-interval? [ " and " 0% ] unless
|
||||||
|
] [ to>> "to" where-interval ] 2tri
|
||||||
] in-parens ;
|
] in-parens ;
|
||||||
|
|
||||||
M: sequence where ( spec obj -- )
|
M: sequence where ( spec obj -- )
|
||||||
|
@ -80,12 +94,29 @@ M: integer where ( spec obj -- ) object-where ;
|
||||||
|
|
||||||
M: string where ( spec obj -- ) object-where ;
|
M: string where ( spec obj -- ) object-where ;
|
||||||
|
|
||||||
|
: filter-slots ( tuple specs -- specs' )
|
||||||
|
[
|
||||||
|
slot-name>> swap get-slot-named
|
||||||
|
dup double-infinite-interval? [ drop f ] when
|
||||||
|
] with filter ;
|
||||||
|
|
||||||
: where-clause ( tuple specs -- )
|
: where-clause ( tuple specs -- )
|
||||||
|
dupd filter-slots
|
||||||
|
dup empty? [
|
||||||
|
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 ;
|
||||||
|
|
||||||
|
M: db <delete-tuple-statement> ( tuple table -- sql )
|
||||||
|
[
|
||||||
|
"delete from " 0% 0%
|
||||||
|
where-clause
|
||||||
|
] query-make ;
|
||||||
|
|
||||||
M: db <select-by-slots-statement> ( tuple class -- statement )
|
M: db <select-by-slots-statement> ( tuple class -- statement )
|
||||||
[
|
[
|
||||||
|
@ -94,7 +125,5 @@ M: db <select-by-slots-statement> ( tuple class -- statement )
|
||||||
[ dup column-name>> 0% 2, ] interleave
|
[ dup column-name>> 0% 2, ] interleave
|
||||||
|
|
||||||
" from " 0% 0%
|
" from " 0% 0%
|
||||||
dupd
|
where-clause
|
||||||
[ slot-name>> swap get-slot-named ] with filter
|
|
||||||
dup empty? [ 2drop ] [ where-clause ] if ";" 0%
|
|
||||||
] query-make ;
|
] query-make ;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
USING: kernel parser quotations classes.tuple words math.order
|
USING: kernel parser quotations classes.tuple words math.order
|
||||||
namespaces.lib namespaces sequences arrays combinators
|
namespaces.lib namespaces sequences arrays combinators
|
||||||
prettyprint strings math.parser sequences.lib math symbols ;
|
prettyprint strings math.parser sequences.lib math symbols ;
|
||||||
USE: tools.walker
|
|
||||||
IN: db.sql
|
IN: db.sql
|
||||||
|
|
||||||
SYMBOLS: insert update delete select distinct columns from as
|
SYMBOLS: insert update delete select distinct columns from as
|
||||||
|
|
|
@ -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
|
||||||
tools.walker io.backend ;
|
io.backend ;
|
||||||
IN: db.sqlite.lib
|
IN: db.sqlite.lib
|
||||||
|
|
||||||
: sqlite-error ( n -- * )
|
: sqlite-error ( n -- * )
|
||||||
|
@ -106,7 +106,7 @@ IN: db.sqlite.lib
|
||||||
object>bytes
|
object>bytes
|
||||||
sqlite-bind-blob-by-name
|
sqlite-bind-blob-by-name
|
||||||
] }
|
] }
|
||||||
{ +native-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 ] }
|
||||||
[ no-sql-type ]
|
[ no-sql-type ]
|
||||||
|
@ -132,7 +132,7 @@ IN: db.sqlite.lib
|
||||||
: sqlite-column-typed ( handle index type -- obj )
|
: sqlite-column-typed ( handle index type -- obj )
|
||||||
dup array? [ first ] when
|
dup array? [ first ] when
|
||||||
{
|
{
|
||||||
{ +native-id+ [ sqlite3_column_int64 ] }
|
{ +db-assigned-id+ [ sqlite3_column_int64 ] }
|
||||||
{ +random-id+ [ sqlite3-column-uint64 ] }
|
{ +random-id+ [ sqlite3-column-uint64 ] }
|
||||||
{ INTEGER [ sqlite3_column_int ] }
|
{ INTEGER [ sqlite3_column_int ] }
|
||||||
{ BIG-INTEGER [ sqlite3_column_int64 ] }
|
{ BIG-INTEGER [ sqlite3_column_int64 ] }
|
||||||
|
|
|
@ -79,8 +79,10 @@ M: literal-bind sqlite-bind-conversion ( tuple literal-bind -- array )
|
||||||
<sqlite-low-level-binding> ;
|
<sqlite-low-level-binding> ;
|
||||||
|
|
||||||
M: generator-bind sqlite-bind-conversion ( tuple generate-bind -- array )
|
M: generator-bind sqlite-bind-conversion ( tuple generate-bind -- array )
|
||||||
nip [ key>> ] [ singleton>> eval-generator ] [ type>> ] tri
|
tuck
|
||||||
<sqlite-low-level-binding> ;
|
[ generator-singleton>> eval-generator tuck ] [ slot-name>> ] bi
|
||||||
|
rot set-slot-named
|
||||||
|
>r [ key>> ] [ type>> ] bi r> swap <sqlite-low-level-binding> ;
|
||||||
|
|
||||||
M: sqlite-statement bind-tuple ( tuple statement -- )
|
M: sqlite-statement bind-tuple ( tuple statement -- )
|
||||||
[
|
[
|
||||||
|
@ -129,19 +131,20 @@ M: sqlite-db create-sql-statement ( class -- statement )
|
||||||
M: sqlite-db drop-sql-statement ( class -- statement )
|
M: sqlite-db drop-sql-statement ( class -- statement )
|
||||||
[ "drop table " 0% 0% ";" 0% drop ] query-make ;
|
[ "drop table " 0% 0% ";" 0% drop ] query-make ;
|
||||||
|
|
||||||
M: sqlite-db <insert-native-statement> ( tuple -- statement )
|
M: sqlite-db <insert-db-assigned-statement> ( tuple -- statement )
|
||||||
[
|
[
|
||||||
"insert into " 0% 0%
|
"insert into " 0% 0%
|
||||||
"(" 0%
|
"(" 0%
|
||||||
maybe-remove-id
|
remove-db-assigned-id
|
||||||
dup [ ", " 0% ] [ column-name>> 0% ] interleave
|
dup [ ", " 0% ] [ column-name>> 0% ] interleave
|
||||||
") values(" 0%
|
") values(" 0%
|
||||||
[ ", " 0% ] [
|
[ ", " 0% ] [
|
||||||
dup type>> +random-id+ = [
|
dup type>> +random-id+ = [
|
||||||
|
[ slot-name>> ]
|
||||||
[
|
[
|
||||||
column-name>> ":" prepend dup 0%
|
column-name>> ":" prepend dup 0%
|
||||||
random-id-generator
|
random-id-generator
|
||||||
] [ type>> ] bi <generator-bind> 1,
|
] [ type>> ] tri <generator-bind> 1,
|
||||||
] [
|
] [
|
||||||
bind%
|
bind%
|
||||||
] if
|
] if
|
||||||
|
@ -149,8 +152,8 @@ M: sqlite-db <insert-native-statement> ( tuple -- statement )
|
||||||
");" 0%
|
");" 0%
|
||||||
] query-make ;
|
] query-make ;
|
||||||
|
|
||||||
M: sqlite-db <insert-nonnative-statement> ( tuple -- statement )
|
M: sqlite-db <insert-user-assigned-statement> ( tuple -- statement )
|
||||||
<insert-native-statement> ;
|
<insert-db-assigned-statement> ;
|
||||||
|
|
||||||
M: sqlite-db bind# ( spec obj -- )
|
M: sqlite-db bind# ( spec obj -- )
|
||||||
>r
|
>r
|
||||||
|
@ -163,8 +166,8 @@ M: sqlite-db bind% ( spec -- )
|
||||||
|
|
||||||
M: sqlite-db persistent-table ( -- assoc )
|
M: sqlite-db persistent-table ( -- assoc )
|
||||||
H{
|
H{
|
||||||
{ +native-id+ { "integer primary key" "integer primary key" "primary key" } }
|
{ +db-assigned-id+ { "integer primary key" "integer primary key" "primary key" } }
|
||||||
{ +assigned-id+ { f f "primary key" } }
|
{ +user-assigned-id+ { f f "primary key" } }
|
||||||
{ +random-id+ { "integer primary key" "integer primary key" "primary key" } }
|
{ +random-id+ { "integer primary key" "integer primary key" "primary key" } }
|
||||||
{ INTEGER { "integer" "integer" "primary key" } }
|
{ INTEGER { "integer" "integer" "primary key" } }
|
||||||
{ BIG-INTEGER { "bigint" "bigint" } }
|
{ BIG-INTEGER { "bigint" "bigint" } }
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: io.files kernel tools.test db db.tuples classes
|
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 tools.walker calendar sequences db.sqlite
|
prettyprint calendar sequences db.sqlite math.intervals
|
||||||
math.intervals db.postgresql accessors random math.bitfields.lib ;
|
db.postgresql accessors random math.bitfields.lib ;
|
||||||
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
|
||||||
|
@ -21,7 +21,7 @@ ts date time blob factor-blob ;
|
||||||
set-person-factor-blob
|
set-person-factor-blob
|
||||||
} person construct ;
|
} person construct ;
|
||||||
|
|
||||||
: <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 -- person )
|
||||||
<person> [ set-person-the-id ] keep ;
|
<person> [ set-person-the-id ] keep ;
|
||||||
|
|
||||||
SYMBOL: person1
|
SYMBOL: person1
|
||||||
|
@ -30,6 +30,7 @@ SYMBOL: person3
|
||||||
SYMBOL: person4
|
SYMBOL: person4
|
||||||
|
|
||||||
: test-tuples ( -- )
|
: test-tuples ( -- )
|
||||||
|
[ ] [ person recreate-table ] unit-test
|
||||||
[ ] [ person ensure-table ] unit-test
|
[ ] [ person ensure-table ] unit-test
|
||||||
[ ] [ person drop-table ] unit-test
|
[ ] [ person drop-table ] unit-test
|
||||||
[ ] [ person create-table ] unit-test
|
[ ] [ person create-table ] unit-test
|
||||||
|
@ -106,10 +107,10 @@ SYMBOL: person4
|
||||||
|
|
||||||
[ ] [ person drop-table ] unit-test ;
|
[ ] [ person drop-table ] unit-test ;
|
||||||
|
|
||||||
: native-person-schema ( -- )
|
: db-assigned-person-schema ( -- )
|
||||||
person "PERSON"
|
person "PERSON"
|
||||||
{
|
{
|
||||||
{ "the-id" "ID" +native-id+ }
|
{ "the-id" "ID" +db-assigned-id+ }
|
||||||
{ "the-name" "NAME" { VARCHAR 256 } +not-null+ }
|
{ "the-name" "NAME" { VARCHAR 256 } +not-null+ }
|
||||||
{ "the-number" "AGE" INTEGER { +default+ 0 } }
|
{ "the-number" "AGE" INTEGER { +default+ 0 } }
|
||||||
{ "the-real" "REAL" DOUBLE { +default+ 0.3 } }
|
{ "the-real" "REAL" DOUBLE { +default+ 0.3 } }
|
||||||
|
@ -132,10 +133,10 @@ 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 H{ { 1 2 } { 3 4 } { 5 "lol" } } <person> person4 set ;
|
f H{ { 1 2 } { 3 4 } { 5 "lol" } } <person> person4 set ;
|
||||||
|
|
||||||
: assigned-person-schema ( -- )
|
: user-assigned-person-schema ( -- )
|
||||||
person "PERSON"
|
person "PERSON"
|
||||||
{
|
{
|
||||||
{ "the-id" "ID" INTEGER +assigned-id+ }
|
{ "the-id" "ID" INTEGER +user-assigned-id+ }
|
||||||
{ "the-name" "NAME" { VARCHAR 256 } +not-null+ }
|
{ "the-name" "NAME" { VARCHAR 256 } +not-null+ }
|
||||||
{ "the-number" "AGE" INTEGER { +default+ 0 } }
|
{ "the-number" "AGE" INTEGER { +default+ 0 } }
|
||||||
{ "the-real" "REAL" DOUBLE { +default+ 0.3 } }
|
{ "the-real" "REAL" DOUBLE { +default+ 0.3 } }
|
||||||
|
@ -145,27 +146,27 @@ SYMBOL: person4
|
||||||
{ "blob" "B" BLOB }
|
{ "blob" "B" BLOB }
|
||||||
{ "factor-blob" "FB" FACTOR-BLOB }
|
{ "factor-blob" "FB" FACTOR-BLOB }
|
||||||
} define-persistent
|
} define-persistent
|
||||||
1 "billy" 10 3.14 f f f f f <assigned-person> person1 set
|
1 "billy" 10 3.14 f f f f f <user-assigned-person> person1 set
|
||||||
2 "johnny" 10 3.14 f f f f f <assigned-person> person2 set
|
2 "johnny" 10 3.14 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 <assigned-person> person3 set
|
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" } } <assigned-person> person4 set ;
|
f H{ { 1 2 } { 3 4 } { 5 "lol" } } <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 ;
|
||||||
|
|
||||||
: native-paste-schema ( -- )
|
: db-assigned-paste-schema ( -- )
|
||||||
paste "PASTE"
|
paste "PASTE"
|
||||||
{
|
{
|
||||||
{ "n" "ID" +native-id+ }
|
{ "n" "ID" +db-assigned-id+ }
|
||||||
{ "summary" "SUMMARY" TEXT }
|
{ "summary" "SUMMARY" TEXT }
|
||||||
{ "author" "AUTHOR" TEXT }
|
{ "author" "AUTHOR" TEXT }
|
||||||
{ "channel" "CHANNEL" TEXT }
|
{ "channel" "CHANNEL" TEXT }
|
||||||
|
@ -177,7 +178,7 @@ TUPLE: annotation n paste-id summary author mode contents ;
|
||||||
|
|
||||||
annotation "ANNOTATION"
|
annotation "ANNOTATION"
|
||||||
{
|
{
|
||||||
{ "n" "ID" +native-id+ }
|
{ "n" "ID" +db-assigned-id+ }
|
||||||
{ "paste-id" "PASTE_ID" INTEGER { +foreign-id+ paste "n" } }
|
{ "paste-id" "PASTE_ID" INTEGER { +foreign-id+ paste "n" } }
|
||||||
{ "summary" "SUMMARY" TEXT }
|
{ "summary" "SUMMARY" TEXT }
|
||||||
{ "author" "AUTHOR" TEXT }
|
{ "author" "AUTHOR" TEXT }
|
||||||
|
@ -210,7 +211,7 @@ TUPLE: serialize-me id data ;
|
||||||
: test-serialize ( -- )
|
: test-serialize ( -- )
|
||||||
serialize-me "SERIALIZED"
|
serialize-me "SERIALIZED"
|
||||||
{
|
{
|
||||||
{ "id" "ID" +native-id+ }
|
{ "id" "ID" +db-assigned-id+ }
|
||||||
{ "data" "DATA" FACTOR-BLOB }
|
{ "data" "DATA" FACTOR-BLOB }
|
||||||
} define-persistent
|
} define-persistent
|
||||||
[ serialize-me drop-table ] [ drop ] recover
|
[ serialize-me drop-table ] [ drop ] recover
|
||||||
|
@ -226,7 +227,7 @@ TUPLE: exam id name score ;
|
||||||
: test-intervals ( -- )
|
: test-intervals ( -- )
|
||||||
exam "EXAM"
|
exam "EXAM"
|
||||||
{
|
{
|
||||||
{ "id" "ID" +native-id+ }
|
{ "id" "ID" +db-assigned-id+ }
|
||||||
{ "name" "NAME" TEXT }
|
{ "name" "NAME" TEXT }
|
||||||
{ "score" "SCORE" INTEGER }
|
{ "score" "SCORE" INTEGER }
|
||||||
} define-persistent
|
} define-persistent
|
||||||
|
@ -292,6 +293,46 @@ TUPLE: exam id name score ;
|
||||||
}
|
}
|
||||||
] [
|
] [
|
||||||
T{ exam f T{ range f 1 3 1 } } select-tuples
|
T{ exam f T{ range f 1 3 1 } } select-tuples
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
T{ exam f 2 "Stan" 80 }
|
||||||
|
T{ exam f 3 "Kenny" 60 }
|
||||||
|
T{ exam f 4 "Cartman" 41 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
T{ exam f T{ interval f { 2 t } { 1.0/0.0 f } } } select-tuples
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
T{ exam f 1 "Kyle" 100 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
T{ exam f T{ interval f { -1.0/0.0 t } { 2 f } } } select-tuples
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
T{ exam f 1 "Kyle" 100 }
|
||||||
|
T{ exam f 2 "Stan" 80 }
|
||||||
|
T{ exam f 3 "Kenny" 60 }
|
||||||
|
T{ exam f 4 "Cartman" 41 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
T{ exam f T{ interval f { -1.0/0.0 t } { 1/0. f } } } select-tuples
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
T{ exam f 1 "Kyle" 100 }
|
||||||
|
T{ exam f 2 "Stan" 80 }
|
||||||
|
T{ exam f 3 "Kenny" 60 }
|
||||||
|
T{ exam f 4 "Cartman" 41 }
|
||||||
|
}
|
||||||
|
] [
|
||||||
|
T{ exam } select-tuples
|
||||||
] unit-test ;
|
] unit-test ;
|
||||||
|
|
||||||
TUPLE: bignum-test id m n o ;
|
TUPLE: bignum-test id m n o ;
|
||||||
|
@ -304,7 +345,7 @@ TUPLE: bignum-test id m n o ;
|
||||||
: test-bignum
|
: test-bignum
|
||||||
bignum-test "BIGNUM_TEST"
|
bignum-test "BIGNUM_TEST"
|
||||||
{
|
{
|
||||||
{ "id" "ID" +native-id+ }
|
{ "id" "ID" +db-assigned-id+ }
|
||||||
{ "m" "M" BIG-INTEGER }
|
{ "m" "M" BIG-INTEGER }
|
||||||
{ "n" "N" UNSIGNED-BIG-INTEGER }
|
{ "n" "N" UNSIGNED-BIG-INTEGER }
|
||||||
{ "o" "O" SIGNED-BIG-INTEGER }
|
{ "o" "O" SIGNED-BIG-INTEGER }
|
||||||
|
@ -328,9 +369,9 @@ C: <secret> secret
|
||||||
{ "message" "MESSAGE" TEXT }
|
{ "message" "MESSAGE" TEXT }
|
||||||
} define-persistent
|
} define-persistent
|
||||||
|
|
||||||
[ ] [ secret ensure-table ] unit-test
|
[ ] [ secret recreate-table ] unit-test
|
||||||
|
|
||||||
[ ] [ f "kilroy was here" <secret> insert-tuple ] unit-test
|
[ t ] [ f "kilroy was here" <secret> [ insert-tuple ] keep n>> integer? ] unit-test
|
||||||
|
|
||||||
[ ] [ f "kilroy was here2" <secret> insert-tuple ] unit-test
|
[ ] [ f "kilroy was here2" <secret> insert-tuple ] unit-test
|
||||||
|
|
||||||
|
@ -345,17 +386,17 @@ C: <secret> secret
|
||||||
T{ secret } select-tuples length 3 =
|
T{ secret } select-tuples length 3 =
|
||||||
] unit-test ;
|
] unit-test ;
|
||||||
|
|
||||||
[ native-person-schema test-tuples ] test-sqlite
|
[ db-assigned-person-schema test-tuples ] test-sqlite
|
||||||
[ assigned-person-schema test-tuples ] test-sqlite
|
[ user-assigned-person-schema test-tuples ] test-sqlite
|
||||||
[ assigned-person-schema test-repeated-insert ] test-sqlite
|
[ user-assigned-person-schema test-repeated-insert ] test-sqlite
|
||||||
[ test-bignum ] test-sqlite
|
[ test-bignum ] test-sqlite
|
||||||
[ test-serialize ] test-sqlite
|
[ test-serialize ] test-sqlite
|
||||||
[ test-intervals ] test-sqlite
|
[ test-intervals ] test-sqlite
|
||||||
[ test-random-id ] test-sqlite
|
[ test-random-id ] test-sqlite
|
||||||
|
|
||||||
[ native-person-schema test-tuples ] test-postgresql
|
[ db-assigned-person-schema test-tuples ] test-postgresql
|
||||||
[ assigned-person-schema test-tuples ] test-postgresql
|
[ user-assigned-person-schema test-tuples ] test-postgresql
|
||||||
[ assigned-person-schema test-repeated-insert ] test-postgresql
|
[ user-assigned-person-schema test-repeated-insert ] test-postgresql
|
||||||
[ test-bignum ] test-postgresql
|
[ test-bignum ] test-postgresql
|
||||||
[ test-serialize ] test-postgresql
|
[ test-serialize ] test-postgresql
|
||||||
[ test-intervals ] test-postgresql
|
[ test-intervals ] test-postgresql
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
USING: arrays assocs classes db kernel namespaces
|
USING: arrays assocs classes db kernel namespaces
|
||||||
classes.tuple words sequences slots math accessors
|
classes.tuple words sequences slots math accessors
|
||||||
math.parser io prettyprint db.types continuations
|
math.parser io prettyprint db.types continuations
|
||||||
mirrors sequences.lib tools.walker combinators.lib ;
|
mirrors sequences.lib combinators.lib ;
|
||||||
IN: db.tuples
|
IN: db.tuples
|
||||||
|
|
||||||
: define-persistent ( class table columns -- )
|
: define-persistent ( class table columns -- )
|
||||||
|
@ -37,15 +37,10 @@ SYMBOL: sql-counter
|
||||||
HOOK: create-sql-statement db ( class -- obj )
|
HOOK: create-sql-statement db ( class -- obj )
|
||||||
HOOK: drop-sql-statement db ( class -- obj )
|
HOOK: drop-sql-statement db ( class -- obj )
|
||||||
|
|
||||||
HOOK: <insert-native-statement> db ( class -- obj )
|
HOOK: <insert-db-assigned-statement> db ( class -- obj )
|
||||||
HOOK: <insert-nonnative-statement> db ( class -- obj )
|
HOOK: <insert-user-assigned-statement> db ( class -- obj )
|
||||||
|
|
||||||
HOOK: <update-tuple-statement> db ( class -- obj )
|
HOOK: <update-tuple-statement> db ( class -- obj )
|
||||||
HOOK: <update-tuples-statement> db ( class -- obj )
|
HOOK: <delete-tuple-statement> db ( tuple class -- obj )
|
||||||
|
|
||||||
HOOK: <delete-tuple-statement> db ( class -- obj )
|
|
||||||
HOOK: <delete-tuples-statement> db ( class -- obj )
|
|
||||||
|
|
||||||
HOOK: <select-by-slots-statement> db ( tuple class -- tuple )
|
HOOK: <select-by-slots-statement> db ( tuple class -- tuple )
|
||||||
|
|
||||||
HOOK: insert-tuple* db ( tuple statement -- )
|
HOOK: insert-tuple* db ( tuple statement -- )
|
||||||
|
@ -65,7 +60,7 @@ SINGLETON: retryable
|
||||||
[ bind-params>> ] [ in-params>> ] bi
|
[ bind-params>> ] [ in-params>> ] bi
|
||||||
[
|
[
|
||||||
dup generator-bind? [
|
dup generator-bind? [
|
||||||
singleton>> eval-generator >>value
|
generator-singleton>> eval-generator >>value
|
||||||
] [
|
] [
|
||||||
drop
|
drop
|
||||||
] if
|
] if
|
||||||
|
@ -113,25 +108,28 @@ M: retryable execute-statement* ( statement type -- )
|
||||||
: drop-table ( class -- )
|
: drop-table ( class -- )
|
||||||
drop-sql-statement [ execute-statement ] with-disposals ;
|
drop-sql-statement [ execute-statement ] with-disposals ;
|
||||||
|
|
||||||
: ensure-table ( class -- )
|
: recreate-table ( class -- )
|
||||||
[
|
[
|
||||||
drop-sql-statement make-nonthrowable
|
drop-sql-statement make-nonthrowable
|
||||||
[ execute-statement ] with-disposals
|
[ execute-statement ] with-disposals
|
||||||
] [ create-table ] bi ;
|
] [ create-table ] bi ;
|
||||||
|
|
||||||
: insert-native ( tuple -- )
|
: ensure-table ( class -- )
|
||||||
|
[ create-table ] curry ignore-errors ;
|
||||||
|
|
||||||
|
: insert-db-assigned-statement ( tuple -- )
|
||||||
dup class
|
dup class
|
||||||
db get db-insert-statements [ <insert-native-statement> ] cache
|
db get db-insert-statements [ <insert-db-assigned-statement> ] cache
|
||||||
[ bind-tuple ] 2keep insert-tuple* ;
|
[ bind-tuple ] 2keep insert-tuple* ;
|
||||||
|
|
||||||
: insert-nonnative ( tuple -- )
|
: insert-user-assigned-statement ( tuple -- )
|
||||||
dup class
|
dup class
|
||||||
db get db-insert-statements [ <insert-nonnative-statement> ] cache
|
db get db-insert-statements [ <insert-user-assigned-statement> ] cache
|
||||||
[ bind-tuple ] keep execute-statement ;
|
[ bind-tuple ] keep execute-statement ;
|
||||||
|
|
||||||
: insert-tuple ( tuple -- )
|
: insert-tuple ( tuple -- )
|
||||||
dup class db-columns find-primary-key nonnative-id?
|
dup class db-columns find-primary-key db-assigned-id-spec?
|
||||||
[ insert-nonnative ] [ insert-native ] if ;
|
[ insert-db-assigned-statement ] [ insert-user-assigned-statement ] if ;
|
||||||
|
|
||||||
: update-tuple ( tuple -- )
|
: update-tuple ( tuple -- )
|
||||||
dup class
|
dup class
|
||||||
|
@ -139,9 +137,9 @@ M: retryable execute-statement* ( statement type -- )
|
||||||
[ bind-tuple ] keep execute-statement ;
|
[ bind-tuple ] keep execute-statement ;
|
||||||
|
|
||||||
: delete-tuple ( tuple -- )
|
: delete-tuple ( tuple -- )
|
||||||
dup class
|
dup dup class <delete-tuple-statement> [
|
||||||
db get db-delete-statements [ <delete-tuple-statement> ] cache
|
[ bind-tuple ] keep execute-statement
|
||||||
[ bind-tuple ] keep execute-statement ;
|
] with-disposal ;
|
||||||
|
|
||||||
: select-tuples ( tuple -- tuples )
|
: select-tuples ( tuple -- tuples )
|
||||||
dup dup class <select-by-slots-statement> [
|
dup dup class <select-by-slots-statement> [
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: arrays assocs db kernel math math.parser
|
USING: arrays assocs db kernel math math.parser
|
||||||
sequences continuations sequences.deep sequences.lib
|
sequences continuations sequences.deep sequences.lib
|
||||||
words namespaces tools.walker slots slots.private classes
|
words namespaces slots slots.private classes mirrors
|
||||||
mirrors classes.tuple combinators calendar.format symbols
|
classes.tuple combinators calendar.format symbols
|
||||||
classes.singleton accessors quotations random ;
|
classes.singleton accessors quotations random ;
|
||||||
IN: db.types
|
IN: db.types
|
||||||
|
|
||||||
|
@ -15,18 +15,17 @@ TUPLE: sql-spec class slot-name column-name type primary-key modifiers ;
|
||||||
TUPLE: literal-bind key type value ;
|
TUPLE: literal-bind key type value ;
|
||||||
C: <literal-bind> literal-bind
|
C: <literal-bind> literal-bind
|
||||||
|
|
||||||
TUPLE: generator-bind key singleton type ;
|
TUPLE: generator-bind slot-name key generator-singleton type ;
|
||||||
C: <generator-bind> generator-bind
|
C: <generator-bind> generator-bind
|
||||||
SINGLETON: random-id-generator
|
SINGLETON: random-id-generator
|
||||||
|
|
||||||
TUPLE: low-level-binding value ;
|
TUPLE: low-level-binding value ;
|
||||||
C: <low-level-binding> low-level-binding
|
C: <low-level-binding> low-level-binding
|
||||||
|
|
||||||
SINGLETON: +native-id+
|
SINGLETON: +db-assigned-id+
|
||||||
SINGLETON: +assigned-id+
|
SINGLETON: +user-assigned-id+
|
||||||
SINGLETON: +random-id+
|
SINGLETON: +random-id+
|
||||||
UNION: +primary-key+ +native-id+ +assigned-id+ +random-id+ ;
|
UNION: +primary-key+ +db-assigned-id+ +user-assigned-id+ +random-id+ ;
|
||||||
UNION: +nonnative-id+ +random-id+ +assigned-id+ ;
|
|
||||||
|
|
||||||
SYMBOLS: +autoincrement+ +serial+ +unique+ +default+ +null+ +not-null+
|
SYMBOLS: +autoincrement+ +serial+ +unique+ +default+ +null+ +not-null+
|
||||||
+foreign-id+ +has-many+ ;
|
+foreign-id+ +has-many+ ;
|
||||||
|
@ -43,11 +42,11 @@ SYMBOLS: +autoincrement+ +serial+ +unique+ +default+ +null+ +not-null+
|
||||||
: primary-key? ( spec -- ? )
|
: primary-key? ( spec -- ? )
|
||||||
primary-key>> +primary-key+? ;
|
primary-key>> +primary-key+? ;
|
||||||
|
|
||||||
: native-id? ( spec -- ? )
|
: db-assigned-id-spec? ( spec -- ? )
|
||||||
primary-key>> +native-id+? ;
|
primary-key>> +db-assigned-id+? ;
|
||||||
|
|
||||||
: nonnative-id? ( spec -- ? )
|
: assigned-id-spec? ( spec -- ? )
|
||||||
primary-key>> +nonnative-id+? ;
|
primary-key>> +user-assigned-id+? ;
|
||||||
|
|
||||||
: normalize-spec ( spec -- )
|
: normalize-spec ( spec -- )
|
||||||
dup type>> dup +primary-key+? [
|
dup type>> dup +primary-key+? [
|
||||||
|
@ -82,8 +81,8 @@ FACTOR-BLOB NULL ;
|
||||||
: number>string* ( n/str -- str )
|
: number>string* ( n/str -- str )
|
||||||
dup number? [ number>string ] when ;
|
dup number? [ number>string ] when ;
|
||||||
|
|
||||||
: maybe-remove-id ( specs -- obj )
|
: remove-db-assigned-id ( specs -- obj )
|
||||||
[ +native-id+? not ] filter ;
|
[ +db-assigned-id+? not ] filter ;
|
||||||
|
|
||||||
: remove-relations ( specs -- newcolumns )
|
: remove-relations ( specs -- newcolumns )
|
||||||
[ relation? not ] filter ;
|
[ relation? not ] filter ;
|
||||||
|
|
|
@ -113,7 +113,7 @@ ARTICLE: "help" "Help system"
|
||||||
"The help system maintains documentation written in a simple markup language, along with cross-referencing and search. Documentation can either exist as free-standing " { $emphasis "articles" } " or be associated with words."
|
"The help system maintains documentation written in a simple markup language, along with cross-referencing and search. Documentation can either exist as free-standing " { $emphasis "articles" } " or be associated with words."
|
||||||
{ $subsection "browsing-help" }
|
{ $subsection "browsing-help" }
|
||||||
{ $subsection "writing-help" }
|
{ $subsection "writing-help" }
|
||||||
{ $subsection "help.lint" }
|
{ $vocab-subsection "Help lint tool" "help.lint" }
|
||||||
{ $subsection "help-impl" } ;
|
{ $subsection "help-impl" } ;
|
||||||
|
|
||||||
IN: help
|
IN: help
|
||||||
|
|
|
@ -194,7 +194,7 @@ test-db [
|
||||||
<dispatcher>
|
<dispatcher>
|
||||||
<action> <protected>
|
<action> <protected>
|
||||||
<login>
|
<login>
|
||||||
<session-manager>
|
<sessions>
|
||||||
sessions-in-db >>sessions
|
sessions-in-db >>sessions
|
||||||
"" add-responder
|
"" add-responder
|
||||||
add-quit-action
|
add-quit-action
|
||||||
|
@ -225,7 +225,7 @@ test-db [
|
||||||
<dispatcher>
|
<dispatcher>
|
||||||
<action> [ "text/plain" <content> [ "Hi" write ] >>body ] >>display
|
<action> [ "text/plain" <content> [ "Hi" write ] >>body ] >>display
|
||||||
<login>
|
<login>
|
||||||
<session-manager>
|
<sessions>
|
||||||
sessions-in-db >>sessions
|
sessions-in-db >>sessions
|
||||||
"" add-responder
|
"" add-responder
|
||||||
add-quit-action
|
add-quit-action
|
||||||
|
|
|
@ -7,7 +7,7 @@ IN: http.server.auth.providers.db
|
||||||
|
|
||||||
user "USERS"
|
user "USERS"
|
||||||
{
|
{
|
||||||
{ "username" "USERNAME" { VARCHAR 256 } +assigned-id+ }
|
{ "username" "USERNAME" { VARCHAR 256 } +user-assigned-id+ }
|
||||||
{ "realname" "REALNAME" { VARCHAR 256 } }
|
{ "realname" "REALNAME" { VARCHAR 256 } }
|
||||||
{ "password" "PASSWORD" { VARCHAR 256 } +not-null+ }
|
{ "password" "PASSWORD" { VARCHAR 256 } +not-null+ }
|
||||||
{ "email" "EMAIL" { VARCHAR 256 } }
|
{ "email" "EMAIL" { VARCHAR 256 } }
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
IN: http.server.sessions.tests
|
IN: http.server.sessions.tests
|
||||||
USING: tools.test http http.server.sessions
|
USING: tools.test http http.server.sessions
|
||||||
http.server.sessions.storage http.server.sessions.storage.db
|
|
||||||
http.server.actions http.server math namespaces kernel accessors
|
http.server.actions http.server math namespaces kernel accessors
|
||||||
prettyprint io.streams.string io.files splitting destructors
|
prettyprint io.streams.string io.files splitting destructors
|
||||||
sequences db db.sqlite continuations ;
|
sequences db db.sqlite continuations ;
|
||||||
|
|
||||||
: with-session
|
: with-session
|
||||||
[
|
[
|
||||||
>r
|
>r [ save-session-after ] [ session set ] bi r> call
|
||||||
[ session-manager get swap save-session-after ]
|
|
||||||
[ \ session set ] bi
|
|
||||||
r> call
|
|
||||||
] with-destructors ; inline
|
] with-destructors ; inline
|
||||||
|
|
||||||
TUPLE: foo ;
|
TUPLE: foo ;
|
||||||
|
@ -31,18 +27,18 @@ M: foo call-responder*
|
||||||
"id" get session-id-key set-query-param
|
"id" get session-id-key set-query-param
|
||||||
"/" >>path
|
"/" >>path
|
||||||
request set
|
request set
|
||||||
{ } session-manager get call-responder
|
{ } sessions get call-responder
|
||||||
[ write-response-body drop ] with-string-writer
|
[ write-response-body drop ] with-string-writer
|
||||||
] with-destructors ;
|
] with-destructors ;
|
||||||
|
|
||||||
: session-manager-mock-test
|
: sessions-mock-test
|
||||||
[
|
[
|
||||||
<request>
|
<request>
|
||||||
"GET" >>method
|
"GET" >>method
|
||||||
"cookies" get >>cookies
|
"cookies" get >>cookies
|
||||||
"/" >>path
|
"/" >>path
|
||||||
request set
|
request set
|
||||||
{ } session-manager get call-responder
|
{ } sessions get call-responder
|
||||||
[ write-response-body drop ] with-string-writer
|
[ write-response-body drop ] with-string-writer
|
||||||
] with-destructors ;
|
] with-destructors ;
|
||||||
|
|
||||||
|
@ -60,14 +56,15 @@ M: foo call-responder*
|
||||||
init-sessions-table
|
init-sessions-table
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
<foo> <session-manager>
|
<foo> <sessions>
|
||||||
sessions-in-db >>sessions
|
sessions set
|
||||||
session-manager set
|
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
|
[ ] [
|
||||||
empty-session
|
empty-session
|
||||||
123 >>id session set
|
123 >>id session set
|
||||||
|
] unit-test
|
||||||
|
|
||||||
[ ] [ 3 "x" sset ] unit-test
|
[ ] [ 3 "x" sset ] unit-test
|
||||||
|
|
||||||
|
@ -81,39 +78,38 @@ M: foo call-responder*
|
||||||
] with-scope
|
] with-scope
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
session-manager get begin-session id>>
|
begin-session id>>
|
||||||
session-manager get sessions>> get-session session?
|
get-session session?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ { 5 0 } ] [
|
[ { 5 0 } ] [
|
||||||
[
|
[
|
||||||
session-manager get begin-session
|
begin-session
|
||||||
dup [ 5 "a" sset ] with-session
|
dup [ 5 "a" sset ] with-session
|
||||||
dup [ "a" sget , ] with-session
|
dup [ "a" sget , ] with-session
|
||||||
dup [ "x" sget , ] with-session
|
dup [ "x" sget , ] with-session
|
||||||
id>> session-manager get sessions>> delete-session
|
drop
|
||||||
] { } make
|
] { } make
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ 0 ] [
|
[ 0 ] [
|
||||||
session-manager get begin-session id>>
|
begin-session id>>
|
||||||
session-manager get sessions>> get-session [ "x" sget ] with-session
|
get-session [ "x" sget ] with-session
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ { 5 0 } ] [
|
[ { 5 0 } ] [
|
||||||
[
|
[
|
||||||
session-manager get begin-session id>>
|
begin-session id>>
|
||||||
dup session-manager get sessions>> get-session [ 5 "a" sset ] with-session
|
dup get-session [ 5 "a" sset ] with-session
|
||||||
dup session-manager get sessions>> get-session [ "a" sget , ] with-session
|
dup get-session [ "a" sget , ] with-session
|
||||||
dup session-manager get sessions>> get-session [ "x" sget , ] with-session
|
dup get-session [ "x" sget , ] with-session
|
||||||
session-manager get sessions>> delete-session
|
drop
|
||||||
] { } make
|
] { } make
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
<foo> <session-manager>
|
<foo> <sessions>
|
||||||
sessions-in-db >>sessions
|
sessions set
|
||||||
session-manager set
|
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@ -121,7 +117,7 @@ M: foo call-responder*
|
||||||
"GET" >>method
|
"GET" >>method
|
||||||
"/" >>path
|
"/" >>path
|
||||||
request set
|
request set
|
||||||
{ "etc" } session-manager get call-responder response set
|
{ "etc" } sessions get call-responder response set
|
||||||
[ "1" ] [ [ response get write-response-body drop ] with-string-writer ] unit-test
|
[ "1" ] [ [ response get write-response-body drop ] with-string-writer ] unit-test
|
||||||
response get
|
response get
|
||||||
] with-destructors
|
] with-destructors
|
||||||
|
@ -129,9 +125,9 @@ M: foo call-responder*
|
||||||
|
|
||||||
[ ] [ response get cookies>> "cookies" set ] unit-test
|
[ ] [ response get cookies>> "cookies" set ] unit-test
|
||||||
|
|
||||||
[ "2" ] [ session-manager-mock-test ] unit-test
|
[ "2" ] [ sessions-mock-test ] unit-test
|
||||||
[ "3" ] [ session-manager-mock-test ] unit-test
|
[ "3" ] [ sessions-mock-test ] unit-test
|
||||||
[ "4" ] [ session-manager-mock-test ] unit-test
|
[ "4" ] [ sessions-mock-test ] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
[ ] [
|
[ ] [
|
||||||
|
@ -142,8 +138,7 @@ M: foo call-responder*
|
||||||
request set
|
request set
|
||||||
|
|
||||||
[
|
[
|
||||||
{ } <exiting-action> <session-manager>
|
{ } <exiting-action> <sessions>
|
||||||
sessions-in-db >>sessions
|
|
||||||
call-responder
|
call-responder
|
||||||
] with-destructors response set
|
] with-destructors response set
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
! Copyright (C) 2008 Doug Coleman, Slava Pestov.
|
! Copyright (C) 2008 Doug Coleman, Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: assocs kernel math.parser namespaces random
|
USING: assocs kernel math.intervals math.parser namespaces
|
||||||
accessors quotations hashtables sequences continuations
|
random accessors quotations hashtables sequences continuations
|
||||||
fry calendar combinators destructors
|
fry calendar combinators destructors alarms
|
||||||
http
|
db db.tuples db.types
|
||||||
http.server
|
http http.server html.elements ;
|
||||||
http.server.sessions.storage
|
|
||||||
http.server.sessions.storage.null
|
|
||||||
html.elements ;
|
|
||||||
IN: http.server.sessions
|
IN: http.server.sessions
|
||||||
|
|
||||||
TUPLE: session id expires namespace changed? ;
|
TUPLE: session id expires namespace changed? ;
|
||||||
|
@ -16,6 +13,28 @@ TUPLE: session id expires namespace changed? ;
|
||||||
session new
|
session new
|
||||||
swap >>id ;
|
swap >>id ;
|
||||||
|
|
||||||
|
session "SESSIONS"
|
||||||
|
{
|
||||||
|
{ "id" "ID" +random-id+ system-random-generator }
|
||||||
|
{ "expires" "EXPIRES" BIG-INTEGER +not-null+ }
|
||||||
|
{ "namespace" "NAMESPACE" FACTOR-BLOB }
|
||||||
|
} define-persistent
|
||||||
|
|
||||||
|
: get-session ( id -- session )
|
||||||
|
dup [ <session> select-tuple ] when ;
|
||||||
|
|
||||||
|
: init-sessions-table session ensure-table ;
|
||||||
|
|
||||||
|
: expired-sessions ( -- session )
|
||||||
|
f <session>
|
||||||
|
-1.0/0.0 now timestamp>millis [a,b] >>expires
|
||||||
|
select-tuples ;
|
||||||
|
|
||||||
|
: start-expiring-sessions ( db seq -- )
|
||||||
|
'[
|
||||||
|
, , [ expired-sessions [ delete-tuple ] each ] with-db
|
||||||
|
] 5 minutes every drop ;
|
||||||
|
|
||||||
GENERIC: init-session* ( responder -- )
|
GENERIC: init-session* ( responder -- )
|
||||||
|
|
||||||
M: object init-session* drop ;
|
M: object init-session* drop ;
|
||||||
|
@ -24,12 +43,11 @@ M: dispatcher init-session* default>> init-session* ;
|
||||||
|
|
||||||
M: filter-responder init-session* responder>> init-session* ;
|
M: filter-responder init-session* responder>> init-session* ;
|
||||||
|
|
||||||
TUPLE: session-manager < filter-responder sessions timeout domain ;
|
TUPLE: sessions < filter-responder timeout domain ;
|
||||||
|
|
||||||
: <session-manager> ( responder -- responder' )
|
: <sessions> ( responder -- responder' )
|
||||||
session-manager new
|
sessions new
|
||||||
swap >>responder
|
swap >>responder
|
||||||
null-sessions >>sessions
|
|
||||||
20 minutes >>timeout ;
|
20 minutes >>timeout ;
|
||||||
|
|
||||||
: (session-changed) ( session -- )
|
: (session-changed) ( session -- )
|
||||||
|
@ -50,11 +68,11 @@ TUPLE: session-manager < filter-responder sessions timeout domain ;
|
||||||
[ namespace>> swap change-at ] keep
|
[ namespace>> swap change-at ] keep
|
||||||
(session-changed) ; inline
|
(session-changed) ; inline
|
||||||
|
|
||||||
: init-session ( session managed -- )
|
: init-session ( session -- )
|
||||||
>r session r> '[ , init-session* ] with-variable ;
|
session [ sessions get init-session* ] with-variable ;
|
||||||
|
|
||||||
: cutoff-time ( -- time )
|
: cutoff-time ( -- time )
|
||||||
session-manager get timeout>> from-now timestamp>millis ;
|
sessions get timeout>> from-now timestamp>millis ;
|
||||||
|
|
||||||
: touch-session ( session -- )
|
: touch-session ( session -- )
|
||||||
cutoff-time >>expires drop ;
|
cutoff-time >>expires drop ;
|
||||||
|
@ -64,57 +82,50 @@ TUPLE: session-manager < filter-responder sessions timeout domain ;
|
||||||
H{ } clone >>namespace
|
H{ } clone >>namespace
|
||||||
dup touch-session ;
|
dup touch-session ;
|
||||||
|
|
||||||
: begin-session ( responder -- session )
|
: begin-session ( -- session )
|
||||||
>r empty-session r>
|
empty-session [ init-session ] [ insert-tuple ] [ ] tri ;
|
||||||
[ init-session ]
|
|
||||||
[ sessions>> new-session ]
|
|
||||||
[ drop ]
|
|
||||||
2tri ;
|
|
||||||
|
|
||||||
! Destructor
|
! Destructor
|
||||||
TUPLE: session-saver manager session ;
|
TUPLE: session-saver session ;
|
||||||
|
|
||||||
C: <session-saver> session-saver
|
C: <session-saver> session-saver
|
||||||
|
|
||||||
M: session-saver dispose
|
M: session-saver dispose
|
||||||
[ session>> ] [ manager>> sessions>> ] bi
|
session>> dup changed?>> [
|
||||||
over changed?>> [
|
[ touch-session ] [ update-tuple ] bi
|
||||||
[ drop touch-session ] [ update-session ] 2bi
|
] [ drop ] if ;
|
||||||
] [ 2drop ] if ;
|
|
||||||
|
|
||||||
: save-session-after ( manager session -- )
|
: save-session-after ( session -- )
|
||||||
<session-saver> add-always-destructor ;
|
<session-saver> add-always-destructor ;
|
||||||
|
|
||||||
: existing-session ( path manager session -- response )
|
: existing-session ( path session -- response )
|
||||||
[ nip session set ]
|
[ session set ] [ save-session-after ] bi
|
||||||
[ save-session-after ]
|
sessions get responder>> call-responder ;
|
||||||
[ drop responder>> ] 2tri
|
|
||||||
call-responder ;
|
|
||||||
|
|
||||||
: session-id-key "factorsessid" ;
|
: session-id-key "factorsessid" ;
|
||||||
|
|
||||||
: cookie-session-id ( -- id/f )
|
: cookie-session-id ( request -- id/f )
|
||||||
request get session-id-key get-cookie
|
session-id-key get-cookie
|
||||||
dup [ value>> string>number ] when ;
|
dup [ value>> string>number ] when ;
|
||||||
|
|
||||||
: post-session-id ( -- id/f )
|
: post-session-id ( request -- id/f )
|
||||||
session-id-key request get post-data>> at string>number ;
|
session-id-key swap post-data>> at string>number ;
|
||||||
|
|
||||||
: request-session-id ( -- id/f )
|
: request-session-id ( -- id/f )
|
||||||
request get method>> {
|
request get dup method>> {
|
||||||
{ "GET" [ cookie-session-id ] }
|
{ "GET" [ cookie-session-id ] }
|
||||||
{ "HEAD" [ cookie-session-id ] }
|
{ "HEAD" [ cookie-session-id ] }
|
||||||
{ "POST" [ post-session-id ] }
|
{ "POST" [ post-session-id ] }
|
||||||
} case ;
|
} case ;
|
||||||
|
|
||||||
: request-session ( responder -- session/f )
|
: request-session ( -- session/f )
|
||||||
>r request-session-id r> sessions>> get-session ;
|
request-session-id get-session ;
|
||||||
|
|
||||||
: <session-cookie> ( id -- cookie )
|
: <session-cookie> ( id -- cookie )
|
||||||
session-id-key <cookie>
|
session-id-key <cookie>
|
||||||
"$session-manager" resolve-base-path >>path
|
"$sessions" resolve-base-path >>path
|
||||||
session-manager get timeout>> from-now >>expires
|
sessions get timeout>> from-now >>expires
|
||||||
session-manager get domain>> >>domain ;
|
sessions get domain>> >>domain ;
|
||||||
|
|
||||||
: put-session-cookie ( response -- response' )
|
: put-session-cookie ( response -- response' )
|
||||||
session get id>> number>string <session-cookie> put-cookie ;
|
session get id>> number>string <session-cookie> put-cookie ;
|
||||||
|
@ -126,8 +137,8 @@ M: session-saver dispose
|
||||||
session get id>> number>string =value
|
session get id>> number>string =value
|
||||||
input/> ;
|
input/> ;
|
||||||
|
|
||||||
M: session-manager call-responder* ( path responder -- response )
|
M: sessions call-responder* ( path responder -- response )
|
||||||
[ session-form-field ] add-form-hook
|
[ session-form-field ] add-form-hook
|
||||||
dup session-manager set
|
sessions set
|
||||||
dup request-session [ dup begin-session ] unless*
|
request-session [ begin-session ] unless*
|
||||||
existing-session put-session-cookie ;
|
existing-session put-session-cookie ;
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
USING: assocs accessors kernel http.server.sessions.storage
|
|
||||||
http.server.sessions http.server db db.tuples db.types math.parser
|
|
||||||
math.intervals fry random calendar sequences alarms ;
|
|
||||||
IN: http.server.sessions.storage.db
|
|
||||||
|
|
||||||
SINGLETON: sessions-in-db
|
|
||||||
|
|
||||||
session "SESSIONS"
|
|
||||||
{
|
|
||||||
! { "id" "ID" +random-id+ system-random-generator }
|
|
||||||
{ "id" "ID" INTEGER +native-id+ }
|
|
||||||
{ "expires" "EXPIRES" BIG-INTEGER +not-null+ }
|
|
||||||
{ "namespace" "NAMESPACE" FACTOR-BLOB }
|
|
||||||
} define-persistent
|
|
||||||
|
|
||||||
: init-sessions-table session ensure-table ;
|
|
||||||
|
|
||||||
M: sessions-in-db get-session ( id storage -- session/f )
|
|
||||||
drop dup [ <session> select-tuple ] when ;
|
|
||||||
|
|
||||||
M: sessions-in-db update-session ( session storage -- )
|
|
||||||
drop update-tuple ;
|
|
||||||
|
|
||||||
M: sessions-in-db delete-session ( id storage -- )
|
|
||||||
drop <session> delete-tuple ;
|
|
||||||
|
|
||||||
M: sessions-in-db new-session ( session storage -- )
|
|
||||||
drop insert-tuple ;
|
|
||||||
|
|
||||||
: expired-sessions ( -- session )
|
|
||||||
f <session>
|
|
||||||
USE: math now timestamp>millis [ 60 60 * 1000 * - ] keep [a,b] >>expires
|
|
||||||
select-tuples ;
|
|
||||||
|
|
||||||
: start-expiring-sessions ( db seq -- )
|
|
||||||
'[
|
|
||||||
, , [ expired-sessions [ delete-tuple ] each ] with-db
|
|
||||||
] 5 minutes every drop ;
|
|
|
@ -1,16 +0,0 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
USING: kernel http.server.sessions.storage ;
|
|
||||||
IN: http.server.sessions.storage.null
|
|
||||||
|
|
||||||
SINGLETON: null-sessions
|
|
||||||
|
|
||||||
: null-sessions-error "No session storage installed" throw ;
|
|
||||||
|
|
||||||
M: null-sessions get-session null-sessions-error ;
|
|
||||||
|
|
||||||
M: null-sessions update-session null-sessions-error ;
|
|
||||||
|
|
||||||
M: null-sessions delete-session null-sessions-error ;
|
|
||||||
|
|
||||||
M: null-sessions new-session null-sessions-error ;
|
|
|
@ -1,12 +0,0 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
USING: calendar ;
|
|
||||||
IN: http.server.sessions.storage
|
|
||||||
|
|
||||||
GENERIC: get-session ( id storage -- session )
|
|
||||||
|
|
||||||
GENERIC: update-session ( session storage -- )
|
|
||||||
|
|
||||||
GENERIC: delete-session ( id storage -- )
|
|
||||||
|
|
||||||
GENERIC: new-session ( session storage -- )
|
|
|
@ -120,9 +120,11 @@ $nl
|
||||||
"Another limitation is that closure conversion does not descend into arrays, hashtables or other types of literals. For example, the following does not work:"
|
"Another limitation is that closure conversion does not descend into arrays, hashtables or other types of literals. For example, the following does not work:"
|
||||||
{ $code
|
{ $code
|
||||||
":: bad-cond-usage ( a -- ... )"
|
":: bad-cond-usage ( a -- ... )"
|
||||||
|
" {"
|
||||||
" { [ a 0 < ] [ ... ] }"
|
" { [ a 0 < ] [ ... ] }"
|
||||||
" { [ a 0 > ] [ ... ] }"
|
" { [ a 0 > ] [ ... ] }"
|
||||||
" { [ a 0 = ] [ ... ] } ;"
|
" { [ a 0 = ] [ ... ] }"
|
||||||
|
" } cond ;"
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
ARTICLE: "locals" "Local variables and lexical closures"
|
ARTICLE: "locals" "Local variables and lexical closures"
|
||||||
|
|
|
@ -80,10 +80,6 @@ M: integer (^)
|
||||||
-rot (^mod)
|
-rot (^mod)
|
||||||
] if ; foldable
|
] if ; foldable
|
||||||
|
|
||||||
GENERIC: abs ( x -- y ) foldable
|
|
||||||
|
|
||||||
M: real abs dup 0 < [ neg ] when ;
|
|
||||||
|
|
||||||
GENERIC: absq ( x -- y ) foldable
|
GENERIC: absq ( x -- y ) foldable
|
||||||
|
|
||||||
M: real absq sq ;
|
M: real absq sq ;
|
||||||
|
|
|
@ -47,5 +47,6 @@ M: ratio - 2dup scale - -rot ratio+d / ;
|
||||||
M: ratio * 2>fraction * >r * r> / ;
|
M: ratio * 2>fraction * >r * r> / ;
|
||||||
M: ratio / scale / ;
|
M: ratio / scale / ;
|
||||||
M: ratio /i scale /i ;
|
M: ratio /i scale /i ;
|
||||||
|
M: ratio /f scale /f ;
|
||||||
M: ratio mod 2dup >r >r /i r> r> rot * - ;
|
M: ratio mod 2dup >r >r /i r> r> rot * - ;
|
||||||
M: ratio /mod [ /i ] 2keep mod ;
|
M: ratio /mod [ /i ] 2keep mod ;
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
! Copyright (C) 2007 Chris Double.
|
! Copyright (C) 2007 Chris Double.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
!
|
!
|
||||||
USING: kernel tools.test peg peg.ebnf words math math.parser sequences ;
|
USING: kernel tools.test peg peg.ebnf words math math.parser
|
||||||
|
sequences accessors ;
|
||||||
IN: peg.ebnf.tests
|
IN: peg.ebnf.tests
|
||||||
|
|
||||||
{ T{ ebnf-non-terminal f "abc" } } [
|
{ T{ ebnf-non-terminal f "abc" } } [
|
||||||
"abc" 'non-terminal' parse parse-result-ast
|
"abc" 'non-terminal' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ T{ ebnf-terminal f "55" } } [
|
{ T{ ebnf-terminal f "55" } } [
|
||||||
"'55'" 'terminal' parse parse-result-ast
|
"'55'" 'terminal' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -20,7 +21,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"digit = '1' | '2'" 'rule' parse parse-result-ast
|
"digit = '1' | '2'" 'rule' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -31,7 +32,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"digit = '1' '2'" 'rule' parse parse-result-ast
|
"digit = '1' '2'" 'rule' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -44,20 +45,22 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one two | three" 'choice' parse parse-result-ast
|
"one two | three" 'choice' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
T{ ebnf-sequence f
|
T{ ebnf-sequence f
|
||||||
V{
|
V{
|
||||||
T{ ebnf-non-terminal f "one" }
|
T{ ebnf-non-terminal f "one" }
|
||||||
|
T{ ebnf-whitespace f
|
||||||
T{ ebnf-choice f
|
T{ ebnf-choice f
|
||||||
V{ T{ ebnf-non-terminal f "two" } T{ ebnf-non-terminal f "three" } }
|
V{ T{ ebnf-non-terminal f "two" } T{ ebnf-non-terminal f "three" } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} [
|
} [
|
||||||
"one (two | three)" 'choice' parse parse-result-ast
|
"one {two | three}" 'choice' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -77,7 +80,7 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one ((two | three) four)*" 'choice' parse parse-result-ast
|
"one ((two | three) four)*" 'choice' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -89,43 +92,43 @@ IN: peg.ebnf.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} [
|
} [
|
||||||
"one ( two )? three" 'choice' parse parse-result-ast
|
"one ( two )? three" 'choice' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"\"foo\"" 'identifier' parse parse-result-ast
|
"\"foo\"" 'identifier' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"'foo'" 'identifier' parse parse-result-ast
|
"'foo'" 'identifier' parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"foo" 'non-terminal' parse parse-result-ast ebnf-non-terminal-symbol
|
"foo" 'non-terminal' parse ast>> ebnf-non-terminal-symbol
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"foo]" 'non-terminal' parse parse-result-ast ebnf-non-terminal-symbol
|
"foo]" 'non-terminal' parse ast>> ebnf-non-terminal-symbol
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "b" } } [
|
{ V{ "a" "b" } } [
|
||||||
"ab" [EBNF foo='a' 'b' EBNF] call parse-result-ast
|
"ab" [EBNF foo='a' 'b' EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ 1 "b" } } [
|
{ V{ 1 "b" } } [
|
||||||
"ab" [EBNF foo=('a')[[ drop 1 ]] 'b' EBNF] call parse-result-ast
|
"ab" [EBNF foo=('a')[[ drop 1 ]] 'b' EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ 1 2 } } [
|
{ V{ 1 2 } } [
|
||||||
"ab" [EBNF foo=('a') [[ drop 1 ]] ('b') [[ drop 2 ]] EBNF] call parse-result-ast
|
"ab" [EBNF foo=('a') [[ drop 1 ]] ('b') [[ drop 2 ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: A } [
|
{ CHAR: A } [
|
||||||
"A" [EBNF foo=[A-Z] EBNF] call parse-result-ast
|
"A" [EBNF foo=[A-Z] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: Z } [
|
{ CHAR: Z } [
|
||||||
"Z" [EBNF foo=[A-Z] EBNF] call parse-result-ast
|
"Z" [EBNF foo=[A-Z] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -133,7 +136,7 @@ IN: peg.ebnf.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: 0 } [
|
{ CHAR: 0 } [
|
||||||
"0" [EBNF foo=[^A-Z] EBNF] call parse-result-ast
|
"0" [EBNF foo=[^A-Z] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -145,31 +148,31 @@ IN: peg.ebnf.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "1" "+" "foo" } } [
|
{ V{ "1" "+" "foo" } } [
|
||||||
"1+1" [EBNF foo='1' '+' '1' [[ drop "foo" ]] EBNF] call parse-result-ast
|
"1+1" [EBNF foo='1' '+' '1' [[ drop "foo" ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"1+1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] EBNF] call parse-result-ast
|
"1+1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "foo" } [
|
{ "foo" } [
|
||||||
"1+1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] | '1' '-' '1' => [[ drop "bar" ]] EBNF] call parse-result-ast
|
"1+1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] | '1' '-' '1' => [[ drop "bar" ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "bar" } [
|
{ "bar" } [
|
||||||
"1-1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] | '1' '-' '1' => [[ drop "bar" ]] EBNF] call parse-result-ast
|
"1-1" [EBNF foo='1' '+' '1' => [[ drop "foo" ]] | '1' '-' '1' => [[ drop "bar" ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 6 } [
|
{ 6 } [
|
||||||
"4+2" [EBNF num=[0-9] => [[ digit> ]] foo=num:x '+' num:y => [[ drop x y + ]] EBNF] call parse-result-ast
|
"4+2" [EBNF num=[0-9] => [[ digit> ]] foo=num:x '+' num:y => [[ drop x y + ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 6 } [
|
{ 6 } [
|
||||||
"4+2" [EBNF foo=[0-9]:x '+' [0-9]:y => [[ drop x digit> y digit> + ]] EBNF] call parse-result-ast
|
"4+2" [EBNF foo=[0-9]:x '+' [0-9]:y => [[ drop x digit> y digit> + ]] EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 10 } [
|
{ 10 } [
|
||||||
{ 1 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call parse-result-ast
|
{ 1 2 3 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -177,7 +180,7 @@ IN: peg.ebnf.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 3 } [
|
{ 3 } [
|
||||||
{ 1 2 "a" 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call parse-result-ast
|
{ 1 2 "a" 4 } [EBNF num=. ?[ number? ]? list=list:x num:y => [[ drop x y + ]] | num EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -185,44 +188,44 @@ IN: peg.ebnf.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" " " "b" } } [
|
{ V{ "a" " " "b" } } [
|
||||||
"a b" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call parse-result-ast
|
"a b" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "\t" "b" } } [
|
{ V{ "a" "\t" "b" } } [
|
||||||
"a\tb" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call parse-result-ast
|
"a\tb" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "\n" "b" } } [
|
{ V{ "a" "\n" "b" } } [
|
||||||
"a\nb" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call parse-result-ast
|
"a\nb" [EBNF -=" " | "\t" | "\n" foo="a" - "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" f "b" } } [
|
{ V{ "a" f "b" } } [
|
||||||
"ab" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
"ab" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" " " "b" } } [
|
{ V{ "a" " " "b" } } [
|
||||||
"a b" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
"a b" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
|
||||||
{ V{ "a" "\t" "b" } } [
|
{ V{ "a" "\t" "b" } } [
|
||||||
"a\tb" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
"a\tb" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "\n" "b" } } [
|
{ V{ "a" "\n" "b" } } [
|
||||||
"a\nb" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call parse-result-ast
|
"a\nb" [EBNF -=" " | "\t" | "\n" foo="a" (-)? "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "b" } } [
|
{ V{ "a" "b" } } [
|
||||||
"ab" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call parse-result-ast
|
"ab" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "b" } } [
|
{ V{ "a" "b" } } [
|
||||||
"a\tb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call parse-result-ast
|
"a\tb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "b" } } [
|
{ V{ "a" "b" } } [
|
||||||
"a\nb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call parse-result-ast
|
"a\nb" [EBNF -=(" " | "\t" | "\n")? => [[ drop ignore ]] foo="a" - "b" EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -232,19 +235,19 @@ IN: peg.ebnf.tests
|
||||||
{ V{ V{ 49 } "+" V{ 49 } } } [
|
{ V{ V{ 49 } "+" V{ 49 } } } [
|
||||||
#! Test direct left recursion.
|
#! Test direct left recursion.
|
||||||
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
||||||
"1+1" [EBNF num=([0-9])+ expr=expr "+" num | num EBNF] call parse-result-ast
|
"1+1" [EBNF num=([0-9])+ expr=expr "+" num | num EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [
|
{ V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [
|
||||||
#! Test direct left recursion.
|
#! Test direct left recursion.
|
||||||
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
||||||
"1+1+1" [EBNF num=([0-9])+ expr=expr "+" num | num EBNF] call parse-result-ast
|
"1+1+1" [EBNF num=([0-9])+ expr=expr "+" num | num EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [
|
{ V{ V{ V{ 49 } "+" V{ 49 } } "+" V{ 49 } } } [
|
||||||
#! Test indirect left recursion.
|
#! Test indirect left recursion.
|
||||||
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
#! Using packrat, so first part of expr fails, causing 2nd choice to be used
|
||||||
"1+1+1" [EBNF num=([0-9])+ x=expr expr=x "+" num | num EBNF] call parse-result-ast
|
"1+1+1" [EBNF num=([0-9])+ x=expr expr=x "+" num | num EBNF] call ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
|
@ -277,23 +280,88 @@ main = Primary
|
||||||
;EBNF
|
;EBNF
|
||||||
|
|
||||||
{ "this" } [
|
{ "this" } [
|
||||||
"this" primary parse-result-ast
|
"this" primary ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "this" "." "x" } } [
|
{ V{ "this" "." "x" } } [
|
||||||
"this.x" primary parse-result-ast
|
"this.x" primary ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ V{ "this" "." "x" } "." "y" } } [
|
{ V{ V{ "this" "." "x" } "." "y" } } [
|
||||||
"this.x.y" primary parse-result-ast
|
"this.x.y" primary ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ V{ "this" "." "x" } "." "m" "(" ")" } } [
|
{ V{ V{ "this" "." "x" } "." "m" "(" ")" } } [
|
||||||
"this.x.m()" primary parse-result-ast
|
"this.x.m()" primary ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ V{ V{ "x" "[" "i" "]" } "[" "j" "]" } "." "y" } } [
|
{ V{ V{ V{ "x" "[" "i" "]" } "[" "j" "]" } "." "y" } } [
|
||||||
"x[i][j].y" primary parse-result-ast
|
"x[i][j].y" primary ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
'ebnf' compile must-infer
|
'ebnf' compile must-infer
|
||||||
|
|
||||||
|
{ V{ V{ "a" "b" } "c" } } [
|
||||||
|
"abc" [EBNF a="a" "b" foo=(a "c") EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ V{ "a" "b" } "c" } } [
|
||||||
|
"abc" [EBNF a="a" "b" foo={a "c"} EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ V{ "a" "b" } "c" } } [
|
||||||
|
"abc" [EBNF a="a" "b" foo=a "c" EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"a bc" [EBNF a="a" "b" foo=(a "c") EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"a bc" [EBNF a="a" "b" foo=a "c" EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"a bc" [EBNF a="a" "b" foo={a "c"} EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"ab c" [EBNF a="a" "b" foo=a "c" EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ V{ "a" "b" } "c" } } [
|
||||||
|
"ab c" [EBNF a="a" "b" foo={a "c"} EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"ab c" [EBNF a="a" "b" foo=(a "c") EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"a b c" [EBNF a="a" "b" foo=a "c" EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"a b c" [EBNF a="a" "b" foo=(a "c") EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ f } [
|
||||||
|
"a b c" [EBNF a="a" "b" foo={a "c"} EBNF] call
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ V{ V{ "a" "b" } "c" } V{ V{ "a" "b" } "c" } } } [
|
||||||
|
"ab cab c" [EBNF a="a" "b" foo={a "c"}* EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ } } [
|
||||||
|
"ab cab c" [EBNF a="a" "b" foo=(a "c")* EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ V{ V{ "a" "b" } "c" } V{ V{ "a" "b" } "c" } } } [
|
||||||
|
"ab c ab c" [EBNF a="a" "b" foo={a "c"}* EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
{ V{ } } [
|
||||||
|
"ab c ab c" [EBNF a="a" "b" foo=(a "c")* EBNF] call ast>>
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ TUPLE: ebnf-sequence elements ;
|
||||||
TUPLE: ebnf-repeat0 group ;
|
TUPLE: ebnf-repeat0 group ;
|
||||||
TUPLE: ebnf-repeat1 group ;
|
TUPLE: ebnf-repeat1 group ;
|
||||||
TUPLE: ebnf-optional group ;
|
TUPLE: ebnf-optional group ;
|
||||||
|
TUPLE: ebnf-whitespace group ;
|
||||||
TUPLE: ebnf-rule symbol elements ;
|
TUPLE: ebnf-rule symbol elements ;
|
||||||
TUPLE: ebnf-action parser code ;
|
TUPLE: ebnf-action parser code ;
|
||||||
TUPLE: ebnf-var parser name ;
|
TUPLE: ebnf-var parser name ;
|
||||||
|
@ -34,6 +35,7 @@ C: <ebnf-sequence> ebnf-sequence
|
||||||
C: <ebnf-repeat0> ebnf-repeat0
|
C: <ebnf-repeat0> ebnf-repeat0
|
||||||
C: <ebnf-repeat1> ebnf-repeat1
|
C: <ebnf-repeat1> ebnf-repeat1
|
||||||
C: <ebnf-optional> ebnf-optional
|
C: <ebnf-optional> ebnf-optional
|
||||||
|
C: <ebnf-whitespace> ebnf-whitespace
|
||||||
C: <ebnf-rule> ebnf-rule
|
C: <ebnf-rule> ebnf-rule
|
||||||
C: <ebnf-action> ebnf-action
|
C: <ebnf-action> ebnf-action
|
||||||
C: <ebnf-var> ebnf-var
|
C: <ebnf-var> ebnf-var
|
||||||
|
@ -84,6 +86,7 @@ C: <ebnf> ebnf
|
||||||
[ dup CHAR: + = ]
|
[ dup CHAR: + = ]
|
||||||
[ dup CHAR: ? = ]
|
[ dup CHAR: ? = ]
|
||||||
[ dup CHAR: : = ]
|
[ dup CHAR: : = ]
|
||||||
|
[ dup CHAR: ~ = ]
|
||||||
} || not nip
|
} || not nip
|
||||||
] satisfy repeat1 [ >string <ebnf-non-terminal> ] action ;
|
] satisfy repeat1 [ >string <ebnf-non-terminal> ] action ;
|
||||||
|
|
||||||
|
@ -134,9 +137,15 @@ DEFER: 'choice'
|
||||||
#! Parse a group of choices, with a suffix indicating
|
#! Parse a group of choices, with a suffix indicating
|
||||||
#! the type of group (repeat0, repeat1, etc) and
|
#! the type of group (repeat0, repeat1, etc) and
|
||||||
#! an quot that is the action that produces the AST.
|
#! an quot that is the action that produces the AST.
|
||||||
|
2dup
|
||||||
|
[
|
||||||
"(" [ 'choice' sp ] delay ")" syntax-pack
|
"(" [ 'choice' sp ] delay ")" syntax-pack
|
||||||
swap 2seq
|
swap 2seq
|
||||||
[ first ] rot compose action ;
|
[ first ] rot compose action ,
|
||||||
|
"{" [ 'choice' sp ] delay "}" syntax-pack
|
||||||
|
swap 2seq
|
||||||
|
[ first <ebnf-whitespace> ] rot compose action ,
|
||||||
|
] choice* ;
|
||||||
|
|
||||||
: 'group' ( -- parser )
|
: 'group' ( -- parser )
|
||||||
#! A grouping with no suffix. Used for precedence.
|
#! A grouping with no suffix. Used for precedence.
|
||||||
|
@ -238,9 +247,15 @@ GENERIC: (transform) ( ast -- parser )
|
||||||
|
|
||||||
SYMBOL: parser
|
SYMBOL: parser
|
||||||
SYMBOL: main
|
SYMBOL: main
|
||||||
|
SYMBOL: ignore-ws
|
||||||
|
|
||||||
: transform ( ast -- object )
|
: transform ( ast -- object )
|
||||||
H{ } clone dup dup [ parser set swap (transform) main set ] bind ;
|
H{ } clone dup dup [
|
||||||
|
f ignore-ws set
|
||||||
|
parser set
|
||||||
|
swap (transform)
|
||||||
|
main set
|
||||||
|
] bind ;
|
||||||
|
|
||||||
M: ebnf (transform) ( ast -- parser )
|
M: ebnf (transform) ( ast -- parser )
|
||||||
rules>> [ (transform) ] map peek ;
|
rules>> [ (transform) ] map peek ;
|
||||||
|
@ -252,7 +267,13 @@ M: ebnf-rule (transform) ( ast -- parser )
|
||||||
] keep ;
|
] keep ;
|
||||||
|
|
||||||
M: ebnf-sequence (transform) ( ast -- parser )
|
M: ebnf-sequence (transform) ( ast -- parser )
|
||||||
elements>> [ (transform) ] map seq [ dup length 1 = [ first ] when ] action ;
|
#! If ignore-ws is set then each element of the sequence
|
||||||
|
#! ignores leading whitespace. This is not inherited by
|
||||||
|
#! subelements of the sequence.
|
||||||
|
elements>> [
|
||||||
|
f ignore-ws [ (transform) ] with-variable
|
||||||
|
ignore-ws get [ sp ] when
|
||||||
|
] map seq [ dup length 1 = [ first ] when ] action ;
|
||||||
|
|
||||||
M: ebnf-choice (transform) ( ast -- parser )
|
M: ebnf-choice (transform) ( ast -- parser )
|
||||||
options>> [ (transform) ] map choice ;
|
options>> [ (transform) ] map choice ;
|
||||||
|
@ -282,6 +303,9 @@ M: ebnf-repeat1 (transform) ( ast -- parser )
|
||||||
M: ebnf-optional (transform) ( ast -- parser )
|
M: ebnf-optional (transform) ( ast -- parser )
|
||||||
transform-group optional ;
|
transform-group optional ;
|
||||||
|
|
||||||
|
M: ebnf-whitespace (transform) ( ast -- parser )
|
||||||
|
t ignore-ws [ transform-group ] with-variable ;
|
||||||
|
|
||||||
GENERIC: build-locals ( code ast -- code )
|
GENERIC: build-locals ( code ast -- code )
|
||||||
|
|
||||||
M: ebnf-sequence build-locals ( code ast -- code )
|
M: ebnf-sequence build-locals ( code ast -- code )
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
! Copyright (C) 2008 Chris Double.
|
! Copyright (C) 2008 Chris Double.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel arrays strings math.parser sequences
|
USING: kernel arrays strings math.parser sequences
|
||||||
peg peg.ebnf peg.parsers memoize math ;
|
peg peg.ebnf peg.parsers memoize math accessors ;
|
||||||
IN: peg.expr
|
IN: peg.expr
|
||||||
|
|
||||||
EBNF: expr
|
EBNF: expr
|
||||||
|
@ -20,5 +20,5 @@ exp = exp "+" fac => [[ first3 nip + ]]
|
||||||
;EBNF
|
;EBNF
|
||||||
|
|
||||||
: eval-expr ( string -- number )
|
: eval-expr ( string -- number )
|
||||||
expr parse-result-ast ;
|
expr ast>> ;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
! Copyright (C) 2007 Chris Double.
|
! Copyright (C) 2007 Chris Double.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
!
|
!
|
||||||
USING: kernel tools.test strings namespaces arrays sequences peg peg.private accessors words math ;
|
USING: kernel tools.test strings namespaces arrays sequences
|
||||||
|
peg peg.private accessors words math accessors ;
|
||||||
IN: peg.tests
|
IN: peg.tests
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -10,7 +11,7 @@ IN: peg.tests
|
||||||
|
|
||||||
{ "begin" "end" } [
|
{ "begin" "end" } [
|
||||||
"beginend" "begin" token parse
|
"beginend" "begin" token parse
|
||||||
{ parse-result-ast parse-result-remaining } get-slots
|
{ ast>> remaining>> } get-slots
|
||||||
>string
|
>string
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
@ -23,11 +24,11 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: a } [
|
{ CHAR: a } [
|
||||||
"abcd" CHAR: a CHAR: z range parse parse-result-ast
|
"abcd" CHAR: a CHAR: z range parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: z } [
|
{ CHAR: z } [
|
||||||
"zbcd" CHAR: a CHAR: z range parse parse-result-ast
|
"zbcd" CHAR: a CHAR: z range parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -35,15 +36,15 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "g" "o" } } [
|
{ V{ "g" "o" } } [
|
||||||
"good" "g" token "o" token 2array seq parse parse-result-ast
|
"good" "g" token "o" token 2array seq parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "a" } [
|
{ "a" } [
|
||||||
"abcd" "a" token "b" token 2array choice parse parse-result-ast
|
"abcd" "a" token "b" token 2array choice parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "b" } [
|
{ "b" } [
|
||||||
"bbcd" "a" token "b" token 2array choice parse parse-result-ast
|
"bbcd" "a" token "b" token 2array choice parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -55,15 +56,15 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 0 } [
|
{ 0 } [
|
||||||
"" "a" token repeat0 parse parse-result-ast length
|
"" "a" token repeat0 parse ast>> length
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 0 } [
|
{ 0 } [
|
||||||
"b" "a" token repeat0 parse parse-result-ast length
|
"b" "a" token repeat0 parse ast>> length
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "a" "a" } } [
|
{ V{ "a" "a" "a" } } [
|
||||||
"aaab" "a" token repeat0 parse parse-result-ast
|
"aaab" "a" token repeat0 parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -75,15 +76,15 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "a" "a" } } [
|
{ V{ "a" "a" "a" } } [
|
||||||
"aaab" "a" token repeat1 parse parse-result-ast
|
"aaab" "a" token repeat1 parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" "b" } } [
|
{ V{ "a" "b" } } [
|
||||||
"ab" "a" token optional "b" token 2array seq parse parse-result-ast
|
"ab" "a" token optional "b" token 2array seq parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ f "b" } } [
|
{ V{ f "b" } } [
|
||||||
"b" "a" token optional "b" token 2array seq parse parse-result-ast
|
"b" "a" token optional "b" token 2array seq parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -91,7 +92,7 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ CHAR: a CHAR: b } } [
|
{ V{ CHAR: a CHAR: b } } [
|
||||||
"ab" "a" token ensure CHAR: a CHAR: z range dup 3array seq parse parse-result-ast
|
"ab" "a" token ensure CHAR: a CHAR: z range dup 3array seq parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -123,11 +124,11 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ 1 } [
|
{ 1 } [
|
||||||
"a" "a" token [ drop 1 ] action parse parse-result-ast
|
"a" "a" token [ drop 1 ] action parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ 1 1 } } [
|
{ V{ 1 1 } } [
|
||||||
"aa" "a" token [ drop 1 ] action dup 2array seq parse parse-result-ast
|
"aa" "a" token [ drop 1 ] action dup 2array seq parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -139,19 +140,19 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: a } [
|
{ CHAR: a } [
|
||||||
"a" [ CHAR: a = ] satisfy parse parse-result-ast
|
"a" [ CHAR: a = ] satisfy parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "a" } [
|
{ "a" } [
|
||||||
" a" "a" token sp parse parse-result-ast
|
" a" "a" token sp parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ "a" } [
|
{ "a" } [
|
||||||
"a" "a" token sp parse parse-result-ast
|
"a" "a" token sp parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ V{ "a" } } [
|
{ V{ "a" } } [
|
||||||
"[a]" "[" token hide "a" token "]" token hide 3array seq parse parse-result-ast
|
"[a]" "[" token hide "a" token "]" token hide 3array seq parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -164,8 +165,8 @@ IN: peg.tests
|
||||||
[ "1" token , "-" token , "1" token , ] seq* ,
|
[ "1" token , "-" token , "1" token , ] seq* ,
|
||||||
[ "1" token , "+" token , "1" token , ] seq* ,
|
[ "1" token , "+" token , "1" token , ] seq* ,
|
||||||
] choice*
|
] choice*
|
||||||
"1-1" over parse parse-result-ast swap
|
"1-1" over parse ast>> swap
|
||||||
"1+1" swap parse parse-result-ast
|
"1+1" swap parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
: expr ( -- parser )
|
: expr ( -- parser )
|
||||||
|
@ -174,7 +175,7 @@ IN: peg.tests
|
||||||
[ expr ] delay "+" token "1" token 3seq "1" token 2choice ;
|
[ expr ] delay "+" token "1" token 3seq "1" token 2choice ;
|
||||||
|
|
||||||
{ V{ V{ "1" "+" "1" } "+" "1" } } [
|
{ V{ V{ "1" "+" "1" } "+" "1" } } [
|
||||||
"1+1+1" expr parse parse-result-ast
|
"1+1+1" expr parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
|
@ -189,6 +190,6 @@ IN: peg.tests
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ CHAR: B } [
|
{ CHAR: B } [
|
||||||
"B" [ drop t ] satisfy [ 66 >= ] semantic parse parse-result-ast
|
"B" [ drop t ] satisfy [ 66 >= ] semantic parse ast>>
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
|
|
@ -1,43 +1,44 @@
|
||||||
! Copyright (C) 2007 Chris Double.
|
! Copyright (C) 2007 Chris Double.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
!
|
!
|
||||||
USING: kernel tools.test peg peg.ebnf peg.pl0 multiline sequences ;
|
USING: kernel tools.test peg peg.ebnf peg.pl0
|
||||||
|
multiline sequences accessors ;
|
||||||
IN: peg.pl0.tests
|
IN: peg.pl0.tests
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"CONST foo = 1;" "block" \ pl0 rule parse parse-result-remaining empty?
|
"CONST foo = 1;" "block" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"VAR foo;" "block" \ pl0 rule parse parse-result-remaining empty?
|
"VAR foo;" "block" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"VAR foo,bar , baz;" "block" \ pl0 rule parse parse-result-remaining empty?
|
"VAR foo,bar , baz;" "block" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"foo := 5" "statement" \ pl0 rule parse parse-result-remaining empty?
|
"foo := 5" "statement" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"BEGIN foo := 5 END" "statement" \ pl0 rule parse parse-result-remaining empty?
|
"BEGIN foo := 5 END" "statement" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"IF 1=1 THEN foo := 5" "statement" \ pl0 rule parse parse-result-remaining empty?
|
"IF 1=1 THEN foo := 5" "statement" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"WHILE 1=1 DO foo := 5" "statement" \ pl0 rule parse parse-result-remaining empty?
|
"WHILE 1=1 DO foo := 5" "statement" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"WHILE ODD 1 DO foo := 5" "statement" \ pl0 rule parse parse-result-remaining empty?
|
"WHILE ODD 1 DO foo := 5" "statement" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
"PROCEDURE square; BEGIN squ:=x*x END" "block" \ pl0 rule parse parse-result-remaining empty?
|
"PROCEDURE square; BEGIN squ:=x*x END" "block" \ pl0 rule parse remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ t } [
|
{ t } [
|
||||||
|
@ -57,7 +58,7 @@ BEGIN
|
||||||
x := x + 1;
|
x := x + 1;
|
||||||
END
|
END
|
||||||
END.
|
END.
|
||||||
"> pl0 parse-result-remaining empty?
|
"> pl0 remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
{ f } [
|
{ f } [
|
||||||
|
@ -123,5 +124,5 @@ BEGIN
|
||||||
y := 36;
|
y := 36;
|
||||||
CALL gcd;
|
CALL gcd;
|
||||||
END.
|
END.
|
||||||
"> pl0 parse-result-remaining empty?
|
"> pl0 remaining>> empty?
|
||||||
] unit-test
|
] unit-test
|
|
@ -7,52 +7,22 @@ IN: peg.pl0
|
||||||
#! Grammar for PL/0 based on http://en.wikipedia.org/wiki/PL/0
|
#! Grammar for PL/0 based on http://en.wikipedia.org/wiki/PL/0
|
||||||
|
|
||||||
EBNF: pl0
|
EBNF: pl0
|
||||||
_ = (" " | "\t" | "\n")* => [[ drop ignore ]]
|
|
||||||
|
|
||||||
BEGIN = "BEGIN" _
|
block = { "CONST" ident "=" number { "," ident "=" number }* ";" }?
|
||||||
CALL = "CALL" _
|
{ "VAR" ident { "," ident }* ";" }?
|
||||||
CONST = "CONST" _
|
{ "PROCEDURE" ident ";" { block ";" }? }* statement
|
||||||
DO = "DO" _
|
statement = { ident ":=" expression
|
||||||
END = "END" _
|
| "CALL" ident
|
||||||
IF = "IF" _
|
| "BEGIN" statement { ";" statement }* "END"
|
||||||
THEN = "THEN" _
|
| "IF" condition "THEN" statement
|
||||||
ODD = "ODD" _
|
| "WHILE" condition "DO" statement }?
|
||||||
PROCEDURE = "PROCEDURE" _
|
condition = { "ODD" expression }
|
||||||
VAR = "VAR" _
|
| { expression ("=" | "#" | "<=" | "<" | ">=" | ">") expression }
|
||||||
WHILE = "WHILE" _
|
expression = {"+" | "-"}? term { {"+" | "-"} term }*
|
||||||
EQ = "=" _
|
term = factor { {"*" | "/"} factor }*
|
||||||
LTEQ = "<=" _
|
factor = ident | number | "(" expression ")"
|
||||||
LT = "<" _
|
ident = (([a-zA-Z])+) => [[ >string ]]
|
||||||
GT = ">" _
|
|
||||||
GTEQ = ">=" _
|
|
||||||
NEQ = "#" _
|
|
||||||
COMMA = "," _
|
|
||||||
SEMICOLON = ";" _
|
|
||||||
ASSIGN = ":=" _
|
|
||||||
|
|
||||||
ADD = "+" _
|
|
||||||
SUBTRACT = "-" _
|
|
||||||
MULTIPLY = "*" _
|
|
||||||
DIVIDE = "/" _
|
|
||||||
|
|
||||||
LPAREN = "(" _
|
|
||||||
RPAREN = ")" _
|
|
||||||
|
|
||||||
block = ( CONST ident EQ number ( COMMA ident EQ number )* SEMICOLON )?
|
|
||||||
( VAR ident ( COMMA ident )* SEMICOLON )?
|
|
||||||
( PROCEDURE ident SEMICOLON ( block SEMICOLON )? )* statement
|
|
||||||
statement = ( ident ASSIGN expression
|
|
||||||
| CALL ident
|
|
||||||
| BEGIN statement ( SEMICOLON statement )* END
|
|
||||||
| IF condition THEN statement
|
|
||||||
| WHILE condition DO statement )?
|
|
||||||
condition = ODD expression
|
|
||||||
| expression (EQ | NEQ | LTEQ | LT | GTEQ | GT) expression
|
|
||||||
expression = (ADD | SUBTRACT)? term ( (ADD | SUBTRACT) term )* _
|
|
||||||
term = factor ( (MULTIPLY | DIVIDE) factor )*
|
|
||||||
factor = ident | number | LPAREN expression RPAREN
|
|
||||||
ident = (([a-zA-Z])+) _ => [[ >string ]]
|
|
||||||
digit = ([0-9]) => [[ digit> ]]
|
digit = ([0-9]) => [[ digit> ]]
|
||||||
number = ((digit)+) _ => [[ 10 digits>integer ]]
|
number = (digit)+ => [[ 10 digits>integer ]]
|
||||||
program = _ block "."
|
program = { block "." }
|
||||||
;EBNF
|
;EBNF
|
||||||
|
|
|
@ -12,7 +12,7 @@ TUPLE: node id content ;
|
||||||
|
|
||||||
node "node"
|
node "node"
|
||||||
{
|
{
|
||||||
{ "id" "id" +native-id+ +autoincrement+ }
|
{ "id" "id" +db-assigned-id+ +autoincrement+ }
|
||||||
{ "content" "content" TEXT }
|
{ "content" "content" TEXT }
|
||||||
} define-persistent
|
} define-persistent
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ TUPLE: arc id relation subject object ;
|
||||||
|
|
||||||
arc "arc"
|
arc "arc"
|
||||||
{
|
{
|
||||||
{ "id" "id" INTEGER +assigned-id+ } ! foreign key to node table?
|
{ "id" "id" INTEGER +user-assigned-id+ } ! foreign key to node table?
|
||||||
{ "relation" "relation" INTEGER +not-null+ }
|
{ "relation" "relation" INTEGER +not-null+ }
|
||||||
{ "subject" "subject" INTEGER +not-null+ }
|
{ "subject" "subject" INTEGER +not-null+ }
|
||||||
{ "object" "object" INTEGER +not-null+ }
|
{ "object" "object" INTEGER +not-null+ }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: arrays hashtables kernel models math namespaces sequences
|
USING: arrays hashtables kernel models math namespaces sequences
|
||||||
quotations math.vectors combinators sorting vectors dlists
|
quotations math.vectors combinators sorting vectors dlists
|
||||||
models threads concurrency.flags ;
|
models threads concurrency.flags math.order ;
|
||||||
IN: ui.gadgets
|
IN: ui.gadgets
|
||||||
|
|
||||||
SYMBOL: ui-notify-flag
|
SYMBOL: ui-notify-flag
|
||||||
|
@ -106,7 +106,7 @@ GENERIC: children-on ( rect/point gadget -- seq )
|
||||||
M: gadget children-on nip gadget-children ;
|
M: gadget children-on nip gadget-children ;
|
||||||
|
|
||||||
: (fast-children-on) ( dim axis gadgets -- i )
|
: (fast-children-on) ( dim axis gadgets -- i )
|
||||||
swapd [ rect-loc v- over v. ] binsearch nip ;
|
swapd [ rect-loc v- over v. 0 <=> ] binsearch nip ;
|
||||||
|
|
||||||
: fast-children-on ( rect axis children -- from to )
|
: fast-children-on ( rect axis children -- from to )
|
||||||
3dup
|
3dup
|
||||||
|
|
|
@ -22,7 +22,8 @@ IN: update
|
||||||
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
: remote-clean-image ( -- url )
|
: remote-clean-image ( -- url )
|
||||||
"http://factorcode.org/images/clean/" my-boot-image-name append ;
|
{ "http://factorcode.org/images/clean/" platform "/" my-boot-image-name }
|
||||||
|
to-string ;
|
||||||
|
|
||||||
: download-clean-image ( -- ) remote-clean-image download ;
|
: download-clean-image ( -- ) remote-clean-image download ;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
USING: math kernel accessors http.server http.server.actions
|
||||||
|
http.server.sessions http.server.templating.fhtml locals ;
|
||||||
|
IN: webapps.counter
|
||||||
|
|
||||||
|
SYMBOL: count
|
||||||
|
|
||||||
|
TUPLE: counter-app < dispatcher ;
|
||||||
|
|
||||||
|
M: counter-app init-session*
|
||||||
|
drop 0 count sset ;
|
||||||
|
|
||||||
|
:: <counter-action> ( quot -- action )
|
||||||
|
<action> [
|
||||||
|
count quot schange
|
||||||
|
"" f <standard-redirect>
|
||||||
|
] >>display ;
|
||||||
|
|
||||||
|
: <display-action> ( -- action )
|
||||||
|
<action> [
|
||||||
|
"text/html" <content>
|
||||||
|
"resource:extra/webapps/counter/counter.fhtml" <fhtml> >>body
|
||||||
|
] >>display ;
|
||||||
|
|
||||||
|
: <counter-app> ( -- responder )
|
||||||
|
counter-app new-dispatcher
|
||||||
|
[ 1+ ] <counter-action> "inc" add-responder
|
||||||
|
[ 1- ] <counter-action> "dec" add-responder
|
||||||
|
<display-action> "" add-responder
|
||||||
|
<sessions> ;
|
|
@ -0,0 +1,10 @@
|
||||||
|
<% USING: io math.parser http.server.sessions webapps.counter ; %>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1><% count sget number>string write %></h1>
|
||||||
|
|
||||||
|
<a href="inc">++</a>
|
||||||
|
<a href="dec">--</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -47,7 +47,7 @@ IN: webapps.factor-website
|
||||||
<boilerplate>
|
<boilerplate>
|
||||||
"page" factor-template >>template
|
"page" factor-template >>template
|
||||||
<flows>
|
<flows>
|
||||||
<session-manager>
|
<sessions>
|
||||||
sessions-in-db >>sessions
|
sessions-in-db >>sessions
|
||||||
test-db <db-persistence> ;
|
test-db <db-persistence> ;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ TUPLE: paste id summary author mode date contents annotations captcha ;
|
||||||
|
|
||||||
paste "PASTE"
|
paste "PASTE"
|
||||||
{
|
{
|
||||||
{ "id" "ID" INTEGER +native-id+ }
|
{ "id" "ID" INTEGER +db-assigned-id+ }
|
||||||
{ "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
|
{ "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
|
||||||
{ "author" "AUTHOR" { VARCHAR 256 } +not-null+ }
|
{ "author" "AUTHOR" { VARCHAR 256 } +not-null+ }
|
||||||
{ "mode" "MODE" { VARCHAR 256 } +not-null+ }
|
{ "mode" "MODE" { VARCHAR 256 } +not-null+ }
|
||||||
|
@ -43,7 +43,7 @@ TUPLE: annotation aid id summary author mode contents date captcha ;
|
||||||
|
|
||||||
annotation "ANNOTATION"
|
annotation "ANNOTATION"
|
||||||
{
|
{
|
||||||
{ "aid" "AID" INTEGER +native-id+ }
|
{ "aid" "AID" INTEGER +db-assigned-id+ }
|
||||||
{ "id" "ID" INTEGER +not-null+ }
|
{ "id" "ID" INTEGER +not-null+ }
|
||||||
{ "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
|
{ "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
|
||||||
{ "author" "AUTHOR" { VARCHAR 256 } +not-null+ }
|
{ "author" "AUTHOR" { VARCHAR 256 } +not-null+ }
|
||||||
|
|
|
@ -27,7 +27,7 @@ M: blog link-href www-url>> ;
|
||||||
|
|
||||||
blog "BLOGS"
|
blog "BLOGS"
|
||||||
{
|
{
|
||||||
{ "id" "ID" INTEGER +native-id+ }
|
{ "id" "ID" INTEGER +db-assigned-id+ }
|
||||||
{ "name" "NAME" { VARCHAR 256 } +not-null+ }
|
{ "name" "NAME" { VARCHAR 256 } +not-null+ }
|
||||||
{ "www-url" "WWWURL" { VARCHAR 256 } +not-null+ }
|
{ "www-url" "WWWURL" { VARCHAR 256 } +not-null+ }
|
||||||
{ "feed-url" "FEEDURL" { VARCHAR 256 } +not-null+ }
|
{ "feed-url" "FEEDURL" { VARCHAR 256 } +not-null+ }
|
||||||
|
|
|
@ -15,7 +15,7 @@ TUPLE: todo uid id priority summary description ;
|
||||||
todo "TODO"
|
todo "TODO"
|
||||||
{
|
{
|
||||||
{ "uid" "UID" { VARCHAR 256 } +not-null+ }
|
{ "uid" "UID" { VARCHAR 256 } +not-null+ }
|
||||||
{ "id" "ID" +native-id+ }
|
{ "id" "ID" +db-assigned-id+ }
|
||||||
{ "priority" "PRIORITY" INTEGER +not-null+ }
|
{ "priority" "PRIORITY" INTEGER +not-null+ }
|
||||||
{ "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
|
{ "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
|
||||||
{ "description" "DESCRIPTION" { VARCHAR 256 } }
|
{ "description" "DESCRIPTION" { VARCHAR 256 } }
|
||||||
|
|
|
@ -57,7 +57,7 @@ unless
|
||||||
|
|
||||||
: family-tree ( definition -- definitions )
|
: family-tree ( definition -- definitions )
|
||||||
dup parent>> [ family-tree ] [ { } ] if*
|
dup parent>> [ family-tree ] [ { } ] if*
|
||||||
swap add ;
|
swap suffix ;
|
||||||
|
|
||||||
: family-tree-functions ( definition -- functions )
|
: family-tree-functions ( definition -- functions )
|
||||||
dup parent>> [ family-tree-functions ] [ { } ] if*
|
dup parent>> [ family-tree-functions ] [ { } ] if*
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
USING: alien alien.syntax alien.c-types alien.strings math
|
USING: alien alien.syntax alien.c-types alien.strings math
|
||||||
kernel sequences windows windows.types combinators.lib ;
|
kernel sequences windows windows.types combinators.lib
|
||||||
|
math.order ;
|
||||||
IN: windows.ole32
|
IN: windows.ole32
|
||||||
|
|
||||||
LIBRARY: ole32
|
LIBRARY: ole32
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue