]> gitweb.factorcode.org Git - factor.git/commitdiff
Fix conflict from master
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 27 Apr 2009 22:09:09 +0000 (17:09 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Mon, 27 Apr 2009 22:09:09 +0000 (17:09 -0500)
93 files changed:
Makefile
basis/calendar/calendar-tests.factor
basis/calendar/calendar.factor
basis/checksums/md5/md5.factor
basis/combinators/smart/smart.factor
basis/compiler/tests/alien.factor
basis/compiler/tests/codegen.factor
basis/compiler/tests/curry.factor
basis/compiler/tests/float.factor
basis/compiler/tests/folding.factor
basis/compiler/tests/intrinsics.factor
basis/compiler/tests/optimizer.factor
basis/compiler/tests/peg-regression-2.factor
basis/compiler/tests/peg-regression.factor
basis/compiler/tests/redefine0.factor
basis/compiler/tests/redefine1.factor
basis/compiler/tests/redefine10.factor
basis/compiler/tests/redefine11.factor
basis/compiler/tests/redefine15.factor
basis/compiler/tests/redefine2.factor
basis/compiler/tests/redefine3.factor
basis/compiler/tests/redefine4.factor
basis/compiler/tests/redefine5.factor
basis/compiler/tests/redefine6.factor
basis/compiler/tests/redefine7.factor
basis/compiler/tests/redefine8.factor
basis/compiler/tests/redefine9.factor
basis/compiler/tests/reload.factor
basis/compiler/tests/simple.factor
basis/compiler/tests/spilling.factor
basis/compiler/tests/stack-trace.factor
basis/compiler/tests/tuples.factor
basis/compiler/tree/builder/builder.factor
basis/functors/functors-tests.factor
basis/functors/functors.factor
basis/generalizations/generalizations.factor
basis/inverse/inverse.factor
basis/io/directories/search/search.factor
basis/io/mmap/functor/functor.factor
basis/io/mmap/mmap-docs.factor
basis/io/mmap/mmap-tests.factor
basis/io/mmap/mmap.factor
basis/io/mmap/unix/unix.factor
basis/io/mmap/windows/windows.factor
basis/math/blas/config/config.factor
basis/math/quaternions/quaternions-docs.factor
basis/math/quaternions/quaternions-tests.factor
basis/math/quaternions/quaternions.factor
basis/tuple-arrays/authors.txt
basis/tuple-arrays/summary.txt [deleted file]
basis/tuple-arrays/tags.txt [deleted file]
basis/tuple-arrays/tuple-arrays-docs.factor [deleted file]
basis/tuple-arrays/tuple-arrays-tests.factor
basis/tuple-arrays/tuple-arrays.factor
core/classes/tuple/parser/parser.factor
extra/benchmark/fasta/fasta.factor
extra/benchmark/tuple-arrays/authors.txt [new file with mode: 0644]
extra/benchmark/tuple-arrays/tuple-arrays.factor [new file with mode: 0644]
extra/id3/id3.factor
extra/images/viewer/viewer.factor
extra/mason/notify/notify.factor
extra/mason/report/report.factor
extra/morse/morse-tests.factor
extra/morse/morse.factor
extra/pair-methods/authors.txt [new file with mode: 0644]
extra/pair-methods/pair-methods-tests.factor [new file with mode: 0644]
extra/pair-methods/pair-methods.factor [new file with mode: 0644]
extra/pair-methods/summary.txt [new file with mode: 0644]
extra/pair-rocket/authors.txt [new file with mode: 0644]
extra/pair-rocket/pair-rocket-docs.factor [new file with mode: 0644]
extra/pair-rocket/pair-rocket-tests.factor [new file with mode: 0644]
extra/pair-rocket/pair-rocket.factor [new file with mode: 0644]
extra/pair-rocket/summary.txt [new file with mode: 0644]
extra/qw/authors.txt [new file with mode: 0644]
extra/qw/qw-docs.factor [new file with mode: 0644]
extra/qw/qw-tests.factor [new file with mode: 0644]
extra/qw/qw.factor [new file with mode: 0644]
extra/qw/summary.txt [new file with mode: 0644]
extra/roles/authors.txt [new file with mode: 0644]
extra/roles/roles-docs.factor [new file with mode: 0644]
extra/roles/roles-tests.factor [new file with mode: 0644]
extra/roles/roles.factor [new file with mode: 0644]
extra/roles/summary.txt [new file with mode: 0644]
extra/sequences/product/authors.txt [new file with mode: 0644]
extra/sequences/product/product-docs.factor [new file with mode: 0644]
extra/sequences/product/product-tests.factor
extra/sequences/product/product.factor [new file with mode: 0644]
extra/sequences/product/summary.txt [new file with mode: 0644]
vm/code_gc.c
vm/code_gc.h [changed mode: 0644->0755]
vm/data_gc.c
vm/data_gc.h
vm/data_heap.h

index 9be68fea818497d4b4774a5ac5280f8a4567bd6b..a346bdfa0ab81e2fe3a2c4f0c69c009f2f866e5b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -15,9 +15,11 @@ FFI_TEST_CFLAGS = -fPIC
 ifdef DEBUG
        CFLAGS += -g
 else
-       CFLAGS += -O3 $(SITE_CFLAGS)
+       CFLAGS += -O3
 endif
 
+CFLAGS += $(SITE_CFLAGS)
+
 ENGINE = $(DLL_PREFIX)factor$(DLL_SUFFIX)$(DLL_EXTENSION)
 
 ifdef CONFIG
index 256b4e1b424d1734a6e63baf2b511ae912c4768b..8d1071122d98f5c58bb214097f785a460311a6cf 100644 (file)
@@ -1,5 +1,5 @@
 USING: arrays calendar kernel math sequences tools.test
-continuations system math.order threads ;
+continuations system math.order threads accessors ;
 IN: calendar.tests
 
 [ f ] [ 2004 12 32 0   0  0 instant <timestamp> valid-timestamp? ] unit-test
@@ -163,3 +163,10 @@ IN: calendar.tests
 [ t ] [ now 50 milliseconds sleep now before? ] unit-test
 [ t ] [ now 50 milliseconds sleep now swap after? ] unit-test
 [ t ] [ now 50 milliseconds sleep now 50 milliseconds sleep now swapd between? ] unit-test
+
+[ 4 12 ] [ 2009 easter [ month>> ] [ day>> ] bi ] unit-test
+[ 4 2 ] [ 1961 easter [ month>> ] [ day>> ] bi ] unit-test
+
+[ f ] [ now dup midnight eq? ] unit-test
+[ f ] [ now dup easter eq? ] unit-test
+[ f ] [ now dup beginning-of-year eq? ] unit-test
index 7a03fe44089323f929f406fd4a0e6001fa6ae35d..4b58b1b496b825302690c82dca6bbd9312d9189f 100644 (file)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2007 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays classes.tuple combinators combinators.short-circuit
-    kernel locals math math.functions math.order namespaces sequences strings
-    summary system threads vocabs.loader ;
+USING: accessors arrays classes.tuple combinators
+combinators.short-circuit kernel locals math math.functions
+math.order sequences summary system threads vocabs.loader ;
 IN: calendar
 
 HOOK: gmt-offset os ( -- hours minutes seconds )
@@ -94,26 +94,50 @@ CONSTANT: day-abbreviations3
 :: julian-day-number ( year month day -- n )
     #! Returns a composite date number
     #! Not valid before year -4800
-    [let* | a [ 14 month - 12 /i ]
-            y [ year 4800 + a - ]
-            m [ month 12 a * + 3 - ] |
-        day 153 m * 2 + 5 /i + 365 y * +
-        y 4 /i + y 100 /i - y 400 /i + 32045 -
-    ] ;
+    14 month - 12 /i :> a
+    year 4800 + a - :> y
+    month 12 a * + 3 - :> m
+
+    day 153 m * 2 + 5 /i + 365 y * +
+    y 4 /i + y 100 /i - y 400 /i + 32045 - ;
 
 :: julian-day-number>date ( n -- year month day )
     #! Inverse of julian-day-number
-    [let* | a [ n 32044 + ]
-            b [ 4 a * 3 + 146097 /i ]
-            c [ a 146097 b * 4 /i - ]
-            d [ 4 c * 3 + 1461 /i ]
-            e [ c 1461 d * 4 /i - ]
-            m [ 5 e * 2 + 153 /i ] |
-        100 b * d + 4800 -
-        m 10 /i + m 3 +
-        12 m 10 /i * -
-        e 153 m * 2 + 5 /i - 1+
-    ] ;
+    n 32044 + :> a
+    4 a * 3 + 146097 /i :> b
+    a 146097 b * 4 /i - :> c
+    4 c * 3 + 1461 /i :> d
+    c 1461 d * 4 /i - :> e
+    5 e * 2 + 153 /i :> m
+
+    100 b * d + 4800 -
+    m 10 /i + m 3 +
+    12 m 10 /i * -
+    e 153 m * 2 + 5 /i - 1+ ;
+
+GENERIC: easter ( obj -- obj' )
+
+:: easter-month-day ( year -- month day )
+    year 19 mod :> a
+    year 100 /mod :> c :> b
+    b 4 /mod :> e :> d
+    b 8 + 25 /i :> f
+    b f - 1 + 3 /i :> g
+    19 a * b + d - g - 15 + 30 mod :> h
+    c 4 /mod :> k :> i
+    32 2 e * + 2 i * + h - k - 7 mod :> l
+    a 11 h * + 22 l * + 451 /i :> m
+
+    h l + 7 m * - 114 + 31 /mod 1 + :> day :> month
+    month day ;
+
+M: integer easter ( year -- timestamp )
+    dup easter-month-day <date> ;
+
+M: timestamp easter ( timestamp -- timestamp )
+    clone
+    dup year>> easter-month-day
+    swapd >>day swap >>month ;
 
 : >date< ( timestamp -- year month day )
     [ year>> ] [ month>> ] [ day>> ] tri ;
index 04c6c2497edadb2c52af7162a5c730e59568e372..29620b089d7483e623e4c6db0dcad91e10b90d48 100644 (file)
@@ -14,7 +14,7 @@ IN: checksums.md5
 SYMBOLS: a b c d old-a old-b old-c old-d ;
 
 : T ( N -- Y )
-    sin abs 4294967296 * >integer ; foldable
+    sin abs 32 2^ * >integer ; foldable
 
 : initialize-md5 ( -- )
     0 bytes-read set
index aa7960539cca6f6d66c022b8262911481c0f06d1..9519847810c81d1487ece27d68fcf5d992f7735a 100644 (file)
@@ -18,6 +18,10 @@ MACRO: input<sequence ( quot -- newquot )
     [ infer in>> ] keep
     '[ _ firstn @ ] ;
 
+MACRO: input<sequence-unsafe ( quot -- newquot )
+    [ infer in>> ] keep
+    '[ _ firstn-unsafe @ ] ;
+
 MACRO: reduce-outputs ( quot operation -- newquot )
     [ dup infer out>> 1 [-] ] dip n*quot compose ;
 
index 4d7882ad081307367076c1131428925a4111a0ce..42ed90d64ad0a7d85d1672b774585e6b15b3d5cf 100755 (executable)
@@ -5,7 +5,7 @@ continuations effects namespaces.private io io.streams.string
 memory system threads tools.test math accessors combinators
 specialized-arrays.float alien.libraries io.pathnames
 io.backend ;
-IN: compiler.tests
+IN: compiler.tests.alien
 
 <<
 : libfactor-ffi-tests-path ( -- string )
index 2e02e5476c735b89e45879c46773838f346b1c12..c746fdfb45ba5b06fe915ee888ec4169dbac4658 100644 (file)
@@ -4,7 +4,7 @@ sequences sequences.private tools.test namespaces.private
 slots.private sequences.private byte-arrays alien
 alien.accessors layouts words definitions compiler.units io
 combinators vectors grouping make ;
-IN: compiler.tests
+IN: compiler.tests.codegen
 
 ! Originally, this file did black box testing of templating
 ! optimization. We now have a different codegen, but the tests
@@ -281,4 +281,4 @@ TUPLE: cucumber ;
 
 M: cucumber equal? "The cucumber has no equal" throw ;
 
-[ t ] [ [ cucumber ] compile-call cucumber eq? ] unit-test
\ No newline at end of file
+[ t ] [ [ cucumber ] compile-call cucumber eq? ] unit-test
index 2d1f15b9a80842fdf90d294308385391b61a7f2b..32611ba87a1d36ba1386f76d2ee958552da592a0 100644 (file)
@@ -1,6 +1,6 @@
 USING: tools.test quotations math kernel sequences
 assocs namespaces make compiler.units compiler ;
-IN: compiler.tests
+IN: compiler.tests.curry
 
 [ 3 ] [ 5 [ [ 2 - ] curry call ] compile-call ] unit-test
 [ 3 ] [ [ 5 [ 2 - ] curry call ] compile-call ] unit-test
index b439b5f6a4adfa123c7583fc09540e0e8be4caf3..1a604dbd8ede3ae83e17a3458059eeb9ea6bd5a2 100644 (file)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.float
 USING: compiler.units compiler kernel kernel.private memory math
 math.private tools.test math.floats.private ;
 
index fe2f801de23bfe65b346b9d9416074e3ff5ff5f2..5050ce1950e268af5de88ab5f3fb2fc06c942015 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel classes.mixin arrays ;
-IN: compiler.tests
+IN: compiler.tests.folding
 
 ! Calls to generic words were not folded away.
 
index 93860db92475b13cc32980a61c7db294c34147b9..a6e827ea3372c337cc6d877deb2fdad832fcaa19 100644 (file)
@@ -6,7 +6,7 @@ sbufs strings.private slots.private alien math.order
 alien.accessors alien.c-types alien.syntax alien.strings
 namespaces libc sequences.private io.encodings.ascii
 classes compiler ;
-IN: compiler.tests
+IN: compiler.tests.intrinsics
 
 ! Make sure that intrinsic ops compile to correct code.
 [ ] [ 1 [ drop ] compile-call ] unit-test
index 99bdb188126447ede8a87bc0c9f39d360db79ad1..bd7008f9099a51f80e944a5eb8ea3ccb1f24fdbe 100644 (file)
@@ -5,7 +5,7 @@ quotations classes classes.algebra classes.tuple.private
 continuations growable namespaces hints alien.accessors
 compiler.tree.builder compiler.tree.optimizer sequences.deep
 compiler ;
-IN: optimizer.tests
+IN: compiler.tests.optimizer
 
 GENERIC: xyz ( obj -- obj )
 M: array xyz xyz ;
index 1efadba3aaefbaef2c4f89e998ed7c71d4275398..7929d9e6f6c13b6f211fad969f604d419d725e34 100644 (file)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.peg-regression-2
 USING: peg.ebnf strings tools.test ;
 
 GENERIC: <times> ( times -- term' )
@@ -12,4 +12,4 @@ Regexp = Times:t => [[ t <times> ]]
 
 ;EBNF
 
-[ "foo" ] [ "a" parse-regexp ] unit-test
\ No newline at end of file
+[ "foo" ] [ "a" parse-regexp ] unit-test
index 56a4021eed3e9f995fba9effb38eee1131651a4a..e10713530596f2daed2c236a41049a666ad8f368 100644 (file)
@@ -5,7 +5,7 @@
 ! end of a compilation unit.
 
 USING: kernel accessors peg.ebnf ;
-IN: compiler.tests
+IN: compiler.tests.peg-regression
 
 TUPLE: pipeline-expr background ;
 
index 87b63aa0290134ebcac23a4d6cef5c3a2f4ad3ec..3d7a05a74b8ae274403f5bd29ced99fd9ea5b4c9 100644 (file)
@@ -104,4 +104,4 @@ quot global delete-at
         \ test-11 forget
         \ quot forget
     ] with-compilation-unit
-] unit-test
\ No newline at end of file
+] unit-test
index a28b183fb65fe4f2f77853a50c4742d0b99aa33f..6bb623cac4513f3442fe959c0d5559f84558480a 100644 (file)
@@ -1,7 +1,7 @@
 USING: accessors compiler compiler.units tools.test math parser
 kernel sequences sequences.private classes.mixin generic
 definitions arrays words assocs eval strings ;
-IN: compiler.tests
+IN: compiler.tests.redefine1
 
 GENERIC: method-redefine-generic-1 ( a -- b )
 
@@ -11,7 +11,7 @@ M: integer method-redefine-generic-1 3 + ;
 
 [ 6 ] [ method-redefine-test-1 ] unit-test
 
-[ ] [ "IN: compiler.tests USE: math M: fixnum method-redefine-generic-1 4 + ;" eval( -- ) ] unit-test
+[ ] [ "IN: compiler.tests.redefine1 USE: math M: fixnum method-redefine-generic-1 4 + ;" eval( -- ) ] unit-test
 
 [ 7 ] [ method-redefine-test-1 ] unit-test
 
@@ -27,7 +27,7 @@ M: integer method-redefine-generic-2 3 + ;
 
 [ 6 ] [ method-redefine-test-2 ] unit-test
 
-[ ] [ "IN: compiler.tests USE: kernel USE: math M: fixnum method-redefine-generic-2 4 + ; USE: strings M: string method-redefine-generic-2 drop f ;" eval( -- ) ] unit-test
+[ ] [ "IN: compiler.tests.redefine1 USE: kernel USE: math M: fixnum method-redefine-generic-2 4 + ; USE: strings M: string method-redefine-generic-2 drop f ;" eval( -- ) ] unit-test
 
 [ 7 ] [ method-redefine-test-2 ] unit-test
 
index faae7b8ed1e7c9ba6e9ad5b1b07d40e26dc7860d..66edd7509763e1e3b9e437c388d71c73b67ce275 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel ;
-IN: compiler.tests
+IN: compiler.tests.redefine10
 
 ! Mixin redefinition did not recompile all necessary words.
 
index 57f9f9caf071dd4ac94f1d595577d7b04ff5fc84..dbec57e3d5c9c64b2780e5d040385200bdca77a7 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel classes.mixin arrays ;
-IN: compiler.tests
+IN: compiler.tests.redefine11
 
 ! Mixin redefinition did not recompile all necessary words.
 
index 797460a411cbe798f5cf8ee37347048ec23da587..33aa080bacb4955fa4762323b865f6cb8a6fde8f 100644 (file)
@@ -17,4 +17,4 @@ DEFER: word-1
 
 [ \ word-3 [ [ 2 + ] bi@ ] (( a b -- c d )) define-declared ] with-compilation-unit
 
-[ 2 3 ] [ 0 word-4 ] unit-test
\ No newline at end of file
+[ 2 3 ] [ 0 word-4 ] unit-test
index 6a7b7a6941e78b9e7e5c12d7c1c7ec6207cfa60d..9112a1e1afb439bf6b173e236785a9a19555ae4d 100644 (file)
@@ -1,11 +1,11 @@
-IN: compiler.tests
+IN: compiler.tests.redefine2
 USING: compiler compiler.units tools.test math parser kernel
 sequences sequences.private classes.mixin generic definitions
 arrays words assocs eval words.symbol ;
 
 DEFER: redefine2-test
 
-[ ] [ "USE: sequences USE: kernel IN: compiler.tests TUPLE: redefine2-test ; M: redefine2-test nth 2drop 3 ; INSTANCE: redefine2-test sequence" eval( -- ) ] unit-test
+[ ] [ "USE: sequences USE: kernel IN: compiler.tests.redefine2 TUPLE: redefine2-test ; M: redefine2-test nth 2drop 3 ; INSTANCE: redefine2-test sequence" eval( -- ) ] unit-test
 
 [ t ] [ \ redefine2-test symbol? ] unit-test
 
index 87ab100879b681994e0ebad1ae06ca132480cb08..51ce33c1bd738d9fafd8c48097ca8a6158115dc1 100644 (file)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.redefine3
 USING: accessors compiler compiler.units tools.test math parser
 kernel sequences sequences.private classes.mixin generic
 definitions arrays words assocs eval ;
@@ -18,7 +18,7 @@ M: empty-mixin sheeple drop "wake up" ;
 [ t ] [ object \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
 [ f ] [ empty-mixin \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
 
-[ ] [ "IN: compiler.tests USE: arrays INSTANCE: array empty-mixin" eval( -- ) ] unit-test
+[ ] [ "IN: compiler.tests.redefine3 USE: arrays INSTANCE: array empty-mixin" eval( -- ) ] unit-test
 
 [ "wake up" ] [ sheeple-test ] unit-test
 [ f ] [ object \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
index 88b40f0c5a36a1c44aa9d206ba8523d3beaba3e8..2320f64af60a6da4ddbad5d66cd2795bd803a198 100644 (file)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.redefine4
 USING: io.streams.string kernel tools.test eval ;
 
 : declaration-test-1 ( -- a ) 3 ; flushable
@@ -7,6 +7,6 @@ USING: io.streams.string kernel tools.test eval ;
 
 [ "" ] [ [ declaration-test ] with-string-writer ] unit-test
 
-[ ] [ "IN: compiler.tests USE: io : declaration-test-1 ( -- a ) \"X\" write f ;" eval( -- ) ] unit-test
+[ ] [ "IN: compiler.tests.redefine4 USE: io : declaration-test-1 ( -- a ) \"X\" write f ;" eval( -- ) ] unit-test
 
 [ "X" ] [ [ declaration-test ] with-string-writer ] unit-test
index c390f9a1ecaddfecf4dc7c96ba74b4735183bf88..761398785292012df94f591166f31551f4a989b5 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel ;
-IN: compiler.tests
+IN: compiler.tests.redefine5
 
 ! Regression: if dispatch was eliminated but method was not inlined,
 ! compiled usage information was not recorded.
index 7f1be973e7aab7025f1c6a01aacf3bbde901b4f3..fdf3e7edbbcafcd729562408618e41383ed6c8c6 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel ;
-IN: compiler.tests
+IN: compiler.tests.redefine6
 
 ! Mixin redefinition did not recompile all necessary words.
 
index d6dfdf20fd30d79403fa45bca8aae8fd7b91d998..cfe29603f9cc930f180336e75c82e175432ccce8 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel ;
-IN: compiler.tests
+IN: compiler.tests.redefine7
 
 ! Mixin redefinition did not recompile all necessary words.
 
index 3499c5070a0a97578ae7c03aa176a8a401799796..a79bfb5af5bf46acea9f748aa0f8453ea60666bd 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel ;
-IN: compiler.tests
+IN: compiler.tests.redefine8
 
 ! Mixin redefinition did not recompile all necessary words.
 
index 25ed5f15db2e28e4aaae556916d658ce4ecbcb8d..2598246472e11e1d45489d20b7dd5e0a750a892b 100644 (file)
@@ -1,6 +1,6 @@
 USING: eval tools.test compiler.units vocabs multiline words
 kernel generic.math ;
-IN: compiler.tests
+IN: compiler.tests.redefine9
 
 ! Mixin redefinition did not recompile all necessary words.
 
index b2b65b5868bcaf8350ced989046fe6191c9c4c30..62c7c31bc2bd3975a6750ec2f4209d0659aedcaf 100644 (file)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.reload
 USE: vocabs.loader
 
 ! "parser" reload
index 11b27979d5fd518a8de0a229e19885f6f85f4172..82cc97e0f6a4c115ce4c92cf61b5b8b68cea30de 100644 (file)
@@ -1,7 +1,7 @@
 USING: compiler compiler.units tools.test kernel kernel.private
 sequences.private math.private math combinators strings alien
 arrays memory vocabs parser eval ;
-IN: compiler.tests
+IN: compiler.tests.simple
 
 ! Test empty word
 [ ] [ [ ] compile-call ] unit-test
index 4092352fd5930d154a5f305fe444f522c8e64f2a..2ec6fbde9520e6ebe54b7288875a693e2ad29c80 100644 (file)
@@ -1,6 +1,6 @@
 USING: math.private kernel combinators accessors arrays
 generalizations tools.test ;
-IN: compiler.tests
+IN: compiler.tests.spilling
 
 : float-spill-bug ( a -- b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b )
     {
index b317ed3eb5e5ef6a606625919540b1a9cecf020b..1cb11571ef7fa833712c08c55f4cc96d646b6f52 100755 (executable)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.stack-trace
 USING: compiler tools.test namespaces sequences
 kernel.private kernel math continuations continuations.private
 words splitting grouping sorting accessors ;
index caa214b70cccd1328b42d83ef8279a818c570a3f..fc249d99db30fa1b36b6fa33df68d1954a451928 100644 (file)
@@ -1,4 +1,4 @@
-IN: compiler.tests
+IN: compiler.tests.tuples
 USING: kernel tools.test compiler.units compiler ;
 
 TUPLE: color red green blue ;
index 7f760650e7035b4e5a34ca0b915e286c92c6caab..37cc1f05da8fe83c8b8b2e26b5f16c838a293d6b 100644 (file)
@@ -54,15 +54,16 @@ PRIVATE>
     #! This slows down compiler.tree.propagation.inlining since then every
     #! inlined usage of a method has an inline-dependency on the mixin, and
     #! not the more specific type at the call site.
-    specialize-method? off
-    [
-        #call in-d>> word/quot build-tree-with unclip-last in-d>> :> in-d
-        {
-            { [ dup not ] [ ] }
-            { [ dup ends-with-terminate? ] [ #call out-d>> [ f swap #push ] map append ] }
-            [ in-d #call out-d>> #copy suffix ]
-        } cond
-    ] [ dup inference-error? [ drop f ] [ rethrow ] if ] recover ;
+    f specialize-method? [
+        [
+            #call in-d>> word/quot build-tree-with unclip-last in-d>> :> in-d
+            {
+                { [ dup not ] [ ] }
+                { [ dup ends-with-terminate? ] [ #call out-d>> [ f swap #push ] map append ] }
+                [ in-d #call out-d>> #copy suffix ]
+            } cond
+        ] [ dup inference-error? [ drop f ] [ rethrow ] if ] recover
+    ] with-variable ;
 
 : contains-breakpoints? ( word -- ? )
     def>> [ word? ] filter [ "break?" word-prop ] any? ;
index 37ec1d3e15b3d763787ee4c94c3fe9ef614a834a..b500d9f5ca864c951e5523049d84c549d7fc9f4f 100644 (file)
@@ -63,6 +63,24 @@ WHERE
 
 [ 4 ] [ 1 3 blah ] unit-test
 
+<<
+
+FUNCTOR: symbol-test ( W -- )
+
+W DEFINES ${W}
+
+WHERE
+
+SYMBOL: W
+
+;FUNCTOR
+
+"blorgh" symbol-test
+
+>>
+
+[ blorgh ] [ blorgh ] unit-test
+
 GENERIC: some-generic ( a -- b )
 
 ! Does replacing an ordinary word with a functor-generated one work?
@@ -72,6 +90,7 @@ GENERIC: some-generic ( a -- b )
     TUPLE: some-tuple ;
     : some-word ( -- ) ;
     M: some-tuple some-generic ;
+    SYMBOL: some-symbol
     "> <string-reader> "functors-test" parse-stream
 ] unit-test
 
@@ -82,6 +101,7 @@ GENERIC: some-generic ( a -- b )
         "some-tuple" "functors.tests" lookup
         "some-generic" "functors.tests" lookup method >boolean
     ] unit-test ;
+    [ t ] [ "some-symbol" "functors.tests" lookup >boolean ] unit-test
 
 test-redefinition
 
@@ -90,12 +110,14 @@ FUNCTOR: redefine-test ( W -- )
 W-word DEFINES ${W}-word
 W-tuple DEFINES-CLASS ${W}-tuple
 W-generic IS ${W}-generic
+W-symbol DEFINES ${W}-symbol
 
 WHERE
 
 TUPLE: W-tuple ;
 : W-word ( -- ) ;
 M: W-tuple W-generic ;
+SYMBOL: W-symbol
 
 ;FUNCTOR
 
@@ -105,4 +127,5 @@ M: W-tuple W-generic ;
     "> <string-reader> "functors-test" parse-stream
 ] unit-test
 
-test-redefinition
\ No newline at end of file
+test-redefinition
+
index 309154fb491e3887a5e78b7e8ce64fbfae9f4e3b..ce069ac95335abb2224e15575614e108dd967cb5 100644 (file)
@@ -5,7 +5,7 @@ words interpolate namespaces sequences io.streams.string fry
 classes.mixin effects lexer parser classes.tuple.parser
 effects.parser locals.types locals.parser generic.parser
 locals.rewrite.closures vocabs.parser classes.parser
-arrays accessors ;
+arrays accessors words.symbol ;
 IN: functors
 
 ! This is a hack
@@ -18,6 +18,8 @@ IN: functors
 
 : define-declared* ( word def effect -- ) pick set-word define-declared ;
 
+TUPLE: fake-call-next-method ;
+
 TUPLE: fake-quotation seq ;
 
 GENERIC: >fake-quotations ( quot -- fake )
@@ -29,17 +31,25 @@ M: array >fake-quotations [ >fake-quotations ] { } map-as ;
 
 M: object >fake-quotations ;
 
-GENERIC: fake-quotations> ( fake -- quot )
+GENERIC: (fake-quotations>) ( fake -- )
+
+: fake-quotations> ( fake -- quot )
+    [ (fake-quotations>) ] [ ] make ;
+
+M: fake-quotation (fake-quotations>)
+    [ seq>> [ (fake-quotations>) ] each ] [ ] make , ;
 
-M: fake-quotation fake-quotations>
-    seq>> [ fake-quotations> ] [ ] map-as ;
+M: array (fake-quotations>)
+    [ [ (fake-quotations>) ] each ] { } make , ;
 
-M: array fake-quotations> [ fake-quotations> ] map ;
+M: fake-call-next-method (fake-quotations>)
+    drop method-body get literalize , \ (call-next-method) , ;
 
-M: object fake-quotations> ;
+M: object (fake-quotations>) , ;
 
 : parse-definition* ( accum -- accum )
-    parse-definition >fake-quotations parsed \ fake-quotations> parsed ;
+    parse-definition >fake-quotations parsed
+    [ fake-quotations> first ] over push-all ;
 
 : parse-declared* ( accum -- accum )
     complete-effect
@@ -64,7 +74,7 @@ SYNTAX: `TUPLE:
 SYNTAX: `M:
     scan-param parsed
     scan-param parsed
-    \ create-method-in parsed
+    [ create-method-in dup method-body set ] over push-all
     parse-definition*
     \ define* parsed ;
 
@@ -80,6 +90,10 @@ SYNTAX: `:
     parse-declared*
     \ define-declared* parsed ;
 
+SYNTAX: `SYMBOL:
+    scan-param parsed
+    \ define-symbol parsed ;
+
 SYNTAX: `SYNTAX:
     scan-param parsed
     parse-definition*
@@ -92,6 +106,8 @@ SYNTAX: `INSTANCE:
 
 SYNTAX: `inline [ word make-inline ] over push-all ;
 
+SYNTAX: `call-next-method T{ fake-call-next-method } parsed ;
+
 : (INTERPOLATE) ( accum quot -- accum )
     [ scan interpolate-locals ] dip
     '[ _ with-string-writer @ ] parsed ;
@@ -116,7 +132,9 @@ DEFER: ;FUNCTOR delimiter
         { ":" POSTPONE: `: }
         { "INSTANCE:" POSTPONE: `INSTANCE: }
         { "SYNTAX:" POSTPONE: `SYNTAX: }
+        { "SYMBOL:" POSTPONE: `SYMBOL: }
         { "inline" POSTPONE: `inline }
+        { "call-next-method" POSTPONE: `call-next-method }
     } ;
 
 : push-functor-words ( -- )
index edee44acc67c96511e3eddde255c1a431145f4e6..139b7a528add97756ddd2848585b57fc7368e7fc 100644 (file)
@@ -26,11 +26,14 @@ MACRO: narray ( n -- )
 MACRO: nsum ( n -- )
     1- [ + ] n*quot ;
 
+MACRO: firstn-unsafe ( n -- )
+    [ '[ [ _ ] dip nth-unsafe ] ] map '[ _ cleave ] ;
+
 MACRO: firstn ( n -- )
     dup zero? [ drop [ drop ] ] [
-        [ [ '[ [ _ ] dip nth-unsafe ] ] map ]
-        [ 1- '[ [ _ ] dip bounds-check 2drop ] ]
-        bi prefix '[ _ cleave ]
+        [ 1- swap bounds-check 2drop ]
+        [ firstn-unsafe ]
+        bi-curry '[ _ _ bi ]
     ] if ;
 
 MACRO: npick ( n -- )
index a9880632934e47a2b027bdd54a2b7c4d887a8a73..0b86b02e9206526e6d7b4b76c67556362caeecbc 100755 (executable)
@@ -12,7 +12,7 @@ IN: inverse
 ERROR: fail ;
 M: fail summary drop "Matching failed" ;
 
-: assure ( ? -- ) [ fail ] unless ;
+: assure ( ? -- ) [ fail ] unless ; inline
 
 : =/fail ( obj1 obj2 -- ) = assure ;
 
index 2202f7aa086e5f8bc0a02cd7e17e2e5174c4de9a..f7d18306f8a1cff9bd106da87dd48a29425ea299 100755 (executable)
@@ -39,55 +39,55 @@ TUPLE: directory-iterator path bfs queue ;
         dup directory?
         [ name>> over push-directory-entries next-directory-entry ]
         [ nip ] if
-    ] if ; recursive
+    ] if ;
 
-:: iterate-directory-entries ( iter quot -- directory-entry/f )
+:: iterate-directory-entries ( iter quot: ( obj -- obj ) -- directory-entry/f )
     iter next-directory-entry [
-        quot call( obj -- obj )
+        quot call
         [ iter quot iterate-directory-entries ] unless*
     ] [
         f
     ] if* ; inline recursive
 
 : iterate-directory ( iter quot -- path/f )
-    [ name>> ] prepose iterate-directory-entries ;
+    [ name>> ] prepose iterate-directory-entries ; inline
 
 : setup-traversal ( path bfs quot -- iterator quot' )
-    [ <directory-iterator> ] dip [ f ] compose ;
+    [ <directory-iterator> ] dip [ f ] compose ; inline
 
 PRIVATE>
 
 : each-file ( path bfs? quot -- )
-    setup-traversal iterate-directory drop ;
+    setup-traversal iterate-directory drop ; inline
 
 : each-directory-entry ( path bfs? quot -- )
-    setup-traversal iterate-directory-entries drop ;
+    setup-traversal iterate-directory-entries drop ; inline
 
 : recursive-directory-files ( path bfs? -- paths )
-    [ ] accumulator [ each-file ] dip ;
+    [ ] accumulator [ each-file ] dip ; inline
 
-: recursive-directory-entries ( path bfs? -- paths )
-    [ ] accumulator [ each-directory-entry ] dip ;
+: recursive-directory-entries ( path bfs? -- directory-entries )
+    [ ] accumulator [ each-directory-entry ] dip ; inline
 
 : find-file ( path bfs? quot -- path/f )
     [ <directory-iterator> ] dip
-    [ keep and ] curry iterate-directory ;
+    [ keep and ] curry iterate-directory ; inline
 
 : find-all-files ( path quot -- paths/f )
     [ f <directory-iterator> ] dip pusher
-    [ [ f ] compose iterate-directory drop ] dip ;
+    [ [ f ] compose iterate-directory drop ] dip ; inline
 
 ERROR: file-not-found path bfs? quot ;
 
 : find-file-throws ( path bfs? quot -- path )
-    3dup find-file dup [ 2nip nip ] [ drop file-not-found ] if ;
+    3dup find-file dup [ 2nip nip ] [ drop file-not-found ] if ; inline
 
 : find-in-directories ( directories bfs? quot -- path'/f )
     '[ _ [ _ _ find-file-throws ] attempt-all ]
-    [ drop f ] recover ;
+    [ drop f ] recover ; inline
 
 : find-all-in-directories ( directories quot -- paths/f )
-    '[ _ find-all-files ] map concat ;
+    '[ _ find-all-files ] map concat ; inline
 
 : link-size/0 ( path -- n )
     [ link-info size-on-disk>> ] [ 2drop 0 ] recover ;
index 21b3d294c99265d95820f050bd1046e916c874cc..a80ce3bc82b1705fdc2d871214a8b26934b4b39c 100644 (file)
@@ -9,13 +9,14 @@ SLOT: length
 
 : mapped-file>direct ( mapped-file type -- alien length )
     [ [ address>> ] [ length>> ] bi ] dip
-    heap-size [ 1- + ] keep /i ;
+    heap-size [ 1 - + ] keep /i ;
 
 FUNCTOR: define-mapped-array ( T -- )
 
-<mapped-A>         DEFINES <mapped-${T}-array>
-<A>                IS      <direct-${T}-array>
-with-mapped-A-file DEFINES with-mapped-${T}-file
+<mapped-A>                DEFINES <mapped-${T}-array>
+<A>                       IS      <direct-${T}-array>
+with-mapped-A-file        DEFINES with-mapped-${T}-file
+with-mapped-A-file-reader DEFINES with-mapped-${T}-file-reader
 
 WHERE
 
@@ -25,4 +26,7 @@ WHERE
 : with-mapped-A-file ( path quot -- )
     '[ <mapped-A> @ ] with-mapped-file ; inline
 
+: with-mapped-A-file-reader ( path quot -- )
+    '[ <mapped-A> @ ] with-mapped-file-reader ; inline
+
 ;FUNCTOR
index f0adb4732112bab5957f19e7e22b7205cafb40fc..1da82e42e222f8c3781250bc01af7128aecd731b 100644 (file)
@@ -18,7 +18,13 @@ HELP: <mapped-file>
 
 HELP: with-mapped-file
 { $values { "path" "a pathname string" } { "quot" { $quotation "( mmap -- )" } } }
-{ $contract "Opens a file and maps its contents into memory, passing the " { $link mapped-file } " instance to the quotation. The mapped file is disposed of when the quotation returns, or if an error is thrown." }
+{ $contract "Opens a file for read/write access and maps its contents into memory, passing the " { $link mapped-file } " instance to the quotation. The mapped file is disposed of when the quotation returns, or if an error is thrown." }
+{ $notes "This is a low-level word, because " { $link mapped-file } " objects simply expose their base address and length. Most applications should use " { $link "io.mmap.arrays" } " instead." }
+{ $errors "Throws an error if a memory mapping could not be established." } ;
+
+HELP: with-mapped-file-reader
+{ $values { "path" "a pathname string" } { "quot" { $quotation "( mmap -- )" } } }
+{ $contract "Opens a file for read-only access and maps its contents into memory, passing the " { $link mapped-file } " instance to the quotation. The mapped file is disposed of when the quotation returns, or if an error is thrown." }
 { $notes "This is a low-level word, because " { $link mapped-file } " objects simply expose their base address and length. Most applications should use " { $link "io.mmap.arrays" } " instead." }
 { $errors "Throws an error if a memory mapping could not be established." } ;
 
index a4d55f3c1e040380c4b6ac1161ae3b3676585f24..0e1cd1a03691904e6c758e68f68d153a915112ae 100644 (file)
@@ -7,6 +7,7 @@ IN: io.mmap.tests
 [ ] [ "12345" "mmap-test-file.txt" temp-file ascii set-file-contents ] unit-test
 [ ] [ "mmap-test-file.txt" temp-file [ CHAR: 2 0 pick set-nth drop ] with-mapped-char-file ] unit-test
 [ 5 ] [ "mmap-test-file.txt" temp-file [ length ] with-mapped-char-file ] unit-test
+[ 5 ] [ "mmap-test-file.txt" temp-file [ length ] with-mapped-char-file-reader ] unit-test
 [ "22345" ] [ "mmap-test-file.txt" temp-file ascii file-contents ] unit-test
 [ "mmap-test-file.txt" temp-file delete-file ] ignore-errors
 
index 1a584715144b470606f5e1a48a63c39f7fd767be..e03d5fb30b8c3f2954c08b0b9139b91d4f99762d 100644 (file)
@@ -8,14 +8,27 @@ IN: io.mmap
 
 TUPLE: mapped-file address handle length disposed ;
 
-HOOK: (mapped-file) os ( path length -- address handle )
+HOOK: (mapped-file-reader) os ( path length -- address handle )
+HOOK: (mapped-file-r/w) os ( path length -- address handle )
 
 ERROR: bad-mmap-size path size ;
 
-: <mapped-file> ( path -- mmap )
+<PRIVATE
+
+: prepare-mapped-file ( path -- path' n )
     [ normalize-path ] [ file-info size>> ] bi
-    dup 0 <= [ bad-mmap-size ] when
-    [ (mapped-file) ] keep
+    dup 0 <= [ bad-mmap-size ] when ;
+
+PRIVATE>
+
+: <mapped-file-reader> ( path -- mmap )
+    prepare-mapped-file
+    [ (mapped-file-reader) ] keep
+    f mapped-file boa ;
+
+: <mapped-file> ( path -- mmap )
+    prepare-mapped-file
+    [ (mapped-file-r/w) ] keep
     f mapped-file boa ;
 
 HOOK: close-mapped-file io-backend ( mmap -- )
@@ -25,6 +38,9 @@ M: mapped-file dispose* ( mmap -- ) close-mapped-file ;
 : with-mapped-file ( path quot -- )
     [ <mapped-file> ] dip with-disposal ; inline
 
+: with-mapped-file-reader ( path quot -- )
+    [ <mapped-file-reader> ] dip with-disposal ; inline
+
 {
     { [ os unix? ] [ "io.mmap.unix" require ] }
     { [ os winnt? ] [ "io.mmap.windows" require ] }
index 0fa8e1151f2c9e850578160ab34df811c3174008..7d12d52361c3284aca17d9aabf6395f320f76bac 100644 (file)
@@ -4,21 +4,23 @@ USING: alien io io.files kernel math math.bitwise system unix
 io.backend.unix io.ports io.mmap destructors locals accessors ;
 IN: io.mmap.unix
 
-: open-r/w ( path -- fd ) O_RDWR file-mode open-file ;
-
-:: mmap-open ( path length prot flags -- alien fd )
+:: mmap-open ( path length prot flags open-mode -- alien fd )
     [
         f length prot flags
-        path open-r/w [ <fd> |dispose drop ] keep
+        path open-mode file-mode open-file [ <fd> |dispose drop ] keep
         [ 0 mmap dup MAP_FAILED = [ (io-error) ] when ] keep
     ] with-destructors ;
 
-M: unix (mapped-file)
+M: unix (mapped-file-r/w)
     { PROT_READ PROT_WRITE } flags
     { MAP_FILE MAP_SHARED } flags
-    mmap-open ;
+    O_RDWR mmap-open ;
+
+M: unix (mapped-file-reader)
+    { PROT_READ } flags
+    { MAP_FILE MAP_SHARED } flags
+    O_RDONLY mmap-open ;
 
 M: unix close-mapped-file ( mmap -- )
     [ [ address>> ] [ length>> ] bi munmap io-error ]
-    [ handle>> close-file ]
-    bi ;
+    [ handle>> close-file ] bi ;
index fcdf4165115d779b392e04df24ee8475473c3c94..ebd8109d14e8c82b90b7f687af385e8a81133551 100644 (file)
@@ -28,7 +28,7 @@ M: win32-mapped-file dispose
 
 C: <win32-mapped-file> win32-mapped-file
 
-M: windows (mapped-file)
+M: windows (mapped-file-r/w)
     [
         { GENERIC_WRITE GENERIC_READ } flags
         OPEN_ALWAYS
@@ -37,6 +37,15 @@ M: windows (mapped-file)
         -rot <win32-mapped-file>
     ] with-destructors ;
 
+M: windows (mapped-file-reader)
+    [
+        GENERIC_READ
+        OPEN_ALWAYS
+        { PAGE_READONLY SEC_COMMIT } flags
+        FILE_MAP_READ mmap-open
+        -rot <win32-mapped-file>
+    ] with-destructors ;
+
 M: windows close-mapped-file ( mapped-file -- )
     [
         [ handle>> &dispose drop ]
index 327c546963ffb1dd290646304b1fa7a2eb9cb161..09f736c0367841dfed157d48f034bd6e63f72a7d 100644 (file)
@@ -18,7 +18,7 @@ blas-fortran-abi [
         { [ os netbsd?  cpu x86.64? and ] [ g95-abi        ] }
         { [ os windows? cpu x86.64? and ] [ gfortran-abi   ] }
         { [ os freebsd?                 ] [ gfortran-abi   ] }
-        { [ os linux?   cpu x86.32? and ] [ gfortran-abi   ] }
+        { [ os linux?                   ] [ gfortran-abi   ] }
         [ f2c-abi ]
     } cond
 ] initialize
index bb34ec8da2dc5ae9598ca28251151f5bae2b3daf..a24011cb7c6c275d543719a8b72c96f5b7b723dd 100644 (file)
@@ -1,6 +1,16 @@
 USING: help.markup help.syntax math math.vectors vectors ;
 IN: math.quaternions
 
+HELP: q+
+{ $values { "u" "a quaternion" } { "v" "a quaternion" } { "u+v" "a quaternion" } }
+{ $description "Add quaternions." }
+{ $examples { $example "USING: math.quaternions prettyprint ;" "{ C{ 0 1 } 0 } { 0 1 } q+ ." "{ C{ 0 1 } 1 }" } } ;
+
+HELP: q-
+{ $values { "u" "a quaternion" } { "v" "a quaternion" } { "u-v" "a quaternion" } }
+{ $description "Subtract quaternions." }
+{ $examples { $example "USING: math.quaternions prettyprint ;" "{ C{ 0 1 } 0 } { 0 1 } q- ." "{ C{ 0 1 } -1 }" } } ;
+
 HELP: q*
 { $values { "u" "a quaternion" } { "v" "a quaternion" } { "u*v" "a quaternion" } }
 { $description "Multiply quaternions." }
index a6d255e421f47ba5a0e9c73f05930cb6b3ec4d99..3efc417e420be84827d8caef6ecd3e839dd6ebe6 100644 (file)
@@ -24,3 +24,7 @@ math.constants ;
 [ t ] [ qk q>v v>q qk = ] unit-test
 [ t ] [ 1 c>q q1 = ] unit-test
 [ t ] [ C{ 0 1 } c>q qi = ] unit-test
+[ t ] [ qi qi q+ qi 2 q*n = ] unit-test
+[ t ] [ qi qi q- q0 = ] unit-test
+[ t ] [ qi qj q+ qj qi q+ = ] unit-test
+[ t ] [ qi qj q- qj qi q- -1 q*n = ] unit-test
index f2c2c6d226051727e007403d6e002deb1fa30037..b713f44ebdbbf528a04aa79243befa7bc3a0bbde 100755 (executable)
@@ -20,6 +20,12 @@ IN: math.quaternions
 
 PRIVATE>
 
+: q+ ( u v -- u+v )
+    v+ ;
+
+: q- ( u v -- u-v )
+    v- ;
+
 : q* ( u v -- u*v )
     [ q*a ] [ q*b ] 2bi 2array ;
 
index f990dd0ed29ff1ada6887e18c53cbca2d40a2481..d4f5d6b3aeb70f66356d80c70755fbb63ef584df 100644 (file)
@@ -1 +1 @@
-Daniel Ehrenberg
+Slava Pestov
\ No newline at end of file
diff --git a/basis/tuple-arrays/summary.txt b/basis/tuple-arrays/summary.txt
deleted file mode 100644 (file)
index ac05ae9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Packed homogeneous tuple arrays
diff --git a/basis/tuple-arrays/tags.txt b/basis/tuple-arrays/tags.txt
deleted file mode 100644 (file)
index 42d711b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-collections
diff --git a/basis/tuple-arrays/tuple-arrays-docs.factor b/basis/tuple-arrays/tuple-arrays-docs.factor
deleted file mode 100644 (file)
index 18f5547..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-USING: help.syntax help.markup splitting kernel sequences ;
-IN: tuple-arrays
-
-HELP: tuple-array
-{ $description "The class of packed homogeneous tuple arrays. They are created with " { $link <tuple-array> } ". All elements are of the same tuple class. Mutations done to an element are not copied back to the packed array unless it is explicitly written back. To convert a sequence to a tuple array, use the word " { $link >tuple-array } "." } ;
-
-HELP: <tuple-array>
-{ $values { "class" "a tuple class" } { "length" "a non-negative integer" } { "tuple-array" tuple-array } }
-{ $description "Creates an instance of the " { $link <tuple-array> } " class with the given length and containing the given tuple class." } ;
-
-HELP: >tuple-array
-{ $values { "seq" sequence } { "tuple-array" tuple-array } }
-{ $description "Converts a sequence into a homogeneous unboxed tuple array of the type indicated by the first element." } ;
index 7aa49b880fe4239059b0f515b502c2fe4e4a6135..2eeae20aa1d2b0cf1b57c7cea7350a52acc4efb7 100644 (file)
@@ -5,17 +5,28 @@ IN: tuple-arrays.tests
 SYMBOL: mat
 TUPLE: foo bar ;
 C: <foo> foo
-[ 2 ] [ 2 foo <tuple-array> dup mat set length ] unit-test
+TUPLE-ARRAY: foo
+
+[ 2 ] [ 2 <foo-array> dup mat set length ] unit-test
 [ T{ foo } ] [ mat get first ] unit-test
 [ T{ foo f 2 } ] [ T{ foo f 2 } 0 mat get [ set-nth ] keep first ] unit-test
-[ t ] [ { T{ foo f 1 } T{ foo f 2 } } >tuple-array dup mat set tuple-array? ] unit-test
+[ t ] [ { T{ foo f 1 } T{ foo f 2 } } >foo-array dup mat set foo-array? ] unit-test
 [ T{ foo f 3 } t ] 
-[ mat get [ bar>> 2 + <foo> ] map [ first ] keep tuple-array? ] unit-test
+[ mat get [ bar>> 2 + <foo> ] map [ first ] keep foo-array? ] unit-test
 
-[ 2 ] [ 2 foo <tuple-array> dup mat set length ] unit-test
+[ 2 ] [ 2 <foo-array> dup mat set length ] unit-test
 [ T{ foo } ] [ mat get first ] unit-test
 [ T{ foo f 1 } ] [ T{ foo f 1 } 0 mat get [ set-nth ] keep first ] unit-test
 
 TUPLE: baz { bing integer } bong ;
-[ 0 ] [ 1 baz <tuple-array> first bing>> ] unit-test
-[ f ] [ 1 baz <tuple-array> first bong>> ] unit-test
+TUPLE-ARRAY: baz
+
+[ 0 ] [ 1 <baz-array> first bing>> ] unit-test
+[ f ] [ 1 <baz-array> first bong>> ] unit-test
+
+TUPLE: broken x ;
+: broken ( -- ) ;
+
+TUPLE-ARRAY: broken
+
+[ 100 ] [ 100 <broken-array> length ] unit-test
\ No newline at end of file
index af62c0b0d714389320e798cba4f7c269380863d4..35d771416c468473b3301d9497b0e07c455ff8f6 100644 (file)
@@ -1,34 +1,73 @@
-! Copyright (C) 2007 Daniel Ehrenberg.
+! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: splitting grouping classes.tuple classes math kernel
-sequences arrays accessors ;
+USING: accessors arrays combinators.smart fry functors kernel
+kernel.private macros sequences combinators sequences.private
+stack-checker parser math classes.tuple.private ;
+FROM: inverse => undo ;
 IN: tuple-arrays
 
-TUPLE: tuple-array { seq read-only } { class read-only } ;
+<PRIVATE
 
-: <tuple-array> ( length class -- tuple-array )
-    [
-        new tuple>array 1 tail
-        [ <repetition> concat ] [ length ] bi <sliced-groups>
-    ] [ ] bi tuple-array boa ;
+MACRO: boa-unsafe ( class -- quot ) tuple-layout '[ _ <tuple-boa> ] ;
 
-M: tuple-array nth
-    [ seq>> nth ] [ class>> ] bi prefix >tuple ;
+MACRO: infer-in ( class -- quot ) infer in>> '[ _ ] ;
 
-M: tuple-array set-nth ( elt n seq -- )
-    [ tuple>array 1 tail ] 2dip seq>> set-nth ;
+: tuple-arity ( class -- quot ) '[ _ boa ] infer-in ; inline
 
-M: tuple-array new-sequence
-    class>> <tuple-array> ;
+: smart-tuple>array ( tuple class -- array )
+    '[ [ _ boa ] undo ] output>array ; inline
 
-: >tuple-array ( seq -- tuple-array )
-    dup empty? [
-        0 over first class <tuple-array> clone-like
-    ] unless ;
+: tuple-prototype ( class -- array )
+    [ new ] [ smart-tuple>array ] bi ; inline
 
-M: tuple-array like 
-    drop dup tuple-array? [ >tuple-array ] unless ;
+: tuple-slice ( n seq -- slice )
+    [ n>> [ * dup ] keep + ] [ seq>> ] bi { array } declare slice boa ; inline
 
-M: tuple-array length seq>> length ;
+: read-tuple ( slice class -- tuple )
+    '[ _ boa-unsafe ] input<sequence-unsafe ; inline
 
-INSTANCE: tuple-array sequence
+MACRO: write-tuple ( class -- quot )
+    [ '[ [ _ boa ] undo ] ]
+    [ tuple-arity <reversed> [ '[ [ _ ] dip set-nth-unsafe ] ] map '[ _ cleave ] ]
+    bi '[ _ dip @ ] ;
+
+PRIVATE>
+
+FUNCTOR: define-tuple-array ( CLASS -- )
+
+CLASS IS ${CLASS}
+
+CLASS-array DEFINES-CLASS ${CLASS}-array
+CLASS-array? IS ${CLASS-array}?
+
+<CLASS-array> DEFINES <${CLASS}-array>
+>CLASS-array DEFINES >${CLASS}-array
+
+WHERE
+
+TUPLE: CLASS-array
+{ seq array read-only }
+{ n array-capacity read-only }
+{ length array-capacity read-only } ;
+
+: <CLASS-array> ( length -- tuple-array )
+    [ \ CLASS [ tuple-prototype <repetition> concat ] [ tuple-arity ] bi ] keep
+    \ CLASS-array boa ; inline
+
+M: CLASS-array length length>> ;
+
+M: CLASS-array nth-unsafe tuple-slice \ CLASS read-tuple ;
+
+M: CLASS-array set-nth-unsafe tuple-slice \ CLASS write-tuple ;
+
+M: CLASS-array new-sequence drop <CLASS-array> ;
+
+: >CLASS-array ( seq -- tuple-array ) 0 <CLASS-array> clone-like ;
+
+M: CLASS-array like drop dup CLASS-array? [ >CLASS-array ] unless ;
+
+INSTANCE: CLASS-array sequence
+
+;FUNCTOR
+
+SYNTAX: TUPLE-ARRAY: scan-word define-tuple-array ;
index 5e12322a4868cceaee6a96a3864f5dcbe5db44f7..85a6249dd3090dab000b4a641d1d55e19fe3dd68 100644 (file)
@@ -89,11 +89,14 @@ ERROR: bad-literal-tuple ;
     swap [ [ slot-named offset>> 2 - ] curry dip ] curry assoc-map
     [ dup <enum> ] dip update boa>tuple ;
 
-: parse-tuple-literal ( -- tuple )
-    scan-word scan {
+: parse-tuple-literal-slots ( class -- tuple )
+    scan {
         { f [ unexpected-eof ] }
         { "f" [ \ } parse-until boa>tuple ] }
         { "{" [ parse-slot-values assoc>tuple ] }
         { "}" [ new ] }
         [ bad-literal-tuple ]
     } case ;
+
+: parse-tuple-literal ( -- tuple )
+    scan-word parse-tuple-literal-slots ;
index 2ae5ada8a1ca5afe9bdcce1e7b8384e419613219..f457b90c309fe7b1d12d517e94db7afd9e3359fb 100755 (executable)
@@ -46,8 +46,8 @@ CONSTANT: homo-sapiens
     }
 
 : make-cumulative ( freq -- chars floats )
-    dup keys >byte-array
-    swap values >double-array unclip [ + ] accumulate swap suffix ;
+    [ keys >byte-array ]
+    [ values >double-array ] bi unclip [ + ] accumulate swap suffix ;
 
 :: select-random ( seed chars floats -- seed elt )
     floats seed random -rot
@@ -55,7 +55,7 @@ CONSTANT: homo-sapiens
     chars nth-unsafe ; inline
 
 : make-random-fasta ( seed len chars floats -- seed )
-    [ rot drop select-random ] 2curry B{ } map-as print ; inline
+    [ rot drop select-random ] 2curry "" map-as print ; inline
 
 : write-description ( desc id -- )
     ">" write write bl print ; inline
@@ -71,7 +71,7 @@ CONSTANT: homo-sapiens
 
 :: make-repeat-fasta ( k len alu -- k' )
     [let | kn [ alu length ] |
-        len [ k + kn mod alu nth-unsafe ] B{ } map-as print
+        len [ k + kn mod alu nth-unsafe ] "" map-as print
         k len +
     ] ; inline
 
diff --git a/extra/benchmark/tuple-arrays/authors.txt b/extra/benchmark/tuple-arrays/authors.txt
new file mode 100644 (file)
index 0000000..d4f5d6b
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
\ No newline at end of file
diff --git a/extra/benchmark/tuple-arrays/tuple-arrays.factor b/extra/benchmark/tuple-arrays/tuple-arrays.factor
new file mode 100644 (file)
index 0000000..483311d
--- /dev/null
@@ -0,0 +1,20 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions tuple-arrays accessors fry sequences
+prettyprint ;
+IN: benchmark.tuple-arrays
+
+TUPLE: point { x float } { y float } { z float } ;
+
+TUPLE-ARRAY: point
+
+: tuple-array-benchmark ( -- )
+    100 [
+        drop 5000 <point-array> [
+            [ 1+ ] change-x
+            [ 1- ] change-y
+            [ 1+ 2 / ] change-z
+        ] map [ z>> ] sigma
+    ] sigma . ;
+
+MAIN: tuple-array-benchmark
\ No newline at end of file
index a5671a5822811364fc8906e5e67f46ed9bc0a416..79df00ff5e723c91acb6ee825c634143200fd60f 100644 (file)
@@ -6,7 +6,7 @@ combinators math.ranges unicode.categories byte-arrays
 io.encodings.string io.encodings.utf16 assocs math.parser
 combinators.short-circuit fry namespaces combinators.smart
 splitting io.encodings.ascii arrays io.files.info unicode.case
-io.directories.search literals math.functions ;
+io.directories.search literals math.functions continuations ;
 IN: id3
 
 <PRIVATE
@@ -205,7 +205,9 @@ CONSTANT: id3v1+-offset $[ 128 227 + ]
         drop
     ] if ;
 
-: (mp3>id3) ( path -- id3v2/f )
+PRIVATE>
+
+: mp3>id3 ( path -- id3/f )
     [
         [ <id3> ] dip
         {
@@ -213,12 +215,7 @@ CONSTANT: id3v1+-offset $[ 128 227 + ]
             [ dup id3v1+? [ read-v1+-tags merge-id3v1 ] [ drop ] if ]
             [ dup id3v2? [ read-v2-tags ] [ drop ] if ]
         } cleave
-    ] with-mapped-uchar-file ;
-
-PRIVATE>
-
-: mp3>id3 ( path -- id3/f )
-    dup file-info size>> 0 <= [ drop f ] [ (mp3>id3) ] if ;
+    ] with-mapped-uchar-file-reader ;
 
 : find-id3-frame ( id3 name -- obj/f )
     swap frames>> at* [ data>> ] when ;
@@ -239,8 +236,14 @@ PRIVATE>
 : find-mp3s ( path -- seq )
     [ >lower ".mp3" tail? ] find-all-files ;
 
+ERROR: id3-parse-error path error ;
+
+: (mp3-paths>id3s) ( seq -- seq' )
+    [ dup [ mp3>id3 ] [ \ id3-parse-error boa ] recover ] { } map>assoc ;
+
 : mp3-paths>id3s ( seq -- seq' )
-    [ dup mp3>id3 ] { } map>assoc ;
+    (mp3-paths>id3s)
+    [ dup second id3-parse-error? [ f over set-second ] when ] map ;
 
 : parse-mp3-directory ( path -- seq )
     find-mp3s mp3-paths>id3s ;
index cf9e9c836aceb06ca93cafc7cc0c78d2ba30ca61..2818c16f9f6fc02760ec29b400a283b6f2df4976 100644 (file)
@@ -2,33 +2,26 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors images images.loader io.pathnames kernel namespaces
 opengl opengl.gl opengl.textures sequences strings ui ui.gadgets
-ui.gadgets.panes ui.render ;
+ui.gadgets.panes ui.render ui.images ;
 IN: images.viewer
 
-TUPLE: image-gadget < gadget { image image } ;
+TUPLE: image-gadget < gadget image-name ;
 
 M: image-gadget pref-dim*
-    image>> dim>> ;
-
-: draw-image ( image -- )
-    0 0 glRasterPos2i 1.0 -1.0 glPixelZoom
-    [ dim>> first2 ] [ component-order>> component-order>format ] [ bitmap>> ] tri
-    glDrawPixels ;
+    image-name>> image-dim ;
 
 M: image-gadget draw-gadget* ( gadget -- )
-    image>> draw-image ;
+    image-name>> draw-image ;
 
-: <image-gadget> ( image -- gadget )
+: <image-gadget> ( image-name -- gadget )
     \ image-gadget new
-        swap >>image ;
+        swap >>image-name ;
 
 : image-window ( path -- gadget )
-    [ load-image <image-gadget> dup ] [ open-window ] bi ;
+    [ <image-name> <image-gadget> dup ] [ open-window ] bi ;
 
 GENERIC: image. ( object -- )
 
-M: string image. ( image -- ) load-image image. ;
-
-M: pathname image. ( image -- ) load-image image. ;
+M: string image. ( image -- ) <image-name> <image-gadget> gadget. ;
 
-M: image image. ( image -- ) <image-gadget> gadget. ;
+M: pathname image. ( image -- ) <image-name> <image-gadget> gadget. ;
index 6bf4ae090d7b6bec01c3a5d2d9b9eb36513cf8f5..96e31c4a450cecfaaef1ecad18d16d43b7a19ab2 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays accessors io io.sockets io.encodings.utf8 io.files
 io.launcher kernel make mason.config mason.common mason.email
-mason.twitter namespaces sequences ;
+mason.twitter namespaces sequences prettyprint ;
 IN: mason.notify
 
 : status-notify ( input-file args -- )
@@ -38,7 +38,7 @@ IN: mason.notify
     f { "test" } status-notify ;
 
 : notify-report ( status -- )
-    [ "Build finished with status: " write print flush ]
+    [ "Build finished with status: " write . flush ]
     [
         [ "report" utf8 file-contents ] dip email-report
         "report" { "report" } status-notify
index edc8416235354aee67e10496da2a480f947234ca..64d31b43688f3708ac78dd6c5c434ed69eb5e04e 100644 (file)
@@ -28,7 +28,7 @@ IN: mason.report
         common-report
         _ call( -- xml )
         [XML <html><body><-><-></body></html> XML]
-        pprint-xml
+        write-xml
     ] with-file-writer ; inline
 
 :: failed-report ( error file what -- status )
index fd52df1c4d54987bf06ca7fe78e480c9554d04b6..f1da7ce13962187edbe6c8e67164f27074a7832c 100644 (file)
@@ -3,7 +3,7 @@
 USING: arrays morse strings tools.test ;
 IN: morse.tests
 
-[ CHAR: ? ] [ CHAR: \\ ch>morse ] unit-test
+[ "?" ] [ CHAR: \\ ch>morse ] unit-test
 [ "..." ] [ CHAR: s ch>morse ] unit-test
 [ CHAR: s ] [ "..." morse>ch ] unit-test
 [ CHAR: \s ] [ "..--..--.." morse>ch ] unit-test
@@ -41,3 +41,4 @@ IN: morse.tests
     MORSE] ] unit-test
 ! [ ] [ "sos" 0.075 play-as-morse* ] unit-test
 ! [ ] [ "Factor rocks!" play-as-morse ] unit-test
+! [ ] [ "\n" play-as-morse ] unit-test
index ef4b9d4b889520b12d93ea6a05950472f410ef02..20989f2f2f45e4480a081d4bf7de334e5d2e1805 100644 (file)
@@ -3,13 +3,15 @@
 USING: accessors ascii assocs biassocs combinators hashtables kernel lists literals math namespaces make multiline openal parser sequences splitting strings synth synth.buffers ;
 IN: morse
 
+ERROR: no-morse-code ch ;
+
 <PRIVATE
 
 CONSTANT: dot-char CHAR: .
 CONSTANT: dash-char CHAR: -
 CONSTANT: char-gap-char CHAR: \s
 CONSTANT: word-gap-char CHAR: /
-CONSTANT: unknown-char CHAR: ?
+CONSTANT: unknown-char "?"
 
 PRIVATE>
 
@@ -74,10 +76,10 @@ CONSTANT: morse-code-table $[
 ]
 
 : ch>morse ( ch -- morse )
-    ch>lower morse-code-table at [ unknown-char ] unless* ;
+    ch>lower morse-code-table at unknown-char or ;
 
 : morse>ch ( str -- ch )
-    morse-code-table value-at [ char-gap-char ] unless* ;
+    morse-code-table value-at char-gap-char or ;
     
 <PRIVATE
     
@@ -148,12 +150,13 @@ CONSTANT: beep-freq 880
         source get source-play
     ] with-scope ; inline
 
-: play-char ( ch -- )
+: play-char ( string -- )
     [ intra-char-gap ] [
         {
             { dot-char [ dot ] }
             { dash-char [ dash ] }
             { word-gap-char [ intra-char-gap ] }
+            [ drop intra-char-gap ]
         } case
     ] interleave ;
 
diff --git a/extra/pair-methods/authors.txt b/extra/pair-methods/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/pair-methods/pair-methods-tests.factor b/extra/pair-methods/pair-methods-tests.factor
new file mode 100644 (file)
index 0000000..f88ca96
--- /dev/null
@@ -0,0 +1,43 @@
+! (c)2009 Joe Groff bsd license
+USING: accessors pair-methods classes kernel sequences tools.test ;
+IN: pair-methods.tests
+
+TUPLE: thang ;
+
+TUPLE: foom < thang ;
+TUPLE: barm < foom ;
+
+TUPLE: zim < thang ;
+TUPLE: zang < zim ;
+
+: class-names ( a b prefix -- string )
+    [ [ class name>> ] bi@ "-" glue ] dip prepend ;
+
+PAIR-GENERIC: blibble ( a b -- c )
+
+PAIR-M: thang thang blibble
+    "vanilla " class-names ;
+
+PAIR-M: foom thang blibble
+    "chocolate " class-names ;
+
+PAIR-M: barm thang blibble
+    "strawberry " class-names ;
+
+PAIR-M: barm zim blibble
+    "coconut " class-names ;
+
+[ "vanilla zang-zim" ] [ zim new zang new blibble ] unit-test
+
+! args automatically swap to match most specific method
+[ "chocolate foom-zim" ] [ foom new zim  new blibble ] unit-test
+[ "chocolate foom-zim" ] [ zim  new foom new blibble ] unit-test
+
+[ "strawberry barm-barm" ] [ barm new barm new blibble ] unit-test
+[ "strawberry barm-foom" ] [ barm new foom new blibble ] unit-test
+[ "strawberry barm-foom" ] [ foom new barm new blibble ] unit-test
+
+[ "coconut barm-zang" ] [ zang new barm new blibble ] unit-test
+[ "coconut barm-zim" ] [ barm new zim  new blibble ] unit-test
+
+[ 1 2 blibble ] [ no-pair-method? ] must-fail-with
diff --git a/extra/pair-methods/pair-methods.factor b/extra/pair-methods/pair-methods.factor
new file mode 100644 (file)
index 0000000..d44d5bc
--- /dev/null
@@ -0,0 +1,57 @@
+! (c)2009 Joe Groff bsd license
+USING: arrays assocs classes classes.tuple.private combinators
+effects.parser generic.parser kernel math math.order parser
+quotations sequences sorting words ;
+IN: pair-methods
+
+ERROR: no-pair-method a b generic ;
+
+: ?swap ( a b ? -- a/b b/a )
+    [ swap ] when ;
+
+: method-sort-key ( pair -- key )
+    first2 [ tuple-layout third ] bi@ + ;
+
+: pair-match-condition ( pair -- quot )
+    first2 [ [ instance? ] swap prefix ] bi@ [ ] 2sequence
+    [ 2dup ] [ bi* and ] surround ;
+
+: pair-method-cond ( pair quot -- array )
+    [ pair-match-condition ] [ ] bi* 2array ;
+
+: sorted-pair-methods ( word -- alist )
+    "pair-generic-methods" word-prop >alist
+    [ [ first method-sort-key ] bi@ >=< ] sort ;
+
+: pair-generic-definition ( word -- def )
+    [ sorted-pair-methods [ first2 pair-method-cond ] map ]
+    [ [ no-pair-method ] curry suffix ] bi 1quotation
+    [ 2dup [ class ] bi@ <=> +gt+ eq? ?swap ] [ cond ] surround ;
+
+: make-pair-generic ( word -- )
+    dup pair-generic-definition define ;
+
+: define-pair-generic ( word effect -- )
+    [ swap set-stack-effect ]
+    [ drop H{ } clone "pair-generic-methods" set-word-prop ]
+    [ drop make-pair-generic ] 2tri ;
+
+: (PAIR-GENERIC:) ( -- )
+    CREATE-GENERIC complete-effect define-pair-generic ;
+
+SYNTAX: PAIR-GENERIC: (PAIR-GENERIC:) ;
+
+: define-pair-method ( a b pair-generic definition -- )
+    [ 2array ] 2dip swap
+    [ "pair-generic-methods" word-prop [ swap ] dip set-at ] 
+    [ make-pair-generic ] bi ;
+
+: ?prefix-swap ( quot ? -- quot' )
+    [ \ swap prefix ] when ;
+
+: (PAIR-M:) ( -- )
+    scan-word scan-word 2dup <=> +gt+ eq? [
+        ?swap scan-word parse-definition 
+    ] keep ?prefix-swap define-pair-method ;
+
+SYNTAX: PAIR-M: (PAIR-M:) ;
diff --git a/extra/pair-methods/summary.txt b/extra/pair-methods/summary.txt
new file mode 100644 (file)
index 0000000..823bc71
--- /dev/null
@@ -0,0 +1 @@
+Order-insensitive double dispatch generics
diff --git a/extra/pair-rocket/authors.txt b/extra/pair-rocket/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/pair-rocket/pair-rocket-docs.factor b/extra/pair-rocket/pair-rocket-docs.factor
new file mode 100644 (file)
index 0000000..d66df62
--- /dev/null
@@ -0,0 +1,15 @@
+! (c)2009 Joe Groff bsd license
+USING: help.markup help.syntax multiline ;
+IN: pair-rocket
+
+HELP: =>
+{ $syntax "a => b" }
+{ $description "Constructs a two-element array from the objects immediately before and after the " { $snippet "=>" } ". This syntax can be used inside sequence and assoc literals." }
+{ $examples
+{ $unchecked-example <" USING: pair-rocket prettyprint ;
+
+H{ "foo" => 1 "bar" => 2 } .
+"> <" H{ { "foo" 1 } { "bar" 2 } } "> }
+}
+;
+
diff --git a/extra/pair-rocket/pair-rocket-tests.factor b/extra/pair-rocket/pair-rocket-tests.factor
new file mode 100644 (file)
index 0000000..695e50e
--- /dev/null
@@ -0,0 +1,10 @@
+! (c)2009 Joe Groff bsd license
+USING: kernel pair-rocket tools.test ;
+IN: pair-rocket.tests
+
+[ { "a" 1 } ] [ "a" => 1 ] unit-test
+[ { { "a" } { 1 } } ] [ { "a" } => { 1 } ] unit-test
+[ { drop 1 } ] [ drop => 1 ] unit-test
+
+[ H{ { "zippity" 5 } { "doo" 2 } { "dah" 7 } } ]
+[ H{ "zippity" => 5 "doo" => 2 "dah" => 7 } ] unit-test
diff --git a/extra/pair-rocket/pair-rocket.factor b/extra/pair-rocket/pair-rocket.factor
new file mode 100644 (file)
index 0000000..3bd8a09
--- /dev/null
@@ -0,0 +1,6 @@
+! (c)2009 Joe Groff bsd license
+USING: arrays kernel parser sequences ;
+IN: pair-rocket
+
+SYNTAX: => dup pop scan-object 2array parsed ;
+
diff --git a/extra/pair-rocket/summary.txt b/extra/pair-rocket/summary.txt
new file mode 100644 (file)
index 0000000..79c8d60
--- /dev/null
@@ -0,0 +1 @@
+H{ "foo" => 1 "bar" => 2 } style literal syntax
diff --git a/extra/qw/authors.txt b/extra/qw/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/qw/qw-docs.factor b/extra/qw/qw-docs.factor
new file mode 100644 (file)
index 0000000..4709ef6
--- /dev/null
@@ -0,0 +1,12 @@
+! (c)2009 Joe Groff bsd license
+USING: help.markup help.syntax multiline ;
+IN: qw
+
+HELP: qw{
+{ $syntax "qw{ lorem ipsum }" }
+{ $description "Marks the beginning of a literal array of strings. Component strings are delimited by whitespace." }
+{ $examples
+{ $unchecked-example <" USING: prettyprint qw ;
+qw{ pop quiz my hive of big wild ex tranny jocks } . ">
+<" { "pop" "quiz" "my" "hive" "of" "big" "wild" "ex" "tranny" "jocks" } "> }
+} ;
diff --git a/extra/qw/qw-tests.factor b/extra/qw/qw-tests.factor
new file mode 100644 (file)
index 0000000..c9d9208
--- /dev/null
@@ -0,0 +1,5 @@
+! (c)2009 Joe Groff bsd license
+USING: qw tools.test ;
+IN: qw.tests
+
+[ { "zippity" "doo" "dah" } ] [ qw{ zippity doo dah } ] unit-test
diff --git a/extra/qw/qw.factor b/extra/qw/qw.factor
new file mode 100644 (file)
index 0000000..ce96587
--- /dev/null
@@ -0,0 +1,5 @@
+! (c)2009 Joe Groff bsd license
+USING: lexer parser ;
+IN: qw
+
+SYNTAX: qw{ "}" parse-tokens parsed ;
diff --git a/extra/qw/summary.txt b/extra/qw/summary.txt
new file mode 100644 (file)
index 0000000..8c31961
--- /dev/null
@@ -0,0 +1 @@
+Perlish syntax for literal arrays of whitespace-delimited strings (qw{ foo bar })
diff --git a/extra/roles/authors.txt b/extra/roles/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/roles/roles-docs.factor b/extra/roles/roles-docs.factor
new file mode 100644 (file)
index 0000000..412a7b8
--- /dev/null
@@ -0,0 +1,48 @@
+! (c)2009 Joe Groff bsd license
+USING: classes.mixin help.markup help.syntax kernel multiline roles ;
+IN: roles
+
+HELP: ROLE:
+{ $syntax <" ROLE: name slots... ;
+ROLE: name < role slots... ;
+ROLE: name <{ roles... } slots... ; "> }
+{ $description "Defines a new " { $link role } ". " { $link tuple } " classes which inherit this role will contain the specified " { $snippet "slots" } " as well as the slots associated with the optional inherited " { $snippet "roles" } "."
+$nl
+"Slot specifiers take one of the following three forms:"
+{ $list
+    { { $snippet "name" } " - a slot which can hold any object, with no attributes" }
+    { { $snippet "{ name attributes... }" } " - a slot which can hold any object, with optional attributes" }
+    { { $snippet "{ name class attributes... }" } " - a slot specialized to a specific class, with optional attributes" }
+}
+"Slot attributes are lists of slot attribute specifiers followed by values; a slot attribute specifier is one of " { $link initial: } " or " { $link read-only } ". See " { $link "tuple-declarations" } " for details." } ; 
+
+HELP: TUPLE:
+{ $syntax <" TUPLE: name slots ;
+TUPLE: name < estate slots ;
+TUPLE: name <{ estates... } slots... ; "> }
+{ $description "Defines a new " { $link tuple } " class."
+$nl
+"The list of inherited " { $snippet "estates" } " is optional; a single tuple superclass and/or a set of " { $link role } "s can be specified. If no superclass is provided, it defaults to " { $link tuple } "."
+$nl
+"Slot specifiers take one of the following three forms:"
+{ $list
+    { { $snippet "name" } " - a slot which can hold any object, with no attributes" }
+    { { $snippet "{ name attributes... }" } " - a slot which can hold any object, with optional attributes" }
+    { { $snippet "{ name class attributes... }" } " - a slot specialized to a specific class, with optional attributes" }
+}
+"Slot attributes are lists of slot attribute specifiers followed by values; a slot attribute specifier is one of " { $link initial: } " or " { $link read-only } ". See " { $link "tuple-declarations" } " for details." } ; 
+
+{
+    POSTPONE: ROLE:
+    POSTPONE: TUPLE:
+} related-words
+
+HELP: role
+{ $class-description "The superclass of all role classes. A " { $snippet "role" } " is a " { $link mixin-class } " that includes a set of slot definitions that can be added to " { $link tuple } " classes alongside other " { $snippet "role" } "s." } ;
+
+HELP: multiple-inheritance-attempted
+{ $class-description "This error is thrown if a " { $link POSTPONE: TUPLE: } " definition attempts to inherit more than one " { $link tuple } " class." } ;
+
+HELP: role-slot-overlap
+{ $class-description "This error is thrown if a " { $link POSTPONE: TUPLE: } " or " { $link POSTPONE: ROLE: } " definition attempts to inherit a set of " { $link role } "s in which more than one attempts to define the same slot." } ;
+
diff --git a/extra/roles/roles-tests.factor b/extra/roles/roles-tests.factor
new file mode 100644 (file)
index 0000000..fcbc20d
--- /dev/null
@@ -0,0 +1,67 @@
+! (c)2009 Joe Groff bsd license
+USING: accessors classes.tuple compiler.units kernel qw roles sequences
+tools.test ;
+IN: roles.tests
+
+ROLE: fork tines ;
+ROLE: spoon bowl ;
+ROLE: instrument tone ;
+ROLE: tuning-fork <{ fork instrument } volume ;
+
+TUPLE: utensil handle ;
+
+! role consumption and tuple inheritance can be mixed
+TUPLE: foon <{ utensil fork spoon } ;
+TUPLE: tuning-spork <{ utensil spoon tuning-fork } ;
+
+! role class testing
+[ t ] [ fork role? ] unit-test
+[ f ] [ foon role? ] unit-test
+
+! roles aren't tuple classes by themselves and can't be instantiated
+[ f ] [ fork tuple-class? ] unit-test
+[ fork new ] must-fail
+
+! tuples which consume roles fall under their class
+[ t ] [ foon new fork? ] unit-test
+[ t ] [ foon new spoon? ] unit-test
+[ f ] [ foon new tuning-fork? ] unit-test
+[ f ] [ foon new instrument? ] unit-test
+
+[ t ] [ tuning-spork new fork? ] unit-test
+[ t ] [ tuning-spork new spoon? ] unit-test
+[ t ] [ tuning-spork new tuning-fork? ] unit-test
+[ t ] [ tuning-spork new instrument? ] unit-test
+
+! consumed role slots are placed in tuples in order
+[ qw{ handle tines bowl } ] [ foon all-slots [ name>> ] map ] unit-test
+[ qw{ handle bowl tines tone volume } ] [ tuning-spork all-slots [ name>> ] map ] unit-test
+
+! can't combine roles whose slots overlap
+ROLE: bong bowl ;
+SYMBOL: spong
+
+[ [ spong { spoon bong } { } define-tuple-class-with-roles ] with-compilation-unit ]
+[ role-slot-overlap? ] must-fail-with 
+
+[ [ spong { spoon bong } { } define-role ] with-compilation-unit ]
+[ role-slot-overlap? ] must-fail-with 
+
+! can't try to inherit multiple tuple classes
+TUPLE: tool blade ;
+SYMBOL: knife
+
+[ knife { utensil tool } { } define-tuple-class-with-roles ]
+[ multiple-inheritance-attempted? ] must-fail-with 
+
+! make sure method dispatch works
+GENERIC: poke ( pokee poker -- result )
+GENERIC: scoop ( scoopee scooper -- result )
+GENERIC: tune ( tunee tuner -- result )
+
+M: fork poke drop " got poked" append ;
+M: spoon scoop drop " got scooped" append ;
+M: instrument tune drop " got tuned" append ;
+
+[ "potato got poked" "potato got scooped" "potato got tuned" ]
+[ "potato" tuning-spork new [ poke ] [ scoop ] [ tune ] 2tri ] unit-test
diff --git a/extra/roles/roles.factor b/extra/roles/roles.factor
new file mode 100644 (file)
index 0000000..d54b433
--- /dev/null
@@ -0,0 +1,69 @@
+! (c)2009 Joe Groff bsd license
+USING: accessors arrays classes classes.mixin classes.parser
+classes.tuple classes.tuple.parser combinators
+combinators.short-circuit kernel lexer make parser sequences
+sets strings words ;
+IN: roles
+
+ERROR: role-slot-overlap class slots ;
+ERROR: multiple-inheritance-attempted classes ;
+
+PREDICATE: role < mixin-class
+    "role-slots" word-prop >boolean ;
+
+: parse-role-definition ( -- class superroles slots )
+    CREATE-CLASS scan {
+        { ";" [ { } { } ] }
+        { "<" [ scan-word 1array [ parse-tuple-slots ] { } make ] }
+        { "<{" [ \ } parse-until >array [ parse-tuple-slots ] { } make ] }
+        [ { } swap [ parse-slot-name [ parse-tuple-slots ] when ] { } make ]
+    } case ;
+
+: slot-name ( name/array -- name )
+    dup string? [ ] [ first ] if ;
+: slot-names ( array -- names )
+    [ slot-name ] map ;
+
+: role-slots ( role -- slots )
+    [ "superroles" word-prop [ role-slots ] map concat ]
+    [ "role-slots" word-prop ] bi append ;
+
+: role-or-tuple-slot-names ( role-or-tuple -- names )
+    dup role?
+    [ role-slots slot-names ]
+    [ all-slots [ name>> ] map ] if ;
+
+: check-for-slot-overlap ( class roles-and-superclass slots -- )
+    [ [ role-or-tuple-slot-names ] map concat ] [ slot-names ] bi* append
+    duplicates dup empty? [ 2drop ] [ role-slot-overlap ] if ;
+
+: roles>slots ( roles-and-superclass slots -- superclass slots' )
+    [
+        [ role? ] partition
+        dup length {
+            { 0 [ drop tuple ] }
+            { 1 [ first ] }
+            [ drop multiple-inheritance-attempted ]
+        } case
+        swap [ role-slots ] map concat
+    ] dip append ;
+
+: add-to-roles ( class roles -- )
+    [ add-mixin-instance ] with each ;
+
+: (define-role) ( class superroles slots -- )
+    [ "superroles" set-word-prop ] [ "role-slots" set-word-prop ] bi-curry*
+    [ define-mixin-class ] tri ;
+
+: define-role ( class superroles slots -- )
+    [ check-for-slot-overlap ] [ (define-role) ] [ drop add-to-roles ] 3tri ;
+
+: define-tuple-class-with-roles ( class roles-and-superclass slots -- )
+    [ check-for-slot-overlap ]
+    [ roles>slots define-tuple-class ]
+    [ drop [ role? ] filter add-to-roles ] 3tri ;
+
+SYNTAX: ROLE: parse-role-definition define-role ;
+SYNTAX: TUPLE: parse-role-definition define-tuple-class-with-roles ;
+
+
diff --git a/extra/roles/summary.txt b/extra/roles/summary.txt
new file mode 100644 (file)
index 0000000..a14aae4
--- /dev/null
@@ -0,0 +1 @@
+Mixins for tuples
diff --git a/extra/sequences/product/authors.txt b/extra/sequences/product/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/sequences/product/product-docs.factor b/extra/sequences/product/product-docs.factor
new file mode 100644 (file)
index 0000000..b7dcaa6
--- /dev/null
@@ -0,0 +1,61 @@
+! (c)2009 Joe Groff bsd license
+USING: help.markup help.syntax multiline quotations sequences sequences.product ;
+IN: sequences
+
+HELP: product-sequence
+{ $class-description "A class of virtual sequences that present the cartesian product of their underlying set of sequences. Product sequences are constructed with the " { $link <product-sequence> } " word." }
+{ $examples
+{ $example <" USING: arrays prettyprint sequences.product ;
+{ { 1 2 3 } { "a" "b" "c" } } <product-sequence> >array .
+"> <" {
+    { 1 "a" }
+    { 2 "a" }
+    { 3 "a" }
+    { 1 "b" }
+    { 2 "b" }
+    { 3 "b" }
+    { 1 "c" }
+    { 2 "c" }
+    { 3 "c" }
+}"> } } ;
+
+HELP: <product-sequence>
+{ $values { "sequences" sequence } { "product-sequence" product-sequence } }
+{ $description "Constructs a " { $link product-sequence } " over " { $snippet "sequences" } "." }
+{ $examples
+{ $example <" USING: arrays prettyprint sequences.product ;
+{ { 1 2 3 } { "a" "b" "c" } } <product-sequence> >array .
+"> <" {
+    { 1 "a" }
+    { 2 "a" }
+    { 3 "a" }
+    { 1 "b" }
+    { 2 "b" }
+    { 3 "b" }
+    { 1 "c" }
+    { 2 "c" }
+    { 3 "c" }
+}"> } } ;
+
+{ product-sequence <product-sequence> } related-words
+
+HELP: product-map
+{ $values { "sequences" sequence } { "quot" { $quotation "( sequence -- value )" } } { "sequence" sequence } }
+{ $description "Calls " { $snippet "quot" } " for every element of the cartesian product of " { $snippet "sequences" } " and collects the results from " { $snippet "quot" } " into an output sequence." }
+{ $notes { $snippet "[ ... ] product-map" } " is equivalent to, but more efficient than, " { $snippet "<product-sequence> [ ... ] map" } "." } ;
+
+HELP: product-each
+{ $values { "sequences" sequence } { "quot" { $quotation "( sequence -- )" } } }
+{ $description "Calls " { $snippet "quot" } " for every element of the cartesian product of " { $snippet "sequences" } "." }
+{ $notes { $snippet "[ ... ] product-each" } " is equivalent to, but more efficient than, " { $snippet "<product-sequence> [ ... ] each" } "." } ;
+
+{ product-map product-each } related-words
+
+ARTICLE: "sequences.product" "Product sequences"
+"The " { $vocab-link "sequences.product" } " vocabulary provides a virtual sequence and combinators for manipulating the cartesian product of a set of sequences."
+{ $subsection product-sequence }
+{ $subsection <product-sequence> }
+{ $subsection product-map }
+{ $subsection product-each } ;
+
+ABOUT: "sequences.product"
index dfabc166acc49ead7d396315f4450c6b931fc27a..5e0997dc2e0da73709bfe7f89bf731dd1125d8a4 100644 (file)
@@ -1,19 +1,26 @@
-USING: arrays kernel sequences sequences.cartesian-product tools.test ;
+! (c)2009 Joe Groff bsd license
+USING: arrays kernel make sequences sequences.product tools.test ;
 IN: sequences.product.tests
 
-[
-    { { 0 "a" } { 1 "a" } { 2 "a" } { 0 "b" } { 1 "b" } { 2 "b" } }
-] [ { { 0 1 2 } { "a" "b" } } [ ] cartesian-product-map ] unit-test
+
+[ { { 0 "a" } { 1 "a" } { 2 "a" } { 0 "b" } { 1 "b" } { 2 "b" } } ]
+[ { { 0 1 2 } { "a" "b" } } <product-sequence> >array ] unit-test
+
+: x ( n s -- sss ) <repetition> concat ;
+
+[ { "a" "aa" "aaa" "b" "bb" "bbb" } ]
+[ { { 1 2 3 } { "a" "b" } } [ first2 x ] product-map ] unit-test
 
 [
     {
         { 0 "a" t } { 1 "a" t } { 2 "a" t } { 0 "b" t } { 1 "b" t } { 2 "b" t }
         { 0 "a" f } { 1 "a" f } { 2 "a" f } { 0 "b" f } { 1 "b" f } { 2 "b" f }
     }
-] [ { { 0 1 2 } { "a" "b" } { t f } } [ ] cartesian-product-map ] unit-test
-
-[
-    { "012012" "aaabbb" }
-] [ { { "0" "1" "2" } { "a" "b" } } [ [ first2 ] bi* [ append ] bi@ 2array ] cartesian-product-each ] unit-test
-
+] [ { { 0 1 2 } { "a" "b" } { t f } } [ ] product-map ] unit-test
 
+[ "a1b1c1a2b2c2" ] [
+    [
+        { { "a" "b" "c" } { "1" "2" } }
+        [ [ % ] each ] product-each
+    ] "" make
+] unit-test
diff --git a/extra/sequences/product/product.factor b/extra/sequences/product/product.factor
new file mode 100644 (file)
index 0000000..665d43f
--- /dev/null
@@ -0,0 +1,63 @@
+! (c)2009 Joe Groff bsd license
+USING: accessors arrays kernel locals math sequences ;
+IN: sequences.product
+
+TUPLE: product-sequence { sequences array read-only } { lengths array read-only } ;
+
+: <product-sequence> ( sequences -- product-sequence )
+    >array dup [ length ] map product-sequence boa ;
+
+INSTANCE: product-sequence sequence
+
+M: product-sequence length lengths>> product ;
+
+<PRIVATE
+
+: ns ( n lengths -- ns )
+    [ V{ } clone ] 2dip [ /mod swap [ over push ] dip ] each drop ;
+
+: nths ( ns seqs -- nths )
+    [ nth ] { } 2map-as ;
+
+: product@ ( n product-sequence -- ns seqs )
+    [ lengths>> ns ] [ nip sequences>> ] 2bi ;
+
+:: (carry-n) ( ns lengths i -- )
+    ns length i 1+ = [
+        i ns nth i lengths nth = [
+            0 i ns set-nth
+            i 1+ ns [ 1+ ] change-nth
+            ns lengths i 1+ (carry-n)
+        ] when
+    ] unless ;
+
+: carry-ns ( ns lengths -- )
+    0 (carry-n) ;
+    
+: product-iter ( ns lengths -- )
+    [ 0 over [ 1+ ] change-nth ] dip carry-ns ;
+
+: start-product-iter ( sequence-product -- ns lengths )
+    [ [ drop 0 ] map ] [ [ length ] map ] bi ;
+
+: end-product-iter? ( ns lengths -- ? )
+    [ 1 tail* first ] bi@ = ;
+
+PRIVATE>
+
+M: product-sequence nth 
+    product@ nths ;
+
+:: product-each ( sequences quot -- )
+    sequences start-product-iter :> lengths :> ns
+    [ ns lengths end-product-iter? ]
+    [ ns sequences nths quot call ns lengths product-iter ] until ; inline
+
+:: product-map ( sequences quot -- sequence )
+    0 :> i!
+    sequences [ length ] [ * ] map-reduce sequences
+    [| result |
+        sequences [ quot call i result set-nth i 1+ i! ] product-each
+        result
+    ] new-like ; inline
+
diff --git a/extra/sequences/product/summary.txt b/extra/sequences/product/summary.txt
new file mode 100644 (file)
index 0000000..c234c84
--- /dev/null
@@ -0,0 +1 @@
+Cartesian products of sequences
index c3c5bc9a108c04c010f1386e461b18b925d8aa01..1405daa93fb83a5e674f0e90c747918072fcd1dd 100755 (executable)
@@ -1,5 +1,10 @@
 #include "master.h"
 
+static void clear_free_list(F_HEAP *heap)
+{
+       memset(&heap->free,0,sizeof(F_HEAP_FREE_LIST));
+}
+
 /* This malloc-style heap code is reasonably generic. Maybe in the future, it
 will be used for the data heap too, if we ever get incremental
 mark/sweep/compact GC. */
@@ -8,17 +13,23 @@ void new_heap(F_HEAP *heap, CELL size)
        heap->segment = alloc_segment(align_page(size));
        if(!heap->segment)
                fatal_error("Out of memory in new_heap",size);
-       heap->free_list = NULL;
+
+       clear_free_list(heap);
 }
 
-/* If there is no previous block, next_free becomes the head of the free list,
-else its linked in */
-INLINE void update_free_list(F_HEAP *heap, F_FREE_BLOCK *prev, F_FREE_BLOCK *next_free)
+void add_to_free_list(F_HEAP *heap, F_FREE_BLOCK *block)
 {
-       if(prev)
-               prev->next_free = next_free;
+       if(block->block.size < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT)
+       {
+               int index = block->block.size / BLOCK_SIZE_INCREMENT;
+               block->next_free = heap->free.small_blocks[index];
+               heap->free.small_blocks[index] = block;
+       }
        else
-               heap->free_list = next_free;
+       {
+               block->next_free = heap->free.large_blocks;
+               heap->free.large_blocks = block;
+       }
 }
 
 /* Called after reading the code heap from the image file, and after code GC.
@@ -28,7 +39,11 @@ compiling.limit. */
 void build_free_list(F_HEAP *heap, CELL size)
 {
        F_BLOCK *prev = NULL;
-       F_FREE_BLOCK *prev_free = NULL;
+
+       clear_free_list(heap);
+
+       size = (size + BLOCK_SIZE_INCREMENT - 1) & ~(BLOCK_SIZE_INCREMENT - 1);
+
        F_BLOCK *scan = first_block(heap);
        F_FREE_BLOCK *end = (F_FREE_BLOCK *)(heap->segment->start + size);
 
@@ -38,8 +53,7 @@ void build_free_list(F_HEAP *heap, CELL size)
                switch(scan->status)
                {
                case B_FREE:
-                       update_free_list(heap,prev_free,(F_FREE_BLOCK *)scan);
-                       prev_free = (F_FREE_BLOCK *)scan;
+                       add_to_free_list(heap,(F_FREE_BLOCK *)scan);
                        break;
                case B_ALLOCATED:
                        break;
@@ -58,10 +72,9 @@ void build_free_list(F_HEAP *heap, CELL size)
        {
                end->block.status = B_FREE;
                end->block.size = heap->segment->end - (CELL)end;
-               end->next_free = NULL;
 
                /* add final free block */
-               update_free_list(heap,prev_free,end);
+               add_to_free_list(heap,end);
        }
        /* This branch is taken if the newly loaded image fits exactly, or
        after code GC */
@@ -70,65 +83,90 @@ void build_free_list(F_HEAP *heap, CELL size)
                /* even if there's no room at the end of the heap for a new
                free block, we might have to jigger it up by a few bytes in
                case prev + prev->size */
-               if(prev)
-                       prev->size = heap->segment->end - (CELL)prev;
-
-               /* this is the last free block */
-               update_free_list(heap,prev_free,NULL);
+               if(prev) prev->size = heap->segment->end - (CELL)prev;
        }
 
 }
 
-/* Allocate a block of memory from the mark and sweep GC heap */
-F_BLOCK *heap_allot(F_HEAP *heap, CELL size)
+static void assert_free_block(F_FREE_BLOCK *block)
 {
-       F_FREE_BLOCK *prev = NULL;
-       F_FREE_BLOCK *scan = heap->free_list;
-
-       size = (size + 31) & ~31;
+       if(block->block.status != B_FREE)
+               critical_error("Invalid block in free list",(CELL)block);
+}
+               
+F_FREE_BLOCK *find_free_block(F_HEAP *heap, CELL size)
+{
+       CELL attempt = size;
 
-       while(scan)
+       while(attempt < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT)
        {
-               if(scan->block.status != B_FREE)
-                       critical_error("Invalid block in free list",(CELL)scan);
-
-               if(scan->block.size < size)
+               int index = attempt / BLOCK_SIZE_INCREMENT;
+               F_FREE_BLOCK *block = heap->free.small_blocks[index];
+               if(block)
                {
-                       prev = scan;
-                       scan = scan->next_free;
-                       continue;
+                       assert_free_block(block);
+                       heap->free.small_blocks[index] = block->next_free;
+                       return block;
                }
 
-               /* we found a candidate block */
-               F_FREE_BLOCK *next_free;
+               attempt *= 2;
+       }
 
-               if(scan->block.size - size <= sizeof(F_BLOCK) * 2)
-               {
-                       /* too small to be split */
-                       next_free = scan->next_free;
-               }
-               else
+       F_FREE_BLOCK *prev = NULL;
+       F_FREE_BLOCK *block = heap->free.large_blocks;
+
+       while(block)
+       {
+               assert_free_block(block);
+               if(block->block.size >= size)
                {
-                       /* split the block in two */
-                       F_FREE_BLOCK *split = (F_FREE_BLOCK *)((CELL)scan + size);
-                       split->block.status = B_FREE;
-                       split->block.size = scan->block.size - size;
-                       split->next_free = scan->next_free;
-                       scan->block.size = size;
-                       next_free = split;
+                       if(prev)
+                               prev->next_free = block->next_free;
+                       else
+                               heap->free.large_blocks = block->next_free;
+                       return block;
                }
 
-               /* update the free list */
-               update_free_list(heap,prev,next_free);
-
-               /* this is our new block */
-               scan->block.status = B_ALLOCATED;
-               return &scan->block;
+               prev = block;
+               block = block->next_free;
        }
 
        return NULL;
 }
 
+F_FREE_BLOCK *split_free_block(F_HEAP *heap, F_FREE_BLOCK *block, CELL size)
+{
+       if(block->block.size != size )
+       {
+               /* split the block in two */
+               F_FREE_BLOCK *split = (F_FREE_BLOCK *)((CELL)block + size);
+               split->block.status = B_FREE;
+               split->block.size = block->block.size - size;
+               split->next_free = block->next_free;
+               block->block.size = size;
+               add_to_free_list(heap,split);
+       }
+
+       return block;
+}
+
+/* Allocate a block of memory from the mark and sweep GC heap */
+F_BLOCK *heap_allot(F_HEAP *heap, CELL size)
+{
+       size = (size + BLOCK_SIZE_INCREMENT - 1) & ~(BLOCK_SIZE_INCREMENT - 1);
+
+       F_FREE_BLOCK *block = find_free_block(heap,size);
+       if(block)
+       {
+               block = split_free_block(heap,block,size);
+
+               block->block.status = B_ALLOCATED;
+               return &block->block;
+       }
+       else
+               return NULL;
+}
+
 void mark_block(F_BLOCK *block)
 {
        /* If already marked, do nothing */
@@ -162,8 +200,10 @@ void unmark_marked(F_HEAP *heap)
 
 /* After code GC, all referenced code blocks have status set to B_MARKED, so any
 which are allocated and not marked can be reclaimed. */
-void free_unmarked(F_HEAP *heap)
+void free_unmarked(F_HEAP *heap, HEAP_ITERATOR iter)
 {
+       clear_free_list(heap);
+
        F_BLOCK *prev = NULL;
        F_BLOCK *scan = first_block(heap);
 
@@ -183,10 +223,15 @@ void free_unmarked(F_HEAP *heap)
                case B_FREE:
                        if(prev && prev->status == B_FREE)
                                prev->size += scan->size;
+                       else
+                               prev = scan;
                        break;
                case B_MARKED:
+                       if(prev && prev->status == B_FREE)
+                               add_to_free_list(heap,(F_FREE_BLOCK *)prev);
                        scan->status = B_ALLOCATED;
                        prev = scan;
+                       iter(scan);
                        break;
                default:
                        critical_error("Invalid scan->status",(CELL)scan);
@@ -195,7 +240,8 @@ void free_unmarked(F_HEAP *heap)
                scan = next_block(heap,scan);
        }
 
-       build_free_list(heap,heap->segment->size);
+       if(prev && prev->status == B_FREE)
+               add_to_free_list(heap,(F_FREE_BLOCK *)prev);
 }
 
 /* Compute total sum of sizes of free blocks, and size of largest free block */
old mode 100644 (file)
new mode 100755 (executable)
index cc2c42f..d71dee2
@@ -1,14 +1,24 @@
+#define FREE_LIST_COUNT 16
+#define BLOCK_SIZE_INCREMENT 32
+
+typedef struct {
+       F_FREE_BLOCK *small_blocks[FREE_LIST_COUNT];
+       F_FREE_BLOCK *large_blocks;
+} F_HEAP_FREE_LIST;
+
 typedef struct {
        F_SEGMENT *segment;
-       F_FREE_BLOCK *free_list;
+       F_HEAP_FREE_LIST free;
 } F_HEAP;
 
+typedef void (*HEAP_ITERATOR)(F_BLOCK *compiled);
+
 void new_heap(F_HEAP *heap, CELL size);
 void build_free_list(F_HEAP *heap, CELL size);
 F_BLOCK *heap_allot(F_HEAP *heap, CELL size);
 void mark_block(F_BLOCK *block);
 void unmark_marked(F_HEAP *heap);
-void free_unmarked(F_HEAP *heap);
+void free_unmarked(F_HEAP *heap, HEAP_ITERATOR iter);
 void heap_usage(F_HEAP *heap, CELL *used, CELL *total_free, CELL *max_free);
 CELL heap_size(F_HEAP *heap);
 CELL compute_heap_forwarding(F_HEAP *heap);
index 0b210310a2a1ec07f821fa926b81202bc4e915f0..872358d3621b4a5edd2ff75ca260de646a5acd5a 100755 (executable)
@@ -330,7 +330,7 @@ CELL copy_next_from_tenured(CELL scan)
 
 void copy_reachable_objects(CELL scan, CELL *end)
 {
-       if(HAVE_NURSERY_P && collecting_gen == NURSERY)
+       if(collecting_gen == NURSERY)
        {
                while(scan < *end)
                        scan = copy_next_from_nursery(scan);
@@ -405,7 +405,7 @@ void end_gc(CELL gc_elapsed)
                if(collecting_gen != NURSERY)
                        reset_generations(NURSERY,collecting_gen - 1);
        }
-       else if(HAVE_NURSERY_P && collecting_gen == NURSERY)
+       else if(collecting_gen == NURSERY)
        {
                nursery.here = nursery.start;
        }
@@ -416,13 +416,6 @@ void end_gc(CELL gc_elapsed)
                reset_generations(NURSERY,collecting_gen);
        }
 
-       if(collecting_gen == TENURED)
-       {
-               /* now that all reachable code blocks have been marked,
-               deallocate the rest */
-               free_unmarked(&code_heap);
-       }
-
        collecting_aging_again = false;
 }
 
@@ -491,7 +484,7 @@ void garbage_collection(CELL gen,
                code_heap_scans++;
 
                if(collecting_gen == TENURED)
-                       update_code_heap_roots();
+                       free_unmarked(&code_heap,(HEAP_ITERATOR)update_literal_references);
                else
                        copy_code_heap_roots();
 
index b59cb0eb9eeedf150c9ca9208815913a5c4f5e62..a1184d53d4ef07495eac115a2025a27a257b52ce 100755 (executable)
@@ -58,7 +58,7 @@ INLINE bool should_copy(CELL untagged)
                return true;
        else if(HAVE_AGING_P && collecting_gen == AGING)
                return !in_zone(&data_heap->generations[TENURED],untagged);
-       else if(HAVE_NURSERY_P && collecting_gen == NURSERY)
+       else if(collecting_gen == NURSERY)
                return in_zone(&nursery,untagged);
        else
        {
@@ -78,6 +78,11 @@ allocation (which does not call GC because of possible roots in volatile
 registers) does not run out of memory */
 #define ALLOT_BUFFER_ZONE 1024
 
+/* If this is defined, we GC every 100 allocations. This catches missing local roots */
+#ifdef GC_DEBUG
+int gc_count;
+#endif
+
 /*
  * It is up to the caller to fill in the object's fields in a meaningful
  * fashion!
@@ -85,10 +90,18 @@ registers) does not run out of memory */
 int count;
 INLINE void *allot_object(CELL type, CELL a)
 {
-  if(!gc_off) { if(count++ % 100 == 0) { printf("!\n"); gc(); } }
+#ifdef GC_DEBUG
+       if(!gc_off)
+       {
+               if(gc_count++ % 1000 == 0)
+                       gc();
+
+       }
+#endif
+
        CELL *object;
 
-       if(HAVE_NURSERY_P && nursery.size - ALLOT_BUFFER_ZONE > a)
+       if(nursery.size - ALLOT_BUFFER_ZONE > a)
        {
                /* If there is insufficient room, collect the nursery */
                if(nursery.here + ALLOT_BUFFER_ZONE + a > nursery.end)
index a7f44e73f8d66e60db5dea5d4945c5bb8e1acb5a..583696729573223c5bcd49ed2ca8046dd489eafa 100644 (file)
@@ -37,7 +37,6 @@ F_DATA_HEAP *data_heap;
 
 /* the 0th generation is where new objects are allocated. */
 #define NURSERY 0
-#define HAVE_NURSERY_P (data_heap->gen_count>1)
 /* where objects hang around */
 #define AGING (data_heap->gen_count-2)
 #define HAVE_AGING_P (data_heap->gen_count>2)