]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorJoe Groff <arcata@gmail.com>
Wed, 10 Jun 2009 18:06:44 +0000 (13:06 -0500)
committerJoe Groff <arcata@gmail.com>
Wed, 10 Jun 2009 18:06:44 +0000 (13:06 -0500)
56 files changed:
basis/bitstreams/bitstreams.factor
basis/circular/circular-tests.factor
basis/circular/circular.factor
basis/compiler/cfg/cfg.factor
basis/compiler/cfg/checker/checker.factor
basis/compiler/cfg/linear-scan/allocation/allocation.factor
basis/compiler/cfg/linear-scan/assignment/assignment.factor
basis/compiler/cfg/linear-scan/linear-scan-tests.factor
basis/compiler/cfg/linear-scan/linear-scan.factor
basis/compiler/cfg/linear-scan/live-intervals/live-intervals.factor
basis/compiler/cfg/optimizer/optimizer.factor
basis/compiler/cfg/two-operand/two-operand.factor
basis/compiler/codegen/codegen.factor
basis/compiler/compiler.factor
basis/compression/run-length/run-length.factor
basis/constructors/constructors-tests.factor
basis/constructors/constructors.factor
basis/cpu/architecture/architecture.factor
basis/cpu/ppc/ppc.factor
basis/cpu/x86/assembler/assembler-tests.factor
basis/cpu/x86/assembler/assembler.factor
basis/cpu/x86/x86.factor
basis/formatting/formatting-tests.factor
basis/help/lint/lint.factor
basis/images/bitmap/bitmap.factor
basis/images/images.factor
basis/images/jpeg/jpeg.factor
basis/images/loader/loader.factor
basis/images/png/png.factor
basis/images/tiff/tiff.factor
basis/io/streams/limited/limited.factor
basis/json/reader/authors.txt
basis/json/reader/reader-tests.factor
basis/json/reader/reader.factor
basis/listener/listener-docs.factor
basis/listener/listener.factor
basis/prettyprint/prettyprint-tests.factor
basis/tools/deploy/shaker/shaker.factor
core/parser/parser.factor
core/vocabs/parser/parser-docs.factor
core/vocabs/parser/parser.factor
extra/brainfuck/authors.txt [new file with mode: 0644]
extra/brainfuck/brainfuck-docs.factor [new file with mode: 0644]
extra/brainfuck/brainfuck-tests.factor [new file with mode: 0644]
extra/brainfuck/brainfuck.factor [new file with mode: 0644]
extra/brainfuck/summary.txt [new file with mode: 0644]
extra/fuel/help/help.factor
extra/images/processing/rotation/rotation-tests.factor
extra/managed-server/chat/chat.factor
extra/managed-server/managed-server.factor
misc/bash/cdfactor.sh [new file with mode: 0755]
misc/fuel/factor-mode.el
misc/fuel/fuel-markup.el
misc/fuel/fuel-mode.el
misc/fuel/fuel-scaffold.el
misc/fuel/fuel-table.el

index cb6a753735ca0b7d1f4aebb31129865cadd6559e..4718f137e42188c8018f91171e343896e4bb1fad 100644 (file)
@@ -158,3 +158,9 @@ M: msb0-bit-reader peek ( n bs -- bits ) \ be> \ subseq>bits-be (peek) ;
         writer bytes>> swap push
     ] unless
     writer bytes>> ;
+
+:: byte-array-n>seq ( byte-array n -- seq )
+    byte-array length 8 * n / iota
+    byte-array <msb0-bit-reader> '[
+        drop n _ read
+    ] { } map-as ;
index 3a94e14640d8614f0a4bbe7efdb4719486186765..b4a9d547f2edc888bde7efce60371f3f53616502 100644 (file)
@@ -13,6 +13,7 @@ circular strings ;
  
 [ [ 1 2 3 ] ] [ { 1 2 3 } <circular> [ ] like ] unit-test
 [ [ 2 3 1 ] ] [ { 1 2 3 } <circular> [ rotate-circular ] keep [ ] like ] unit-test
+[ [ 3 1 2 ] ] [ { 1 2 3 } <circular> [ rotate-circular ] keep [ rotate-circular ] keep [ ] like ] unit-test
 [ [ 2 3 1 ] ] [ { 1 2 3 } <circular> 1 over change-circular-start [ ] like ] unit-test
 [ [ 3 1 2 ] ] [ { 1 2 3 } <circular> 1 over change-circular-start 1 over change-circular-start [ ] like ] unit-test
 [ [ 3 1 2 ] ] [ { 1 2 3 } <circular> -100 over change-circular-start [ ] like ] unit-test
index ae79e70d7356a0ef558905e31e284804c9e15218..d47b954ecfb1b555c4d905609347c6692a40e99d 100644 (file)
@@ -28,10 +28,10 @@ M: circular virtual-seq seq>> ;
     circular-wrap (>>start) ;
 
 : rotate-circular ( circular -- )
-    [ start>> 1 + ] keep circular-wrap (>>start) ;
+    [ 1 ] dip change-circular-start ;
 
 : push-circular ( elt circular -- )
-    [ set-first ] [ 1 swap change-circular-start ] bi ;
+    [ set-first ] [ rotate-circular ] bi ;
 
 : <circular-string> ( n -- circular )
     0 <string> <circular> ;
index c3ae15f069efac396561a3c03c48b32153e57af6..dabc7338d28377ffa2ac667bb7114bf515497023 100644 (file)
@@ -1,11 +1,11 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel arrays vectors accessors
-namespaces make fry sequences ;
+namespaces math make fry sequences ;
 IN: compiler.cfg
 
 TUPLE: basic-block < identity-tuple
-id
+{ id integer }
 number
 { instructions vector }
 { successors vector }
index 4aa208814398aaeb080ef3e179d532881180b86d..4f215f1dc8081417703fd47ae558e6d5726a0bed 100644 (file)
@@ -16,6 +16,9 @@ ERROR: last-insn-not-a-jump insn ;
         [ ##return? ]
         [ ##callback-return? ]
         [ ##jump? ]
+        [ ##fixnum-add-tail? ]
+        [ ##fixnum-sub-tail? ]
+        [ ##fixnum-mul-tail? ]
         [ ##call? ]
     } 1|| [ drop ] [ last-insn-not-a-jump ] if ;
 
index 908bf2475b980e154ffdf445699ccf3466f64e32..7b56bd61503e789c8de4e8a847fd1f2c92c1d13e 100644 (file)
@@ -1,9 +1,9 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces sequences math math.order kernel assocs
-accessors vectors fry heaps cpu.architecture combinators
-compiler.cfg.registers
-compiler.cfg.linear-scan.live-intervals ;
+accessors vectors fry heaps cpu.architecture sorting locals
+combinators compiler.cfg.registers
+compiler.cfg.linear-scan.live-intervals hints ;
 IN: compiler.cfg.linear-scan.allocation
 
 ! Mapping from register classes to sequences of machine registers
@@ -27,13 +27,61 @@ SYMBOL: active-intervals
 : delete-active ( live-interval -- )
     dup vreg>> active-intervals-for delq ;
 
-: expire-old-intervals ( n -- )
-    active-intervals swap '[
-        [
-            [ end>> _ < ] partition
-            [ [ deallocate-register ] each ] dip
-        ] assoc-map
-    ] change ;
+! Vector of inactive live intervals
+SYMBOL: inactive-intervals
+
+: inactive-intervals-for ( vreg -- seq )
+    reg-class>> inactive-intervals get at ;
+
+: add-inactive ( live-interval -- )
+    dup vreg>> inactive-intervals-for push ;
+
+! Vector of handled live intervals
+SYMBOL: handled-intervals
+
+: add-handled ( live-interval -- )
+    handled-intervals get push ;
+
+: finished? ( n live-interval -- ? ) end>> swap < ;
+
+: finish ( n live-interval -- keep? )
+    nip [ deallocate-register ] [ add-handled ] bi f ;
+
+: activate ( n live-interval -- keep? )
+    nip add-active f ;
+
+: deactivate ( n live-interval -- keep? )
+    nip add-inactive f ;
+
+: don't-change ( n live-interval -- keep? ) 2drop t ;
+
+! Moving intervals between active and inactive sets
+: process-intervals ( n symbol quots -- )
+    ! symbol stores an alist mapping register classes to vectors
+    [ get values ] dip '[ [ _ cond ] with filter-here ] with each ; inline
+
+: covers? ( insn# live-interval -- ? )
+    ranges>> [ [ from>> ] [ to>> ] bi between? ] with any? ;
+
+: deactivate-intervals ( n -- )
+    ! Any active intervals which have ended are moved to handled
+    ! Any active intervals which cover the current position
+    ! are moved to inactive
+    active-intervals {
+        { [ 2dup finished? ] [ finish ] }
+        { [ 2dup covers? not ] [ deactivate ] }
+        [ don't-change ]
+    } process-intervals ;
+
+: activate-intervals ( n -- )
+    ! Any inactive intervals which have ended are moved to handled
+    ! Any inactive intervals which do not cover the current position
+    ! are moved to active
+    inactive-intervals {
+        { [ 2dup finished? ] [ finish ] }
+        { [ 2dup covers? ] [ activate ] }
+        [ don't-change ]
+    } process-intervals ;
 
 ! Minheap of live intervals which still need a register allocation
 SYMBOL: unhandled-intervals
@@ -66,29 +114,64 @@ SYMBOL: progress
 
 : coalesce ( live-interval -- )
     dup copy-from>> active-interval
-    [ [ add-active ] [ delete-active ] bi* ]
+    [ [ add-active ] [ [ delete-active ] [ add-handled ] bi ] bi* ]
     [ reg>> >>reg drop ]
     2bi ;
 
 ! Splitting
-: find-use ( live-interval n quot -- i elt )
-    [ uses>> ] 2dip curry find ; inline
+: split-range ( live-range n -- before after )
+    [ [ from>> ] dip <live-range> ]
+    [ 1 + swap to>> <live-range> ]
+    2bi ;
+
+: split-last-range? ( last n -- ? )
+    swap to>> <= ;
 
-: split-before ( live-interval i -- before )
-    [ clone dup uses>> ] dip
-    [ head >>uses ] [ 1- swap nth >>end ] 2bi ;
+: split-last-range ( before after last n -- before' after' )
+    split-range [ [ but-last ] dip suffix ] [ prefix ] bi-curry* bi* ;
 
-: split-after ( live-interval i -- after )
-    [ clone dup uses>> ] dip
-    [ tail >>uses ] [ swap nth >>start ] 2bi
-    f >>reg f >>copy-from ;
+: split-ranges ( live-ranges n -- before after )
+    [ '[ from>> _ <= ] partition ]
+    [
+        pick empty? [ drop ] [
+            [ over last ] dip 2dup split-last-range?
+            [ split-last-range ] [ 2drop ] if
+        ] if
+    ] bi ;
 
-: split-interval ( live-interval n -- before after )
-    [ drop ] [ [ > ] find-use drop ] 2bi
-    [ split-before ] [ split-after ] 2bi ;
+: split-uses ( uses n -- before after )
+    '[ _ <= ] partition ;
 
 : record-split ( live-interval before after -- )
-    [ >>split-before ] [ >>split-after ] bi* drop ;
+    [ >>split-before ] [ >>split-after ] bi* drop ; inline
+
+: check-split ( live-interval -- )
+    [ end>> ] [ start>> ] bi - 0 =
+    [ "BUG: splitting atomic interval" throw ] when ; inline
+
+: split-before ( before -- before' )
+    [ [ ranges>> last ] [ uses>> last ] bi >>to drop ]
+    [ compute-start/end ]
+    [ ]
+    tri ; inline
+
+: split-after ( after -- after' )
+    [ [ ranges>> first ] [ uses>> first ] bi >>from drop ]
+    [ compute-start/end ]
+    [ ]
+    tri ; inline
+
+:: split-interval ( live-interval n -- before after )
+    live-interval check-split
+    live-interval clone :> before
+    live-interval clone f >>copy-from f >>reg :> after
+    live-interval uses>> n split-uses before after [ (>>uses) ] bi-curry@ bi*
+    live-interval ranges>> n split-ranges before after [ (>>ranges) ] bi-curry@ bi*
+    live-interval before after record-split
+    before split-before
+    after split-after ;
+
+HINTS: split-interval live-interval object ;
 
 ! Spilling
 SYMBOL: spill-counts
@@ -96,6 +179,9 @@ SYMBOL: spill-counts
 : next-spill-location ( reg-class -- n )
     spill-counts get [ dup 1+ ] change-at ;
 
+: find-use ( live-interval n quot -- i elt )
+    [ uses>> ] 2dip curry find ; inline
+
 : interval-to-spill ( active-intervals current -- live-interval )
     #! We spill the interval with the most distant use location.
     start>> '[ dup _ [ >= ] find-use nip ] { } map>assoc
@@ -108,8 +194,7 @@ SYMBOL: spill-counts
     [ >>spill-to ] [ >>reload-from ] bi-curry bi* ;
 
 : split-and-spill ( new existing -- before after )
-    dup rot start>> split-interval
-    [ record-split ] [ assign-spill ] 2bi ;
+    swap start>> split-interval assign-spill ;
 
 : reuse-register ( new existing -- )
     reg>> >>reg add-active ;
@@ -121,7 +206,7 @@ SYMBOL: spill-counts
     #! of the existing interval again.
     [ reuse-register ]
     [ nip delete-active ]
-    [ split-and-spill [ drop ] [ add-unhandled ] bi* ] 2tri ;
+    [ split-and-spill [ add-handled ] [ add-unhandled ] bi* ] 2tri ;
 
 : spill-new ( new existing -- )
     #! Our new interval will be used after the active interval
@@ -141,37 +226,101 @@ SYMBOL: spill-counts
 : assign-free-register ( new registers -- )
     pop >>reg add-active ;
 
-: assign-register ( new -- )
-    dup coalesce? [
-        coalesce
+: relevant-ranges ( new inactive -- new' inactive' )
+    ! Slice off all ranges of 'inactive' that precede the start of 'new'
+    [ [ ranges>> ] bi@ ] [ nip start>> ] 2bi '[ to>> _ >= ] filter ;
+
+: intersect-live-range ( range1 range2 -- n/f )
+    2dup [ from>> ] bi@ > [ swap ] when
+    2dup [ to>> ] [ from>> ] bi* >= [ nip from>> ] [ 2drop f ] if ;
+
+: intersect-live-ranges ( ranges1 ranges2 -- n )
+    {
+        { [ over empty? ] [ 2drop 1/0. ] }
+        { [ dup empty? ] [ 2drop 1/0. ] }
+        [
+            2dup [ first ] bi@ intersect-live-range dup [ 2nip ] [
+                drop
+                2dup [ first from>> ] bi@ <
+                [ [ rest-slice ] dip ] [ rest-slice ] if
+                intersect-live-ranges
+            ] if
+        ]
+    } cond ;
+
+: intersect-inactive ( new inactive -- n )
+    relevant-ranges intersect-live-ranges ;
+
+: intersecting-inactive ( new -- live-intervals )
+    dup vreg>> inactive-intervals-for
+    [ tuck intersect-inactive ] with { } map>assoc ;
+
+: fits-in-hole ( new pair -- )
+    first reuse-register ;
+
+: split-before-use ( new pair -- before after )
+    ! Find optimal split position
+    ! Insert move instruction
+    second split-interval ;
+
+: assign-inactive-register ( new live-intervals -- )
+    ! If there is an interval which is inactive for the entire lifetime
+    ! if the new interval, reuse its vreg. Otherwise, split new so that
+    ! the first half fits.
+    sort-values last
+    2dup [ end>> ] [ second ] bi* < [
+        fits-in-hole
     ] [
-        dup vreg>> free-registers-for
-        [ assign-blocked-register ]
-        [ assign-free-register ]
+        [ split-before-use ] keep
+       '[ _ fits-in-hole ] [ add-unhandled ] bi*
+    ] if ;
+
+: assign-register ( new -- )
+    dup coalesce? [ coalesce ] [
+        dup vreg>> free-registers-for [
+            dup intersecting-inactive
+            [ assign-blocked-register ]
+            [ assign-inactive-register ]
+            if-empty
+        ] [ assign-free-register ]
         if-empty
     ] if ;
 
 ! Main loop
-: reg-classes ( -- seq ) { int-regs double-float-regs } ; inline
+CONSTANT: reg-classes { int-regs double-float-regs }
+
+: reg-class-assoc ( quot -- assoc )
+    [ reg-classes ] dip { } map>assoc ; inline
 
 : init-allocator ( registers -- )
-    <min-heap> unhandled-intervals set
     [ reverse >vector ] assoc-map free-registers set
-    reg-classes [ 0 ] { } map>assoc spill-counts set
-    reg-classes [ V{ } clone ] { } map>assoc active-intervals set
+    [ 0 ] reg-class-assoc spill-counts set
+    <min-heap> unhandled-intervals set
+    [ V{ } clone ] reg-class-assoc active-intervals set
+    [ V{ } clone ] reg-class-assoc inactive-intervals set
+    V{ } clone handled-intervals set
     -1 progress set ;
 
 : handle-interval ( live-interval -- )
-    [ start>> progress set ]
-    [ start>> expire-old-intervals ]
-    [ assign-register ]
-    tri ;
+    [
+        start>>
+        [ progress set ]
+        [ deactivate-intervals ]
+        [ activate-intervals ] tri
+    ] [ assign-register ] bi ;
 
 : (allocate-registers) ( -- )
     unhandled-intervals get [ handle-interval ] slurp-heap ;
 
+: finish-allocation ( -- )
+    ! Sanity check: all live intervals should've been processed
+    active-intervals inactive-intervals
+    [ get values [ handled-intervals get push-all ] each ] bi@ ;
+
 : allocate-registers ( live-intervals machine-registers -- live-intervals )
     #! This modifies the input live-intervals.
     init-allocator
-    dup init-unhandled
-    (allocate-registers) ;
+    init-unhandled
+    (allocate-registers)
+    finish-allocation
+    handled-intervals get ;
index 0de350c215d27bbbca2333f0c0856e91e16cbd98..6fcd6e757071f08dda0a468b8524abf99982593a 100644 (file)
@@ -1,11 +1,12 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel math assocs namespaces sequences heaps
-fry make combinators
+fry make combinators sets
 cpu.architecture
 compiler.cfg.def-use
 compiler.cfg.registers
 compiler.cfg.instructions
+compiler.cfg.linear-scan.allocation
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.assignment
 
@@ -25,35 +26,49 @@ TUPLE: active-intervals seq ;
 SYMBOL: unhandled-intervals
 
 : add-unhandled ( live-interval -- )
-    dup split-before>> [
-        [ split-before>> ] [ split-after>> ] bi
-        [ add-unhandled ] bi@
-    ] [
-        dup start>> unhandled-intervals get heap-push
-    ] if ;
+    dup start>> unhandled-intervals get heap-push ;
 
 : init-unhandled ( live-intervals -- )
     [ add-unhandled ] each ;
 
+! Mapping spill slots to vregs
+SYMBOL: spill-slots
+
+: spill-slots-for ( vreg -- assoc )
+    reg-class>> spill-slots get at ;
+
+: record-spill ( live-interval -- )
+    [ dup spill-to>> ] [ vreg>> spill-slots-for ] bi
+    2dup key? [ "BUG: Already spilled" throw ] [ set-at ] if ;
+
 : insert-spill ( live-interval -- )
-    [ reg>> ] [ vreg>> reg-class>> ] [ spill-to>> ] tri
-    dup [ _spill ] [ 3drop ] if ;
+    [ reg>> ] [ vreg>> reg-class>> ] [ spill-to>> ] tri _spill ;
+
+: handle-spill ( live-interval -- )
+    dup spill-to>> [ [ record-spill ] [ insert-spill ] bi ] [ drop ] if ;
 
 : expire-old-intervals ( n -- )
     active-intervals get
     [ swap '[ end>> _ = ] partition ] change-seq drop
-    [ insert-spill ] each ;
+    [ handle-spill ] each ;
+
+: record-reload ( live-interval -- )
+    [ reload-from>> ] [ vreg>> spill-slots-for ] bi
+    2dup key? [ delete-at ] [ "BUG: Already reloaded" throw ] if ;
 
 : insert-reload ( live-interval -- )
-    [ reg>> ] [ vreg>> reg-class>> ] [ reload-from>> ] tri
-    dup [ _reload ] [ 3drop ] if ;
+    [ reg>> ] [ vreg>> reg-class>> ] [ reload-from>> ] tri _reload ;
+
+: handle-reload ( live-interval -- )
+    dup reload-from>> [ [ record-reload ] [ insert-reload ] bi ] [ drop ] if ;
 
 : activate-new-intervals ( n -- )
     #! Any live intervals which start on the current instruction
     #! are added to the active set.
     unhandled-intervals get dup heap-empty? [ 2drop ] [
         2dup heap-peek drop start>> = [
-            heap-pop drop [ add-active ] [ insert-reload ] bi
+            heap-pop drop
+            [ add-active ] [ handle-reload ] bi
             activate-new-intervals
         ] [ 2drop ] if
     ] if ;
@@ -76,8 +91,7 @@ M: insn assign-before drop ;
     active-intervals get seq>> [ [ vreg>> ] [ reg>> ] bi ] { } map>assoc ;
 
 : compute-live-spill-slots ( -- spill-slots )
-    unhandled-intervals get
-    heap-values [ reload-from>> ] filter
+    spill-slots get values [ values ] map concat
     [ [ vreg>> ] [ reload-from>> ] bi ] { } map>assoc ;
 
 M: ##gc assign-after
@@ -93,6 +107,7 @@ M: insn assign-after drop ;
 : init-assignment ( live-intervals -- )
     <active-intervals> active-intervals set
     <min-heap> unhandled-intervals set
+    [ H{ } clone ] reg-class-assoc spill-slots set 
     init-unhandled ;
 
 : assign-registers-in-block ( bb -- )
index e0cbe3774f4c7f69e72e12dc9d316c0160462c97..ccfc4a1ff76690bd32c441f3905594b06fff0e13 100644 (file)
@@ -12,6 +12,60 @@ compiler.cfg.linear-scan.live-intervals
 compiler.cfg.linear-scan.allocation
 compiler.cfg.linear-scan.debugger ;
 
+[
+    { T{ live-range f 1 10 } T{ live-range f 15 15 } }
+    { T{ live-range f 16 20 } }
+] [
+    {
+        T{ live-range f 1 10 }
+        T{ live-range f 15 20 }
+    } 15 split-ranges
+] unit-test
+
+[
+    { T{ live-range f 1 10 } T{ live-range f 15 16 } }
+    { T{ live-range f 17 20 } }
+] [
+    {
+        T{ live-range f 1 10 }
+        T{ live-range f 15 20 }
+    } 16 split-ranges
+] unit-test
+
+[
+    { T{ live-range f 1 10 } }
+    { T{ live-range f 15 20 } }
+] [
+    {
+        T{ live-range f 1 10 }
+        T{ live-range f 15 20 }
+    } 12 split-ranges
+] unit-test
+
+[
+    { T{ live-range f 1 10 } T{ live-range f 15 17 } }
+    { T{ live-range f 18 20 } }
+] [
+    {
+        T{ live-range f 1 10 }
+        T{ live-range f 15 20 }
+    } 17 split-ranges
+] unit-test
+
+[
+    { }
+    { T{ live-range f 1 10 } }
+] [
+    { T{ live-range f 1 10 } } 0 split-ranges
+] unit-test
+
+[
+    { T{ live-range f 0 0 } }
+    { T{ live-range f 1 5 } }
+] [
+    { T{ live-range f 0 5 } } 0 split-ranges
+] unit-test
+
 [ 7 ] [
     T{ live-interval
         { vreg T{ vreg { reg-class int-regs } { n 2 } } }
@@ -44,23 +98,26 @@ compiler.cfg.linear-scan.debugger ;
 
 [
     T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 0 }
-        { end 1 }
-        { uses V{ 0 1 } }
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { start 0 }
+       { end 1 }
+       { uses V{ 0 1 } }
+       { ranges V{ T{ live-range f 0 1 } } }
     }
     T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 5 }
-        { end 5 }
-        { uses V{ 5 } }
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { start 5 }
+       { end 5 }
+       { uses V{ 5 } }
+       { ranges V{ T{ live-range f 5 5 } } }
     }
 ] [
     T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 0 }
-        { end 5 }
-        { uses V{ 0 1 5 } }
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { start 0 }
+       { end 5 }
+       { uses V{ 0 1 5 } }
+       { ranges V{ T{ live-range f 0 5 } } }
     } 2 split-interval
 ] unit-test
 
@@ -70,12 +127,14 @@ compiler.cfg.linear-scan.debugger ;
         { start 0 }
         { end 0 }
         { uses V{ 0 } }
+        { ranges V{ T{ live-range f 0 0 } } }
     }
     T{ live-interval
         { vreg T{ vreg { reg-class int-regs } { n 1 } } }
         { start 1 }
         { end 5 }
         { uses V{ 1 5 } }
+        { ranges V{ T{ live-range f 1 5 } } }
     }
 ] [
     T{ live-interval
@@ -83,6 +142,7 @@ compiler.cfg.linear-scan.debugger ;
         { start 0 }
         { end 5 }
         { uses V{ 0 1 5 } }
+         { ranges V{ T{ live-range f 0 5 } } }
     } 0 split-interval
 ] unit-test
 
@@ -173,7 +233,13 @@ compiler.cfg.linear-scan.debugger ;
 
 [ ] [
     {
-        T{ live-interval { vreg T{ vreg { n 1 } { reg-class int-regs } } } { start 0 } { end 100 } { uses V{ 0 100 } } }
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 100 }
+           { uses V{ 0 100 } }
+           { ranges V{ T{ live-range f 0 100 } } }
+        }
     }
     H{ { int-regs { "A" } } }
     check-linear-scan
@@ -181,8 +247,20 @@ compiler.cfg.linear-scan.debugger ;
 
 [ ] [
     {
-        T{ live-interval { vreg T{ vreg { n 1 } { reg-class int-regs } } } { start 0 } { end 10 } { uses V{ 0 10 } } }
-        T{ live-interval { vreg T{ vreg { n 2 } { reg-class int-regs } } } { start 11 } { end 20 } { uses V{ 11 20 } } }
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 10 }
+           { uses V{ 0 10 } }
+           { ranges V{ T{ live-range f 0 10 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 2 } { reg-class int-regs } } }
+           { start 11 }
+           { end 20 }
+           { uses V{ 11 20 } }
+           { ranges V{ T{ live-range f 11 20 } } }
+        }
     }
     H{ { int-regs { "A" } } }
     check-linear-scan
@@ -190,8 +268,20 @@ compiler.cfg.linear-scan.debugger ;
 
 [ ] [
     {
-        T{ live-interval { vreg T{ vreg { n 1 } { reg-class int-regs } } } { start 0 } { end 100 } { uses V{ 0 100 } } }
-        T{ live-interval { vreg T{ vreg { n 2 } { reg-class int-regs } } } { start 30 } { end 60 } { uses V{ 30 60 } } }
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 100 }
+           { uses V{ 0 100 } }
+           { ranges V{ T{ live-range f 0 100 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 2 } { reg-class int-regs } } }
+           { start 30 }
+           { end 60 }
+           { uses V{ 30 60 } }
+           { ranges V{ T{ live-range f 30 60 } } }
+        }
     }
     H{ { int-regs { "A" } } }
     check-linear-scan
@@ -199,8 +289,20 @@ compiler.cfg.linear-scan.debugger ;
 
 [ ] [
     {
-        T{ live-interval { vreg T{ vreg { n 1 } { reg-class int-regs } } } { start 0 } { end 100 } { uses V{ 0 100 } } }
-        T{ live-interval { vreg T{ vreg { n 2 } { reg-class int-regs } } } { start 30 } { end 200 } { uses V{ 30 200 } } }
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 100 }
+           { uses V{ 0 100 } }
+           { ranges V{ T{ live-range f 0 100 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 2 } { reg-class int-regs } } }
+           { start 30 }
+           { end 200 }
+           { uses V{ 30 200 } }
+           { ranges V{ T{ live-range f 30 200 } } }
+        }
     }
     H{ { int-regs { "A" } } }
     check-linear-scan
@@ -208,8 +310,20 @@ compiler.cfg.linear-scan.debugger ;
 
 [
     {
-        T{ live-interval { vreg T{ vreg { n 1 } { reg-class int-regs } } } { start 0 } { end 100 } { uses V{ 0 100 } } }
-        T{ live-interval { vreg T{ vreg { n 2 } { reg-class int-regs } } } { start 30 } { end 100 } { uses V{ 30 100 } } }
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 100 }
+           { uses V{ 0 100 } }
+           { ranges V{ T{ live-range f 0 100 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 2 } { reg-class int-regs } } }
+           { start 30 }
+           { end 100 }
+           { uses V{ 30 100 } }
+           { ranges V{ T{ live-range f 30 100 } } }
+        }
     }
     H{ { int-regs { "A" } } }
     check-linear-scan
@@ -272,31 +386,10 @@ USING: math.private compiler.cfg.debugger ;
     test-cfg first optimize-cfg linear-scan drop
 ] unit-test
 
-[ 0 1 ] [
-    {
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 0 }
-            { end 5 }
-            { uses V{ 0 1 5 } }
-        }
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-            { start 3 }
-            { end 4 }
-            { uses V{ 3 4 } }
-        }
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 3 } } }
-            { start 2 }
-            { end 6 }
-            { uses V{ 2 4 6 } }
-        }
-    } [ clone ] map
-    H{ { int-regs { "A" "B" } } }
-    allocate-registers
-    first split-before>> [ start>> ] [ end>> ] bi
-] unit-test
+: fake-live-ranges ( seq -- seq' )
+    [
+        clone dup [ start>> ] [ end>> ] bi <live-range> 1vector >>ranges
+    ] map ;
 
 ! Coalescing interacted badly with splitting
 [ ] [
@@ -345,7 +438,7 @@ USING: math.private compiler.cfg.debugger ;
             { end 10 }
             { uses V{ 9 10 } }
         }
-    }
+    } fake-live-ranges
     { { int-regs { 0 1 2 3 } } }
     allocate-registers drop
 ] unit-test
@@ -1100,7 +1193,7 @@ USING: math.private compiler.cfg.debugger ;
             { end 109 }
             { uses V{ 103 109 } }
         }
-    }
+    } fake-live-ranges
     { { int-regs { 0 1 2 3 4 } } }
     allocate-registers drop
 ] unit-test
@@ -1193,7 +1286,92 @@ USING: math.private compiler.cfg.debugger ;
             { end 92 }
             { uses V{ 42 45 78 80 92 } }
         }
-    }
+    } fake-live-ranges
     { { int-regs { 0 1 2 3 } } }
     allocate-registers drop
 ] unit-test
+
+! Spill slot liveness was computed incorrectly, leading to a FEP
+! early in bootstrap on x86-32
+[ t ] [
+    T{ basic-block
+       { instructions
+         V{
+             T{ ##gc f V int-regs 6 V int-regs 7 }
+             T{ ##peek f V int-regs 0 D 0 }
+             T{ ##peek f V int-regs 1 D 1 }
+             T{ ##peek f V int-regs 2 D 2 }
+             T{ ##peek f V int-regs 3 D 3 }
+             T{ ##peek f V int-regs 4 D 4 }
+             T{ ##peek f V int-regs 5 D 5 }
+             T{ ##replace f V int-regs 0 D 1 }
+             T{ ##replace f V int-regs 1 D 2 }
+             T{ ##replace f V int-regs 2 D 3 }
+             T{ ##replace f V int-regs 3 D 4 }
+             T{ ##replace f V int-regs 4 D 5 }
+             T{ ##replace f V int-regs 5 D 0 }
+         }
+       }
+    } dup 1array { { int-regs V{ 0 1 2 3 } } } (linear-scan)
+    instructions>> first live-spill-slots>> empty?
+] unit-test
+
+[ f ] [
+    T{ live-range f 0 10 }
+    T{ live-range f 20 30 }
+    intersect-live-range
+] unit-test
+
+[ 10 ] [
+    T{ live-range f 0 10 }
+    T{ live-range f 10 30 }
+    intersect-live-range
+] unit-test
+
+[ 5 ] [
+    T{ live-range f 0 10 }
+    T{ live-range f 5 30 }
+    intersect-live-range
+] unit-test
+
+[ 5 ] [
+    T{ live-range f 5 30 }
+    T{ live-range f 0 10 }
+    intersect-live-range
+] unit-test
+
+[ 5 ] [
+    T{ live-range f 5 10 }
+    T{ live-range f 0 15 }
+    intersect-live-range
+] unit-test
+
+[ 50 ] [
+    {
+        T{ live-range f 0 10 }
+        T{ live-range f 20 30 }
+        T{ live-range f 40 50 }
+    }
+    {
+        T{ live-range f 11 15 }
+        T{ live-range f 31 35 }
+        T{ live-range f 50 55 }
+    }
+    intersect-live-ranges
+] unit-test
+
+[ 5 ] [
+    T{ live-interval
+       { start 0 }
+       { end 10 }
+       { uses { 0 10 } }
+       { ranges V{ T{ live-range f 0 10 } } }
+    }
+    T{ live-interval
+       { start 5 }
+       { end 10 }
+       { uses { 5 10 } }
+       { ranges V{ T{ live-range f 5 10 } } }
+    }
+    intersect-inactive
+] unit-test
\ No newline at end of file
index 1e6b9d02c8ae75d788252c1955bc351aca6859a1..ffa356bfc2687da311abea750f4244f79d399be4 100644 (file)
@@ -25,13 +25,15 @@ IN: compiler.cfg.linear-scan
 ! by Omri Traub, Glenn Holloway, Michael D. Smith
 ! http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.8435
 
-: (linear-scan) ( rpo -- )
-    dup number-instructions
-    dup compute-live-intervals
-    machine-registers allocate-registers assign-registers ;
+: (linear-scan) ( rpo machine-registers -- )
+    [
+        dup number-instructions
+        dup compute-live-intervals
+    ] dip
+    allocate-registers assign-registers ;
 
 : linear-scan ( cfg -- cfg' )
     [
-        dup reverse-post-order (linear-scan)
+        dup reverse-post-order machine-registers (linear-scan)
         spill-counts get >>spill-counts
     ] with-scope ;
index 78ac9428d89b9989214717295c1574565220b8b5..546443b289c62cb86e7a55320e96bfd5b6b6a0da 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces kernel assocs accessors sequences math math.order fry
-compiler.cfg.instructions compiler.cfg.registers
+binary-search compiler.cfg.instructions compiler.cfg.registers
 compiler.cfg.def-use compiler.cfg.liveness compiler.cfg ;
 IN: compiler.cfg.linear-scan.live-intervals
 
@@ -109,6 +109,7 @@ M: ##copy-float compute-live-intervals*
 
 : compute-start/end ( live-interval -- )
     dup ranges>> [ first from>> ] [ last to>> ] bi
+    2dup > [ "BUG: start > end" throw ] when
     [ >>start ] [ >>end ] bi* drop ;
 
 : finish-live-intervals ( live-intervals -- )
index 8ceafd1693ff954ef7ccdcbde03e86e6fd367ff1..9d481ef1d2b1edffe297a372ba27b591954de253 100644 (file)
@@ -11,9 +11,17 @@ compiler.cfg.dce
 compiler.cfg.write-barrier
 compiler.cfg.liveness
 compiler.cfg.rpo
-compiler.cfg.phi-elimination ;
+compiler.cfg.phi-elimination
+compiler.cfg.checker ;
 IN: compiler.cfg.optimizer
 
+SYMBOL: check-optimizer?
+
+: ?check ( cfg -- cfg' )
+    check-optimizer? get [
+        dup check-cfg
+    ] when ;
+
 : optimize-cfg ( cfg -- cfg' )
     [
         compute-predecessors
@@ -27,4 +35,5 @@ IN: compiler.cfg.optimizer
         eliminate-dead-code
         eliminate-write-barriers
         eliminate-phis
+        ?check
     ] with-scope ;
index a3a83b9d14a800dddfda00d56f822074237a1c20..d30a02b0d35ebc39388921ad88a2f791e0a14181 100644 (file)
@@ -1,15 +1,15 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays kernel sequences make compiler.cfg.instructions
-compiler.cfg.rpo cpu.architecture ;
+USING: accessors kernel sequences make compiler.cfg.instructions
+compiler.cfg.local cpu.architecture ;
 IN: compiler.cfg.two-operand
 
 ! On x86, instructions take the form x = x op y
 ! Our SSA IR is x = y op z
 
-! We don't bother with ##add, ##add-imm or ##sub-imm since x86
-! has a LEA instruction which is effectively a three-operand
-! addition
+! We don't bother with ##add, ##add-imm, ##sub-imm or ##mul-imm
+! since x86 has LEA and IMUL instructions which are effectively
+! three-operand addition and multiplication, respectively.
 
 : make-copy ( dst src -- insn ) \ ##copy new-insn ; inline
 
@@ -34,7 +34,6 @@ M: ##not convert-two-operand*
 
 M: ##sub convert-two-operand* convert-two-operand/integer ;
 M: ##mul convert-two-operand* convert-two-operand/integer ;
-M: ##mul-imm convert-two-operand* convert-two-operand/integer ;
 M: ##and convert-two-operand* convert-two-operand/integer ;
 M: ##and-imm convert-two-operand* convert-two-operand/integer ;
 M: ##or convert-two-operand* convert-two-operand/integer ;
@@ -54,9 +53,7 @@ M: insn convert-two-operand* , ;
 
 : convert-two-operand ( cfg -- cfg' )
     two-operand? [
-        dup [
-            [
-                [ [ convert-two-operand* ] each ] V{ } make
-            ] change-instructions drop
-        ] each-basic-block
+        [ drop ]
+        [ [ [ convert-two-operand* ] each ] V{ } make ]
+        local-optimization
     ] when ;
index 7bdaace1db3c37388dc6f6ca12d20a6c9fa54549..7602295284cd98adb33474ff0a71d09e08fdbff7 100755 (executable)
@@ -8,6 +8,7 @@ continuations.private fry cpu.architecture
 source-files.errors
 compiler.errors
 compiler.alien
+compiler.constants
 compiler.cfg
 compiler.cfg.instructions
 compiler.cfg.stack-frame
@@ -94,7 +95,9 @@ M: _dispatch generate-insn
     [ src>> register ] [ temp>> register ] bi %dispatch ;
 
 M: _dispatch-label generate-insn
-    label>> lookup-label %dispatch-label ;
+    label>> lookup-label
+    cell 0 <repetition> %
+    rc-absolute-cell label-fixup ;
 
 : >slot< ( insn -- dst obj slot tag )
     {
index 7527f6b3397e65d8015ca5ece4a650fa09d5df8b..6d0f6f3acefdaf3643709c83cfe9e5e9ca79a555 100644 (file)
@@ -193,7 +193,8 @@ M: optimizing-compiler recompile ( words -- alist )
         ] each
         compile-queue get compile-loop
         compiled get >alist
-    ] with-scope ;
+    ] with-scope
+    "trace-compilation" get [ "--- compile done" print flush ] when ;
 
 : with-optimizer ( quot -- )
     [ optimizing-compiler compiler-impl ] dip with-variable ; inline
index d281b0718a84370cfd64841982ebe68a5551b6c7..65538605465183ca9a96c38967f4203c8defef37 100644 (file)
@@ -3,5 +3,5 @@
 USING: arrays grouping sequences ;
 IN: compression.run-length
 
-: run-length-uncompress8 ( byte-array -- byte-array' )
+: run-length-uncompress ( byte-array -- byte-array' )
     2 group [ first2 <array> ] map concat ;
index 367f0ad1433ac5d100f2d744129726d4b52793e9..271e173718cf9e96a7055291611f2fd505c1fb7d 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: tools.test constructors calendar kernel accessors
-combinators.short-circuit ;
+combinators.short-circuit initializers math ;
 IN: constructors.tests
 
 TUPLE: stock-spread stock spread timestamp ;
@@ -18,4 +18,42 @@ SYMBOL: AAPL
         [ spread>> 1234 = ]
         [ timestamp>> timestamp? ]
     } 1&&
-] unit-test
\ No newline at end of file
+] unit-test
+
+TUPLE: ct1 a ;
+TUPLE: ct2 < ct1 b ;
+TUPLE: ct3 < ct2 c ;
+TUPLE: ct4 < ct3 d ;
+
+CONSTRUCTOR: ct1 ( a -- obj )
+    [ 1 + ] change-a ;
+
+CONSTRUCTOR: ct2 ( a b -- obj )
+    initialize-ct1
+    [ 1 + ] change-a ;
+
+CONSTRUCTOR: ct3 ( a b c -- obj )
+    initialize-ct1
+    [ 1 + ] change-a ;
+
+CONSTRUCTOR: ct4 ( a b c d -- obj )
+    initialize-ct3
+    [ 1 + ] change-a ;
+
+[ 1001 ] [ 1000 <ct1> a>> ] unit-test
+[ 2 ] [ 0 0 <ct2> a>> ] unit-test
+[ 2 ] [ 0 0 0 <ct3> a>> ] unit-test
+[ 3 ] [ 0 0 0 0 <ct4> a>> ] unit-test
+
+
+TUPLE: rofl a b c ;
+CONSTRUCTOR: rofl ( b c a  -- obj ) ;
+
+[ T{ rofl { a 3 } { b 1 } { c 2 } } ] [ 1 2 3 <rofl> ] unit-test
+
+
+TUPLE: default { a integer initial: 0 } ;
+
+CONSTRUCTOR: default ( -- obj ) ;
+
+[ 0 ] [ <default> a>> ] unit-test
index 7a98cd5e0a905baf7f975cec6df1a421825f4400..e6982e3d98aaaf7961f2ff54b1c59dcc319451ea 100644 (file)
@@ -1,23 +1,54 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009 Slava Pestov, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: slots kernel sequences fry accessors parser lexer words
-effects.parser macros ;
+USING: accessors assocs classes.tuple effects.parser fry
+generalizations generic.standard kernel lexer locals macros
+parser sequences slots vocabs words ;
 IN: constructors
 
 ! An experiment
 
-MACRO: set-slots ( slots -- quot )
-    <reversed> [ setter-word '[ swap _ execute ] ] map [ ] join ;
+: initializer-name ( class -- word )
+    name>> "initialize-" prepend ;
 
-: construct ( ... class slots -- instance )
-    [ new ] dip set-slots ; inline
+: lookup-initializer ( class -- word/f )
+    initializer-name "initializers" lookup ;
 
-: define-constructor ( name class effect body -- )
-    [ [ in>> '[ _ _ construct ] ] dip compose ] [ drop ] 2bi
-    define-declared ;
+: initializer-word ( class -- word )
+    initializer-name
+    "initializers" create-vocab create
+    [ t "initializer" set-word-prop ] [ ] bi ;
+
+: define-initializer-generic ( name -- )
+    initializer-word (( object -- object )) define-simple-generic ;
+
+: define-initializer ( class def -- )
+    [ drop define-initializer-generic ]
+    [ [ dup lookup-initializer ] dip H{ } clone define-typecheck ] 2bi ;
+
+MACRO:: slots>constructor ( class slots -- quot )
+    class all-slots [ [ name>> ] [ initial>> ] bi ] { } map>assoc :> params
+    slots length
+    params length
+    '[
+        _ narray slots swap zip 
+        params swap assoc-union
+        values _ firstn class boa
+    ] ;
+
+:: define-constructor ( constructor-word class effect def -- )
+    constructor-word
+    class def define-initializer
+    class effect in>> '[ _ _ slots>constructor ]
+    class lookup-initializer
+    '[ @ _ execute( obj -- obj ) ] effect define-declared ;
+
+: scan-constructor ( -- class word )
+    scan-word [ name>> "<" ">" surround create-in ] keep ;
 
 SYNTAX: CONSTRUCTOR:
-    scan-word [ name>> "<" ">" surround create-in ] keep
+    scan-constructor
     complete-effect
     parse-definition
-    define-constructor ;
\ No newline at end of file
+    define-constructor ;
+
+"initializers" create-vocab drop
index 805ba4fd71e7d75c2f2ee98455c942a489ef1c18..556424f50cf565c70036c22f1ad7875c6c2f62a6 100644 (file)
@@ -55,7 +55,6 @@ HOOK: %jump-label cpu ( label -- )
 HOOK: %return cpu ( -- )
 
 HOOK: %dispatch cpu ( src temp -- )
-HOOK: %dispatch-label cpu ( label -- )
 
 HOOK: %slot cpu ( dst obj slot tag temp -- )
 HOOK: %slot-imm cpu ( dst obj slot tag -- )
index 934b456075eb86b577f90c5da72c18afbc887845..003eccfa18a23cdb36cb5c921f12af65c0ae0a7f 100644 (file)
@@ -3,10 +3,11 @@
 USING: accessors assocs sequences kernel combinators make math
 math.order math.ranges system namespaces locals layouts words
 alien alien.accessors alien.c-types literals cpu.architecture
-cpu.ppc.assembler cpu.ppc.assembler.backend literals compiler.cfg.registers
+cpu.ppc.assembler cpu.ppc.assembler.backend compiler.cfg.registers
 compiler.cfg.instructions compiler.constants compiler.codegen
 compiler.codegen.fixup compiler.cfg.intrinsics
-compiler.cfg.stack-frame compiler.units ;
+compiler.cfg.stack-frame compiler.cfg.build-stack-frame
+compiler.units ;
 FROM: cpu.ppc.assembler => B ;
 IN: cpu.ppc
 
@@ -461,16 +462,18 @@ M:: ppc %write-barrier ( src card# table -- )
     src card# deck-bits SRWI
     table scratch-reg card# STBX ;
 
-M: ppc %gc
+M:: ppc %gc ( temp1 temp2 gc-roots gc-root-count -- )
     "end" define-label
-    12 load-zone-ptr
-    11 12 cell LWZ ! nursery.here -> r11
-    12 12 3 cells LWZ ! nursery.end -> r12
-    11 11 1024 ADDI ! add ALLOT_BUFFER_ZONE to here
-    11 0 12 CMP ! is here >= end?
+    temp2 load-zone-ptr
+    temp1 temp2 cell LWZ
+    temp2 temp2 3 cells LWZ
+    temp1 temp1 1024 ADDI ! add ALLOT_BUFFER_ZONE to here
+    temp1 0 temp2 CMP ! is here >= end?
     "end" get BLE
     %prepare-alien-invoke
-    "minor_gc" f %alien-invoke
+    0 3 LI
+    0 4 LI
+    "inline_gc" f %alien-invoke
     "end" resolve-label ;
 
 M: ppc %prologue ( n -- )
index 203edf956e31297f50922a9b9e2c93d6320ae9e0..a8c54fa65ea06308abbe4015e59e21341f403788 100644 (file)
@@ -64,3 +64,11 @@ IN: cpu.x86.assembler.tests
 [ { HEX: 48 HEX: d3 HEX: e9 } ] [ [ RCX CL SHR ] { } make ] unit-test
 
 [ { HEX: f7 HEX: c1 HEX: d2 HEX: 04 HEX: 00 HEX: 00 } ] [ [ ECX 1234 TEST ] { } make ] unit-test
+
+[ { HEX: 4d HEX: 6b HEX: c0 HEX: 03 } ] [ [ R8 R8 3 IMUL3 ] { } make ] unit-test
+[ { HEX: 49 HEX: 6b HEX: c0 HEX: 03 } ] [ [ RAX R8 3 IMUL3 ] { } make ] unit-test
+[ { HEX: 4c HEX: 6b HEX: c0 HEX: 03 } ] [ [ R8 RAX 3 IMUL3 ] { } make ] unit-test
+[ { HEX: 48 HEX: 6b HEX: c1 HEX: 03 } ] [ [ RAX RCX 3 IMUL3 ] { } make ] unit-test
+[ { HEX: 48 HEX: 69 HEX: c1 HEX: 44 HEX: 03 HEX: 00 HEX: 00 } ] [ [ RAX RCX HEX: 344 IMUL3 ] { } make ] unit-test
+
+[ { 15 183 195 } ] [ [ EAX BX MOVZX ] { } make ] unit-test
index 2b40aa2053f0b55779c64b97056966d397cbc531..95b85ac2ddc205ebf06b038765b96cbcc32550cb 100644 (file)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays io.binary kernel combinators
-kernel.private math namespaces make sequences words system layouts
-math.order accessors cpu.x86.assembler.syntax ;
+USING: arrays io.binary kernel combinators kernel.private math
+namespaces make sequences words system layouts math.order accessors
+cpu.x86.assembler.syntax ;
 IN: cpu.x86.assembler
 
 ! A postfix assembler for x86-32 and x86-64.
@@ -402,20 +402,26 @@ M: operand TEST OCT: 204 2-operand ;
 : SHR ( dst n -- ) BIN: 101 (SHIFT) ;
 : SAR ( dst n -- ) BIN: 111 (SHIFT) ;
 
-GENERIC: IMUL2 ( dst src -- )
-M: immediate IMUL2 swap dup reg-code t HEX: 68 3array immediate-1/4 ;
-M: operand IMUL2 OCT: 257 extended-opcode (2-operand) ;
+: IMUL2 ( dst src -- )
+    OCT: 257 extended-opcode (2-operand) ;
+
+: IMUL3 ( dst src imm -- )
+    dup fits-in-byte? [
+        [ swap HEX: 6a 2-operand ] dip 1,
+    ] [
+        [ swap HEX: 68 2-operand ] dip 4,
+    ] if ;
 
 : MOVSX ( dst src -- )
-    dup register-32? OCT: 143 OCT: 276 extended-opcode ?
-    over register-16? [ BIN: 1 opcode-or ] when
-    swapd
+    swap
+    over register-32? OCT: 143 OCT: 276 extended-opcode ?
+    pick register-16? [ BIN: 1 opcode-or ] when
     (2-operand) ;
 
 : MOVZX ( dst src -- )
+    swap
     OCT: 266 extended-opcode
-    over register-16? [ BIN: 1 opcode-or ] when
-    swapd
+    pick register-16? [ BIN: 1 opcode-or ] when
     (2-operand) ;
 
 ! Conditional move
index ef353281e50e80583034e6be15837e4f0dba652c..15c54aa7d81503ce63b8a33df8e54880c5f798c6 100644 (file)
@@ -91,9 +91,6 @@ M: x86 %return ( -- ) 0 RET ;
 : align-code ( n -- )
     0 <repetition> % ;
 
-M: x86 %dispatch-label ( label -- )
-    0 cell, rc-absolute-cell label-fixup ;
-
 :: (%slot) ( obj slot tag temp -- op )
     temp slot obj [+] LEA
     temp tag neg [+] ; inline
@@ -111,7 +108,7 @@ M: x86 %add-imm [+] LEA ;
 M: x86 %sub     nip SUB ;
 M: x86 %sub-imm neg [+] LEA ;
 M: x86 %mul     nip swap IMUL2 ;
-M: x86 %mul-imm nip IMUL2 ;
+M: x86 %mul-imm IMUL3 ;
 M: x86 %and     nip AND ;
 M: x86 %and-imm nip AND ;
 M: x86 %or      nip OR ;
index c7e9fb985ef2e4b25b780b096fa1f905ab2aa960..c56372f023d19f337a388bd84217541c9465f91f 100644 (file)
@@ -77,6 +77,9 @@ IN: formatting.tests
 [ t ] [ "[####monkey]" "monkey" "[%'#10s]" sprintf = ] unit-test
 [ t ] [ "[many monke]" "many monkeys" "[%10.10s]" sprintf = ] unit-test
 
+[ t ] [ "{ 1, 2, 3 }" { 1 2 3 } "%[%s, %]" sprintf = ] unit-test
+[ t ] [ "{ 1:2, 3:4 }" H{ { 1 2 } { 3 4 } } "%[%s: %s %]" sprintf = ] unit-test
+
 
 [ "%H:%M:%S" strftime ] must-infer
 
@@ -95,3 +98,4 @@ IN: formatting.tests
 [ t ] [ "Thu Oct 09 12:03:15 2008" testtime "%c" strftime = ] unit-test
 [ t ] [ "PM" testtime "%p" strftime = ] unit-test
 
+
index 08cf4b2cd4932bdf8235a904ca34bbac9dd65364..4ead01159ae67e5ea3794323f61516773d058a88 100755 (executable)
@@ -3,7 +3,7 @@
 USING: assocs continuations fry help help.lint.checks
 help.topics io kernel namespaces parser sequences
 source-files.errors vocabs.hierarchy vocabs words classes
-locals tools.errors ;
+locals tools.errors listener ;
 FROM: help.lint.checks => all-vocabs ;
 IN: help.lint
 
index 8bf8d599443b2ee8a144f0c5174958a531019669..4f2ad720b63c337f3b7b446ce968862a753c9830 100755 (executable)
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors alien alien.c-types arrays byte-arrays columns
 combinators compression.run-length endian fry grouping images
-images.loader io io.binary io.encodings.binary io.files kernel
-locals macros math math.bitwise math.functions namespaces
-sequences strings summary ;
+images.loader io io.binary io.encodings.binary io.files
+io.streams.limited kernel locals macros math math.bitwise
+math.functions namespaces sequences specialized-arrays.uint
+specialized-arrays.ushort strings summary io.encodings.8-bit
+io.encodings.string ;
+QUALIFIED-WITH: bitstreams b
 IN: images.bitmap
 
-: assert-sequence= ( a b -- )
-    2dup sequence= [ 2drop ] [ assert ] if ;
-
 : read2 ( -- n ) 2 read le> ;
 : read4 ( -- n ) 4 read le> ;
 : write2 ( n -- ) 2 >le write ;
 : write4 ( n -- ) 4 >le write ;
 
-TUPLE: bitmap-image < image ;
-
-! Used to construct the final bitmap-image
+SINGLETON: bitmap-image
+"bmp" bitmap-image register-image-class
 
 TUPLE: loading-bitmap 
-size reserved offset header-length width
+magic size reserved1 reserved2 offset header-length width
 height planes bit-count compression size-image
-x-pels y-pels color-used color-important color-palette color-index
-uncompressed-bytes ;
+x-pels y-pels color-used color-important
+red-mask green-mask blue-mask alpha-mask
+cs-type end-points
+gamma-red gamma-green gamma-blue
+intent profile-data profile-size reserved3
+color-palette color-index bitfields ;
 
-ERROR: bitmap-magic magic ;
-
-M: bitmap-magic summary
-    drop "First two bytes of bitmap stream must be 'BM'" ;
+! endpoints-triple is ciexyzX/Y/Z, 3x fixed-point-2.30 aka 3x uint
 
 <PRIVATE
 
-: 8bit>buffer ( bitmap -- array )
-    [ color-palette>> 4 <sliced-groups> [ 3 head-slice ] map ]
-    [ color-index>> >array ] bi [ swap nth ] with map concat ;
+: os2-color-lookup ( loading-bitmap -- seq )
+    [ color-index>> >array ]
+    [ color-palette>> 3 <sliced-groups> ] bi
+    '[ _ nth ] map concat ;
+
+: os2v2-color-lookup ( loading-bitmap -- seq )
+    [ color-index>> >array ]
+    [ color-palette>> 3 <sliced-groups> ] bi
+    '[ _ nth ] map concat ;
+
+: v3-color-lookup ( loading-bitmap -- seq )
+    [ color-index>> >array ]
+    [ color-palette>> 4 <sliced-groups> [ 3 head-slice ] map ] bi
+    '[ _ nth ] map concat ;
+
+: color-lookup ( loading-bitmap -- seq )
+    dup header-length>> {
+        { 12 [ os2-color-lookup ] }
+        { 64 [ os2v2-color-lookup ] }
+        { 40 [ v3-color-lookup ] }
+        ! { 108 [ v4-color-lookup ] }
+        ! { 124 [ v5-color-lookup ] }
+    } case ;
 
 ERROR: bmp-not-supported n ;
 
-: reverse-lines ( byte-array width -- byte-array )
-    <sliced-groups> <reversed> concat ; inline
+: uncompress-bitfield ( seq masks -- bytes' )
+    '[
+        _ [
+            [ bitand ] [ bit-count ] [ log2 ] tri - shift
+        ] with map
+    ] { } map-as B{ } concat-as ;
 
-: bitmap>bytes ( loading-bitmap -- array )
+: bitmap>bytes ( loading-bitmap -- byte-array )
     dup bit-count>>
     {
         { 32 [ color-index>> ] }
-        { 24 [ [ color-index>> ] [ width>> 3 * ] bi reverse-lines ] }
-        { 8 [ [ 8bit>buffer ] [ width>> 3 * ] bi reverse-lines ] }
+        { 24 [ color-index>> ] }
+        { 16 [
+            [
+                ! byte-array>ushort-array
+                2 group [ le> ] map
+                ! 5 6 5
+                ! { HEX: f800 HEX: 7e0 HEX: 1f } uncompress-bitfield
+                ! 5 5 5
+                { HEX: 7c00 HEX: 3e0 HEX: 1f } uncompress-bitfield
+            ] change-color-index
+            color-index>>
+        ] }
+        { 8 [ color-lookup ] }
+        { 4 [ [ 4 b:byte-array-n>seq ] change-color-index color-lookup ] }
+        { 1 [ [ 1 b:byte-array-n>seq ] change-color-index color-lookup ] }
         [ bmp-not-supported ]
     } case >byte-array ;
 
+: set-bitfield-widths ( loading-bitmap -- loading-bitmap' )
+    dup bit-count>> {
+        { 16 [ dup color-palette>> 4 group [ le> ] map ] }
+        { 32 [ { HEX: ff0000 HEX: ff00 HEX: ff } ] }
+    } case reverse >>bitfields ;
+
+ERROR: unsupported-bitfield-widths n ;
+
+M: unsupported-bitfield-widths summary
+    drop "Bitmaps only support bitfield compression in 16/32bit images" ;
+
+: uncompress-bitfield-widths ( loading-bitmap -- loading-bitmap' )
+    set-bitfield-widths
+    dup bit-count>> {
+        { 16 [
+            dup bitfields>> '[
+                byte-array>ushort-array _ uncompress-bitfield
+            ] change-color-index
+        ] }
+        { 32 [
+            dup bitfields>> '[
+                byte-array>uint-array _ uncompress-bitfield
+            ] change-color-index
+        ] }
+        [ unsupported-bitfield-widths ]
+    } case ;
+
 ERROR: unsupported-bitmap-compression compression ;
 
 : uncompress-bitmap ( loading-bitmap -- loading-bitmap' )
     dup compression>> {
+        { f [ ] }
         { 0 [ ] }
-        { 1 [ [ run-length-uncompress8 ] change-color-index ] }
-        { 2 [ "run-length encoding 4" unsupported-bitmap-compression ] }
-        { 3 [ "bitfields" unsupported-bitmap-compression ] }
+        { 1 [ [ run-length-uncompress ] change-color-index ] }
+        { 2 [ [ 4 b:byte-array-n>seq run-length-uncompress >byte-array ] change-color-index ] }
+        { 3 [ uncompress-bitfield-widths ] }
         { 4 [ "jpeg" unsupported-bitmap-compression ] }
         { 5 [ "png" unsupported-bitmap-compression ] }
     } case ;
 
+: bitmap-padding ( width -- n )
+    3 * 4 mod 4 swap - 4 mod ; inline
+
 : loading-bitmap>bytes ( loading-bitmap -- byte-array )
-    uncompress-bitmap bitmap>bytes ;
+    uncompress-bitmap
+    bitmap>bytes ;
 
 : parse-file-header ( loading-bitmap -- loading-bitmap )
-    2 read "BM" assert-sequence=
+    2 read latin1 decode >>magic
     read4 >>size
-    read4 >>reserved
+    read2 >>reserved1
+    read2 >>reserved2
     read4 >>offset ;
 
-: parse-bitmap-header ( loading-bitmap -- loading-bitmap )
-    read4 >>header-length
+: read-v3-header ( loading-bitmap -- loading-bitmap )
     read4 >>width
     read4 32 >signed >>height
     read2 >>planes
@@ -84,6 +153,50 @@ ERROR: unsupported-bitmap-compression compression ;
     read4 >>color-used
     read4 >>color-important ;
 
+: read-v4-header ( loading-bitmap -- loading-bitmap )
+    read-v3-header
+    read4 >>red-mask
+    read4 >>green-mask
+    read4 >>blue-mask
+    read4 >>alpha-mask
+    read4 >>cs-type
+    read4 read4 read4 3array >>end-points
+    read4 >>gamma-red
+    read4 >>gamma-green
+    read4 >>gamma-blue ;
+
+: read-v5-header ( loading-bitmap -- loading-bitmap )
+    read-v4-header
+    read4 >>intent
+    read4 >>profile-data
+    read4 >>profile-size
+    read4 >>reserved3 ;
+
+: read-os2-header ( loading-bitmap -- loading-bitmap )
+    read2 >>width
+    read2 16 >signed >>height
+    read2 >>planes
+    read2 >>bit-count ;
+
+: read-os2v2-header ( loading-bitmap -- loading-bitmap )
+    read4 >>width
+    read4 32 >signed >>height
+    read2 >>planes
+    read2 >>bit-count ;
+
+ERROR: unknown-bitmap-header n ;
+
+: parse-bitmap-header ( loading-bitmap -- loading-bitmap )
+    read4 [ >>header-length ] keep
+    {
+        { 12 [ read-os2-header ] }
+        { 64 [ read-os2v2-header ] }
+        { 40 [ read-v3-header ] }
+        { 108 [ read-v4-header ] }
+        { 124 [ read-v5-header ] }
+        [ unknown-bitmap-header ]
+    } case ;
+
 : color-palette-length ( loading-bitmap -- n )
     [ offset>> 14 - ] [ header-length>> ] bi - ;
 
@@ -98,56 +211,54 @@ ERROR: unsupported-bitmap-compression compression ;
 : image-size ( loading-bitmap -- n )
     [ [ width>> ] [ height>> ] bi * ] [ bit-count>> 8 /i ] bi * abs ;
 
-: bitmap-padding ( width -- n )
-    3 * 4 mod 4 swap - 4 mod ; inline
-
-:: fixup-color-index ( loading-bitmap -- loading-bitmap )
-    loading-bitmap width>> :> width
-    width 3 * :> width*3
-    loading-bitmap width>> bitmap-padding :> padding
-    loading-bitmap [ color-index>> length ] [ height>> abs ] bi /i :> stride
-    loading-bitmap
-    padding 0 > [
-        [
-            stride <sliced-groups>
-            [ width*3 head-slice ] map concat
-        ] change-color-index
-    ] when ;
-
 : parse-bitmap ( loading-bitmap -- loading-bitmap )
     dup color-palette-length read >>color-palette
-    dup color-index-length read >>color-index
-    fixup-color-index ;
+    dup size-image>> dup 0 > [
+        read >>color-index
+    ] [
+        drop dup color-index-length read >>color-index
+    ] if ;
+
+ERROR: unsupported-bitmap-file magic ;
 
 : load-bitmap ( path -- loading-bitmap )
-    binary [
+    binary stream-throws <limited-file-reader> [
         loading-bitmap new
-        parse-file-header parse-bitmap-header parse-bitmap
-    ] with-file-reader ;
+        parse-file-header dup magic>> {
+            { "BM" [ parse-bitmap-header parse-bitmap ] }
+            ! { "BA" [ parse-os2-bitmap-array ] }
+            ! { "CI" [ parse-os2-color-icon ] }
+            ! { "CP" [ parse-os2-color-pointer ] }
+            ! { "IC" [ parse-os2-icon ] }
+            ! { "PT" [ parse-os2-pointer ] }
+            [ unsupported-bitmap-file ]
+        } case 
+    ] with-input-stream ;
 
 ERROR: unknown-component-order bitmap ;
 
 : bitmap>component-order ( loading-bitmap -- object )
     bit-count>> {
-        { 32 [ BGRA ] }
+        { 32 [ BGR ] }
         { 24 [ BGR ] }
+        { 16 [ BGR ] }
         { 8 [ BGR ] }
+        { 4 [ BGR ] }
+        { 1 [ BGR ] }
         [ unknown-component-order ]
     } case ;
 
-: loading-bitmap>bitmap-image ( bitmap-image loading-bitmap -- bitmap-image )
+M: bitmap-image load-image* ( path bitmap-image -- bitmap )
+    drop load-bitmap
+    [ image new ] dip
     {
         [ loading-bitmap>bytes >>bitmap ]
         [ [ width>> ] [ height>> abs ] bi 2array >>dim ]
-        [ height>> 0 < [ t >>upside-down? ] when ]
+        [ height>> 0 < not >>upside-down? ]
+        [ compression>> 3 = [ t >>upside-down? ] when ]
         [ bitmap>component-order >>component-order ]
     } cleave ;
 
-M: bitmap-image load-image* ( path loading-bitmap -- bitmap )
-    swap load-bitmap loading-bitmap>bitmap-image ;
-
-"bmp" bitmap-image register-image-class
-
 PRIVATE>
 
 : bitmap>color-index ( bitmap -- byte-array )
@@ -165,6 +276,9 @@ PRIVATE>
         ] if
     ] bi ;
 
+: reverse-lines ( byte-array width -- byte-array )
+    <sliced-groups> <reversed> concat ; inline
+
 : save-bitmap ( image path -- )
     binary [
         B{ CHAR: B CHAR: M } write
index 62c4f7e2ed3cf60c0b481d3186ddf2168764ae76..4c76b85459ec14c62c8187e22419ede4cb292ab4 100755 (executable)
@@ -34,14 +34,7 @@ TUPLE: image dim component-order upside-down? bitmap ;
 
 : has-alpha? ( image -- ? ) component-order>> alpha-channel? ;
 
-GENERIC: load-image* ( path tuple -- image )
-
-: make-image ( bitmap -- image )
-    ! bitmap is a sequence of sequences of pixels which are RGBA
-    <image>
-        over [ first length ] [ length ] bi 2array >>dim
-        RGBA >>component-order
-        swap concat concat B{ } like >>bitmap ;
+GENERIC: load-image* ( path class -- image )
 
 <PRIVATE
 
index 9d44aa1187e69088e9a86e3d41f51856746772c3..2cdc32e9df5bbd71812b441b170c62f9e6dae43f 100755 (executable)
@@ -7,11 +7,13 @@ io.streams.byte-array kernel locals math math.bitwise
 math.constants math.functions math.matrices math.order\r
 math.ranges math.vectors memoize multiline namespaces\r
 sequences sequences.deep images.loader ;\r
+QUALIFIED-WITH: bitstreams bs\r
 IN: images.jpeg\r
 \r
-QUALIFIED-WITH: bitstreams bs\r
+SINGLETON: jpeg-image\r
+{ "jpg" "jpeg" } [ jpeg-image register-image-class ] each\r
 \r
-TUPLE: jpeg-image < image\r
+TUPLE: loading-jpeg < image\r
     { headers }\r
     { bitstream }\r
     { color-info initial: { f f f f } }\r
@@ -21,7 +23,7 @@ TUPLE: jpeg-image < image
 \r
 <PRIVATE\r
 \r
-CONSTRUCTOR: jpeg-image ( headers bitstream -- image ) ;\r
+CONSTRUCTOR: loading-jpeg ( headers bitstream -- image ) ;\r
 \r
 SINGLETONS: SOF DHT DAC RST SOI EOI SOS DQT DNL DRI DHP EXP\r
 APP JPG COM TEM RES ;\r
@@ -63,7 +65,7 @@ TUPLE: jpeg-color-info
 \r
 CONSTRUCTOR: jpeg-color-info ( h v quant-table -- jpeg-color-info ) ;\r
 \r
-: jpeg> ( -- jpeg-image ) jpeg-image get ;\r
+: jpeg> ( -- jpeg-image ) loading-jpeg get ;\r
 \r
 : apply-diff ( dc color -- dc' )\r
     [ diff>> + dup ] [ (>>diff) ] bi ;\r
@@ -291,9 +293,9 @@ PRIVATE>
     binary [\r
         parse-marker { SOI } assert=\r
         parse-headers\r
-        contents <jpeg-image>\r
+        contents <loading-jpeg>\r
     ] with-file-reader\r
-    dup jpeg-image [\r
+    dup loading-jpeg [\r
         baseline-parse\r
         baseline-decompress\r
         jpeg> bitmap>> 3 <groups> [ color-transform ] change-each\r
@@ -302,5 +304,3 @@ PRIVATE>
 \r
 M: jpeg-image load-image* ( path jpeg-image -- bitmap )\r
     drop load-jpeg ;\r
-\r
-{ "jpg" "jpeg" } [ jpeg-image register-image-class ] each\r
index 19f2fd12c8d1ce572494d97140ddd8c8e7454723..51d4e0fadffdb80ff21bb6914c7bc1e6bb393d8c 100644 (file)
@@ -7,16 +7,18 @@ IN: images.loader
 ERROR: unknown-image-extension extension ;
 
 <PRIVATE
+
 SYMBOL: types
 types [ H{ } clone ] initialize
 
 : image-class ( path -- class )
     file-extension >lower types get ?at
     [ unknown-image-extension ] unless ;
+
 PRIVATE>
 
 : register-image-class ( extension class -- )
     swap types get set-at ;
 
 : load-image ( path -- image )
-    dup image-class new load-image* ;
+    dup image-class load-image* ;
index d4b284142f34e2ea9922169280fb4d4f6dbf58d4..fd5e36e2125eac6c2202b2a37d2af893ec582dea 100755 (executable)
@@ -7,12 +7,15 @@ checksums checksums.crc32 compression.inflate grouping byte-arrays
 images.loader ;
 IN: images.png
 
-TUPLE: png-image < image chunks
+SINGLETON: png-image
+"png" png-image register-image-class
+
+TUPLE: loading-png < image chunks
 width height bit-depth color-type compression-method
 filter-method interlace-method uncompressed ;
 
-CONSTRUCTOR: png-image ( -- image )
-V{ } clone >>chunks ;
+CONSTRUCTOR: loading-png ( -- image )
+    V{ } clone >>chunks ;
 
 TUPLE: png-chunk length type data ;
 
@@ -104,9 +107,8 @@ ERROR: unimplemented-color-type image ;
     } case ;
 
 : load-png ( path -- image )
-    [ binary <file-reader> ] [ file-info size>> ] bi
-    stream-throws <limited-stream> [
-        <png-image>
+    binary stream-throws <limited-file-reader> [
+        <loading-png>
         read-png-header
         read-png-chunks
         parse-ihdr-chunk
@@ -116,5 +118,3 @@ ERROR: unimplemented-color-type image ;
 
 M: png-image load-image*
     drop load-png ;
-
-"png" png-image register-image-class
index c98f737b11f73bae1fc14dc0aa372c50a242d5fe..876076e9fea4a4f627c408f22835425ebfe5c7be 100755 (executable)
@@ -9,10 +9,10 @@ strings math.vectors specialized-arrays.float locals
 images.loader ;
 IN: images.tiff
 
-TUPLE: tiff-image < image ;
+SINGLETON: tiff-image
 
-TUPLE: parsed-tiff endianness the-answer ifd-offset ifds ;
-CONSTRUCTOR: parsed-tiff ( -- tiff ) V{ } clone >>ifds ;
+TUPLE: loading-tiff endianness the-answer ifd-offset ifds ;
+CONSTRUCTOR: loading-tiff ( -- tiff ) V{ } clone >>ifds ;
 
 TUPLE: ifd count ifd-entries next
 processed-tags strips bitmap ;
@@ -410,7 +410,7 @@ ERROR: bad-small-ifd-type n ;
         [ nip unhandled-ifd-entry swap ]
     } case ;
 
-: process-ifds ( parsed-tiff -- parsed-tiff )
+: process-ifds ( loading-tiff -- loading-tiff )
     [
         [
             dup ifd-entries>>
@@ -483,18 +483,6 @@ ERROR: unknown-component-order ifd ;
         [ unknown-component-order ]
     } case ;
 
-: normalize-alpha-data ( seq -- byte-array )
-    B{ } like dup
-    byte-array>float-array
-    4 <sliced-groups>
-    [
-        dup fourth dup 0 = [
-            2drop
-        ] [
-            [ 3 head-slice ] dip '[ _ / ] change-each
-        ] if
-    ] each ;
-
 : handle-alpha-data ( ifd -- ifd )
     dup extra-samples find-tag {
         { extra-samples-associated-alpha-data [ ] }
@@ -508,17 +496,17 @@ ERROR: unknown-component-order ifd ;
         [ [ image-width find-tag ] [ image-length find-tag ] bi 2array ]
         [ ifd-component-order f ]
         [ bitmap>> ]
-    } cleave tiff-image boa ;
+    } cleave image boa ;
 
 : tiff>image ( image -- image )
     ifds>> [ ifd>image ] map first ;
 
-: with-tiff-endianness ( parsed-tiff quot -- )
+: with-tiff-endianness ( loading-tiff quot -- )
     [ dup endianness>> ] dip with-endianness ; inline
 
-: load-tiff-ifds ( path -- parsed-tiff )
+: load-tiff-ifds ( path -- loading-tiff )
     binary [
-        <parsed-tiff>
+        <loading-tiff>
         read-header [
             dup ifd-offset>> read-ifds
             process-ifds
@@ -550,10 +538,10 @@ ERROR: unknown-component-order ifd ;
         drop "no planar configuration" throw
     ] if ;
 
-: process-tif-ifds ( parsed-tiff -- )
+: process-tif-ifds ( loading-tiff -- )
     ifds>> [ process-ifd ] each ;
 
-: load-tiff ( path -- parsed-tiff )
+: load-tiff ( path -- loading-tiff )
     [ load-tiff-ifds dup ] keep
     binary [
         [ process-tif-ifds ] with-tiff-endianness
index b1b07a08c07c2c288d658f906c7547b07664d532..fd441e4c4dd8cab4c4fad6c17d592583cc2901b1 100755 (executable)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math io io.encodings destructors accessors
-sequences namespaces byte-vectors fry combinators ;
+USING: accessors byte-vectors combinators destructors fry io
+io.encodings io.files io.files.info kernel math namespaces
+sequences ;
 IN: io.streams.limited
 
 TUPLE: limited-stream stream count limit mode stack ;
@@ -16,6 +17,12 @@ SINGLETONS: stream-throws stream-eofs ;
         swap >>stream
         0 >>count ;
 
+: <limited-file-reader> ( path encoding mode -- stream' )
+    [
+        [ <file-reader> ]
+        [ drop file-info size>> ] 2bi
+    ] dip <limited-stream> ;
+
 GENERIC# limit 2 ( stream limit mode -- stream' )
 
 M: decoder limit ( stream limit mode -- stream' )
index 44b06f94bce2ac1f87c75319d38703e6ad205a53..d269b4ffb5eeb52d93237bde1cc2ce661ffd9618 100644 (file)
@@ -1 +1,3 @@
 Chris Double
+Peter Burns
+Philipp Winkler
index e97d45babe179f928e83cc285dc50a60ea680b9b..14a54b89c0ff3ea2f4934e919894dad7e8d10367 100644 (file)
@@ -19,6 +19,8 @@ IN: json.reader.tests
 { 10.25 } [ "1025e-2" json> ] unit-test
 { 0.125 } [ "0.125" json> ] unit-test
 { -0.125 } [ "-0.125" json> ] unit-test
+{ -0.00125 } [ "-0.125e-2" json> ] unit-test
+{ -012.5 } [ "-0.125e+2" json> ] unit-test
 
 ! not widely supported by javascript, but allowed in the grammar, and a nice
 ! feature to get
@@ -31,6 +33,7 @@ IN: json.reader.tests
 { 8 9 10 12 13 34 47 92 } >string 1array [ <" "\b\t\n\f\r\"\/\\" "> json> ] unit-test
 { HEX: abcd } >string 1array [ <" "\uaBCd" "> json> ] unit-test
 
+{ H{ { "a" { } } { "b" 123 } } } [ "{\"a\":[],\"b\":123}" json> ] unit-test
 { { } } [ "[]" json> ] unit-test 
 { { 1 "two" 3.0 } } [ <" [1, "two", 3.0] "> json> ] unit-test
 { H{ } } [ "{}" json> ] unit-test
index 887a7a50e5672e396aae587b46d55e26c7991831..9886e316d7af2231feaa57f8fadcd6f60c803191 100644 (file)
-! Copyright (C) 2008 Peter Burns.
+! Copyright (C) 2008 Peter Burns, 2009 Philipp Winkler
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel peg peg.ebnf math.parser math.parser.private strings math
-math.functions sequences arrays vectors hashtables assocs
-prettyprint json ;
+USING: arrays assocs combinators io io.streams.string json
+kernel math math.parser math.parser.private prettyprint
+sequences strings vectors ;
 IN: json.reader
 
 <PRIVATE
+: value ( char -- num char )
+    1string " \t\r\n,:}]" read-until
+    [
+        append
+        [ string>float ]
+        [ [ "eE." index ] any? [ >integer ] unless ] bi
+    ] dip ;
 
-: grammar-list>vector ( seq -- vec ) first2 values swap prefix ;
+DEFER: j-string
+    
+: convert-string ( str -- str )
+    read1
+    {
+        { CHAR: b [ 8 ] }
+        { CHAR: f [ 12 ] }
+        { CHAR: n [ CHAR: \n ] }
+        { CHAR: r [ CHAR: \r ] }
+        { CHAR: t [ CHAR: \t ] }
+        { CHAR: u [ 4 read hex> ] }
+        [ ]
+    } case
+    dup
+    [ 1string append j-string append ]
+    [ drop ] if ;
+    
+: j-string ( -- str )
+    "\\\"" read-until CHAR: \" =
+    [ convert-string ] unless ;
+    
+: second-last ( seq -- second-last )
+    [ length 2 - ] keep nth ; inline
 
-! Grammar for JSON from RFC 4627
-EBNF: (json>)
+: third-last ( seq -- third-last )
+    [ length 3 - ] keep nth ; inline
+    
+: last2 ( seq -- second-last last )
+    [ second-last ] [ last ] bi ; inline
 
-ws = (" " | "\r" | "\t" | "\n")*
+: last3 ( seq -- third-last second-last last )
+    [ third-last ] [ last2 ] bi ; inline
 
-true = "true" => [[ t ]]
-false = "false" => [[ f ]]
-null = "null" => [[ json-null ]]
+: v-over-push ( vec -- vec' )
+    dup length 2 >=
+    [
+        dup
+        [ pop ]
+        [ last ] bi push
+    ] when ;
 
-hex = [0-9a-fA-F]
-char = '\\"'  [[ CHAR: "  ]]
-     | "\\\\" [[ CHAR: \  ]]
-     | "\\/"  [[ CHAR: /  ]]
-     | "\\b"  [[ 8        ]]
-     | "\\f"  [[ 12       ]]
-     | "\\n"  [[ CHAR: \n ]]
-     | "\\r"  [[ CHAR: \r ]]
-     | "\\t"  [[ CHAR: \t ]]
-     | "\\u" (hex hex hex hex) [[ hex> ]] => [[ second ]]
-     | [^"\]
-string = '"' char*:cs '"' => [[ cs >string ]]
+: v-pick-push ( vec -- vec' )
+    dup length 3 >=
+    [
+        dup
+        [ pop ]
+        [ second-last ] bi push
+    ] when ;
 
-sign = ("-" | "+")? => [[ "-" = "-" "" ? ]]
-digits = [0-9]+     => [[ >string ]]
-decimal = "." digits  => [[ concat ]]
-exp = ("e" | "E") sign digits => [[ concat ]]
-number = sign digits decimal? exp? => [[ dup concat swap fourth [ string>float ] [ string>number ] if ]]
+: (close-array) ( accum -- accum' )
+    dup last vector? [ v-over-push ] unless
+    dup pop >array over push ;
 
-elements = value ("," value)* => [[ grammar-list>vector ]]
-array = "[" elements?:arr "]" => [[ arr >array ]]
-
-pair = ws string:key ws ":" value:val => [[ { key val } ]]
-members = pair ("," pair)* => [[ grammar-list>vector ]]
-object = "{" members?:hash "}" => [[ hash >hashtable ]]
-
-val = true
-    | false
-    | null
-    | string
-    | number
-    | array
-    | object
-
-value = ws val:v ws => [[ v ]]
-
-;EBNF
+: (close-hash) ( accum -- accum' )
+    dup length 3 >= [ v-over-push ] when
+    dup dup [ pop ] dip pop swap
+    zip H{ } assoc-clone-like over push ;
+                                                 
+: scan ( accum char -- accum )
+    ! 2dup . . ! Great for debug...
+    [
+        {
+            { CHAR: \" [ j-string over push ] }
+            { CHAR: [  [ V{ } clone over push ] }
+            { CHAR: ,  [ v-over-push ] }
+            { CHAR: ]  [ (close-array) ] }
+            { CHAR: {  [ 2 [ V{ } clone over push ] times ] }
+            { CHAR: :  [ v-pick-push ] }
+            { CHAR: }  [ (close-hash) ] }
+            { CHAR: \u000020 [ ] }
+            { CHAR: \t [ ] }
+            { CHAR: \r [ ] }
+            { CHAR: \n [ ] }
+            { CHAR: t  [ 3 read drop t over push ] }
+            { CHAR: f  [ 4 read drop f over push ] }
+            { CHAR: n  [ 3 read drop json-null over push ] }
+            [ value [ over push ] dip [ scan ] when*  ]
+        } case 
+    ] when* ;
 
+: (json-parser>) ( string -- object )
+    [ V{ } clone [ read1 dup ] [ scan ] while drop first ] with-string-reader ;
+    
 PRIVATE>
-
-: json> ( string -- object ) (json>) ;
\ No newline at end of file
+    
+: json> ( string -- object )
+    (json-parser>) ;
\ No newline at end of file
index 0f13b6dd8624064c264d500e0f8b2edd4df0e00d..7470ef9daaf388a7ba0044ba7984e5ab27dabe00 100644 (file)
@@ -13,6 +13,10 @@ ARTICLE: "listener-watch" "Watching variables in the listener"
 "Hiding all visible variables:"
 { $subsection hide-all-vars } ;
 
+HELP: only-use-vocabs
+{ $values { "vocabs" "a sequence of vocabulary specifiers" } }
+{ $description "Replaces the current manifest's vocabulary search path with the given set of vocabularies." } ;
+
 HELP: show-var
 { $values { "var" "a variable name" } }
 { $description "Adds a variable to the watch list; its value will be printed by the listener after every expression." } ;
index 4563f61ab79a146f08bf20a6d5a5dd6bcf0af38e..34d9eac121cb74d3458d816a3e85a4ca493c4359 100644 (file)
@@ -4,7 +4,7 @@ USING: arrays hashtables io kernel math math.parser memory
 namespaces parser lexer sequences strings io.styles
 vectors words generic system combinators continuations debugger
 definitions compiler.units accessors colors prettyprint fry
-sets vocabs.parser source-files.errors locals ;
+sets vocabs.parser source-files.errors locals vocabs vocabs.loader ;
 IN: listener
 
 GENERIC: stream-read-quot ( stream -- quot/f )
@@ -124,6 +124,78 @@ t error-summary? set-global
 
 PRIVATE>
 
+SYMBOL: interactive-vocabs
+
+{
+    "accessors"
+    "arrays"
+    "assocs"
+    "combinators"
+    "compiler"
+    "compiler.errors"
+    "compiler.units"
+    "continuations"
+    "debugger"
+    "definitions"
+    "editors"
+    "help"
+    "help.apropos"
+    "help.lint"
+    "help.vocabs"
+    "inspector"
+    "io"
+    "io.files"
+    "io.pathnames"
+    "kernel"
+    "listener"
+    "math"
+    "math.order"
+    "memory"
+    "namespaces"
+    "parser"
+    "prettyprint"
+    "see"
+    "sequences"
+    "slicing"
+    "sorting"
+    "stack-checker"
+    "strings"
+    "syntax"
+    "tools.annotations"
+    "tools.crossref"
+    "tools.disassembler"
+    "tools.errors"
+    "tools.memory"
+    "tools.profiler"
+    "tools.test"
+    "tools.threads"
+    "tools.time"
+    "vocabs"
+    "vocabs.loader"
+    "vocabs.refresh"
+    "vocabs.hierarchy"
+    "words"
+    "scratchpad"
+} interactive-vocabs set-global
+
+: only-use-vocabs ( vocabs -- )
+    clear-manifest
+    [ vocab ] filter
+    [
+        vocab
+        [ find-vocab-root not ]
+        [ source-loaded?>> +done+ eq? ] bi or
+    ] filter
+    [ use-vocab ] each ;
+
+: with-interactive-vocabs ( quot -- )
+    [
+        <manifest> manifest set
+        "scratchpad" set-current-vocab
+        interactive-vocabs get only-use-vocabs
+        call
+    ] with-scope ; inline
+
 : listener ( -- )
     [ [ { } (listener) ] with-interactive-vocabs ] with-return ;
 
index cd10278760c5b2e466adc7dc5b08c91515082359..a2696b12631e3fd478fa6a5c505fa3097eda38a7 100644 (file)
@@ -3,7 +3,8 @@ kernel math namespaces parser prettyprint prettyprint.config
 prettyprint.sections sequences tools.test vectors words
 effects splitting generic.standard prettyprint.private
 continuations generic compiler.units tools.continuations
-tools.continuations.private eval accessors make vocabs.parser see ;
+tools.continuations.private eval accessors make vocabs.parser see
+listener ;
 IN: prettyprint.tests
 
 [ "4" ] [ 4 unparse ] unit-test
index 46572de47bee63c1777f43d8617463e0401b48cd..270b55fda6a1f59754d8e5fc357e95c8aba9292e 100755 (executable)
@@ -277,8 +277,6 @@ IN: tools.deploy.shaker
                 compiled-generic-crossref
                 compiler-impl
                 compiler.errors:compiler-errors
-                ! definition-observers
-                interactive-vocabs
                 lexer-factory
                 print-use-hook
                 root-cache
index 8d52dcaa2cb50269031cf1ec3fbc4c85f7406f7e..94eb0a865cf563ef5a3092aa60bf3941d4e54922 100644 (file)
@@ -112,68 +112,6 @@ SYMBOL: bootstrap-syntax
         call
     ] with-scope ; inline
 
-SYMBOL: interactive-vocabs
-
-{
-    "accessors"
-    "arrays"
-    "assocs"
-    "combinators"
-    "compiler"
-    "compiler.errors"
-    "compiler.units"
-    "continuations"
-    "debugger"
-    "definitions"
-    "editors"
-    "help"
-    "help.apropos"
-    "help.lint"
-    "help.vocabs"
-    "inspector"
-    "io"
-    "io.files"
-    "io.pathnames"
-    "kernel"
-    "listener"
-    "math"
-    "math.order"
-    "memory"
-    "namespaces"
-    "parser"
-    "prettyprint"
-    "see"
-    "sequences"
-    "slicing"
-    "sorting"
-    "stack-checker"
-    "strings"
-    "syntax"
-    "tools.annotations"
-    "tools.crossref"
-    "tools.disassembler"
-    "tools.errors"
-    "tools.memory"
-    "tools.profiler"
-    "tools.test"
-    "tools.threads"
-    "tools.time"
-    "vocabs"
-    "vocabs.loader"
-    "vocabs.refresh"
-    "vocabs.hierarchy"
-    "words"
-    "scratchpad"
-} interactive-vocabs set-global
-
-: with-interactive-vocabs ( quot -- )
-    [
-        <manifest> manifest set
-        "scratchpad" set-current-vocab
-        interactive-vocabs get only-use-vocabs
-        call
-    ] with-scope ; inline
-
 SYMBOL: print-use-hook
 
 print-use-hook [ [ ] ] initialize
index e54993b6ebc0f628854fe2c1df868b03ac4d0b54..96619a7114e5d3a00e361e37c0fde772122b7337 100644 (file)
@@ -65,7 +65,6 @@ $nl
 "Words for working with the current manifest:"
 { $subsection use-vocab }
 { $subsection unuse-vocab }
-{ $subsection only-use-vocabs }
 { $subsection add-qualified }
 { $subsection add-words-from }
 { $subsection add-words-excluding }
@@ -117,10 +116,6 @@ HELP: unuse-vocab
 { $description "Removes a vocabulary from the current manifest." }
 { $notes "This word is used to implement " { $link POSTPONE: UNUSE: } "." } ;
 
-HELP: only-use-vocabs
-{ $values { "vocabs" "a sequence of vocabulary specifiers" } }
-{ $description "Replaces the current manifest's vocabulary search path with the given set of vocabularies." } ;
-
 HELP: add-qualified
 { $values { "vocab" "a vocabulary specifier" } { "prefix" string } }
 { $description "Adds the vocabulary's words, prefixed with the given string, to the current manifest." }
index ca783c13e6ada1c01aa4c2c9e53ccf6161881f36..0bfb607a52f67c33a95374405b96851684e35ac3 100644 (file)
@@ -52,8 +52,6 @@ M: extra-words equal?
 
 C: <extra-words> extra-words
 
-<PRIVATE
-
 : clear-manifest ( -- )
     manifest get
     [ search-vocab-names>> clear-assoc ]
@@ -61,6 +59,8 @@ C: <extra-words> extra-words
     [ qualified-vocabs>> delete-all ]
     tri ;
 
+<PRIVATE
+
 : (add-qualified) ( qualified -- )
     manifest get qualified-vocabs>> push ;
 
@@ -126,9 +126,6 @@ TUPLE: no-current-vocab ;
         2bi
     ] [ drop ] if ;
 
-: only-use-vocabs ( vocabs -- )
-    clear-manifest [ vocab ] filter [ use-vocab ] each ;
-
 TUPLE: qualified vocab prefix words ;
 
 : <qualified> ( vocab prefix -- qualified )
diff --git a/extra/brainfuck/authors.txt b/extra/brainfuck/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/brainfuck/brainfuck-docs.factor b/extra/brainfuck/brainfuck-docs.factor
new file mode 100644 (file)
index 0000000..c11c05a
--- /dev/null
@@ -0,0 +1,49 @@
+! Copyright (C) 2009 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.syntax help.markup brainfuck strings ;
+
+IN: brainfuck 
+
+HELP: run-brainfuck
+{ $values { "code" string } }
+{ $description
+    "A brainfuck program is a sequence of eight commands that are "
+    "executed sequentially.  An instruction pointer begins at the first "
+    "command, and each command is executed until the program terminates "
+    "when the instruction pointer moves beyond the last command.\n"
+    "\n"
+    "The eight language commands, each consisting of a single character, "
+    "are the following:\n"
+    { $table
+        { "Character" "Meaning" }
+        { ">" "increment the data pointer (to point to the next cell to the right)." }
+        { "<" "decrement the data pointer (to point to the next cell to the left)." }
+        { "+" "increment (increase by one) the byte at the data pointer." }
+        { "-" "decrement (decrease by one) the byte at the data pointer." }
+        { "." "output the value of the byte at the data pointer." }
+        { "," "accept one byte of input, storing its value in the byte at the data pointer." }
+        { "[" "if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching ] command*." }
+        { "]" "if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching [ command*." }
+    }
+    "\n"
+    "Brainfuck programs can be translated into C using the following "
+    "substitutions, assuming ptr is of type unsigned char* and has been "
+    "initialized to point to an array of zeroed bytes:\n"
+    { $table
+        { "Character" "C equivalent" }
+        { ">" "++ptr;" }
+        { "<" "--ptr;" }
+        { "+" "++*ptr;" }
+        { "-" "--*ptr;" }
+        { "." "putchar(*ptr);" }
+        { "," "*ptr=getchar();" }
+        { "[" "while (*ptr) {" }
+        { "]" "}" }
+    }
+} ;
+
+HELP: get-brainfuck
+{ $values { "code" string } { "result" string } }
+{ $description "Returns the output from a brainfuck program as a result string." }  
+{ $see-also run-brainfuck } ;
diff --git a/extra/brainfuck/brainfuck-tests.factor b/extra/brainfuck/brainfuck-tests.factor
new file mode 100644 (file)
index 0000000..2fa6b84
--- /dev/null
@@ -0,0 +1,62 @@
+! Copyright (C) 2009 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: brainfuck kernel io.streams.string math math.parser math.ranges 
+multiline quotations sequences tools.test ;
+
+
+[ "+" run-brainfuck ] must-infer
+[ "+" get-brainfuck ] must-infer
+
+! Hello World!
+
+[ "Hello World!\n" ] [ <" ++++++++++[>+++++++>++++++++++>+++>+<<<<-]
+                          >++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.
+                          ------.--------.>+.>. "> get-brainfuck ] unit-test
+
+! Addition (single-digit)
+
+[ "8" ] [ "35" [ ",>++++++[<-------->-],[<+>-]<." 
+          get-brainfuck ] with-string-reader ] unit-test
+
+! Multiplication (single-digit)
+
+[ "8\0" ] [ "24" [ <" ,>,>++++++++[<------<------>>-]
+                    <<[>[>+>+<<-]>>[<<+>>-]<<<-]
+                    >>>++++++[<++++++++>-],<.>. "> 
+          get-brainfuck ] with-string-reader ] unit-test
+
+! Division (single-digit, integer)
+
+[ "3" ] [ "62" [ <" ,>,>++++++[-<--------<-------->>]
+                    <<[
+                    >[->+>+<<]
+                    >[-<<-
+                    [>]>>>[<[>>>-<<<[-]]>>]<<]
+                    >>>+
+                    <<[-<<+>>]
+                    <<<]
+                    >[-]>>>>[-<<<<<+>>>>>]
+                    <<<<++++++[-<++++++++>]<. ">
+           get-brainfuck ] with-string-reader ] unit-test 
+
+! Uppercase
+
+[ "A" ] [ "a\n" [ ",----------[----------------------.,----------]"
+          get-brainfuck ] with-string-reader ] unit-test 
+
+! cat
+
+[ "ABC" ] [ "ABC\0" [ ",[.,]" get-brainfuck ] with-string-reader ] unit-test
+
+! Squares of numbers from 0 to 100
+
+100 [0,b] [ dup * number>string ] map "\n" join "\n" append 1quotation
+[ <" ++++[>+++++<-]>[<+++++>-]+<+[
+     >[>+>+<<-]++>>[<<+>>-]>>>[-]++>[-]+
+     >>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<]
+     <<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>
+     [-[<->-]+[<<<]]<[>+<-]>]<<-]<<-] ">
+  get-brainfuck ] unit-test
+
+
diff --git a/extra/brainfuck/brainfuck.factor b/extra/brainfuck/brainfuck.factor
new file mode 100644 (file)
index 0000000..f29e7dc
--- /dev/null
@@ -0,0 +1,77 @@
+! Copyright (C) 2009 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors assocs fry io io.streams.string kernel macros math 
+peg.ebnf prettyprint quotations sequences strings ;
+
+IN: brainfuck
+
+<PRIVATE
+
+TUPLE: brainfuck pointer memory ;
+
+: <brainfuck> ( -- brainfuck ) 
+    0 H{ } clone brainfuck boa ;
+
+: get-memory ( brainfuck -- brainfuck value )
+    dup [ pointer>> ] [ memory>> ] bi at 0 or ;
+
+: set-memory ( brainfuck value -- brainfuck )
+    over [ pointer>> ] [ memory>> ] bi set-at ;
+
+: (+) ( brainfuck n -- brainfuck )
+    [ get-memory ] dip + 255 bitand set-memory ;
+
+: (-) ( brainfuck n -- brainfuck )
+    [ get-memory ] dip - 255 bitand set-memory ;
+
+: (?) ( brainfuck -- brainfuck t/f )
+    get-memory 0 = not ;
+
+: (.) ( brainfuck -- brainfuck )
+    get-memory 1string write ;
+
+: (,) ( brainfuck -- brainfuck )
+    read1 set-memory ;
+
+: (>) ( brainfuck n -- brainfuck )
+    [ dup pointer>> ] dip + >>pointer ;
+
+: (<) ( brainfuck n -- brainfuck ) 
+    [ dup pointer>> ] dip - >>pointer ;
+
+: (#) ( brainfuck -- brainfuck ) 
+    dup 
+    [ "ptr=" write pointer>> pprint ] 
+    [ ",mem=" write memory>> pprint nl ] bi ;
+
+: compose-all ( seq -- quot ) 
+    [ ] [ compose ] reduce ;
+
+EBNF: parse-brainfuck
+
+inc-ptr  = (">")+  => [[ length 1quotation [ (>) ] append ]]
+dec-ptr  = ("<")+  => [[ length 1quotation [ (<) ] append ]]
+inc-mem  = ("+")+  => [[ length 1quotation [ (+) ] append ]]
+dec-mem  = ("-")+  => [[ length 1quotation [ (-) ] append ]]
+output   = "."  => [[ [ (.) ] ]]
+input    = ","  => [[ [ (,) ] ]]
+debug    = "#"  => [[ [ (#) ] ]]
+space    = (" "|"\t"|"\r\n"|"\n")+ => [[ [ ] ]] 
+unknown  = (.)  => [[ "Invalid input" throw ]]
+
+ops   = inc-ptr|dec-ptr|inc-mem|dec-mem|output|input|debug|space
+loop  = "[" {loop|ops}+ "]" => [[ second compose-all 1quotation [ [ (?) ] ] prepend [ while ] append ]]
+
+code  = (loop|ops|unknown)*  => [[ compose-all ]]
+
+;EBNF
+
+PRIVATE>
+
+MACRO: run-brainfuck ( code -- )
+    [ <brainfuck> ] swap parse-brainfuck [ drop flush ] 3append ;
+
+: get-brainfuck ( code -- result ) 
+    [ run-brainfuck ] with-string-writer ; inline 
+
diff --git a/extra/brainfuck/summary.txt b/extra/brainfuck/summary.txt
new file mode 100644 (file)
index 0000000..792dbba
--- /dev/null
@@ -0,0 +1 @@
+Brainfuck programming language.
index 6c43e646df97046e0e53673fc535960e1921c1fa..f20e67f9bcb9939f460e772dc8b3c0ad5ff87cbd 100644 (file)
@@ -4,7 +4,8 @@
 USING: accessors arrays assocs combinators help help.crossref
 help.markup help.topics io io.streams.string kernel make namespaces
 parser prettyprint sequences summary help.vocabs
-vocabs vocabs.loader vocabs.hierarchy vocabs.metadata words see ;
+vocabs vocabs.loader vocabs.hierarchy vocabs.metadata words see
+listener ;
 
 IN: fuel.help
 
index 493f09b145df34d6ceacd54f99b51167a3762411..9d9e72a20580480a55a7d84445c218315fce1f2c 100755 (executable)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2009 Kobi Lurie, Doug Coleman.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
-USING: accessors fry images.loader images.normalization\r
+USING: accessors fry images.loader\r
 images.processing.rotation kernel literals math sequences\r
 tools.test images.processing.rotation.private ;\r
 IN: images.processing.rotation.tests\r
@@ -24,13 +24,13 @@ IN: images.processing.rotation.tests
 CONSTANT: pasted-image\r
     $[\r
         "vocab:images/processing/rotation/test-bitmaps/PastedImage.bmp"\r
-        load-image normalize-image clone-image\r
+        load-image clone-image\r
     ]\r
 \r
 CONSTANT: pasted-image90\r
     $[\r
         "vocab:images/processing/rotation/test-bitmaps/PastedImage90.bmp"\r
-        load-image normalize-image clone-image\r
+        load-image clone-image\r
     ]\r
 \r
 CONSTANT: lake-image\r
@@ -55,7 +55,7 @@ CONSTANT: lake-image
     "vocab:images/processing/rotation/test-bitmaps/small.bmp"\r
     load-image 90 rotate \r
     "vocab:images/processing/rotation/test-bitmaps/small-rotated.bmp"\r
-    load-image normalize-image =\r
+    load-image =\r
 ] unit-test\r
     \r
 [ t ] [\r
index 4e841ec95e19e8a319840e1095eee1f9425812b5..f60445c48f96d8b464bae2df41fadbdcf922f328 100644 (file)
@@ -126,7 +126,8 @@ M: chat-server handle-client-disconnect
     ] "" append-outputs-as send-everyone ;
 
 M: chat-server handle-already-logged-in
-    username username-taken-string send-line ;
+    username username-taken-string send-line
+    t client (>>quit?) ;
 
 M: chat-server handle-managed-client*
     readln dup f = [ t client (>>quit?) ] when
index 4d4a4405258e96819427d9aff1e1f52e2ca328ec..6f9bdf25f109007eac438e0afc760e762809d605 100644 (file)
@@ -11,7 +11,7 @@ TUPLE: managed-server < threaded-server clients ;
 
 TUPLE: managed-client
 input-stream output-stream local-address remote-address
-username object quit? ;
+username object quit? logged-in? ;
 
 HOOK: handle-login threaded-server ( -- username )
 HOOK: handle-managed-client* managed-server ( -- )
@@ -62,26 +62,39 @@ PRIVATE>
         local-address get >>local-address
         remote-address get >>remote-address ;
 
-: check-logged-in ( username -- username )
-    dup clients key? [ handle-already-logged-in ] when ;
+: maybe-login-client ( -- )
+    username clients key? [
+        handle-already-logged-in
+    ] [
+        t client (>>logged-in?)
+        client username clients set-at
+    ] if ;
 
-: add-managed-client ( -- )
-    client username check-logged-in clients set-at ;
+: when-logged-in ( quot -- )
+    client logged-in?>> [ call ] [ drop ] if ; inline
 
 : delete-managed-client ( -- )
-    username server clients>> delete-at ;
+    [ username server clients>> delete-at ] when-logged-in ;
 
 : handle-managed-client ( -- )
     handle-login <managed-client> managed-client set
-    add-managed-client handle-client-join
-    [ handle-managed-client* client quit?>> not ] loop ;
+    maybe-login-client [
+        handle-client-join
+        [ handle-managed-client* client quit?>> not ] loop
+    ] when-logged-in ;
+
+: cleanup-client ( -- )
+    [
+        delete-managed-client
+        handle-client-disconnect
+    ] when-logged-in ;
 
 PRIVATE>
 
 M: managed-server handle-client*
     managed-server set
     [ handle-managed-client ]
-    [ delete-managed-client handle-client-disconnect ]
+    [ cleanup-client ]
     [ ] cleanup ;
 
 : new-managed-server ( port name encoding class -- server )
diff --git a/misc/bash/cdfactor.sh b/misc/bash/cdfactor.sh
new file mode 100755 (executable)
index 0000000..cee2d3a
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash 
+
+# change directories to a factor module
+function cdfactor { 
+    code=$(printf "USING: io io.pathnames vocabs vocabs.loader ; "
+           printf "\"%s\" <vocab> vocab-source-path (normalize-path) print" $1)
+    echo $code > $HOME/.cdfactor
+    fn=$(factor $HOME/.cdfactor)
+    dn=$(dirname $fn)
+    echo $dn
+    if [ -z "$dn" ]; then
+        echo "Warning: directory '$1' not found" 1>&2
+    else
+        cd $dn
+    fi
+}
+
+
index b302fb6b8fcd3f79f442c1a1c44e2496f0bb67dc..cc8ebe35fb998af210d8013c10631d880909e56d 100644 (file)
@@ -125,7 +125,8 @@ code in the buffer."
 (defun factor-mode--indent-setter-line ()
   (when (fuel-syntax--at-setter-line)
     (save-excursion
-      (let ((indent (and (fuel-syntax--at-constructor-line) (current-indentation))))
+      (let ((indent (and (fuel-syntax--at-constructor-line)
+                         (current-indentation))))
         (while (not (or indent
                         (bobp)
                         (fuel-syntax--at-begin-of-def)
@@ -225,6 +226,19 @@ code in the buffer."
 (defsubst factor-mode--cycling-setup ()
   (setq factor-mode--cycling-no-ask nil))
 
+(defun factor-mode--code-file (kind &optional file)
+  (let* ((file (or file (buffer-file-name)))
+         (bn (file-name-nondirectory file)))
+    (and (string-match (format "\\(.+\\)-%s\\.factor$" kind) bn)
+         (expand-file-name (concat (match-string 1 bn) ".factor")
+                           (file-name-directory file)))))
+
+(defsubst factor-mode--in-docs (&optional file)
+  (factor-mode--code-file "docs"))
+
+(defsubst factor-mode--in-tests (&optional file)
+  (factor-mode--code-file "tests"))
+
 (defun factor-mode-visit-other-file (&optional skip)
   "Cycle between code, tests and docs factor files.
 With prefix, non-existing files will be skipped."
index 80fe8e830b6e1fe5a793d1db0f50bc58c024dc70..cc788fe5dc5c864e4bd8f51792647e8f9679d1f2 100644 (file)
         (when (looking-at "Word *\\(Stack effect\\|Syntax\\)$")
           (push (list "Word" (match-string-no-properties 1)) rows)
           (forward-line))
-        (while (looking-at "\\(.+?\\)\\( +\\(.+\\)\\)?$")
+        (while (looking-at " ?\\(.+?\\)\\( +\\(.+\\)\\)?$")
           (let ((word `($link ,(match-string-no-properties 1)
                               ,(match-string-no-properties 1)
                               word))
index 0186392f3445736e830dbb8764c1e9df549a52c7..282ef3240f15ae83f5cdcedaec1be22ad2e33dc4 100644 (file)
@@ -172,7 +172,10 @@ interacting with a factor listener is at your disposal.
   (when fuel-mode-autodoc-p (fuel-autodoc-mode fuel-mode))
 
   (setq fuel-stack-mode-string "/S")
-  (when fuel-mode-stack-p (fuel-stack-mode fuel-mode)))
+  (when fuel-mode-stack-p (fuel-stack-mode fuel-mode))
+
+  (when (and fuel-mode (not (file-exists-p (buffer-file-name))))
+    (fuel-scaffold--maybe-insert)))
 
 \f
 ;;; Keys:
index b1c446250397e074ac6d56ba3554b207989dfa1d..9b7d9861c715b4c2c33c418d752db4e726cac7d4 100644 (file)
   (let ((cmd '(:fuel* (vocab-roots get :get) "fuel")))
     (fuel-eval--retort-result (fuel-eval--send/wait cmd))))
 
+(defun fuel-scaffold--dev-name ()
+  (or fuel-scaffold-developer-name
+      (let ((cmd '(:fuel* (developer-name get :get) "fuel")))
+        (fuel-eval--retort-result (fuel-eval--send/wait cmd)))
+      "Your name"))
+
+(defun fuel-scaffold--first-vocab ()
+  (goto-char (point-min))
+  (re-search-forward fuel-syntax--current-vocab-regex nil t))
+
+(defsubst fuel-scaffold--vocab (file)
+  (save-excursion
+    (set-buffer (find-file-noselect file))
+    (fuel-scaffold--first-vocab)
+    (fuel-syntax--current-vocab)))
+
+(defconst fuel-scaffold--tests-header-format
+  "! Copyright (C) %s %s
+! See http://factorcode.org/license.txt for BSD license.
+USING: %s tools.test ;
+IN: %s
+")
+
+(defsubst fuel-scaffold--check-auto (var)
+  (and var (or (eq var 'always) (y-or-n-p "Insert template? "))))
+
+(defun fuel-scaffold--tests (parent)
+  (when (and parent (fuel-scaffold--check-auto fuel-scaffold-test-autoinsert-p))
+    (let ((year (format-time-string "%Y"))
+          (name (fuel-scaffold--dev-name))
+          (vocab (fuel-scaffold--vocab parent)))
+      (insert (format fuel-scaffold--tests-header-format
+                      year name vocab vocab))
+      t)))
+
+(defsubst fuel-scaffold--create-docs (vocab)
+  (let ((cmd `(:fuel* (,vocab ,fuel-scaffold-developer-name fuel-scaffold-help)
+                      "fuel")))
+    (fuel-eval--send/wait cmd)))
+
+(defun fuel-scaffold--help (parent)
+  (when (and parent (fuel-scaffold--check-auto fuel-scaffold-help-autoinsert-p))
+    (let* ((ret (fuel-scaffold--create-docs (fuel-scaffold--vocab parent)))
+           (file (fuel-eval--retort-result ret)))
+      (when file
+        (revert-buffer t t t)
+        (when (and fuel-scaffold-help-header-only-p
+                   (fuel-scaffold--first-vocab))
+          (delete-region (1+ (point)) (point-max))
+          (save-buffer))
+        (message "Inserting template ... done."))
+      (goto-char (point-min)))))
+
+(defun fuel-scaffold--maybe-insert ()
+  (ignore-errors
+    (or (fuel-scaffold--tests (factor-mode--in-tests))
+        (fuel-scaffold--help (factor-mode--in-docs)))))
+
 \f
 ;;; User interface:
 
@@ -73,9 +131,7 @@ You can configure `fuel-scaffold-developer-name' (set by default to
   (interactive "P")
   (let* ((vocab (or (and (not arg) (fuel-syntax--current-vocab))
                     (fuel-completion--read-vocab nil)))
-         (cmd `(:fuel* (,vocab ,fuel-scaffold-developer-name fuel-scaffold-help)
-                       "fuel"))
-         (ret (fuel-eval--send/wait cmd))
+         (ret (fuel-scaffold--create-docs vocab))
          (file (fuel-eval--retort-result ret)))
         (unless file
           (error "Error creating help file" (car (fuel-eval--retort-error ret))))
index a00b21bf2fd6242127a76bca91898c6dd65a003d..1af2e25712f992cfe69516e278c613d19f71f7ae 100644 (file)
         (push (fuel-table--pad-row (reverse frow)) frows)))
     (reverse frows)))
 
+(defvar fuel-table-corner-lt "┌")
+(defvar fuel-table-corner-lb "└")
+(defvar fuel-table-corner-rt "┐")
+(defvar fuel-table-corner-rb "┘")
+(defvar fuel-table-line "─")
+(defvar fuel-table-tee-t "┬")
+(defvar fuel-table-tee-b "┴")
+(defvar fuel-table-tee-l "├")
+(defvar fuel-table-tee-r "┤")
+(defvar fuel-table-crux "┼")
+(defvar fuel-table-sep "│")
+
+(defun fuel-table--insert-line (widths first last sep)
+  (insert first fuel-table-line)
+  (dolist (w widths)
+    (while (> w 0)
+      (insert fuel-table-line)
+      (setq w (1- w)))
+    (insert fuel-table-line sep fuel-table-line))
+  (delete-char -2)
+  (insert fuel-table-line last)
+  (newline))
+
+(defun fuel-table--insert-first-line (widths)
+  (fuel-table--insert-line widths
+                           fuel-table-corner-lt
+                           fuel-table-corner-rt
+                           fuel-table-tee-t))
+
+(defun fuel-table--insert-middle-line (widths)
+  (fuel-table--insert-line widths
+                           fuel-table-tee-l
+                           fuel-table-tee-r
+                           fuel-table-crux))
+
+(defun fuel-table--insert-last-line (widths)
+  (fuel-table--insert-line widths
+                           fuel-table-corner-lb
+                           fuel-table-corner-rb
+                           fuel-table-tee-b))
+
+(defun fuel-table--insert-row (r)
+  (let ((ln (length (car r)))
+        (l 0))
+    (while (< l ln)
+      (insert (concat fuel-table-sep " "
+                      (mapconcat 'identity
+                                 (mapcar `(lambda (x) (nth ,l x)) r)
+                                 (concat " " fuel-table-sep " "))
+                      "  " fuel-table-sep "\n"))
+      (setq l (1+ l)))))
+
 (defun fuel-table--insert (rows)
   (let* ((widths (fuel-table--col-widths rows))
-         (rows (fuel-table--format-rows rows widths))
-         (ls (concat "+" (mapconcat (lambda (n) (make-string n ?-)) widths "-+") "-+")))
-    (insert ls "\n")
+         (rows (fuel-table--format-rows rows widths)))
+    (fuel-table--insert-first-line widths)
     (dolist (r rows)
-      (let ((ln (length (car r)))
-            (l 0))
-        (while (< l ln)
-          (insert (concat "|" (mapconcat 'identity
-                                         (mapcar `(lambda (x) (nth ,l x)) r)
-                                         " |")
-                          " |\n"))
-          (setq l (1+ l))))
-      (insert ls "\n"))))
+      (fuel-table--insert-row r)
+      (fuel-table--insert-middle-line widths))
+    (kill-line -1)
+    (fuel-table--insert-last-line widths)))
 
 \f
 (provide 'fuel-table)