Merge branch 'master' of git://factorcode.org/git/factor
commit
17f395281a
|
@ -607,7 +607,7 @@ tuple
|
||||||
{ "(exists?)" "io.files.private" }
|
{ "(exists?)" "io.files.private" }
|
||||||
{ "(directory)" "io.files.private" }
|
{ "(directory)" "io.files.private" }
|
||||||
{ "gc" "memory" }
|
{ "gc" "memory" }
|
||||||
{ "gc-time" "memory" }
|
{ "gc-stats" "memory" }
|
||||||
{ "save-image" "memory" }
|
{ "save-image" "memory" }
|
||||||
{ "save-image-and-exit" "memory" }
|
{ "save-image-and-exit" "memory" }
|
||||||
{ "datastack" "kernel" }
|
{ "datastack" "kernel" }
|
||||||
|
@ -702,6 +702,7 @@ tuple
|
||||||
{ "resize-float-array" "float-arrays" }
|
{ "resize-float-array" "float-arrays" }
|
||||||
{ "dll-valid?" "alien" }
|
{ "dll-valid?" "alien" }
|
||||||
{ "unimplemented" "kernel.private" }
|
{ "unimplemented" "kernel.private" }
|
||||||
|
{ "gc-reset" "memory" }
|
||||||
}
|
}
|
||||||
dup length [ >r first2 r> make-primitive ] 2each
|
dup length [ >r first2 r> make-primitive ] 2each
|
||||||
|
|
||||||
|
|
|
@ -48,4 +48,5 @@ $nl
|
||||||
{ $subsection "checksums.crc32" }
|
{ $subsection "checksums.crc32" }
|
||||||
{ $vocab-subsection "MD5 checksum" "checksums.md5" }
|
{ $vocab-subsection "MD5 checksum" "checksums.md5" }
|
||||||
{ $vocab-subsection "SHA1 checksum" "checksums.sha1" }
|
{ $vocab-subsection "SHA1 checksum" "checksums.sha1" }
|
||||||
{ $vocab-subsection "SHA2 checksum" "checksums.sha2" } ;
|
{ $vocab-subsection "SHA2 checksum" "checksums.sha2" }
|
||||||
|
{ $vocab-subsection "Adler-32 checksum" "checksums.adler-32" } ;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
IN: checksums.tests
|
||||||
|
USING: checksums tools.test ;
|
||||||
|
|
||||||
|
\ checksum-bytes must-infer
|
||||||
|
\ checksum-stream must-infer
|
||||||
|
\ checksum-lines must-infer
|
||||||
|
\ checksum-file must-infer
|
|
@ -542,3 +542,15 @@ TUPLE: another-forget-accessors-test ;
|
||||||
|
|
||||||
! Missing error check
|
! Missing error check
|
||||||
[ "IN: tuples.test USE: words TUPLE: wrong-superclass < word ;" eval ] must-fail
|
[ "IN: tuples.test USE: words TUPLE: wrong-superclass < word ;" eval ] must-fail
|
||||||
|
|
||||||
|
TUPLE: subclass-forget-test ;
|
||||||
|
|
||||||
|
TUPLE: subclass-forget-test-1 < subclass-forget-test ;
|
||||||
|
TUPLE: subclass-forget-test-2 < subclass-forget-test ;
|
||||||
|
TUPLE: subclass-forget-test-3 < subclass-forget-test-2 ;
|
||||||
|
|
||||||
|
[ ] [ "IN: classes.tuple.tests FORGET: subclass-forget-test" eval ] unit-test
|
||||||
|
|
||||||
|
[ f ] [ subclass-forget-test-1 tuple-class? ] unit-test
|
||||||
|
[ f ] [ subclass-forget-test-2 tuple-class? ] unit-test
|
||||||
|
[ subclass-forget-test-3 new ] must-fail
|
||||||
|
|
|
@ -102,7 +102,7 @@ ERROR: bad-superclass class ;
|
||||||
dup tuple-predicate-quot define-predicate ;
|
dup tuple-predicate-quot define-predicate ;
|
||||||
|
|
||||||
: superclass-size ( class -- n )
|
: superclass-size ( class -- n )
|
||||||
superclasses 1 head-slice*
|
superclasses but-last-slice
|
||||||
[ slot-names length ] map sum ;
|
[ slot-names length ] map sum ;
|
||||||
|
|
||||||
: generate-tuple-slots ( class slots -- slot-specs )
|
: generate-tuple-slots ( class slots -- slot-specs )
|
||||||
|
|
|
@ -4,38 +4,55 @@ USING: kernel namespaces arrays sequences io inference.backend
|
||||||
inference.state generator debugger words compiler.units
|
inference.state generator debugger words compiler.units
|
||||||
continuations vocabs assocs alien.compiler dlists optimizer
|
continuations vocabs assocs alien.compiler dlists optimizer
|
||||||
definitions math compiler.errors threads graphs generic
|
definitions math compiler.errors threads graphs generic
|
||||||
inference ;
|
inference combinators ;
|
||||||
IN: compiler
|
IN: compiler
|
||||||
|
|
||||||
: ripple-up ( word -- )
|
: ripple-up ( word -- )
|
||||||
compiled-usage [ drop queue-compile ] assoc-each ;
|
compiled-usage [ drop queue-compile ] assoc-each ;
|
||||||
|
|
||||||
: save-effect ( word effect -- )
|
: save-effect ( word effect -- )
|
||||||
over "compiled-uses" word-prop [
|
|
||||||
2dup swap "compiled-effect" word-prop =
|
|
||||||
[ over ripple-up ] unless
|
|
||||||
] when
|
|
||||||
"compiled-effect" set-word-prop ;
|
|
||||||
|
|
||||||
: finish-compile ( word effect dependencies -- )
|
|
||||||
>r dupd save-effect r>
|
|
||||||
over compiled-unxref
|
|
||||||
over compiled-crossref? [ compiled-xref ] [ 2drop ] if ;
|
|
||||||
|
|
||||||
: compile-succeeded ( word -- effect dependencies )
|
|
||||||
[
|
[
|
||||||
[ word-dataflow optimize ] keep dup generate
|
over "compiled-effect" word-prop = [
|
||||||
] computing-dependencies ;
|
dup "compiled-uses" word-prop
|
||||||
|
[ dup ripple-up ] when
|
||||||
|
] unless drop
|
||||||
|
]
|
||||||
|
[ "compiled-effect" set-word-prop ] 2bi ;
|
||||||
|
|
||||||
|
: compile-begins ( word -- )
|
||||||
|
f swap compiler-error ;
|
||||||
|
|
||||||
: compile-failed ( word error -- )
|
: compile-failed ( word error -- )
|
||||||
f pick compiled get set-at
|
[ swap compiler-error ]
|
||||||
swap compiler-error ;
|
[
|
||||||
|
drop
|
||||||
|
[ f swap compiled get set-at ]
|
||||||
|
[ f save-effect ]
|
||||||
|
bi
|
||||||
|
] 2bi ;
|
||||||
|
|
||||||
|
: compile-succeeded ( effect word -- )
|
||||||
|
[ swap save-effect ]
|
||||||
|
[ compiled-unxref ]
|
||||||
|
[
|
||||||
|
dup compiled-crossref?
|
||||||
|
[ dependencies get compiled-xref ] [ drop ] if
|
||||||
|
] tri ;
|
||||||
|
|
||||||
: (compile) ( word -- )
|
: (compile) ( word -- )
|
||||||
f over compiler-error
|
[
|
||||||
[ dup compile-succeeded finish-compile ]
|
H{ } clone dependencies set
|
||||||
[ dupd compile-failed f save-effect ]
|
|
||||||
recover ;
|
{
|
||||||
|
[ compile-begins ]
|
||||||
|
[
|
||||||
|
[ word-dataflow ] [ compile-failed return ] recover
|
||||||
|
optimize
|
||||||
|
]
|
||||||
|
[ dup generate ]
|
||||||
|
[ compile-succeeded ]
|
||||||
|
} cleave
|
||||||
|
] curry with-return ;
|
||||||
|
|
||||||
: compile-loop ( assoc -- )
|
: compile-loop ( assoc -- )
|
||||||
dup assoc-empty? [ drop ] [
|
dup assoc-empty? [ drop ] [
|
||||||
|
|
|
@ -5,6 +5,7 @@ IN: compiler.constants
|
||||||
|
|
||||||
! These constants must match vm/memory.h
|
! These constants must match vm/memory.h
|
||||||
: card-bits 6 ;
|
: card-bits 6 ;
|
||||||
|
: deck-bits 12 ;
|
||||||
: card-mark HEX: 40 HEX: 80 bitor ;
|
: card-mark HEX: 40 HEX: 80 bitor ;
|
||||||
|
|
||||||
! These constants must match vm/layouts.h
|
! These constants must match vm/layouts.h
|
||||||
|
|
|
@ -117,3 +117,5 @@ T{ dispose-dummy } "b" set
|
||||||
[ { "a" "b" } [ get ] map dispose-each ] [ 3 = ] must-fail-with
|
[ { "a" "b" } [ get ] map dispose-each ] [ 3 = ] must-fail-with
|
||||||
|
|
||||||
[ t ] [ "b" get disposed?>> ] unit-test
|
[ t ] [ "b" get disposed?>> ] unit-test
|
||||||
|
|
||||||
|
[ ] [ [ return ] with-return ] unit-test
|
||||||
|
|
|
@ -101,6 +101,14 @@ PRIVATE>
|
||||||
: continue ( continuation -- )
|
: continue ( continuation -- )
|
||||||
f swap continue-with ;
|
f swap continue-with ;
|
||||||
|
|
||||||
|
SYMBOL: return-continuation
|
||||||
|
|
||||||
|
: with-return ( quot -- )
|
||||||
|
[ [ return-continuation set ] prepose callcc0 ] with-scope ; inline
|
||||||
|
|
||||||
|
: return ( -- )
|
||||||
|
return-continuation get continue ;
|
||||||
|
|
||||||
GENERIC: compute-restarts ( error -- seq )
|
GENERIC: compute-restarts ( error -- seq )
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
|
@ -56,14 +56,22 @@ IN: cpu.ppc.intrinsics
|
||||||
: load-cards-offset ( dest -- )
|
: load-cards-offset ( dest -- )
|
||||||
"cards_offset" f pick %load-dlsym dup 0 LWZ ;
|
"cards_offset" f pick %load-dlsym dup 0 LWZ ;
|
||||||
|
|
||||||
|
: load-decks-offset ( dest -- )
|
||||||
|
"decks_offset" f pick %load-dlsym dup 0 LWZ ;
|
||||||
|
|
||||||
: %write-barrier ( -- )
|
: %write-barrier ( -- )
|
||||||
"val" get operand-immediate? "obj" get fresh-object? or [
|
"val" get operand-immediate? "obj" get fresh-object? or [
|
||||||
"obj" operand "scratch" operand card-bits SRWI
|
"scratch1" operand card-mark LI
|
||||||
|
|
||||||
|
! Mark the card
|
||||||
"val" operand load-cards-offset
|
"val" operand load-cards-offset
|
||||||
"scratch" operand dup "val" operand ADD
|
"obj" operand "scratch2" operand card-bits SRWI
|
||||||
"val" operand "scratch" operand 0 LBZ
|
"val" operand "scratch2" operand "val" operand STBX
|
||||||
"val" operand dup card-mark ORI
|
|
||||||
"val" operand "scratch" operand 0 STB
|
! Mark the card deck
|
||||||
|
"val" operand load-decks-offset
|
||||||
|
"obj" operand "scratch" operand deck-bits SRWI
|
||||||
|
"val" operand "scratch" operand "val" operand STBX
|
||||||
] unless ;
|
] unless ;
|
||||||
|
|
||||||
\ set-slot {
|
\ set-slot {
|
||||||
|
@ -71,7 +79,7 @@ IN: cpu.ppc.intrinsics
|
||||||
{
|
{
|
||||||
[ %slot-literal-known-tag STW %write-barrier ] H{
|
[ %slot-literal-known-tag STW %write-barrier ] H{
|
||||||
{ +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } }
|
{ +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } }
|
||||||
{ +scratch+ { { f "scratch" } } }
|
{ +scratch+ { { f "scratch1" } { f "scratch2" } } }
|
||||||
{ +clobber+ { "val" } }
|
{ +clobber+ { "val" } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,9 @@ M: x86.32 temp-reg-2 ECX ;
|
||||||
|
|
||||||
M: temp-reg v>operand drop EBX ;
|
M: temp-reg v>operand drop EBX ;
|
||||||
|
|
||||||
M: x86.32 %alien-invoke ( symbol dll -- )
|
M: x86.32 %alien-global 0 [] MOV rc-absolute-cell rel-dlsym ;
|
||||||
(CALL) rel-dlsym ;
|
|
||||||
|
M: x86.32 %alien-invoke (CALL) rel-dlsym ;
|
||||||
|
|
||||||
! On x86, parameters are never passed in registers.
|
! On x86, parameters are never passed in registers.
|
||||||
M: int-regs return-reg drop EAX ;
|
M: int-regs return-reg drop EAX ;
|
||||||
|
|
|
@ -130,7 +130,10 @@ M: x86.64 %prepare-box-struct ( size -- )
|
||||||
|
|
||||||
M: x86.64 %prepare-var-args RAX RAX XOR ;
|
M: x86.64 %prepare-var-args RAX RAX XOR ;
|
||||||
|
|
||||||
M: x86.64 %alien-invoke ( symbol dll -- )
|
M: x86.64 %alien-global
|
||||||
|
[ 0 MOV rc-absolute-cell rel-dlsym ] [ dup [] MOV ] bi ;
|
||||||
|
|
||||||
|
M: x86.64 %alien-invoke
|
||||||
0 address-operand >r rc-absolute-cell rel-dlsym r> CALL ;
|
0 address-operand >r rc-absolute-cell rel-dlsym r> CALL ;
|
||||||
|
|
||||||
M: x86.64 %prepare-alien-indirect ( -- )
|
M: x86.64 %prepare-alien-indirect ( -- )
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
! Copyright (C) 2005, 2008 Slava Pestov.
|
! Copyright (C) 2005, 2008 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: alien alien.c-types alien.compiler arrays
|
USING: alien alien.c-types alien.compiler arrays
|
||||||
cpu.x86.assembler cpu.architecture kernel kernel.private math
|
cpu.x86.assembler cpu.x86.assembler.private cpu.architecture
|
||||||
memory namespaces sequences words generator generator.registers
|
kernel kernel.private math memory namespaces sequences words
|
||||||
generator.fixup system layouts combinators compiler.constants
|
generator generator.registers generator.fixup system layouts
|
||||||
math.order ;
|
combinators compiler.constants math.order ;
|
||||||
IN: cpu.x86.architecture
|
IN: cpu.x86.architecture
|
||||||
|
|
||||||
HOOK: ds-reg cpu
|
HOOK: ds-reg cpu
|
||||||
|
@ -63,8 +63,7 @@ M: x86 %prologue ( n -- )
|
||||||
M: x86 %epilogue ( n -- )
|
M: x86 %epilogue ( n -- )
|
||||||
stack-reg swap ADD ;
|
stack-reg swap ADD ;
|
||||||
|
|
||||||
: %alien-global ( symbol dll register -- )
|
HOOK: %alien-global cpu ( symbol dll register -- )
|
||||||
[ 0 MOV rc-absolute-cell rel-dlsym ] keep dup [] MOV ;
|
|
||||||
|
|
||||||
M: x86 %prepare-alien-invoke
|
M: x86 %prepare-alien-invoke
|
||||||
#! Save Factor stack pointers in case the C code calls a
|
#! Save Factor stack pointers in case the C code calls a
|
||||||
|
|
|
@ -36,3 +36,6 @@ IN: cpu.x86.assembler.tests
|
||||||
|
|
||||||
[ { HEX: 0f HEX: be HEX: c3 } ] [ [ EAX BL MOVSX ] { } make ] unit-test
|
[ { HEX: 0f HEX: be HEX: c3 } ] [ [ EAX BL MOVSX ] { } make ] unit-test
|
||||||
[ { HEX: 0f HEX: bf HEX: c3 } ] [ [ EAX BX MOVSX ] { } make ] unit-test
|
[ { HEX: 0f HEX: bf HEX: c3 } ] [ [ EAX BX MOVSX ] { } make ] unit-test
|
||||||
|
|
||||||
|
[ { HEX: 80 HEX: 08 HEX: 05 } ] [ [ EAX [] 5 <byte> OR ] { } make ] unit-test
|
||||||
|
[ { HEX: c6 HEX: 00 HEX: 05 } ] [ [ EAX [] 5 <byte> MOV ] { } make ] unit-test
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: arrays generator.fixup io.binary kernel
|
USING: arrays generator.fixup io.binary kernel
|
||||||
combinators kernel.private math namespaces parser sequences
|
combinators kernel.private math namespaces parser sequences
|
||||||
words system layouts math.order ;
|
words system layouts math.order accessors ;
|
||||||
IN: cpu.x86.assembler
|
IN: cpu.x86.assembler
|
||||||
|
|
||||||
! A postfix assembler for x86 and AMD64.
|
! A postfix assembler for x86 and AMD64.
|
||||||
|
@ -11,11 +11,6 @@ IN: cpu.x86.assembler
|
||||||
! In 64-bit mode, { 1234 } is RIP-relative.
|
! In 64-bit mode, { 1234 } is RIP-relative.
|
||||||
! Beware!
|
! Beware!
|
||||||
|
|
||||||
: n, >le % ; inline
|
|
||||||
: 4, 4 n, ; inline
|
|
||||||
: 2, 2 n, ; inline
|
|
||||||
: cell, bootstrap-cell n, ; inline
|
|
||||||
|
|
||||||
! Register operands -- eg, ECX
|
! Register operands -- eg, ECX
|
||||||
<<
|
<<
|
||||||
|
|
||||||
|
@ -45,6 +40,10 @@ REGISTERS: 128
|
||||||
XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
|
XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
|
||||||
XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15 ;
|
XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15 ;
|
||||||
|
|
||||||
|
TUPLE: byte value ;
|
||||||
|
|
||||||
|
C: <byte> byte
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
#! Extended AMD64 registers (R8-R15) return true.
|
#! Extended AMD64 registers (R8-R15) return true.
|
||||||
|
@ -75,50 +74,38 @@ M: register extended? "register" word-prop 7 > ;
|
||||||
! Addressing modes
|
! Addressing modes
|
||||||
TUPLE: indirect base index scale displacement ;
|
TUPLE: indirect base index scale displacement ;
|
||||||
|
|
||||||
M: indirect extended? indirect-base extended? ;
|
M: indirect extended? base>> extended? ;
|
||||||
|
|
||||||
: canonicalize-EBP
|
: canonicalize-EBP
|
||||||
#! { EBP } ==> { EBP 0 }
|
#! { EBP } ==> { EBP 0 }
|
||||||
dup indirect-base { EBP RBP R13 } memq? [
|
dup base>> { EBP RBP R13 } member? [
|
||||||
dup indirect-displacement [
|
dup displacement>> [ 0 >>displacement ] unless
|
||||||
drop
|
] when drop ;
|
||||||
] [
|
|
||||||
0 swap set-indirect-displacement
|
|
||||||
] if
|
|
||||||
] [
|
|
||||||
drop
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
: canonicalize-ESP
|
: canonicalize-ESP
|
||||||
#! { ESP } ==> { ESP ESP }
|
#! { ESP } ==> { ESP ESP }
|
||||||
dup indirect-base { ESP RSP R12 } memq? [
|
dup base>> { ESP RSP R12 } member? [ ESP >>index ] when drop ;
|
||||||
ESP swap set-indirect-index
|
|
||||||
] [
|
|
||||||
drop
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
: canonicalize ( indirect -- )
|
: canonicalize ( indirect -- )
|
||||||
#! Modify the indirect to work around certain addressing mode
|
#! Modify the indirect to work around certain addressing mode
|
||||||
#! quirks.
|
#! quirks.
|
||||||
dup canonicalize-EBP
|
[ canonicalize-EBP ] [ canonicalize-ESP ] bi ;
|
||||||
canonicalize-ESP ;
|
|
||||||
|
|
||||||
: <indirect> ( base index scale displacement -- indirect )
|
: <indirect> ( base index scale displacement -- indirect )
|
||||||
indirect boa dup canonicalize ;
|
indirect boa dup canonicalize ;
|
||||||
|
|
||||||
: reg-code "register" word-prop 7 bitand ;
|
: reg-code "register" word-prop 7 bitand ;
|
||||||
|
|
||||||
: indirect-base* indirect-base EBP or reg-code ;
|
: indirect-base* base>> EBP or reg-code ;
|
||||||
|
|
||||||
: indirect-index* indirect-index ESP or reg-code ;
|
: indirect-index* index>> ESP or reg-code ;
|
||||||
|
|
||||||
: indirect-scale* indirect-scale 0 or ;
|
: indirect-scale* scale>> 0 or ;
|
||||||
|
|
||||||
GENERIC: sib-present? ( op -- ? )
|
GENERIC: sib-present? ( op -- ? )
|
||||||
|
|
||||||
M: indirect sib-present?
|
M: indirect sib-present?
|
||||||
dup indirect-base { ESP RSP } memq?
|
[ base>> { ESP RSP } member? ] [ index>> ] [ scale>> ] tri or or ;
|
||||||
over indirect-index rot indirect-scale or or ;
|
|
||||||
|
|
||||||
M: register sib-present? drop f ;
|
M: register sib-present? drop f ;
|
||||||
|
|
||||||
|
@ -130,16 +117,23 @@ M: indirect r/m
|
||||||
|
|
||||||
M: register r/m reg-code ;
|
M: register r/m reg-code ;
|
||||||
|
|
||||||
: byte? -128 127 between? ;
|
! Immediate operands
|
||||||
|
UNION: immediate byte integer ;
|
||||||
|
|
||||||
|
GENERIC: fits-in-byte? ( value -- ? )
|
||||||
|
|
||||||
|
M: byte fits-in-byte? drop t ;
|
||||||
|
|
||||||
|
M: integer fits-in-byte? -128 127 between? ;
|
||||||
|
|
||||||
GENERIC: modifier ( op -- n )
|
GENERIC: modifier ( op -- n )
|
||||||
|
|
||||||
M: indirect modifier
|
M: indirect modifier
|
||||||
dup indirect-base [
|
dup base>> [
|
||||||
indirect-displacement {
|
displacement>> {
|
||||||
{ [ dup not ] [ BIN: 00 ] }
|
{ [ dup not ] [ BIN: 00 ] }
|
||||||
{ [ dup byte? ] [ BIN: 01 ] }
|
{ [ dup fits-in-byte? ] [ BIN: 01 ] }
|
||||||
{ [ dup integer? ] [ BIN: 10 ] }
|
{ [ dup immediate? ] [ BIN: 10 ] }
|
||||||
} cond nip
|
} cond nip
|
||||||
] [
|
] [
|
||||||
drop BIN: 00
|
drop BIN: 00
|
||||||
|
@ -147,14 +141,23 @@ M: indirect modifier
|
||||||
|
|
||||||
M: register modifier drop BIN: 11 ;
|
M: register modifier drop BIN: 11 ;
|
||||||
|
|
||||||
|
GENERIC# n, 1 ( value n -- )
|
||||||
|
|
||||||
|
M: integer n, >le % ;
|
||||||
|
M: byte n, >r value>> r> n, ;
|
||||||
|
: 1, 1 n, ; inline
|
||||||
|
: 4, 4 n, ; inline
|
||||||
|
: 2, 2 n, ; inline
|
||||||
|
: cell, bootstrap-cell n, ; inline
|
||||||
|
|
||||||
: mod-r/m, ( reg# indirect -- )
|
: mod-r/m, ( reg# indirect -- )
|
||||||
dup modifier 6 shift rot 3 shift rot r/m bitor bitor , ;
|
[ 3 shift ] [ [ modifier 6 shift ] [ r/m ] bi ] bi* bitor bitor , ;
|
||||||
|
|
||||||
: sib, ( indirect -- )
|
: sib, ( indirect -- )
|
||||||
dup sib-present? [
|
dup sib-present? [
|
||||||
dup indirect-base*
|
[ indirect-base* ]
|
||||||
over indirect-index* 3 shift bitor
|
[ indirect-index* 3 shift ]
|
||||||
swap indirect-scale* 6 shift bitor ,
|
[ indirect-scale* 6 shift ] tri bitor bitor ,
|
||||||
] [
|
] [
|
||||||
drop
|
drop
|
||||||
] if ;
|
] if ;
|
||||||
|
@ -162,9 +165,9 @@ M: register modifier drop BIN: 11 ;
|
||||||
GENERIC: displacement, ( op -- )
|
GENERIC: displacement, ( op -- )
|
||||||
|
|
||||||
M: indirect displacement,
|
M: indirect displacement,
|
||||||
dup indirect-displacement dup [
|
dup displacement>> dup [
|
||||||
swap indirect-base
|
swap base>>
|
||||||
[ dup byte? [ , ] [ 4, ] if ] [ 4, ] if
|
[ dup fits-in-byte? [ , ] [ 4, ] if ] [ 4, ] if
|
||||||
] [
|
] [
|
||||||
2drop
|
2drop
|
||||||
] if ;
|
] if ;
|
||||||
|
@ -172,18 +175,19 @@ M: indirect displacement,
|
||||||
M: register displacement, drop ;
|
M: register displacement, drop ;
|
||||||
|
|
||||||
: addressing ( reg# indirect -- )
|
: addressing ( reg# indirect -- )
|
||||||
[ mod-r/m, ] keep [ sib, ] keep displacement, ;
|
[ mod-r/m, ] [ sib, ] [ displacement, ] tri ;
|
||||||
|
|
||||||
! Utilities
|
! Utilities
|
||||||
UNION: operand register indirect ;
|
UNION: operand register indirect ;
|
||||||
|
|
||||||
: operand-64? ( operand -- ? )
|
GENERIC: operand-64? ( operand -- ? )
|
||||||
dup indirect? [
|
|
||||||
dup indirect-base register-64?
|
M: indirect operand-64?
|
||||||
swap indirect-index register-64? or
|
[ base>> ] [ index>> ] bi [ operand-64? ] either? ;
|
||||||
] [
|
|
||||||
register-64?
|
M: register-64 operand-64? drop t ;
|
||||||
] if ;
|
|
||||||
|
M: object operand-64? drop f ;
|
||||||
|
|
||||||
: rex.w? ( rex.w reg r/m -- ? )
|
: rex.w? ( rex.w reg r/m -- ? )
|
||||||
{
|
{
|
||||||
|
@ -198,8 +202,7 @@ UNION: operand register indirect ;
|
||||||
: rex.b
|
: rex.b
|
||||||
[ extended? [ BIN: 00000001 bitor ] when ] keep
|
[ extended? [ BIN: 00000001 bitor ] when ] keep
|
||||||
dup indirect? [
|
dup indirect? [
|
||||||
indirect-index extended?
|
index>> extended? [ BIN: 00000010 bitor ] when
|
||||||
[ BIN: 00000010 bitor ] when
|
|
||||||
] [
|
] [
|
||||||
drop
|
drop
|
||||||
] if ;
|
] if ;
|
||||||
|
@ -230,25 +233,34 @@ UNION: operand register indirect ;
|
||||||
|
|
||||||
: opcode-or ( opcode mask -- opcode' )
|
: opcode-or ( opcode mask -- opcode' )
|
||||||
swap dup array?
|
swap dup array?
|
||||||
[ 1 cut* first rot bitor suffix ] [ bitor ] if ;
|
[ unclip-last rot bitor suffix ] [ bitor ] if ;
|
||||||
|
|
||||||
: 1-operand ( op reg rex.w opcode -- )
|
: 1-operand ( op reg,rex.w,opcode -- )
|
||||||
#! The 'reg' is not really a register, but a value for the
|
#! The 'reg' is not really a register, but a value for the
|
||||||
#! 'reg' field of the mod-r/m byte.
|
#! 'reg' field of the mod-r/m byte.
|
||||||
>r >r over r> prefix-1 r> opcode, swap addressing ;
|
first3 >r >r over r> prefix-1 r> opcode, swap addressing ;
|
||||||
|
|
||||||
: immediate-1 ( imm dst reg rex.w opcode -- )
|
: immediate-operand-size-bit
|
||||||
1-operand , ;
|
pick integer? [ first3 BIN: 1 opcode-or 3array ] when ;
|
||||||
|
|
||||||
: immediate-1/4 ( imm dst reg rex.w opcode -- )
|
: immediate-1 ( imm dst reg,rex.w,opcode -- )
|
||||||
|
immediate-operand-size-bit 1-operand 1, ;
|
||||||
|
|
||||||
|
: immediate-4 ( imm dst reg,rex.w,opcode -- )
|
||||||
|
immediate-operand-size-bit 1-operand 4, ;
|
||||||
|
|
||||||
|
: immediate-fits-in-size-bit
|
||||||
|
pick integer? [ first3 BIN: 10 opcode-or 3array ] when ;
|
||||||
|
|
||||||
|
: immediate-1/4 ( imm dst reg,rex.w,opcode -- )
|
||||||
#! If imm is a byte, compile the opcode and the byte.
|
#! If imm is a byte, compile the opcode and the byte.
|
||||||
#! Otherwise, set the 32-bit operand flag in the opcode, and
|
#! Otherwise, set the 8-bit operand flag in the opcode, and
|
||||||
#! compile the cell. The 'reg' is not really a register, but
|
#! compile the cell. The 'reg' is not really a register, but
|
||||||
#! a value for the 'reg' field of the mod-r/m byte.
|
#! a value for the 'reg' field of the mod-r/m byte.
|
||||||
>r >r pick byte? [
|
pick fits-in-byte? [
|
||||||
r> r> BIN: 10 opcode-or immediate-1
|
immediate-fits-in-size-bit immediate-1
|
||||||
] [
|
] [
|
||||||
r> r> 1-operand 4,
|
immediate-4
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
: (2-operand) ( dst src op -- )
|
: (2-operand) ( dst src op -- )
|
||||||
|
@ -283,22 +295,24 @@ PRIVATE>
|
||||||
! Moving stuff
|
! Moving stuff
|
||||||
GENERIC: PUSH ( op -- )
|
GENERIC: PUSH ( op -- )
|
||||||
M: register PUSH f HEX: 50 short-operand ;
|
M: register PUSH f HEX: 50 short-operand ;
|
||||||
M: integer PUSH HEX: 68 , 4, ;
|
M: immediate PUSH HEX: 68 , 4, ;
|
||||||
M: operand PUSH BIN: 110 f HEX: ff 1-operand ;
|
M: operand PUSH { BIN: 110 f HEX: ff } 1-operand ;
|
||||||
|
|
||||||
GENERIC: POP ( op -- )
|
GENERIC: POP ( op -- )
|
||||||
M: register POP f HEX: 58 short-operand ;
|
M: register POP f HEX: 58 short-operand ;
|
||||||
M: operand POP BIN: 000 f HEX: 8f 1-operand ;
|
M: operand POP { BIN: 000 f HEX: 8f } 1-operand ;
|
||||||
|
|
||||||
! MOV where the src is immediate.
|
! MOV where the src is immediate.
|
||||||
GENERIC: (MOV-I) ( src dst -- )
|
GENERIC: (MOV-I) ( src dst -- )
|
||||||
M: register (MOV-I) t HEX: b8 short-operand cell, ;
|
M: register (MOV-I) t HEX: b8 short-operand cell, ;
|
||||||
M: operand (MOV-I) BIN: 000 t HEX: c7 1-operand 4, ;
|
M: operand (MOV-I)
|
||||||
|
{ BIN: 000 t HEX: c6 }
|
||||||
|
pick byte? [ immediate-1 ] [ immediate-4 ] if ;
|
||||||
|
|
||||||
PREDICATE: callable < word register? not ;
|
PREDICATE: callable < word register? not ;
|
||||||
|
|
||||||
GENERIC: MOV ( dst src -- )
|
GENERIC: MOV ( dst src -- )
|
||||||
M: integer MOV swap (MOV-I) ;
|
M: immediate MOV swap (MOV-I) ;
|
||||||
M: callable MOV 0 rot (MOV-I) rc-absolute-cell rel-word ;
|
M: callable MOV 0 rot (MOV-I) rc-absolute-cell rel-word ;
|
||||||
M: operand MOV HEX: 88 2-operand ;
|
M: operand MOV HEX: 88 2-operand ;
|
||||||
|
|
||||||
|
@ -309,13 +323,13 @@ GENERIC: JMP ( op -- )
|
||||||
: (JMP) HEX: e9 , 0 4, rc-relative ;
|
: (JMP) HEX: e9 , 0 4, rc-relative ;
|
||||||
M: callable JMP (JMP) rel-word ;
|
M: callable JMP (JMP) rel-word ;
|
||||||
M: label JMP (JMP) label-fixup ;
|
M: label JMP (JMP) label-fixup ;
|
||||||
M: operand JMP BIN: 100 t HEX: ff 1-operand ;
|
M: operand JMP { BIN: 100 t HEX: ff } 1-operand ;
|
||||||
|
|
||||||
GENERIC: CALL ( op -- )
|
GENERIC: CALL ( op -- )
|
||||||
: (CALL) HEX: e8 , 0 4, rc-relative ;
|
: (CALL) HEX: e8 , 0 4, rc-relative ;
|
||||||
M: callable CALL (CALL) rel-word ;
|
M: callable CALL (CALL) rel-word ;
|
||||||
M: label CALL (CALL) label-fixup ;
|
M: label CALL (CALL) label-fixup ;
|
||||||
M: operand CALL BIN: 010 t HEX: ff 1-operand ;
|
M: operand CALL { BIN: 010 t HEX: ff } 1-operand ;
|
||||||
|
|
||||||
GENERIC# JUMPcc 1 ( addr opcode -- )
|
GENERIC# JUMPcc 1 ( addr opcode -- )
|
||||||
: (JUMPcc) extended-opcode, 0 4, rc-relative ;
|
: (JUMPcc) extended-opcode, 0 4, rc-relative ;
|
||||||
|
@ -347,57 +361,57 @@ M: label JUMPcc (JUMPcc) label-fixup ;
|
||||||
! Arithmetic
|
! Arithmetic
|
||||||
|
|
||||||
GENERIC: ADD ( dst src -- )
|
GENERIC: ADD ( dst src -- )
|
||||||
M: integer ADD swap BIN: 000 t HEX: 81 immediate-1/4 ;
|
M: immediate ADD swap { BIN: 000 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand ADD OCT: 000 2-operand ;
|
M: operand ADD OCT: 000 2-operand ;
|
||||||
|
|
||||||
GENERIC: OR ( dst src -- )
|
GENERIC: OR ( dst src -- )
|
||||||
M: integer OR swap BIN: 001 t HEX: 81 immediate-1/4 ;
|
M: immediate OR swap { BIN: 001 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand OR OCT: 010 2-operand ;
|
M: operand OR OCT: 010 2-operand ;
|
||||||
|
|
||||||
GENERIC: ADC ( dst src -- )
|
GENERIC: ADC ( dst src -- )
|
||||||
M: integer ADC swap BIN: 010 t HEX: 81 immediate-1/4 ;
|
M: immediate ADC swap { BIN: 010 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand ADC OCT: 020 2-operand ;
|
M: operand ADC OCT: 020 2-operand ;
|
||||||
|
|
||||||
GENERIC: SBB ( dst src -- )
|
GENERIC: SBB ( dst src -- )
|
||||||
M: integer SBB swap BIN: 011 t HEX: 81 immediate-1/4 ;
|
M: immediate SBB swap { BIN: 011 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand SBB OCT: 030 2-operand ;
|
M: operand SBB OCT: 030 2-operand ;
|
||||||
|
|
||||||
GENERIC: AND ( dst src -- )
|
GENERIC: AND ( dst src -- )
|
||||||
M: integer AND swap BIN: 100 t HEX: 81 immediate-1/4 ;
|
M: immediate AND swap { BIN: 100 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand AND OCT: 040 2-operand ;
|
M: operand AND OCT: 040 2-operand ;
|
||||||
|
|
||||||
GENERIC: SUB ( dst src -- )
|
GENERIC: SUB ( dst src -- )
|
||||||
M: integer SUB swap BIN: 101 t HEX: 81 immediate-1/4 ;
|
M: immediate SUB swap { BIN: 101 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand SUB OCT: 050 2-operand ;
|
M: operand SUB OCT: 050 2-operand ;
|
||||||
|
|
||||||
GENERIC: XOR ( dst src -- )
|
GENERIC: XOR ( dst src -- )
|
||||||
M: integer XOR swap BIN: 110 t HEX: 81 immediate-1/4 ;
|
M: immediate XOR swap { BIN: 110 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand XOR OCT: 060 2-operand ;
|
M: operand XOR OCT: 060 2-operand ;
|
||||||
|
|
||||||
GENERIC: CMP ( dst src -- )
|
GENERIC: CMP ( dst src -- )
|
||||||
M: integer CMP swap BIN: 111 t HEX: 81 immediate-1/4 ;
|
M: immediate CMP swap { BIN: 111 t HEX: 80 } immediate-1/4 ;
|
||||||
M: operand CMP OCT: 070 2-operand ;
|
M: operand CMP OCT: 070 2-operand ;
|
||||||
|
|
||||||
: NOT ( dst -- ) BIN: 010 t HEX: f7 1-operand ;
|
: NOT ( dst -- ) { BIN: 010 t HEX: f7 } 1-operand ;
|
||||||
: NEG ( dst -- ) BIN: 011 t HEX: f7 1-operand ;
|
: NEG ( dst -- ) { BIN: 011 t HEX: f7 } 1-operand ;
|
||||||
: MUL ( dst -- ) BIN: 100 t HEX: f7 1-operand ;
|
: MUL ( dst -- ) { BIN: 100 t HEX: f7 } 1-operand ;
|
||||||
: IMUL ( src -- ) BIN: 101 t HEX: f7 1-operand ;
|
: IMUL ( src -- ) { BIN: 101 t HEX: f7 } 1-operand ;
|
||||||
: DIV ( dst -- ) BIN: 110 t HEX: f7 1-operand ;
|
: DIV ( dst -- ) { BIN: 110 t HEX: f7 } 1-operand ;
|
||||||
: IDIV ( src -- ) BIN: 111 t HEX: f7 1-operand ;
|
: IDIV ( src -- ) { BIN: 111 t HEX: f7 } 1-operand ;
|
||||||
|
|
||||||
: CDQ HEX: 99 , ;
|
: CDQ HEX: 99 , ;
|
||||||
: CQO HEX: 48 , CDQ ;
|
: CQO HEX: 48 , CDQ ;
|
||||||
|
|
||||||
: ROL ( dst n -- ) swap BIN: 000 t HEX: c1 immediate-1 ;
|
: ROL ( dst n -- ) swap { BIN: 000 t HEX: c0 } immediate-1 ;
|
||||||
: ROR ( dst n -- ) swap BIN: 001 t HEX: c1 immediate-1 ;
|
: ROR ( dst n -- ) swap { BIN: 001 t HEX: c0 } immediate-1 ;
|
||||||
: RCL ( dst n -- ) swap BIN: 010 t HEX: c1 immediate-1 ;
|
: RCL ( dst n -- ) swap { BIN: 010 t HEX: c0 } immediate-1 ;
|
||||||
: RCR ( dst n -- ) swap BIN: 011 t HEX: c1 immediate-1 ;
|
: RCR ( dst n -- ) swap { BIN: 011 t HEX: c0 } immediate-1 ;
|
||||||
: SHL ( dst n -- ) swap BIN: 100 t HEX: c1 immediate-1 ;
|
: SHL ( dst n -- ) swap { BIN: 100 t HEX: c0 } immediate-1 ;
|
||||||
: SHR ( dst n -- ) swap BIN: 101 t HEX: c1 immediate-1 ;
|
: SHR ( dst n -- ) swap { BIN: 101 t HEX: c0 } immediate-1 ;
|
||||||
: SAR ( dst n -- ) swap BIN: 111 t HEX: c1 immediate-1 ;
|
: SAR ( dst n -- ) swap { BIN: 111 t HEX: c0 } immediate-1 ;
|
||||||
|
|
||||||
GENERIC: IMUL2 ( dst src -- )
|
GENERIC: IMUL2 ( dst src -- )
|
||||||
M: integer IMUL2 swap dup reg-code t HEX: 69 immediate-1/4 ;
|
M: immediate IMUL2 swap dup reg-code t HEX: 68 3array immediate-1/4 ;
|
||||||
M: operand IMUL2 OCT: 257 extended-opcode (2-operand) ;
|
M: operand IMUL2 OCT: 257 extended-opcode (2-operand) ;
|
||||||
|
|
||||||
: MOVSX ( dst src -- )
|
: MOVSX ( dst src -- )
|
||||||
|
@ -432,11 +446,11 @@ M: operand IMUL2 OCT: 257 extended-opcode (2-operand) ;
|
||||||
|
|
||||||
! x87 Floating Point Unit
|
! x87 Floating Point Unit
|
||||||
|
|
||||||
: FSTPS ( operand -- ) BIN: 011 f HEX: d9 1-operand ;
|
: FSTPS ( operand -- ) { BIN: 011 f HEX: d9 } 1-operand ;
|
||||||
: FSTPL ( operand -- ) BIN: 011 f HEX: dd 1-operand ;
|
: FSTPL ( operand -- ) { BIN: 011 f HEX: dd } 1-operand ;
|
||||||
|
|
||||||
: FLDS ( operand -- ) BIN: 000 f HEX: d9 1-operand ;
|
: FLDS ( operand -- ) { BIN: 000 f HEX: d9 } 1-operand ;
|
||||||
: FLDL ( operand -- ) BIN: 000 f HEX: dd 1-operand ;
|
: FLDL ( operand -- ) { BIN: 000 f HEX: dd } 1-operand ;
|
||||||
|
|
||||||
! SSE multimedia instructions
|
! SSE multimedia instructions
|
||||||
|
|
||||||
|
|
|
@ -63,9 +63,15 @@ IN: cpu.x86.intrinsics
|
||||||
: generate-write-barrier ( -- )
|
: generate-write-barrier ( -- )
|
||||||
#! Mark the card pointed to by vreg.
|
#! Mark the card pointed to by vreg.
|
||||||
"val" get operand-immediate? "obj" get fresh-object? or [
|
"val" get operand-immediate? "obj" get fresh-object? or [
|
||||||
|
! Mark the card
|
||||||
"obj" operand card-bits SHR
|
"obj" operand card-bits SHR
|
||||||
"cards_offset" f temp-reg v>operand %alien-global
|
"cards_offset" f temp-reg v>operand %alien-global
|
||||||
temp-reg v>operand "obj" operand [+] card-mark OR
|
temp-reg v>operand "obj" operand [+] card-mark <byte> MOV
|
||||||
|
|
||||||
|
! Mark the card deck
|
||||||
|
"obj" operand deck-bits card-bits - SHR
|
||||||
|
"decks_offset" f temp-reg v>operand %alien-global
|
||||||
|
temp-reg v>operand "obj" operand [+] card-mark <byte> MOV
|
||||||
] unless ;
|
] unless ;
|
||||||
|
|
||||||
\ set-slot {
|
\ set-slot {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
USING: alien arrays generic generic.math help.markup help.syntax
|
USING: alien arrays generic generic.math help.markup help.syntax
|
||||||
kernel math memory strings sbufs vectors io io.files classes
|
kernel math memory strings sbufs vectors io io.files classes
|
||||||
help generic.standard continuations system debugger.private
|
help generic.standard continuations system debugger.private
|
||||||
io.files.private ;
|
io.files.private listener ;
|
||||||
IN: debugger
|
IN: debugger
|
||||||
|
|
||||||
ARTICLE: "errors-assert" "Assertions"
|
ARTICLE: "errors-assert" "Assertions"
|
||||||
|
@ -81,13 +81,9 @@ HELP: print-error
|
||||||
HELP: restarts.
|
HELP: restarts.
|
||||||
{ $description "Print a list of restarts for the most recently thrown error to " { $link output-stream } "." } ;
|
{ $description "Print a list of restarts for the most recently thrown error to " { $link output-stream } "." } ;
|
||||||
|
|
||||||
HELP: error-hook
|
|
||||||
{ $var-description "A quotation with stack effect " { $snippet "( error -- )" } " which is used by " { $link try } " to report the error to the user." }
|
|
||||||
{ $examples "The default value prints the error with " { $link print-error } ", followed by a list of restarts and a help message. The graphical listener sets this variable to display a popup instead." } ;
|
|
||||||
|
|
||||||
HELP: try
|
HELP: try
|
||||||
{ $values { "quot" "a quotation" } }
|
{ $values { "quot" "a quotation" } }
|
||||||
{ $description "Attempts to call a quotation; if it throws an error, the " { $link error-hook } " gets called, stacks are restored, and execution continues after the call to " { $link try } "." }
|
{ $description "Attempts to call a quotation; if it throws an error, the error is printed to " { $link output-stream } ", stacks are restored, and execution continues after the call to " { $link try } "." }
|
||||||
{ $examples
|
{ $examples
|
||||||
"The following example prints an error and keeps going:"
|
"The following example prints an error and keeps going:"
|
||||||
{ $code
|
{ $code
|
||||||
|
|
|
@ -64,13 +64,14 @@ M: string error. print ;
|
||||||
[ global [ "Error in print-error!" print drop ] bind ]
|
[ global [ "Error in print-error!" print drop ] bind ]
|
||||||
recover ;
|
recover ;
|
||||||
|
|
||||||
|
: print-error-and-restarts ( error -- )
|
||||||
|
print-error
|
||||||
|
restarts.
|
||||||
|
nl
|
||||||
|
"Type :help for debugging help." print flush ;
|
||||||
|
|
||||||
: try ( quot -- )
|
: try ( quot -- )
|
||||||
[
|
[ print-error-and-restarts ] recover ;
|
||||||
print-error
|
|
||||||
restarts.
|
|
||||||
nl
|
|
||||||
"Type :help for debugging help." print flush
|
|
||||||
] recover ;
|
|
||||||
|
|
||||||
ERROR: assert got expect ;
|
ERROR: assert got expect ;
|
||||||
|
|
||||||
|
@ -269,8 +270,7 @@ M: double-free summary
|
||||||
M: realloc-error summary
|
M: realloc-error summary
|
||||||
drop "Memory reallocation failed" ;
|
drop "Memory reallocation failed" ;
|
||||||
|
|
||||||
: error-in-thread. ( -- )
|
: error-in-thread. ( thread -- )
|
||||||
error-thread get-global
|
|
||||||
"Error in thread " write
|
"Error in thread " write
|
||||||
[
|
[
|
||||||
dup thread-id #
|
dup thread-id #
|
||||||
|
@ -284,7 +284,7 @@ M: thread error-in-thread ( error thread -- )
|
||||||
die drop
|
die drop
|
||||||
] [
|
] [
|
||||||
global [
|
global [
|
||||||
error-in-thread. print-error flush
|
error-thread get-global error-in-thread. print-error flush
|
||||||
] bind
|
] bind
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
|
|
|
@ -362,7 +362,7 @@ M: object infer-call
|
||||||
|
|
||||||
\ gc { } { } <effect> set-primitive-effect
|
\ gc { } { } <effect> set-primitive-effect
|
||||||
|
|
||||||
\ gc-time { } { integer } <effect> set-primitive-effect
|
\ gc-stats { } { array } <effect> set-primitive-effect
|
||||||
|
|
||||||
\ save-image { string } { } <effect> set-primitive-effect
|
\ save-image { string } { } <effect> set-primitive-effect
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ M: object infer-call
|
||||||
t over set-effect-terminated?
|
t over set-effect-terminated?
|
||||||
set-primitive-effect
|
set-primitive-effect
|
||||||
|
|
||||||
\ data-room { } { integer array } <effect> set-primitive-effect
|
\ data-room { } { integer integer array } <effect> set-primitive-effect
|
||||||
\ data-room make-flushable
|
\ data-room make-flushable
|
||||||
|
|
||||||
\ code-room { } { integer integer integer integer } <effect> set-primitive-effect
|
\ code-room { } { integer integer integer integer } <effect> set-primitive-effect
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
IN: inference.state.tests
|
IN: inference.state.tests
|
||||||
USING: tools.test inference.state words ;
|
USING: tools.test inference.state words kernel namespaces ;
|
||||||
|
|
||||||
|
: computing-dependencies ( quot -- dependencies )
|
||||||
|
H{ } clone [ dependencies rot with-variable ] keep ;
|
||||||
|
inline
|
||||||
|
|
||||||
SYMBOL: a
|
SYMBOL: a
|
||||||
SYMBOL: b
|
SYMBOL: b
|
||||||
|
|
|
@ -36,10 +36,6 @@ SYMBOL: dependencies
|
||||||
2dup at +inlined+ eq? [ 3drop ] [ set-at ] if
|
2dup at +inlined+ eq? [ 3drop ] [ set-at ] if
|
||||||
] [ 3drop ] if ;
|
] [ 3drop ] if ;
|
||||||
|
|
||||||
: computing-dependencies ( quot -- dependencies )
|
|
||||||
H{ } clone [ dependencies rot with-variable ] keep ;
|
|
||||||
inline
|
|
||||||
|
|
||||||
! Did the current control-flow path throw an error?
|
! Did the current control-flow path throw an error?
|
||||||
SYMBOL: terminated?
|
SYMBOL: terminated?
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ IN: inference.transforms
|
||||||
drop [ no-case ]
|
drop [ no-case ]
|
||||||
] [
|
] [
|
||||||
dup peek quotation? [
|
dup peek quotation? [
|
||||||
dup peek swap 1 head*
|
dup peek swap but-last
|
||||||
] [
|
] [
|
||||||
[ no-case ] swap
|
[ no-case ] swap
|
||||||
] if case>quot
|
] if case>quot
|
||||||
|
|
|
@ -2,11 +2,8 @@ USING: io.files io.streams.string io
|
||||||
tools.test kernel io.encodings.ascii ;
|
tools.test kernel io.encodings.ascii ;
|
||||||
IN: io.streams.encodings.tests
|
IN: io.streams.encodings.tests
|
||||||
|
|
||||||
: <resource-reader> ( resource -- stream )
|
|
||||||
resource-path ascii <file-reader> ;
|
|
||||||
|
|
||||||
[ { } ]
|
[ { } ]
|
||||||
[ "core/io/test/empty-file.txt" <resource-reader> lines ]
|
[ "resource:core/io/test/empty-file.txt" ascii <file-reader> lines ]
|
||||||
unit-test
|
unit-test
|
||||||
|
|
||||||
: lines-test ( stream -- line1 line2 )
|
: lines-test ( stream -- line1 line2 )
|
||||||
|
@ -16,21 +13,24 @@ unit-test
|
||||||
"This is a line."
|
"This is a line."
|
||||||
"This is another line."
|
"This is another line."
|
||||||
] [
|
] [
|
||||||
"core/io/test/windows-eol.txt" <resource-reader> lines-test
|
"resource:core/io/test/windows-eol.txt"
|
||||||
|
ascii <file-reader> lines-test
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
"This is a line."
|
"This is a line."
|
||||||
"This is another line."
|
"This is another line."
|
||||||
] [
|
] [
|
||||||
"core/io/test/mac-os-eol.txt" <resource-reader> lines-test
|
"resource:core/io/test/mac-os-eol.txt"
|
||||||
|
ascii <file-reader> lines-test
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
"This is a line."
|
"This is a line."
|
||||||
"This is another line."
|
"This is another line."
|
||||||
] [
|
] [
|
||||||
"core/io/test/unix-eol.txt" <resource-reader> lines-test
|
"resource:core/io/test/unix-eol.txt"
|
||||||
|
ascii <file-reader> lines-test
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|
|
@ -273,11 +273,11 @@ $nl
|
||||||
|
|
||||||
HELP: append-path
|
HELP: append-path
|
||||||
{ $values { "str1" "a string" } { "str2" "a string" } { "str" "a string" } }
|
{ $values { "str1" "a string" } { "str2" "a string" } { "str" "a string" } }
|
||||||
{ $description "Concatenates two pathnames." } ;
|
{ $description "Appends " { $snippet "str1" } " and " { $snippet "str2" } " to form a pathname." } ;
|
||||||
|
|
||||||
HELP: prepend-path
|
HELP: prepend-path
|
||||||
{ $values { "str1" "a string" } { "str2" "a string" } { "str" "a string" } }
|
{ $values { "str1" "a string" } { "str2" "a string" } { "str" "a string" } }
|
||||||
{ $description "Concatenates two pathnames." } ;
|
{ $description "Appends " { $snippet "str2" } " and " { $snippet "str1" } " to form a pathname." } ;
|
||||||
|
|
||||||
{ append-path prepend-path } related-words
|
{ append-path prepend-path } related-words
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ $nl
|
||||||
ABOUT: "streams"
|
ABOUT: "streams"
|
||||||
|
|
||||||
HELP: stream-readln
|
HELP: stream-readln
|
||||||
{ $values { "stream" "an input stream" } { "str" string } }
|
{ $values { "stream" "an input stream" } { "str/f" "a string or " { $link f } } }
|
||||||
{ $contract "Reads a line of input from the stream. Outputs " { $link f } " on stream exhaustion." }
|
{ $contract "Reads a line of input from the stream. Outputs " { $link f } " on stream exhaustion." }
|
||||||
{ $notes "Most code only works on one stream at a time and should instead use " { $link readln } "; see " { $link "stdio" } "." }
|
{ $notes "Most code only works on one stream at a time and should instead use " { $link readln } "; see " { $link "stdio" } "." }
|
||||||
$io-error ;
|
$io-error ;
|
||||||
|
@ -139,7 +139,7 @@ $io-error ;
|
||||||
HELP: stream-read
|
HELP: stream-read
|
||||||
{ $values { "n" "a non-negative integer" } { "stream" "an input stream" } { "str/f" "a string or " { $link f } } }
|
{ $values { "n" "a non-negative integer" } { "stream" "an input stream" } { "str/f" "a string or " { $link f } } }
|
||||||
{ $contract "Reads " { $snippet "n" } " characters of input from the stream. Outputs a truncated string or " { $link f } " on stream exhaustion." }
|
{ $contract "Reads " { $snippet "n" } " characters of input from the stream. Outputs a truncated string or " { $link f } " on stream exhaustion." }
|
||||||
{ $notes "Most code only works on one stream at a time and should instead use " { $link read1 } "; see " { $link "stdio" } "." }
|
{ $notes "Most code only works on one stream at a time and should instead use " { $link read } "; see " { $link "stdio" } "." }
|
||||||
$io-error ;
|
$io-error ;
|
||||||
|
|
||||||
HELP: stream-read-until
|
HELP: stream-read-until
|
||||||
|
|
|
@ -8,20 +8,17 @@ IN: io.tests
|
||||||
"foo" "io.tests" lookup
|
"foo" "io.tests" lookup
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
: <resource-reader> ( resource -- stream )
|
|
||||||
resource-path latin1 <file-reader> ;
|
|
||||||
|
|
||||||
[
|
[
|
||||||
"This is a line.\rThis is another line.\r"
|
"This is a line.\rThis is another line.\r"
|
||||||
] [
|
] [
|
||||||
"core/io/test/mac-os-eol.txt" <resource-reader>
|
"resource:core/io/test/mac-os-eol.txt" latin1 <file-reader>
|
||||||
[ 500 read ] with-input-stream
|
[ 500 read ] with-input-stream
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[
|
[
|
||||||
255
|
255
|
||||||
] [
|
] [
|
||||||
"core/io/test/binary.txt" <resource-reader>
|
"resource:core/io/test/binary.txt" latin1 <file-reader>
|
||||||
[ read1 ] with-input-stream >fixnum
|
[ read1 ] with-input-stream >fixnum
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
@ -36,7 +33,8 @@ IN: io.tests
|
||||||
}
|
}
|
||||||
] [
|
] [
|
||||||
[
|
[
|
||||||
"core/io/test/separator-test.txt" <resource-reader> [
|
"resource:core/io/test/separator-test.txt"
|
||||||
|
latin1 <file-reader> [
|
||||||
"J" read-until 2array ,
|
"J" read-until 2array ,
|
||||||
"i" read-until 2array ,
|
"i" read-until 2array ,
|
||||||
"X" read-until 2array ,
|
"X" read-until 2array ,
|
||||||
|
|
|
@ -4,7 +4,7 @@ USING: hashtables generic kernel math namespaces sequences
|
||||||
continuations assocs io.styles ;
|
continuations assocs io.styles ;
|
||||||
IN: io
|
IN: io
|
||||||
|
|
||||||
GENERIC: stream-readln ( stream -- str )
|
GENERIC: stream-readln ( stream -- str/f )
|
||||||
GENERIC: stream-read1 ( stream -- ch/f )
|
GENERIC: stream-read1 ( stream -- ch/f )
|
||||||
GENERIC: stream-read ( n stream -- str/f )
|
GENERIC: stream-read ( n stream -- str/f )
|
||||||
GENERIC: stream-read-until ( seps stream -- str/f sep/f )
|
GENERIC: stream-read-until ( seps stream -- str/f sep/f )
|
||||||
|
|
|
@ -45,6 +45,8 @@ M: object stream-read-quot
|
||||||
|
|
||||||
SYMBOL: error-hook
|
SYMBOL: error-hook
|
||||||
|
|
||||||
|
[ print-error-and-restarts ] error-hook set-global
|
||||||
|
|
||||||
: listen ( -- )
|
: listen ( -- )
|
||||||
listener-hook get call prompt.
|
listener-hook get call prompt.
|
||||||
[ read-quot [ [ error-hook get call ] recover ] [ bye ] if* ]
|
[ read-quot [ [ error-hook get call ] recover ] [ bye ] if* ]
|
||||||
|
|
|
@ -40,10 +40,6 @@ HELP: instances
|
||||||
HELP: gc ( -- )
|
HELP: gc ( -- )
|
||||||
{ $description "Performs a full garbage collection." } ;
|
{ $description "Performs a full garbage collection." } ;
|
||||||
|
|
||||||
HELP: gc-time ( -- n )
|
|
||||||
{ $values { "n" "a timestamp in milliseconds" } }
|
|
||||||
{ $description "Outputs the total time spent in garbage collection during this Factor session." } ;
|
|
||||||
|
|
||||||
HELP: data-room ( -- cards generations )
|
HELP: data-room ( -- cards generations )
|
||||||
{ $values { "cards" "number of bytes reserved for card marking" } { "generations" "array of free/total bytes pairs" } }
|
{ $values { "cards" "number of bytes reserved for card marking" } { "generations" "array of free/total bytes pairs" } }
|
||||||
{ $description "Queries the runtime for memory usage information." } ;
|
{ $description "Queries the runtime for memory usage information." } ;
|
||||||
|
|
|
@ -114,7 +114,7 @@ unit-test
|
||||||
[ parse-fresh drop ] with-compilation-unit
|
[ parse-fresh drop ] with-compilation-unit
|
||||||
[
|
[
|
||||||
"prettyprint.tests" lookup see
|
"prettyprint.tests" lookup see
|
||||||
] with-string-writer "\n" split 1 head*
|
] with-string-writer "\n" split but-last
|
||||||
] keep =
|
] keep =
|
||||||
] with-scope ;
|
] with-scope ;
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ SYMBOL: pprinter-stack
|
||||||
SYMBOL: pprinter-in
|
SYMBOL: pprinter-in
|
||||||
SYMBOL: pprinter-use
|
SYMBOL: pprinter-use
|
||||||
|
|
||||||
TUPLE: pprinter last-newline line-count end-printing indent ;
|
TUPLE: pprinter last-newline line-count indent ;
|
||||||
|
|
||||||
: <pprinter> ( -- pprinter ) 0 1 f 0 pprinter boa ;
|
: <pprinter> ( -- pprinter ) 0 1 0 pprinter boa ;
|
||||||
|
|
||||||
: record-vocab ( word -- )
|
: record-vocab ( word -- )
|
||||||
word-vocabulary [ dup pprinter-use get set-at ] when* ;
|
word-vocabulary [ dup pprinter-use get set-at ] when* ;
|
||||||
|
@ -34,7 +34,7 @@ TUPLE: pprinter last-newline line-count end-printing indent ;
|
||||||
] [
|
] [
|
||||||
pprinter get (>>last-newline)
|
pprinter get (>>last-newline)
|
||||||
line-limit? [
|
line-limit? [
|
||||||
"..." write pprinter get end-printing>> continue
|
"..." write pprinter get return
|
||||||
] when
|
] when
|
||||||
pprinter get [ 1+ ] change-line-count drop
|
pprinter get [ 1+ ] change-line-count drop
|
||||||
nl do-indent
|
nl do-indent
|
||||||
|
@ -275,16 +275,15 @@ M: colon unindent-first-line? drop t ;
|
||||||
[
|
[
|
||||||
dup style>> [
|
dup style>> [
|
||||||
[
|
[
|
||||||
>r pprinter get (>>end-printing) r>
|
|
||||||
short-section
|
short-section
|
||||||
] curry callcc0
|
] curry with-return
|
||||||
] with-nesting
|
] with-nesting
|
||||||
] if-nonempty
|
] if-nonempty
|
||||||
] with-variable ;
|
] with-variable ;
|
||||||
|
|
||||||
! Long section layout algorithm
|
! Long section layout algorithm
|
||||||
: chop-break ( seq -- seq )
|
: chop-break ( seq -- seq )
|
||||||
dup peek line-break? [ 1 head-slice* chop-break ] when ;
|
dup peek line-break? [ but-last-slice chop-break ] when ;
|
||||||
|
|
||||||
SYMBOL: prev
|
SYMBOL: prev
|
||||||
SYMBOL: next
|
SYMBOL: next
|
||||||
|
|
|
@ -92,9 +92,11 @@ ARTICLE: "sequences-slices" "Subsequences and slices"
|
||||||
{ $subsection subseq }
|
{ $subsection subseq }
|
||||||
{ $subsection head }
|
{ $subsection head }
|
||||||
{ $subsection tail }
|
{ $subsection tail }
|
||||||
{ $subsection rest }
|
|
||||||
{ $subsection head* }
|
{ $subsection head* }
|
||||||
{ $subsection tail* }
|
{ $subsection tail* }
|
||||||
|
"Removing the first or last element:"
|
||||||
|
{ $subsection rest }
|
||||||
|
{ $subsection but-last }
|
||||||
"Taking a sequence apart into a head and a tail:"
|
"Taking a sequence apart into a head and a tail:"
|
||||||
{ $subsection unclip }
|
{ $subsection unclip }
|
||||||
{ $subsection cut }
|
{ $subsection cut }
|
||||||
|
@ -106,6 +108,7 @@ ARTICLE: "sequences-slices" "Subsequences and slices"
|
||||||
{ $subsection <slice> }
|
{ $subsection <slice> }
|
||||||
{ $subsection head-slice }
|
{ $subsection head-slice }
|
||||||
{ $subsection tail-slice }
|
{ $subsection tail-slice }
|
||||||
|
{ $subsection but-last-slice }
|
||||||
{ $subsection rest-slice }
|
{ $subsection rest-slice }
|
||||||
{ $subsection head-slice* }
|
{ $subsection head-slice* }
|
||||||
{ $subsection tail-slice* }
|
{ $subsection tail-slice* }
|
||||||
|
@ -836,11 +839,16 @@ HELP: tail-slice
|
||||||
{ $description "Outputs a virtual sequence sharing storage with all elements from the " { $snippet "n" } "th index until the end of the input sequence." }
|
{ $description "Outputs a virtual sequence sharing storage with all elements from the " { $snippet "n" } "th index until the end of the input sequence." }
|
||||||
{ $errors "Throws an error if the index is out of bounds." } ;
|
{ $errors "Throws an error if the index is out of bounds." } ;
|
||||||
|
|
||||||
|
HELP: but-last-slice
|
||||||
|
{ $values { "seq" sequence } { "slice" "a slice" } }
|
||||||
|
{ $description "Outputs a virtual sequence sharing storage with all but the last element of the input sequence." }
|
||||||
|
{ $errors "Throws an error on an empty sequence." } ;
|
||||||
|
|
||||||
HELP: rest-slice
|
HELP: rest-slice
|
||||||
{ $values { "seq" sequence } { "slice" "a slice" } }
|
{ $values { "seq" sequence } { "slice" "a slice" } }
|
||||||
{ $description "Outputs a virtual sequence sharing storage with all elements from the 1st index until the end of the input sequence." }
|
{ $description "Outputs a virtual sequence sharing storage with all elements from the 1st index until the end of the input sequence." }
|
||||||
{ $notes "Equivalent to " { $snippet "1 tail" } }
|
{ $notes "Equivalent to " { $snippet "1 tail" } }
|
||||||
{ $errors "Throws an error if the index is out of bounds." } ;
|
{ $errors "Throws an error on an empty sequence." } ;
|
||||||
|
|
||||||
HELP: head-slice*
|
HELP: head-slice*
|
||||||
{ $values { "seq" sequence } { "n" "a non-negative integer" } { "slice" "a slice" } }
|
{ $values { "seq" sequence } { "n" "a non-negative integer" } { "slice" "a slice" } }
|
||||||
|
@ -862,6 +870,11 @@ HELP: tail
|
||||||
{ $description "Outputs a new sequence consisting of the input sequence with the first n items removed." }
|
{ $description "Outputs a new sequence consisting of the input sequence with the first n items removed." }
|
||||||
{ $errors "Throws an error if the index is out of bounds." } ;
|
{ $errors "Throws an error if the index is out of bounds." } ;
|
||||||
|
|
||||||
|
HELP: but-last
|
||||||
|
{ $values { "seq" sequence } { "headseq" "a new sequence" } }
|
||||||
|
{ $description "Outputs a new sequence consisting of the input sequence with the last item removed." }
|
||||||
|
{ $errors "Throws an error on an empty sequence." } ;
|
||||||
|
|
||||||
HELP: rest
|
HELP: rest
|
||||||
{ $values { "seq" sequence } { "tailseq" "a new sequence" } }
|
{ $values { "seq" sequence } { "tailseq" "a new sequence" } }
|
||||||
{ $description "Outputs a new sequence consisting of the input sequence with the first item removed." }
|
{ $description "Outputs a new sequence consisting of the input sequence with the first item removed." }
|
||||||
|
|
|
@ -216,6 +216,8 @@ M: slice length dup slice-to swap slice-from - ;
|
||||||
|
|
||||||
: tail-slice* ( seq n -- slice ) from-end tail-slice ;
|
: tail-slice* ( seq n -- slice ) from-end tail-slice ;
|
||||||
|
|
||||||
|
: but-last-slice ( seq -- slice ) 1 head-slice* ;
|
||||||
|
|
||||||
INSTANCE: slice virtual-sequence
|
INSTANCE: slice virtual-sequence
|
||||||
|
|
||||||
! One element repeated many times
|
! One element repeated many times
|
||||||
|
@ -263,6 +265,8 @@ PRIVATE>
|
||||||
|
|
||||||
: tail* ( seq n -- tailseq ) from-end tail ;
|
: tail* ( seq n -- tailseq ) from-end tail ;
|
||||||
|
|
||||||
|
: but-last ( seq -- headseq ) 1 head* ;
|
||||||
|
|
||||||
: copy ( src i dst -- )
|
: copy ( src i dst -- )
|
||||||
pick length >r 3dup check-copy spin 0 r>
|
pick length >r 3dup check-copy spin 0 r>
|
||||||
(copy) drop ; inline
|
(copy) drop ; inline
|
||||||
|
@ -671,13 +675,13 @@ PRIVATE>
|
||||||
[ rest ] [ first ] bi ;
|
[ rest ] [ first ] bi ;
|
||||||
|
|
||||||
: unclip-last ( seq -- butfirst last )
|
: unclip-last ( seq -- butfirst last )
|
||||||
[ 1 head* ] [ peek ] bi ;
|
[ but-last ] [ peek ] bi ;
|
||||||
|
|
||||||
: unclip-slice ( seq -- rest first )
|
: unclip-slice ( seq -- rest first )
|
||||||
[ rest-slice ] [ first ] bi ;
|
[ rest-slice ] [ first ] bi ;
|
||||||
|
|
||||||
: unclip-last-slice ( seq -- butfirst last )
|
: unclip-last-slice ( seq -- butfirst last )
|
||||||
[ 1 head-slice* ] [ peek ] bi ;
|
[ but-last-slice ] [ peek ] bi ;
|
||||||
|
|
||||||
: <flat-slice> ( seq -- slice )
|
: <flat-slice> ( seq -- slice )
|
||||||
dup slice? [ { } like ] when 0 over length rot <slice> ;
|
dup slice? [ { } like ] when 0 over length rot <slice> ;
|
||||||
|
|
|
@ -104,7 +104,7 @@ M: sliced-clumps nth group@ <slice> ;
|
||||||
1array
|
1array
|
||||||
] [
|
] [
|
||||||
"\n" split [
|
"\n" split [
|
||||||
1 head-slice* [
|
but-last-slice [
|
||||||
"\r" ?tail drop "\r" split
|
"\r" ?tail drop "\r" split
|
||||||
] map
|
] map
|
||||||
] keep peek "\r" split suffix concat
|
] keep peek "\r" split suffix concat
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
USING: namespaces io tools.test threads kernel
|
USING: namespaces io tools.test threads kernel
|
||||||
concurrency.combinators math ;
|
concurrency.combinators concurrency.promises locals math
|
||||||
|
words ;
|
||||||
IN: threads.tests
|
IN: threads.tests
|
||||||
|
|
||||||
3 "x" set
|
3 "x" set
|
||||||
|
@ -27,3 +28,16 @@ yield
|
||||||
"i" tget
|
"i" tget
|
||||||
] parallel-map
|
] parallel-map
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
[ [ 3 throw ] "A" suspend ] [ 3 = ] must-fail-with
|
||||||
|
|
||||||
|
:: spawn-namespace-test ( -- )
|
||||||
|
[let | p [ <promise> ] g [ gensym ] |
|
||||||
|
[
|
||||||
|
g "x" set
|
||||||
|
[ "x" get p fulfill ] "B" spawn drop
|
||||||
|
] with-scope
|
||||||
|
p ?promise g eq?
|
||||||
|
] ;
|
||||||
|
|
||||||
|
[ t ] [ spawn-namespace-test ] unit-test
|
||||||
|
|
|
@ -12,7 +12,7 @@ SYMBOL: initial-thread
|
||||||
TUPLE: thread
|
TUPLE: thread
|
||||||
name quot exit-handler
|
name quot exit-handler
|
||||||
id
|
id
|
||||||
continuation state
|
continuation state runnable
|
||||||
mailbox variables sleep-entry ;
|
mailbox variables sleep-entry ;
|
||||||
|
|
||||||
: self ( -- thread ) 40 getenv ; inline
|
: self ( -- thread ) 40 getenv ; inline
|
||||||
|
@ -91,6 +91,8 @@ PRIVATE>
|
||||||
[ sleep-queue heap-peek nip millis [-] ]
|
[ sleep-queue heap-peek nip millis [-] ]
|
||||||
} cond ;
|
} cond ;
|
||||||
|
|
||||||
|
DEFER: stop
|
||||||
|
|
||||||
<PRIVATE
|
<PRIVATE
|
||||||
|
|
||||||
: schedule-sleep ( thread dt -- )
|
: schedule-sleep ( thread dt -- )
|
||||||
|
@ -111,36 +113,57 @@ PRIVATE>
|
||||||
[ ] while
|
[ ] while
|
||||||
drop ;
|
drop ;
|
||||||
|
|
||||||
|
: start ( namestack thread -- )
|
||||||
|
[
|
||||||
|
set-self
|
||||||
|
set-namestack
|
||||||
|
V{ } set-catchstack
|
||||||
|
{ } set-retainstack
|
||||||
|
{ } set-datastack
|
||||||
|
self quot>> [ call stop ] call-clear
|
||||||
|
] 2 (throw) ;
|
||||||
|
|
||||||
|
DEFER: next
|
||||||
|
|
||||||
|
: no-runnable-threads ( -- * )
|
||||||
|
! We should never be in a state where the only threads
|
||||||
|
! are sleeping; the I/O wait thread is always runnable.
|
||||||
|
! However, if it dies, we handle this case
|
||||||
|
! semi-gracefully.
|
||||||
|
!
|
||||||
|
! And if sleep-time outputs f, there are no sleeping
|
||||||
|
! threads either... so WTF.
|
||||||
|
sleep-time [ die 0 ] unless* (sleep) next ;
|
||||||
|
|
||||||
|
: (next) ( arg thread -- * )
|
||||||
|
f >>state
|
||||||
|
dup set-self
|
||||||
|
dup runnable>> [
|
||||||
|
continuation>> box> continue-with
|
||||||
|
] [
|
||||||
|
t >>runnable start
|
||||||
|
] if ;
|
||||||
|
|
||||||
: next ( -- * )
|
: next ( -- * )
|
||||||
expire-sleep-loop
|
expire-sleep-loop
|
||||||
run-queue dup dlist-empty? [
|
run-queue dup dlist-empty? [
|
||||||
! We should never be in a state where the only threads
|
drop no-runnable-threads
|
||||||
! are sleeping; the I/O wait thread is always runnable.
|
|
||||||
! However, if it dies, we handle this case
|
|
||||||
! semi-gracefully.
|
|
||||||
!
|
|
||||||
! And if sleep-time outputs f, there are no sleeping
|
|
||||||
! threads either... so WTF.
|
|
||||||
drop sleep-time [ die 0 ] unless* (sleep) next
|
|
||||||
] [
|
] [
|
||||||
pop-back
|
pop-back dup array? [ first2 ] [ f swap ] if (next)
|
||||||
dup array? [ first2 ] [ f swap ] if dup set-self
|
|
||||||
f >>state
|
|
||||||
continuation>> box>
|
|
||||||
continue-with
|
|
||||||
] if ;
|
] if ;
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
: stop ( -- )
|
: stop ( -- )
|
||||||
self dup exit-handler>> call
|
self [ exit-handler>> call ] [ unregister-thread ] bi next ;
|
||||||
unregister-thread next ;
|
|
||||||
|
|
||||||
: suspend ( quot state -- obj )
|
: suspend ( quot state -- obj )
|
||||||
[
|
[
|
||||||
self continuation>> >box
|
>r
|
||||||
self (>>state)
|
>r self swap call
|
||||||
self swap call next
|
r> self (>>state)
|
||||||
|
r> self continuation>> >box
|
||||||
|
next
|
||||||
] callcc1 2nip ; inline
|
] callcc1 2nip ; inline
|
||||||
|
|
||||||
: yield ( -- ) [ resume ] f suspend drop ;
|
: yield ( -- ) [ resume ] f suspend drop ;
|
||||||
|
@ -166,16 +189,7 @@ M: real sleep
|
||||||
] when drop ;
|
] when drop ;
|
||||||
|
|
||||||
: (spawn) ( thread -- )
|
: (spawn) ( thread -- )
|
||||||
[
|
[ register-thread ] [ namestack swap resume-with ] bi ;
|
||||||
resume-now [
|
|
||||||
dup set-self
|
|
||||||
dup register-thread
|
|
||||||
V{ } set-catchstack
|
|
||||||
{ } set-retainstack
|
|
||||||
>r { } set-datastack r>
|
|
||||||
quot>> [ call stop ] call-clear
|
|
||||||
] 1 (throw)
|
|
||||||
] "spawn" suspend 2drop ;
|
|
||||||
|
|
||||||
: spawn ( quot name -- thread )
|
: spawn ( quot name -- thread )
|
||||||
<thread> [ (spawn) ] keep ;
|
<thread> [ (spawn) ] keep ;
|
||||||
|
@ -184,8 +198,8 @@ M: real sleep
|
||||||
>r [ [ ] [ ] while ] curry r> spawn ;
|
>r [ [ ] [ ] while ] curry r> spawn ;
|
||||||
|
|
||||||
: in-thread ( quot -- )
|
: in-thread ( quot -- )
|
||||||
>r datastack namestack r>
|
>r datastack r>
|
||||||
[ >r set-namestack set-datastack r> call ] 3curry
|
[ >r set-datastack r> call ] 2curry
|
||||||
"Thread" spawn drop ;
|
"Thread" spawn drop ;
|
||||||
|
|
||||||
GENERIC: error-in-thread ( error thread -- )
|
GENERIC: error-in-thread ( error thread -- )
|
||||||
|
@ -199,6 +213,7 @@ GENERIC: error-in-thread ( error thread -- )
|
||||||
initial-thread global
|
initial-thread global
|
||||||
[ drop f "Initial" <thread> ] cache
|
[ drop f "Initial" <thread> ] cache
|
||||||
<box> >>continuation
|
<box> >>continuation
|
||||||
|
t >>runnable
|
||||||
f >>state
|
f >>state
|
||||||
dup register-thread
|
dup register-thread
|
||||||
set-self ;
|
set-self ;
|
||||||
|
|
|
@ -6,7 +6,7 @@ continuations debugger ;
|
||||||
IN: benchmark
|
IN: benchmark
|
||||||
|
|
||||||
: run-benchmark ( vocab -- result )
|
: run-benchmark ( vocab -- result )
|
||||||
[ [ require ] [ [ run ] benchmark nip ] bi ] curry
|
[ [ require ] [ [ run ] benchmark ] bi ] curry
|
||||||
[ error. f ] recover ;
|
[ error. f ] recover ;
|
||||||
|
|
||||||
: run-benchmarks ( -- assoc )
|
: run-benchmarks ( -- assoc )
|
||||||
|
|
|
@ -53,3 +53,5 @@ M: f item-check drop 0 ;
|
||||||
|
|
||||||
: binary-trees-main ( -- )
|
: binary-trees-main ( -- )
|
||||||
16 binary-trees ;
|
16 binary-trees ;
|
||||||
|
|
||||||
|
MAIN: binary-trees-main
|
||||||
|
|
|
@ -81,7 +81,7 @@ HINTS: random fixnum ;
|
||||||
write-description
|
write-description
|
||||||
[let | k! [ 0 ] alu [ ] |
|
[let | k! [ 0 ] alu [ ] |
|
||||||
[| len | k len alu make-repeat-fasta k! ] split-lines
|
[| len | k len alu make-repeat-fasta k! ] split-lines
|
||||||
] with-locals ; inline
|
] ; inline
|
||||||
|
|
||||||
: fasta ( n out -- )
|
: fasta ( n out -- )
|
||||||
homo-sapiens make-cumulative
|
homo-sapiens make-cumulative
|
||||||
|
@ -103,7 +103,7 @@ HINTS: random fixnum ;
|
||||||
drop
|
drop
|
||||||
] with-file-writer
|
] with-file-writer
|
||||||
|
|
||||||
] with-locals ;
|
] ;
|
||||||
|
|
||||||
: run-fasta 2500000 reverse-complement-in fasta ;
|
: run-fasta 2500000 reverse-complement-in fasta ;
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ IN: benchmark.knucleotide
|
||||||
drop ;
|
drop ;
|
||||||
|
|
||||||
: knucleotide ( -- )
|
: knucleotide ( -- )
|
||||||
"extra/benchmark/knucleotide/knucleotide-input.txt" resource-path
|
"resource:extra/benchmark/knucleotide/knucleotide-input.txt"
|
||||||
ascii [ read-input ] with-file-reader
|
ascii [ read-input ] with-file-reader
|
||||||
process-input ;
|
process-input ;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@ prettyprint words hints ;
|
||||||
IN: benchmark.partial-sums
|
IN: benchmark.partial-sums
|
||||||
|
|
||||||
: summing ( n quot -- y )
|
: summing ( n quot -- y )
|
||||||
[ + ] compose 0.0 -rot 1 -rot (each-integer) ; inline
|
[ >float ] swap [ + ] 3compose
|
||||||
|
0.0 -rot 1 -rot (each-integer) ; inline
|
||||||
|
|
||||||
: 2/3^k ( n -- y ) [ 2.0 3.0 / swap 1- ^ ] summing ;
|
: 2/3^k ( n -- y ) [ 2.0 3.0 / swap 1- ^ ] summing ;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ SYMBOL: counter
|
||||||
: server-addr "127.0.0.1" 7777 <inet4> ;
|
: server-addr "127.0.0.1" 7777 <inet4> ;
|
||||||
|
|
||||||
: server-loop ( server -- )
|
: server-loop ( server -- )
|
||||||
dup accept [
|
dup accept drop [
|
||||||
[
|
[
|
||||||
read1 CHAR: x = [
|
read1 CHAR: x = [
|
||||||
"server" get dispose
|
"server" get dispose
|
||||||
|
|
|
@ -3,6 +3,7 @@ USING: kernel namespaces assocs
|
||||||
io.files io.encodings.utf8 prettyprint
|
io.files io.encodings.utf8 prettyprint
|
||||||
help.lint
|
help.lint
|
||||||
benchmark
|
benchmark
|
||||||
|
tools.time
|
||||||
bootstrap.stage2
|
bootstrap.stage2
|
||||||
tools.test tools.vocabs
|
tools.test tools.vocabs
|
||||||
builder.util ;
|
builder.util ;
|
||||||
|
@ -26,8 +27,8 @@ IN: builder.test
|
||||||
|
|
||||||
: do-all ( -- )
|
: do-all ( -- )
|
||||||
bootstrap-time get "../boot-time" utf8 [ . ] with-file-writer
|
bootstrap-time get "../boot-time" utf8 [ . ] with-file-writer
|
||||||
[ do-load ] runtime "../load-time" utf8 [ . ] with-file-writer
|
[ do-load ] benchmark "../load-time" utf8 [ . ] with-file-writer
|
||||||
[ do-tests ] runtime "../test-time" utf8 [ . ] with-file-writer
|
[ do-tests ] benchmark "../test-time" utf8 [ . ] with-file-writer
|
||||||
do-help-lint
|
do-help-lint
|
||||||
do-benchmarks ;
|
do-benchmarks ;
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,6 @@ IN: builder.util
|
||||||
|
|
||||||
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
: runtime ( quot -- time ) benchmark nip ;
|
|
||||||
|
|
||||||
: minutes>ms ( min -- ms ) 60 * 1000 * ;
|
: minutes>ms ( min -- ms ) 60 * 1000 * ;
|
||||||
|
|
||||||
: file>string ( file -- string ) utf8 file-contents ;
|
: file>string ( file -- string ) utf8 file-contents ;
|
||||||
|
|
|
@ -21,7 +21,7 @@ ERROR: cairo-error string ;
|
||||||
{ CAIRO_STATUS_FILE_NOT_FOUND [ "Cairo: file not found" cairo-error ] }
|
{ CAIRO_STATUS_FILE_NOT_FOUND [ "Cairo: file not found" cairo-error ] }
|
||||||
{ CAIRO_STATUS_READ_ERROR [ "Cairo: read error" cairo-error ] }
|
{ CAIRO_STATUS_READ_ERROR [ "Cairo: read error" cairo-error ] }
|
||||||
[ drop ]
|
[ drop ]
|
||||||
} cond ;
|
} case ;
|
||||||
|
|
||||||
: <png> ( path -- png )
|
: <png> ( path -- png )
|
||||||
normalize-path
|
normalize-path
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
USING: help.markup help.syntax ;
|
||||||
|
IN: checksums.adler-32
|
||||||
|
|
||||||
|
HELP: adler-32
|
||||||
|
{ $description "Adler-32 checksum algorithm." } ;
|
||||||
|
|
||||||
|
ARTICLE: "checksums.adler-32" "Adler-32 checksum"
|
||||||
|
"The Adler-32 checksum algorithm implements simple and fast checksum. It is used in zlib and rsync."
|
||||||
|
{ $subsection adler-32 } ;
|
||||||
|
|
||||||
|
ABOUT: "checksums.adler-32"
|
|
@ -0,0 +1,5 @@
|
||||||
|
USING: checksums.adler-32 checksums strings tools.test ;
|
||||||
|
IN: checksums.adler-32.tests
|
||||||
|
|
||||||
|
[ 300286872 ] [ "Wikipedia" adler-32 checksum-bytes ] unit-test
|
||||||
|
[ 2679885283 ] [ 10000 CHAR: a <string> adler-32 checksum-bytes ] unit-test
|
|
@ -0,0 +1,15 @@
|
||||||
|
! Copyright (C) 2008 Doug Coleman.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: checksums classes.singleton kernel math math.ranges
|
||||||
|
math.vectors sequences ;
|
||||||
|
IN: checksums.adler-32
|
||||||
|
|
||||||
|
SINGLETON: adler-32
|
||||||
|
|
||||||
|
: adler-32-modulus 65521 ; inline
|
||||||
|
|
||||||
|
M: adler-32 checksum-bytes ( bytes checksum -- value )
|
||||||
|
drop
|
||||||
|
[ sum 1+ ]
|
||||||
|
[ [ dup length [1,b] <reversed> v. ] [ length ] bi + ] bi
|
||||||
|
[ adler-32-modulus mod ] bi@ 16 shift bitor ;
|
|
@ -0,0 +1 @@
|
||||||
|
Doug Coleman
|
|
@ -1,8 +1,8 @@
|
||||||
USING: checksums ;
|
USING: checksums kernel ;
|
||||||
IN: checksums.null
|
IN: checksums.null
|
||||||
|
|
||||||
SINGLETON: null
|
SINGLETON: null
|
||||||
|
|
||||||
INSTANCE: null checksum
|
INSTANCE: null checksum
|
||||||
|
|
||||||
M: null checksum-bytes ;
|
M: null checksum-bytes drop ;
|
||||||
|
|
|
@ -26,7 +26,7 @@ HELP: with-cocoa
|
||||||
{ $values { "quot" quotation } }
|
{ $values { "quot" quotation } }
|
||||||
{ $description "Sets up an autorelease pool, initializes the " { $snippet "NSApplication" } " singleton, and calls the quotation." } ;
|
{ $description "Sets up an autorelease pool, initializes the " { $snippet "NSApplication" } " singleton, and calls the quotation." } ;
|
||||||
|
|
||||||
HELP: do-events
|
HELP: do-event
|
||||||
{ $values { "app" "an " { $snippet "NSApplication" } } }
|
{ $values { "app" "an " { $snippet "NSApplication" } } }
|
||||||
{ $description "Processes any pending events in the queue. Does not block." } ;
|
{ $description "Processes any pending events in the queue. Does not block." } ;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ ARTICLE: "cocoa-application-utils" "Cocoa application utilities"
|
||||||
{ $subsection NSApp }
|
{ $subsection NSApp }
|
||||||
{ $subsection with-autorelease-pool }
|
{ $subsection with-autorelease-pool }
|
||||||
{ $subsection with-cocoa }
|
{ $subsection with-cocoa }
|
||||||
{ $subsection do-events }
|
{ $subsection do-event }
|
||||||
{ $subsection add-observer }
|
{ $subsection add-observer }
|
||||||
{ $subsection remove-observer }
|
{ $subsection remove-observer }
|
||||||
{ $subsection install-delegate } ;
|
{ $subsection install-delegate } ;
|
||||||
|
|
|
@ -29,9 +29,6 @@ IN: cocoa.application
|
||||||
: do-event ( app -- ? )
|
: do-event ( app -- ? )
|
||||||
dup next-event [ -> sendEvent: t ] [ drop f ] if* ;
|
dup next-event [ -> sendEvent: t ] [ drop f ] if* ;
|
||||||
|
|
||||||
: do-events ( app -- )
|
|
||||||
dup do-event [ do-events ] [ drop ] if ;
|
|
||||||
|
|
||||||
: add-observer ( observer selector name object -- )
|
: add-observer ( observer selector name object -- )
|
||||||
>r >r >r >r NSNotificationCenter -> defaultCenter
|
>r >r >r >r NSNotificationCenter -> defaultCenter
|
||||||
r> r> sel_registerName
|
r> r> sel_registerName
|
||||||
|
|
|
@ -169,3 +169,8 @@ MACRO: multikeep ( word out-indexes -- ... )
|
||||||
: generate ( generator predicate -- obj )
|
: generate ( generator predicate -- obj )
|
||||||
[ dup ] swap [ dup [ nip ] unless not ] 3compose
|
[ dup ] swap [ dup [ nip ] unless not ] 3compose
|
||||||
swap [ ] do-while ;
|
swap [ ] do-while ;
|
||||||
|
|
||||||
|
MACRO: predicates ( seq -- quot/f )
|
||||||
|
dup [ 1quotation [ drop ] prepend ] map
|
||||||
|
>r [ [ dup ] prepend ] map r> zip [ drop f ] suffix
|
||||||
|
[ cond ] curry ;
|
||||||
|
|
|
@ -6,11 +6,21 @@ HELP: parallel-map
|
||||||
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to every element of " { $snippet "seq" } ", collecting the results at the end." }
|
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to every element of " { $snippet "seq" } ", collecting the results at the end." }
|
||||||
{ $errors "Throws an error if one of the iterations throws an error." } ;
|
{ $errors "Throws an error if one of the iterations throws an error." } ;
|
||||||
|
|
||||||
|
HELP: 2parallel-map
|
||||||
|
{ $values { "seq1" sequence } { "seq2" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- newelt )" } } { "newseq" sequence } }
|
||||||
|
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to pairwise elements of " { $snippet "seq1" } " and " { $snippet "seq2" } ", collecting the results at the end." }
|
||||||
|
{ $errors "Throws an error if one of the iterations throws an error." } ;
|
||||||
|
|
||||||
HELP: parallel-each
|
HELP: parallel-each
|
||||||
{ $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- )" } } }
|
{ $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- )" } } }
|
||||||
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to every element of " { $snippet "seq" } ", blocking until all quotations complete." }
|
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to every element of " { $snippet "seq" } ", blocking until all quotations complete." }
|
||||||
{ $errors "Throws an error if one of the iterations throws an error." } ;
|
{ $errors "Throws an error if one of the iterations throws an error." } ;
|
||||||
|
|
||||||
|
HELP: 2parallel-each
|
||||||
|
{ $values { "seq1" sequence } { "seq2" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- )" } } }
|
||||||
|
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to pairwise elements of " { $snippet "seq1" } " and " { $snippet "seq2" } ", blocking until all quotations complete." }
|
||||||
|
{ $errors "Throws an error if one of the iterations throws an error." } ;
|
||||||
|
|
||||||
HELP: parallel-filter
|
HELP: parallel-filter
|
||||||
{ $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- ? )" } } { "newseq" sequence } }
|
{ $values { "seq" sequence } { "quot" "a quotation with stack effect " { $snippet "( elt -- ? )" } } { "newseq" sequence } }
|
||||||
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to every element of " { $snippet "seq" } ", collecting the elements for which the quotation yielded a true value." }
|
{ $description "Spawns a new thread for applying " { $snippet "quot" } " to every element of " { $snippet "seq" } ", collecting the elements for which the quotation yielded a true value." }
|
||||||
|
@ -19,7 +29,9 @@ HELP: parallel-filter
|
||||||
ARTICLE: "concurrency.combinators" "Concurrent combinators"
|
ARTICLE: "concurrency.combinators" "Concurrent combinators"
|
||||||
"The " { $vocab-link "concurrency.combinators" } " vocabulary provides concurrent variants of " { $link each } ", " { $link map } " and " { $link filter } ":"
|
"The " { $vocab-link "concurrency.combinators" } " vocabulary provides concurrent variants of " { $link each } ", " { $link map } " and " { $link filter } ":"
|
||||||
{ $subsection parallel-each }
|
{ $subsection parallel-each }
|
||||||
|
{ $subsection 2parallel-each }
|
||||||
{ $subsection parallel-map }
|
{ $subsection parallel-map }
|
||||||
|
{ $subsection 2parallel-map }
|
||||||
{ $subsection parallel-filter } ;
|
{ $subsection parallel-filter } ;
|
||||||
|
|
||||||
ABOUT: "concurrency.combinators"
|
ABOUT: "concurrency.combinators"
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
IN: concurrency.combinators.tests
|
IN: concurrency.combinators.tests
|
||||||
USING: concurrency.combinators tools.test random kernel math
|
USING: concurrency.combinators tools.test random kernel math
|
||||||
concurrency.mailboxes threads sequences accessors ;
|
concurrency.mailboxes threads sequences accessors arrays ;
|
||||||
|
|
||||||
[ [ drop ] parallel-each ] must-infer
|
[ [ drop ] parallel-each ] must-infer
|
||||||
|
{ 2 0 } [ [ 2drop ] 2parallel-each ] must-infer-as
|
||||||
[ [ ] parallel-map ] must-infer
|
[ [ ] parallel-map ] must-infer
|
||||||
|
{ 2 1 } [ [ 2array ] 2parallel-map ] must-infer-as
|
||||||
[ [ ] parallel-filter ] must-infer
|
[ [ ] parallel-filter ] must-infer
|
||||||
|
|
||||||
[ { 1 4 9 } ] [ { 1 2 3 } [ sq ] parallel-map ] unit-test
|
[ { 1 4 9 } ] [ { 1 2 3 } [ sq ] parallel-map ] unit-test
|
||||||
|
@ -22,3 +24,24 @@ concurrency.mailboxes threads sequences accessors ;
|
||||||
10 over [ push ] curry parallel-each
|
10 over [ push ] curry parallel-each
|
||||||
length
|
length
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
[ { 10 20 30 } ] [
|
||||||
|
{ 1 4 3 } { 10 5 10 } [ * ] 2parallel-map
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ { -9 -1 -7 } ] [
|
||||||
|
{ 1 4 3 } { 10 5 10 } [ - ] 2parallel-map
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[
|
||||||
|
{ 1 4 3 } { 1 0 1 } [ / drop ] 2parallel-each
|
||||||
|
] must-fail
|
||||||
|
|
||||||
|
[ 20 ]
|
||||||
|
[
|
||||||
|
V{ } clone
|
||||||
|
10 10 pick [ [ push ] [ push ] bi ] curry 2parallel-each
|
||||||
|
length
|
||||||
|
] unit-test
|
||||||
|
|
||||||
|
[ { f } [ "OOPS" throw ] parallel-each ] must-fail
|
||||||
|
|
|
@ -4,14 +4,27 @@ USING: concurrency.futures concurrency.count-downs sequences
|
||||||
kernel ;
|
kernel ;
|
||||||
IN: concurrency.combinators
|
IN: concurrency.combinators
|
||||||
|
|
||||||
: parallel-map ( seq quot -- newseq )
|
: (parallel-each) ( n quot -- )
|
||||||
[ curry future ] curry map dup [ ?future ] change-each ;
|
>r <count-down> r> keep await ; inline
|
||||||
inline
|
|
||||||
|
|
||||||
: parallel-each ( seq quot -- )
|
: parallel-each ( seq quot -- )
|
||||||
over length <count-down>
|
over length [
|
||||||
[ [ >r curry r> spawn-stage ] 2curry each ] keep await ;
|
[ >r curry r> spawn-stage ] 2curry each
|
||||||
inline
|
] (parallel-each) ; inline
|
||||||
|
|
||||||
|
: 2parallel-each ( seq1 seq2 quot -- )
|
||||||
|
2over min-length [
|
||||||
|
[ >r 2curry r> spawn-stage ] 2curry 2each
|
||||||
|
] (parallel-each) ; inline
|
||||||
|
|
||||||
: parallel-filter ( seq quot -- newseq )
|
: parallel-filter ( seq quot -- newseq )
|
||||||
over >r pusher >r each r> r> like ; inline
|
over >r pusher >r each r> r> like ; inline
|
||||||
|
|
||||||
|
: future-values dup [ ?future ] change-each ; inline
|
||||||
|
|
||||||
|
: parallel-map ( seq quot -- newseq )
|
||||||
|
[ curry future ] curry map future-values ;
|
||||||
|
inline
|
||||||
|
|
||||||
|
: 2parallel-map ( seq1 seq2 quot -- newseq )
|
||||||
|
[ 2curry future ] curry 2map future-values ;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: dlists kernel math concurrency.promises
|
USING: dlists kernel math concurrency.promises
|
||||||
concurrency.mailboxes ;
|
concurrency.mailboxes debugger accessors ;
|
||||||
IN: concurrency.count-downs
|
IN: concurrency.count-downs
|
||||||
|
|
||||||
! http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html
|
! http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html
|
||||||
|
@ -9,9 +9,7 @@ IN: concurrency.count-downs
|
||||||
TUPLE: count-down n promise ;
|
TUPLE: count-down n promise ;
|
||||||
|
|
||||||
: count-down-check ( count-down -- )
|
: count-down-check ( count-down -- )
|
||||||
dup count-down-n zero? [
|
dup n>> zero? [ t swap promise>> fulfill ] [ drop ] if ;
|
||||||
t swap count-down-promise fulfill
|
|
||||||
] [ drop ] if ;
|
|
||||||
|
|
||||||
: <count-down> ( n -- count-down )
|
: <count-down> ( n -- count-down )
|
||||||
dup 0 < [ "Invalid count for count down" throw ] when
|
dup 0 < [ "Invalid count for count down" throw ] when
|
||||||
|
@ -19,15 +17,12 @@ TUPLE: count-down n promise ;
|
||||||
dup count-down-check ;
|
dup count-down-check ;
|
||||||
|
|
||||||
: count-down ( count-down -- )
|
: count-down ( count-down -- )
|
||||||
dup count-down-n dup zero? [
|
dup n>> dup zero?
|
||||||
"Count down already done" throw
|
[ "Count down already done" throw ]
|
||||||
] [
|
[ 1- >>n count-down-check ] if ;
|
||||||
1- over set-count-down-n
|
|
||||||
count-down-check
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
: await-timeout ( count-down timeout -- )
|
: await-timeout ( count-down timeout -- )
|
||||||
>r count-down-promise r> ?promise-timeout drop ;
|
>r promise>> r> ?promise-timeout ?linked t assert= ;
|
||||||
|
|
||||||
: await ( count-down -- )
|
: await ( count-down -- )
|
||||||
f await-timeout ;
|
f await-timeout ;
|
||||||
|
@ -35,5 +30,4 @@ TUPLE: count-down n promise ;
|
||||||
: spawn-stage ( quot count-down -- )
|
: spawn-stage ( quot count-down -- )
|
||||||
[ [ count-down ] curry compose ] keep
|
[ [ count-down ] curry compose ] keep
|
||||||
"Count down stage"
|
"Count down stage"
|
||||||
swap count-down-promise
|
swap promise>> mailbox>> spawn-linked-to drop ;
|
||||||
promise-mailbox spawn-linked-to drop ;
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
IN: concurrency.flags.tests
|
IN: concurrency.flags.tests
|
||||||
USING: tools.test concurrency.flags kernel threads locals ;
|
USING: tools.test concurrency.flags concurrency.combinators
|
||||||
|
kernel threads locals accessors ;
|
||||||
|
|
||||||
:: flag-test-1 ( -- )
|
:: flag-test-1 ( -- )
|
||||||
[let | f [ <flag> ] |
|
[let | f [ <flag> ] |
|
||||||
[ f raise-flag ] "Flag test" spawn drop
|
[ f raise-flag ] "Flag test" spawn drop
|
||||||
f lower-flag
|
f lower-flag
|
||||||
f flag-value?
|
f value>>
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
[ f ] [ flag-test-1 ] unit-test
|
[ f ] [ flag-test-1 ] unit-test
|
||||||
|
@ -14,7 +15,7 @@ USING: tools.test concurrency.flags kernel threads locals ;
|
||||||
[let | f [ <flag> ] |
|
[let | f [ <flag> ] |
|
||||||
[ 1000 sleep f raise-flag ] "Flag test" spawn drop
|
[ 1000 sleep f raise-flag ] "Flag test" spawn drop
|
||||||
f lower-flag
|
f lower-flag
|
||||||
f flag-value?
|
f value>>
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
[ f ] [ flag-test-2 ] unit-test
|
[ f ] [ flag-test-2 ] unit-test
|
||||||
|
@ -22,7 +23,7 @@ USING: tools.test concurrency.flags kernel threads locals ;
|
||||||
:: flag-test-3 ( -- )
|
:: flag-test-3 ( -- )
|
||||||
[let | f [ <flag> ] |
|
[let | f [ <flag> ] |
|
||||||
f raise-flag
|
f raise-flag
|
||||||
f flag-value?
|
f value>>
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
[ t ] [ flag-test-3 ] unit-test
|
[ t ] [ flag-test-3 ] unit-test
|
||||||
|
@ -31,7 +32,7 @@ USING: tools.test concurrency.flags kernel threads locals ;
|
||||||
[let | f [ <flag> ] |
|
[let | f [ <flag> ] |
|
||||||
[ f raise-flag ] "Flag test" spawn drop
|
[ f raise-flag ] "Flag test" spawn drop
|
||||||
f wait-for-flag
|
f wait-for-flag
|
||||||
f flag-value?
|
f value>>
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
[ t ] [ flag-test-4 ] unit-test
|
[ t ] [ flag-test-4 ] unit-test
|
||||||
|
@ -40,7 +41,13 @@ USING: tools.test concurrency.flags kernel threads locals ;
|
||||||
[let | f [ <flag> ] |
|
[let | f [ <flag> ] |
|
||||||
[ 1000 sleep f raise-flag ] "Flag test" spawn drop
|
[ 1000 sleep f raise-flag ] "Flag test" spawn drop
|
||||||
f wait-for-flag
|
f wait-for-flag
|
||||||
f flag-value?
|
f value>>
|
||||||
] ;
|
] ;
|
||||||
|
|
||||||
[ t ] [ flag-test-5 ] unit-test
|
[ t ] [ flag-test-5 ] unit-test
|
||||||
|
|
||||||
|
[ ] [
|
||||||
|
{ 1 2 } <flag>
|
||||||
|
[ [ 1000 sleep raise-flag ] curry "Flag test" spawn drop ]
|
||||||
|
[ [ wait-for-flag drop ] curry parallel-each ] bi
|
||||||
|
] unit-test
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: boxes kernel threads ;
|
USING: dlists kernel threads concurrency.conditions accessors ;
|
||||||
IN: concurrency.flags
|
IN: concurrency.flags
|
||||||
|
|
||||||
TUPLE: flag value? thread ;
|
TUPLE: flag value threads ;
|
||||||
|
|
||||||
: <flag> ( -- flag ) f <box> flag boa ;
|
: <flag> ( -- flag ) f <dlist> flag boa ;
|
||||||
|
|
||||||
: raise-flag ( flag -- )
|
: raise-flag ( flag -- )
|
||||||
dup flag-value? [
|
dup value>> [ drop ] [ t >>value threads>> notify-all ] if ;
|
||||||
t over set-flag-value?
|
|
||||||
dup flag-thread [ resume ] if-box?
|
: wait-for-flag-timeout ( flag timeout -- )
|
||||||
] unless drop ;
|
over value>> [ 2drop ] [ >r threads>> r> "flag" wait ] if ;
|
||||||
|
|
||||||
: wait-for-flag ( flag -- )
|
: wait-for-flag ( flag -- )
|
||||||
dup flag-value? [ drop ] [
|
f wait-for-flag-timeout ;
|
||||||
[ flag-thread >box ] curry "flag" suspend drop
|
|
||||||
] if ;
|
|
||||||
|
|
||||||
: lower-flag ( flag -- )
|
: lower-flag ( flag -- )
|
||||||
dup wait-for-flag f swap set-flag-value? ;
|
[ wait-for-flag ] [ f >>value drop ] bi ;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
IN: concurrency.mailboxes
|
IN: concurrency.mailboxes
|
||||||
USING: dlists threads sequences continuations
|
USING: dlists threads sequences continuations
|
||||||
namespaces random math quotations words kernel arrays assocs
|
namespaces random math quotations words kernel arrays assocs
|
||||||
init system concurrency.conditions accessors ;
|
init system concurrency.conditions accessors debugger ;
|
||||||
|
|
||||||
TUPLE: mailbox threads data closed ;
|
TUPLE: mailbox threads data closed ;
|
||||||
|
|
||||||
|
@ -83,6 +83,9 @@ M: mailbox dispose
|
||||||
|
|
||||||
TUPLE: linked-error error thread ;
|
TUPLE: linked-error error thread ;
|
||||||
|
|
||||||
|
M: linked-error error.
|
||||||
|
[ thread>> error-in-thread. ] [ error>> error. ] bi ;
|
||||||
|
|
||||||
C: <linked-error> linked-error
|
C: <linked-error> linked-error
|
||||||
|
|
||||||
: ?linked dup linked-error? [ rethrow ] when ;
|
: ?linked dup linked-error? [ rethrow ] when ;
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
IN: contributors.tests
|
||||||
|
USING: contributors tools.test ;
|
||||||
|
|
||||||
|
\ contributors must-infer
|
||||||
|
[ ] [ contributors ] unit-test
|
|
@ -1,13 +1,13 @@
|
||||||
! Copyright (C) 2007 Slava Pestov.
|
! Copyright (C) 2007 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: io.files io.launcher io.styles io hashtables kernel
|
USING: io.files io.launcher io.styles io.encodings.ascii io
|
||||||
sequences sequences.lib assocs system sorting math.parser
|
hashtables kernel sequences sequences.lib assocs system sorting
|
||||||
sets ;
|
math.parser sets ;
|
||||||
IN: contributors
|
IN: contributors
|
||||||
|
|
||||||
: changelog ( -- authors )
|
: changelog ( -- authors )
|
||||||
image parent-directory [
|
image parent-directory [
|
||||||
"git-log --pretty=format:%an" <process-reader> lines
|
"git-log --pretty=format:%an" ascii <process-reader> lines
|
||||||
] with-directory ;
|
] with-directory ;
|
||||||
|
|
||||||
: patch-counts ( authors -- assoc )
|
: patch-counts ( authors -- assoc )
|
||||||
|
|
|
@ -10,7 +10,7 @@ IN: help.lint
|
||||||
|
|
||||||
: check-example ( element -- )
|
: check-example ( element -- )
|
||||||
rest [
|
rest [
|
||||||
1 head* "\n" join 1vector
|
but-last "\n" join 1vector
|
||||||
[
|
[
|
||||||
use [ clone ] change
|
use [ clone ] change
|
||||||
[ eval>string ] with-datastack
|
[ eval>string ] with-datastack
|
||||||
|
|
|
@ -99,7 +99,7 @@ IN: html.parser.analyzer
|
||||||
|
|
||||||
: find-between ( i/f tag/f vector -- vector )
|
: find-between ( i/f tag/f vector -- vector )
|
||||||
find-between* dup length 3 >= [
|
find-between* dup length 3 >= [
|
||||||
[ rest-slice 1 head-slice* ] keep like
|
[ rest-slice but-last-slice ] keep like
|
||||||
] when ;
|
] when ;
|
||||||
|
|
||||||
: find-between-first ( string vector -- vector' )
|
: find-between-first ( string vector -- vector' )
|
||||||
|
|
|
@ -36,7 +36,7 @@ IN: html.parser.utils
|
||||||
dup quoted? [ quote ] unless ;
|
dup quoted? [ quote ] unless ;
|
||||||
|
|
||||||
: unquote ( str -- newstr )
|
: unquote ( str -- newstr )
|
||||||
dup quoted? [ 1 head-slice* rest-slice >string ] when ;
|
dup quoted? [ but-last-slice rest-slice >string ] when ;
|
||||||
|
|
||||||
: quote? ( ch -- ? ) "'\"" member? ;
|
: quote? ( ch -- ? ) "'\"" member? ;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ test-db [
|
||||||
<dispatcher>
|
<dispatcher>
|
||||||
add-quit-action
|
add-quit-action
|
||||||
<dispatcher>
|
<dispatcher>
|
||||||
"extra/http/test" resource-path <static> >>default
|
"resource:extra/http/test" <static> >>default
|
||||||
"nested" add-responder
|
"nested" add-responder
|
||||||
<action>
|
<action>
|
||||||
[ "redirect-loop" f <standard-redirect> ] >>display
|
[ "redirect-loop" f <standard-redirect> ] >>display
|
||||||
|
@ -178,7 +178,7 @@ test-db [
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
"extra/http/test/foo.html" resource-path ascii file-contents
|
"resource:extra/http/test/foo.html" ascii file-contents
|
||||||
"http://localhost:1237/nested/foo.html" http-get =
|
"http://localhost:1237/nested/foo.html" http-get =
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
|
|
|
@ -148,4 +148,4 @@ SYMBOL: open-arrays
|
||||||
init f exec-loop ;
|
init f exec-loop ;
|
||||||
|
|
||||||
: run-sand ( -- )
|
: run-sand ( -- )
|
||||||
"extra/icfp/2006/sandmark.umz" resource-path run-prog ;
|
"resource:extra/icfp/2006/sandmark.umz" run-prog ;
|
||||||
|
|
|
@ -11,3 +11,8 @@ SYMBOL: test
|
||||||
[ 2 ] [ 1 test get interval-at ] unit-test
|
[ 2 ] [ 1 test get interval-at ] unit-test
|
||||||
[ f ] [ 2 test get interval-at ] unit-test
|
[ f ] [ 2 test get interval-at ] unit-test
|
||||||
[ f ] [ 0 test get interval-at ] unit-test
|
[ f ] [ 0 test get interval-at ] unit-test
|
||||||
|
|
||||||
|
[ { { { 1 4 } 3 } { { 4 8 } 6 } } <interval-map> ] must-fail
|
||||||
|
|
||||||
|
[ { { { 1 3 } 2 } { { 4 5 } 4 } { { 7 8 } 4 } } ]
|
||||||
|
[ { { 1 2 } { 2 2 } { 3 2 } { 4 4 } { 5 4 } { 7 4 } { 8 4 } } coalesce ] unit-test
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
USING: kernel sequences arrays math.intervals accessors
|
USING: kernel sequences arrays math.intervals accessors
|
||||||
math.order sorting math assocs ;
|
math.order sorting math assocs locals namespaces ;
|
||||||
IN: interval-maps
|
IN: interval-maps
|
||||||
|
|
||||||
TUPLE: interval-map array ;
|
TUPLE: interval-map array ;
|
||||||
|
@ -24,6 +24,8 @@ M: interval >interval ;
|
||||||
: ensure-disjoint ( intervals -- intervals )
|
: ensure-disjoint ( intervals -- intervals )
|
||||||
dup keys [ interval-intersect not ] monotonic?
|
dup keys [ interval-intersect not ] monotonic?
|
||||||
[ "Intervals are not disjoint" throw ] unless ;
|
[ "Intervals are not disjoint" throw ] unless ;
|
||||||
|
|
||||||
|
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
: interval-at* ( key map -- value ? )
|
: interval-at* ( key map -- value ? )
|
||||||
|
@ -35,7 +37,20 @@ PRIVATE>
|
||||||
: interval-key? ( key map -- ? ) interval-at* nip ;
|
: interval-key? ( key map -- ? ) interval-at* nip ;
|
||||||
|
|
||||||
: <interval-map> ( specification -- map )
|
: <interval-map> ( specification -- map )
|
||||||
all-intervals ensure-disjoint
|
all-intervals { } assoc-like
|
||||||
[ [ first to>> ] compare ] sort
|
[ [ first to>> ] compare ] sort ensure-disjoint
|
||||||
[ interval-node boa ] { } assoc>map
|
[ interval-node boa ] { } assoc>map
|
||||||
interval-map boa ;
|
interval-map boa ;
|
||||||
|
|
||||||
|
:: coalesce ( alist -- specification )
|
||||||
|
! Only works with integer keys, because they're discrete
|
||||||
|
! Makes 2array keys
|
||||||
|
[
|
||||||
|
alist sort-keys unclip first2 dupd roll
|
||||||
|
[| oldkey oldval key val | ! Underneath is start
|
||||||
|
oldkey 1+ key =
|
||||||
|
oldval val = and
|
||||||
|
[ oldkey 2array oldval 2array , key ] unless
|
||||||
|
key val
|
||||||
|
] assoc-each [ 2array ] bi@ ,
|
||||||
|
] { } make ;
|
||||||
|
|
|
@ -197,7 +197,7 @@ DEFER: _
|
||||||
|
|
||||||
\ prefix [ unclip ] define-inverse
|
\ prefix [ unclip ] define-inverse
|
||||||
\ unclip [ prefix ] define-inverse
|
\ unclip [ prefix ] define-inverse
|
||||||
\ suffix [ dup 1 head* swap peek ] define-inverse
|
\ suffix [ dup but-last swap peek ] define-inverse
|
||||||
|
|
||||||
! Constructor inverse
|
! Constructor inverse
|
||||||
: deconstruct-pred ( class -- quot )
|
: deconstruct-pred ( class -- quot )
|
||||||
|
|
|
@ -30,9 +30,8 @@ IN: io.encodings.8-bit
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
: encoding-file ( file-name -- stream )
|
: encoding-file ( file-name -- stream )
|
||||||
"extra/io/encodings/8-bit/" ".TXT"
|
"resource:extra/io/encodings/8-bit/" ".TXT"
|
||||||
swapd 3append resource-path
|
swapd 3append ascii <file-reader> ;
|
||||||
ascii <file-reader> ;
|
|
||||||
|
|
||||||
: tail-if ( seq n -- newseq )
|
: tail-if ( seq n -- newseq )
|
||||||
2dup swap length <= [ tail ] [ drop ] if ;
|
2dup swap length <= [ tail ] [ drop ] if ;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
! Copyright (C) 2008 Slava Pestov.
|
! Copyright (C) 2008 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: io io.backend io.timeouts io.pipes system kernel
|
USING: system kernel namespaces strings hashtables sequences
|
||||||
namespaces strings hashtables sequences assocs combinators
|
assocs combinators vocabs.loader init threads continuations
|
||||||
vocabs.loader init threads continuations math io.encodings
|
math accessors concurrency.flags destructors
|
||||||
io.streams.duplex io.nonblocking io.streams.duplex accessors
|
io io.backend io.timeouts io.pipes io.pipes.private io.encodings
|
||||||
concurrency.flags destructors ;
|
io.streams.duplex io.nonblocking ;
|
||||||
IN: io.launcher
|
IN: io.launcher
|
||||||
|
|
||||||
TUPLE: process < identity-tuple
|
TUPLE: process < identity-tuple
|
||||||
|
@ -149,15 +149,11 @@ M: process set-timeout set-process-timeout ;
|
||||||
|
|
||||||
M: process timed-out kill-process ;
|
M: process timed-out kill-process ;
|
||||||
|
|
||||||
M: object pipeline-element-quot
|
M: object run-pipeline-element
|
||||||
[
|
[ >process swap >>stdout swap >>stdin run-detached ]
|
||||||
>process
|
[ drop [ [ close-handle ] when* ] bi@ ]
|
||||||
swap >>stdout
|
3bi
|
||||||
swap >>stdin
|
wait-for-process ;
|
||||||
run-detached
|
|
||||||
] curry ;
|
|
||||||
|
|
||||||
M: process wait-for-pipeline-element wait-for-process ;
|
|
||||||
|
|
||||||
: <process-reader*> ( process encoding -- process stream )
|
: <process-reader*> ( process encoding -- process stream )
|
||||||
[
|
[
|
||||||
|
|
|
@ -23,34 +23,31 @@ HOOK: (pipe) io-backend ( -- pipe )
|
||||||
r> <encoder-duplex>
|
r> <encoder-duplex>
|
||||||
] with-destructors ;
|
] with-destructors ;
|
||||||
|
|
||||||
: with-fds ( input-fd output-fd quot -- )
|
<PRIVATE
|
||||||
>r >r [ <reader> dup add-always-destructor ] [ input-stream get ] if* r> r> [
|
|
||||||
>r [ <writer> dup add-always-destructor ] [ output-stream get ] if* r>
|
|
||||||
with-output-stream*
|
|
||||||
] 2curry with-input-stream* ; inline
|
|
||||||
|
|
||||||
: <pipes> ( n -- pipes )
|
: ?reader [ <reader> dup add-always-destructor ] [ input-stream get ] if* ;
|
||||||
[ (pipe) dup add-always-destructor ] replicate
|
: ?writer [ <writer> dup add-always-destructor ] [ output-stream get ] if* ;
|
||||||
f f pipe boa [ prefix ] [ suffix ] bi
|
|
||||||
2 <clumps> ;
|
|
||||||
|
|
||||||
: with-pipe-fds ( seq -- results )
|
GENERIC: run-pipeline-element ( input-fd output-fd obj -- quot )
|
||||||
|
|
||||||
|
M: callable run-pipeline-element
|
||||||
[
|
[
|
||||||
[ length dup zero? [ drop { } ] [ 1- <pipes> ] if ] keep
|
>r [ ?reader ] [ ?writer ] bi*
|
||||||
[ >r [ first in>> ] [ second out>> ] bi r> 2curry ] 2map
|
r> with-streams*
|
||||||
[ call ] parallel-map
|
|
||||||
] with-destructors ;
|
] with-destructors ;
|
||||||
|
|
||||||
GENERIC: pipeline-element-quot ( obj -- quot )
|
: <pipes> ( n -- pipes )
|
||||||
|
[
|
||||||
|
[ (pipe) dup add-error-destructor ] replicate
|
||||||
|
T{ pipe } [ prefix ] [ suffix ] bi
|
||||||
|
2 <clumps>
|
||||||
|
] with-destructors ;
|
||||||
|
|
||||||
M: callable pipeline-element-quot
|
PRIVATE>
|
||||||
[ with-fds ] curry ;
|
|
||||||
|
|
||||||
GENERIC: wait-for-pipeline-element ( obj -- result )
|
|
||||||
|
|
||||||
M: object wait-for-pipeline-element ;
|
|
||||||
|
|
||||||
: run-pipeline ( seq -- results )
|
: run-pipeline ( seq -- results )
|
||||||
[ pipeline-element-quot ] map
|
[ length dup zero? [ drop { } ] [ 1- <pipes> ] if ] keep
|
||||||
with-pipe-fds
|
[
|
||||||
[ wait-for-pipeline-element ] map ;
|
>r [ first in>> ] [ second out>> ] bi
|
||||||
|
r> run-pipeline-element
|
||||||
|
] 2parallel-map ;
|
||||||
|
|
|
@ -99,7 +99,7 @@ accessors kernel sequences io.encodings.utf8 ;
|
||||||
utf8 file-contents
|
utf8 file-contents
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ ] [ "append-test" temp-file delete-file ] unit-test
|
[ "append-test" temp-file delete-file ] ignore-errors
|
||||||
|
|
||||||
[ "hi\nhi\n" ] [
|
[ "hi\nhi\n" ] [
|
||||||
2 [
|
2 [
|
||||||
|
|
|
@ -13,9 +13,11 @@ TUPLE: macosx-monitor < monitor handle ;
|
||||||
] curry each ;
|
] curry each ;
|
||||||
|
|
||||||
M:: macosx (monitor) ( path recursive? mailbox -- monitor )
|
M:: macosx (monitor) ( path recursive? mailbox -- monitor )
|
||||||
path mailbox macosx-monitor new-monitor
|
[let | path [ path normalize-path ] |
|
||||||
dup [ enqueue-notifications ] curry
|
path mailbox macosx-monitor new-monitor
|
||||||
path 1array 0 0 <event-stream> >>handle ;
|
dup [ enqueue-notifications ] curry
|
||||||
|
path 1array 0 0 <event-stream> >>handle
|
||||||
|
] ;
|
||||||
|
|
||||||
M: macosx-monitor dispose
|
M: macosx-monitor dispose
|
||||||
handle>> dispose ;
|
handle>> dispose ;
|
||||||
|
|
|
@ -9,6 +9,7 @@ IN: io.unix.pipes.tests
|
||||||
"ls"
|
"ls"
|
||||||
[
|
[
|
||||||
input-stream [ utf8 <decoder> ] change
|
input-stream [ utf8 <decoder> ] change
|
||||||
|
output-stream [ utf8 <encoder> ] change
|
||||||
input-stream get lines reverse [ print ] each f
|
input-stream get lines reverse [ print ] each f
|
||||||
]
|
]
|
||||||
"grep x"
|
"grep x"
|
||||||
|
|
|
@ -41,7 +41,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "stderr.factor" 3array >>command
|
vm "-script" "stderr.factor" 3array >>command
|
||||||
"out.txt" temp-file >>stdout
|
"out.txt" temp-file >>stdout
|
||||||
|
@ -59,7 +59,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ ] [
|
[ ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "stderr.factor" 3array >>command
|
vm "-script" "stderr.factor" 3array >>command
|
||||||
"out.txt" temp-file >>stdout
|
"out.txt" temp-file >>stdout
|
||||||
|
@ -73,7 +73,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ "output" ] [
|
[ "output" ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "stderr.factor" 3array >>command
|
vm "-script" "stderr.factor" 3array >>command
|
||||||
"err2.txt" temp-file >>stderr
|
"err2.txt" temp-file >>stderr
|
||||||
|
@ -86,7 +86,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "env.factor" 3array >>command
|
vm "-script" "env.factor" 3array >>command
|
||||||
ascii <process-reader> contents
|
ascii <process-reader> contents
|
||||||
|
@ -96,7 +96,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ t ] [
|
[ t ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "env.factor" 3array >>command
|
vm "-script" "env.factor" 3array >>command
|
||||||
+replace-environment+ >>environment-mode
|
+replace-environment+ >>environment-mode
|
||||||
|
@ -108,7 +108,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ "B" ] [
|
[ "B" ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "env.factor" 3array >>command
|
vm "-script" "env.factor" 3array >>command
|
||||||
{ { "A" "B" } } >>environment
|
{ { "A" "B" } } >>environment
|
||||||
|
@ -119,7 +119,7 @@ sequences parser assocs hashtables math continuations ;
|
||||||
] unit-test
|
] unit-test
|
||||||
|
|
||||||
[ f ] [
|
[ f ] [
|
||||||
"extra/io/windows/nt/launcher/test" resource-path [
|
"resource:extra/io/windows/nt/launcher/test" [
|
||||||
<process>
|
<process>
|
||||||
vm "-script" "env.factor" 3array >>command
|
vm "-script" "env.factor" 3array >>command
|
||||||
{ { "HOME" "XXX" } } >>environment
|
{ { "HOME" "XXX" } } >>environment
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
USING: tools.deploy.config ;
|
||||||
|
V{
|
||||||
|
{ deploy-ui? t }
|
||||||
|
{ deploy-io 1 }
|
||||||
|
{ deploy-reflection 1 }
|
||||||
|
{ deploy-compiler? t }
|
||||||
|
{ deploy-math? t }
|
||||||
|
{ deploy-word-props? f }
|
||||||
|
{ deploy-c-types? f }
|
||||||
|
{ "stop-after-last-window?" t }
|
||||||
|
{ deploy-name "Jamshred" }
|
||||||
|
}
|
|
@ -1,26 +1,31 @@
|
||||||
! Copyright (C) 2007 Alex Chapman
|
! Copyright (C) 2007 Alex Chapman
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel opengl arrays sequences jamshred.tunnel
|
USING: accessors kernel opengl arrays sequences jamshred.log jamshred.player jamshred.sound jamshred.tunnel math.vectors ;
|
||||||
jamshred.player math.vectors ;
|
|
||||||
IN: jamshred.game
|
IN: jamshred.game
|
||||||
|
|
||||||
TUPLE: jamshred tunnel players running ;
|
TUPLE: jamshred sounds tunnel players running quit ;
|
||||||
|
|
||||||
: <jamshred> ( -- jamshred )
|
: <jamshred> ( -- jamshred )
|
||||||
<random-tunnel> "Player 1" <player> 2dup swap play-in-tunnel 1array f
|
<sounds> <random-tunnel> "Player 1" pick <player>
|
||||||
jamshred boa ;
|
2dup swap play-in-tunnel 1array f f jamshred boa ;
|
||||||
|
|
||||||
: jamshred-player ( jamshred -- player )
|
: jamshred-player ( jamshred -- player )
|
||||||
! TODO: support more than one player
|
! TODO: support more than one player
|
||||||
jamshred-players first ;
|
players>> first ;
|
||||||
|
|
||||||
: jamshred-update ( jamshred -- )
|
: jamshred-update ( jamshred -- )
|
||||||
dup jamshred-running [
|
dup running>> [
|
||||||
jamshred-player update-player
|
jamshred-player update-player
|
||||||
] [ drop ] if ;
|
] [ drop ] if ;
|
||||||
|
|
||||||
: toggle-running ( jamshred -- )
|
: toggle-running ( jamshred -- )
|
||||||
dup jamshred-running not swap set-jamshred-running ;
|
dup running>> [
|
||||||
|
f >>running drop
|
||||||
|
] [
|
||||||
|
[ jamshred-player moved ]
|
||||||
|
[ t >>running drop ] bi
|
||||||
|
] if ;
|
||||||
|
|
||||||
: mouse-moved ( x-radians y-radians jamshred -- )
|
: mouse-moved ( x-radians y-radians jamshred -- )
|
||||||
jamshred-player -rot turn-player ;
|
jamshred-player -rot turn-player ;
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,48 @@
|
||||||
! Copyright (C) 2007, 2008 Alex Chapman
|
! Copyright (C) 2007, 2008 Alex Chapman
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: alarms arrays calendar jamshred.game jamshred.gl kernel math
|
USING: accessors alarms arrays calendar jamshred.game jamshred.gl jamshred.player jamshred.log kernel math math.constants namespaces sequences threads ui ui.backend ui.gadgets ui.gadgets.worlds ui.gestures ui.render math.vectors ;
|
||||||
math.constants namespaces sequences ui ui.gadgets ui.gestures ui.render
|
|
||||||
math.vectors ;
|
|
||||||
IN: jamshred
|
IN: jamshred
|
||||||
|
|
||||||
TUPLE: jamshred-gadget jamshred last-hand-loc alarm ;
|
TUPLE: jamshred-gadget jamshred last-hand-loc alarm ;
|
||||||
|
|
||||||
: <jamshred-gadget> ( jamshred -- gadget )
|
: <jamshred-gadget> ( jamshred -- gadget )
|
||||||
jamshred-gadget construct-gadget tuck set-jamshred-gadget-jamshred ;
|
jamshred-gadget construct-gadget swap >>jamshred ;
|
||||||
|
|
||||||
: default-width ( -- x ) 1024 ;
|
: default-width ( -- x ) 800 ;
|
||||||
: default-height ( -- y ) 768 ;
|
: default-height ( -- y ) 600 ;
|
||||||
|
|
||||||
M: jamshred-gadget pref-dim*
|
M: jamshred-gadget pref-dim*
|
||||||
drop default-width default-height 2array ;
|
drop default-width default-height 2array ;
|
||||||
|
|
||||||
M: jamshred-gadget draw-gadget* ( gadget -- )
|
M: jamshred-gadget draw-gadget* ( gadget -- )
|
||||||
dup jamshred-gadget-jamshred swap rect-dim first2 draw-jamshred ;
|
[ jamshred>> ] [ rect-dim first2 draw-jamshred ] bi ;
|
||||||
|
|
||||||
: tick ( gadget -- )
|
: jamshred-loop ( gadget -- )
|
||||||
dup jamshred-gadget-jamshred jamshred-update relayout-1 ;
|
dup jamshred>> quit>> [
|
||||||
|
drop
|
||||||
|
] [
|
||||||
|
dup [ jamshred>> jamshred-update ]
|
||||||
|
[ relayout-1 ] bi
|
||||||
|
yield jamshred-loop
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: fullscreen ( gadget -- )
|
||||||
|
find-world t swap set-fullscreen* ;
|
||||||
|
|
||||||
|
: no-fullscreen ( gadget -- )
|
||||||
|
find-world f swap set-fullscreen* ;
|
||||||
|
|
||||||
|
: toggle-fullscreen ( world -- )
|
||||||
|
[ fullscreen? not ] keep set-fullscreen* ;
|
||||||
|
|
||||||
M: jamshred-gadget graft* ( gadget -- )
|
M: jamshred-gadget graft* ( gadget -- )
|
||||||
[
|
[ jamshred-loop ] in-thread drop ;
|
||||||
[ tick ] curry 10 milliseconds from-now 10 milliseconds add-alarm
|
|
||||||
] keep set-jamshred-gadget-alarm ;
|
|
||||||
|
|
||||||
M: jamshred-gadget ungraft* ( gadget -- )
|
M: jamshred-gadget ungraft* ( gadget -- )
|
||||||
[ jamshred-gadget-alarm cancel-alarm f ] keep
|
jamshred>> t swap (>>quit) ;
|
||||||
set-jamshred-gadget-alarm ;
|
|
||||||
|
|
||||||
: jamshred-restart ( jamshred-gadget -- )
|
: jamshred-restart ( jamshred-gadget -- )
|
||||||
<jamshred> swap set-jamshred-gadget-jamshred ;
|
<jamshred> >>jamshred drop ;
|
||||||
|
|
||||||
: pix>radians ( n m -- theta )
|
: pix>radians ( n m -- theta )
|
||||||
2 / / pi 2 * * ;
|
2 / / pi 2 * * ;
|
||||||
|
@ -46,22 +56,31 @@ M: jamshred-gadget ungraft* ( gadget -- )
|
||||||
rect-dim second pix>radians ;
|
rect-dim second pix>radians ;
|
||||||
|
|
||||||
: (handle-mouse-motion) ( jamshred-gadget mouse-motion -- )
|
: (handle-mouse-motion) ( jamshred-gadget mouse-motion -- )
|
||||||
over jamshred-gadget-jamshred >r
|
over jamshred>> >r
|
||||||
[ first swap x>radians ] 2keep second swap y>radians
|
[ first swap x>radians ] 2keep second swap y>radians
|
||||||
r> mouse-moved ;
|
r> mouse-moved ;
|
||||||
|
|
||||||
: handle-mouse-motion ( jamshred-gadget -- )
|
: handle-mouse-motion ( jamshred-gadget -- )
|
||||||
hand-loc get [
|
hand-loc get [
|
||||||
over jamshred-gadget-last-hand-loc [
|
over last-hand-loc>> [
|
||||||
v- (handle-mouse-motion)
|
v- (handle-mouse-motion)
|
||||||
] [ 2drop ] if*
|
] [ 2drop ] if*
|
||||||
] 2keep swap set-jamshred-gadget-last-hand-loc ;
|
] 2keep >>last-hand-loc drop ;
|
||||||
|
|
||||||
|
: handle-mouse-scroll ( jamshred-gadget -- )
|
||||||
|
jamshred>> jamshred-player scroll-direction get
|
||||||
|
second neg swap change-player-speed ;
|
||||||
|
|
||||||
|
: quit ( gadget -- )
|
||||||
|
[ no-fullscreen ] [ close-window ] bi ;
|
||||||
|
|
||||||
USE: vocabs.loader
|
|
||||||
jamshred-gadget H{
|
jamshred-gadget H{
|
||||||
{ T{ key-down f f "r" } [ jamshred-restart ] }
|
{ T{ key-down f f "r" } [ jamshred-restart ] }
|
||||||
{ T{ key-down f f " " } [ jamshred-gadget-jamshred toggle-running ] }
|
{ T{ key-down f f " " } [ jamshred>> toggle-running ] }
|
||||||
|
{ T{ key-down f f "f" } [ find-world toggle-fullscreen ] }
|
||||||
|
{ T{ key-down f f "q" } [ quit ] }
|
||||||
{ T{ motion } [ handle-mouse-motion ] }
|
{ T{ motion } [ handle-mouse-motion ] }
|
||||||
|
{ T{ mouse-scroll } [ handle-mouse-scroll ] }
|
||||||
} set-gestures
|
} set-gestures
|
||||||
|
|
||||||
: jamshred-window ( -- )
|
: jamshred-window ( -- )
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
USING: kernel logging ;
|
||||||
|
IN: jamshred.log
|
||||||
|
|
||||||
|
LOG: (jamshred-log) DEBUG
|
||||||
|
|
||||||
|
: with-jamshred-log ( quot -- )
|
||||||
|
"jamshred" swap with-logging ;
|
||||||
|
|
||||||
|
: jamshred-log ( message -- )
|
||||||
|
[ (jamshred-log) ] with-jamshred-log ; ! ugly...
|
|
@ -0,0 +1,8 @@
|
||||||
|
USING: jamshred.oint tools.test ;
|
||||||
|
IN: jamshred.oint-tests
|
||||||
|
|
||||||
|
[ { 0 -1 -1 } ] [ { 0 1 -1 } { 0 -1 0 } reflect ] unit-test
|
||||||
|
[ { 0 1 0 } ] [ { 1 1 0 } { 1 0 0 } proj-perp ] unit-test
|
||||||
|
[ { 1 0 0 } ] [ { 1 1 0 } { 0 1 0 } proj-perp ] unit-test
|
||||||
|
[ { 1/2 -1/2 0 } ] [ { 1 0 0 } { 1 1 0 } proj-perp ] unit-test
|
||||||
|
[ { -1/2 1/2 0 } ] [ { 0 1 0 } { 1 1 0 } proj-perp ] unit-test
|
|
@ -1,6 +1,6 @@
|
||||||
! Copyright (C) 2007 Alex Chapman
|
! Copyright (C) 2007 Alex Chapman
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: arrays float-arrays kernel math math.constants math.functions math.matrices math.vectors math.quaternions random sequences ;
|
USING: accessors arrays float-arrays kernel locals math math.constants math.functions math.matrices math.vectors math.quaternions random sequences ;
|
||||||
IN: jamshred.oint
|
IN: jamshred.oint
|
||||||
|
|
||||||
! An oint is a point with three linearly independent unit vectors
|
! An oint is a point with three linearly independent unit vectors
|
||||||
|
@ -9,47 +9,25 @@ IN: jamshred.oint
|
||||||
! segment's location and orientation are given by an oint.
|
! segment's location and orientation are given by an oint.
|
||||||
|
|
||||||
TUPLE: oint location forward up left ;
|
TUPLE: oint location forward up left ;
|
||||||
|
C: <oint> oint
|
||||||
: <oint> ( location forward up left -- oint )
|
|
||||||
oint boa ;
|
|
||||||
|
|
||||||
! : x-rotation ( theta -- matrix )
|
|
||||||
! #! construct this matrix:
|
|
||||||
! #! { { 1 0 0 }
|
|
||||||
! #! { 0 cos(theta) sin(theta) }
|
|
||||||
! #! { 0 -sin(theta) cos(theta) } }
|
|
||||||
! dup sin neg swap cos 2dup 0 -rot 3float-array >r
|
|
||||||
! swap neg 0 -rot 3float-array >r
|
|
||||||
! { 1 0 0 } r> r> 3float-array ;
|
|
||||||
!
|
|
||||||
! : y-rotation ( theta -- matrix )
|
|
||||||
! #! costruct this matrix:
|
|
||||||
! #! { { cos(theta) 0 -sin(theta) }
|
|
||||||
! #! { 0 1 0 }
|
|
||||||
! #! { sin(theta) 0 cos(theta) } }
|
|
||||||
! dup sin swap cos 2dup
|
|
||||||
! 0 swap 3float-array >r
|
|
||||||
! { 0 1 0 } >r
|
|
||||||
! 0 rot neg 3float-array r> r> 3float-array ;
|
|
||||||
|
|
||||||
: apply-to-oint ( oint quot -- )
|
|
||||||
#! apply quot to each of forward, up, and left, storing the results
|
|
||||||
over oint-forward over call pick set-oint-forward
|
|
||||||
over oint-up over call pick set-oint-up
|
|
||||||
over oint-left swap call swap set-oint-left ;
|
|
||||||
|
|
||||||
: rotation-quaternion ( theta axis -- quaternion )
|
: rotation-quaternion ( theta axis -- quaternion )
|
||||||
swap 2 / dup cos swap sin rot n*v first3 rect> >r rect> r> 2array ;
|
swap 2 / dup cos swap sin rot n*v first3 rect> >r rect> r> 2array ;
|
||||||
|
|
||||||
|
: rotate-vector ( q qrecip v -- v )
|
||||||
|
v>q swap q* q* q>v ;
|
||||||
|
|
||||||
: rotate-oint ( oint theta axis -- )
|
: rotate-oint ( oint theta axis -- )
|
||||||
rotation-quaternion dup qrecip
|
rotation-quaternion dup qrecip pick
|
||||||
[ rot v>q swap q* q* q>v ] curry curry apply-to-oint ;
|
[ forward>> rotate-vector >>forward ]
|
||||||
|
[ up>> rotate-vector >>up ]
|
||||||
|
[ left>> rotate-vector >>left ] 3tri drop ;
|
||||||
|
|
||||||
: left-pivot ( oint theta -- )
|
: left-pivot ( oint theta -- )
|
||||||
over oint-left rotate-oint ;
|
over left>> rotate-oint ;
|
||||||
|
|
||||||
: up-pivot ( oint theta -- )
|
: up-pivot ( oint theta -- )
|
||||||
over oint-up rotate-oint ;
|
over up>> rotate-oint ;
|
||||||
|
|
||||||
: random-float+- ( n -- m )
|
: random-float+- ( n -- m )
|
||||||
#! find a random float between -n/2 and n/2
|
#! find a random float between -n/2 and n/2
|
||||||
|
@ -59,10 +37,10 @@ TUPLE: oint location forward up left ;
|
||||||
2 / 2dup random-float+- left-pivot random-float+- up-pivot ;
|
2 / 2dup random-float+- left-pivot random-float+- up-pivot ;
|
||||||
|
|
||||||
: go-forward ( distance oint -- )
|
: go-forward ( distance oint -- )
|
||||||
tuck oint-forward n*v over oint-location v+ swap set-oint-location ;
|
[ forward>> n*v ] [ location>> v+ ] [ (>>location) ] tri ;
|
||||||
|
|
||||||
: distance-vector ( oint oint -- vector )
|
: distance-vector ( oint oint -- vector )
|
||||||
oint-location swap oint-location v- ;
|
[ location>> ] bi@ swap v- ;
|
||||||
|
|
||||||
: distance ( oint oint -- distance )
|
: distance ( oint oint -- distance )
|
||||||
distance-vector norm ;
|
distance-vector norm ;
|
||||||
|
@ -71,6 +49,13 @@ TUPLE: oint location forward up left ;
|
||||||
#! the scalar projection of v1 onto v2
|
#! the scalar projection of v1 onto v2
|
||||||
tuck v. swap norm / ;
|
tuck v. swap norm / ;
|
||||||
|
|
||||||
|
: proj-perp ( u v -- w )
|
||||||
|
dupd proj v- ;
|
||||||
|
|
||||||
: perpendicular-distance ( oint oint -- distance )
|
: perpendicular-distance ( oint oint -- distance )
|
||||||
tuck distance-vector swap 2dup oint-left scalar-projection abs
|
tuck distance-vector swap 2dup left>> scalar-projection abs
|
||||||
-rot oint-up scalar-projection abs + ;
|
-rot up>> scalar-projection abs + ;
|
||||||
|
|
||||||
|
:: reflect ( v n -- v' )
|
||||||
|
#! bounce v on a surface with normal n
|
||||||
|
v v n v. n n v. / 2 * n n*v v- ;
|
||||||
|
|
|
@ -1,38 +1,68 @@
|
||||||
! Copyright (C) 2007 Alex Chapman
|
! Copyright (C) 2007 Alex Chapman
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: colors jamshred.oint jamshred.tunnel kernel
|
USING: accessors colors jamshred.log jamshred.oint jamshred.sound jamshred.tunnel kernel math math.constants math.order math.ranges shuffle sequences system ;
|
||||||
math math.constants sequences ;
|
|
||||||
IN: jamshred.player
|
IN: jamshred.player
|
||||||
|
|
||||||
TUPLE: player name tunnel nearest-segment ;
|
TUPLE: player < oint name sounds tunnel nearest-segment last-move speed ;
|
||||||
|
|
||||||
: <player> ( name -- player )
|
! speeds are in GL units / second
|
||||||
f f player boa
|
: default-speed ( -- speed ) 1.0 ;
|
||||||
F{ 0 0 5 } F{ 0 0 -1 } F{ 0 1 0 } F{ -1 0 0 } <oint> over set-delegate ;
|
: max-speed ( -- speed ) 30.0 ;
|
||||||
|
|
||||||
|
: <player> ( name sounds -- player )
|
||||||
|
[ F{ 0 0 5 } F{ 0 0 -1 } F{ 0 1 0 } F{ -1 0 0 } ] 2dip
|
||||||
|
f f f default-speed player boa ;
|
||||||
|
|
||||||
: turn-player ( player x-radians y-radians -- )
|
: turn-player ( player x-radians y-radians -- )
|
||||||
>r over r> left-pivot up-pivot ;
|
>r over r> left-pivot up-pivot ;
|
||||||
|
|
||||||
: to-tunnel-start ( player -- )
|
: to-tunnel-start ( player -- )
|
||||||
dup player-tunnel first dup oint-location pick set-oint-location
|
[ tunnel>> first dup location>> ]
|
||||||
swap set-player-nearest-segment ;
|
[ tuck (>>location) (>>nearest-segment) ] bi ;
|
||||||
|
|
||||||
: play-in-tunnel ( player segments -- )
|
: play-in-tunnel ( player segments -- )
|
||||||
over set-player-tunnel to-tunnel-start ;
|
>>tunnel to-tunnel-start ;
|
||||||
|
|
||||||
: update-nearest-segment ( player -- )
|
: update-nearest-segment ( player -- )
|
||||||
dup player-tunnel over dup player-nearest-segment nearest-segment
|
[ tunnel>> ] [ dup nearest-segment>> nearest-segment ]
|
||||||
swap set-player-nearest-segment ;
|
[ (>>nearest-segment) ] tri ;
|
||||||
|
|
||||||
: max-speed ( -- speed )
|
: moved ( player -- ) millis swap (>>last-move) ;
|
||||||
0.3 ;
|
|
||||||
|
|
||||||
: player-speed ( player -- speed )
|
: speed-range ( -- range )
|
||||||
dup player-nearest-segment fraction-from-wall sq max-speed * ;
|
max-speed [0,b] ;
|
||||||
|
|
||||||
|
: change-player-speed ( inc player -- )
|
||||||
|
[ + speed-range clamp-to-range ] change-speed drop ;
|
||||||
|
|
||||||
|
: distance-to-move ( player -- distance )
|
||||||
|
[ speed>> ] [ last-move>> millis dup >r swap - 1000 / * r> ]
|
||||||
|
[ (>>last-move) ] tri ;
|
||||||
|
|
||||||
|
DEFER: (move-player)
|
||||||
|
|
||||||
|
: ?bounce ( distance-remaining player -- )
|
||||||
|
over 0 > [
|
||||||
|
[ dup nearest-segment>> bounce ] [ sounds>> bang ]
|
||||||
|
[ (move-player) ] tri
|
||||||
|
] [
|
||||||
|
2drop
|
||||||
|
] if ;
|
||||||
|
|
||||||
|
: move-player-distance ( distance-remaining player distance -- distance-remaining player )
|
||||||
|
pick min tuck over go-forward [ - ] dip ;
|
||||||
|
|
||||||
|
: (move-player) ( distance-remaining player -- )
|
||||||
|
over 0 <= [
|
||||||
|
2drop
|
||||||
|
] [
|
||||||
|
dup dup nearest-segment>> distance-to-collision
|
||||||
|
move-player-distance ?bounce
|
||||||
|
] if ;
|
||||||
|
|
||||||
: move-player ( player -- )
|
: move-player ( player -- )
|
||||||
dup player-speed over go-forward update-nearest-segment ;
|
[ distance-to-move ] [ (move-player) ] [ update-nearest-segment ] tri ;
|
||||||
|
|
||||||
: update-player ( player -- )
|
: update-player ( player -- )
|
||||||
dup move-player player-nearest-segment
|
dup move-player nearest-segment>>
|
||||||
white swap set-segment-color ;
|
white swap set-segment-color ;
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,13 @@
|
||||||
|
USING: accessors io.files kernel openal sequences ;
|
||||||
|
IN: jamshred.sound
|
||||||
|
|
||||||
|
TUPLE: sounds bang ;
|
||||||
|
|
||||||
|
: assign-sound ( source wav-path -- )
|
||||||
|
resource-path create-buffer-from-wav AL_BUFFER swap set-source-param ;
|
||||||
|
|
||||||
|
: <sounds> ( -- sounds )
|
||||||
|
init-openal 1 gen-sources first sounds boa
|
||||||
|
dup bang>> "extra/jamshred/sound/bang.wav" assign-sound ;
|
||||||
|
|
||||||
|
: bang ( sounds -- ) bang>> source-play check-error ;
|
|
@ -3,8 +3,8 @@
|
||||||
USING: jamshred.oint jamshred.tunnel kernel sequences tools.test ;
|
USING: jamshred.oint jamshred.tunnel kernel sequences tools.test ;
|
||||||
IN: jamshred.tunnel.tests
|
IN: jamshred.tunnel.tests
|
||||||
|
|
||||||
[ 0 ] [ T{ segment T{ oint f { 0 0 0 } } 0 }
|
[ 0 ] [ T{ segment f { 0 0 0 } f f f 0 }
|
||||||
T{ segment T{ oint f { 1 1 1 } } 1 }
|
T{ segment f { 1 1 1 } f f f 1 }
|
||||||
T{ oint f { 0 0 0.25 } }
|
T{ oint f { 0 0 0.25 } }
|
||||||
nearer-segment segment-number ] unit-test
|
nearer-segment segment-number ] unit-test
|
||||||
|
|
||||||
|
@ -15,3 +15,30 @@ IN: jamshred.tunnel.tests
|
||||||
[ 3 ] [ <straight-tunnel> T{ oint f { 0 0 -3.25 } } 0 nearest-segment-forward segment-number ] unit-test
|
[ 3 ] [ <straight-tunnel> T{ oint f { 0 0 -3.25 } } 0 nearest-segment-forward segment-number ] unit-test
|
||||||
|
|
||||||
[ F{ 0 0 0 } ] [ <straight-tunnel> T{ oint f { 0 0 -0.25 } } over first nearest-segment oint-location ] unit-test
|
[ F{ 0 0 0 } ] [ <straight-tunnel> T{ oint f { 0 0 -0.25 } } over first nearest-segment oint-location ] unit-test
|
||||||
|
|
||||||
|
: test-segment-oint ( -- oint )
|
||||||
|
{ 0 0 0 } { 0 0 -1 } { 0 1 0 } { -1 0 0 } <oint> ;
|
||||||
|
|
||||||
|
[ { -1 0 0 } ] [ test-segment-oint { 1 0 0 } vector-to-centre ] unit-test
|
||||||
|
[ { 1 0 0 } ] [ test-segment-oint { -1 0 0 } vector-to-centre ] unit-test
|
||||||
|
[ { 0 -1 0 } ] [ test-segment-oint { 0 1 0 } vector-to-centre ] unit-test
|
||||||
|
[ { 0 1 0 } ] [ test-segment-oint { 0 -1 0 } vector-to-centre ] unit-test
|
||||||
|
[ { -1 0 0 } ] [ test-segment-oint { 1 0 -1 } vector-to-centre ] unit-test
|
||||||
|
[ { 1 0 0 } ] [ test-segment-oint { -1 0 -1 } vector-to-centre ] unit-test
|
||||||
|
[ { 0 -1 0 } ] [ test-segment-oint { 0 1 -1 } vector-to-centre ] unit-test
|
||||||
|
[ { 0 1 0 } ] [ test-segment-oint { 0 -1 -1 } vector-to-centre ] unit-test
|
||||||
|
|
||||||
|
: simplest-straight-ahead ( -- oint segment )
|
||||||
|
{ 0 0 0 } { 0 0 -1 } { 0 1 0 } { -1 0 0 } <oint>
|
||||||
|
initial-segment ;
|
||||||
|
|
||||||
|
[ { 0 0 0 } ] [ simplest-straight-ahead sideways-heading ] unit-test
|
||||||
|
[ { 0 0 0 } ] [ simplest-straight-ahead sideways-relative-location ] unit-test
|
||||||
|
|
||||||
|
: simple-collision-up ( -- oint segment )
|
||||||
|
{ 0 0 0 } { 0 1 0 } { 0 0 1 } { -1 0 0 } <oint>
|
||||||
|
initial-segment ;
|
||||||
|
|
||||||
|
[ { 0 1 0 } ] [ simple-collision-up sideways-heading ] unit-test
|
||||||
|
[ { 0 0 0 } ] [ simple-collision-up sideways-relative-location ] unit-test
|
||||||
|
[ { 0 1 0 } ] [ simple-collision-up collision-vector ] unit-test
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
! Copyright (C) 2007 Alex Chapman
|
! Copyright (C) 2007 Alex Chapman
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: arrays float-arrays kernel jamshred.oint math math.functions
|
USING: accessors arrays combinators float-arrays kernel jamshred.oint locals math math.functions math.constants math.matrices math.order math.ranges math.vectors math.quadratic random sequences vectors ;
|
||||||
math.ranges math.vectors math.constants random sequences vectors ;
|
|
||||||
IN: jamshred.tunnel
|
IN: jamshred.tunnel
|
||||||
|
|
||||||
: n-segments ( -- n ) 5000 ; inline
|
: n-segments ( -- n ) 5000 ; inline
|
||||||
|
|
||||||
TUPLE: segment number color radius ;
|
TUPLE: segment < oint number color radius ;
|
||||||
|
C: <segment> segment
|
||||||
: <segment> ( number color radius location forward up left -- segment )
|
|
||||||
<oint> >r segment boa r> over set-delegate ;
|
|
||||||
|
|
||||||
: segment-vertex ( theta segment -- vertex )
|
: segment-vertex ( theta segment -- vertex )
|
||||||
tuck 2dup oint-up swap sin v*n
|
tuck 2dup up>> swap sin v*n
|
||||||
>r oint-left swap cos v*n r> v+
|
>r left>> swap cos v*n r> v+
|
||||||
swap oint-location v+ ;
|
swap location>> v+ ;
|
||||||
|
|
||||||
: segment-vertex-normal ( vertex segment -- normal )
|
: segment-vertex-normal ( vertex segment -- normal )
|
||||||
oint-location swap v- normalize ;
|
location>> swap v- normalize ;
|
||||||
|
|
||||||
: segment-vertex-and-normal ( segment theta -- vertex normal )
|
: segment-vertex-and-normal ( segment theta -- vertex normal )
|
||||||
swap [ segment-vertex ] keep dupd segment-vertex-normal ;
|
swap [ segment-vertex ] keep dupd segment-vertex-normal ;
|
||||||
|
@ -27,7 +24,7 @@ TUPLE: segment number color radius ;
|
||||||
dup [ / pi 2 * * ] curry map ;
|
dup [ / pi 2 * * ] curry map ;
|
||||||
|
|
||||||
: segment-number++ ( segment -- )
|
: segment-number++ ( segment -- )
|
||||||
dup segment-number 1+ swap set-segment-number ;
|
[ number>> 1+ ] keep (>>number) ;
|
||||||
|
|
||||||
: random-color ( -- color )
|
: random-color ( -- color )
|
||||||
{ 100 100 100 } [ random 100 / >float ] map { 1.0 } append ;
|
{ 100 100 100 } [ random 100 / >float ] map { 1.0 } append ;
|
||||||
|
@ -50,15 +47,15 @@ TUPLE: segment number color radius ;
|
||||||
: default-segment-radius ( -- r ) 1 ;
|
: default-segment-radius ( -- r ) 1 ;
|
||||||
|
|
||||||
: initial-segment ( -- segment )
|
: initial-segment ( -- segment )
|
||||||
0 random-color default-segment-radius
|
F{ 0 0 0 } F{ 0 0 -1 } F{ 0 1 0 } F{ -1 0 0 }
|
||||||
F{ 0 0 0 } F{ 0 0 -1 } F{ 0 1 0 } F{ -1 0 0 } <segment> ;
|
0 random-color default-segment-radius <segment> ;
|
||||||
|
|
||||||
: random-segments ( n -- segments )
|
: random-segments ( n -- segments )
|
||||||
initial-segment 1vector swap (random-segments) ;
|
initial-segment 1vector swap (random-segments) ;
|
||||||
|
|
||||||
: simple-segment ( n -- segment )
|
: simple-segment ( n -- segment )
|
||||||
random-color default-segment-radius pick F{ 0 0 -1 } n*v
|
[ F{ 0 0 -1 } n*v F{ 0 0 -1 } F{ 0 1 0 } F{ -1 0 0 } ] keep
|
||||||
F{ 0 0 -1 } F{ 0 1 0 } F{ -1 0 0 } <segment> ;
|
random-color default-segment-radius <segment> ;
|
||||||
|
|
||||||
: simple-segments ( n -- segments )
|
: simple-segments ( n -- segments )
|
||||||
[ simple-segment ] map ;
|
[ simple-segment ] map ;
|
||||||
|
@ -100,14 +97,54 @@ TUPLE: segment number color radius ;
|
||||||
[ nearest-segment-forward ] 3keep
|
[ nearest-segment-forward ] 3keep
|
||||||
nearest-segment-backward r> nearer-segment ;
|
nearest-segment-backward r> nearer-segment ;
|
||||||
|
|
||||||
: distance-from-centre ( oint segment -- distance )
|
: vector-to-centre ( seg loc -- v )
|
||||||
perpendicular-distance ;
|
over location>> swap v- swap forward>> proj-perp ;
|
||||||
|
|
||||||
: distance-from-wall ( oint segment -- distance )
|
: distance-from-centre ( seg loc -- distance )
|
||||||
tuck distance-from-centre swap segment-radius swap - ;
|
vector-to-centre norm ;
|
||||||
|
|
||||||
: fraction-from-centre ( oint segment -- fraction )
|
: wall-normal ( seg oint -- n )
|
||||||
tuck distance-from-centre swap segment-radius / ;
|
location>> vector-to-centre normalize ;
|
||||||
|
|
||||||
: fraction-from-wall ( oint segment -- fraction )
|
: from ( seg loc -- radius d-f-c )
|
||||||
|
dupd location>> distance-from-centre [ radius>> ] dip ;
|
||||||
|
|
||||||
|
: distance-from-wall ( seg loc -- distance ) from - ;
|
||||||
|
: fraction-from-centre ( seg loc -- fraction ) from / ;
|
||||||
|
: fraction-from-wall ( seg loc -- fraction )
|
||||||
fraction-from-centre 1 swap - ;
|
fraction-from-centre 1 swap - ;
|
||||||
|
|
||||||
|
:: collision-coefficient ( v w r -- c )
|
||||||
|
[let* | a [ v dup v. ]
|
||||||
|
b [ v w v. 2 * ]
|
||||||
|
c [ w dup v. r sq - ] |
|
||||||
|
c b a quadratic max ] ;
|
||||||
|
|
||||||
|
: sideways-heading ( oint segment -- v )
|
||||||
|
[ forward>> ] bi@ proj-perp ;
|
||||||
|
|
||||||
|
: sideways-relative-location ( oint segment -- loc )
|
||||||
|
[ [ location>> ] bi@ v- ] keep forward>> proj-perp ;
|
||||||
|
|
||||||
|
: collision-vector ( oint segment -- v )
|
||||||
|
[ sideways-heading ] [ sideways-relative-location ] [ radius>> ] 2tri
|
||||||
|
swap [ collision-coefficient ] dip forward>> n*v ;
|
||||||
|
|
||||||
|
: distance-to-collision ( oint segment -- distance )
|
||||||
|
collision-vector norm ;
|
||||||
|
|
||||||
|
: bounce-forward ( segment oint -- )
|
||||||
|
[ wall-normal ] [ forward>> swap reflect ] [ (>>forward) ] tri ;
|
||||||
|
|
||||||
|
: bounce-left ( segment oint -- )
|
||||||
|
#! must be done after forward
|
||||||
|
[ forward>> vneg ] dip [ left>> swap reflect ]
|
||||||
|
[ forward>> proj-perp normalize ] [ (>>left) ] tri ;
|
||||||
|
|
||||||
|
: bounce-up ( segment oint -- )
|
||||||
|
#! must be done after forward and left!
|
||||||
|
nip [ forward>> ] [ left>> cross ] [ (>>up) ] tri ;
|
||||||
|
|
||||||
|
: bounce ( oint segment -- )
|
||||||
|
swap [ bounce-forward ] [ bounce-left ] [ bounce-up ] 2tri ;
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ DEFER: (d)
|
||||||
[ length ] keep [ (graded-ker/im-d) ] curry map ;
|
[ length ] keep [ (graded-ker/im-d) ] curry map ;
|
||||||
|
|
||||||
: graded-betti ( generators -- seq )
|
: graded-betti ( generators -- seq )
|
||||||
basis graded graded-ker/im-d flip first2 1 head* 0 prefix v- ;
|
basis graded graded-ker/im-d flip first2 but-last 0 prefix v- ;
|
||||||
|
|
||||||
! Bi-graded for two-step complexes
|
! Bi-graded for two-step complexes
|
||||||
: (bigraded-ker/im-d) ( u-deg z-deg bigraded-basis -- null/rank )
|
: (bigraded-ker/im-d) ( u-deg z-deg bigraded-basis -- null/rank )
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Daniel Ehrenberg
|
|
@ -0,0 +1,35 @@
|
||||||
|
USING: help.syntax help.markup ;
|
||||||
|
IN: lcs
|
||||||
|
|
||||||
|
HELP: levenshtein
|
||||||
|
{ $values { "old" "a sequence" } { "new" "a sequence" } { "n" "the Levenshtein distance" } }
|
||||||
|
{ $description "Calculates the Levenshtein distance between old and new, that is, the minimal number of changes from the old sequence to the new one, in terms of deleting, inserting and replacing characters." } ;
|
||||||
|
|
||||||
|
HELP: lcs
|
||||||
|
{ $values { "seq1" "a sequence" } { "seq2" "a sequence" } { "lcs" "a longest common subsequence" } }
|
||||||
|
{ $description "Given two sequences, calculates a longest common subsequence between them. Note two things: this is only one of the many possible LCSs, and the LCS may not be contiguous." } ;
|
||||||
|
|
||||||
|
HELP: diff
|
||||||
|
{ $values { "old" "a sequence" } { "new" "a sequence" } { "diff" "an edit script" } }
|
||||||
|
{ $description "Given two sequences, find a minimal edit script from the old to the new. There may be more than one minimal edit script, and this chooses one arbitrarily. This script is in the form of an array of the tuples of the classes " { $link retain } ", " { $link delete } " and " { $link insert } " which have their information stored in the 'item' slot." } ;
|
||||||
|
|
||||||
|
HELP: retain
|
||||||
|
{ $class-description "Represents an action in an edit script where an item is kept, going from the initial sequence to the final sequence. This has one slot, called item, containing the thing which is retained" } ;
|
||||||
|
|
||||||
|
HELP: delete
|
||||||
|
{ $class-description "Represents an action in an edit script where an item is deleted, going from the initial sequence to the final sequence. This has one slot, called item, containing the thing which is deleted" } ;
|
||||||
|
|
||||||
|
HELP: insert
|
||||||
|
{ $class-description "Represents an action in an edit script where an item is added, going from the initial sequence to the final sequence. This has one slot, called item, containing the thing which is inserted" } ;
|
||||||
|
|
||||||
|
ARTICLE: "lcs" "LCS, Diffing and Distance"
|
||||||
|
"This vocabulary provides words for three apparently unrelated but in fact very similar problems: finding a longest common subsequence between two sequences, getting a minimal edit script (diff) between two sequences, and calculating the Levenshtein distance between two sequences. The implementations of these algorithms are very closely related, and all running times are O(nm), where n and m are the lengths of the input sequences."
|
||||||
|
{ $subsection lcs }
|
||||||
|
{ $subsection diff }
|
||||||
|
{ $subsection levenshtein }
|
||||||
|
"The " { $link diff } " word returns a sequence of tuples of the following classes. They all hold their contents in the 'item' slot."
|
||||||
|
{ $subsection insert }
|
||||||
|
{ $subsection delete }
|
||||||
|
{ $subsection retain } ;
|
||||||
|
|
||||||
|
ABOUT: "lcs"
|
|
@ -0,0 +1,25 @@
|
||||||
|
! Copyright (C) 2006 Slava Pestov.
|
||||||
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
|
USING: tools.test lcs ;
|
||||||
|
|
||||||
|
[ 3 ] [ "sitting" "kitten" levenshtein ] unit-test
|
||||||
|
[ 3 ] [ "kitten" "sitting" levenshtein ] unit-test
|
||||||
|
[ 1 ] [ "freshpak" "freshpack" levenshtein ] unit-test
|
||||||
|
[ 1 ] [ "freshpack" "freshpak" levenshtein ] unit-test
|
||||||
|
|
||||||
|
[ "hell" ] [ "hello" "hell" lcs ] unit-test
|
||||||
|
[ "hell" ] [ "hell" "hello" lcs ] unit-test
|
||||||
|
[ "ell" ] [ "ell" "hell" lcs ] unit-test
|
||||||
|
[ "ell" ] [ "hell" "ell" lcs ] unit-test
|
||||||
|
[ "abd" ] [ "faxbcd" "abdef" lcs ] unit-test
|
||||||
|
|
||||||
|
[ {
|
||||||
|
T{ delete f CHAR: f }
|
||||||
|
T{ retain f CHAR: a }
|
||||||
|
T{ delete f CHAR: x }
|
||||||
|
T{ retain f CHAR: b }
|
||||||
|
T{ delete f CHAR: c }
|
||||||
|
T{ retain f CHAR: d }
|
||||||
|
T{ insert f CHAR: e }
|
||||||
|
T{ insert f CHAR: f }
|
||||||
|
} ] [ "faxbcd" "abdef" diff ] unit-test
|
|
@ -0,0 +1,97 @@
|
||||||
|
USING: sequences kernel math locals math.order math.ranges
|
||||||
|
accessors combinators.lib arrays namespaces combinators ;
|
||||||
|
IN: lcs
|
||||||
|
|
||||||
|
<PRIVATE
|
||||||
|
: levenshtein-step ( insert delete change same? -- next )
|
||||||
|
0 1 ? + >r [ 1+ ] bi@ r> min min ;
|
||||||
|
|
||||||
|
: lcs-step ( insert delete change same? -- next )
|
||||||
|
1 -9999 ? + max max ; ! Replace -9999 with -inf when added
|
||||||
|
|
||||||
|
:: loop-step ( i j matrix old new step -- )
|
||||||
|
i j 1+ matrix nth nth ! insertion
|
||||||
|
i 1+ j matrix nth nth ! deletion
|
||||||
|
i j matrix nth nth ! replace/retain
|
||||||
|
i old nth j new nth = ! same?
|
||||||
|
step call
|
||||||
|
i 1+ j 1+ matrix nth set-nth ; inline
|
||||||
|
|
||||||
|
: lcs-initialize ( |str1| |str2| -- matrix )
|
||||||
|
[ drop 0 <array> ] with map ;
|
||||||
|
|
||||||
|
: levenshtein-initialize ( |str1| |str2| -- matrix )
|
||||||
|
[ [ + ] curry map ] with map ;
|
||||||
|
|
||||||
|
:: run-lcs ( old new init step -- matrix )
|
||||||
|
[let | matrix [ old length 1+ new length 1+ init call ] |
|
||||||
|
old length [0,b) [| i |
|
||||||
|
new length [0,b)
|
||||||
|
[| j | i j matrix old new step loop-step ]
|
||||||
|
each
|
||||||
|
] each matrix ] ; inline
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: levenshtein ( old new -- n )
|
||||||
|
[ levenshtein-initialize ] [ levenshtein-step ]
|
||||||
|
run-lcs peek peek ;
|
||||||
|
|
||||||
|
TUPLE: retain item ;
|
||||||
|
TUPLE: delete item ;
|
||||||
|
TUPLE: insert item ;
|
||||||
|
|
||||||
|
<PRIVATE
|
||||||
|
TUPLE: trace-state old new table i j ;
|
||||||
|
|
||||||
|
: old-nth ( state -- elt )
|
||||||
|
[ i>> 1- ] [ old>> ] bi nth ;
|
||||||
|
|
||||||
|
: new-nth ( state -- elt )
|
||||||
|
[ j>> 1- ] [ new>> ] bi nth ;
|
||||||
|
|
||||||
|
: top-beats-side? ( state -- ? )
|
||||||
|
[ [ i>> ] [ j>> 1- ] [ table>> ] tri nth nth ]
|
||||||
|
[ [ i>> 1- ] [ j>> ] [ table>> ] tri nth nth ] bi > ;
|
||||||
|
|
||||||
|
: retained? ( state -- ? )
|
||||||
|
{
|
||||||
|
[ i>> 0 > ] [ j>> 0 > ]
|
||||||
|
[ [ old-nth ] [ new-nth ] bi = ]
|
||||||
|
} <-&& ;
|
||||||
|
|
||||||
|
: do-retain ( state -- state )
|
||||||
|
dup old-nth retain boa ,
|
||||||
|
[ 1- ] change-i [ 1- ] change-j ;
|
||||||
|
|
||||||
|
: inserted? ( state -- ? )
|
||||||
|
[ j>> 0 > ]
|
||||||
|
[ [ i>> zero? ] [ top-beats-side? ] or? ] and? ;
|
||||||
|
|
||||||
|
: do-insert ( state -- state )
|
||||||
|
dup new-nth insert boa , [ 1- ] change-j ;
|
||||||
|
|
||||||
|
: deleted? ( state -- ? )
|
||||||
|
[ i>> 0 > ]
|
||||||
|
[ [ j>> zero? ] [ top-beats-side? not ] or? ] and? ;
|
||||||
|
|
||||||
|
: do-delete ( state -- state )
|
||||||
|
dup old-nth delete boa , [ 1- ] change-i ;
|
||||||
|
|
||||||
|
: (trace-diff) ( state -- )
|
||||||
|
{
|
||||||
|
{ [ dup retained? ] [ do-retain (trace-diff) ] }
|
||||||
|
{ [ dup inserted? ] [ do-insert (trace-diff) ] }
|
||||||
|
{ [ dup deleted? ] [ do-delete (trace-diff) ] }
|
||||||
|
[ drop ] ! i=j=0
|
||||||
|
} cond ;
|
||||||
|
|
||||||
|
: trace-diff ( old new table -- diff )
|
||||||
|
[ ] [ first length 1- ] [ length 1- ] tri trace-state boa
|
||||||
|
[ (trace-diff) ] { } make reverse ;
|
||||||
|
PRIVATE>
|
||||||
|
|
||||||
|
: diff ( old new -- diff )
|
||||||
|
2dup [ lcs-initialize ] [ lcs-step ] run-lcs trace-diff ;
|
||||||
|
|
||||||
|
: lcs ( seq1 seq2 -- lcs )
|
||||||
|
[ diff [ retain? ] filter ] keep [ item>> ] swap map-as ;
|
|
@ -0,0 +1 @@
|
||||||
|
Levenshtein distance and diff between sequences
|
|
@ -0,0 +1 @@
|
||||||
|
algorithms
|
|
@ -1 +0,0 @@
|
||||||
Slava Pestov
|
|
|
@ -1,9 +0,0 @@
|
||||||
! Copyright (C) 2006 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
IN: levenshtein.tests
|
|
||||||
USING: tools.test levenshtein ;
|
|
||||||
|
|
||||||
[ 3 ] [ "sitting" "kitten" levenshtein ] unit-test
|
|
||||||
[ 3 ] [ "kitten" "sitting" levenshtein ] unit-test
|
|
||||||
[ 1 ] [ "freshpak" "freshpack" levenshtein ] unit-test
|
|
||||||
[ 1 ] [ "freshpack" "freshpak" levenshtein ] unit-test
|
|
|
@ -1,47 +0,0 @@
|
||||||
! Copyright (C) 2006 Slava Pestov.
|
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
|
||||||
USING: arrays help io kernel math namespaces sequences
|
|
||||||
math.order ;
|
|
||||||
IN: levenshtein
|
|
||||||
|
|
||||||
: <matrix> ( m n -- matrix )
|
|
||||||
[ drop 0 <array> ] with map ; inline
|
|
||||||
|
|
||||||
: matrix-> nth nth ; inline
|
|
||||||
: ->matrix nth set-nth ; inline
|
|
||||||
|
|
||||||
SYMBOL: d
|
|
||||||
|
|
||||||
: ->d ( n i j -- ) d get ->matrix ; inline
|
|
||||||
: d-> ( i j -- n ) d get matrix-> ; inline
|
|
||||||
|
|
||||||
SYMBOL: costs
|
|
||||||
|
|
||||||
: init-d ( str1 str2 -- )
|
|
||||||
[ length 1+ ] bi@ 2dup <matrix> d set
|
|
||||||
[ 0 over ->d ] each
|
|
||||||
[ dup 0 ->d ] each ; inline
|
|
||||||
|
|
||||||
: compute-costs ( str1 str2 -- )
|
|
||||||
swap [
|
|
||||||
[ = 0 1 ? ] with { } map-as
|
|
||||||
] curry { } map-as costs set ; inline
|
|
||||||
|
|
||||||
: levenshtein-step ( i j -- )
|
|
||||||
[ 1+ d-> 1+ ] 2keep
|
|
||||||
[ >r 1+ r> d-> 1+ ] 2keep
|
|
||||||
[ d-> ] 2keep
|
|
||||||
[ costs get matrix-> + min min ] 2keep
|
|
||||||
>r 1+ r> 1+ ->d ; inline
|
|
||||||
|
|
||||||
: levenshtein-result ( -- n ) d get peek peek ; inline
|
|
||||||
|
|
||||||
: levenshtein ( str1 str2 -- n )
|
|
||||||
[
|
|
||||||
2dup init-d
|
|
||||||
2dup compute-costs
|
|
||||||
[ length ] bi@ [
|
|
||||||
[ levenshtein-step ] curry each
|
|
||||||
] with each
|
|
||||||
levenshtein-result
|
|
||||||
] with-scope ;
|
|
|
@ -1 +0,0 @@
|
||||||
Levenshtein edit distance algorithm
|
|
|
@ -2,15 +2,6 @@ USING: help.syntax help.markup kernel macros prettyprint
|
||||||
memoize ;
|
memoize ;
|
||||||
IN: locals
|
IN: locals
|
||||||
|
|
||||||
<PRIVATE
|
|
||||||
|
|
||||||
: $with-locals-note
|
|
||||||
drop {
|
|
||||||
"This form must appear either in a word defined by " { $link POSTPONE: :: } " or " { $link POSTPONE: MACRO:: } ", or alternatively, " { $link with-locals } " must be called on the top-level form of the word to perform closure conversion."
|
|
||||||
} $notes ;
|
|
||||||
|
|
||||||
PRIVATE>
|
|
||||||
|
|
||||||
HELP: [|
|
HELP: [|
|
||||||
{ $syntax "[| bindings... | body... ]" }
|
{ $syntax "[| bindings... | body... ]" }
|
||||||
{ $description "A lambda abstraction. When called, reads stack values into the bindings from left to right; the body may then refer to these bindings." }
|
{ $description "A lambda abstraction. When called, reads stack values into the bindings from left to right; the body may then refer to these bindings." }
|
||||||
|
@ -22,8 +13,7 @@ HELP: [|
|
||||||
"3 5 adder call ."
|
"3 5 adder call ."
|
||||||
"8"
|
"8"
|
||||||
}
|
}
|
||||||
}
|
} ;
|
||||||
$with-locals-note ;
|
|
||||||
|
|
||||||
HELP: [let
|
HELP: [let
|
||||||
{ $syntax "[let | binding1 [ value1... ]\n binding2 [ value2... ]\n ... |\n body... ]" }
|
{ $syntax "[let | binding1 [ value1... ]\n binding2 [ value2... ]\n ... |\n body... ]" }
|
||||||
|
@ -38,8 +28,7 @@ HELP: [let
|
||||||
"6 { 36 14 } frobnicate ."
|
"6 { 36 14 } frobnicate ."
|
||||||
"{ 36 2 }"
|
"{ 36 2 }"
|
||||||
}
|
}
|
||||||
}
|
} ;
|
||||||
$with-locals-note ;
|
|
||||||
|
|
||||||
HELP: [let*
|
HELP: [let*
|
||||||
{ $syntax "[let* | binding1 [ value1... ]\n binding2 [ value2... ]\n ... |\n body... ]" }
|
{ $syntax "[let* | binding1 [ value1... ]\n binding2 [ value2... ]\n ... |\n body... ]" }
|
||||||
|
@ -55,8 +44,7 @@ HELP: [let*
|
||||||
"1 { 32 48 } frobnicate ."
|
"1 { 32 48 } frobnicate ."
|
||||||
"{ 2 3 }"
|
"{ 2 3 }"
|
||||||
}
|
}
|
||||||
}
|
} ;
|
||||||
$with-locals-note ;
|
|
||||||
|
|
||||||
{ POSTPONE: [let POSTPONE: [let* } related-words
|
{ POSTPONE: [let POSTPONE: [let* } related-words
|
||||||
|
|
||||||
|
@ -75,10 +63,6 @@ HELP: [wlet
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
HELP: with-locals
|
|
||||||
{ $values { "form" "a quotation, lambda, let or wlet form" } { "quot" "a quotation" } }
|
|
||||||
{ $description "Performs closure conversion of a lexically-scoped form. All nested sub-forms are converted. This word must be applied to a " { $link POSTPONE: [| } ", " { $link POSTPONE: [let } " or " { $link POSTPONE: [wlet } " used in an ordinary definition, however forms in " { $link POSTPONE: :: } " and " { $link POSTPONE: MACRO:: } " definitions are automatically closure-converted and there is no need to use this word." } ;
|
|
||||||
|
|
||||||
HELP: ::
|
HELP: ::
|
||||||
{ $syntax ":: word ( bindings... -- outputs... ) body... ;" }
|
{ $syntax ":: word ( bindings... -- outputs... ) body... ;" }
|
||||||
{ $description "Defines a word with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope. Any " { $link POSTPONE: [| } ", " { $link POSTPONE: [let } " or " { $link POSTPONE: [wlet } " forms used in the body of the word definition are automatically closure-converted." }
|
{ $description "Defines a word with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope. Any " { $link POSTPONE: [| } ", " { $link POSTPONE: [let } " or " { $link POSTPONE: [wlet } " forms used in the body of the word definition are automatically closure-converted." }
|
||||||
|
@ -136,8 +120,6 @@ $nl
|
||||||
{ $subsection POSTPONE: :: }
|
{ $subsection POSTPONE: :: }
|
||||||
{ $subsection POSTPONE: MEMO:: }
|
{ $subsection POSTPONE: MEMO:: }
|
||||||
{ $subsection POSTPONE: MACRO:: }
|
{ $subsection POSTPONE: MACRO:: }
|
||||||
"Explicit closure conversion outside of applicative word definitions:"
|
|
||||||
{ $subsection with-locals }
|
|
||||||
"Lexical binding forms:"
|
"Lexical binding forms:"
|
||||||
{ $subsection POSTPONE: [let }
|
{ $subsection POSTPONE: [let }
|
||||||
{ $subsection POSTPONE: [let* }
|
{ $subsection POSTPONE: [let* }
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue