diff --git a/basis/alias/alias-docs.factor b/basis/alias/alias-docs.factor index 4dcf1a7738..3f2eee6460 100644 --- a/basis/alias/alias-docs.factor +++ b/basis/alias/alias-docs.factor @@ -16,7 +16,7 @@ HELP: ALIAS: } } ; -ARTICLE: "alias" "Alias" +ARTICLE: "alias" "Word aliasing" "The " { $vocab-link "alias" } " vocabulary implements a way to make many different names for the same word. Although creating new names for words is generally frowned upon, aliases are useful for the Win32 API and other cases where words need to be renamed for symmetry." $nl "Make a new word that aliases another word:" { $subsection define-alias } diff --git a/basis/bootstrap/image/image.factor b/basis/bootstrap/image/image.factor index 8b0051148f..c0fafdc0f5 100644 --- a/basis/bootstrap/image/image.factor +++ b/basis/bootstrap/image/image.factor @@ -134,6 +134,7 @@ SYMBOL: jit-epilog SYMBOL: jit-return SYMBOL: jit-profiling SYMBOL: jit-declare-word +SYMBOL: jit-save-stack ! Default definition for undefined words SYMBOL: undefined-quot @@ -158,6 +159,7 @@ SYMBOL: undefined-quot { jit-profiling 35 } { jit-push-immediate 36 } { jit-declare-word 42 } + { jit-save-stack 43 } { undefined-quot 60 } } at header-size + ; @@ -459,6 +461,7 @@ M: quotation ' jit-return jit-profiling jit-declare-word + jit-save-stack undefined-quot } [ emit-userenv ] each ; diff --git a/basis/bootstrap/stage2.factor b/basis/bootstrap/stage2.factor index 3b6c04329c..d25394e978 100644 --- a/basis/bootstrap/stage2.factor +++ b/basis/bootstrap/stage2.factor @@ -8,6 +8,8 @@ definitions assocs compiler.errors compiler.units math.parser generic sets debugger command-line ; IN: bootstrap.stage2 +SYMBOL: core-bootstrap-time + SYMBOL: bootstrap-time : default-image-name ( -- string ) @@ -30,11 +32,15 @@ SYMBOL: bootstrap-time : count-words ( pred -- ) all-words swap count number>string write ; -: print-report ( time -- ) +: print-time ( time -- ) 1000 /i 60 /mod swap - "Bootstrap completed in " write number>string write - " minutes and " write number>string write " seconds." print + number>string write + " minutes and " write number>string write " seconds." print ; + +: print-report ( -- ) + "Core bootstrap completed in " write core-bootstrap-time get print-time + "Bootstrap completed in " write bootstrap-time get print-time [ compiled>> ] count-words " compiled words" print [ symbol? ] count-words " symbol words" print @@ -46,7 +52,7 @@ SYMBOL: bootstrap-time [ ! We time bootstrap - millis >r + millis default-image-name "output-image" set-global @@ -71,6 +77,8 @@ SYMBOL: bootstrap-time [ load-components + millis over - core-bootstrap-time set-global + run-bootstrap-init ] with-compiler-errors :errors @@ -92,7 +100,7 @@ SYMBOL: bootstrap-time ] [ print-error 1 exit ] recover ] set-boot-quot - millis r> - dup bootstrap-time set-global + millis swap - bootstrap-time set-global print-report "output-image" get save-image-and-exit diff --git a/basis/compiler/cfg/builder/builder.factor b/basis/compiler/cfg/builder/builder.factor index 17a5942af2..7bad44f7a6 100755 --- a/basis/compiler/cfg/builder/builder.factor +++ b/basis/compiler/cfg/builder/builder.factor @@ -190,7 +190,7 @@ M: #if emit-node : emit-dispatch ( node -- ) ##epilogue - ds-pop ^^offset>slot i ##dispatch + ds-pop ^^offset>slot i 0 ##dispatch dispatch-branches ; : ( -- word ) @@ -221,21 +221,14 @@ M: #push emit-node literal>> ^^load-literal ds-push iterate-next ; ! #shuffle -: emit-shuffle ( effect -- ) - [ out>> ] [ in>> dup length ds-load zip ] bi - '[ _ at ] map ds-store ; - M: #shuffle emit-node - shuffle-effect emit-shuffle iterate-next ; - -M: #>r emit-node - [ in-d>> length ] [ out-r>> empty? ] bi - [ neg ##inc-d ] [ ds-load rs-store ] if - iterate-next ; - -M: #r> emit-node - [ in-r>> length ] [ out-d>> empty? ] bi - [ neg ##inc-r ] [ rs-load ds-store ] if + dup + H{ } clone + [ [ in-d>> [ length ds-load ] keep ] dip '[ _ set-at ] 2each ] + [ [ in-r>> [ length rs-load ] keep ] dip '[ _ set-at ] 2each ] + [ nip ] 2tri + [ [ [ out-d>> ] [ mapping>> ] bi ] dip '[ _ at _ at ] map ds-store ] + [ [ [ out-r>> ] [ mapping>> ] bi ] dip '[ _ at _ at ] map rs-store ] 2bi iterate-next ; ! #return diff --git a/basis/compiler/cfg/instructions/instructions.factor b/basis/compiler/cfg/instructions/instructions.factor index c39f517671..b2c752e612 100644 --- a/basis/compiler/cfg/instructions/instructions.factor +++ b/basis/compiler/cfg/instructions/instructions.factor @@ -62,7 +62,7 @@ INSN: ##jump word ; INSN: ##return ; ! Jump tables -INSN: ##dispatch src temp ; +INSN: ##dispatch src temp offset ; INSN: ##dispatch-label label ; ! Slot access diff --git a/basis/compiler/cfg/linearization/linearization.factor b/basis/compiler/cfg/linearization/linearization.factor index d397c9d448..7433df9617 100644 --- a/basis/compiler/cfg/linearization/linearization.factor +++ b/basis/compiler/cfg/linearization/linearization.factor @@ -43,8 +43,8 @@ M: ##branch linearize-insn : binary-conditional ( basic-block insn -- basic-block successor label2 src1 src2 cc ) [ (binary-conditional) ] - [ drop dup successors>> first useless-branch? ] 2bi - [ [ number>> ] 3dip negate-cc ] [ [ swap number>> ] 3dip ] if ; + [ drop dup successors>> second useless-branch? ] 2bi + [ [ swap number>> ] 3dip ] [ [ number>> ] 3dip negate-cc ] if ; M: ##compare-branch linearize-insn binary-conditional _compare-branch emit-branch ; diff --git a/basis/compiler/cfg/rpo/rpo.factor b/basis/compiler/cfg/rpo/rpo.factor index 7f4b09e68f..158903b4bf 100644 --- a/basis/compiler/cfg/rpo/rpo.factor +++ b/basis/compiler/cfg/rpo/rpo.factor @@ -9,7 +9,10 @@ SYMBOL: visited : post-order-traversal ( bb -- ) dup id>> visited get key? [ drop ] [ dup id>> visited get conjoin - [ successors>> [ post-order-traversal ] each ] [ , ] bi + [ + successors>> + [ post-order-traversal ] each + ] [ , ] bi ] if ; : post-order ( bb -- blocks ) diff --git a/basis/compiler/cfg/stacks/stacks.factor b/basis/compiler/cfg/stacks/stacks.factor index f138f673e0..c8fcae87c0 100755 --- a/basis/compiler/cfg/stacks/stacks.factor +++ b/basis/compiler/cfg/stacks/stacks.factor @@ -15,16 +15,28 @@ IN: compiler.cfg.stacks 1 ##inc-d D 0 ##replace ; : ds-load ( n -- vregs ) - [ [ ^^peek ] map ] [ neg ##inc-d ] bi ; + dup 0 = + [ drop f ] + [ [ [ ^^peek ] map ] [ neg ##inc-d ] bi ] if ; : ds-store ( vregs -- ) - [ length ##inc-d ] [ [ ##replace ] each-index ] bi ; + [ + + [ length ##inc-d ] + [ [ ##replace ] each-index ] bi + ] unless-empty ; : rs-load ( n -- vregs ) - [ [ ^^peek ] map ] [ neg ##inc-r ] bi ; + dup 0 = + [ drop f ] + [ [ [ ^^peek ] map ] [ neg ##inc-r ] bi ] if ; : rs-store ( vregs -- ) - [ length ##inc-r ] [ [ ##replace ] each-index ] bi ; + [ + + [ length ##inc-r ] + [ [ ##replace ] each-index ] bi + ] unless-empty ; : 2inputs ( -- vreg1 vreg2 ) D 1 ^^peek D 0 ^^peek -2 ##inc-d ; diff --git a/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor b/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor index 94c3f0d6f9..5f67f8097e 100644 --- a/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor +++ b/basis/compiler/cfg/value-numbering/rewrite/rewrite.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel sequences layouts accessors combinators namespaces -math +math fry compiler.cfg.instructions compiler.cfg.value-numbering.graph compiler.cfg.value-numbering.simplify @@ -113,4 +113,18 @@ M: ##compare-imm rewrite ] when ] when ; +: dispatch-offset ( expr -- n ) + [ in2>> vn>constant tag-bits get neg shift ] [ op>> ] bi + \ ##sub-imm eq? [ neg ] when ; + +: add-dispatch-offset? ( insn -- expr ? ) + src>> vreg>expr dup op>> { ##add-imm ##sub-imm } memq? ; inline + +M: ##dispatch rewrite + dup add-dispatch-offset? [ + [ clone ] dip + [ in1>> vn>vreg >>src ] + [ dispatch-offset '[ _ + ] change-offset ] bi + ] [ drop ] if ; + M: insn rewrite ; diff --git a/basis/compiler/cfg/value-numbering/value-numbering-tests.factor b/basis/compiler/cfg/value-numbering/value-numbering-tests.factor index d3be68c3c9..b73736ed14 100644 --- a/basis/compiler/cfg/value-numbering/value-numbering-tests.factor +++ b/basis/compiler/cfg/value-numbering/value-numbering-tests.factor @@ -34,7 +34,7 @@ compiler.cfg.registers cpu.architecture tools.test kernel math ; [ t ] [ { T{ ##peek f V int-regs 1 D 0 } - T{ ##dispatch f V int-regs 1 V int-regs 2 } + T{ ##dispatch f V int-regs 1 V int-regs 2 0 } } dup value-numbering = ] unit-test diff --git a/basis/compiler/codegen/codegen.factor b/basis/compiler/codegen/codegen.factor index 35d4d59253..0d45b28126 100644 --- a/basis/compiler/codegen/codegen.factor +++ b/basis/compiler/codegen/codegen.factor @@ -93,7 +93,7 @@ M: ##return generate-insn drop %return ; M: ##dispatch-label generate-insn label>> %dispatch-label ; M: ##dispatch generate-insn - [ src>> register ] [ temp>> register ] bi %dispatch ; + [ src>> register ] [ temp>> register ] [ offset>> ] tri %dispatch ; : >slot< { diff --git a/basis/compiler/codegen/fixup/fixup.factor b/basis/compiler/codegen/fixup/fixup.factor index fe270f4410..b25f1fa8fe 100755 --- a/basis/compiler/codegen/fixup/fixup.factor +++ b/basis/compiler/codegen/fixup/fixup.factor @@ -72,8 +72,8 @@ SYMBOL: literal-table : rel-this ( class -- ) 0 swap rt-label rel-fixup ; -: rel-here ( class -- ) - 0 swap rt-here rel-fixup ; +: rel-here ( offset class -- ) + rt-here rel-fixup ; : init-fixup ( -- ) BV{ } clone relocation-table set diff --git a/basis/compiler/constants/constants.factor b/basis/compiler/constants/constants.factor index cd68602768..86c1f65049 100644 --- a/basis/compiler/constants/constants.factor +++ b/basis/compiler/constants/constants.factor @@ -37,14 +37,15 @@ IN: compiler.constants : rc-indirect-arm-pc 8 ; inline ! Relocation types -: rt-primitive 0 ; inline -: rt-dlsym 1 ; inline -: rt-literal 2 ; inline -: rt-dispatch 3 ; inline -: rt-xt 4 ; inline -: rt-here 5 ; inline -: rt-label 6 ; inline -: rt-immediate 7 ; inline +: rt-primitive 0 ; inline +: rt-dlsym 1 ; inline +: rt-literal 2 ; inline +: rt-dispatch 3 ; inline +: rt-xt 4 ; inline +: rt-here 5 ; inline +: rt-label 6 ; inline +: rt-immediate 7 ; inline +: rt-stack-chain 8 ; inline : rc-absolute? ( n -- ? ) [ rc-absolute-ppc-2/2 = ] diff --git a/basis/compiler/tests/templates.factor b/basis/compiler/tests/codegen.factor similarity index 95% rename from basis/compiler/tests/templates.factor rename to basis/compiler/tests/codegen.factor index 0a109a15eb..a56ee55c82 100644 --- a/basis/compiler/tests/templates.factor +++ b/basis/compiler/tests/codegen.factor @@ -230,3 +230,14 @@ TUPLE: id obj ; 10000000 [ "hi" 0 (gc-check-bug) drop ] times ; [ ] [ gc-check-bug ] unit-test + +! New optimization +: test-1 ( a -- b ) 8 fixnum-fast { [ "a" ] [ "b" ] } dispatch ; + +[ "a" ] [ 8 test-1 ] unit-test +[ "b" ] [ 9 test-1 ] unit-test + +: test-2 ( a -- b ) 1 fixnum-fast { [ "a" ] [ "b" ] } dispatch ; + +[ "a" ] [ 1 test-2 ] unit-test +[ "b" ] [ 2 test-2 ] unit-test diff --git a/basis/compiler/tree/builder/builder.factor b/basis/compiler/tree/builder/builder.factor index 19d80ec14f..c2ec6552cd 100644 --- a/basis/compiler/tree/builder/builder.factor +++ b/basis/compiler/tree/builder/builder.factor @@ -1,9 +1,13 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: fry accessors quotations kernel sequences namespaces -assocs words arrays vectors hints combinators stack-checker -stack-checker.state stack-checker.visitor stack-checker.errors -stack-checker.backend compiler.tree ; +assocs words arrays vectors hints combinators compiler.tree +stack-checker +stack-checker.state +stack-checker.errors +stack-checker.visitor +stack-checker.backend +stack-checker.recursive-state ; IN: compiler.tree.builder : with-tree-builder ( quot -- nodes ) @@ -12,12 +16,13 @@ IN: compiler.tree.builder : build-tree ( quot -- nodes ) #! Not safe to call from inference transforms. - [ f infer-quot ] with-tree-builder nip ; + [ f initial-recursive-state infer-quot ] with-tree-builder nip ; : build-tree-with ( in-stack quot -- nodes out-stack ) #! Not safe to call from inference transforms. [ - [ >vector meta-d set ] [ f infer-quot ] bi* + [ >vector meta-d set ] + [ f initial-recursive-state infer-quot ] bi* ] with-tree-builder nip unclip-last in-d>> ; @@ -32,10 +37,10 @@ IN: compiler.tree.builder dup [ "inline" word-prop ] [ "recursive" word-prop ] bi and [ - 1quotation f infer-quot + 1quotation f initial-recursive-state infer-quot ] [ - [ specialized-def ] - [ dup 2array 1array ] bi infer-quot + [ specialized-def ] [ initial-recursive-state ] bi + infer-quot ] if ; : check-cannot-infer ( word -- ) diff --git a/basis/compiler/tree/checker/checker.factor b/basis/compiler/tree/checker/checker.factor index b712a6e354..4f99fa015d 100644 --- a/basis/compiler/tree/checker/checker.factor +++ b/basis/compiler/tree/checker/checker.factor @@ -22,8 +22,8 @@ ERROR: check-use-error value message ; GENERIC: check-node* ( node -- ) M: #shuffle check-node* - [ [ mapping>> values ] [ in-d>> ] bi subset? [ "Bad mapping inputs" throw ] unless ] - [ [ mapping>> keys ] [ out-d>> ] bi set= [ "Bad mapping outputs" throw ] unless ] + [ [ mapping>> values ] [ [ in-d>> ] [ in-r>> ] bi append ] bi subset? [ "Bad mapping inputs" throw ] unless ] + [ [ mapping>> keys ] [ [ out-d>> ] [ out-r>> ] bi append ] bi set= [ "Bad mapping outputs" throw ] unless ] bi ; : check-lengths ( seq -- ) @@ -31,13 +31,6 @@ M: #shuffle check-node* M: #copy check-node* inputs/outputs 2array check-lengths ; -: check->r/r> ( node -- ) - inputs/outputs [ drop ] [ 2array check-lengths ] if-empty ; - -M: #>r check-node* check->r/r> ; - -M: #r> check-node* check->r/r> ; - M: #return-recursive check-node* inputs/outputs 2array check-lengths ; M: #phi check-node* @@ -113,11 +106,8 @@ M: #push check-stack-flow* check-out-d ; M: #call check-stack-flow* [ check-in-d ] [ check-out-d ] bi ; -M: #shuffle check-stack-flow* [ check-in-d ] [ check-out-d ] bi ; - -M: #>r check-stack-flow* [ check-in-d ] [ check-out-r ] bi ; - -M: #r> check-stack-flow* [ check-in-r ] [ check-out-d ] bi ; +M: #shuffle check-stack-flow* + { [ check-in-d ] [ check-in-r ] [ check-out-d ] [ check-out-r ] } cleave ; : assert-datastack-empty ( -- ) datastack get empty? [ "Data stack not empty" throw ] unless ; diff --git a/basis/compiler/tree/cleanup/cleanup-tests.factor b/basis/compiler/tree/cleanup/cleanup-tests.factor index b77a27800f..4a6198db37 100644 --- a/basis/compiler/tree/cleanup/cleanup-tests.factor +++ b/basis/compiler/tree/cleanup/cleanup-tests.factor @@ -5,7 +5,7 @@ strings sbufs sequences.private slots.private combinators definitions system layouts vectors math.partial-dispatch math.order math.functions accessors hashtables classes assocs io.encodings.utf8 io.encodings.ascii io.encodings fry slots -sorting.private combinators.short-circuit +sorting.private combinators.short-circuit grouping prettyprint compiler.tree compiler.tree.combinators compiler.tree.cleanup @@ -500,3 +500,13 @@ cell-bits 32 = [ [ { array-capacity } declare 1 fixnum+ ] cleaned-up-tree [ { [ #call? ] [ node-input-infos second literal>> 1 = ] } 1&& ] contains? ] unit-test + +[ ] [ + [ { null } declare [ 1 ] [ 2 ] if ] + build-tree normalize propagate cleanup check-nodes +] unit-test + +[ t ] [ + [ { array } declare 2 [ . . ] assoc-each ] + \ nth-unsafe inlined? +] unit-test diff --git a/basis/compiler/tree/cleanup/cleanup.factor b/basis/compiler/tree/cleanup/cleanup.factor index 4ca058b2e3..becac01cd5 100644 --- a/basis/compiler/tree/cleanup/cleanup.factor +++ b/basis/compiler/tree/cleanup/cleanup.factor @@ -102,7 +102,7 @@ M: #declare cleanup* drop f ; #! If only one branch is live we don't need to branch at #! all; just drop the condition value. dup live-children sift dup length { - { 0 [ 2drop f ] } + { 0 [ drop in-d>> #drop ] } { 1 [ first swap in-d>> #drop prefix ] } [ 2drop ] } case ; diff --git a/basis/compiler/tree/dead-code/branches/branches.factor b/basis/compiler/tree/dead-code/branches/branches.factor index 719c80f911..eba82384ab 100644 --- a/basis/compiler/tree/dead-code/branches/branches.factor +++ b/basis/compiler/tree/dead-code/branches/branches.factor @@ -39,7 +39,7 @@ M: #branch remove-dead-code* [ drop filter-live ] [ swap nths ] 2bi [ make-values ] keep [ drop ] [ zip ] 2bi - #shuffle ; + #data-shuffle ; : insert-drops ( nodes values indices -- nodes' ) '[ diff --git a/basis/compiler/tree/dead-code/simple/simple.factor b/basis/compiler/tree/dead-code/simple/simple.factor index addb13ced3..185c776c4e 100644 --- a/basis/compiler/tree/dead-code/simple/simple.factor +++ b/basis/compiler/tree/dead-code/simple/simple.factor @@ -39,12 +39,6 @@ M: #copy compute-live-values* M: #call compute-live-values* nip look-at-inputs ; -M: #>r compute-live-values* - [ out-r>> ] [ in-d>> ] bi look-at-mapping ; - -M: #r> compute-live-values* - [ out-d>> ] [ in-r>> ] bi look-at-mapping ; - M: #shuffle compute-live-values* mapping>> at look-at-value ; @@ -61,7 +55,7 @@ M: #alien-indirect compute-live-values* nip look-at-inputs ; zip filter-mapping values ; : filter-live ( values -- values' ) - [ live-value? ] filter ; + dup empty? [ [ live-value? ] filter ] unless ; :: drop-values ( inputs outputs mapping-keys mapping-values -- #shuffle ) inputs @@ -69,7 +63,7 @@ M: #alien-indirect compute-live-values* nip look-at-inputs ; outputs mapping-keys mapping-values - filter-corresponding zip #shuffle ; inline + filter-corresponding zip #data-shuffle ; inline :: drop-dead-values ( outputs -- #shuffle ) [let* | new-outputs [ outputs make-values ] @@ -95,16 +89,6 @@ M: #alien-indirect compute-live-values* nip look-at-inputs ; M: #introduce remove-dead-code* ( #introduce -- nodes ) maybe-drop-dead-outputs ; -M: #>r remove-dead-code* - [ filter-live ] change-out-r - [ filter-live ] change-in-d - dup in-d>> empty? [ drop f ] when ; - -M: #r> remove-dead-code* - [ filter-live ] change-out-d - [ filter-live ] change-in-r - dup in-r>> empty? [ drop f ] when ; - M: #push remove-dead-code* dup out-d>> first live-value? [ drop f ] unless ; @@ -125,12 +109,14 @@ M: #call remove-dead-code* M: #shuffle remove-dead-code* [ filter-live ] change-in-d [ filter-live ] change-out-d + [ filter-live ] change-in-r + [ filter-live ] change-out-r [ filter-mapping ] change-mapping - dup in-d>> empty? [ drop f ] when ; + dup [ in-d>> empty? ] [ in-r>> empty? ] bi and [ drop f ] when ; M: #copy remove-dead-code* [ in-d>> ] [ out-d>> ] bi - 2dup swap zip #shuffle + 2dup swap zip #data-shuffle remove-dead-code* ; M: #terminate remove-dead-code* diff --git a/basis/compiler/tree/debugger/debugger.factor b/basis/compiler/tree/debugger/debugger.factor index 59a028a4f4..a1d8773484 100644 --- a/basis/compiler/tree/debugger/debugger.factor +++ b/basis/compiler/tree/debugger/debugger.factor @@ -3,7 +3,7 @@ USING: kernel assocs match fry accessors namespaces make effects sequences sequences.private quotations generic macros arrays prettyprint prettyprint.backend prettyprint.sections math words -combinators io sorting hints qualified +combinators combinators.short-circuit io sorting hints qualified compiler.tree compiler.tree.recursive compiler.tree.normalization @@ -57,9 +57,41 @@ TUPLE: shuffle-node { effect effect } ; M: shuffle-node pprint* effect>> effect>string text ; +: (shuffle-effect) ( in out #shuffle -- effect ) + mapping>> '[ _ at ] map ; + +: shuffle-effect ( #shuffle -- effect ) + [ in-d>> ] [ out-d>> ] [ ] tri (shuffle-effect) ; + +: #>r? ( #shuffle -- ? ) + { + [ in-d>> length 1 = ] + [ out-r>> length 1 = ] + [ in-r>> empty? ] + [ out-d>> empty? ] + } 1&& ; + +: #r>? ( #shuffle -- ? ) + { + [ in-d>> empty? ] + [ out-r>> empty? ] + [ in-r>> length 1 = ] + [ out-d>> length 1 = ] + } 1&& ; + M: #shuffle node>quot - shuffle-effect dup pretty-shuffle - [ % ] [ shuffle-node boa , ] ?if ; + { + { [ dup #>r? ] [ drop \ >r , ] } + { [ dup #r>? ] [ drop \ r> , ] } + { + [ dup [ in-r>> empty? ] [ out-r>> empty? ] bi and ] + [ + shuffle-effect dup pretty-shuffle + [ % ] [ shuffle-node boa , ] ?if + ] + } + [ drop "COMPLEX SHUFFLE" , ] + } cond ; M: #push node>quot literal>> , ; @@ -82,16 +114,6 @@ M: #if node>quot M: #dispatch node>quot children>> [ nodes>quot ] map , \ dispatch , ; -M: #>r node>quot - [ in-d>> length ] [ out-r>> empty? \ drop \ >r ? ] bi - % ; - -DEFER: rdrop - -M: #r> node>quot - [ in-r>> length ] [ out-d>> empty? \ rdrop \ r> ? ] bi - % ; - M: #alien-invoke node>quot params>> , \ #alien-invoke , ; M: #alien-indirect node>quot params>> , \ #alien-indirect , ; diff --git a/basis/compiler/tree/def-use/def-use.factor b/basis/compiler/tree/def-use/def-use.factor index 2379f3918d..9be9f13043 100644 --- a/basis/compiler/tree/def-use/def-use.factor +++ b/basis/compiler/tree/def-use/def-use.factor @@ -38,16 +38,16 @@ GENERIC: node-uses-values ( node -- values ) M: #introduce node-uses-values drop f ; M: #push node-uses-values drop f ; -M: #r> node-uses-values in-r>> ; M: #phi node-uses-values phi-in-d>> concat remove-bottom prune ; M: #declare node-uses-values declaration>> keys ; M: #terminate node-uses-values [ in-d>> ] [ in-r>> ] bi append ; +M: #shuffle node-uses-values [ in-d>> ] [ in-r>> ] bi append ; M: #alien-callback node-uses-values drop f ; M: node node-uses-values in-d>> ; GENERIC: node-defs-values ( node -- values ) -M: #>r node-defs-values out-r>> ; +M: #shuffle node-defs-values [ out-d>> ] [ out-r>> ] bi append ; M: #branch node-defs-values drop f ; M: #declare node-defs-values drop f ; M: #return node-defs-values drop f ; diff --git a/basis/compiler/tree/escape-analysis/allocations/allocations.factor b/basis/compiler/tree/escape-analysis/allocations/allocations.factor index 4c197d7fc0..5d34eaad15 100644 --- a/basis/compiler/tree/escape-analysis/allocations/allocations.factor +++ b/basis/compiler/tree/escape-analysis/allocations/allocations.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs namespaces sequences kernel math -combinators sets disjoint-sets fry stack-checker.state ; +combinators sets disjoint-sets fry stack-checker.values ; IN: compiler.tree.escape-analysis.allocations ! A map from values to one of the following: diff --git a/basis/compiler/tree/escape-analysis/escape-analysis-tests.factor b/basis/compiler/tree/escape-analysis/escape-analysis-tests.factor index 4ed194e81d..9a226b954f 100644 --- a/basis/compiler/tree/escape-analysis/escape-analysis-tests.factor +++ b/basis/compiler/tree/escape-analysis/escape-analysis-tests.factor @@ -8,6 +8,7 @@ math.private kernel tools.test accessors slots.private quotations.private prettyprint classes.tuple.private classes classes.tuple namespaces compiler.tree.propagation.info stack-checker.errors +compiler.tree.checker kernel.private ; \ escape-analysis must-infer @@ -34,6 +35,7 @@ M: node count-unboxed-allocations* drop ; propagate cleanup escape-analysis + dup check-nodes 0 swap [ count-unboxed-allocations* ] each-node ; [ 0 ] [ [ [ + ] curry ] count-unboxed-allocations ] unit-test @@ -307,7 +309,7 @@ C: ro-box : bleach-node ( quot: ( node -- ) -- ) [ bleach-node ] curry [ ] compose impeach-node ; inline recursive -[ 2 ] [ [ [ ] bleach-node ] count-unboxed-allocations ] unit-test +[ 3 ] [ [ [ ] bleach-node ] count-unboxed-allocations ] unit-test [ 0 ] [ [ dup -1 over >= [ 0 >= [ "A" throw ] unless ] [ drop ] if ] diff --git a/basis/compiler/tree/finalization/finalization.factor b/basis/compiler/tree/finalization/finalization.factor index 2d2e429994..16a27e020a 100644 --- a/basis/compiler/tree/finalization/finalization.factor +++ b/basis/compiler/tree/finalization/finalization.factor @@ -1,6 +1,7 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel accessors sequences words memoize classes.builtin +fry assocs compiler.tree compiler.tree.combinators compiler.tree.propagation.info @@ -27,9 +28,10 @@ GENERIC: finalize* ( node -- nodes ) M: #copy finalize* drop f ; M: #shuffle finalize* - dup shuffle-effect - [ in>> ] [ out>> ] bi sequence= - [ drop f ] when ; + dup + [ [ in-d>> ] [ out-d>> ] [ mapping>> ] tri '[ _ at ] map sequence= ] + [ [ in-r>> ] [ out-r>> ] [ mapping>> ] tri '[ _ at ] map sequence= ] + bi and [ drop f ] when ; : builtin-predicate? ( #call -- ? ) word>> "predicating" word-prop builtin-class? ; diff --git a/basis/compiler/tree/identities/identities.factor b/basis/compiler/tree/identities/identities.factor index d6ed59cbaa..00632ec6f6 100644 --- a/basis/compiler/tree/identities/identities.factor +++ b/basis/compiler/tree/identities/identities.factor @@ -79,7 +79,7 @@ GENERIC: apply-identities* ( node -- node ) : select-input ( node n -- #shuffle ) [ [ in-d>> ] [ out-d>> ] bi ] dip - pick nth over first associate #shuffle ; + pick nth over first associate #data-shuffle ; M: #call apply-identities* dup word>> "identities" word-prop [ diff --git a/basis/compiler/tree/normalization/renaming/renaming.factor b/basis/compiler/tree/normalization/renaming/renaming.factor index 3050df2611..9d68f4a733 100644 --- a/basis/compiler/tree/normalization/renaming/renaming.factor +++ b/basis/compiler/tree/normalization/renaming/renaming.factor @@ -10,7 +10,7 @@ SYMBOL: rename-map [ rename-map get at ] keep or ; : rename-values ( values -- values' ) - rename-map get '[ [ _ at ] keep or ] map ; + dup empty? [ rename-map get '[ [ _ at ] keep or ] map ] unless ; : add-renamings ( old new -- ) [ rename-values ] dip @@ -22,13 +22,11 @@ M: #introduce rename-node-values* ; M: #shuffle rename-node-values* [ rename-values ] change-in-d + [ rename-values ] change-in-r [ [ rename-value ] assoc-map ] change-mapping ; M: #push rename-node-values* ; -M: #r> rename-node-values* - [ rename-values ] change-in-r ; - M: #terminate rename-node-values* [ rename-values ] change-in-d [ rename-values ] change-in-r ; diff --git a/basis/compiler/tree/propagation/branches/branches.factor b/basis/compiler/tree/propagation/branches/branches.factor index c76217f8ae..424cd8a01c 100644 --- a/basis/compiler/tree/propagation/branches/branches.factor +++ b/basis/compiler/tree/propagation/branches/branches.factor @@ -40,8 +40,8 @@ M: #dispatch live-branches SYMBOL: infer-children-data : copy-value-info ( -- ) - value-infos [ clone ] change - constraints [ clone ] change ; + value-infos [ H{ } clone suffix ] change + constraints [ H{ } clone suffix ] change ; : no-value-info ( -- ) value-infos off diff --git a/basis/compiler/tree/propagation/constraints/constraints.factor b/basis/compiler/tree/propagation/constraints/constraints.factor index cfdf7f5169..2652547aad 100644 --- a/basis/compiler/tree/propagation/constraints/constraints.factor +++ b/basis/compiler/tree/propagation/constraints/constraints.factor @@ -32,7 +32,7 @@ TUPLE: true-constraint value ; M: true-constraint assume* [ \ f class-not swap value>> refine-value-info ] - [ constraints get at [ assume ] when* ] + [ constraints get assoc-stack [ assume ] when* ] bi ; M: true-constraint satisfied? @@ -44,7 +44,7 @@ TUPLE: false-constraint value ; M: false-constraint assume* [ \ f swap value>> refine-value-info ] - [ constraints get at [ assume ] when* ] + [ constraints get assoc-stack [ assume ] when* ] bi ; M: false-constraint satisfied? @@ -83,7 +83,7 @@ TUPLE: implication p q ; C: --> implication : assume-implication ( p q -- ) - [ constraints get [ swap suffix ] change-at ] + [ constraints get [ assoc-stack swap suffix ] 2keep peek set-at ] [ satisfied? [ assume ] [ drop ] if ] 2bi ; M: implication assume* diff --git a/basis/compiler/tree/propagation/info/info-tests.factor b/basis/compiler/tree/propagation/info/info-tests.factor index 24f4ca59dc..2c3314994b 100644 --- a/basis/compiler/tree/propagation/info/info-tests.factor +++ b/basis/compiler/tree/propagation/info/info-tests.factor @@ -70,3 +70,7 @@ TUPLE: test-tuple { x read-only } ; f f 3 3array test-tuple dup object-info value-info-intersect = ] unit-test + +[ t ] [ + null-info 3 value-info<= +] unit-test diff --git a/basis/compiler/tree/propagation/info/info.factor b/basis/compiler/tree/propagation/info/info.factor index d1d8189f7a..e89a9c6211 100644 --- a/basis/compiler/tree/propagation/info/info.factor +++ b/basis/compiler/tree/propagation/info/info.factor @@ -34,7 +34,7 @@ slots ; : null-info T{ value-info f null empty-interval } ; inline -: object-info T{ value-info f object T{ interval f { -1.0/0.0 t } { 1.0/0.0 t } } } ; inline +: object-info T{ value-info f object full-interval } ; inline : class-interval ( class -- interval ) dup real class<= @@ -43,7 +43,7 @@ slots ; : interval>literal ( class interval -- literal literal? ) #! If interval has zero length and the class is sufficiently #! precise, we can turn it into a literal - dup empty-interval eq? [ + dup special-interval? [ 2drop f f ] [ dup from>> first { @@ -243,7 +243,7 @@ DEFER: (value-info-union) : literals<= ( info1 info2 -- ? ) { { [ dup literal?>> not ] [ 2drop t ] } - { [ over literal?>> not ] [ 2drop f ] } + { [ over literal?>> not ] [ drop class>> null-class? ] } [ [ literal>> ] bi@ eql? ] } cond ; @@ -262,17 +262,19 @@ DEFER: (value-info-union) ] } cond ; -! Current value --> info mapping +! Assoc stack of current value --> info mapping SYMBOL: value-infos : value-info ( value -- info ) - resolve-copy value-infos get at null-info or ; + resolve-copy value-infos get assoc-stack null-info or ; : set-value-info ( info value -- ) - resolve-copy value-infos get set-at ; + resolve-copy value-infos get peek set-at ; : refine-value-info ( info value -- ) - resolve-copy value-infos get [ value-info-intersect ] change-at ; + resolve-copy value-infos get + [ assoc-stack value-info-intersect ] 2keep + peek set-at ; : value-literal ( value -- obj ? ) value-info >literal< ; diff --git a/basis/compiler/tree/propagation/propagation-tests.factor b/basis/compiler/tree/propagation/propagation-tests.factor index 101320f92c..760ff167aa 100644 --- a/basis/compiler/tree/propagation/propagation-tests.factor +++ b/basis/compiler/tree/propagation/propagation-tests.factor @@ -8,7 +8,7 @@ math.functions math.private strings layouts compiler.tree.propagation.info compiler.tree.def-use compiler.tree.debugger compiler.tree.checker slots.private words hashtables classes assocs locals -float-arrays system ; +float-arrays system sorting ; IN: compiler.tree.propagation.tests \ propagate must-infer @@ -592,6 +592,8 @@ MIXIN: empty-mixin [ V{ t } ] [ [ netbsd unix? ] final-literals ] unit-test +[ V{ array } ] [ [ [ <=> ] sort [ <=> ] sort ] final-classes ] unit-test + ! [ V{ string } ] [ ! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes ! ] unit-test diff --git a/basis/compiler/tree/propagation/propagation.factor b/basis/compiler/tree/propagation/propagation.factor index d82ebed433..b9822d2c6b 100644 --- a/basis/compiler/tree/propagation/propagation.factor +++ b/basis/compiler/tree/propagation/propagation.factor @@ -1,6 +1,6 @@ ! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: accessors kernel sequences namespaces hashtables +USING: accessors kernel sequences namespaces hashtables arrays compiler.tree compiler.tree.propagation.copy compiler.tree.propagation.info @@ -17,7 +17,7 @@ IN: compiler.tree.propagation : propagate ( node -- node ) H{ } clone copies set - H{ } clone constraints set - H{ } clone value-infos set + H{ } clone 1array value-infos set + H{ } clone 1array constraints set dup count-nodes dup (propagate) ; diff --git a/basis/compiler/tree/propagation/recursive/recursive.factor b/basis/compiler/tree/propagation/recursive/recursive.factor index 53dce813a3..7f10f87016 100644 --- a/basis/compiler/tree/propagation/recursive/recursive.factor +++ b/basis/compiler/tree/propagation/recursive/recursive.factor @@ -17,9 +17,12 @@ IN: compiler.tree.propagation.recursive [ value-info<= ] 2all? [ drop ] [ label>> f >>fixed-point drop ] if ; +: latest-input-infos ( node -- infos ) + in-d>> [ value-info ] map ; + : recursive-stacks ( #enter-recursive -- stacks initial ) [ label>> calls>> [ node-input-infos ] map flip ] - [ in-d>> [ value-info ] map ] bi ; + [ latest-input-infos ] bi ; : generalize-counter-interval ( interval initial-interval -- interval' ) { @@ -46,14 +49,13 @@ IN: compiler.tree.propagation.recursive ] if ; : propagate-recursive-phi ( #enter-recursive -- ) - [ ] [ recursive-stacks unify-recursive-stacks ] [ ] tri - [ node-output-infos check-fixed-point ] - [ out-d>> set-value-infos drop ] - 3bi ; + [ recursive-stacks unify-recursive-stacks ] keep + out-d>> set-value-infos ; M: #recursive propagate-around ( #recursive -- ) + constraints [ H{ } clone suffix ] change [ - constraints [ clone ] change + constraints [ but-last H{ } clone suffix ] change child>> [ first compute-copy-equiv ] @@ -62,6 +64,9 @@ M: #recursive propagate-around ( #recursive -- ) tri ] until-fixed-point ; +: recursive-phi-infos ( node -- infos ) + label>> enter-recursive>> node-output-infos ; + : generalize-return-interval ( info -- info' ) dup [ literal?>> ] [ class>> null-class? ] bi or [ clone [-inf,inf] >>interval ] unless ; @@ -70,12 +75,25 @@ M: #recursive propagate-around ( #recursive -- ) [ generalize-return-interval ] map ; : return-infos ( node -- infos ) - label>> [ return>> node-input-infos ] [ loop?>> ] bi - [ generalize-return ] unless ; + label>> return>> node-input-infos generalize-return ; + +: save-return-infos ( node infos -- ) + swap out-d>> set-value-infos ; + +: unless-loop ( node quot -- ) + [ dup label>> loop?>> [ drop ] ] dip if ; inline M: #call-recursive propagate-before ( #call-recursive -- ) - [ ] [ return-infos ] [ node-output-infos ] tri - [ check-fixed-point ] [ drop swap out-d>> set-value-infos ] 3bi ; + [ + [ ] [ latest-input-infos ] [ recursive-phi-infos ] tri + check-fixed-point + ] + [ + [ + [ ] [ return-infos ] [ node-output-infos ] tri + [ check-fixed-point ] [ drop save-return-infos ] 3bi + ] unless-loop + ] bi ; M: #call-recursive annotate-node dup [ in-d>> ] [ out-d>> ] bi append (annotate-node) ; @@ -83,5 +101,11 @@ M: #call-recursive annotate-node M: #enter-recursive annotate-node dup out-d>> (annotate-node) ; +M: #return-recursive propagate-before ( #return-recursive -- ) + [ + [ ] [ latest-input-infos ] [ node-input-infos ] tri + check-fixed-point + ] unless-loop ; + M: #return-recursive annotate-node dup in-d>> (annotate-node) ; diff --git a/basis/compiler/tree/tree.factor b/basis/compiler/tree/tree.factor index 05f33902ec..9f9a43df64 100644 --- a/basis/compiler/tree/tree.factor +++ b/basis/compiler/tree/tree.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: fry arrays generic assocs kernel math namespaces parser -sequences words vectors math.intervals effects classes +sequences words vectors math.intervals classes accessors combinators stack-checker.state stack-checker.visitor stack-checker.inlining ; IN: compiler.tree @@ -42,30 +42,21 @@ TUPLE: #push < node literal out-d ; TUPLE: #renaming < node ; -TUPLE: #shuffle < #renaming mapping in-d out-d ; +TUPLE: #shuffle < #renaming mapping in-d out-d in-r out-r ; -: #shuffle ( inputs outputs mapping -- node ) +: #shuffle ( in-d out-d in-r out-r mapping -- node ) \ #shuffle new swap >>mapping + swap >>out-r + swap >>in-r swap >>out-d swap >>in-d ; +: #data-shuffle ( in-d out-d mapping -- node ) + [ f f ] dip #shuffle ; inline + : #drop ( inputs -- node ) - { } { } #shuffle ; - -TUPLE: #>r < #renaming in-d out-r ; - -: #>r ( inputs outputs -- node ) - \ #>r new - swap >>out-r - swap >>in-d ; - -TUPLE: #r> < #renaming in-r out-d ; - -: #r> ( inputs outputs -- node ) - \ #r> new - swap >>out-d - swap >>in-r ; + { } { } #data-shuffle ; TUPLE: #terminate < node in-d in-r ; @@ -171,16 +162,9 @@ TUPLE: #alien-callback < #alien-node ; GENERIC: inputs/outputs ( #renaming -- inputs outputs ) M: #shuffle inputs/outputs mapping>> unzip swap ; -M: #>r inputs/outputs [ in-d>> ] [ out-r>> ] bi ; -M: #r> inputs/outputs [ in-r>> ] [ out-d>> ] bi ; M: #copy inputs/outputs [ in-d>> ] [ out-d>> ] bi ; M: #return-recursive inputs/outputs [ in-d>> ] [ out-d>> ] bi ; -: shuffle-effect ( #shuffle -- effect ) - [ in-d>> ] [ out-d>> ] [ mapping>> ] tri - '[ _ at ] map - ; - : recursive-phi-in ( #enter-recursive -- seq ) [ label>> calls>> [ in-d>> ] map ] [ in-d>> ] bi suffix ; @@ -193,8 +177,8 @@ M: vector #call, #call node, ; M: vector #push, #push node, ; M: vector #shuffle, #shuffle node, ; M: vector #drop, #drop node, ; -M: vector #>r, #>r node, ; -M: vector #r>, #r> node, ; +M: vector #>r, [ [ f f ] dip ] [ swap zip ] 2bi #shuffle, ; +M: vector #r>, [ swap [ f swap ] dip f ] [ swap zip ] 2bi #shuffle, ; M: vector #return, #return node, ; M: vector #enter-recursive, #enter-recursive node, ; M: vector #return-recursive, #return-recursive node, ; diff --git a/basis/compiler/tree/tuple-unboxing/tuple-unboxing.factor b/basis/compiler/tree/tuple-unboxing/tuple-unboxing.factor index 8e07c08194..52903fce8d 100644 --- a/basis/compiler/tree/tuple-unboxing/tuple-unboxing.factor +++ b/basis/compiler/tree/tuple-unboxing/tuple-unboxing.factor @@ -42,7 +42,7 @@ M: #push unbox-tuples* ( #push -- nodes ) [ dup unboxed-allocation [ (flatten-values) ] [ ] ?if ] map ; : flatten-values ( values -- values' ) - (flatten-values) flatten ; + dup empty? [ (flatten-values) flatten ] unless ; : prepare-slot-access ( #call -- tuple-values outputs slot-values ) [ in-d>> flatten-values ] @@ -54,7 +54,7 @@ M: #push unbox-tuples* ( #push -- nodes ) ] tri ; : slot-access-shuffle ( tuple-values outputs slot-values -- #shuffle ) - [ drop ] [ zip ] 2bi #shuffle ; + [ drop ] [ zip ] 2bi #data-shuffle ; : unbox-slot-access ( #call -- nodes ) dup out-d>> first unboxed-slot-access? [ @@ -77,17 +77,11 @@ M: #copy unbox-tuples* [ flatten-values ] change-in-d [ flatten-values ] change-out-d ; -M: #>r unbox-tuples* - [ flatten-values ] change-in-d - [ flatten-values ] change-out-r ; - -M: #r> unbox-tuples* - [ flatten-values ] change-in-r - [ flatten-values ] change-out-d ; - M: #shuffle unbox-tuples* [ flatten-values ] change-in-d [ flatten-values ] change-out-d + [ flatten-values ] change-in-r + [ flatten-values ] change-out-r [ unzip [ flatten-values ] bi@ zip ] change-mapping ; M: #terminate unbox-tuples* diff --git a/basis/cpu/architecture/architecture.factor b/basis/cpu/architecture/architecture.factor index b0b5b048d9..96dd577c10 100644 --- a/basis/cpu/architecture/architecture.factor +++ b/basis/cpu/architecture/architecture.factor @@ -50,7 +50,7 @@ HOOK: %call cpu ( word -- ) HOOK: %jump-label cpu ( label -- ) HOOK: %return cpu ( -- ) -HOOK: %dispatch cpu ( src temp -- ) +HOOK: %dispatch cpu ( src temp offset -- ) HOOK: %dispatch-label cpu ( word -- ) HOOK: %slot cpu ( dst obj slot tag temp -- ) diff --git a/basis/cpu/ppc/bootstrap.factor b/basis/cpu/ppc/bootstrap.factor index 9bf88185c5..aee0f3f4f3 100644 --- a/basis/cpu/ppc/bootstrap.factor +++ b/basis/cpu/ppc/bootstrap.factor @@ -57,7 +57,12 @@ big-endian on [ 0 6 LOAD32 - 4 1 MR + 7 6 0 LWZ + 1 7 0 STW +] rc-absolute-ppc-2/2 rt-stack-chain 1 jit-save-stack jit-define + +[ + 0 6 LOAD32 6 MTCTR BCTR ] rc-absolute-ppc-2/2 rt-primitive 1 jit-primitive jit-define diff --git a/basis/cpu/ppc/ppc.factor b/basis/cpu/ppc/ppc.factor index 49caae4bb8..c656ae4d89 100644 --- a/basis/cpu/ppc/ppc.factor +++ b/basis/cpu/ppc/ppc.factor @@ -111,10 +111,10 @@ M: ppc %call ( label -- ) BL ; M: ppc %jump-label ( label -- ) B ; M: ppc %return ( -- ) BLR ; -M:: ppc %dispatch ( src temp -- ) - 0 temp LOAD32 rc-absolute-ppc-2/2 rel-here - temp temp src ADD - temp temp 5 cells LWZ +M:: ppc %dispatch ( src temp offset -- ) + 0 temp LOAD32 + 4 offset + cells rc-absolute-ppc-2/2 rel-here + temp temp src LWZX temp MTCTR BCTR ; diff --git a/basis/cpu/x86/32/32.factor b/basis/cpu/x86/32/32.factor index f26d76551a..f892271fd5 100644 --- a/basis/cpu/x86/32/32.factor +++ b/basis/cpu/x86/32/32.factor @@ -6,7 +6,7 @@ accessors init combinators command-line cpu.x86.assembler cpu.x86 cpu.architecture compiler compiler.units compiler.constants compiler.alien compiler.codegen compiler.codegen.fixup compiler.cfg.instructions -compiler.cfg.builder compiler.cfg.intrinsics ; +compiler.cfg.builder compiler.cfg.intrinsics make ; IN: cpu.x86.32 ! We implement the FFI for Linux, OS X and Windows all at once. @@ -26,6 +26,18 @@ M: x86.32 stack-reg ESP ; M: x86.32 temp-reg-1 EAX ; M: x86.32 temp-reg-2 ECX ; +M:: x86.32 %dispatch ( src temp offset -- ) + ! Load jump table base. + src HEX: ffffffff ADD + offset cells rc-absolute-cell rel-here + ! Go + src HEX: 7f [+] JMP + ! Fix up the displacement above + cell code-alignment + [ 7 + building get dup pop* push ] + [ align-code ] + bi ; + M: x86.32 reserved-area-size 0 ; M: x86.32 %alien-global 0 [] MOV rc-absolute-cell rel-dlsym ; diff --git a/basis/cpu/x86/32/bootstrap.factor b/basis/cpu/x86/32/bootstrap.factor index 44f840e66a..ba963ab477 100644 --- a/basis/cpu/x86/32/bootstrap.factor +++ b/basis/cpu/x86/32/bootstrap.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: bootstrap.image.private kernel namespaces system -cpu.x86.assembler layouts vocabs parser ; +cpu.x86.assembler layouts vocabs parser compiler.constants ; IN: bootstrap.x86 4 \ cell set @@ -19,5 +19,14 @@ IN: bootstrap.x86 : fixnum>slot@ ( -- ) arg0 1 SAR ; : rex-length ( -- n ) 0 ; +[ + arg0 0 [] MOV ! load stack_chain + arg0 [] stack-reg MOV ! save stack pointer +] rc-absolute-cell rt-stack-chain 2 jit-save-stack jit-define + +[ + (JMP) drop +] rc-relative rt-primitive 1 jit-primitive jit-define + << "resource:basis/cpu/x86/bootstrap.factor" parse-file parsed >> call diff --git a/basis/cpu/x86/64/64.factor b/basis/cpu/x86/64/64.factor index 0d20660021..75c808b50a 100644 --- a/basis/cpu/x86/64/64.factor +++ b/basis/cpu/x86/64/64.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays kernel math namespaces make sequences system layouts alien alien.c-types alien.accessors alien.structs -slots splitting assocs combinators cpu.x86.assembler +slots splitting assocs combinators make locals cpu.x86.assembler cpu.x86 cpu.architecture compiler.constants compiler.codegen compiler.codegen.fixup compiler.cfg.instructions compiler.cfg.builder @@ -24,6 +24,19 @@ M: x86.64 stack-reg RSP ; M: x86.64 temp-reg-1 RAX ; M: x86.64 temp-reg-2 RCX ; +M:: x86.64 %dispatch ( src temp offset -- ) + ! Load jump table base. + temp HEX: ffffffff MOV + offset cells rc-absolute-cell rel-here + ! Add jump table base + src temp ADD + src HEX: 7f [+] JMP + ! Fix up the displacement above + cell code-alignment + [ 15 + building get dup pop* push ] + [ align-code ] + bi ; + : param-reg-1 int-regs param-regs first ; inline : param-reg-2 int-regs param-regs second ; inline : param-reg-3 int-regs param-regs third ; inline diff --git a/basis/cpu/x86/64/bootstrap.factor b/basis/cpu/x86/64/bootstrap.factor index acac8b55bc..83a72d6dd3 100644 --- a/basis/cpu/x86/64/bootstrap.factor +++ b/basis/cpu/x86/64/bootstrap.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: bootstrap.image.private kernel namespaces system -cpu.x86.assembler layouts vocabs parser ; +cpu.x86.assembler layouts vocabs parser compiler.constants math ; IN: bootstrap.x86 8 \ cell set @@ -16,5 +16,16 @@ IN: bootstrap.x86 : fixnum>slot@ ( -- ) ; : rex-length ( -- n ) 1 ; +[ + arg0 0 MOV ! load stack_chain + arg0 arg0 [] MOV + arg0 [] stack-reg MOV ! save stack pointer +] rc-absolute-cell rt-stack-chain 1 rex-length + jit-save-stack jit-define + +[ + arg1 0 MOV ! load XT + arg1 JMP ! go +] rc-absolute-cell rt-primitive 1 rex-length + jit-primitive jit-define + << "resource:basis/cpu/x86/bootstrap.factor" parse-file parsed >> call diff --git a/basis/cpu/x86/bootstrap.factor b/basis/cpu/x86/bootstrap.factor index 6dadbc096c..1ee74a434b 100644 --- a/basis/cpu/x86/bootstrap.factor +++ b/basis/cpu/x86/bootstrap.factor @@ -44,12 +44,6 @@ big-endian off ds-reg [] arg0 MOV ! store literal on datastack ] rc-absolute-cell rt-immediate 1 rex-length + jit-push-immediate jit-define -[ - arg0 0 MOV ! load XT - arg1 stack-reg MOV ! pass callstack pointer as arg 2 - arg0 JMP ! go -] rc-absolute-cell rt-primitive 1 rex-length + jit-primitive jit-define - [ (JMP) drop ] rc-relative rt-xt 1 jit-word-jump jit-define diff --git a/basis/cpu/x86/x86.factor b/basis/cpu/x86/x86.factor index 4f72fe45e1..dfe3d3e55e 100644 --- a/basis/cpu/x86/x86.factor +++ b/basis/cpu/x86/x86.factor @@ -60,19 +60,6 @@ M: x86 %return ( -- ) 0 RET ; : align-code ( n -- ) 0 % ; -M:: x86 %dispatch ( src temp -- ) - ! Load jump table base. We use a temporary register - ! since on AMD64 we have to load a 64-bit immediate. On - ! x86, this is redundant. - ! Add jump table base - temp HEX: ffffffff MOV rc-absolute-cell rel-here - src temp ADD - src HEX: 7f [+] JMP - ! Fix up the displacement above - cell code-alignment dup bootstrap-cell 8 = 15 9 ? + - building get dup pop* push - align-code ; - M: x86 %dispatch-label ( word -- ) 0 cell, rc-absolute-cell rel-word ; diff --git a/basis/dlists/dlists-tests.factor b/basis/dlists/dlists-tests.factor index 15022452ee..92b141dca8 100644 --- a/basis/dlists/dlists-tests.factor +++ b/basis/dlists/dlists-tests.factor @@ -77,3 +77,10 @@ IN: dlists.tests [ f ] [ 3 over push-front 4 over push-back -1 swap deque-member? ] unit-test [ f ] [ 0 swap deque-member? ] unit-test + +! Make sure clone does the right thing +[ V{ 2 1 } V{ 2 1 3 } ] [ + 1 over push-front 2 over push-front + dup clone 3 over push-back + [ dlist>seq ] bi@ +] unit-test diff --git a/basis/dlists/dlists.factor b/basis/dlists/dlists.factor index 3b3cae2820..5072c3edfd 100644 --- a/basis/dlists/dlists.factor +++ b/basis/dlists/dlists.factor @@ -154,6 +154,14 @@ M: dlist clear-deque ( dlist -- ) : dlist-each ( dlist quot -- ) [ obj>> ] prepose dlist-each-node ; inline +: dlist>seq ( dlist -- seq ) + [ ] pusher [ dlist-each ] dip ; + : 1dlist ( obj -- dlist ) [ push-front ] keep ; +M: dlist clone + [ + [ push-back ] curry dlist-each + ] keep ; + INSTANCE: dlist deque diff --git a/basis/editors/emacs/emacs.factor b/basis/editors/emacs/emacs.factor index 1d9f72f8c3..1550fccc0b 100644 --- a/basis/editors/emacs/emacs.factor +++ b/basis/editors/emacs/emacs.factor @@ -4,7 +4,7 @@ IN: editors.emacs : emacsclient ( file line -- ) [ - "emacsclient" , + \ emacsclient get "emacsclient" or , "--no-wait" , "+" swap number>string append , , diff --git a/basis/editors/etexteditor/authors.txt b/basis/editors/etexteditor/authors.txt new file mode 100755 index 0000000000..7b1e3b7fa0 --- /dev/null +++ b/basis/editors/etexteditor/authors.txt @@ -0,0 +1 @@ +Kibleur Christophe \ No newline at end of file diff --git a/basis/editors/etexteditor/etexteditor.factor b/basis/editors/etexteditor/etexteditor.factor new file mode 100755 index 0000000000..316bd24cfa --- /dev/null +++ b/basis/editors/etexteditor/etexteditor.factor @@ -0,0 +1,18 @@ +! Copyright (C) 2008 Kibleur Christophe. +! See http://factorcode.org/license.txt for BSD license. +USING: editors io.files io.launcher kernel math.parser +namespaces sequences windows.shell32 make ; +IN: editors.etexteditor + +: etexteditor-path ( -- str ) + \ etexteditor-path get-global [ + program-files "e\\e.exe" append-path + ] unless* ; + +: etexteditor ( file line -- ) + [ + etexteditor-path , + [ , ] [ "--line" , number>string , ] bi* + ] { } make run-detached drop ; + +[ etexteditor ] edit-hook set-global diff --git a/basis/editors/etexteditor/summary.txt b/basis/editors/etexteditor/summary.txt new file mode 100755 index 0000000000..46537003d9 --- /dev/null +++ b/basis/editors/etexteditor/summary.txt @@ -0,0 +1 @@ +etexteditor integration diff --git a/basis/editors/etexteditor/tags.txt b/basis/editors/etexteditor/tags.txt new file mode 100755 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/editors/etexteditor/tags.txt @@ -0,0 +1 @@ +unportable diff --git a/basis/furnace/actions/actions-docs.factor b/basis/furnace/actions/actions-docs.factor new file mode 100644 index 0000000000..509e0bcdee --- /dev/null +++ b/basis/furnace/actions/actions-docs.factor @@ -0,0 +1,170 @@ +USING: assocs classes help.markup help.syntax io.streams.string +http http.server.dispatchers http.server.responses +furnace.redirection strings multiline ; +IN: furnace.actions + +HELP: +{ $values { "action" action } } +{ $description "Creates a new action." } ; + +HELP: +{ $values + { "path" "a pathname string" } + { "response" response } +} +{ $description "Creates an HTTP response which serves a Chloe template. See " { $link "html.templates.chloe" } "." } ; + +HELP: +{ $values { "page" action } } +{ $description "Creates a new action which serves a Chloe template when servicing a GET request." } ; + +HELP: action +{ $description "The class of Furnace actions. New instances are created with " { $link } ". New instances of subclasses can be created with " { $link new-action } ". The " { $link page-action } " class is a useful subclass." +$nl +"Action slots are documented in " { $link "furnace.actions.config" } "." } ; + +HELP: new-action +{ $values + { "class" class } + { "action" action } +} +{ $description "Constructs a subclass of " { $link action } "." } ; + +HELP: page-action +{ $description "The class of Chloe page actions. These are actions whose " { $slot "display" } " slot is pre-set to serve the Chloe template stored in the " { $slot "page" } " slot." } ; + +HELP: param +{ $values + { "name" string } + { "value" string } +} +{ $description "Outputs the value of a query parameter (if the current request is a GET or HEAD request) or a POST parameter (if the current request is a POST request)." } +{ $notes "Instead of using this word, it is better to use " { $link validate-params } " and then access parameters via " { $link "html.forms.values" } " words." } ; + +HELP: params +{ $var-description "A variable holding an assoc of query parameters (if the current request is a GET or HEAD request) or POST parameters (if the current request is a POST request)." } +{ $notes "Instead of using this word, it is better to use " { $link validate-params } " and then access parameters via " { $link "html.forms.values" } " words." } ; + +HELP: validate-integer-id +{ $description "A utility word which validates an integer parameter named " { $snippet "id" } "." } +{ $examples + { $code + "" + " [" + " validate-integer-id" + " \"id\" value select-tuple from-object" + " ] >>init" + } +} ; + +HELP: validate-params +{ $values + { "validators" "an association list mapping parameter names to validator quotations" } +} +{ $description "Validates query or POST parameters, depending on the request type, and stores them in " { $link "html.forms.values" } ". The validator quotations can execute " { $link "validators" } "." } +{ $examples + "A simple validator from " { $vocab-link "webapps.todo" } "; this word is invoked from the " { $slot "validate" } " quotation of action for editing a todo list item:" + { $code + <" : validate-todo ( -- ) + { + { "summary" [ v-one-line ] } + { "priority" [ v-integer 0 v-min-value 10 v-max-value ] } + { "description" [ v-required ] } + } validate-params ;"> + } +} ; + +HELP: validation-failed +{ $description "Stops processing the current request and takes action depending on the type of the current request:" + { $list + { "For GET or HEAD requests, the client receives a " { $link <400> } " response." } + { "For POST requests, the client is sent back to the page containing the form submission, with current form values and validation errors passed in a " { $link "furnace.conversations" } "." } + } +"This word is called by " { $link validate-params } " and can also be called directly. For more details, see " { $link "furnace.actions.lifecycle" } "." } ; + +ARTICLE: "furnace.actions.page.example" "Furnace page action example" +"The " { $vocab-link "webapps.counter" } " vocabulary defines a subclass of " { $link dispatcher } ":" +{ $code "TUPLE: counter-app < dispatcher ;" } +"The " { $snippet "" } " constructor word creates a new instance of the " { $snippet "counter-app" } " class, and adds a " { $link page-action } " instance to the dispatcher. This " { $link page-action } " has its " { $slot "template" } " slot set as follows," +{ $code "{ counter-app \"counter\" } >>template" } +"This means the action will serve the Chloe template located at " { $snippet "resource:extra/webapps/counter/counter.xml" } " upon receiving a GET request." ; + +ARTICLE: "furnace.actions.page" "Furnace page actions" +"Page actions implement the common case of an action that simply serves a Chloe template in response to a GET request." +{ $subsection page-action } +{ $subsection } +"When using a page action, instead of setting the " { $slot "display" } " slot, the " { $slot "template" } " slot is set instead. The " { $slot "init" } ", " { $slot "authorize" } ", " { $slot "validate" } " and " { $slot "submit" } " slots can still be set as usual." +$nl +"The " { $slot "template" } " slot of a " { $link page-action } " contains a pair with shape " { $snippet "{ responder name }" } ", where " { $snippet "responder" } " is a responder class, usually a subclass of " { $link dispatcher } ", and " { $snippet "name" } " is the name of a template file, without the " { $snippet ".xml" } " extension, relative to the directory containing the responder's vocabulary source file." +{ $subsection "furnace.actions.page.example" } ; + +ARTICLE: "furnace.actions.config" "Furnace action configuration" +"Actions have the following slots:" +{ $table + { { $slot "rest" } { "A parameter name to map the rest of the URL, after the action name, to. If this is not set, then navigating to a URL where the action is not the last path component will return to the client with an error." } } + { { $slot "init" } { "A quotation called at the beginning of a GET or HEAD request. Typically this quotation configures " { $link "html.forms" } " and parses query parameters." } } + { { $slot "authorize" } { "A quotation called at the beginning of a GET, HEAD or POST request. In GET requests, it is called after the " { $slot "init" } " quotation; in POST requests, it is called after the " { $slot "validate" } " quotation. By convention, this quotation performs custom authorization checks which depend on query parameters or POST parameters." } } + { { $slot "display" } { "A quotation called after the " { $slot "init" } " quotation in a GET request. This quotation must return an HTTP " { $link response } "." } } + { { $slot "validate" } { "A quotation called at the beginning of a POST request to validate POST parameters." } } + { { $slot "submit" } { "A quotation called after the " { $slot "validate" } " quotation in a POST request. This quotation must return an HTTP " { $link response } "." } } +} +"At least one of the " { $slot "display" } " and " { $slot "submit" } " slots must be set, otherwise the action will be useless." ; + +ARTICLE: "furnace.actions.validation" "Form validation with actions" +"The action code is set up so that the " { $slot "init" } " quotation can validate query parameters, and the " { $slot "validate" } " quotation can validate POST parameters." +$nl +"A word to validate parameters and make them available as HTML form values (see " { $link "html.forms.values" } "); typically this word is invoked from the " { $slot "init" } " and " { $slot "validate" } " quotations:" +{ $subsection validate-params } +"The above word expects an association list mapping parameter names to validator quotations; validator quotations can use the words in the " +"Custom validation logic can invoke a word when validation fails; " { $link validate-params } " invokes this word for you:" +{ $subsection validation-failed } +"If validation fails, no more action code is executed, and the client is redirected back to the originating page, where validation errors can be displayed. Note that validation errors are rendered automatically by the " { $link "html.components" } " words, and in particular, " { $link "html.templates.chloe" } " use these words." ; + +ARTICLE: "furnace.actions.lifecycle" "Furnace action lifecycle" +{ $heading "GET request lifecycle" } +"A GET request results in the following sequence of events:" +{ $list + { "The " { $snippet "init" } " quotation is called." } + { "The " { $snippet "authorize" } " quotation is called." } + { "If the GET request was generated as a result of form validation failing during a POST, then the form values entered by the user, along with validation errors, are stored in " { $link "html.forms.values" } "." } + { "The " { $snippet "display" } " quotation is called; it is expected to output an HTTP " { $link response } " on the stack." } +} +"Any one of the above steps can perform validation; if " { $link validation-failed } " is called during a GET request, the client receives a " { $link <400> } " error." +{ $heading "HEAD request lifecycle" } +"A HEAD request proceeds exactly like a GET request. The only difference is that the " { $slot "body" } " slot of the " { $link response } " object is never rendered." +{ $heading "POST request lifecycle" } +"A POST request results in the following sequence of events:" +{ $list + { "The " { $snippet "validate" } " quotation is called." } + { "The " { $snippet "authorize" } " quotation is called." } + { "The " { $snippet "submit" } " quotation is called; it is expected to output an HTTP " { $link response } " on the stack. By convention, this response should be a " { $link } "." } +} +"Any one of the above steps can perform validation; if " { $link validation-failed } " is called during a POST request, the client is sent back to the page containing the form submission, with current form values and validation errors passed in a " { $link "furnace.conversations" } "." ; + +ARTICLE: "furnace.actions.impl" "Furnace actions implementation" +"The following words are used by the action implementation and there is rarely any reason to call them directly:" +{ $subsection new-action } +{ $subsection param } +{ $subsection params } ; + +ARTICLE: "furnace.actions" "Furnace actions" +"The " { $vocab-link "furnace.actions" } " vocabulary implements a type of responder, called an " { $emphasis "action" } ", which handles the form validation lifecycle." +$nl +"Other than form validation capability, actions are also often simpler to use than implementing new responders directly, since creating a new class is not required, and the action dispatches on the request type (GET, HEAD, or POST)." +$nl +"The class of actions:" +{ $subsection action } +"Creating a new action:" +{ $subsection } +"Once created, an action needs to be configured; typically the creation and configuration of an action is encapsulated into a single word:" +{ $subsection "furnace.actions.config" } +"Validating forms with actions:" +{ $subsection "furnace.actions.validation" } +"More about the form validation lifecycle:" +{ $subsection "furnace.actions.lifecycle" } +"A convenience class:" +{ $subsection "furnace.actions.page" } +"Low-level features:" +{ $subsection "furnace.actions.impl" } ; + +ABOUT: "furnace.actions" diff --git a/basis/furnace/actions/actions.factor b/basis/furnace/actions/actions.factor index 7505b3c612..6c56a8ad7b 100644 --- a/basis/furnace/actions/actions.factor +++ b/basis/furnace/actions/actions.factor @@ -22,18 +22,7 @@ SYMBOL: params SYMBOL: rest -: render-validation-messages ( -- ) - form get errors>> - [ -
    - [
  • escape-string write
  • ] each -
- ] unless-empty ; - -CHLOE: validation-messages - drop [ render-validation-messages ] [code] ; - -TUPLE: action rest authorize init display validate submit ; +TUPLE: action rest init authorize display validate submit ; : new-action ( class -- action ) new [ ] >>init [ ] >>validate [ ] >>authorize ; inline diff --git a/basis/furnace/alloy/alloy-docs.factor b/basis/furnace/alloy/alloy-docs.factor new file mode 100644 index 0000000000..f108428c90 --- /dev/null +++ b/basis/furnace/alloy/alloy-docs.factor @@ -0,0 +1,42 @@ +IN: furnace.alloy +USING: help.markup help.syntax db multiline ; + +HELP: init-furnace-tables +{ $description "Initializes database tables used by asides, conversations and session management. This word must be invoked inside a " { $link with-db } " scope." } ; + +HELP: +{ $values { "responder" "a responder" } { "db" db } { "responder'" "an alloy responder" } } +{ $description "Wraps the responder with support for asides, conversations, sessions and database persistence." } +{ $examples + "The " { $vocab-link "webapps.counter" } " vocabulary uses an alloy to configure the counter:" + { $code + <" : counter-db ( -- db ) "counter.db" ; + +: run-counter ( -- ) + + counter-db + main-responder set-global + 8080 httpd ;"> + } +} ; + +HELP: start-expiring +{ $values { "db" db } } +{ $description "Starts a timer which expires old session state from the given database." } ; + +ARTICLE: "furnace.alloy" "Furnace alloy responder" +"The " { $vocab-link "furnace.alloy" } " vocabulary implements a convenience responder which combines several Furnace features into one easy-to-use wrapper:" +{ $list + { $link "furnace.asides" } + { $link "furnace.conversations" } + { $link "furnace.sessions" } + { $link "furnace.db" } +} +"A word to wrap a responder in an alloy:" +{ $subsection } +"Initializing database tables for asides, conversations and sessions:" +{ $subsection init-furnace-tables } +"Start a timer to expire asides, conversations and sessions:" +{ $subsection start-expiring } ; + +ABOUT: "furnace.alloy" diff --git a/basis/furnace/asides/asides-docs.factor b/basis/furnace/asides/asides-docs.factor new file mode 100644 index 0000000000..b977474b5f --- /dev/null +++ b/basis/furnace/asides/asides-docs.factor @@ -0,0 +1,33 @@ +USING: help.markup help.syntax io.streams.string urls +furnace.redirection http furnace.sessions furnace.db ; +IN: furnace.asides + +HELP: +{ $values + { "responder" "a responder" } + { "responder'" asides } +} +{ $description "Creates a new " { $link asides } " responder wrapping an existing responder." } ; + +HELP: begin-aside +{ $values { "url" url } } +{ $description "Begins an aside. When the current action returns a " { $link } ", the redirect will have query parameters which reference the current page via an opaque handle." } ; + +HELP: end-aside +{ $values { "default" url } { "response" response } } +{ $description "Ends an aside. If an aside is currently active, the response redirects the client " } ; + +ARTICLE: "furnace.asides" "Furnace asides" +"The " { $vocab-link "furnace.asides" } " vocabulary provides support for sending a user to a page which can then return to the former location." +$nl +"To use asides, wrap your responder in an aside responder:" +{ $subsection } +"The aside responder must be wrapped inside a session responder (" { $link } "), which in turn must be wrapped inside a database persistence responder (" { $link } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one." +$nl +"Saving the current page in an aside which propagates through " { $link } " responses:" +{ $subsection begin-aside } +"Returning from an aside:" +{ $subsection end-aside } +"Asides are used by " { $vocab-link "furnace.auth.login" } "; when the client requests a protected page, an aside begins and the client is redirected to a login page. Upon a successful login, the aside ends and the client returns to the protected page. If the client directly visits the login page and logs in, there is no current aside, so the client is sent to the default URL passed to " { $link end-aside } ", which in the case of login is the root URL." ; + +ABOUT: "furnace.asides" diff --git a/basis/furnace/auth/features/edit-profile/edit-profile.xml b/basis/furnace/auth/features/edit-profile/edit-profile.xml index f486f4e246..878bdd64fb 100644 --- a/basis/furnace/auth/features/edit-profile/edit-profile.xml +++ b/basis/furnace/auth/features/edit-profile/edit-profile.xml @@ -62,7 +62,7 @@

- +

diff --git a/basis/furnace/auth/features/recover-password/recover-3.xml b/basis/furnace/auth/features/recover-password/recover-3.xml index a8ea635a1f..2df400ffe2 100644 --- a/basis/furnace/auth/features/recover-password/recover-3.xml +++ b/basis/furnace/auth/features/recover-password/recover-3.xml @@ -32,7 +32,7 @@

- +

diff --git a/basis/furnace/auth/features/registration/register.xml b/basis/furnace/auth/features/registration/register.xml index b0d6971d1b..45c090905e 100644 --- a/basis/furnace/auth/features/registration/register.xml +++ b/basis/furnace/auth/features/registration/register.xml @@ -63,7 +63,7 @@

- +

diff --git a/basis/furnace/auth/login/login.xml b/basis/furnace/auth/login/login.xml index 766c097ca5..917c182fb3 100644 --- a/basis/furnace/auth/login/login.xml +++ b/basis/furnace/auth/login/login.xml @@ -36,7 +36,7 @@

- +

diff --git a/basis/furnace/boilerplate/boilerplate-docs.factor b/basis/furnace/boilerplate/boilerplate-docs.factor new file mode 100644 index 0000000000..5594928082 --- /dev/null +++ b/basis/furnace/boilerplate/boilerplate-docs.factor @@ -0,0 +1,27 @@ +! Copyright (C) 2008 Your name. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax io.streams.string ; +IN: furnace.boilerplate + +HELP: +{ $values + { "responder" null } + { "boilerplate" null } +} +{ $description "" } ; + +HELP: boilerplate +{ $description "" } ; + +HELP: wrap-boilerplate? +{ $values + { "response" null } + { "?" "a boolean" } +} +{ $description "" } ; + +ARTICLE: "furnace.boilerplate" "Furnace boilerplate support" +{ $vocab-link "furnace.boilerplate" } +; + +ABOUT: "furnace.boilerplate" diff --git a/basis/furnace/conversations/conversations-docs.factor b/basis/furnace/conversations/conversations-docs.factor new file mode 100644 index 0000000000..5e161f2457 --- /dev/null +++ b/basis/furnace/conversations/conversations-docs.factor @@ -0,0 +1,6 @@ +USING: help.markup help.syntax ; +IN: furnace.conversations + +ARTICLE: "furnace.conversations" "Furnace conversation scope" + +; diff --git a/basis/furnace/db/db-docs.factor b/basis/furnace/db/db-docs.factor new file mode 100644 index 0000000000..a7ef02b77f --- /dev/null +++ b/basis/furnace/db/db-docs.factor @@ -0,0 +1,16 @@ +USING: help.markup help.syntax db http.server ; +IN: furnace.db + +HELP: +{ $values + { "responder" "a responder" } { "db" db } + { "responder'" db-persistence } +} +{ $description "Wraps a responder with database persistence support. The responder's " { $link call-responder* } " method will run in a " { $link with-db } " scope." } ; + +ARTICLE: "furnace.db" "Furnace database support" +"The " { $vocab-link "furnace.db" } " vocabulary implements a responder which maintains a database connection pool and runs each request in a " { $link with-db } " scope." +{ $subsection } +"The " { $vocab-link "furnace.alloy" } " vocabulary combines database persistence with several other features." ; + +ABOUT: "furnace.db" diff --git a/basis/furnace/furnace-docs.factor b/basis/furnace/furnace-docs.factor new file mode 100644 index 0000000000..0e2e6c1f40 --- /dev/null +++ b/basis/furnace/furnace-docs.factor @@ -0,0 +1,189 @@ +USING: assocs help.markup help.syntax io.streams.string quotations sequences strings urls ; +IN: furnace + +HELP: adjust-redirect-url +{ $values + { "url" url } + { "url'" url } +} +{ $description "" } ; + +HELP: adjust-url +{ $values + { "url" url } + { "url'" url } +} +{ $description "" } ; + +HELP: base-path +{ $values + { "string" string } + { "pair" null } +} +{ $description "" } ; + +HELP: client-state +{ $values + { "key" null } + { "value/f" null } +} +{ $description "" } ; + +HELP: cookie-client-state +{ $values + { "key" null } { "request" null } + { "value/f" null } +} +{ $description "" } ; + +HELP: each-responder +{ $values + { "quot" quotation } +} +{ $description "" } ; + +HELP: exit-continuation +{ $description "" } ; + +HELP: exit-with +{ $values + { "value" null } +} +{ $description "" } ; + +HELP: hidden-form-field +{ $values + { "value" null } { "name" null } +} +{ $description "" } ; + +HELP: link-attr +{ $values + { "tag" null } { "responder" null } +} +{ $description "" } ; + +HELP: modify-form +{ $values + { "responder" null } +} +{ $description "" } ; + +HELP: modify-query +{ $values + { "query" null } { "responder" null } + { "query'" null } +} +{ $description "" } ; + +HELP: modify-redirect-query +{ $values + { "query" null } { "responder" null } + { "query'" null } +} +{ $description "" } ; + +HELP: nested-forms-key +{ $description "" } ; + +HELP: nested-responders +{ $values + + { "seq" sequence } +} +{ $description "" } ; + +HELP: post-client-state +{ $values + { "key" null } { "request" null } + { "value/f" null } +} +{ $description "" } ; + +HELP: referrer +{ $values + + { "referrer/f" null } +} +{ $description "" } ; + +HELP: request-params +{ $values + { "request" null } + { "assoc" assoc } +} +{ $description "" } ; + +HELP: resolve-base-path +{ $values + { "string" string } + { "string'" string } +} +{ $description "" } ; + +HELP: resolve-template-path +{ $values + { "pair" null } + { "path" "a pathname string" } +} +{ $description "" } ; + +HELP: same-host? +{ $values + { "url" url } + { "?" "a boolean" } +} +{ $description "" } ; + +HELP: user-agent +{ $values + + { "user-agent" null } +} +{ $description "" } ; + +HELP: vocab-path +{ $values + { "vocab" "a vocabulary specifier" } + { "path" "a pathname string" } +} +{ $description "" } ; + +HELP: with-exit-continuation +{ $values + { "quot" quotation } +} +{ $description "" } ; + +ARTICLE: "furnace" "Furnace web framework" +"The " { $vocab-link "furnace" } " vocabulary implements a full-featured web framework on top of the " { $link "http.server" } ". Some of its features include:" +{ $list + "Session management capable of load-balancing and fail-over" + "Form components and validation" + "Authentication system with basic authentication or login pages, and pluggable authentication backends" + "Easy Atom feed syndication" + "Conversation scope and asides for complex page flow" +} +"Major functionality:" +{ $subsection "furnace.actions" } +{ $subsection "furnace.syndication" } +{ $subsection "furnace.boilerplate" } +{ $subsection "furnace.db" } +"Server-side state:" +{ $subsection "furnace.sessions" } +{ $subsection "furnace.conversations" } +{ $subsection "furnace.asides" } +"HTML components:" +{ $subsection "html.components" } +{ $subsection "html.forms" } +"Content templates:" +{ $subsection "html.templates" } +{ $subsection "html.templates.chloe" } +{ $subsection "html.templates.fhtml" } +"Utilities:" +{ $subsection "furnace.alloy" } +{ $subsection "furnace.json" } +{ $subsection "furnace.redirection" } +{ $subsection "furnace.referrer" } ; + +ABOUT: "furnace" diff --git a/basis/furnace/furnace.factor b/basis/furnace/furnace.factor index 7285c436bc..a77b0d28c7 100644 --- a/basis/furnace/furnace.factor +++ b/basis/furnace/furnace.factor @@ -128,4 +128,27 @@ SYMBOL: exit-continuation : with-exit-continuation ( quot -- ) '[ exit-continuation set @ ] callcc1 exit-continuation off ; +USE: vocabs.loader +"furnace.actions" require +"furnace.alloy" require +"furnace.asides" require +"furnace.auth" require +"furnace.auth.basic" require +"furnace.auth.features.deactivate-user" require +"furnace.auth.features.edit-profile" require +"furnace.auth.features.recover-password" require +"furnace.auth.features.registration" require +"furnace.auth.login" require +"furnace.auth.providers.assoc" require +"furnace.auth.providers.db" require +"furnace.auth.providers.null" require +"furnace.boilerplate" require "furnace.chloe-tags" require +"furnace.conversations" require +"furnace.db" require +"furnace.json" require +"furnace.redirection" require +"furnace.referrer" require +"furnace.scopes" require +"furnace.sessions" require +"furnace.syndication" require diff --git a/basis/furnace/json/json-docs.factor b/basis/furnace/json/json-docs.factor new file mode 100644 index 0000000000..c20c2e6c91 --- /dev/null +++ b/basis/furnace/json/json-docs.factor @@ -0,0 +1,12 @@ +USING: kernel http.server help.markup help.syntax http ; +IN: furnace.json + +HELP: +{ $values { "body" object } { "response" response } } +{ $description "Creates an HTTP response which serves a serialized JSON object to the client." } ; + +ARTICLE: "furnace.json" "Furnace JSON support" +"The " { $vocab-link "furnace.json" } " vocabulary provides a utility word for serving HTTP responses with JSON content." +{ $subsection } ; + +ABOUT: "furnace.json" diff --git a/basis/furnace/redirection/redirection-docs.factor b/basis/furnace/redirection/redirection-docs.factor new file mode 100644 index 0000000000..fd3671fa1c --- /dev/null +++ b/basis/furnace/redirection/redirection-docs.factor @@ -0,0 +1,59 @@ +USING: help.markup help.syntax io.streams.string quotations urls +http.server http ; +IN: furnace.redirection + +HELP: +{ $values { "url" url } { "responder" "a responder" } } +{ $description "Creates a responder which unconditionally redirects the client to the given URL." } ; + +HELP: +{ $values { "url" url } { "response" response } } +{ $description "Creates a response which redirects the client to the given URL." } ; + +HELP: ( responder -- responder' ) +{ $values { "responder" "a responder" } { "responder'" "a responder" } } +{ $description "Creates a new responder which ensures that the client is connecting via HTTPS before delegating to the underlying responder. If the client is connecting via HTTP, a redirect is sent instead." } ; + +HELP: +{ $values + { "url" url } + { "response" response } +} +{ $description "Creates a responder which unconditionally redirects the client to the given URL after setting its protocol to HTTPS." } +{ $notes "This word is intended to be used with a relative URL. The client is redirected to the relative URL, but with HTTPS instead of HTTP." } ; + +HELP: >secure-url +{ $values + { "url" url } + { "url'" url } +} +{ $description "Sets the protocol of a URL to HTTPS." } ; + +HELP: if-secure +{ $values + { "quot" quotation } + { "response" response } +} +{ $description "Runs a quotation if the current request was made over HTTPS, otherwise returns a redirect to have the client request the current page again via HTTPS." } ; + +ARTICLE: "furnace.redirection.secure" "Secure redirection" +"The words in this section help with implementing sites which require SSL/TLS for additional security." +$nl +"Converting a HTTP URL into an HTTPS URL:" +{ $subsection >secure-url } +"Redirecting the client to an HTTPS URL:" +{ $subsection } +"Tools for writing responders which require SSL/TLS connections:" +{ $subsection if-secure } +{ $subsection } ; + +ARTICLE: "furnace.redirection" "Furnace redirection support" +"The " { $vocab-link "furnace.redirection" } " vocabulary builds additional functionality on top of " { $vocab-link "http.server.redirection" } ", and integrates with various Furnace features such as " { $link "furnace.asides" } " and " { $link "furnace.conversations" } "." +$nl +"A redirection response which takes asides and conversations into account:" +{ $subsection } +"A responder which unconditionally redirects the client to another URL:" +{ $subsection } +{ $subsection "furnace.redirection.secure" } ; + +ABOUT: "furnace.redirection" diff --git a/basis/furnace/referrer/referrer-docs.factor b/basis/furnace/referrer/referrer-docs.factor new file mode 100644 index 0000000000..5deebbe9a7 --- /dev/null +++ b/basis/furnace/referrer/referrer-docs.factor @@ -0,0 +1,15 @@ +USING: help.markup help.syntax io.streams.string ; +IN: furnace.referrer + +HELP: +{ $values + { "responder" "a responder" } + { "responder'" "a responder" } +} +{ $description "Wraps the responder in a filter responder which ensures that form submissions originate from a page on the same server. Any submissions which do not are sent back with a 403 error." } ; + +ARTICLE: "furnace.referrer" "Form submission referrer checking" +"The " { $vocab-link "furnace.referrer" } " implements a simple security measure which can be used to thwart cross-site scripting attacks." +{ $subsection } ; + +ABOUT: "furnace.referrer" diff --git a/basis/furnace/sessions/sessions-docs.factor b/basis/furnace/sessions/sessions-docs.factor new file mode 100644 index 0000000000..6ec77e00f5 --- /dev/null +++ b/basis/furnace/sessions/sessions-docs.factor @@ -0,0 +1,149 @@ +! Copyright (C) 2008 Your name. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax io.streams.string quotations strings ; +IN: furnace.sessions + +HELP: +{ $values + + { "cookie" null } +} +{ $description "" } ; + +HELP: +{ $values + { "id" null } + { "session" null } +} +{ $description "" } ; + +HELP: +{ $values + { "responder" null } + { "responder'" null } +} +{ $description "" } ; + +HELP: begin-session +{ $values + + { "session" null } +} +{ $description "" } ; + +HELP: check-session +{ $values + { "state/f" null } + { "state/f" null } +} +{ $description "" } ; + +HELP: empty-session +{ $values + + { "session" null } +} +{ $description "" } ; + +HELP: existing-session +{ $values + { "path" "a pathname string" } { "session" null } + { "response" null } +} +{ $description "" } ; + +HELP: get-session +{ $values + { "id" null } + { "session" null } +} +{ $description "" } ; + +HELP: init-session +{ $values + { "session" null } +} +{ $description "" } ; + +HELP: init-session* +{ $values + { "responder" null } +} +{ $description "" } ; + +HELP: put-session-cookie +{ $values + { "response" null } + { "response'" null } +} +{ $description "" } ; + +HELP: remote-host +{ $values + + { "string" string } +} +{ $description "" } ; + +HELP: request-session +{ $values + + { "session/f" null } +} +{ $description "" } ; + +HELP: save-session-after +{ $values + { "session" null } +} +{ $description "" } ; + +HELP: schange +{ $values + { "key" null } { "quot" quotation } +} +{ $description "" } ; + +HELP: session +{ $description "" } ; + +HELP: session-changed +{ $description "" } ; + +HELP: session-id-key +{ $description "" } ; + +HELP: sessions +{ $description "" } ; + +HELP: sget +{ $values + { "key" null } + { "value" null } +} +{ $description "" } ; + +HELP: sset +{ $values + { "value" null } { "key" null } +} +{ $description "" } ; + +HELP: touch-session +{ $values + { "session" null } +} +{ $description "" } ; + +HELP: verify-session +{ $values + { "session" null } + { "session" null } +} +{ $description "" } ; + +ARTICLE: "furnace.sessions" "Furnace sessions" +{ $vocab-link "furnace.sessions" } +; + +ABOUT: "furnace.sessions" diff --git a/basis/furnace/syndication/syndication-docs.factor b/basis/furnace/syndication/syndication-docs.factor new file mode 100644 index 0000000000..7a9ec57468 --- /dev/null +++ b/basis/furnace/syndication/syndication-docs.factor @@ -0,0 +1,69 @@ +! Copyright (C) 2008 Your name. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax io.streams.string kernel sequences strings urls ; +IN: furnace.syndication + +HELP: +{ $values + + { "action" null } +} +{ $description "" } ; + +HELP: +{ $values + { "body" null } + { "response" null } +} +{ $description "" } ; + +HELP: >entry +{ $values + { "object" object } + { "entry" null } +} +{ $description "" } ; + +HELP: feed-action +{ $description "" } ; + +HELP: feed-entry-date +{ $values + { "object" object } + { "timestamp" null } +} +{ $description "" } ; + +HELP: feed-entry-description +{ $values + { "object" object } + { "description" null } +} +{ $description "" } ; + +HELP: feed-entry-title +{ $values + { "object" object } + { "string" string } +} +{ $description "" } ; + +HELP: feed-entry-url +{ $values + { "object" object } + { "url" url } +} +{ $description "" } ; + +HELP: process-entries +{ $values + { "seq" sequence } + { "seq'" sequence } +} +{ $description "" } ; + +ARTICLE: "furnace.syndication" "Furnace Atom syndication support" +{ $vocab-link "furnace.syndication" } +; + +ABOUT: "furnace.syndication" diff --git a/core/grouping/authors.txt b/basis/grouping/authors.txt similarity index 100% rename from core/grouping/authors.txt rename to basis/grouping/authors.txt diff --git a/core/grouping/grouping-docs.factor b/basis/grouping/grouping-docs.factor similarity index 100% rename from core/grouping/grouping-docs.factor rename to basis/grouping/grouping-docs.factor diff --git a/core/grouping/grouping-tests.factor b/basis/grouping/grouping-tests.factor similarity index 100% rename from core/grouping/grouping-tests.factor rename to basis/grouping/grouping-tests.factor diff --git a/core/grouping/grouping.factor b/basis/grouping/grouping.factor similarity index 53% rename from core/grouping/grouping.factor rename to basis/grouping/grouping.factor index 332fd2635a..4a1b8c7b90 100644 --- a/core/grouping/grouping.factor +++ b/basis/grouping/grouping.factor @@ -1,10 +1,12 @@ ! Copyright (C) 2005, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel math math.order strings arrays vectors sequences -accessors ; +sequences.private accessors ; IN: grouping -TUPLE: abstract-groups { seq read-only } { n read-only } ; + 0 swap copy ; -M: abstract-groups set-nth group@ 0 swap copy ; +M: chunking-seq like drop { } like ; -M: abstract-groups like drop { } like ; +INSTANCE: chunking-seq sequence -INSTANCE: abstract-groups sequence +MIXIN: subseq-chunking + +M: subseq-chunking nth group@ subseq ; + +MIXIN: slice-chunking + +M: slice-chunking nth group@ ; + +M: slice-chunking nth-unsafe group@ slice boa ; + +TUPLE: abstract-groups < chunking-seq ; + +M: abstract-groups length + [ seq>> length ] [ n>> ] bi [ + 1- ] keep /i ; + +M: abstract-groups set-length + [ n>> * ] [ seq>> ] bi set-length ; + +M: abstract-groups group@ + [ n>> [ * dup ] keep + ] [ seq>> ] bi [ length min ] keep ; + +TUPLE: abstract-clumps < chunking-seq ; + +M: abstract-clumps length + [ seq>> length ] [ n>> ] bi - 1+ ; + +M: abstract-clumps set-length + [ n>> + 1- ] [ seq>> ] bi set-length ; + +M: abstract-clumps group@ + [ n>> over + ] [ seq>> ] bi ; + +PRIVATE> TUPLE: groups < abstract-groups ; : ( seq n -- groups ) groups new-groups ; inline -M: groups length - [ seq>> length ] [ n>> ] bi [ + 1- ] keep /i ; +INSTANCE: groups subseq-chunking -M: groups set-length - [ n>> * ] [ seq>> ] bi set-length ; - -M: groups group@ - [ n>> [ * dup ] keep + ] [ seq>> ] bi [ length min ] keep ; - -TUPLE: sliced-groups < groups ; +TUPLE: sliced-groups < abstract-groups ; : ( seq n -- groups ) sliced-groups new-groups ; inline -M: sliced-groups nth group@ ; +INSTANCE: sliced-groups slice-chunking -TUPLE: clumps < abstract-groups ; +TUPLE: clumps < abstract-clumps ; : ( seq n -- clumps ) clumps new-groups ; inline -M: clumps length - [ seq>> length ] [ n>> ] bi - 1+ ; +INSTANCE: clumps subseq-chunking -M: clumps set-length - [ n>> + 1- ] [ seq>> ] bi set-length ; - -M: clumps group@ - [ n>> over + ] [ seq>> ] bi ; - -TUPLE: sliced-clumps < clumps ; +TUPLE: sliced-clumps < abstract-clumps ; : ( seq n -- clumps ) sliced-clumps new-groups ; inline -M: sliced-clumps nth group@ ; +INSTANCE: sliced-clumps slice-chunking : group ( seq n -- array ) { } like ; diff --git a/core/grouping/summary.txt b/basis/grouping/summary.txt similarity index 100% rename from core/grouping/summary.txt rename to basis/grouping/summary.txt diff --git a/core/grouping/tags.txt b/basis/grouping/tags.txt similarity index 100% rename from core/grouping/tags.txt rename to basis/grouping/tags.txt diff --git a/basis/heaps/heaps.factor b/basis/heaps/heaps.factor index 6c387632ed..92146755d9 100644 --- a/basis/heaps/heaps.factor +++ b/basis/heaps/heaps.factor @@ -62,7 +62,7 @@ M: heap heap-size ( heap -- n ) : data-set-nth ( entry n heap -- ) >r [ >>index drop ] 2keep r> - data>> set-nth-unsafe ; + data>> set-nth-unsafe ; inline : data-push ( entry heap -- n ) dup heap-size [ diff --git a/basis/help/handbook/handbook.factor b/basis/help/handbook/handbook.factor index 5b60102e46..d1d9ca049a 100644 --- a/basis/help/handbook/handbook.factor +++ b/basis/help/handbook/handbook.factor @@ -166,16 +166,16 @@ ARTICLE: "io" "Input and output" { $heading "Encodings" } { $subsection "encodings-introduction" } { $subsection "io.encodings" } -"Wrapper streams:" +{ $heading "Wrapper streams" } { $subsection "io.streams.duplex" } { $subsection "io.streams.plain" } { $subsection "io.streams.string" } { $subsection "io.streams.byte-array" } -"Utilities:" +{ $heading "Utilities" } { $subsection "stream-binary" } { $subsection "styles" } { $subsection "checksums" } -"Implementation:" +{ $heading "Implementation" } { $subsection "io.streams.c" } { $subsection "io.ports" } { $see-also "destructors" } ; diff --git a/basis/help/tutorial/tutorial.factor b/basis/help/tutorial/tutorial.factor index cafa758c7e..afa16bbf8a 100644 --- a/basis/help/tutorial/tutorial.factor +++ b/basis/help/tutorial/tutorial.factor @@ -1,29 +1,24 @@ USING: help.markup help.syntax ui.commands ui.operations ui.tools.search ui.tools.workspace editors vocabs.loader kernel sequences prettyprint tools.test tools.vocabs strings -unicode.categories unicode.case ; +unicode.categories unicode.case ui.tools.browser ; IN: help.tutorial ARTICLE: "first-program-start" "Creating a vocabulary for your first program" "Factor source code is organized into " { $link "vocabularies" } ". Before we can write our first program, we must create a vocabulary for it." $nl -"Start by asking Factor for the path to your ``work'' directory, where you will place your own code:" +"Start by loading the scaffold tool:" +{ $code "USE: tools.scaffold" } +"Then, ask the scaffold tool to create a new vocabulary named " { $snippet "palindrome" } ":" +{ $code "\"resource:work\" \"palindrome\" scaffold-vocab" } +"If you look at the output, you will see that a few files were created in your ``work'' directory. The following phrase will print the full path of your work directory:" { $code "\"work\" resource-path ." } -"Open the work directory in your file manager, and create a subdirectory named " { $snippet "palindrome" } ". Inside this directory, create a file named " { $snippet "palindrome.factor" } " using your favorite text editor. Leave the file empty for now." +"Open the work directory in your file manager, and open the subdirectory named " { $snippet "palindrome" } ". Inside this subdirectory you will see a file named " { $snippet "palindrome.factor" } ". We will be editing this file." $nl -"Inside the Factor listener, type" -{ $code "USE: palindrome" } -"The source file should now load. Since it is empty, it does nothing. If you get an error message, make sure you created the directory and the file in the right place and gave them the right names." -$nl -"Now, we will start filling out this source file. Go back to your editor, and type:" -{ $code - "! Copyright (C) 2008 " - "! See http://factorcode.org/license.txt for BSD license." -} -"This is the standard header for Factor source files; it consists of two " { $link "syntax-comments" } "." -$nl -"Now, we tell Factor that all definitions in this source file should go into the " { $snippet "palindrome" } " vocabulary using the " { $link POSTPONE: IN: } " word:" +"Notice that the file ends with an " { $link POSTPONE: IN: } " form telling Factor that all definitions in this source file should go into the " { $snippet "palindrome" } " vocabulary using the " { $link POSTPONE: IN: } " word:" { $code "IN: palindrome" } +"We will add new definitions after the " { $link POSTPONE: IN: } " form." +$nl "You are now ready to go on to the next section: " { $link "first-program-logic" } "." ; ARTICLE: "first-program-logic" "Writing some logic in your first program" @@ -43,20 +38,16 @@ $nl $nl "When you do this, you will get an error about the " { $link dup } " word not being found. This is because this word is part of the " { $vocab-link "kernel" } " vocabulary, but this vocabulary is not part of the source file's " { $link "vocabulary-search" } ". You must explicitly list dependencies in source files. This allows Factor to automatically load required vocabularies and makes larger programs easier to maintain." $nl -"To add the word to the search path, first convince yourself that this word is in the " { $vocab-link "kernel" } " vocabulary by entering the following in the listener:" -{ $code "\\ dup see" } -"This shows the definition of " { $link dup } ", along with an " { $link POSTPONE: IN: } " form." +"To add the word to the search path, first convince yourself that this word is in the " { $vocab-link "kernel" } " vocabulary. Enter " { $snippet "dup" } " in the listener's input area, and press " { $operation com-follow } ". This will open the documentation browser tool, viewing the help for the " { $link dup } " word. One of the subheadings in the help article will mention the word's vocabulary." $nl -"Now, add the following at the start of the source file:" +"So now, add the following at the start of the source file:" { $code "USING: kernel ;" } -"Next, find out what vocabulary " { $link reverse } " lives in:" -{ $code "\\ reverse see" } +"Next, find out what vocabulary " { $link reverse } " lives in; type the word name " { $snippet "reverse" } " in the workspace listener's input area, and press " { $operation com-follow } "." +$nl "It lives in the " { $vocab-link "sequences" } " vocabulary, so we add that to the search path:" { $code "USING: kernel sequences ;" } -"Finally, check what vocabulary " { $link = } " lives in:" -{ $code "\\ = see" } -"It's in the " { $vocab-link "kernel" } " vocabulary, which we've already added to the search path." - +"Finally, check what vocabulary " { $link = } " lives in, and confirm that it's in the " { $vocab-link "kernel" } " vocabulary, which we've already added to the search path." +$nl "Now press " { $command workspace "workflow" refresh-all } " again, and the source file should reload without any errors. You can now go on and learn about " { $link "first-program-test" } "." ; ARTICLE: "first-program-test" "Testing your first program" @@ -81,9 +72,9 @@ $nl { $code "." } "What we just did is called " { $emphasis "interactive testing" } ". A more advanced technique which comes into play with larger programs is " { $link "tools.test" } "." $nl -"Create a file named " { $snippet "palindrome-tests.factor" } " in the same directory as " { $snippet "palindrome.factor" } ". Now, we can run unit tests from the listener:" -{ $code "\"palindrome\" test" } -"We will add some unit tests corresponding to the interactive tests we did above. Unit tests are defined with the " { $link unit-test } " word, which takes a sequence of expected outputs, and a piece of code. It runs the code, and asserts that it outputs the expected values." +"Open the file named " { $snippet "palindrome-tests.factor" } "; it is located in the same directory as " { $snippet "palindrome.factor" } ", and it was created by the scaffold tool." +$nl +"We will add some unit tests, which are similar to the interactive tests we did above. Unit tests are defined with the " { $link unit-test } " word, which takes a sequence of expected outputs, and a piece of code. It runs the code, and asserts that it outputs the expected values." $nl "Add the following three lines to " { $snippet "palindrome-tests.factor" } ":" { $code @@ -145,7 +136,7 @@ $nl ARTICLE: "first-program" "Your first program" "In this tutorial, we will write a simple Factor program which prompts the user to enter a word, and tests if it is a palindrome (that is, the word is spelled the same backwards and forwards)." $nl -"In this tutorial, you will learn about basic Factor development tools, as well as application deployment." +"In this tutorial, you will learn about basic Factor development tools. You may want to open a second workspace window by pressing " { $command workspace "workflow" workspace-window } "; this will allow you to read this tutorial and browse other documentation at the same time." { $subsection "first-program-start" } { $subsection "first-program-logic" } { $subsection "first-program-test" } diff --git a/basis/html/forms/forms-docs.factor b/basis/html/forms/forms-docs.factor index 6556d2eac2..089a516072 100644 --- a/basis/html/forms/forms-docs.factor +++ b/basis/html/forms/forms-docs.factor @@ -85,6 +85,14 @@ HELP: validate-values { $values { "assoc" assoc } { "validators" "an assoc mapping value names to quotations" } } { $description "Validates values in the assoc by looking up the corresponding validation quotation, and storing the results in named values of the current form." } ; +HELP: validation-error +{ $values { "message" string } } +{ $description "Reports a validation error not associated with a specific form field." } +{ $notes "Such errors can be rendered by calling the " { $link render-validation-errors } " word." } ; + +HELP: render-validation-errors +{ $description "Renders any validation errors reported by calls to the " { $link validation-error } " word." } ; + ARTICLE: "html.forms.forms" "HTML form infrastructure" "The below words are used to implement the " { $vocab-link "furnace.actions" } " vocabulary. Calling them directly is rarely necessary." $nl diff --git a/basis/html/forms/forms.factor b/basis/html/forms/forms.factor index c1c1aa3def..f92f8d0764 100644 --- a/basis/html/forms/forms.factor +++ b/basis/html/forms/forms.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. -USING: kernel accessors strings namespaces assocs hashtables -mirrors math fry sequences words continuations ; +USING: kernel accessors strings namespaces assocs hashtables io +mirrors math fry sequences words continuations html.elements +xml.entities ; IN: html.forms TUPLE: form errors values validation-failed ; @@ -104,3 +105,11 @@ C: validation-error : validate-values ( assoc validators -- ) swap '[ [ dup _ at ] dip validate-value ] assoc-each ; + +: render-validation-errors ( -- ) + form get errors>> + [ +
    + [
  • escape-string write
  • ] each +
+ ] unless-empty ; diff --git a/basis/html/templates/chloe/chloe-docs.factor b/basis/html/templates/chloe/chloe-docs.factor index f390aad238..402b6e68a9 100644 --- a/basis/html/templates/chloe/chloe-docs.factor +++ b/basis/html/templates/chloe/chloe-docs.factor @@ -154,6 +154,9 @@ ARTICLE: "html.templates.chloe.tags.form" "Chloe link and form tags" "" } } } + { { $snippet "t:validation-errors" } { + "Renders validation errors in the current form which are not associated with any field. Such errors are reported by invoking " { $link validation-error } "." + } } } ; ARTICLE: "html.templates.chloe.tags" "Standard Chloe tags" diff --git a/basis/html/templates/chloe/chloe.factor b/basis/html/templates/chloe/chloe.factor index 1bc4684d5c..da3f80e9a5 100644 --- a/basis/html/templates/chloe/chloe.factor +++ b/basis/html/templates/chloe/chloe.factor @@ -65,6 +65,9 @@ CHLOE: comment drop ; CHLOE: call-next-template drop reset-buffer \ call-next-template , ; +CHLOE: validation-errors + drop [ render-validation-errors ] [code] ; + : attr>word ( value -- word/f ) ":" split1 swap lookup ; diff --git a/basis/io/encodings/string/string-docs.factor b/basis/io/encodings/string/string-docs.factor index 0a35eee272..dc0f547301 100644 --- a/basis/io/encodings/string/string-docs.factor +++ b/basis/io/encodings/string/string-docs.factor @@ -4,7 +4,8 @@ USING: help.markup help.syntax byte-arrays strings ; IN: io.encodings.string ARTICLE: "io.encodings.string" "Encoding and decoding strings" -"Strings can be encoded or decoded to and from byte arrays through an encoding with the following words:" +"Strings can be encoded or decoded to and from byte arrays through an encoding by passing " +{ $link "encodings-descriptors" } " to the following words:" { $subsection encode } { $subsection decode } ; diff --git a/extra/hexdump/authors.txt b/basis/io/files/listing/authors.txt similarity index 100% rename from extra/hexdump/authors.txt rename to basis/io/files/listing/authors.txt diff --git a/basis/io/files/listing/listing-docs.factor b/basis/io/files/listing/listing-docs.factor new file mode 100644 index 0000000000..6b19e9bfa7 --- /dev/null +++ b/basis/io/files/listing/listing-docs.factor @@ -0,0 +1,17 @@ +! Copyright (C) 2008 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax io.streams.string strings ; +IN: io.files.listing + +HELP: directory. +{ $values + { "path" "a pathname string" } +} +{ $description "Prints information about all files in a directory to the output stream in a cross-platform way similar to the Unix " { $snippet "ls" } " command." } ; + +ARTICLE: "io.files.listing" "Listing files" +"The " { $vocab-link "io.files.listing" } " vocabulary implements directory file listing in a cross-platform way." $nl +"Listing a directory:" +{ $subsection directory. } ; + +ABOUT: "io.files.listing" diff --git a/basis/io/files/listing/listing-tests.factor b/basis/io/files/listing/listing-tests.factor new file mode 100644 index 0000000000..a2347c8db9 --- /dev/null +++ b/basis/io/files/listing/listing-tests.factor @@ -0,0 +1,6 @@ +! Copyright (C) 2008 Your name. +! See http://factorcode.org/license.txt for BSD license. +USING: tools.test io.files.listing strings kernel ; +IN: io.files.listing.tests + +[ ] [ "" directory. ] unit-test diff --git a/basis/io/files/listing/listing.factor b/basis/io/files/listing/listing.factor new file mode 100755 index 0000000000..f88fcec3a1 --- /dev/null +++ b/basis/io/files/listing/listing.factor @@ -0,0 +1,39 @@ +! Copyright (C) 2008 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors arrays combinators io io.files kernel +math.parser sequences system vocabs.loader calendar ; + +IN: io.files.listing + +> ] [ minute>> ] bi + [ number>string 2 CHAR: 0 pad-left ] bi@ ":" swap 3append ; + +: ls-timestamp ( timestamp -- string ) + [ month>> month-abbreviation ] + [ day>> number>string 2 CHAR: \s pad-left ] + [ + dup year>> dup now year>> = + [ drop ls-time ] [ nip number>string ] if + 5 CHAR: \s pad-left + ] tri 3array " " join ; + +: read>string ( ? -- string ) "r" "-" ? ; inline + +: write>string ( ? -- string ) "w" "-" ? ; inline + +: execute>string ( ? -- string ) "x" "-" ? ; inline + +HOOK: (directory.) os ( path -- lines ) + +PRIVATE> + +: directory. ( path -- ) + [ (directory.) ] with-directory-files [ print ] each ; + +{ + { [ os unix? ] [ "io.files.listing.unix" ] } + { [ os windows? ] [ "io.files.listing.windows" ] } +} cond require diff --git a/basis/io/files/listing/tags.txt b/basis/io/files/listing/tags.txt new file mode 100644 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/io/files/listing/tags.txt @@ -0,0 +1 @@ +unportable diff --git a/basis/io/files/listing/unix/authors.txt b/basis/io/files/listing/unix/authors.txt new file mode 100755 index 0000000000..7c1b2f2279 --- /dev/null +++ b/basis/io/files/listing/unix/authors.txt @@ -0,0 +1 @@ +Doug Coleman diff --git a/basis/io/files/listing/unix/tags.txt b/basis/io/files/listing/unix/tags.txt new file mode 100644 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/io/files/listing/unix/tags.txt @@ -0,0 +1 @@ +unportable diff --git a/basis/io/files/listing/unix/unix.factor b/basis/io/files/listing/unix/unix.factor new file mode 100755 index 0000000000..313ce1f79a --- /dev/null +++ b/basis/io/files/listing/unix/unix.factor @@ -0,0 +1,48 @@ +! Copyright (C) 2008 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors combinators kernel system unicode.case +io.unix.files io.files.listing generalizations strings +arrays sequences io.files math.parser unix.groups unix.users +io.files.listing.private ; +IN: io.files.listing.unix + +string ( str bools -- str' ) + swap { + { { t t } [ >lower ] } + { { t f } [ >upper ] } + { { f t } [ drop "x" ] } + [ 2drop "-" ] + } case ; + +: permissions-string ( permissions -- str ) + { + [ type>> file-type>ch 1string ] + [ user-read? read>string ] + [ user-write? write>string ] + [ [ uid? ] [ user-execute? ] bi 2array "s" unix-execute>string ] + [ group-read? read>string ] + [ group-write? write>string ] + [ [ gid? ] [ group-execute? ] bi 2array "s" unix-execute>string ] + [ other-read? read>string ] + [ other-write? write>string ] + [ [ sticky? ] [ other-execute? ] bi 2array "t" unix-execute>string ] + } cleave 10 narray concat ; + +M: unix (directory.) ( path -- lines ) + [ [ + [ + dup file-info + { + [ permissions-string ] + [ nlink>> number>string 3 CHAR: \s pad-left ] + ! [ uid>> ] + ! [ gid>> ] + [ size>> number>string 15 CHAR: \s pad-left ] + [ modified>> ls-timestamp ] + } cleave 4 narray swap suffix " " join + ] map + ] with-group-cache ] with-user-cache ; + +PRIVATE> diff --git a/basis/io/files/listing/windows/authors.txt b/basis/io/files/listing/windows/authors.txt new file mode 100755 index 0000000000..7c1b2f2279 --- /dev/null +++ b/basis/io/files/listing/windows/authors.txt @@ -0,0 +1 @@ +Doug Coleman diff --git a/basis/io/files/listing/windows/tags.txt b/basis/io/files/listing/windows/tags.txt new file mode 100644 index 0000000000..6bf68304bb --- /dev/null +++ b/basis/io/files/listing/windows/tags.txt @@ -0,0 +1 @@ +unportable diff --git a/basis/io/files/listing/windows/windows.factor b/basis/io/files/listing/windows/windows.factor new file mode 100755 index 0000000000..33ab47a50a --- /dev/null +++ b/basis/io/files/listing/windows/windows.factor @@ -0,0 +1,25 @@ +! Copyright (C) 2008 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors calendar.format combinators io.files +kernel math.parser sequences splitting system io.files.listing +generalizations io.files.listing.private ; +IN: io.files.listing.windows + +" 20 CHAR: \s pad-right + ] [ + size>> number>string 20 CHAR: \s pad-left + ] if ; + +M: windows (directory.) ( entries -- lines ) + [ + dup file-info { + [ modified>> timestamp>ymdhms ] + [ directory-or-size ] + } cleave 2 narray swap suffix " " join + ] map ; + +PRIVATE> diff --git a/basis/io/servers/connection/connection-docs.factor b/basis/io/servers/connection/connection-docs.factor index 00711ce226..22c40da3d7 100644 --- a/basis/io/servers/connection/connection-docs.factor +++ b/basis/io/servers/connection/connection-docs.factor @@ -45,15 +45,20 @@ ARTICLE: "server-config-handler" "Client handler quotation" $nl "The two methods are equivalent, representing a functional versus an object-oriented approach to the problem." ; +ARTICLE: "server-examples" "Threaded server examples" +"The " { $vocab-link "time-server" } " vocabulary implements a simple threaded server which sends the current time to the client. The " { $vocab-link "concurrency.distributed" } ", " { $vocab-link "ftp.server" } ", and " { $vocab-link "http.server" } " vocabularies demonstrate more complex usage of the threaded server library." ; + ARTICLE: "io.servers.connection" "Threaded servers" "The " { $vocab-link "io.servers.connection" } " vocabulary implements a generic server abstraction for " { $link "network-connection" } ". A set of threads listen for connections, and additional threads are spawned for each client connection. In addition to this basic functionality, it provides some advanced features such as logging, connection limits and secure socket support." -{ $subsection threaded-server } -{ $subsection "server-config" } +{ $subsection "server-examples" } "Creating threaded servers with client handler quotations:" { $subsection } "Client handlers can also be implemented by subclassing a threaded server; see " { $link "server-config-handler" } " for details:" +{ $subsection threaded-server } { $subsection new-threaded-server } { $subsection handle-client* } +"The server must be configured before it can be started." +{ $subsection "server-config" } "Starting the server:" { $subsection start-server } { $subsection start-server* } diff --git a/basis/io/unix/files/files.factor b/basis/io/unix/files/files.factor index 9ebfdaaa5a..3f254e7713 100644 --- a/basis/io/unix/files/files.factor +++ b/basis/io/unix/files/files.factor @@ -172,6 +172,30 @@ M: unix (directory-entries) ( path -- seq ) PRIVATE> +: ch>file-type ( ch -- type ) + { + { CHAR: b [ +block-device+ ] } + { CHAR: c [ +character-device+ ] } + { CHAR: d [ +directory+ ] } + { CHAR: l [ +symbolic-link+ ] } + { CHAR: s [ +socket+ ] } + { CHAR: p [ +fifo+ ] } + { CHAR: - [ +regular-file+ ] } + [ drop +unknown+ ] + } case ; + +: file-type>ch ( type -- string ) + { + { +block-device+ [ CHAR: b ] } + { +character-device+ [ CHAR: c ] } + { +directory+ [ CHAR: d ] } + { +symbolic-link+ [ CHAR: l ] } + { +socket+ [ CHAR: s ] } + { +fifo+ [ CHAR: p ] } + { +regular-file+ [ CHAR: - ] } + [ drop CHAR: - ] + } case ; + : UID OCT: 0004000 ; inline : GID OCT: 0002000 ; inline : STICKY OCT: 0001000 ; inline diff --git a/basis/io/windows/files/files.factor b/basis/io/windows/files/files.factor index 3952299543..d0409ce59a 100755 --- a/basis/io/windows/files/files.factor +++ b/basis/io/windows/files/files.factor @@ -149,35 +149,39 @@ SYMBOLS: +read-only+ +hidden+ +system+ +sparse-file+ +reparse-point+ +compressed+ +offline+ +not-content-indexed+ +encrypted+ ; -: win32-file-attribute ( n attr symbol -- n ) - >r dupd mask? r> swap [ , ] [ drop ] if ; +TUPLE: windows-file-info < file-info attributes ; + +: win32-file-attribute ( n attr symbol -- ) + rot mask? [ , ] [ drop ] if ; : win32-file-attributes ( n -- seq ) [ - FILE_ATTRIBUTE_READONLY +read-only+ win32-file-attribute - FILE_ATTRIBUTE_HIDDEN +hidden+ win32-file-attribute - FILE_ATTRIBUTE_SYSTEM +system+ win32-file-attribute - FILE_ATTRIBUTE_DIRECTORY +directory+ win32-file-attribute - FILE_ATTRIBUTE_ARCHIVE +archive+ win32-file-attribute - FILE_ATTRIBUTE_DEVICE +device+ win32-file-attribute - FILE_ATTRIBUTE_NORMAL +normal+ win32-file-attribute - FILE_ATTRIBUTE_TEMPORARY +temporary+ win32-file-attribute - FILE_ATTRIBUTE_SPARSE_FILE +sparse-file+ win32-file-attribute - FILE_ATTRIBUTE_REPARSE_POINT +reparse-point+ win32-file-attribute - FILE_ATTRIBUTE_COMPRESSED +compressed+ win32-file-attribute - FILE_ATTRIBUTE_OFFLINE +offline+ win32-file-attribute - FILE_ATTRIBUTE_NOT_CONTENT_INDEXED +not-content-indexed+ win32-file-attribute - FILE_ATTRIBUTE_ENCRYPTED +encrypted+ win32-file-attribute - drop + { + [ +read-only+ FILE_ATTRIBUTE_READONLY win32-file-attribute ] + [ +hidden+ FILE_ATTRIBUTE_HIDDEN win32-file-attribute ] + [ +system+ FILE_ATTRIBUTE_SYSTEM win32-file-attribute ] + [ +directory+ FILE_ATTRIBUTE_DIRECTORY win32-file-attribute ] + [ +archive+ FILE_ATTRIBUTE_ARCHIVE win32-file-attribute ] + [ +device+ FILE_ATTRIBUTE_DEVICE win32-file-attribute ] + [ +normal+ FILE_ATTRIBUTE_NORMAL win32-file-attribute ] + [ +temporary+ FILE_ATTRIBUTE_TEMPORARY win32-file-attribute ] + [ +sparse-file+ FILE_ATTRIBUTE_SPARSE_FILE win32-file-attribute ] + [ +reparse-point+ FILE_ATTRIBUTE_REPARSE_POINT win32-file-attribute ] + [ +compressed+ FILE_ATTRIBUTE_COMPRESSED win32-file-attribute ] + [ +offline+ FILE_ATTRIBUTE_OFFLINE win32-file-attribute ] + [ +not-content-indexed+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED win32-file-attribute ] + [ +encrypted+ FILE_ATTRIBUTE_ENCRYPTED win32-file-attribute ] + } cleave ] { } make ; : win32-file-type ( n -- symbol ) FILE_ATTRIBUTE_DIRECTORY mask? +directory+ +regular-file+ ? ; : WIN32_FIND_DATA>file-info ( WIN32_FIND_DATA -- file-info ) - [ \ file-info new ] dip + [ \ windows-file-info new ] dip { [ WIN32_FIND_DATA-dwFileAttributes win32-file-type >>type ] + [ WIN32_FIND_DATA-dwFileAttributes win32-file-attributes >>attributes ] [ [ WIN32_FIND_DATA-nFileSizeLow ] [ WIN32_FIND_DATA-nFileSizeHigh ] bi >64bit >>size @@ -196,9 +200,10 @@ SYMBOLS: +read-only+ +hidden+ +system+ ] keep ; : BY_HANDLE_FILE_INFORMATION>file-info ( HANDLE_FILE_INFORMATION -- file-info ) - [ \ file-info new ] dip + [ \ windows-file-info new ] dip { [ BY_HANDLE_FILE_INFORMATION-dwFileAttributes win32-file-type >>type ] + [ BY_HANDLE_FILE_INFORMATION-dwFileAttributes win32-file-attributes >>attributes ] [ [ BY_HANDLE_FILE_INFORMATION-nFileSizeLow ] [ BY_HANDLE_FILE_INFORMATION-nFileSizeHigh ] bi >64bit >>size @@ -276,18 +281,31 @@ M: winnt file-system-info ( path -- file-system-info ) swap >>type swap >>mount-point ; +: volume>paths ( string -- array ) + 16384 "ushort" tuck dup length + 0 dup [ GetVolumePathNamesForVolumeName 0 = ] dip swap [ + win32-error-string throw + ] [ + *uint "ushort" heap-size * head + utf16n alien>string CHAR: \0 split + ] if ; + : find-first-volume ( -- string handle ) MAX_PATH 1+ dup length dupd FindFirstVolume dup win32-error=0/f [ utf16n alien>string ] dip ; -: find-next-volume ( handle -- string ) +: find-next-volume ( handle -- string/f ) MAX_PATH 1+ dup length - [ FindNextVolume win32-error=0/f ] 2keep drop - utf16n alien>string ; + over [ FindNextVolume ] dip swap 0 = [ + GetLastError ERROR_NO_MORE_FILES = + [ drop f ] [ win32-error ] if + ] [ + utf16n alien>string + ] if ; -: mounted ( -- array ) +: find-volumes ( -- array ) find-first-volume [ '[ @@ -298,6 +316,13 @@ M: winnt file-system-info ( path -- file-system-info ) ] ] [ '[ _ FindVolumeClose win32-error=0/f ] ] bi [ ] cleanup ; +M: winnt file-systems ( -- array ) + find-volumes [ volume>paths ] map + concat [ + [ file-system-info ] + [ drop winnt-file-system-info new swap >>mount-point ] recover + ] map ; + : file-times ( path -- timestamp timestamp timestamp ) [ normalize-path open-existing &dispose handle>> diff --git a/basis/linked-assocs/authors.txt b/basis/linked-assocs/authors.txt new file mode 100644 index 0000000000..35a4db1737 --- /dev/null +++ b/basis/linked-assocs/authors.txt @@ -0,0 +1,2 @@ +Slava Pestov +James Cash diff --git a/basis/linked-assocs/linked-assocs-docs.factor b/basis/linked-assocs/linked-assocs-docs.factor new file mode 100644 index 0000000000..6fd42954aa --- /dev/null +++ b/basis/linked-assocs/linked-assocs-docs.factor @@ -0,0 +1,23 @@ +IN: linked-assocs +USING: help.markup help.syntax assocs ; + +HELP: linked-assoc +{ $class-description "The class of linked assocs. Linked assoc are implemented by combining an assoc with a dlist. The assoc is used for lookup and retrieval of single values, while the dlist is used for getting lists of keys/values, which will be in insertion order." } ; + +HELP: +{ $values { "exemplar" "an exemplar assoc" } { "assoc" linked-assoc } } +{ $description "Creates an empty linked assoc backed by a new instance of the same type as the exemplar." } ; + +HELP: +{ $values { "assoc" linked-assoc } } +{ $description "Creates an empty linked assoc backed by a hashtable." } ; + +ARTICLE: "linked-assocs" "Linked assocs" +"A " { $emphasis "linked assoc" } " is an assoc which combines an underlying assoc with a dlist to form a structure which has the insertion and retrieval characteristics of the underlying assoc (typically a hashtable), but with the ability to get the entries in insertion order by calling " { $link >alist } "." +$nl +"Linked assocs are implemented in the " { $vocab-link "linked-assocs" } " vocabulary." +{ $subsection linked-assoc } +{ $subsection } +{ $subsection } ; + +ABOUT: "linked-assocs" \ No newline at end of file diff --git a/basis/linked-assocs/linked-assocs-tests.factor b/basis/linked-assocs/linked-assocs-tests.factor new file mode 100644 index 0000000000..7a259ee59a --- /dev/null +++ b/basis/linked-assocs/linked-assocs-tests.factor @@ -0,0 +1,57 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel sequences assocs tools.test linked-assocs math ; +IN: linked-assocs.test + +{ { 1 2 3 } } [ + 1 "b" pick set-at + 2 "c" pick set-at + 3 "a" pick set-at + values +] unit-test + +{ 2 t } [ + 1 "b" pick set-at + 2 "c" pick set-at + 3 "a" pick set-at + "c" swap at* +] unit-test + +{ { 2 3 4 } { "c" "a" "d" } 3 } [ + 1 "a" pick set-at + 2 "c" pick set-at + 3 "a" pick set-at + 4 "d" pick set-at + [ values ] [ keys ] [ assoc-size ] tri +] unit-test + +{ f 1 } [ + 1 "c" pick set-at + 2 "b" pick set-at + "c" over delete-at + "c" over at swap assoc-size +] unit-test + +{ { } 0 } [ + 1 "a" pick set-at + 2 "c" pick set-at + 3 "a" pick set-at + 4 "d" pick set-at + dup clear-assoc [ keys ] [ assoc-size ] bi +] unit-test + +{ { } { 1 2 3 } } [ + dup clone + 1 "c" pick set-at + 2 "q" pick set-at + 3 "a" pick set-at + [ values ] bi@ +] unit-test + +{ 9 } [ + + { [ 3 * ] [ 1- ] } "first" pick set-at + { [ [ 1- ] bi@ ] [ 2 / ] } "second" pick set-at + 4 6 pick values [ first call ] each + + swap values [ second call ] each +] unit-test \ No newline at end of file diff --git a/basis/linked-assocs/linked-assocs.factor b/basis/linked-assocs/linked-assocs.factor new file mode 100644 index 0000000000..7330ac1a56 --- /dev/null +++ b/basis/linked-assocs/linked-assocs.factor @@ -0,0 +1,44 @@ +! Copyright (C) 2008 Slava Pestov, James Cash. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors assocs arrays kernel deques dlists sequences fry ; +IN: linked-assocs + +TUPLE: linked-assoc assoc dlist ; + +: ( exemplar -- assoc ) + 0 swap new-assoc linked-assoc boa ; + +: ( -- assoc ) + H{ } ; + +M: linked-assoc assoc-size assoc>> assoc-size ; + +M: linked-assoc at* assoc>> at* [ [ obj>> second ] when ] keep ; + +M: linked-assoc delete-at + [ [ assoc>> ] [ dlist>> ] bi [ at ] dip '[ _ delete-node ] when* ] + [ assoc>> delete-at ] 2bi ; + +> push-back* ; +PRIVATE> + +M: linked-assoc set-at + [ 2dup assoc>> key? [ 2dup delete-at ] when add-to-dlist ] 2keep + assoc>> set-at ; + +: dlist>seq ( dlist -- seq ) + [ ] pusher [ dlist-each ] dip ; + +M: linked-assoc >alist + dlist>> dlist>seq ; + +M: linked-assoc clear-assoc + [ assoc>> clear-assoc ] [ dlist>> clear-deque ] bi ; + +M: linked-assoc clone + [ assoc>> clone ] [ dlist>> clone ] bi + linked-assoc boa ; + +INSTANCE: linked-assoc assoc diff --git a/basis/linked-assocs/summary.txt b/basis/linked-assocs/summary.txt new file mode 100644 index 0000000000..54b0d14d4c --- /dev/null +++ b/basis/linked-assocs/summary.txt @@ -0,0 +1 @@ +Assocs that yield items in insertion order diff --git a/basis/linked-assocs/tags.txt b/basis/linked-assocs/tags.txt new file mode 100644 index 0000000000..031765c41b --- /dev/null +++ b/basis/linked-assocs/tags.txt @@ -0,0 +1 @@ +assocs diff --git a/basis/locals/locals-docs.factor b/basis/locals/locals-docs.factor index eb368936d4..35e0536530 100644 --- a/basis/locals/locals-docs.factor +++ b/basis/locals/locals-docs.factor @@ -1,5 +1,5 @@ USING: help.syntax help.markup kernel macros prettyprint -memoize ; +memoize combinators arrays ; IN: locals HELP: [| @@ -84,6 +84,39 @@ HELP: MEMO:: { POSTPONE: MEMO: POSTPONE: MEMO:: } related-words +ARTICLE: "locals-literals" "Locals in array and hashtable literals" +"Certain data type literals are permitted to contain free variables. Any such literals are written into code which constructs an instance of the type with the free variable values spliced in. Conceptually, this is similar to the transformation applied to quotations containing free variables." +$nl +"The data types which receive this special handling are the following:" +{ $list + { $link "arrays" } + { $link "hashtables" } + { $link "vectors" } + { $link "tuples" } +} +"This feature changes the semantics of literal object identity. An ordinary word containing a literal pushes the same literal on the stack every time it is invoked:" +{ $example + "IN: scratchpad" + "TUPLE: person first-name last-name ;" + ": ordinary-word-test ( -- tuple )" + " T{ person { first-name \"Alan\" } { last-name \"Kay\" } } ;" + "ordinary-word-test ordinary-word-test eq? ." + "t" +} +"In a word with locals, literals expand into code which constructs the literal, and so every invocation pushes a new object:" +{ $example + "IN: scratchpad" + "TUPLE: person first-name last-name ;" + ":: ordinary-word-test ( -- tuple )" + " T{ person { first-name \"Alan\" } { last-name \"Kay\" } } ;" + "ordinary-word-test ordinary-word-test eq? ." + "f" +} +"One exception to the above rule is that array instances containing no free variables do retain identity. This allows macros such as " { $link cond } " to recognize that the array is constant and expand at compile-time." +$nl +"For example, here is an implementation of the " { $link 3array } " word which uses this feature:" +{ $code ":: 3array ( x y z -- array ) { x y z } ;" } ; + ARTICLE: "locals-mutable" "Mutable locals" "In the list of bindings supplied to " { $link POSTPONE: :: } ", " { $link POSTPONE: [let } ", " { $link POSTPONE: [let* } " or " { $link POSTPONE: [| } ", a mutable binding may be introduced by suffixing its named with " { $snippet "!" } ". Mutable bindings are read by giving their name as usual; the suffix is not part of the binding's name. To write to a mutable binding, use the binding's name with the " { $snippet "!" } " suffix." $nl @@ -139,6 +172,7 @@ $nl "Lambda abstractions:" { $subsection POSTPONE: [| } "Additional topics:" +{ $subsection "locals-literals" } { $subsection "locals-mutable" } { $subsection "locals-limitations" } "Locals complement dynamically scoped variables implemented in the " { $vocab-link "namespaces" } " vocabulary." ; diff --git a/basis/locals/locals.factor b/basis/locals/locals.factor index c588269284..e74ecf3dc9 100644 --- a/basis/locals/locals.factor +++ b/basis/locals/locals.factor @@ -6,8 +6,7 @@ quotations debugger macros arrays macros splitting combinators prettyprint.backend definitions prettyprint hashtables prettyprint.sections sets sequences.private effects effects.parser generic generic.parser compiler.units accessors -locals.backend memoize macros.expander lexer classes -stack-checker.known-words ; +locals.backend memoize macros.expander lexer classes ; IN: locals ! Inspired by @@ -49,8 +48,7 @@ PREDICATE: local < word "local?" word-prop ; : ( name -- word ) #! Create a local variable identifier f - dup t "local?" set-word-prop - dup { } { object } define-primitive ; + dup t "local?" set-word-prop ; PREDICATE: local-word < word "local-word?" word-prop ; @@ -61,14 +59,12 @@ PREDICATE: local-reader < word "local-reader?" word-prop ; : ( name -- word ) f - dup t "local-reader?" set-word-prop - dup { } { object } define-primitive ; + dup t "local-reader?" set-word-prop ; PREDICATE: local-writer < word "local-writer?" word-prop ; : ( reader -- word ) dup name>> "!" append f { - [ nip { object } { } define-primitive ] [ nip t "local-writer?" set-word-prop ] [ swap "local-reader" set-word-prop ] [ "local-writer" set-word-prop ] diff --git a/basis/macros/expander/expander.factor b/basis/macros/expander/expander.factor index c2fceffae6..3666fa2423 100644 --- a/basis/macros/expander/expander.factor +++ b/basis/macros/expander/expander.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: kernel sequences sequences.private namespaces make quotations accessors words continuations vectors effects math -generalizations stack-checker.transforms fry ; +generalizations fry ; IN: macros.expander GENERIC: expand-macros ( quot -- quot' ) diff --git a/basis/macros/macros.factor b/basis/macros/macros.factor index 0a6621f044..794d523d00 100644 --- a/basis/macros/macros.factor +++ b/basis/macros/macros.factor @@ -1,21 +1,18 @@ ! Copyright (C) 2007, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: parser kernel sequences words effects -stack-checker.transforms combinators assocs definitions -quotations namespaces memoize accessors ; +USING: parser kernel sequences words effects combinators assocs +definitions quotations namespaces memoize accessors ; IN: macros : real-macro-effect ( word -- effect' ) "declared-effect" word-prop in>> 1 ; : define-macro ( word definition -- ) - over "declared-effect" word-prop in>> length >r - 2dup "macro" set-word-prop - 2dup over real-macro-effect memoize-quot [ call ] append define - r> define-transform ; + [ "macro" set-word-prop ] + [ over real-macro-effect memoize-quot [ call ] append define ] + 2bi ; -: MACRO: - (:) define-macro ; parsing +: MACRO: (:) define-macro ; parsing PREDICATE: macro < word "macro" word-prop >boolean ; diff --git a/basis/math/bitwise/bitwise-docs.factor b/basis/math/bitwise/bitwise-docs.factor index 247523369b..4f2606bda0 100644 --- a/basis/math/bitwise/bitwise-docs.factor +++ b/basis/math/bitwise/bitwise-docs.factor @@ -1,12 +1,8 @@ -USING: help.markup help.syntax math ; +! Copyright (C) 2008 Doug Coleman. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax math sequences ; IN: math.bitwise -ARTICLE: "math-bitfields" "Constructing bit fields" -"Some applications, such as binary communication protocols and assemblers, need to construct integers from elaborate bit field specifications. Hand-coding this using " { $link shift } " and " { $link bitor } " results in repetitive code. A higher-level facility exists to factor out this repetition:" -{ $subsection bitfield } ; - -ABOUT: "math-bitfields" - HELP: bitfield { $values { "values..." "a series of objects" } { "bitspec" "an array" } { "n" integer } } { $description "Constructs an integer from a series of values on the stack together with a bit field specifier, which is an array whose elements have one of the following shapes:" @@ -42,9 +38,307 @@ HELP: bits { $example "USING: math.bitwise prettyprint ;" "HEX: 123abcdef 16 bits .h" "cdef" } ; HELP: bitroll -{ $values { "x" "an integer (input)" } { "s" "an integer (shift)" } { "w" "an integer (wrap)" } { "y" integer } } +{ $values { "x" integer } { "s" "a shift integer" } { "w" "a wrap integer" } { "y" integer } +} { $description "Roll n by s bits to the left, wrapping around after w bits." } { $examples { $example "USING: math.bitwise prettyprint ;" "1 -1 32 bitroll .b" "10000000000000000000000000000000" } { $example "USING: math.bitwise prettyprint ;" "HEX: ffff0000 8 32 bitroll .h" "ff0000ff" } } ; + +HELP: bit-clear? +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Returns " { $link t } " if the nth bit is set to zero." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: ff 8 bit-clear? ." + "t" + } + { $example "" "USING: math.bitwise prettyprint ;" + "HEX: ff 7 bit-clear? ." + "f" + } +} ; + +{ bit? bit-clear? set-bit clear-bit } related-words + +HELP: bit-count +{ $values + { "x" integer } + { "n" integer } +} +{ $description "Returns the number of set bits as an integer." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: f0 bit-count ." + "4" + } + { $example "USING: math.bitwise prettyprint ;" + "-7 bit-count ." + "2" + } +} ; + +HELP: bitroll-32 +{ $values + { "n" integer } { "s" integer } + { "n'" integer } +} +{ $description "Rolls the number " { $snippet "n" } " by " { $snippet "s" } " bits to the left, wrapping around after 32 bits." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 10 bitroll-32 .h" + "400" + } + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 -10 bitroll-32 .h" + "400000" + } +} ; + +HELP: bitroll-64 +{ $values + { "n" integer } { "s" "a shift integer" } + { "n'" integer } +} +{ $description "Rolls the number " { $snippet "n" } " by " { $snippet "s" } " bits to the left, wrapping around after 64 bits." } +{ $examples + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 10 bitroll-64 .h" + "400" + } + { $example "USING: math.bitwise prettyprint ;" + "HEX: 1 -10 bitroll-64 .h" + "40000000000000" + } +} ; + +{ bitroll bitroll-32 bitroll-64 } related-words + +HELP: clear-bit +{ $values + { "x" integer } { "n" integer } + { "y" integer } +} +{ $description "Sets the nth bit of " { $snippet "x" } " to zero." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff 7 clear-bit .h" + "7f" + } +} ; + +HELP: flags +{ $values + { "values" sequence } +} +{ $description "Constructs a constant flag value from a sequence of integers or words that output integers. The resulting constant is computed at compile-time, which makes this word as efficient as using a literal integer." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "IN: scratchpad" + ": MY-CONSTANT HEX: 1 ; inline" + "{ HEX: 20 MY-CONSTANT BIN: 100 } flags .h" + "25" + } +} ; + +HELP: mask +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "After the operation, only the bits that were set in both the mask and the original number are set." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "BIN: 11111111 BIN: 101 mask .b" + "101" + } +} ; + +HELP: mask-bit +{ $values + { "m" integer } { "n" integer } + { "m'" integer } +} +{ $description "Turns off all bits besides the nth bit." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff 2 mask-bit .b" + "100" + } +} ; + +HELP: mask? +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Returns true if all of the bits in the mask " { $snippet "n" } " are set in the integer input " { $snippet "x" } "." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff HEX: f mask? ." + "t" + } + + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: f0 HEX: 1 mask? ." + "f" + } +} ; + +HELP: on-bits +{ $values + { "n" integer } + { "m" integer } +} +{ $description "Returns an integer with " { $snippet "n" } " bits set." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "6 on-bits .h" + "3f" + } + { $example "USING: math.bitwise kernel prettyprint ;" + "64 on-bits .h" + "ffffffffffffffff" + } +} +; + +HELP: set-bit +{ $values + { "x" integer } { "n" integer } + { "y" integer } +} +{ $description "Sets the nth bit of " { $snippet "x" } "." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "0 5 set-bit .h" + "20" + } +} ; + +HELP: shift-mod +{ $values + { "n" integer } { "s" integer } { "w" integer } + { "n" integer } +} +{ $description "" } ; + +HELP: unmask +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Clears the bits in " { $snippet "x" } " if they are set in the mask " { $snippet "n" } "." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff HEX: 0f unmask .h" + "f0" + } +} ; + +HELP: unmask? +{ $values + { "x" integer } { "n" integer } + { "?" "a boolean" } +} +{ $description "Tests whether unmasking the bits in " { $snippet "x" } " would return an integer greater than zero." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ff HEX: 0f unmask? ." + "t" + } +} ; + +HELP: w* +{ $values + { "int" integer } { "int" integer } + { "int" integer } +} +{ $description "Multiplies two integers and wraps the result to 32 bits." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ffffffff HEX: 2 w* ." + "4294967294" + } +} ; + +HELP: w+ +{ $values + { "int" integer } { "int" integer } + { "int" integer } +} +{ $description "Adds two integers and wraps the result to 32 bits." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: ffffffff HEX: 2 w+ ." + "1" + } +} ; + +HELP: w- +{ $values + { "int" integer } { "int" integer } + { "int" integer } +} +{ $description "Subtracts two integers and wraps the result to 32 bits." } +{ $examples + { $example "USING: math.bitwise kernel prettyprint ;" + "HEX: 0 HEX: ff w- ." + "4294967041" + } +} ; + +HELP: wrap +{ $values + { "m" integer } { "n" integer } + { "m'" integer } +} +{ $description "Wraps an integer " { $snippet "m" } " by modding it by " { $snippet "n" } ". This word is uses bitwise arithmetic and does not actually call the modulus word, and as such can only mod by powers of two." } +{ $examples "Equivalent to modding by 8:" + { $example + "USING: math.bitwise prettyprint ;" + "HEX: ffff 8 wrap .h" + "7" + } +} ; + +ARTICLE: "math-bitfields" "Constructing bit fields" +"Some applications, such as binary communication protocols and assemblers, need to construct integers from elaborate bit field specifications. Hand-coding this using " { $link shift } " and " { $link bitor } " results in repetitive code. A higher-level facility exists to factor out this repetition:" +{ $subsection bitfield } ; + +ARTICLE: "math.bitwise" "Bitwise arithmetic" +"The " { $vocab-link "math.bitwise" } " vocabulary can implements bitwise arithmetic words that are useful for efficiency, low-level programming, and interfacing with C libraries." $nl +"Setting and clearing bits:" +{ $subsection set-bit } +{ $subsection clear-bit } +"Testing if bits are set or clear:" +{ $subsection bit? } +{ $subsection bit-clear? } +"Operations with bitmasks:" +{ $subsection mask } +{ $subsection unmask } +{ $subsection mask? } +{ $subsection unmask? } +"Generating an integer with n set bits:" +{ $subsection on-bits } +"Counting the number of set bits:" +{ $subsection bit-count } +"More efficient modding by powers of two:" +{ $subsection wrap } +"Bit-rolling:" +{ $subsection bitroll } +{ $subsection bitroll-32 } +{ $subsection bitroll-64 } +"32-bit arithmetic:" +{ $subsection w+ } +{ $subsection w- } +{ $subsection w* } +"Bitfields:" +{ $subsection flags } +{ $subsection "math-bitfields" } ; + +ABOUT: "math.bitwise" diff --git a/basis/math/bitwise/bitwise-tests.factor b/basis/math/bitwise/bitwise-tests.factor index 8b13cb23b3..4422992956 100644 --- a/basis/math/bitwise/bitwise-tests.factor +++ b/basis/math/bitwise/bitwise-tests.factor @@ -27,3 +27,5 @@ IN: math.bitwise.tests [ 3 ] [ foo ] unit-test [ 3 ] [ { a b } flags ] unit-test \ foo must-infer + +[ 1 ] [ { 1 } flags ] unit-test diff --git a/basis/math/bitwise/bitwise.factor b/basis/math/bitwise/bitwise.factor index 871f40e74c..ad1907fcb0 100644 --- a/basis/math/bitwise/bitwise.factor +++ b/basis/math/bitwise/bitwise.factor @@ -1,4 +1,4 @@ -! Copyright (C) 2007, 2008 Slava Pestov. +! Copyright (C) 2007, 2008 Slava Pestov, Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: arrays kernel math math.functions sequences sequences.private words namespaces macros hints @@ -8,28 +8,29 @@ IN: math.bitwise ! utilities : clear-bit ( x n -- y ) 2^ bitnot bitand ; inline : set-bit ( x n -- y ) 2^ bitor ; inline -: bit-clear? ( x n -- ? ) 2^ bitand zero? ; inline +: bit-clear? ( x n -- ? ) 2^ bitand 0 = ; inline : unmask ( x n -- ? ) bitnot bitand ; inline : unmask? ( x n -- ? ) unmask 0 > ; inline : mask ( x n -- ? ) bitand ; inline : mask? ( x n -- ? ) mask 0 > ; inline : wrap ( m n -- m' ) 1- bitand ; inline : bits ( m n -- m' ) 2^ wrap ; inline -: mask-bit ( m n -- m' ) 1- 2^ mask ; inline +: mask-bit ( m n -- m' ) 2^ mask ; inline +: on-bits ( n -- m ) 2^ 1- ; inline : shift-mod ( n s w -- n ) - >r shift r> 2^ wrap ; inline + [ shift ] dip 2^ wrap ; inline : bitroll ( x s w -- y ) - [ wrap ] keep - [ shift-mod ] - [ [ - ] keep shift-mod ] 3bi bitor ; inline + [ wrap ] keep + [ shift-mod ] + [ [ - ] keep shift-mod ] 3bi bitor ; inline -: bitroll-32 ( n s -- n' ) 32 bitroll ; +: bitroll-32 ( n s -- n' ) 32 bitroll ; inline HINTS: bitroll-32 bignum fixnum ; -: bitroll-64 ( n s -- n' ) 64 bitroll ; +: bitroll-64 ( n s -- n' ) 64 bitroll ; inline HINTS: bitroll-64 bignum fixnum ; @@ -40,7 +41,7 @@ HINTS: bitroll-64 bignum fixnum ; ! flags MACRO: flags ( values -- ) - [ 0 ] [ [ execute bitor ] curry compose ] reduce ; + [ 0 ] [ [ dup word? [ execute ] when bitor ] curry compose ] reduce ; ! bitfield r swapd execute r> ] [ ] ? + first2 over word? [ [ swapd execute ] dip ] [ ] ? [ shift bitor ] append 2curry ; PRIVATE> @@ -91,4 +92,4 @@ M: bignum (bit-count) PRIVATE> : bit-count ( x -- n ) - dup 0 >= [ (bit-count) ] [ bitnot (bit-count) ] if ; inline + dup 0 < [ bitnot ] when (bit-count) ; inline diff --git a/basis/math/functions/functions-tests.factor b/basis/math/functions/functions-tests.factor index cbaf37daf8..a06a67e4a1 100644 --- a/basis/math/functions/functions-tests.factor +++ b/basis/math/functions/functions-tests.factor @@ -134,3 +134,6 @@ IN: math.functions.tests [ -4.0 ] [ -4.4 round ] unit-test [ 5.0 ] [ 4.5 round ] unit-test [ 4.0 ] [ 4.4 round ] unit-test + +[ 6 59967 ] [ 3837888 factor-2s ] unit-test +[ 6 -59967 ] [ -3837888 factor-2s ] unit-test diff --git a/basis/math/functions/functions.factor b/basis/math/functions/functions.factor index 8516292e9d..43efc35c27 100644 --- a/basis/math/functions/functions.factor +++ b/basis/math/functions/functions.factor @@ -1,9 +1,12 @@ -! Copyright (C) 2004, 2007 Slava Pestov. +! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: math kernel math.constants math.private -math.libm combinators math.order ; +math.libm combinators math.order sequences ; IN: math.functions +: >fraction ( a/b -- a b ) + [ numerator ] [ denominator ] bi ; inline + ) ( x y -- z ) @@ -30,14 +33,35 @@ M: real sqrt 2dup >r >r >r odd? r> call r> 2/ r> each-bit ] if ; inline recursive -: ^n ( z w -- z^w ) - 1 swap [ - [ dupd * ] when >r sq r> - ] each-bit nip ; inline +: map-bits ( n quot: ( ? -- obj ) -- seq ) + accumulator [ each-bit ] dip ; inline + +: factor-2s ( n -- r s ) + #! factor an integer into 2^r * s + dup 0 = [ 1 ] [ + 0 swap [ dup even? ] [ [ 1+ ] [ 2/ ] bi* ] [ ] while + ] if ; inline + +fraction ] dip tuck [ ^n ] 2bi@ / ; + +M: float ^n + (^n) ; : integer^ ( x y -- z ) dup 0 > [ ^n ] [ neg ^n recip ] if ; inline +PRIVATE> + : >rect ( z -- x y ) [ real-part ] [ imaginary-part ] bi ; inline @@ -52,6 +76,8 @@ M: real sqrt : polar> ( abs arg -- z ) cis * ; inline +r >r >float-rect swap r> swap fpow r> rot * fexp /f ; inline @@ -68,6 +94,8 @@ M: real sqrt : 0^ ( x -- z ) dup zero? [ drop 0./0. ] [ 0 < 1./0. 0 ? ] if ; inline +PRIVATE> + : ^ ( x y -- z ) { { [ over zero? ] [ nip 0^ ] } diff --git a/basis/math/intervals/intervals-tests.factor b/basis/math/intervals/intervals-tests.factor index 0fdcb51291..8c29171a57 100644 --- a/basis/math/intervals/intervals-tests.factor +++ b/basis/math/intervals/intervals-tests.factor @@ -95,6 +95,10 @@ IN: math.intervals.tests [ empty-interval ] [ 0 5 (a,b] empty-interval interval-intersect ] unit-test +[ t ] [ + 0 1 (a,b) full-interval interval-intersect 0 1 (a,b) = +] unit-test + [ t ] [ empty-interval empty-interval interval-subset? ] unit-test @@ -209,22 +213,28 @@ IN: math.intervals.tests ! Interval random tester : random-element ( interval -- n ) - dup to>> first over from>> first tuck - random + - 2dup swap interval-contains? [ - nip + dup full-interval eq? [ + drop 32 random-bits 31 2^ - ] [ - drop random-element + dup to>> first over from>> first tuck - random + + 2dup swap interval-contains? [ + nip + ] [ + drop random-element + ] if ] if ; : random-interval ( -- interval ) - 2000 random 1000 - dup 2 1000 random + + - 1 random zero? [ [ neg ] bi@ swap ] when - 4 random { - { 0 [ [a,b] ] } - { 1 [ [a,b) ] } - { 2 [ (a,b) ] } - { 3 [ (a,b] ] } - } case ; + 10 random 0 = [ full-interval ] [ + 2000 random 1000 - dup 2 1000 random + + + 1 random zero? [ [ neg ] bi@ swap ] when + 4 random { + { 0 [ [a,b] ] } + { 1 [ [a,b) ] } + { 2 [ (a,b) ] } + { 3 [ (a,b] ] } + } case + ] if ; : random-unary-op ( -- pair ) { @@ -263,7 +273,7 @@ IN: math.intervals.tests { bitand interval-bitand } { bitor interval-bitor } { bitxor interval-bitxor } - { shift interval-shift } + ! { shift interval-shift } { min interval-min } { max interval-max } } diff --git a/basis/math/intervals/intervals.factor b/basis/math/intervals/intervals.factor index 33430e83c3..54ee0ac894 100644 --- a/basis/math/intervals/intervals.factor +++ b/basis/math/intervals/intervals.factor @@ -7,6 +7,8 @@ IN: math.intervals SYMBOL: empty-interval +SYMBOL: full-interval + TUPLE: interval { from read-only } { to read-only } ; : ( from to -- int ) @@ -46,8 +48,7 @@ TUPLE: interval { from read-only } { to read-only } ; : (a,inf] ( a -- interval ) 1./0. (a,b] ; inline -: [-inf,inf] ( -- interval ) - T{ interval f { -1./0. t } { 1./0. t } } ; inline +: [-inf,inf] ( -- interval ) full-interval ; inline : compare-endpoints ( p1 p2 quot -- ? ) >r over first over first r> call [ @@ -99,8 +100,10 @@ TUPLE: interval { from read-only } { to read-only } ; : do-empty-interval ( i1 i2 quot -- i3 ) { - { [ pick empty-interval eq? ] [ drop drop ] } + { [ pick empty-interval eq? ] [ 2drop ] } { [ over empty-interval eq? ] [ drop nip ] } + { [ pick full-interval eq? ] [ 2drop ] } + { [ over full-interval eq? ] [ drop nip ] } [ call ] } cond ; inline @@ -112,8 +115,10 @@ TUPLE: interval { from read-only } { to read-only } ; : interval-intersect ( i1 i2 -- i3 ) { - { [ dup empty-interval eq? ] [ nip ] } { [ over empty-interval eq? ] [ drop ] } + { [ dup empty-interval eq? ] [ nip ] } + { [ over full-interval eq? ] [ nip ] } + { [ dup full-interval eq? ] [ drop ] } [ [ interval>points ] bi@ swapd [ [ swap endpoint< ] most ] @@ -127,8 +132,10 @@ TUPLE: interval { from read-only } { to read-only } ; : interval-union ( i1 i2 -- i3 ) { - { [ dup empty-interval eq? ] [ drop ] } { [ over empty-interval eq? ] [ nip ] } + { [ dup empty-interval eq? ] [ drop ] } + { [ over full-interval eq? ] [ drop ] } + { [ dup full-interval eq? ] [ nip ] } [ [ interval>points 2array ] bi@ append points>interval ] } cond ; @@ -137,9 +144,11 @@ TUPLE: interval { from read-only } { to read-only } ; : interval-contains? ( x int -- ? ) dup empty-interval eq? [ 2drop f ] [ - [ from>> first2 [ >= ] [ > ] if ] - [ to>> first2 [ <= ] [ < ] if ] - 2bi and + dup full-interval eq? [ 2drop t ] [ + [ from>> first2 [ >= ] [ > ] if ] + [ to>> first2 [ <= ] [ < ] if ] + 2bi and + ] if ] if ; : interval-zero? ( int -- ? ) @@ -160,8 +169,11 @@ TUPLE: interval { from read-only } { to read-only } ; : interval-sq ( i1 -- i2 ) dup interval* ; +: special-interval? ( interval -- ? ) + { empty-interval full-interval } memq? ; + : interval-singleton? ( int -- ? ) - dup empty-interval eq? [ + dup special-interval? [ drop f ] [ interval>points @@ -173,6 +185,7 @@ TUPLE: interval { from read-only } { to read-only } ; : interval-length ( int -- n ) { { [ dup empty-interval eq? ] [ drop 0 ] } + { [ dup full-interval eq? ] [ drop 1/0. ] } [ interval>points [ first ] bi@ swap - ] } cond ; @@ -211,7 +224,7 @@ TUPLE: interval { from read-only } { to read-only } ; [ [ interval-closure ] bi@ [ min ] interval-op ] do-empty-interval ; : interval-interior ( i1 -- i2 ) - dup empty-interval eq? [ + dup special-interval? [ interval>points [ first ] bi@ (a,b) ] unless ; @@ -249,6 +262,7 @@ TUPLE: interval { from read-only } { to read-only } ; : interval-abs ( i1 -- i2 ) { { [ dup empty-interval eq? ] [ ] } + { [ dup full-interval eq? ] [ drop 0 [a,inf] ] } { [ 0 over interval-contains? ] [ (interval-abs) { 0 t } suffix points>interval ] } [ (interval-abs) points>interval ] } cond ; @@ -292,7 +306,7 @@ SYMBOL: incomparable : interval< ( i1 i2 -- ? ) { - { [ 2dup [ empty-interval eq? ] either? ] [ incomparable ] } + { [ 2dup [ special-interval? ] either? ] [ incomparable ] } { [ 2dup interval-intersect empty-interval eq? ] [ (interval<) ] } { [ 2dup left-endpoint-< ] [ f ] } { [ 2dup right-endpoint-< ] [ f ] } @@ -307,7 +321,7 @@ SYMBOL: incomparable : interval<= ( i1 i2 -- ? ) { - { [ 2dup [ empty-interval eq? ] either? ] [ incomparable ] } + { [ 2dup [ special-interval? ] either? ] [ incomparable ] } { [ 2dup interval-intersect empty-interval eq? ] [ (interval<) ] } { [ 2dup right-endpoint-<= ] [ t ] } [ incomparable ] @@ -360,27 +374,27 @@ SYMBOL: incomparable interval-bitor ; : assume< ( i1 i2 -- i3 ) - dup empty-interval eq? [ drop ] [ + dup special-interval? [ drop ] [ to>> first [-inf,a) interval-intersect ] if ; : assume<= ( i1 i2 -- i3 ) - dup empty-interval eq? [ drop ] [ + dup special-interval? [ drop ] [ to>> first [-inf,a] interval-intersect ] if ; : assume> ( i1 i2 -- i3 ) - dup empty-interval eq? [ drop ] [ + dup special-interval? [ drop ] [ from>> first (a,inf] interval-intersect ] if ; : assume>= ( i1 i2 -- i3 ) - dup empty-interval eq? [ drop ] [ + dup special-interval? [ drop ] [ from>> first [a,inf] interval-intersect ] if ; : integral-closure ( i1 -- i2 ) - dup empty-interval eq? [ + dup special-interval? [ [ from>> first2 [ 1+ ] unless ] [ to>> first2 [ 1- ] unless ] bi [a,b] diff --git a/basis/math/ratios/ratios-docs.factor b/basis/math/ratios/ratios-docs.factor index 903017e371..7b6393dabe 100644 --- a/basis/math/ratios/ratios-docs.factor +++ b/basis/math/ratios/ratios-docs.factor @@ -1,5 +1,5 @@ USING: help.markup help.syntax math math.private -math.ratios.private ; +math.ratios.private math.functions ; IN: math.ratios ARTICLE: "rationals" "Rational numbers" diff --git a/basis/math/ratios/ratios.factor b/basis/math/ratios/ratios.factor index 5dde4fbb99..d9dea22b7b 100644 --- a/basis/math/ratios/ratios.factor +++ b/basis/math/ratios/ratios.factor @@ -3,9 +3,6 @@ USING: accessors kernel kernel.private math math.functions math.private ; IN: math.ratios -: >fraction ( a/b -- a b ) - dup numerator swap denominator ; inline - : 2>fraction ( a/b c/d -- a c b d ) [ >fraction ] bi@ swapd ; inline diff --git a/basis/opengl/opengl-docs.factor b/basis/opengl/opengl-docs.factor index 87981789a7..b1ea89178b 100644 --- a/basis/opengl/opengl-docs.factor +++ b/basis/opengl/opengl-docs.factor @@ -9,14 +9,6 @@ HELP: gl-color HELP: gl-error { $description "If the most recent OpenGL call resulted in an error, print the error to " { $link output-stream } "." } ; -HELP: do-state - { - $values - { "mode" { "One of the " { $link "opengl-geometric-primitives" } } } - { "quot" quotation } - } -{ $description "Wraps a quotation in " { $link glBegin } "/" { $link glEnd } " calls." } ; - HELP: do-enabled { $values { "what" integer } { "quot" quotation } } { $description "Wraps a quotation in " { $link glEnable } "/" { $link glDisable } " calls." } ; @@ -25,37 +17,17 @@ HELP: do-matrix { $values { "mode" { $link GL_MODELVIEW } " or " { $link GL_PROJECTION } } { "quot" quotation } } { $description "Saves and restores the matrix specified by " { $snippet "mode" } " before and after calling the quotation." } ; -HELP: gl-vertex -{ $values { "point" "a pair of integers" } } -{ $description "Wrapper for " { $link glVertex2d } " taking a point object." } ; - HELP: gl-line { $values { "a" "a pair of integers" } { "b" "a pair of integers" } } { $description "Draws a line between two points." } ; HELP: gl-fill-rect -{ $values { "loc" "a pair of integers" } { "ext" "a pair of integers" } } -{ $description "Draws a filled rectangle with top-left corner " { $snippet "loc" } " and bottom-right corner " { $snippet "ext" } "." } ; +{ $values { "dim" "a pair of integers" } } +{ $description "Draws a filled rectangle with the top-left corner at the origin and the given dimensions." } ; HELP: gl-rect -{ $values { "loc" "a pair of integers" } { "ext" "a pair of integers" } } -{ $description "Draws the outline of a rectangle with top-left corner " { $snippet "loc" } " and bottom-right corner " { $snippet "ext" } "." } ; - -HELP: rect-vertices -{ $values { "lower-left" "A pair of numbers indicating the lower-left coordinates of the rectangle." } { "upper-right" "The upper-right coordinates of the rectangle." } } -{ $description "Emits" { $link glVertex2d } " calls outlining the axis-aligned rectangle from " { $snippet "lower-left" } " to " { $snippet "upper-right" } " on the z=0 plane in counterclockwise order." } ; - -HELP: gl-fill-poly -{ $values { "points" "a sequence of pairs of integers" } } -{ $description "Draws a filled polygon." } ; - -HELP: gl-poly -{ $values { "points" "a sequence of pairs of integers" } } -{ $description "Draws the outline of a polygon." } ; - -HELP: gl-gradient -{ $values { "direction" "an orientation specifier" } { "colors" "a sequence of color specifiers" } { "dim" "a pair of integers" } } -{ $description "Draws a rectangle with top-left corner " { $snippet "{ 0 0 }" } " and dimensions " { $snippet "dim" } ", filled with a smoothly shaded transition between the colors in " { $snippet "colors" } "." } ; +{ $values { "dim" "a pair of integers" } } +{ $description "Draws the outline of a rectangle with the top-left corner at the origin and the given dimensions." } ; HELP: gen-texture { $values { "id" integer } } @@ -131,12 +103,10 @@ $nl { $subsection "opengl-low-level" } "Wrappers:" { $subsection gl-color } -{ $subsection gl-vertex } { $subsection gl-translate } { $subsection gen-texture } { $subsection bind-texture-unit } "Combinators:" -{ $subsection do-state } { $subsection do-enabled } { $subsection do-attribs } { $subsection do-matrix } @@ -146,9 +116,6 @@ $nl { $subsection gl-line } { $subsection gl-fill-rect } { $subsection gl-rect } -{ $subsection gl-fill-poly } -{ $subsection gl-poly } -{ $subsection gl-gradient } ; ABOUT: "gl-utilities" diff --git a/basis/opengl/opengl.factor b/basis/opengl/opengl.factor index bae05f4244..64326f340e 100644 --- a/basis/opengl/opengl.factor +++ b/basis/opengl/opengl.factor @@ -2,44 +2,31 @@ ! Portions copyright (C) 2007 Eduardo Cavazos. ! Portions copyright (C) 2008 Joe Groff. ! See http://factorcode.org/license.txt for BSD license. - USING: alien alien.c-types continuations kernel libc math macros - namespaces math.vectors math.constants math.functions - math.parser opengl.gl opengl.glu combinators arrays sequences - splitting words byte-arrays assocs colors accessors ; - +namespaces math.vectors math.constants math.functions +math.parser opengl.gl opengl.glu combinators arrays sequences +splitting words byte-arrays assocs colors accessors +generalizations locals memoize ; IN: opengl -: coordinates ( point1 point2 -- x1 y2 x2 y2 ) - [ first2 ] bi@ ; +: color>raw ( object -- r g b a ) + >rgba { [ red>> ] [ green>> ] [ blue>> ] [ alpha>> ] } cleave ; inline -: fix-coordinates ( point1 point2 -- x1 y2 x2 y2 ) - [ first2 [ >fixnum ] bi@ ] bi@ ; +: gl-color ( color -- ) color>raw glColor4d ; inline -: gl-color ( color -- ) first4 glColor4d ; inline - -: gl-clear-color ( color -- ) - first4 glClearColor ; +: gl-clear-color ( color -- ) color>raw glClearColor ; : gl-clear ( color -- ) gl-clear-color GL_COLOR_BUFFER_BIT glClear ; -: color>raw ( object -- r g b a ) - >rgba { [ red>> ] [ green>> ] [ blue>> ] [ alpha>> ] } cleave ; - -: set-color ( object -- ) color>raw glColor4d ; -: set-clear-color ( object -- ) color>raw glClearColor ; - : gl-error ( -- ) glGetError dup zero? [ "GL error: " over gluErrorString append throw ] unless drop ; -: do-state ( mode quot -- ) - swap glBegin call glEnd ; inline - : do-enabled ( what quot -- ) over glEnable dip glDisable ; inline + : do-enabled-client-state ( what quot -- ) over glEnableClientState dip glDisableClientState ; inline @@ -48,6 +35,7 @@ IN: opengl : (all-enabled) ( seq quot -- ) over [ glEnable ] each dip [ glDisable ] each ; inline + : (all-enabled-client-state) ( seq quot -- ) [ dup [ glEnableClientState ] each ] dip dip @@ -55,6 +43,7 @@ IN: opengl MACRO: all-enabled ( seq quot -- ) >r words>values r> [ (all-enabled) ] 2curry ; + MACRO: all-enabled-client-state ( seq quot -- ) >r words>values r> [ (all-enabled-client-state) ] 2curry ; @@ -62,37 +51,57 @@ MACRO: all-enabled-client-state ( seq quot -- ) swap [ glMatrixMode glPushMatrix call ] keep glMatrixMode glPopMatrix ; inline -: gl-vertex ( point -- ) - dup length { - { 2 [ first2 glVertex2d ] } - { 3 [ first3 glVertex3d ] } - { 4 [ first4 glVertex4d ] } - } case ; - -: gl-normal ( normal -- ) first3 glNormal3d ; - : gl-material ( face pname params -- ) >c-float-array glMaterialfv ; +: gl-vertex-pointer ( seq -- ) + [ 2 GL_FLOAT 0 ] dip glVertexPointer ; inline + +: gl-color-pointer ( seq -- ) + [ 4 GL_FLOAT 0 ] dip glColorPointer ; inline + +: gl-texture-coord-pointer ( seq -- ) + [ 2 GL_FLOAT 0 ] dip glTexCoordPointer ; inline + +: line-vertices ( a b -- ) + append >c-float-array gl-vertex-pointer ; + : gl-line ( a b -- ) - GL_LINES [ gl-vertex gl-vertex ] do-state ; + line-vertices GL_LINES 0 2 glDrawArrays ; -: gl-fill-rect ( loc ext -- ) - coordinates glRectd ; +: (rect-vertices) ( dim -- vertices ) + { + [ drop 0 1 ] + [ first 1- 1 ] + [ [ first 1- ] [ second ] bi ] + [ second 0 swap ] + } cleave 8 narray >c-float-array ; -: gl-rect ( loc ext -- ) - GL_FRONT_AND_BACK GL_LINE glPolygonMode - >r { 0.5 0.5 } v+ r> { 0.5 0.5 } v- gl-fill-rect - GL_FRONT_AND_BACK GL_FILL glPolygonMode ; +: rect-vertices ( dim -- ) + (rect-vertices) gl-vertex-pointer ; -: (gl-poly) ( points state -- ) - [ [ gl-vertex ] each ] do-state ; +: (gl-rect) ( -- ) + GL_LINE_LOOP 0 4 glDrawArrays ; -: gl-fill-poly ( points -- ) - dup length 2 > GL_POLYGON GL_LINES ? (gl-poly) ; +: gl-rect ( dim -- ) + rect-vertices (gl-rect) ; -: gl-poly ( points -- ) - GL_LINE_LOOP (gl-poly) ; +: (fill-rect-vertices) ( dim -- vertices ) + { + [ drop 0 0 ] + [ first 0 ] + [ first2 ] + [ second 0 swap ] + } cleave 8 narray >c-float-array ; + +: fill-rect-vertices ( dim -- ) + (fill-rect-vertices) gl-vertex-pointer ; + +: (gl-fill-rect) ( -- ) + GL_QUADS 0 4 glDrawArrays ; + +: gl-fill-rect ( dim -- ) + fill-rect-vertices (gl-fill-rect) ; : circle-steps ( steps -- angles ) dup length v/n 2 pi * v*n ; @@ -109,35 +118,24 @@ MACRO: all-enabled-client-state ( seq quot -- ) : circle-points ( loc dim steps -- points ) circle-steps unit-circle adjust-points scale-points ; -: gl-circle ( loc dim steps -- ) - circle-points gl-poly ; - -: gl-fill-circle ( loc dim steps -- ) - circle-points gl-fill-poly ; - -: prepare-gradient ( direction dim -- v1 v2 ) - tuck v* [ v- ] keep ; - -: gl-gradient ( direction colors dim -- ) - GL_QUAD_STRIP [ - swap >r prepare-gradient r> - [ length dup 1- v/n ] keep [ - >r >r 2dup r> r> set-color v*n - dup gl-vertex v+ gl-vertex - ] 2each 2drop - ] do-state ; +: circle-vertices ( loc dim steps -- vertices ) + circle-points concat >c-float-array ; : (gen-gl-object) ( quot -- id ) >r 1 0 r> keep *uint ; inline + : gen-texture ( -- id ) [ glGenTextures ] (gen-gl-object) ; + : gen-gl-buffer ( -- id ) [ glGenBuffers ] (gen-gl-object) ; : (delete-gl-object) ( id quot -- ) >r 1 swap r> call ; inline + : delete-texture ( id -- ) [ glDeleteTextures ] (delete-gl-object) ; + : delete-gl-buffer ( id -- ) [ glDeleteBuffers ] (delete-gl-object) ; @@ -205,35 +203,21 @@ TUPLE: sprite loc dim dim2 dlist texture ; : gl-translate ( point -- ) first2 0.0 glTranslated ; -c-float-array ; -: top-left drop 0 0 glTexCoord2i 0.0 0.0 glVertex2d ; inline - -: top-right 1 0 glTexCoord2i first 0.0 glVertex2d ; inline - -: bottom-left 0 1 glTexCoord2i second 0.0 swap glVertex2d ; inline - -: bottom-right 1 1 glTexCoord2i gl-vertex ; inline - -PRIVATE> - -: four-sides ( dim -- ) - dup top-left dup top-right dup bottom-right bottom-left ; +: rect-texture-coords ( -- ) + (rect-texture-coords) gl-texture-coord-pointer ; : draw-sprite ( sprite -- ) - dup loc>> gl-translate - GL_TEXTURE_2D over texture>> glBindTexture - init-texture - GL_QUADS [ dim2>> four-sides ] do-state - GL_TEXTURE_2D 0 glBindTexture ; - -: rect-vertices ( lower-left upper-right -- ) - GL_QUADS [ - over first2 glVertex2d - dup first pick second glVertex2d - dup first2 glVertex2d - swap first swap second glVertex2d - ] do-state ; + GL_TEXTURE_COORD_ARRAY [ + dup loc>> gl-translate + GL_TEXTURE_2D over texture>> glBindTexture + init-texture rect-texture-coords + dim2>> fill-rect-vertices + (gl-fill-rect) + GL_TEXTURE_2D 0 glBindTexture + ] do-enabled-client-state ; : make-sprite-dlist ( sprite -- id ) GL_MODELVIEW [ @@ -256,6 +240,9 @@ PRIVATE> : with-translation ( loc quot -- ) GL_MODELVIEW [ >r gl-translate r> call ] do-matrix ; inline +: fix-coordinates ( point1 point2 -- x1 y2 x2 y2 ) + [ first2 [ >fixnum ] bi@ ] bi@ ; + : gl-set-clip ( loc dim -- ) fix-coordinates glScissor ; diff --git a/basis/persistent/hashtables/hashtables.factor b/basis/persistent/hashtables/hashtables.factor index a867dbb2e3..e50fd52c10 100644 --- a/basis/persistent/hashtables/hashtables.factor +++ b/basis/persistent/hashtables/hashtables.factor @@ -53,3 +53,6 @@ M: persistent-hash clone ; M: persistent-hash pprint-delims drop \ PH{ \ } ; M: persistent-hash >pprint-sequence >alist ; M: persistent-hash pprint* pprint-object ; + +: passociate ( value key -- phash ) + T{ persistent-hash } new-at ; inline diff --git a/basis/persistent/sequences/sequences.factor b/basis/persistent/sequences/sequences.factor index 961e8bfce7..5503e369b4 100644 --- a/basis/persistent/sequences/sequences.factor +++ b/basis/persistent/sequences/sequences.factor @@ -14,3 +14,6 @@ M: sequence ppop 1 head* ; GENERIC: new-nth ( val i seq -- seq' ) M: sequence new-nth clone [ set-nth ] keep ; + +: changed-nth ( i seq quot -- seq' ) + [ [ nth ] dip call ] [ drop new-nth ] 3bi ; inline diff --git a/basis/prettyprint/backend/backend.factor b/basis/prettyprint/backend/backend.factor index b749bd63eb..31b6ba3f26 100644 --- a/basis/prettyprint/backend/backend.factor +++ b/basis/prettyprint/backend/backend.factor @@ -214,6 +214,7 @@ M: tuple pprint-narrow? drop t ; M: object pprint* pprint-object ; M: vector pprint* pprint-object ; +M: byte-vector pprint* pprint-object ; M: hashtable pprint* pprint-object ; M: curry pprint* diff --git a/basis/prettyprint/prettyprint-docs.factor b/basis/prettyprint/prettyprint-docs.factor index 44cf5f724f..159421c18c 100644 --- a/basis/prettyprint/prettyprint-docs.factor +++ b/basis/prettyprint/prettyprint-docs.factor @@ -1,6 +1,6 @@ USING: prettyprint.backend prettyprint.config prettyprint.sections prettyprint.private help.markup help.syntax -io kernel words definitions quotations strings ; +io kernel words definitions quotations strings generic classes ; IN: prettyprint ARTICLE: "prettyprint-numbers" "Prettyprinting numbers" @@ -150,6 +150,8 @@ $nl { $subsection pprint-cell } "Printing a definition (see " { $link "definitions" } "):" { $subsection see } +"Printing the methods defined on a generic word or class (see " { $link "objects" } "):" +{ $subsection see-methods } "More prettyprinter usage:" { $subsection "prettyprint-numbers" } { $subsection "prettyprint-stacks" } @@ -167,17 +169,26 @@ HELP: with-pprint HELP: pprint { $values { "obj" object } } -{ $description "Prettyprints an object to " { $link output-stream } ". Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; +{ $description "Prettyprints an object to " { $link output-stream } ". Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } +{ $warning + "Unparsing a large object can take a long time and consume a lot of memory. If you need to print large objects, use " { $link pprint-short } " or set some " { $link "prettyprint-variables" } " to limit output size." +} ; { pprint pprint* with-pprint } related-words HELP: . { $values { "obj" object } } -{ $description "Prettyprints an object to " { $link output-stream } " with a trailing line break. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; +{ $description "Prettyprints an object to " { $link output-stream } " with a trailing line break. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } +{ $warning + "Printing a large object can take a long time and consume a lot of memory. If you need to print large objects, use " { $link short. } " or set some " { $link "prettyprint-variables" } " to limit output size." +} ; HELP: unparse { $values { "obj" object } { "str" "Factor source string" } } -{ $description "Outputs a prettyprinted string representation of an object. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; +{ $description "Outputs a prettyprinted string representation of an object. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } +{ $warning + "Unparsing a large object can take a long time and consume a lot of memory. If you need to unparse large objects, use " { $link unparse-short } " or set some " { $link "prettyprint-variables" } " to limit output size." +} ; HELP: pprint-short { $values { "obj" object } } @@ -240,6 +251,10 @@ HELP: see { $values { "defspec" "a definition specifier" } } { $contract "Prettyprints a definition." } ; +HELP: see-methods +{ $values { "word" "a " { $link generic } " or a " { $link class } } } +{ $contract "Prettyprints the methods defined on a generic word or class." } ; + HELP: definer { $values { "defspec" "a definition specifier" } { "start" word } { "end" "a word or " { $link f } } } { $contract "Outputs the parsing words which delimit the definition." } diff --git a/basis/random/mersenne-twister/mersenne-twister.factor b/basis/random/mersenne-twister/mersenne-twister.factor index 712883e4b8..c31d338fac 100644 --- a/basis/random/mersenne-twister/mersenne-twister.factor +++ b/basis/random/mersenne-twister/mersenne-twister.factor @@ -16,7 +16,7 @@ TUPLE: mersenne-twister seq i ; : mt-a HEX: 9908b0df ; inline : calculate-y ( n seq -- y ) - [ nth 32 mask-bit ] + [ nth 31 mask-bit ] [ [ 1+ ] [ nth ] bi* 31 bits ] 2bi bitor ; inline : (mt-generate) ( n seq -- next-mt ) diff --git a/basis/random/random.factor b/basis/random/random.factor index a0b62cf7de..5c93606ab5 100755 --- a/basis/random/random.factor +++ b/basis/random/random.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: alien.c-types kernel math namespaces sequences io.backend io.binary combinators system vocabs.loader -summary math.bitwise ; +summary math.bitwise byte-vectors fry byte-arrays ; IN: random SYMBOL: system-random-generator @@ -14,7 +14,12 @@ GENERIC: random-32* ( tuple -- r ) GENERIC: random-bytes* ( n tuple -- byte-array ) M: object random-bytes* ( n tuple -- byte-array ) - [ random-32* ] curry replicate [ 4 >le ] map concat ; + [ [ ] keep 4 /mod ] dip tuck + [ pick '[ _ random-32* 4 >le _ push-all ] times ] + [ + over zero? + [ 2drop ] [ random-32* 4 >le swap head over push-all ] if + ] 2bi* ; M: object random-32* ( tuple -- r ) 4 random-bytes* le> ; @@ -28,16 +33,13 @@ M: f random-bytes* ( n obj -- * ) no-random-number-generator ; M: f random-32* ( obj -- * ) no-random-number-generator ; : random-bytes ( n -- byte-array ) - [ - dup 3 mask zero? [ 1+ ] unless - random-generator get random-bytes* - ] keep head ; + random-generator get random-bytes* ; bignum ] + [ random-bytes >byte-array byte-array>bignum ] [ 3 shift 2^ ] bi / * >integer ; PRIVATE> diff --git a/basis/stack-checker/backend/backend-tests.factor b/basis/stack-checker/backend/backend-tests.factor new file mode 100644 index 0000000000..3bbba0fcb8 --- /dev/null +++ b/basis/stack-checker/backend/backend-tests.factor @@ -0,0 +1,22 @@ +USING: stack-checker.backend tools.test kernel namespaces +stack-checker.state sequences ; +IN: stack-checker.backend.tests + +[ ] [ + V{ } clone meta-d set + V{ } clone meta-r set + 0 d-in set +] unit-test + +[ 0 ] [ 0 ensure-d length ] unit-test + +[ 2 ] [ 2 ensure-d length ] unit-test +[ 2 ] [ meta-d get length ] unit-test + +[ 3 ] [ 3 ensure-d length ] unit-test +[ 3 ] [ meta-d get length ] unit-test + +[ 1 ] [ 1 ensure-d length ] unit-test +[ 3 ] [ meta-d get length ] unit-test + +[ ] [ 1 consume-d drop ] unit-test diff --git a/basis/stack-checker/backend/backend.factor b/basis/stack-checker/backend/backend.factor index f8dec5f823..94e59950f7 100644 --- a/basis/stack-checker/backend/backend.factor +++ b/basis/stack-checker/backend/backend.factor @@ -5,7 +5,8 @@ namespaces parser prettyprint sequences strings vectors words quotations effects classes continuations debugger assocs combinators compiler.errors accessors math.order definitions sets generic.standard.engines.tuple stack-checker.state -stack-checker.visitor stack-checker.errors ; +stack-checker.visitor stack-checker.errors +stack-checker.values stack-checker.recursive-state ; IN: stack-checker.backend : push-d ( obj -- ) meta-d get push ; @@ -17,15 +18,25 @@ IN: stack-checker.backend : peek-d ( -- obj ) pop-d dup push-d ; -: consume-d ( n -- seq ) [ pop-d ] replicate reverse ; - -: output-d ( values -- ) meta-d get push-all ; - -: ensure-d ( n -- values ) consume-d dup output-d ; - : make-values ( n -- values ) [ ] replicate ; +: ensure-d ( n -- values ) + meta-d get 2dup length > [ + 2dup + [ nip >array ] [ length - make-values ] [ nip delete-all ] 2tri + [ length d-in +@ ] [ #introduce, ] [ meta-d get push-all ] tri + meta-d get push-all + ] when swap tail* ; + +: shorten-by ( n seq -- ) + [ length swap - ] keep shorten ; inline + +: consume-d ( n -- seq ) + [ ensure-d ] [ meta-d get shorten-by ] bi ; + +: output-d ( values -- ) meta-d get push-all ; + : produce-d ( n -- values ) make-values dup meta-d get push-all ; @@ -35,7 +46,10 @@ IN: stack-checker.backend meta-r get dup empty? [ too-many-r> inference-error ] [ pop ] if ; -: consume-r ( n -- seq ) [ pop-r ] replicate reverse ; +: consume-r ( n -- seq ) + meta-r get 2dup length > + [ too-many-r> inference-error ] when + [ swap tail* ] [ shorten-by ] 2bi ; : output-r ( seq -- ) meta-r get push-all ; @@ -69,9 +83,6 @@ M: object apply-object push-literal ; infer-quot-here ] dip recursive-state set ; -: infer-quot-recursive ( quot word label -- ) - 2array recursive-state get swap prefix infer-quot ; - : time-bomb ( error -- ) '[ _ throw ] infer-quot-here ; @@ -84,7 +95,7 @@ M: object apply-object push-literal ; ] [ dup value>> callable? [ [ value>> ] - [ [ recursion>> ] keep f 2array prefix ] + [ [ recursion>> ] keep add-local-quotation ] bi infer-quot ] [ drop bad-call @@ -113,6 +124,9 @@ M: object apply-object push-literal ; terminated?>> [ terminate ] when ] 2bi ; inline +: infer-word-def ( word -- ) + [ def>> ] [ add-recursive-state ] bi infer-quot ; + : check->r ( -- ) meta-r get empty? terminated? get or [ \ too-many->r inference-error ] unless ; @@ -161,7 +175,7 @@ M: object apply-object push-literal ; stack-visitor off dependencies off generic-dependencies off - [ [ def>> ] [ ] [ ] tri infer-quot-recursive end-infer ] + [ infer-word-def end-infer ] [ finish-word current-effect ] bi ] with-scope diff --git a/basis/stack-checker/branches/branches.factor b/basis/stack-checker/branches/branches.factor index d1417d035c..7b461d0028 100644 --- a/basis/stack-checker/branches/branches.factor +++ b/basis/stack-checker/branches/branches.factor @@ -3,7 +3,7 @@ USING: fry vectors sequences assocs math accessors kernel combinators quotations namespaces stack-checker.state stack-checker.backend stack-checker.errors stack-checker.visitor -; +stack-checker.values stack-checker.recursive-state ; IN: stack-checker.branches : balanced? ( pairs -- ? ) diff --git a/basis/stack-checker/errors/errors.factor b/basis/stack-checker/errors/errors.factor index bab6c17c85..efdc7e23b2 100644 --- a/basis/stack-checker/errors/errors.factor +++ b/basis/stack-checker/errors/errors.factor @@ -2,12 +2,11 @@ ! See http://factorcode.org/license.txt for BSD license. USING: kernel generic sequences prettyprint io words arrays summary effects debugger assocs accessors namespaces -compiler.errors ; +compiler.errors stack-checker.values +stack-checker.recursive-state ; IN: stack-checker.errors -SYMBOL: recursive-state - -TUPLE: inference-error error type rstate ; +TUPLE: inference-error error type word ; M: inference-error compiler-error-type type>> ; @@ -15,7 +14,7 @@ M: inference-error error-help error>> error-help ; : (inference-error) ( ... class type -- * ) >r boa r> - recursive-state get + recursive-state get word>> \ inference-error boa throw ; inline : inference-error ( ... class -- * ) @@ -25,16 +24,15 @@ M: inference-error error-help error>> error-help ; +warning+ (inference-error) ; inline M: inference-error error. - [ - rstate>> - [ "Nesting:" print stack. ] unless-empty - ] [ error>> error. ] bi ; + [ "In word: " write word>> . ] [ error>> error. ] bi ; TUPLE: literal-expected ; M: literal-expected summary drop "Literal value expected" ; +M: object (literal) \ literal-expected inference-warning ; + TUPLE: unbalanced-branches-error branches quots ; : unbalanced-branches-error ( branches quots -- * ) diff --git a/basis/stack-checker/inlining/inlining.factor b/basis/stack-checker/inlining/inlining.factor index 7847fdfdcf..b6a988652b 100644 --- a/basis/stack-checker/inlining/inlining.factor +++ b/basis/stack-checker/inlining/inlining.factor @@ -4,18 +4,20 @@ USING: fry namespaces assocs kernel sequences words accessors definitions math math.order effects classes arrays combinators vectors arrays stack-checker.state +stack-checker.errors +stack-checker.values stack-checker.visitor stack-checker.backend stack-checker.branches -stack-checker.errors -stack-checker.known-words ; +stack-checker.known-words +stack-checker.recursive-state ; IN: stack-checker.inlining ! Code to handle inline words. Much of the complexity stems from ! having to handle recursive inline words. -: (inline-word) ( word label -- ) - [ [ def>> ] keep ] dip infer-quot-recursive ; +: infer-inline-word-def ( word label -- ) + [ drop def>> ] [ add-inline-word ] 2bi infer-quot ; TUPLE: inline-recursive < identity-tuple id @@ -88,7 +90,7 @@ SYMBOL: enter-out nest-visitor dup - [ dup emit-enter-recursive (inline-word) ] + [ dup emit-enter-recursive infer-inline-word-def ] [ end-recursive-word ] [ nip ] 2tri @@ -133,20 +135,23 @@ SYMBOL: enter-out object '[ _ prepend ] bi@ ; -: call-recursive-inline-word ( word -- ) - dup "recursive" word-prop [ - [ required-stack-effect adjust-stack-effect ] [ ] [ recursive-label ] tri - [ 2nip check-call ] [ nip '[ _ #call-recursive, ] consume/produce ] 3bi - ] [ undeclared-recursion-error inference-error ] if ; +: call-recursive-inline-word ( word label -- ) + over "recursive" word-prop [ + [ required-stack-effect adjust-stack-effect ] dip + [ check-call ] [ '[ _ #call-recursive, ] consume/produce ] bi + ] [ drop undeclared-recursion-error inference-error ] if ; : inline-word ( word -- ) [ inlined-dependency depends-on ] [ - { - { [ dup inline-recursive-label ] [ call-recursive-inline-word ] } - { [ dup "recursive" word-prop ] [ inline-recursive-word ] } - [ dup (inline-word) ] - } cond + dup inline-recursive-label [ + call-recursive-inline-word + ] [ + dup "recursive" word-prop + [ inline-recursive-word ] + [ dup infer-inline-word-def ] + if + ] if* ] bi ; M: word apply-object diff --git a/basis/stack-checker/known-words/known-words.factor b/basis/stack-checker/known-words/known-words.factor index c40b94fd3c..4aea0f2d28 100644 --- a/basis/stack-checker/known-words/known-words.factor +++ b/basis/stack-checker/known-words/known-words.factor @@ -10,14 +10,16 @@ sequences sequences.private slots.private strings strings.private system threads.private classes.tuple classes.tuple.private vectors vectors.private words definitions words.private assocs summary compiler.units system.private -combinators locals.backend words.private quotations.private +combinators locals locals.backend locals.private words.private +quotations.private stack-checker.values +stack-checker.alien stack-checker.state +stack-checker.errors +stack-checker.visitor stack-checker.backend stack-checker.branches -stack-checker.errors stack-checker.transforms -stack-checker.visitor -stack-checker.alien ; +stack-checker.recursive-state ; IN: stack-checker.known-words : infer-primitive ( word -- ) @@ -48,7 +50,7 @@ IN: stack-checker.known-words : infer-shuffle ( shuffle -- ) [ in>> length consume-d ] keep ! inputs shuffle [ drop ] [ shuffle dup copy-values dup output-d ] 2bi ! inputs outputs copies - [ nip ] [ swap zip ] 2bi ! inputs copies mapping + [ nip f f ] [ swap zip ] 2bi ! in-d out-d in-r out-r mapping #shuffle, ; : infer-shuffle-word ( word -- ) @@ -123,21 +125,23 @@ M: object infer-call* : infer-load-locals ( -- ) pop-literal nip - [ dup reverse infer-shuffle ] - [ infer->r ] - bi ; + consume-d dup reverse copy-values dup output-r + [ [ f f ] dip ] [ reverse swap zip ] 2bi #shuffle, ; : infer-get-local ( -- ) - pop-literal nip - [ infer-r> ] - [ dup 0 prefix infer-shuffle ] - [ infer->r ] - tri ; + [let* | n [ pop-literal nip ] + in-r [ n consume-r ] + out-d [ in-r first copy-value 1array ] + out-r [ in-r copy-values ] | + out-d output-d + out-r output-r + f out-d in-r out-r + out-r in-r zip out-d first in-r first 2array suffix + #shuffle, + ] ; : infer-drop-locals ( -- ) - pop-literal nip - [ infer-r> ] - [ { } infer-shuffle ] bi ; + f f pop-literal nip consume-r f f #shuffle, ; : infer-special ( word -- ) { @@ -164,6 +168,12 @@ M: object infer-call* { \ alien-callback [ infer-alien-callback ] } } case ; +: infer-local-reader ( word -- ) + (( -- value )) apply-word/effect ; + +: infer-local-writer ( word -- ) + (( value -- )) apply-word/effect ; + { >r r> declare call (call) curry compose execute (execute) if dispatch (throw) load-locals get-local drop-locals @@ -183,7 +193,10 @@ do-primitive alien-invoke alien-indirect alien-callback { [ dup "macro" word-prop ] [ apply-macro ] } { [ dup "cannot-infer" word-prop ] [ cannot-infer-effect ] } { [ dup "inferred-effect" word-prop ] [ cached-infer ] } - { [ dup recursive-label ] [ call-recursive-word ] } + { [ dup local? ] [ infer-local-reader ] } + { [ dup local-reader? ] [ infer-local-reader ] } + { [ dup local-writer? ] [ infer-local-writer ] } + { [ dup recursive-word? ] [ call-recursive-word ] } [ dup infer-word apply-word/effect ] } cond ; diff --git a/basis/stack-checker/recursive-state/recursive-state.factor b/basis/stack-checker/recursive-state/recursive-state.factor new file mode 100644 index 0000000000..41d7331230 --- /dev/null +++ b/basis/stack-checker/recursive-state/recursive-state.factor @@ -0,0 +1,43 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors arrays sequences kernel sequences assocs +namespaces stack-checker.recursive-state.tree ; +IN: stack-checker.recursive-state + +TUPLE: recursive-state words word quotations inline-words ; + +C: recursive-state + +: prepare-recursive-state ( word rstate -- rstate ) + swap >>word + f >>quotations + f >>inline-words ; inline + +: initial-recursive-state ( word -- state ) + recursive-state new + f >>words + prepare-recursive-state ; inline + +f initial-recursive-state recursive-state set-global + +: add-recursive-state ( word -- rstate ) + recursive-state get clone + [ word>> dup ] keep [ store ] change-words + prepare-recursive-state ; + +: add-local-quotation ( recursive-state quot -- rstate ) + swap clone [ dupd store ] change-quotations ; + +: add-inline-word ( word label -- rstate ) + swap recursive-state get clone + [ store ] change-inline-words ; + +: recursive-word? ( word -- ? ) + recursive-state get 2dup word>> eq? + [ 2drop t ] [ words>> lookup ] if ; + +: inline-recursive-label ( word -- label/f ) + recursive-state get inline-words>> lookup ; + +: recursive-quotation? ( quot -- ? ) + recursive-state get quotations>> lookup ; diff --git a/basis/stack-checker/recursive-state/tree/tree.factor b/basis/stack-checker/recursive-state/tree/tree.factor new file mode 100644 index 0000000000..dd392af7c9 --- /dev/null +++ b/basis/stack-checker/recursive-state/tree/tree.factor @@ -0,0 +1,31 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors kernel sequences math math.order ; +IN: stack-checker.recursive-state.tree + +! Persistent unbalanced hash tree using eq? comparison. +! We use this to speed up stack-checker.recursive-state. +! Perhaps this should go somewhere else + +TUPLE: node value key hashcode left right ; + +GENERIC: lookup ( key node -- value/f ) + +M: f lookup nip ; + +: decide ( key node -- key node ? ) + over hashcode over hashcode>> <= ; inline + +M: node lookup + 2dup key>> eq? + [ nip value>> ] + [ decide [ left>> ] [ right>> ] if lookup ] if ; + +GENERIC: store ( value key node -- node' ) + +M: f store drop dup hashcode f f node boa ; + +M: node store + clone decide + [ [ store ] change-left ] + [ [ store ] change-right ] if ; diff --git a/basis/stack-checker/stack-checker-docs.factor b/basis/stack-checker/stack-checker-docs.factor index a9df463703..f208178b10 100644 --- a/basis/stack-checker/stack-checker-docs.factor +++ b/basis/stack-checker/stack-checker-docs.factor @@ -27,7 +27,7 @@ ARTICLE: "inference-combinators" "Combinator stack effects" "Consider a combinator such as " { $link keep } ". The combinator itself does not have a stack effect, because it applies " { $link call } " to a potentially arbitrary quotation. However, since the combinator is declared " { $link POSTPONE: inline } ", a given usage of it can have a stack effect:" { $example "[ [ 2 + ] keep ] infer." "( object -- object object )" } "Another example is the " { $link compose } " combinator. Because it is decared " { $link POSTPONE: inline } ", we can infer the stack effect of applying " { $link call } " to the result of " { $link compose } ":" -{ $example "[ 2 [ + ] curry [ sq ] compose ] infer." "( -- object object )" } +{ $example "[ 2 [ + ] curry [ sq ] compose ] infer." "( -- object )" } "Incidentally, this example demonstrates that the stack effect of nested currying and composition can also be inferred." $nl "A general rule of thumb is that any word which applies " { $link call } " or " { $link curry } " to one of its inputs must be declared " { $link POSTPONE: inline } "." diff --git a/basis/stack-checker/state/state.factor b/basis/stack-checker/state/state.factor index 11dc6f9ef8..2706ec60ef 100644 --- a/basis/stack-checker/state/state.factor +++ b/basis/stack-checker/state/state.factor @@ -1,48 +1,10 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: assocs namespaces sequences kernel definitions math -effects accessors words fry classes.algebra stack-checker.errors +USING: assocs arrays namespaces sequences kernel definitions +math effects accessors words fry classes.algebra compiler.units ; IN: stack-checker.state -: ( -- value ) \ counter ; - -SYMBOL: known-values - -: known ( value -- known ) known-values get at ; - -: set-known ( known value -- ) - over [ known-values get set-at ] [ 2drop ] if ; - -: make-known ( known -- value ) - [ set-known ] keep ; - -: copy-value ( value -- value' ) - known make-known ; - -: copy-values ( values -- values' ) - [ copy-value ] map ; - -! Literal value -TUPLE: literal < identity-tuple value recursion ; - -: ( obj -- value ) - recursive-state get \ literal boa ; - -: literal ( value -- literal ) - known dup literal? - [ \ literal-expected inference-warning ] unless ; - -! Result of curry -TUPLE: curried obj quot ; - -C: curried - -! Result of compose -TUPLE: composed quot1 quot2 ; - -C: composed - ! Did the current control-flow path throw an error? SYMBOL: terminated? @@ -68,23 +30,6 @@ SYMBOL: meta-r V{ } clone meta-r set 0 d-in set ; -: init-known-values ( -- ) - H{ } clone known-values set ; - -: recursive-label ( word -- label/f ) - recursive-state get at ; - -: local-recursive-state ( -- assoc ) - recursive-state get dup - [ first dup word? [ inline? ] when not ] find drop - [ head-slice ] when* ; - -: inline-recursive-label ( word -- label/f ) - local-recursive-state at ; - -: recursive-quotation? ( quot -- ? ) - local-recursive-state [ first eq? ] with contains? ; - ! Words that the current quotation depends on SYMBOL: dependencies @@ -98,9 +43,12 @@ SYMBOL: dependencies ! Generic words that the current quotation depends on SYMBOL: generic-dependencies +: ?class-or ( class/f class -- class' ) + swap [ class-or ] when* ; + : depends-on-generic ( generic class -- ) generic-dependencies get dup - [ swap '[ null or _ class-or ] change-at ] [ 3drop ] if ; + [ swap '[ _ ?class-or ] change-at ] [ 3drop ] if ; ! Words we've inferred the stack effect of, for rollback SYMBOL: recorded diff --git a/basis/stack-checker/transforms/transforms.factor b/basis/stack-checker/transforms/transforms.factor index abc3ae1950..e4f8c50eeb 100644 --- a/basis/stack-checker/transforms/transforms.factor +++ b/basis/stack-checker/transforms/transforms.factor @@ -5,11 +5,12 @@ namespaces make quotations assocs combinators classes.tuple classes.tuple.private effects summary hashtables classes generic sets definitions generic.standard slots.private continuations stack-checker.backend stack-checker.state stack-checker.visitor -stack-checker.errors ; +stack-checker.errors stack-checker.values +stack-checker.recursive-state ; IN: stack-checker.transforms : give-up-transform ( word -- ) - dup recursive-label + dup recursive-word? [ call-recursive-word ] [ dup infer-word apply-word/effect ] if ; diff --git a/basis/stack-checker/values/values.factor b/basis/stack-checker/values/values.factor new file mode 100644 index 0000000000..97aa774e55 --- /dev/null +++ b/basis/stack-checker/values/values.factor @@ -0,0 +1,52 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors namespaces kernel assocs sequences +stack-checker.recursive-state ; +IN: stack-checker.values + +! Values +: ( -- value ) \ counter ; + +SYMBOL: known-values + +: init-known-values ( -- ) + H{ } clone known-values set ; + +: known ( value -- known ) known-values get at ; + +: set-known ( known value -- ) + over [ known-values get set-at ] [ 2drop ] if ; + +: make-known ( known -- value ) + [ set-known ] keep ; + +: copy-value ( value -- value' ) + known make-known ; + +: copy-values ( values -- values' ) + [ copy-value ] map ; + +! Literal value +TUPLE: literal < identity-tuple value recursion hashcode ; + +M: literal hashcode* nip hashcode>> ; + +: ( obj -- value ) + recursive-state get over hashcode \ literal boa ; + +GENERIC: (literal) ( value -- literal ) + +M: literal (literal) ; + +: literal ( value -- literal ) + known (literal) ; + +! Result of curry +TUPLE: curried obj quot ; + +C: curried + +! Result of compose +TUPLE: composed quot1 quot2 ; + +C: composed diff --git a/basis/stack-checker/visitor/dummy/dummy.factor b/basis/stack-checker/visitor/dummy/dummy.factor index a24d8e226d..5f05d97d1a 100644 --- a/basis/stack-checker/visitor/dummy/dummy.factor +++ b/basis/stack-checker/visitor/dummy/dummy.factor @@ -8,7 +8,7 @@ M: f #introduce, drop ; M: f #call, 3drop ; M: f #call-recursive, 3drop ; M: f #push, 2drop ; -M: f #shuffle, 3drop ; +M: f #shuffle, 2drop 2drop drop ; M: f #>r, 2drop ; M: f #r>, 2drop ; M: f #return, drop ; diff --git a/basis/stack-checker/visitor/visitor.factor b/basis/stack-checker/visitor/visitor.factor index 7d8ec90453..6093cd008a 100644 --- a/basis/stack-checker/visitor/visitor.factor +++ b/basis/stack-checker/visitor/visitor.factor @@ -13,7 +13,7 @@ HOOK: #introduce, stack-visitor ( values -- ) HOOK: #call, stack-visitor ( inputs outputs word -- ) HOOK: #call-recursive, stack-visitor ( inputs outputs word -- ) HOOK: #push, stack-visitor ( literal value -- ) -HOOK: #shuffle, stack-visitor ( inputs outputs mapping -- ) +HOOK: #shuffle, stack-visitor ( in-d out-d in-r out-r mapping -- ) HOOK: #drop, stack-visitor ( values -- ) HOOK: #>r, stack-visitor ( inputs outputs -- ) HOOK: #r>, stack-visitor ( inputs outputs -- ) diff --git a/extra/suffix-arrays/authors.txt b/basis/suffix-arrays/authors.txt similarity index 100% rename from extra/suffix-arrays/authors.txt rename to basis/suffix-arrays/authors.txt diff --git a/extra/suffix-arrays/suffix-arrays-docs.factor b/basis/suffix-arrays/suffix-arrays-docs.factor similarity index 100% rename from extra/suffix-arrays/suffix-arrays-docs.factor rename to basis/suffix-arrays/suffix-arrays-docs.factor diff --git a/extra/suffix-arrays/suffix-arrays-tests.factor b/basis/suffix-arrays/suffix-arrays-tests.factor similarity index 100% rename from extra/suffix-arrays/suffix-arrays-tests.factor rename to basis/suffix-arrays/suffix-arrays-tests.factor diff --git a/extra/suffix-arrays/suffix-arrays.factor b/basis/suffix-arrays/suffix-arrays.factor similarity index 100% rename from extra/suffix-arrays/suffix-arrays.factor rename to basis/suffix-arrays/suffix-arrays.factor diff --git a/extra/suffix-arrays/summary.txt b/basis/suffix-arrays/summary.txt similarity index 100% rename from extra/suffix-arrays/summary.txt rename to basis/suffix-arrays/summary.txt diff --git a/extra/suffix-arrays/tags.txt b/basis/suffix-arrays/tags.txt similarity index 100% rename from extra/suffix-arrays/tags.txt rename to basis/suffix-arrays/tags.txt diff --git a/extra/suffix-arrays/words/words.factor b/basis/suffix-arrays/words/words.factor similarity index 100% rename from extra/suffix-arrays/words/words.factor rename to basis/suffix-arrays/words/words.factor diff --git a/basis/tools/crossref/crossref-docs.factor b/basis/tools/crossref/crossref-docs.factor index 477ea01ef6..b7ec0d07a2 100644 --- a/basis/tools/crossref/crossref-docs.factor +++ b/basis/tools/crossref/crossref-docs.factor @@ -1,10 +1,10 @@ -USING: help.markup help.syntax words definitions ; +USING: help.markup help.syntax words definitions prettyprint ; IN: tools.crossref ARTICLE: "tools.crossref" "Cross-referencing tools" { $subsection usage. } { $subsection apropos } -{ $see-also "definitions" "words" } ; +{ $see-also "definitions" "words" see see-methods } ; ABOUT: "tools.crossref" diff --git a/basis/tools/hexdump/authors.txt b/basis/tools/hexdump/authors.txt new file mode 100644 index 0000000000..7c1b2f2279 --- /dev/null +++ b/basis/tools/hexdump/authors.txt @@ -0,0 +1 @@ +Doug Coleman diff --git a/extra/hexdump/hexdump-docs.factor b/basis/tools/hexdump/hexdump-docs.factor similarity index 79% rename from extra/hexdump/hexdump-docs.factor rename to basis/tools/hexdump/hexdump-docs.factor index 4278e92f0e..9579fb7f81 100644 --- a/extra/hexdump/hexdump-docs.factor +++ b/basis/tools/hexdump/hexdump-docs.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2008 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: help.markup help.syntax kernel sequences strings ; -IN: hexdump +IN: tools.hexdump HELP: hexdump. { $values { "seq" sequence } } @@ -12,11 +12,11 @@ HELP: hexdump { $description "Converts a sequence to its hexadecimal and ASCII representation sixteen characters at a time. Lines are separated by a newline character." } { $see-also hexdump. } ; -ARTICLE: "hexdump" "Hexdump" -"The " { $vocab-link "hexdump" } " vocabulary provides a traditional hexdump view of a sequence." $nl +ARTICLE: "tools.hexdump" "Hexdump" +"The " { $vocab-link "tools.hexdump" } " vocabulary provides a traditional hexdump view of a sequence." $nl "Write hexdump to string:" { $subsection hexdump } "Write the hexdump to the output stream:" { $subsection hexdump. } ; -ABOUT: "hexdump" +ABOUT: "tools.hexdump" diff --git a/extra/hexdump/hexdump-tests.factor b/basis/tools/hexdump/hexdump-tests.factor similarity index 95% rename from extra/hexdump/hexdump-tests.factor rename to basis/tools/hexdump/hexdump-tests.factor index b3c03196f5..7202e4402c 100644 --- a/extra/hexdump/hexdump-tests.factor +++ b/basis/tools/hexdump/hexdump-tests.factor @@ -1,5 +1,5 @@ -IN: hexdump.tests -USING: hexdump kernel sequences tools.test ; +USING: tools.hexdump kernel sequences tools.test ; +IN: tools.hexdump.tests [ t ] [ "" hexdump "Length: 0, 0h\n" = ] unit-test [ t ] [ "abcdefghijklmnopqrstuvwxyz" hexdump "Length: 26, 1ah\n00000000h: 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 abcdefghijklmnop\n00000010h: 71 72 73 74 75 76 77 78 79 7a qrstuvwxyz\n" = ] unit-test diff --git a/extra/hexdump/hexdump.factor b/basis/tools/hexdump/hexdump.factor similarity index 98% rename from extra/hexdump/hexdump.factor rename to basis/tools/hexdump/hexdump.factor index ecbc2d6169..c8b9f4accc 100644 --- a/extra/hexdump/hexdump.factor +++ b/basis/tools/hexdump/hexdump.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: arrays io io.streams.string kernel math math.parser namespaces sequences splitting grouping strings ascii ; -IN: hexdump +IN: tools.hexdump > @@ -54,3 +55,7 @@ threads alien tools.profiler.private sequences compiler.units ; ] unit-test [ 666 ] [ \ recompile-while-profiling-test counter>> ] unit-test + +[ ] [ [ [ ] compile-call ] profile ] unit-test + +[ [ gensym execute ] profile ] [ T{ undefined } = ] must-fail-with diff --git a/basis/tools/scaffold/scaffold.factor b/basis/tools/scaffold/scaffold.factor index 6659940b2b..2811801266 100644 --- a/basis/tools/scaffold/scaffold.factor +++ b/basis/tools/scaffold/scaffold.factor @@ -148,7 +148,7 @@ ERROR: no-vocab vocab ; "{ $values" print [ " " write ($values.) ] [ [ nl " " write ($values.) ] unless-empty ] bi* - " }" write nl + nl "}" print ] if ] when* ; @@ -263,3 +263,12 @@ SYMBOL: examples-flag [ example ] times "}" print ] with-variable ; + +: scaffold-rc ( path -- ) + [ touch-file ] [ "Click to edit: " write . ] bi ; + +: scaffold-factor-boot-rc ( -- ) + home ".factor-boot-rc" append-path scaffold-rc ; + +: scaffold-factor-rc ( -- ) + home ".factor-rc" append-path scaffold-rc ; diff --git a/basis/ui/freetype/freetype.factor b/basis/ui/freetype/freetype.factor index d2dfe56ed4..5a6118fb00 100644 --- a/basis/ui/freetype/freetype.factor +++ b/basis/ui/freetype/freetype.factor @@ -196,6 +196,7 @@ M: freetype-renderer string-height ( open-font string -- h ) :: (draw-string) ( open-font sprites string loc -- ) GL_TEXTURE_2D [ loc [ + -0.5 0.5 0.0 glTranslated string open-font string char-widths scan-sums [ [ open-font sprites ] 2dip draw-char ] 2each diff --git a/basis/ui/gadgets/buttons/buttons.factor b/basis/ui/gadgets/buttons/buttons.factor index 4ad9e14874..11fb69fc7d 100644 --- a/basis/ui/gadgets/buttons/buttons.factor +++ b/basis/ui/gadgets/buttons/buttons.factor @@ -1,12 +1,11 @@ ! Copyright (C) 2005, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays kernel math models namespaces sequences - strings quotations assocs combinators classes colors - classes.tuple opengl math.vectors - ui.commands ui.gadgets ui.gadgets.borders - ui.gadgets.labels ui.gadgets.theme - ui.gadgets.tracks ui.gadgets.packs ui.gadgets.worlds ui.gestures - ui.render math.geometry.rect ; +strings quotations assocs combinators classes colors +classes.tuple opengl opengl.gl math.vectors ui.commands ui.gadgets +ui.gadgets.borders ui.gadgets.labels ui.gadgets.theme +ui.gadgets.tracks ui.gadgets.packs ui.gadgets.worlds ui.gestures +ui.render math.geometry.rect locals alien.c-types ; IN: ui.gadgets.buttons @@ -62,10 +61,10 @@ C: button-paint } cond ; M: button-paint draw-interior - button-paint draw-interior ; + button-paint dup [ draw-interior ] [ 2drop ] if ; M: button-paint draw-boundary - button-paint draw-boundary ; + button-paint dup [ draw-boundary ] [ 2drop ] if ; : align-left ( button -- button ) { 0 1/2 } >>align ; inline @@ -103,17 +102,34 @@ repeat-button H{ #! the mouse is held down. repeat-button new-button bevel-button-theme ; -TUPLE: checkmark-paint color ; +TUPLE: checkmark-paint < caching-pen color last-vertices ; -C: checkmark-paint +: ( color -- paint ) + checkmark-paint new swap >>color ; + +c-float-array ; + +PRIVATE> + +M: checkmark-paint recompute-pen + swap dim>> checkmark-vertices >>last-vertices drop ; M: checkmark-paint draw-interior - color>> set-color - origin get [ - rect-dim - { 0 0 } over gl-line - dup { 0 1 } v* swap { 1 0 } v* gl-line - ] with-translation ; + [ compute-pen ] + [ color>> gl-color ] + [ last-vertices>> gl-vertex-pointer ] tri + GL_LINES 0 4 glDrawArrays ; : checkmark-theme ( gadget -- gadget ) f @@ -148,30 +164,47 @@ TUPLE: checkbox < button ; M: checkbox model-changed swap value>> >>selected? relayout-1 ; -TUPLE: radio-paint color ; +TUPLE: radio-paint < caching-pen color interior-vertices boundary-vertices ; -C: radio-paint +: ( color -- paint ) radio-paint new swap >>color ; + + + +M: radio-paint recompute-pen + swap dim>> + [ { 4 4 } swap { 9 9 } v- circle-steps circle-vertices >>interior-vertices ] + [ { 1 1 } swap { 3 3 } v- circle-steps circle-vertices >>boundary-vertices ] bi + drop ; + +> gl-color ] bi ; + +PRIVATE> M: radio-paint draw-interior - color>> set-color - origin get { 4 4 } v+ swap rect-dim { 8 8 } v- 12 gl-fill-circle ; + [ (radio-paint) ] [ interior-vertices>> gl-vertex-pointer ] bi + GL_POLYGON 0 circle-steps glDrawArrays ; M: radio-paint draw-boundary - color>> set-color - origin get { 1 1 } v+ swap rect-dim { 2 2 } v- 12 gl-circle ; + [ (radio-paint) ] [ boundary-vertices>> gl-vertex-pointer ] bi + GL_LINE_LOOP 0 circle-steps glDrawArrays ; -: radio-knob-theme ( gadget -- gadget ) - f - f - black - black - >>interior - black >>boundary ; +:: radio-knob-theme ( gadget -- gadget ) + [let | radio-paint [ black ] | + gadget + f f radio-paint radio-paint >>interior + radio-paint >>boundary + { 16 16 } >>dim + ] ; : ( -- gadget ) - - radio-knob-theme - { 16 16 } >>dim ; + radio-knob-theme ; TUPLE: radio-control < button value ; diff --git a/basis/ui/gadgets/editors/editors.factor b/basis/ui/gadgets/editors/editors.factor index a1026ef35a..0d0611f532 100644 --- a/basis/ui/gadgets/editors/editors.factor +++ b/basis/ui/gadgets/editors/editors.factor @@ -127,10 +127,12 @@ M: editor ungraft* : draw-caret ( -- ) editor get focused?>> [ editor get - dup caret-color>> set-color - dup caret-loc origin get v+ - swap caret-dim over v+ - [ { 0.5 -0.5 } v+ ] bi@ gl-line + [ caret-color>> gl-color ] + [ + dup caret-loc origin get v+ + swap caret-dim over v+ + gl-line + ] bi ] when ; : line-translation ( n -- loc ) @@ -171,7 +173,7 @@ M: editor ungraft* : draw-lines ( -- ) \ first-visible-line get [ - editor get dup color>> set-color + editor get dup color>> gl-color dup visible-lines [ draw-line 1 translate-lines ] with each ] with-editor-translation ; @@ -180,17 +182,19 @@ M: editor ungraft* dup editor-mark* swap editor-caret* sort-pair ; : (draw-selection) ( x1 x2 -- ) - 2dup = [ 2 + ] when - 0.0 swap editor get line-height glRectd ; + over - + dup 0 = [ 2 + ] when + [ 0.0 2array ] [ editor get line-height 2array ] bi* + swap [ gl-fill-rect ] with-translation ; : draw-selected-line ( start end n -- ) [ start/end-on-line ] keep tuck - >r >r editor get offset>x r> r> + [ editor get offset>x ] 2dip editor get offset>x (draw-selection) ; : draw-selection ( -- ) - editor get selection-color>> set-color + editor get selection-color>> gl-color editor get selection-start/end over first [ 2dup [ diff --git a/basis/ui/gadgets/grid-lines/grid-lines.factor b/basis/ui/gadgets/grid-lines/grid-lines.factor index f4266adba1..0356e7fd4d 100644 --- a/basis/ui/gadgets/grid-lines/grid-lines.factor +++ b/basis/ui/gadgets/grid-lines/grid-lines.factor @@ -23,13 +23,10 @@ SYMBOL: grid-dim ] with each ; M: grid-lines draw-boundary - origin get [ - -0.5 -0.5 0.0 glTranslated - color>> set-color [ - dup grid set - dup rect-dim half-gap v- grid-dim set - compute-grid - { 0 1 } draw-grid-lines - { 1 0 } draw-grid-lines - ] with-scope - ] with-translation ; + color>> gl-color [ + dup grid set + dup rect-dim half-gap v- grid-dim set + compute-grid + { 0 1 } draw-grid-lines + { 1 0 } draw-grid-lines + ] with-scope ; diff --git a/basis/ui/gadgets/labelled/labelled.factor b/basis/ui/gadgets/labelled/labelled.factor index 37b1d251e8..79a485b711 100644 --- a/basis/ui/gadgets/labelled/labelled.factor +++ b/basis/ui/gadgets/labelled/labelled.factor @@ -30,10 +30,10 @@ M: labelled-gadget focusable-child* content>> ; : title-theme ( gadget -- gadget ) { 1 0 } >>orientation - T{ gradient f { + { T{ rgba f 0.65 0.65 1.0 1.0 } T{ rgba f 0.65 0.45 1.0 1.0 } - } } >>interior ; + } >>interior ; : ( text -- label )