]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge git://github.com/Keyholder/factor into keyholder
authorDoug Coleman <erg@jobim.local>
Thu, 16 Apr 2009 20:21:20 +0000 (15:21 -0500)
committerDoug Coleman <erg@jobim.local>
Thu, 16 Apr 2009 20:21:20 +0000 (15:21 -0500)
468 files changed:
.gitignore
Makefile
README.txt
basis/alien/destructors/destructors.factor [changed mode: 0644->0755]
basis/alien/fortran/fortran-docs.factor
basis/alien/fortran/fortran.factor
basis/alien/syntax/tags.txt [new file with mode: 0644]
basis/assoc-heaps/assoc-heaps-docs.factor [deleted file]
basis/assoc-heaps/assoc-heaps-tests.factor [deleted file]
basis/assoc-heaps/assoc-heaps.factor [deleted file]
basis/assoc-heaps/authors.txt [deleted file]
basis/assoc-heaps/summary.txt [deleted file]
basis/base64/base64-tests.factor
basis/base64/base64.factor
basis/binary-search/binary-search-docs.factor
basis/bootstrap/stage2.factor
basis/calendar/calendar.factor
basis/colors/colors-docs.factor
basis/combinators/short-circuit/smart/tags.txt [new file with mode: 0644]
basis/combinators/short-circuit/tags.txt [new file with mode: 0644]
basis/combinators/smart/smart-docs.factor
basis/combinators/smart/smart.factor
basis/combinators/smart/tags.txt [new file with mode: 0644]
basis/command-line/command-line.factor
basis/compiler/cfg/linear-scan/allocation/allocation.factor
basis/compiler/tree/debugger/debugger.factor
basis/compiler/tree/propagation/info/info.factor
basis/compiler/tree/propagation/recursive/recursive.factor
basis/concurrency/conditions/conditions.factor
basis/concurrency/mailboxes/mailboxes-tests.factor
basis/concurrency/mailboxes/mailboxes.factor
basis/core-graphics/core-graphics-docs.factor [deleted file]
basis/db/errors/sqlite/sqlite.factor
basis/db/queries/queries.factor
basis/db/tuples/tuples-tests.factor
basis/delegate/protocols/protocols.factor
basis/editors/editors-docs.factor
basis/furnace/actions/actions.factor
basis/furnace/cache/cache.factor
basis/furnace/furnace.factor
basis/furnace/redirection/redirection.factor
basis/help/cookbook/cookbook.factor
basis/help/handbook/handbook.factor
basis/help/home/home-docs.factor
basis/help/home/home.factor
basis/help/html/html.factor
basis/help/syntax/tags.txt [new file with mode: 0644]
basis/help/tips/tips-docs.factor
basis/hints/hints.factor
basis/http/client/client.factor
basis/http/http-tests.factor
basis/http/server/static/static.factor
basis/images/bitmap/bitmap-tests.factor
basis/images/bitmap/bitmap.factor
basis/images/images.factor [changed mode: 0644->0755]
basis/images/loader/loader.factor
basis/images/normalization/authors.txt [deleted file]
basis/images/normalization/normalization.factor [deleted file]
basis/images/tiff/tiff.factor
basis/interpolate/tags.txt [new file with mode: 0644]
basis/io/files/unique/unique-docs.factor
basis/io/files/unique/unique.factor
basis/io/streams/limited/limited-tests.factor
basis/io/streams/limited/limited.factor
basis/lcs/lcs.factor
basis/locals/locals-docs.factor
basis/locals/locals-tests.factor
basis/math/blas/config/config-docs.factor [new file with mode: 0644]
basis/math/blas/config/config.factor [new file with mode: 0644]
basis/math/blas/ffi/ffi.factor
basis/math/blas/matrices/matrices-docs.factor
basis/math/functions/functions-docs.factor
basis/math/functions/functions-tests.factor
basis/math/functions/functions.factor
basis/math/intervals/intervals.factor
basis/math/libm/libm-docs.factor
basis/math/primes/factors/factors.factor
basis/math/ranges/ranges-docs.factor
basis/models/arrow/smart/smart-docs.factor [new file with mode: 0644]
basis/models/history/history-docs.factor [deleted file]
basis/models/history/history-tests.factor [deleted file]
basis/models/history/history.factor [deleted file]
basis/models/history/summary.txt [deleted file]
basis/models/models-docs.factor
basis/opengl/authors.txt
basis/opengl/capabilities/capabilities.factor
basis/opengl/gl/authors.txt
basis/opengl/glu/authors.txt [deleted file]
basis/opengl/glu/glu.factor [deleted file]
basis/opengl/glu/summary.txt [deleted file]
basis/opengl/glu/tags.txt [deleted file]
basis/opengl/opengl-docs.factor
basis/opengl/opengl.factor
basis/opengl/textures/textures-tests.factor
basis/opengl/textures/textures.factor [changed mode: 0644->0755]
basis/pack/pack.factor
basis/pango/layouts/layouts.factor
basis/peg/ebnf/tags.txt
basis/prettyprint/backend/backend.factor
basis/prettyprint/prettyprint-tests.factor
basis/regexp/ast/ast.factor
basis/regexp/dfa/dfa.factor
basis/regexp/parser/parser.factor
basis/regexp/transition-tables/transition-tables.factor
basis/see/see-docs.factor
basis/see/see-tests.factor [new file with mode: 0644]
basis/see/see.factor
basis/sorting/functor/authors.txt [new file with mode: 0644]
basis/sorting/functor/functor.factor [new file with mode: 0644]
basis/sorting/human/human-docs.factor
basis/sorting/human/human-tests.factor
basis/sorting/human/human.factor
basis/sorting/slots/slots-docs.factor
basis/sorting/slots/slots-tests.factor
basis/sorting/slots/slots.factor
basis/sorting/title/authors.txt [new file with mode: 0644]
basis/sorting/title/title-tests.factor [new file with mode: 0644]
basis/sorting/title/title.factor [new file with mode: 0644]
basis/stack-checker/known-words/known-words.factor
basis/stack-checker/transforms/transforms.factor
basis/tools/annotations/annotations-tests.factor
basis/tools/annotations/annotations.factor
basis/tools/deploy/backend/backend.factor
basis/tools/deploy/macosx/macosx.factor
basis/tools/deploy/shaker/shaker.factor
basis/tools/deploy/windows/windows.factor
basis/tools/disassembler/disassembler-tests.factor
basis/tools/disassembler/disassembler.factor
basis/tools/hexdump/hexdump.factor
basis/ui/backend/backend.factor
basis/ui/backend/cocoa/cocoa.factor
basis/ui/backend/cocoa/views/views.factor
basis/ui/backend/windows/windows.factor
basis/ui/backend/x11/x11.factor
basis/ui/gadgets/buttons/buttons-docs.factor
basis/ui/gadgets/editors/editors.factor
basis/ui/gadgets/gadgets.factor
basis/ui/gadgets/line-support/line-support.factor
basis/ui/gadgets/panes/panes.factor
basis/ui/gadgets/scrollers/scrollers-docs.factor
basis/ui/gadgets/scrollers/scrollers-tests.factor
basis/ui/gadgets/scrollers/scrollers.factor
basis/ui/gadgets/search-tables/search-tables-tests.factor [new file with mode: 0644]
basis/ui/gadgets/search-tables/search-tables.factor
basis/ui/gadgets/tables/tables.factor
basis/ui/gadgets/viewports/viewports.factor
basis/ui/gadgets/worlds/worlds.factor
basis/ui/images/images.factor [changed mode: 0644->0755]
basis/ui/render/render.factor
basis/ui/text/core-text/core-text.factor [changed mode: 0644->0755]
basis/ui/text/pango/pango.factor
basis/ui/text/pango/summary.txt [new file with mode: 0755]
basis/ui/text/text-tests.factor [changed mode: 0644->0755]
basis/ui/text/text.factor [changed mode: 0644->0755]
basis/ui/text/uniscribe/authors.txt [new file with mode: 0755]
basis/ui/text/uniscribe/summary.txt [new file with mode: 0755]
basis/ui/text/uniscribe/tags.txt [new file with mode: 0755]
basis/ui/text/uniscribe/uniscribe.factor [new file with mode: 0755]
basis/ui/tools/browser/browser.factor
basis/ui/tools/browser/history/authors.txt [new file with mode: 0644]
basis/ui/tools/browser/history/history-tests.factor [new file with mode: 0644]
basis/ui/tools/browser/history/history.factor [new file with mode: 0644]
basis/ui/tools/listener/completion/completion.factor
basis/ui/tools/tools-docs.factor
basis/ui/traverse/traverse-docs.factor [new file with mode: 0644]
basis/ui/traverse/traverse-tests.factor
basis/ui/traverse/traverse.factor
basis/ui/ui.factor
basis/unicode/categories/categories-tests.factor
basis/unicode/categories/categories.factor
basis/unicode/unicode-docs.factor
basis/urls/encoding/encoding-tests.factor
basis/urls/encoding/encoding.factor
basis/urls/prettyprint/prettyprint.factor
basis/urls/urls-docs.factor
basis/urls/urls-tests.factor
basis/urls/urls.factor
basis/values/values-docs.factor
basis/windows/fonts/fonts.factor [new file with mode: 0755]
basis/windows/gdi32/gdi32.factor
basis/windows/offscreen/authors.txt [new file with mode: 0644]
basis/windows/offscreen/offscreen-tests.factor [new file with mode: 0755]
basis/windows/offscreen/offscreen.factor [new file with mode: 0755]
basis/windows/offscreen/summary.txt [new file with mode: 0755]
basis/windows/offscreen/tags.txt [new file with mode: 0755]
basis/windows/types/types.factor
basis/windows/uniscribe/authors.txt [new file with mode: 0644]
basis/windows/uniscribe/summary.txt [new file with mode: 0755]
basis/windows/uniscribe/tags.txt [new file with mode: 0755]
basis/windows/uniscribe/uniscribe.factor [new file with mode: 0755]
basis/windows/usp10/usp10.factor
basis/windows/windows.factor [changed mode: 0644->0755]
basis/wrap/wrap.factor
basis/x11/windows/windows.factor
basis/xml/syntax/tags.txt
build-support/dlls.txt [deleted file]
build-support/factor.sh
core/alien/alien-tests.factor
core/alien/alien.factor
core/bootstrap/primitives.factor
core/bootstrap/syntax.factor
core/classes/builtin/builtin.factor
core/classes/classes.factor
core/classes/tuple/tuple-docs.factor
core/classes/tuple/tuple-tests.factor
core/combinators/combinators-docs.factor
core/definitions/definitions-docs.factor
core/definitions/definitions-tests.factor
core/definitions/definitions.factor
core/effects/effects-docs.factor
core/generic/generic-docs.factor
core/generic/generic-tests.factor
core/generic/generic.factor
core/generic/math/math-docs.factor
core/io/encodings/encodings-docs.factor
core/io/streams/c/c.factor
core/kernel/kernel-docs.factor
core/math/floats/floats-tests.factor
core/math/integers/integers.factor
core/math/math-docs.factor
core/math/order/order-docs.factor
core/math/parser/parser-docs.factor
core/math/parser/parser-tests.factor
core/math/parser/parser.factor
core/namespaces/namespaces-docs.factor
core/parser/parser-docs.factor
core/quotations/quotations-docs.factor
core/sequences/sequences-docs.factor
core/sequences/sequences-tests.factor
core/sequences/sequences.factor
core/slots/slots-docs.factor
core/syntax/syntax-docs.factor
core/syntax/syntax.factor
core/words/alias/alias.factor
core/words/constant/constant-tests.factor [new file with mode: 0644]
core/words/constant/constant.factor
core/words/symbol/symbol.factor
extra/4DNav/camera/camera.factor
extra/assoc-heaps/assoc-heaps-docs.factor [new file with mode: 0644]
extra/assoc-heaps/assoc-heaps-tests.factor [new file with mode: 0644]
extra/assoc-heaps/assoc-heaps.factor [new file with mode: 0644]
extra/assoc-heaps/authors.txt [new file with mode: 0644]
extra/assoc-heaps/summary.txt [new file with mode: 0644]
extra/benchmark/fib6/deploy.factor [new file with mode: 0644]
extra/benchmark/raytracer/raytracer.factor
extra/c/preprocessor/authors.txt [new file with mode: 0644]
extra/c/preprocessor/preprocessor-tests.factor [new file with mode: 0644]
extra/c/preprocessor/preprocessor.factor [new file with mode: 0644]
extra/c/tests/test1/README [new file with mode: 0644]
extra/c/tests/test1/hi.h [new file with mode: 0644]
extra/c/tests/test1/lo.h [new file with mode: 0644]
extra/c/tests/test1/test1.c [new file with mode: 0644]
extra/c/tests/test10/test10.c [new file with mode: 0644]
extra/c/tests/test11/foo.h [new file with mode: 0644]
extra/c/tests/test11/test11.c [new file with mode: 0644]
extra/c/tests/test12/test12.c [new file with mode: 0644]
extra/c/tests/test13/test13.c [new file with mode: 0644]
extra/c/tests/test14/test14.c [new file with mode: 0644]
extra/c/tests/test2/README [new file with mode: 0644]
extra/c/tests/test2/test2.c [new file with mode: 0644]
extra/c/tests/test3/README [new file with mode: 0644]
extra/c/tests/test3/test3.c [new file with mode: 0644]
extra/c/tests/test4/test4.c [new file with mode: 0644]
extra/c/tests/test5/test5.c [new file with mode: 0644]
extra/c/tests/test6/test6.c [new file with mode: 0644]
extra/c/tests/test7/test7.c [new file with mode: 0644]
extra/c/tests/test8/test8.c [new file with mode: 0644]
extra/c/tests/test9/test9.c [new file with mode: 0644]
extra/chicago-talk/deploy.factor [new file with mode: 0755]
extra/chicago-talk/summary.txt [new file with mode: 0755]
extra/chicago-talk/tags.txt [new file with mode: 0644]
extra/color-picker/deploy.factor
extra/color-table/color-table.factor
extra/db2/authors.txt [new file with mode: 0644]
extra/db2/connections/authors.txt [new file with mode: 0644]
extra/db2/connections/connections-tests.factor [new file with mode: 0644]
extra/db2/connections/connections.factor [new file with mode: 0644]
extra/db2/db2-tests.factor [new file with mode: 0644]
extra/db2/db2.factor [new file with mode: 0644]
extra/db2/errors/errors.factor [new file with mode: 0644]
extra/db2/errors/summary.txt [new file with mode: 0644]
extra/db2/fql/authors.txt [new file with mode: 0644]
extra/db2/fql/fql-tests.factor [new file with mode: 0644]
extra/db2/fql/fql.factor [new file with mode: 0644]
extra/db2/introspection/authors.txt [new file with mode: 0644]
extra/db2/introspection/introspection.factor [new file with mode: 0644]
extra/db2/pools/authors.txt [new file with mode: 0644]
extra/db2/pools/pools-tests.factor [new file with mode: 0644]
extra/db2/pools/pools.factor [new file with mode: 0644]
extra/db2/result-sets/authors.txt [new file with mode: 0644]
extra/db2/result-sets/result-sets.factor [new file with mode: 0644]
extra/db2/sqlite/authors.txt [new file with mode: 0644]
extra/db2/sqlite/connections/authors.txt [new file with mode: 0644]
extra/db2/sqlite/connections/connections-tests.factor [new file with mode: 0644]
extra/db2/sqlite/connections/connections.factor [new file with mode: 0644]
extra/db2/sqlite/db/authors.txt [new file with mode: 0644]
extra/db2/sqlite/db/db.factor [new file with mode: 0644]
extra/db2/sqlite/errors/authors.txt [new file with mode: 0644]
extra/db2/sqlite/errors/errors.factor [new file with mode: 0644]
extra/db2/sqlite/ffi/ffi.factor [new file with mode: 0644]
extra/db2/sqlite/introspection/authors.txt [new file with mode: 0644]
extra/db2/sqlite/introspection/introspection-tests.factor [new file with mode: 0644]
extra/db2/sqlite/introspection/introspection.factor [new file with mode: 0644]
extra/db2/sqlite/lib/lib.factor [new file with mode: 0644]
extra/db2/sqlite/result-sets/authors.txt [new file with mode: 0644]
extra/db2/sqlite/result-sets/result-sets.factor [new file with mode: 0644]
extra/db2/sqlite/sqlite.factor [new file with mode: 0644]
extra/db2/sqlite/statements/authors.txt [new file with mode: 0644]
extra/db2/sqlite/statements/statements.factor [new file with mode: 0644]
extra/db2/sqlite/types/authors.txt [new file with mode: 0644]
extra/db2/sqlite/types/types.factor [new file with mode: 0644]
extra/db2/statements/authors.txt [new file with mode: 0644]
extra/db2/statements/statements-tests.factor [new file with mode: 0644]
extra/db2/statements/statements.factor [new file with mode: 0644]
extra/db2/tester/authors.txt [new file with mode: 0644]
extra/db2/tester/tester-tests.factor [new file with mode: 0644]
extra/db2/tester/tester.factor [new file with mode: 0644]
extra/db2/transactions/authors.txt [new file with mode: 0644]
extra/db2/transactions/transactions.factor [new file with mode: 0644]
extra/db2/types/authors.txt [new file with mode: 0644]
extra/db2/types/types.factor [new file with mode: 0644]
extra/db2/utils/authors.txt [new file with mode: 0644]
extra/db2/utils/utils.factor [new file with mode: 0644]
extra/demos/demos.factor
extra/descriptive/descriptive-docs.factor
extra/descriptive/descriptive.factor
extra/descriptive/tags.txt [new file with mode: 0644]
extra/html/parser/analyzer/analyzer.factor
extra/html/parser/parser-tests.factor
extra/html/parser/parser.factor
extra/html/parser/state/state-tests.factor [deleted file]
extra/html/parser/state/state.factor [deleted file]
extra/html/parser/utils/utils.factor
extra/id3/id3-docs.factor
extra/id3/id3-tests.factor
extra/id3/id3.factor
extra/images/normalization/authors.txt [new file with mode: 0644]
extra/images/normalization/normalization.factor [new file with mode: 0755]
extra/irc/client/base/authors.txt [new file with mode: 0644]
extra/irc/client/base/base.factor [new file with mode: 0644]
extra/irc/client/chats/authors.txt [new file with mode: 0644]
extra/irc/client/chats/chats-docs.factor [new file with mode: 0644]
extra/irc/client/chats/chats.factor [new file with mode: 0644]
extra/irc/client/chats/summary.txt [new file with mode: 0644]
extra/irc/client/client-docs.factor
extra/irc/client/client-tests.factor [deleted file]
extra/irc/client/client.factor
extra/irc/client/internals/authors.txt [new file with mode: 0644]
extra/irc/client/internals/internals-tests.factor [new file with mode: 0644]
extra/irc/client/internals/internals.factor [new file with mode: 0644]
extra/irc/client/internals/summary.txt [new file with mode: 0644]
extra/irc/client/participants/authors.txt [new file with mode: 0644]
extra/irc/client/participants/participants.factor [new file with mode: 0644]
extra/irc/client/participants/summary.txt [new file with mode: 0644]
extra/irc/gitbot/gitbot.factor
extra/irc/logbot/authors.txt [new file with mode: 0644]
extra/irc/logbot/log-line/authors.txt [new file with mode: 0644]
extra/irc/logbot/log-line/log-line.factor [new file with mode: 0644]
extra/irc/logbot/log-line/summary.txt [new file with mode: 0644]
extra/irc/logbot/logbot.factor [new file with mode: 0644]
extra/irc/logbot/summary.txt [new file with mode: 0644]
extra/irc/messages/base/authors.txt [new file with mode: 0644]
extra/irc/messages/base/base.factor [new file with mode: 0644]
extra/irc/messages/base/summary.txt [new file with mode: 0644]
extra/irc/messages/messages-tests.factor
extra/irc/messages/messages.factor
extra/irc/messages/parser/authors.txt [new file with mode: 0644]
extra/irc/messages/parser/parser.factor [new file with mode: 0644]
extra/irc/messages/parser/summary.txt [new file with mode: 0644]
extra/irc/messages/summary.txt [new file with mode: 0644]
extra/mason/child/child-tests.factor
extra/mason/child/child.factor [changed mode: 0644->0755]
extra/mason/cleanup/cleanup.factor [changed mode: 0644->0755]
extra/mason/common/common.factor [changed mode: 0644->0755]
extra/mason/release/archive/archive.factor [changed mode: 0644->0755]
extra/mason/release/tidy/tidy.factor [changed mode: 0644->0755]
extra/mason/test/test.factor
extra/math/analysis/analysis.factor
extra/minneapolis-talk/deploy.factor
extra/minneapolis-talk/summary.txt
extra/models/history/history-docs.factor [new file with mode: 0644]
extra/models/history/history-tests.factor [new file with mode: 0644]
extra/models/history/history.factor [new file with mode: 0644]
extra/models/history/summary.txt [new file with mode: 0644]
extra/multi-methods/tags.txt [new file with mode: 0644]
extra/opengl/glu/authors.txt [new file with mode: 0644]
extra/opengl/glu/glu.factor [new file with mode: 0644]
extra/opengl/glu/summary.txt [new file with mode: 0644]
extra/opengl/glu/tags.txt [new file with mode: 0644]
extra/peg-lexer/tags.txt
extra/peg/pl0/pl0.factor
extra/poker/arrays/arrays.factor [new file with mode: 0644]
extra/poker/authors.txt [new file with mode: 0644]
extra/poker/poker-docs.factor [new file with mode: 0644]
extra/poker/poker-tests.factor [new file with mode: 0644]
extra/poker/poker.factor [new file with mode: 0644]
extra/poker/summary.txt [new file with mode: 0644]
extra/project-euler/001/001-tests.factor
extra/project-euler/001/001.factor
extra/project-euler/004/004.factor
extra/project-euler/007/007.factor
extra/project-euler/014/014.factor
extra/project-euler/033/033.factor
extra/project-euler/043/043.factor
extra/project-euler/049/049-tests.factor [new file with mode: 0644]
extra/project-euler/049/049.factor [new file with mode: 0644]
extra/project-euler/052/052.factor
extra/project-euler/054/054-tests.factor [new file with mode: 0644]
extra/project-euler/054/054.factor [new file with mode: 0644]
extra/project-euler/054/poker.txt [new file with mode: 0644]
extra/project-euler/058/058-tests.factor [new file with mode: 0644]
extra/project-euler/058/058.factor [new file with mode: 0644]
extra/project-euler/063/063-tests.factor [new file with mode: 0644]
extra/project-euler/063/063.factor [new file with mode: 0644]
extra/project-euler/069/069-tests.factor [new file with mode: 0644]
extra/project-euler/069/069.factor [new file with mode: 0644]
extra/project-euler/071/071.factor
extra/project-euler/common/common.factor
extra/project-euler/project-euler.factor
extra/robots/robots-tests.factor
extra/robots/robots.factor
extra/sequence-parser/sequence-parser-tests.factor [new file with mode: 0644]
extra/sequence-parser/sequence-parser.factor [new file with mode: 0644]
extra/site-watcher/db/db.factor
extra/site-watcher/email/authors.txt [new file with mode: 0644]
extra/site-watcher/email/email.factor [new file with mode: 0644]
extra/site-watcher/site-watcher-tests.factor
extra/site-watcher/site-watcher.factor
extra/site-watcher/spider/authors.txt [new file with mode: 0644]
extra/site-watcher/spider/spider.factor [new file with mode: 0644]
extra/spider/report/authors.txt [new file with mode: 0644]
extra/spider/report/report.factor [new file with mode: 0644]
extra/spider/spider.factor
extra/spider/unique-deque/authors.txt [new file with mode: 0644]
extra/spider/unique-deque/unique-deque.factor [new file with mode: 0644]
extra/tar/tar.factor
extra/tetris/gl/gl.factor
extra/ui/offscreen/offscreen-docs.factor
extra/ui/offscreen/offscreen.factor
extra/ui/offscreen/tags.txt
extra/webapps/site-watcher/common/authors.txt [new file with mode: 0644]
extra/webapps/site-watcher/common/common.factor [new file with mode: 0644]
extra/webapps/site-watcher/common/main.xml [new file with mode: 0644]
extra/webapps/site-watcher/common/site-list.xml [new file with mode: 0644]
extra/webapps/site-watcher/common/site-watcher.xml [new file with mode: 0644]
extra/webapps/site-watcher/common/spider-list.xml [new file with mode: 0644]
extra/webapps/site-watcher/common/update-notify.xml [new file with mode: 0644]
extra/webapps/site-watcher/main.xml [deleted file]
extra/webapps/site-watcher/site-list.xml [deleted file]
extra/webapps/site-watcher/site-watcher.factor
extra/webapps/site-watcher/site-watcher.xml [deleted file]
extra/webapps/site-watcher/spidering/authors.txt [new file with mode: 0644]
extra/webapps/site-watcher/spidering/spidering.factor [new file with mode: 0644]
extra/webapps/site-watcher/update-notify.xml [deleted file]
extra/webapps/site-watcher/watching/authors.txt [new file with mode: 0644]
extra/webapps/site-watcher/watching/watching.factor [new file with mode: 0644]
misc/fuel/fuel-font-lock.el
misc/fuel/fuel-refactor.el
misc/fuel/fuel-syntax.el
vm/Config.unix
vm/factor.c
vm/image.c
vm/io.c
vm/io.h
vm/os-unix.h
vm/os-windows.h
vm/platform.h
vm/primitives.c

index 22dda8efb4b7d80d0abffccb5a77eeb385b6d221..aa877b1cb593c73b54bd4ca85ee30064de9c0f4b 100644 (file)
@@ -25,3 +25,4 @@ build-support/wordsize
 .#*
 *.swo
 checksums.txt
+a.out
index 5e63017218230ffe80f20e0084d7c551eccc01c7..35a5ba58bfac5e73a25aa4911718dce7262bb955 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -166,7 +166,7 @@ factor-ffi-test: vm/ffi_test.o
 
 clean:
        rm -f vm/*.o
-       rm -f factor*.dll libfactor.{a,so,dylib} libfactor-ffi-test.{a,so,dylib}
+       rm -f factor*.dll libfactor.{a,so,dylib} libfactor-ffi-test.{a,so,dylib} Factor.app/Contents/Frameworks/libfactor.dylib
 
 vm/resources.o:
        $(WINDRES) vm/factor.rs vm/resources.o
index bd9da0ab2bc85318bf37526af68a75b4ca312ecb..c5d53de84275c86a69f8b4eb7394800fbd98ea8c 100755 (executable)
@@ -113,12 +113,6 @@ the command prompt using the console application:
 
   factor.com -i=boot.<cpu>.image
 
-Before bootstrapping, you will need to download the DLLs for the Pango
-text rendering library. The required DLLs are listed in
-build-support/dlls.txt and are available from the following location:
-
-  <http://factorcode.org/dlls>
-
 Once bootstrapped, double-clicking factor.exe or factor.com starts
 the Factor UI.
 
old mode 100644 (file)
new mode 100755 (executable)
index 1b6022d..374d642
@@ -1,6 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: functors destructors accessors kernel parser words ;
+USING: functors destructors accessors kernel parser words
+effects generalizations sequences ;
 IN: alien.destructors
 
 SLOT: alien
@@ -11,6 +12,7 @@ F-destructor DEFINES-CLASS ${F}-destructor
 <F-destructor> DEFINES <${F}-destructor>
 &F DEFINES &${F}
 |F DEFINES |${F}
+N [ F stack-effect out>> length ]
 
 WHERE
 
@@ -18,7 +20,7 @@ TUPLE: F-destructor alien disposed ;
 
 : <F-destructor> ( alien -- destructor ) f F-destructor boa ; inline
 
-M: F-destructor dispose* alien>> F ;
+M: F-destructor dispose* alien>> F N ndrop ;
 
 : &F ( alien -- alien ) dup <F-destructor> &dispose drop ; inline
 
index c5d124e198a744be4eb80b68eae43ae2812f0eba..8027020c75004e57e0a50fea5dc5fd7c8c8b54d9 100644 (file)
@@ -7,10 +7,10 @@ IN: alien.fortran
 ARTICLE: "alien.fortran-abis" "Fortran ABIs"
 "Fortran does not have a standard ABI like C does. Factor supports the following Fortran ABIs:"
 { $list
-    { { $subsection gfortran-abi } " is used by gfortran, the Fortran compiler included with GCC 4." }
-    { { $subsection f2c-abi } " is used by the F2C Fortran-to-C translator and G77, the Fortran compiler included with GCC 3.x and earlier. It is also used by gfortran when compiling with the -ff2c flag." }
-    { { $subsection intel-unix-abi } " is used by the Intel Fortran Compiler on Linux and Mac OS X." }
-    { { $subsection intel-windows-abi } " is used by the Intel Fortran Compiler on Windows." }
+    { { $link gfortran-abi } " is used by gfortran, the Fortran compiler included with GCC 4." }
+    { { $link f2c-abi } " is used by the F2C Fortran-to-C translator and G77, the Fortran compiler included with GCC 3.x and earlier. It is also used by gfortran when compiling with the -ff2c flag." }
+    { { $link intel-unix-abi } " is used by the Intel Fortran Compiler on Linux and Mac OS X." }
+    { { $link intel-windows-abi } " is used by the Intel Fortran Compiler on Windows." }
 }
 "A library's ABI is specified when that library is opened by the " { $link add-fortran-library } " word." ;
 
index 71efa1aa24760b77a63bf8165ee44d12daf47b8f..b27c62b9a1399691b3bae335eeb2bebcddcf78b8 100644 (file)
@@ -8,7 +8,7 @@ io.encodings.ascii io.encodings.string shuffle effects math.ranges
 math.order sorting strings system alien.libraries ;
 IN: alien.fortran
 
-SINGLETONS: f2c-abi gfortran-abi intel-unix-abi intel-windows-abi ;
+SINGLETONS: f2c-abi g95-abi gfortran-abi intel-unix-abi intel-windows-abi ;
 
 << 
 : add-f2c-libraries ( -- )
@@ -42,30 +42,35 @@ library-fortran-abis [ H{ } clone ] initialize
 
 HOOK: fortran-c-abi fortran-abi ( -- abi )
 M: f2c-abi fortran-c-abi "cdecl" ;
+M: g95-abi fortran-c-abi "cdecl" ;
 M: gfortran-abi fortran-c-abi "cdecl" ;
 M: intel-unix-abi fortran-c-abi "cdecl" ;
 M: intel-windows-abi fortran-c-abi "cdecl" ;
 
 HOOK: real-functions-return-double? fortran-abi ( -- ? )
 M: f2c-abi real-functions-return-double? t ;
+M: g95-abi real-functions-return-double? f ;
 M: gfortran-abi real-functions-return-double? f ;
 M: intel-unix-abi real-functions-return-double? f ;
 M: intel-windows-abi real-functions-return-double? f ;
 
 HOOK: complex-functions-return-by-value? fortran-abi ( -- ? )
 M: f2c-abi complex-functions-return-by-value? f ;
+M: g95-abi complex-functions-return-by-value? f ;
 M: gfortran-abi complex-functions-return-by-value? t ;
 M: intel-unix-abi complex-functions-return-by-value? f ;
 M: intel-windows-abi complex-functions-return-by-value? f ;
 
 HOOK: character(1)-maps-to-char? fortran-abi ( -- ? )
 M: f2c-abi character(1)-maps-to-char? f ;
+M: g95-abi character(1)-maps-to-char? f ;
 M: gfortran-abi character(1)-maps-to-char? f ;
 M: intel-unix-abi character(1)-maps-to-char? t ;
 M: intel-windows-abi character(1)-maps-to-char? t ;
 
 HOOK: mangle-name fortran-abi ( name -- name' )
 M: f2c-abi mangle-name lowercase-name-with-extra-underscore ;
+M: g95-abi mangle-name lowercase-name-with-extra-underscore ;
 M: gfortran-abi mangle-name lowercase-name-with-underscore ;
 M: intel-unix-abi mangle-name lowercase-name-with-underscore ;
 M: intel-windows-abi mangle-name >upper ;
diff --git a/basis/alien/syntax/tags.txt b/basis/alien/syntax/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
diff --git a/basis/assoc-heaps/assoc-heaps-docs.factor b/basis/assoc-heaps/assoc-heaps-docs.factor
deleted file mode 100644 (file)
index b148995..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: help.markup help.syntax io.streams.string assocs
-heaps.private ;
-IN: assoc-heaps
-
-HELP: <assoc-heap>
-{ $values { "assoc" assoc } { "heap" heap } { "assoc-heap" assoc-heap } }
-{ $description "Constructs a new " { $link assoc-heap } " from two existing data structures." } ;
-
-HELP: <unique-max-heap>
-{ $values { "unique-heap" assoc-heap } }
-{ $description "Creates a new " { $link assoc-heap } " where the assoc is a hashtable and the heap is a max-heap. Popping an element from the heap leaves this element in the hashtable to ensure that the element will not be processed again." } ;
-
-HELP: <unique-min-heap>
-{ $values { "unique-heap" assoc-heap } }
-{ $description "Creates a new " { $link assoc-heap } " where the assoc is a hashtable and the heap is a min-heap. Popping an element from the heap leaves this element in the hashtable to ensure that the element will not be processed again." } ;
-
-{ <unique-max-heap> <unique-min-heap> } related-words
-
-HELP: assoc-heap
-{ $description "A data structure containing an assoc and a heap to get certain properties with better time constraints at the expense of more space and complexity. For instance, a hashtable and a heap can be combined into one assoc-heap to get a sorted data structure with O(1) lookup. Operations on assoc-heap may update both the assoc and the heap or leave them out of sync if it's advantageous." } ;
-
-ARTICLE: "assoc-heaps" "Associative heaps"
-"The " { $vocab-link "assoc-heaps" } " vocabulary combines exists to synthesize data structures with better time properties than either of the two component data structures alone." $nl
-"Associative heap constructor:"
-{ $subsection <assoc-heap> }
-"Unique heaps:"
-{ $subsection <unique-min-heap> }
-{ $subsection <unique-max-heap> } ;
-
-ABOUT: "assoc-heaps"
diff --git a/basis/assoc-heaps/assoc-heaps-tests.factor b/basis/assoc-heaps/assoc-heaps-tests.factor
deleted file mode 100644 (file)
index 6ea3fe1..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: tools.test assoc-heaps ;
-IN: assoc-heaps.tests
diff --git a/basis/assoc-heaps/assoc-heaps.factor b/basis/assoc-heaps/assoc-heaps.factor
deleted file mode 100644 (file)
index a495aed..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-! Copyright (C) 2008 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs hashtables heaps kernel ;
-IN: assoc-heaps
-
-TUPLE: assoc-heap assoc heap ;
-
-C: <assoc-heap> assoc-heap
-
-: <unique-min-heap> ( -- unique-heap )
-    H{ } clone <min-heap> <assoc-heap> ;
-
-: <unique-max-heap> ( -- unique-heap )
-    H{ } clone <max-heap> <assoc-heap> ;
-
-M: assoc-heap heap-push* ( value key assoc-heap -- entry )
-    pick over assoc>> key? [
-        3drop f
-    ] [
-        [ assoc>> swapd set-at ] [ heap>> heap-push* ] 3bi
-    ] if ;
-
-M: assoc-heap heap-pop ( assoc-heap -- value key )
-    heap>> heap-pop ;
-
-M: assoc-heap heap-peek ( assoc-heap -- value key )
-    heap>> heap-peek ;
-
-M: assoc-heap heap-empty? ( assoc-heap -- value key )
-    heap>> heap-empty? ;
diff --git a/basis/assoc-heaps/authors.txt b/basis/assoc-heaps/authors.txt
deleted file mode 100644 (file)
index b4bd0e7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
\ No newline at end of file
diff --git a/basis/assoc-heaps/summary.txt b/basis/assoc-heaps/summary.txt
deleted file mode 100644 (file)
index 792be0a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Priority queue with fast insertion, removal of first element, and lookup of arbitrary elements by key
index ddefff35bb653a57356a502a5d997e4859bdabbc..572d8a5227db00f68e687376b5fa05658f811b21 100644 (file)
@@ -23,5 +23,8 @@ IN: base64.tests
     ascii encode >base64-lines >string
 ] unit-test
 
+[ { 33 52 17 40 12 51 33 43 18 33 23 } base64> ]
+[ malformed-base64? ] must-fail-with
+
 \ >base64 must-infer
 \ base64> must-infer
index c51d871bb5996009d8a3b226c81bc29901b5cef3..47147fa3066f90711f64dc5d6d1266f17b6c7fca 100644 (file)
@@ -5,6 +5,8 @@ io.streams.byte-array kernel math namespaces
 sequences strings io.crlf ;
 IN: base64
 
+ERROR: malformed-base64 ;
+
 <PRIVATE
 
 : read1-ignoring ( ignoring -- ch )
@@ -25,7 +27,7 @@ IN: base64
         f 0 f f f 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
         22 23 24 25 f f f f f f 26 27 28 29 30 31 32 33 34 35 36 37 38 39
         40 41 42 43 44 45 46 47 48 49 50 51
-    } nth ; inline
+    } nth [ malformed-base64 ] unless* ; inline
 
 SYMBOL: column
 
@@ -48,8 +50,6 @@ SYMBOL: column
     [ 3 0 pad-tail binary [ encode3 ] with-byte-writer ]
     [ 1+ ] bi* head-slice 4 CHAR: = pad-tail write-lines ; inline
 
-ERROR: malformed-base64 ;
-
 : decode4 ( seq -- )
     [ 0 [ base64>ch swap 6 shift bitor ] reduce 3 >be ]
     [ [ CHAR: = = ] count ] bi head-slice*
index cf7915159abb5a4dc1cba1c2a3b3d80a7ef47a83..20b33a0bcbf3e5dbf492fb743e20331f5234e423 100644 (file)
@@ -14,7 +14,7 @@ $nl
 
 HELP: sorted-index
 { $values { "obj" object } { "seq" "a sorted sequence" } { "i" "an index, or " { $link f } } }
-{ $description "Outputs the index and value of the element closest to " { $snippet "elt" } " in the sequence. See " { $link search } " for details." }
+{ $description "Outputs the index of the element closest to " { $snippet "elt" } " in the sequence. See " { $link search } " for details." }
 { $notes "If the sequence has at least one element, this word always outputs a valid index, because it finds the closest match, not necessarily an exact one. In this respect its behavior differs from " { $link index } "." } ;
 
 { index index-from last-index last-index-from sorted-index } related-words
index 6c824b6155745e7b1cdac3be454ae76a128c896d..12741f2170fba9dbb826481b26664cabdfc58b11 100644 (file)
@@ -45,11 +45,18 @@ SYMBOL: bootstrap-time
     [ optimized>> ] count-words " compiled words" print
     [ symbol? ] count-words " symbol words" print
     [ ] count-words " words total" print
-
+    
     "Bootstrapping is complete." print
     "Now, you can run Factor:" print
     vm write " -i=" write "output-image" get print flush ;
 
+: save/restore-error ( quot -- )
+    error get-global
+    error-continuation get-global
+    [ call ] 2dip
+    error-continuation set-global
+    error set-global ; inline
+
 [
     ! We time bootstrap
     millis
@@ -104,6 +111,7 @@ SYMBOL: bootstrap-time
     drop
     [
         load-help? off
-        "vocab:bootstrap/bootstrap-error.factor" run-file
+        [ "vocab:bootstrap/bootstrap-error.factor" parse-file ] save/restore-error
+        call
     ] with-scope
 ] recover
index 104941ddb21adfc07167000056ad5da6f04fead4..7a03fe44089323f929f406fd4a0e6001fa6ae35d 100644 (file)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2007 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays kernel math math.functions namespaces sequences
-strings system vocabs.loader threads accessors combinators
-locals classes.tuple math.order summary combinators.short-circuit ;
+USING: accessors arrays classes.tuple combinators combinators.short-circuit
+    kernel locals math math.functions math.order namespaces sequences strings
+    summary system threads vocabs.loader ;
 IN: calendar
 
 HOOK: gmt-offset os ( -- hours minutes seconds )
@@ -136,7 +136,7 @@ CONSTANT: day-abbreviations3
 GENERIC: leap-year? ( obj -- ? )
 
 M: integer leap-year? ( year -- ? )
-    dup 100 mod zero? 400 4 ? mod zero? ;
+    dup 100 divisor? 400 4 ? divisor? ;
 
 M: timestamp leap-year? ( timestamp -- ? )
     year>> leap-year? ;
@@ -348,7 +348,7 @@ M: duration time-
     #! good for any date since October 15, 1582
     [
         dup 2 <= [ [ 1- ] [ 12 + ] bi* ] when
-        [ dup [ 4 /i + ] keep [ 100 /i - ] keep 400 /i + ] dip
+        [ dup [ 4 /i + ] [ 100 /i - ] [ 400 /i + ] tri ] dip
         [ 1+ 3 * 5 /i + ] keep 2 * +
     ] dip 1+ + 7 mod ;
 
index 8881d8971144a6ef8aec3b662b7851c05e28fa35..5e2b09380dbb1264b839d0afd4fb1434c3daced9 100644 (file)
@@ -23,7 +23,7 @@ $nl
 ARTICLE: "colors" "Colors"
 "The " { $vocab-link "colors" } " vocabulary defines a protocol for colors, with a concrete implementation for RGBA colors. This vocabulary is used by " { $vocab-link "io.styles" } ", " { $vocab-link "ui" } " and other vocabularies, but it is independent of them."
 $nl
-"RGBA colors:"
+"RGBA colors with floating point components in the range " { $snippet "[0,1]" } ":"
 { $subsection rgba }
 { $subsection <rgba> }
 "Converting a color to RGBA:"
diff --git a/basis/combinators/short-circuit/smart/tags.txt b/basis/combinators/short-circuit/smart/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
diff --git a/basis/combinators/short-circuit/tags.txt b/basis/combinators/short-circuit/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
index 75f83c1a5576ac46185c98bb069d7e96e817c20b..679b5877594d7af40cdfb0b1b6bca227ee0e92f5 100644 (file)
@@ -108,17 +108,19 @@ HELP: append-outputs-as
 
 
 ARTICLE: "combinators.smart" "Smart combinators"
-"The " { $vocab-link "combinators.smart" } " vocabulary implements " { $emphasis "smart combinators" } ". A smart combinator is one whose behavior depends on the static stack effect of an input quotation." $nl
-"Smart inputs from a sequence:"
+"The macros in the " { $vocab-link "combinators.smart" } " vocabulary look at the static stack effects of input quotations and generate code which produces or consumes the relevant number of stack values." $nl
+"Call a quotation and discard all output values:"
+{ $subsection drop-outputs }
+"Take all input values from a sequence:"
 { $subsection input<sequence }
-"Smart outputs to a sequence:"
+"Store all output values to a sequence:"
 { $subsection output>sequence }
 { $subsection output>array }
-"Reducing the output of a quotation:"
+"Reducing the set of output values:"
 { $subsection reduce-outputs }
-"Summing the output of a quotation:"
+"Summing output values:"
 { $subsection sum-outputs }
-"Appending the results of a quotation:"
+"Concatenating output values:"
 { $subsection append-outputs }
 { $subsection append-outputs-as } ;
 
index e7bdd75ced39028508cd709d1c41d53ae75772c3..aa7960539cca6f6d66c022b8262911481c0f06d1 100644 (file)
@@ -4,6 +4,9 @@ USING: accessors fry generalizations kernel macros math.order
 stack-checker math ;
 IN: combinators.smart
 
+MACRO: drop-outputs ( quot -- quot' )
+    dup infer out>> '[ @ _ ndrop ] ;
+
 MACRO: output>sequence ( quot exemplar -- newquot )
     [ dup infer out>> ] dip
     '[ @ _ _ nsequence ] ;
diff --git a/basis/combinators/smart/tags.txt b/basis/combinators/smart/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
index 73a01aa352a7640fae860fb429a51243ed602caf..56d7fbd2070bcf8366e3eab60347ee03cd2cb750 100644 (file)
@@ -60,7 +60,6 @@ SYMBOL: main-vocab-hook
 : default-cli-args ( -- )
     global [
         "quiet" off
-        "script" off
         "e" off
         "user-init" on
         embedded? "quiet" set
index 8d00a14ea2142c69463605ef53404dae56607f19..908bf2475b980e154ffdf445699ccf3466f64e32 100644 (file)
@@ -99,7 +99,7 @@ SYMBOL: spill-counts
 : 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
-    unclip-slice [ [ [ second ] bi@ > ] most ] reduce first ;
+    [ ] [ [ [ second ] bi@ > ] most ] map-reduce first ;
 
 : assign-spill ( before after -- before after )
     #! If it has been spilled already, reuse spill location.
index 430424291ebc19c338c5441ccbd32e915c0bc58a..8e102e0ea3cc9bc6da4dd3b768ad5d9ac1d852ad 100644 (file)
@@ -130,8 +130,6 @@ M: node node>quot drop ;
 
 GENERIC: optimized. ( quot/word -- )
 
-M: method-spec optimized. first2 method optimized. ;
-
 M: word optimized. specialized-def optimized. ;
 
 M: callable optimized. build-tree optimize-tree nodes>quot . ;
index c56db570b21735c1c0574d45ccec102ec1ccd00c..a22b7aa1727f70f801c062b5a16279fffac94a17 100644 (file)
@@ -238,7 +238,7 @@ DEFER: (value-info-union)
 
 : value-infos-union ( infos -- info )
     [ null-info ]
-    [ unclip-slice [ value-info-union ] reduce ] if-empty ;
+    [ [ ] [ value-info-union ] map-reduce ] if-empty ;
 
 : literals<= ( info1 info2 -- ? )
     {
index 1bcd36f6b0a6a285551c197d961e64e8f3315e91..b8d1760a0b4edaf7aca4e780b8fe858a54e4f931 100644 (file)
@@ -28,8 +28,8 @@ IN: compiler.tree.propagation.recursive
     {
         { [ 2dup interval-subset? ] [ empty-interval ] }
         { [ over empty-interval eq? ] [ empty-interval ] }
-        { [ 2dup interval>= t eq? ] [ 1./0. [a,a] ] }
-        { [ 2dup interval<= t eq? ] [ -1./0. [a,a] ] }
+        { [ 2dup interval>= t eq? ] [ 1/0. [a,a] ] }
+        { [ 2dup interval<= t eq? ] [ -1/0. [a,a] ] }
         [ [-inf,inf] ]
     } cond interval-union nip ;
 
index 11e624110c634e790eb1d88cd4ba41f20c84da91..ad00bbdfa9ff262ca7f36af3248efc478c81f4c5 100644 (file)
@@ -20,10 +20,12 @@ IN: concurrency.conditions
         ]\r
     ] dip later ;\r
 \r
+ERROR: wait-timeout ;\r
+\r
 : wait ( queue timeout status -- )\r
     over [\r
         [ queue-timeout [ drop ] ] dip suspend\r
-        [ "Timeout" throw ] [ cancel-alarm ] if\r
+        [ wait-timeout ] [ cancel-alarm ] if\r
     ] [\r
         [ drop '[ _ push-front ] ] dip suspend drop\r
     ] if ;\r
index 64971eeb77c95f7b45322d4987efd1bd4038a9d2..81e54f18078d907f7740ec97dafd371140eaf837 100644 (file)
@@ -1,6 +1,6 @@
 IN: concurrency.mailboxes.tests\r
-USING: concurrency.mailboxes concurrency.count-downs vectors\r
-sequences threads tools.test math kernel strings namespaces\r
+USING: concurrency.mailboxes concurrency.count-downs concurrency.conditions\r
+vectors sequences threads tools.test math kernel strings namespaces\r
 continuations calendar destructors ;\r
 \r
 { 1 1 } [ [ integer? ] mailbox-get? ] must-infer-as\r
@@ -75,3 +75,15 @@ continuations calendar destructors ;
 [ ] [ "d" get 5 seconds await-timeout ] unit-test\r
 \r
 [ ] [ "m" get dispose ] unit-test\r
+\r
+[ { "foo" "bar" } ] [\r
+    <mailbox>\r
+    "foo" over mailbox-put\r
+    "bar" over mailbox-put\r
+    mailbox-get-all\r
+] unit-test\r
+\r
+[\r
+    <mailbox> 1 seconds mailbox-get-timeout\r
+] [ wait-timeout? ] must-fail-with\r
+    
\ No newline at end of file
index f6aec94b4140de12537dbc0e9e8a83bfe3c79a51..200adb14aea9148793785c66458504ce70e6e8e7 100755 (executable)
@@ -49,7 +49,7 @@ M: mailbox dispose* threads>> notify-all ;
 \r
 : mailbox-get-all-timeout ( mailbox timeout -- array )\r
     block-if-empty\r
-    [ dup mailbox-empty? ]\r
+    [ dup mailbox-empty? not ]\r
     [ dup data>> pop-back ]\r
     produce nip ;\r
 \r
diff --git a/basis/core-graphics/core-graphics-docs.factor b/basis/core-graphics/core-graphics-docs.factor
deleted file mode 100644 (file)
index e69de29..0000000
index c247a36257b20032a4bb1c385c1e27e41c908213..c73409b850b576aeb0231f34f63634f9e9af0ae7 100644 (file)
@@ -4,7 +4,8 @@ USING: accessors combinators db kernel sequences peg.ebnf
 strings db.errors ;
 IN: db.errors.sqlite
 
-ERROR: unparsed-sqlite-error error ;
+TUPLE: unparsed-sqlite-error error ;
+C: <unparsed-sqlite-error> unparsed-sqlite-error
 
 SINGLETONS: table-exists table-missing ;
 
@@ -22,4 +23,6 @@ SqliteError =
       => [[ table >string message sqlite-table-error ]]
     | "no such table: " .+:table
       => [[ table >string <sql-table-missing> ]]
+    | .*:error
+      => [[ error >string <unparsed-sqlite-error> ]]
 ;EBNF
index 2730340bfc11c376936e7b19da3989336c47886f..c4aa47d383b3a1281ff091887449bb6e6ad39be6 100755 (executable)
@@ -4,7 +4,7 @@ USING: accessors kernel math namespaces make sequences random
 strings math.parser math.intervals combinators math.bitwise
 nmake db db.tuples db.types classes words shuffle arrays
 destructors continuations db.tuples.private prettyprint
-db.private ;
+db.private byte-arrays ;
 IN: db.queries
 
 GENERIC: where ( specs obj -- )
@@ -115,6 +115,9 @@ M: sequence where ( spec obj -- )
         [ " or " 0% ] [ dupd where ] interleave drop
     ] in-parens ;
 
+M: byte-array where ( spec obj -- )
+    over column-name>> 0% " = " 0% bind# ;
+
 M: NULL where ( spec obj -- )
     drop column-name>> 0% " is NULL" 0% ;
 
index 50d7f044d169336e111d806a7f929cfbfebcd3df..375ee509bba339b85ba0a63e7c7cb7142492345c 100644 (file)
@@ -411,7 +411,7 @@ TUPLE: exam id name score ;
             T{ exam f 4 "Cartman" 41 }
         }
     ] [
-        T{ exam f T{ interval f { 2 t } { 1.0/0.0 f } } } select-tuples
+        T{ exam f T{ interval f { 2 t } { 1/0. f } } } select-tuples
     ] unit-test
 
     [
@@ -419,7 +419,7 @@ TUPLE: exam id name score ;
             T{ exam f 1 "Kyle" 100 }
         }
     ] [
-        T{ exam f T{ interval f { -1.0/0.0 t } { 2 f } } } select-tuples
+        T{ exam f T{ interval f { -1/0. t } { 2 f } } } select-tuples
     ] unit-test
 
     [
@@ -430,7 +430,7 @@ TUPLE: exam id name score ;
             T{ exam f 4 "Cartman" 41 }
         }
     ] [
-        T{ exam f T{ interval f { -1.0/0.0 t } { 1/0. f } } } select-tuples
+        T{ exam f T{ interval f { -1/0. t } { 1/0. f } } } select-tuples
     ] unit-test
     
     [
@@ -634,3 +634,22 @@ compound-foo "COMPOUND_FOO"
 
 [ test-compound-primary-key ] test-sqlite
 [ test-compound-primary-key ] test-postgresql
+
+
+TUPLE: example id data ;
+
+example "EXAMPLE"
+{
+    { "id" "ID" +db-assigned-id+ }
+    { "data" "DATA" BLOB }
+} define-persistent
+
+: test-blob-select ( -- )
+    example ensure-table
+    [ ] [ example new B{ 1 2 3 4 5 } >>data insert-tuple ] unit-test
+    [
+        T{ example { id 1 } { data B{ 1 2 3 4 5 } } }
+    ] [ example new B{ 1 2 3 4 5 } >>data select-tuple ] unit-test ;
+
+[ test-blob-select ] test-sqlite
+[ test-blob-select ] test-postgresql
index f568a3e3885b09285c3a02c7b16dc895348d6fd8..40054bc4b0f721858c81efe706880855898d83d3 100644 (file)
@@ -1,7 +1,6 @@
 ! Copyright (C) 2007 Daniel Ehrenberg
 ! See http://factorcode.org/license.txt for BSD license.
-USING: delegate sequences.private sequences assocs
-io definitions kernel continuations ;
+USING: delegate sequences.private sequences assocs io ;
 IN: delegate.protocols
 
 PROTOCOL: sequence-protocol
@@ -19,7 +18,3 @@ stream-read-until ;
 
 PROTOCOL: output-stream-protocol
 stream-flush stream-write1 stream-write stream-nl ;
-
-PROTOCOL: definition-protocol
-where set-where forget uses
-synopsis* definer definition ;
index 0f50e40eb404f25d65061abd0a10c7710ba7d94d..e3961aef80dbab80e76181fe54fdf46f3b73e02e 100644 (file)
@@ -22,7 +22,7 @@ HELP: edit
     "A word's documentation:"
     { $code "\\ foo >link edit" }
     "A method definition:"
-    { $code "{ editor draw-gadget* } edit" }
+    { $code "M\\ fixnum + edit" }
     "A help article:"
     { $code "\"handbook\" >link edit" }
 } ;
index a582755dc4e6cce6802f81477139acb081ca4a8e..c7893117d16f8ae609275cad7bb989d46cb794b6 100644 (file)
@@ -9,6 +9,7 @@ http.server.responses
 furnace.utilities\r
 furnace.redirection\r
 furnace.conversations\r
+furnace.chloe-tags\r
 html.forms\r
 html.components\r
 html.components\r
index a5308c171e027b27bee38ae1fc2e6203d8d6fcd6..fe2840c9eba3d2e1f14e71daeb82cac4ae386176 100644 (file)
@@ -22,7 +22,7 @@ server-state f
 
 : expire-state ( class -- )
     new
-        -1.0/0.0 millis [a,b] >>expires
+        -1/0. millis [a,b] >>expires
     delete-tuples ;
 
 TUPLE: server-state-manager < filter-responder timeout ;
index adafb215242dc85aee1849c832acf3ac75da4cad..37b2f40e82b5075f16aa2f6c876f1894b791a517 100644 (file)
@@ -17,7 +17,6 @@ USE: vocabs.loader
 "furnace.auth.providers.db" require
 "furnace.auth.providers.null" require
 "furnace.boilerplate" require
-"furnace.chloe-tags" require
 "furnace.conversations" require
 "furnace.db" require
 "furnace.json" require
index 01297288dc8fb4274320854ce9aaeec20f63191a..ff81d73f7f7fd21017a898d59210c800d529e8f6 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors combinators namespaces fry urls http
-http.server http.server.redirection http.server.responses
+USING: kernel accessors combinators namespaces fry urls urls.secure
+http http.server http.server.redirection http.server.responses
 http.server.remapping http.server.filters furnace.utilities ;
 IN: furnace.redirection
 
index 2cc19f87ddc2f857760aa68bec6d6ac1db57f8b8..867f3732098b8d855683b0f934624b3160e5651f 100644 (file)
@@ -117,7 +117,7 @@ $nl
 }
 { $references
     { "Since quotations are objects, they can be constructed and taken apart at will. You can write code that writes code. Arrays are just one of the various types of sequences, and the sequence operations such as " { $link each } " and " { $link map } " operate on all types of sequences. There are many more sequence iteration operations than the ones above, too." }
-    "dataflow"
+    "combinators"
     "sequences"
 } ;
 
index ed2a14a2f2acf19294ada9ff4b7516a5dda68e92..0845264d61312c9068d80f3fd2a0f4f49bb03b6a 100644 (file)
@@ -5,7 +5,7 @@ math system strings sbufs vectors byte-arrays quotations
 io.streams.byte-array classes.builtin parser lexer
 classes.predicate classes.union classes.intersection
 classes.singleton classes.tuple help.vocabs math.parser
-accessors ;
+accessors definitions ;
 IN: help.handbook
 
 ARTICLE: "conventions" "Conventions"
@@ -49,13 +49,15 @@ $nl
     { "associative mapping" { "an object whose class implements the " { $link "assocs-protocol" } } }
     { "boolean"               { { $link t } " or " { $link f } } }
     { "class"                 { "a set of objects identified by a " { $emphasis "class word" } " together with a discriminating predicate. See " { $link "classes" } } }
-    { "definition specifier"  { "a " { $link word } ", " { $link method-spec } ", " { $link link } ", vocabulary specifier, or any other object whose class implements the " { $link "definition-protocol" } } }
+    { "combinator"            { "a word taking a quotation or another word as input; a higher-order function. See " { $link "combinators" } } }
+    { "definition specifier"  { "an instance of " { $link definition } " which implements the " { $link "definition-protocol" } } }
     { "generalized boolean"   { "an object interpreted as a boolean; a value of " { $link f } " denotes false and anything else denotes true" } }
     { "generic word"          { "a word whose behavior depends can be specialized on the class of one of its inputs. See " { $link "generic" } } }
     { "method"                { "a specialized behavior of a generic word on a class. See " { $link "generic" } } }
     { "object"                { "any datum which can be identified" } }
     { "ordering specifier"    { "see " { $link "order-specifiers" } } }
     { "pathname string"       { "an OS-specific pathname which identifies a file" } }
+    { "quotation"             { "an anonymous function; an instance of the " { $link quotation } " class. More generally, instances of the " { $link callable } " class can be used in many places documented to expect quotations" } }
     { "sequence" { "a sequence; see " { $link "sequence-protocol" } } }
     { "slot"                  { "a component of an object which can store a value" } }
     { "stack effect"          { "a pictorial representation of a word's inputs and outputs, for example " { $snippet "+ ( x y -- z )" } ". See " { $link "effects" } } }
@@ -70,7 +72,7 @@ ARTICLE: "tail-call-opt" "Tail-call optimization"
 $nl
 "Tail-call optimization allows iterative algorithms to be implemented in an efficient manner using recursion, without the need for any kind of primitive looping construct in the language. However, in practice, most iteration is performed via combinators such as " { $link while } ", " { $link each } ", " { $link map } ", " { $link assoc-each } ", and so on. The definitions of these combinators do bottom-out in recursive words, however." ;
 
-ARTICLE: "evaluator" "Evaluation semantics"
+ARTICLE: "evaluator" "Stack machine model"
 { $link "quotations" } " are evaluated sequentially from beginning to end. When the end is reached, the quotation returns to its caller. As each object in the quotation is evaluated in turn, an action is taken based on its type:"
 { $list
     { "a " { $link word } " - the word's definition quotation is called. See " { $link "words" } }
@@ -84,12 +86,13 @@ ARTICLE: "objects" "Objects"
 "An " { $emphasis "object" } " is any datum which may be identified. All values are objects in Factor. Each object carries type information, and types are checked at runtime; Factor is dynamically typed."
 { $subsection "equality" }
 { $subsection "math.order" }
-{ $subsection "destructors" }
 { $subsection "classes" }
 { $subsection "tuples" }
 { $subsection "generic" }
-{ $subsection "slots" }
-{ $subsection "mirrors" } ;
+"Advanced features:"
+{ $subsection "delegate" }
+{ $subsection "mirrors" }
+{ $subsection "slots" } ;
 
 ARTICLE: "numbers" "Numbers"
 { $subsection "arithmetic" }
@@ -118,9 +121,9 @@ ARTICLE: "collections" "Collections"
 "Fixed-length sequences:"
 { $subsection "arrays" }
 { $subsection "quotations" }
-"Fixed-length specialized sequences:"
 { $subsection "strings" }
 { $subsection "byte-arrays" }
+{ $subsection "specialized-arrays" }
 "Resizable sequences:"
 { $subsection "vectors" }
 { $subsection "byte-vectors" }
@@ -128,7 +131,8 @@ ARTICLE: "collections" "Collections"
 { $subsection "growable" }
 { $heading "Associative mappings" }
 { $subsection "assocs" }
-{ $subsection "namespaces" }
+{ $subsection "linked-assocs" }
+{ $subsection "biassocs" }
 { $subsection "refs" }
 "Implementations:"
 { $subsection "hashtables" }
@@ -140,26 +144,29 @@ ARTICLE: "collections" "Collections"
 { $subsection "dlists" }
 { $subsection "search-deques" }
 { $heading "Other collections" }
-{ $subsection "boxes" }
+{ $subsection "lists" }
+{ $subsection "disjoint-sets" }
+{ $subsection "interval-maps" }
 { $subsection "heaps" }
+{ $subsection "boxes" }
 { $subsection "graphs" }
 { $subsection "buffers" }
 "There are also many other vocabularies tagged " { $link T{ vocab-tag { name "collections" } } } " in the library." ;
 
-USING: io.encodings.utf8 io.encodings.utf16 io.encodings.binary io.encodings.ascii io.files ;
+USING: io.encodings.utf8 io.encodings.binary io.files ;
 
 ARTICLE: "encodings-introduction" "An introduction to encodings"
 "In order to express text in terms of binary, some sort of encoding has to be used. In a modern context, this is understood as a two-way mapping between Unicode code points (characters) and some amount of binary. Since English isn't the only language in the world, ASCII is not sufficient as a mapping from binary to Unicode; it can't even express em-dashes or curly quotes. Unicode was designed as a universal character set that could potentially represent everything." $nl
 "Not all encodings can represent all Unicode code points, but Unicode can represent basically everything that exists in modern encodings. Some encodings are language-specific, and some can represent everything in Unicode. Though the world is moving toward Unicode and UTF-8, the reality today is that there are several encodings which must be taken into account." $nl
-"Factor uses a system of encoding descriptors to denote encodings. Encoding descriptors are objects which describe encodings. Examples are " { $link utf8 } ", " { $link ascii } " and " { $link binary } ". Encoding descriptors can be passed around independently. Each encoding descriptor has some method for constructing an encoded or decoded stream, and the resulting stream has an encoding descriptor stored which has methods for reading or writing characters." $nl
+"Factor uses a system of encoding descriptors to denote encodings. Encoding descriptors are objects which describe encodings. Examples are " { $link utf8 } " and " { $link binary } ". Encoding descriptors can be passed around independently. Each encoding descriptor has some method for constructing an encoded or decoded stream, and the resulting stream has an encoding descriptor stored which has methods for reading or writing characters." $nl
 "Constructors for streams which deal with bytes usually take an encoding as an explicit parameter. For example, to open a text file for reading whose contents are in UTF-8, use the following"
 { $code "\"file.txt\" utf8 <file-reader>" }
 "If there is an error in the encoded stream, a replacement character (0xFFFD) will be inserted. To throw an exception upon error, use a strict encoding as follows"
 { $code "\"file.txt\" utf8 strict <file-reader>" }
 "In a similar way, encodings can be specified when opening a file for writing."
-{ $code "\"file.txt\" ascii <file-writer>" }
+{ $code "USE: io.encodings.ascii" "\"file.txt\" ascii <file-writer>" }
 "An encoding is also needed for some words that don't return streams, such as " { $link file-contents } ", for example"
-{ $code "\"file.txt\" utf16 file-contents" }
+{ $code "USE: io.encodings.utf16" "\"file.txt\" utf16 file-contents" }
 "Encoding descriptors are also used by " { $link "io.streams.byte-array" } " and taken by combinators like " { $link with-file-writer } " and " { $link with-byte-reader } " which deal with streams. It is " { $emphasis "not" } " used with " { $link "io.streams.string" } " because these deal with abstract text."
 $nl
 "When the " { $link binary } " encoding is used, a " { $link byte-array } " is expected for writing and returned for reading, since the stream deals with bytes. All other encodings deal with strings, since they are used to represent text." ;
@@ -239,40 +246,57 @@ ARTICLE: "class-index" "Class index"
 { $heading "Predicate classes" }
 { $index [ classes [ predicate-class? ] filter ] } ;
 
-ARTICLE: "program-org" "Program organization"
-{ $subsection "definitions" }
-{ $subsection "vocabularies" }
-{ $subsection "parser" }
-{ $subsection "vocabs.loader" }
-{ $subsection "source-files" } ;
-
 USING: help.cookbook help.tutorial ;
 
 ARTICLE: "handbook-language-reference" "Language reference"
+"Fundamentals:"
 { $subsection "conventions" }
 { $subsection "syntax" }
-{ $subsection "dataflow" }
-{ $subsection "objects" }
-{ $subsection "program-org" }
+{ $subsection "effects" }
+"Data types:"
+{ $subsection "booleans" }
 { $subsection "numbers" }
 { $subsection "collections" }
-{ $subsection "io" }
+"Evaluation semantics:"
+{ $subsection "evaluator" }
+{ $subsection "words" }
+{ $subsection "shuffle-words" }
+{ $subsection "combinators" }
+{ $subsection "errors" }
+{ $subsection "continuations" }
+"Named values:"
+{ $subsection "locals" }
+{ $subsection "namespaces" }
+{ $subsection "namespaces-global" }
+{ $subsection "values" }
+"Abstractions:"
+{ $subsection "objects" }
+{ $subsection "destructors" }
+{ $subsection "macros" }
+{ $subsection "fry" }
+"Program organization:"
+{ $subsection "vocabs.loader" }
 "Vocabularies tagged " { $link T{ vocab-tag { name "extensions" } } } " implement various additional language abstractions." ;
 
 ARTICLE: "handbook-environment-reference" "Environment reference"
+"Parse time and compile time:"
+{ $subsection "parser" }
+{ $subsection "definitions" }
+{ $subsection "vocabularies" }
+{ $subsection "source-files" }
+{ $subsection "compiler" }
+"Tools:"
 { $subsection "prettyprint" }
 { $subsection "tools" }
-{ $subsection "cli" }
-{ $subsection "rc-files" }
 { $subsection "help" }
 { $subsection "inference" }
-{ $subsection "compiler" }
-{ $subsection "system" }
 { $subsection "images" }
-{ $subsection "alien" }
+"VM:"
+{ $subsection "cli" }
+{ $subsection "rc-files" }
 { $subsection "init" }
-{ $subsection "layouts" }
-{ $see-also "program-org" } ;
+{ $subsection "system" }
+{ $subsection "layouts" } ;
 
 ARTICLE: "handbook-library-reference" "Library reference"
 "This index only includes articles from loaded vocabularies. To explore more vocabularies, see " { $link "vocab-index" } "."
@@ -282,9 +306,14 @@ ARTICLE: "handbook" "Factor handbook"
 "Learn the language:"
 { $subsection "cookbook" }
 { $subsection "first-program" }
+"Reference material:"
 { $subsection "handbook-language-reference" }
 { $subsection "handbook-environment-reference" }
+{ $subsection "io" }
 { $subsection "ui" }
+{ $subsection "ui-tools" }
+{ $subsection "unicode" }
+{ $subsection "alien" }
 { $subsection "handbook-library-reference" }
 "Explore loaded libraries:"
 { $subsection "article-index" }
index 6608a6e9c0eaee311f74d1fb595dfa68a4e6e8db..e6db2d3b9c3c7e400cb7c1b651ae8bf5006f0701 100644 (file)
@@ -8,7 +8,6 @@ ARTICLE: "help.home" "Factor documentation"
   { $link "handbook" }
   { $link "vocab-index" }
   { $link "ui-tools" }
-  { $link "handbook-library-reference" }
 }
 { $heading "Recently visited" }
 { $table
index f32c0db30d48e60f2aa728053467eb7f41f80f86..9cb3c6f1bbec6ae8395fb0eb51081cdca53d5001 100644 (file)
@@ -21,7 +21,7 @@ M: apropos add-recent-where recent-searches ;
 M: object add-recent-where f ;
 
 : $recent ( element -- )
-    first get [ nl ] [ 1array $pretty-link ] interleave ;
+    first get reverse [ nl ] [ 1array $pretty-link ] interleave ;
 
 : $recent-searches ( element -- )
     drop recent-searches get [ <$link> ] map $list ;
index 66d864b2a04a6e852b40156c85bf189811c34c16..f4a874248617f9645421e41e783e1a6b2e502ec0 100644 (file)
@@ -4,24 +4,26 @@ USING: io.encodings.utf8 io.encodings.ascii io.encodings.binary
 io.files io.files.temp io.directories html.streams help kernel
 assocs sequences make words accessors arrays help.topics vocabs
 tools.vocabs help.vocabs namespaces prettyprint io
-vocabs.loader serialize fry memoize unicode.case math.order
-sorting debugger html xml.syntax xml.writer ;
+vocabs.loader serialize fry memoize ascii unicode.case math.order
+sorting debugger html xml.syntax xml.writer math.parser ;
 IN: help.html
 
 : escape-char ( ch -- )
-    dup H{
-        { CHAR: " "__quo__" }
-        { CHAR: * "__star__" }
-        { CHAR: : "__colon__" }
-        { CHAR: < "__lt__" }
-        { CHAR: > "__gt__" }
-        { CHAR: ? "__que__" }
-        { CHAR: \\ "__back__" }
-        { CHAR: | "__pipe__" }
-        { CHAR: / "__slash__" }
-        { CHAR: , "__comma__" }
-        { CHAR: @ "__at__" }
-    } at [ % ] [ , ] ?if ;
+    dup ascii? [
+        dup H{
+            { CHAR: " "__quo__" }
+            { CHAR: * "__star__" }
+            { CHAR: : "__colon__" }
+            { CHAR: < "__lt__" }
+            { CHAR: > "__gt__" }
+            { CHAR: ? "__que__" }
+            { CHAR: \\ "__back__" }
+            { CHAR: | "__pipe__" }
+            { CHAR: / "__slash__" }
+            { CHAR: , "__comma__" }
+            { CHAR: @ "__at__" }
+        } at [ % ] [ , ] ?if
+    ] [ number>string "__" "__" surround % ] if ;
 
 : escape-filename ( string -- filename )
     [ [ escape-char ] each ] "" make ;
@@ -60,7 +62,7 @@ M: topic url-of topic>filename ;
 : help>html ( topic -- xml )
     [ article-title ]
     [ drop help-stylesheet ]
-    [ [ help ] with-html-writer ]
+    [ [ print-topic ] with-html-writer ]
     tri simple-page ;
           
 : generate-help-file ( topic -- )
diff --git a/basis/help/syntax/tags.txt b/basis/help/syntax/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
index 750eff7a52b7d8b1fda97ef0ba5c1427f5873434..030c546f0c4c7f005ab8c319f8e793a4eefada62 100644 (file)
@@ -1,6 +1,6 @@
 IN: help.tips
 USING: help.markup help.syntax debugger prettyprint see help help.vocabs
-help.apropos tools.time stack-checker editors ;
+help.apropos tools.time stack-checker editors memory ;
 
 TIP: "To look at the most recent error, run " { $link :error } ". To look at the most recent error's callstack, run " { $link :c } "." ;
 
@@ -20,6 +20,10 @@ TIP: "Power tools: " { $links see edit help about apropos time infer. } ;
 
 TIP: "Tips of the day implement the " { $link "definition-protocol" } " and new tips of the day can be defined using the " { $link POSTPONE: TIP: } " parsing word." ;
 
+TIP: "Try some simple demo applications, then look at the source code in " { $snippet "extra/" } ": " { $snippet "\"demos\" run" } ;
+
+TIP: "To save time on reloading big libraries such as the " { $vocab-link "furnace" } " web framework, save the image after loading them using the " { $link save } " word." ;
+
 HELP: TIP:
 { $syntax "TIP: content ;" }
 { $values { "content" "a markup element" } }
index 804ef035f45f178eb64183c346fe4f1c5f259132..d44bf92bf4e53c08823fecac816a9a0941b82a0c 100644 (file)
@@ -3,7 +3,7 @@
 USING: parser words definitions kernel sequences assocs arrays
 kernel.private fry combinators accessors vectors strings sbufs
 byte-arrays byte-vectors io.binary io.streams.string splitting
-math generic generic.standard generic.standard.engines classes
+math math.parser generic generic.standard generic.standard.engines classes
 hashtables ;
 IN: hints
 
@@ -25,7 +25,7 @@ M: object specializer-declaration class ;
     [ drop object eq? not ] assoc-filter
     [ [ t ] ] [
         [ swap specializer-predicate append ] { } assoc>map
-        unclip [ swap [ f ] \ if 3array append [ ] like ] reduce
+        [ ] [ swap [ f ] \ if 3array append [ ] like ] map-reduce
     ] if-empty ;
 
 : specializer-cases ( quot word -- default alist )
@@ -65,7 +65,6 @@ M: object specializer-declaration class ;
 
 SYNTAX: HINTS:
     scan-object
-    dup method-spec? [ first2 method ] when
     [ redefined ]
     [ parse-definition "specializer" set-word-prop ] bi ;
 
@@ -119,6 +118,8 @@ SYNTAX: HINTS:
 
 \ >be { { bignum fixnum } { fixnum fixnum } } "specializer" set-word-prop
 
-\ hashtable \ at* method { { fixnum object } { word object } } "specializer" set-word-prop
+\ base> { string fixnum } "specializer" set-word-prop
 
-\ hashtable \ set-at method { { object fixnum object } { object word object } } "specializer" set-word-prop
+M\ hashtable at* { { fixnum object } { word object } } "specializer" set-word-prop
+
+M\ hashtable set-at { { object fixnum object } { object word object } } "specializer" set-word-prop
index 4099e3d84cc35fea26d929db7ed75a060d13c1b2..307fdd50314749880eed2d21aca99c3ac76433ea 100644 (file)
@@ -6,7 +6,7 @@ math.order hashtables byte-arrays destructors
 io io.sockets io.streams.string io.files io.timeouts
 io.pathnames io.encodings io.encodings.string io.encodings.ascii
 io.encodings.utf8 io.encodings.8-bit io.encodings.binary io.crlf
-io.streams.duplex fry ascii urls urls.encoding present
+io.streams.duplex fry ascii urls urls.encoding present locals
 http http.parsers http.client.post-data ;
 IN: http.client
 
@@ -77,12 +77,13 @@ SYMBOL: redirects
 : redirect? ( response -- ? )
     code>> 300 399 between? ;
 
-: do-redirect ( quot: ( chunk -- ) response -- response )
+:: do-redirect ( quot: ( chunk -- ) response -- response )
     redirects inc
     redirects get max-redirects < [
         request get clone
-        swap "location" header redirect-url
-        "GET" >>method swap (with-http-request)
+        response "location" header redirect-url
+        response code>> 307 = [ "GET" >>method ] unless
+        quot (with-http-request)
     ] [ too-many-redirects ] if ; inline recursive
 
 : read-chunk-size ( -- n )
@@ -164,7 +165,7 @@ ERROR: download-failed response ;
     present file-name "?" split1 drop "/" ?tail drop ;
 
 : download-to ( url file -- )
-    binary [ [ write ] with-http-get drop ] with-file-writer ;
+    binary [ [ write ] with-http-get check-response drop ] with-file-writer ;
 
 : download ( url -- )
     dup download-name download-to ;
index bc906fad44b3e4862e84d8ca15b33c0ea1f5eb97..5c73377cbe5fb3bed094dc128c823b9f194d031b 100644 (file)
@@ -1,8 +1,8 @@
-USING: http http.server http.client http.client.private tools.test multiline
-io.streams.string io.encodings.utf8 io.encodings.8-bit
-io.encodings.binary io.encodings.string kernel arrays splitting
-sequences assocs io.sockets db db.sqlite continuations urls
-hashtables accessors namespaces xml.data ;
+USING: http http.server http.client http.client.private tools.test
+multiline io.streams.string io.encodings.utf8 io.encodings.8-bit
+io.encodings.binary io.encodings.string io.encodings.ascii kernel
+arrays splitting sequences assocs io.sockets db db.sqlite
+continuations urls hashtables accessors namespaces xml.data ;
 IN: http.tests
 
 [ "text/plain" latin1 ] [ "text/plain" parse-content-type ] unit-test
@@ -359,4 +359,44 @@ SYMBOL: a
 ! Test basic auth
 [ "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" ] [ <request> "Aladdin" "open sesame" set-basic-auth "Authorization" header ] unit-test
 
+! Test a corner case with static responder
+[ ] [
+    <dispatcher>
+        add-quit-action
+        "vocab:http/test/foo.html" <static> >>default
+    test-httpd
+] unit-test
+
+[ t ] [
+    "http://localhost/" add-port http-get nip
+    "vocab:http/test/foo.html" ascii file-contents =
+] unit-test
+
+[ ] [ "http://localhost/quit" add-port http-get 2drop ] unit-test
+
+! Check behavior of 307 redirect (reported by Chris Double)
+[ ] [
+    <dispatcher>
+        add-quit-action
+        <action>
+            [ "b" <temporary-redirect> ] >>submit
+        "a" add-responder
+        <action>
+            [
+                request get post-data>> data>> "data" =
+                [ "OK" "text/plain" <content> ] [ "OOPS" throw ] if
+            ] >>submit
+        "b" add-responder
+    test-httpd
+] unit-test
+
+[ "OK" ] [ "data" "http://localhost/a" add-port http-post nip ] unit-test
+
+! Check that download throws errors (reported by Chris Double)
+[
+    "resource:temp" [
+        "http://localhost/tweet_my_twat" add-port download
+    ] with-directory
+] must-fail
 
+[ ] [ "http://localhost/quit" add-port http-get 2drop ] unit-test
index bbca70d84591dab79913dc8a0ebf68f107c69d9b..f80a3cc7cde7338549bbedbae949cf1d354ac6f1 100644 (file)
@@ -47,8 +47,8 @@ TUPLE: file-responder root hook special allow-listings ;
     if ;\r
 \r
 : serving-path ( filename -- filename )\r
-    [ file-responder get root>> trim-tail-separators "/" ] dip\r
-    "" or trim-head-separators 3append ;\r
+    [ file-responder get root>> trim-tail-separators ] dip\r
+    [ "/" swap trim-head-separators 3append ] unless-empty ;\r
 \r
 : serve-file ( filename -- response )\r
     dup mime-type\r
index e154df26a1f2887f33be8487922026899cf5313e..29ba3b9b80133ddc53a7ded0456796fb8cbfad89 100644 (file)
@@ -1,6 +1,7 @@
 USING: images.bitmap images.viewer io.encodings.binary
 io.files io.files.unique kernel tools.test images.loader
-literals sequences ;
+literals sequences checksums.md5 checksums
+images.normalization ;
 IN: images.bitmap.tests
 
 CONSTANT: test-bitmap24 "vocab:images/test-images/thiswayup24.bmp"
@@ -11,17 +12,33 @@ CONSTANT: test-bitmap4 "vocab:images/test-images/rgb4bit.bmp"
 
 CONSTANT: test-bitmap1 "vocab:images/test-images/1bit.bmp"
 
-[ t ]
-[
-    test-bitmap24
-    [ binary file-contents ] [ load-image ] bi
-
-    "test-bitmap24" unique-file
-    [ save-bitmap ] [ binary file-contents ] bi =
-] unit-test
+CONSTANT: test-40 "vocab:images/test-images/40red24bit.bmp"
+CONSTANT: test-41 "vocab:images/test-images/41red24bit.bmp"
+CONSTANT: test-42 "vocab:images/test-images/42red24bit.bmp"
+CONSTANT: test-43 "vocab:images/test-images/43red24bit.bmp"
 
 {
     $ test-bitmap8
     $ test-bitmap24
     "vocab:ui/render/test/reference.bmp"
-} [ [ ] swap [ load-image drop ] curry unit-test ] each
\ No newline at end of file
+} [ [ ] swap [ load-image drop ] curry unit-test ] each
+
+
+: test-bitmap-save ( path -- ? )
+    [ md5 checksum-file ]
+    [ load-image normalize-image ] bi
+    "bitmap-save-test" unique-file
+    [ save-bitmap ]
+    [ md5 checksum-file ] bi = ;
+
+[
+    t   
+] [
+    {
+        $ test-40
+        $ test-41
+        $ test-42
+        $ test-43
+        $ test-bitmap24
+    } [ test-bitmap-save ] all?
+] unit-test
index 8209159a8e4c33386e27f6224d33b370bc54ae82..48095bb26bf99800da68e7252dbd170bb4c65721 100755 (executable)
@@ -37,14 +37,14 @@ M: bitmap-magic summary
 ERROR: bmp-not-supported n ;
 
 : reverse-lines ( byte-array width -- byte-array )
-    3 * <sliced-groups> <reversed> concat ; inline
+    <sliced-groups> <reversed> concat ; inline
 
 : raw-bitmap>seq ( loading-bitmap -- array )
     dup bit-count>>
     {
         { 32 [ color-index>> ] }
-        { 24 [ [ color-index>> ] [ width>> ] bi reverse-lines ] }
-        { 8 [ [ 8bit>buffer ] [ width>> ] bi reverse-lines ] }
+        { 24 [ [ color-index>> ] [ width>> 3 * ] bi reverse-lines ] }
+        { 8 [ [ 8bit>buffer ] [ width>> 3 * ] bi reverse-lines ] }
         [ bmp-not-supported ]
     } case >byte-array ;
 
@@ -81,30 +81,31 @@ ERROR: bmp-not-supported n ;
 : 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 height>> abs :> height
-    loading-bitmap color-index>> length :> color-index-length
-    color-index-length height /i :> stride
-    color-index-length width*3 height * - height /i :> padding
+    loading-bitmap width>> bitmap-padding :> padding
+    loading-bitmap [ color-index>> length ] [ height>> abs ] bi /i :> stride
+    loading-bitmap
     padding 0 > [
-        loading-bitmap [
+        [
             stride <sliced-groups>
             [ width*3 head-slice ] map concat
         ] change-color-index
-    ] [
-        loading-bitmap
-    ] if ;
+    ] when ;
 
 : parse-bitmap ( loading-bitmap -- loading-bitmap )
     dup rgb-quads-length read >>rgb-quads
     dup color-index-length read >>color-index
     fixup-color-index ;
 
-: load-bitmap-data ( path loading-bitmap -- loading-bitmap )
-    [ binary ] dip '[
-        _ parse-file-header parse-bitmap-header parse-bitmap
+: load-bitmap-data ( path -- loading-bitmap )
+    binary [
+        loading-bitmap new
+        parse-file-header parse-bitmap-header parse-bitmap
     ] with-file-reader ;
 
 ERROR: unknown-component-order bitmap ;
@@ -117,8 +118,7 @@ ERROR: unknown-component-order bitmap ;
         [ unknown-component-order ]
     } case ;
 
-: loading-bitmap>bitmap-image ( loading-bitmap -- bitmap-image )
-    [ bitmap-image new ] dip
+: loading-bitmap>bitmap-image ( bitmap-image loading-bitmap -- bitmap-image )
     {
         [ raw-bitmap>seq >>bitmap ]
         [ [ width>> ] [ height>> abs ] bi 2array >>dim ]
@@ -127,20 +127,30 @@ ERROR: unknown-component-order bitmap ;
     } cleave ;
 
 M: bitmap-image load-image* ( path loading-bitmap -- bitmap )
-    drop loading-bitmap new
-    load-bitmap-data
-    loading-bitmap>bitmap-image ;
+    swap load-bitmap-data loading-bitmap>bitmap-image ;
 
 PRIVATE>
 
-: bitmap>color-index ( bitmap-array -- byte-array )
-    4 <sliced-groups> [ 3 head-slice <reversed> ] map B{ } join ; inline
+: bitmap>color-index ( bitmap -- byte-array )
+    [
+        bitmap>>
+        4 <sliced-groups>
+        [ 3 head-slice <reversed> ] map
+        B{ } join
+    ] [
+        dim>> first dup bitmap-padding dup 0 > [
+            [ 3 * group ] dip '[ _ <byte-array> append ] map
+            B{ } join
+        ] [
+            2drop
+        ] if
+    ] bi ;
 
 : save-bitmap ( image path -- )
     binary [
         B{ CHAR: B CHAR: M } write
         [
-            bitmap>> bitmap>color-index length 14 + 40 + write4
+            bitmap>color-index length 14 + 40 + write4
             0 write4
             54 write4
             40 write4
@@ -159,7 +169,7 @@ PRIVATE>
                 [ drop 0 write4 ]
 
                 ! size-image
-                [ bitmap>> bitmap>color-index length write4 ]
+                [ bitmap>color-index length write4 ]
 
                 ! x-pels
                 [ drop 0 write4 ]
@@ -175,7 +185,9 @@ PRIVATE>
 
                 ! rgb-quads
                 [
-                    [ bitmap>> bitmap>color-index ] [ dim>> first ] bi
+                    [ bitmap>color-index ]
+                    [ dim>> first 3 * ]
+                    [ dim>> first bitmap-padding + ] tri
                     reverse-lines write
                 ]
             } cleave
old mode 100644 (file)
new mode 100755 (executable)
index 08fbdd4..178b91a
@@ -1,14 +1,17 @@
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: combinators kernel ;
+USING: combinators kernel accessors ;
 IN: images
 
-SINGLETONS: L BGR RGB BGRA RGBA ABGR ARGB RGBX XRGB BGRX XBGR
+SINGLETONS: L LA BGR RGB BGRA RGBA ABGR ARGB RGBX XRGB BGRX XBGR
 R16G16B16 R32G32B32 R16G16B16A16 R32G32B32A32 ;
 
+UNION: alpha-channel BGRA RGBA ABGR ARGB R16G16B16A16 R32G32B32A32 ;
+
 : bytes-per-pixel ( component-order -- n )
     {
         { L [ 1 ] }
+        { LA [ 2 ] }
         { BGR [ 3 ] }
         { RGB [ 3 ] }
         { BGRA [ 4 ] }
@@ -29,4 +32,6 @@ TUPLE: image dim component-order upside-down? bitmap ;
 
 : <image> ( -- image ) image new ; inline
 
-GENERIC: load-image* ( path tuple -- image )
\ No newline at end of file
+: has-alpha? ( image -- ? ) component-order>> alpha-channel? ;
+
+GENERIC: load-image* ( path tuple -- image )
index b8bafc021f6a85a638641b3e2f0e657c86ddd5a1..fe33cc8f0055490d46fb37a911c0e7cd5d91d6db 100644 (file)
@@ -1,8 +1,7 @@
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: constructors kernel splitting unicode.case combinators
-accessors images.bitmap images.tiff images images.normalization
-io.pathnames ;
+accessors images.bitmap images.tiff images io.pathnames ;
 IN: images.loader
 
 ERROR: unknown-image-extension extension ;
@@ -16,4 +15,4 @@ ERROR: unknown-image-extension extension ;
     } case ;
 
 : load-image ( path -- image )
-    dup image-class new load-image* normalize-image ;
+    dup image-class new load-image* ;
diff --git a/basis/images/normalization/authors.txt b/basis/images/normalization/authors.txt
deleted file mode 100644 (file)
index 7c1b2f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
diff --git a/basis/images/normalization/normalization.factor b/basis/images/normalization/normalization.factor
deleted file mode 100644 (file)
index bcdf841..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-! Copyright (C) 2009 Doug Coleman
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors grouping sequences combinators
-math specialized-arrays.direct.uint byte-arrays fry
-specialized-arrays.direct.ushort specialized-arrays.uint
-specialized-arrays.ushort specialized-arrays.float images ;
-IN: images.normalization
-
-<PRIVATE
-
-: add-dummy-alpha ( seq -- seq' )
-    3 <groups> [ 255 suffix ] map concat ;
-
-: normalize-floats ( byte-array -- byte-array )
-    byte-array>float-array [ 255.0 * >integer ] B{ } map-as ;
-
-GENERIC: normalize-component-order* ( image component-order -- image )
-
-: normalize-component-order ( image -- image )
-    dup component-order>> '[ _ normalize-component-order* ] change-bitmap ;
-
-M: RGBA normalize-component-order* drop ;
-
-M: R32G32B32A32 normalize-component-order*
-    drop normalize-floats ;
-
-M: R32G32B32 normalize-component-order*
-    drop normalize-floats add-dummy-alpha ;
-
-: RGB16>8 ( bitmap -- bitmap' )
-    byte-array>ushort-array [ -8 shift ] B{ } map-as ; inline
-
-M: R16G16B16A16 normalize-component-order*
-    drop RGB16>8 ;
-
-M: R16G16B16 normalize-component-order*
-    drop RGB16>8 add-dummy-alpha ;
-
-: BGR>RGB ( bitmap -- pixels )
-    3 <sliced-groups> [ <reversed> ] map B{ } join ; inline
-
-: BGRA>RGBA ( bitmap -- pixels )
-    4 <sliced-groups>
-    [ unclip-last-slice [ <reversed> ] dip suffix ] map concat ; inline
-
-M: BGRA normalize-component-order*
-    drop BGRA>RGBA ;
-
-M: RGB normalize-component-order*
-    drop add-dummy-alpha ;
-
-M: BGR normalize-component-order*
-    drop BGR>RGB add-dummy-alpha ;
-
-: ARGB>RGBA ( bitmap -- bitmap' )
-    4 <groups> [ unclip suffix ] map B{ } join ; inline
-
-M: ARGB normalize-component-order*
-    drop ARGB>RGBA ;
-
-M: ABGR normalize-component-order*
-    drop ARGB>RGBA BGRA>RGBA ;
-
-: normalize-scan-line-order ( image -- image )
-    dup upside-down?>> [
-        dup dim>> first 4 * '[
-            _ <groups> reverse concat
-        ] change-bitmap
-        f >>upside-down?
-    ] when ;
-
-PRIVATE>
-
-: normalize-image ( image -- image )
-    [ >byte-array ] change-bitmap
-    normalize-component-order
-    normalize-scan-line-order
-    RGBA >>component-order ;
index 80eaff81400f30e800d6dbc5296ef9e287431894..6bf1ea2ff115175c3f28b0746092399812d9d627 100755 (executable)
@@ -463,6 +463,7 @@ ERROR: unknown-component-order ifd ;
         { { 16 16 16 } [ 2 seq>native-endianness ] }
         { { 8 8 8 8 } [ ] }
         { { 8 8 8 } [ ] }
+        { 8 [ ] }
         [ unknown-component-order ]
     } case >>bitmap ;
 
@@ -474,11 +475,11 @@ ERROR: unknown-component-order ifd ;
         { { 16 16 16 } [ R16G16B16 ] }
         { { 8 8 8 8 } [ RGBA ] }
         { { 8 8 8 } [ RGB ] }
+        { 8 [ LA ] }
         [ unknown-component-order ]
     } case ;
 
 : normalize-alpha-data ( seq -- byte-array )
-    ! [ normalize-alpha-data ] change-bitmap
     B{ } like dup
     byte-array>float-array
     4 <sliced-groups>
diff --git a/basis/interpolate/tags.txt b/basis/interpolate/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
index 74fc0450329863eaa44f97d7f94d727b7e7d52e4..6a7be478130bcc7887d06ff4e80c8fdbe60bc8c2 100644 (file)
@@ -62,8 +62,8 @@ HELP: current-temporary-directory
 
 HELP: unique-file
 { $values
+     { "prefix" string }
      { "path" "a pathname string" }
-     { "path'" "a pathname string" }
 }
 { $description "Creates a temporary file in the directory stored in " { $link current-temporary-directory } " and outputs the path name." } ;
 
index 7bd96aa63b4a10a1b7cf2f850ef6c34a5586d9a0..0e4338e3e0415d37a530e5a3d74da5c2de9e477d 100644 (file)
@@ -64,7 +64,7 @@ PRIVATE>
     [ unique-directory ] dip
     '[ _ with-temporary-directory ] [ delete-tree ] bi ; inline
 
-: unique-file ( path -- path' )
+: unique-file ( prefix -- path )
     "" make-unique-file ;
 
 {
index 36c257fb5eaa78aeb8f6dd1b734ca316724b082c..86d652d17c52e5d438e8ce7bfb929455ace4498d 100644 (file)
@@ -76,3 +76,9 @@ IN: io.streams.limited.tests
         [ decoder? ] both?
     ] with-destructors
 ] unit-test
+
+[ "HELL" ] [
+    "HELLO"
+    [ f stream-throws limit-input 4 read ]
+    with-string-reader
+] unit-test
\ No newline at end of file
index fe3dd9ad9319589dd3ff6f43b04a6a59020324d3..b1b07a08c07c2c288d658f906c7547b07664d532 100755 (executable)
@@ -22,7 +22,7 @@ M: decoder limit ( stream limit mode -- stream' )
     [ clone ] 2dip '[ _ _ limit ] change-stream ;
 
 M: object limit ( stream limit mode -- stream' )
-    <limited-stream> ;
+    over [ <limited-stream> ] [ 2drop ] if ;
 
 GENERIC: unlimited ( stream -- stream' )
 
@@ -32,9 +32,11 @@ M: decoder unlimited ( stream -- stream' )
 M: object unlimited ( stream -- stream' )
     stream>> stream>> ;
 
-: limit-input ( limit mode -- ) input-stream [ -rot limit ] change ;
+: limit-input ( limit mode -- )
+    [ input-stream ] 2dip '[ _ _ limit ] change ;
 
-: unlimited-input ( -- ) input-stream [ unlimited ] change ;
+: unlimited-input ( -- )
+    input-stream [ unlimited ] change ;
 
 : with-unlimited-stream ( stream quot -- )
     [ clone unlimited ] dip call ; inline
index 8c67590697a603698d9a9ac48736efce9204ca57..d32b1998738bf76e7dc17bf03ee59c5d96d1238a 100644 (file)
@@ -8,7 +8,7 @@ IN: lcs
     0 1 ? + [ [ 1+ ] bi@ ] dip min min ;\r
 \r
 : lcs-step ( insert delete change same? -- next )\r
-    1 -1./0. ? + max max ; ! -1./0. is -inf (float)\r
+    1 -1/0. ? + max max ; ! -1/0. is -inf (float)\r
 \r
 :: loop-step ( i j matrix old new step -- )\r
     i j 1+ matrix nth nth ! insertion\r
index 18dabed4b039518e3b559e65273560a28b2b124c..b1f0b6ca1732b3d59b6092d32b665c1d04d08ea2 100644 (file)
@@ -112,7 +112,15 @@ HELP: MEMO::
 { $description "Defines a memoized word with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope." } ;
 
 { POSTPONE: MEMO: POSTPONE: MEMO:: } related-words
+                                          
+HELP: M::
+{ $syntax "M:: class generic ( bindings... -- outputs... ) body... ;" }
+{ $description "Defines a method with named inputs; it reads stack values into bindings from left to right, then executes the body with those bindings in lexical scope." }
+{ $notes "The output names do not affect the word's behavior, however the compiler attempts to check the stack effect as with other definitions." } ;
+
+{ POSTPONE: M: POSTPONE: M:: } related-words
 
+                                                 
 ARTICLE: "locals-literals" "Locals in literals"
 "Certain data type literals are permitted to contain free variables. Any such literals are written into code which constructs an instance of the type with the free variable values spliced in. Conceptually, this is similar to the transformation applied to quotations containing free variables."
 $nl
@@ -237,13 +245,14 @@ $nl
 }
 "The reason is that locals are rewritten into stack code at parse time, whereas macro expansion is performed later during compile time. To circumvent this problem, the " { $vocab-link "macros.expander" } " vocabulary is used to rewrite simple macro usages prior to local transformation, however "{ $vocab-link "macros.expander" } " does not deal with more complicated cases where the literal inputs to the macro do not immediately precede the macro call in the source." ;
 
-ARTICLE: "locals" "Local variables and lexical closures"
+ARTICLE: "locals" "Lexical variables and closures"
 "The " { $vocab-link "locals" } " vocabulary implements lexical scope with full closures, both downward and upward. Mutable bindings are supported, including assignment to bindings in outer scope."
 $nl
 "Compile-time transformation is used to compile local variables to efficient code; prettyprinter extensions are defined so that " { $link see } " can display original word definitions with local variables and not the closure-converted concatenative code which results."
 $nl
 "Applicative word definitions where the inputs are named local variables:"
 { $subsection POSTPONE: :: }
+{ $subsection POSTPONE: M:: }
 { $subsection POSTPONE: MEMO:: }
 { $subsection POSTPONE: MACRO:: }
 "Lexical binding forms:"
index 8e61e39faf8a511f9b8891b2ccdf0f7fa344a19c..5e61c1ddfd45f0b881417557dcf7e9326d9547b4 100644 (file)
@@ -455,7 +455,7 @@ GENERIC: lambda-method-forget-test ( a -- b )
 
 M:: integer lambda-method-forget-test ( a -- b ) ;
 
-[ ] [ [ { integer lambda-method-forget-test } forget ] with-compilation-unit ] unit-test
+[ ] [ [ M\ integer lambda-method-forget-test forget ] with-compilation-unit ] unit-test
 
 [ 10 ] [ 10 [| A | { [ A ] } ] call first call ] unit-test
 
diff --git a/basis/math/blas/config/config-docs.factor b/basis/math/blas/config/config-docs.factor
new file mode 100644 (file)
index 0000000..60eaff2
--- /dev/null
@@ -0,0 +1,23 @@
+USING: alien.fortran help.markup help.syntax math.blas.config multiline ;
+IN: math.blas.config
+
+ARTICLE: "math.blas.config" "Configuring the BLAS interface"
+"The " { $link "math.blas-summary" } " chooses the underlying BLAS interface to use based on the values of the following global variables:"
+{ $subsection blas-library }
+{ $subsection blas-fortran-abi }
+"The interface attempts to set default values based on the ones encountered on the Factor project's build machines. If these settings don't work with your system's BLAS, or you wish to use a commercial BLAS, you may change the global values of those variables in your " { $link "factor-rc" } ". For example, to use AMD's ACML library on Windows with " { $snippet "math.blas" } ", your " { $snippet "factor-rc" } " would look like this:"
+{ $code <"
+USING: math.blas.config namespaces ;
+"X:\\path\\to\\acml.dll" blas-library set-global
+intel-windows-abi blas-fortran-abi set-global
+"> }
+"To take effect, the " { $snippet "blas-library" } " and " { $snippet "blas-fortran-abi" } " variables must be set before any other " { $snippet "math.blas" } " vocabularies are loaded."
+;
+
+HELP: blas-library
+{ $description "The name of the shared library containing the BLAS interface to load. The value of this variable must be a valid shared library name that can be passed to " { $link add-fortran-library } ". To take effect, this variable must be set before any other " { $snippet "math.blas" } " vocabularies are loaded. See " { $link "math.blas.config" } " for details and examples." } ;
+
+HELP: blas-fortran-abi
+{ $description "The Fortran ABI used by the BLAS interface specified in the " { $link blas-library } " variable. The value of " { $snippet "blas-fortran-abi" } " must be one of the " { $link "alien.fortran-abis" } " that can be passed to " { $link add-fortran-library } ". To take effect, this variable must be set before any other " { $snippet "math.blas" } " vocabularies are loaded. See " { $link "math.blas.config" } " for details and examples." } ;
+
+ABOUT: "math.blas.config"
diff --git a/basis/math/blas/config/config.factor b/basis/math/blas/config/config.factor
new file mode 100644 (file)
index 0000000..327c546
--- /dev/null
@@ -0,0 +1,24 @@
+USING: alien.fortran combinators kernel namespaces system ;
+IN: math.blas.config
+
+SYMBOLS: blas-library blas-fortran-abi ;
+
+blas-library [
+    {
+        { [ os macosx?  ] [ "libblas.dylib" ] }
+        { [ os windows? ] [ "blas.dll"      ] }
+        [ "libblas.so" ]
+    } cond
+] initialize
+
+blas-fortran-abi [
+    {
+        { [ os macosx?                  ] [ intel-unix-abi ] }
+        { [ os windows? cpu x86.32? and ] [ f2c-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   ] }
+        [ f2c-abi ]
+    } cond
+] initialize
index 0603a913708b3571ab2fe6a3153a61b55abe7a35..b7748f500f825db77ea536c4d19cfd928a3a7bdf 100644 (file)
@@ -1,19 +1,9 @@
-USING: alien alien.fortran kernel system combinators
-alien.libraries ;
+USING: alien.fortran kernel math.blas.config namespaces ;
 IN: math.blas.ffi
 
 <<
-"blas" {
-    { [ os macosx? ] [ "libblas.dylib" intel-unix-abi add-fortran-library ] }
-    { [ os windows? cpu x86.32? and ] [ "blas.dll" f2c-abi add-fortran-library ] }
-    { [ os windows? cpu x86.64? and ] [ "blas.dll" gfortran-abi add-fortran-library ] }
-    {
-        [ os [ freebsd? ] [ linux? cpu x86.32? and ] bi or ]
-        [ "libblas.so" gfortran-abi add-fortran-library ]
-    }
-    { [ os [ freebsd? ] [ linux? ] bi or ] [ "libblas.so" gfortran-abi add-fortran-library ] }
-    [ "libblas.so" f2c-abi add-fortran-library ]
-} cond
+"blas" blas-library blas-fortran-abi [ get ] bi@
+add-fortran-library
 >>
 
 LIBRARY: blas
index 17d2f9ccd1cb83feb17c771800953e5b501308f1..5662cd99059744be7455532a11acda14f1d90cf2 100644 (file)
@@ -2,13 +2,14 @@ USING: alien byte-arrays help.markup help.syntax math math.blas.vectors sequence
 IN: math.blas.matrices
 
 ARTICLE: "math.blas-summary" "Basic Linear Algebra Subroutines (BLAS) interface"
-"Factor provides an interface to high-performance vector and matrix math routines available in the system's BLAS library. A set of specialized types are provided for handling packed, unboxed vector data:"
+"Factor provides an interface to high-performance vector and matrix math routines available in implementations of the BLAS math library. A set of specialized types are provided for handling packed, unboxed vector data:"
 { $subsection "math.blas-types" }
 "Scalar-vector and vector-vector operations are available in the " { $vocab-link "math.blas.vectors" } " vocabulary:"
 { $subsection "math.blas.vectors" }
 "Vector-matrix and matrix-matrix operations are available in the " { $vocab-link "math.blas.matrices" } " vocabulary:"
 { $subsection "math.blas.matrices" }
-"The low-level BLAS Fortran interface can be accessed directly through the " { $vocab-link "math.blas.ffi" } " vocabulary." ;
+"The low-level BLAS Fortran interface can be accessed directly through the " { $vocab-link "math.blas.ffi" } " vocabulary. The BLAS interface can be configured to use different underlying BLAS implementations:"
+{ $subsection "math.blas.config" } ;
 
 ARTICLE: "math.blas-types" "BLAS interface types"
 "BLAS vectors come in single- and double-precision, real and complex flavors:"
index 33a5d96fc468dffd5bea90fe287fdc2d72b75f66..f7d0d5a94160ea527f967b853936e945ccd18b68 100644 (file)
@@ -13,7 +13,8 @@ ARTICLE: "integer-functions" "Integer functions"
 "Tests:"
 { $subsection power-of-2? }
 { $subsection even? }
-{ $subsection odd? } ;
+{ $subsection odd? }
+{ $subsection divisor? } ;
 
 ARTICLE: "arithmetic-functions" "Arithmetic functions"
 "Computing additive and multiplicative inverses:"
@@ -269,6 +270,11 @@ HELP: gcd
 { $description "Computes the positive greatest common divisor " { $snippet "d" } " of " { $snippet "x" } " and " { $snippet "y" } ", and another value " { $snippet "a" } " satisfying:" { $code "a*y = d mod x" } }
 { $notes "If " { $snippet "d" } " is 1, then " { $snippet "a" } " is the inverse of " { $snippet "y" } " modulo " { $snippet "x" } "." } ;
 
+HELP: divisor?
+{ $values { "m" integer } { "n" integer } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "n" } " is a divisor of " { $snippet "m" } ". This is the same thing as asking if " { $snippet "m" } " is divisible by " { $snippet "n" } "." }
+{ $notes "Returns t for both negative and positive divisors, as well as for trivial and non-trivial divisors." } ;
+
 HELP: mod-inv
 { $values { "x" integer } { "n" integer } { "y" integer } }
 { $description "Outputs an integer " { $snippet "y" } " such that " { $snippet "xy = 1 (mod n)" } "." }
index 9f5ce36be1fb593bafc1277b6e7e86f592476539..397a7cc2f3faa66e9bec396f0dd1eda396da3300 100644 (file)
@@ -22,9 +22,9 @@ IN: math.functions.tests
 [ t ] [ e pi i* ^ imaginary-part -0.00001 0.00001 between? ] unit-test
 
 [ t ] [ 0 0 ^ fp-nan? ] unit-test
-[ 1.0/0.0 ] [ 0 -2 ^ ] unit-test
+[ 1/0. ] [ 0 -2 ^ ] unit-test
 [ t ] [ 0 0.0 ^ fp-nan? ] unit-test
-[ 1.0/0.0 ] [ 0 -2.0 ^ ] unit-test
+[ 1/0. ] [ 0 -2.0 ^ ] unit-test
 [ 0 ] [ 0 3.0 ^ ] unit-test
 [ 0 ] [ 0 3 ^ ] unit-test
 
@@ -32,13 +32,13 @@ IN: math.functions.tests
 
 [ 1.0 ] [ 0 cosh ] unit-test
 [ 0.0 ] [ 1 acosh ] unit-test
-            
+
 [ 1.0 ] [ 0 cos ] unit-test
 [ 0.0 ] [ 1 acos ] unit-test
-            
+
 [ 0.0 ] [ 0 sinh ] unit-test
 [ 0.0 ] [ 0 asinh ] unit-test
-            
+
 [ 0.0 ] [ 0 sin ] unit-test
 [ 0.0 ] [ 0 asin ] unit-test
 
@@ -97,11 +97,17 @@ IN: math.functions.tests
 
 : verify-gcd ( a b -- ? )
     2dup gcd
-    [ rot * swap rem ] dip = ; 
+    [ rot * swap rem ] dip = ;
 
 [ t ] [ 123 124 verify-gcd ] unit-test
 [ t ] [ 50 120 verify-gcd ] unit-test
 
+[ t ] [ 0 42 divisor? ] unit-test
+[ t ] [ 42 7 divisor? ] unit-test
+[ t ] [ 42 -7 divisor? ] unit-test
+[ t ] [ 42 42 divisor? ] unit-test
+[ f ] [ 42 16 divisor? ] unit-test
+
 [ 3 ] [ 5 7 mod-inv ] unit-test
 [ 78572682077 ] [ 234829342 342389423843 mod-inv ] unit-test
 
@@ -150,4 +156,4 @@ IN: math.functions.tests
     1067811677921310779
     2135623355842621559
     [ >bignum ] tri@ ^mod
-] unit-test
\ No newline at end of file
+] unit-test
index a87b3995d7eb03a6b0b65f46dba4f8c08ab160d7..a6beb87345926b08d2c27bc0f7df28c3b8a9d3c6 100644 (file)
@@ -81,7 +81,7 @@ PRIVATE>
     2dup [ real? ] both? [ drop 0 >= ] [ 2drop f ] if ; inline
 
 : 0^ ( x -- z )
-    dup zero? [ drop 0./0. ] [ 0 < 1./0. 0 ? ] if ; inline
+    dup zero? [ drop 0/0. ] [ 0 < 1/0. 0 ? ] if ; inline
 
 : (^mod) ( n x y -- z )
     make-bits 1 [
@@ -111,6 +111,9 @@ PRIVATE>
 : lcm ( a b -- c )
     [ * ] 2keep gcd nip /i ; foldable
 
+: divisor? ( m n -- ? )
+    mod 0 = ;
+
 : mod-inv ( x n -- y )
     [ nip ] [ gcd 1 = ] 2bi
     [ dup 0 < [ + ] [ nip ] if ]
@@ -198,7 +201,7 @@ M: real sin fsin ;
 
 GENERIC: sinh ( x -- y ) foldable
 
-M: complex sinh 
+M: complex sinh
     >float-rect
     [ [ fsinh ] [ fcos ] bi* * ]
     [ [ fcosh ] [ fsin ] bi* * ] 2bi rect> ;
index 4fbc88097122989f9dde59e3b8a514a0e002ba1e..02ea181f4e7b365188cfb0111e6229cd6dc94aa2 100755 (executable)
@@ -40,13 +40,13 @@ TUPLE: interval { from read-only } { to read-only } ;
 : [a,a] ( a -- interval )
     closed-point dup <interval> ; foldable
 
-: [-inf,a] ( a -- interval ) -1./0. swap [a,b] ; inline
+: [-inf,a] ( a -- interval ) -1/0. swap [a,b] ; inline
 
-: [-inf,a) ( a -- interval ) -1./0. swap [a,b) ; inline
+: [-inf,a) ( a -- interval ) -1/0. swap [a,b) ; inline
 
-: [a,inf] ( a -- interval ) 1./0. [a,b] ; inline
+: [a,inf] ( a -- interval ) 1/0. [a,b] ; inline
 
-: (a,inf] ( a -- interval ) 1./0. (a,b] ; inline
+: (a,inf] ( a -- interval ) 1/0. (a,b] ; inline
 
 : [-inf,inf] ( -- interval ) full-interval ; inline
 
index bf4c608d77bbac41fd036db7c02ee88a21f7c366..a890a59c19daecefce02bfc1452a48a61110e030 100644 (file)
@@ -6,7 +6,7 @@ ARTICLE: "math.libm" "C standard library math functions"
 $nl
 "They can be called directly, however there is little reason to do so, since they only implement real-valued functions, and in some cases place restrictions on the domain:"
 { $example "USE: math.functions" "2 acos ." "C{ 0.0 1.316957896924817 }" }
-{ $unchecked-example "USE: math.libm" "2 facos ." "0.0/0.0" }
+{ $unchecked-example "USE: math.libm" "2 facos ." "0/0." }
 "Trigonometric functions:"
 { $subsection fcos }
 { $subsection fsin }
index 199b72b7e146143f510a6752b4e8488db830b820..278bf70b3d28d9c263600e5c6511e89ef79bf003 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2007-2009 Samuel Tardieu.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays combinators kernel make math math.primes sequences ;
+USING: arrays combinators kernel make math math.functions math.primes sequences ;
 IN: math.primes.factors
 
 <PRIVATE
@@ -11,7 +11,7 @@ IN: math.primes.factors
     swap ;
 
 : write-factor ( n d -- n' d' )
-    2dup mod zero? [
+    2dup divisor? [
         [ [ count-factor ] keep swap 2array , ] keep
         ! If the remainder is a prime number, increase d so that
         ! the caller stops looking for factors.
index 8987def80bbae6727504c3d32449e4d2de93089c..e35adb10e55e7b0d16b7b2ff3165f7eb64f5b002 100644 (file)
@@ -2,7 +2,7 @@ USING: help.syntax help.markup arrays sequences ;
 
 IN: math.ranges
 
-ARTICLE: "ranges" "Ranges"
+ARTICLE: "math.ranges" "Numeric ranges"
 "A " { $emphasis "range" } " is a virtual sequence with real number elements "
 "ranging from " { $emphasis "a" } " to " { $emphasis "b" } " by " { $emphasis "step" } ". Ascending as well as descending ranges are supported."
 $nl
@@ -24,4 +24,4 @@ $nl
 { $code "100 1 [a,b] product" }
 "A range can be converted into a concrete sequence using a word such as " { $link >array } ". In most cases this is unnecessary since ranges implement the sequence protocol already. It is necessary if a mutable sequence is needed, for use with words such as " { $link set-nth } " or " { $link change-each } "." ;
   
-ABOUT: "ranges"
\ No newline at end of file
+ABOUT: "math.ranges"
\ No newline at end of file
diff --git a/basis/models/arrow/smart/smart-docs.factor b/basis/models/arrow/smart/smart-docs.factor
new file mode 100644 (file)
index 0000000..45faf52
--- /dev/null
@@ -0,0 +1,21 @@
+IN: models.arrow.smart
+USING: help.syntax help.markup models.product ;
+
+HELP: <smart-arrow>
+{ $values { "quot" { $quotation "( ... -- output )" } } }
+{ $description "A macro that expands into a form with the stack effect of the quotation. The form constructs a model which applies the quotation to values from an underlying " { $link product } " model having as many components as the quotation has inputs." }
+{ $examples
+  "A model which adds the values of two existing models:"
+  { $example
+    "USING: models models.arrows.smart accessors math prettyprint ;"
+    "1 <model> 2 <model> [ + ] <smart-arrow>"
+    "[ activate-model ] [ value>> ] bi ."
+    "3"
+  }
+} ;
+
+ARTICLE: "models.arrows.smart" "Smart arrow models"
+"The " { $vocab-link "models.arrows.smart" } " vocabulary generalizes arrows to arbitrary input arity. They're called “smart” because they resemble " { $link "combinators.smart" } "."
+{ $subsection <smart-arrow> } ;
+
+ABOUT: "models.arrows.smart"
\ No newline at end of file
diff --git a/basis/models/history/history-docs.factor b/basis/models/history/history-docs.factor
deleted file mode 100644 (file)
index d157729..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-USING: help.syntax help.markup kernel math classes classes.tuple\r
-calendar models ;\r
-IN: models.history\r
-\r
-HELP: history\r
-{ $class-description "History models record a timeline of previous values on calls to " { $link add-history } ", and can travel back and forth on the timeline with " { $link go-back } " and " { $link go-forward } ". History models are constructed by " { $link <history> } "." } ;\r
-\r
-HELP: <history>\r
-{ $values { "value" object } { "history" "a new " { $link history } } }\r
-{ $description "Creates a new history model with an initial value." } ;\r
-\r
-{ <history> add-history go-back go-forward } related-words\r
-\r
-HELP: go-back\r
-{ $values { "history" history } }\r
-{ $description "Restores the previous value and calls " { $link model-changed } " on all observers registered with " { $link add-connection } "." } ;\r
-\r
-HELP: go-forward\r
-{ $values { "history" history } }\r
-{ $description "Restores the value set prior to the last call to " { $link go-back } " and calls " { $link model-changed } " on all observers registered with " { $link add-connection } "." } ;\r
-\r
-HELP: add-history\r
-{ $values { "history" history } }\r
-{ $description "Adds the current value to the history." } ;\r
-\r
-ARTICLE: "models-history" "History models"\r
-"History models record previous values."\r
-{ $subsection history }\r
-{ $subsection <history> }\r
-"Recording history:"\r
-{ $subsection add-history }\r
-"Navigating the history:"\r
-{ $subsection go-back }\r
-{ $subsection go-forward } ;\r
-\r
-ABOUT: "models-history"\r
diff --git a/basis/models/history/history-tests.factor b/basis/models/history/history-tests.factor
deleted file mode 100644 (file)
index c89dd5c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-USING: arrays generic kernel math models namespaces sequences assocs\r
-tools.test models.history accessors ;\r
-IN: models.history.tests\r
-\r
-f <history> "history" set\r
-\r
-"history" get add-history\r
-\r
-[ t ] [ "history" get back>> empty? ] unit-test\r
-[ t ] [ "history" get forward>> empty? ] unit-test\r
-\r
-"history" get add-history\r
-3 "history" get set-model\r
-\r
-[ t ] [ "history" get back>> empty? ] unit-test\r
-[ t ] [ "history" get forward>> empty? ] unit-test\r
-\r
-"history" get add-history\r
-4 "history" get set-model\r
-\r
-[ f ] [ "history" get back>> empty? ] unit-test\r
-[ t ] [ "history" get forward>> empty? ] unit-test\r
-\r
-"history" get go-back\r
-\r
-[ 3 ] [ "history" get value>> ] unit-test\r
-\r
-[ t ] [ "history" get back>> empty? ] unit-test\r
-[ f ] [ "history" get forward>> empty? ] unit-test\r
-\r
-"history" get go-forward\r
-\r
-[ 4 ] [ "history" get value>> ] unit-test\r
-\r
-[ f ] [ "history" get back>> empty? ] unit-test\r
-[ t ] [ "history" get forward>> empty? ] unit-test\r
-\r
diff --git a/basis/models/history/history.factor b/basis/models/history/history.factor
deleted file mode 100644 (file)
index 90d6b59..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.\r
-! See http://factorcode.org/license.txt for BSD license.\r
-USING: accessors kernel models sequences ;\r
-IN: models.history\r
-\r
-TUPLE: history < model back forward ;\r
-\r
-: reset-history ( history -- history )\r
-    V{ } clone >>back\r
-    V{ } clone >>forward ; inline\r
-\r
-: <history> ( value -- history )\r
-    history new-model\r
-        reset-history ;\r
-\r
-: (add-history) ( history to -- )\r
-    swap value>> dup [ swap push ] [ 2drop ] if ;\r
-\r
-: go-back/forward ( history to from -- )\r
-    [ 2drop ]\r
-    [ [ dupd (add-history) ] dip pop swap set-model ] if-empty ;\r
-\r
-: go-back ( history -- )\r
-    dup [ forward>> ] [ back>> ] bi go-back/forward ;\r
-\r
-: go-forward ( history -- )\r
-    dup [ back>> ] [ forward>> ] bi go-back/forward ;\r
-\r
-: add-history ( history -- )\r
-    dup forward>> delete-all\r
-    dup back>> (add-history) ;\r
diff --git a/basis/models/history/summary.txt b/basis/models/history/summary.txt
deleted file mode 100644 (file)
index 76f7b88..0000000
+++ /dev/null
@@ -1 +0,0 @@
-History models remember prior values
index 2b90bdb0d5b638d08697de297423eb5d5e16dc22..8f40a8adbe90c725f975632e933243e3716c9fa4 100644 (file)
@@ -133,7 +133,6 @@ $nl
 { $subsection "models-impl" }
 { $subsection "models.arrow" }
 { $subsection "models.product" }
-{ $subsection "models-history" }
 { $subsection "models-range" }
 { $subsection "models-delay" } ;
 
index 55ac3c728e5f18205c67bd0b04ff03d7476e7035..f4e25322b8837d0e372b21d2d236b93c349ff615 100644 (file)
@@ -1,3 +1,4 @@
 Slava Pestov
 Eduardo Cavazos
 Joe Groff
+Alex Chapman
index 09d49b33c284645939a952a03696b9acb8babb60..ad04ce7fa5ce72547a841ab979f2a39636cba985 100755 (executable)
@@ -32,6 +32,8 @@ IN: opengl.capabilities
     (gl-version) drop ;
 : gl-vendor-version ( -- version )
     (gl-version) nip ;
+: gl-vendor ( -- name )
+    GL_VENDOR glGetString ;
 : has-gl-version? ( version -- ? )
     gl-version version-before? ;
 : (make-gl-version-error) ( required-version -- )
index 1901f27a24507e2512d93a1f956aaaa0d2f05714..e9c193bac72836f0710fc5440af248256e9fc736 100644 (file)
@@ -1 +1 @@
-Slava Pestov
+Alex Chapman
diff --git a/basis/opengl/glu/authors.txt b/basis/opengl/glu/authors.txt
deleted file mode 100644 (file)
index 1901f27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
diff --git a/basis/opengl/glu/glu.factor b/basis/opengl/glu/glu.factor
deleted file mode 100644 (file)
index d603724..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-! Copyright (C) 2005 Alex Chapman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.syntax kernel sequences words ;
-IN: opengl.glu
-
-! These are defined as structs in glu.h, but we only ever use pointers to them
-TYPEDEF: void* GLUnurbs*
-TYPEDEF: void* GLUquadric*
-TYPEDEF: void* GLUtesselator*
-TYPEDEF: void* GLubyte*
-TYPEDEF: void* GLUfuncptr
-
-! StringName
-CONSTANT: GLU_VERSION                        100800
-CONSTANT: GLU_EXTENSIONS                     100801
-
-! ErrorCode
-CONSTANT: GLU_INVALID_ENUM                   100900
-CONSTANT: GLU_INVALID_VALUE                  100901
-CONSTANT: GLU_OUT_OF_MEMORY                  100902
-CONSTANT: GLU_INCOMPATIBLE_GL_VERSION        100903
-CONSTANT: GLU_INVALID_OPERATION              100904
-
-! NurbsDisplay
-CONSTANT: GLU_OUTLINE_POLYGON                100240
-CONSTANT: GLU_OUTLINE_PATCH                  100241
-
-! NurbsCallback
-CONSTANT: GLU_NURBS_ERROR                    100103
-CONSTANT: GLU_ERROR                          100103
-CONSTANT: GLU_NURBS_BEGIN                    100164
-CONSTANT: GLU_NURBS_BEGIN_EXT                100164
-CONSTANT: GLU_NURBS_VERTEX                   100165
-CONSTANT: GLU_NURBS_VERTEX_EXT               100165
-CONSTANT: GLU_NURBS_NORMAL                   100166
-CONSTANT: GLU_NURBS_NORMAL_EXT               100166
-CONSTANT: GLU_NURBS_COLOR                    100167
-CONSTANT: GLU_NURBS_COLOR_EXT                100167
-CONSTANT: GLU_NURBS_TEXTURE_COORD            100168
-CONSTANT: GLU_NURBS_TEX_COORD_EXT            100168
-CONSTANT: GLU_NURBS_END                      100169
-CONSTANT: GLU_NURBS_END_EXT                  100169
-CONSTANT: GLU_NURBS_BEGIN_DATA               100170
-CONSTANT: GLU_NURBS_BEGIN_DATA_EXT           100170
-CONSTANT: GLU_NURBS_VERTEX_DATA              100171
-CONSTANT: GLU_NURBS_VERTEX_DATA_EXT          100171
-CONSTANT: GLU_NURBS_NORMAL_DATA              100172
-CONSTANT: GLU_NURBS_NORMAL_DATA_EXT          100172
-CONSTANT: GLU_NURBS_COLOR_DATA               100173
-CONSTANT: GLU_NURBS_COLOR_DATA_EXT           100173
-CONSTANT: GLU_NURBS_TEXTURE_COORD_DATA       100174
-CONSTANT: GLU_NURBS_TEX_COORD_DATA_EXT       100174
-CONSTANT: GLU_NURBS_END_DATA                 100175
-CONSTANT: GLU_NURBS_END_DATA_EXT             100175
-
-! NurbsError
-CONSTANT: GLU_NURBS_ERROR1                   100251
-CONSTANT: GLU_NURBS_ERROR2                   100252
-CONSTANT: GLU_NURBS_ERROR3                   100253
-CONSTANT: GLU_NURBS_ERROR4                   100254
-CONSTANT: GLU_NURBS_ERROR5                   100255
-CONSTANT: GLU_NURBS_ERROR6                   100256
-CONSTANT: GLU_NURBS_ERROR7                   100257
-CONSTANT: GLU_NURBS_ERROR8                   100258
-CONSTANT: GLU_NURBS_ERROR9                   100259
-CONSTANT: GLU_NURBS_ERROR10                  100260
-CONSTANT: GLU_NURBS_ERROR11                  100261
-CONSTANT: GLU_NURBS_ERROR12                  100262
-CONSTANT: GLU_NURBS_ERROR13                  100263
-CONSTANT: GLU_NURBS_ERROR14                  100264
-CONSTANT: GLU_NURBS_ERROR15                  100265
-CONSTANT: GLU_NURBS_ERROR16                  100266
-CONSTANT: GLU_NURBS_ERROR17                  100267
-CONSTANT: GLU_NURBS_ERROR18                  100268
-CONSTANT: GLU_NURBS_ERROR19                  100269
-CONSTANT: GLU_NURBS_ERROR20                  100270
-CONSTANT: GLU_NURBS_ERROR21                  100271
-CONSTANT: GLU_NURBS_ERROR22                  100272
-CONSTANT: GLU_NURBS_ERROR23                  100273
-CONSTANT: GLU_NURBS_ERROR24                  100274
-CONSTANT: GLU_NURBS_ERROR25                  100275
-CONSTANT: GLU_NURBS_ERROR26                  100276
-CONSTANT: GLU_NURBS_ERROR27                  100277
-CONSTANT: GLU_NURBS_ERROR28                  100278
-CONSTANT: GLU_NURBS_ERROR29                  100279
-CONSTANT: GLU_NURBS_ERROR30                  100280
-CONSTANT: GLU_NURBS_ERROR31                  100281
-CONSTANT: GLU_NURBS_ERROR32                  100282
-CONSTANT: GLU_NURBS_ERROR33                  100283
-CONSTANT: GLU_NURBS_ERROR34                  100284
-CONSTANT: GLU_NURBS_ERROR35                  100285
-CONSTANT: GLU_NURBS_ERROR36                  100286
-CONSTANT: GLU_NURBS_ERROR37                  100287
-
-! NurbsProperty
-CONSTANT: GLU_AUTO_LOAD_MATRIX               100200
-CONSTANT: GLU_CULLING                        100201
-CONSTANT: GLU_SAMPLING_TOLERANCE             100203
-CONSTANT: GLU_DISPLAY_MODE                   100204
-CONSTANT: GLU_PARAMETRIC_TOLERANCE           100202
-CONSTANT: GLU_SAMPLING_METHOD                100205
-CONSTANT: GLU_U_STEP                         100206
-CONSTANT: GLU_V_STEP                         100207
-CONSTANT: GLU_NURBS_MODE                     100160
-CONSTANT: GLU_NURBS_MODE_EXT                 100160
-CONSTANT: GLU_NURBS_TESSELLATOR              100161
-CONSTANT: GLU_NURBS_TESSELLATOR_EXT          100161
-CONSTANT: GLU_NURBS_RENDERER                 100162
-CONSTANT: GLU_NURBS_RENDERER_EXT             100162
-
-! NurbsSampling
-CONSTANT: GLU_OBJECT_PARAMETRIC_ERROR        100208
-CONSTANT: GLU_OBJECT_PARAMETRIC_ERROR_EXT    100208
-CONSTANT: GLU_OBJECT_PATH_LENGTH             100209
-CONSTANT: GLU_OBJECT_PATH_LENGTH_EXT         100209
-CONSTANT: GLU_PATH_LENGTH                    100215
-CONSTANT: GLU_PARAMETRIC_ERROR               100216
-CONSTANT: GLU_DOMAIN_DISTANCE                100217
-
-! NurbsTrim
-CONSTANT: GLU_MAP1_TRIM_2                    100210
-CONSTANT: GLU_MAP1_TRIM_3                    100211
-
-! QuadricDrawStyle
-CONSTANT: GLU_POINT                          100010
-CONSTANT: GLU_LINE                           100011
-CONSTANT: GLU_FILL                           100012
-CONSTANT: GLU_SILHOUETTE                     100013
-
-! QuadricNormal
-CONSTANT: GLU_SMOOTH                         100000
-CONSTANT: GLU_FLAT                           100001
-CONSTANT: GLU_NONE                           100002
-
-! QuadricOrientation
-CONSTANT: GLU_OUTSIDE                        100020
-CONSTANT: GLU_INSIDE                         100021
-
-! TessCallback
-CONSTANT: GLU_TESS_BEGIN                     100100
-CONSTANT: GLU_BEGIN                          100100
-CONSTANT: GLU_TESS_VERTEX                    100101
-CONSTANT: GLU_VERTEX                         100101
-CONSTANT: GLU_TESS_END                       100102
-CONSTANT: GLU_END                            100102
-CONSTANT: GLU_TESS_ERROR                     100103
-CONSTANT: GLU_TESS_EDGE_FLAG                 100104
-CONSTANT: GLU_EDGE_FLAG                      100104
-CONSTANT: GLU_TESS_COMBINE                   100105
-CONSTANT: GLU_TESS_BEGIN_DATA                100106
-CONSTANT: GLU_TESS_VERTEX_DATA               100107
-CONSTANT: GLU_TESS_END_DATA                  100108
-CONSTANT: GLU_TESS_ERROR_DATA                100109
-CONSTANT: GLU_TESS_EDGE_FLAG_DATA            100110
-CONSTANT: GLU_TESS_COMBINE_DATA              100111
-
-! TessContour
-CONSTANT: GLU_CW                             100120
-CONSTANT: GLU_CCW                            100121
-CONSTANT: GLU_INTERIOR                       100122
-CONSTANT: GLU_EXTERIOR                       100123
-CONSTANT: GLU_UNKNOWN                        100124
-
-! TessProperty
-CONSTANT: GLU_TESS_WINDING_RULE              100140
-CONSTANT: GLU_TESS_BOUNDARY_ONLY             100141
-CONSTANT: GLU_TESS_TOLERANCE                 100142
-
-! TessError
-CONSTANT: GLU_TESS_ERROR1                    100151
-CONSTANT: GLU_TESS_ERROR2                    100152
-CONSTANT: GLU_TESS_ERROR3                    100153
-CONSTANT: GLU_TESS_ERROR4                    100154
-CONSTANT: GLU_TESS_ERROR5                    100155
-CONSTANT: GLU_TESS_ERROR6                    100156
-CONSTANT: GLU_TESS_ERROR7                    100157
-CONSTANT: GLU_TESS_ERROR8                    100158
-CONSTANT: GLU_TESS_MISSING_BEGIN_POLYGON     100151
-CONSTANT: GLU_TESS_MISSING_BEGIN_CONTOUR     100152
-CONSTANT: GLU_TESS_MISSING_END_POLYGON       100153
-CONSTANT: GLU_TESS_MISSING_END_CONTOUR       100154
-CONSTANT: GLU_TESS_COORD_TOO_LARGE           100155
-CONSTANT: GLU_TESS_NEED_COMBINE_CALLBACK     100156
-
-! TessWinding
-CONSTANT: GLU_TESS_WINDING_ODD               100130
-CONSTANT: GLU_TESS_WINDING_NONZERO           100131
-CONSTANT: GLU_TESS_WINDING_POSITIVE          100132
-CONSTANT: GLU_TESS_WINDING_NEGATIVE          100133
-CONSTANT: GLU_TESS_WINDING_ABS_GEQ_TWO       100134
-
-LIBRARY: glu
-
-FUNCTION: void gluBeginCurve ( GLUnurbs* nurb ) ;
-FUNCTION: void gluBeginPolygon ( GLUtesselator* tess ) ;
-FUNCTION: void gluBeginSurface ( GLUnurbs* nurb ) ;
-FUNCTION: void gluBeginTrim ( GLUnurbs* nurb ) ;
-
-FUNCTION: void gluCylinder ( GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks ) ;
-FUNCTION: void gluDeleteNurbsRenderer ( GLUnurbs* nurb ) ;
-FUNCTION: void gluDeleteQuadric ( GLUquadric* quad ) ;
-FUNCTION: void gluDeleteTess ( GLUtesselator* tess ) ;
-FUNCTION: void gluDisk ( GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops ) ;
-FUNCTION: void gluEndCurve ( GLUnurbs* nurb ) ;
-FUNCTION: void gluEndPolygon ( GLUtesselator* tess ) ;
-FUNCTION: void gluEndSurface ( GLUnurbs* nurb ) ;
-FUNCTION: void gluEndTrim ( GLUnurbs* nurb ) ;
-FUNCTION: char* gluErrorString ( GLenum error ) ;
-FUNCTION: void gluGetNurbsProperty ( GLUnurbs* nurb, GLenum property, GLfloat* data ) ;
-FUNCTION: char* gluGetString ( GLenum name ) ;
-FUNCTION: void gluGetTessProperty ( GLUtesselator* tess, GLenum which, GLdouble* data ) ;
-FUNCTION: void gluLoadSamplingMatrices ( GLUnurbs* nurb, GLfloat* model, GLfloat* perspective, GLint* view ) ;
-FUNCTION: void gluLookAt ( GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble upX, GLdouble upY, GLdouble upZ ) ;
-FUNCTION: GLUnurbs* gluNewNurbsRenderer ( ) ;
-FUNCTION: GLUquadric* gluNewQuadric ( ) ;
-FUNCTION: GLUtesselator* gluNewTess ( ) ;
-FUNCTION: void gluNextContour ( GLUtesselator* tess, GLenum type ) ;
-FUNCTION: void gluNurbsCallback ( GLUnurbs* nurb, GLenum which, GLUfuncptr CallBackFunc ) ;
-! FUNCTION: void gluNurbsCallbackData ( GLUnurbs* nurb, GLvoid* userData ) ;
-! FUNCTION: void gluNurbsCallbackDataEXT ( GLUnurbs* nurb, GLvoid* userData ) ;
-FUNCTION: void gluNurbsCurve ( GLUnurbs* nurb, GLint knotCount, GLfloat *knots, GLint stride, GLfloat *control, GLint order, GLenum type ) ;
-FUNCTION: void gluNurbsProperty ( GLUnurbs* nurb, GLenum property, GLfloat value ) ;
-FUNCTION: void gluNurbsSurface ( GLUnurbs* nurb, GLint sKnotCount, GLfloat* sKnots, GLint tKnotCount, GLfloat* tKnots, GLint sStride, GLint tStride, GLfloat* control, GLint sOrder, GLint tOrder, GLenum type ) ;
-FUNCTION: void gluOrtho2D ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) ;
-FUNCTION: void gluPartialDisk ( GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops, GLdouble start, GLdouble sweep ) ;
-FUNCTION: void gluPerspective ( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) ;
-FUNCTION: void gluPickMatrix ( GLdouble x, GLdouble y, GLdouble delX, GLdouble delY, GLint* viewport ) ;
-FUNCTION: GLint gluProject ( GLdouble objX, GLdouble objY, GLdouble objZ, GLdouble* model, GLdouble* proj, GLint* view, GLdouble* winX, GLdouble* winY, GLdouble* winZ ) ;
-FUNCTION: void gluPwlCurve ( GLUnurbs* nurb, GLint count, GLfloat* data, GLint stride, GLenum type ) ;
-FUNCTION: void gluQuadricCallback ( GLUquadric* quad, GLenum which, GLUfuncptr CallBackFunc ) ;
-FUNCTION: void gluQuadricDrawStyle ( GLUquadric* quad, GLenum draw ) ;
-FUNCTION: void gluQuadricNormals ( GLUquadric* quad, GLenum normal ) ;
-FUNCTION: void gluQuadricOrientation ( GLUquadric* quad, GLenum orientation ) ;
-FUNCTION: void gluQuadricTexture ( GLUquadric* quad, GLboolean texture ) ;
-FUNCTION: GLint gluScaleImage ( GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, void* dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut ) ;
-FUNCTION: void gluSphere ( GLUquadric* quad, GLdouble radius, GLint slices, GLint stacks ) ;
-FUNCTION: void gluTessBeginContour ( GLUtesselator* tess ) ;
-FUNCTION: void gluTessBeginPolygon ( GLUtesselator* tess, GLvoid* data ) ;
-FUNCTION: void gluTessCallback ( GLUtesselator* tess, GLenum which, GLUfuncptr CallBackFunc ) ;
-FUNCTION: void gluTessEndContour ( GLUtesselator* tess ) ;
-FUNCTION: void gluTessEndPolygon ( GLUtesselator* tess ) ;
-FUNCTION: void gluTessNormal ( GLUtesselator* tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ ) ;
-FUNCTION: void gluTessProperty ( GLUtesselator* tess, GLenum which, GLdouble data ) ;
-FUNCTION: void gluTessVertex ( GLUtesselator* tess, GLdouble* location, GLvoid* data ) ;
-FUNCTION: GLint gluUnProject ( GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble* model, GLdouble* proj, GLint* view, GLdouble* objX, GLdouble* objY, GLdouble* objZ ) ;
-
-! Not present on Windows
-! FUNCTION: GLint gluBuild1DMipmapLevels ( GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, GLint level, GLint base, GLint max, void* data ) ;
-! FUNCTION: GLint gluBuild1DMipmaps ( GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, void* data ) ;
-! FUNCTION: GLint gluBuild2DMipmapLevels ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint level, GLint base, GLint max, void* data ) ;
-! FUNCTION: GLint gluBuild2DMipmaps ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, void* data ) ;
-! FUNCTION: GLint gluBuild3DMipmapLevels ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint level, GLint base, GLint max, void* data ) ;
-! FUNCTION: GLint gluBuild3DMipmaps ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void* data ) ;
-! FUNCTION: GLboolean gluCheckExtension ( GLubyte* extName, GLubyte* extString ) ;
-! FUNCTION: GLint gluUnProject4 ( GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, GLdouble* model, GLdouble* proj, GLint* view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW ) ;
diff --git a/basis/opengl/glu/summary.txt b/basis/opengl/glu/summary.txt
deleted file mode 100644 (file)
index a90f4a3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-OpenGL binding - libGLU
diff --git a/basis/opengl/glu/tags.txt b/basis/opengl/glu/tags.txt
deleted file mode 100644 (file)
index bb863cf..0000000
+++ /dev/null
@@ -1 +0,0 @@
-bindings
index f474c97b73ce800587f81155f371ced10b494829..b7738332804694ba8dd5ae7ca708064ace7f1e6f 100644 (file)
@@ -15,8 +15,8 @@ HELP: do-enabled
 { $description "Wraps a quotation in " { $link glEnable } "/" { $link glDisable } " calls." } ;
 
 HELP: do-matrix
-{ $values { "mode" { $link GL_MODELVIEW } " or " { $link GL_PROJECTION } } { "quot" quotation } }
-{ $description "Saves and restores the matrix specified by " { $snippet "mode" } " before and after calling the quotation." } ;
+{ $values { "quot" quotation } }
+{ $description "Saves and restores the current matrix before and after calling the quotation." } ;
 
 HELP: gl-line
 { $values { "a" "a pair of integers" } { "b" "a pair of integers" } }
index 0a21f67376cc524d564c5af27a07c89f53dd8d9f..72ca8b8cdbbb2306d7a647aac6251b3197aea9b1 100644 (file)
@@ -3,7 +3,7 @@
 ! Portions copyright (C) 2008 Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types continuations kernel libc math macros
-namespaces math.vectors math.parser opengl.gl opengl.glu combinators
+namespaces math.vectors math.parser opengl.gl combinators
 combinators.smart arrays sequences splitting words byte-arrays assocs
 colors colors.constants accessors generalizations locals fry
 specialized-arrays.float specialized-arrays.uint ;
@@ -16,10 +16,23 @@ IN: opengl
 : gl-clear ( color -- )
     gl-clear-color GL_COLOR_BUFFER_BIT glClear ;
 
+: error>string ( n -- string )
+    H{
+        { HEX: 0 "No error" }
+        { HEX: 0501 "Invalid value" }
+        { HEX: 0500 "Invalid enumerant" }
+        { HEX: 0502 "Invalid operation" }
+        { HEX: 0503 "Stack overflow" }
+        { HEX: 0504 "Stack underflow" }
+        { HEX: 0505 "Out of memory" }
+    } at "Unknown error" or ;
+
+TUPLE: gl-error code string ;
+
 : gl-error ( -- )
-    glGetError dup zero? [
-        "GL error: " over gluErrorString append throw
-    ] unless drop ;
+    glGetError dup 0 = [ drop ] [
+        dup error>string \ gl-error boa throw
+    ] if ;
 
 : do-enabled ( what quot -- )
     over glEnable dip glDisable ; inline
@@ -44,9 +57,8 @@ MACRO: all-enabled ( seq quot -- )
 MACRO: all-enabled-client-state ( seq quot -- )
     [ words>values ] dip '[ _ _ (all-enabled-client-state) ] ;
 
-: do-matrix ( mode quot -- )
-    swap [ glMatrixMode glPushMatrix call ] keep
-    glMatrixMode glPopMatrix ; inline
+: do-matrix ( quot -- )
+    glPushMatrix call glPopMatrix ; inline
 
 : gl-material ( face pname params -- )
     float-array{ } like glMaterialfv ;
@@ -152,9 +164,6 @@ MACRO: all-enabled-client-state ( seq quot -- )
 MACRO: set-draw-buffers ( buffers -- )
     words>values '[ _ (set-draw-buffers) ] ;
 
-: gl-look-at ( eye focus up -- )
-    [ first3 ] tri@ gluLookAt ;
-
 : gen-dlist ( -- id ) 1 glGenLists ;
 
 : make-dlist ( type quot -- id )
@@ -165,7 +174,7 @@ MACRO: set-draw-buffers ( buffers -- )
 : delete-dlist ( id -- ) 1 glDeleteLists ;
 
 : with-translation ( loc quot -- )
-    GL_MODELVIEW [ [ gl-translate ] dip call ] do-matrix ; inline
+    [ [ gl-translate ] dip call ] do-matrix ; inline
 
 : fix-coordinates ( point1 point2 -- x1 y2 x2 y2 )
     [ first2 [ >fixnum ] bi@ ] bi@ ;
@@ -177,6 +186,7 @@ MACRO: set-draw-buffers ( buffers -- )
     fix-coordinates glViewport ;
 
 : init-matrices ( -- )
+    #! Leaves with matrix mode GL_MODELVIEW
     GL_PROJECTION glMatrixMode
     glLoadIdentity
     GL_MODELVIEW glMatrixMode
index 163871028d5901415f5cd03db3bd19bdbfaa9645..3efdb43cd8b9616c4a662b5fe3458ce5fb06af79 100644 (file)
@@ -5,56 +5,6 @@ opengl.textures.private images kernel namespaces accessors
 sequences ;
 IN: opengl.textures.tests
 
-[ ] [
-    T{ image
-       { dim { 3 5 } }
-       { component-order RGB }
-       { bitmap
-         B{
-             1 2 3 4 5 6 7 8 9
-             10 11 12 13 14 15 16 17 18
-             19 20 21 22 23 24 25 26 27
-             28 29 30 31 32 33 34 35 36
-             37 38 39 40 41 42 43 44 45
-         }
-       }
-    } "image" set
-] unit-test
-
-[
-    T{ image
-        { dim { 4 8 } }
-        { component-order RGB }
-        { bitmap
-          B{
-              1 2 3 4 5 6 7 8 9 7 8 9
-              10 11 12 13 14 15 16 17 18 16 17 18
-              19 20 21 22 23 24 25 26 27 25 26 27
-              28 29 30 31 32 33 34 35 36 34 35 36
-              37 38 39 40 41 42 43 44 45 43 44 45
-              37 38 39 40 41 42 43 44 45 43 44 45
-              37 38 39 40 41 42 43 44 45 43 44 45
-              37 38 39 40 41 42 43 44 45 43 44 45
-          }
-        }
-    }
-] [
-    "image" get power-of-2-image
-] unit-test
-
-[
-    T{ image
-       { dim { 0 0 } }
-       { component-order R32G32B32 }
-       { bitmap B{ } } }
-] [
-    T{ image
-       { dim { 0 0 } }
-       { component-order R32G32B32 }
-       { bitmap B{ } }
-    } power-of-2-image
-] unit-test
-
 [
     {
         { { 0 0 } { 10 0 } }
old mode 100644 (file)
new mode 100755 (executable)
index 810aaa2..76e0c47
@@ -1,11 +1,23 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs cache colors.constants destructors fry kernel
-opengl opengl.gl combinators images images.tesselation grouping
-specialized-arrays.float locals sequences math math.vectors
-math.matrices generalizations fry columns ;
+opengl opengl.gl opengl.capabilities combinators images
+images.tesselation grouping specialized-arrays.float sequences math
+math.vectors math.matrices generalizations fry arrays namespaces
+system ;
 IN: opengl.textures
 
+SYMBOL: non-power-of-2-textures?
+
+: check-extensions ( -- )
+    #! ATI frglx driver doesn't implement GL_ARB_texture_non_power_of_two properly.
+    #! See thread 'Linux font display problem' April 2009 on Factor-talk
+    gl-vendor "ATI Technologies Inc." = not os macosx? or [
+        "2.0" { "GL_ARB_texture_non_power_of_two" }
+        has-gl-version-or-extensions?
+        non-power-of-2-textures? set
+    ] when ;
+
 : gen-texture ( -- id ) [ glGenTextures ] (gen-gl-object) ;
 
 : delete-texture ( id -- ) [ glDeleteTextures ] (delete-gl-object) ;
@@ -17,60 +29,53 @@ M: BGR component-order>format drop GL_BGR GL_UNSIGNED_BYTE ;
 M: RGBA component-order>format drop GL_RGBA GL_UNSIGNED_BYTE ;
 M: ARGB component-order>format drop GL_BGRA_EXT GL_UNSIGNED_INT_8_8_8_8_REV ;
 M: BGRA component-order>format drop GL_BGRA_EXT GL_UNSIGNED_BYTE ;
+M: BGRX component-order>format drop GL_BGRA_EXT GL_UNSIGNED_BYTE ;
+M: LA component-order>format drop GL_LUMINANCE_ALPHA GL_UNSIGNED_BYTE ;
+M: L component-order>format drop GL_LUMINANCE GL_UNSIGNED_BYTE ;
+
+SLOT: display-list
 
-GENERIC: draw-texture ( texture -- )
+: draw-texture ( texture -- ) display-list>> [ glCallList ] when* ;
 
 GENERIC: draw-scaled-texture ( dim texture -- )
 
 <PRIVATE
 
-TUPLE: single-texture loc dim texture-coords texture display-list disposed ;
-
-: repeat-last ( seq n -- seq' )
-    over peek pad-tail concat ;
-
-: power-of-2-bitmap ( rows dim size -- bitmap dim )
-    '[
-        first2
-        [ [ _ ] dip '[ _ group _ repeat-last ] map ]
-        [ repeat-last ]
-        bi*
-    ] keep ;
+TUPLE: single-texture image dim loc texture-coords texture display-list disposed ;
 
-: image-rows ( image -- rows )
-    [ bitmap>> ]
-    [ dim>> first ]
-    [ component-order>> bytes-per-pixel ]
-    tri * group ; inline
-
-: power-of-2-image ( image -- image )
-    dup dim>> [ 0 = ] all? [
-        clone dup
-        [ image-rows ]
-        [ dim>> [ next-power-of-2 ] map ]
-        [ component-order>> bytes-per-pixel ] tri
-        power-of-2-bitmap
-        [ >>bitmap ] [ >>dim ] bi*
+: adjust-texture-dim ( dim -- dim' )
+    non-power-of-2-textures? get [
+        [ next-power-of-2 ] map
     ] unless ;
 
-:: make-texture ( image -- id )
+: (tex-image) ( image bitmap -- )
+    [
+        [ GL_TEXTURE_2D 0 GL_RGBA ] dip
+        [ dim>> adjust-texture-dim first2 0 ]
+        [ component-order>> component-order>format ] bi
+    ] dip
+    glTexImage2D ;
+
+: (tex-sub-image) ( image -- )
+    [ GL_TEXTURE_2D 0 0 0 ] dip
+    [ dim>> first2 ] [ component-order>> component-order>format ] [ bitmap>> ] tri
+    glTexSubImage2D ;
+
+: make-texture ( image -- id )
+    #! We use glTexSubImage2D to work around the power of 2 texture size
+    #! limitation
     gen-texture [
         GL_TEXTURE_BIT [
             GL_TEXTURE_2D swap glBindTexture
-            GL_TEXTURE_2D
-            0
-            GL_RGBA
-            image dim>> first2
-            0
-            image component-order>> component-order>format
-            image bitmap>>
-            glTexImage2D
+            non-power-of-2-textures? get
+            [ dup bitmap>> (tex-image) ]
+            [ [ f (tex-image) ] [ (tex-sub-image) ] bi ] if
         ] do-attribs
     ] keep ;
 
 : init-texture ( -- )
-    GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_LINEAR glTexParameteri
-    GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_LINEAR glTexParameteri
+    GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_NEAREST glTexParameteri
+    GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_NEAREST glTexParameteri
     GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_REPEAT glTexParameteri
     GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_REPEAT glTexParameteri ;
 
@@ -92,26 +97,29 @@ TUPLE: single-texture loc dim texture-coords texture display-list disposed ;
 
 : draw-textured-rect ( dim texture -- )
     [
-        (draw-textured-rect)
-        GL_TEXTURE_2D 0 glBindTexture
+        [ image>> has-alpha? [ GL_BLEND glDisable ] unless ]
+        [ (draw-textured-rect) GL_TEXTURE_2D 0 glBindTexture ]
+        [ image>> has-alpha? [ GL_BLEND glEnable ] unless ]
+        tri
     ] with-texturing ;
 
-: texture-coords ( dim -- coords )
-    [ dup next-power-of-2 /f ] map
-    { { 0 0 } { 1 0 } { 1 1 } { 0 1 } } [ v* ] with map
-    float-array{ } join ;
+: texture-coords ( texture -- coords )
+    [ [ dim>> ] [ image>> dim>> adjust-texture-dim ] bi v/ ]
+    [
+        image>> upside-down?>>
+        { { 0 1 } { 1 1 } { 1 0 } { 0 0 } }
+        { { 0 0 } { 1 0 } { 1 1 } { 0 1 } } ?
+    ] bi
+    [ v* ] with map float-array{ } join ;
 
 : make-texture-display-list ( texture -- dlist )
     GL_COMPILE [ [ dim>> ] keep draw-textured-rect ] make-dlist ;
 
 : <single-texture> ( image loc -- texture )
-   single-texture new swap >>loc
-    swap
-    [ dim>> >>dim ] keep
-    [ dim>> product 0 = ] keep '[
-        _
-        [ dim>> texture-coords >>texture-coords ]
-        [ power-of-2-image make-texture >>texture ] bi
+    single-texture new swap >>loc swap [ >>image ] [ dim>> >>dim ] bi
+    dup image>> dim>> product 0 = [
+        dup texture-coords >>texture-coords
+        dup image>> make-texture >>texture
         dup make-texture-display-list >>display-list
     ] unless ;
 
@@ -119,15 +127,13 @@ M: single-texture dispose*
     [ texture>> [ delete-texture ] when* ]
     [ display-list>> [ delete-dlist ] when* ] bi ;
 
-M: single-texture draw-texture display-list>> [ glCallList ] when* ;
-
 M: single-texture draw-scaled-texture
     dup texture>> [ draw-textured-rect ] [ 2drop ] if ;
 
 TUPLE: multi-texture grid display-list loc disposed ;
 
 : image-locs ( image-grid -- loc-grid )
-    [ first [ dim>> first ] map ] [ 0 <column> [ dim>> second ] map ] bi
+    [ first [ dim>> first ] map ] [ [ first dim>> second ] map ] bi
     [ 0 [ + ] accumulate nip ] bi@
     cross-zip flip ;
 
@@ -138,14 +144,15 @@ TUPLE: multi-texture grid display-list loc disposed ;
 : draw-textured-grid ( grid -- )
     [ [ [ dim>> ] keep (draw-textured-rect) ] each ] each ;
 
+: grid-has-alpha? ( grid -- ? )
+    first first image>> has-alpha? ;
+
 : make-textured-grid-display-list ( grid -- dlist )
     GL_COMPILE [
         [
-            [
-                [
-                    [ dim>> ] keep (draw-textured-rect)
-                ] each
-            ] each
+            [ grid-has-alpha? [ GL_BLEND glDisable ] unless ]
+            [ [ [ [ dim>> ] keep (draw-textured-rect) ] each ] each ]
+            [ grid-has-alpha? [ GL_BLEND glEnable ] unless ] tri
             GL_TEXTURE_2D 0 glBindTexture
         ] with-texturing
     ] make-dlist ;
@@ -159,15 +166,13 @@ TUPLE: multi-texture grid display-list loc disposed ;
         f multi-texture boa
     ] with-destructors ;
 
-M: multi-texture draw-texture display-list>> [ glCallList ] when* ;
-
 M: multi-texture dispose* grid>> [ [ dispose ] each ] each ;
 
-CONSTANT: max-texture-size { 256 256 }
+CONSTANT: max-texture-size { 512 512 }
 
 PRIVATE>
 
 : <texture> ( image loc -- texture )
     over dim>> max-texture-size [ <= ] 2all?
     [ <single-texture> ]
-    [ [ max-texture-size tesselate ] dip <multi-texture> ] if ;
\ No newline at end of file
+    [ [ max-texture-size tesselate ] dip <multi-texture> ] if ;
index 27cba6d6e729b22a7e45bd01a31e25b5c2642edc..3b9739fb0f143dc6169b06dcfb972737d1de99b3 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types arrays assocs byte-arrays io
 io.binary io.streams.string kernel math math.parser namespaces
-make parser prettyprint quotations sequences strings vectors
+make parser quotations sequences strings vectors
 words macros math.functions math.bitwise fry generalizations
 combinators.smart io.streams.byte-array io.encodings.binary
 math.vectors combinators multiline endian ;
index defcdec6f84f96b7db808a290b277479df3f4227..25aee74ca49cf76f071aead5f7da9d1248f7a078 100644 (file)
@@ -44,7 +44,7 @@ FUNCTION: PangoLayoutLine*
 pango_layout_get_line_readonly ( PangoLayout* layout, int line ) ;
                                                          
 FUNCTION: void
-pango_layout_line_index_to_x ( PangoLayoutLine* line, int index_, gboolean trailing, int* x_pos ) ;
+pango_layout_line_index_to_x ( PangoLayoutLine* line, int index_, uint trailing, int* x_pos ) ;
 
 FUNCTION: gboolean
 pango_layout_line_x_to_index ( PangoLayoutLine* line, int x_pos, int* index_, int* trailing ) ;
@@ -122,7 +122,7 @@ MEMO: missing-font-metrics ( font -- metrics )
 : line-offset>x ( layout n -- x )
     #! n is an index into the UTF8 encoding of the text
     [ drop first-line ] [ swap string>> >utf8-index ] 2bi
-    f 0 <int> [ pango_layout_line_index_to_x ] keep
+    0 0 <int> [ pango_layout_line_index_to_x ] keep
     *int pango>float ;
 
 : x>line-offset ( layout x -- n )
@@ -205,4 +205,4 @@ SYMBOL: cached-layouts
 : cached-line ( font string -- line )
     cached-layout layout>> first-line ;
 
-[ <cache-assoc> cached-layouts set-global ] "pango.layouts" add-init-hook
\ No newline at end of file
+[ <cache-assoc> cached-layouts set-global ] "pango.layouts" add-init-hook
index 5af5dba74811bd315ffe3b3b2e9775ea15fca681..1ccdafb2bbe27ecce00b298124ca756bc956f389 100644 (file)
@@ -1,2 +1,3 @@
+extensions
 text
 parsing
index bcd91a4d942a5970be9c6c61f04e5ca71ae51638..8004c1141fb978a2b136b69c794c490789076d84 100644 (file)
@@ -41,18 +41,18 @@ M: effect pprint* effect>string "(" ")" surround text ;
 : pprint-prefix ( word quot -- )
     <block swap pprint-word call block> ; inline
 
+M: parsing-word pprint*
+    \ POSTPONE: [ pprint-word ] pprint-prefix ;
+
 M: word pprint*
-    dup parsing-word? [
-        \ POSTPONE: [ pprint-word ] pprint-prefix
-    ] [
-        {
-            [ "break-before" word-prop line-break ]
-            [ pprint-word ]
-            [ ?start-group ]
-            [ ?end-group ]
-            [ "break-after" word-prop line-break ]
-        } cleave
-    ] if ;
+    [ pprint-word ] [ ?start-group ] [ ?end-group ] tri ;
+
+M: method-body pprint*
+    <block
+    \ M\ pprint-word
+    [ "method-class" word-prop pprint-word ]
+    [ "method-generic" word-prop pprint-word ] bi
+    block> ;
 
 M: real pprint* number>string text ;
 
@@ -206,8 +206,8 @@ M: curry pprint* pprint-object ;
 M: compose pprint* pprint-object ;
 
 M: wrapper pprint*
-    dup wrapped>> word? [
-        <block \ \ pprint-word wrapped>> pprint-word block>
-    ] [
-        pprint-object
-    ] if ;
+    {
+        { [ dup wrapped>> method-body? ] [ wrapped>> pprint* ] }
+        { [ dup wrapped>> word? ] [ <block \ \ pprint-word wrapped>> pprint-word block> ] }
+        [ pprint-object ]
+    } cond ;
index 7e37aa0da57fe910de07c6c7c6a73543191a731f..799d500c188256ac8a6c2de5d6e7f293b7658bba 100644 (file)
@@ -180,28 +180,6 @@ DEFER: parse-error-file
     "string-layout-test" string-layout check-see
 ] unit-test
 
-! Define dummy words for the below...
-: <NSRect> ( a b c d -- e ) ;
-: <PixelFormat> ( -- fmt ) ;
-: send ( obj -- ) ;
-
-\ send soft "break-after" set-word-prop
-
-: final-soft-break-test ( -- str )
-    {
-        "USING: kernel sequences ;"
-        "IN: prettyprint.tests"
-        ": final-soft-break-layout ( class dim -- view )"
-        "    [ \"alloc\" send 0 0 ] dip first2 <NSRect>"
-        "    <PixelFormat> \"initWithFrame:pixelFormat:\" send"
-        "    dup 1 \"setPostsBoundsChangedNotifications:\" send"
-        "    dup 1 \"setPostsFrameChangedNotifications:\" send ;"
-    } ;
-
-[ t ] [
-    "final-soft-break-layout" final-soft-break-test check-see
-] unit-test
-
 : narrow-test ( -- str )
     {
         "USING: arrays combinators continuations kernel sequences ;"
@@ -300,11 +278,7 @@ GENERIC: generic-see-test-with-f ( obj -- obj )
 M: f generic-see-test-with-f ;
 
 [ "USING: prettyprint.tests ;\nM: f generic-see-test-with-f ;\n" ] [
-    [ { POSTPONE: f generic-see-test-with-f } see ] with-string-writer
-] unit-test
-
-[ "USING: prettyprint.tests ;\nM: f generic-see-test-with-f ;\n" ] [
-    [ \ f \ generic-see-test-with-f method see ] with-string-writer
+    [ M\ f generic-see-test-with-f see ] with-string-writer
 ] unit-test
 
 PREDICATE: predicate-see-test < integer even? ;
@@ -331,5 +305,5 @@ GENERIC: ended-up-ballin' ( a -- b )
 M: started-out-hustlin' ended-up-ballin' ; inline
 
 [ "USING: prettyprint.tests ;\nM: started-out-hustlin' ended-up-ballin' ; inline\n" ] [
-    [ { started-out-hustlin' ended-up-ballin' } see ] with-string-writer
+    [ M\ started-out-hustlin' ended-up-ballin' see ] with-string-writer
 ] unit-test
index be657227e521a2c522a0adc20ff34bb4e6d6fdc7..2916ef7c32be08352ba6ed3836443e663e37b8a3 100644 (file)
@@ -21,12 +21,12 @@ CONSTANT: epsilon T{ tagged-epsilon { tag t } }
 TUPLE: concatenation first second ;
 
 : <concatenation> ( seq -- concatenation )
-    [ epsilon ] [ unclip [ concatenation boa ] reduce ] if-empty ;
+    [ epsilon ] [ [ ] [ concatenation boa ] map-reduce ] if-empty ;
 
 TUPLE: alternation first second ;
 
 : <alternation> ( seq -- alternation )
-    unclip [ alternation boa ] reduce ;
+    [ ] [ alternation boa ] map-reduce ;
 
 TUPLE: star term ;
 C: <star> star
index d137ee3e4f1c6087488be5fd67c19afc4912e91e..2de4e8b0e02322d7a3391c86f607944d18125ace 100644 (file)
@@ -51,10 +51,13 @@ IN: regexp.dfa
     [ condition-states ] 2dip
     '[ _ _ add-todo-state ] each ;
 
+: ensure-state ( key table -- )
+    2dup key? [ 2drop ] [ [ H{ } clone ] 2dip set-at ] if ; inline
+
 :: new-transitions ( nfa dfa new-states visited-states -- nfa dfa )
     new-states [ nfa dfa ] [
         pop :> state
-        state dfa transitions>> maybe-initialize-key
+        state dfa transitions>> ensure-state
         state nfa find-transitions
         [| trans |
             state trans nfa find-closure :> new-state
index 9fcadc40084f78d7e3924d2b5264afcee144cab4..70281aa798d38708f2d234265634cbe65d62c6fc 100644 (file)
@@ -102,8 +102,10 @@ MEMO: simple-category-table ( -- table )
         { CHAR: s dotall }
     } ;
 
+ERROR: nonexistent-option name ;
+
 : ch>option ( ch -- singleton )
-    options-assoc at ;
+    dup options-assoc at [ ] [ nonexistent-option ] ?if ;
 
 : option>ch ( option -- string )
     options-assoc value-at ;
index 3c33ae88466da489ce2a91df898d6e33c87a0a15..f452e3d24a4e46c25523a904332647d725c9ea74 100644 (file)
@@ -11,12 +11,7 @@ TUPLE: transition-table transitions start-state final-states ;
         H{ } clone >>transitions
         H{ } clone >>final-states ;
 
-: maybe-initialize-key ( key hashtable -- )
-    ! Why do we have to do this?
-    2dup key? [ 2drop ] [ [ H{ } clone ] 2dip set-at ] if ;
-
 :: (set-transition) ( from to obj hash -- )
-    to condition? [ to hash maybe-initialize-key ] unless
     from hash at
     [ [ to obj ] dip set-at ]
     [ to obj associate from hash set-at ] if* ;
@@ -25,7 +20,6 @@ TUPLE: transition-table transitions start-state final-states ;
     transitions>> (set-transition) ;
 
 :: (add-transition) ( from to obj hash -- )
-    to hash maybe-initialize-key
     from hash at
     [ [ to obj ] dip push-at ]
     [ to 1vector obj associate from hash set-at ] if* ;
index 6d51b42a86c11214ae7f29a92e36cddcf7fefbd2..b2e99843c7ca230e641f456a2e745699382d01a7 100644 (file)
@@ -13,7 +13,12 @@ HELP: synopsis*
 
 HELP: see
 { $values { "defspec" "a definition specifier" } }
-{ $contract "Prettyprints a definition." } ;
+{ $contract "Prettyprints a definition." }
+{ $examples
+  "A word:" { $code "\\ append see" }
+  "A method:" { $code "USE: arrays" "M\\ array length see" }
+  "A help article:" { $code "USE: help.topics" "\"help\" >link see" }
+} ;
 
 HELP: see-methods
 { $values { "word" "a " { $link generic } " or a " { $link class } } }
diff --git a/basis/see/see-tests.factor b/basis/see/see-tests.factor
new file mode 100644 (file)
index 0000000..3f11ec9
--- /dev/null
@@ -0,0 +1,11 @@
+IN: see.tests
+USING: see tools.test io.streams.string math ;
+
+CONSTANT: test-const 10
+[ "IN: see.tests\nCONSTANT: test-const 10 inline\n" ]
+[ [ \ test-const see ] with-string-writer ] unit-test
+
+ALIAS: test-alias +
+
+[ "USING: math ;\nIN: see.tests\nALIAS: test-alias + inline\n" ]
+[ [ \ test-alias see ] with-string-writer ] unit-test
index 32f49499dbf5dca6c65515160bdfe4f6af00a544..2494c72fa4134b6e12cc8f884e69b19f2ab7dd38 100644 (file)
@@ -7,7 +7,7 @@ definitions effects generic generic.standard io io.pathnames
 io.streams.string io.styles kernel make namespaces prettyprint
 prettyprint.backend prettyprint.config prettyprint.custom
 prettyprint.sections sequences sets sorting strings summary
-words words.symbol ;
+words words.symbol words.constant words.alias ;
 IN: see
 
 GENERIC: synopsis* ( defspec -- )
@@ -29,8 +29,16 @@ GENERIC: see* ( defspec -- )
 : comment. ( text -- )
     H{ { font-style italic } } styled-text ;
 
+GENERIC: print-stack-effect? ( word -- ? )
+
+M: parsing-word print-stack-effect? drop f ;
+M: symbol print-stack-effect? drop f ;
+M: constant print-stack-effect? drop f ;
+M: alias print-stack-effect? drop f ;
+M: word print-stack-effect? drop t ;
+
 : stack-effect. ( word -- )
-    [ [ parsing-word? ] [ symbol? ] bi or not ] [ stack-effect ] bi and
+    [ print-stack-effect? ] [ stack-effect ] bi and
     [ effect>string comment. ] when* ;
 
 <PRIVATE
@@ -68,9 +76,6 @@ M: hook-generic synopsis*
         [ stack-effect. ]
     } cleave ;
 
-M: method-spec synopsis*
-    first2 method synopsis* ;
-
 M: method-body synopsis*
     [ definer. ]
     [ "method-class" word-prop pprint-word ]
@@ -114,9 +119,6 @@ M: object see*
         block>
     ] with-use ;
 
-M: method-spec see*
-    first2 method see* ;
-
 GENERIC: see-class* ( word -- )
 
 M: union-class see-class*
diff --git a/basis/sorting/functor/authors.txt b/basis/sorting/functor/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/basis/sorting/functor/functor.factor b/basis/sorting/functor/functor.factor
new file mode 100644 (file)
index 0000000..7f46af4
--- /dev/null
@@ -0,0 +1,16 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: functors kernel math.order sequences sorting ;
+IN: sorting.functor
+
+FUNCTOR: define-sorting ( NAME QUOT -- )
+
+NAME<=> DEFINES ${NAME}<=>
+NAME>=< DEFINES ${NAME}>=<
+
+WHERE
+
+: NAME<=> ( obj1 obj2 -- <=> ) QUOT bi@ <=> ;
+: NAME>=< ( obj1 obj2 -- >=< ) NAME<=> invert-comparison ;
+
+;FUNCTOR
index 5952b3e3f9fb21d0c1edd205416d99c8aea83904..4bb62b13132eeadd1129d280cfca672c6986754c 100644 (file)
@@ -25,46 +25,11 @@ HELP: human>=<
 }
 { $description "Compares two objects using the " { $link human<=> } " word and inverts the result." } ;
 
-HELP: human-compare
-{ $values
-     { "obj1" object } { "obj2" object } { "quot" quotation }
-     { "<=>" "an ordering specifier" }
-}
-{ $description "Compares the results of applying the quotation to both objects via <=>." } ;
-
-HELP: human-sort
-{ $values
-     { "seq" sequence }
-     { "seq'" sequence }
-}
-{ $description "Sorts a sequence of objects by comparing the magnitude of any integers in the input string using the <=> word." } ;
-
-HELP: human-sort-keys
-{ $values
-     { "seq" "an alist" }
-     { "sortedseq" "a new sorted sequence" }
-}
-{ $description "Sorts the elements comparing first elements of pairs using the " { $link human<=> } " word." } ;
-
-HELP: human-sort-values
-{ $values
-     { "seq" "an alist" }
-     { "sortedseq" "a new sorted sequence" }
-}
-{ $description "Sorts the elements comparing second elements of pairs using the " { $link human<=> } " word." } ;
-
-{ <=> >=< human-compare human-sort human-sort-keys human-sort-values } related-words
-
 ARTICLE: "sorting.human" "Human-friendly sorting"
 "The " { $vocab-link "sorting.human" } " vocabulary sorts by numbers as a human would -- by comparing their magnitudes -- rather than in a lexicographic way. For example, sorting a1, a10, a03, a2 with human sort returns a1, a2, a03, a10, while sorting with natural sort returns a03, a1, a10, a2." $nl
 "Comparing two objects:"
 { $subsection human<=> }
 { $subsection human>=< }
-{ $subsection human-compare }
-"Sort a sequence:"
-{ $subsection human-sort }
-{ $subsection human-sort-keys }
-{ $subsection human-sort-values }
 "Splitting a string into substrings and integers:"
 { $subsection find-numbers } ;
 
index 0e20b54c2f7460f0527454de279bc40f77896aec..20a607188cafc19d6ec06b21e34511706a99286d 100644 (file)
@@ -1,6 +1,4 @@
-USING: sorting.human tools.test ;
+USING: sorting.human tools.test sorting.slots ;
 IN: sorting.human.tests
 
-\ human-sort must-infer
-
-[ { "x1y" "x2" "x10y" } ] [ { "x1y" "x10y" "x2" } human-sort ] unit-test
+[ { "x1y" "x2" "x10y" } ] [ { "x1y" "x10y" "x2" } { human<=> } sort-by ] unit-test
index c07ed8758ba0e1d9cf947d502a34ff3bc8ad3fc0..b3dae45a9b87d26fd94d46ed04e9439be96a1ebd 100644 (file)
@@ -1,22 +1,9 @@
 ! Copyright (C) 2008 Doug Coleman, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: peg.ebnf math.parser kernel assocs sorting fry
-math.order sequences ascii splitting.monotonic ;
+USING: math.parser peg.ebnf sorting.functor ;
 IN: sorting.human
 
 : find-numbers ( string -- seq )
     [EBNF Result = ([0-9]+ => [[ string>number ]] | (!([0-9]) .)+)* EBNF] ;
 
-: human<=> ( obj1 obj2 -- <=> ) [ find-numbers ] bi@ <=> ;
-
-: human>=< ( obj1 obj2 -- >=< ) human<=> invert-comparison ; inline
-
-: human-compare ( obj1 obj2 quot -- <=> ) bi@ human<=> ; inline
-
-: human-sort ( seq -- seq' ) [ human<=> ] sort ;
-
-: human-sort-keys ( seq -- sortedseq )
-    [ [ first ] human-compare ] sort ;
-
-: human-sort-values ( seq -- sortedseq )
-    [ [ second ] human-compare ] sort ;
+<< "human" [ find-numbers ] define-sorting >>
index a3bdbf9ac1cbc880ac883eed136c091507484558..cc89d497e78202b7349e121e214dd3ee4e255042 100644 (file)
@@ -14,7 +14,7 @@ HELP: compare-slots
 HELP: sort-by-slots
 { $values
      { "seq" sequence } { "sort-specs" "a sequence of accessors ending with a comparator" }
-     { "seq'" sequence }
+     { "sortedseq" sequence }
 }
 { $description "Sorts a sequence of tuples by the sort-specs in " { $snippet "sort-spec" } ". A sort-spec is a sequence of slot accessors ending in a comparator." }
 { $examples
@@ -39,11 +39,20 @@ HELP: split-by-slots
 }
 { $description "Splits a sequence of tuples into a sequence of slices of tuples that have the same values in all slots in the accessor sequence. This word is only useful for splitting a sorted sequence, but is more efficient than partitioning in such a case." } ;
 
+HELP: sort-by
+{ $values
+    { "seq" sequence } { "sort-seq" "a sequence of comparators" }
+    { "sortedseq" sequence }
+}
+{ $description "Sorts a sequence by comparing elements by comparators, using subsequent comparators when there is a tie." } ;
+
 ARTICLE: "sorting.slots" "Sorting by slots"
 "The " { $vocab-link "sorting.slots" } " vocabulary can sort tuples by slot in ascending or descending order, using subsequent slots as tie-breakers." $nl
 "Comparing two objects by a sequence of slots:"
 { $subsection compare-slots }
-"Sorting a sequence by a sequence of slots:"
-{ $subsection sort-by-slots } ;
+"Sorting a sequence of tuples by a slot/comparator pairs:"
+{ $subsection sort-by-slots }
+"Sorting a sequence by a sequence of comparators:"
+{ $subsection sort-by } ;
 
 ABOUT: "sorting.slots"
index 46824c6fdb17d6738a364ac0070a7a60d810c5cd..83900461c3dfbe0255c209edc71399b981ae3e30 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors math.order sorting.slots tools.test
-sorting.human arrays sequences kernel assocs multiline ;
+sorting.human arrays sequences kernel assocs multiline
+sorting.functor ;
 IN: sorting.literals.tests
 
 TUPLE: sort-test a b c tuple2 ;
@@ -76,6 +77,9 @@ TUPLE: tuple2 d ;
 [ { } ]
 [ { } { { a>> <=> } { b>> >=< } { c>> <=> } } sort-by-slots ] unit-test
 
+[ { } ]
+[ { } { } sort-by-slots ] unit-test
+
 [
     {
         T{ sort-test { a 6 } { tuple2 T{ tuple2 { d 1 } } } }
@@ -143,3 +147,15 @@ TUPLE: tuple2 d ;
         T{ sort-test { a 5 } { tuple2 T{ tuple2 { d 4 } } } }
     } { { tuple2>> d>> } { a>> } } split-by-slots [ >array ] map
 ] unit-test
+
+
+[ { "a" "b" "c" } ] [ { "b" "c" "a" } { <=> <=> } sort-by ] unit-test
+[ { "b" "c" "a" } ] [ { "b" "c" "a" } { } sort-by ] unit-test
+
+<< "length-test" [ length ] define-sorting >>
+
+[ { { 1 } { 1 2 3 } { 1 3 2 } { 3 2 1 } } ]
+[
+    { { 3 2 1 } { 1 2 3 } { 1 3 2 } { 1 } }
+    { length-test<=> <=> } sort-by
+] unit-test
index 56b6a115f07350f505dfb588fc8176512a6ac68c..efec960c2749855d67a2a4ef86bc5b3e4c7b6d8c 100644 (file)
@@ -7,13 +7,16 @@ IN: sorting.slots
 
 <PRIVATE
 
+: short-circuit-comparator ( obj1 obj2 word --  comparator/? )
+    execute dup +eq+ eq? [ drop f ] when ; inline
+
 : slot-comparator ( seq -- quot )
     [
         but-last-slice
         [ '[ [ _ execute ] bi@ ] ] map concat
     ] [
         peek
-        '[ @ _ execute dup +eq+ eq? [ drop f ] when ]
+        '[ @ _ short-circuit-comparator ]
     ] bi ;
 
 PRIVATE>
@@ -22,8 +25,20 @@ MACRO: compare-slots ( sort-specs -- <=> )
     #! sort-spec: { accessors comparator }
     [ slot-comparator ] map '[ _ 2|| +eq+ or ] ;
 
-: sort-by-slots ( seq sort-specs -- seq' )
-    '[ _ compare-slots ] sort ;
+MACRO: sort-by-slots ( sort-specs -- quot )
+    '[ [ _ compare-slots ] sort ] ;
+
+MACRO: compare-seq ( seq -- quot )
+    [ '[ _ short-circuit-comparator ] ] map '[ _ 2|| +eq+ or ] ;
+
+MACRO: sort-by ( sort-seq -- quot )
+    '[ [ _ compare-seq ] sort ] ;
+
+MACRO: sort-keys-by ( sort-seq -- quot )
+    '[ [ first ] bi@ _ compare-seq ] sort ;
+
+MACRO: sort-values-by ( sort-seq -- quot )
+    '[ [ second ] bi@ _ compare-seq ] sort ;
 
 MACRO: split-by-slots ( accessor-seqs -- quot )
     [ [ '[ [ _ execute ] bi@ ] ] map concat [ = ] compose ] map
diff --git a/basis/sorting/title/authors.txt b/basis/sorting/title/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/basis/sorting/title/title-tests.factor b/basis/sorting/title/title-tests.factor
new file mode 100644 (file)
index 0000000..65a58e4
--- /dev/null
@@ -0,0 +1,40 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test sorting.title sorting.slots ;
+IN: sorting.title.tests
+
+: sort-me ( -- seq )
+    {
+        "The Beatles"
+        "A river runs through it"
+        "Another"
+        "la vida loca"
+        "Basketball"
+        "racquetball"
+        "Los Fujis"
+        "los Fujis"
+        "La cucaracha"
+        "a day to remember"
+        "of mice and men"
+        "on belay"
+        "for the horde"
+    } ;
+[
+    {
+        "Another"
+        "Basketball"
+        "The Beatles"
+        "La cucaracha"
+        "a day to remember"
+        "for the horde"
+        "Los Fujis"
+        "los Fujis"
+        "of mice and men"
+        "on belay"
+        "racquetball"
+        "A river runs through it"
+        "la vida loca"
+    }
+] [
+    sort-me { title<=> } sort-by
+] unit-test
diff --git a/basis/sorting/title/title.factor b/basis/sorting/title/title.factor
new file mode 100644 (file)
index 0000000..dbdbf8a
--- /dev/null
@@ -0,0 +1,7 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: sorting.functor regexp kernel accessors sequences
+unicode.case ;
+IN: sorting.title
+
+<< "title" [ >lower dup R/ ^(the|a|an|el|la|los|las|il) / first-match [ to>> tail-slice ] when* ] define-sorting >>
index a38bb42c7efa5cad2089d20f899e703c492e7f55..c55e69a8a275fcda4af42d749345d63880cfad3d 100644 (file)
@@ -605,6 +605,8 @@ M: object infer-call*
 
 \ fflush { alien } { } define-primitive
 
+\ fseek { alien integer integer } { } define-primitive
+
 \ fclose { alien } { } define-primitive
 
 \ <wrapper> { object } { wrapper } define-primitive
index c2b348f5f1228ede105a61b80ee5d62b24e05982..dfa46be7e2d5b19a92afb81f9a15446bb4ac49a3 100755 (executable)
@@ -1,13 +1,13 @@
 ! Copyright (C) 2007, 2009 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: fry accessors arrays kernel kernel.private combinators.private
-words sequences generic math math.order namespaces make quotations assocs
-combinators combinators.short-circuit classes.tuple
+words sequences generic math math.order namespaces make quotations
+assocs combinators combinators.short-circuit classes.tuple
 classes.tuple.private effects summary hashtables classes generic sets
 definitions generic.standard slots.private continuations locals
-generalizations stack-checker.backend stack-checker.state
-stack-checker.visitor stack-checker.errors stack-checker.values
-stack-checker.recursive-state ;
+sequences.private generalizations stack-checker.backend
+stack-checker.state stack-checker.visitor stack-checker.errors
+stack-checker.values stack-checker.recursive-state ;
 IN: stack-checker.transforms
 
 : give-up-transform ( word -- )
@@ -106,40 +106,68 @@ IN: stack-checker.transforms
     ] [ drop f ] if
 ] 1 define-transform
 
-! Membership testing
-CONSTANT: bit-member-max 256
+! Fast at for integer maps
+CONSTANT: lookup-table-at-max 256
 
-: bit-member? ( seq -- ? )
+: lookup-table-at? ( assoc -- ? )
     #! Can we use a fast byte array test here?
     {
-        [ length 4 > ]
+        [ assoc-size 4 > ]
+        [ values [ ] all? ]
+        [ keys [ integer? ] all? ]
+        [ keys [ 0 lookup-table-at-max between? ] all? ]
+    } 1&& ;
+
+: lookup-table-seq ( assoc -- table )
+    [ keys supremum 1+ ] keep '[ _ at ] { } map-as ;
+
+: lookup-table-quot ( seq -- newquot )
+    lookup-table-seq
+    '[
+        _ over integer? [
+            2dup bounds-check? [
+                nth-unsafe dup >boolean
+            ] [ 2drop f f ] if
+        ] [ 2drop f f ] if
+    ] ;
+
+: fast-lookup-table-at? ( assoc -- ? )
+    values {
         [ [ integer? ] all? ]
-        [ [ 0 bit-member-max between? ] any? ]
+        [ [ 0 254 between? ] all? ]
     } 1&& ;
 
-: bit-member-seq ( seq -- flags )
-    [ supremum 1+ ] keep '[ _ member? 1 0 ? ] B{ } map-as ;
+: fast-lookup-table-seq ( assoc -- table )
+    lookup-table-seq [ 255 or ] B{ } map-as ;
 
-: bit-member-quot ( seq -- newquot )
-    bit-member-seq
+: fast-lookup-table-quot ( seq -- newquot )
+    fast-lookup-table-seq
     '[
-        _ {
-            { [ over fixnum? ] [ ?nth 1 eq? ] }
-            { [ over bignum? ] [ ?nth 1 eq? ] }
-            [ 2drop f ]
-        } cond
+        _ over integer? [
+            2dup bounds-check? [
+                nth-unsafe dup 255 eq? [ drop f f ] [ t ] if
+            ] [ 2drop f f ] if
+        ] [ 2drop f f ] if
     ] ;
 
-: member-quot ( seq -- newquot )
-    dup bit-member? [
-        bit-member-quot
-    ] [
-        dup length 4 <= [
-            [ drop f ] swap
-            [ literalize [ t ] ] { } map>assoc linear-case-quot
+: at-quot ( assoc -- quot )
+    dup lookup-table-at? [
+        dup fast-lookup-table-at? [
+            fast-lookup-table-quot
         ] [
-            unique [ key? ] curry
+            lookup-table-quot
         ] if
+    ] [ drop f ] if ;
+
+\ at* [ at-quot ] 1 define-transform
+
+! Membership testing
+: member-quot ( seq -- newquot )
+    dup length 4 <= [
+        [ drop f ] swap
+        [ literalize [ t ] ] { } map>assoc linear-case-quot
+    ] [
+        unique [ key? ] curry
     ] if ;
 
 \ member? [
@@ -170,4 +198,4 @@ CONSTANT: bit-member-max 256
 
 \ shuffle [
     shuffle-mapping nths-quot
-] 1 define-transform
\ No newline at end of file
+] 1 define-transform
index f47852aca754115dcb54d1f9ec944c27f748b8e4..9fa9d1e2aa1b317c401dbf762fe285eff76e91e2 100644 (file)
@@ -43,6 +43,6 @@ GENERIC: blah-generic ( a -- b )
 
 M: string blah-generic ;
 
-{ string blah-generic } watch
+[ ] [ M\ string blah-generic watch ] unit-test
 
 [ "hi" ] [ "hi" blah-generic ] unit-test
index 8c3d95f2b877e017892ebf2074fbc5c74cc2f91a..64e6508ab62e34f45022872dbd1e638514b65667 100644 (file)
@@ -20,9 +20,6 @@ M: word reset
         f "unannotated-def" set-word-prop
     ] [ drop ] if ;
 
-M: method-spec reset
-    first2 method reset ;
-
 ERROR: cannot-annotate-twice word ;
 
 <PRIVATE
@@ -32,9 +29,6 @@ ERROR: cannot-annotate-twice word ;
         cannot-annotate-twice
     ] when ;
 
-: method-spec>word ( obj -- word )
-    dup method-spec? [ first2 method ] when ;
-
 : save-unannotated-def ( word -- )
     dup def>> "unannotated-def" set-word-prop ;
 
@@ -44,7 +38,7 @@ ERROR: cannot-annotate-twice word ;
 PRIVATE>
 
 : annotate ( word quot -- )
-    [ method-spec>word check-annotate-twice ] dip
+    [ check-annotate-twice ] dip
     [ over save-unannotated-def (annotate) ] with-compilation-unit ;
 
 <PRIVATE
@@ -103,9 +97,6 @@ M: generic annotate-methods
 M: word annotate-methods
     annotate ;
 
-M: method-spec annotate-methods
-    annotate ;
-
 : breakpoint ( word -- )
     [ add-breakpoint ] annotate-methods ;
 
index 28a32790dcae934258d70b92e52b08ce9debfe7c..6ca54ca36b6ca1b7b3c8a4d42ed154ace4b751c5 100755 (executable)
@@ -8,7 +8,7 @@ debugger io.streams.c io.files io.files.temp io.pathnames
 io.directories io.directories.hierarchy io.backend quotations
 io.launcher words.private tools.deploy.config
 tools.deploy.config.editor bootstrap.image io.encodings.utf8
-destructors accessors ;
+destructors accessors hashtables ;
 IN: tools.deploy.backend
 
 : copy-vm ( executable bundle-name -- vm )
@@ -88,7 +88,7 @@ DEFER: ?make-staging-image
     [ drop ] [ make-staging-image ] if ;
 
 : make-deploy-config ( vocab -- file )
-    [ deploy-config unparse-use ]
+    [ deploy-config vocab-roots get vocab-roots associate assoc-union unparse-use ]
     [ "deploy-config-" prepend temp-file ] bi
     [ utf8 set-file-contents ] keep ;
 
index 11e2b8957b8ce96e2ae40b806a31c34e24a404ab..f753e38fb2bf8c3a1e3355d37670d684d085278c 100755 (executable)
@@ -42,11 +42,12 @@ IN: tools.deploy.macosx
 
 : create-app-dir ( vocab bundle-name -- vm )
     [
-        nip
-        [ copy-dll ]
-        [ copy-nib ]
-        [ "Contents/Resources" append-path make-directories ]
-        tri
+        nip {
+            [ copy-dll ]
+            [ copy-nib ]
+            [ "Contents/Resources" append-path make-directories ]
+            [ "Contents/Resources" copy-theme ]
+        } cleave
     ]
     [ create-app-plist ]
     [ "Contents/MacOS/" append-path copy-vm ] 2tri
index 8ee03930912ce96d0cea98c459ce477e4870dd09..7c9a38796b5de053f56b9a0a3ba4c4f8c1bd64ff 100755 (executable)
@@ -157,7 +157,8 @@ IN: tools.deploy.shaker
                 "specializer"
                 "step-into"
                 "step-into?"
-                "superclass"
+                ! UI needs this
+                ! "superclass"
                 "transform-n"
                 "transform-quot"
                 "tuple-dispatch-generic"
@@ -169,8 +170,6 @@ IN: tools.deploy.shaker
         
         strip-prettyprint? [
             {
-                "break-before"
-                "break-after"
                 "delimiter"
                 "flushable"
                 "foldable"
@@ -276,7 +275,6 @@ IN: tools.deploy.shaker
                 lexer-factory
                 print-use-hook
                 root-cache
-                vocab-roots
                 vocabs:dictionary
                 vocabs:load-vocab-hook
                 word
index bfa096ad2fb674ace677073a420d75b4f53a3ae0..f21f4ac363a83c3efc9a25f4a332e872ee8b2ab7 100755 (executable)
@@ -9,11 +9,6 @@ IN: tools.deploy.windows
 : copy-dll ( bundle-name -- )
     "resource:factor.dll" swap copy-file-into ;
 
-: copy-pango ( bundle-name -- )
-    "resource:build-support/dlls.txt" ascii file-lines
-    [ "resource:" prepend-path ] map
-    swap copy-files-into ;
-
 :: copy-vm ( executable bundle-name extension -- vm )
     vm "." split1-last drop extension append
     bundle-name executable ".exe" append append-path
@@ -22,9 +17,7 @@ IN: tools.deploy.windows
 : create-exe-dir ( vocab bundle-name -- vm )
     dup copy-dll
     deploy-ui? get [
-        [ copy-pango ]
-        [ "" copy-theme ]
-        [ ".exe" copy-vm ] tri
+        [ "" copy-theme ] [ ".exe" copy-vm ] bi
     ] [ ".com" copy-vm ] if ;
 
 M: winnt deploy*
index 96f5a043788c83f6113bfeddbb347c513aabf709..49cfb054a13e03b44240c9379edc0939025f64e7 100644 (file)
@@ -3,4 +3,4 @@ USING: math classes.tuple prettyprint.custom
 tools.disassembler tools.test strings ;\r
 \r
 [ ] [ \ + disassemble ] unit-test\r
-[ ] [ { string pprint* } disassemble ] unit-test\r
+[ ] [ M\ string pprint* disassemble ] unit-test\r
index 83b7dfef81b70e7db97d78bf7ae2fbf49c0cba22..744318a0a435c580d670e3c89a37f1aa1e371c43 100755 (executable)
@@ -16,8 +16,6 @@ M: pair disassemble first2 disassemble* [ tabs>spaces print ] each ;
 
 M: word disassemble word-xt 2array disassemble ;
 
-M: method-spec disassemble first2 method disassemble ;
-
 cpu x86?
 "tools.disassembler.udis"
 "tools.disassembler.gdb" ?
index 63b55729fbd0454698431af4a43c9ec362c19d32..666e05108811a08b74d720339bb6d398c099e63c 100644 (file)
@@ -16,10 +16,11 @@ IN: tools.hexdump
     16 * >hex 8 CHAR: 0 pad-head write "h: " write ;
 
 : >hex-digit ( digit -- str )
-    >hex 2 CHAR: 0 pad-head " " append ;
+    >hex 2 CHAR: 0 pad-head ;
 
 : >hex-digits ( bytes -- str )
-    [ >hex-digit ] { } map-as concat 48 CHAR: \s pad-tail ;
+    [ >hex-digit " " append ] { } map-as concat
+    48 CHAR: \s pad-tail ;
 
 : >ascii ( bytes -- str )
     [ [ printable? ] keep CHAR: . ? ] "" map-as ;
index 76fbc7286b0e4c62081162797edcb909285bfda4..9c844d366386873b725857a14bcb5734b363af58 100755 (executable)
@@ -1,6 +1,6 @@
-! Copyright (C) 2006, 2007 Slava Pestov.
+! Copyright (C) 2006, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel namespaces opengl opengl.gl ;
+USING: kernel namespaces opengl opengl.gl fry ;
 IN: ui.backend
 
 SYMBOL: ui-backend
@@ -28,7 +28,7 @@ GENERIC: flush-gl-context ( handle -- )
 HOOK: offscreen-pixels ui-backend ( world -- alien w h )
 
 : with-gl-context ( handle quot -- )
-    swap [ select-gl-context call ] keep
-    glFlush flush-gl-context gl-error ; inline
+    '[ select-gl-context @ ]
+    [ flush-gl-context gl-error ] bi ; inline
 
 HOOK: (with-ui) ui-backend ( quot -- )
\ No newline at end of file
index fc392c595d40e0dc13f940211c3a5d5d3f030b14..362305c8f70a4a32cdcf793babfaadd934bfe883 100755 (executable)
@@ -39,13 +39,16 @@ M: pasteboard set-clipboard-contents
     [ 0 0 ] dip dim>> first2 <CGRect> ;
 
 : auto-position ( window loc -- )
+    #! Note: if this is the initial window, the length of the windows
+    #! vector should be 1, since (open-window) calls auto-position
+    #! after register-window.
     dup { 0 0 } = [
         drop
-        windows get [ -> center ] [
-            peek second window-loc>>
+        windows get length 1 <= [ -> center ] [
+            windows get peek second window-loc>>
             dupd first2 <CGPoint> -> cascadeTopLeftFromPoint:
             -> setFrameTopLeftPoint:
-        ] if-empty
+        ] if
     ] [ first2 <CGPoint> -> setFrameTopLeftPoint: ] if ;
 
 M: cocoa-ui-backend set-title ( string world -- )
@@ -70,8 +73,8 @@ M:: cocoa-ui-backend (open-window) ( world -- )
     world dim>> <FactorView> :> view
     view world world>NSRect <ViewWindow> :> window
     view -> release
-    window world window-loc>> auto-position
     world view register-window
+    window world window-loc>> auto-position
     world window save-position
     window install-window-delegate
     view window <window-handle> world (>>handle)
index b59848260da9f172ab461e73c91addb96d94ef40..602c9bec73c188e2a6d0656870dcd11c8534ac4c 100644 (file)
@@ -336,7 +336,7 @@ CLASS: {
 
 ! Initialization
 { "updateFactorGadgetSize:" "void" { "id" "SEL" "id" }
-    [ 2drop dup view-dim swap window (>>dim) yield ]
+    [ 2drop [ window ] [ view-dim ] bi >>dim drop yield ]
 }
 
 { "doCommandBySelector:" "void" { "id" "SEL" "SEL" }
index 80dd313e8543e9d913ef4ae71452eaccbe80184c..e405efb540d16f21ee39849e804d2c7c2a6690d8 100755 (executable)
@@ -1,16 +1,16 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! Portions copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types alien.strings arrays assocs ui
-ui.private ui.gadgets ui.gadgets.private ui.backend
-ui.clipboards ui.gadgets.worlds ui.gestures ui.event-loop io
-kernel math math.vectors namespaces make sequences strings
-vectors words windows.kernel32 windows.gdi32 windows.user32
-windows.opengl32 windows.messages windows.types windows.nt
-windows threads libc combinators fry combinators.short-circuit
-continuations command-line shuffle opengl ui.render ascii
-math.bitwise locals accessors math.rectangles math.order ascii
-calendar io.encodings.utf16n ;
+USING: alien alien.c-types alien.strings arrays assocs ui ui.private
+ui.gadgets ui.gadgets.private ui.backend ui.clipboards
+ui.gadgets.worlds ui.gestures ui.event-loop io kernel math
+math.vectors namespaces make sequences strings vectors words
+windows.kernel32 windows.gdi32 windows.user32 windows.opengl32
+windows.messages windows.types windows.offscreen windows.nt windows
+threads libc combinators fry combinators.short-circuit continuations
+command-line shuffle opengl ui.render ascii math.bitwise locals
+accessors math.rectangles math.order ascii calendar
+io.encodings.utf16n ;
 IN: ui.backend.windows
 
 SINGLETON: windows-ui-backend
@@ -433,12 +433,7 @@ M: windows-ui-backend do-events
     style 0 ex-style AdjustWindowRectEx win32-error=0/f ;
 
 : make-RECT ( world -- RECT )
-    [ window-loc>> dup ] [ dim>> ] bi v+
-    "RECT" <c-object>
-    over first over set-RECT-right
-    swap second over set-RECT-bottom
-    over first over set-RECT-left
-    swap second over set-RECT-top ;
+    [ window-loc>> ] [ dim>> ] bi <RECT> ;
 
 : default-position-RECT ( RECT -- )
     dup get-RECT-dimensions [ 2drop ] 2dip
@@ -501,35 +496,12 @@ M: windows-ui-backend (open-window) ( world -- )
     hWnd>> show-window ;
 
 M: win-base select-gl-context ( handle -- )
-    [ hDC>> ] keep hRC>> wglMakeCurrent win32-error=0/f
+    [ hDC>> ] [ hRC>> ] bi wglMakeCurrent win32-error=0/f
     GdiFlush drop ;
 
 M: win-base flush-gl-context ( handle -- )
     hDC>> SwapBuffers win32-error=0/f ;
 
-: (bitmap-info) ( dim -- BITMAPINFO )
-    "BITMAPINFO" <c-object> [
-        BITMAPINFO-bmiHeader {
-            [ nip "BITMAPINFOHEADER" heap-size swap set-BITMAPINFOHEADER-biSize ]
-            [ [ first ] dip set-BITMAPINFOHEADER-biWidth ]
-            [ [ second ] dip set-BITMAPINFOHEADER-biHeight ]
-            [ nip 1 swap set-BITMAPINFOHEADER-biPlanes ]
-            [ nip 32 swap set-BITMAPINFOHEADER-biBitCount ]
-            [ nip BI_RGB swap set-BITMAPINFOHEADER-biCompression ]
-            [ [ first2 * 4 * ] dip set-BITMAPINFOHEADER-biSizeImage ]
-            [ nip 72 swap set-BITMAPINFOHEADER-biXPelsPerMeter ]
-            [ nip 72 swap set-BITMAPINFOHEADER-biYPelsPerMeter ]
-            [ nip 0 swap set-BITMAPINFOHEADER-biClrUsed ]
-            [ nip 0 swap set-BITMAPINFOHEADER-biClrImportant ]
-        } 2cleave
-    ] keep ;
-
-: make-offscreen-dc-and-bitmap ( dim -- hDC hBitmap bits )
-    f CreateCompatibleDC
-    dup rot (bitmap-info) DIB_RGB_COLORS f <void*>
-    [ f 0 CreateDIBSection ] keep *void*
-    [ 2dup SelectObject drop ] dip ;
-
 : setup-offscreen-gl ( dim -- hDC hRC hBitmap bits )
     make-offscreen-dc-and-bitmap [
         [ dup offscreen-pfd-dwFlags setup-pixel-format ]
@@ -548,13 +520,12 @@ M: windows-ui-backend (close-offscreen-buffer) ( handle -- )
 ! each pixel; it's left as zero
 
 : (make-opaque) ( byte-array -- byte-array' )
-    [ length 4 / ]
+    [ length 4 /i ]
     [ '[ 255 swap 4 * 3 + _ set-nth ] each ]
     [ ] tri ;
 
 : (opaque-pixels) ( world -- pixels )
-    [ handle>> bits>> ] [ dim>> first2 * 4 * ] bi
-    memory>byte-array (make-opaque) ;
+    [ handle>> bits>> ] [ dim>> ] bi bitmap>byte-array (make-opaque) ;
 
 M: windows-ui-backend offscreen-pixels ( world -- alien w h )
     [ (opaque-pixels) ] [ dim>> first2 ] bi ;
index 422efbd188c66236757173f0227c5abedaf202bb..d4b29592976e4dc4c5e99710a8c71b62e370001f 100755 (executable)
@@ -224,6 +224,10 @@ M: x-clipboard paste-clipboard
     [ XA_NET_WM_NAME XA_UTF8_STRING 8 PropModeReplace ] dip
     utf8 encode dup length XChangeProperty drop ;
 
+: set-class ( dpy window -- )
+    XA_WM_CLASS XA_UTF8_STRING 8 PropModeReplace "Factor"
+    utf8 encode dup length XChangeProperty drop ;
+
 M: x11-ui-backend set-title ( string world -- )
     handle>> window>> swap
     [ dpy get ] 2dip [ set-title-old ] [ set-title-new ] 3bi ;
@@ -242,11 +246,15 @@ M: x11-ui-backend set-fullscreen* ( ? world -- )
 
 M: x11-ui-backend (open-window) ( world -- )
     dup gadget-window
-    handle>> window>> dup set-closable map-window ;
+    handle>> window>>
+    [ set-closable ] [ dpy get swap set-class ] [ map-window ] tri ;
 
 M: x11-ui-backend raise-window* ( world -- )
     handle>> [
-        dpy get swap window>> XRaiseWindow drop
+        dpy get swap window>>
+        [ RevertToPointerRoot CurrentTime XSetInputFocus drop ]
+        [ XRaiseWindow drop ]
+        2bi
     ] when* ;
 
 M: x11-handle select-gl-context ( handle -- )
index 6042a398865827bfa205731702bd89d044fbb12d..a28a6aef84162b017cc9be515cd04a3c6bc57904 100644 (file)
@@ -26,7 +26,7 @@ HELP: <repeat-button>
 { $description "Creates a new " { $link button } " derived from a " { $link <border-button> } " which calls the quotation every 100 milliseconds as long as the mouse button is held down." } ;
 
 HELP: button-pen
-{ $class-description "A class implementing the " { $link draw-boundary } " and " { $link draw-interior } " gneeric words by delegating to an object in one of four slots which depend on the state of the button being drawn:"
+{ $class-description "A class implementing the " { $link draw-boundary } " and " { $link draw-interior } " generic words by delegating to an object in one of four slots which depend on the state of the button being drawn:"
     { $list
         { { $snippet "plain"    } " - the button is inactive" }
         { { $snippet "rollover" } " - the button is under the mouse" }
index f5b7f63d22bcb16ce17ad547755040dbc25894a9..9461b2348f5f877052431b3c95d13b12d2015edd 100755 (executable)
@@ -141,7 +141,7 @@ M: editor ungraft*
 : scroll>caret ( editor -- )
     dup graft-state>> second [
         [
-            [ caret-loc ] [ caret-dim { 1 0 } v+ ] bi <rect>
+            [ caret-loc ] [ caret-dim { 2 1 } v+ ] bi <rect>
         ] keep scroll>rect
     ] [ drop ] if ;
 
@@ -452,6 +452,7 @@ editor "caret-motion" f {
 
 editor "selection" f {
     { T{ button-down f { S+ } 1 } extend-selection }
+    { T{ button-up f { S+ } 1 } com-copy-selection }
     { T{ drag } drag-selection }
     { gain-focus focus-editor }
     { lose-focus unfocus-editor }
index adcfdfb00d195c58bc8973d280b4cbf0401b3209..bc07006d623d8c5efffb4a531b41c105b23cdd0f 100644 (file)
@@ -11,6 +11,7 @@ CONSTANT: horizontal { 1 0 }
 CONSTANT: vertical { 0 1 }
 
 TUPLE: gadget < rect
+id
 pref-dim
 parent
 children
@@ -28,7 +29,7 @@ model ;
 
 M: gadget equal? 2drop f ;
 
-M: gadget hashcode* drop gadget hashcode* ;
+M: gadget hashcode* nip [ [ \ gadget counter ] unless* ] change-id id>> ;
 
 M: gadget model-changed 2drop ;
 
index 80feb31ad2215f83d177491c59a77c2c0b80d839..b9fe10c530b83e71ce1265a1f8edb8a255d57732 100644 (file)
@@ -30,6 +30,9 @@ M: line-gadget line-height font>> font-metrics height>> ceiling ;
 : validate-line ( m gadget -- n )
     control-value [ drop f ] [ length 1- min 0 max ] if-empty ;
 
+: valid-line? ( n gadget -- ? )
+    control-value length 1- 0 swap between? ;
+
 : visible-line ( gadget quot -- n )
     '[
         [ clip get @ origin get [ second ] bi@ - ] dip
index a6bd5c4e291199f3c3460b6093935ec6dc22c881..6f6e7ee95f52da0029c088c6712b5d62c77e00d4 100644 (file)
@@ -49,13 +49,13 @@ M: pane-stream stream-element-type drop +character+ ;
 : pane-caret&mark ( pane -- caret mark )
     [ caret>> ] [ mark>> ] bi ; inline
 
-: selected-children ( pane -- seq )
+: selected-subtree ( pane -- seq )
     [ pane-caret&mark sort-pair ] keep gadget-subtree ;
 
 M: pane gadget-selection? pane-caret&mark and ;
 
 M: pane gadget-selection ( pane -- string/f )
-    selected-children gadget-text ;
+    selected-subtree gadget-text ;
 
 : init-prototype ( pane -- pane )
     <shelf> +baseline+ >>align >>prototype ; inline
@@ -72,31 +72,12 @@ M: pane gadget-selection ( pane -- string/f )
     [ >>last-line ] [ 1 track-add ] bi
     dup prepare-last-line ; inline
 
-GENERIC: draw-selection ( loc obj -- )
-
-: if-fits ( rect quot -- )
-    [ clip get over contains-rect? ] dip [ drop ] if ; inline
-
-M: gadget draw-selection ( loc gadget -- )
-    swap offset-rect [
-        rect-bounds gl-fill-rect
-    ] if-fits ;
-
-M: node draw-selection ( loc node -- )
-    2dup value>> swap offset-rect [
-        drop 2dup
-        [ value>> loc>> v+ ] keep
-        children>> [ draw-selection ] with each
-    ] if-fits 2drop ;
-
-M: pane draw-gadget*
+M: pane selected-children
     dup gadget-selection? [
-        [ selection-color>> gl-color ]
-        [
-            [ loc>> vneg ] keep selected-children
-            [ draw-selection ] with each
-        ] bi
-    ] [ drop ] if ;
+        [ selected-subtree leaves ]
+        [ selection-color>> ]
+        bi
+    ] [ drop f f ] if ;
 
 : scroll-pane ( pane -- )
     dup scrolls?>> [ scroll>bottom ] [ drop ] if ;
index 8e0131ec3182d32e3eee98bcadb224c86b9c47aa..011afa5c97d25f2f7b268bc1c7ec315f30b77496 100644 (file)
@@ -11,11 +11,11 @@ HELP: find-scroller
 { $values { "gadget" gadget } { "scroller/f" { $maybe scroller } } }
 { $description "Finds the first parent of " { $snippet "gadget" } " which is a " { $link scroller } ". Outputs " { $link f } " if the gadget is not contained in a " { $link scroller } "." } ;
 
-HELP: scroller-value
+HELP: scroll-position
 { $values { "scroller" scroller } { "loc" "a pair of integers" } }
 { $description "Outputs the offset of the top-left corner of the scroller's " { $link viewport } "'s child." } ;
 
-{ scroller-value scroll scroll>bottom scroll>top scroll>rect } related-words
+{ scroll-position set-scroll-position scroll>bottom scroll>top scroll>rect } related-words
 
 HELP: <scroller>
 { $values { "gadget" gadget } { "scroller" "a new " { $link scroller } } }
@@ -23,7 +23,7 @@ HELP: <scroller>
 
 { <viewport> <scroller> } related-words
 
-HELP: scroll
+HELP: set-scroll-position
 { $values { "scroller" scroller } { "value" "a pair of integers" } }
 { $description "Sets the offset of the top-left corner of the scroller's " { $link viewport } "'s child." } ;
 
@@ -48,8 +48,8 @@ ARTICLE: "ui.gadgets.scrollers" "Scroller gadgets"
 { $subsection scroller }
 { $subsection <scroller> }
 "Getting and setting the scroll position:"
-{ $subsection scroller-value }
-{ $subsection scroll }
+{ $subsection scroll-position }
+{ $subsection set-scroll-position }
 "Writing scrolling-aware gadgets:"
 { $subsection scroll>bottom }
 { $subsection scroll>top }
index d4cdc95daff2518e5102cf2197feb500ac844e83..22df1f328ba373e58f1740bf2c8b4cf5ff1a4665 100644 (file)
@@ -45,13 +45,13 @@ IN: ui.gadgets.scrollers.tests
 
     [ { 100 100 } ] [ "s" get viewport>> gadget-child pref-dim ] unit-test
 
-    [ ] [ { 0 0 } "s" get scroll ] unit-test
+    [ ] [ { 0 0 } "s" get set-scroll-position ] unit-test
 
     [ { 0 0 } ] [ "s" get model>> range-min-value ] unit-test
 
     [ { 100 100 } ] [ "s" get model>> range-max-value ] unit-test
 
-    [ ] [ { 10 20 } "s" get scroll ] unit-test
+    [ ] [ { 10 20 } "s" get set-scroll-position ] unit-test
 
     [ { 10 20 } ] [ "s" get model>> range-value ] unit-test
 
@@ -74,7 +74,7 @@ dup layout
         drop
         "g2" get scroll>gadget
         "s" get layout
-        "s" get scroller-value
+        "s" get scroll-position
     ] map [ { 0 0 } = ] all?
 ] unit-test
 
index 64e035c81bb505858741b5d73b4c5414f75a5008..0852a6fe5ddb3c3de21497a9bfe4e332be9e60f1 100644 (file)
@@ -29,6 +29,13 @@ M: gadget viewport-column-header drop f ;
 
 : scroll-down-line ( scroller -- ) y>> 1 swap slide-by-line ;
 
+: set-scroll-position ( value scroller -- )
+    [
+        viewport>> [ dim>> { 0 0 } ] [ gadget-child pref-dim ] bi
+        4array flip
+    ] keep
+    2dup control-value = [ 2drop ] [ set-control-value ] if ;
+
 <PRIVATE
 
 : do-mouse-scroll ( scroller -- )
@@ -46,21 +53,14 @@ scroller H{
 
 M: viewport pref-dim* gadget-child pref-viewport-dim ;
 
-: scroll ( value scroller -- )
-    [
-        viewport>> [ dim>> { 0 0 } ] [ gadget-child pref-dim ] bi
-        4array flip
-    ] keep
-    2dup control-value = [ 2drop ] [ set-control-value ] if ;
-
 : (scroll>rect) ( rect scroller -- )
-    [ [ loc>> ] [ dim>> { 1 1 } v+ ] bi <rect> ] dip
     {
-        [ scroller-value vneg offset-rect ]
+        [ scroll-position vneg offset-rect ]
         [ viewport>> dim>> rect-min ]
+        [ viewport>> loc>> offset-rect ]
         [ viewport>> [ v- { 0 0 } vmin ] [ v- { 0 0 } vmax ] with-rect-extents v+ ]
-        [ scroller-value v+ ]
-        [ scroll ]
+        [ scroll-position v+ ]
+        [ set-scroll-position ]
     } cleave ;
 
 : relative-scroll-rect ( rect gadget scroller -- newrect )
@@ -72,7 +72,7 @@ M: viewport pref-dim* gadget-child pref-viewport-dim ;
     2&& ;
 
 : (update-scroller) ( scroller -- )
-    [ scroller-value ] keep scroll ;
+    [ scroll-position ] keep set-scroll-position ;
 
 : (scroll>gadget) ( gadget scroller -- )
     2dup swap child? [
@@ -82,7 +82,8 @@ M: viewport pref-dim* gadget-child pref-viewport-dim ;
     ] [ f >>follows (update-scroller) drop ] if ;
 
 : (scroll>bottom) ( scroller -- )
-    [ viewport>> gadget-child pref-dim { 0 1 } v* ] keep scroll ;
+    [ viewport>> gadget-child pref-dim { 0 1 } v* ] keep
+    set-scroll-position ;
 
 GENERIC: update-scroller ( scroller follows -- )
 
diff --git a/basis/ui/gadgets/search-tables/search-tables-tests.factor b/basis/ui/gadgets/search-tables/search-tables-tests.factor
new file mode 100644 (file)
index 0000000..5a62728
--- /dev/null
@@ -0,0 +1,3 @@
+IN: ui.gadgets.search-tables.tests
+USING: ui.gadgets.search-tables sequences tools.test ;
+[ [ second ] <search-table> ] must-infer
index 4a2983bfe09627da18ae6d84f7d4a41e937a09d2..17570a8714a805903c79f213533e0afa7a6da4be 100644 (file)
@@ -28,6 +28,7 @@ TUPLE: search-field < track field ;
 
 : <search-field> ( model -- gadget )
     horizontal search-field new-track
+        0 >>fill
         { 5 5 } >>gap
         +baseline+ >>align
         swap <model-field> 10 >>min-cols >>field
index f2ed5b10e0a5d520e64f8980a544ab4565d006eb..77249149aee11e97986ee9b95d05e5791c765d40 100644 (file)
@@ -268,12 +268,13 @@ M: table model-changed
 : mouse-row ( table -- n )
     [ hand-rel second ] keep y>line ;
 
+: if-mouse-row ( table true: ( table mouse-index -- ) false: ( table -- ) -- )
+    [ [ mouse-row ] keep 2dup valid-line? ]
+    [ ] [ '[ nip @ ] ] tri* if ; inline
+
 : table-button-down ( table -- )
     dup takes-focus?>> [ dup request-focus ] when
-    dup control-value empty? [ drop ] [
-        dup [ mouse-row ] keep validate-line
-        [ >>mouse-index ] [ (select-row) ] bi
-    ] if ;
+    [ swap [ >>mouse-index ] [ (select-row) ] bi ] [ drop ] if-mouse-row ;
 
 PRIVATE>
 
@@ -283,11 +284,14 @@ PRIVATE>
     [ 2drop ]
     if ;
 
+: row-action? ( table -- ? )
+    [ [ mouse-row ] keep valid-line? ]
+    [ single-click?>> hand-click# get 2 = or ] bi and ;
+
 <PRIVATE
 
 : table-button-up ( table -- )
-    dup single-click?>> hand-click# get 2 = or
-    [ row-action ] [ update-selected-value ] if ;
+    dup row-action? [ row-action ] [ update-selected-value ] if ;
 
 : select-row ( table n -- )
     over validate-line
@@ -320,13 +324,6 @@ PRIVATE>
 : next-page ( table -- )
     1 prev/next-page ;
 
-: valid-row? ( row table -- ? )
-    control-value length 1- 0 swap between? ;
-
-: if-mouse-row ( table true false -- )
-    [ [ mouse-row ] keep 2dup valid-row? ]
-    [ ] [ '[ nip @ ] ] tri* if ; inline
-
 : show-mouse-help ( table -- )
     [
         swap
index c14c7f01fb1ea83ac5f89ca3b74de4b9125df95c..b154ef2322f4925d06eb14b06190c9e092ec303e 100644 (file)
@@ -23,7 +23,7 @@ M: viewport layout*
 M: viewport focusable-child*
     gadget-child ;
 
-: scroller-value ( scroller -- loc )
+: scroll-position ( scroller -- loc )
     model>> range-value [ >integer ] map ;
 
 M: viewport model-changed
@@ -31,7 +31,7 @@ M: viewport model-changed
     [ relayout-1 ]
     [
         [ gadget-child ]
-        [ scroller-value vneg ]
+        [ scroll-position vneg ]
         [ constraint>> ]
         tri v* >>loc drop
     ] bi ;
index 655c9ba49dfa35ac2c1beb9f518c63f2849777db..a186de76709cbe4197514c2f26f243665de07083 100644 (file)
@@ -1,9 +1,10 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs continuations kernel math models
-namespaces opengl sequences io combinators combinators.short-circuit
-fry math.vectors math.rectangles cache ui.gadgets ui.gestures
-ui.render ui.backend ui.gadgets.tracks ui.commands ;
+namespaces opengl opengl.textures sequences io combinators
+combinators.short-circuit fry math.vectors math.rectangles cache
+ui.gadgets ui.gestures ui.render ui.backend ui.gadgets.tracks
+ui.commands ;
 IN: ui.gadgets.worlds
 
 TUPLE: world < track
@@ -78,6 +79,7 @@ flush-layout-cache-hook [ [ ] ] initialize
 
 : (draw-world) ( world -- )
     dup handle>> [
+        check-extensions
         {
             [ init-gl ]
             [ draw-gadget ]
old mode 100644 (file)
new mode 100755 (executable)
index 4c8f7c24e5a7f251159122c92529ac282d13a42b..c4e6f5688639d1b21a125a237e6895070495f45f 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: math.rectangles math.vectors namespaces kernel accessors
-combinators sequences opengl opengl.gl opengl.glu colors
+assocs combinators sequences opengl opengl.gl colors
 colors.constants ui.gadgets ui.pens ;
 IN: ui.render
 
@@ -22,7 +22,7 @@ SYMBOL: viewport-translation
         dim>>
         [ { 0 1 } v* viewport-translation set ]
         [ [ { 0 0 } ] dip gl-viewport ]
-        [ [ 0 ] dip first2 0 gluOrtho2D ] tri
+        [ [ 0 ] dip first2 0 1 -1 glOrtho ] tri
     ]
     [ clip set ] bi
     do-clip ;
@@ -55,21 +55,57 @@ SYMBOL: origin
 
 GENERIC: draw-children ( gadget -- )
 
+! For gadget selection
+SYMBOL: selected-gadgets
+
+SYMBOL: selection-background
+
+GENERIC: selected-children ( gadget -- assoc/f selection-background )
+
+M: gadget selected-children drop f f ;
+
+! For text rendering
+SYMBOL: background
+
+SYMBOL: foreground
+
+GENERIC: gadget-background ( gadget -- color )
+
+M: gadget gadget-background dup interior>> pen-background ;
+
+GENERIC: gadget-foreground ( gadget -- color )
+
+M: gadget gadget-foreground dup interior>> pen-foreground ;
+
+<PRIVATE
+
+: draw-selection-background ( gadget -- )
+    selection-background get background set
+    selection-background get gl-color
+    [ { 0 0 } ] dip dim>> gl-fill-rect ;
+
+: draw-standard-background ( object -- )
+    dup interior>> dup [ draw-interior ] [ 2drop ] if ;
+
+: draw-background ( gadget -- )
+    origin get [
+        [
+            dup selected-gadgets get key?
+            [ draw-selection-background ]
+            [ draw-standard-background ] if
+        ] [ draw-gadget* ] bi
+    ] with-translation ;
+
+: draw-border ( object -- )
+    dup boundary>> dup [
+        origin get [ draw-boundary ] with-translation
+    ] [ 2drop ] if ;
+
+PRIVATE>
+
 : (draw-gadget) ( gadget -- )
     dup loc>> origin get v+ origin [
-        [
-            origin get [
-                [ dup interior>> dup [ draw-interior ] [ 2drop ] if ]
-                [ draw-gadget* ]
-                bi
-            ] with-translation
-        ]
-        [ draw-children ]
-        [
-            dup boundary>> dup [
-                origin get [ draw-boundary ] with-translation
-            ] [ 2drop ] if
-        ] tri
+        [ draw-background ] [ draw-children ] [ draw-border ] tri
     ] with-variable ;
 
 : >absolute ( rect -- rect )
@@ -88,27 +124,24 @@ GENERIC: draw-children ( gadget -- )
         [ [ (draw-gadget) ] with-clipping ]
     } cond ;
 
-! For text rendering
-SYMBOL: background
-
-SYMBOL: foreground
-
-GENERIC: gadget-background ( gadget -- color )
-
-M: gadget gadget-background dup interior>> pen-background ;
-
-GENERIC: gadget-foreground ( gadget -- color )
-
-M: gadget gadget-foreground dup interior>> pen-foreground ;
-
 M: gadget draw-children
-    [ visible-children ]
-    [ gadget-background ]
-    [ gadget-foreground ] tri [
-        [ foreground set ] when*
-        [ background set ] when*
-        [ draw-gadget ] each
-    ] with-scope ;
+    dup children>> [
+        {
+            [ visible-children ]
+            [ selected-children ]
+            [ gadget-background ]
+            [ gadget-foreground ]
+        } cleave [
+            
+            {
+                [ [ selected-gadgets set ] when* ]
+                [ [ selection-background set ] when* ]
+                [ [ background set ] when* ]
+                [ [ foreground set ] when* ]
+            } spread
+            [ draw-gadget ] each
+        ] with-scope
+    ] [ drop ] if ;
 
 CONSTANT: selection-color T{ rgba f 0.8 0.8 1.0 1.0 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 3704189..0d720ac
@@ -10,9 +10,6 @@ IN: ui.text.core-text
 
 SINGLETON: core-text-renderer
 
-M: core-text-renderer init-text-rendering
-    <cache-assoc> >>text-handle drop ;
-
 M: core-text-renderer string-dim
     [ " " string-dim { 0 1 } v* ]
     [ cached-line dim>> ]
@@ -22,9 +19,9 @@ M: core-text-renderer flush-layout-cache
     cached-lines get purge-cache ;
 
 : rendered-line ( font string -- texture )
-    world get world-text-handle
-    [ cached-line [ image>> ] [ loc>> ] bi <texture> ]
-    2cache ;
+    world get world-text-handle [
+        cached-line [ image>> ] [ loc>> ] bi <texture>
+    2cache ;
 
 M: core-text-renderer draw-string ( font string -- )
     rendered-line draw-texture ;
index 017a4b2cf24d44a09d5c15883e01cd0ab403378e..92c4fe5c75f245206c66e776ee5ce6c7e0dceca3 100755 (executable)
@@ -7,9 +7,6 @@ IN: ui.text.pango
 
 SINGLETON: pango-renderer
 
-M: pango-renderer init-text-rendering
-    <cache-assoc> >>text-handle drop ;
-
 M: pango-renderer string-dim
     [ " " string-dim { 0 1 } v* ]
     [ cached-layout logical-rect>> dim>> [ >integer ] map ] if-empty ;
@@ -18,9 +15,9 @@ M: pango-renderer flush-layout-cache
     cached-layouts get purge-cache ;
 
 : rendered-layout ( font string -- texture )
-    world get world-text-handle
-    [ cached-layout [ image>> ] [ text-position vneg ] bi <texture> ]
-    2cache ;
+    world get world-text-handle [
+        cached-layout [ image>> ] [ text-position vneg ] bi <texture>
+    2cache ;
 
 M: pango-renderer draw-string ( font string -- )
     rendered-layout draw-texture ;
diff --git a/basis/ui/text/pango/summary.txt b/basis/ui/text/pango/summary.txt
new file mode 100755 (executable)
index 0000000..0e2e18c
--- /dev/null
@@ -0,0 +1 @@
+UI text rendering implementation using cross-platform Pango library\r
old mode 100644 (file)
new mode 100755 (executable)
index 939e262..7ee901d
@@ -1,6 +1,22 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: tools.test ui.text fonts ;
+USING: tools.test ui.text fonts math accessors kernel sequences ;
 IN: ui.text.tests
 
-[ 0.0 ] [ 0 sans-serif-font "aaa" offset>x ] unit-test
+[ t ] [ 0 sans-serif-font "aaa" offset>x zero? ] unit-test
+[ t ] [ 1 sans-serif-font "aaa" offset>x 0.0 > ] unit-test
+[ t ] [ 3 sans-serif-font "aaa" offset>x 0.0 > ] unit-test
+[ t ] [ 1 monospace-font "a" offset>x 0.0 > ] unit-test
+[ 0 ] [ 0 sans-serif-font "aaa" x>offset ] unit-test
+[ 3 ] [ 100 sans-serif-font "aaa" x>offset ] unit-test
+[ 0 ] [ 0 sans-serif-font "" x>offset ] unit-test
+
+[ t ] [
+    sans-serif-font "aaa" line-metrics
+    [ [ ascent>> ] [ descent>> ] bi + ] [ height>> ] bi =
+] unit-test
+
+[ f ] [ sans-serif-font "\0a" text-dim first zero? ] unit-test
+[ t ] [ sans-serif-font "" text-dim first zero? ] unit-test
+
+[ f ] [ sans-serif-font font-metrics height>> zero? ] unit-test
old mode 100644 (file)
new mode 100755 (executable)
index ebf4b9c..2edb20f
@@ -1,17 +1,16 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel arrays sequences math math.order opengl opengl.gl
-strings fonts colors accessors namespaces ui.gadgets.worlds ;
+USING: kernel arrays sequences math math.order cache opengl
+opengl.gl strings fonts colors accessors namespaces
+ui.gadgets.worlds ;
 IN: ui.text
 
 <PRIVATE
 
 SYMBOL: font-renderer
 
-HOOK: init-text-rendering font-renderer ( world -- )
-
 : world-text-handle ( world -- handle )
-    dup text-handle>> [ dup init-text-rendering ] unless
+    dup text-handle>> [ <cache-assoc> >>text-handle ] unless
     text-handle>> ;
 
 HOOK: flush-layout-cache font-renderer ( -- )
@@ -67,7 +66,7 @@ M: string draw-text draw-string ;
 M: selection draw-text draw-string ;
 
 M: array draw-text
-    GL_MODELVIEW [
+    [
         [
             [ draw-string ]
             [ [ 0.0 ] 2dip string-height 0.0 glTranslated ] 2bi
@@ -79,7 +78,7 @@ USING: vocabs.loader namespaces system combinators ;
 "ui-backend" get [
     {
         { [ os macosx? ] [ "core-text" ] }
-        { [ os windows? ] [ "pango" ] }
+        { [ os windows? ] [ "uniscribe" ] }
         { [ os unix? ] [ "pango" ] }
     } cond
 ] unless* "ui.text." prepend require
\ No newline at end of file
diff --git a/basis/ui/text/uniscribe/authors.txt b/basis/ui/text/uniscribe/authors.txt
new file mode 100755 (executable)
index 0000000..56f4654
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov\r
diff --git a/basis/ui/text/uniscribe/summary.txt b/basis/ui/text/uniscribe/summary.txt
new file mode 100755 (executable)
index 0000000..6fe24d9
--- /dev/null
@@ -0,0 +1 @@
+UI text rendering implementation using the MS Windows Uniscribe library\r
diff --git a/basis/ui/text/uniscribe/tags.txt b/basis/ui/text/uniscribe/tags.txt
new file mode 100755 (executable)
index 0000000..6abe115
--- /dev/null
@@ -0,0 +1 @@
+unportable\r
diff --git a/basis/ui/text/uniscribe/uniscribe.factor b/basis/ui/text/uniscribe/uniscribe.factor
new file mode 100755 (executable)
index 0000000..d56da86
--- /dev/null
@@ -0,0 +1,42 @@
+! Copyright (C) 2009 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: accessors assocs cache kernel math math.vectors sequences fonts\r
+namespaces opengl.textures ui.text ui.text.private ui.gadgets.worlds \r
+windows.uniscribe ;\r
+IN: ui.text.uniscribe\r
+\r
+SINGLETON: uniscribe-renderer\r
+\r
+M: uniscribe-renderer string-dim\r
+    [ " " string-dim { 0 1 } v* ]\r
+    [ cached-script-string size>> ] if-empty ;\r
+\r
+M: uniscribe-renderer flush-layout-cache\r
+    cached-script-strings get purge-cache ;\r
+\r
+: rendered-script-string ( font string -- texture )\r
+    world get world-text-handle\r
+    [ cached-script-string image>> { 0 0 } <texture> ]\r
+    2cache ;\r
+\r
+M: uniscribe-renderer draw-string ( font string -- )\r
+    dup dup selection? [ string>> ] when empty?\r
+    [ 2drop ] [ rendered-script-string draw-texture ] if ;\r
+\r
+M: uniscribe-renderer x>offset ( x font string -- n )\r
+    [ 2drop 0 ] [\r
+        cached-script-string x>line-offset 0 = [ 1+ ] unless\r
+    ] if-empty ;\r
+\r
+M: uniscribe-renderer offset>x ( n font string -- x )\r
+    [ 2drop 0 ] [ cached-script-string line-offset>x ] if-empty ;\r
+\r
+M: uniscribe-renderer font-metrics ( font -- metrics )\r
+    " " cached-script-string metrics>> clone f >>width ;\r
+\r
+M: uniscribe-renderer line-metrics ( font string -- metrics )\r
+    [ " " line-metrics clone 0 >>width ]\r
+    [ cached-script-string metrics>> 50 >>width 10 >>cap-height 10 >>x-height ]\r
+    if-empty ;\r
+\r
+uniscribe-renderer font-renderer set-global\r
index e242b743f8c399a6dbc9c35e7be5febac0b72df4..0c6e1fe05a5b34f111bd4d4bd13c2c8492f69433 100644 (file)
@@ -1,23 +1,33 @@
 ! Copyright (C) 2006, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: debugger help help.topics help.crossref help.home kernel
-models compiler.units assocs words vocabs accessors fry
-combinators.short-circuit namespaces sequences models
-models.history help.apropos combinators ui.commands ui.gadgets
-ui.gadgets.panes ui.gadgets.scrollers ui.gadgets.tracks
-ui.gestures ui.gadgets.buttons ui.gadgets.packs
-ui.gadgets.editors ui.gadgets.labels ui.gadgets.status-bar
-ui.gadgets.glass ui.gadgets.borders ui.tools.common
-ui.tools.browser.popups ui ;
+USING: debugger help help.topics help.crossref help.home kernel models
+compiler.units assocs words vocabs accessors fry arrays
+combinators.short-circuit namespaces sequences models help.apropos
+combinators ui ui.commands ui.gadgets ui.gadgets.panes
+ui.gadgets.scrollers ui.gadgets.tracks ui.gestures ui.gadgets.buttons
+ui.gadgets.packs ui.gadgets.editors ui.gadgets.labels
+ui.gadgets.status-bar ui.gadgets.glass ui.gadgets.borders ui.gadgets.viewports
+ui.tools.common ui.tools.browser.popups ui.tools.browser.history ;
 IN: ui.tools.browser
 
-TUPLE: browser-gadget < tool pane scroller search-field popup ;
+TUPLE: browser-gadget < tool history pane scroller search-field popup ;
 
 { 650 400 } browser-gadget set-tool-dim
 
+M: browser-gadget history-value
+    [ control-value ] [ scroller>> scroll-position ]
+    bi 2array ;
+
+M: browser-gadget set-history-value
+    [ first2 ] dip
+    [ set-control-value ] [ scroller>> set-scroll-position ]
+    bi-curry bi* ;
+
 : show-help ( link browser-gadget -- )
-    [ >link ] [ model>> ] bi*
-    [ [ add-recent ] [ add-history ] bi* ] [ set-model ] 2bi ;
+    [ >link ] dip
+    [ [ add-recent ] [ history>> add-history ] bi* ]
+    [ model>> set-model ]
+    2bi ;
 
 : <help-pane> ( browser-gadget -- gadget )
     model>> [ '[ _ print-topic ] try ] <pane-control> ;
@@ -41,7 +51,8 @@ TUPLE: browser-gadget < tool pane scroller search-field popup ;
 : <browser-gadget> ( link -- gadget )
     vertical browser-gadget new-track
         1 >>fill
-        swap >link <history> >>model
+        swap >link <model> >>model
+        dup <history> >>history
         dup <search-field> >>search-field
         dup <browser-toolbar> { 3 3 } <border> { 1 0 } >>fill f track-add
         dup <help-pane> >>pane
@@ -93,9 +104,9 @@ M: browser-gadget focusable-child* search-field>> ;
 
 \ show-browser H{ { +nullary+ t } } define-command
 
-: com-back ( browser -- ) model>> go-back ;
+: com-back ( browser -- ) history>> go-back ;
 
-: com-forward ( browser -- ) model>> go-forward ;
+: com-forward ( browser -- ) history>> go-forward ;
 
 : com-home ( browser -- ) "help.home" swap show-help ;
 
diff --git a/basis/ui/tools/browser/history/authors.txt b/basis/ui/tools/browser/history/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/basis/ui/tools/browser/history/history-tests.factor b/basis/ui/tools/browser/history/history-tests.factor
new file mode 100644 (file)
index 0000000..454e470
--- /dev/null
@@ -0,0 +1,42 @@
+USING: namespaces ui.tools.browser.history sequences tools.test
+accessors kernel ;
+IN: ui.tools.browser.history.tests
+
+TUPLE: dummy obj ;
+
+M: dummy history-value obj>> ;
+M: dummy set-history-value (>>obj) ;
+
+dummy new <history> "history" set
+
+"history" get add-history
+
+[ t ] [ "history" get back>> empty? ] unit-test
+[ t ] [ "history" get forward>> empty? ] unit-test
+
+"history" get add-history
+3 "history" get owner>> set-history-value
+
+[ t ] [ "history" get back>> empty? ] unit-test
+[ t ] [ "history" get forward>> empty? ] unit-test
+
+"history" get add-history
+4 "history" get owner>> set-history-value
+
+[ f ] [ "history" get back>> empty? ] unit-test
+[ t ] [ "history" get forward>> empty? ] unit-test
+
+"history" get go-back
+
+[ 3 ] [ "history" get owner>> history-value ] unit-test
+
+[ t ] [ "history" get back>> empty? ] unit-test
+[ f ] [ "history" get forward>> empty? ] unit-test
+
+"history" get go-forward
+
+[ 4 ] [ "history" get owner>> history-value ] unit-test
+
+[ f ] [ "history" get back>> empty? ] unit-test
+[ t ] [ "history" get forward>> empty? ] unit-test
+
diff --git a/basis/ui/tools/browser/history/history.factor b/basis/ui/tools/browser/history/history.factor
new file mode 100644 (file)
index 0000000..f80189c
--- /dev/null
@@ -0,0 +1,32 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors sequences locals ;
+IN: ui.tools.browser.history
+
+TUPLE: history owner back forward ;
+
+: <history> ( owner -- history )
+    V{ } clone V{ } clone history boa ;
+
+GENERIC: history-value ( object -- value )
+
+GENERIC: set-history-value ( value object -- )
+
+: (add-history) ( history to -- )
+    swap owner>> history-value dup [ swap push ] [ 2drop ] if ;
+
+:: go-back/forward ( history to from -- )
+    from empty? [
+        history to (add-history)
+        from pop history owner>> set-history-value
+    ] unless ;
+
+: go-back ( history -- )
+    dup [ forward>> ] [ back>> ] bi go-back/forward ;
+
+: go-forward ( history -- )
+    dup [ back>> ] [ forward>> ] bi go-back/forward ;
+
+: add-history ( history -- )
+    dup forward>> delete-all
+    dup back>> (add-history) ;
\ No newline at end of file
index 022a2daabfc61d4a893aba29c90080ca7348b193..ba66121bc223cad84682107ce3e0c10a62527b36 100644 (file)
@@ -141,6 +141,7 @@ GENERIC# accept-completion-hook 1 ( item popup -- )
         t >>selection-required?
         t >>single-click?
         30 >>min-cols
+        10 >>min-rows
         10 >>max-rows
         dup '[ _ accept-completion ] >>action ;
 
index 93f45591a540bb65e1b65bae425143a160964dce..52cd77d7263cdb656b02bad68248c59eca720dd1 100644 (file)
@@ -55,7 +55,7 @@ $nl
 
 ARTICLE: "ui-tools" "UI developer tools"
 "The " { $vocab-link "ui.tools" } " vocabulary hierarchy implements a collection of simple developer tools."
-$nl
+{ $subsection "starting-ui-tools" }
 "To take full advantage of the UI tools, you should be using a supported text editor. See " { $link "editor" } "."
 $nl
 "Common functionality:"
@@ -66,7 +66,7 @@ $nl
 { $subsection "ui-listener" }
 { $subsection "ui-browser" }
 { $subsection "ui-inspector" }
-{ $subsection "ui-profiler" }
+{ $subsection "ui.tools.profiler" }
 { $subsection "ui-walker" }
 { $subsection "ui.tools.deploy" }
 "Platform-specific features:"
diff --git a/basis/ui/traverse/traverse-docs.factor b/basis/ui/traverse/traverse-docs.factor
new file mode 100644 (file)
index 0000000..e69de29
index e18637a652da2af05897f4f2f526237190266f62..4d2072db1c70e6448f6bedded25ec3f258fa4145 100644 (file)
@@ -62,4 +62,4 @@ M: object (flatten-tree) , ;
     { 0 1 } { 2 0 1 } { { "a" "b" "c" "d" } { "e" "f" "g" } { { "h" "i" } "j" } } gadgets-in-range
 ] unit-test
 
-[ { array children>> } forget ] with-compilation-unit
+[ M\ array children>> forget ] with-compilation-unit
index 63c656205c9d410fcc1a17b5d759aae3d82aa324..9df084210dfdacea63ab361169543653f64ac0d6 100644 (file)
@@ -1,7 +1,7 @@
-! Copyright (C) 2007, 2008 Slava Pestov.
+! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors namespaces make sequences kernel math arrays io
-ui.gadgets generic combinators ;
+ui.gadgets generic combinators fry sets ;
 IN: ui.traverse
 
 TUPLE: node value children ;
@@ -85,3 +85,13 @@ M: node gadget-text*
 
 : gadget-at-path ( parent path -- gadget )
     [ swap nth-gadget ] each ;
+
+GENERIC# leaves* 1 ( tree assoc -- )
+
+M: node leaves* [ children>> ] dip leaves* ;
+
+M: array leaves* '[ _ leaves* ] each ;
+
+M: gadget leaves* conjoin ;
+
+: leaves ( tree -- assoc ) H{ } clone [ leaves* ] keep ;
\ No newline at end of file
index bf17e455f835e6dfb062f0197fee1920891e27f5..8be486cb1a32fc646f35aa7183d002dfb0974102 100644 (file)
@@ -2,9 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs io kernel math models namespaces make dlists
 deques sequences threads sequences words continuations init
-combinators hashtables concurrency.flags sets accessors calendar fry
-destructors ui.gadgets ui.gadgets.private ui.gadgets.worlds
-ui.gadgets.tracks ui.gestures ui.backend ui.render ;
+combinators combinators.short-circuit hashtables concurrency.flags
+sets accessors calendar fry destructors ui.gadgets ui.gadgets.private
+ui.gadgets.worlds ui.gadgets.tracks ui.gestures ui.backend ui.render ;
 IN: ui
 
 <PRIVATE
@@ -117,12 +117,10 @@ M: world ungraft*
     gesture-queue [ send-queued-gesture notify-queued ] slurp-deque ;
 
 : update-ui ( -- )
-    [
-        notify-queued
-        layout-queued
-        redraw-worlds
-        send-queued-gestures
-    ] [ ui-error ] recover ;
+    notify-queued
+    layout-queued
+    redraw-worlds
+    send-queued-gestures ;
 
 SYMBOL: ui-thread
 
@@ -133,8 +131,7 @@ SYMBOL: ui-thread
 PRIVATE>
 
 : find-window ( quot -- world )
-    windows get values
-    [ gadget-child swap call ] with find-last nip ; inline
+    [ windows get values ] dip '[ gadget-child @ ] find-last nip ; inline
 
 : ui-running? ( -- ? )
     \ ui-running get-global ;
@@ -142,9 +139,15 @@ PRIVATE>
 <PRIVATE
 
 : update-ui-loop ( -- )
-    [ ui-running? ui-thread get-global self eq? and ]
-    [ ui-notify-flag get lower-flag update-ui ]
-    while ;
+    #! Note the logic: if update-ui fails, we open an error window
+    #! and run one iteration of update-ui. If that also fails, well,
+    #! the whole UI subsystem is broken so we exit out of the
+    #! update-ui-loop.
+    [ { [ ui-running? ] [ ui-thread get-global self eq? ] } 0&& ]
+    [
+        ui-notify-flag get lower-flag
+        [ update-ui ] [ ui-error update-ui ] recover
+    ] while ;
 
 : start-ui-thread ( -- )
     [ self ui-thread set-global update-ui-loop ]
@@ -193,4 +196,4 @@ M: object close-window
 : with-ui ( quot -- )
     ui-running? [ call( -- ) ] [ '[ init-ui @ ] (with-ui) ] if ;
 
-HOOK: beep ui-backend ( -- )
\ No newline at end of file
+HOOK: beep ui-backend ( -- )
index 1e718cf9b7c76dbac78e681771eda8e575ba24b3..0970df7ad8c6618b55cdd5c3e09e2433ba2b3e13 100644 (file)
@@ -12,3 +12,8 @@ IN: unicode.categories.tests
 [ "Lo" ] [ HEX: 3450 category ] unit-test
 [ "Lo" ] [ HEX: 4DB5 category ] unit-test
 [ "Cs" ] [ HEX: DD00 category ] unit-test
+[ t ] [ CHAR: \t blank? ] unit-test
+[ t ] [ CHAR: \s blank? ] unit-test
+[ t ] [ CHAR: \r blank? ] unit-test
+[ t ] [ CHAR: \n blank? ] unit-test
+[ f ] [ CHAR: a blank? ] unit-test
index 126c03c8698c431e5fea9b32be446675122f1948..4ca5c9a90e74bbd9723b14277376a20f4a430654 100644 (file)
@@ -3,7 +3,7 @@
 USING: unicode.categories.syntax sequences unicode.data ;
 IN: unicode.categories
 
-CATEGORY: blank Zs Zl Zp | "\r\n" member? ;
+CATEGORY: blank Zs Zl Zp | "\r\n\t" member? ;
 CATEGORY: letter Ll | "Other_Lowercase" property? ;
 CATEGORY: LETTER Lu | "Other_Uppercase" property? ;
 CATEGORY: Letter Lu Ll Lt Lm Lo Nl ;
index 9450b49f0bd2f14bae20dcc19c15ecfb7093f92c..56432585c0fac349dc4840d5e847df9db8df9cdd 100644 (file)
@@ -1,7 +1,7 @@
 USING: help.markup help.syntax strings ;
 IN: unicode
 
-ARTICLE: "unicode" "Unicode"
+ARTICLE: "unicode" "Unicode support"
 "The " { $vocab-link "unicode" } " vocabulary and its sub-vocabularies implement support for the Unicode 5.1 character set."
 $nl
 "The Unicode character set contains most of the world's writing systems. Unicode is intended as a replacement for, and is a superset of, such legacy character sets as ASCII, Latin1, MacRoman, and so on. Unicode characters are called " { $emphasis "code points" } "; Factor's " { $link "strings" } " are sequences of code points."
index 87b1812ef8dccf3c4700a90a862c4fdf7e45532c..78e31a764df16020d3debd71f959eb7cd8ce17b4 100644 (file)
@@ -26,3 +26,7 @@ USING: urls.encoding tools.test arrays kernel assocs present accessors ;
 [ H{ { "text" "hello world" } } ] [ "text=hello+world" query>assoc ] unit-test
 
 [ "a=3" ] [ { { "a" 3 } } assoc>query ] unit-test
+
+[ "a" ] [ { { "a" f } } assoc>query ] unit-test
+
+[ H{ { "a" f } } ] [ "a" query>assoc ] unit-test
\ No newline at end of file
index 7fed4b5f58736b7d142b7dbf8853c8670a6c0b67..15b71ac0dbc37b617bad000b810d7acba3d0c3c3 100644 (file)
@@ -72,6 +72,15 @@ PRIVATE>
         ] when*
     ] 2keep set-at ;
 
+: assoc-strings ( assoc -- assoc' )
+    [
+        {
+            { [ dup not ] [ ] }
+            { [ dup array? ] [ [ present ] map ] }
+            [ present 1array ]
+        } cond
+    ] assoc-map ;
+
 PRIVATE>
 
 : query>assoc ( query -- assoc )
@@ -86,11 +95,8 @@ PRIVATE>
 
 : assoc>query ( assoc -- str )
     [
-        dup array? [ [ present ] map ] [ present 1array ] if
-    ] assoc-map
-    [
-        [
+        assoc-strings [
             [ url-encode ] dip
-            [ url-encode "=" glue , ] with each
+            [ [ url-encode "=" glue , ] with each ] [ , ] if*
         ] assoc-each
     ] { } make "&" join ;
index 59fb79e8d35c5c39f406836d9a537e09fe6a9f35..35e428c8fa30005b650b03c0ff21bd2686fe2e4c 100644 (file)
@@ -1,6 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel present prettyprint.custom prettyprint.backend urls ;
+USING: kernel present prettyprint.custom prettyprint.sections
+prettyprint.backend urls ;
 IN: urls.prettyprint
 
-M: url pprint* dup present "URL\" " "\"" pprint-string ;
+M: url pprint*
+    \ URL" record-vocab
+    dup present "URL\" " "\"" pprint-string ;
index 707caf31880bb6275ea71c3d8f6c7a783ef0b690..eb8e452ca4a628d16ef6b329639dab7dbe46493b 100644 (file)
@@ -65,9 +65,8 @@ HELP: derive-url
 } ;
 
 HELP: ensure-port
-{ $values { "url" url } }
-{ $description "If the URL does not specify a port number, fill in the default for the URL's protocol. If the protocol is unknown, the port number is not changed." }
-{ $side-effects "url" }
+{ $values { "url" url } { "url'" url } }
+{ $description "If the URL does not specify a port number, create a new URL which is equal except the port number is set to the default for the URL's protocol. If the protocol is unknown, outputs an exact copy of the input URL." }
 { $examples
     { $example
         "USING: accessors prettyprint urls ;"
index 74eea9506c2bc428016eb0fcb91414a8e7b97667..f2ecd6ec6921d0ecf6e6883e7b875c52865cd482 100644 (file)
@@ -1,5 +1,5 @@
 IN: urls.tests
-USING: urls urls.private tools.test
+USING: urls urls.private tools.test prettyprint
 arrays kernel assocs present accessors ;
 
 CONSTANT: urls
@@ -80,6 +80,15 @@ CONSTANT: urls
             }
             "ftp://slava:secret@ftp.kernel.org/"
         }
+        {
+            T{ url
+               { protocol "http" }
+               { host "foo.com" }
+               { path "/" }
+               { query H{ { "a" f } } }
+            }
+            "http://foo.com/?a"
+        }
     }
 
 urls [
@@ -227,3 +236,5 @@ urls [
 [ "http://localhost/?foo=bar" >url ] unit-test
 
 [ "/" ] [ "http://www.jedit.org" >url path>> ] unit-test
+
+[ "USING: urls ;\nURL\" foo\"" ] [ URL" foo" unparse-use ] unit-test
\ No newline at end of file
index 38d0016d5658ab5d183ccfe32c668dcef38373ed..1e886ae3e26e1e6fac90f75bb175640023d031d9 100644 (file)
@@ -175,8 +175,8 @@ PRIVATE>
     ] [ protocol>> ] bi
     secure-protocol? [ >secure-addr ] when ;
 
-: ensure-port ( url -- url )
-    dup protocol>> '[ _ protocol-port or ] change-port ;
+: ensure-port ( url -- url' )
+    clone dup protocol>> '[ _ protocol-port or ] change-port ;
 
 ! Literal syntax
 SYNTAX: URL" lexer get skip-blank parse-string >url parsed ;
index df38869fbf35ae52a5f5cb53555a848172580df1..7c96f19ac9fd40830464f1a890a36c3fe421effa 100644 (file)
@@ -2,7 +2,7 @@ USING: help.markup help.syntax ;
 IN: values\r
 \r
 ARTICLE: "values" "Global values"\r
-"Usually, dynamically scoped variables are sufficient for holding data which is not literal. But occasionally, for global information that's calculated just once, it's useful to use the word mechanism instead, and set the word to the appropriate value just once. The " { $vocab-link "values" } " vocabulary implements " { $emphasis "values" } ", which abstract over this concept. To create a new word as a value, use the following syntax:"\r
+"Usually, dynamically-scoped variables subsume global variables and are sufficient for holding global data. But occasionally, for global information that's calculated just once and must be accessed more rapidly than a dynamic variable lookup can provide, it's useful to use the word mechanism instead, and set a word to the appropriate value just once. The " { $vocab-link "values" } " vocabulary implements " { $emphasis "values" } ", which abstract over this concept. To create a new word as a value, use the following syntax:"\r
 { $subsection POSTPONE: VALUE: }\r
 "To get the value, just call the word. The following words manipulate values:"\r
 { $subsection get-value }\r
diff --git a/basis/windows/fonts/fonts.factor b/basis/windows/fonts/fonts.factor
new file mode 100755 (executable)
index 0000000..a034856
--- /dev/null
@@ -0,0 +1,37 @@
+USING: assocs memoize locals kernel accessors init fonts math\r
+combinators windows windows.types windows.gdi32 ;\r
+IN: windows.fonts\r
+\r
+: windows-font-name ( string -- string' )\r
+    H{\r
+        { "sans-serif" "Tahoma" }\r
+        { "serif" "Times New Roman" }\r
+        { "monospace" "Courier New" }\r
+    } at-default ;\r
+    \r
+MEMO:: (cache-font) ( font -- HFONT )\r
+    font size>> neg ! nHeight\r
+    0 0 0 ! nWidth, nEscapement, nOrientation\r
+    font bold?>> FW_BOLD FW_NORMAL ? ! fnWeight\r
+    font italic?>> TRUE FALSE ? ! fdwItalic\r
+    FALSE ! fdwUnderline\r
+    FALSE ! fdWStrikeOut\r
+    DEFAULT_CHARSET ! fdwCharSet\r
+    OUT_OUTLINE_PRECIS ! fdwOutputPrecision\r
+    CLIP_DEFAULT_PRECIS ! fdwClipPrecision\r
+    DEFAULT_QUALITY ! fdwQuality\r
+    DEFAULT_PITCH ! fdwPitchAndFamily\r
+    font name>> windows-font-name\r
+    CreateFont\r
+    dup win32-error=0/f ;\r
+\r
+: cache-font ( font -- HFONT ) strip-font-colors (cache-font) ;\r
+\r
+[ \ (cache-font) reset-memoized ] "windows.fonts" add-init-hook\r
+\r
+: TEXTMETRIC>metrics ( TEXTMETRIC -- metrics )\r
+    [ metrics new 0 >>width ] dip {\r
+        [ TEXTMETRICW-tmHeight >>height ]\r
+        [ TEXTMETRICW-tmAscent >>ascent ]\r
+        [ TEXTMETRICW-tmDescent >>descent ]\r
+    } cleave ;\r
index 077adf1961bc75eb4731cf5d78c0777b4737925f..794aa0e32e17277fd1cfc92ab5263bc43838d84c 100755 (executable)
-! FUNCTION: AbortDoc
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.syntax kernel windows.types ;
+USING: alien alien.syntax alien.destructors kernel windows.types
+math.bitwise ;
 IN: windows.gdi32
 
-! Stock Logical Objects
-CONSTANT: WHITE_BRUSH         0
-CONSTANT: LTGRAY_BRUSH        1
-CONSTANT: GRAY_BRUSH          2
-CONSTANT: DKGRAY_BRUSH        3
-CONSTANT: BLACK_BRUSH         4
-CONSTANT: NULL_BRUSH          5
-ALIAS: HOLLOW_BRUSH        NULL_BRUSH
-CONSTANT: WHITE_PEN           6
-CONSTANT: BLACK_PEN           7
-CONSTANT: NULL_PEN            8
-CONSTANT: OEM_FIXED_FONT      10
-CONSTANT: ANSI_FIXED_FONT     11
-CONSTANT: ANSI_VAR_FONT       12
-CONSTANT: SYSTEM_FONT         13
+CONSTANT: BI_RGB 0
+CONSTANT: BI_RLE8 1
+CONSTANT: BI_RLE4 2
+CONSTANT: BI_BITFIELDS 3
+CONSTANT: BI_JPEG 4
+CONSTANT: BI_PNG 5
+CONSTANT: LF_FACESIZE 32
+CONSTANT: LF_FULLFACESIZE 64
+CONSTANT: CA_NEGATIVE 1
+CONSTANT: CA_LOG_FILTER 2
+CONSTANT: ILLUMINANT_DEVICE_DEFAULT 0
+CONSTANT: ILLUMINANT_A 1
+CONSTANT: ILLUMINANT_B 2
+CONSTANT: ILLUMINANT_C 3
+CONSTANT: ILLUMINANT_D50 4
+CONSTANT: ILLUMINANT_D55 5
+CONSTANT: ILLUMINANT_D65 6
+CONSTANT: ILLUMINANT_D75 7
+CONSTANT: ILLUMINANT_F2 8
+ALIAS: ILLUMINANT_MAX_INDEX ILLUMINANT_F2
+ALIAS: ILLUMINANT_TUNGSTEN ILLUMINANT_A
+ALIAS: ILLUMINANT_DAYLIGHT ILLUMINANT_C
+ALIAS: ILLUMINANT_FLUORESCENT ILLUMINANT_F2
+ALIAS: ILLUMINANT_NTSC ILLUMINANT_C
+CONSTANT: RGB_GAMMA_MIN 2500
+CONSTANT: RGB_GAMMA_MAX 65000
+CONSTANT: REFERENCE_WHITE_MIN 6000
+CONSTANT: REFERENCE_WHITE_MAX 10000
+CONSTANT: REFERENCE_BLACK_MIN 0
+CONSTANT: REFERENCE_BLACK_MAX 4000
+CONSTANT: COLOR_ADJ_MIN -100
+CONSTANT: COLOR_ADJ_MAX 100
+CONSTANT: CCHDEVICENAME 32
+CONSTANT: CCHFORMNAME 32
+CONSTANT: DI_COMPAT 4
+CONSTANT: DI_DEFAULTSIZE 8
+CONSTANT: DI_IMAGE 2
+CONSTANT: DI_MASK 1
+CONSTANT: DI_NORMAL 3
+CONSTANT: DI_APPBANDING 1
+CONSTANT: EMR_HEADER 1
+CONSTANT: EMR_POLYBEZIER 2
+CONSTANT: EMR_POLYGON 3
+CONSTANT: EMR_POLYLINE 4
+CONSTANT: EMR_POLYBEZIERTO 5
+CONSTANT: EMR_POLYLINETO 6
+CONSTANT: EMR_POLYPOLYLINE 7
+CONSTANT: EMR_POLYPOLYGON 8
+CONSTANT: EMR_SETWINDOWEXTEX 9
+CONSTANT: EMR_SETWINDOWORGEX 10
+CONSTANT: EMR_SETVIEWPORTEXTEX 11
+CONSTANT: EMR_SETVIEWPORTORGEX 12
+CONSTANT: EMR_SETBRUSHORGEX 13
+CONSTANT: EMR_EOF 14
+CONSTANT: EMR_SETPIXELV 15
+CONSTANT: EMR_SETMAPPERFLAGS 16
+CONSTANT: EMR_SETMAPMODE 17
+CONSTANT: EMR_SETBKMODE 18
+CONSTANT: EMR_SETPOLYFILLMODE 19
+CONSTANT: EMR_SETROP2 20
+CONSTANT: EMR_SETSTRETCHBLTMODE 21
+CONSTANT: EMR_SETTEXTALIGN 22
+CONSTANT: EMR_SETCOLORADJUSTMENT 23
+CONSTANT: EMR_SETTEXTCOLOR 24
+CONSTANT: EMR_SETBKCOLOR 25
+CONSTANT: EMR_OFFSETCLIPRGN 26
+CONSTANT: EMR_MOVETOEX 27
+CONSTANT: EMR_SETMETARGN 28
+CONSTANT: EMR_EXCLUDECLIPRECT 29
+CONSTANT: EMR_INTERSECTCLIPRECT 30
+CONSTANT: EMR_SCALEVIEWPORTEXTEX 31
+CONSTANT: EMR_SCALEWINDOWEXTEX 32
+CONSTANT: EMR_SAVEDC 33
+CONSTANT: EMR_RESTOREDC 34
+CONSTANT: EMR_SETWORLDTRANSFORM 35
+CONSTANT: EMR_MODIFYWORLDTRANSFORM 36
+CONSTANT: EMR_SELECTOBJECT 37
+CONSTANT: EMR_CREATEPEN 38
+CONSTANT: EMR_CREATEBRUSHINDIRECT 39
+CONSTANT: EMR_DELETEOBJECT 40
+CONSTANT: EMR_ANGLEARC 41
+CONSTANT: EMR_ELLIPSE 42
+CONSTANT: EMR_RECTANGLE 43
+CONSTANT: EMR_ROUNDRECT 44
+CONSTANT: EMR_ARC 45
+CONSTANT: EMR_CHORD 46
+CONSTANT: EMR_PIE 47
+CONSTANT: EMR_SELECTPALETTE 48
+CONSTANT: EMR_CREATEPALETTE 49
+CONSTANT: EMR_SETPALETTEENTRIES 50
+CONSTANT: EMR_RESIZEPALETTE 51
+CONSTANT: EMR_REALIZEPALETTE 52
+CONSTANT: EMR_EXTFLOODFILL 53
+CONSTANT: EMR_LINETO 54
+CONSTANT: EMR_ARCTO 55
+CONSTANT: EMR_POLYDRAW 56
+CONSTANT: EMR_SETARCDIRECTION 57
+CONSTANT: EMR_SETMITERLIMIT 58
+CONSTANT: EMR_BEGINPATH 59
+CONSTANT: EMR_ENDPATH 60
+CONSTANT: EMR_CLOSEFIGURE 61
+CONSTANT: EMR_FILLPATH 62
+CONSTANT: EMR_STROKEANDFILLPATH 63
+CONSTANT: EMR_STROKEPATH 64
+CONSTANT: EMR_FLATTENPATH 65
+CONSTANT: EMR_WIDENPATH 66
+CONSTANT: EMR_SELECTCLIPPATH 67
+CONSTANT: EMR_ABORTPATH 68
+CONSTANT: EMR_GDICOMMENT 70
+CONSTANT: EMR_FILLRGN 71
+CONSTANT: EMR_FRAMERGN 72
+CONSTANT: EMR_INVERTRGN 73
+CONSTANT: EMR_PAINTRGN 74
+CONSTANT: EMR_EXTSELECTCLIPRGN 75
+CONSTANT: EMR_BITBLT 76
+CONSTANT: EMR_STRETCHBLT 77
+CONSTANT: EMR_MASKBLT 78
+CONSTANT: EMR_PLGBLT 79
+CONSTANT: EMR_SETDIBITSTODEVICE 80
+CONSTANT: EMR_STRETCHDIBITS 81
+CONSTANT: EMR_EXTCREATEFONTINDIRECTW 82
+CONSTANT: EMR_EXTTEXTOUTA 83
+CONSTANT: EMR_EXTTEXTOUTW 84
+CONSTANT: EMR_POLYBEZIER16 85
+CONSTANT: EMR_POLYGON16 86
+CONSTANT: EMR_POLYLINE16 87
+CONSTANT: EMR_POLYBEZIERTO16 88
+CONSTANT: EMR_POLYLINETO16 89
+CONSTANT: EMR_POLYPOLYLINE16 90
+CONSTANT: EMR_POLYPOLYGON16 91
+CONSTANT: EMR_POLYDRAW16 92
+CONSTANT: EMR_CREATEMONOBRUSH 93
+CONSTANT: EMR_CREATEDIBPATTERNBRUSHPT 94
+CONSTANT: EMR_EXTCREATEPEN 95
+CONSTANT: EMR_POLYTEXTOUTA 96
+CONSTANT: EMR_POLYTEXTOUTW 97
+CONSTANT: EMR_SETICMMODE 98
+CONSTANT: EMR_CREATECOLORSPACE 99
+CONSTANT: EMR_SETCOLORSPACE 100
+CONSTANT: EMR_DELETECOLORSPACE 101
+CONSTANT: EMR_GLSRECORD 102
+CONSTANT: EMR_GLSBOUNDEDRECORD 103
+CONSTANT: EMR_PIXELFORMAT 104
+CONSTANT: ENHMETA_SIGNATURE 1179469088
+CONSTANT: EPS_SIGNATURE HEX: 46535045
+CONSTANT: FR_PRIVATE HEX: 10
+CONSTANT: FR_NOT_ENUM HEX: 20
+CONSTANT: META_SETBKCOLOR HEX: 201
+CONSTANT: META_SETBKMODE HEX: 102
+CONSTANT: META_SETMAPMODE HEX: 103
+CONSTANT: META_SETROP2 HEX: 104
+CONSTANT: META_SETRELABS HEX: 105
+CONSTANT: META_SETPOLYFILLMODE HEX: 106
+CONSTANT: META_SETSTRETCHBLTMODE HEX: 107
+CONSTANT: META_SETTEXTCHAREXTRA HEX: 108
+CONSTANT: META_SETTEXTCOLOR HEX: 209
+CONSTANT: META_SETTEXTJUSTIFICATION HEX: 20A
+CONSTANT: META_SETWINDOWORG HEX: 20B
+CONSTANT: META_SETWINDOWEXT HEX: 20C
+CONSTANT: META_SETVIEWPORTORG HEX: 20D
+CONSTANT: META_SETVIEWPORTEXT HEX: 20E
+CONSTANT: META_OFFSETWINDOWORG HEX: 20F
+CONSTANT: META_SCALEWINDOWEXT HEX: 410
+CONSTANT: META_OFFSETVIEWPORTORG HEX: 211
+CONSTANT: META_SCALEVIEWPORTEXT HEX: 412
+CONSTANT: META_LINETO HEX: 213
+CONSTANT: META_MOVETO HEX: 214
+CONSTANT: META_EXCLUDECLIPRECT HEX: 415
+CONSTANT: META_INTERSECTCLIPRECT HEX: 416
+CONSTANT: META_ARC HEX: 817
+CONSTANT: META_ELLIPSE HEX: 418
+CONSTANT: META_FLOODFILL HEX: 419
+CONSTANT: META_PIE HEX: 81A
+CONSTANT: META_RECTANGLE HEX: 41B
+CONSTANT: META_ROUNDRECT HEX: 61C
+CONSTANT: META_PATBLT HEX: 61D
+CONSTANT: META_SAVEDC HEX: 1E
+CONSTANT: META_SETPIXEL HEX: 41F
+CONSTANT: META_OFFSETCLIPRGN HEX: 220
+CONSTANT: META_TEXTOUT HEX: 521
+CONSTANT: META_BITBLT HEX: 922
+CONSTANT: META_STRETCHBLT HEX: b23
+CONSTANT: META_POLYGON HEX: 324
+CONSTANT: META_POLYLINE HEX: 325
+CONSTANT: META_ESCAPE HEX: 626
+CONSTANT: META_RESTOREDC HEX: 127
+CONSTANT: META_FILLREGION HEX: 228
+CONSTANT: META_FRAMEREGION HEX: 429
+CONSTANT: META_INVERTREGION HEX: 12A
+CONSTANT: META_PAINTREGION HEX: 12B
+CONSTANT: META_SELECTCLIPREGION HEX: 12C
+CONSTANT: META_SELECTOBJECT HEX: 12D
+CONSTANT: META_SETTEXTALIGN HEX: 12E
+CONSTANT: META_CHORD HEX: 830
+CONSTANT: META_SETMAPPERFLAGS HEX: 231
+CONSTANT: META_EXTTEXTOUT HEX: a32
+CONSTANT: META_SETDIBTODEV HEX: d33
+CONSTANT: META_SELECTPALETTE HEX: 234
+CONSTANT: META_REALIZEPALETTE HEX: 35
+CONSTANT: META_ANIMATEPALETTE HEX: 436
+CONSTANT: META_SETPALENTRIES HEX: 37
+CONSTANT: META_POLYPOLYGON HEX: 538
+CONSTANT: META_RESIZEPALETTE HEX: 139
+CONSTANT: META_DIBBITBLT HEX: 940
+CONSTANT: META_DIBSTRETCHBLT HEX: b41
+CONSTANT: META_DIBCREATEPATTERNBRUSH HEX: 142
+CONSTANT: META_STRETCHDIB HEX: f43
+CONSTANT: META_EXTFLOODFILL HEX: 548
+CONSTANT: META_DELETEOBJECT HEX: 1f0
+CONSTANT: META_CREATEPALETTE HEX: f7
+CONSTANT: META_CREATEPATTERNBRUSH HEX: 1F9
+CONSTANT: META_CREATEPENINDIRECT HEX: 2FA
+CONSTANT: META_CREATEFONTINDIRECT HEX: 2FB
+CONSTANT: META_CREATEBRUSHINDIRECT HEX: 2FC
+CONSTANT: META_CREATEREGION HEX: 6FF
+CONSTANT: ELF_VENDOR_SIZE 4
+CONSTANT: ELF_VERSION 0
+CONSTANT: ELF_CULTURE_LATIN 0
+CONSTANT: PFD_TYPE_RGBA 0
+CONSTANT: PFD_TYPE_COLORINDEX 1
+CONSTANT: PFD_MAIN_PLANE 0
+CONSTANT: PFD_OVERLAY_PLANE 1
+CONSTANT: PFD_UNDERLAY_PLANE -1
+CONSTANT: PFD_DOUBLEBUFFER 1
+CONSTANT: PFD_STEREO 2
+CONSTANT: PFD_DRAW_TO_WINDOW 4
+CONSTANT: PFD_DRAW_TO_BITMAP 8
+CONSTANT: PFD_SUPPORT_GDI 16
+CONSTANT: PFD_SUPPORT_OPENGL 32
+CONSTANT: PFD_GENERIC_FORMAT 64
+CONSTANT: PFD_NEED_PALETTE 128
+CONSTANT: PFD_NEED_SYSTEM_PALETTE HEX: 00000100
+CONSTANT: PFD_SWAP_EXCHANGE HEX: 00000200
+CONSTANT: PFD_SWAP_COPY HEX: 00000400
+CONSTANT: PFD_SWAP_LAYER_BUFFERS HEX: 00000800
+CONSTANT: PFD_GENERIC_ACCELERATED HEX: 00001000
+CONSTANT: PFD_DEPTH_DONTCARE HEX: 20000000
+CONSTANT: PFD_DOUBLEBUFFER_DONTCARE HEX: 40000000
+CONSTANT: PFD_STEREO_DONTCARE HEX: 80000000
+CONSTANT: SP_ERROR -1
+CONSTANT: SP_OUTOFDISK -4
+CONSTANT: SP_OUTOFMEMORY -5
+CONSTANT: SP_USERABORT -3
+CONSTANT: SP_APPABORT -2
+CONSTANT: BLACKNESS HEX: 00000042
+CONSTANT: NOTSRCERASE HEX: 001100A6
+CONSTANT: NOTSRCCOPY HEX: 00330008
+CONSTANT: SRCERASE HEX: 00440328
+CONSTANT: DSTINVERT HEX: 00550009
+CONSTANT: PATINVERT HEX: 005A0049
+CONSTANT: SRCINVERT HEX: 00660046
+CONSTANT: SRCAND HEX: 008800C6
+CONSTANT: MERGEPAINT HEX: 00BB0226
+CONSTANT: MERGECOPY HEX: 00C000CA
+CONSTANT: SRCCOPY HEX: 00CC0020
+CONSTANT: SRCPAINT HEX: 00EE0086
+CONSTANT: PATCOPY HEX: 00F00021
+CONSTANT: PATPAINT HEX: 00FB0A09
+CONSTANT: WHITENESS HEX: 00FF0062
+CONSTANT: CAPTUREBLT HEX: 40000000
+CONSTANT: NOMIRRORBITMAP HEX: 80000000
+CONSTANT: R2_BLACK 1
+CONSTANT: R2_COPYPEN 13
+CONSTANT: R2_MASKNOTPEN 3
+CONSTANT: R2_MASKPEN 9
+CONSTANT: R2_MASKPENNOT 5
+CONSTANT: R2_MERGENOTPEN 12
+CONSTANT: R2_MERGEPEN 15
+CONSTANT: R2_MERGEPENNOT 14
+CONSTANT: R2_NOP 11
+CONSTANT: R2_NOT 6
+CONSTANT: R2_NOTCOPYPEN 4
+CONSTANT: R2_NOTMASKPEN 8
+CONSTANT: R2_NOTMERGEPEN 2
+CONSTANT: R2_NOTXORPEN 10
+CONSTANT: R2_WHITE 16
+CONSTANT: R2_XORPEN 7
+CONSTANT: CM_OUT_OF_GAMUT 255
+CONSTANT: CM_IN_GAMUT 0
+CONSTANT: RGN_AND 1
+CONSTANT: RGN_COPY 5
+CONSTANT: RGN_DIFF 4
+CONSTANT: RGN_OR 2
+CONSTANT: RGN_XOR 3
+CONSTANT: NULLREGION 1
+CONSTANT: SIMPLEREGION 2
+CONSTANT: COMPLEXREGION 3
+CONSTANT: ERROR 0
+CONSTANT: CBM_INIT 4
+CONSTANT: DIB_PAL_COLORS 1
+CONSTANT: DIB_RGB_COLORS 0
+CONSTANT: FW_DONTCARE 0
+CONSTANT: FW_THIN 100
+CONSTANT: FW_EXTRALIGHT 200
+ALIAS: FW_ULTRALIGHT FW_EXTRALIGHT
+CONSTANT: FW_LIGHT 300
+CONSTANT: FW_NORMAL 400
+CONSTANT: FW_REGULAR 400
+CONSTANT: FW_MEDIUM 500
+CONSTANT: FW_SEMIBOLD 600
+ALIAS: FW_DEMIBOLD FW_SEMIBOLD
+CONSTANT: FW_BOLD 700
+CONSTANT: FW_EXTRABOLD 800
+ALIAS: FW_ULTRABOLD FW_EXTRABOLD
+CONSTANT: FW_HEAVY 900
+ALIAS: FW_BLACK FW_HEAVY
+CONSTANT: ANSI_CHARSET 0
+CONSTANT: DEFAULT_CHARSET 1
+CONSTANT: SYMBOL_CHARSET 2
+CONSTANT: SHIFTJIS_CHARSET 128
+CONSTANT: HANGEUL_CHARSET 129
+CONSTANT: HANGUL_CHARSET 129
+CONSTANT: GB2312_CHARSET 134
+CONSTANT: CHINESEBIG5_CHARSET 136
+CONSTANT: GREEK_CHARSET 161
+CONSTANT: TURKISH_CHARSET 162
+CONSTANT: HEBREW_CHARSET 177
+CONSTANT: ARABIC_CHARSET 178
+CONSTANT: BALTIC_CHARSET 186
+CONSTANT: RUSSIAN_CHARSET 204
+CONSTANT: THAI_CHARSET 222
+CONSTANT: EASTEUROPE_CHARSET 238
+CONSTANT: OEM_CHARSET 255
+CONSTANT: JOHAB_CHARSET 130
+CONSTANT: VIETNAMESE_CHARSET 163
+CONSTANT: MAC_CHARSET 77
+CONSTANT: OUT_DEFAULT_PRECIS 0
+CONSTANT: OUT_STRING_PRECIS 1
+CONSTANT: OUT_CHARACTER_PRECIS 2
+CONSTANT: OUT_STROKE_PRECIS 3
+CONSTANT: OUT_TT_PRECIS 4
+CONSTANT: OUT_DEVICE_PRECIS 5
+CONSTANT: OUT_RASTER_PRECIS 6
+CONSTANT: OUT_TT_ONLY_PRECIS 7
+CONSTANT: OUT_OUTLINE_PRECIS 8
+CONSTANT: CLIP_DEFAULT_PRECIS 0
+CONSTANT: CLIP_CHARACTER_PRECIS 1
+CONSTANT: CLIP_STROKE_PRECIS 2
+CONSTANT: CLIP_MASK 15
+CONSTANT: CLIP_LH_ANGLES 16
+CONSTANT: CLIP_TT_ALWAYS 32
+CONSTANT: CLIP_EMBEDDED 128
+CONSTANT: DEFAULT_QUALITY 0
+CONSTANT: DRAFT_QUALITY 1
+CONSTANT: PROOF_QUALITY 2
+CONSTANT: NONANTIALIASED_QUALITY 3
+CONSTANT: ANTIALIASED_QUALITY 4
+CONSTANT: DEFAULT_PITCH 0
+CONSTANT: FIXED_PITCH 1
+CONSTANT: VARIABLE_PITCH 2
+CONSTANT: MONO_FONT 8
+CONSTANT: FF_DECORATIVE 80
+CONSTANT: FF_DONTCARE 0
+CONSTANT: FF_MODERN 48
+CONSTANT: FF_ROMAN 16
+CONSTANT: FF_SCRIPT 64
+CONSTANT: FF_SWISS 32
+CONSTANT: PANOSE_COUNT 10
+CONSTANT: PAN_FAMILYTYPE_INDEX 0
+CONSTANT: PAN_SERIFSTYLE_INDEX 1
+CONSTANT: PAN_WEIGHT_INDEX 2
+CONSTANT: PAN_PROPORTION_INDEX 3
+CONSTANT: PAN_CONTRAST_INDEX 4
+CONSTANT: PAN_STROKEVARIATION_INDEX 5
+CONSTANT: PAN_ARMSTYLE_INDEX 6
+CONSTANT: PAN_LETTERFORM_INDEX 7
+CONSTANT: PAN_MIDLINE_INDEX 8
+CONSTANT: PAN_XHEIGHT_INDEX 9
+CONSTANT: PAN_CULTURE_LATIN 0
+CONSTANT: PAN_ANY 0
+CONSTANT: PAN_NO_FIT 1
+CONSTANT: PAN_FAMILY_TEXT_DISPLAY 2
+CONSTANT: PAN_FAMILY_SCRIPT 3
+CONSTANT: PAN_FAMILY_DECORATIVE 4
+CONSTANT: PAN_FAMILY_PICTORIAL 5
+CONSTANT: PAN_SERIF_COVE 2
+CONSTANT: PAN_SERIF_OBTUSE_COVE 3
+CONSTANT: PAN_SERIF_SQUARE_COVE 4
+CONSTANT: PAN_SERIF_OBTUSE_SQUARE_COVE 5
+CONSTANT: PAN_SERIF_SQUARE 6
+CONSTANT: PAN_SERIF_THIN 7
+CONSTANT: PAN_SERIF_BONE 8
+CONSTANT: PAN_SERIF_EXAGGERATED 9
+CONSTANT: PAN_SERIF_TRIANGLE 10
+CONSTANT: PAN_SERIF_NORMAL_SANS 11
+CONSTANT: PAN_SERIF_OBTUSE_SANS 12
+CONSTANT: PAN_SERIF_PERP_SANS 13
+CONSTANT: PAN_SERIF_FLARED 14
+CONSTANT: PAN_SERIF_ROUNDED 15
+CONSTANT: PAN_WEIGHT_VERY_LIGHT 2
+CONSTANT: PAN_WEIGHT_LIGHT 3
+CONSTANT: PAN_WEIGHT_THIN 4
+CONSTANT: PAN_WEIGHT_BOOK 5
+CONSTANT: PAN_WEIGHT_MEDIUM 6
+CONSTANT: PAN_WEIGHT_DEMI 7
+CONSTANT: PAN_WEIGHT_BOLD 8
+CONSTANT: PAN_WEIGHT_HEAVY 9
+CONSTANT: PAN_WEIGHT_BLACK 10
+CONSTANT: PAN_WEIGHT_NORD 11
+CONSTANT: PAN_PROP_OLD_STYLE 2
+CONSTANT: PAN_PROP_MODERN 3
+CONSTANT: PAN_PROP_EVEN_WIDTH 4
+CONSTANT: PAN_PROP_EXPANDED 5
+CONSTANT: PAN_PROP_CONDENSED 6
+CONSTANT: PAN_PROP_VERY_EXPANDED 7
+CONSTANT: PAN_PROP_VERY_CONDENSED 8
+CONSTANT: PAN_PROP_MONOSPACED 9
+CONSTANT: PAN_CONTRAST_NONE 2
+CONSTANT: PAN_CONTRAST_VERY_LOW 3
+CONSTANT: PAN_CONTRAST_LOW 4
+CONSTANT: PAN_CONTRAST_MEDIUM_LOW 5
+CONSTANT: PAN_CONTRAST_MEDIUM 6
+CONSTANT: PAN_CONTRAST_MEDIUM_HIGH 7
+CONSTANT: PAN_CONTRAST_HIGH 8
+CONSTANT: PAN_CONTRAST_VERY_HIGH 9
+CONSTANT: PAN_STROKE_GRADUAL_DIAG 2
+CONSTANT: PAN_STROKE_GRADUAL_TRAN 3
+CONSTANT: PAN_STROKE_GRADUAL_VERT 4
+CONSTANT: PAN_STROKE_GRADUAL_HORZ 5
+CONSTANT: PAN_STROKE_RAPID_VERT 6
+CONSTANT: PAN_STROKE_RAPID_HORZ 7
+CONSTANT: PAN_STROKE_INSTANT_VERT 8
+CONSTANT: PAN_STRAIGHT_ARMS_HORZ 2
+CONSTANT: PAN_STRAIGHT_ARMS_WEDGE 3
+CONSTANT: PAN_STRAIGHT_ARMS_VERT 4
+CONSTANT: PAN_STRAIGHT_ARMS_SINGLE_SERIF 5
+CONSTANT: PAN_STRAIGHT_ARMS_DOUBLE_SERIF 6
+CONSTANT: PAN_BENT_ARMS_HORZ 7
+CONSTANT: PAN_BENT_ARMS_WEDGE 8
+CONSTANT: PAN_BENT_ARMS_VERT 9
+CONSTANT: PAN_BENT_ARMS_SINGLE_SERIF 10
+CONSTANT: PAN_BENT_ARMS_DOUBLE_SERIF 11
+CONSTANT: PAN_LETT_NORMAL_CONTACT 2
+CONSTANT: PAN_LETT_NORMAL_WEIGHTED 3
+CONSTANT: PAN_LETT_NORMAL_BOXED 4
+CONSTANT: PAN_LETT_NORMAL_FLATTENED 5
+CONSTANT: PAN_LETT_NORMAL_ROUNDED 6
+CONSTANT: PAN_LETT_NORMAL_OFF_CENTER 7
+CONSTANT: PAN_LETT_NORMAL_SQUARE 8
+CONSTANT: PAN_LETT_OBLIQUE_CONTACT 9
+CONSTANT: PAN_LETT_OBLIQUE_WEIGHTED 10
+CONSTANT: PAN_LETT_OBLIQUE_BOXED 11
+CONSTANT: PAN_LETT_OBLIQUE_FLATTENED 12
+CONSTANT: PAN_LETT_OBLIQUE_ROUNDED 13
+CONSTANT: PAN_LETT_OBLIQUE_OFF_CENTER 14
+CONSTANT: PAN_LETT_OBLIQUE_SQUARE 15
+CONSTANT: PAN_MIDLINE_STANDARD_TRIMMED 2
+CONSTANT: PAN_MIDLINE_STANDARD_POINTED 3
+CONSTANT: PAN_MIDLINE_STANDARD_SERIFED 4
+CONSTANT: PAN_MIDLINE_HIGH_TRIMMED 5
+CONSTANT: PAN_MIDLINE_HIGH_POINTED 6
+CONSTANT: PAN_MIDLINE_HIGH_SERIFED 7
+CONSTANT: PAN_MIDLINE_CONSTANT_TRIMMED 8
+CONSTANT: PAN_MIDLINE_CONSTANT_POINTED 9
+CONSTANT: PAN_MIDLINE_CONSTANT_SERIFED 10
+CONSTANT: PAN_MIDLINE_LOW_TRIMMED 11
+CONSTANT: PAN_MIDLINE_LOW_POINTED 12
+CONSTANT: PAN_MIDLINE_LOW_SERIFED 13
+CONSTANT: PAN_XHEIGHT_CONSTANT_SMALL 2
+CONSTANT: PAN_XHEIGHT_CONSTANT_STD 3
+CONSTANT: PAN_XHEIGHT_CONSTANT_LARGE 4
+CONSTANT: PAN_XHEIGHT_DUCKING_SMALL 5
+CONSTANT: PAN_XHEIGHT_DUCKING_STD 6
+CONSTANT: PAN_XHEIGHT_DUCKING_LARGE 7
+CONSTANT: FS_LATIN1 1
+CONSTANT: FS_LATIN2 2
+CONSTANT: FS_CYRILLIC 4
+CONSTANT: FS_GREEK 8
+CONSTANT: FS_TURKISH 16
+CONSTANT: FS_HEBREW 32
+CONSTANT: FS_ARABIC 64
+CONSTANT: FS_BALTIC 128
+CONSTANT: FS_THAI HEX: 10000
+CONSTANT: FS_JISJAPAN HEX: 20000
+CONSTANT: FS_CHINESESIMP HEX: 40000
+CONSTANT: FS_WANSUNG HEX: 80000
+CONSTANT: FS_CHINESETRAD HEX: 100000
+CONSTANT: FS_JOHAB HEX: 200000
+CONSTANT: FS_SYMBOL HEX: 80000000
+CONSTANT: HS_BDIAGONAL 3
+CONSTANT: HS_CROSS 4
+CONSTANT: HS_DIAGCROSS 5
+CONSTANT: HS_FDIAGONAL 2
+CONSTANT: HS_HORIZONTAL 0
+CONSTANT: HS_VERTICAL 1
+CONSTANT: PS_GEOMETRIC 65536
+CONSTANT: PS_COSMETIC 0
+CONSTANT: PS_ALTERNATE 8
+CONSTANT: PS_SOLID 0
+CONSTANT: PS_DASH 1
+CONSTANT: PS_DOT 2
+CONSTANT: PS_DASHDOT 3
+CONSTANT: PS_DASHDOTDOT 4
+CONSTANT: PS_NULL 5
+CONSTANT: PS_USERSTYLE 7
+CONSTANT: PS_INSIDEFRAME 6
+CONSTANT: PS_ENDCAP_ROUND 0
+CONSTANT: PS_ENDCAP_SQUARE 256
+CONSTANT: PS_ENDCAP_FLAT 512
+CONSTANT: PS_JOIN_BEVEL 4096
+CONSTANT: PS_JOIN_MITER 8192
+CONSTANT: PS_JOIN_ROUND 0
+CONSTANT: PS_STYLE_MASK 15
+CONSTANT: PS_ENDCAP_MASK 3840
+CONSTANT: PS_TYPE_MASK 983040
+CONSTANT: ALTERNATE 1
+CONSTANT: WINDING 2
+CONSTANT: DC_BINNAMES 12
+CONSTANT: DC_BINS 6
+CONSTANT: DC_COPIES 18
+CONSTANT: DC_DRIVER 11
+CONSTANT: DC_DATATYPE_PRODUCED 21
+CONSTANT: DC_DUPLEX 7
+CONSTANT: DC_EMF_COMPLIANT 20
+CONSTANT: DC_ENUMRESOLUTIONS 13
+CONSTANT: DC_EXTRA 9
+CONSTANT: DC_FIELDS 1
+CONSTANT: DC_FILEDEPENDENCIES 14
+CONSTANT: DC_MAXEXTENT 5
+CONSTANT: DC_MINEXTENT 4
+CONSTANT: DC_ORIENTATION 17
+CONSTANT: DC_PAPERNAMES 16
+CONSTANT: DC_PAPERS 2
+CONSTANT: DC_PAPERSIZE 3
+CONSTANT: DC_SIZE 8
+CONSTANT: DC_TRUETYPE 15
+CONSTANT: DCTT_BITMAP 1
+CONSTANT: DCTT_DOWNLOAD 2
+CONSTANT: DCTT_SUBDEV 4
+CONSTANT: DCTT_DOWNLOAD_OUTLINE 8
+CONSTANT: DC_VERSION 10
+CONSTANT: DC_BINADJUST 19
+CONSTANT: DC_MANUFACTURER 23
+CONSTANT: DC_MODEL 24
+CONSTANT: DC_PERSONALITY 25
+CONSTANT: DC_PRINTRATE 26
+CONSTANT: DC_PRINTRATEUNIT 27
+CONSTANT: DC_PRINTERMEM 28
+CONSTANT: DC_MEDIAREADY 29
+CONSTANT: DC_STAPLE 30
+CONSTANT: DC_PRINTRATEPPM 31
+CONSTANT: DC_COLORDEVICE 32
+CONSTANT: DC_NUP 33
+CONSTANT: DC_MEDIATYPENAMES 34
+CONSTANT: DC_MEDIATYPES 35
+CONSTANT: DCBA_FACEUPNONE 0
+CONSTANT: DCBA_FACEUPCENTER 1
+CONSTANT: DCBA_FACEUPLEFT 2
+CONSTANT: DCBA_FACEUPRIGHT 3
+CONSTANT: DCBA_FACEDOWNNONE 256
+CONSTANT: DCBA_FACEDOWNCENTER 257
+CONSTANT: DCBA_FACEDOWNLEFT 258
+CONSTANT: DCBA_FACEDOWNRIGHT 259
+CONSTANT: FLOODFILLBORDER 0
+CONSTANT: FLOODFILLSURFACE 1
+CONSTANT: ETO_CLIPPED HEX: 0004
+CONSTANT: ETO_GLYPH_INDEX HEX: 0010
+CONSTANT: ETO_OPAQUE HEX: 0002
+CONSTANT: ETO_NUMERICSLATIN HEX: 0800
+CONSTANT: ETO_NUMERICSLOCAL HEX: 0400
+CONSTANT: ETO_RTLREADING HEX: 0080
+CONSTANT: ETO_IGNORELANGUAGE HEX: 1000
+CONSTANT: ETO_PDY HEX: 2000
+CONSTANT: GDICOMMENT_WINDOWS_METAFILE -2147483647
+CONSTANT: GDICOMMENT_BEGINGROUP 2
+CONSTANT: GDICOMMENT_ENDGROUP 3
+CONSTANT: GDICOMMENT_MULTIFORMATS 1073741828
+CONSTANT: GDICOMMENT_IDENTIFIER 1128875079
+CONSTANT: AD_COUNTERCLOCKWISE 1
+CONSTANT: AD_CLOCKWISE 2
+CONSTANT: RDH_RECTANGLES 1
+CONSTANT: GCPCLASS_LATIN 1
+CONSTANT: GCPCLASS_HEBREW 2
+CONSTANT: GCPCLASS_ARABIC 2
+CONSTANT: GCPCLASS_NEUTRAL 3
+CONSTANT: GCPCLASS_LOCALNUMBER 4
+CONSTANT: GCPCLASS_LATINNUMBER 5
+CONSTANT: GCPCLASS_LATINNUMERICTERMINATOR 6
+CONSTANT: GCPCLASS_LATINNUMERICSEPARATOR 7
+CONSTANT: GCPCLASS_NUMERICSEPARATOR 8
+CONSTANT: GCPCLASS_PREBOUNDLTR 128
+CONSTANT: GCPCLASS_PREBOUNDRTL 64
+CONSTANT: GCPCLASS_POSTBOUNDLTR 32
+CONSTANT: GCPCLASS_POSTBOUNDRTL 16
+CONSTANT: GCPGLYPH_LINKBEFORE HEX: 8000
+CONSTANT: GCPGLYPH_LINKAFTER HEX: 4000
+CONSTANT: DCB_DISABLE 8
+CONSTANT: DCB_ENABLE 4
+CONSTANT: DCB_RESET 1
+CONSTANT: DCB_SET 3
+CONSTANT: DCB_ACCUMULATE 2
+CONSTANT: DCB_DIRTY 2
+CONSTANT: OBJ_BRUSH 2
+CONSTANT: OBJ_PEN 1
+CONSTANT: OBJ_PAL 5
+CONSTANT: OBJ_FONT 6
+CONSTANT: OBJ_BITMAP 7
+CONSTANT: OBJ_EXTPEN 11
+CONSTANT: OBJ_REGION 8
+CONSTANT: OBJ_DC 3
+CONSTANT: OBJ_MEMDC 10
+CONSTANT: OBJ_METAFILE 9
+CONSTANT: OBJ_METADC 4
+CONSTANT: OBJ_ENHMETAFILE 13
+CONSTANT: OBJ_ENHMETADC 12
+CONSTANT: DRIVERVERSION 0
+CONSTANT: TECHNOLOGY 2
+CONSTANT: DT_PLOTTER 0
+CONSTANT: DT_RASDISPLAY 1
+CONSTANT: DT_RASPRINTER 2
+CONSTANT: DT_RASCAMERA 3
+CONSTANT: DT_CHARSTREAM 4
+CONSTANT: DT_METAFILE 5
+CONSTANT: DT_DISPFILE 6
+CONSTANT: HORZSIZE 4
+CONSTANT: VERTSIZE 6
+CONSTANT: HORZRES 8
+CONSTANT: VERTRES 10
+CONSTANT: LOGPIXELSX 88
+CONSTANT: LOGPIXELSY 90
+CONSTANT: BITSPIXEL 12
+CONSTANT: PLANES 14
+CONSTANT: NUMBRUSHES 16
+CONSTANT: NUMPENS 18
+CONSTANT: NUMFONTS 22
+CONSTANT: NUMCOLORS 24
+CONSTANT: NUMMARKERS 20
+CONSTANT: ASPECTX 40
+CONSTANT: ASPECTY 42
+CONSTANT: ASPECTXY 44
+CONSTANT: PDEVICESIZE 26
+CONSTANT: CLIPCAPS 36
+CONSTANT: SIZEPALETTE 104
+CONSTANT: NUMRESERVED 106
+CONSTANT: COLORRES 108
+CONSTANT: PHYSICALWIDTH 110
+CONSTANT: PHYSICALHEIGHT 111
+CONSTANT: PHYSICALOFFSETX 112
+CONSTANT: PHYSICALOFFSETY 113
+CONSTANT: SCALINGFACTORX 114
+CONSTANT: SCALINGFACTORY 115
+CONSTANT: VREFRESH 116
+CONSTANT: DESKTOPHORZRES 118
+CONSTANT: DESKTOPVERTRES 117
+CONSTANT: BLTALIGNMENT 119
+CONSTANT: SHADEBLENDCAPS 120
+CONSTANT: SB_NONE HEX: 00
+CONSTANT: SB_CONST_ALPHA HEX: 01
+CONSTANT: SB_PIXEL_ALPHA HEX: 02
+CONSTANT: SB_PREMULT_ALPHA HEX: 04
+CONSTANT: SB_GRAD_RECT HEX: 10
+CONSTANT: SB_GRAD_TRI HEX: 20
+CONSTANT: COLORMGMTCAPS 121
+CONSTANT: CM_NONE HEX: 00
+CONSTANT: CM_DEVICE_ICM HEX: 01
+CONSTANT: CM_GAMMA_RAMP HEX: 02
+CONSTANT: CM_CMYK_COLOR HEX: 04
+CONSTANT: RASTERCAPS 38
+CONSTANT: RC_BITBLT 1
+CONSTANT: RC_BITMAP64 8
+CONSTANT: RC_DI_BITMAP 128
+CONSTANT: RC_DIBTODEV 512
+CONSTANT: RC_FLOODFILL 4096
+CONSTANT: RC_STRETCHBLT 2048
+CONSTANT: RC_STRETCHDIB 8192
+CONSTANT: CURVECAPS 28
+CONSTANT: CC_NONE 0
+CONSTANT: CC_CIRCLES 1
+CONSTANT: CC_PIE 2
+CONSTANT: CC_CHORD 4
+CONSTANT: CC_ELLIPSES 8
+CONSTANT: CC_WIDE 16
+CONSTANT: CC_STYLED 32
+CONSTANT: CC_WIDESTYLED 64
+CONSTANT: CC_INTERIORS 128
+CONSTANT: CC_ROUNDRECT 256
+CONSTANT: LINECAPS 30
+CONSTANT: LC_NONE 0
+CONSTANT: LC_POLYLINE 2
+CONSTANT: LC_MARKER 4
+CONSTANT: LC_POLYMARKER 8
+CONSTANT: LC_WIDE 16
+CONSTANT: LC_STYLED 32
+CONSTANT: LC_WIDESTYLED 64
+CONSTANT: LC_INTERIORS 128
+CONSTANT: POLYGONALCAPS 32
+CONSTANT: RC_BANDING 2
+CONSTANT: RC_BIGFONT 1024
+CONSTANT: RC_DEVBITS HEX: 8000
+CONSTANT: RC_GDI20_OUTPUT 16
+CONSTANT: RC_GDI20_STATE 32
+CONSTANT: RC_NONE 0
+CONSTANT: RC_OP_DX_OUTPUT HEX: 4000
+CONSTANT: RC_PALETTE 256
+CONSTANT: RC_SAVEBITMAP 64
+CONSTANT: RC_SCALING 4
+CONSTANT: PC_NONE 0
+CONSTANT: PC_POLYGON 1
+CONSTANT: PC_POLYPOLYGON 256
+CONSTANT: PC_PATHS 512
+CONSTANT: PC_RECTANGLE 2
+CONSTANT: PC_WINDPOLYGON 4
+CONSTANT: PC_SCANLINE 8
+CONSTANT: PC_TRAPEZOID 4
+CONSTANT: PC_WIDE 16
+CONSTANT: PC_STYLED 32
+CONSTANT: PC_WIDESTYLED 64
+CONSTANT: PC_INTERIORS 128
+CONSTANT: TEXTCAPS 34
+CONSTANT: TC_OP_CHARACTER 1
+CONSTANT: TC_OP_STROKE 2
+CONSTANT: TC_CP_STROKE 4
+CONSTANT: TC_CR_90 8
+CONSTANT: TC_CR_ANY 16
+CONSTANT: TC_SF_X_YINDEP 32
+CONSTANT: TC_SA_DOUBLE 64
+CONSTANT: TC_SA_INTEGER 128
+CONSTANT: TC_SA_CONTIN 256
+CONSTANT: TC_EA_DOUBLE 512
+CONSTANT: TC_IA_ABLE 1024
+CONSTANT: TC_UA_ABLE 2048
+CONSTANT: TC_SO_ABLE 4096
+CONSTANT: TC_RA_ABLE 8192
+CONSTANT: TC_VA_ABLE 16384
+CONSTANT: TC_RESERVED 32768
+CONSTANT: TC_SCROLLBLT 65536
+CONSTANT: GCP_DBCS 1
+CONSTANT: GCP_ERROR HEX: 8000
+CONSTANT: GCP_CLASSIN HEX: 80000
+CONSTANT: GCP_DIACRITIC 256
+CONSTANT: GCP_DISPLAYZWG HEX: 400000
+CONSTANT: GCP_GLYPHSHAPE 16
+CONSTANT: GCP_JUSTIFY HEX: 10000
+CONSTANT: GCP_JUSTIFYIN HEX: 200000
+CONSTANT: GCP_KASHIDA 1024
+CONSTANT: GCP_LIGATE 32
+CONSTANT: GCP_MAXEXTENT HEX: 100000
+CONSTANT: GCP_NEUTRALOVERRIDE HEX: 2000000
+CONSTANT: GCP_NUMERICOVERRIDE HEX: 1000000
+CONSTANT: GCP_NUMERICSLATIN HEX: 4000000
+CONSTANT: GCP_NUMERICSLOCAL HEX: 8000000
+CONSTANT: GCP_REORDER 2
+CONSTANT: GCP_SYMSWAPOFF HEX: 800000
+CONSTANT: GCP_USEKERNING 8
+CONSTANT: FLI_GLYPHS HEX: 40000
+CONSTANT: FLI_MASK HEX: 103b
+CONSTANT: GGO_METRICS 0
+CONSTANT: GGO_BITMAP 1
+CONSTANT: GGO_NATIVE 2
+CONSTANT: GGO_BEZIER 3
+CONSTANT: GGO_GRAY2_BITMAP 4
+CONSTANT: GGO_GRAY4_BITMAP 5
+CONSTANT: GGO_GRAY8_BITMAP 6
+CONSTANT: GGO_GLYPH_INDEX 128
+CONSTANT: GGO_UNHINTED 256
+CONSTANT: GM_COMPATIBLE 1
+CONSTANT: GM_ADVANCED 2
+CONSTANT: MM_ANISOTROPIC 8
+CONSTANT: MM_HIENGLISH 5
+CONSTANT: MM_HIMETRIC 3
+CONSTANT: MM_ISOTROPIC 7
+CONSTANT: MM_LOENGLISH 4
+CONSTANT: MM_LOMETRIC 2
+CONSTANT: MM_TEXT 1
+CONSTANT: MM_TWIPS 6
+ALIAS: MM_MAX_FIXEDSCALE MM_TWIPS
+CONSTANT: ABSOLUTE 1
+CONSTANT: RELATIVE 2
+CONSTANT: PC_EXPLICIT 2
+CONSTANT: PC_NOCOLLAPSE 4
+CONSTANT: PC_RESERVED 1
+CONSTANT: CLR_NONE HEX: ffffffff
+ALIAS: CLR_INVALID CLR_NONE
+CONSTANT: CLR_DEFAULT HEX: ff000000
+CONSTANT: PT_MOVETO 6
+CONSTANT: PT_LINETO 2
+CONSTANT: PT_BEZIERTO 4
+CONSTANT: PT_CLOSEFIGURE 1
+CONSTANT: TT_AVAILABLE 1
+CONSTANT: TT_ENABLED 2
+CONSTANT: BLACK_BRUSH 4
+CONSTANT: DKGRAY_BRUSH 3
+CONSTANT: GRAY_BRUSH 2
+CONSTANT: HOLLOW_BRUSH 5
+CONSTANT: LTGRAY_BRUSH 1
+CONSTANT: NULL_BRUSH 5
+CONSTANT: WHITE_BRUSH 0
+CONSTANT: BLACK_PEN 7
+CONSTANT: NULL_PEN 8
+CONSTANT: WHITE_PEN 6
+CONSTANT: ANSI_FIXED_FONT 11
+CONSTANT: ANSI_VAR_FONT 12
 CONSTANT: DEVICE_DEFAULT_FONT 14
-CONSTANT: DEFAULT_PALETTE     15
-CONSTANT: SYSTEM_FIXED_FONT   16
-CONSTANT: DEFAULT_GUI_FONT    17
-CONSTANT: DC_BRUSH            18
-CONSTANT: DC_PEN              19
-                  
-CONSTANT: BI_RGB        0
-CONSTANT: BI_RLE8       1
-CONSTANT: BI_RLE4       2
-CONSTANT: BI_BITFIELDS  3
+CONSTANT: DEFAULT_GUI_FONT 17
+CONSTANT: OEM_FIXED_FONT 10
+CONSTANT: SYSTEM_FONT 13
+CONSTANT: SYSTEM_FIXED_FONT 16
+CONSTANT: DEFAULT_PALETTE 15
+CONSTANT: DC_BRUSH 18
+CONSTANT: DC_PEN 19
+CONSTANT: SYSPAL_ERROR 0
+CONSTANT: SYSPAL_STATIC 1
+CONSTANT: SYSPAL_NOSTATIC 2
+CONSTANT: SYSPAL_NOSTATIC256 3 
+CONSTANT: TA_BASELINE 24
+CONSTANT: TA_BOTTOM 8
+CONSTANT: TA_TOP 0
+CONSTANT: TA_CENTER 6
+CONSTANT: TA_LEFT 0
+CONSTANT: TA_RIGHT 2
+CONSTANT: TA_RTLREADING 256
+CONSTANT: TA_NOUPDATECP 0
+CONSTANT: TA_UPDATECP 1
+: TA_MASK ( -- n ) { TA_BASELINE TA_CENTER TA_UPDATECP TA_RTLREADING } flags ; foldable
+CONSTANT: VTA_BASELINE 24
+CONSTANT: VTA_CENTER 6
+ALIAS: VTA_LEFT TA_BOTTOM
+ALIAS: VTA_RIGHT TA_TOP
+ALIAS: VTA_BOTTOM TA_RIGHT
+ALIAS: VTA_TOP TA_LEFT
+CONSTANT: MWT_IDENTITY 1
+CONSTANT: MWT_LEFTMULTIPLY 2
+CONSTANT: MWT_RIGHTMULTIPLY 3
+CONSTANT: OPAQUE 2
+CONSTANT: TRANSPARENT 1
+CONSTANT: BLACKONWHITE 1
+CONSTANT: WHITEONBLACK 2
+CONSTANT: COLORONCOLOR 3
+CONSTANT: HALFTONE 4
+CONSTANT: MAXSTRETCHBLTMODE 4
+CONSTANT: STRETCH_ANDSCANS 1
+CONSTANT: STRETCH_DELETESCANS 3
+CONSTANT: STRETCH_HALFTONE 4
+CONSTANT: STRETCH_ORSCANS 2
+CONSTANT: TCI_SRCCHARSET 1
+CONSTANT: TCI_SRCCODEPAGE 2
+CONSTANT: TCI_SRCFONTSIG 3
+CONSTANT: ICM_ON 2
+CONSTANT: ICM_OFF 1
+CONSTANT: ICM_QUERY 3
+CONSTANT: NEWFRAME 1
+CONSTANT: ABORTDOC 2
+CONSTANT: NEXTBAND 3
+CONSTANT: SETCOLORTABLE 4
+CONSTANT: GETCOLORTABLE 5
+CONSTANT: FLUSHOUTPUT 6
+CONSTANT: DRAFTMODE 7
+CONSTANT: QUERYESCSUPPORT 8
+CONSTANT: SETABORTPROC 9
+CONSTANT: STARTDOC 10
+CONSTANT: ENDDOC 11
+CONSTANT: GETPHYSPAGESIZE 12
+CONSTANT: GETPRINTINGOFFSET 13
+CONSTANT: GETSCALINGFACTOR 14
+CONSTANT: MFCOMMENT 15
+CONSTANT: GETPENWIDTH 16
+CONSTANT: SETCOPYCOUNT 17
+CONSTANT: SELECTPAPERSOURCE 18
+CONSTANT: DEVICEDATA 19
+CONSTANT: PASSTHROUGH 19
+CONSTANT: GETTECHNOLGY 20
+CONSTANT: GETTECHNOLOGY 20
+CONSTANT: SETLINECAP 21
+CONSTANT: SETLINEJOIN 22
+CONSTANT: SETMITERLIMIT 23
+CONSTANT: BANDINFO 24
+CONSTANT: DRAWPATTERNRECT 25
+CONSTANT: GETVECTORPENSIZE 26
+CONSTANT: GETVECTORBRUSHSIZE 27
+CONSTANT: ENABLEDUPLEX 28
+CONSTANT: GETSETPAPERBINS 29
+CONSTANT: GETSETPRINTORIENT 30
+CONSTANT: ENUMPAPERBINS 31
+CONSTANT: SETDIBSCALING 32
+CONSTANT: EPSPRINTING 33
+CONSTANT: ENUMPAPERMETRICS 34
+CONSTANT: GETSETPAPERMETRICS 35
+CONSTANT: POSTSCRIPT_DATA 37
+CONSTANT: POSTSCRIPT_IGNORE 38
+CONSTANT: MOUSETRAILS 39
+CONSTANT: GETDEVICEUNITS 42
+CONSTANT: GETEXTENDEDTEXTMETRICS 256
+CONSTANT: GETEXTENTTABLE 257
+CONSTANT: GETPAIRKERNTABLE 258
+CONSTANT: GETTRACKKERNTABLE 259
+CONSTANT: EXTTEXTOUT 512
+CONSTANT: GETFACENAME 513
+CONSTANT: DOWNLOADFACE 514
+CONSTANT: ENABLERELATIVEWIDTHS 768
+CONSTANT: ENABLEPAIRKERNING 769
+CONSTANT: SETKERNTRACK 770
+CONSTANT: SETALLJUSTVALUES 771
+CONSTANT: SETCHARSET 772
+CONSTANT: STRETCHBLT 2048
+CONSTANT: GETSETSCREENPARAMS 3072
+CONSTANT: QUERYDIBSUPPORT 3073
+CONSTANT: BEGIN_PATH 4096
+CONSTANT: CLIP_TO_PATH 4097
+CONSTANT: END_PATH 4098
+CONSTANT: EXT_DEVICE_CAPS 4099
+CONSTANT: RESTORE_CTM 4100
+CONSTANT: SAVE_CTM 4101
+CONSTANT: SET_ARC_DIRECTION 4102
+CONSTANT: SET_BACKGROUND_COLOR 4103
+CONSTANT: SET_POLY_MODE 4104
+CONSTANT: SET_SCREEN_ANGLE 4105
+CONSTANT: SET_SPREAD 4106
+CONSTANT: TRANSFORM_CTM 4107
+CONSTANT: SET_CLIP_BOX 4108
+CONSTANT: SET_BOUNDS 4109
+CONSTANT: SET_MIRROR_MODE 4110
+CONSTANT: OPENCHANNEL 4110
+CONSTANT: DOWNLOADHEADER 4111
+CONSTANT: CLOSECHANNEL 4112
+CONSTANT: POSTSCRIPT_PASSTHROUGH 4115
+CONSTANT: ENCAPSULATED_POSTSCRIPT 4116
+CONSTANT: QDI_SETDIBITS 1
+CONSTANT: QDI_GETDIBITS 2
+CONSTANT: QDI_DIBTOSCREEN 4
+CONSTANT: QDI_STRETCHDIB 8
+CONSTANT: SP_NOTREPORTED HEX: 4000
+CONSTANT: PR_JOBSTATUS 0
+CONSTANT: ASPECT_FILTERING 1
+CONSTANT: BS_SOLID 0
+CONSTANT: BS_NULL 1
+CONSTANT: BS_HOLLOW 1
+CONSTANT: BS_HATCHED 2
+CONSTANT: BS_PATTERN 3
+CONSTANT: BS_INDEXED 4
+CONSTANT: BS_DIBPATTERN 5
+CONSTANT: BS_DIBPATTERNPT 6
+CONSTANT: BS_PATTERN8X8 7
+CONSTANT: BS_DIBPATTERN8X8 8
+CONSTANT: LCS_CALIBRATED_RGB 0
+CONSTANT: LCS_DEVICE_RGB 1
+CONSTANT: LCS_DEVICE_CMYK 2
+CONSTANT: LCS_GM_BUSINESS 1
+CONSTANT: LCS_GM_GRAPHICS 2
+CONSTANT: LCS_GM_IMAGES 4
+CONSTANT: RASTER_FONTTYPE 1
+CONSTANT: DEVICE_FONTTYPE 2
+CONSTANT: TRUETYPE_FONTTYPE 4
+CONSTANT: DMORIENT_PORTRAIT 1
+CONSTANT: DMORIENT_LANDSCAPE 2
+CONSTANT: DMPAPER_FIRST 1
+CONSTANT: DMPAPER_LETTER 1
+CONSTANT: DMPAPER_LETTERSMALL 2
+CONSTANT: DMPAPER_TABLOID 3
+CONSTANT: DMPAPER_LEDGER 4
+CONSTANT: DMPAPER_LEGAL 5
+CONSTANT: DMPAPER_STATEMENT 6
+CONSTANT: DMPAPER_EXECUTIVE 7
+CONSTANT: DMPAPER_A3 8
+CONSTANT: DMPAPER_A4 9
+CONSTANT: DMPAPER_A4SMALL 10
+CONSTANT: DMPAPER_A5 11
+CONSTANT: DMPAPER_B4 12
+CONSTANT: DMPAPER_B5 13
+CONSTANT: DMPAPER_FOLIO 14
+CONSTANT: DMPAPER_QUARTO 15
+CONSTANT: DMPAPER_10X14 16
+CONSTANT: DMPAPER_11X17 17
+CONSTANT: DMPAPER_NOTE 18
+CONSTANT: DMPAPER_ENV_9 19
+CONSTANT: DMPAPER_ENV_10 20
+CONSTANT: DMPAPER_ENV_11 21
+CONSTANT: DMPAPER_ENV_12 22
+CONSTANT: DMPAPER_ENV_14 23
+CONSTANT: DMPAPER_CSHEET 24
+CONSTANT: DMPAPER_DSHEET 25
+CONSTANT: DMPAPER_ESHEET 26
+CONSTANT: DMPAPER_ENV_DL 27
+CONSTANT: DMPAPER_ENV_C5 28
+CONSTANT: DMPAPER_ENV_C3 29
+CONSTANT: DMPAPER_ENV_C4 30
+CONSTANT: DMPAPER_ENV_C6 31
+CONSTANT: DMPAPER_ENV_C65 32
+CONSTANT: DMPAPER_ENV_B4 33
+CONSTANT: DMPAPER_ENV_B5 34
+CONSTANT: DMPAPER_ENV_B6 35
+CONSTANT: DMPAPER_ENV_ITALY 36
+CONSTANT: DMPAPER_ENV_MONARCH 37
+CONSTANT: DMPAPER_ENV_PERSONAL 38
+CONSTANT: DMPAPER_FANFOLD_US 39
+CONSTANT: DMPAPER_FANFOLD_STD_GERMAN 40
+CONSTANT: DMPAPER_FANFOLD_LGL_GERMAN 41
+CONSTANT: DMPAPER_ISO_B4 42
+CONSTANT: DMPAPER_JAPANESE_POSTCARD 43
+CONSTANT: DMPAPER_9X11 44
+CONSTANT: DMPAPER_10X11 45
+CONSTANT: DMPAPER_15X11 46
+CONSTANT: DMPAPER_ENV_INVITE 47
+CONSTANT: DMPAPER_RESERVED_48 48
+CONSTANT: DMPAPER_RESERVED_49 49
+CONSTANT: DMPAPER_LETTER_EXTRA 50
+CONSTANT: DMPAPER_LEGAL_EXTRA 51
+CONSTANT: DMPAPER_TABLOID_EXTRA 52
+CONSTANT: DMPAPER_A4_EXTRA 53
+CONSTANT: DMPAPER_LETTER_TRANSVERSE 54
+CONSTANT: DMPAPER_A4_TRANSVERSE 55
+CONSTANT: DMPAPER_LETTER_EXTRA_TRANSVERSE 56
+CONSTANT: DMPAPER_A_PLUS 57
+CONSTANT: DMPAPER_B_PLUS 58
+CONSTANT: DMPAPER_LETTER_PLUS 59
+CONSTANT: DMPAPER_A4_PLUS 60
+CONSTANT: DMPAPER_A5_TRANSVERSE 61
+CONSTANT: DMPAPER_B5_TRANSVERSE 62
+CONSTANT: DMPAPER_A3_EXTRA 63
+CONSTANT: DMPAPER_A5_EXTRA 64
+CONSTANT: DMPAPER_B5_EXTRA 65
+CONSTANT: DMPAPER_A2 66
+CONSTANT: DMPAPER_A3_TRANSVERSE 67
+CONSTANT: DMPAPER_A3_EXTRA_TRANSVERSE 68
+CONSTANT: DMPAPER_DBL_JAPANESE_POSTCARD 69
+CONSTANT: DMPAPER_A6 70
+CONSTANT: DMPAPER_JENV_KAKU2 71
+CONSTANT: DMPAPER_JENV_KAKU3 72
+CONSTANT: DMPAPER_JENV_CHOU3 73
+CONSTANT: DMPAPER_JENV_CHOU4 74
+CONSTANT: DMPAPER_LETTER_ROTATED 75
+CONSTANT: DMPAPER_A3_ROTATED 76
+CONSTANT: DMPAPER_A4_ROTATED 77
+CONSTANT: DMPAPER_A5_ROTATED 78
+CONSTANT: DMPAPER_B4_JIS_ROTATED 79
+CONSTANT: DMPAPER_B5_JIS_ROTATED 80
+CONSTANT: DMPAPER_JAPANESE_POSTCARD_ROTATED 81
+CONSTANT: DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED 82
+CONSTANT: DMPAPER_A6_ROTATED 83
+CONSTANT: DMPAPER_JENV_KAKU2_ROTATED 84
+CONSTANT: DMPAPER_JENV_KAKU3_ROTATED 85
+CONSTANT: DMPAPER_JENV_CHOU3_ROTATED 86
+CONSTANT: DMPAPER_JENV_CHOU4_ROTATED 87
+CONSTANT: DMPAPER_B6_JIS 88
+CONSTANT: DMPAPER_B6_JIS_ROTATED 89
+CONSTANT: DMPAPER_12X11 90
+CONSTANT: DMPAPER_JENV_YOU4 91
+CONSTANT: DMPAPER_JENV_YOU4_ROTATED 92
+CONSTANT: DMPAPER_P16K 93
+CONSTANT: DMPAPER_P32K 94
+CONSTANT: DMPAPER_P32KBIG 95
+CONSTANT: DMPAPER_PENV_1 96
+CONSTANT: DMPAPER_PENV_2 97
+CONSTANT: DMPAPER_PENV_3 98
+CONSTANT: DMPAPER_PENV_4 99
+CONSTANT: DMPAPER_PENV_5 100
+CONSTANT: DMPAPER_PENV_6 101
+CONSTANT: DMPAPER_PENV_7 102
+CONSTANT: DMPAPER_PENV_8 103
+CONSTANT: DMPAPER_PENV_9 104
+CONSTANT: DMPAPER_PENV_10 105
+CONSTANT: DMPAPER_P16K_ROTATED 106
+CONSTANT: DMPAPER_P32K_ROTATED 107
+CONSTANT: DMPAPER_P32KBIG_ROTATED 108
+CONSTANT: DMPAPER_PENV_1_ROTATED 109
+CONSTANT: DMPAPER_PENV_2_ROTATED 110
+CONSTANT: DMPAPER_PENV_3_ROTATED 111
+CONSTANT: DMPAPER_PENV_4_ROTATED 112
+CONSTANT: DMPAPER_PENV_5_ROTATED 113
+CONSTANT: DMPAPER_PENV_6_ROTATED 114
+CONSTANT: DMPAPER_PENV_7_ROTATED 115
+CONSTANT: DMPAPER_PENV_8_ROTATED 116
+CONSTANT: DMPAPER_PENV_9_ROTATED 117
+CONSTANT: DMPAPER_PENV_10_ROTATED 118
+CONSTANT: DMPAPER_LAST 118
+CONSTANT: DMPAPER_USER 256
+CONSTANT: DMBIN_FIRST 1
+CONSTANT: DMBIN_UPPER 1
+CONSTANT: DMBIN_ONLYONE 1
+CONSTANT: DMBIN_LOWER 2
+CONSTANT: DMBIN_MIDDLE 3
+CONSTANT: DMBIN_MANUAL 4
+CONSTANT: DMBIN_ENVELOPE 5
+CONSTANT: DMBIN_ENVMANUAL 6
+CONSTANT: DMBIN_AUTO 7
+CONSTANT: DMBIN_TRACTOR 8
+CONSTANT: DMBIN_SMALLFMT 9
+CONSTANT: DMBIN_LARGEFMT 10
+CONSTANT: DMBIN_LARGECAPACITY 11
+CONSTANT: DMBIN_CASSETTE 14
+CONSTANT: DMBIN_FORMSOURCE 15
+CONSTANT: DMBIN_LAST 15
+CONSTANT: DMBIN_USER 256
+CONSTANT: DMRES_DRAFT -1
+CONSTANT: DMRES_LOW -2
+CONSTANT: DMRES_MEDIUM -3
+CONSTANT: DMRES_HIGH -4
+CONSTANT: DMCOLOR_MONOCHROME 1
+CONSTANT: DMCOLOR_COLOR 2
+CONSTANT: DMDUP_SIMPLEX 1
+CONSTANT: DMDUP_VERTICAL 2
+CONSTANT: DMDUP_HORIZONTAL 3
+CONSTANT: DMTT_BITMAP 1
+CONSTANT: DMTT_DOWNLOAD 2
+CONSTANT: DMTT_SUBDEV 3
+CONSTANT: DMTT_DOWNLOAD_OUTLINE 4
+CONSTANT: DMCOLLATE_FALSE 0
+CONSTANT: DMCOLLATE_TRUE 1
+CONSTANT: DM_SPECVERSION 800
+CONSTANT: DM_GRAYSCALE 1
+CONSTANT: DM_INTERLACED 2
+CONSTANT: DM_UPDATE 1
+CONSTANT: DM_COPY 2
+CONSTANT: DM_PROMPT 4
+CONSTANT: DM_MODIFY 8
+ALIAS: DM_IN_BUFFER DM_MODIFY
+ALIAS: DM_IN_PROMPT DM_PROMPT
+ALIAS: DM_OUT_BUFFER DM_COPY
+ALIAS: DM_OUT_DEFAULT DM_UPDATE
+CONSTANT: DM_ORIENTATION HEX: 00000001
+CONSTANT: DM_PAPERSIZE HEX: 00000002
+CONSTANT: DM_PAPERLENGTH HEX: 00000004
+CONSTANT: DM_PAPERWIDTH HEX: 00000008
+CONSTANT: DM_SCALE HEX: 00000010
+CONSTANT: DM_POSITION HEX: 00000020
+CONSTANT: DM_COPIES HEX: 00000100
+CONSTANT: DM_DEFAULTSOURCE HEX: 00000200
+CONSTANT: DM_PRINTQUALITY HEX: 00000400
+CONSTANT: DM_COLOR HEX: 00000800
+CONSTANT: DM_DUPLEX HEX: 00001000
+CONSTANT: DM_YRESOLUTION HEX: 00002000
+CONSTANT: DM_TTOPTION HEX: 00004000
+CONSTANT: DM_COLLATE HEX: 00008000
+CONSTANT: DM_FORMNAME HEX: 00010000
+CONSTANT: DM_LOGPIXELS HEX: 00020000
+CONSTANT: DM_BITSPERPEL HEX: 00040000
+CONSTANT: DM_PELSWIDTH HEX: 00080000
+CONSTANT: DM_PELSHEIGHT HEX: 00100000
+CONSTANT: DM_DISPLAYFLAGS HEX: 00200000
+CONSTANT: DM_DISPLAYFREQUENCY HEX: 00400000
+CONSTANT: DM_ICMMETHOD HEX: 00800000
+CONSTANT: DM_ICMINTENT HEX: 01000000
+CONSTANT: DM_MEDIATYPE HEX: 02000000
+CONSTANT: DM_DITHERTYPE HEX: 04000000
+CONSTANT: DM_PANNINGWIDTH HEX: 08000000
+CONSTANT: DM_PANNINGHEIGHT HEX: 10000000
+CONSTANT: DM_DISPLAYFIXEDOUTPUT HEX: 20000000
+CONSTANT: DM_DISPLAYORIENTATION HEX: 00000080
+CONSTANT: DMDO_DEFAULT HEX: 00000000
+CONSTANT: DMDO_90 HEX: 00000001
+CONSTANT: DMDO_180 HEX: 00000002
+CONSTANT: DMDO_270 HEX: 00000003
+CONSTANT: DMDFO_DEFAULT HEX: 00000000
+CONSTANT: DMDFO_STRETCH HEX: 00000001
+CONSTANT: DMDFO_CENTER HEX: 00000002
+CONSTANT: DMICMMETHOD_NONE 1
+CONSTANT: DMICMMETHOD_SYSTEM 2
+CONSTANT: DMICMMETHOD_DRIVER 3
+CONSTANT: DMICMMETHOD_DEVICE 4
+CONSTANT: DMICMMETHOD_USER 256
+CONSTANT: DMICM_SATURATE 1
+CONSTANT: DMICM_CONTRAST 2
+CONSTANT: DMICM_COLORMETRIC 3
+CONSTANT: DMICM_USER 256
+CONSTANT: DMMEDIA_STANDARD 1
+CONSTANT: DMMEDIA_TRANSPARENCY 2
+CONSTANT: DMMEDIA_GLOSSY 3
+CONSTANT: DMMEDIA_USER 256
+CONSTANT: DMDITHER_NONE 1
+CONSTANT: DMDITHER_COARSE 2
+CONSTANT: DMDITHER_FINE 3
+CONSTANT: DMDITHER_LINEART 4
+CONSTANT: DMDITHER_ERRORDIFFUSION 5
+CONSTANT: DMDITHER_RESERVED6 6
+CONSTANT: DMDITHER_RESERVED7 7
+CONSTANT: DMDITHER_RESERVED8 8
+CONSTANT: DMDITHER_RESERVED9 9
+CONSTANT: DMDITHER_GRAYSCALE 10
+CONSTANT: DMDITHER_USER 256
+CONSTANT: GDI_ERROR HEX: FFFFFFFF
+: HGDI_ERROR ( -- alien ) GDI_ERROR <alien> ; inline
+CONSTANT: TMPF_FIXED_PITCH 1
+CONSTANT: TMPF_VECTOR 2
+CONSTANT: TMPF_TRUETYPE 4
+CONSTANT: TMPF_DEVICE 8
+CONSTANT: NTM_ITALIC 1
+CONSTANT: NTM_BOLD 32
+CONSTANT: NTM_REGULAR 64
+CONSTANT: TT_POLYGON_TYPE 24
+CONSTANT: TT_PRIM_LINE 1
+CONSTANT: TT_PRIM_QSPLINE 2
+CONSTANT: TT_PRIM_CSPLINE 3 
+CONSTANT: FONTMAPPER_MAX 10
+CONSTANT: ENHMETA_STOCK_OBJECT HEX: 80000000
+CONSTANT: WGL_FONT_LINES 0
+CONSTANT: WGL_FONT_POLYGONS 1
+CONSTANT: LPD_DOUBLEBUFFER 1
+CONSTANT: LPD_STEREO 2
+CONSTANT: LPD_SUPPORT_GDI 16
+CONSTANT: LPD_SUPPORT_OPENGL 32
+CONSTANT: LPD_SHARE_DEPTH 64
+CONSTANT: LPD_SHARE_STENCIL 128
+CONSTANT: LPD_SHARE_ACCUM 256
+CONSTANT: LPD_SWAP_EXCHANGE 512
+CONSTANT: LPD_SWAP_COPY 1024
+CONSTANT: LPD_TRANSPARENT 4096
+CONSTANT: LPD_TYPE_RGBA 0
+CONSTANT: LPD_TYPE_COLORINDEX 1
+CONSTANT: WGL_SWAP_MAIN_PLANE 1
+CONSTANT: WGL_SWAP_OVERLAY1 2
+CONSTANT: WGL_SWAP_OVERLAY2 4
+CONSTANT: WGL_SWAP_OVERLAY3 8
+CONSTANT: WGL_SWAP_OVERLAY4 16
+CONSTANT: WGL_SWAP_OVERLAY5 32
+CONSTANT: WGL_SWAP_OVERLAY6 64
+CONSTANT: WGL_SWAP_OVERLAY7 128
+CONSTANT: WGL_SWAP_OVERLAY8 256
+CONSTANT: WGL_SWAP_OVERLAY9 512
+CONSTANT: WGL_SWAP_OVERLAY10 1024
+CONSTANT: WGL_SWAP_OVERLAY11 2048
+CONSTANT: WGL_SWAP_OVERLAY12 4096
+CONSTANT: WGL_SWAP_OVERLAY13 8192
+CONSTANT: WGL_SWAP_OVERLAY14 16384
+CONSTANT: WGL_SWAP_OVERLAY15 32768
+CONSTANT: WGL_SWAP_UNDERLAY1 65536
+CONSTANT: WGL_SWAP_UNDERLAY2 HEX: 20000
+CONSTANT: WGL_SWAP_UNDERLAY3 HEX: 40000
+CONSTANT: WGL_SWAP_UNDERLAY4 HEX: 80000
+CONSTANT: WGL_SWAP_UNDERLAY5 HEX: 100000
+CONSTANT: WGL_SWAP_UNDERLAY6 HEX: 200000
+CONSTANT: WGL_SWAP_UNDERLAY7 HEX: 400000
+CONSTANT: WGL_SWAP_UNDERLAY8 HEX: 800000
+CONSTANT: WGL_SWAP_UNDERLAY9 HEX: 1000000
+CONSTANT: WGL_SWAP_UNDERLAY10 HEX: 2000000
+CONSTANT: WGL_SWAP_UNDERLAY11 HEX: 4000000
+CONSTANT: WGL_SWAP_UNDERLAY12 HEX: 8000000
+CONSTANT: WGL_SWAP_UNDERLAY13 HEX: 10000000
+CONSTANT: WGL_SWAP_UNDERLAY14 HEX: 20000000
+CONSTANT: WGL_SWAP_UNDERLAY15 HEX: 40000000
+CONSTANT: AC_SRC_OVER HEX: 00
+CONSTANT: AC_SRC_ALPHA HEX: 01
+CONSTANT: AC_SRC_NO_PREMULT_ALPHA HEX: 01
+CONSTANT: AC_SRC_NO_ALPHA HEX: 02
+CONSTANT: AC_DST_NO_PREMULT_ALPHA HEX: 10
+CONSTANT: AC_DST_NO_ALPHA HEX: 20
+CONSTANT: LAYOUT_RTL 1
+CONSTANT: LAYOUT_BITMAPORIENTATIONPRESERVED 8
+CONSTANT: CS_ENABLE HEX: 00000001
+CONSTANT: CS_DISABLE HEX: 00000002
+CONSTANT: CS_DELETE_TRANSFORM HEX: 00000003
+CONSTANT: GRADIENT_FILL_RECT_H HEX: 00
+CONSTANT: GRADIENT_FILL_RECT_V HEX: 01
+CONSTANT: GRADIENT_FILL_TRIANGLE HEX: 02
+CONSTANT: GRADIENT_FILL_OP_FLAG HEX: ff
+CONSTANT: COLORMATCHTOTARGET_EMBEDED HEX: 00000001
+CONSTANT: CREATECOLORSPACE_EMBEDED HEX: 00000001
+CONSTANT: SETICMPROFILE_EMBEDED HEX: 00000001
 
-CONSTANT: DIB_RGB_COLORS 0
-CONSTANT: DIB_PAL_COLORS 1
+CONSTANT: DISPLAY_DEVICE_ATTACHED_TO_DESKTOP HEX: 00000001
+CONSTANT: DISPLAY_DEVICE_MULTI_DRIVER HEX: 00000002
+CONSTANT: DISPLAY_DEVICE_PRIMARY_DEVICE HEX: 00000004
+CONSTANT: DISPLAY_DEVICE_MIRRORING_DRIVER HEX: 00000008
+CONSTANT: DISPLAY_DEVICE_VGA_COMPATIBLE HEX: 00000010
+CONSTANT: DISPLAY_DEVICE_REMOVABLE HEX: 00000020
+CONSTANT: DISPLAY_DEVICE_MODESPRUNED HEX: 08000000
+
+CONSTANT: NTM_NONNEGATIVE_AC HEX: 00010000
+CONSTANT: NTM_PS_OPENTYPE HEX: 00020000
+CONSTANT: NTM_TT_OPENTYPE HEX: 00040000
+CONSTANT: NTM_MULTIPLEMASTER HEX: 00080000
+CONSTANT: NTM_TYPE1 HEX: 00100000
+CONSTANT: NTM_DSIG HEX: 00200000
+
+CONSTANT: GGI_MARK_NONEXISTING_GLYPHS 1
 
 LIBRARY: gdi32
 
+! FUNCTION: AbortDoc
 ! FUNCTION: AbortPath
 ! FUNCTION: AddFontMemResourceEx
 ! FUNCTION: AddFontResourceA
@@ -100,7 +1335,8 @@ FUNCTION: HBITMAP CreateDIBSection ( HDC hdc, BITMAPINFO* pbmi, UINT iUsage, voi
 ! FUNCTION: CreateFontIndirectExA
 ! FUNCTION: CreateFontIndirectExW
 ! FUNCTION: CreateFontIndirectW
-! FUNCTION: CreateFontW
+FUNCTION: HFONT CreateFontW ( int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet, DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality, DWORD fdwPitchAndFamily, LPCTSTR lpszFace ) ;
+ALIAS: CreateFont CreateFontW
 ! FUNCTION: CreateHalftonePalette
 ! FUNCTION: CreateHatchBrush
 ! FUNCTION: CreateICA
@@ -118,7 +1354,7 @@ FUNCTION: HRGN CreateRectRgn ( int x, int y, int w, int h ) ;
 ! FUNCTION: CreateRoundRectRgn
 ! FUNCTION: CreateScalableFontResourceA
 ! FUNCTION: CreateScalableFontResourceW
-! FUNCTION: CreateSolidBrush
+FUNCTION: HBRUSH CreateSolidBrush ( COLORREF colorref ) ;
 ! FUNCTION: DdEntry0
 ! FUNCTION: DdEntry1
 ! FUNCTION: DdEntry10
@@ -178,9 +1414,11 @@ FUNCTION: HRGN CreateRectRgn ( int x, int y, int w, int h ) ;
 ! FUNCTION: DdEntry9
 ! FUNCTION: DeleteColorSpace
 FUNCTION: BOOL DeleteDC ( HDC hdc ) ;
+DESTRUCTOR: DeleteDC
 ! FUNCTION: DeleteEnhMetaFile
 ! FUNCTION: DeleteMetaFile
 FUNCTION: BOOL DeleteObject ( HGDIOBJ hObject ) ;
+DESTRUCTOR: DeleteObject
 ! FUNCTION: DescribePixelFormat
 ! FUNCTION: DeviceCapabilitiesExA
 ! FUNCTION: DeviceCapabilitiesExW
@@ -260,8 +1498,10 @@ FUNCTION: BOOL DeleteObject ( HGDIOBJ hObject ) ;
 ! FUNCTION: ExtFloodFill
 ! FUNCTION: ExtSelectClipRgn
 ! FUNCTION: ExtTextOutA
-! FUNCTION: ExtTextOutW
+FUNCTION: BOOL ExtTextOutW ( HDC hdc, int X, int Y, UINT fuOptions, RECT* lprc, LPCTSTR lpString, UINT cbCount, INT* lpDx ) ;
+ALIAS: ExtTextOut ExtTextOutW
 ! FUNCTION: FillPath
+FUNCTION: int FillRect ( HDC hDC, RECT* lprc, HBRUSH hbr ) ;
 ! FUNCTION: FillRgn
 ! FUNCTION: FixBrushOrgEx
 ! FUNCTION: FlattenPath
@@ -484,7 +1724,8 @@ FUNCTION: HGDIOBJ GetStockObject ( int fnObject ) ;
 ! FUNCTION: GetTextFaceAliasW
 ! FUNCTION: GetTextFaceW
 ! FUNCTION: GetTextMetricsA
-! FUNCTION: GetTextMetricsW
+FUNCTION: BOOL GetTextMetricsW ( HDC hdc, LPTEXTMETRIC lptm ) ;
+ALIAS: GetTextMetrics GetTextMetricsW
 ! FUNCTION: GetTransform
 ! FUNCTION: GetViewportExtEx
 ! FUNCTION: GetViewportOrgEx
@@ -539,7 +1780,7 @@ FUNCTION: HGDIOBJ GetStockObject ( int fnObject ) ;
 ! FUNCTION: PtVisible
 ! FUNCTION: QueryFontAssocStatus
 ! FUNCTION: RealizePalette
-! FUNCTION: Rectangle
+FUNCTION: BOOL Rectangle ( HDC hdc, int x, int y, int w, int h ) ;
 ! FUNCTION: RectInRegion
 ! FUNCTION: RectVisible
 ! FUNCTION: RemoveFontMemResourceEx
@@ -567,15 +1808,15 @@ FUNCTION: HGDIOBJ SelectObject ( HDC hdc, HGDIOBJ hgdiobj ) ;
 ! FUNCTION: SetBitmapAttributes
 ! FUNCTION: SetBitmapBits
 ! FUNCTION: SetBitmapDimensionEx
-! FUNCTION: SetBkColor
+FUNCTION: COLORREF SetBkColor ( HDC hdc, COLORREF color ) ;
 ! FUNCTION: SetBkMode
 ! FUNCTION: SetBoundsRect
 ! FUNCTION: SetBrushAttributes
 ! FUNCTION: SetBrushOrgEx
 ! FUNCTION: SetColorAdjustment
 ! FUNCTION: SetColorSpace
-! FUNCTION: SetDCBrushColor
-! FUNCTION: SetDCPenColor
+FUNCTION: COLORREF SetDCBrushColor ( HDC hdc, COLORREF color ) ;
+FUNCTION: COLORREF SetDCPenColor ( HDC hdc, COLORREF color ) ;
 ! FUNCTION: SetDeviceGammaRamp
 ! FUNCTION: SetDIBColorTable
 ! FUNCTION: SetDIBits
@@ -606,7 +1847,8 @@ FUNCTION: BOOL SetPixelFormat ( HDC hDC, int iPixelFormat, PFD* ppfd ) ;
 ! FUNCTION: SetSystemPaletteUse
 ! FUNCTION: SetTextAlign
 ! FUNCTION: SetTextCharacterExtra
-! FUNCTION: SetTextColor
+FUNCTION: COLORREF SetTextColor ( HDC hdc, COLORREF crColor ) ;
+! FUNCTION: SetTextColor ( HDC hDC, 
 ! FUNCTION: SetTextJustification
 ! FUNCTION: SetViewportExtEx
 ! FUNCTION: SetViewportOrgEx
diff --git a/basis/windows/offscreen/authors.txt b/basis/windows/offscreen/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/basis/windows/offscreen/offscreen-tests.factor b/basis/windows/offscreen/offscreen-tests.factor
new file mode 100755 (executable)
index 0000000..5827397
--- /dev/null
@@ -0,0 +1,5 @@
+IN: windows.offscreen.tests\r
+USING: windows.offscreen effects tools.test kernel images ;\r
+\r
+{ 1 1 } [ [ [ ] make-bitmap-image ] with-memory-dc ] must-infer-as\r
+[ t ] [ [ { 10 10 } swap [ ] make-bitmap-image ] with-memory-dc image? ] unit-test\r
diff --git a/basis/windows/offscreen/offscreen.factor b/basis/windows/offscreen/offscreen.factor
new file mode 100755 (executable)
index 0000000..6e65958
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2009 Joe Groff, Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.c-types kernel combinators sequences
+math windows.gdi32 windows.types images destructors
+accessors fry locals ;
+IN: windows.offscreen
+
+: (bitmap-info) ( dim -- BITMAPINFO )
+    "BITMAPINFO" <c-object> [
+        BITMAPINFO-bmiHeader {
+            [ nip "BITMAPINFOHEADER" heap-size swap set-BITMAPINFOHEADER-biSize ]
+            [ [ first ] dip set-BITMAPINFOHEADER-biWidth ]
+            [ [ second ] dip set-BITMAPINFOHEADER-biHeight ]
+            [ nip 1 swap set-BITMAPINFOHEADER-biPlanes ]
+            [ nip 32 swap set-BITMAPINFOHEADER-biBitCount ]
+            [ nip BI_RGB swap set-BITMAPINFOHEADER-biCompression ]
+            [ [ first2 * 4 * ] dip set-BITMAPINFOHEADER-biSizeImage ]
+            [ nip 72 swap set-BITMAPINFOHEADER-biXPelsPerMeter ]
+            [ nip 72 swap set-BITMAPINFOHEADER-biYPelsPerMeter ]
+            [ nip 0 swap set-BITMAPINFOHEADER-biClrUsed ]
+            [ nip 0 swap set-BITMAPINFOHEADER-biClrImportant ]
+        } 2cleave
+    ] keep ;
+
+: make-bitmap ( dim dc -- hBitmap bits )
+    [ nip ]
+    [
+        swap (bitmap-info) DIB_RGB_COLORS f <void*>
+        [ f 0 CreateDIBSection ] keep *void*
+    ] 2bi
+    [ [ SelectObject drop ] keep ] dip ;
+
+: make-offscreen-dc-and-bitmap ( dim -- dc hBitmap bits )
+    [ f CreateCompatibleDC ] dip over make-bitmap ;
+
+: bitmap>byte-array ( bits dim -- byte-array )
+    product 4 * memory>byte-array ;
+
+: bitmap>image ( bits dim -- image )
+    [ bitmap>byte-array ] keep
+    <image>
+        swap >>dim
+        swap >>bitmap
+        BGRX >>component-order
+        t >>upside-down? ;
+
+: with-memory-dc ( quot: ( hDC -- ) -- )
+    [ [ f CreateCompatibleDC &DeleteDC ] dip call ] with-destructors ; inline
+
+:: make-bitmap-image ( dim dc quot -- image )
+    dim dc make-bitmap [ &DeleteObject drop ] dip
+    quot dip
+    dim bitmap>image ; inline
\ No newline at end of file
diff --git a/basis/windows/offscreen/summary.txt b/basis/windows/offscreen/summary.txt
new file mode 100755 (executable)
index 0000000..dd70405
--- /dev/null
@@ -0,0 +1 @@
+Utility words for memory DCs and bitmaps\r
diff --git a/basis/windows/offscreen/tags.txt b/basis/windows/offscreen/tags.txt
new file mode 100755 (executable)
index 0000000..6abe115
--- /dev/null
@@ -0,0 +1 @@
+unportable\r
index ee74e47feaa223e86b7c1d2ba3dbb8417c4df412..20bae06f30d82fb872b9291c1ae81659bc6c2bf3 100755 (executable)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.syntax namespaces kernel words ;
+USING: alien alien.c-types alien.syntax namespaces kernel words
+sequences math math.bitwise math.vectors colors ;
 IN: windows.types
 
 TYPEDEF: char                CHAR
@@ -244,14 +245,14 @@ C-STRUCT: RECT
     { "LONG" "right" }
     { "LONG" "bottom" } ;
 
-C-STRUCT: PAINTSTRUCT
-    { "HDC" " hdc" }
-    { "BOOL" "fErase" }
-    { "RECT" "rcPaint" }
-    { "BOOL" "fRestore" }
-    { "BOOL" "fIncUpdate" }
-    { "BYTE[32]" "rgbReserved" }
-;
+C-STRUCT: PAINTSTRUCT
+    { "HDC" " hdc" }
+    { "BOOL" "fErase" }
+    { "RECT" "rcPaint" }
+    { "BOOL" "fRestore" }
+    { "BOOL" "fIncUpdate" }
+    { "BYTE[32]" "rgbReserved" }
+;
 
 C-STRUCT: BITMAPINFOHEADER
     { "DWORD"  "biSize" }
@@ -283,6 +284,10 @@ C-STRUCT: POINT
     { "LONG" "x" }
     { "LONG" "y" } ; 
 
+C-STRUCT: SIZE
+    { "LONG" "cx" }
+    { "LONG" "cy" } ; 
+
 C-STRUCT: MSG
     { "HWND" "hWnd" }
     { "UINT" "message" }
@@ -327,6 +332,14 @@ C-STRUCT: RECT
     { "LONG" "right" }
     { "LONG" "bottom" } ;
 
+: <RECT> ( loc dim -- RECT )
+    over v+
+    "RECT" <c-object>
+    over first over set-RECT-right
+    swap second over set-RECT-bottom
+    over first over set-RECT-left
+    swap second over set-RECT-top ;
+
 TYPEDEF: RECT* PRECT
 TYPEDEF: RECT* LPRECT
 TYPEDEF: PIXELFORMATDESCRIPTOR PFD
@@ -363,3 +376,36 @@ C-STRUCT: ACCEL
     { "WORD" "key" }
     { "WORD" "cmd" } ;
 TYPEDEF: ACCEL* LPACCEL
+
+TYPEDEF: DWORD COLORREF
+TYPEDEF: DWORD* LPCOLORREF
+
+: RGB ( r g b -- COLORREF )
+    { 16 8 0 } bitfield ; inline
+
+: color>RGB ( color -- COLORREF )
+    >rgba-components drop [ 255 * >integer ] tri@ RGB ;
+
+C-STRUCT: TEXTMETRICW
+    { "LONG" "tmHeight" }
+    { "LONG" "tmAscent" }
+    { "LONG" "tmDescent" }
+    { "LONG" "tmInternalLeading" }
+    { "LONG" "tmExternalLeading" }
+    { "LONG" "tmAveCharWidth" }
+    { "LONG" "tmMaxCharWidth" }
+    { "LONG" "tmWeight" }
+    { "LONG" "tmOverhang" }
+    { "LONG" "tmDigitizedAspectX" }
+    { "LONG" "tmDigitizedAspectY" }
+    { "WCHAR" "tmFirstChar" }
+    { "WCHAR" "tmLastChar" }
+    { "WCHAR" "tmDefaultChar" }
+    { "WCHAR" "tmBreakChar" }
+    { "BYTE" "tmItalic" }
+    { "BYTE" "tmUnderlined" }
+    { "BYTE" "tmStruckOut" }
+    { "BYTE" "tmPitchAndFamily" }
+    { "BYTE" "tmCharSet" } ;
+
+TYPEDEF: TEXTMETRICW* LPTEXTMETRIC
diff --git a/basis/windows/uniscribe/authors.txt b/basis/windows/uniscribe/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/basis/windows/uniscribe/summary.txt b/basis/windows/uniscribe/summary.txt
new file mode 100755 (executable)
index 0000000..7b71cf1
--- /dev/null
@@ -0,0 +1 @@
+High-level wrapper around Uniscribe binding\r
diff --git a/basis/windows/uniscribe/tags.txt b/basis/windows/uniscribe/tags.txt
new file mode 100755 (executable)
index 0000000..6abe115
--- /dev/null
@@ -0,0 +1 @@
+unportable\r
diff --git a/basis/windows/uniscribe/uniscribe.factor b/basis/windows/uniscribe/uniscribe.factor
new file mode 100755 (executable)
index 0000000..fb0c134
--- /dev/null
@@ -0,0 +1,115 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel assocs math sequences fry io.encodings.string
+io.encodings.utf16n accessors arrays combinators destructors
+cache namespaces init fonts alien.c-types windows windows.usp10
+windows.offscreen windows.gdi32 windows.ole32 windows.types
+windows.fonts opengl.textures locals ;
+IN: windows.uniscribe
+
+TUPLE: script-string font string metrics ssa size image disposed ;
+
+: line-offset>x ( n script-string -- x )
+    2dup string>> length = [
+        ssa>> ! ssa
+        swap 1- ! icp
+        TRUE ! fTrailing
+    ] [
+        ssa>>
+        swap ! icp
+        FALSE ! fTrailing
+    ] if
+    0 <int> [ ScriptStringCPtoX ole32-error ] keep *int ;
+
+: x>line-offset ( x script-string -- n trailing )
+    ssa>> ! ssa
+    swap ! iX
+    0 <int> ! pCh
+    0 <int> ! piTrailing
+    [ ScriptStringXtoCP ole32-error ] 2keep [ *int ] bi@ ;
+
+<PRIVATE
+
+: make-script-string ( dc string -- script-string )
+    dup selection? [ string>> ] when
+    [ utf16n encode ] ! pString
+    [ length ] bi ! cString
+    dup 1.5 * 16 + >integer ! cGlyphs -- MSDN says this is "recommended size"
+    -1 ! iCharset -- Unicode
+    SSA_GLYPHS ! dwFlags
+    0 ! iReqWidth
+    f ! psControl
+    f ! psState
+    f ! piDx
+    f ! pTabdef
+    f ! pbInClass
+    f <void*> ! pssa
+    [ ScriptStringAnalyse ] keep
+    [ ole32-error ] [ |ScriptStringFree *void* ] bi* ;
+
+: set-dc-colors ( dc font -- )
+    [ background>> color>RGB SetBkColor drop ]
+    [ foreground>> color>RGB SetTextColor drop ] 2bi ;
+
+: selection-start/end ( script-string -- iMinSel iMaxSel )
+    string>> dup selection? [ [ start>> ] [ end>> ] bi ] [ drop 0 0 ] if ;
+
+: (draw-script-string) ( script-string -- )
+    [
+        ssa>> ! ssa
+        0 ! iX
+        0 ! iY
+        ETO_OPAQUE ! uOptions
+    ]
+    [ [ { 0 0 } ] dip size>> <RECT> ]
+    [ selection-start/end ] tri
+    ! iMinSel
+    ! iMaxSel
+    FALSE ! fDisabled
+    ScriptStringOut ole32-error ;
+
+: draw-script-string ( dc script-string -- )
+    [ font>> set-dc-colors ] keep (draw-script-string) ;
+
+:: make-script-string-image ( dc script-string -- image )
+    script-string size>> dc
+    [ dc script-string draw-script-string ] make-bitmap-image ;
+
+: set-dc-font ( dc font -- )
+    cache-font SelectObject win32-error=0/f ;
+
+: script-string-size ( script-string -- dim )
+    ssa>> ScriptString_pSize
+    dup win32-error=0/f
+    [ SIZE-cx ] [ SIZE-cy ] bi 2array ;
+
+: dc-metrics ( dc -- metrics )
+    "TEXTMETRICW" <c-object>
+    [ GetTextMetrics drop ] keep
+    TEXTMETRIC>metrics ;
+
+: <script-string> ( font string -- script-string )
+    [ script-string new ] 2dip
+        [ >>font ] [ >>string ] bi*
+    [
+        {
+            [ over font>> set-dc-font ]
+            [ dc-metrics >>metrics ]
+            [ over string>> make-script-string >>ssa ]
+            [ drop dup script-string-size >>size ]
+            [ over make-script-string-image >>image ]
+        } cleave
+    ] with-memory-dc ;
+
+PRIVATE>
+
+M: script-string dispose*
+    ssa>> <void*> ScriptStringFree ole32-error ;
+
+SYMBOL: cached-script-strings
+
+: cached-script-string ( font string -- script-string )
+    cached-script-strings get-global [ <script-string> ] 2cache ;
+
+[ <cache-assoc> cached-script-strings set-global ]
+"windows.uniscribe" add-init-hook
index 64e5a60019e10f2fddb85f07aa7086eff1a4ef3b..50fa98996c7fe3fee90c7ba8f858002a87379a0d 100755 (executable)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien.syntax ;
+USING: alien.syntax alien.destructors ;
 IN: windows.usp10
 
 LIBRARY: usp10
@@ -262,6 +262,8 @@ FUNCTION: HRESULT ScriptStringFree (
     SCRIPT_STRING_ANALYSIS* pssa
 ) ;
 
+DESTRUCTOR: ScriptStringFree
+
 FUNCTION: SIZE* ScriptString_pSize ( SCRIPT_STRING_ANALYSIS ssa ) ;
 
 FUNCTION: int* ScriptString_pcOutChars ( SCRIPT_STRING_ANALYSIS ssa ) ;
old mode 100644 (file)
new mode 100755 (executable)
index 44db355..902b1be
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.syntax alien.c-types alien.strings arrays
-combinators kernel math namespaces parser prettyprint sequences
+combinators kernel math namespaces parser sequences
 windows.errors windows.types windows.kernel32 words
 io.encodings.utf16n ;
 IN: windows
index 58957ba8e74265239d2e2346fd839a267c1553f6..482d50ab5f31dc089bf5ef2acb2ea73d73bd22c9 100644 (file)
@@ -30,7 +30,7 @@ SYMBOL: line-ideal
     { [ lines>> car 1list? ] [ top-fits? ] } 1|| ;
 
 :: min-by ( seq quot -- elt )
-    f 1.0/0.0 seq [| key value new |
+    f 1/0. seq [| key value new |
         new quot call :> newvalue
         newvalue value < [ new newvalue ] [ key value ] if
     ] each drop ; inline
index 9619ae0bee3f1e252a04f94a81fa8bd3256947a0..8085907bef7c8e2fb950fd60738134376033d3d6 100644 (file)
@@ -6,10 +6,10 @@ arrays fry ;
 IN: x11.windows
 
 : create-window-mask ( -- n )
-    { CWBackPixel CWBorderPixel CWColormap CWEventMask } flags ;
+    { CWColormap CWEventMask } flags ;
 
 : create-colormap ( visinfo -- colormap )
-    dpy get root get rot XVisualInfo-visual AllocNone
+    [ dpy get root get ] dip XVisualInfo-visual AllocNone
     XCreateColormap ;
 
 : event-mask ( -- n )
@@ -29,8 +29,6 @@ IN: x11.windows
 
 : window-attributes ( visinfo -- attributes )
     "XSetWindowAttributes" <c-object>
-    0 over set-XSetWindowAttributes-background_pixel
-    0 over set-XSetWindowAttributes-border_pixel
     [ [ create-colormap ] dip set-XSetWindowAttributes-colormap ] keep
     event-mask over set-XSetWindowAttributes-event_mask ;
 
index 71c0ff728276e0787cbda7cfcb9e0b4656368f1e..4f4a20b1cb83326b5706914cdb913f14055e1d0b 100644 (file)
@@ -1 +1,2 @@
+extensions
 syntax
diff --git a/build-support/dlls.txt b/build-support/dlls.txt
deleted file mode 100644 (file)
index 97d0cf6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-libcairo-2.dll
-libgio-2.0-0.dll
-libglib-2.0-0.dll
-libgmodule-2.0-0.dll
-libgobject-2.0-0.dll
-libgthread-2.0-0.dll
-libpango-1.0-0.dll
-libpangocairo-1.0-0.dll
-libpangowin32-1.0-0.dll
-libpng12-0.dll
-libtiff3.dll
-zlib1.dll
index 61450dacb48121cb9f2128172632eccad610cc72..53aab9ad045c0e5c6628243cac88a6b6ab06d1be 100755 (executable)
@@ -139,7 +139,6 @@ check_library_exists() {
 }
 
 check_X11_libraries() {
-    check_library_exists GLU
     check_library_exists GL
     check_library_exists X11
     check_library_exists pango-1.0
@@ -199,7 +198,7 @@ find_architecture() {
 
 write_test_program() {
     echo "#include <stdio.h>" > $C_WORD.c
-    echo "int main(){printf(\"%d\", 8*sizeof(void*)); return 0; }" >> $C_WORD.c
+    echo "int main(){printf(\"%ld\", 8*sizeof(void*)); return 0; }" >> $C_WORD.c
 }
 
 c_find_word_size() {
@@ -445,16 +444,6 @@ get_url() {
     check_ret $DOWNLOADER
 }
 
-maybe_download_dlls() {
-    if [[ $OS == winnt ]] ; then
-       for file in `cat build-support/dlls.txt`; do
-           get_url http://factorcode.org/dlls/$file
-            chmod 777 *.dll
-            check_ret chmod
-       done
-    fi
-}
-
 get_config_info() {
     find_build_info
     check_installed_programs
@@ -472,7 +461,6 @@ install() {
     cd_factor
     make_factor
     get_boot_image
-    maybe_download_dlls
     bootstrap
 }
 
@@ -502,7 +490,7 @@ make_boot_image() {
 }
 
 install_build_system_apt() {
-    sudo apt-get --yes install libc6-dev libpango1.0-dev libx11-dev xorg-dev glutg3-dev wget git-core git-doc rlwrap gcc make
+    sudo apt-get --yes install libc6-dev libpango1.0-dev libx11-dev xorg-dev wget git-core git-doc rlwrap gcc make
     check_ret sudo
 }
 
@@ -547,7 +535,6 @@ case "$1" in
     update) update; update_bootstrap ;;
     bootstrap) get_config_info; bootstrap ;;
     report) find_build_info ;;
-    dlls) get_config_info; maybe_download_dlls;;
     net-bootstrap) get_config_info; update_boot_images; bootstrap ;;
     make-target) ECHO=false; find_build_info; echo $MAKE_TARGET ;;
     *) usage ;;
index 57dc298c00c19de11fe8e4d385a126cedf4e4724..d3265f31bbc245779b7fe6265207b7203ce0d5f8 100644 (file)
@@ -1,6 +1,6 @@
 USING: accessors alien alien.accessors alien.syntax byte-arrays arrays
 kernel kernel.private namespaces tools.test sequences libc math
-system prettyprint layouts alien.libraries ;
+system prettyprint layouts alien.libraries sets ;
 IN: alien.tests
 
 [ t ] [ -1 <alien> alien-address 0 > ] unit-test
@@ -86,3 +86,5 @@ f initialize-test set-global
 [ ] [ initialize-test get BAD-ALIEN >>alien drop ] unit-test
 
 [ 7575 ] [ initialize-test [ 7575 ] initialize-alien ] unit-test
+
+[ V{ BAD-ALIEN } ] [ { BAD-ALIEN BAD-ALIEN BAD-ALIEN } prune ] unit-test
\ No newline at end of file
index ea0cb9208e19378ac519e15ea7dce845fecc3a04..ec38e3be5b8b5b9ff821339012ff6af25414a446 100644 (file)
@@ -49,6 +49,8 @@ M: alien equal?
         2drop f
     ] if ;
 
+M: simple-alien hashcode* nip dup expired>> [ drop 1234 ] [ alien-address ] if ;
+
 ERROR: alien-callback-error ;
 
 : alien-callback ( return parameters abi quot -- alien )
index e3803f21500b14ddf6841862fb196c195ff26221..4466bd9bfe00aab5e50e3e90cc2e0150da143dde 100644 (file)
@@ -510,6 +510,7 @@ tuple
     { "fputc" "io.streams.c" (( ch alien -- )) }
     { "fwrite" "io.streams.c" (( string alien -- )) }
     { "fflush" "io.streams.c" (( alien -- )) }
+    { "fseek" "io.streams.c" (( alien offset whence -- )) }
     { "fclose" "io.streams.c" (( alien -- )) }
     { "<wrapper>" "kernel" (( obj -- wrapper )) }
     { "(clone)" "kernel" (( obj -- newobj )) }
index 6e6812e25c3ca3e1c098bc75bfc6f49530ed3489..a0b349be51b9e2c2731297f450e599d2d8cd29bb 100644 (file)
@@ -62,6 +62,7 @@ IN: bootstrap.syntax
     "W{"
     "["
     "\\"
+    "M\\"
     "]"
     "delimiter"
     "f"
index 0e4a3b56fde4218ae824fa275becf8547b513e39..f95d66fd05c02731d556752b4df57611cd72d3bb 100644 (file)
@@ -55,7 +55,7 @@ M: anonymous-intersection (flatten-class)
     [
         builtins get sift [ (flatten-class) ] each
     ] [
-        unclip [ assoc-intersect ] reduce [ swap set ] assoc-each
+        [ ] [ assoc-intersect ] map-reduce [ swap set ] assoc-each
     ] if-empty ;
 
 M: anonymous-complement (flatten-class)
index eded33beed3788bbd69e21493204f151b7349229..ab8ba398cda09ad22208424f97005a127b423977 100644 (file)
@@ -174,8 +174,7 @@ GENERIC: update-methods ( class seq -- )
         [ forget ] [ drop ] if
     ] [ 2drop ] if ;
 
-: forget-methods ( class -- )
-    [ implementors ] [ [ swap 2array ] curry ] bi map forget-all ;
+GENERIC: forget-methods ( class -- )
 
 GENERIC: class-forgotten ( use class -- )
 
index 32cab6590446182decc73d11e81472cd75c3d39e..d76faddf15fdd9537e1eb9b16a00a1af7cbead90 100644 (file)
@@ -92,7 +92,7 @@ ARTICLE: "tuple-constructors" "Tuple constructors"
 $nl
 "Constructors play a part in enforcing the invariant that slot values must always match slot declarations. The " { $link new } " word fills in the tuple with initial values, and " { $link boa } " ensures that the values on the stack match the corresponding slot declarations. See " { $link "tuple-declarations" } "."
 $nl
-"All tuple construction should be done through constructor words, and construction primitives should be encapsulated and never called outside of the vocabulary where the class is defined, because this encourages looser coupling. For example, a constructor word could be changed to use memoization instead of always constructing a new instance, or it could be changed to construt a different class, without breaking callers."
+"All tuple construction should be done through constructor words, and construction primitives should be encapsulated and never called outside of the vocabulary where the class is defined, because this encourages looser coupling. For example, a constructor word could be changed to use memoization instead of always constructing a new instance, or it could be changed to construct a different class, without breaking callers."
 $nl
 "Examples of constructors:"
 { $code
@@ -220,13 +220,13 @@ ARTICLE: "tuple-examples" "Tuple examples"
     "    <employee> \"project manager\" >>position ;" }
 "An alternative strategy is to define the most general BOA constructor first:"
 { $code
-    ": <employee> ( name position -- person )"
+    ": <employee> ( name position -- employee )"
     "    40000 employee boa ;"
 }
 "Now we can define more specific constructors:"
 { $code
-    ": <manager> ( name -- person )"
-    "    \"manager\" <person> ;" }
+    ": <manager> ( name -- employee )"
+    "    \"manager\" <employee> ;" }
 "An example using reader words:"
 { $code
     "TUPLE: check to amount number ;"
@@ -256,7 +256,7 @@ ARTICLE: "tuple-examples" "Tuple examples"
     ": next-position ( role -- newrole )"
     "    positions [ index 1+ ] keep nth ;"
     ""
-    ": promote ( person -- person )"
+    ": promote ( employee -- employee )"
     "    [ 1.2 * ] change-salary"
     "    [ next-position ] change-position ;"
 }
index fa2df4e3121c18507b42b460f81209e763cb763f..75d733b213213c7d22e35224a62a35c4bd13943c 100644 (file)
@@ -133,7 +133,7 @@ M: integer forget-robustness-generic ;
 [
     [ ] [ \ forget-robustness-generic forget ] unit-test
     [ ] [ \ forget-robustness forget ] unit-test
-    [ ] [ { forget-robustness forget-robustness-generic } forget ] unit-test
+    [ ] [ M\ forget-robustness forget-robustness-generic forget ] unit-test
 ] with-compilation-unit
 
 ! rapido found this one
@@ -559,7 +559,7 @@ DEFER: subclass-reset-test-3
 
 GENERIC: break-me ( obj -- )
 
-[ ] [ [ { integer break-me } forget ] with-compilation-unit ] unit-test
+[ ] [ [ M\ integer break-me forget ] with-compilation-unit ] unit-test
 
 [ ] [ "IN: classes.tuple.tests TUPLE: subclass-reset-test ;" <string-reader> "subclass-reset-test" parse-stream drop ] unit-test
 [ ] [ "IN: classes.tuple.tests TUPLE: subclass-reset-test-1 < subclass-reset-test ;" eval ] unit-test
index cc502140ad18db3284fab98ee088b2144ab7f20f..9c96fe34c9d1f75badaba22d20e92676198237c9 100644 (file)
@@ -4,46 +4,313 @@ math assocs sequences sequences.private combinators.private
 effects words ;
 IN: combinators
 
+ARTICLE: "cleave-shuffle-equivalence" "Expressing shuffle words with cleave combinators"
+"Cleave combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to cleave combinators are discussed in the documentation for " { $link bi } ", " { $link 2bi } ", " { $link 3bi } ", " { $link tri } ", " { $link 2tri } " and " { $link 3tri } "."
+$nl
+"Certain shuffle words can also be expressed in terms of the cleave combinators. Internalizing such identities can help with understanding and writing code using cleave combinators:"
+{ $code
+    ": keep  [ ] bi ;"
+    ": 2keep [ ] 2bi ;"
+    ": 3keep [ ] 3bi ;"
+    ""
+    ": dup   [ ] [ ] bi ;"
+    ": 2dup  [ ] [ ] 2bi ;"
+    ": 3dup  [ ] [ ] 3bi ;"
+    ""
+    ": tuck  [ nip ] [ ] 2bi ;"
+    ": swap  [ nip ] [ drop ] 2bi ;"
+    ""
+    ": over  [ ] [ drop ] 2bi ;"
+    ": pick  [ ] [ 2drop ] 3bi ;"
+    ": 2over [ ] [ drop ] 3bi ;"
+} ;
+
+ARTICLE: "cleave-combinators" "Cleave combinators"
+"The cleave combinators apply multiple quotations to a single value."
+$nl
+"Two quotations:"
+{ $subsection bi }
+{ $subsection 2bi }
+{ $subsection 3bi }
+"Three quotations:"
+{ $subsection tri }
+{ $subsection 2tri }
+{ $subsection 3tri }
+"An array of quotations:"
+{ $subsection cleave }
+{ $subsection 2cleave }
+{ $subsection 3cleave }
+"Technically, the cleave combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on the top of the stack can be written in one of two ways:"
+{ $code
+    "! First alternative; uses keep"
+    "[ 1 + ] keep"
+    "[ 1 - ] keep"
+    "2 *"
+    "! Second alternative: uses tri"
+    "[ 1 + ]"
+    "[ 1 - ]"
+    "[ 2 * ] tri"
+}
+"The latter is more aesthetically pleasing than the former."
+{ $subsection "cleave-shuffle-equivalence" } ;
+
+ARTICLE: "spread-shuffle-equivalence" "Expressing shuffle words with spread combinators"
+"Spread combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to spread combinators are discussed in the documentation for " { $link bi* } ", " { $link 2bi* } ", " { $link tri* } ", and " { $link 2tri* } "."
+$nl
+"Certain shuffle words can also be expressed in terms of the spread combinators. Internalizing such identities can help with understanding and writing code using spread combinators:"
+{ $code
+    ": dip   [ ] bi* ;"
+    ": 2dip  [ ] [ ] tri* ;"
+    ""
+    ": slip  [ call ] [ ] bi* ;"
+    ": 2slip [ call ] [ ] [ ] tri* ;"
+    ""
+    ": nip   [ drop ] [ ] bi* ;"
+    ": 2nip  [ drop ] [ drop ] [ ] tri* ;"
+    ""
+    ": rot"
+    "    [ [ drop ] [      ] [ drop ] tri* ]"
+    "    [ [ drop ] [ drop ] [      ] tri* ]"
+    "    [ [      ] [ drop ] [ drop ] tri* ]"
+    "    3tri ;"
+    ""
+    ": -rot"
+    "    [ [ drop ] [ drop ] [      ] tri* ]"
+    "    [ [      ] [ drop ] [ drop ] tri* ]"
+    "    [ [ drop ] [      ] [ drop ] tri* ]"
+    "    3tri ;"
+    ""
+    ": spin"
+    "    [ [ drop ] [ drop ] [      ] tri* ]"
+    "    [ [ drop ] [      ] [ drop ] tri* ]"
+    "    [ [      ] [ drop ] [ drop ] tri* ]"
+    "    3tri ;"
+} ;
+
+ARTICLE: "spread-combinators" "Spread combinators"
+"The spread combinators apply multiple quotations to multiple values. The " { $snippet "*" } " suffix signifies spreading."
+$nl
+"Two quotations:"
+{ $subsection bi* }
+{ $subsection 2bi* }
+"Three quotations:"
+{ $subsection tri* }
+{ $subsection 2tri* }
+"An array of quotations:"
+{ $subsection spread }
+"Technically, the spread combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on three related values can be written in one of two ways:"
+{ $code
+    "! First alternative; uses dip"
+    "[ [ 1 + ] dip 1 - ] dip 2 *"
+    "! Second alternative: uses tri*"
+    "[ 1 + ] [ 1 - ] [ 2 * ] tri*"
+}
+"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "."
+{ $subsection "spread-shuffle-equivalence" } ;
+
+ARTICLE: "apply-combinators" "Apply combinators"
+"The apply combinators apply a single quotation to multiple values. The " { $snippet "@" } " suffix signifies application."
+$nl
+"Two quotations:"
+{ $subsection bi@ }
+{ $subsection 2bi@ }
+"Three quotations:"
+{ $subsection tri@ }
+{ $subsection 2tri@ }
+"A pair of utility words built from " { $link bi@ } ":"
+{ $subsection both? }
+{ $subsection either? } ;
+
+ARTICLE: "slip-keep-combinators" "Retain stack combinators"
+"Sometimes an additional storage area is needed to hold objects. The " { $emphasis "retain stack" } " is an auxilliary stack for this purpose. Objects can be moved between the data and retain stacks using a set of combinators."
+$nl
+"The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:"
+{ $subsection dip }
+{ $subsection 2dip }
+{ $subsection 3dip }
+{ $subsection 4dip }
+"The slip combinators invoke a quotation further down on the stack. They are most useful for implementing other combinators:"
+{ $subsection slip }
+{ $subsection 2slip }
+{ $subsection 3slip }
+"The keep combinators invoke a quotation which takes a number of values off the stack, and then they restore those values:"
+{ $subsection keep }
+{ $subsection 2keep }
+{ $subsection 3keep } ;
+
+ARTICLE: "curried-dataflow" "Curried dataflow combinators"
+"Curried cleave combinators:"
+{ $subsection bi-curry }
+{ $subsection tri-curry }
+"Curried spread combinators:"
+{ $subsection bi-curry* }
+{ $subsection tri-curry* }
+"Curried apply combinators:"
+{ $subsection bi-curry@ }
+{ $subsection tri-curry@ }
+{ $see-also "dataflow-combinators" } ;
+
+ARTICLE: "compositional-examples" "Examples of compositional combinator usage"
+"Consider printing the same message ten times:"
+{ $code ": print-10 ( -- ) 10 [ \"Hello, world.\" print ] times ;" }
+"if we wanted to abstract out the message into a parameter, we could keep it on the stack between iterations:"
+{ $code ": print-10 ( message -- ) 10 [ dup print ] times drop ;" }
+"However, keeping loop-invariant values on the stack doesn't always work out nicely. For example, a word to subtract a value from each element of a sequence:"
+{ $code ": subtract-n ( seq n -- seq' ) swap [ over - ] map nip ;" }
+"Three shuffle words are required to pass the value around. Instead, the loop-invariant value can be partially applied to a quotation using " { $link curry } ", yielding a new quotation that is passed to " { $link map } ":"
+{ $example
+  "USING: kernel math prettyprint sequences ;"
+  ": subtract-n ( seq n -- seq' ) [ - ] curry map ;"
+  "{ 10 20 30 } 5 subtract-n ."
+  "{ 5 15 25 }"
+}
+"Now consider the word that is dual to the one above; instead of subtracting " { $snippet "n" } " from each stack element, it subtracts each element from " { $snippet "n" } "."
+$nl
+"One way to write this is with a pair of " { $link swap } "s:"
+{ $code ": n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;" }
+"Since this pattern comes up often, " { $link with } " encapsulates it:"
+{ $example
+  "USING: kernel math prettyprint sequences ;"
+  ": n-subtract ( n seq -- seq' ) [ - ] with map ;"
+  "30 { 10 20 30 } n-subtract ."
+  "{ 20 10 0 }"
+}
+{ $see-also "fry.examples" } ;
+
+ARTICLE: "compositional-combinators" "Compositional combinators"
+"Certain combinators transform quotations to produce a new quotation."
+{ $subsection "compositional-examples" }
+"Fundamental operations:"
+{ $subsection curry }
+{ $subsection compose }
+"Derived operations:"
+{ $subsection 2curry }
+{ $subsection 3curry }
+{ $subsection with }
+{ $subsection prepose }
+"These operations run in constant time, and in many cases are optimized out altogether by the " { $link "compiler" } ". " { $link "fry" } " are an abstraction built on top of these operations, and code that uses this abstraction is often clearer than direct calls to the below words."
+$nl
+"Curried dataflow combinators can be used to build more complex dataflow by combining cleave, spread and apply patterns in various ways."
+{ $subsection "curried-dataflow" }
+"Quotations also implement the sequence protocol, and can be manipulated with sequence words; see " { $link "quotations" } ". However, such runtime quotation manipulation will not be optimized by the optimizing compiler." ;
+
+ARTICLE: "booleans" "Booleans"
+"In Factor, any object that is not " { $link f } " has a true value, and " { $link f } " has a false value. The " { $link t } " object is the canonical true value."
+{ $subsection f }
+{ $subsection t }
+"There are some logical operations on booleans:"
+{ $subsection >boolean }
+{ $subsection not }
+{ $subsection and }
+{ $subsection or }
+{ $subsection xor }
+"Boolean values are most frequently used for " { $link "conditionals" } "."
+{ $heading "The f object and f class" }
+"The " { $link f } " object is the unique instance of the " { $link f } " class; the two are distinct objects. The latter is also a parsing word which adds the " { $link f } " object to the parse tree at parse time. To refer to the class itself you must use " { $link POSTPONE: POSTPONE: } " or " { $link POSTPONE: \ } " to prevent the parsing word from executing."
+$nl
+"Here is the " { $link f } " object:"
+{ $example "f ." "f" }
+"Here is the " { $link f } " class:"
+{ $example "\\ f ." "POSTPONE: f" }
+"They are not equal:"
+{ $example "f \\ f = ." "f" }
+"Here is an array containing the " { $link f } " object:"
+{ $example "{ f } ." "{ f }" }
+"Here is an array containing the " { $link f } " class:"
+{ $example "{ POSTPONE: f } ." "{ POSTPONE: f }" }
+"The " { $link f } " object is an instance of the " { $link f } " class:"
+{ $example "USE: classes" "f class ." "POSTPONE: f" }
+"The " { $link f } " class is an instance of " { $link word } ":"
+{ $example "USE: classes" "\\ f class ." "word" }
+"On the other hand, " { $link t } " is just a word, and there is no class which it is a unique instance of."
+{ $example "t \\ t eq? ." "t" }
+"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "." ;
+
+ARTICLE: "conditionals-boolean-equivalence" "Expressing conditionals with boolean logic"
+"Certain simple conditional forms can be expressed in a simpler manner using boolean logic."
+$nl
+"The following two lines are equivalent:"
+{ $code "[ drop f ] unless" "swap and" }
+"The following two lines are equivalent:"
+{ $code "[ ] [ ] ?if" "swap or" }
+"The following two lines are equivalent, where " { $snippet "L" } " is a literal:"
+{ $code "[ L ] unless*" "L or" } ;
+
+ARTICLE: "conditionals" "Conditional combinators"
+"The basic conditionals:"
+{ $subsection if }
+{ $subsection when }
+{ $subsection unless }
+"Forms abstracting a common stack shuffle pattern:"
+{ $subsection if* }
+{ $subsection when* }
+{ $subsection unless* }
+"Another form abstracting a common stack shuffle pattern:"
+{ $subsection ?if }
+"Sometimes instead of branching, you just need to pick one of two values:"
+{ $subsection ? }
+"Two combinators which abstract out nested chains of " { $link if } ":"
+{ $subsection cond }
+{ $subsection case }
+{ $subsection "conditionals-boolean-equivalence" }
+{ $see-also "booleans" "bitwise-arithmetic" both? either? } ;
+
+ARTICLE: "dataflow-combinators" "Data flow combinators"
+"Data flow combinators pass values between quotations:"
+{ $subsection "slip-keep-combinators" }
+{ $subsection "cleave-combinators" }
+{ $subsection "spread-combinators" }
+{ $subsection "apply-combinators" }
+{ $see-also "curried-dataflow" } ;
+
 ARTICLE: "combinators-quot" "Quotation construction utilities"
 "Some words for creating quotations which can be useful for implementing method combinations and compiler transforms:"
 { $subsection cond>quot }
 { $subsection case>quot }
 { $subsection alist>quot } ;
 
-ARTICLE: "call" "Calling code with known stack effects"
-"Arbitrary quotations and words can be called from code accepted by the optimizing compiler. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate."
+ARTICLE: "call" "Fundamental combinators"
+"The most basic combinators are those that take either a quotation or word, and invoke it immediately. There are two sets of combinators; they differe in whether or not the stack effect of the expected code is declared."
 $nl
-"Quotations:"
-{ $subsection POSTPONE: call( }
+"The simplest combinators do not take an effect declaration:"
+{ $subsection call }
+{ $subsection execute }
+"These combinators only get optimized by the compiler if the quotation or word parameter is a literal; otherwise a compiler warning will result. Definitions of combinators which require literal parameters must be followed by the " { $link POSTPONE: inline } " declaration. For example:"
+{ $code
+    ": keep ( x quot -- x )"
+    "    over [ call ] dip ; inline"
+}
+"See " { $link "declarations" } " and " { $link "compiler-errors" } " for details."
+$nl
+"The other set of combinators allow arbitrary quotations and words to be called from optimized code. This is done by specifying the stack effect of the quotation literally. It is checked at runtime that the stack effect is accurate."
 { $subsection call-effect }
-"Words:"
-{ $subsection POSTPONE: execute( }
 { $subsection execute-effect }
-"Unsafe calls:"
+"A simple layer of syntax sugar is defined on top:"
+{ $subsection POSTPONE: call( }
+{ $subsection POSTPONE: execute( }
+"Unsafe calls declare an effect statically without any runtime checking:"
 { $subsection call-effect-unsafe }
-{ $subsection execute-effect-unsafe } ;
+{ $subsection execute-effect-unsafe }
+{ $see-also "effects" "inference" } ;
 
-ARTICLE: "combinators" "Additional combinators"
-"The " { $vocab-link "combinators" } " vocabulary provides a few useful combinators."
+ARTICLE: "combinators" "Combinators"
+"A central concept in Factor is that of a " { $emphasis "combinator" } ", which is a word taking code as input."
+{ $subsection "call" }
+{ $subsection "dataflow-combinators" }
+{ $subsection "conditionals" }
+{ $subsection "looping-combinators" }
+{ $subsection "compositional-combinators" }
+{ $subsection "combinators.short-circuit" }
+{ $subsection "combinators.smart" }
+"More combinators are defined for working on data structures, such as " { $link "sequences-combinators" } " and " { $link "assocs-combinators" } "."
 $nl
-"Generalization of " { $link bi } " and " { $link tri } ":"
-{ $subsection cleave }
-"Generalization of " { $link 2bi } " and " { $link 2tri } ":"
-{ $subsection 2cleave }
-"Generalization of " { $link 3bi } " and " { $link 3tri }  ":"
-{ $subsection 3cleave }
-"Generalization of " { $link bi* } " and " { $link tri* } ":"
-{ $subsection spread }
-"Two combinators which abstract out nested chains of " { $link if } ":"
-{ $subsection cond }
-{ $subsection case }
-"The " { $vocab-link "combinators" } " also provides some less frequently-used features."
+"The " { $vocab-link "combinators" } " provides some less frequently-used features."
 $nl
 "A combinator which can help with implementing methods on " { $link hashcode* } ":"
 { $subsection recursive-hashcode }
-{ $subsection "call" }
 { $subsection "combinators-quot" }
-{ $see-also "quotations" "dataflow" } ;
+"Advanced topics:"
+{ $see-also "quotations" } ;
 
 ABOUT: "combinators"
 
index b53ab28cbc7b99e2898bcc44ed45532e3a3bc8c7..9d49cf62c64231379d7e99762675b9c92bfa7d0a 100644 (file)
@@ -56,11 +56,24 @@ $nl
 { $subsection redefine-error } ;
 
 ARTICLE: "definitions" "Definitions"
-"A " { $emphasis "definition" } " is an artifact read from a source file. This includes words, methods, help articles, and path names (which represent the source file at that location). Words for working with definitions are found in the " { $vocab-link "definitions" } " vocabulary."
+"A " { $emphasis "definition" } " is an artifact read from a source file. Words for working with definitions are found in the " { $vocab-link "definitions" } " vocabulary."
+$nl
+"Definitions are defined using parsing words. Examples of definitions together with their defining parsing words are words (" { $link POSTPONE: : } "), methods (" { $link POSTPONE: M: } "), and vocabularies (" { $link POSTPONE: IN: } ")."
+$nl
+"All definitions share some common traits:"
+{ $list
+  "There is a word to list all definitions of a given type"
+  "There is a parsing word for creating new definitions"
+  "There is an ordinary word which is the runtime equivalent of the parsing word, for introspection"
+  "Instances of the definition may be introspected and modified with the definition protocol"
+}
+"For every source file loaded into the system, a list of definitions is maintained. Pathname objects implement the definition protocol, acting over the definitions their source files contain. See " { $link "source-files" } " for details."
 { $subsection "definition-protocol" }
 { $subsection "definition-crossref" }
 { $subsection "definition-checking" }
 { $subsection "compilation-units" }
+"A parsing word to remove definitions:"
+{ $subsection POSTPONE: FORGET: }
 { $see-also "see" "parser" "source-files" "words" "generic" "help-impl" } ;
 
 ABOUT: "definitions"
index b2d265a2e3cf3a43032f048171b36086109f8f5a..558b25910343dc4025009e6e19203dde138adb3e 100644 (file)
@@ -20,14 +20,11 @@ TUPLE: some-class ;
 
 M: some-class some-generic ;
 
-TUPLE: another-class some-generic ;
-
 [ ] [
     [
-        {
-            some-generic
-            some-class
-            { another-class some-generic }
-        } forget-all
+        \ some-generic
+        \ some-class
+        2array
+        forget-all
     ] with-compilation-unit
 ] unit-test
index c95c5816ac19c1baa754b6aed779b66b45cc9319..7463a863e5b466201ee47163c95db9c10ef4f607 100644 (file)
@@ -42,7 +42,7 @@ GENERIC: set-where ( loc defspec -- )
 
 GENERIC: forget* ( defspec -- )
 
-M: object forget* drop ;
+M: f forget* drop ;
 
 SYMBOL: forgotten-definitions
 
@@ -53,8 +53,6 @@ SYMBOL: forgotten-definitions
 
 : forget-all ( definitions -- ) [ forget ] each ;
 
-GENERIC: synopsis* ( defspec -- )
-
 GENERIC: definer ( defspec -- start end )
 
 GENERIC: definition ( defspec -- seq )
index b209dcf259eaf149b1a1bcc52074200cdbb48842..20709ca8075fa5cc1b711fe9e201423d8757e594 100644 (file)
@@ -1,4 +1,4 @@
-USING: help.markup help.syntax math strings words kernel ;
+USING: help.markup help.syntax math strings words kernel combinators ;
 IN: effects
 
 ARTICLE: "effect-declaration" "Stack effect declaration"
@@ -29,14 +29,11 @@ $nl
 "The stack effect inferencer verifies stack effect comments to ensure the correct number of inputs and outputs is listed. Value names are ignored; only their number matters. An error is thrown if a word's declared stack effect does not match its inferred stack effect. See " { $link "inference" } "." ;
 
 ARTICLE: "effects" "Stack effects"
-"A " { $emphasis "stack effect declaration" } ", for example " { $snippet "( x y -- z )" } " denotes that an operation takes two inputs, with " { $snippet "y" } " at the top of the stack, and returns one output."
+"A " { $emphasis "stack effect declaration" } ", for example " { $snippet "( x y -- z )" } " denotes that an operation takes two inputs, with " { $snippet "y" } " at the top of the stack, and returns one output. Stack effects are first-class, and words for working with them are found in the " { $vocab-link "effects" } " vocabulary."
 $nl
-"Stack effects of words can be declared."
+"Stack effects of words must be declared, and the " { $link "compiler" } " checks that these declarations are correct. Invalid declarations are reported as " { $link "compiler-errors" } ". The " { $link "inference" } " tool can be used to check stack effects interactively."
 { $subsection "effect-declaration" }
-"Stack effects are first-class, and words for working with them are found in the " { $vocab-link "effects" } " vocabulary."
-{ $subsection effect }
-{ $subsection effect? }
-"There is a literal syntax for stack objects. It is most often used with " { $link define-declared } "."
+"There is a literal syntax for stack objects. It is most often used with " { $link define-declared } ", " { $link call-effect } " and " { $link execute-effect } "."
 { $subsection POSTPONE: (( }
 "Getting a word's declared stack effect:"
 { $subsection stack-effect }
@@ -45,7 +42,9 @@ $nl
 "Comparing effects:"
 { $subsection effect-height }
 { $subsection effect<= }
-{ $see-also "inference" } ;
+"The class of stack effects:"
+{ $subsection effect }
+{ $subsection effect? } ;
 
 ABOUT: "effects"
 
index 06a8fa87a3b36397e99641fcf0538d31009e18cf..7017ef8a087928d93bb777d7cb38170050696a63 100644 (file)
@@ -45,8 +45,8 @@ $nl
 { $subsection make-generic }
 "Low-level method constructor:"
 { $subsection <method> }
-"A " { $emphasis "method specifier" } " refers to a method and implements the " { $link "definition-protocol" } ":"
-{ $subsection method-spec }
+"Methods may be pushed on the stack with a literal syntax:"
+{ $subsection POSTPONE: M\ }
 { $see-also "see" } ;
 
 ARTICLE: "method-combination" "Custom method combination"
@@ -98,8 +98,8 @@ $nl
 "Generic words must declare their stack effect in order to compile. See " { $link "effect-declaration" } "."
 { $subsection "method-order" }
 { $subsection "call-next-method" }
-{ $subsection "generic-introspection" }
 { $subsection "method-combination" }
+{ $subsection "generic-introspection" }
 "Generic words specialize behavior based on the class of an object; sometimes behavior needs to be specialized on the object's " { $emphasis "structure" } "; this is known as " { $emphasis "pattern matching" } " and is implemented in the " { $vocab-link "match" } " vocabulary." ;
 
 ABOUT: "generic"
@@ -119,9 +119,10 @@ HELP: define-generic
 { $description "Defines a generic word. A method combination is an object which responds to the " { $link perform-combination } " generic word." }
 { $contract "The method combination quotation is called each time the generic word has to be updated (for example, when a method is added), and thus must be side-effect free." } ;
 
-HELP: method-spec
-{ $class-description "The class of method specifiers, which are two-element arrays consisting of a class word followed by a generic word." }
-{ $examples { $code "{ fixnum + }" "{ editor draw-gadget* }" } } ;
+HELP: M\
+{ $syntax "M\\ class generic" }
+{ $class-description "Pushes a method on the stack." }
+{ $examples { $code "M\\ fixnum + see" } { $code "USING: ui.gadgets ui.gadgets.editors ;" "M\\ editor draw-gadget* edit" } } ;
 
 HELP: method-body
 { $class-description "The class of method bodies, which are words with special word properties set." } ;
index aadc44833fa8c3713c41e50f99c1fb04cc42f0e0..f28332353e66de182023887fcf5920d327e58919 100755 (executable)
@@ -105,9 +105,6 @@ M: shit big-generic-test "shit" ;
 [ float ] [ \ real \ float math-class-max ] unit-test
 [ fixnum ] [ \ fixnum \ null math-class-max ] unit-test
 
-[ t ] [ { hashtable equal? } method-spec? ] unit-test
-[ f ] [ { word = } method-spec? ] unit-test
-
 ! Regression
 TUPLE: first-one ;
 TUPLE: second-one ;
@@ -164,7 +161,7 @@ M: sequence generic-forget-test-2 = ;
 ] unit-test
 
 [ ] [
-    [ { sequence generic-forget-test-2 } forget ] with-compilation-unit
+    [ M\ sequence generic-forget-test-2 forget ] with-compilation-unit
 ] unit-test
 
 [ f ] [
@@ -234,7 +231,7 @@ M: number c-n-m-cache ;
 
 [ 3 ] [ 2 c-n-m-cache ] unit-test
 
-[ ] [ [ { integer c-n-m-cache } forget ] with-compilation-unit ] unit-test
+[ ] [ [ M\ integer c-n-m-cache forget ] with-compilation-unit ] unit-test
 
 [ 2 ] [ 2 c-n-m-cache ] unit-test
 
index c22641d4391318eb8e28eabd8b877fa9267db2ec..65a802dc2dd3c968a85e96fe66292abee698848a 100644 (file)
@@ -24,11 +24,6 @@ M: generic definition drop f ;
 : method ( class generic -- method/f )
     "methods" word-prop at ;
 
-PREDICATE: method-spec < pair
-    first2 generic? swap class? and ;
-
-INSTANCE: method-spec definition
-
 : order ( generic -- seq )
     "methods" word-prop keys sort-classes ;
 
@@ -90,9 +85,6 @@ TUPLE: check-method class generic ;
 PREDICATE: method-body < word
     "method-generic" word-prop >boolean ;
 
-M: method-spec stack-effect
-    first2 method stack-effect ;
-
 M: method-body stack-effect
     "method-generic" word-prop stack-effect ;
 
@@ -139,24 +131,6 @@ M: default-method irrelevant? drop t ;
     dupd <default-method> "default-method" set-word-prop ;
 
 ! Definition protocol
-M: method-spec where
-    dup first2 method [ ] [ second ] ?if where ;
-
-M: method-spec set-where
-    first2 method set-where ;
-
-M: method-spec definer
-    first2 method definer ;
-
-M: method-spec definition
-    first2 method definition ;
-
-M: method-spec forget*
-    first2 method [ forgotten-definition ] [ forget* ] bi ;
-
-M: method-spec smart-usage
-    second smart-usage ;
-
 M: method-body definer
     drop \ M: \ ; ;
 
@@ -214,5 +188,8 @@ M: generic subwords
 M: generic forget*
     [ subwords forget-all ] [ call-next-method ] bi ;
 
+M: class forget-methods
+    [ implementors ] [ [ swap method ] curry ] bi map forget-all ;
+
 : xref-generics ( -- )
     all-words [ subwords [ xref ] each ] each ;
index 4323f91bc3dfe46659c3b6d8058af21b9c8f065c..60fa7453394f53b43a00e0f2ab7a8eae796d9295 100644 (file)
@@ -15,7 +15,7 @@ HELP: no-math-method
 HELP: math-method
 { $values { "word" generic } { "class1" class } { "class2" class } { "quot" quotation } }
 { $description "Generates a definition for " { $snippet "word" } " when the two inputs are instances of " { $snippet "class1" } " and " { $snippet "class2" } ", respectively." }
-{ $examples { $example "USING: generic.math math prettyprint ;" "\\ + fixnum float math-method ." "[ { fixnum float } declare [ >float ] dip float=>+ ]" } } ;
+{ $examples { $example "USING: generic.math math prettyprint ;" "\\ + fixnum float math-method ." "[ { fixnum float } declare [ >float ] dip M\\ float + ]" } } ;
 
 HELP: math-class
 { $class-description "The class of subtypes of " { $link number } " which are not " { $link null } "." } ;
index 204441c19ad42af27234bc1d420be453f542c1fc..d0f968a791d528a41f8ed5f4e017eef6a0329354 100644 (file)
@@ -80,12 +80,12 @@ ARTICLE: "encodings-descriptors" "Encoding descriptors"
 "An encoding descriptor is something which can be used with binary input or output streams to encode or decode bytes stored in a certain representation. It must conform to the " { $link "encodings-protocol" } ". Encodings which you can use are defined in the following vocabularies:"
 { $subsection "io.encodings.binary" }
 { $subsection "io.encodings.utf8" }
-{ $subsection "io.encodings.utf16" }
+{ $vocab-subsection "UTF-16 encoding" "io.encodings.utf16" }
 { $vocab-subsection "UTF-32 encoding" "io.encodings.utf32" }
 { $vocab-subsection "Strict encodings" "io.encodings.strict" }
 "Legacy encodings:"
 { $vocab-subsection "8-bit encodings" "io.encodings.8-bit" }
-{ $vocab-subsection "ASCII" "io.encodings.ascii" }
+{ $vocab-subsection "ASCII encoding" "io.encodings.ascii" }
 { $see-also "encodings-introduction" } ;
 
 ARTICLE: "encodings-protocol" "Encoding protocol"
index eb23a627b922acf2df727bf73df78f5dddfeb9c7..bec3bdc6bfab34682137fd8dde38c79514f8234d 100755 (executable)
@@ -1,11 +1,24 @@
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel kernel.private namespaces make io io.encodings
 sequences math generic threads.private classes io.backend
-io.files continuations destructors byte-arrays accessors ;
+io.files continuations destructors byte-arrays accessors
+combinators ;
 IN: io.streams.c
 
-TUPLE: c-writer handle disposed ;
+TUPLE: c-stream handle disposed ;
+
+M: c-stream dispose* handle>> fclose ;
+
+M: c-stream stream-seek
+    handle>> swap {
+        { seek-absolute [ 0 ] }
+        { seek-relative [ 1 ] }
+        { seek-end [ 2 ] }
+        [ bad-seek-type ]
+    } case fseek ;
+
+TUPLE: c-writer < c-stream ;
 
 : <c-writer> ( handle -- stream ) f c-writer boa ;
 
@@ -17,9 +30,7 @@ M: c-writer stream-write dup check-disposed handle>> fwrite ;
 
 M: c-writer stream-flush dup check-disposed handle>> fflush ;
 
-M: c-writer dispose* handle>> fclose ;
-
-TUPLE: c-reader handle disposed ;
+TUPLE: c-reader < c-stream ;
 
 : <c-reader> ( handle -- stream ) f c-reader boa ;
 
@@ -43,9 +54,6 @@ M: c-reader stream-read-until
     [ swap read-until-loop ] B{ } make swap
     over empty? over not and [ 2drop f f ] when ;
 
-M: c-reader dispose*
-    handle>> fclose ;
-
 M: c-io-backend init-io ;
 
 : stdin-handle ( -- alien ) 11 getenv ;
index c178573a0a4d9390d78f343989800df26a01e05d..36d04f1437eabe8176f5e9b8783fb17a163efab7 100644 (file)
@@ -841,260 +841,6 @@ $nl
 { $subsection roll }
 { $subsection -roll } ;
 
-ARTICLE: "cleave-shuffle-equivalence" "Expressing shuffle words with cleave combinators"
-"Cleave combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to cleave combinators are discussed in the documentation for " { $link bi } ", " { $link 2bi } ", " { $link 3bi } ", " { $link tri } ", " { $link 2tri } " and " { $link 3tri } "."
-$nl
-"Certain shuffle words can also be expressed in terms of the cleave combinators. Internalizing such identities can help with understanding and writing code using cleave combinators:"
-{ $code
-    ": keep  [ ] bi ;"
-    ": 2keep [ ] 2bi ;"
-    ": 3keep [ ] 3bi ;"
-    ""
-    ": dup   [ ] [ ] bi ;"
-    ": 2dup  [ ] [ ] 2bi ;"
-    ": 3dup  [ ] [ ] 3bi ;"
-    ""
-    ": tuck  [ nip ] [ ] 2bi ;"
-    ": swap  [ nip ] [ drop ] 2bi ;"
-    ""
-    ": over  [ ] [ drop ] 2bi ;"
-    ": pick  [ ] [ 2drop ] 3bi ;"
-    ": 2over [ ] [ drop ] 3bi ;"
-} ;
-
-ARTICLE: "cleave-combinators" "Cleave combinators"
-"The cleave combinators apply multiple quotations to a single value."
-$nl
-"Two quotations:"
-{ $subsection bi }
-{ $subsection 2bi }
-{ $subsection 3bi }
-"Three quotations:"
-{ $subsection tri }
-{ $subsection 2tri }
-{ $subsection 3tri }
-"Technically, the cleave combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on the top of the stack can be written in one of two ways:"
-{ $code
-    "! First alternative; uses keep"
-    "[ 1 + ] keep"
-    "[ 1 - ] keep"
-    "2 *"
-    "! Second alternative: uses tri"
-    "[ 1 + ]"
-    "[ 1 - ]"
-    "[ 2 * ] tri"
-}
-"The latter is more aesthetically pleasing than the former."
-$nl
-"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "."
-{ $subsection "cleave-shuffle-equivalence" } ;
-
-ARTICLE: "spread-shuffle-equivalence" "Expressing shuffle words with spread combinators"
-"Spread combinators are defined in terms of shuffle words, and mappings from certain shuffle idioms to spread combinators are discussed in the documentation for " { $link bi* } ", " { $link 2bi* } ", " { $link tri* } ", and " { $link 2tri* } "."
-$nl
-"Certain shuffle words can also be expressed in terms of the spread combinators. Internalizing such identities can help with understanding and writing code using spread combinators:"
-{ $code
-    ": dip   [ ] bi* ;"
-    ": 2dip  [ ] [ ] tri* ;"
-    ""
-    ": slip  [ call ] [ ] bi* ;"
-    ": 2slip [ call ] [ ] [ ] tri* ;"
-    ""
-    ": nip   [ drop ] [ ] bi* ;"
-    ": 2nip  [ drop ] [ drop ] [ ] tri* ;"
-    ""
-    ": rot"
-    "    [ [ drop ] [      ] [ drop ] tri* ]"
-    "    [ [ drop ] [ drop ] [      ] tri* ]"
-    "    [ [      ] [ drop ] [ drop ] tri* ]"
-    "    3tri ;"
-    ""
-    ": -rot"
-    "    [ [ drop ] [ drop ] [      ] tri* ]"
-    "    [ [      ] [ drop ] [ drop ] tri* ]"
-    "    [ [ drop ] [      ] [ drop ] tri* ]"
-    "    3tri ;"
-    ""
-    ": spin"
-    "    [ [ drop ] [ drop ] [      ] tri* ]"
-    "    [ [ drop ] [      ] [ drop ] tri* ]"
-    "    [ [      ] [ drop ] [ drop ] tri* ]"
-    "    3tri ;"
-} ;
-
-ARTICLE: "spread-combinators" "Spread combinators"
-"The spread combinators apply multiple quotations to multiple values. The " { $snippet "*" } " suffix signifies spreading."
-$nl
-"Two quotations:"
-{ $subsection bi* }
-{ $subsection 2bi* }
-"Three quotations:"
-{ $subsection tri* }
-{ $subsection 2tri* }
-"Technically, the spread combinators are redundant because they can be simulated using shuffle words and other combinators, and in addition, they do not reduce token counts by much, if at all. However, they can make code more readable by expressing intention and exploiting any inherent symmetry. For example, a piece of code which performs three operations on three related values can be written in one of two ways:"
-{ $code
-    "! First alternative; uses dip"
-    "[ [ 1 + ] dip 1 - ] dip 2 *"
-    "! Second alternative: uses tri*"
-    "[ 1 + ] [ 1 - ] [ 2 * ] tri*"
-}
-"A generalization of the above combinators to any number of quotations can be found in " { $link "combinators" } "."
-{ $subsection "spread-shuffle-equivalence" } ;
-
-ARTICLE: "apply-combinators" "Apply combinators"
-"The apply combinators apply a single quotation to multiple values. The " { $snippet "@" } " suffix signifies application."
-$nl
-"Two quotations:"
-{ $subsection bi@ }
-{ $subsection 2bi@ }
-"Three quotations:"
-{ $subsection tri@ }
-{ $subsection 2tri@ }
-"A pair of utility words built from " { $link bi@ } ":"
-{ $subsection both? }
-{ $subsection either? } ;
-
-ARTICLE: "slip-keep-combinators" "Retain stack combinators"
-"Sometimes an additional storage area is needed to hold objects. The " { $emphasis "retain stack" } " is an auxilliary stack for this purpose. Objects can be moved between the data and retain stacks using a set of combinators."
-$nl
-"The dip combinators invoke the quotation at the top of the stack, hiding the values underneath:"
-{ $subsection dip }
-{ $subsection 2dip }
-{ $subsection 3dip }
-{ $subsection 4dip }
-"The slip combinators invoke a quotation further down on the stack. They are most useful for implementing other combinators:"
-{ $subsection slip }
-{ $subsection 2slip }
-{ $subsection 3slip }
-"The keep combinators invoke a quotation which takes a number of values off the stack, and then they restore those values:"
-{ $subsection keep }
-{ $subsection 2keep }
-{ $subsection 3keep } ;
-
-ARTICLE: "curried-dataflow" "Curried dataflow combinators"
-"Curried cleave combinators:"
-{ $subsection bi-curry }
-{ $subsection tri-curry }
-"Curried spread combinators:"
-{ $subsection bi-curry* }
-{ $subsection tri-curry* }
-"Curried apply combinators:"
-{ $subsection bi-curry@ }
-{ $subsection tri-curry@ }
-{ $see-also "dataflow-combinators" } ;
-
-ARTICLE: "compositional-examples" "Examples of compositional combinator usage"
-"Consider printing the same message ten times:"
-{ $code ": print-10 ( -- ) 10 [ \"Hello, world.\" print ] times ;" }
-"if we wanted to abstract out the message into a parameter, we could keep it on the stack between iterations:"
-{ $code ": print-10 ( message -- ) 10 [ dup print ] times drop ;" }
-"However, keeping loop-invariant values on the stack doesn't always work out nicely. For example, a word to subtract a value from each element of a sequence:"
-{ $code ": subtract-n ( seq n -- seq' ) swap [ over - ] map nip ;" }
-"Three shuffle words are required to pass the value around. Instead, the loop-invariant value can be partially applied to a quotation using " { $link curry } ", yielding a new quotation that is passed to " { $link map } ":"
-{ $example
-  "USING: kernel math prettyprint sequences ;"
-  ": subtract-n ( seq n -- seq' ) [ - ] curry map ;"
-  "{ 10 20 30 } 5 subtract-n ."
-  "{ 5 15 25 }"
-}
-"Now consider the word that is dual to the one above; instead of subtracting " { $snippet "n" } " from each stack element, it subtracts each element from " { $snippet "n" } "."
-$nl
-"One way to write this is with a pair of " { $link swap } "s:"
-{ $code ": n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;" }
-"Since this pattern comes up often, " { $link with } " encapsulates it:"
-{ $example
-  "USING: kernel math prettyprint sequences ;"
-  ": n-subtract ( n seq -- seq' ) [ - ] with map ;"
-  "30 { 10 20 30 } n-subtract ."
-  "{ 20 10 0 }"
-}
-{ $see-also "fry.examples" } ;
-
-ARTICLE: "compositional-combinators" "Compositional combinators"
-"Certain combinators transform quotations to produce a new quotation."
-{ $subsection "compositional-examples" }
-"Fundamental operations:"
-{ $subsection curry }
-{ $subsection compose }
-"Derived operations:"
-{ $subsection 2curry }
-{ $subsection 3curry }
-{ $subsection with }
-{ $subsection prepose }
-"These operations run in constant time, and in many cases are optimized out altogether by the " { $link "compiler" } ". " { $link "fry" } " are an abstraction built on top of these operations, and code that uses this abstraction is often clearer than direct calls to the below words."
-$nl
-"Curried dataflow combinators can be used to build more complex dataflow by combining cleave, spread and apply patterns in various ways."
-{ $subsection "curried-dataflow" }
-"Quotations also implement the sequence protocol, and can be manipulated with sequence words; see " { $link "quotations" } ". However, such runtime quotation manipulation will not be optimized by the optimizing compiler." ;
-
-ARTICLE: "implementing-combinators" "Implementing combinators"
-"The following pair of words invoke words and quotations reflectively:"
-{ $subsection call }
-{ $subsection execute }
-"These words are used to implement combinators. Note that combinator definitions must be followed by the " { $link POSTPONE: inline } " declaration in order to compile in the optimizing compiler; for example:"
-{ $code
-    ": keep ( x quot -- x )"
-    "    over [ call ] dip ; inline"
-}
-"Word inlining is documented in " { $link "declarations" } "." ;
-
-ARTICLE: "booleans" "Booleans"
-"In Factor, any object that is not " { $link f } " has a true value, and " { $link f } " has a false value. The " { $link t } " object is the canonical true value."
-{ $subsection f }
-{ $subsection t }
-"The " { $link f } " object is the unique instance of the " { $link f } " class; the two are distinct objects. The latter is also a parsing word which adds the " { $link f } " object to the parse tree at parse time. To refer to the class itself you must use " { $link POSTPONE: POSTPONE: } " or " { $link POSTPONE: \ } " to prevent the parsing word from executing."
-$nl
-"Here is the " { $link f } " object:"
-{ $example "f ." "f" }
-"Here is the " { $link f } " class:"
-{ $example "\\ f ." "POSTPONE: f" }
-"They are not equal:"
-{ $example "f \\ f = ." "f" }
-"Here is an array containing the " { $link f } " object:"
-{ $example "{ f } ." "{ f }" }
-"Here is an array containing the " { $link f } " class:"
-{ $example "{ POSTPONE: f } ." "{ POSTPONE: f }" }
-"The " { $link f } " object is an instance of the " { $link f } " class:"
-{ $example "USE: classes" "f class ." "POSTPONE: f" }
-"The " { $link f } " class is an instance of " { $link word } ":"
-{ $example "USE: classes" "\\ f class ." "word" }
-"On the other hand, " { $link t } " is just a word, and there is no class which it is a unique instance of."
-{ $example "t \\ t eq? ." "t" }
-"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "." ;
-
-ARTICLE: "conditionals-boolean-equivalence" "Expressing conditionals with boolean logic"
-"Certain simple conditional forms can be expressed in a simpler manner using boolean logic."
-$nl
-"The following two lines are equivalent:"
-{ $code "[ drop f ] unless" "swap and" }
-"The following two lines are equivalent:"
-{ $code "[ ] [ ] ?if" "swap or" }
-"The following two lines are equivalent, where " { $snippet "L" } " is a literal:"
-{ $code "[ L ] unless*" "L or" } ;
-
-ARTICLE: "conditionals" "Conditionals and logic"
-"The basic conditionals:"
-{ $subsection if }
-{ $subsection when }
-{ $subsection unless }
-"Forms abstracting a common stack shuffle pattern:"
-{ $subsection if* }
-{ $subsection when* }
-{ $subsection unless* }
-"Another form abstracting a common stack shuffle pattern:"
-{ $subsection ?if }
-"Sometimes instead of branching, you just need to pick one of two values:"
-{ $subsection ? }
-"There are some logical operations on booleans:"
-{ $subsection >boolean }
-{ $subsection not }
-{ $subsection and }
-{ $subsection or }
-{ $subsection xor }
-{ $subsection "conditionals-boolean-equivalence" }
-"See " { $link "combinators" } " for forms which abstract away common patterns involving multiple nested branches."
-{ $see-also "booleans" "bitwise-arithmetic" both? either? } ;
-
 ARTICLE: "equality" "Equality"
 "There are two distinct notions of “sameness” when it comes to objects."
 $nl
@@ -1116,34 +862,3 @@ ARTICLE: "assertions" "Assertions"
 { $subsection assert }
 { $subsection assert= } ;
 
-ARTICLE: "dataflow-combinators" "Data flow combinators"
-"Data flow combinators pass values between quotations:"
-{ $subsection "slip-keep-combinators" }
-{ $subsection "cleave-combinators" }
-{ $subsection "spread-combinators" }
-{ $subsection "apply-combinators" }
-{ $see-also "curried-dataflow" } ;
-
-ARTICLE: "dataflow" "Data and control flow"
-{ $subsection "evaluator" }
-{ $subsection "words" }
-{ $subsection "effects" }
-{ $subsection "booleans" }
-{ $subsection "shuffle-words" }
-"A central concept in Factor is that of a " { $emphasis "combinator" } ", which is a word taking code as input."
-{ $subsection "dataflow-combinators" }
-{ $subsection "conditionals" }
-{ $subsection "looping-combinators" }
-{ $subsection "compositional-combinators" }
-{ $subsection "combinators" }
-"More combinators are defined for working on data structures, such as " { $link "sequences-combinators" } " and " { $link "assocs-combinators" } "."
-$nl
-"Advanced topics:"
-{ $subsection "assertions" }
-{ $subsection "implementing-combinators" }
-{ $subsection "macros" }
-{ $subsection "errors" }
-{ $subsection "continuations" } ;
-
-ABOUT: "dataflow"
-
index 27cc510ea2861f70549961965ab02f4931b41058..9f8f7b06fc5e7dc236be41cb88f52d1207c98f72 100644 (file)
@@ -56,8 +56,6 @@ unit-test
 [ t ] [ 0.0 zero? ] unit-test
 [ t ] [ -0.0 zero? ] unit-test
 
-! [ f ] [ 0.0/0.0 0.0/0.0 number= ] unit-test
-
 [ 0 ] [ 1/0. >bignum ] unit-test
 
 [ t ] [ 64 [ 2^ 0.5 * ] map [ < ] monotonic? ] unit-test
index e88caa77039fb1cb24cc792f5de53754c78a1d88..868d9fc02ea2ff866616eaa2d9db2a6bdb6098d3 100644 (file)
@@ -122,7 +122,7 @@ M: bignum (log2) bignum-log2 ;
         2drop 0.0
     ] [
         dup zero? [
-            2drop 1.0/0.0
+            2drop 1/0.
         ] [
             pre-scale
             /f-loop over odd?
index f79dcb54815da0c91a1d0cdb0b263efb3970878b..c28bf062c1954abd705f692fcf5c0bb1adf694da 100644 (file)
@@ -355,8 +355,9 @@ ARTICLE: "bitwise-arithmetic" "Bitwise arithmetic"
 { $subsection 2/ }
 { $subsection 2^ }
 { $subsection bit? }
-"The " { $vocab-link "math.bitwise" } " vocabulary implements additional bitwise integer operations."
-{ $see-also "conditionals" } ;
+{ $subsection "math.bitwise" }
+{ $subsection "math.bits" }
+{ $see-also "booleans" } ;
 
 ARTICLE: "arithmetic" "Arithmetic"
 "Factor attempts to preserve natural mathematical semantics for numbers. Multiplying two large integers never results in overflow, and dividing two integers yields an exact ratio. Floating point numbers are also supported, along with complex numbers."
index 1bdd1009e9c77c7b03504554de13b22973285ac6..8b2200aa6710fdbb14425acbc5a5e2f0e333c735 100644 (file)
@@ -87,7 +87,14 @@ ARTICLE: "order-specifiers" "Ordering specifiers"
 { $subsection +lt+ }
 { $subsection +eq+ }
 { $subsection +gt+ } ;
-    
+
+ARTICLE: "math.order.example" "Linear order example"
+"A tuple class which defines an ordering among instances by comparing the values of the " { $snippet "id" } " slot:"
+{ $code
+  "TUPLE: sprite id name bitmap ;"
+  "M: sprite <=> [ id>> ] compare ;"
+} ;
+
 ARTICLE: "math.order" "Linear order protocol"
 "Some classes have an intrinsic order amongst instances:"
 { $subsection <=> }
@@ -101,6 +108,8 @@ ARTICLE: "math.order" "Linear order protocol"
 { $subsection before? }
 { $subsection after=? }
 { $subsection before=? }
+"Out of the above generic words, it suffices to implement " { $link <=> } " alone. The others may be provided as an optimization."
+{ $subsection "math.order.example" }
 { $see-also "sequences-sorting" } ;
 
 ABOUT: "math.order"
index bcc75a842aa9b9abd34b3217384e1bde9ab1c45d..ba0df3e35748df8c7a9f677c7204a25a790be40b 100644 (file)
@@ -25,7 +25,7 @@ $nl
 ABOUT: "number-strings"
 
 HELP: digits>integer
-{ $values { "seq" "a sequence of integers" } { "radix" "an integer between 2 and 36" } { "n" integer } }
+{ $values { "seq" "a sequence of integers" } { "radix" "an integer between 2 and 36" } { "n/f" { $maybe integer } } }
 { $description "Converts a sequence of digits (with most significant digit first) into an integer." }
 { $notes "This is one of the factors of " { $link string>number } "." } ;
 
index 0fb2559854d5f06371321470d4f2c9d149b2024c..c655965e353f817e10e9e190c4a33728f870eabd 100644 (file)
@@ -95,17 +95,17 @@ unit-test
 [ 1 0 >base ] must-fail
 [ 1 -1 >base ] must-fail
 
-[ "0.0/0.0" ] [ 0.0 0.0 / number>string ] unit-test
+[ "0/0." ] [ 0.0 0.0 / number>string ] unit-test
 
-[ "1.0/0.0" ] [ 1.0 0.0 / number>string ] unit-test
+[ "1/0." ] [ 1.0 0.0 / number>string ] unit-test
 
-[ "-1.0/0.0" ] [ -1.0 0.0 / number>string ] unit-test
+[ "-1/0." ] [ -1.0 0.0 / number>string ] unit-test
 
 [ t ] [ "0/0." string>number fp-nan? ] unit-test
 
-[ 1.0/0.0 ] [ "1/0." string>number ] unit-test
+[ 1/0. ] [ "1/0." string>number ] unit-test
 
-[ -1.0/0.0 ] [ "-1/0." string>number ] unit-test
+[ -1/0. ] [ "-1/0." string>number ] unit-test
 
 [ "-0.0" ] [ -0.0 number>string ] unit-test
 
index 0d8f0c0b08d057a6bb617baf7bdd3ae93c51abb3..3fd62e69a03c48ebf084420cc90afe0ee3cd596b 100644 (file)
@@ -1,7 +1,7 @@
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math.private namespaces sequences strings
-arrays combinators splitting math assocs make ;
+USING: kernel math.private namespaces sequences sequences.private
+strings arrays combinators splitting math assocs make ;
 IN: math.parser
 
 : digit> ( ch -- n )
@@ -28,13 +28,19 @@ IN: math.parser
         { CHAR: d 13 }
         { CHAR: e 14 }
         { CHAR: f 15 }
-    } at ;
+    } at 255 or ; inline
 
 : string>digits ( str -- digits )
-    [ digit> ] { } map-as ;
+    [ digit> ] B{ } map-as ; inline
 
-: digits>integer ( seq radix -- n )
-    0 swap [ swapd * + ] curry reduce ;
+: (digits>integer) ( valid? accum digit radix -- valid? accum )
+    2dup < [ swapd * + ] [ 2drop 2drop f 0 ] if ; inline
+
+: each-digit ( seq radix quot -- n/f )
+    [ t 0 ] 3dip curry each swap [ drop f ] unless ; inline
+
+: digits>integer ( seq radix -- n/f )
+    [ (digits>integer) ] each-digit ; inline
 
 DEFER: base>
 
@@ -43,6 +49,11 @@ DEFER: base>
 SYMBOL: radix
 SYMBOL: negative?
 
+: string>natural ( seq radix -- n/f )
+    over empty? [ 2drop f ] [
+        [ [ digit> ] dip (digits>integer) ] each-digit
+    ] if ; inline
+
 : sign ( -- str ) negative? get "-" "+" ? ;
 
 : with-radix ( radix quot -- )
@@ -54,37 +65,30 @@ SYMBOL: negative?
     sign split1 [ (base>) ] dip
     dup [ (base>) ] [ drop 0 swap ] if ;
 
-: string>ratio ( str -- a/b )
-    "-" ?head dup negative? set swap
-    "/" split1 (base>) [ whole-part ] dip
-    3dup and and [ / + swap [ neg ] when ] [ 2drop 2drop f ] if ;
-
-: valid-digits? ( seq -- ? )
-    {
-        { [ dup empty? ] [ drop f ] }
-        { [ f over memq? ] [ drop f ] }
-        [ radix get [ < ] curry all? ]
-    } cond ;
+: string>ratio ( str radix -- a/b )
+    [
+        "-" ?head dup negative? set swap
+        "/" split1 (base>) [ whole-part ] dip
+        3dup and and [ / + swap [ neg ] when ] [ 2drop 2drop f ] if
+    ] with-radix ;
 
-: string>integer ( str -- n/f )
-    "-" ?head swap
-    string>digits dup valid-digits?
-    [ radix get digits>integer swap [ neg ] when ] [ 2drop f ] if ;
+: string>integer ( str radix -- n/f )
+    over first-unsafe CHAR: - = [
+        [ rest-slice ] dip string>natural dup [ neg ] when
+    ] [
+        string>natural
+    ] if ; inline
 
 PRIVATE>
 
 : base> ( str radix -- n/f )
-    [
-        CHAR: / over member? [
-            string>ratio
-        ] [
-            CHAR: . over member? [
-                string>float
-            ] [
-                string>integer
-            ] if
-        ] if
-    ] with-radix ;
+    over empty? [ 2drop f ] [
+        over [ "/." member? ] find nip {
+            { CHAR: / [ string>ratio ] }
+            { CHAR: . [ drop string>float ] }
+            [ drop string>integer ]
+        } case
+    ] if ;
 
 : string>number ( str -- n/f ) 10 base> ;
 : bin> ( str -- n/f ) 2 base> ;
@@ -147,9 +151,9 @@ M: ratio >base
 
 M: float >base
     drop {
-        { [ dup fp-nan? ] [ drop "0.0/0.0" ] }
-        { [ dup 1.0/0.0 = ] [ drop "1.0/0.0" ] }
-        { [ dup -1.0/0.0 = ] [ drop "-1.0/0.0" ] }
+        { [ dup fp-nan? ] [ drop "0/0." ] }
+        { [ dup 1/0. = ] [ drop "1/0." ] }
+        { [ dup -1/0. = ] [ drop "-1/0." ] }
         { [ dup double>bits HEX: 8000000000000000 = ] [ drop "-0.0" ] }
         [ float>string fix-float ]
     } cond ;
index ff0542a7b87da8b877c0c7f326033d9d48f6b60f..74d7c58963807d4c8552a6612c6b693b48a3a90e 100644 (file)
@@ -32,7 +32,7 @@ ARTICLE: "namespaces.private" "Namespace implementation details"
 { $subsection >n }
 { $subsection ndrop } ;
 
-ARTICLE: "namespaces" "Variables and namespaces"
+ARTICLE: "namespaces" "Dynamic variables and namespaces"
 "The " { $vocab-link "namespaces" } " vocabulary implements simple dynamically-scoped variables."
 $nl
 "A variable is an entry in an assoc of bindings, where the assoc is implicit rather than passed on the stack. These assocs are termed " { $emphasis "namespaces" } ". Nesting of scopes is implemented with a search order on namespaces, defined by a " { $emphasis "namestack" } ". Since namespaces are just assoc, any object can be used as a variable, however by convention, variables are keyed by symbols (see " { $link "words.symbol" } ")."
@@ -43,7 +43,6 @@ $nl
 "Various utility words abstract away common variable access patterns:"
 { $subsection "namespaces-change" }
 { $subsection "namespaces-combinators" }
-{ $subsection "namespaces-global" }
 "Implementation details your code probably does not care about:"
 { $subsection "namespaces.private" }
 "An alternative to dynamic scope is lexical scope. Lexically-scoped values and closures are implemented in the " { $vocab-link "locals" } " vocabulary." ;
index 547f7c0490ebd3805c2ca5277eaa85b8be8245b7..be4b345f4f05db887bcc8410c4790d10d1e3341f 100644 (file)
@@ -92,9 +92,7 @@ ARTICLE: "parser" "The parser"
 "This parser is a general facility for reading textual representations of objects and definitions. The parser is implemented in the " { $vocab-link "parser" } " and " { $vocab-link "syntax" } " vocabularies."
 $nl
 "This section concerns itself with usage and extension of the parser. Standard syntax is described in " { $link "syntax" } "."
-{ $subsection "vocabulary-search" }
 { $subsection "parser-files" }
-{ $subsection "top-level-forms" }
 "The parser can be extended."
 { $subsection "parsing-words" }
 { $subsection "parser-lexer" }
index 2a03b7c74f6bca70dd24916390a81d475c68d82b..a72f4adf8805b30e8390baf7aefc543220e0fd4d 100644 (file)
@@ -24,7 +24,7 @@ ARTICLE: "wrappers" "Wrappers"
 "Wrappers are used to push words on the data stack; they evaluate to the object being wrapped:"
 { $subsection wrapper }
 { $subsection literalize }
-{ $see-also "dataflow" "combinators" } ;
+{ $see-also "combinators" } ;
 
 ABOUT: "quotations"
 
index c171555737eddf6895eab8753cf1bd09a3044d62..556e41249e24032abdb00d79ae423b8e57c39f0b 100755 (executable)
@@ -311,7 +311,7 @@ HELP: each-index
 
 HELP: map-index
 { $values
-     { "seq" sequence } { "quot" quotation } }
+  { "seq" sequence } { "quot" quotation } { "newseq" sequence } }
 { $description "Calls the quotation with the element of the sequence and its index on the stack, with the index on the top of the stack. Collects the outputs of the quotation and outputs them in a sequence of the same type as the input sequence." }
 { $examples { $example "USING: sequences prettyprint math ;"
 "{ 10 20 30 } [ + ] map-index ."
@@ -1354,14 +1354,16 @@ ARTICLE: "virtual-sequences" "Virtual sequences"
 "Virtual sequences allow different ways of accessing a sequence without having to create a new sequence or a new data structure altogether. To do this, they translate the virtual index into a normal index into an underlying sequence using the " { $link "virtual-sequences-protocol" } "."
 { $subsection "virtual-sequences-protocol" } ;
 
-ARTICLE: "sequences-integers" "Integer sequences and counted loops"
+ARTICLE: "sequences-integers" "Counted loops"
 "Integers support the sequence protocol in a trivial fashion; a non-negative integer presents its non-negative predecessors as elements. For example, the integer 3, when viewed as a sequence, contains the elements 0, 1, and 2. This is very useful for performing counted loops."
 $nl
 "For example, the " { $link each } " combinator, given an integer, simply calls a quotation that number of times, pushing a counter on each iteration that ranges from 0 up to that integer:"
 { $example "3 [ . ] each" "0\n1\n2" }
 "A common idiom is to iterate over a sequence, while also maintaining a loop counter. This can be done using " { $link each-index } ", " { $link map-index } " and " { $link reduce-index } "."
 $nl
-"Combinators that produce new sequences, such as " { $link map } ", will output an array if the input is an integer." ;
+"Combinators that produce new sequences, such as " { $link map } ", will output an array if the input is an integer."
+$nl
+"More elaborate counted loops can be performed with " { $link "math.ranges" } "." ;
 
 ARTICLE: "sequences-access" "Accessing sequence elements"
 { $subsection ?nth }
@@ -1593,7 +1595,6 @@ $nl
 "Sequences implement a protocol:"
 { $subsection "sequence-protocol" }
 { $subsection "sequences-f" }
-{ $subsection "sequences-integers" }
 "Sequence utility words can operate on any object whose class implements the sequence protocol. Most implementations are backed by storage. Some implementations obtain their elements from an underlying sequence, or compute them on the fly. These are known as " { $link "virtual-sequences" } "."
 { $subsection "sequences-access" }
 { $subsection "sequences-combinators" }
@@ -1612,6 +1613,10 @@ $nl
 { $subsection "binary-search" }
 { $subsection "sets" }
 { $subsection "sequences-trimming" }
+{ $subsection "sequences.deep" }
+"Using sequences for looping:"
+{ $subsection "sequences-integers" }
+{ $subsection "math.ranges" }
 "For inner loops:"
 { $subsection "sequences-unsafe" } ;
 
index da495f410fb62ae0a23adf304553a330b1e472dc..85f9d5659652eeacff10cc958d67f868b33b1d1a 100644 (file)
@@ -227,7 +227,7 @@ unit-test
 [ -3 10 nth ] must-fail
 [ 11 10 nth ] must-fail
 
-[ -1./0. 0 delete-nth ] must-fail
+[ -1/0. 0 delete-nth ] must-fail
 [ "" ] [ "" [ CHAR: \s = ] trim ] unit-test
 [ "" ] [ "" [ CHAR: \s = ] trim-head ] unit-test
 [ "" ] [ "" [ CHAR: \s = ] trim-tail ] unit-test
index f352705e85698751916d02bb1b23ed236f2acb3d..564309a6fb5c4e9aed549a92ac5c3df17f297eaa 100755 (executable)
@@ -506,7 +506,7 @@ PRIVATE>
     [ [ 0 = ] 2dip if ] 2curry
     each-index ; inline
 
-: map-index ( seq quot -- )
+: map-index ( seq quot -- newseq )
     prepare-index 2map ; inline
 
 : reduce-index ( seq identity quot -- )
index 840fe628e0a52dbba67707b277bb459a1ce467ac..1e5f9bf1ddbf4e7fcc4e4547724c7f4817be690e 100644 (file)
@@ -83,7 +83,7 @@ $nl
 "A word can be used to check if a class has an initial value or not:"
 { $subsection initial-value } ;
 
-ARTICLE: "slots" "Slots"
+ARTICLE: "slots" "Low-level slot operations"
 "The " { $vocab-link "slots" } " vocabulary contains words for introspecting the slots of an object. A " { $emphasis "slot" } " is a component of an object which can store a value."
 $nl
 { $link "tuples" } " are composed entirely of slots, and instances of " { $link "builtin-classes" } " consist of slots together with intrinsic data."
@@ -104,6 +104,9 @@ $nl
 { $subsection define-changer }
 { $subsection define-slot-methods }
 { $subsection define-accessors }
+"Unsafe slot access:"
+{ $subsection slot }
+{ $subsection set-slot }
 { $see-also "accessors" "mirrors" } ;
 
 ABOUT: "slots"
index df9eb568f6e6f88de2bfae58f7acb634587b4042..33a0096ff9324a8f7564562d00b397bb5986ce68 100644 (file)
@@ -66,6 +66,12 @@ ARTICLE: "syntax-floats" "Float syntax"
     "7.e13"
     "1.0e-5"
 }
+"There are three special float values:"
+{ $table
+{ "Positive infinity" { $snippet "1/0." } }
+{ "Negative infinity" { $snippet "-1/0." } }
+{ "Not-a-number" { $snippet "0/0." } }
+}
 "More information on floats can be found in " { $link "floats" } "." ;
 
 ARTICLE: "syntax-complex-numbers" "Complex number syntax"
@@ -167,6 +173,8 @@ $nl
 ARTICLE: "syntax" "Syntax"
 "Factor has two main forms of syntax: " { $emphasis "definition" } " syntax and " { $emphasis "literal" } " syntax. Code is data, so the syntax for code is a special case of object literal syntax. This section documents literal syntax. Definition syntax is covered in " { $link "words" } ". Extending the parser is the main topic of " { $link "parser" } "."
 { $subsection "parser-algorithm" }
+{ $subsection "vocabulary-search" }
+{ $subsection "top-level-forms" }
 { $subsection "syntax-comments" }
 { $subsection "syntax-literals" }
 { $subsection "syntax-immediate" } ;
@@ -762,7 +770,9 @@ HELP: >>
 { $description "Marks the end of a parse time code block." } ;
 
 HELP: call-next-method
+{ $syntax "call-next-method" }
 { $description "Calls the next applicable method. Only valid inside a method definition. The values at the top of the stack are passed on to the next method, and they must be compatible with that method's class specializer." }
+{ $notes "This word looks like an ordinary word but it is a parsing word. It cannot be factored out of a method definition, since the code expansion references the current method object directly." }
 { $errors
     "Throws a " { $link no-next-method } " error if this is the least specific method, and throws an " { $link inconsistent-next-method } " error if the values at the top of the stack are not compatible with the current method's specializer."
 } ;
index cb5cdfd5acc4b0438cb1c1d6541ecb8fa447b5c0..2e072f72d823d867ef423adb92ea04b722f360b8 100644 (file)
@@ -104,6 +104,7 @@ IN: bootstrap.syntax
 
     "POSTPONE:" [ scan-word parsed ] define-core-syntax
     "\\" [ scan-word <wrapper> parsed ] define-core-syntax
+    "M\\" [ scan-word scan-word method <wrapper> parsed ] define-core-syntax
     "inline" [ word make-inline ] define-core-syntax
     "recursive" [ word make-recursive ] define-core-syntax
     "foldable" [ word make-foldable ] define-core-syntax
index 0615e8333e570ec828f1cae969fe1c1864cc537a..73e270dffcf00484c60d5e1b36ff4e69c83a5073 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: quotations effects accessors sequences words kernel ;
+USING: quotations effects accessors sequences words kernel definitions ;
 IN: words.alias
 
 PREDICATE: alias < word "alias" word-prop ;
@@ -12,5 +12,6 @@ PREDICATE: alias < word "alias" word-prop ;
 M: alias reset-word
     [ call-next-method ] [ f "alias" set-word-prop ] bi ;
 
-M: alias stack-effect
-    def>> first stack-effect ;
+M: alias definer drop \ ALIAS: f ;
+
+M: alias definition def>> first 1quotation ;
\ No newline at end of file
diff --git a/core/words/constant/constant-tests.factor b/core/words/constant/constant-tests.factor
new file mode 100644 (file)
index 0000000..721846b
--- /dev/null
@@ -0,0 +1,20 @@
+IN: words.constant.tests
+USING: tools.test math words.constant ;
+
+CONSTANT: a +
+
+[ + ] [ a ] unit-test
+
+[ t ] [ \ a constant? ] unit-test
+
+CONSTANT: b \ +
+
+[ \ + ] [ b ] unit-test
+
+CONSTANT: c { 1 2 3 }
+
+[ { 1 2 3 } ] [ c ] unit-test
+
+SYMBOL: foo
+
+[ f ] [ \ foo constant? ] unit-test
\ No newline at end of file
index 43b7f37599c50d11f82ee891cf7e148cd35a591c..b518760bf980ded0d0fb3c6c8186c35f161a3c98 100644 (file)
@@ -1,10 +1,17 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel sequences words ;
+USING: accessors kernel sequences words definitions quotations ;
 IN: words.constant
 
-PREDICATE: constant < word ( obj -- ? )
-    def>> dup length 1 = [ first word? not ] [ drop f ] if ;
+PREDICATE: constant < word "constant" word-prop >boolean ;
 
 : define-constant ( word value -- )
-    [ ] curry (( -- value )) define-inline ;
+    [ "constant" set-word-prop ]
+    [ [ ] curry (( -- value )) define-inline ] 2bi ;
+
+M: constant reset-word
+    [ call-next-method ] [ f "constant" set-word-prop ] bi ;
+
+M: constant definer drop \ CONSTANT: f ;
+
+M: constant definition "constant" word-prop literalize 1quotation ;
\ No newline at end of file
index a107808eec35073761310c47a1e968cba061bf79..34ec6b9174f41f3d6e041024e9a1a9f18ed42721 100644 (file)
@@ -1,10 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences accessors definitions
-words words.constant ;
+USING: kernel sequences accessors definitions words ;
 IN: words.symbol
 
-PREDICATE: symbol < constant ( obj -- ? )
+PREDICATE: symbol < word ( obj -- ? )
     [ def>> ] [ [ ] curry ] bi sequence= ;
 
 M: symbol definer drop \ SYMBOL: f ;
@@ -12,4 +11,4 @@ M: symbol definer drop \ SYMBOL: f ;
 M: symbol definition drop f ;
 
 : define-symbol ( word -- )
-    dup define-constant ;
+    dup [ ] curry (( -- value )) define-inline ;
index 1f36a4627581364a65a69bcd66d867ee85ec8cf4..0d46d73f55d2d2b4716fd2081cb17798728020e1 100755 (executable)
@@ -1,4 +1,4 @@
-USING: kernel namespaces math.vectors opengl 4DNav.turtle  ;
+USING: kernel namespaces math.vectors opengl opengl.glu 4DNav.turtle  ;
 
 IN: 4DNav.camera
 
diff --git a/extra/assoc-heaps/assoc-heaps-docs.factor b/extra/assoc-heaps/assoc-heaps-docs.factor
new file mode 100644 (file)
index 0000000..b148995
--- /dev/null
@@ -0,0 +1,32 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax io.streams.string assocs
+heaps.private ;
+IN: assoc-heaps
+
+HELP: <assoc-heap>
+{ $values { "assoc" assoc } { "heap" heap } { "assoc-heap" assoc-heap } }
+{ $description "Constructs a new " { $link assoc-heap } " from two existing data structures." } ;
+
+HELP: <unique-max-heap>
+{ $values { "unique-heap" assoc-heap } }
+{ $description "Creates a new " { $link assoc-heap } " where the assoc is a hashtable and the heap is a max-heap. Popping an element from the heap leaves this element in the hashtable to ensure that the element will not be processed again." } ;
+
+HELP: <unique-min-heap>
+{ $values { "unique-heap" assoc-heap } }
+{ $description "Creates a new " { $link assoc-heap } " where the assoc is a hashtable and the heap is a min-heap. Popping an element from the heap leaves this element in the hashtable to ensure that the element will not be processed again." } ;
+
+{ <unique-max-heap> <unique-min-heap> } related-words
+
+HELP: assoc-heap
+{ $description "A data structure containing an assoc and a heap to get certain properties with better time constraints at the expense of more space and complexity. For instance, a hashtable and a heap can be combined into one assoc-heap to get a sorted data structure with O(1) lookup. Operations on assoc-heap may update both the assoc and the heap or leave them out of sync if it's advantageous." } ;
+
+ARTICLE: "assoc-heaps" "Associative heaps"
+"The " { $vocab-link "assoc-heaps" } " vocabulary combines exists to synthesize data structures with better time properties than either of the two component data structures alone." $nl
+"Associative heap constructor:"
+{ $subsection <assoc-heap> }
+"Unique heaps:"
+{ $subsection <unique-min-heap> }
+{ $subsection <unique-max-heap> } ;
+
+ABOUT: "assoc-heaps"
diff --git a/extra/assoc-heaps/assoc-heaps-tests.factor b/extra/assoc-heaps/assoc-heaps-tests.factor
new file mode 100644 (file)
index 0000000..6ea3fe1
--- /dev/null
@@ -0,0 +1,4 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test assoc-heaps ;
+IN: assoc-heaps.tests
diff --git a/extra/assoc-heaps/assoc-heaps.factor b/extra/assoc-heaps/assoc-heaps.factor
new file mode 100644 (file)
index 0000000..a495aed
--- /dev/null
@@ -0,0 +1,30 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs hashtables heaps kernel ;
+IN: assoc-heaps
+
+TUPLE: assoc-heap assoc heap ;
+
+C: <assoc-heap> assoc-heap
+
+: <unique-min-heap> ( -- unique-heap )
+    H{ } clone <min-heap> <assoc-heap> ;
+
+: <unique-max-heap> ( -- unique-heap )
+    H{ } clone <max-heap> <assoc-heap> ;
+
+M: assoc-heap heap-push* ( value key assoc-heap -- entry )
+    pick over assoc>> key? [
+        3drop f
+    ] [
+        [ assoc>> swapd set-at ] [ heap>> heap-push* ] 3bi
+    ] if ;
+
+M: assoc-heap heap-pop ( assoc-heap -- value key )
+    heap>> heap-pop ;
+
+M: assoc-heap heap-peek ( assoc-heap -- value key )
+    heap>> heap-peek ;
+
+M: assoc-heap heap-empty? ( assoc-heap -- value key )
+    heap>> heap-empty? ;
diff --git a/extra/assoc-heaps/authors.txt b/extra/assoc-heaps/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/assoc-heaps/summary.txt b/extra/assoc-heaps/summary.txt
new file mode 100644 (file)
index 0000000..792be0a
--- /dev/null
@@ -0,0 +1 @@
+Priority queue with fast insertion, removal of first element, and lookup of arbitrary elements by key
diff --git a/extra/benchmark/fib6/deploy.factor b/extra/benchmark/fib6/deploy.factor
new file mode 100644 (file)
index 0000000..3a367dc
--- /dev/null
@@ -0,0 +1,15 @@
+USING: tools.deploy.config ;
+H{
+    { deploy-name "benchmark.fib6" }
+    { deploy-threads? f }
+    { deploy-math? f }
+    { deploy-word-props? f }
+    { deploy-ui? f }
+    { deploy-io 1 }
+    { deploy-compiler? t }
+    { deploy-reflection 1 }
+    { "stop-after-last-window?" t }
+    { deploy-unicode? f }
+    { deploy-word-defs? f }
+    { deploy-c-types? f }
+}
index a4df1fe04dd992a706ce11e684571c419247205a..642b3dbb934cda14f88f578ce076b0eafe2898a6 100755 (executable)
@@ -53,7 +53,7 @@ C: <sphere> sphere
 
 : sphere-t ( b d -- t )
     -+ dup 0.0 <
-    [ 2drop 1.0/0.0 ] [ [ [ 0.0 > ] keep ] dip ? ] if ; inline
+    [ 2drop 1/0. ] [ [ [ 0.0 > ] keep ] dip ? ] if ; inline
 
 : sphere-b&v ( sphere ray -- b v )
     [ sphere-v ] [ nip ] 2bi
diff --git a/extra/c/preprocessor/authors.txt b/extra/c/preprocessor/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/c/preprocessor/preprocessor-tests.factor b/extra/c/preprocessor/preprocessor-tests.factor
new file mode 100644 (file)
index 0000000..ba0531d
--- /dev/null
@@ -0,0 +1,26 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test c.preprocessor kernel accessors multiline ;
+IN: c.preprocessor.tests
+
+[ "vocab:c/tests/test1/test1.c" start-preprocess-file ]
+[ include-nested-too-deeply? ] must-fail-with
+
+[ "yo\n\n\n\nyo4\n" ]
+[ "vocab:c/tests/test2/test2.c" start-preprocess-file nip ] unit-test
+
+/*
+[ "vocab:c/tests/test3/test3.c" start-preprocess-file ]
+[ "\"BOO\"" = ] must-fail-with
+*/
+
+[ V{ "\"omg\"" "\"lol\"" } ]
+[ "vocab:c/tests/test4/test4.c" start-preprocess-file drop warnings>> ] unit-test
+
+
+/*
+f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); 
+f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); 
+int i[] = { 1, 23, 4, 5, }; 
+char c[2][6] = { "hello", "" }; 
+*/
diff --git a/extra/c/preprocessor/preprocessor.factor b/extra/c/preprocessor/preprocessor.factor
new file mode 100644 (file)
index 0000000..f787bef
--- /dev/null
@@ -0,0 +1,201 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: sequence-parser io io.encodings.utf8 io.files
+io.streams.string kernel combinators accessors io.pathnames
+fry sequences arrays locals namespaces io.directories
+assocs math splitting make unicode.categories
+combinators.short-circuit ;
+IN: c.preprocessor
+
+: initial-library-paths ( -- seq )
+    V{ "/usr/include" } clone ;
+
+: initial-symbol-table ( -- hashtable )
+    H{
+        { "__APPLE__" "" }
+        { "__amd64__" "" }
+        { "__x86_64__" "" }
+    } clone ;
+
+TUPLE: preprocessor-state library-paths symbol-table
+include-nesting include-nesting-max processing-disabled?
+ifdef-nesting warnings errors
+pragmas
+include-nexts
+ifs elifs elses ;
+
+: <preprocessor-state> ( -- preprocessor-state )
+    preprocessor-state new
+        initial-library-paths >>library-paths
+        initial-symbol-table >>symbol-table
+        0 >>include-nesting
+        200 >>include-nesting-max
+        0 >>ifdef-nesting
+        V{ } clone >>warnings
+        V{ } clone >>errors
+        V{ } clone >>pragmas
+        V{ } clone >>include-nexts
+        V{ } clone >>ifs
+        V{ } clone >>elifs
+        V{ } clone >>elses ;
+
+DEFER: preprocess-file
+
+ERROR: unknown-c-preprocessor sequence-parser name ;
+
+ERROR: bad-include-line line ;
+
+ERROR: header-file-missing path ;
+
+:: read-standard-include ( preprocessor-state path -- )
+    preprocessor-state dup library-paths>>
+    [ path append-path exists? ] find nip
+    [
+        dup [
+            path append-path
+            preprocess-file
+        ] with-directory
+    ] [
+        ! path header-file-missing
+        drop
+    ] if* ;
+
+:: read-local-include ( preprocessor-state path -- )
+    current-directory get path append-path dup :> full-path
+    dup exists? [
+        [ preprocessor-state ] dip preprocess-file
+    ] [
+        ! full-path header-file-missing
+        drop
+    ] if ;
+
+: skip-whitespace/comments ( sequence-parser -- sequence-parser )
+    skip-whitespace
+    {
+        { [ dup take-c-comment ] [ skip-whitespace/comments ] }
+        { [ dup take-c++-comment ] [ skip-whitespace/comments ] }
+        [ ]
+    } cond ;
+
+: handle-include ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments advance dup previous {
+        { CHAR: < [ CHAR: > take-until-object read-standard-include ] }
+        { CHAR: " [ CHAR: " take-until-object read-local-include ] }
+        [ bad-include-line ]
+    } case ;
+
+: (readlns) ( -- )
+    readln "\\" ?tail [ , ] dip [ (readlns) ] when ;
+
+: readlns ( -- string ) [ (readlns) ] { } make concat ;
+
+: take-define-identifier ( sequence-parser -- string )
+    skip-whitespace/comments
+    [ current { [ blank? ] [ CHAR: ( = ] } 1|| ] take-until ;
+
+: handle-define ( preprocessor-state sequence-parser -- )
+    [ take-define-identifier ]
+    [ skip-whitespace/comments take-rest ] bi 
+    "\\" ?tail [ readlns append ] when
+    spin symbol-table>> set-at ;
+
+: handle-undef ( preprocessor-state sequence-parser -- )
+    take-token swap symbol-table>> delete-at ;
+
+: handle-ifdef ( preprocessor-state sequence-parser -- )
+    [ [ 1 + ] change-ifdef-nesting ] dip
+    take-token over symbol-table>> key?
+    [ drop ] [ t >>processing-disabled? drop ] if ;
+
+: handle-ifndef ( preprocessor-state sequence-parser -- )
+    [ [ 1 + ] change-ifdef-nesting ] dip
+    take-token over symbol-table>> key?
+    [ t >>processing-disabled? drop ]
+    [ drop ] if ; 
+
+: handle-endif ( preprocessor-state sequence-parser -- )
+    drop [ 1 - ] change-ifdef-nesting drop ;
+
+: handle-if ( preprocessor-state sequence-parser -- )
+    [ [ 1 + ] change-ifdef-nesting ] dip
+    skip-whitespace/comments take-rest swap ifs>> push ;
+
+: handle-elif ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments take-rest swap elifs>> push ;
+
+: handle-else ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments take-rest swap elses>> push ;
+
+: handle-pragma ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments take-rest swap pragmas>> push ;
+
+: handle-include-next ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments take-rest swap include-nexts>> push ;
+
+: handle-error ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments take-rest swap errors>> push ;
+    ! nip take-rest throw ;
+
+: handle-warning ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments
+    take-rest swap warnings>> push ;
+
+: parse-directive ( preprocessor-state sequence-parser string -- )
+    {
+        { "warning" [ handle-warning ] }
+        { "error" [ handle-error ] }
+        { "include" [ handle-include ] }
+        { "define" [ handle-define ] }
+        { "undef" [ handle-undef ] }
+        { "ifdef" [ handle-ifdef ] }
+        { "ifndef" [ handle-ifndef ] }
+        { "endif" [ handle-endif ] }
+        { "if" [ handle-if ] }
+        { "elif" [ handle-elif ] }
+        { "else" [ handle-else ] }
+        { "pragma" [ handle-pragma ] }
+        { "include_next" [ handle-include-next ] }
+        [ unknown-c-preprocessor ]
+    } case ;
+
+: parse-directive-line ( preprocessor-state sequence-parser -- )
+    advance dup take-token
+    pick processing-disabled?>> [
+        "endif" = [
+            drop f >>processing-disabled?
+            [ 1 - ] change-ifdef-nesting
+            drop
+         ] [ 2drop ] if
+    ] [
+        parse-directive
+    ] if ;
+
+: preprocess-line ( preprocessor-state sequence-parser -- )
+    skip-whitespace/comments dup current CHAR: # =
+    [ parse-directive-line ]
+    [ swap processing-disabled?>> [ drop ] [ write-full nl ] if ] if ;
+
+: preprocess-lines ( preprocessor-state -- )
+    readln 
+    [ <sequence-parser> [ preprocess-line ] [ drop preprocess-lines ] 2bi ]
+    [ drop ] if* ;
+
+ERROR: include-nested-too-deeply ;
+
+: check-nesting ( preprocessor-state -- preprocessor-state )
+    [ 1 + ] change-include-nesting
+    dup [ include-nesting>> ] [ include-nesting-max>> ] bi > [
+        include-nested-too-deeply
+    ] when ;
+
+: preprocess-file ( preprocessor-state path -- )
+    [ check-nesting ] dip
+    [ utf8 [ preprocess-lines ] with-file-reader ]
+    [ drop [ 1 - ] change-include-nesting drop ] 2bi ;
+
+: start-preprocess-file ( path -- preprocessor-state string )
+    dup parent-directory [
+        [
+            [ <preprocessor-state> dup ] dip preprocess-file
+        ] with-string-writer
+    ] with-directory ;
diff --git a/extra/c/tests/test1/README b/extra/c/tests/test1/README
new file mode 100644 (file)
index 0000000..9987313
--- /dev/null
@@ -0,0 +1 @@
+Tests if the preprocessor bails on an infinite loop caused by mutually recursive #include lines.
diff --git a/extra/c/tests/test1/hi.h b/extra/c/tests/test1/hi.h
new file mode 100644 (file)
index 0000000..c9f337c
--- /dev/null
@@ -0,0 +1 @@
+#include "lo.h"
diff --git a/extra/c/tests/test1/lo.h b/extra/c/tests/test1/lo.h
new file mode 100644 (file)
index 0000000..d59fdd2
--- /dev/null
@@ -0,0 +1 @@
+#include "hi.h"
diff --git a/extra/c/tests/test1/test1.c b/extra/c/tests/test1/test1.c
new file mode 100644 (file)
index 0000000..d59fdd2
--- /dev/null
@@ -0,0 +1 @@
+#include "hi.h"
diff --git a/extra/c/tests/test10/test10.c b/extra/c/tests/test10/test10.c
new file mode 100644 (file)
index 0000000..7f38e70
--- /dev/null
@@ -0,0 +1,3 @@
+/*
+# lol
+*/
diff --git a/extra/c/tests/test11/foo.h b/extra/c/tests/test11/foo.h
new file mode 100644 (file)
index 0000000..381b753
--- /dev/null
@@ -0,0 +1 @@
+foo.h ftw
diff --git a/extra/c/tests/test11/test11.c b/extra/c/tests/test11/test11.c
new file mode 100644 (file)
index 0000000..1b05118
--- /dev/null
@@ -0,0 +1,2 @@
+#define FOO_H "foo.h"
+#include FOO_H
diff --git a/extra/c/tests/test12/test12.c b/extra/c/tests/test12/test12.c
new file mode 100644 (file)
index 0000000..2da127b
--- /dev/null
@@ -0,0 +1,3 @@
+#if 4 > (5 - 4++)
+#error "Umm"
+#endif
diff --git a/extra/c/tests/test13/test13.c b/extra/c/tests/test13/test13.c
new file mode 100644 (file)
index 0000000..13c48ff
--- /dev/null
@@ -0,0 +1,2 @@
+#if 10
+#error "Umm"
diff --git a/extra/c/tests/test14/test14.c b/extra/c/tests/test14/test14.c
new file mode 100644 (file)
index 0000000..1697ea1
--- /dev/null
@@ -0,0 +1,15 @@
+#if 4 > (1 + 2) 
+good
+#endif
+
+#if 4 > 1 + 2
+good
+#endif
+
+#if (4 > 1) - 1
+bad
+#endif
+
+#if (4 > 1) - 2
+good
+#endif
diff --git a/extra/c/tests/test2/README b/extra/c/tests/test2/README
new file mode 100644 (file)
index 0000000..4244828
--- /dev/null
@@ -0,0 +1 @@
+Tests whether #define and #ifdef/#endif work in the positive case.
diff --git a/extra/c/tests/test2/test2.c b/extra/c/tests/test2/test2.c
new file mode 100644 (file)
index 0000000..4cc4191
--- /dev/null
@@ -0,0 +1,17 @@
+#define YO
+#ifdef YO
+yo
+#endif
+
+#define YO2
+#ifndef YO2
+yo2
+#endif
+
+#ifdef YO3
+yo3
+#endif
+
+#ifndef YO4
+yo4
+#endif
diff --git a/extra/c/tests/test3/README b/extra/c/tests/test3/README
new file mode 100644 (file)
index 0000000..4244828
--- /dev/null
@@ -0,0 +1 @@
+Tests whether #define and #ifdef/#endif work in the positive case.
diff --git a/extra/c/tests/test3/test3.c b/extra/c/tests/test3/test3.c
new file mode 100644 (file)
index 0000000..8d08e83
--- /dev/null
@@ -0,0 +1 @@
+#error "BOO"
diff --git a/extra/c/tests/test4/test4.c b/extra/c/tests/test4/test4.c
new file mode 100644 (file)
index 0000000..5acd20d
--- /dev/null
@@ -0,0 +1,2 @@
+#warning "omg"
+#warning "lol"
diff --git a/extra/c/tests/test5/test5.c b/extra/c/tests/test5/test5.c
new file mode 100644 (file)
index 0000000..4c16964
--- /dev/null
@@ -0,0 +1,3 @@
+#define TABSIZE 100
+
+int table[TABSIZE];
diff --git a/extra/c/tests/test6/test6.c b/extra/c/tests/test6/test6.c
new file mode 100644 (file)
index 0000000..3b0353a
--- /dev/null
@@ -0,0 +1 @@
+#define max(a, b) ((a) > (b) ? (a) : (b))
diff --git a/extra/c/tests/test7/test7.c b/extra/c/tests/test7/test7.c
new file mode 100644 (file)
index 0000000..4d5e66b
--- /dev/null
@@ -0,0 +1,19 @@
+#define x 3 
+#define f(a) f(x * (a)) 
+#undef x 
+#define x 2 
+#define g f 
+#define z z[0] 
+#define h g(~ 
+#define m(a) a(w) 
+#define w 0,1 
+#define t(a) a 
+#define p() int 
+#define q(x) x 
+#define r(x,y) x ## y 
+#define str(x) # x 
+f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); 
+g(x+(3,4)-w) | h 5) & m 
+(f)^m(m); 
+p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; 
+char c[2][6] = { str(hello), str() }; 
diff --git a/extra/c/tests/test8/test8.c b/extra/c/tests/test8/test8.c
new file mode 100644 (file)
index 0000000..bc1e273
--- /dev/null
@@ -0,0 +1,15 @@
+#define str(s) #s 
+#define xstr(s) str(s) 
+#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ 
+x ## s, x ## t) 
+#define INCFILE(n) vers ## n 
+#define glue(a, b) a## b 
+#define xglue(a, b) glue(a, b) 
+#define HIGHLOW "hello" 
+#define LOW LOW ", world" 
+debug(1, 2); 
+fputs(str(strncmp("abc\0d", "abc", '\4') //this goes away 
+== 0) str(: @\n), s); 
+#include xstr(INCFILE(2).h) 
+glue(HIGH, LOW); 
+xglue(HIGH, LOW) 
diff --git a/extra/c/tests/test9/test9.c b/extra/c/tests/test9/test9.c
new file mode 100644 (file)
index 0000000..86940cf
--- /dev/null
@@ -0,0 +1,4 @@
+#define t(x,y,z) x ## y ## z 
+int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), 
+t(10,,), t(,11,), t(,,12), t(,,) }; 
+
diff --git a/extra/chicago-talk/deploy.factor b/extra/chicago-talk/deploy.factor
new file mode 100755 (executable)
index 0000000..8f8adc1
--- /dev/null
@@ -0,0 +1,12 @@
+USING: tools.deploy.config ;
+V{
+    { deploy-ui? t }
+    { deploy-io 1 }
+    { deploy-reflection 1 }
+    { deploy-compiler? t }
+    { deploy-math? t }
+    { deploy-word-props? f }
+    { deploy-c-types? f }
+    { "stop-after-last-window?" t }
+    { deploy-name "Chicago Talk" }
+}
diff --git a/extra/chicago-talk/summary.txt b/extra/chicago-talk/summary.txt
new file mode 100755 (executable)
index 0000000..229e1a3
--- /dev/null
@@ -0,0 +1 @@
+Slides for a talk at the Pycon VM Summit, Chicago, IL, March 2009
diff --git a/extra/chicago-talk/tags.txt b/extra/chicago-talk/tags.txt
new file mode 100644 (file)
index 0000000..cb5fc20
--- /dev/null
@@ -0,0 +1 @@
+demos
index fcb4dbd69d1654023e950a74506ee3168a215ee9..eeeb63dd7db86f61de4a72153f5b3d5f470a83d6 100755 (executable)
@@ -1,12 +1,15 @@
 USING: tools.deploy.config ;
-V{
-    { deploy-ui? t }
-    { deploy-io 1 }
-    { deploy-reflection 1 }
-    { deploy-compiler? t }
-    { deploy-math? t }
+H{
+    { deploy-name "Color Picker" }
     { deploy-word-props? f }
+    { deploy-ui? t }
+    { deploy-threads? t }
+    { deploy-unicode? f }
     { deploy-c-types? f }
+    { deploy-word-defs? f }
+    { deploy-compiler? t }
+    { deploy-io 2 }
+    { deploy-reflection 1 }
     { "stop-after-last-window?" t }
-    { deploy-name "Color Picker" }
+    { deploy-math? t }
 }
index 13a516eaf14621640d20174a63441770dfb493a3..0865dabcf7f17a69ae91fc6aa209102ef25e7654 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel accessors combinators.smart sorting.human
-models colors.constants present
+models colors.constants present sorting.slots
 ui ui.gadgets.tables ui.gadgets.scrollers ;
 IN: color-table
 
@@ -29,7 +29,7 @@ M: color-renderer row-value
     drop named-color ;
 
 : <color-table> ( -- table )
-    named-colors human-sort <model>
+    named-colors { human<=> } sort-by <model>
     color-renderer
     <table>
         5 >>gap
@@ -40,4 +40,4 @@ M: color-renderer row-value
 : color-table-demo ( -- )
     [ <color-table> <scroller> "Colors" open-window ] with-ui ;
 
-MAIN: color-table-demo
\ No newline at end of file
+MAIN: color-table-demo
diff --git a/extra/db2/authors.txt b/extra/db2/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/connections/authors.txt b/extra/db2/connections/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/connections/connections-tests.factor b/extra/db2/connections/connections-tests.factor
new file mode 100644 (file)
index 0000000..f96a201
--- /dev/null
@@ -0,0 +1,8 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test db2.connections db2.tester ;
+IN: db2.connections.tests
+
+! Tests connection
+
+{ 1 0 } [ [ ] with-db ] must-infer-as
diff --git a/extra/db2/connections/connections.factor b/extra/db2/connections/connections.factor
new file mode 100644 (file)
index 0000000..7957cb9
--- /dev/null
@@ -0,0 +1,20 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors destructors fry kernel namespaces ;
+IN: db2.connections
+
+TUPLE: db-connection handle ;
+
+: new-db-connection ( handle class -- db-connection )
+    new
+        swap >>handle ; inline
+
+GENERIC: db-open ( db -- db-connection )
+GENERIC: db-close ( handle  -- )
+
+M: db-connection dispose ( db-connection -- )
+    [ db-close ] [ f >>handle drop ] bi ;
+
+: with-db ( db quot -- )
+    [ db-open db-connection over ] dip
+    '[ _ [ drop @ ] with-disposal ] with-variable ; inline
diff --git a/extra/db2/db2-tests.factor b/extra/db2/db2-tests.factor
new file mode 100644 (file)
index 0000000..30ee7b3
--- /dev/null
@@ -0,0 +1,5 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test db2 kernel ;
+IN: db2.tests
+
diff --git a/extra/db2/db2.factor b/extra/db2/db2.factor
new file mode 100644 (file)
index 0000000..b14ee96
--- /dev/null
@@ -0,0 +1,78 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors continuations db2.result-sets db2.sqlite.lib
+db2.sqlite.result-sets db2.sqlite.statements db2.statements
+destructors fry kernel math namespaces sequences strings
+db2.sqlite.types ;
+IN: db2
+
+ERROR: no-in-types statement ;
+ERROR: no-out-types statement ;
+
+: guard-in ( statement -- statement )
+    dup in>> [ no-in-types ] unless ;
+
+: guard-out ( statement -- statement )
+    dup out>> [ no-out-types ] unless ;
+
+GENERIC: sql-command ( object -- )
+GENERIC: sql-query ( object -- sequence )
+GENERIC: sql-bind-command ( object -- )
+GENERIC: sql-bind-query ( object -- sequence )
+GENERIC: sql-bind-typed-command ( object -- )
+GENERIC: sql-bind-typed-query ( object -- sequence )
+
+M: string sql-command ( string -- )
+    f f <statement> sql-command ;
+
+M: string sql-query ( string -- sequence )
+    f f <statement> sql-query ;
+
+M: statement sql-command ( statement -- )
+    [ execute-statement ] with-disposal ;
+
+M: statement sql-query ( statement -- sequence )
+    [ statement>result-sequence ] with-disposal ;
+
+M: statement sql-bind-command ( statement -- )
+    [
+        guard-in
+        prepare-statement
+        [ bind-sequence ] [ statement>result-set drop ] bi
+    ] with-disposal ;
+
+M: statement sql-bind-query ( statement -- sequence )
+    [
+        guard-in
+        prepare-statement
+        [ bind-sequence ] [ statement>result-sequence ] bi
+    ] with-disposal ;
+
+M: statement sql-bind-typed-command ( statement -- )
+    [
+        guard-in
+        prepare-statement
+        [ bind-typed-sequence ] [ statement>result-set drop ] bi
+    ] with-disposal ;
+
+M: statement sql-bind-typed-query ( statement -- sequence )
+    [
+        guard-in
+        guard-out
+        prepare-statement
+        [ bind-typed-sequence ] [ statement>typed-result-sequence ] bi
+    ] with-disposal ;
+
+M: sequence sql-command [ sql-command ] each ;
+M: sequence sql-query [ sql-query ] map ;
+M: sequence sql-bind-command [ sql-bind-command ] each ;
+M: sequence sql-bind-query [ sql-bind-query ] map ;
+M: sequence sql-bind-typed-command [ sql-bind-typed-command ] each ;
+M: sequence sql-bind-typed-query [ sql-bind-typed-query ] map ;
+
+M: integer sql-command throw ;
+M: integer sql-query throw ;
+M: integer sql-bind-command throw ;
+M: integer sql-bind-query throw ;
+M: integer sql-bind-typed-command throw ;
+M: integer sql-bind-typed-query throw ;
diff --git a/extra/db2/errors/errors.factor b/extra/db2/errors/errors.factor
new file mode 100644 (file)
index 0000000..45353f6
--- /dev/null
@@ -0,0 +1,42 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel continuations fry words constructors
+db2.connections ;
+IN: db2.errors
+
+ERROR: db-error ;
+ERROR: sql-error location ;
+HOOK: parse-sql-error db-connection ( error -- error' )
+
+ERROR: sql-unknown-error < sql-error message ;
+CONSTRUCTOR: sql-unknown-error ( message -- error ) ;
+
+ERROR: sql-table-exists < sql-error table ;
+CONSTRUCTOR: sql-table-exists ( table -- error ) ;
+
+ERROR: sql-table-missing < sql-error table ;
+CONSTRUCTOR: sql-table-missing ( table -- error ) ;
+
+ERROR: sql-syntax-error < sql-error message ;
+CONSTRUCTOR: sql-syntax-error ( message -- error ) ;
+
+ERROR: sql-function-exists < sql-error message ;
+CONSTRUCTOR: sql-function-exists ( message -- error ) ;
+
+ERROR: sql-function-missing < sql-error message ;
+CONSTRUCTOR: sql-function-missing ( message -- error ) ;
+
+: ignore-error ( quot word -- )
+    '[ dup _ execute [ drop ] [ rethrow ] if ] recover ; inline
+
+: ignore-table-exists ( quot -- )
+    \ sql-table-exists? ignore-error ; inline
+
+: ignore-table-missing ( quot -- )
+    \ sql-table-missing? ignore-error ; inline
+
+: ignore-function-exists ( quot -- )
+    \ sql-function-exists? ignore-error ; inline
+
+: ignore-function-missing ( quot -- )
+    \ sql-function-missing? ignore-error ; inline
diff --git a/extra/db2/errors/summary.txt b/extra/db2/errors/summary.txt
new file mode 100644 (file)
index 0000000..1cd1021
--- /dev/null
@@ -0,0 +1 @@
+Errors thrown by database library
diff --git a/extra/db2/fql/authors.txt b/extra/db2/fql/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/fql/fql-tests.factor b/extra/db2/fql/fql-tests.factor
new file mode 100644 (file)
index 0000000..84698c0
--- /dev/null
@@ -0,0 +1,72 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors db2 db2.statements.tests db2.tester
+kernel tools.test db2.fql ;
+IN: db2.fql.tests
+
+: test-fql ( -- )
+    create-computer-table
+
+    [ "insert into computer (name, os) values (?, ?);" ]
+    [
+        "computer" { "name" "os" } { "lol" "os2" } <insert> expand-fql
+        sql>>
+    ] unit-test
+
+    [ "select name, os from computer" ]
+    [
+        select new
+            { "name" "os" } >>names
+            "computer" >>from
+        expand-fql sql>>
+    ] unit-test
+    
+    [ "select name, os from computer group by os order by lol offset 100 limit 3" ]
+    [
+        select new
+            { "name" "os" } >>names
+            "computer" >>from
+            "os" >>group-by
+            "lol" >>order-by
+            100 >>offset
+            3 >>limit
+        expand-fql sql>>
+    ] unit-test
+
+    [
+        "select name, os from computer where (hmm > 1 or foo is NULL) group by os order by lol offset 100 limit 3"
+    ] [
+        select new
+            { "name" "os" } >>names
+            "computer" >>from
+            T{ or f { "hmm > 1" "foo is NULL" } } >>where
+            "os" >>group-by
+            "lol" >>order-by
+            100 >>offset
+            3 >>limit
+        expand-fql sql>>
+    ] unit-test
+
+    [ "delete from computer order by omg limit 3" ]
+    [
+        delete new
+            "computer" >>tables
+            "omg" >>order-by
+            3 >>limit
+        expand-fql sql>>
+    ] unit-test
+
+    [ "update computer set name = oscar order by omg limit 3" ]
+    [
+        update new
+            "computer" >>tables
+            "name" >>keys
+            "oscar" >>values
+            "omg" >>order-by
+            3 >>limit
+        expand-fql sql>>
+    ] unit-test
+
+    ;
+
+[ test-fql ] test-dbs
diff --git a/extra/db2/fql/fql.factor b/extra/db2/fql/fql.factor
new file mode 100644 (file)
index 0000000..0896899
--- /dev/null
@@ -0,0 +1,116 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays combinators constructors db2
+db2.private db2.sqlite.lib db2.statements db2.utils destructors
+kernel make math.parser sequences strings assocs db2.utils ;
+IN: db2.fql
+
+GENERIC: expand-fql* ( object -- sequence/statement )
+GENERIC: normalize-fql ( object -- sequence/statement )
+
+! M: object normalize-fql ;
+
+TUPLE: insert into names values ;
+CONSTRUCTOR: insert ( into names values -- obj ) ;
+M: insert normalize-fql ( insert -- insert )
+    [ ??1array ] change-names ;
+
+TUPLE: update tables keys values where order-by limit ;
+CONSTRUCTOR: update ( tables keys values where -- obj ) ;
+M: update normalize-fql ( insert -- insert )
+    [ ??1array ] change-tables
+    [ ??1array ] change-keys
+    [ ??1array ] change-values
+    [ ??1array ] change-order-by ;
+
+TUPLE: delete tables where order-by limit ;
+CONSTRUCTOR: delete ( tables keys values where -- obj ) ;
+M: delete normalize-fql ( insert -- insert )
+    [ ??1array ] change-tables
+    [ ??1array ] change-order-by ;
+
+TUPLE: select names from where group-by order-by offset limit ;
+CONSTRUCTOR: select ( names from -- obj ) ;
+M: select normalize-fql ( select -- select )
+    [ ??1array ] change-names
+    [ ??1array ] change-from
+    [ ??1array ] change-group-by
+    [ ??1array ] change-order-by ;
+
+! TUPLE: where sequence ;
+! M: where normalize-fql ( where -- where )
+    ! [ ??1array ] change-sequence ;
+
+TUPLE: and sequence ;
+
+TUPLE: or sequence ;
+
+: expand-fql ( object1 -- object2 ) normalize-fql expand-fql* ;
+
+M: or expand-fql* ( obj -- string )
+    [
+        sequence>> "(" %
+        [ " or " % ] [ expand-fql* % ] interleave
+        ")" %
+    ] "" make ;
+
+M: and expand-fql* ( obj -- string )
+    [
+        sequence>> "(" %
+        [ " and " % ] [ expand-fql* % ] interleave
+        ")" %
+    ] "" make ;
+
+M: string expand-fql* ( string -- string ) ;
+
+M: insert expand-fql*
+    [ statement new ] dip
+    [
+        {
+            [ "insert into " % into>> % ]
+            [ " (" % names>> ", " join % ")" % ]
+            [ " values (" % values>> length "?" <array> ", " join % ");" % ]
+            [ values>> >>in ]
+        } cleave
+    ] "" make >>sql ;
+
+M: update expand-fql*
+    [ statement new ] dip
+    [
+        {
+            [ "update " % tables>> ", " join % ]
+            [
+                " set " % [ keys>> ] [ values>> ] bi 
+                zip [ ", " % ] [ first2 [ % ] dip " = " % % ] interleave
+            ]
+            ! [ "  " % from>> ", " join % ]
+            [ where>> [ " where " % expand-fql* % ] when* ]
+            [ order-by>> [ " order by " % ", " join % ] when* ]
+            [ limit>> [ " limit " % # ] when* ]
+        } cleave
+    ] "" make >>sql ;
+
+M: delete expand-fql*
+    [ statement new ] dip
+    [
+        {
+            [ "delete from " % tables>> ", " join % ]
+            [ where>> [ " where " % expand-fql* % ] when* ]
+                [ order-by>> [ " order by " % ", " join % ] when* ]
+            [ limit>> [ " limit " % # ] when* ]
+        } cleave
+    ] "" make >>sql ;
+
+M: select expand-fql*
+    [ statement new ] dip
+    [
+        {
+            [ "select " % names>> ", " join % ]
+            [ " from " % from>> ", " join % ]
+            [ where>> [ " where " % expand-fql* % ] when* ]
+            [ group-by>> [ " group by " % ", " join % ] when* ]
+            [ order-by>> [ " order by " % ", " join % ] when* ]
+            [ offset>> [ " offset " % # ] when* ]
+            [ limit>> [ " limit " % # ] when* ]
+        } cleave
+    ] "" make >>sql ;
diff --git a/extra/db2/introspection/authors.txt b/extra/db2/introspection/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/introspection/introspection.factor b/extra/db2/introspection/introspection.factor
new file mode 100644 (file)
index 0000000..8ab0887
--- /dev/null
@@ -0,0 +1,34 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: combinators constructors db2.connections
+db2.sqlite.types kernel sequence-parser sequences splitting ;
+IN: db2.introspection
+
+TUPLE: table-schema table columns ;
+CONSTRUCTOR: table-schema ( table columns -- table-schema ) ;
+
+TUPLE: column name type modifiers ;
+CONSTRUCTOR: column ( name type modifiers -- column ) ;
+
+HOOK: query-table-schema* db-connection ( name -- table-schema )
+HOOK: parse-create-statement db-connection ( name -- table-schema )
+
+: parse-column ( string -- column )
+    <sequence-parser> skip-whitespace
+    [ " " take-until-sequence ]
+    [ take-token sqlite-type>fql-type ]
+    [ take-rest ] tri <column> ;
+
+: parse-columns ( string -- seq )
+    "," split [ parse-column ] map ;
+
+M: object parse-create-statement ( string -- table-schema )
+    <sequence-parser> {
+        [ "CREATE TABLE " take-sequence* ]
+        [ "(" take-until-sequence ]
+        [ "(" take-sequence* ]
+        [ take-rest [ CHAR: ) = ] trim-tail parse-columns ]
+    } cleave <table-schema> ;
+
+: query-table-schema ( name -- table-schema )
+    query-table-schema* [ parse-create-statement ] map ;
diff --git a/extra/db2/pools/authors.txt b/extra/db2/pools/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/extra/db2/pools/pools-tests.factor b/extra/db2/pools/pools-tests.factor
new file mode 100644 (file)
index 0000000..d61b745
--- /dev/null
@@ -0,0 +1,23 @@
+USING: accessors continuations db2.pools db2.sqlite
+db2.sqlite.connections destructors io.directories io.files
+io.files.temp kernel math namespaces tools.test
+db2.sqlite.connections ;
+IN: db2.pools.tests
+
+\ <db-pool> must-infer
+
+{ 1 0 } [ [ ] with-db-pool ] must-infer-as
+
+{ 1 0 } [ [ ] with-pooled-db ] must-infer-as
+
+! Test behavior after image save/load
+
+[ "pool-test.db" temp-file delete-file ] ignore-errors
+
+[ ] [ "pool-test.db" temp-file <sqlite-db> <db-pool> "pool" set ] unit-test
+
+[ ] [ "pool" get expired>> t >>expired drop ] unit-test
+
+[ ] [ 1000 [ "pool" get [ ] with-pooled-db ] times ] unit-test
+
+[ ] [ "pool" get dispose ] unit-test
diff --git a/extra/db2/pools/pools.factor b/extra/db2/pools/pools.factor
new file mode 100644 (file)
index 0000000..2b1aa2f
--- /dev/null
@@ -0,0 +1,20 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors db2.connections fry io.pools kernel
+namespaces ;
+IN: db2.pools
+
+TUPLE: db-pool < pool db ;
+
+: <db-pool> ( db -- pool )
+    db-pool <pool>
+        swap >>db ;
+
+: with-db-pool ( db quot -- )
+    [ <db-pool> ] dip with-pool ; inline
+
+M: db-pool make-connection ( pool -- )
+    db>> db-open ;
+
+: with-pooled-db ( pool quot -- )
+    '[ db-connection _ with-variable ] with-pooled-connection ; inline
diff --git a/extra/db2/result-sets/authors.txt b/extra/db2/result-sets/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/result-sets/result-sets.factor b/extra/db2/result-sets/result-sets.factor
new file mode 100644 (file)
index 0000000..4998089
--- /dev/null
@@ -0,0 +1,33 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel sequences combinators fry ;
+IN: db2.result-sets
+
+TUPLE: result-set sql in out handle n max ;
+
+GENERIC: #rows ( result-set -- n )
+GENERIC: #columns ( result-set -- n )
+GENERIC: advance-row ( result-set -- )
+GENERIC: more-rows? ( result-set -- ? )
+GENERIC# column 1 ( result-set column -- obj )
+GENERIC# column-typed 2 ( result-set column type -- sql )
+
+: init-result-set ( result-set -- result-set )
+    dup #rows >>max
+    0 >>n ;
+
+: new-result-set ( query class -- result-set )
+    new
+        swap {
+            [ handle>> >>handle ]
+            [ sql>> >>sql ]
+            [ in>> >>in ]
+            [ out>> >>out ]
+        } cleave ;
+
+: sql-row ( result-set -- seq )
+    dup #columns [ column ] with map ;
+
+: sql-row-typed ( result-set -- seq )
+    [ #columns ] [ out>> ] [ ] tri
+    '[ [ _ ] 2dip column-typed ] 2map ;
diff --git a/extra/db2/sqlite/authors.txt b/extra/db2/sqlite/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/connections/authors.txt b/extra/db2/sqlite/connections/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/connections/connections-tests.factor b/extra/db2/sqlite/connections/connections-tests.factor
new file mode 100644 (file)
index 0000000..ed80810
--- /dev/null
@@ -0,0 +1,4 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test db2.sqlite.connections ;
+IN: db2.sqlite.connections.tests
diff --git a/extra/db2/sqlite/connections/connections.factor b/extra/db2/sqlite/connections/connections.factor
new file mode 100644 (file)
index 0000000..ae96e58
--- /dev/null
@@ -0,0 +1,17 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators db2.connections db2.sqlite
+db2.sqlite.errors db2.sqlite.lib kernel db2.errors ;
+IN: db2.sqlite.connections
+
+M: sqlite-db db-open ( db -- db-connection )
+    path>> sqlite-open <sqlite-db-connection> ;
+
+M: sqlite-db-connection db-close ( db-connection -- )
+    handle>> sqlite-close ;
+
+M: sqlite-db-connection parse-sql-error ( error -- error' )
+    dup n>> {
+        { 1 [ string>> parse-sqlite-sql-error ] }
+        [ drop ]
+    } case ;
diff --git a/extra/db2/sqlite/db/authors.txt b/extra/db2/sqlite/db/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/db/db.factor b/extra/db2/sqlite/db/db.factor
new file mode 100644 (file)
index 0000000..d5d580c
--- /dev/null
@@ -0,0 +1,12 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors ;
+IN: db2.sqlite.db
+
+TUPLE: sqlite-db path ;
+
+: <sqlite-db> ( path -- sqlite-db )
+    sqlite-db new
+        swap >>path ;
+
+
diff --git a/extra/db2/sqlite/errors/authors.txt b/extra/db2/sqlite/errors/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/errors/errors.factor b/extra/db2/sqlite/errors/errors.factor
new file mode 100644 (file)
index 0000000..61e70f2
--- /dev/null
@@ -0,0 +1,35 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators db2.connections db2.errors
+db2.sqlite.ffi kernel locals namespaces peg.ebnf sequences
+strings ;
+IN: db2.sqlite.errors
+
+ERROR: sqlite-error < db-error n string ;
+ERROR: sqlite-sql-error < sql-error n string ;
+
+: sqlite-statement-error ( -- * )
+    SQLITE_ERROR
+    db-connection get handle>> sqlite3_errmsg sqlite-sql-error ;
+
+TUPLE: unparsed-sqlite-error error ;
+C: <unparsed-sqlite-error> unparsed-sqlite-error
+
+EBNF: parse-sqlite-sql-error
+
+TableMessage = " already exists"
+SyntaxError = ": syntax error"
+
+SqliteError =
+    "table " (!(TableMessage).)+:table TableMessage:message
+      => [[ table >string <sql-table-exists> ]]
+    | "near " (!(SyntaxError).)+:syntax SyntaxError:message
+      => [[ syntax >string <sql-syntax-error> ]]
+    | "no such table: " .+:table
+      => [[ table >string <sql-table-missing> ]]
+    | .*:error
+      => [[ error >string <unparsed-sqlite-error> ]]
+;EBNF
+
+: throw-sqlite-error ( n -- * )
+    dup sqlite-error-messages nth sqlite-error ;
diff --git a/extra/db2/sqlite/ffi/ffi.factor b/extra/db2/sqlite/ffi/ffi.factor
new file mode 100644 (file)
index 0000000..2594978
--- /dev/null
@@ -0,0 +1,142 @@
+! Copyright (C) 2005 Chris Double, Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+! Not all functions have been wrapped.
+USING: alien alien.libraries alien.syntax combinators system ;
+IN: db2.sqlite.ffi
+
+<< "sqlite" {
+        { [ os winnt? ]  [ "sqlite3.dll" ] }
+        { [ os macosx? ] [ "/usr/lib/libsqlite3.dylib" ] }
+        { [ os unix? ]  [ "libsqlite3.so" ] }
+    } cond "cdecl" add-library >>
+
+LIBRARY: sqlite
+
+! Return values from sqlite functions
+CONSTANT: SQLITE_OK           0 ! Successful result
+CONSTANT: SQLITE_ERROR        1 ! SQL error or missing database
+CONSTANT: SQLITE_INTERNAL     2 ! An internal logic error in SQLite 
+CONSTANT: SQLITE_PERM         3 ! Access permission denied 
+CONSTANT: SQLITE_ABORT        4 ! Callback routine requested an abort 
+CONSTANT: SQLITE_BUSY         5 ! The database file is locked 
+CONSTANT: SQLITE_LOCKED       6 ! A table in the database is locked 
+CONSTANT: SQLITE_NOMEM        7 ! A malloc() failed 
+CONSTANT: SQLITE_READONLY     8 ! Attempt to write a readonly database 
+CONSTANT: SQLITE_INTERRUPT    9 ! Operation terminated by sqlite_interrupt() 
+CONSTANT: SQLITE_IOERR       10 ! Some kind of disk I/O error occurred 
+CONSTANT: SQLITE_CORRUPT     11 ! The database disk image is malformed 
+CONSTANT: SQLITE_NOTFOUND    12 ! (Internal Only) Table or record not found 
+CONSTANT: SQLITE_FULL        13 ! Insertion failed because database is full 
+CONSTANT: SQLITE_CANTOPEN    14 ! Unable to open the database file 
+CONSTANT: SQLITE_PROTOCOL    15 ! Database lock protocol error 
+CONSTANT: SQLITE_EMPTY       16 ! (Internal Only) Database table is empty 
+CONSTANT: SQLITE_SCHEMA      17 ! The database schema changed 
+CONSTANT: SQLITE_TOOBIG      18 ! Too much data for one row of a table 
+CONSTANT: SQLITE_CONSTRAINT  19 ! Abort due to contraint violation 
+CONSTANT: SQLITE_MISMATCH    20 ! Data type mismatch 
+CONSTANT: SQLITE_MISUSE      21 ! Library used incorrectly 
+CONSTANT: SQLITE_NOLFS       22 ! Uses OS features not supported on host 
+CONSTANT: SQLITE_AUTH        23 ! Authorization denied 
+CONSTANT: SQLITE_FORMAT      24 ! Auxiliary database format error
+CONSTANT: SQLITE_RANGE       25 ! 2nd parameter to sqlite3_bind out of range
+CONSTANT: SQLITE_NOTADB      26 ! File opened that is not a database file
+
+CONSTANT: sqlite-error-messages
+{
+    "Successful result"
+    "SQL error or missing database"
+    "An internal logic error in SQLite"
+    "Access permission denied"
+    "Callback routine requested an abort"
+    "The database file is locked"
+    "A table in the database is locked"
+    "A malloc() failed"
+    "Attempt to write a readonly database"
+    "Operation terminated by sqlite_interrupt()"
+    "Some kind of disk I/O error occurred"
+    "The database disk image is malformed"
+    "(Internal Only) Table or record not found"
+    "Insertion failed because database is full"
+    "Unable to open the database file"
+    "Database lock protocol error"
+    "(Internal Only) Database table is empty"
+    "The database schema changed"
+    "Too much data for one row of a table"
+    "Abort due to contraint violation"
+    "Data type mismatch"
+    "Library used incorrectly"
+    "Uses OS features not supported on host"
+    "Authorization denied"
+    "Auxiliary database format error"
+    "2nd parameter to sqlite3_bind out of range"
+    "File opened that is not a database file"
+}
+
+! Return values from sqlite3_step
+CONSTANT: SQLITE_ROW         100
+CONSTANT: SQLITE_DONE        101
+
+! Return values from the sqlite3_column_type function
+CONSTANT: SQLITE_INTEGER     1
+CONSTANT: SQLITE_FLOAT       2
+CONSTANT: SQLITE_TEXT        3
+CONSTANT: SQLITE_BLOB        4
+CONSTANT: SQLITE_NULL        5
+
+! Values for the 'destructor' parameter of the 'bind' routines. 
+CONSTANT: SQLITE_STATIC      0
+CONSTANT: SQLITE_TRANSIENT   -1
+
+CONSTANT: SQLITE_OPEN_READONLY         HEX: 00000001
+CONSTANT: SQLITE_OPEN_READWRITE        HEX: 00000002
+CONSTANT: SQLITE_OPEN_CREATE           HEX: 00000004
+CONSTANT: SQLITE_OPEN_DELETEONCLOSE    HEX: 00000008
+CONSTANT: SQLITE_OPEN_EXCLUSIVE        HEX: 00000010
+CONSTANT: SQLITE_OPEN_MAIN_DB          HEX: 00000100
+CONSTANT: SQLITE_OPEN_TEMP_DB          HEX: 00000200
+CONSTANT: SQLITE_OPEN_TRANSIENT_DB     HEX: 00000400
+CONSTANT: SQLITE_OPEN_MAIN_JOURNAL     HEX: 00000800
+CONSTANT: SQLITE_OPEN_TEMP_JOURNAL     HEX: 00001000
+CONSTANT: SQLITE_OPEN_SUBJOURNAL       HEX: 00002000
+CONSTANT: SQLITE_OPEN_MASTER_JOURNAL   HEX: 00004000
+
+TYPEDEF: void sqlite3
+TYPEDEF: void sqlite3_stmt
+TYPEDEF: longlong sqlite3_int64
+TYPEDEF: ulonglong sqlite3_uint64
+
+FUNCTION: int sqlite3_open ( char* filename, void* ppDb ) ;
+FUNCTION: int sqlite3_close ( sqlite3* pDb ) ;
+FUNCTION: char* sqlite3_errmsg ( sqlite3* pDb ) ;
+FUNCTION: int sqlite3_prepare ( sqlite3* pDb, char* zSql, int nBytes, void* ppStmt, void* pzTail ) ;
+FUNCTION: int sqlite3_prepare_v2 ( sqlite3* pDb, char* zSql, int nBytes, void* ppStmt, void* pzTail ) ;
+FUNCTION: int sqlite3_finalize ( sqlite3_stmt* pStmt ) ;
+FUNCTION: int sqlite3_reset ( sqlite3_stmt* pStmt ) ;
+FUNCTION: int sqlite3_step ( sqlite3_stmt* pStmt ) ;
+FUNCTION: sqlite3_uint64 sqlite3_last_insert_rowid ( sqlite3* pStmt ) ;
+FUNCTION: int sqlite3_bind_blob ( sqlite3_stmt* pStmt, int index, void* ptr, int len, int destructor ) ;
+FUNCTION: int sqlite3_bind_double ( sqlite3_stmt* pStmt, int index, double x ) ;
+FUNCTION: int sqlite3_bind_int ( sqlite3_stmt* pStmt, int index, int n ) ;
+FUNCTION: int sqlite3_bind_int64 ( sqlite3_stmt* pStmt, int index, sqlite3_int64 n ) ;
+! Bind the same function as above, but for unsigned 64bit integers
+: sqlite3-bind-uint64 ( pStmt index in64 -- int )
+    "int" "sqlite" "sqlite3_bind_int64"
+    { "sqlite3_stmt*" "int" "sqlite3_uint64" } alien-invoke ;
+FUNCTION: int sqlite3_bind_null ( sqlite3_stmt* pStmt, int n ) ;
+FUNCTION: int sqlite3_bind_text ( sqlite3_stmt* pStmt, int index, char* text, int len, int destructor ) ;
+FUNCTION: int sqlite3_bind_parameter_index ( sqlite3_stmt* pStmt, char* name ) ;
+FUNCTION: int sqlite3_clear_bindings ( sqlite3_stmt* pStmt ) ;
+FUNCTION: int sqlite3_column_count ( sqlite3_stmt* pStmt ) ;
+FUNCTION: void* sqlite3_column_blob ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: int sqlite3_column_bytes ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: char* sqlite3_column_decltype ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: int sqlite3_column_int ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: sqlite3_int64 sqlite3_column_int64 ( sqlite3_stmt* pStmt, int col ) ;
+! Bind the same function as above, but for unsigned 64bit integers
+: sqlite3-column-uint64 ( pStmt col -- uint64 )
+    "sqlite3_uint64" "sqlite" "sqlite3_column_int64"
+    { "sqlite3_stmt*" "int" } alien-invoke ;
+FUNCTION: double sqlite3_column_double ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: char* sqlite3_column_name ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: char* sqlite3_column_text ( sqlite3_stmt* pStmt, int col ) ;
+FUNCTION: int sqlite3_column_type ( sqlite3_stmt* pStmt, int col ) ;
diff --git a/extra/db2/sqlite/introspection/authors.txt b/extra/db2/sqlite/introspection/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/introspection/introspection-tests.factor b/extra/db2/sqlite/introspection/introspection-tests.factor
new file mode 100644 (file)
index 0000000..d8ebc4d
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: db2.connections db2.introspection
+db2.sqlite.introspection db2.tester db2.types tools.test ;
+IN: db2.sqlite.introspection.tests
+
+
+: test-sqlite-introspection ( -- )
+    [
+        {
+            T{ table-schema
+                { table "computer" }
+                { columns
+                    {
+                        T{ column
+                            { name "name" }
+                            { type VARCHAR }
+                            { modifiers "" }
+                        }
+                        T{ column
+                            { name "os" }
+                            { type VARCHAR }
+                            { modifiers "" }
+                        }
+                    }
+                }
+            }
+        }
+    ] [
+        
+        sqlite-test-db [
+            "computer" query-table-schema
+        ] with-db
+    ] unit-test
+
+    ;
+
+[ test-sqlite-introspection ] test-sqlite
diff --git a/extra/db2/sqlite/introspection/introspection.factor b/extra/db2/sqlite/introspection/introspection.factor
new file mode 100644 (file)
index 0000000..41def2c
--- /dev/null
@@ -0,0 +1,16 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays db2 db2.introspection db2.sqlite multiline
+sequences ;
+IN: db2.sqlite.introspection
+
+M: sqlite-db-connection query-table-schema*
+    1array
+<"
+SELECT sql FROM 
+   (SELECT * FROM sqlite_master UNION ALL
+    SELECT * FROM sqlite_temp_master)
+WHERE type!='meta' and tbl_name = ?
+ORDER BY tbl_name, type DESC, name
+">
+    sql-bind-query* first ;
diff --git a/extra/db2/sqlite/lib/lib.factor b/extra/db2/sqlite/lib/lib.factor
new file mode 100644 (file)
index 0000000..e366305
--- /dev/null
@@ -0,0 +1,110 @@
+! Copyright (C) 2008 Chris Double, Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien.c-types arrays calendar.format
+combinators db2.sqlite.errors
+io.backend io.encodings.string io.encodings.utf8 kernel math
+namespaces present sequences serialize urls db2.sqlite.ffi ;
+IN: db2.sqlite.lib
+
+: sqlite-check-result ( n -- )
+    {
+        { SQLITE_OK [ ] }
+        { SQLITE_ERROR [ sqlite-statement-error ] }
+        [ throw-sqlite-error ]
+    } case ;
+
+: sqlite-open ( path -- db )
+    "void*" <c-object>
+    [ sqlite3_open sqlite-check-result ] keep *void* ;
+
+: sqlite-close ( db -- )
+    sqlite3_close sqlite-check-result ;
+
+: sqlite-prepare ( db sql -- handle )
+    utf8 encode dup length "void*" <c-object> "void*" <c-object>
+    [ sqlite3_prepare_v2 sqlite-check-result ] 2keep
+    drop *void* ;
+
+: sqlite-bind-parameter-index ( handle name -- index )
+    sqlite3_bind_parameter_index ;
+
+: parameter-index ( handle name text -- handle name text )
+    [ dupd sqlite-bind-parameter-index ] dip ;
+
+: sqlite-bind-text ( handle index text -- )
+    utf8 encode dup length SQLITE_TRANSIENT
+    sqlite3_bind_text sqlite-check-result ;
+
+: sqlite-bind-int ( handle i n -- )
+    sqlite3_bind_int sqlite-check-result ;
+
+: sqlite-bind-int64 ( handle i n -- )
+    sqlite3_bind_int64 sqlite-check-result ;
+
+: sqlite-bind-uint64 ( handle i n -- )
+    sqlite3-bind-uint64 sqlite-check-result ;
+
+: sqlite-bind-boolean ( handle name obj -- )
+    >boolean 1 0 ? sqlite-bind-int ;
+
+: sqlite-bind-double ( handle i x -- )
+    sqlite3_bind_double sqlite-check-result ;
+
+: sqlite-bind-null ( handle i -- )
+    sqlite3_bind_null sqlite-check-result ;
+
+: sqlite-bind-blob ( handle i byte-array -- )
+    dup length SQLITE_TRANSIENT
+    sqlite3_bind_blob sqlite-check-result ;
+
+: sqlite-bind-text-by-name ( handle name text -- )
+    parameter-index sqlite-bind-text ;
+
+: sqlite-bind-int-by-name ( handle name int -- )
+    parameter-index sqlite-bind-int ;
+
+: sqlite-bind-int64-by-name ( handle name int64 -- )
+    parameter-index sqlite-bind-int64 ;
+
+: sqlite-bind-uint64-by-name ( handle name int64 -- )
+    parameter-index sqlite-bind-uint64 ;
+
+: sqlite-bind-boolean-by-name ( handle name obj -- )
+    >boolean 1 0 ? parameter-index sqlite-bind-int ;
+
+: sqlite-bind-double-by-name ( handle name double -- )
+    parameter-index sqlite-bind-double ;
+
+: sqlite-bind-blob-by-name ( handle name blob -- )
+    parameter-index sqlite-bind-blob ;
+
+: sqlite-bind-null-by-name ( handle name obj -- )
+    parameter-index drop sqlite-bind-null ;
+
+: sqlite-finalize ( handle -- ) sqlite3_finalize sqlite-check-result ;
+: sqlite-reset ( handle -- ) sqlite3_reset sqlite-check-result ;
+: sqlite-clear-bindings ( handle -- )
+    sqlite3_clear_bindings sqlite-check-result ;
+: sqlite-#columns ( query -- int ) sqlite3_column_count ;
+: sqlite-column ( handle index -- string ) sqlite3_column_text ;
+: sqlite-column-name ( handle index -- string ) sqlite3_column_name ;
+: sqlite-column-type ( handle index -- string ) sqlite3_column_type ;
+
+: sqlite-column-blob ( handle index -- byte-array/f )
+    [ sqlite3_column_bytes ] 2keep
+    pick zero? [
+        3drop f
+    ] [
+        sqlite3_column_blob swap memory>byte-array
+    ] if ;
+
+: sqlite-step-has-more-rows? ( prepared -- ? )
+    {
+        { SQLITE_ROW [ t ] }
+        { SQLITE_DONE [ f ] }
+        [ sqlite-check-result f ]
+    } case ;
+
+: sqlite-next ( prepared -- ? )
+    sqlite3_step sqlite-step-has-more-rows? ;
+
diff --git a/extra/db2/sqlite/result-sets/authors.txt b/extra/db2/sqlite/result-sets/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/result-sets/result-sets.factor b/extra/db2/sqlite/result-sets/result-sets.factor
new file mode 100644 (file)
index 0000000..3b3226e
--- /dev/null
@@ -0,0 +1,30 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors db2.result-sets db2.sqlite.statements
+db2.statements kernel db2.sqlite.lib destructors
+db2.sqlite.types ;
+IN: db2.sqlite.result-sets
+
+TUPLE: sqlite-result-set < result-set has-more? ;
+
+M: sqlite-result-set dispose
+    f >>handle drop ;
+
+M: sqlite-statement statement>result-set*
+    prepare-statement
+    sqlite-result-set new-result-set dup advance-row ;
+
+M: sqlite-result-set advance-row ( result-set -- )
+    dup handle>> sqlite-next >>has-more? drop ;
+
+M: sqlite-result-set more-rows? ( result-set -- )
+    has-more?>> ;
+
+M: sqlite-result-set #columns ( result-set -- n )
+    handle>> sqlite-#columns ;
+
+M: sqlite-result-set column ( result-set n -- obj )
+    [ handle>> ] [ sqlite-column ] bi* ;
+
+M: sqlite-result-set column-typed ( result-set n type -- obj )
+    [ handle>> ] 2dip sqlite-type ;
diff --git a/extra/db2/sqlite/sqlite.factor b/extra/db2/sqlite/sqlite.factor
new file mode 100644 (file)
index 0000000..82337ae
--- /dev/null
@@ -0,0 +1,12 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: constructors db2.connections ;
+IN: db2.sqlite
+
+TUPLE: sqlite-db path ;
+CONSTRUCTOR: sqlite-db ( path -- sqlite-db ) ;
+
+TUPLE: sqlite-db-connection < db-connection ;
+
+: <sqlite-db-connection> ( handle -- db-connection )
+    sqlite-db-connection new-db-connection ;
diff --git a/extra/db2/sqlite/statements/authors.txt b/extra/db2/sqlite/statements/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/statements/statements.factor b/extra/db2/sqlite/statements/statements.factor
new file mode 100644 (file)
index 0000000..0033ad0
--- /dev/null
@@ -0,0 +1,19 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors db2.connections db2.sqlite.connections
+db2.sqlite.ffi db2.sqlite.lib db2.statements destructors kernel
+namespaces db2.sqlite ;
+IN: db2.sqlite.statements
+
+TUPLE: sqlite-statement < statement ;
+
+M: sqlite-db-connection <statement> ( string in out -- obj )
+    sqlite-statement new-statement ;
+
+M: sqlite-statement dispose
+    handle>>
+    [ [ sqlite3_reset drop ] [ sqlite-finalize ] bi ] when* ;
+
+M: sqlite-statement prepare-statement* ( statement -- statement )
+    db-connection get handle>> over sql>> sqlite-prepare
+    >>handle ;
diff --git a/extra/db2/sqlite/types/authors.txt b/extra/db2/sqlite/types/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/sqlite/types/types.factor b/extra/db2/sqlite/types/types.factor
new file mode 100644 (file)
index 0000000..d2047c1
--- /dev/null
@@ -0,0 +1,104 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays calendar.format combinators
+db2.sqlite.ffi db2.sqlite.lib db2.sqlite.statements
+db2.statements db2.types db2.utils fry kernel math present
+sequences serialize urls ;
+IN: db2.sqlite.types
+
+: (bind-sqlite-type) ( handle key value type -- )
+    dup array? [ first ] when
+    {
+        { INTEGER [ sqlite-bind-int-by-name ] }
+        { BIG-INTEGER [ sqlite-bind-int64-by-name ] }
+        { SIGNED-BIG-INTEGER [ sqlite-bind-int64-by-name ] }
+        { UNSIGNED-BIG-INTEGER [ sqlite-bind-uint64-by-name ] }
+        { BOOLEAN [ sqlite-bind-boolean-by-name ] }
+        { TEXT [ sqlite-bind-text-by-name ] }
+        { VARCHAR [ sqlite-bind-text-by-name ] }
+        { DOUBLE [ sqlite-bind-double-by-name ] }
+        { DATE [ timestamp>ymd sqlite-bind-text-by-name ] }
+        { TIME [ timestamp>hms sqlite-bind-text-by-name ] }
+        { DATETIME [ timestamp>ymdhms sqlite-bind-text-by-name ] }
+        { TIMESTAMP [ timestamp>ymdhms sqlite-bind-text-by-name ] }
+        { BLOB [ sqlite-bind-blob-by-name ] }
+        { FACTOR-BLOB [ object>bytes sqlite-bind-blob-by-name ] }
+        { URL [ present sqlite-bind-text-by-name ] }
+        { +db-assigned-id+ [ sqlite-bind-int-by-name ] }
+        { +random-id+ [ sqlite-bind-int64-by-name ] }
+        { NULL [ sqlite-bind-null-by-name ] }
+        [ no-sql-type ]
+    } case ;
+
+: bind-next-sqlite-type ( handle key value type -- )
+    dup array? [ first ] when
+    {
+        { INTEGER [ sqlite-bind-int ] }
+        { BIG-INTEGER [ sqlite-bind-int64 ] }
+        { SIGNED-BIG-INTEGER [ sqlite-bind-int64 ] }
+        { UNSIGNED-BIG-INTEGER [ sqlite-bind-uint64 ] }
+        { BOOLEAN [ sqlite-bind-boolean ] }
+        { TEXT [ sqlite-bind-text ] }
+        { VARCHAR [ sqlite-bind-text ] }
+        { DOUBLE [ sqlite-bind-double ] }
+        { DATE [ timestamp>ymd sqlite-bind-text ] }
+        { TIME [ timestamp>hms sqlite-bind-text ] }
+        { DATETIME [ timestamp>ymdhms sqlite-bind-text ] }
+        { TIMESTAMP [ timestamp>ymdhms sqlite-bind-text ] }
+        { BLOB [ sqlite-bind-blob ] }
+        { FACTOR-BLOB [ object>bytes sqlite-bind-blob ] }
+        { URL [ present sqlite-bind-text ] }
+        { +db-assigned-id+ [ sqlite-bind-int ] }
+        { +random-id+ [ sqlite-bind-int64 ] }
+        { NULL [ drop sqlite-bind-null ] }
+        [ no-sql-type ]
+    } case ;
+
+: bind-sqlite-type ( handle key value type -- )
+    #! null and empty values need to be set by sqlite-bind-null-by-name
+    over [
+        NULL = [ 2drop NULL NULL ] when
+    ] [
+        drop NULL
+    ] if* (bind-sqlite-type) ;
+
+: sqlite-type ( handle index type -- obj )
+    dup array? [ first ] when
+    {
+        { +db-assigned-id+ [ sqlite3_column_int64  ] }
+        { +random-id+ [ sqlite3-column-uint64 ] }
+        { INTEGER [ sqlite3_column_int ] }
+        { BIG-INTEGER [ sqlite3_column_int64 ] }
+        { SIGNED-BIG-INTEGER [ sqlite3_column_int64 ] }
+        { UNSIGNED-BIG-INTEGER [ sqlite3-column-uint64 ] }
+        { BOOLEAN [ sqlite3_column_int 1 = ] }
+        { DOUBLE [ sqlite3_column_double ] }
+        { TEXT [ sqlite3_column_text ] }
+        { VARCHAR [ sqlite3_column_text ] }
+        { DATE [ sqlite3_column_text [ ymd>timestamp ] ?when ] }
+        { TIME [ sqlite3_column_text [ hms>timestamp ] ?when ] }
+        { TIMESTAMP [ sqlite3_column_text [ ymdhms>timestamp ] ?when ] }
+        { DATETIME [ sqlite3_column_text [ ymdhms>timestamp ] ?when ] }
+        { BLOB [ sqlite-column-blob ] }
+        { URL [ sqlite3_column_text [ >url ] ?when ] }
+        { FACTOR-BLOB [ sqlite-column-blob [ bytes>object ] ?when ] }
+        [ no-sql-type ]
+    } case ;
+
+M: sqlite-statement bind-sequence ( statement -- )
+    [ in>> ] [ handle>> ] bi '[
+        [ _ ] 2dip 1+ swap sqlite-bind-text
+    ] each-index ;
+
+M: sqlite-statement bind-typed-sequence ( statement -- )
+    [ in>> ] [ handle>> ] bi '[
+        [ _ ] 2dip 1+ swap first2 swap bind-next-sqlite-type
+    ] each-index ;
+
+ERROR: no-fql-type type ;
+
+: sqlite-type>fql-type ( string -- type )
+    {
+        { "varchar" [ VARCHAR ] }
+        [ no-fql-type ]
+    } case ;
diff --git a/extra/db2/statements/authors.txt b/extra/db2/statements/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/statements/statements-tests.factor b/extra/db2/statements/statements-tests.factor
new file mode 100644 (file)
index 0000000..8a87229
--- /dev/null
@@ -0,0 +1,73 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test db2.statements kernel db2 db2.tester
+continuations db2.errors accessors db2.types ;
+IN: db2.statements.tests
+
+{ 1 0 } [ [ drop ] result-set-each ] must-infer-as
+{ 1 1 } [ [ ] result-set-map ] must-infer-as
+
+: create-computer-table ( -- )
+    [ "drop table computer;" sql-command ] ignore-errors
+
+    [ "drop table computer;" sql-command ]
+    [ [ sql-table-missing? ] [ table>> "computer" = ] bi and ] must-fail-with
+
+    [ ] [
+        "create table computer(name varchar, os varchar, version integer);"
+        sql-command
+    ] unit-test ;
+
+
+: test-sql-command ( -- )
+    create-computer-table
+    
+    [ ] [
+        "insert into computer (name, os) values('rocky', 'mac');"
+        sql-command
+    ] unit-test
+    
+    [ { { "rocky" "mac" } } ]
+    [
+        "select name, os from computer;"
+        f f <statement> sql-query
+    ] unit-test
+
+    [ "insert into" sql-command ]
+    [ sql-syntax-error? ] must-fail-with
+
+    [ "selectt" sql-query ]
+    [ sql-syntax-error? ] must-fail-with
+
+    [ ] [
+        "insert into computer (name, os, version) values(?, ?, ?);"
+        { "clubber" "windows" "7" }
+        f <statement>
+        sql-bind-command
+    ] unit-test
+
+    [ { { "windows" } } ] [
+        "select os from computer where name = ?;"
+        { "clubber" } f <statement> sql-bind-query
+    ] unit-test
+
+    [ { { "windows" 7 } } ] [
+        "select os, version from computer where name = ?;"
+        { { VARCHAR "clubber" } }
+        { VARCHAR INTEGER }
+        <statement> sql-bind-typed-query
+    ] unit-test
+
+    [ ] [
+        "insert into computer (name, os, version) values(?, ?, ?);"
+        {
+            { VARCHAR "paulie" }
+            { VARCHAR "netbsd" }
+            { INTEGER 7 }
+        } f <statement>
+        sql-bind-typed-command
+    ] unit-test
+
+    ;
+
+[ test-sql-command ] test-dbs
diff --git a/extra/db2/statements/statements.factor b/extra/db2/statements/statements.factor
new file mode 100644 (file)
index 0000000..9ddd74d
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors continuations destructors fry kernel
+sequences db2.result-sets db2.connections db2.errors ;
+IN: db2.statements
+
+TUPLE: statement handle sql in out type ;
+
+: new-statement ( sql in out class -- statement )
+    new
+        swap >>out
+        swap >>in
+        swap >>sql ;
+
+HOOK: <statement> db-connection ( sql in out -- statement )
+GENERIC: statement>result-set* ( statement -- result-set )
+GENERIC: execute-statement* ( statement type -- )
+GENERIC: prepare-statement* ( statement -- statement' )
+GENERIC: bind-sequence ( statement -- )
+GENERIC: bind-typed-sequence ( statement -- )
+
+: statement>result-set ( statement -- result-set )
+    [ statement>result-set* ]
+    [ dup sql-error? [ parse-sql-error ] when rethrow ] recover ;
+
+M: object execute-statement* ( statement type -- )
+    drop statement>result-set dispose ;
+
+: execute-one-statement ( statement -- )
+    dup type>> execute-statement* ;
+
+: execute-statement ( statement -- )
+    dup sequence?
+    [ [ execute-one-statement ] each ]
+    [ execute-one-statement ] if ;
+
+: prepare-statement ( statement -- statement )
+    dup handle>> [ prepare-statement* ] unless ;
+
+: result-set-each ( statement quot: ( statement -- ) -- )
+    over more-rows?
+    [ [ call ] 2keep over advance-row result-set-each ]
+    [ 2drop ] if ; inline recursive
+
+: result-set-map ( statement quot -- sequence )
+    accumulator [ result-set-each ] dip { } like ; inline
+
+: statement>result-sequence ( statement -- sequence )
+    statement>result-set [ [ sql-row ] result-set-map ] with-disposal ;
+
+: statement>typed-result-sequence ( statement -- sequence )
+    statement>result-set
+    [ [ sql-row-typed ] result-set-map ] with-disposal ;
diff --git a/extra/db2/tester/authors.txt b/extra/db2/tester/authors.txt
new file mode 100644 (file)
index 0000000..f372b57
--- /dev/null
@@ -0,0 +1,2 @@
+Slava Pestov
+Doug Coleman
diff --git a/extra/db2/tester/tester-tests.factor b/extra/db2/tester/tester-tests.factor
new file mode 100644 (file)
index 0000000..b3e8f19
--- /dev/null
@@ -0,0 +1,7 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test db2.tester ;
+IN: db2.tester.tests
+
+! [ ] [ sqlite-test-db db-tester ] unit-test
+! [ ] [ sqlite-test-db db-tester2 ] unit-test
diff --git a/extra/db2/tester/tester.factor b/extra/db2/tester/tester.factor
new file mode 100644 (file)
index 0000000..471752f
--- /dev/null
@@ -0,0 +1,96 @@
+! Copyright (C) 2008 Slava Pestov, Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: concurrency.combinators db2.connections
+db2.pools db2.sqlite db2.types fry io.files.temp kernel math
+namespaces random threads tools.test combinators ;
+IN: db2.tester
+USE: multiline
+
+: sqlite-test-db ( -- sqlite-db )
+    "tuples-test.db" temp-file <sqlite-db> ;
+
+! These words leak resources, but are useful for interactivel testing
+: set-sqlite-db ( -- )
+    sqlite-db db-open db-connection set ;
+
+: test-sqlite ( quot -- )
+    '[
+        [ ] [ sqlite-test-db _ with-db ] unit-test
+    ] call ; inline
+
+: test-dbs ( quot -- )
+    {
+        [ test-sqlite ]
+    } cleave ;
+
+/*
+: postgresql-test-db ( -- postgresql-db )
+    <postgresql-db>
+        "localhost" >>host
+        "postgres" >>username
+        "thepasswordistrust" >>password
+        "factor-test" >>database ;
+
+: set-postgresql-db ( -- )
+    postgresql-db db-open db-connection set ;
+
+: test-postgresql ( quot -- )
+    '[
+        os windows? cpu x86.64? and [
+            [ ] [ postgresql-test-db _ with-db ] unit-test
+        ] unless
+    ] call ; inline
+
+TUPLE: test-1 id a b c ;
+
+test-1 "TEST1" {
+   { "id" "ID" INTEGER +db-assigned-id+ }
+   { "a" "A" { VARCHAR 256 } +not-null+ }
+   { "b" "B" { VARCHAR 256 } +not-null+ }
+   { "c" "C" { VARCHAR 256 } +not-null+ }
+} define-persistent
+
+TUPLE: test-2 id x y z ;
+
+test-2 "TEST2" {
+   { "id" "ID" INTEGER +db-assigned-id+ }
+   { "x" "X" { VARCHAR 256 } +not-null+ }
+   { "y" "Y" { VARCHAR 256 } +not-null+ }
+   { "z" "Z" { VARCHAR 256 } +not-null+ }
+} define-persistent
+
+: db-tester ( test-db -- )
+    [
+        [
+            test-1 ensure-table
+            test-2 ensure-table
+        ] with-db
+    ] [
+        10 [
+            drop
+            10 [
+                dup [
+                    f 100 random 100 random 100 random test-1 boa
+                    insert-tuple yield
+                ] with-db
+            ] times
+        ] with parallel-each
+    ] bi ;
+
+: db-tester2 ( test-db -- )
+    [
+        [
+            test-1 ensure-table
+            test-2 ensure-table
+        ] with-db
+    ] [
+        <db-pool> [
+            10 [
+                10 [
+                    f 100 random 100 random 100 random test-1 boa
+                    insert-tuple yield
+                ] times
+            ] parallel-each
+        ] with-pooled-db
+    ] bi ;
+*/
diff --git a/extra/db2/transactions/authors.txt b/extra/db2/transactions/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/transactions/transactions.factor b/extra/db2/transactions/transactions.factor
new file mode 100644 (file)
index 0000000..fd0e6ad
--- /dev/null
@@ -0,0 +1,26 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: continuations db2 db2.connections namespaces ;
+IN: db2.transactions
+
+SYMBOL: in-transaction
+
+HOOK: begin-transaction db-connection ( -- )
+
+HOOK: commit-transaction db-connection ( -- )
+
+HOOK: rollback-transaction db-connection ( -- )
+
+M: db-connection begin-transaction ( -- ) "BEGIN" sql-command ;
+
+M: db-connection commit-transaction ( -- ) "COMMIT" sql-command ;
+
+M: db-connection rollback-transaction ( -- ) "ROLLBACK" sql-command ;
+
+: in-transaction? ( -- ? ) in-transaction get ;
+
+: with-transaction ( quot -- )
+    t in-transaction [
+        begin-transaction
+        [ ] [ rollback-transaction ] cleanup commit-transaction
+    ] with-variable ; inline
diff --git a/extra/db2/types/authors.txt b/extra/db2/types/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/types/types.factor b/extra/db2/types/types.factor
new file mode 100644 (file)
index 0000000..97f9ca0
--- /dev/null
@@ -0,0 +1,17 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: ;
+IN: db2.types
+
+SINGLETONS: +db-assigned-id+ +user-assigned-id+ +random-id+ ;
+UNION: +primary-key+ +db-assigned-id+ +user-assigned-id+ +random-id+ ;
+
+SYMBOLS: +autoincrement+ +serial+ +unique+ +default+ +null+ +not-null+
++foreign-id+ +has-many+ +on-update+ +on-delete+ +restrict+ +cascade+
++set-null+ +set-default+ ;
+
+SINGLETONS: INTEGER BIG-INTEGER SIGNED-BIG-INTEGER UNSIGNED-BIG-INTEGER
+DOUBLE REAL BOOLEAN TEXT VARCHAR DATE TIME DATETIME TIMESTAMP BLOB
+FACTOR-BLOB NULL URL ;
+
+ERROR: no-sql-type type ;
diff --git a/extra/db2/utils/authors.txt b/extra/db2/utils/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/db2/utils/utils.factor b/extra/db2/utils/utils.factor
new file mode 100644 (file)
index 0000000..0557593
--- /dev/null
@@ -0,0 +1,32 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays kernel math math.parser strings sequences
+words ;
+IN: db2.utils
+
+: ?when ( object quot -- object' ) dupd when ; inline
+: ?1array ( obj -- array ) dup string? [ 1array ] when ; inline
+: ??1array ( obj -- array/f ) [ ?1array ] ?when ; inline
+
+: ?first ( sequence -- object/f ) 0 ?nth ;
+: ?second ( sequence -- object/f ) 1 ?nth ;
+
+: ?first2 ( sequence -- object1/f object2/f )
+    [ ?first ] [ ?second ] bi ;
+
+: assoc-with ( object sequence quot -- obj curry )
+    swapd [ [ -rot ] dip  call ] 2curry ; inline
+
+: ?number>string ( n/string -- string )
+    dup number? [ number>string ] when ;
+
+ERROR: no-accessor name ;
+
+: lookup-accessor ( string -- accessor )
+    dup ">>" append "accessors" lookup
+    [ nip ] [ no-accessor ] if* ;
+
+ERROR: string-expected object ;
+
+: ensure-string ( object -- string )
+    dup string? [ string-expected ] unless ;
index 8c55945105bce4d266a70bb4ad0eb01a740252ef..dfd73f1236d84f758dd6589c03c75c1b95d1fe1e 100644 (file)
@@ -1,22 +1,16 @@
-
-USING: kernel fry sequences
-       vocabs.loader help.vocabs
-       ui ui.gadgets ui.gadgets.buttons ui.gadgets.packs ui.gadgets.scrollers
-       ui.tools.listener
-       accessors ;
-
+USING: kernel fry sequences vocabs.loader help.vocabs ui
+ui.gadgets ui.gadgets.buttons ui.gadgets.packs ui.gadgets.borders
+ui.gadgets.scrollers ui.tools.listener accessors ;
 IN: demos
 
 : demo-vocabs ( -- seq ) "demos" tagged [ second ] map concat [ name>> ] map ;
 
 : <run-vocab-button> ( vocab-name -- button )
-  dup '[ drop [ _ run ] call-listener ] <border-button> ;
+    dup '[ drop [ _ run ] \ run call-listener ] <border-button> ;
 
 : <demo-runner> ( -- gadget )
-  <pile> 1 >>fill demo-vocabs [ <run-vocab-button> add-gadget ] each ;
-
-: demos ( -- ) [ <demo-runner> <scroller> "Demos" open-window ] with-ui ;
+    <pile> 1 >>fill { 2 2 } >>gap demo-vocabs [ <run-vocab-button> add-gadget ] each ;
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+: demos ( -- ) [ <demo-runner> { 2 2 } <border> <scroller> "Demos" open-window ] with-ui ;
 
 MAIN: demos
\ No newline at end of file
index dc02f8bd9d04e4eddb1838f6d12c46f67fc2f7fc..6ced201c13a51918c324ed54dd53ce94f8d3c82d 100755 (executable)
@@ -1,20 +1,28 @@
-USING: help.syntax help.markup ;\r
+USING: help.syntax help.markup words ;\r
 IN: descriptive\r
 \r
 HELP: DESCRIPTIVE:\r
 { $syntax "DESCRIPTIVE: word ( inputs -- outputs ) definition ;" }\r
-{ $description "Defines a word such that, if an error is thrown from within it, that error is wrapped in a descriptive tag including the arguments to that word." } ;\r
+{ $description "Defines a word such that, if an error is thrown from within it, that error is wrapped in a " { $link descriptive-error } " with the arguments to that word." } ;\r
 \r
 HELP: DESCRIPTIVE::\r
 { $syntax "DESCRIPTIVE:: word ( inputs -- outputs ) definition ;" }\r
-{ $description "Defines a word which uses locals such that, if an error is thrown from within it, that error is wrapped in a descriptive tag including the arguments to that word." } ;\r
+{ $description "Defines a word which uses locals such that, if an error is thrown from within it, that error is wrapped in a " { $link descriptive-error } " with the arguments to that word." } ;\r
 \r
-HELP: descriptive\r
-{ $class-description "The class of errors wrapping another error (in the underlying slot) which were thrown in a word (in the word slot) with a given set of arguments (in the args slot)." } ;\r
+HELP: descriptive-error\r
+{ $error-description "The class of errors wrapping another error (in the underlying slot) which were thrown in a word (in the word slot) with a given set of arguments (in the args slot)." } ;\r
+\r
+HELP: make-descriptive\r
+{ $values { "word" word } }\r
+{ $description "Makes the word wrap errors in " { $link descriptive-error } " instances." } ;\r
 \r
 ARTICLE: "descriptive" "Descriptive errors"\r
-"This vocabulary defines automatic descriptive errors. Using it, you can define a word which acts as normal, except when it throws an error, the error is wrapped in a special descriptor declaring that an error was thrown from inside that word, and including the arguments given to that word. The error is of the following class:"\r
-{ $subsection descriptive }\r
+"This vocabulary defines automatic descriptive errors. Using it, you can define a word which acts as normal, except when it throws an error, the error is wrapped in an instance of a class:"\r
+{ $subsection descriptive-error }\r
+"The wrapper contains the word itself, the input parameters, as well as the original error."\r
+$nl\r
+"To annotate an existing word with descriptive error checking:"\r
+{ $subsection make-descriptive }\r
 "To define words which throw descriptive errors, use the following words:"\r
 { $subsection POSTPONE: DESCRIPTIVE: }\r
 { $subsection POSTPONE: DESCRIPTIVE:: } ;\r
index ba3438e37d41751b3d3ad5b1bcadb3bd53e770ee..9af94aa4ed47fa6b181f96a36ca81af2abc762f7 100755 (executable)
@@ -1,13 +1,19 @@
-USING: words kernel sequences locals locals.parser
+! Copyright (c) 2008 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: words kernel sequences locals locals.parser fry
 locals.definitions accessors parser namespaces continuations
-summary definitions generalizations arrays ;
+summary definitions generalizations arrays prettyprint debugger io
+effects tools.annotations ;
 IN: descriptive
 
 ERROR: descriptive-error args underlying word ;
 
-M: descriptive-error summary
-    word>> "The " swap name>> " word encountered an error."
-    3append ;
+M: descriptive-error error.
+    "The word " write dup word>> pprint " encountered an error." print
+    "Arguments:" print
+    dup args>> stack.
+    "Error:" print
+    underlying>> error. ;
 
 <PRIVATE
 
@@ -20,6 +26,10 @@ M: descriptive-error summary
 
 PRIVATE>
 
+: make-descriptive ( word -- )
+    dup [ ] [ def>> ] [ stack-effect ] tri [descriptive]
+    '[ drop _ ] annotate-methods ;
+
 : define-descriptive ( word def effect -- )
     [ drop "descriptive-definition" set-word-prop ]
     [ [ [ dup ] 2dip [descriptive] ] keep define-declared ]
diff --git a/extra/descriptive/tags.txt b/extra/descriptive/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
index b344ce160f4c64ad9de06f9ded2e05b0a5c07d44..2196f1baaa1493ab4ce485548e9b0c0dac3439b6 100755 (executable)
@@ -3,7 +3,7 @@
 USING: assocs html.parser kernel math sequences strings ascii
 arrays generalizations shuffle unicode.case namespaces make
 splitting http accessors io combinators http.client urls
-urls.encoding fry prettyprint ;
+urls.encoding fry prettyprint sets ;
 IN: html.parser.analyzer
 
 TUPLE: link attributes clickable ;
@@ -126,7 +126,17 @@ TUPLE: link attributes clickable ;
     [ [
         [ name>> "a" = ]
         [ attributes>> "href" swap key? ] bi and ] filter
-    ] map sift [ [ attributes>> "href" swap at ] map ] map concat ;
+    ] map sift
+    [ [ attributes>> "href" swap at ] map ] map concat
+    [ >url ] map ;
+
+: find-frame-links ( vector -- vector' )
+    [ name>> "frame" = ] find-between-all
+    [ [ attributes>> "src" swap at ] map sift ] map concat sift
+    [ >url ] map ;
+
+: find-all-links ( vector -- vector' )
+    [ find-hrefs ] [ find-frame-links ] bi append prune ;
 
 : find-forms ( vector -- vector' )
     "form" over find-opening-tags-by-name
index 9757f70a67d8bb4392e1aa72617aa5ee523835f5..ca276fc54e069fd645570062add13e24c0a79ea7 100644 (file)
@@ -42,6 +42,19 @@ V{
 }
 ] [ "<a   href  =    \"http://factorcode.org/\"    foo   =  bar baz='quux'a=pirsqd  >" parse-html ] unit-test
 
+[
+V{
+    T{ tag f "a"
+        H{
+            { "a" "pirsqd" }
+            { "foo" "bar" }
+            { "href" "http://factorcode.org/" }
+            { "baz" "quux" }
+            { "nofollow" "nofollow" }
+        } f f }
+}
+] [ "<a   href  =    \"http://factorcode.org/\"    nofollow  foo   =  bar baz='quux'a=pirsqd  >" parse-html ] unit-test
+
 [
 V{
     T{ tag f "html" H{ } f f }
index 94ef59bdfdfda0bf0a642f8e440bf56f3a11bee5..d95c79dd887b053d129fe51630d2cc4857c2e032 100644 (file)
@@ -1,17 +1,19 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays hashtables html.parser.state
-html.parser.utils kernel make namespaces sequences
+USING: accessors arrays hashtables sequence-parser
+html.parser.utils kernel namespaces sequences
 unicode.case unicode.categories combinators.short-circuit
-quoting ;
+quoting fry ;
 IN: html.parser
 
-
 TUPLE: tag name attributes text closing? ;
 
 SINGLETON: text
 SINGLETON: dtd
 SINGLETON: comment
+
+<PRIVATE
+
 SYMBOL: tagstack
 
 : push-tag ( tag -- )
@@ -19,7 +21,7 @@ SYMBOL: tagstack
 
 : closing-tag? ( string -- ? )
     [ f ]
-    [ [ first ] [ peek ] bi [ CHAR: / = ] bi@ or ] if-empty ;
+    [ { [ first CHAR: / = ] [ peek CHAR: / = ] } 1|| ] if-empty ;
 
 : <tag> ( name attributes closing? -- tag )
     tag new
@@ -30,103 +32,96 @@ SYMBOL: tagstack
 : make-tag ( string attribs -- tag )
     [ [ closing-tag? ] keep "/" trim1 ] dip rot <tag> ;
 
-: new-tag ( string type -- tag )
+: new-tag ( text name -- tag )
     tag new
         swap >>name
         swap >>text ; inline
 
-: make-text-tag ( string -- tag ) text new-tag ; inline
+: (read-quote) ( sequence-parser ch -- string )
+    '[ [ current _ = ] take-until ] [ advance drop ] bi ;
 
-: make-comment-tag ( string -- tag ) comment new-tag ; inline
+: read-single-quote ( sequence-parser -- string )
+    CHAR: ' (read-quote) ;
 
-: make-dtd-tag ( string -- tag ) dtd new-tag ; inline
+: read-double-quote ( sequence-parser -- string )
+    CHAR: " (read-quote) ;
 
-: read-single-quote ( state-parser -- string )
-    [ [ CHAR: ' = ] take-until ] [ next drop ] bi ;
-
-: read-double-quote ( state-parser -- string )
-    [ [ CHAR: " = ] take-until ] [ next drop ] bi ;
-
-: read-quote ( state-parser -- string )
+: read-quote ( sequence-parser -- string )
     dup get+increment CHAR: ' =
     [ read-single-quote ] [ read-double-quote ] if ;
 
-: read-key ( state-parser -- string )
+: read-key ( sequence-parser -- string )
     skip-whitespace
-    [ { [ CHAR: = = ] [ blank? ] } 1|| ] take-until ;
+    [ current { [ CHAR: = = ] [ blank? ] } 1|| ] take-until ;
 
-: read-= ( state-parser -- )
-    skip-whitespace
-    [ [ CHAR: = = ] take-until drop ] [ next drop ] bi ;
+: read-token ( sequence-parser -- string )
+    [ current blank? ] take-until ;
 
-: read-token ( state-parser -- string )
-    [ blank? ] take-until ;
-
-: read-value ( state-parser -- string )
+: read-value ( sequence-parser -- string )
     skip-whitespace
-    dup get-char quote? [ read-quote ] [ read-token ] if
+    dup current quote? [ read-quote ] [ read-token ] if
     [ blank? ] trim ;
 
-: read-comment ( state-parser -- )
-    "-->" take-until-sequence make-comment-tag push-tag ;
+: read-comment ( sequence-parser -- )
+    "-->" take-until-sequence comment new-tag push-tag ;
 
-: read-dtd ( state-parser -- )
-    ">" take-until-sequence make-dtd-tag push-tag ;
+: read-dtd ( sequence-parser -- )
+    ">" take-until-sequence dtd new-tag push-tag ;
 
-: read-bang ( state-parser -- )
-    next dup { [ get-char CHAR: - = ] [ get-next CHAR: - = ] } 1&& [
-        next next
-        read-comment
-    ] [
-        read-dtd
-    ] if ;
+: read-bang ( sequence-parser -- )
+    advance dup { [ current CHAR: - = ] [ peek-next CHAR: - = ] } 1&&
+    [ advance advance read-comment ] [ read-dtd ] if ;
 
-: read-tag ( state-parser -- string )
-    [ [ "><" member? ] take-until ]
-    [ dup get-char CHAR: < = [ next ] unless drop ] bi ;
+: read-tag ( sequence-parser -- string )
+    [ [ current "><" member? ] take-until ]
+    [ dup current CHAR: < = [ advance ] unless drop ] bi ;
 
-: read-until-< ( state-parser -- string )
-    [ CHAR: < = ] take-until ;
+: read-until-< ( sequence-parser -- string )
+    [ current CHAR: < = ] take-until ;
 
-: parse-text ( state-parser -- )
-    read-until-< [ make-text-tag push-tag ] unless-empty ;
+: parse-text ( sequence-parser -- )
+    read-until-< [ text new-tag push-tag ] unless-empty ;
 
-: (parse-attributes) ( state-parser -- )
+: parse-key/value ( sequence-parser -- key value )
+    [ read-key >lower ]
+    [ skip-whitespace "=" take-sequence ]
+    [ swap [ read-value ] [ drop dup ] if ] tri ;
+
+: (parse-attributes) ( sequence-parser -- )
     skip-whitespace
-    dup state-parse-end? [
+    dup sequence-parse-end? [
         drop
     ] [
-        [
-            [ read-key >lower ] [ read-= ] [ read-value ] tri
-            2array ,
-        ] keep (parse-attributes)
+        [ parse-key/value swap set ] [ (parse-attributes) ] bi
     ] if ;
 
-: parse-attributes ( state-parser -- hashtable )
-    [ (parse-attributes) ] { } make >hashtable ;
+: parse-attributes ( sequence-parser -- hashtable )
+    [ (parse-attributes) ] H{ } make-assoc ;
 
 : (parse-tag) ( string -- string' hashtable )
     [
         [ read-token >lower ] [ parse-attributes ] bi
-    ] state-parse ;
+    ] parse-sequence ;
 
-: read-< ( state-parser -- string/f )
-    next dup get-char [
+: read-< ( sequence-parser -- string/f )
+    advance dup current [
         CHAR: ! = [ read-bang f ] [ read-tag ] if
     ] [
         drop f
     ] if* ;
 
-: parse-tag ( state-parser -- )
+: parse-tag ( sequence-parser -- )
     read-< [ (parse-tag) make-tag push-tag ] unless-empty ;
 
-: (parse-html) ( state-parser -- )
-    dup get-next [
+: (parse-html) ( sequence-parser -- )
+    dup peek-next [
         [ parse-text ] [ parse-tag ] [ (parse-html) ] tri
     ] [ drop ] if ;
 
 : tag-parse ( quot -- vector )
-    V{ } clone tagstack [ state-parse ] with-variable ; inline
+    V{ } clone tagstack [ parse-sequence ] with-variable ; inline
+
+PRIVATE>
 
 : parse-html ( string -- vector )
     [ (parse-html) tagstack get ] tag-parse ;
diff --git a/extra/html/parser/state/state-tests.factor b/extra/html/parser/state/state-tests.factor
deleted file mode 100644 (file)
index f9862e1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-USING: tools.test html.parser.state ascii kernel accessors ;
-IN: html.parser.state.tests
-
-[ "hello" ]
-[ "hello" [ take-rest ] state-parse ] unit-test
-
-[ "hi" " how are you?" ]
-[
-    "hi how are you?"
-    [ [ [ blank? ] take-until ] [ take-rest ] bi ] state-parse
-] unit-test
-
-[ "foo" ";bar" ]
-[
-    "foo;bar" [
-        [ CHAR: ; take-until-object ] [ take-rest ] bi
-    ] state-parse
-] unit-test
-
-[ "foo " " bar" ]
-[
-    "foo and bar" [
-        [ "and" take-until-sequence ] [ take-rest ] bi 
-    ] state-parse
-] unit-test
-
-[ 6 ]
-[
-    "      foo   " [ skip-whitespace n>> ] state-parse
-] unit-test
-
-[ { 1 2 } ]
-[ { 1 2 3 } <state-parser> [ 3 = ] take-until ] unit-test
-
-[ { 1 2 } ]
-[ { 1 2 3 4 } <state-parser> { 3 4 } take-until-sequence ] unit-test
diff --git a/extra/html/parser/state/state.factor b/extra/html/parser/state/state.factor
deleted file mode 100644 (file)
index 2369b1d..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-! Copyright (C) 2005, 2009 Daniel Ehrenberg
-! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces math kernel sequences accessors fry circular
-unicode.case unicode.categories locals ;
-
-IN: html.parser.state
-
-TUPLE: state-parser sequence n ;
-
-: <state-parser> ( sequence -- state-parser )
-    state-parser new
-        swap >>sequence
-        0 >>n ;
-
-: (get-char) ( n state -- char/f )
-    sequence>> ?nth ; inline
-
-: get-char ( state -- char/f )
-    [ n>> ] keep (get-char) ; inline
-
-: get-next ( state -- char/f )
-    [ n>> 1 + ] keep (get-char) ; inline
-
-: next ( state -- state )
-    [ 1 + ] change-n ; inline
-
-: get+increment ( state -- char/f )
-    [ get-char ] [ next drop ] bi ; inline
-
-: state-parse ( sequence quot -- )
-    [ <state-parser> ] dip call ; inline
-
-:: skip-until ( state quot: ( obj -- ? ) -- )
-    state get-char [
-        quot call [ state next quot skip-until ] unless
-    ] when* ; inline recursive
-
-: state-parse-end? ( state -- ? ) get-next not ;
-
-: take-until ( state quot: ( obj -- ? ) -- sequence/f )
-    over state-parse-end? [
-        2drop f
-    ] [
-        [ drop n>> ]
-        [ skip-until ]
-        [ drop [ n>> ] [ sequence>> ] bi ] 2tri subseq
-    ] if ; inline
-
-:: take-until-sequence ( state-parser sequence -- sequence' )
-    sequence length <growing-circular> :> growing
-    state-parser
-    [
-        growing push-growing-circular
-        sequence growing sequence=
-    ] take-until :> found
-    found dup length
-    growing length 1- - head
-    state-parser next drop ;
-    
-: skip-whitespace ( state -- state )
-    [ [ blank? not ] take-until drop ] keep ;
-
-: take-rest ( state -- sequence )
-    [ drop f ] take-until ; inline
-
-: take-until-object ( state obj -- sequence )
-    '[ _ = ] take-until ;
index 7abd2fcdf7a3c19893d2f296b69bdadfa59502fa..afd63daf6bf241bca2c96f4f117501ca8fb42855 100644 (file)
@@ -2,8 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs circular combinators continuations hashtables
 hashtables.private io kernel math namespaces prettyprint
-quotations sequences splitting html.parser.state strings
-combinators.short-circuit quoting ;
+quotations sequences splitting strings quoting
+combinators.short-circuit ;
 IN: html.parser.utils
 
 : trim1 ( seq ch -- newseq )
index feb110fab8daaf58382575702212f462952c8f6a..c43559a630f91f26e2161ee0dd4d4c8d92d486d0 100644 (file)
@@ -7,7 +7,7 @@ IN: id3
 HELP: mp3>id3
 { $values 
     { "path" "a path string" } 
-    { "id3v2-info/f" "a tuple storing ID3v2 metadata or f" } }
+    { "id3/f" "a tuple storing ID3v2 metadata or f" } }
     { $description "Return a tuple containing the ID3 information parsed out of the MP3 file, or " { $link f } " if no metadata is present. Words to access the ID3v1 information are here:"
         { $list
           { $link title }
@@ -22,49 +22,49 @@ HELP: mp3>id3
 
 HELP: album
 { $values
-    { "id3" id3v2-info }
-    { "album/f" "string or f" }
+    { "id3" id3 }
+    { "string/f" "string or f" }
 }
 { $description "Returns the album, or " { $link f } " if this field is missing, from a parsed id3 tag." } ;
 
 HELP: artist
 { $values
-    { "id3" id3v2-info }
-    { "artist/f" "string or f" }
+    { "id3" id3 }
+    { "string/f" "string or f" }
 }
 { $description "Returns the artist, or " { $link f } " if this field is missing, from a parsed id3 tag." } ;
 
 HELP: comment
 { $values
-    { "id3" id3v2-info }
-    { "comment/f" "string or f" }
+    { "id3" id3 }
+    { "string/f" "string or f" }
 }
 { $description "Returns the comment, or " { $link f } " if this field is missing, from a parsed id3 tag." } ;
 
 HELP: genre
 { $values
-    { "id3" id3v2-info }
-    { "genre/f" "string or f" }
+    { "id3" id3 }
+    { "string/f" "string or f" }
 }
 { $description "Returns the genre, or " { $link f } " if this field is missing, from a parsed id3 tag." } ;
 
 HELP: title
 { $values
-    { "id3" id3v2-info }
-    { "title/f" "string or f" }
+    { "id3" id3 }
+    { "string/f" "string or f" }
 }
 { $description "Returns the title, or " { $link f } " if this field is missing, from a parsed id3 tag." } ;
 
 HELP: year
 { $values
-    { "id3" id3v2-info }
-    { "year/f" "string or f" }
+    { "id3" id3 }
+    { "string/f" "string or f" }
 }
 { $description "Returns the year, or " { $link f } " if this field is missing, from a parsed id3 tag." } ;
 
 HELP: find-id3-frame
 { $values
-    { "id3" id3v2-info } { "name" string }
+    { "id3" id3 } { "name" string }
     { "obj/f" "object or f" }
 }
 { $description "Returns the " { $slot "data" } " slot of the ID3 frame with the given name, or " { $link f } "." } ;
index a8f35e582cef10ae7a98adf6b2549f7c7f06c70b..9bb755807771054a1aaf8cda2a74ec6abd8f058d 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2009 Tim Wawrzynczak
 ! See http://factorcode.org/license.txt for BSD license.
-USING: tools.test id3 combinators ;
+USING: tools.test id3 combinators grouping id3.private
+sequences math ;
 IN: id3.tests
 
 : id3-params ( id3 -- title artist album year comment genre )
@@ -40,3 +41,6 @@ IN: id3.tests
    "Big Band"
 ] [ "vocab:id3/tests/blah3.mp3" mp3>id3 id3-params ] unit-test
 
+
+[ t ]
+[ 10000 [ synchsafe>seq seq>synchsafe ] map [ < ] monotonic? ] unit-test
index 8e824d689f2b3b473a7d9c6904c28c1e56e71b69..a5671a5822811364fc8906e5e67f46ed9bc0a416 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 ;
+io.directories.search literals math.functions ;
 IN: id3
 
 <PRIVATE
@@ -37,103 +37,132 @@ CONSTANT: genres
         "Primus" "Porn Groove" "Satire" "Slow Jam" "Club" "Tango" 
         "Samba" "Folklore" "Ballad" "Power Ballad" "Rhythmic Soul" 
         "Freestyle" "Duet" "Punk Rock" "Drum Solo" "A capella" 
-        "Euro-House" "Dance Hall"
+        "Euro-House" "Dance Hall" "Goa" "Drum & Bass" "Club-House"
+        "Hardcore" "Terror" "Indie" "BritPop" "Negerpunk"
+        "Polsk Punk" "Beat" "Christian Gangsta Rap" "Heavy Metal"
+        "Black Metal" "Crossover" "Contemporary Christian"
+        "Christian Rock"
     }
 
 TUPLE: header version flags size ;
 
-TUPLE: frame frame-id flags size data ;
+TUPLE: frame tag flags size data ;
 
-TUPLE: id3v2-info header frames ;
+TUPLE: id3 header frames
+title artist album year comment genre
+speed genre-name start-time end-time ;
 
-TUPLE: id3v1-info title artist album year comment genre ;
-
-: <id3v1-info> ( -- object ) id3v1-info new ; inline
-
-: <id3v2-info> ( header frames -- object )
-    [ [ frame-id>> ] keep ] H{ } map>assoc id3v2-info boa ;
+: <id3> ( -- id3 )
+    id3 new
+    H{ } clone >>frames ; inline
 
 : <header> ( -- object ) header new ; inline
 
 : <frame> ( -- object ) frame new ; inline
 
-: id3v2? ( mmap -- ? ) "ID3" head? ; inline
+: id3v2? ( seq -- ? ) "ID3" head? ; inline
 
-: id3v1? ( mmap -- ? )
-    { [ length 128 >= ] [ 128 tail-slice* "TAG" head? ] } 1&& ; inline
+CONSTANT: id3v1-length 128
+CONSTANT: id3v1-offset 128
+CONSTANT: id3v1+-length 227
+CONSTANT: id3v1+-offset $[ 128 227 + ]
+
+: id3v1? ( seq -- ? )
+    {
+        [ length id3v1-offset >= ]
+        [ id3v1-length tail-slice* "TAG" head? ]
+    } 1&& ;
 
-: id3v1-frame ( string key -- frame )
-    <frame>
-        swap >>frame-id
-        swap >>data ; inline
+: id3v1+? ( seq -- ? )
+    {
+        [ length id3v1+-offset >= ]
+        [ id3v1+-length tail-slice* "TAG+" head? ]
+    } 1&& ;
+
+: pair>frame ( string key -- frame/f )
+    over [
+        <frame>
+            swap >>tag
+            swap >>data
+    ] [
+        2drop f
+    ] if ;
 
-: id3v1>id3v2 ( id3v1 -- id3v2 )
+: id3v1>frames ( id3v1 -- seq )
     [
         {
-            [ title>> "TIT2" id3v1-frame ]
-            [ artist>> "TPE1" id3v1-frame ]
-            [ album>> "TALB" id3v1-frame ]
-            [ year>> "TYER" id3v1-frame ]
-            [ comment>> "COMM" id3v1-frame ]
-            [ genre>> "TCON" id3v1-frame ]
+            [ title>> "TIT2" pair>frame ]
+            [ artist>> "TPE1" pair>frame ]
+            [ album>> "TALB" pair>frame ]
+            [ year>> "TYER" pair>frame ]
+            [ comment>> "COMM" pair>frame ]
+            [ genre>> "TCON" pair>frame ]
         } cleave
-    ] output>array f swap <id3v2-info> ; inline
+    ] output>array sift ;
 
-: >28bitword ( seq -- int )
-    0 [ [ 7 shift ] dip bitor ] reduce ; inline
+: seq>synchsafe ( seq -- n )
+    0 [ [ 7 shift ] dip bitor ] reduce ;
+
+: synchsafe>seq ( n -- seq )
+    dup 1+ log2 1+ 7 / ceiling
+    [ [ -7 shift ] keep HEX: 7f bitand  ] replicate nip reverse ;
 
 : filter-text-data ( data -- filtered )
-    [ printable? ] filter ; inline
+    [ printable? ] filter ;
 
-: valid-frame-id? ( id -- ? )
-    [ { [ digit? ] [ LETTER? ] } 1|| ] all? ; inline
+: valid-tag? ( id -- ? )
+    [ { [ digit? ] [ LETTER? ] } 1|| ] all? ;
 
-: read-frame-data ( frame mmap -- frame data )
-    [ 10 over size>> 10 + ] dip <slice> filter-text-data ; inline
+: read-frame-data ( frame seq -- frame data )
+    [ 10 over size>> 10 + ] dip <slice> filter-text-data ;
 
 : decode-text ( string -- string' )
     dup 2 short head
     { { HEX: ff HEX: fe } { HEX: fe HEX: ff } } member?
-    utf16 ascii ? decode ; inline
+    utf16 ascii ? decode ;
 
-: (read-frame) ( mmap -- frame )
+: (read-frame) ( seq -- frame )
     [ <frame> ] dip
     {
-        [ 4 head-slice decode-text >>frame-id ]
-        [ [ 4 8 ] dip subseq >28bitword >>size ]
+        [ 4 head-slice decode-text >>tag ]
+        [ [ 4 8 ] dip subseq seq>synchsafe >>size ]
         [ [ 8 10 ] dip subseq >byte-array >>flags ]
         [ read-frame-data decode-text >>data ]
-    } cleave ; inline
+    } cleave ;
+
+: read-frame ( seq -- frame/f )
+    dup 4 head-slice valid-tag?
+    [ (read-frame) ] [ drop f ] if ;
 
-: read-frame ( mmap -- frame/f )
-    dup 4 head-slice valid-frame-id?
-    [ (read-frame) ] [ drop f ] if ; inline
+: remove-frame ( seq frame -- seq )
+    size>> 10 + tail-slice ;
 
-: remove-frame ( mmap frame -- mmap )
-    size>> 10 + tail-slice ; inline
+: frames>assoc ( seq -- assoc )
+    [ [ tag>> ] keep ] H{ } map>assoc ;
 
-: read-frames ( mmap -- frames )
-    [ dup read-frame dup ]
-    [ [ remove-frame ] keep ]
-    produce 2nip ; inline
+: read-frames ( seq -- assoc )
+    [ dup read-frame dup ] [ [ remove-frame ] keep ] produce 2nip ;
     
-: read-v2-header ( seq -- id3header )
+: read-v2-header ( seq -- header )
     [ <header> ] dip
     {
         [ [ 3 5 ] dip <slice> >array >>version ]
         [ [ 5 ] dip nth >>flags ]
-        [ [ 6 10 ] dip <slice> >28bitword >>size ]
-    } cleave ; inline
+        [ [ 6 10 ] dip <slice> seq>synchsafe >>size ]
+    } cleave ;
 
-: read-v2-tag-data ( seq -- id3v2-info )
+: merge-frames ( id3 assoc -- id3 )
+    [ dup frames>> ] dip update ;
+
+: merge-id3v1 ( id3 -- id3 )
+    dup id3v1>frames frames>assoc merge-frames ;
+
+: read-v2-tags ( id3 seq -- id3 )
     10 cut-slice
-    [ read-v2-header ]
-    [ read-frames ] bi* <id3v2-info> ; inline
+    [ read-v2-header >>header ]
+    [ read-frames frames>assoc merge-frames ] bi* ;
     
-: skip-to-v1-data ( seq -- seq ) 125 tail-slice* ; inline
-
-: (read-v1-tag-data) ( seq -- mp3-file )
-    [ <id3v1-info> ] dip
+: extract-v1-tags ( id3 seq -- id3 )
     {
         [ 30 head-slice decode-text filter-text-data >>title ]
         [ [ 30 60 ] dip subseq decode-text filter-text-data >>artist ]
@@ -141,10 +170,32 @@ TUPLE: id3v1-info title artist album year comment genre ;
         [ [ 90 94 ] dip subseq decode-text filter-text-data >>year ]
         [ [ 94 124 ] dip subseq decode-text filter-text-data >>comment ]
         [ [ 124 ] dip nth number>string >>genre ]
-    } cleave ; inline
+    } cleave ;
 
-: read-v1-tag-data ( seq -- mp3-file )
-    skip-to-v1-data (read-v1-tag-data) ; inline
+: read-v1-tags ( id3 seq -- id3 )
+    id3v1-offset tail-slice* 3 tail-slice
+    extract-v1-tags ;
+
+: extract-v1+-tags ( id3 seq -- id3 )
+    {
+        [ 60 head-slice decode-text filter-text-data [ append ] change-title ]
+        [
+            [ 60 120 ] dip subseq decode-text filter-text-data
+            [ append ] change-artist
+        ]
+        [
+            [ 120 180 ] dip subseq decode-text filter-text-data
+            [ append ] change-album
+        ]
+        [ [ 180 ] dip nth >>speed ]
+        [ [ 181 211 ] dip subseq decode-text >>genre-name ]
+        [ [ 211 217 ] dip subseq decode-text >>start-time ]
+        [ [ 217 223 ] dip subseq decode-text >>end-time ]
+    } cleave ;
+
+: read-v1+-tags ( id3 seq -- id3 )
+    id3v1+-offset tail-slice* 4 tail-slice
+    extract-v1+-tags ;
 
 : parse-genre ( string -- n/f )
     dup "(" ?head-slice drop ")" ?tail-slice drop
@@ -152,47 +203,44 @@ TUPLE: id3v1-info title artist album year comment genre ;
         genres ?nth swap or
     ] [
         drop
-    ] if ; inline
+    ] if ;
 
-: (mp3>id3) ( path -- id3v2-info/f )
+: (mp3>id3) ( path -- id3v2/f )
     [
+        [ <id3> ] dip
         {
-            { [ dup id3v2? ] [ read-v2-tag-data ] }
-            { [ dup id3v1? ] [ read-v1-tag-data id3v1>id3v2 ] }
-            [ drop f ]
-        } cond
+            [ dup id3v1? [ read-v1-tags merge-id3v1 ] [ drop ] if ]
+            [ dup id3v1+? [ read-v1+-tags merge-id3v1 ] [ drop ] if ]
+            [ dup id3v2? [ read-v2-tags ] [ drop ] if ]
+        } cleave
     ] with-mapped-uchar-file ;
 
-: (find-id3-frame) ( id3 name quot: ( obj -- obj' ) -- obj' )
-    [ swap frames>> at* ] dip
-    [ data>> ] prepose [ drop f ] if ; inline
-
 PRIVATE>
 
-: mp3>id3 ( path -- id3v2-info/f )
-    dup file-info size>> 0 <= [ drop f ] [ (mp3>id3) ] if ; inline
+: mp3>id3 ( path -- id3/f )
+    dup file-info size>> 0 <= [ drop f ] [ (mp3>id3) ] if ;
 
 : find-id3-frame ( id3 name -- obj/f )
-    [ ] (find-id3-frame) ; inline
+    swap frames>> at* [ data>> ] when ;
 
-: title ( id3 -- title/f ) "TIT2" find-id3-frame ; inline
+: title ( id3 -- string/f ) "TIT2" find-id3-frame ;
 
-: artist ( id3 -- artist/f ) "TPE1" find-id3-frame ; inline
+: artist ( id3 -- string/f ) "TPE1" find-id3-frame ;
 
-: album ( id3 -- album/f ) "TALB" find-id3-frame ; inline
+: album ( id3 -- string/f ) "TALB" find-id3-frame ;
 
-: year ( id3 -- year/f ) "TYER" find-id3-frame ; inline
+: year ( id3 -- string/f ) "TYER" find-id3-frame ;
 
-: comment ( id3 -- comment/f ) "COMM" find-id3-frame ; inline
+: comment ( id3 -- string/f ) "COMM" find-id3-frame ;
 
-: genre ( id3 -- genre/f )
-    "TCON" [ parse-genre ] (find-id3-frame) ; inline
+: genre ( id3 -- string/f )
+    "TCON" find-id3-frame parse-genre ;
 
 : find-mp3s ( path -- seq )
-    [ >lower ".mp3" tail? ] find-all-files ; inline
+    [ >lower ".mp3" tail? ] find-all-files ;
 
 : mp3-paths>id3s ( seq -- seq' )
-    [ dup mp3>id3 ] { } map>assoc ; inline
+    [ dup mp3>id3 ] { } map>assoc ;
 
 : parse-mp3-directory ( path -- seq )
     find-mp3s mp3-paths>id3s ;
diff --git a/extra/images/normalization/authors.txt b/extra/images/normalization/authors.txt
new file mode 100644 (file)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/extra/images/normalization/normalization.factor b/extra/images/normalization/normalization.factor
new file mode 100755 (executable)
index 0000000..dcdf39a
--- /dev/null
@@ -0,0 +1,90 @@
+! Copyright (C) 2009 Doug Coleman
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors grouping sequences combinators
+math specialized-arrays.direct.uint byte-arrays fry
+specialized-arrays.direct.ushort specialized-arrays.uint
+specialized-arrays.ushort specialized-arrays.float images ;
+IN: images.normalization
+
+<PRIVATE
+
+: add-dummy-alpha ( seq -- seq' )
+    3 <groups> [ 255 suffix ] map concat ;
+
+: normalize-floats ( byte-array -- byte-array )
+    byte-array>float-array [ 255.0 * >integer ] B{ } map-as ;
+
+GENERIC: normalize-component-order* ( image component-order -- image )
+
+: normalize-component-order ( image -- image )
+    dup component-order>> '[ _ normalize-component-order* ] change-bitmap ;
+
+M: RGBA normalize-component-order* drop ;
+
+M: R32G32B32A32 normalize-component-order*
+    drop normalize-floats ;
+
+M: R32G32B32 normalize-component-order*
+    drop normalize-floats add-dummy-alpha ;
+
+: RGB16>8 ( bitmap -- bitmap' )
+    byte-array>ushort-array [ -8 shift ] B{ } map-as ; inline
+
+M: R16G16B16A16 normalize-component-order*
+    drop RGB16>8 ;
+
+M: R16G16B16 normalize-component-order*
+    drop RGB16>8 add-dummy-alpha ;
+
+: BGR>RGB ( bitmap -- pixels )
+    3 <sliced-groups> [ <reversed> ] map B{ } join ; inline
+
+: BGRA>RGBA ( bitmap -- pixels )
+    4 <sliced-groups>
+    [ unclip-last-slice [ <reversed> ] dip suffix ] map concat ; inline
+
+M: BGRA normalize-component-order*
+    drop BGRA>RGBA ;
+
+M: RGB normalize-component-order*
+    drop add-dummy-alpha ;
+
+M: BGR normalize-component-order*
+    drop BGR>RGB add-dummy-alpha ;
+
+: ARGB>RGBA ( bitmap -- bitmap' )
+    4 <groups> [ unclip suffix ] map B{ } join ; inline
+
+M: ARGB normalize-component-order*
+    drop ARGB>RGBA ;
+
+M: ABGR normalize-component-order*
+    drop ARGB>RGBA BGRA>RGBA ;
+
+: fix-XBGR ( bitmap -- bitmap' )
+    dup 4 <sliced-groups> [ [ 255 0 ] dip set-nth ] each ;
+
+M: XBGR normalize-component-order*
+    drop fix-XBGR ABGR normalize-component-order* ;
+
+: fix-BGRX ( bitmap -- bitmap' )
+    dup 4 <sliced-groups> [ [ 255 3 ] dip set-nth ] each ;
+
+M: BGRX normalize-component-order*
+    drop fix-BGRX BGRA normalize-component-order* ;
+
+: normalize-scan-line-order ( image -- image )
+    dup upside-down?>> [
+        dup dim>> first 4 * '[
+            _ <groups> reverse concat
+        ] change-bitmap
+        f >>upside-down?
+    ] when ;
+
+PRIVATE>
+
+: normalize-image ( image -- image )
+    [ >byte-array ] change-bitmap
+    normalize-component-order
+    normalize-scan-line-order
+    RGBA >>component-order ;
diff --git a/extra/irc/client/base/authors.txt b/extra/irc/client/base/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/client/base/base.factor b/extra/irc/client/base/base.factor
new file mode 100644 (file)
index 0000000..f54e18a
--- /dev/null
@@ -0,0 +1,37 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs concurrency.mailboxes io kernel namespaces
+strings words.symbol irc.client.chats irc.messages ;
+EXCLUDE: sequences => join ;
+IN: irc.client.base
+
+SYMBOL: current-irc-client
+
+: irc> ( -- irc-client ) current-irc-client get ;
+: stream> ( -- stream ) irc> stream>> ;
+: irc-print ( s -- ) stream> [ stream-print ] [ stream-flush ] bi ;
+: irc-send ( irc-message -- ) irc> out-messages>> mailbox-put ;
+: chats> ( -- seq ) irc> chats>> values ;
+: me? ( string -- ? ) irc> nick>> = ;
+
+: with-irc ( irc-client quot: ( -- ) -- )
+    \ current-irc-client swap with-variable ; inline
+
+UNION: to-target privmsg notice ;
+UNION: to-channel join part topic kick rpl-channel-modes
+                  rpl-notopic rpl-topic rpl-names rpl-names-end ;
+UNION: to-one-chat to-target to-channel mode ;
+UNION: to-many-chats nick quit ;
+UNION: to-all-chats irc-end irc-disconnected irc-connected ;
+PREDICATE: to-me < to-target target>> me? ;
+
+GENERIC: chat-name ( irc-message -- name )
+M: mode       chat-name name>> ;
+M: to-target  chat-name target>> ;
+M: to-me      chat-name sender>> ;
+M: to-channel chat-name channel>> ;
+
+GENERIC: chat> ( obj -- chat/f )
+M: string      chat> irc> chats>> at ;
+M: symbol      chat> irc> chats>> at ;
+M: to-one-chat chat> chat-name +server-chat+ or chat> ;
diff --git a/extra/irc/client/chats/authors.txt b/extra/irc/client/chats/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/client/chats/chats-docs.factor b/extra/irc/client/chats/chats-docs.factor
new file mode 100644 (file)
index 0000000..8ab2968
--- /dev/null
@@ -0,0 +1,22 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax quotations kernel ;
+IN: irc.client.chats
+
+HELP: irc-client "IRC Client object" ;
+
+HELP: irc-server-chat "Chat for server messages unmanaged by other chats" ;
+
+HELP: irc-channel-chat "Chat for irc channels" ;
+
+HELP: irc-nick-chat "Chat for irc users" ;
+
+HELP: irc-profile "IRC Client profile object" ;
+
+HELP: irc-chat-end "Message sent to a chat when it has been detached from the client, the chat should stop after it receives this message." ;
+
+HELP: irc-end "Message sent when the client isn't running anymore, the chat should stop after it receives this message." ;
+
+HELP: irc-disconnected "Message sent to notify chats that connection was lost." ;
+
+HELP: irc-connected "Message sent to notify chats that a connection with the irc server was established." ;
diff --git a/extra/irc/client/chats/chats.factor b/extra/irc/client/chats/chats.factor
new file mode 100644 (file)
index 0000000..7910afb
--- /dev/null
@@ -0,0 +1,50 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors concurrency.mailboxes kernel calendar io.sockets io.encodings.8-bit
+destructors arrays sequences ;
+IN: irc.client.chats
+
+CONSTANT: irc-port 6667 ! Default irc port
+
+TUPLE: irc-chat in-messages client ;
+TUPLE: irc-server-chat  < irc-chat ;
+TUPLE: irc-channel-chat < irc-chat name password participants clear-participants ;
+TUPLE: irc-nick-chat    < irc-chat name ;
+SYMBOL: +server-chat+
+
+: <irc-server-chat> ( -- irc-server-chat )
+     irc-server-chat new
+         <mailbox> >>in-messages ;
+
+: <irc-channel-chat> ( name -- irc-channel-chat )
+     irc-channel-chat new
+         swap       >>name
+         <mailbox>  >>in-messages
+         f          >>password
+         H{ } clone >>participants
+         t          >>clear-participants ;
+
+: <irc-nick-chat> ( name -- irc-nick-chat )
+     irc-nick-chat new
+         swap      >>name
+         <mailbox> >>in-messages ;
+
+TUPLE: irc-profile server port nickname password ;
+C: <irc-profile> irc-profile
+
+TUPLE: irc-client profile stream in-messages out-messages
+       chats is-running nick connect reconnect-time is-ready
+       exceptions ;
+
+: <irc-client> ( profile -- irc-client )
+    dup nickname>> irc-client new
+        swap       >>nick
+        swap       >>profile
+        <mailbox>  >>in-messages
+        <mailbox>  >>out-messages
+        H{ } clone >>chats
+        15 seconds >>reconnect-time
+        V{ } clone >>exceptions
+        [ <inet> latin1 <client> ] >>connect ;
+
+SINGLETONS: irc-chat-end irc-end irc-disconnected irc-connected ;
diff --git a/extra/irc/client/chats/summary.txt b/extra/irc/client/chats/summary.txt
new file mode 100644 (file)
index 0000000..6e9493b
--- /dev/null
@@ -0,0 +1 @@
+IRC Client and Chat object definitions
index 6d4fae9b83af233f49150165e804ffa56dbda61e..aa0bcb3bf319b039c379b0d2860efe7596ee8a0b 100644 (file)
@@ -1,16 +1,9 @@
-USING: help.markup help.syntax quotations kernel irc.messages ;
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax quotations kernel
+irc.messages irc.messages.base irc.messages.parser irc.client.chats ;
 IN: irc.client
 
-HELP: irc-client "IRC Client object" ;
-
-HELP: irc-server-chat "Chat for server messages unmanaged by other chats" ;
-
-HELP: irc-channel-chat "Chat for irc channels" ;
-
-HELP: irc-nick-chat "Chat for irc users" ;
-
-HELP: irc-profile "IRC Client profile object" ;
-
 HELP: connect-irc "Connecting to an irc server"
 { $values { "irc-client" "an irc client object" } }
 { $description "Connects and logins " { $link irc-client } " using the settings specified on its " { $link irc-profile } "." } ;
@@ -56,30 +49,31 @@ ARTICLE: "irc.client" "IRC Client"
 "Some of the RFC defined irc messages as objects:"
 { $table
   { { $link irc-message } "base of all irc messages" }
-  { { $link logged-in } "logged in to server" }
+  { { $link rpl-welcome } "logged in to server" }
   { { $link ping } "ping message" }
   { { $link join } "channel join" }
   { { $link part } "channel part" }
   { { $link quit } "quit from irc" }
   { { $link privmsg } "private message (to client or channel)" }
   { { $link kick } "kick from channel" }
-  { { $link roomlist } "list of participants in channel" }
-  { { $link nick-in-use } "chosen nick is in use by another client" }
+  { { $link rpl-names } "list of participants in channel" }
+  { { $link rpl-nickname-in-use } "chosen nick is in use by another client" }
   { { $link notice } "notice message" }
   { { $link mode } "mode change" }
   { { $link unhandled } "uninmplemented/unhandled message" }
   }
+
 { $heading "Special messages" }
 "Some special messages that are created by the library and not by the irc server."
 { $table
   { { $link irc-chat-end } "sent to a chat when it has been detached from the client, the chat should stop after it receives this message. " }
-  { { $link irc-end } " sent when the client isn't running anymore, chats should stop after it receives this message." }
+  { { $link irc-end } " sent when the client isn't running anymore, the chat should stop after it receives this message." }
   { { $link irc-disconnected } " sent to notify chats that connection was lost." }
   { { $link irc-connected } " sent to notify chats that a connection with the irc server was established." } }
 
 { $heading "Example:" }
 { $code
-  "USING: irc.client ;"
+  "USING: irc.client irc.client.chats ;"
   "SYMBOL: bot"
   "SYMBOL: mychannel"
   "! Create the profile and client objects"
@@ -91,7 +85,7 @@ ARTICLE: "irc.client" "IRC Client"
   "! Register and start chat (this joins the channel)"
   "mychannel get bot get attach-chat"
   "! Send a message to the channel"
-  "\"what's up?\" mychannel get speak"
+  "\"Hello World!\" mychannel get speak"
   "! Read a message from the channel"
   "mychannel get hear"
 }
diff --git a/extra/irc/client/client-tests.factor b/extra/irc/client/client-tests.factor
deleted file mode 100644 (file)
index c1cbdcf..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-USING: kernel tools.test accessors arrays sequences
-       io io.streams.duplex namespaces threads destructors
-       calendar irc.client.private irc.client irc.messages.private
-       concurrency.mailboxes classes assocs combinators ;
-EXCLUDE: irc.messages => join ;
-RENAME: join irc.messages => join_
-IN: irc.client.tests
-
-! Streams for testing
-TUPLE: mb-writer lines last-line disposed ;
-TUPLE: mb-reader lines disposed ;
-: <mb-writer> ( -- mb-writer ) V{ } clone V{ } clone f mb-writer boa ;
-: <mb-reader> ( -- mb-reader ) <mailbox> f mb-reader boa ;
-: push-line ( line test-reader-stream -- ) lines>> mailbox-put ;
-: <test-stream> ( -- stream ) <mb-reader> <mb-writer> <duplex-stream> ;
-M: mb-writer stream-write ( line mb-writer -- ) last-line>> push ;
-M: mb-writer stream-flush ( mb-writer -- ) drop ;
-M: mb-reader stream-readln ( mb-reader -- str/f ) lines>> mailbox-get ;
-M: mb-writer stream-nl ( mb-writer -- )
-    [ [ last-line>> concat ] [ lines>> ] bi push ] keep
-    V{ } clone >>last-line drop ;
-M: mb-reader dispose f swap push-line ;
-M: mb-writer dispose drop ;
-
-: spawn-client ( -- irc-client )
-    "someserver" irc-port "factorbot" f <irc-profile>
-    <irc-client>
-        t >>is-ready
-        t >>is-running
-        <test-stream> >>stream
-    dup [ spawn-irc yield ] with-irc-client ;
-
-! to be used inside with-irc-client quotations
-: %add-named-chat ( chat -- ) irc> attach-chat ;
-: %push-line ( line -- ) irc> stream>> in>> push-line yield ;
-: %join ( channel -- ) <irc-channel-chat> irc> attach-chat ;
-
-: read-matching-message ( chat quot: ( msg -- ? ) -- irc-message )
-    [ in-messages>> 0.1 seconds ] dip mailbox-get-timeout? ;
-
-: with-irc ( quot: ( -- ) -- )
-    [ spawn-client ] dip [ irc> terminate-irc ] compose with-irc-client ; inline
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!                       TESTS
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-[ { t } [ irc> nick>> me? ] unit-test
-
-  { "factorbot" } [ irc> nick>> ] unit-test
-
-  { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
-
-  { "#factortest" } [ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
-                      parse-irc-line forward-name ] unit-test
-
-  { "someuser" } [ ":someuser!n=user@some.where PRIVMSG factorbot :hi"
-                   parse-irc-line forward-name ] unit-test
-] with-irc
-
-! Test login and nickname set
-[ { "factorbot2" } [
-    ":some.where 001 factorbot2 :Welcome factorbot2" %push-line
-    irc> nick>>
-  ] unit-test
-] with-irc
-
-! Test connect
-{ V{ "NICK factorbot" "USER factorbot hostname servername :irc.factor" } } [
-    "someserver" irc-port "factorbot" f <irc-profile> <irc-client>
-    [ 2drop <test-stream> t ] >>connect
-    [ connect-irc ] [ stream>> out>> lines>> ] [ terminate-irc ] tri
-] unit-test
-
-! Test join
-[ { "JOIN #factortest" } [
-      "#factortest" %join
-      irc> stream>> out>> lines>> pop
-  ] unit-test
-] with-irc
-
-[ { join_ "#factortest" } [
-      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
-      { ":factorbot!n=factorbo@some.where JOIN :#factortest"
-        ":ircserver.net 353 factorbot @ #factortest :@factorbot "
-        ":ircserver.net 366 factorbot #factortest :End of /NAMES list."
-        ":ircserver.net 477 factorbot #factortest :[ircserver-info] blah blah"
-      } [ %push-line ] each
-      in-messages>> 0.1 seconds mailbox-get-timeout
-      [ class ] [ trailing>> ] bi
-  ] unit-test
-] with-irc
-
-[ { T{ participant-changed f "somebody" +join+ } } [
-      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
-      ":somebody!n=somebody@some.where JOIN :#factortest" %push-line
-      [ participant-changed? ] read-matching-message
-  ] unit-test
-] with-irc
-
-[ { privmsg "#factortest" "hello" } [
-      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
-      ":somebody!n=somebody@some.where PRIVMSG #factortest :hello" %push-line
-      [ privmsg? ] read-matching-message
-      [ class ] [ name>> ] [ trailing>> ] tri
-  ] unit-test
-] with-irc
-
-[ { privmsg "factorbot" "hello" } [
-      "ircuser" <irc-nick-chat>  [ %add-named-chat ] keep
-      ":ircuser!n=user@isp.net PRIVMSG factorbot :hello" %push-line
-      [ privmsg? ] read-matching-message
-      [ class ] [ name>> ] [ trailing>> ] tri
-  ] unit-test
-] with-irc
-
-[ { mode } [
-      "#factortest" <irc-channel-chat>  [ %add-named-chat ] keep
-      ":ircserver.net MODE #factortest +ns" %push-line
-      [ mode? ] read-matching-message class
-  ] unit-test
-] with-irc
-
-! Participant lists tests
-[ { H{ { "ircuser" +normal+ } } } [
-      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
-      ":ircuser!n=user@isp.net JOIN :#factortest" %push-line
-      participants>>
-  ] unit-test
-] with-irc
-
-[ { H{ { "ircuser2" +normal+ } } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser2" +normal+ }
-             { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircuser!n=user@isp.net PART #factortest" %push-line
-      participants>>
-  ] unit-test
-] with-irc
-
-[ { H{ { "ircuser2" +normal+ } } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser2" +normal+ }
-             { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircuser!n=user@isp.net QUIT" %push-line
-      participants>>
-  ] unit-test
-] with-irc
-
-[ { H{ { "ircuser2" +normal+ } } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser2" +normal+ }
-             { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircuser2!n=user2@isp.net KICK #factortest ircuser" %push-line
-      participants>>
-  ] unit-test
-] with-irc
-
-[ { H{ { "ircuser2" +normal+ } } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircuser!n=user2@isp.net NICK :ircuser2" %push-line
-      participants>>
-  ] unit-test
-] with-irc
-
-[ { H{ { "factorbot" +operator+ } { "ircuser" +normal+ } } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircserver.net 353 factorbot @ #factortest :@factorbot " %push-line
-      ":ircserver.net 353 factorbot @ #factortest :ircuser2 " %push-line
-      ":ircserver.net 366 factorbot #factortest :End of /NAMES list." %push-line
-      ":ircserver.net 353 factorbot @ #factortest :@factorbot " %push-line
-      ":ircserver.net 353 factorbot @ #factortest :ircuser " %push-line
-      ":ircserver.net 366 factorbot #factortest :End of /NAMES list." %push-line
-      participants>>
-  ] unit-test
-] with-irc
-
-! Namelist change notification
-[ { T{ participant-changed f f f f } } [
-      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
-      ":ircserver.net 353 factorbot @ #factortest :@factorbot " %push-line
-      ":ircserver.net 366 factorbot #factortest :End of /NAMES list." %push-line
-      [ participant-changed? ] read-matching-message
-  ] unit-test
-] with-irc
-
-[ { T{ participant-changed f "ircuser" +part+ f } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircuser!n=user@isp.net QUIT" %push-line
-      [ participant-changed? ] read-matching-message
-  ] unit-test
-] with-irc
-
-[ { T{ participant-changed f "ircuser" +nick+ "ircuser2" } } [
-      "#factortest" <irc-channel-chat>
-          H{ { "ircuser" +normal+ } } clone >>participants
-      [ %add-named-chat ] keep
-      ":ircuser!n=user2@isp.net NICK :ircuser2" %push-line
-      [ participant-changed? ] read-matching-message
-  ] unit-test
-] with-irc
-
-! Mode change
-[ { T{ participant-changed f "ircuser" +mode+ "+o" } } [
-      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
-      ":ircserver.net MODE #factortest +o ircuser" %push-line
-      [ participant-changed? ] read-matching-message
-  ] unit-test
-] with-irc
index 97fa65920908c5494a119c35f4cc6edfd22d194b..ae48d3ac4e2de0f30522b17cb4bec63f11044a72 100755 (executable)
 ! Copyright (C) 2008 Bruno Deferrari, Doug Coleman, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: concurrency.mailboxes kernel io.sockets io.encodings.8-bit calendar
-       accessors destructors namespaces io assocs arrays fry
-       continuations threads strings classes combinators splitting hashtables
-       ascii irc.messages ;
-RENAME: join sequences => sjoin
-EXCLUDE: sequences => join ;
+USING: accessors concurrency.mailboxes destructors
+irc.client.base irc.client.chats irc.client.internals kernel
+namespaces sequences ;
 IN: irc.client
 
-! ======================================
-! Setup and running objects
-! ======================================
-
-CONSTANT: irc-port 6667 ! Default irc port
-
-TUPLE: irc-profile server port nickname password ;
-C: <irc-profile> irc-profile
-
-TUPLE: irc-client profile stream in-messages out-messages
-       chats is-running nick connect reconnect-time is-ready ;
-
-: <irc-client> ( profile -- irc-client )
-    irc-client new
-        swap >>profile
-        <mailbox> >>in-messages
-        <mailbox> >>out-messages
-        H{ } clone >>chats
-        dup profile>> nickname>> >>nick
-        [ <inet> latin1 <client> ] >>connect
-        15 seconds >>reconnect-time ;
-
-TUPLE: irc-chat in-messages client ;
-TUPLE: irc-server-chat < irc-chat ;
-TUPLE: irc-channel-chat < irc-chat name password timeout participants clean-participants ;
-TUPLE: irc-nick-chat < irc-chat name ;
-SYMBOL: +server-chat+
-
-! participant modes
-SYMBOL: +operator+
-SYMBOL: +voice+
-SYMBOL: +normal+
-
-: participant-mode ( n -- mode )
-    H{ { 64 +operator+ } { 43 +voice+ } { 0 +normal+ } } at ;
-
-! participant changed actions
-SYMBOL: +join+
-SYMBOL: +part+
-SYMBOL: +mode+
-SYMBOL: +nick+
-
-! chat objects
-: <irc-server-chat> ( -- irc-server-chat )
-     <mailbox> f irc-server-chat boa ;
-
-: <irc-channel-chat> ( name -- irc-channel-chat )
-     [ <mailbox> f ] dip f 60 seconds H{ } clone t
-     irc-channel-chat boa ;
-
-: <irc-nick-chat> ( name -- irc-nick-chat )
-     [ <mailbox> f ] dip irc-nick-chat boa ;
-
-! ======================================
-! Message objects
-! ======================================
-
-TUPLE: participant-changed nick action parameter ;
-C: <participant-changed> participant-changed
-
-SINGLETON: irc-chat-end     ! sent to a chat to stop its execution
-SINGLETON: irc-end          ! sent when the client isn't running anymore
-SINGLETON: irc-disconnected ! sent when connection is lost
-SINGLETON: irc-connected    ! sent when connection is established
-
-: terminate-irc ( irc-client -- )
-    [ is-running>> ] keep and [
-        f >>is-running
-        [ stream>> dispose ] keep
-        [ in-messages>> ] [ out-messages>> ] bi 2array
-        [ irc-end swap mailbox-put ] each
-    ] when* ;
-
-<PRIVATE
-
-SYMBOL: current-irc-client
-
-! ======================================
-! Utils
-! ======================================
-
-: irc> ( -- irc-client ) current-irc-client get ;
-: irc-write ( s -- ) irc> stream>> stream-write ;
-: irc-print ( s -- ) irc> stream>> [ stream-print ] keep stream-flush ;
-: irc-send ( irc-message -- ) irc> out-messages>> mailbox-put ;
-: chat> ( name -- chat/f ) irc> chats>> at ;
-: channel-mode? ( mode -- ? ) name>> first "#&" member? ;
-: me? ( string -- ? ) irc> nick>> = ;
-
-GENERIC: to-chat ( message obj -- )
-
-M: string to-chat
-    chat> [ +server-chat+ chat> ] unless*
-    [ to-chat ] [ drop ] if* ;
-
-M: irc-chat to-chat in-messages>> mailbox-put ;
-
-: unregister-chat ( name -- )
-    irc> chats>>
-        [ at [ irc-chat-end ] dip to-chat ]
-        [ delete-at ]
-    2bi ;
-
-: (remove-participant) ( nick chat -- )
-    [ participants>> delete-at ]
-    [ [ +part+ f <participant-changed> ] dip to-chat ] 2bi ;
-
-: remove-participant ( nick channel -- )
-    chat> [ (remove-participant) ] [ drop ] if* ;
-
-: chats-with-participant ( nick -- seq )
-    irc> chats>> values
-    [ [ irc-channel-chat? ] keep and [ participants>> key? ] [ drop f ] if* ]
-    with filter ;
-
-: to-chats-with-participant ( message nickname -- )
-    chats-with-participant [ to-chat ] with each ;
-
-: remove-participant-from-all ( nick -- )
-    dup chats-with-participant [ (remove-participant) ] with each ;
-
-: notify-rename ( newnick oldnick chat -- )
-    [ participant-changed new +nick+ >>action
-      [ (>>nick) ] [ (>>parameter) ] [ ] tri ] dip to-chat ;
-
-: rename-participant ( newnick oldnick chat -- )
-    [ participants>> [ delete-at* drop ] [ swapd set-at ] bi ]
-    [ notify-rename ] 3bi ;
-
-: rename-participant-in-all ( oldnick newnick -- )
-    swap dup chats-with-participant [ rename-participant ] with with each ;
-
-: add-participant ( mode nick channel -- )
-    chat>
-    [ participants>> set-at ]
-    [ [ +join+ f <participant-changed> ] dip to-chat ] 2bi ;
-
-: change-participant-mode ( channel mode nick -- )
-    rot chat>
-    [ participants>> set-at ]
-    [ [ participant-changed new
-        [ (>>nick) ] [ (>>parameter) ] [ +mode+ >>action ] tri ] dip to-chat ]
-    3bi ; ! FIXME
-
-! ======================================
-! IRC client messages
-! ======================================
-
-: /NICK ( nick -- )
-    "NICK " irc-write irc-print ;
-
-: /LOGIN ( nick -- )
-    dup /NICK
-    "USER " irc-write irc-write
-    " hostname servername :irc.factor" irc-print ;
-
-: /CONNECT ( server port -- stream )
-    irc> connect>> call drop ; inline
-
-: /JOIN ( channel password -- )
-    "JOIN " irc-write
-    [ [ " :" ] dip 3append ] when* irc-print ;
-
-: /PONG ( text -- )
-    "PONG " irc-write irc-print ;
-
-! ======================================
-! Server message handling
-! ======================================
-
-GENERIC: initialize-chat ( chat -- )
-M: irc-chat initialize-chat drop ;
-M: irc-channel-chat initialize-chat [ name>> ] [ password>> ] bi /JOIN ;
-
-GENERIC: forward-name ( irc-message -- name )
-M: join forward-name trailing>> ;
-M: part forward-name channel>> ;
-M: kick forward-name channel>> ;
-M: mode forward-name name>> ;
-M: privmsg forward-name dup name>> me? [ irc-message-sender ] [ name>> ] if ;
-
-UNION: single-forward join part kick mode privmsg ;
-UNION: multiple-forward nick quit ;
-UNION: broadcast-forward irc-end irc-disconnected irc-connected ;
-GENERIC: forward-message ( irc-message -- )
-
-M: irc-message forward-message
-    +server-chat+ chat> [ to-chat ] [ drop ] if* ;
-
-M: single-forward forward-message dup forward-name to-chat ;
-
-M: multiple-forward forward-message
-    dup irc-message-sender to-chats-with-participant ;
-  
-M: broadcast-forward forward-message
-    irc> chats>> values [ to-chat ] with each ;
-
-GENERIC: process-message ( irc-message -- )
-M: object      process-message drop ; 
-M: logged-in   process-message
-    name>> t irc> [ (>>is-ready) ] [ (>>nick) ] [ chats>> ] tri
-    values [ initialize-chat ] each ;
-M: ping        process-message trailing>> /PONG ;
-M: nick-in-use process-message name>> "_" append /NICK ;
-
-M: join process-message
-    [ drop +normal+ ] [ irc-message-sender ] [ trailing>> ] tri
-    dup chat> [ add-participant ] [ 3drop ] if ;
-
-M: part process-message
-    [ irc-message-sender ] [ channel>> ] bi remove-participant ;
-
-M: kick process-message
-    [ [ who>> ] [ channel>> ] bi remove-participant ]
-    [ dup who>> me? [ unregister-chat ] [ drop ] if ]
-    bi ;
-
-M: quit process-message
-    irc-message-sender remove-participant-from-all ;
-
-M: nick process-message
-    [ irc-message-sender ] [ trailing>> ] bi rename-participant-in-all ;
-
-M: mode process-message ( mode -- )
-    [ channel-mode? ] keep and [
-        [ name>> ] [ mode>> ] [ parameter>> ] tri
-        [ change-participant-mode ] [ 2drop ] if*
-    ] when* ;
-
-: >nick/mode ( string -- nick mode )
-    dup first "+@" member? [ unclip ] [ 0 ] if participant-mode ;
-
-: names-reply>participants ( names-reply -- participants )
-    trailing>> [ blank? ] trim " " split
-    [ >nick/mode 2array ] map >hashtable ;
-
-: maybe-clean-participants ( channel-chat -- )
-    dup clean-participants>> [
-        H{ } clone >>participants f >>clean-participants
-    ] when drop ;
-
-M: names-reply process-message
-    [ names-reply>participants ] [ channel>> chat> ] bi [
-        [ maybe-clean-participants ] 
-        [ participants>> 2array assoc-combine ]
-        [ (>>participants) ] tri
-    ] [ drop ] if* ;
-
-M: end-of-names process-message
-    channel>> chat> [
-        t >>clean-participants
-        [ f f f <participant-changed> ] dip name>> to-chat
-    ] when* ;
-
-! ======================================
-! Client message handling
-! ======================================
-
-GENERIC: handle-outgoing-irc ( irc-message -- ? )
-M: irc-end     handle-outgoing-irc drop f ;
-M: irc-message handle-outgoing-irc irc-message>client-line irc-print t ;
-
-! ======================================
-! Reader/Writer
-! ======================================
-
-: handle-reader-message ( irc-message -- )
-    irc> in-messages>> mailbox-put ;
-
-DEFER: (connect-irc)
-
-: (handle-disconnect) ( -- )
-    irc>
-        [ [ irc-disconnected ] dip in-messages>> mailbox-put ]
-        [ dup reconnect-time>> sleep (connect-irc) ]
-        [ nick>> /LOGIN ]
-    tri ;
-
-! FIXME: do something with the exception, store somewhere to help debugging
-: handle-disconnect ( error -- ? )
-    drop irc> is-running>> [ (handle-disconnect) t ] [ f ] if ;
-
-: (reader-loop) ( -- ? )
-    irc> stream>> [
-        |dispose stream-readln [
-            parse-irc-line handle-reader-message t
-        ] [
-            handle-disconnect
-        ] if*
-    ] with-destructors ;
-
-: reader-loop ( -- ? )
-    [ (reader-loop) ] [ handle-disconnect ] recover ;
-
-: writer-loop ( -- ? )
-    irc> out-messages>> mailbox-get handle-outgoing-irc ;
-
-! ======================================
-! Processing loops
-! ======================================
-
-: in-multiplexer-loop ( -- ? )
-    irc> in-messages>> mailbox-get
-    [ forward-message ] [ process-message ] [ irc-end? not ] tri ;
-
-: strings>privmsg ( name string -- privmsg )
-    privmsg new [ (>>trailing) ] keep [ (>>name) ] keep ;
-
-: maybe-annotate-with-name ( name obj -- obj )
-    { { [ dup string? ] [ strings>privmsg ] }
-      { [ dup privmsg instance? ] [ swap >>name ] }
-      [ nip ]
-    } cond ;
-
-GENERIC: annotate-message ( chat object -- object )
-M: object  annotate-message nip ;
-M: part    annotate-message swap name>> >>channel ;
-M: privmsg annotate-message swap name>> >>name ;
-M: string  annotate-message [ name>> ] dip strings>privmsg ;
-
-: spawn-irc ( -- )
-    [ reader-loop ] "irc-reader-loop" spawn-server
-    [ writer-loop ] "irc-writer-loop" spawn-server
-    [ in-multiplexer-loop ] "in-multiplexer-loop" spawn-server
-    3drop ;
-
-GENERIC: (attach-chat) ( irc-chat -- )
-USE: prettyprint
-M: irc-chat (attach-chat)
-    [ [ irc> >>client ] [ name>> ] bi irc> chats>> set-at ]
-    [ [ irc> is-ready>> ] dip and [ initialize-chat ] when* ]
-    bi ;
-
-M: irc-server-chat (attach-chat)
-    irc> >>client +server-chat+ irc> chats>> set-at ;
-
-GENERIC: (remove-chat) ( irc-chat -- )
-
-M: irc-nick-chat (remove-chat)
-    name>> unregister-chat ;
-
-M: irc-channel-chat (remove-chat)
-    [ part new annotate-message irc> out-messages>> mailbox-put  ] keep
-    name>> unregister-chat ;
-
-M: irc-server-chat (remove-chat)
-   drop +server-chat+ unregister-chat ;
-
-: (connect-irc) ( irc-client -- )
-    {
-        [ profile>> [ server>> ] [ port>> ] bi /CONNECT ]
-        [ (>>stream) ]
-        [ t swap (>>is-running) ]
-        [ in-messages>> [ irc-connected ] dip mailbox-put ]
-    } cleave ;
-
-: with-irc-client ( irc-client quot: ( -- ) -- )
-    [ \ current-irc-client ] dip with-variable ; inline
-
-PRIVATE>
-
 : connect-irc ( irc-client -- )
-    dup [ [ (connect-irc) ] [ nick>> /LOGIN ] bi spawn-irc ] with-irc-client ;
-
-: attach-chat ( irc-chat irc-client -- ) [ (attach-chat) ] with-irc-client ;
-
-: detach-chat ( irc-chat -- )
-    [ client>> ] keep '[ _ (remove-chat) ] with-irc-client ;
-
-: speak ( message irc-chat -- )
-    [ swap annotate-message ] [ client>> out-messages>> mailbox-put ] bi ;
+    [ (connect-irc) (do-login) spawn-irc ] with-irc ;
 
+: attach-chat ( irc-chat irc-client -- ) [ (attach-chat) ] with-irc ;
+: detach-chat ( irc-chat -- ) dup [ client>> remove-chat ] with-irc ;
+: speak ( message irc-chat -- ) dup client>> [ (speak) ] with-irc ;
 : hear ( irc-chat -- message ) in-messages>> mailbox-get ;
+: terminate-irc ( irc-client -- ) [ (terminate-irc) ] with-irc ;
diff --git a/extra/irc/client/internals/authors.txt b/extra/irc/client/internals/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/client/internals/internals-tests.factor b/extra/irc/client/internals/internals-tests.factor
new file mode 100644 (file)
index 0000000..d20ae50
--- /dev/null
@@ -0,0 +1,213 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel tools.test accessors arrays sequences
+io io.streams.duplex namespaces threads destructors
+calendar concurrency.mailboxes classes assocs combinators
+irc.messages.parser irc.client.base irc.client.chats
+irc.client.participants irc.client.internals ;
+EXCLUDE: irc.messages => join ;
+RENAME: join irc.messages => join_
+IN: irc.client.internals.tests
+
+! Streams for testing
+TUPLE: mb-writer lines last-line disposed ;
+TUPLE: mb-reader lines disposed ;
+: <mb-writer> ( -- mb-writer ) V{ } clone V{ } clone f mb-writer boa ;
+: <mb-reader> ( -- mb-reader ) <mailbox> f mb-reader boa ;
+: push-line ( line test-reader-stream -- ) lines>> mailbox-put ;
+: <test-stream> ( -- stream ) <mb-reader> <mb-writer> <duplex-stream> ;
+M: mb-writer stream-write ( line mb-writer -- ) last-line>> push ;
+M: mb-writer stream-flush ( mb-writer -- ) drop ;
+M: mb-reader stream-readln ( mb-reader -- str/f ) lines>> mailbox-get ;
+M: mb-writer stream-nl ( mb-writer -- )
+    [ [ last-line>> concat ] [ lines>> ] bi push ] keep
+    V{ } clone >>last-line drop ;
+M: mb-reader dispose f swap push-line ;
+M: mb-writer dispose drop ;
+
+: spawn-client ( -- irc-client )
+    "someserver" irc-port "factorbot" f <irc-profile>
+    <irc-client>
+        t >>is-ready
+        t >>is-running
+        <test-stream> >>stream
+    dup [ spawn-irc yield ] with-irc ;
+
+! to be used inside with-irc quotations
+: %add-named-chat ( chat -- ) (attach-chat) ;
+: %push-line ( line -- ) irc> stream>> in>> push-line yield ;
+: %push-lines ( lines -- ) [ %push-line ] each ;
+: %join ( channel -- ) <irc-channel-chat> (attach-chat) ;
+: %pop-output-line ( -- string ) irc> stream>> out>> lines>> pop ;
+
+: read-matching-message ( chat quot: ( msg -- ? ) -- irc-message )
+    [ in-messages>> 0.1 seconds ] dip mailbox-get-timeout? ;
+
+: spawning-irc ( quot: ( -- ) -- )
+    [ spawn-client ] dip [ (terminate-irc) ] compose with-irc ; inline
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!                       TESTS
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+[ { t } [ irc> nick>> me? ] unit-test
+
+  { "factorbot" } [ irc> nick>> ] unit-test
+
+  { "#factortest" } [ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
+                      string>irc-message chat-name ] unit-test
+
+  { "someuser" } [ ":someuser!n=user@some.where PRIVMSG factorbot :hi"
+                   string>irc-message chat-name ] unit-test
+] spawning-irc
+
+{ privmsg "#channel" "hello" } [
+    "#channel" "hello" strings>privmsg
+    [ class ] [ target>> ] [ trailing>> ] tri
+] unit-test
+
+! Test login and nickname set
+[ { "factorbot2" } [
+    ":some.where 001 factorbot2 :Welcome factorbot2" %push-line
+    irc> nick>>
+  ] unit-test
+] spawning-irc
+
+! Test connect
+{ V{ "NICK factorbot" "USER factorbot hostname servername :irc.factor" } } [
+    "someserver" irc-port "factorbot" f <irc-profile> <irc-client>
+    [ 2drop <test-stream> t ] >>connect
+    [
+        (connect-irc)
+        (do-login)
+        irc> stream>> out>> lines>>
+        (terminate-irc)
+    ] with-irc
+] unit-test
+
+! Test join
+[ { "JOIN #factortest" } [
+      "#factortest" %join %pop-output-line
+  ] unit-test
+] spawning-irc
+
+[ { join_ "#factortest"} [
+      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
+      { ":factorbot!n=factorbo@some.where JOIN :#factortest"
+        ":ircserver.net 353 factorbot @ #factortest :@factorbot "
+        ":ircserver.net 366 factorbot #factortest :End of /NAMES list."
+        ":ircserver.net 477 factorbot #factortest :[ircserver-info] blah blah"
+      } %push-lines
+      [ join? ] read-matching-message
+      [ class ] [ channel>> ] bi
+  ] unit-test
+] spawning-irc
+
+[ { privmsg "#factortest" "hello" } [
+      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
+      ":somebody!n=somebody@some.where PRIVMSG #factortest :hello" %push-line
+      [ privmsg? ] read-matching-message
+      [ class ] [ target>> ] [ trailing>> ] tri
+  ] unit-test
+] spawning-irc
+
+[ { privmsg "factorbot" "hello" } [
+      "ircuser" <irc-nick-chat>  [ %add-named-chat ] keep
+      ":ircuser!n=user@isp.net PRIVMSG factorbot :hello" %push-line
+      [ privmsg? ] read-matching-message
+      [ class ] [ target>> ] [ trailing>> ] tri
+  ] unit-test
+] spawning-irc
+
+[ { mode "#factortest" "+ns" } [
+      "#factortest" <irc-channel-chat>  [ %add-named-chat ] keep
+      ":ircserver.net MODE #factortest +ns" %push-line
+      [ mode? ] read-matching-message
+      [ class ] [ name>> ] [ mode>> ] tri
+  ] unit-test
+] spawning-irc
+
+! Participant lists tests
+[ { { "ircuser" } } [
+      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
+      ":ircuser!n=user@isp.net JOIN :#factortest" %push-line
+      participants>> keys
+  ] unit-test
+] spawning-irc
+
+[ { { "ircuser2" } } [
+      "#factortest" <irc-channel-chat>
+      { "ircuser2" "ircuser" } [ over join-participant ] each
+      [ %add-named-chat ] keep
+      ":ircuser!n=user@isp.net PART #factortest" %push-line
+      participants>> keys
+  ] unit-test
+] spawning-irc
+
+[ { { "ircuser2" } } [
+      "#factortest" <irc-channel-chat>
+      { "ircuser2" "ircuser" } [ over join-participant ] each
+      [ %add-named-chat ] keep
+      ":ircuser!n=user@isp.net QUIT" %push-line
+      participants>> keys
+  ] unit-test
+] spawning-irc
+
+[ { { "ircuser2" } } [
+      "#factortest" <irc-channel-chat>
+      { "ircuser2" "ircuser" } [ over join-participant ] each
+      [ %add-named-chat ] keep
+      ":ircuser2!n=user2@isp.net KICK #factortest ircuser" %push-line
+      participants>> keys
+  ] unit-test
+] spawning-irc
+
+[ { H{ { "ircuser2" T{ participant { nick "ircuser2" } } } } } [
+      "#factortest" <irc-channel-chat>
+      "ircuser" over join-participant
+      [ %add-named-chat ] keep
+      ":ircuser!n=user2@isp.net NICK :ircuser2" %push-line
+      participants>>
+  ] unit-test
+] spawning-irc
+
+[ { H{ { "factorbot" T{ participant { nick "factorbot" } { operator t } } }
+       { "ircuser" T{ participant { nick "ircuser" } } }
+       { "voiced" T{ participant { nick "voiced" } { voice t } } } } } [
+      "#factortest" <irc-channel-chat>
+      "ircuser" over join-participant
+      [ %add-named-chat ] keep
+      { ":ircserver.net 353 factorbot @ #factortest :@factorbot "
+        ":ircserver.net 353 factorbot @ #factortest :ircuser2 "
+        ":ircserver.net 366 factorbot #factortest :End of /NAMES list."
+        ":ircserver.net 353 factorbot @ #factortest :@factorbot +voiced "
+        ":ircserver.net 353 factorbot @ #factortest :ircuser "
+        ":ircserver.net 366 factorbot #factortest :End of /NAMES list."
+      } %push-lines
+      participants>>
+  ] unit-test
+] spawning-irc
+
+[ { mode "#factortest" "+o" "ircuser" } [
+      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
+      "ircuser" over join-participant
+      ":ircserver.net MODE #factortest +o ircuser" %push-line
+      [ mode? ] read-matching-message
+      { [ class ] [ name>> ] [ mode>> ] [ parameter>> ] } cleave
+  ] unit-test
+] spawning-irc
+
+[ { T{ participant { nick "ircuser" } { operator t } } } [
+      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
+      "ircuser" over join-participant
+      ":ircserver.net MODE #factortest +o ircuser" %push-line
+      participants>> "ircuser" swap at
+  ] unit-test
+] spawning-irc
+
+! Send privmsg
+[ { "PRIVMSG #factortest :hello" } [
+      "#factortest" <irc-channel-chat> [ %add-named-chat ] keep
+      "hello" swap (speak) %pop-output-line
+  ] unit-test
+] spawning-irc
diff --git a/extra/irc/client/internals/internals.factor b/extra/irc/client/internals/internals.factor
new file mode 100644 (file)
index 0000000..5bae054
--- /dev/null
@@ -0,0 +1,166 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs arrays concurrency.mailboxes continuations destructors
+hashtables io irc.client.base irc.client.chats irc.messages kernel namespaces
+strings words.symbol irc.messages.base irc.client.participants fry threads
+combinators irc.messages.parser ;
+EXCLUDE: sequences => join ;
+IN: irc.client.internals
+
+: /NICK ( nick -- ) "NICK " prepend irc-print ;
+: /PONG ( text -- ) "PONG " prepend irc-print ;
+
+: /LOGIN ( nick -- )
+    dup /NICK
+    "USER " prepend " hostname servername :irc.factor" append irc-print ;
+
+: /CONNECT ( server port -- stream )
+    irc> connect>> call( host port -- stream local ) drop ;
+
+: /JOIN ( channel password -- )
+    [ " :" swap 3append ] when* "JOIN " prepend irc-print ;
+
+: (connect-irc) ( -- )
+    irc> {
+        [ profile>> [ server>> ] [ port>> ] bi /CONNECT ]
+        [ (>>stream) ]
+        [ t swap (>>is-running) ]
+        [ in-messages>> [ irc-connected ] dip mailbox-put ]
+    } cleave ;
+
+: (do-login) ( -- ) irc> nick>> /LOGIN ;
+
+GENERIC: initialize-chat ( chat -- )
+M: irc-chat         initialize-chat drop ;
+M: irc-channel-chat initialize-chat [ name>> ] [ password>> ] bi /JOIN ;
+
+GENERIC: chat-put ( message obj -- )
+M: irc-chat chat-put in-messages>> mailbox-put ;
+M: symbol   chat-put chat> [ chat-put ] [ drop ] if* ;
+M: string   chat-put chat> +server-chat+ or chat-put ;
+M: sequence chat-put [ chat-put ] with each ;
+
+: delete-chat ( name -- ) irc> chats>> delete-at ;
+: unregister-chat ( name -- ) [ irc-chat-end chat-put ] [ delete-chat ] bi ;
+
+! Server message handling
+
+GENERIC: message-forwards ( irc-message -- seq )
+M: irc-message   message-forwards drop +server-chat+ ;
+M: to-one-chat   message-forwards chat> ;
+M: to-all-chats  message-forwards drop chats> ;
+M: to-many-chats message-forwards sender>> participant-chats ;
+
+GENERIC: process-message ( irc-message -- )
+M: object process-message drop ; 
+M: ping   process-message trailing>> /PONG ;
+M: join   process-message [ sender>> ] [ chat> ] bi join-participant ;
+M: part   process-message [ sender>> ] [ chat> ] bi part-participant ;
+M: quit   process-message sender>> quit-participant ;
+M: nick   process-message [ trailing>> ] [ sender>> ] bi rename-participant* ;
+M: rpl-nickname-in-use process-message name>> "_" append /NICK ;
+
+M: rpl-welcome process-message
+    irc>
+        swap nickname>> >>nick
+        t >>is-ready
+    chats>> values [ initialize-chat ] each ;
+
+M: kick process-message
+    [ [ user>> ] [ chat> ] bi part-participant ]
+    [ dup user>> me? [ unregister-chat ] [ drop ] if ]
+    bi ;
+
+M: participant-mode process-message ( participant-mode -- )
+    [ mode>> ] [ name>> ] [ parameter>> ] tri change-participant-mode ;
+
+M: rpl-names process-message
+    [ nicks>> ] [ chat> ] bi dup ?clear-participants
+    '[ _ join-participant ] each ;
+
+M: rpl-names-end process-message chat> t >>clear-participants drop ;
+
+! Client message handling
+
+GENERIC: handle-outgoing-irc ( irc-message -- ? )
+M: irc-end     handle-outgoing-irc drop f ;
+M: irc-message handle-outgoing-irc irc-message>string irc-print t ;
+
+! Reader/Writer
+
+: handle-reader-message ( irc-message -- ) irc> in-messages>> mailbox-put ;
+
+: (handle-disconnect) ( -- )
+    irc-disconnected irc> in-messages>> mailbox-put
+    irc> reconnect-time>> sleep
+    (connect-irc)
+    (do-login) ;
+
+: handle-disconnect ( error -- ? )
+    [ irc> exceptions>> push ] when*
+    irc> is-running>> [ (handle-disconnect) t ] [ f ] if ;
+
+GENERIC: handle-input ( line/f -- ? )
+M: string handle-input string>irc-message handle-reader-message t ;
+M: f      handle-input handle-disconnect ;
+
+: (reader-loop) ( -- ? )
+    stream> [ |dispose stream-readln handle-input ] with-destructors ;
+
+: reader-loop ( -- ? ) [ (reader-loop) ] [ handle-disconnect ] recover ;
+: writer-loop ( -- ? ) irc> out-messages>> mailbox-get handle-outgoing-irc ;
+
+! Processing loops
+
+: in-multiplexer-loop ( -- ? )
+    irc> in-messages>> mailbox-get {
+        [ message-forwards ]
+        [ process-message ]
+        [ swap chat-put ]
+        [ irc-end? not ]
+    } cleave ;
+
+: strings>privmsg ( name string -- privmsg )
+    " :" prepend append "PRIVMSG " prepend string>irc-message ;
+
+GENERIC: annotate-message ( chat object -- object )
+M: object     annotate-message nip ;
+M: to-channel annotate-message swap name>> >>channel ;
+M: to-target  annotate-message swap name>> >>target ;
+M: mode       annotate-message swap name>> >>name ;
+M: string     annotate-message [ name>> ] dip strings>privmsg ;
+
+: spawn-irc ( -- )
+    [ reader-loop ] "irc-reader-loop" spawn-server
+    [ writer-loop ] "irc-writer-loop" spawn-server
+    [ in-multiplexer-loop ] "in-multiplexer-loop" spawn-server
+    3drop ;
+
+GENERIC: (attach-chat) ( irc-chat -- )
+
+M: irc-chat (attach-chat)
+    irc>
+    [ [ chats>> ] [ >>client name>> swap ] 2bi set-at ]
+    [ is-ready>> [ initialize-chat ] [ drop ] if ]
+    2bi ;
+
+M: irc-server-chat (attach-chat)
+    irc> [ (>>client) ] [ chats>> +server-chat+ set-at ] 2bi ;
+
+GENERIC: remove-chat ( irc-chat -- )
+M: irc-nick-chat remove-chat name>> unregister-chat ;
+M: irc-server-chat remove-chat drop +server-chat+ unregister-chat ;
+
+M: irc-channel-chat remove-chat
+    [ part new annotate-message irc-send ]
+    [ name>> unregister-chat ] bi ;
+
+: (terminate-irc) ( -- )
+    irc> dup is-running>> [
+        f >>is-running
+        [ stream>> dispose ] keep
+        [ in-messages>> ] [ out-messages>> ] bi 2array
+        [ irc-end swap mailbox-put ] each
+    ] [ drop ] if ;
+
+: (speak) ( message irc-chat -- ) swap annotate-message irc-send ;
\ No newline at end of file
diff --git a/extra/irc/client/internals/summary.txt b/extra/irc/client/internals/summary.txt
new file mode 100644 (file)
index 0000000..a831199
--- /dev/null
@@ -0,0 +1 @@
+IRC Client internals
diff --git a/extra/irc/client/participants/authors.txt b/extra/irc/client/participants/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/client/participants/participants.factor b/extra/irc/client/participants/participants.factor
new file mode 100644 (file)
index 0000000..8d367db
--- /dev/null
@@ -0,0 +1,55 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs combinators fry hashtables
+irc.client.base irc.client.chats kernel sequences splitting ;
+IN: irc.client.participants
+
+TUPLE: participant nick operator voice ;
+: <participant> ( name -- participant )
+    {
+        { [ "@" ?head ] [ t f ] }
+        { [ "+" ?head ] [ f t ] }
+        [ f f ]
+    } cond participant boa ;
+
+GENERIC: has-participant? ( name irc-chat -- ? )
+M: irc-chat         has-participant? 2drop f ;
+M: irc-channel-chat has-participant? participants>> key? ;
+
+: rename-X ( new old assoc quot: ( obj value -- obj ) -- )
+    '[ delete-at* drop swap @ ] [ nip set-at ] 3bi ; inline
+
+: rename-nick-chat ( new old -- ) irc> chats>> [ >>name ] rename-X ;
+: rename-participant ( new old chat -- ) participants>> [ >>nick ] rename-X ;
+: part-participant ( nick irc-chat -- ) participants>> delete-at ;
+: participant-chats ( nick -- seq ) chats> [ has-participant? ] with filter ;
+
+: quit-participant ( nick -- )
+    dup participant-chats [ part-participant ] with each ;
+
+: rename-participant* ( new old -- )
+    [ dup participant-chats [ rename-participant ] with with each ]
+    [ dup chat> [ rename-nick-chat ] [ 2drop ] if ]
+    2bi ;
+
+: join-participant ( nick irc-channel-chat -- )
+    participants>> [ <participant> dup nick>> ] dip set-at ;
+
+: apply-mode ( ? participant mode -- )
+    {
+        { CHAR: o [ (>>operator) ] }
+        { CHAR: v [ (>>voice) ] }
+        [ 3drop ]
+    } case ;
+
+: apply-modes ( mode-line participant -- )
+    [ unclip CHAR: + = ] dip
+    '[ [ _ _ ] dip apply-mode ] each ;
+
+: change-participant-mode ( mode channel nick -- )
+    swap chat> participants>> at apply-modes ;
+
+: ?clear-participants ( channel-chat -- )
+    dup clear-participants>> [
+        f >>clear-participants participants>> clear-assoc
+    ] [ drop ] if ;
diff --git a/extra/irc/client/participants/summary.txt b/extra/irc/client/participants/summary.txt
new file mode 100644 (file)
index 0000000..3e88e61
--- /dev/null
@@ -0,0 +1 @@
+IRC Client chat participants handling
index 3b7694a34774757b890079fb8619ed17fc275f21..d145b3bd2c447861c04d1101d3644d3ce79a4f5e 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: fry irc.client irc.client.private kernel namespaces
+USING: fry irc.client irc.client.chats kernel namespaces
 sequences threads io.encodings.8-bit io.launcher io splitting
 make mason.common mason.updates calendar math alarms ;
 IN: irc.gitbot
diff --git a/extra/irc/logbot/authors.txt b/extra/irc/logbot/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/logbot/log-line/authors.txt b/extra/irc/logbot/log-line/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/logbot/log-line/log-line.factor b/extra/irc/logbot/log-line/log-line.factor
new file mode 100644 (file)
index 0000000..b3af41a
--- /dev/null
@@ -0,0 +1,37 @@
+! Copyright (C) 2009 Bruno Deferrari.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors irc.messages irc.messages.base kernel make ;
+EXCLUDE: sequences => join ;
+IN: irc.logbot.log-line
+
+: dot-or-parens ( string -- string )
+    [ "." ] [ " (" prepend ")." append ] if-empty ;
+
+GENERIC: >log-line ( object -- line )
+
+M: irc-message >log-line line>> ;
+
+M: privmsg >log-line
+    [ "<" % dup sender>> % "> " % text>> % ] "" make ;
+
+M: join >log-line
+    [ "* " % sender>> % " has joined the channel." % ] "" make ;
+
+M: part >log-line
+    [ "* " % dup sender>> % " has left the channel" %
+      comment>> dot-or-parens % ] "" make ;
+
+M: quit >log-line
+    [ "* " % dup sender>> % " has quit" %
+      comment>> dot-or-parens % ] "" make ;
+
+M: kick >log-line
+    [ "* " % dup sender>> % " has kicked " % dup user>> %
+      " from the channel" % comment>> dot-or-parens % ] "" make ;
+
+M: participant-mode >log-line
+    [ "* " % dup sender>> % " has set mode " % dup mode>> %
+      " to " % parameter>> % ] "" make ;
+
+M: nick >log-line
+    [ "* " % dup sender>> % " is now known as " % nickname>> % ] "" make ;
diff --git a/extra/irc/logbot/log-line/summary.txt b/extra/irc/logbot/log-line/summary.txt
new file mode 100644 (file)
index 0000000..96ab2bf
--- /dev/null
@@ -0,0 +1 @@
+IRC message formatting for logs
diff --git a/extra/irc/logbot/logbot.factor b/extra/irc/logbot/logbot.factor
new file mode 100644 (file)
index 0000000..a389304
--- /dev/null
@@ -0,0 +1,56 @@
+! Copyright (C) 2009 Bruno Deferrari.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors calendar calendar.format destructors fry io io.encodings.8-bit
+io.files io.pathnames irc.client irc.client.chats irc.messages
+irc.messages.base kernel make namespaces sequences threads
+irc.logbot.log-line ;
+IN: irc.logbot
+
+CONSTANT: bot-channel "#concatenative"
+CONSTANT: log-directory "/tmp/logs"
+
+SYMBOL: current-day
+SYMBOL: current-stream
+
+: bot-profile ( -- obj )
+    "irc.freenode.org" 6667 "flogger" f <irc-profile> ;
+
+: add-timestamp ( string timestamp -- string )
+    timestamp>hms "[" prepend "] " append prepend ;
+
+: timestamp-path ( timestamp -- path )
+    timestamp>ymd ".log" append log-directory prepend-path ;
+
+: timestamp>stream ( timestamp  -- stream )
+    dup day-of-year current-day get = [
+        drop
+    ] [
+        current-stream get [ dispose ] when*
+        [ day-of-year current-day set ]
+        [ timestamp-path latin1 <file-writer> ] bi
+        current-stream set
+    ] if current-stream get ;
+
+: log-message ( string timestamp -- )
+    [ add-timestamp ] [ timestamp>stream ] bi
+    [ stream-print ] [ stream-flush ] bi ;
+
+GENERIC: handle-message ( msg -- )
+
+M: object      handle-message drop ;
+M: irc-message handle-message [ >log-line ] [ timestamp>> ] bi log-message ;
+
+: bot-loop ( chat -- ) dup hear handle-message bot-loop ;
+
+: start-bot ( -- )
+    bot-profile <irc-client>
+    [ connect-irc ]
+    [
+        [ bot-channel <irc-channel-chat> ] dip
+        '[ _ [ _ attach-chat ] [ bot-loop ] bi ]
+        "LogBot" spawn drop
+    ] bi ;
+
+: logbot ( -- ) start-bot ;
+
+MAIN: logbot
diff --git a/extra/irc/logbot/summary.txt b/extra/irc/logbot/summary.txt
new file mode 100644 (file)
index 0000000..1e49fcb
--- /dev/null
@@ -0,0 +1 @@
+An IRC logging bot
diff --git a/extra/irc/messages/base/authors.txt b/extra/irc/messages/base/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/messages/base/base.factor b/extra/irc/messages/base/base.factor
new file mode 100644 (file)
index 0000000..d67d226
--- /dev/null
@@ -0,0 +1,115 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs classes.parser classes.tuple
+       combinators fry generic.parser kernel lexer
+       mirrors namespaces parser sequences splitting strings words ;
+IN: irc.messages.base
+
+TUPLE: irc-message line prefix command parameters trailing timestamp sender ;
+TUPLE: unhandled < irc-message ;
+
+SYMBOL: string-irc-type-mapping
+string-irc-type-mapping [ H{ } clone ] initialize
+
+: register-irc-message-type ( type string -- )
+    string-irc-type-mapping get set-at ;
+
+: irc>type ( string -- irc-message-class )
+    string-irc-type-mapping get at unhandled or ;
+
+GENERIC: irc-trailing-slot ( irc-message -- string/f )
+M: irc-message irc-trailing-slot
+    drop f ;
+
+GENERIC: irc-parameter-slots ( irc-message -- seq )
+M: irc-message irc-parameter-slots
+    drop f ;
+
+GENERIC: process-irc-trailing ( irc-message -- )
+M: irc-message process-irc-trailing
+    dup irc-trailing-slot [
+        swap [ trailing>> swap ] [ <mirror> ] bi set-at
+    ] [ drop ] if* ;
+
+GENERIC: process-irc-prefix ( irc-message -- )
+M: irc-message process-irc-prefix
+    drop ;
+
+<PRIVATE
+: [slot-setter] ( mirror -- quot )
+    '[ [ _ set-at ] [ drop ] if* ] ; inline
+PRIVATE>
+
+GENERIC: process-irc-parameters ( irc-message -- )
+M: irc-message process-irc-parameters
+    dup irc-parameter-slots [
+        swap [ parameters>> swap ] [ <mirror> [slot-setter] ] bi 2each
+    ] [ drop ] if* ;
+
+GENERIC: post-process-irc-message ( irc-message -- )
+M: irc-message post-process-irc-message drop ;
+
+GENERIC: fill-irc-message-slots ( irc-message -- )
+M: irc-message fill-irc-message-slots
+    {
+        [ process-irc-trailing ]
+        [ process-irc-prefix ]
+        [ process-irc-parameters ]
+        [ post-process-irc-message ]
+    } cleave ;
+
+GENERIC: irc-command-string ( irc-message -- string )
+M: irc-message irc-command-string drop f ;
+
+! FIXME: inverse of post-process is missing
+GENERIC: set-irc-parameters ( irc-message -- )
+M: irc-message set-irc-parameters
+    dup irc-parameter-slots
+    [ over <mirror> '[ _ at ] map >>parameters ] when* drop ;
+
+GENERIC: set-irc-trailing ( irc-message -- )
+M: irc-message set-irc-trailing
+    dup irc-trailing-slot [ over <mirror> at >>trailing ] when* drop ;
+
+GENERIC: set-irc-command ( irc-message -- )
+M: irc-message set-irc-command
+    [ irc-command-string ] [ (>>command) ] bi ;
+
+: irc-message>string ( irc-message -- string )
+    {
+        [ prefix>> ]
+        [ command>> ]
+        [ parameters>> " " join ]
+        [ trailing>> dup [ CHAR: : prefix ] when ]
+    } cleave 4array sift " " join ;
+
+<PRIVATE
+: ?define-irc-parameters ( class slot-names -- )
+    dup empty? not [
+        [ \ irc-parameter-slots create-method-in ] dip
+        [ [ "_" = not ] keep and ] map '[ drop _ ] define
+    ] [ 2drop ] if ;
+
+: ?define-irc-trailing ( class slot-name -- )
+    [
+        [ \ irc-trailing-slot create-method-in ] dip
+        first '[ drop _ ] define
+    ] [ drop ] if* ;
+
+: define-irc-class ( class params -- )
+    [ { ":" "_" } member? not ] filter
+    [ irc-message ] dip define-tuple-class ;
+
+: define-irc-parameter-slots ( class params -- )
+    { ":" } split1 [ over ] dip
+    [ ?define-irc-parameters ] [ ?define-irc-trailing ] 2bi* ;
+PRIVATE>
+
+#! SYNTAX:
+#! IRC: type "COMMAND" slot1 ...;
+#! IRC: type "COMMAND" slot1 ... : trailing-slot;
+SYNTAX: IRC: ( name string parameters -- )
+    CREATE-CLASS
+    [ scan-object register-irc-message-type ] keep
+    ";" parse-tokens
+    [ define-irc-class ] [ define-irc-parameter-slots ] 2bi ;
diff --git a/extra/irc/messages/base/summary.txt b/extra/irc/messages/base/summary.txt
new file mode 100644 (file)
index 0000000..1a05067
--- /dev/null
@@ -0,0 +1 @@
+IRC messages base implementation
index ac1d003b1b7f475b6316657a46d2dc3cfc6ec88a..218ed92018908c7d6bf2d4d45ba2027f60bb257a 100644 (file)
@@ -1,19 +1,12 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
 USING: kernel tools.test accessors arrays
-       irc.messages irc.messages.private ;
+       irc.messages.parser irc.messages ;
 EXCLUDE: sequences => join ;
 IN: irc.messages.tests
 
 
-{ "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
-
-{ T{ irc-message
-     { line ":someuser!n=user@some.where PRIVMSG #factortest :hi" }
-     { prefix "someuser!n=user@some.where" }
-     { command  "PRIVMSG" }
-     { parameters { "#factortest" } }
-     { trailing "hi" } } }
-[ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
-  string>irc-message f >>timestamp ] unit-test
+! { "someuser" } [ "someuser!n=user@some.where" parse-name ] unit-test
 
 { T{ privmsg
      { line ":someuser!n=user@some.where PRIVMSG #factortest :hi" }
@@ -21,18 +14,22 @@ IN: irc.messages.tests
      { command "PRIVMSG" }
      { parameters { "#factortest" } }
      { trailing "hi" }
-     { name "#factortest" } } }
+     { target "#factortest" }
+     { text "hi" }
+     { sender "someuser" } } }
 [ ":someuser!n=user@some.where PRIVMSG #factortest :hi"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ join
      { line ":someuser!n=user@some.where JOIN :#factortest" }
      { prefix "someuser!n=user@some.where" }
      { command "JOIN" }
      { parameters { } }
-     { trailing "#factortest" } } }
+     { trailing "#factortest" }
+     { sender "someuser" }
+     { channel "#factortest" } } }
 [ ":someuser!n=user@some.where JOIN :#factortest"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ mode
      { line ":ircserver.net MODE #factortest +ns" }
@@ -42,7 +39,7 @@ IN: irc.messages.tests
      { name "#factortest" }
      { mode "+ns" } } }
 [ ":ircserver.net MODE #factortest +ns"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ mode
      { line ":ircserver.net MODE #factortest +o someuser" }
@@ -53,18 +50,19 @@ IN: irc.messages.tests
      { mode "+o" }
      { parameter "someuser" } } }
 [ ":ircserver.net MODE #factortest +o someuser"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
 { T{ nick
      { line ":someuser!n=user@some.where NICK :someuser2" }
      { prefix "someuser!n=user@some.where" }
      { command "NICK" }
      { parameters  { } }
-     { trailing "someuser2" } } }
+     { trailing "someuser2" }
+     { sender "someuser" } } }
 [ ":someuser!n=user@some.where NICK :someuser2"
-  parse-irc-line f >>timestamp ] unit-test
+  string>irc-message f >>timestamp ] unit-test
 
-{ T{ nick-in-use
+{ T{ rpl-nickname-in-use
      { line ":ircserver.net 433 * nickname :Nickname is already in use" }
      { prefix "ircserver.net" }
      { command "433" }
@@ -72,4 +70,4 @@ IN: irc.messages.tests
      { name "nickname" }
      { trailing "Nickname is already in use" } } }
 [ ":ircserver.net 433 * nickname :Nickname is already in use"
-  parse-irc-line f >>timestamp ] unit-test
\ No newline at end of file
+  string>irc-message f >>timestamp ] unit-test
\ No newline at end of file
index c88bbc072ac3aa9c4c8b329ac1fa0614caa006f4..a6bf02f8a700e60af3153760a77123ad81b99954 100755 (executable)
-! Copyright (C) 2008 Bruno Deferrari
+! Copyright (C) 2009 Bruno Deferrari
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel fry splitting ascii calendar accessors combinators
-       arrays classes.tuple math.order ;
-RENAME: join sequences => sjoin
+arrays classes.tuple math.order words assocs strings irc.messages.base ;
 EXCLUDE: sequences => join ;
 IN: irc.messages
 
-TUPLE: irc-message line prefix command parameters trailing timestamp ;
-TUPLE: logged-in < irc-message name ;
-TUPLE: ping < irc-message ;
-TUPLE: join < irc-message ;
-TUPLE: part < irc-message channel ;
-TUPLE: quit < irc-message ;
-TUPLE: nick < irc-message ;
-TUPLE: privmsg < irc-message name ;
-TUPLE: kick < irc-message channel who ;
-TUPLE: roomlist < irc-message channel names ;
-TUPLE: nick-in-use < irc-message name ;
-TUPLE: notice < irc-message type ;
-TUPLE: mode < irc-message name mode parameter ;
-TUPLE: names-reply < irc-message who channel ;
-TUPLE: end-of-names < irc-message who channel ;
-TUPLE: unhandled < irc-message ;
-
-: <irc-client-message> ( command parameters trailing -- irc-message )
-    irc-message new
-        now >>timestamp
-        swap >>trailing
-        swap >>parameters
-        swap >>command ;
-
-<PRIVATE
-
-GENERIC: command-string>> ( irc-message -- string )
-
-M: irc-message command-string>> ( irc-message -- string ) command>> ;
-M: ping        command-string>> ( ping -- string )    drop "PING" ;
-M: join        command-string>> ( join -- string )    drop "JOIN" ;
-M: part        command-string>> ( part -- string )    drop "PART" ;
-M: quit        command-string>> ( quit -- string )    drop "QUIT" ;
-M: nick        command-string>> ( nick -- string )    drop "NICK" ;
-M: privmsg     command-string>> ( privmsg -- string ) drop "PRIVMSG" ;
-M: notice      command-string>> ( notice -- string )  drop "NOTICE" ;
-M: mode        command-string>> ( mode -- string )    drop "MODE" ;
-M: kick        command-string>> ( kick -- string )    drop "KICK" ;
-
-GENERIC: command-parameters>> ( irc-message -- seq )
-
-M: irc-message command-parameters>> ( irc-message -- seq ) parameters>> ;
-M: ping        command-parameters>> ( ping -- seq )    drop { } ;
-M: join        command-parameters>> ( join -- seq )    drop { } ;
-M: part        command-parameters>> ( part -- seq )    channel>> 1array ;
-M: quit        command-parameters>> ( quit -- seq )    drop { } ;
-M: nick        command-parameters>> ( nick -- seq )    drop { } ;
-M: privmsg     command-parameters>> ( privmsg -- seq ) name>> 1array ;
-M: notice      command-parameters>> ( norice -- seq )  type>> 1array ;
-M: kick command-parameters>> ( kick -- seq )
-    [ channel>> ] [ who>> ] bi 2array ;
-M: mode command-parameters>> ( mode -- seq )
-    [ name>> ] [ channel>> ] [ mode>> ] tri 3array ;
-
-GENERIC# >>command-parameters 1 ( irc-message params -- irc-message )
-
-M: irc-message >>command-parameters ( irc-message params -- irc-message )
-    drop ;
-
-M: logged-in >>command-parameters ( part params -- part )
-    first >>name ;
-
-M: privmsg >>command-parameters ( privmsg params -- privmsg )
-    first >>name ;
-
-M: notice >>command-parameters ( notice params -- notice )
-    first >>type ;
-
-M: part >>command-parameters ( part params -- part )
-    first >>channel ;
-
-M: kick >>command-parameters ( kick params -- kick )
-    first2 [ >>channel ] [ >>who ] bi* ;
-
-M: nick-in-use >>command-parameters ( nick-in-use params -- nick-in-use )
-    second >>name ;
-
-M: names-reply >>command-parameters ( names-reply params -- names-reply )
-    first3 nip [ >>who ] [ >>channel ] bi* ;
-
-M: end-of-names >>command-parameters ( names-reply params -- names-reply )
-    first2 [ >>who ] [ >>channel ] bi* ;
-
-M: mode >>command-parameters ( mode params -- mode )
-    dup length {
-        { 3 [ first3 [ >>name ] [ >>mode ] [ >>parameter ] tri* ] }
-        { 2 [ first2 [ >>name ] [ >>mode ] bi* ] }
-        [ drop first >>name dup trailing>> >>mode ]
-    } case ;
-
-PRIVATE>
-
-GENERIC: irc-message>client-line ( irc-message -- string )
-
-M: irc-message irc-message>client-line ( irc-message -- string )
-    [ command-string>> ]
-    [ command-parameters>> " " sjoin ]
-    [ trailing>> [ CHAR: : prefix ] [ "" ] if* ]
-    tri 3array " " sjoin ;
-
-GENERIC: irc-message>server-line ( irc-message -- string )
-
-M: irc-message irc-message>server-line ( irc-message -- string )
-   drop "not implemented yet" ;
-
-<PRIVATE
-
-! ======================================
-! Message parsing
-! ======================================
-
-: split-at-first ( seq separators -- before after )
-    dupd '[ _ member? ] find [ cut 1 tail ] [ swap ] if ;
-
-: remove-heading-: ( seq -- seq )
-    ":" ?head drop ;
-
-: parse-name ( string -- string )
-    remove-heading-: "!" split-at-first drop ;
-
-: split-prefix ( string -- string/f string )
-    dup ":" head?
-    [ remove-heading-: " " split1 ] [ f swap ] if ;
-
-: split-trailing ( string -- string string/f )
-    ":" split1 ;
-
-: copy-message-in ( command irc-message -- command )
-    {
-        [ line>>      >>line ]
-        [ prefix>>    >>prefix ]
-        [ command>>   >>command ]
-        [ trailing>>  >>trailing ]
-        [ timestamp>> >>timestamp ]
-        [ parameters>> [ >>parameters ] [ >>command-parameters ] bi ]
-    } cleave ;
-
-PRIVATE>
-
-UNION: sender-in-prefix privmsg join part quit kick mode nick ;
-GENERIC: irc-message-sender ( irc-message -- sender )
-M: sender-in-prefix irc-message-sender ( sender-in-prefix -- sender )
-    prefix>> parse-name ;
-
-: string>irc-message ( string -- object )
-    dup split-prefix split-trailing
-    [ [ blank? ] trim " " split unclip swap ] dip
-    now irc-message boa ;
-
-: irc-message>command ( irc-message -- command )
-    [
-        command>> {
-            { "PING"    [ ping ] }
-            { "NOTICE"  [ notice ] }
-            { "001"     [ logged-in ] }
-            { "433"     [ nick-in-use ] }
-            { "353"     [ names-reply ] }
-            { "366"     [ end-of-names ] }
-            { "JOIN"    [ join ] }
-            { "PART"    [ part ] }
-            { "NICK"    [ nick ] }
-            { "PRIVMSG" [ privmsg ] }
-            { "QUIT"    [ quit ] }
-            { "MODE"    [ mode ] }
-            { "KICK"    [ kick ] }
-            [ drop unhandled ]
-        } case new
-    ] keep copy-message-in ;
-
-: parse-irc-line ( string -- message )
-    string>irc-message irc-message>command ;
+! connection
+IRC: pass        "PASS"    password ;
+IRC: nick        "NICK"    : nickname ;
+IRC: user        "USER"    user mode _ : realname ;
+IRC: oper        "OPER"    name password ;
+IRC: mode        "MODE"    name mode parameter ;
+IRC: service     "SERVICE" nickname _ distribution type _ : info ;
+IRC: quit        "QUIT"    : comment ;
+IRC: squit       "SQUIT"   server : comment ;
+! channel operations
+IRC: join        "JOIN"    : channel ;
+IRC: part        "PART"    channel : comment ;
+IRC: topic       "TOPIC"   channel : topic ;
+IRC: names       "NAMES"   channel ;
+IRC: list        "LIST"    channel ;
+IRC: invite      "INVITE"  nickname channel ;
+IRC: kick        "KICK"    channel user : comment ;
+! chating
+IRC: privmsg     "PRIVMSG" target : text ;
+IRC: notice      "NOTICE"  target : text ;
+! server queries
+IRC: motd        "MOTD"    target ;
+IRC: lusers      "LUSERS"  mask target ;
+IRC: version     "VERSION" target ;
+IRC: stats       "STATS"   query target ;
+IRC: links       "LINKS"   server mask ;
+IRC: time        "TIME"    target ;
+IRC: connect     "CONNECT" server port remote-server ;
+IRC: trace       "TRACE"   target ;
+IRC: admin       "ADMIN"   target ;
+IRC: info        "INFO"    target ;
+! service queries
+IRC: servlist    "SERVLIST" mask type ;
+IRC: squery      "SQUERY"  service-name : text ;
+! user queries
+IRC: who         "WHO"     mask operator ;
+IRC: whois       "WHOIS"   target mask ;
+IRC: whowas      "WHOWAS"  nickname count target ;
+! misc
+IRC: kill        "KILL"    nickname : comment ;
+IRC: ping        "PING"    server1 server2 ;
+IRC: pong        "PONG"    server1 server2 ;
+IRC: error       "ERROR"   : message ;
+! numeric replies
+IRC: rpl-welcome         "001" nickname : comment ;
+IRC: rpl-whois-user      "311" nicnamek user host _ : real-name ;
+IRC: rpl-channel-modes   "324" channel mode params ;
+IRC: rpl-notopic         "331" channel : topic ;
+IRC: rpl-topic           "332" channel : topic ;
+IRC: rpl-inviting        "341" channel nickname ;
+IRC: rpl-names           "353" nickname _ channel : nicks ;
+IRC: rpl-names-end       "366" nickname channel : comment ;
+! error replies
+IRC: rpl-nickname-in-use "433" _ name ;
+IRC: rpl-nick-collision  "436" nickname : comment ;
+
+M: rpl-names post-process-irc-message ( rpl-names -- )
+    [ [ blank? ] trim " " split ] change-nicks drop ;
+
+PREDICATE: channel-mode < mode name>> first "#&" member? ;
+PREDICATE: participant-mode < channel-mode parameter>> ;
diff --git a/extra/irc/messages/parser/authors.txt b/extra/irc/messages/parser/authors.txt
new file mode 100644 (file)
index 0000000..f4a8cb1
--- /dev/null
@@ -0,0 +1 @@
+Bruno Deferrari
diff --git a/extra/irc/messages/parser/parser.factor b/extra/irc/messages/parser/parser.factor
new file mode 100644 (file)
index 0000000..1fa07fc
--- /dev/null
@@ -0,0 +1,35 @@
+! Copyright (C) 2009 Bruno Deferrari
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel fry splitting ascii calendar accessors combinators
+       arrays classes.tuple math.order words assocs
+       irc.messages.base sequences ;
+IN: irc.messages.parser
+
+<PRIVATE
+: split-at-first ( seq separators -- before after )
+    dupd '[ _ member? ] find [ cut 1 tail ] [ swap ] if ;
+
+: split-trailing ( string -- string string/f ) ":" split1 ;
+: remove-heading-: ( seq -- seq ) ":" ?head drop ;
+
+: split-prefix ( string -- string/f string )
+    dup ":" head? [
+        remove-heading-: " " split1
+    ] [ f swap ] if ;
+
+: split-message ( string -- prefix command parameters trailing )
+    split-prefix split-trailing
+    [ [ blank? ] trim " " split unclip swap ] dip ;
+
+: sender ( irc-message -- sender )
+    prefix>> [ remove-heading-: "!" split-at-first drop ] [ f ] if* ;
+PRIVATE>
+
+: string>irc-message ( string -- irc-message )
+    dup split-message
+    [ [ irc>type new ] [ >>command ] bi ]
+    [ >>parameters ]
+    [ >>trailing ]
+    tri*
+    [ (>>prefix) ] [ fill-irc-message-slots ] [ swap >>line ] tri
+    now >>timestamp dup sender >>sender ;
diff --git a/extra/irc/messages/parser/summary.txt b/extra/irc/messages/parser/summary.txt
new file mode 100644 (file)
index 0000000..7ec732a
--- /dev/null
@@ -0,0 +1 @@
+Basic parser for irc messages
diff --git a/extra/irc/messages/summary.txt b/extra/irc/messages/summary.txt
new file mode 100644 (file)
index 0000000..cf3a8ae
--- /dev/null
@@ -0,0 +1 @@
+IRC message definitions
index 104360e1fa9aa01527d0152331066e9fcf486633..27bb42ed074ad465cda3cc4fefb2868ad39e8b4f 100644 (file)
@@ -32,3 +32,11 @@ USING: mason.child mason.config tools.test namespaces ;
         boot-cmd
     ] with-scope
 ] unit-test
+
+[ { "./factor.com" "-i=boot.x86.32.image" "-no-user-init" } ] [
+    [
+        "winnt" target-os set
+        "x86.32" target-cpu set
+        boot-cmd
+    ] with-scope
+] unit-test
old mode 100644 (file)
new mode 100755 (executable)
index 04c4a09..feb1193
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Eduardo Cavazos, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays calendar combinators.short-circuit
-continuations debugger http.client io.directories io.files io.launcher
+continuations debugger io.directories io.files io.launcher
 io.pathnames io.encodings.ascii kernel make mason.common mason.config
 mason.platform mason.report mason.email namespaces sequences ;
 IN: mason.child
@@ -9,20 +9,8 @@ IN: mason.child
 : make-cmd ( -- args )
     gnu-make platform 2array ;
 
-: dll-url ( -- url )
-    "http://factorcode.org/dlls/"
-    target-cpu get "x86.64" = [ "64/" append ] when ;
-
-: download-dlls ( -- )
-    target-os get "winnt" = [
-        dll-url "build-support/dlls.txt" ascii file-lines
-        [ append download ] with each
-    ] when ;
-
 : make-vm ( -- )
     "factor" [
-        download-dlls
-
         <process>
             make-cmd >>command
             "../compile-log" >>stdout
@@ -37,8 +25,11 @@ IN: mason.child
     builds-factor-image "." copy-file-into
     builds-factor-image "factor" copy-file-into ;
 
+: factor-vm ( -- string )
+    target-os get "winnt" = "./factor.com" "./factor" ? ;
+
 : boot-cmd ( -- cmd )
-    "./factor"
+    factor-vm
     "-i=" boot-image-name append
     "-no-user-init"
     3array ;
@@ -54,7 +45,7 @@ IN: mason.child
         try-process
     ] with-directory ;
 
-: test-cmd ( -- cmd ) { "./factor" "-run=mason.test" } ;
+: test-cmd ( -- cmd ) factor-vm "-run=mason.test" 2array ;
 
 : test ( -- )
     "factor" [
old mode 100644 (file)
new mode 100755 (executable)
index a2c0873..a273696
@@ -18,6 +18,6 @@ IN: mason.cleanup
         build-dir [
             compress-image
             compress-test-log
-            "factor" delete-tree
+            "factor" really-delete-tree
         ] with-directory
     ] unless ;
old mode 100644 (file)
new mode 100755 (executable)
index 3cd38e1..047bdaa
@@ -2,11 +2,22 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces sequences splitting system accessors
 math.functions make io io.files io.pathnames io.directories
-io.launcher io.encodings.utf8 prettyprint
+io.directories.hierarchy io.launcher io.encodings.utf8 prettyprint
 combinators.short-circuit parser combinators calendar
-calendar.format arrays mason.config locals ;
+calendar.format arrays mason.config locals system ;
 IN: mason.common
 
+HOOK: really-delete-tree os ( path -- )
+
+M: windows really-delete-tree
+    #! Workaround: Cygwin GIT creates read-only files for
+    #! some reason.
+    [ { "chmod" "ug+rw" "-R" } swap (normalize-path) suffix try-process ]
+    [ delete-tree ]
+    bi ;
+
+M: unix really-delete-tree delete-tree ;
+
 : short-running-process ( command -- )
     #! Give network operations at most 15 minutes to complete.
     <process>
old mode 100644 (file)
new mode 100755 (executable)
index 5ef424a..fff8b83
@@ -29,7 +29,7 @@ IN: mason.release.archive
         "-fs" "HFS+"
     "-volname" "factor" }
     archive-name suffix try-process
-    "dmg-root" delete-tree ;
+    "dmg-root" really-delete-tree ;
 
 : make-unix-archive ( -- )
     [ "tar" , "-cvzf" , archive-name , "factor" , ] { } make try-process ;
old mode 100644 (file)
new mode 100755 (executable)
index 497be09..054b15f
@@ -12,11 +12,11 @@ IN: mason.release.tidy
     append ;
 
 : remove-common-files ( -- )
-    common-files [ delete-tree ] each ;
+    common-files [ really-delete-tree ] each ;
 
 : remove-factor-app ( -- )
     target-os get "macosx" =
-    [ "Factor.app" delete-tree ] unless ;
+    [ "Factor.app" really-delete-tree ] unless ;
 
 : tidy ( -- )
     "factor" [ remove-factor-app remove-common-files ] with-directory ;
index a15a96c63eaea977e65ee81fcc682affe86641b5..bc00f659fa5ae87625628c001a4e1726ec56635c 100644 (file)
@@ -4,7 +4,7 @@ USING: accessors assocs benchmark bootstrap.stage2
 compiler.errors generic help.html help.lint io.directories
 io.encodings.utf8 io.files kernel mason.common math namespaces
 prettyprint sequences sets sorting tools.test tools.time
-tools.vocabs words ;
+tools.vocabs words system io ;
 IN: mason.test
 
 : do-load ( -- )
@@ -44,9 +44,19 @@ M: method-body word-vocabulary "method-generic" word-prop word-vocabulary ;
 : benchmark-ms ( quot -- ms )
     benchmark 1000 /i ; inline
 
+: check-boot-image ( -- )
+    "" to-refresh drop 2dup [ empty? not ] either?
+    [
+        "Boot image is out of date. Changed vocabs:" print
+        append prune [ print ] each
+        flush
+        1 exit
+    ] [ 2drop ] if ;
+
 : do-all ( -- )
     ".." [
         bootstrap-time get boot-time-file to-file
+        check-boot-image
         [ do-load do-compile-errors ] benchmark-ms load-time-file to-file
         [ generate-help ] benchmark-ms html-help-time-file to-file
         [ do-tests ] benchmark-ms test-time-file to-file
index fa01b0376dcde26bc98664a6aec6f5f7e384c403..a1fc0bd07b904c0301e533bfa74e6e993fa0e652 100755 (executable)
@@ -42,7 +42,7 @@ PRIVATE>
     #! gamma(x) = integral 0..inf [ t^(x-1) exp(-t) ] dt
     #! gamma(n+1) = n! for n > 0
     dup { [ 0.0 <= ] [ 1.0 mod zero? ] } 1&& [
-        drop 1./0.
+        drop 1/0.
     ] [
         [ abs gamma-lanczos6 ] keep dup 0 > [ drop ] [ gamma-neg ] if
     ] if ;
@@ -51,7 +51,7 @@ PRIVATE>
     #! gammaln(x) is an alternative when gamma(x)'s range
     #! varies too widely
     dup 0 < [
-        drop 1./0.
+        drop 1/0.
     ] [
         [ abs gammaln-lanczos6 ] keep dup 0 > [ drop ] [ gamma-neg ] if
     ] if ;
index 2f7f79da9d46cbeda587c8284938b11fe0b930fb..32b78a2c137af31b0547281c96ccb4449af7a898 100755 (executable)
@@ -8,5 +8,5 @@ V{
     { deploy-word-props? f }
     { deploy-c-types? f }
     { "stop-after-last-window?" t }
-    { deploy-name "Catalyst Talk" }
+    { deploy-name "Minnesota Talk" }
 }
index 7fcc7abc882ad69d0acf8aefd0dc6d49619279fd..ef8d1bd5e3a68cd309f1c4f99837048420b76e69 100755 (executable)
@@ -1 +1 @@
-Slides for a talk at Ruby.mn, Minneapolis MN, January 2008
+Slides for a talk at Ruby.mn, Minneapolis, MN, January 2008
diff --git a/extra/models/history/history-docs.factor b/extra/models/history/history-docs.factor
new file mode 100644 (file)
index 0000000..d157729
--- /dev/null
@@ -0,0 +1,36 @@
+USING: help.syntax help.markup kernel math classes classes.tuple\r
+calendar models ;\r
+IN: models.history\r
+\r
+HELP: history\r
+{ $class-description "History models record a timeline of previous values on calls to " { $link add-history } ", and can travel back and forth on the timeline with " { $link go-back } " and " { $link go-forward } ". History models are constructed by " { $link <history> } "." } ;\r
+\r
+HELP: <history>\r
+{ $values { "value" object } { "history" "a new " { $link history } } }\r
+{ $description "Creates a new history model with an initial value." } ;\r
+\r
+{ <history> add-history go-back go-forward } related-words\r
+\r
+HELP: go-back\r
+{ $values { "history" history } }\r
+{ $description "Restores the previous value and calls " { $link model-changed } " on all observers registered with " { $link add-connection } "." } ;\r
+\r
+HELP: go-forward\r
+{ $values { "history" history } }\r
+{ $description "Restores the value set prior to the last call to " { $link go-back } " and calls " { $link model-changed } " on all observers registered with " { $link add-connection } "." } ;\r
+\r
+HELP: add-history\r
+{ $values { "history" history } }\r
+{ $description "Adds the current value to the history." } ;\r
+\r
+ARTICLE: "models-history" "History models"\r
+"History models record previous values."\r
+{ $subsection history }\r
+{ $subsection <history> }\r
+"Recording history:"\r
+{ $subsection add-history }\r
+"Navigating the history:"\r
+{ $subsection go-back }\r
+{ $subsection go-forward } ;\r
+\r
+ABOUT: "models-history"\r
diff --git a/extra/models/history/history-tests.factor b/extra/models/history/history-tests.factor
new file mode 100644 (file)
index 0000000..c89dd5c
--- /dev/null
@@ -0,0 +1,37 @@
+USING: arrays generic kernel math models namespaces sequences assocs\r
+tools.test models.history accessors ;\r
+IN: models.history.tests\r
+\r
+f <history> "history" set\r
+\r
+"history" get add-history\r
+\r
+[ t ] [ "history" get back>> empty? ] unit-test\r
+[ t ] [ "history" get forward>> empty? ] unit-test\r
+\r
+"history" get add-history\r
+3 "history" get set-model\r
+\r
+[ t ] [ "history" get back>> empty? ] unit-test\r
+[ t ] [ "history" get forward>> empty? ] unit-test\r
+\r
+"history" get add-history\r
+4 "history" get set-model\r
+\r
+[ f ] [ "history" get back>> empty? ] unit-test\r
+[ t ] [ "history" get forward>> empty? ] unit-test\r
+\r
+"history" get go-back\r
+\r
+[ 3 ] [ "history" get value>> ] unit-test\r
+\r
+[ t ] [ "history" get back>> empty? ] unit-test\r
+[ f ] [ "history" get forward>> empty? ] unit-test\r
+\r
+"history" get go-forward\r
+\r
+[ 4 ] [ "history" get value>> ] unit-test\r
+\r
+[ f ] [ "history" get back>> empty? ] unit-test\r
+[ t ] [ "history" get forward>> empty? ] unit-test\r
+\r
diff --git a/extra/models/history/history.factor b/extra/models/history/history.factor
new file mode 100644 (file)
index 0000000..90d6b59
--- /dev/null
@@ -0,0 +1,31 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: accessors kernel models sequences ;\r
+IN: models.history\r
+\r
+TUPLE: history < model back forward ;\r
+\r
+: reset-history ( history -- history )\r
+    V{ } clone >>back\r
+    V{ } clone >>forward ; inline\r
+\r
+: <history> ( value -- history )\r
+    history new-model\r
+        reset-history ;\r
+\r
+: (add-history) ( history to -- )\r
+    swap value>> dup [ swap push ] [ 2drop ] if ;\r
+\r
+: go-back/forward ( history to from -- )\r
+    [ 2drop ]\r
+    [ [ dupd (add-history) ] dip pop swap set-model ] if-empty ;\r
+\r
+: go-back ( history -- )\r
+    dup [ forward>> ] [ back>> ] bi go-back/forward ;\r
+\r
+: go-forward ( history -- )\r
+    dup [ back>> ] [ forward>> ] bi go-back/forward ;\r
+\r
+: add-history ( history -- )\r
+    dup forward>> delete-all\r
+    dup back>> (add-history) ;\r
diff --git a/extra/models/history/summary.txt b/extra/models/history/summary.txt
new file mode 100644 (file)
index 0000000..76f7b88
--- /dev/null
@@ -0,0 +1 @@
+History models remember prior values
diff --git a/extra/multi-methods/tags.txt b/extra/multi-methods/tags.txt
new file mode 100644 (file)
index 0000000..f427429
--- /dev/null
@@ -0,0 +1 @@
+extensions
diff --git a/extra/opengl/glu/authors.txt b/extra/opengl/glu/authors.txt
new file mode 100644 (file)
index 0000000..e9c193b
--- /dev/null
@@ -0,0 +1 @@
+Alex Chapman
diff --git a/extra/opengl/glu/glu.factor b/extra/opengl/glu/glu.factor
new file mode 100644 (file)
index 0000000..fe060e3
--- /dev/null
@@ -0,0 +1,267 @@
+! Copyright (C) 2005 Alex Chapman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien alien.libraries alien.syntax kernel sequences words system
+combinators ;
+IN: opengl.glu
+
+os {
+    { [ dup macosx? ] [ drop ] }
+    { [ dup windows? ] [ drop ] }
+    { [ dup unix? ] [ drop "glu" "libGLU.so.1" "cdecl" add-library ] }
+} cond
+
+LIBRARY: glu
+! These are defined as structs in glu.h, but we only ever use pointers to them
+TYPEDEF: void* GLUnurbs*
+TYPEDEF: void* GLUquadric*
+TYPEDEF: void* GLUtesselator*
+TYPEDEF: void* GLubyte*
+TYPEDEF: void* GLUfuncptr
+
+! StringName
+CONSTANT: GLU_VERSION                        100800
+CONSTANT: GLU_EXTENSIONS                     100801
+
+! ErrorCode
+CONSTANT: GLU_INVALID_ENUM                   100900
+CONSTANT: GLU_INVALID_VALUE                  100901
+CONSTANT: GLU_OUT_OF_MEMORY                  100902
+CONSTANT: GLU_INCOMPATIBLE_GL_VERSION        100903
+CONSTANT: GLU_INVALID_OPERATION              100904
+
+! NurbsDisplay
+CONSTANT: GLU_OUTLINE_POLYGON                100240
+CONSTANT: GLU_OUTLINE_PATCH                  100241
+
+! NurbsCallback
+CONSTANT: GLU_NURBS_ERROR                    100103
+CONSTANT: GLU_ERROR                          100103
+CONSTANT: GLU_NURBS_BEGIN                    100164
+CONSTANT: GLU_NURBS_BEGIN_EXT                100164
+CONSTANT: GLU_NURBS_VERTEX                   100165
+CONSTANT: GLU_NURBS_VERTEX_EXT               100165
+CONSTANT: GLU_NURBS_NORMAL                   100166
+CONSTANT: GLU_NURBS_NORMAL_EXT               100166
+CONSTANT: GLU_NURBS_COLOR                    100167
+CONSTANT: GLU_NURBS_COLOR_EXT                100167
+CONSTANT: GLU_NURBS_TEXTURE_COORD            100168
+CONSTANT: GLU_NURBS_TEX_COORD_EXT            100168
+CONSTANT: GLU_NURBS_END                      100169
+CONSTANT: GLU_NURBS_END_EXT                  100169
+CONSTANT: GLU_NURBS_BEGIN_DATA               100170
+CONSTANT: GLU_NURBS_BEGIN_DATA_EXT           100170
+CONSTANT: GLU_NURBS_VERTEX_DATA              100171
+CONSTANT: GLU_NURBS_VERTEX_DATA_EXT          100171
+CONSTANT: GLU_NURBS_NORMAL_DATA              100172
+CONSTANT: GLU_NURBS_NORMAL_DATA_EXT          100172
+CONSTANT: GLU_NURBS_COLOR_DATA               100173
+CONSTANT: GLU_NURBS_COLOR_DATA_EXT           100173
+CONSTANT: GLU_NURBS_TEXTURE_COORD_DATA       100174
+CONSTANT: GLU_NURBS_TEX_COORD_DATA_EXT       100174
+CONSTANT: GLU_NURBS_END_DATA                 100175
+CONSTANT: GLU_NURBS_END_DATA_EXT             100175
+
+! NurbsError
+CONSTANT: GLU_NURBS_ERROR1                   100251
+CONSTANT: GLU_NURBS_ERROR2                   100252
+CONSTANT: GLU_NURBS_ERROR3                   100253
+CONSTANT: GLU_NURBS_ERROR4                   100254
+CONSTANT: GLU_NURBS_ERROR5                   100255
+CONSTANT: GLU_NURBS_ERROR6                   100256
+CONSTANT: GLU_NURBS_ERROR7                   100257
+CONSTANT: GLU_NURBS_ERROR8                   100258
+CONSTANT: GLU_NURBS_ERROR9                   100259
+CONSTANT: GLU_NURBS_ERROR10                  100260
+CONSTANT: GLU_NURBS_ERROR11                  100261
+CONSTANT: GLU_NURBS_ERROR12                  100262
+CONSTANT: GLU_NURBS_ERROR13                  100263
+CONSTANT: GLU_NURBS_ERROR14                  100264
+CONSTANT: GLU_NURBS_ERROR15                  100265
+CONSTANT: GLU_NURBS_ERROR16                  100266
+CONSTANT: GLU_NURBS_ERROR17                  100267
+CONSTANT: GLU_NURBS_ERROR18                  100268
+CONSTANT: GLU_NURBS_ERROR19                  100269
+CONSTANT: GLU_NURBS_ERROR20                  100270
+CONSTANT: GLU_NURBS_ERROR21                  100271
+CONSTANT: GLU_NURBS_ERROR22                  100272
+CONSTANT: GLU_NURBS_ERROR23                  100273
+CONSTANT: GLU_NURBS_ERROR24                  100274
+CONSTANT: GLU_NURBS_ERROR25                  100275
+CONSTANT: GLU_NURBS_ERROR26                  100276
+CONSTANT: GLU_NURBS_ERROR27                  100277
+CONSTANT: GLU_NURBS_ERROR28                  100278
+CONSTANT: GLU_NURBS_ERROR29                  100279
+CONSTANT: GLU_NURBS_ERROR30                  100280
+CONSTANT: GLU_NURBS_ERROR31                  100281
+CONSTANT: GLU_NURBS_ERROR32                  100282
+CONSTANT: GLU_NURBS_ERROR33                  100283
+CONSTANT: GLU_NURBS_ERROR34                  100284
+CONSTANT: GLU_NURBS_ERROR35                  100285
+CONSTANT: GLU_NURBS_ERROR36                  100286
+CONSTANT: GLU_NURBS_ERROR37                  100287
+
+! NurbsProperty
+CONSTANT: GLU_AUTO_LOAD_MATRIX               100200
+CONSTANT: GLU_CULLING                        100201
+CONSTANT: GLU_SAMPLING_TOLERANCE             100203
+CONSTANT: GLU_DISPLAY_MODE                   100204
+CONSTANT: GLU_PARAMETRIC_TOLERANCE           100202
+CONSTANT: GLU_SAMPLING_METHOD                100205
+CONSTANT: GLU_U_STEP                         100206
+CONSTANT: GLU_V_STEP                         100207
+CONSTANT: GLU_NURBS_MODE                     100160
+CONSTANT: GLU_NURBS_MODE_EXT                 100160
+CONSTANT: GLU_NURBS_TESSELLATOR              100161
+CONSTANT: GLU_NURBS_TESSELLATOR_EXT          100161
+CONSTANT: GLU_NURBS_RENDERER                 100162
+CONSTANT: GLU_NURBS_RENDERER_EXT             100162
+
+! NurbsSampling
+CONSTANT: GLU_OBJECT_PARAMETRIC_ERROR        100208
+CONSTANT: GLU_OBJECT_PARAMETRIC_ERROR_EXT    100208
+CONSTANT: GLU_OBJECT_PATH_LENGTH             100209
+CONSTANT: GLU_OBJECT_PATH_LENGTH_EXT         100209
+CONSTANT: GLU_PATH_LENGTH                    100215
+CONSTANT: GLU_PARAMETRIC_ERROR               100216
+CONSTANT: GLU_DOMAIN_DISTANCE                100217
+
+! NurbsTrim
+CONSTANT: GLU_MAP1_TRIM_2                    100210
+CONSTANT: GLU_MAP1_TRIM_3                    100211
+
+! QuadricDrawStyle
+CONSTANT: GLU_POINT                          100010
+CONSTANT: GLU_LINE                           100011
+CONSTANT: GLU_FILL                           100012
+CONSTANT: GLU_SILHOUETTE                     100013
+
+! QuadricNormal
+CONSTANT: GLU_SMOOTH                         100000
+CONSTANT: GLU_FLAT                           100001
+CONSTANT: GLU_NONE                           100002
+
+! QuadricOrientation
+CONSTANT: GLU_OUTSIDE                        100020
+CONSTANT: GLU_INSIDE                         100021
+
+! TessCallback
+CONSTANT: GLU_TESS_BEGIN                     100100
+CONSTANT: GLU_BEGIN                          100100
+CONSTANT: GLU_TESS_VERTEX                    100101
+CONSTANT: GLU_VERTEX                         100101
+CONSTANT: GLU_TESS_END                       100102
+CONSTANT: GLU_END                            100102
+CONSTANT: GLU_TESS_ERROR                     100103
+CONSTANT: GLU_TESS_EDGE_FLAG                 100104
+CONSTANT: GLU_EDGE_FLAG                      100104
+CONSTANT: GLU_TESS_COMBINE                   100105
+CONSTANT: GLU_TESS_BEGIN_DATA                100106
+CONSTANT: GLU_TESS_VERTEX_DATA               100107
+CONSTANT: GLU_TESS_END_DATA                  100108
+CONSTANT: GLU_TESS_ERROR_DATA                100109
+CONSTANT: GLU_TESS_EDGE_FLAG_DATA            100110
+CONSTANT: GLU_TESS_COMBINE_DATA              100111
+
+! TessContour
+CONSTANT: GLU_CW                             100120
+CONSTANT: GLU_CCW                            100121
+CONSTANT: GLU_INTERIOR                       100122
+CONSTANT: GLU_EXTERIOR                       100123
+CONSTANT: GLU_UNKNOWN                        100124
+
+! TessProperty
+CONSTANT: GLU_TESS_WINDING_RULE              100140
+CONSTANT: GLU_TESS_BOUNDARY_ONLY             100141
+CONSTANT: GLU_TESS_TOLERANCE                 100142
+
+! TessError
+CONSTANT: GLU_TESS_ERROR1                    100151
+CONSTANT: GLU_TESS_ERROR2                    100152
+CONSTANT: GLU_TESS_ERROR3                    100153
+CONSTANT: GLU_TESS_ERROR4                    100154
+CONSTANT: GLU_TESS_ERROR5                    100155
+CONSTANT: GLU_TESS_ERROR6                    100156
+CONSTANT: GLU_TESS_ERROR7                    100157
+CONSTANT: GLU_TESS_ERROR8                    100158
+CONSTANT: GLU_TESS_MISSING_BEGIN_POLYGON     100151
+CONSTANT: GLU_TESS_MISSING_BEGIN_CONTOUR     100152
+CONSTANT: GLU_TESS_MISSING_END_POLYGON       100153
+CONSTANT: GLU_TESS_MISSING_END_CONTOUR       100154
+CONSTANT: GLU_TESS_COORD_TOO_LARGE           100155
+CONSTANT: GLU_TESS_NEED_COMBINE_CALLBACK     100156
+
+! TessWinding
+CONSTANT: GLU_TESS_WINDING_ODD               100130
+CONSTANT: GLU_TESS_WINDING_NONZERO           100131
+CONSTANT: GLU_TESS_WINDING_POSITIVE          100132
+CONSTANT: GLU_TESS_WINDING_NEGATIVE          100133
+CONSTANT: GLU_TESS_WINDING_ABS_GEQ_TWO       100134
+
+LIBRARY: glu
+
+FUNCTION: void gluBeginCurve ( GLUnurbs* nurb ) ;
+FUNCTION: void gluBeginPolygon ( GLUtesselator* tess ) ;
+FUNCTION: void gluBeginSurface ( GLUnurbs* nurb ) ;
+FUNCTION: void gluBeginTrim ( GLUnurbs* nurb ) ;
+
+FUNCTION: void gluCylinder ( GLUquadric* quad, GLdouble base, GLdouble top, GLdouble height, GLint slices, GLint stacks ) ;
+FUNCTION: void gluDeleteNurbsRenderer ( GLUnurbs* nurb ) ;
+FUNCTION: void gluDeleteQuadric ( GLUquadric* quad ) ;
+FUNCTION: void gluDeleteTess ( GLUtesselator* tess ) ;
+FUNCTION: void gluDisk ( GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops ) ;
+FUNCTION: void gluEndCurve ( GLUnurbs* nurb ) ;
+FUNCTION: void gluEndPolygon ( GLUtesselator* tess ) ;
+FUNCTION: void gluEndSurface ( GLUnurbs* nurb ) ;
+FUNCTION: void gluEndTrim ( GLUnurbs* nurb ) ;
+FUNCTION: char* gluErrorString ( GLenum error ) ;
+FUNCTION: void gluGetNurbsProperty ( GLUnurbs* nurb, GLenum property, GLfloat* data ) ;
+FUNCTION: char* gluGetString ( GLenum name ) ;
+FUNCTION: void gluGetTessProperty ( GLUtesselator* tess, GLenum which, GLdouble* data ) ;
+FUNCTION: void gluLoadSamplingMatrices ( GLUnurbs* nurb, GLfloat* model, GLfloat* perspective, GLint* view ) ;
+FUNCTION: void gluLookAt ( GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, GLdouble centerX, GLdouble centerY, GLdouble centerZ, GLdouble upX, GLdouble upY, GLdouble upZ ) ;
+FUNCTION: GLUnurbs* gluNewNurbsRenderer ( ) ;
+FUNCTION: GLUquadric* gluNewQuadric ( ) ;
+FUNCTION: GLUtesselator* gluNewTess ( ) ;
+FUNCTION: void gluNextContour ( GLUtesselator* tess, GLenum type ) ;
+FUNCTION: void gluNurbsCallback ( GLUnurbs* nurb, GLenum which, GLUfuncptr CallBackFunc ) ;
+! FUNCTION: void gluNurbsCallbackData ( GLUnurbs* nurb, GLvoid* userData ) ;
+! FUNCTION: void gluNurbsCallbackDataEXT ( GLUnurbs* nurb, GLvoid* userData ) ;
+FUNCTION: void gluNurbsCurve ( GLUnurbs* nurb, GLint knotCount, GLfloat *knots, GLint stride, GLfloat *control, GLint order, GLenum type ) ;
+FUNCTION: void gluNurbsProperty ( GLUnurbs* nurb, GLenum property, GLfloat value ) ;
+FUNCTION: void gluNurbsSurface ( GLUnurbs* nurb, GLint sKnotCount, GLfloat* sKnots, GLint tKnotCount, GLfloat* tKnots, GLint sStride, GLint tStride, GLfloat* control, GLint sOrder, GLint tOrder, GLenum type ) ;
+FUNCTION: void gluOrtho2D ( GLdouble left, GLdouble right, GLdouble bottom, GLdouble top ) ;
+FUNCTION: void gluPartialDisk ( GLUquadric* quad, GLdouble inner, GLdouble outer, GLint slices, GLint loops, GLdouble start, GLdouble sweep ) ;
+FUNCTION: void gluPerspective ( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ) ;
+FUNCTION: void gluPickMatrix ( GLdouble x, GLdouble y, GLdouble delX, GLdouble delY, GLint* viewport ) ;
+FUNCTION: GLint gluProject ( GLdouble objX, GLdouble objY, GLdouble objZ, GLdouble* model, GLdouble* proj, GLint* view, GLdouble* winX, GLdouble* winY, GLdouble* winZ ) ;
+FUNCTION: void gluPwlCurve ( GLUnurbs* nurb, GLint count, GLfloat* data, GLint stride, GLenum type ) ;
+FUNCTION: void gluQuadricCallback ( GLUquadric* quad, GLenum which, GLUfuncptr CallBackFunc ) ;
+FUNCTION: void gluQuadricDrawStyle ( GLUquadric* quad, GLenum draw ) ;
+FUNCTION: void gluQuadricNormals ( GLUquadric* quad, GLenum normal ) ;
+FUNCTION: void gluQuadricOrientation ( GLUquadric* quad, GLenum orientation ) ;
+FUNCTION: void gluQuadricTexture ( GLUquadric* quad, GLboolean texture ) ;
+FUNCTION: GLint gluScaleImage ( GLenum format, GLsizei wIn, GLsizei hIn, GLenum typeIn, void* dataIn, GLsizei wOut, GLsizei hOut, GLenum typeOut, GLvoid* dataOut ) ;
+FUNCTION: void gluSphere ( GLUquadric* quad, GLdouble radius, GLint slices, GLint stacks ) ;
+FUNCTION: void gluTessBeginContour ( GLUtesselator* tess ) ;
+FUNCTION: void gluTessBeginPolygon ( GLUtesselator* tess, GLvoid* data ) ;
+FUNCTION: void gluTessCallback ( GLUtesselator* tess, GLenum which, GLUfuncptr CallBackFunc ) ;
+FUNCTION: void gluTessEndContour ( GLUtesselator* tess ) ;
+FUNCTION: void gluTessEndPolygon ( GLUtesselator* tess ) ;
+FUNCTION: void gluTessNormal ( GLUtesselator* tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ ) ;
+FUNCTION: void gluTessProperty ( GLUtesselator* tess, GLenum which, GLdouble data ) ;
+FUNCTION: void gluTessVertex ( GLUtesselator* tess, GLdouble* location, GLvoid* data ) ;
+FUNCTION: GLint gluUnProject ( GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble* model, GLdouble* proj, GLint* view, GLdouble* objX, GLdouble* objY, GLdouble* objZ ) ;
+
+! Not present on Windows
+! FUNCTION: GLint gluBuild1DMipmapLevels ( GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, GLint level, GLint base, GLint max, void* data ) ;
+! FUNCTION: GLint gluBuild1DMipmaps ( GLenum target, GLint internalFormat, GLsizei width, GLenum format, GLenum type, void* data ) ;
+! FUNCTION: GLint gluBuild2DMipmapLevels ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint level, GLint base, GLint max, void* data ) ;
+! FUNCTION: GLint gluBuild2DMipmaps ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, void* data ) ;
+! FUNCTION: GLint gluBuild3DMipmapLevels ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLint level, GLint base, GLint max, void* data ) ;
+! FUNCTION: GLint gluBuild3DMipmaps ( GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void* data ) ;
+! FUNCTION: GLboolean gluCheckExtension ( GLubyte* extName, GLubyte* extString ) ;
+! FUNCTION: GLint gluUnProject4 ( GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, GLdouble* model, GLdouble* proj, GLint* view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW ) ;
+
+: gl-look-at ( eye focus up -- )
+    [ first3 ] tri@ gluLookAt ;
\ No newline at end of file
diff --git a/extra/opengl/glu/summary.txt b/extra/opengl/glu/summary.txt
new file mode 100644 (file)
index 0000000..a90f4a3
--- /dev/null
@@ -0,0 +1 @@
+OpenGL binding - libGLU
diff --git a/extra/opengl/glu/tags.txt b/extra/opengl/glu/tags.txt
new file mode 100644 (file)
index 0000000..bb863cf
--- /dev/null
@@ -0,0 +1 @@
+bindings
index 47619a17f88aa5134aa9616fcae2acf65fea6e65..44385cf3b7411a8392c9839f3b9a015f0954af2b 100644 (file)
@@ -1 +1,2 @@
-reflection
\ No newline at end of file
+extensions
+reflection
index eff923dc011eba44d708613286efc92679c34e9d..179e03f1cfbc2bd4ff0e69b2173393db94114b57 100644 (file)
@@ -6,20 +6,20 @@ IN: peg.pl0
 
 #! Grammar for PL/0 based on http://en.wikipedia.org/wiki/PL/0
 
-EBNF: pl0 
+EBNF: pl0
 
-block       =  { "CONST" ident "=" number { "," ident "=" number }* ";" }? 
-               { "VAR" ident { "," ident }* ";" }? 
-               { "PROCEDURE" ident ";" { block ";" }? }* statement 
-statement   =  {  ident ":=" expression 
-                | "CALL" ident 
-                | "BEGIN" statement { ";" statement }* "END" 
-                | "IF" condition "THEN" statement 
-                | "WHILE" condition "DO" statement }?  
+block       =  { "CONST" ident "=" number { "," ident "=" number }* ";" }?
+               { "VAR" ident { "," ident }* ";" }?
+               { "PROCEDURE" ident ";" { block ";" }? }* statement
+statement   =  {  ident ":=" expression
+                | "CALL" ident
+                | "BEGIN" statement { ";" statement }* "END"
+                | "IF" condition "THEN" statement
+                | "WHILE" condition "DO" statement }?
 condition   =  { "ODD" expression }
              | { expression ("=" | "#" | "<=" | "<" | ">=" | ">") expression }
-expression  = {"+" | "-"}? term { {"+" | "-"} term }* 
-term        = factor { {"*" | "/"} factor }* 
+expression  = {"+" | "-"}? term { {"+" | "-"} term }*
+term        = factor { {"*" | "/"} factor }*
 factor      = ident | number | "(" expression ")"
 ident       = (([a-zA-Z])+)   => [[ >string ]]
 digit       = ([0-9])         => [[ digit> ]]
diff --git a/extra/poker/arrays/arrays.factor b/extra/poker/arrays/arrays.factor
new file mode 100644 (file)
index 0000000..bf758f1
--- /dev/null
@@ -0,0 +1,1018 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+IN: poker.arrays
+
+! This is a lookup table for all flush hands. A zero means that specific
+! combination is not possible with this type of hand.
+CONSTANT: flushes-table
+{ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 1599 0 0 0 0 0 0 0 1598 0 0 0 1597 0 1596 8 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 1595 0 0 0 0 0 0 0 1594 0 0 0 1593 0 1592 1591 0 0 0 0 0 0 0 0 1590
+0 0 0 1589 0 1588 1587 0 0 0 0 1586 0 1585 1584 0 0 1583 1582 0 7 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 1581 0 0 0 0 0 0 0 1580 0 0 0 1579 0 1578 1577 0 0 0 0 0
+0 0 0 1576 0 0 0 1575 0 1574 1573 0 0 0 0 1572 0 1571 1570 0 0 1569 1568 0 1567
+0 0 0 0 0 0 0 0 0 0 1566 0 0 0 1565 0 1564 1563 0 0 0 0 1562 0 1561 1560 0 0
+1559 1558 0 1557 0 0 0 0 0 0 1556 0 1555 1554 0 0 1553 1552 0 1551 0 0 0 0 1550
+1549 0 1548 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1547 0 0 0 0 0
+0 0 1546 0 0 0 1545 0 1544 1543 0 0 0 0 0 0 0 0 1542 0 0 0 1541 0 1540 1539 0 0
+0 0 1538 0 1537 1536 0 0 1535 1534 0 1533 0 0 0 0 0 0 0 0 0 0 1532 0 0 0 1531 0
+1530 1529 0 0 0 0 1528 0 1527 1526 0 0 1525 1524 0 1523 0 0 0 0 0 0 1522 0 1521
+1520 0 0 1519 1518 0 1517 0 0 0 0 1516 1515 0 1514 0 0 0 1513 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 1512 0 0 0 1511 0 1510 1509 0 0 0 0 1508 0 1507 1506 0 0 1505 1504 0
+1503 0 0 0 0 0 0 1502 0 1501 1500 0 0 1499 1498 0 1497 0 0 0 0 1496 1495 0 1494
+0 0 0 1493 0 0 0 0 0 0 0 0 0 0 1492 0 1491 1490 0 0 1489 1488 0 1487 0 0 0 0
+1486 1485 0 1484 0 0 0 1483 0 0 0 0 0 0 0 0 1482 1481 0 1480 0 0 0 1479 0 0 0 0
+0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1478 0 0 0
+0 0 0 0 1477 0 0 0 1476 0 1475 1474 0 0 0 0 0 0 0 0 1473 0 0 0 1472 0 1471 1470
+0 0 0 0 1469 0 1468 1467 0 0 1466 1465 0 1464 0 0 0 0 0 0 0 0 0 0 1463 0 0 0
+1462 0 1461 1460 0 0 0 0 1459 0 1458 1457 0 0 1456 1455 0 1454 0 0 0 0 0 0 1453
+0 1452 1451 0 0 1450 1449 0 1448 0 0 0 0 1447 1446 0 1445 0 0 0 1444 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 1443 0 0 0 1442 0 1441 1440 0 0 0 0 1439 0 1438 1437 0 0 1436
+1435 0 1434 0 0 0 0 0 0 1433 0 1432 1431 0 0 1430 1429 0 1428 0 0 0 0 1427 1426
+0 1425 0 0 0 1424 0 0 0 0 0 0 0 0 0 0 1423 0 1422 1421 0 0 1420 1419 0 1418 0 0
+0 0 1417 1416 0 1415 0 0 0 1414 0 0 0 0 0 0 0 0 1413 1412 0 1411 0 0 0 1410 0 0
+0 0 0 0 0 1409 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1408 0 0 0 1407 0
+1406 1405 0 0 0 0 1404 0 1403 1402 0 0 1401 1400 0 1399 0 0 0 0 0 0 1398 0 1397
+1396 0 0 1395 1394 0 1393 0 0 0 0 1392 1391 0 1390 0 0 0 1389 0 0 0 0 0 0 0 0 0
+0 1388 0 1387 1386 0 0 1385 1384 0 1383 0 0 0 0 1382 1381 0 1380 0 0 0 1379 0 0
+0 0 0 0 0 0 1378 1377 0 1376 0 0 0 1375 0 0 0 0 0 0 0 1374 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 1373 0 1372 1371 0 0 1370 1369 0 1368 0 0 0 0 1367 1366 0 1365
+0 0 0 1364 0 0 0 0 0 0 0 0 1363 1362 0 1361 0 0 0 1360 0 0 0 0 0 0 0 1359 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 1358 1357 0 1356 0 0 0 1355 0 0 0 0 0 0 0 1354 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1353 0 0 0 0 0 0 0 1352 0 0 0 1351 0 1350
+1349 0 0 0 0 0 0 0 0 1348 0 0 0 1347 0 1346 1345 0 0 0 0 1344 0 1343 1342 0 0
+1341 1340 0 1339 0 0 0 0 0 0 0 0 0 0 1338 0 0 0 1337 0 1336 1335 0 0 0 0 1334 0
+1333 1332 0 0 1331 1330 0 1329 0 0 0 0 0 0 1328 0 1327 1326 0 0 1325 1324 0
+1323 0 0 0 0 1322 1321 0 1320 0 0 0 1319 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1318 0 0 0
+1317 0 1316 1315 0 0 0 0 1314 0 1313 1312 0 0 1311 1310 0 1309 0 0 0 0 0 0 1308
+0 1307 1306 0 0 1305 1304 0 1303 0 0 0 0 1302 1301 0 1300 0 0 0 1299 0 0 0 0 0
+0 0 0 0 0 1298 0 1297 1296 0 0 1295 1294 0 1293 0 0 0 0 1292 1291 0 1290 0 0 0
+1289 0 0 0 0 0 0 0 0 1288 1287 0 1286 0 0 0 1285 0 0 0 0 0 0 0 1284 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1283 0 0 0 1282 0 1281 1280 0 0 0 0 1279 0 1278
+1277 0 0 1276 1275 0 1274 0 0 0 0 0 0 1273 0 1272 1271 0 0 1270 1269 0 1268 0 0
+0 0 1267 1266 0 1265 0 0 0 1264 0 0 0 0 0 0 0 0 0 0 1263 0 1262 1261 0 0 1260
+1259 0 1258 0 0 0 0 1257 1256 0 1255 0 0 0 1254 0 0 0 0 0 0 0 0 1253 1252 0
+1251 0 0 0 1250 0 0 0 0 0 0 0 1249 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1248 0
+1247 1246 0 0 1245 1244 0 1243 0 0 0 0 1242 1241 0 1240 0 0 0 1239 0 0 0 0 0 0
+0 0 1238 1237 0 1236 0 0 0 1235 0 0 0 0 0 0 0 1234 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 1233 1232 0 1231 0 0 0 1230 0 0 0 0 0 0 0 1229 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 1228 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 1227 0 0 0 1226 0 1225 1224 0 0 0 0 1223 0 1222 1221 0 0 1220 1219 0 1218 0
+0 0 0 0 0 1217 0 1216 1215 0 0 1214 1213 0 1212 0 0 0 0 1211 1210 0 1209 0 0 0
+1208 0 0 0 0 0 0 0 0 0 0 1207 0 1206 1205 0 0 1204 1203 0 1202 0 0 0 0 1201
+1200 0 1199 0 0 0 1198 0 0 0 0 0 0 0 0 1197 1196 0 1195 0 0 0 1194 0 0 0 0 0 0
+0 1193 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1192 0 1191 1190 0 0 1189 1188 0
+1187 0 0 0 0 1186 1185 0 1184 0 0 0 1183 0 0 0 0 0 0 0 0 1182 1181 0 1180 0 0 0
+1179 0 0 0 0 0 0 0 1178 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1177 1176 0 1175 0 0 0
+1174 0 0 0 0 0 0 0 1173 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1172 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1171 0 1170 1169 0 0 1168 1167
+0 1166 0 0 0 0 1165 1164 0 1163 0 0 0 1162 0 0 0 0 0 0 0 0 1161 1160 0 1159 0 0
+0 1158 0 0 0 0 0 0 0 1157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1156 1155 0 1154 0 0
+0 1153 0 0 0 0 0 0 0 1152 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1151 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1150 1149 0 1148 0 0 0 1147 0 0 0
+0 0 0 0 1146 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1145 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 1144 0 0 0 0 0 0 0 1143 0 0 0 1142 0 1141 1140 0 0
+0 0 0 0 0 0 1139 0 0 0 1138 0 1137 1136 0 0 0 0 1135 0 1134 1133 0 0 1132 1131
+0 1130 0 0 0 0 0 0 0 0 0 0 1129 0 0 0 1128 0 1127 1126 0 0 0 0 1125 0 1124 1123
+0 0 1122 1121 0 1120 0 0 0 0 0 0 1119 0 1118 1117 0 0 1116 1115 0 1114 0 0 0 0
+1113 1112 0 1111 0 0 0 1110 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1109 0 0 0 1108 0 1107
+1106 0 0 0 0 1105 0 1104 1103 0 0 1102 1101 0 1100 0 0 0 0 0 0 1099 0 1098 1097
+0 0 1096 1095 0 1094 0 0 0 0 1093 1092 0 1091 0 0 0 1090 0 0 0 0 0 0 0 0 0 0
+1089 0 1088 1087 0 0 1086 1085 0 1084 0 0 0 0 1083 1082 0 1081 0 0 0 1080 0 0 0
+0 0 0 0 0 1079 1078 0 1077 0 0 0 1076 0 0 0 0 0 0 0 1075 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 1074 0 0 0 1073 0 1072 1071 0 0 0 0 1070 0 1069 1068 0 0
+1067 1066 0 1065 0 0 0 0 0 0 1064 0 1063 1062 0 0 1061 1060 0 1059 0 0 0 0 1058
+1057 0 1056 0 0 0 1055 0 0 0 0 0 0 0 0 0 0 1054 0 1053 1052 0 0 1051 1050 0
+1049 0 0 0 0 1048 1047 0 1046 0 0 0 1045 0 0 0 0 0 0 0 0 1044 1043 0 1042 0 0 0
+1041 0 0 0 0 0 0 0 1040 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1039 0 1038 1037 0
+0 1036 1035 0 1034 0 0 0 0 1033 1032 0 1031 0 0 0 1030 0 0 0 0 0 0 0 0 1029
+1028 0 1027 0 0 0 1026 0 0 0 0 0 0 0 1025 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1024
+1023 0 1022 0 0 0 1021 0 0 0 0 0 0 0 1020 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1019 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1018
+0 0 0 1017 0 1016 1015 0 0 0 0 1014 0 1013 1012 0 0 1011 1010 0 1009 0 0 0 0 0
+0 1008 0 1007 1006 0 0 1005 1004 0 1003 0 0 0 0 1002 1001 0 1000 0 0 0 999 0 0
+0 0 0 0 0 0 0 0 998 0 997 996 0 0 995 994 0 993 0 0 0 0 992 991 0 990 0 0 0 989
+0 0 0 0 0 0 0 0 988 987 0 986 0 0 0 985 0 0 0 0 0 0 0 984 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 983 0 982 981 0 0 980 979 0 978 0 0 0 0 977 976 0 975 0 0 0 974 0
+0 0 0 0 0 0 0 973 972 0 971 0 0 0 970 0 0 0 0 0 0 0 969 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 968 967 0 966 0 0 0 965 0 0 0 0 0 0 0 964 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+963 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 962 0
+961 960 0 0 959 958 0 957 0 0 0 0 956 955 0 954 0 0 0 953 0 0 0 0 0 0 0 0 952
+951 0 950 0 0 0 949 0 0 0 0 0 0 0 948 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 947 946 0
+945 0 0 0 944 0 0 0 0 0 0 0 943 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 942 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 941 940 0 939 0 0 0 938 0 0 0
+0 0 0 0 937 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 936 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 935 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 934 0 0 0 933 0 932 931 0 0 0 0 930 0 929 928 0 0 927 926 0 925 0 0
+0 0 0 0 924 0 923 922 0 0 921 920 0 919 0 0 0 0 918 917 0 916 0 0 0 915 0 0 0 0
+0 0 0 0 0 0 914 0 913 912 0 0 911 910 0 909 0 0 0 0 908 907 0 906 0 0 0 905 0 0
+0 0 0 0 0 0 904 903 0 902 0 0 0 901 0 0 0 0 0 0 0 900 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 899 0 898 897 0 0 896 895 0 894 0 0 0 0 893 892 0 891 0 0 0 890 0 0 0
+0 0 0 0 0 889 888 0 887 0 0 0 886 0 0 0 0 0 0 0 885 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 884 883 0 882 0 0 0 881 0 0 0 0 0 0 0 880 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 879
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 878 0 877
+876 0 0 875 874 0 873 0 0 0 0 872 871 0 870 0 0 0 869 0 0 0 0 0 0 0 0 868 867 0
+866 0 0 0 865 0 0 0 0 0 0 0 864 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 863 862 0 861 0
+0 0 860 0 0 0 0 0 0 0 859 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 858 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 857 856 0 855 0 0 0 854 0 0 0 0 0 0
+0 853 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 852 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 851 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+850 0 849 848 0 0 847 846 0 845 0 0 0 0 844 843 0 842 0 0 0 841 0 0 0 0 0 0 0 0
+840 839 0 838 0 0 0 837 0 0 0 0 0 0 0 836 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 835
+834 0 833 0 0 0 832 0 0 0 0 0 0 0 831 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 830 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 829 828 0 827 0 0 0 826
+0 0 0 0 0 0 0 825 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 824 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 823 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 822 821 0 820 0 0 0 819 0 0 0 0 0 0 0 818 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+817 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 816 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 10 0 0 0 0 0 0 0 815 0 0 0 814 0 813 812 0 0 0 0 0 0 0 0 811 0 0 0 810 0 809
+808 0 0 0 0 807 0 806 805 0 0 804 803 0 802 0 0 0 0 0 0 0 0 0 0 801 0 0 0 800 0
+799 798 0 0 0 0 797 0 796 795 0 0 794 793 0 792 0 0 0 0 0 0 791 0 790 789 0 0
+788 787 0 786 0 0 0 0 785 784 0 783 0 0 0 782 0 0 0 0 0 0 0 0 0 0 0 0 0 0 781 0
+0 0 780 0 779 778 0 0 0 0 777 0 776 775 0 0 774 773 0 772 0 0 0 0 0 0 771 0 770
+769 0 0 768 767 0 766 0 0 0 0 765 764 0 763 0 0 0 762 0 0 0 0 0 0 0 0 0 0 761 0
+760 759 0 0 758 757 0 756 0 0 0 0 755 754 0 753 0 0 0 752 0 0 0 0 0 0 0 0 751
+750 0 749 0 0 0 748 0 0 0 0 0 0 0 747 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 746 0 0 0 745 0 744 743 0 0 0 0 742 0 741 740 0 0 739 738 0 737 0 0 0 0 0 0
+736 0 735 734 0 0 733 732 0 731 0 0 0 0 730 729 0 728 0 0 0 727 0 0 0 0 0 0 0 0
+0 0 726 0 725 724 0 0 723 722 0 721 0 0 0 0 720 719 0 718 0 0 0 717 0 0 0 0 0 0
+0 0 716 715 0 714 0 0 0 713 0 0 0 0 0 0 0 712 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 711 0 710 709 0 0 708 707 0 706 0 0 0 0 705 704 0 703 0 0 0 702 0 0 0 0 0 0 0
+0 701 700 0 699 0 0 0 698 0 0 0 0 0 0 0 697 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 696
+695 0 694 0 0 0 693 0 0 0 0 0 0 0 692 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 691 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 690 0 0 0
+689 0 688 687 0 0 0 0 686 0 685 684 0 0 683 682 0 681 0 0 0 0 0 0 680 0 679 678
+0 0 677 676 0 675 0 0 0 0 674 673 0 672 0 0 0 671 0 0 0 0 0 0 0 0 0 0 670 0 669
+668 0 0 667 666 0 665 0 0 0 0 664 663 0 662 0 0 0 661 0 0 0 0 0 0 0 0 660 659 0
+658 0 0 0 657 0 0 0 0 0 0 0 656 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 655 0 654
+653 0 0 652 651 0 650 0 0 0 0 649 648 0 647 0 0 0 646 0 0 0 0 0 0 0 0 645 644 0
+643 0 0 0 642 0 0 0 0 0 0 0 641 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 640 639 0 638 0
+0 0 637 0 0 0 0 0 0 0 636 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 635 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 634 0 633 632 0 0 631 630 0 629
+0 0 0 0 628 627 0 626 0 0 0 625 0 0 0 0 0 0 0 0 624 623 0 622 0 0 0 621 0 0 0 0
+0 0 0 620 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 619 618 0 617 0 0 0 616 0 0 0 0 0 0 0
+615 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 614 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 613 612 0 611 0 0 0 610 0 0 0 0 0 0 0 609 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 608 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+607 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 606 0 0 0 605 0
+604 603 0 0 0 0 602 0 601 600 0 0 599 598 0 597 0 0 0 0 0 0 596 0 595 594 0 0
+593 592 0 591 0 0 0 0 590 589 0 588 0 0 0 587 0 0 0 0 0 0 0 0 0 0 586 0 585 584
+0 0 583 582 0 581 0 0 0 0 580 579 0 578 0 0 0 577 0 0 0 0 0 0 0 0 576 575 0 574
+0 0 0 573 0 0 0 0 0 0 0 572 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 571 0 570 569 0
+0 568 567 0 566 0 0 0 0 565 564 0 563 0 0 0 562 0 0 0 0 0 0 0 0 561 560 0 559 0
+0 0 558 0 0 0 0 0 0 0 557 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 556 555 0 554 0 0 0
+553 0 0 0 0 0 0 0 552 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 551 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 550 0 549 548 0 0 547 546 0 545 0 0
+0 0 544 543 0 542 0 0 0 541 0 0 0 0 0 0 0 0 540 539 0 538 0 0 0 537 0 0 0 0 0 0
+0 536 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 535 534 0 533 0 0 0 532 0 0 0 0 0 0 0 531
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 530 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 529 528 0 527 0 0 0 526 0 0 0 0 0 0 0 525 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 524 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 523
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 522 0 521 520 0 0 519 518 0
+517 0 0 0 0 516 515 0 514 0 0 0 513 0 0 0 0 0 0 0 0 512 511 0 510 0 0 0 509 0 0
+0 0 0 0 0 508 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 507 506 0 505 0 0 0 504 0 0 0 0 0
+0 0 503 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 502 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 501 500 0 499 0 0 0 498 0 0 0 0 0 0 0 497 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 496 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 495 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 494 493 0 492 0 0 0 491
+0 0 0 0 0 0 0 490 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 489 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 488 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 487 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 486 0 0 0 485 0 484 483 0 0 0 0 482 0 481
+480 0 0 479 478 0 477 0 0 0 0 0 0 476 0 475 474 0 0 473 472 0 471 0 0 0 0 470
+469 0 468 0 0 0 467 0 0 0 0 0 0 0 0 0 0 466 0 465 464 0 0 463 462 0 461 0 0 0 0
+460 459 0 458 0 0 0 457 0 0 0 0 0 0 0 0 456 455 0 454 0 0 0 453 0 0 0 0 0 0 0
+452 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 451 0 450 449 0 0 448 447 0 446 0 0 0 0
+445 444 0 443 0 0 0 442 0 0 0 0 0 0 0 0 441 440 0 439 0 0 0 438 0 0 0 0 0 0 0
+437 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 436 435 0 434 0 0 0 433 0 0 0 0 0 0 0 432 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 431 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 430 0 429 428 0 0 427 426 0 425 0 0 0 0 424 423 0 422 0 0 0
+421 0 0 0 0 0 0 0 0 420 419 0 418 0 0 0 417 0 0 0 0 0 0 0 416 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 415 414 0 413 0 0 0 412 0 0 0 0 0 0 0 411 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 410 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 409
+408 0 407 0 0 0 406 0 0 0 0 0 0 0 405 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 404 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 403 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 402 0 401 400 0 0 399 398 0 397 0 0 0 0 396 395 0
+394 0 0 0 393 0 0 0 0 0 0 0 0 392 391 0 390 0 0 0 389 0 0 0 0 0 0 0 388 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 387 386 0 385 0 0 0 384 0 0 0 0 0 0 0 383 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 382 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 381 380 0 379 0 0 0 378 0 0 0 0 0 0 0 377 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 376
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 375 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 374 373 0 372 0 0 0 371 0 0 0 0 0 0 0 370 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 369 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 368 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 367 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 366 0 365 364 0 0 363 362 0 361 0 0 0 0 360 359 0 358 0 0 0 357 0 0 0 0 0
+0 0 0 356 355 0 354 0 0 0 353 0 0 0 0 0 0 0 352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+351 350 0 349 0 0 0 348 0 0 0 0 0 0 0 347 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 346 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 345 344 0 343 0 0 0
+342 0 0 0 0 0 0 0 341 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 340 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 339 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 338 337 0 336 0 0 0 335 0 0 0 0 0 0 0 334 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 333 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 332 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 331 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 330 329 0 328 0 0 0
+327 0 0 0 0 0 0 0 326 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 325 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 324 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 323 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 1 }
+
+! This is a lookup table for all non-flush hands consisting of five unique
+! ranks (i.e. either Straights or High Card hands). A zero means that specific
+! combination is not possible with this type of hand.
+CONSTANT: unique5-table
+{ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1608 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 7462 0 0 0 0 0 0 0 7461 0 0 0 7460 0 7459 1607 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 7458 0 0 0 0 0 0 0 7457 0 0 0 7456 0 7455 7454 0 0 0 0 0 0
+0 0 7453 0 0 0 7452 0 7451 7450 0 0 0 0 7449 0 7448 7447 0 0 7446 7445 0 1606 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7444 0 0 0 0 0 0 0 7443 0 0 0 7442 0 7441
+7440 0 0 0 0 0 0 0 0 7439 0 0 0 7438 0 7437 7436 0 0 0 0 7435 0 7434 7433 0 0
+7432 7431 0 7430 0 0 0 0 0 0 0 0 0 0 7429 0 0 0 7428 0 7427 7426 0 0 0 0 7425 0
+7424 7423 0 0 7422 7421 0 7420 0 0 0 0 0 0 7419 0 7418 7417 0 0 7416 7415 0
+7414 0 0 0 0 7413 7412 0 7411 0 0 0 1605 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7410 0 0 0 0 0 0 0 7409 0 0 0 7408 0 7407 7406 0 0 0 0 0 0 0 0 7405 0 0 0
+7404 0 7403 7402 0 0 0 0 7401 0 7400 7399 0 0 7398 7397 0 7396 0 0 0 0 0 0 0 0
+0 0 7395 0 0 0 7394 0 7393 7392 0 0 0 0 7391 0 7390 7389 0 0 7388 7387 0 7386 0
+0 0 0 0 0 7385 0 7384 7383 0 0 7382 7381 0 7380 0 0 0 0 7379 7378 0 7377 0 0 0
+7376 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7375 0 0 0 7374 0 7373 7372 0 0 0 0 7371 0
+7370 7369 0 0 7368 7367 0 7366 0 0 0 0 0 0 7365 0 7364 7363 0 0 7362 7361 0
+7360 0 0 0 0 7359 7358 0 7357 0 0 0 7356 0 0 0 0 0 0 0 0 0 0 7355 0 7354 7353 0
+0 7352 7351 0 7350 0 0 0 0 7349 7348 0 7347 0 0 0 7346 0 0 0 0 0 0 0 0 7345
+7344 0 7343 0 0 0 7342 0 0 0 0 0 0 0 1604 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 7341 0 0 0 0 0 0 0 7340 0 0 0 7339 0 7338 7337 0 0 0 0 0
+0 0 0 7336 0 0 0 7335 0 7334 7333 0 0 0 0 7332 0 7331 7330 0 0 7329 7328 0 7327
+0 0 0 0 0 0 0 0 0 0 7326 0 0 0 7325 0 7324 7323 0 0 0 0 7322 0 7321 7320 0 0
+7319 7318 0 7317 0 0 0 0 0 0 7316 0 7315 7314 0 0 7313 7312 0 7311 0 0 0 0 7310
+7309 0 7308 0 0 0 7307 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7306 0 0 0 7305 0 7304 7303
+0 0 0 0 7302 0 7301 7300 0 0 7299 7298 0 7297 0 0 0 0 0 0 7296 0 7295 7294 0 0
+7293 7292 0 7291 0 0 0 0 7290 7289 0 7288 0 0 0 7287 0 0 0 0 0 0 0 0 0 0 7286 0
+7285 7284 0 0 7283 7282 0 7281 0 0 0 0 7280 7279 0 7278 0 0 0 7277 0 0 0 0 0 0
+0 0 7276 7275 0 7274 0 0 0 7273 0 0 0 0 0 0 0 7272 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 7271 0 0 0 7270 0 7269 7268 0 0 0 0 7267 0 7266 7265 0 0 7264
+7263 0 7262 0 0 0 0 0 0 7261 0 7260 7259 0 0 7258 7257 0 7256 0 0 0 0 7255 7254
+0 7253 0 0 0 7252 0 0 0 0 0 0 0 0 0 0 7251 0 7250 7249 0 0 7248 7247 0 7246 0 0
+0 0 7245 7244 0 7243 0 0 0 7242 0 0 0 0 0 0 0 0 7241 7240 0 7239 0 0 0 7238 0 0
+0 0 0 0 0 7237 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7236 0 7235 7234 0 0 7233
+7232 0 7231 0 0 0 0 7230 7229 0 7228 0 0 0 7227 0 0 0 0 0 0 0 0 7226 7225 0
+7224 0 0 0 7223 0 0 0 0 0 0 0 7222 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7221 7220 0
+7219 0 0 0 7218 0 0 0 0 0 0 0 7217 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1603 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 7216 0 0 0 0 0 0 0 7215 0 0 0 7214 0 7213 7212 0 0 0 0 0 0 0 0 7211 0 0 0
+7210 0 7209 7208 0 0 0 0 7207 0 7206 7205 0 0 7204 7203 0 7202 0 0 0 0 0 0 0 0
+0 0 7201 0 0 0 7200 0 7199 7198 0 0 0 0 7197 0 7196 7195 0 0 7194 7193 0 7192 0
+0 0 0 0 0 7191 0 7190 7189 0 0 7188 7187 0 7186 0 0 0 0 7185 7184 0 7183 0 0 0
+7182 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7181 0 0 0 7180 0 7179 7178 0 0 0 0 7177 0
+7176 7175 0 0 7174 7173 0 7172 0 0 0 0 0 0 7171 0 7170 7169 0 0 7168 7167 0
+7166 0 0 0 0 7165 7164 0 7163 0 0 0 7162 0 0 0 0 0 0 0 0 0 0 7161 0 7160 7159 0
+0 7158 7157 0 7156 0 0 0 0 7155 7154 0 7153 0 0 0 7152 0 0 0 0 0 0 0 0 7151
+7150 0 7149 0 0 0 7148 0 0 0 0 0 0 0 7147 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 7146 0 0 0 7145 0 7144 7143 0 0 0 0 7142 0 7141 7140 0 0 7139 7138 0 7137
+0 0 0 0 0 0 7136 0 7135 7134 0 0 7133 7132 0 7131 0 0 0 0 7130 7129 0 7128 0 0
+0 7127 0 0 0 0 0 0 0 0 0 0 7126 0 7125 7124 0 0 7123 7122 0 7121 0 0 0 0 7120
+7119 0 7118 0 0 0 7117 0 0 0 0 0 0 0 0 7116 7115 0 7114 0 0 0 7113 0 0 0 0 0 0
+0 7112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7111 0 7110 7109 0 0 7108 7107 0
+7106 0 0 0 0 7105 7104 0 7103 0 0 0 7102 0 0 0 0 0 0 0 0 7101 7100 0 7099 0 0 0
+7098 0 0 0 0 0 0 0 7097 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7096 7095 0 7094 0 0 0
+7093 0 0 0 0 0 0 0 7092 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7091 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7090 0 0 0 7089 0 7088
+7087 0 0 0 0 7086 0 7085 7084 0 0 7083 7082 0 7081 0 0 0 0 0 0 7080 0 7079 7078
+0 0 7077 7076 0 7075 0 0 0 0 7074 7073 0 7072 0 0 0 7071 0 0 0 0 0 0 0 0 0 0
+7070 0 7069 7068 0 0 7067 7066 0 7065 0 0 0 0 7064 7063 0 7062 0 0 0 7061 0 0 0
+0 0 0 0 0 7060 7059 0 7058 0 0 0 7057 0 0 0 0 0 0 0 7056 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 7055 0 7054 7053 0 0 7052 7051 0 7050 0 0 0 0 7049 7048 0 7047 0
+0 0 7046 0 0 0 0 0 0 0 0 7045 7044 0 7043 0 0 0 7042 0 0 0 0 0 0 0 7041 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 7040 7039 0 7038 0 0 0 7037 0 0 0 0 0 0 0 7036 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 7035 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 7034 0 7033 7032 0 0 7031 7030 0 7029 0 0 0 0 7028 7027 0 7026
+0 0 0 7025 0 0 0 0 0 0 0 0 7024 7023 0 7022 0 0 0 7021 0 0 0 0 0 0 0 7020 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 7019 7018 0 7017 0 0 0 7016 0 0 0 0 0 0 0 7015 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 7014 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 7013 7012 0 7011 0 0 0 7010 0 0 0 0 0 0 0 7009 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 7008 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+1602 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 7007 0 0 0 0 0 0 0 7006 0 0 0 7005 0 7004 7003 0 0 0 0 0 0 0 0 7002 0 0 0
+7001 0 7000 6999 0 0 0 0 6998 0 6997 6996 0 0 6995 6994 0 6993 0 0 0 0 0 0 0 0
+0 0 6992 0 0 0 6991 0 6990 6989 0 0 0 0 6988 0 6987 6986 0 0 6985 6984 0 6983 0
+0 0 0 0 0 6982 0 6981 6980 0 0 6979 6978 0 6977 0 0 0 0 6976 6975 0 6974 0 0 0
+6973 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6972 0 0 0 6971 0 6970 6969 0 0 0 0 6968 0
+6967 6966 0 0 6965 6964 0 6963 0 0 0 0 0 0 6962 0 6961 6960 0 0 6959 6958 0
+6957 0 0 0 0 6956 6955 0 6954 0 0 0 6953 0 0 0 0 0 0 0 0 0 0 6952 0 6951 6950 0
+0 6949 6948 0 6947 0 0 0 0 6946 6945 0 6944 0 0 0 6943 0 0 0 0 0 0 0 0 6942
+6941 0 6940 0 0 0 6939 0 0 0 0 0 0 0 6938 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 6937 0 0 0 6936 0 6935 6934 0 0 0 0 6933 0 6932 6931 0 0 6930 6929 0 6928
+0 0 0 0 0 0 6927 0 6926 6925 0 0 6924 6923 0 6922 0 0 0 0 6921 6920 0 6919 0 0
+0 6918 0 0 0 0 0 0 0 0 0 0 6917 0 6916 6915 0 0 6914 6913 0 6912 0 0 0 0 6911
+6910 0 6909 0 0 0 6908 0 0 0 0 0 0 0 0 6907 6906 0 6905 0 0 0 6904 0 0 0 0 0 0
+0 6903 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6902 0 6901 6900 0 0 6899 6898 0
+6897 0 0 0 0 6896 6895 0 6894 0 0 0 6893 0 0 0 0 0 0 0 0 6892 6891 0 6890 0 0 0
+6889 0 0 0 0 0 0 0 6888 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6887 6886 0 6885 0 0 0
+6884 0 0 0 0 0 0 0 6883 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6882 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6881 0 0 0 6880 0 6879
+6878 0 0 0 0 6877 0 6876 6875 0 0 6874 6873 0 6872 0 0 0 0 0 0 6871 0 6870 6869
+0 0 6868 6867 0 6866 0 0 0 0 6865 6864 0 6863 0 0 0 6862 0 0 0 0 0 0 0 0 0 0
+6861 0 6860 6859 0 0 6858 6857 0 6856 0 0 0 0 6855 6854 0 6853 0 0 0 6852 0 0 0
+0 0 0 0 0 6851 6850 0 6849 0 0 0 6848 0 0 0 0 0 0 0 6847 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 6846 0 6845 6844 0 0 6843 6842 0 6841 0 0 0 0 6840 6839 0 6838 0
+0 0 6837 0 0 0 0 0 0 0 0 6836 6835 0 6834 0 0 0 6833 0 0 0 0 0 0 0 6832 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 6831 6830 0 6829 0 0 0 6828 0 0 0 0 0 0 0 6827 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 6826 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 6825 0 6824 6823 0 0 6822 6821 0 6820 0 0 0 0 6819 6818 0 6817
+0 0 0 6816 0 0 0 0 0 0 0 0 6815 6814 0 6813 0 0 0 6812 0 0 0 0 0 0 0 6811 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 6810 6809 0 6808 0 0 0 6807 0 0 0 0 0 0 0 6806 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 6805 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 6804 6803 0 6802 0 0 0 6801 0 0 0 0 0 0 0 6800 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 6799 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+6798 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6797 0 0 0
+6796 0 6795 6794 0 0 0 0 6793 0 6792 6791 0 0 6790 6789 0 6788 0 0 0 0 0 0 6787
+0 6786 6785 0 0 6784 6783 0 6782 0 0 0 0 6781 6780 0 6779 0 0 0 6778 0 0 0 0 0
+0 0 0 0 0 6777 0 6776 6775 0 0 6774 6773 0 6772 0 0 0 0 6771 6770 0 6769 0 0 0
+6768 0 0 0 0 0 0 0 0 6767 6766 0 6765 0 0 0 6764 0 0 0 0 0 0 0 6763 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 6762 0 6761 6760 0 0 6759 6758 0 6757 0 0 0 0 6756 6755
+0 6754 0 0 0 6753 0 0 0 0 0 0 0 0 6752 6751 0 6750 0 0 0 6749 0 0 0 0 0 0 0
+6748 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6747 6746 0 6745 0 0 0 6744 0 0 0 0 0 0 0
+6743 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6742 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 6741 0 6740 6739 0 0 6738 6737 0 6736 0 0 0 0 6735
+6734 0 6733 0 0 0 6732 0 0 0 0 0 0 0 0 6731 6730 0 6729 0 0 0 6728 0 0 0 0 0 0
+0 6727 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6726 6725 0 6724 0 0 0 6723 0 0 0 0 0 0
+0 6722 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6721 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 6720 6719 0 6718 0 0 0 6717 0 0 0 0 0 0 0 6716 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 6715 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 6714 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6713 0
+6712 6711 0 0 6710 6709 0 6708 0 0 0 0 6707 6706 0 6705 0 0 0 6704 0 0 0 0 0 0
+0 0 6703 6702 0 6701 0 0 0 6700 0 0 0 0 0 0 0 6699 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 6698 6697 0 6696 0 0 0 6695 0 0 0 0 0 0 0 6694 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 6693 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6692
+6691 0 6690 0 0 0 6689 0 0 0 0 0 0 0 6688 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6687 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6686 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6685 6684 0 6683 0 0 0 6682 0 0 0 0 0 0 0
+6681 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6680 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 6679 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1601
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1609 0 0 0 0 0 0 0 6678 0 0 0 6677
+0 6676 6675 0 0 0 0 0 0 0 0 6674 0 0 0 6673 0 6672 6671 0 0 0 0 6670 0 6669
+6668 0 0 6667 6666 0 6665 0 0 0 0 0 0 0 0 0 0 6664 0 0 0 6663 0 6662 6661 0 0 0
+0 6660 0 6659 6658 0 0 6657 6656 0 6655 0 0 0 0 0 0 6654 0 6653 6652 0 0 6651
+6650 0 6649 0 0 0 0 6648 6647 0 6646 0 0 0 6645 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+6644 0 0 0 6643 0 6642 6641 0 0 0 0 6640 0 6639 6638 0 0 6637 6636 0 6635 0 0 0
+0 0 0 6634 0 6633 6632 0 0 6631 6630 0 6629 0 0 0 0 6628 6627 0 6626 0 0 0 6625
+0 0 0 0 0 0 0 0 0 0 6624 0 6623 6622 0 0 6621 6620 0 6619 0 0 0 0 6618 6617 0
+6616 0 0 0 6615 0 0 0 0 0 0 0 0 6614 6613 0 6612 0 0 0 6611 0 0 0 0 0 0 0 6610
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6609 0 0 0 6608 0 6607 6606 0 0 0 0
+6605 0 6604 6603 0 0 6602 6601 0 6600 0 0 0 0 0 0 6599 0 6598 6597 0 0 6596
+6595 0 6594 0 0 0 0 6593 6592 0 6591 0 0 0 6590 0 0 0 0 0 0 0 0 0 0 6589 0 6588
+6587 0 0 6586 6585 0 6584 0 0 0 0 6583 6582 0 6581 0 0 0 6580 0 0 0 0 0 0 0 0
+6579 6578 0 6577 0 0 0 6576 0 0 0 0 0 0 0 6575 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 6574 0 6573 6572 0 0 6571 6570 0 6569 0 0 0 0 6568 6567 0 6566 0 0 0 6565 0
+0 0 0 0 0 0 0 6564 6563 0 6562 0 0 0 6561 0 0 0 0 0 0 0 6560 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 6559 6558 0 6557 0 0 0 6556 0 0 0 0 0 0 0 6555 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 6554 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 6553 0 0 0 6552 0 6551 6550 0 0 0 0 6549 0 6548 6547 0 0 6546
+6545 0 6544 0 0 0 0 0 0 6543 0 6542 6541 0 0 6540 6539 0 6538 0 0 0 0 6537 6536
+0 6535 0 0 0 6534 0 0 0 0 0 0 0 0 0 0 6533 0 6532 6531 0 0 6530 6529 0 6528 0 0
+0 0 6527 6526 0 6525 0 0 0 6524 0 0 0 0 0 0 0 0 6523 6522 0 6521 0 0 0 6520 0 0
+0 0 0 0 0 6519 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6518 0 6517 6516 0 0 6515
+6514 0 6513 0 0 0 0 6512 6511 0 6510 0 0 0 6509 0 0 0 0 0 0 0 0 6508 6507 0
+6506 0 0 0 6505 0 0 0 0 0 0 0 6504 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6503 6502 0
+6501 0 0 0 6500 0 0 0 0 0 0 0 6499 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6498 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6497 0 6496 6495 0 0
+6494 6493 0 6492 0 0 0 0 6491 6490 0 6489 0 0 0 6488 0 0 0 0 0 0 0 0 6487 6486
+0 6485 0 0 0 6484 0 0 0 0 0 0 0 6483 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6482 6481
+0 6480 0 0 0 6479 0 0 0 0 0 0 0 6478 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6477 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6476 6475 0 6474 0 0 0
+6473 0 0 0 0 0 0 0 6472 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6471 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6470 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 6469 0 0 0 6468 0 6467 6466 0 0 0 0 6465 0 6464
+6463 0 0 6462 6461 0 6460 0 0 0 0 0 0 6459 0 6458 6457 0 0 6456 6455 0 6454 0 0
+0 0 6453 6452 0 6451 0 0 0 6450 0 0 0 0 0 0 0 0 0 0 6449 0 6448 6447 0 0 6446
+6445 0 6444 0 0 0 0 6443 6442 0 6441 0 0 0 6440 0 0 0 0 0 0 0 0 6439 6438 0
+6437 0 0 0 6436 0 0 0 0 0 0 0 6435 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6434 0
+6433 6432 0 0 6431 6430 0 6429 0 0 0 0 6428 6427 0 6426 0 0 0 6425 0 0 0 0 0 0
+0 0 6424 6423 0 6422 0 0 0 6421 0 0 0 0 0 0 0 6420 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 6419 6418 0 6417 0 0 0 6416 0 0 0 0 0 0 0 6415 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 6414 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6413
+0 6412 6411 0 0 6410 6409 0 6408 0 0 0 0 6407 6406 0 6405 0 0 0 6404 0 0 0 0 0
+0 0 0 6403 6402 0 6401 0 0 0 6400 0 0 0 0 0 0 0 6399 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 6398 6397 0 6396 0 0 0 6395 0 0 0 0 0 0 0 6394 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 6393 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6392
+6391 0 6390 0 0 0 6389 0 0 0 0 0 0 0 6388 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6387 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6386 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6385 0 6384 6383 0 0 6382 6381 0 6380 0 0
+0 0 6379 6378 0 6377 0 0 0 6376 0 0 0 0 0 0 0 0 6375 6374 0 6373 0 0 0 6372 0 0
+0 0 0 0 0 6371 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6370 6369 0 6368 0 0 0 6367 0 0
+0 0 0 0 0 6366 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6365 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6364 6363 0 6362 0 0 0 6361 0 0 0 0 0 0 0
+6360 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6359 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 6358 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+6357 6356 0 6355 0 0 0 6354 0 0 0 0 0 0 0 6353 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+6352 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6351 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6349 0
+0 0 6348 0 6347 6346 0 0 0 0 6345 0 6344 6343 0 0 6342 6341 0 6340 0 0 0 0 0 0
+6339 0 6338 6337 0 0 6336 6335 0 6334 0 0 0 0 6333 6332 0 6331 0 0 0 6330 0 0 0
+0 0 0 0 0 0 0 6329 0 6328 6327 0 0 6326 6325 0 6324 0 0 0 0 6323 6322 0 6321 0
+0 0 6320 0 0 0 0 0 0 0 0 6319 6318 0 6317 0 0 0 6316 0 0 0 0 0 0 0 6315 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 6314 0 6313 6312 0 0 6311 6310 0 6309 0 0 0 0 6308
+6307 0 6306 0 0 0 6305 0 0 0 0 0 0 0 0 6304 6303 0 6302 0 0 0 6301 0 0 0 0 0 0
+0 6300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6299 6298 0 6297 0 0 0 6296 0 0 0 0 0 0
+0 6295 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6294 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6293 0 6292 6291 0 0 6290 6289 0 6288 0 0 0 0
+6287 6286 0 6285 0 0 0 6284 0 0 0 0 0 0 0 0 6283 6282 0 6281 0 0 0 6280 0 0 0 0
+0 0 0 6279 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6278 6277 0 6276 0 0 0 6275 0 0 0 0
+0 0 0 6274 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6273 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6272 6271 0 6270 0 0 0 6269 0 0 0 0 0 0 0 6268 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 6267 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 6266 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6265
+0 6264 6263 0 0 6262 6261 0 6260 0 0 0 0 6259 6258 0 6257 0 0 0 6256 0 0 0 0 0
+0 0 0 6255 6254 0 6253 0 0 0 6252 0 0 0 0 0 0 0 6251 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 6250 6249 0 6248 0 0 0 6247 0 0 0 0 0 0 0 6246 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 6245 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6244
+6243 0 6242 0 0 0 6241 0 0 0 0 0 0 0 6240 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6239 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6238 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6237 6236 0 6235 0 0 0 6234 0 0 0 0 0 0 0
+6233 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6232 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 6231 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6230
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 6229 0 6228 6227 0 0 6226 6225 0 6224 0 0 0 0 6223 6222 0
+6221 0 0 0 6220 0 0 0 0 0 0 0 0 6219 6218 0 6217 0 0 0 6216 0 0 0 0 0 0 0 6215
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6214 6213 0 6212 0 0 0 6211 0 0 0 0 0 0 0 6210
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6209 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 6208 6207 0 6206 0 0 0 6205 0 0 0 0 0 0 0 6204 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 6203 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 6202 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6201 6200 0 6199 0
+0 0 6198 0 0 0 0 0 0 0 6197 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6196 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6195 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 6194 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6193 6192 0 6191 0 0 0 6190 0 0 0 0 0 0
+0 6189 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6188 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 6187 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+6186 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 1600 }
+
+! This is a lookup table for the perfect hash adjustment values.
+CONSTANT: adjustments-table
+{ 0 5628 7017 1298 2918 2442 8070 6383 6383 7425 2442 5628 8044 7425 3155 6383
+2918 7452 1533 6849 5586 7452 7452 1533 2209 6029 2794 3509 7992 7733 7452 131
+6029 4491 1814 7452 6110 3155 7077 6675 532 1334 7555 5325 3056 1403 1403 3969
+4491 1403 7592 522 8070 1403 0 1905 3584 2918 922 3304 6675 0 7622 7017 3210
+2139 1403 5225 0 3969 7992 5743 5499 5499 5345 7452 522 305 3056 7017 7017 2139
+1338 3056 7452 1403 6799 3204 3290 4099 1814 2191 4099 5743 1570 1334 7363 1905
+0 6799 4400 1480 6029 1905 0 7525 2028 2794 131 7646 3155 4986 1858 2442 7992
+1607 3584 4986 706 6029 5345 7622 6322 5196 1905 6847 218 1785 0 4099 2981 6849
+4751 3950 7733 3056 5499 4055 6849 1533 131 5196 2918 3879 5325 2794 6029 0 0
+322 7452 6178 2918 2320 6675 3056 6675 1533 6029 1428 2280 2171 6788 7452 3325
+107 4262 311 5562 7857 6110 2139 4942 4600 1905 0 3083 5345 7452 6675 0 6112
+4099 7017 1338 6799 2918 1232 3584 522 6029 5325 1403 6759 6849 508 6675 2987
+7745 6870 896 7452 1232 4400 12 2981 3850 4491 6849 0 6675 747 4491 7525 6675
+7452 7992 6921 7323 6849 3056 1199 2139 6029 6029 190 4351 7891 4400 7134 1533
+1194 3950 6675 5345 6383 7622 131 1905 2883 6383 1533 5345 2794 4303 1403 0
+1338 2794 992 4871 6383 4099 2794 3889 6184 3304 1905 6383 3950 3056 522 1810
+3975 7622 7452 522 6799 5866 7084 7622 6528 2798 7452 1810 7907 642 5345 1905
+6849 6675 7745 2918 4751 3229 2139 6029 5207 6601 2139 7452 5890 1428 5628 7622
+2139 3146 2400 578 941 7672 1814 3210 1533 4491 12 2918 1900 7425 2794 2987
+3465 1377 3822 3969 3210 859 5499 6878 1377 3056 4027 8065 8065 5207 4400 4303
+3210 3210 0 6675 357 5628 5512 1905 3452 1403 7646 859 6788 3210 2139 378 5663
+7733 870 0 4491 4813 2110 578 2139 3056 4099 1905 1298 4672 2191 3950 5499 3969
+4974 6323 6029 7414 6383 0 4974 3210 795 4099 131 5345 5345 6576 1810 1621 4400
+2918 1905 2442 2679 6322 7452 2110 1403 6383 2653 5132 6856 7841 2794 6110 2028
+6675 7425 6999 7441 6029 183 6675 4400 859 1403 2794 5985 5345 1533 322 4400
+1227 5890 4474 4491 3574 8166 6849 7086 5345 5345 5459 3584 6675 3969 7579 8044
+2295 2577 1480 5743 3304 5499 330 4303 6863 3822 4600 4751 5628 3822 2918 6675
+2400 6663 1403 6849 6029 3145 6110 3210 747 3229 3056 2918 7733 330 4055 7322
+5628 2987 3056 1905 2903 669 5325 2845 4099 5225 6283 4099 5000 642 4055 5345
+8034 2918 1041 5769 7051 1538 2918 3366 608 4303 3921 0 2918 1905 218 6687 5963
+859 3083 2987 896 5056 1905 2918 4415 7966 7646 2883 5628 7017 8029 6528 4474
+6322 5562 6669 4610 7006 }
+
+! This is a lookup table for the perfect hash final hand values.
+CONSTANT: values-table
+{ 148 2934 166 5107 4628 166 166 166 166 3033 166 4692 166 5571 2225 166 5340
+3423 166 3191 1752 166 5212 166 166 3520 166 166 166 1867 166 3313 166 3461 166
+166 3174 1737 5010 5008 166 4344 2868 3877 166 4089 166 5041 4748 4073 4066
+5298 3502 1812 166 5309 166 233 3493 166 166 3728 5236 4252 4010 2149 166 164
+4580 3039 4804 3874 166 6170 2812 166 4334 166 166 166 166 166 166 1862 224
+2131 6081 166 2710 166 166 166 4765 166 1964 5060 166 1897 166 3987 166 166
+5566 2021 166 45 166 166 3283 3932 166 166 3519 166 166 291 166 166 5132 2800
+166 166 166 5531 4054 166 3509 166 166 4908 3028 1756 1910 4671 2729 5224 166
+121 3327 3317 166 181 2371 5541 166 1787 2666 5134 5698 166 5480 3870 166 3823
+166 3165 5343 5123 5089 166 2422 3724 166 2735 1953 5724 4444 4871 166 166 5001
+5512 3133 5171 166 2216 166 4877 4542 166 166 166 5270 166 166 166 1922 69 3547
+166 166 166 166 166 231 4547 5155 3357 3464 166 72 3332 166 4392 5971 3896 4451
+3173 2569 166 4466 2518 1698 2850 5349 166 166 4457 5062 166 2202 1650 2191 166
+1950 2583 166 5293 2032 5893 166 3994 5392 3878 96 166 166 3195 166 4001 1900
+2513 6027 166 166 166 166 5407 166 166 2332 5125 5891 3096 3172 166 166 3065
+166 166 4535 166 166 166 4553 3131 3693 166 2255 2613 166 166 166 166 2866 166
+166 166 2940 5333 3199 166 2628 4312 166 166 1794 4681 2058 3606 166 166 3542
+2166 4696 2520 166 4739 166 2563 166 166 3681 166 166 166 4127 1967 2972 166
+5227 166 166 5551 4255 56 166 5553 3219 4367 166 3218 4749 2886 3695 3711 2228
+166 166 166 2268 5054 3749 4825 166 4933 4992 4530 166 4892 3400 166 197 166
+6078 166 166 3971 166 166 5357 1852 3377 166 5196 3740 5320 166 166 3099 166
+4562 6061 3294 166 166 166 166 3266 3627 2567 166 228 2773 166 166 53 1833 2401
+124 166 4272 3922 5959 2903 3923 166 6155 166 166 166 166 216 166 5247 166 5591
+166 166 82 87 4526 166 166 5439 166 4935 166 3187 1869 166 1764 5500 6023 3356
+166 3350 2457 2455 166 1637 166 3342 166 166 3355 5154 166 276 166 166 166 3371
+5969 166 1665 166 166 166 166 166 166 166 4092 1712 3122 5086 166 166 4906 166
+2591 166 166 166 1894 2997 166 4476 4384 166 4747 4109 2655 166 5978 1636 4898
+166 166 166 166 166 166 166 5207 166 166 3712 3876 91 5876 3786 5998 166 166
+166 4391 166 166 2832 2220 4435 166 166 5796 3156 6112 166 1643 1821 3129 166
+4200 166 5857 166 166 2351 5902 1855 5043 166 3167 5191 3996 5718 4876 3071
+2965 5735 5930 6149 2345 3297 3822 166 166 307 6019 1859 2981 4914 3320 6165
+2328 140 2372 308 166 2280 5081 166 3275 166 159 2399 2327 5489 4690 6059 4492
+4269 6058 166 19 166 3323 5708 128 4812 2949 166 166 2890 2630 5237 166 256
+3673 4621 5380 166 3353 166 1651 2573 1635 4011 3429 3370 3720 166 166 6108
+3848 5104 2851 1998 166 166 5106 20 166 2633 166 166 166 166 5662 125 3651 1731
+4702 166 3197 166 2947 3046 4196 2185 6100 166 2602 2908 2487 166 5232 166 4028
+5919 166 2680 3608 3252 166 4899 166 166 166 166 2529 166 166 166 166 166 2534
+166 2299 4076 166 3643 166 3921 166 166 166 1939 2124 1829 2436 3892 166 3481
+271 5307 1697 166 166 5098 2906 5545 166 5980 3203 166 1903 4626 4674 6118 6097
+5926 4136 1677 3232 4720 166 166 166 229 2012 3620 166 3798 166 166 2609 3489
+3809 166 166 166 166 166 166 166 5826 166 166 166 4903 166 166 166 166 6168 166
+5052 5044 5644 2375 2677 4012 3062 5831 4752 166 4125 2610 2062 3238 292 2533
+5872 51 166 1947 4225 166 2288 4845 166 5788 166 5717 166 166 5549 5619 166
+4165 166 2721 2311 5501 4416 4383 166 166 3068 5499 5936 166 4204 4766 4688
+1870 5220 166 166 166 166 237 2523 6039 3061 2793 3998 166 2545 2309 3144 3679
+3969 166 166 166 4379 3574 205 2808 5822 166 166 2188 4823 4990 5561 5711 166
+5627 6034 5253 3783 5047 4405 166 59 1755 3178 318 166 4710 2933 3409 6062 2821
+166 6099 166 4178 166 166 4122 36 4779 166 166 4323 3073 5410 2101 166 166 44
+5690 166 3265 166 5222 5909 1838 166 4755 2215 166 4082 166 166 3210 5140 3124
+5238 166 5913 2321 166 2416 5976 3918 5078 4218 5703 4897 6011 5685 2214 166
+166 6180 5175 1715 166 166 3760 4497 1808 4826 166 2540 166 166 5513 4971 5915
+166 166 2525 166 4480 42 232 2412 2797 3229 5263 2852 5543 2126 3562 166 2872
+4695 5985 5136 2714 4262 5473 166 4160 4347 166 166 166 166 5271 166 166 5108
+166 166 166 166 5437 4875 3963 4362 5820 5559 4890 4728 166 166 2692 166 4870
+3591 5472 166 2690 166 5854 3817 166 280 166 166 113 4128 3396 166 4264 5058
+2283 166 2281 4916 5671 166 2708 166 166 4589 166 166 4689 166 1686 166 166 166
+166 166 1774 166 166 166 5651 3777 2234 166 3864 18 3589 4592 4777 166 166 5254
+4245 166 166 166 4368 5172 3522 166 4306 153 5230 166 5598 5420 311 2414 4159
+2985 5137 166 2179 1801 166 4595 2083 2020 166 3602 2170 4259 3048 166 166 4193
+2350 166 166 2702 166 4521 166 166 2496 166 4593 2006 166 166 2292 4135 166
+6069 4623 166 166 4827 3995 4291 3243 166 166 166 5622 166 3539 166 166 4915
+4373 2479 3775 6008 5838 4321 1612 5530 166 3773 4267 4086 3081 2261 166 166
+4785 4641 5292 166 4820 5612 5556 166 166 166 4396 6084 3414 166 3331 2380 5921
+4315 2340 166 5511 166 4713 3754 2912 2553 166 3468 5388 166 1932 3540 5834 166
+166 3186 5258 166 4107 166 166 166 166 166 166 166 166 2108 12 2368 2789 166
+166 4148 1878 166 166 2324 4179 2945 2531 166 166 166 4485 3765 2308 166 2754
+166 6102 166 1921 260 2241 166 2592 166 166 166 4964 166 3055 5261 4943 2916
+166 201 5728 166 5759 4314 4730 6024 166 4926 4762 1834 2055 166 40 166 5416
+166 3722 2360 1928 166 4889 4590 5550 3498 166 6003 2029 4106 4346 3758 166
+2753 103 1891 5067 166 3398 2079 5784 3074 3787 166 166 3936 166 5766 166 4847
+3928 5119 166 5181 4602 2605 5712 4523 166 166 4717 166 2227 2181 166 4678 166
+166 4901 166 4980 166 166 166 166 5806 2894 5631 4995 2608 166 166 166 3917 166
+3417 166 2795 1655 3189 3364 166 4839 3510 4212 5641 6091 138 166 166 3343 4620
+2722 4566 166 3518 3424 166 166 1653 166 5057 166 5375 4833 166 4273 4348 166
+166 166 4912 166 3662 166 4281 166 5169 166 5883 2737 2572 4685 4068 166 4214
+166 166 2409 166 166 4571 166 5624 5722 5949 166 3675 166 166 5109 3428 166 166
+5446 166 3290 166 3309 166 166 4776 166 166 166 166 166 166 5617 2860 166 166
+166 166 3629 1741 166 166 183 4973 3047 2854 75 2035 3652 2159 166 4150 6037
+3225 4519 1902 2678 2413 1961 166 166 166 166 4972 1847 166 5636 4017 166 3345
+166 4520 166 2861 166 3092 6060 157 2542 2298 4496 166 2607 6110 5707 2314 166
+166 273 166 5952 166 4957 322 6065 2272 6140 2438 3458 3287 166 166 166 166
+2684 288 3354 166 166 3983 1702 166 166 166 2393 2435 4202 3308 5805 5085 166
+166 1938 166 166 2171 5892 2337 166 4648 3116 2486 4363 3567 166 166 2822 2041
+166 4703 3956 5192 166 3975 5720 3647 2134 5932 166 166 5160 263 166 166 166
+4549 166 166 1701 3086 166 166 4737 166 2252 166 170 166 166 166 2301 5478 166
+166 5979 3007 166 166 166 4104 166 2469 2700 166 4998 3376 166 1840 166 166
+4470 166 5235 3930 166 166 166 6031 166 166 166 3827 4700 166 166 166 166 166
+166 4103 3976 166 166 166 166 5027 4322 5130 166 4741 2132 4118 3080 4137 166
+6179 166 166 166 166 166 6120 4188 166 2251 166 3253 166 4887 166 4293 5241 166
+166 166 166 166 166 5076 166 166 4177 166 221 166 2757 5377 166 43 166 166 3180
+5540 166 213 4541 166 166 166 166 166 1641 166 4578 4639 166 166 1683 2139 1689
+5249 5773 5226 166 2820 166 5516 5045 166 4896 5657 5189 166 5770 2725 5148 166
+166 166 2929 166 3479 166 166 4564 3752 4305 4232 166 5906 1779 166 2709 4941
+4342 166 4882 166 4277 2322 166 4879 1610 3038 166 3762 2054 5652 166 4524 3820
+4806 166 166 104 3416 4869 4243 4854 166 4114 166 2121 166 3463 3556 166 4795
+166 2118 3920 166 166 4667 5046 166 166 2088 4360 5787 2198 4233 5552 3970 3523
+2037 5791 166 166 4299 2336 166 166 166 4173 4588 3626 5187 166 3363 4611 294
+4962 5243 2719 6022 4976 3559 166 2662 5779 6151 166 3527 166 5404 6132 1839
+166 3090 166 2253 166 5441 5518 6049 166 166 6136 3026 3474 5960 166 3937 4105
+166 2348 2039 4738 166 5233 3882 3840 166 278 190 166 5751 4313 166 3855 166
+166 6171 166 166 5381 3941 166 166 166 166 3334 166 2038 6088 166 1918 5037
+2325 2378 4894 3514 3715 5168 166 166 4083 2873 166 166 166 2693 166 3543 166
+2577 3013 166 166 4594 2622 166 166 166 3401 166 166 5447 5328 5547 6133 2335
+3739 166 166 166 166 5614 3492 3610 3466 166 5336 4354 166 4662 166 166 4283
+166 166 303 5904 166 2717 166 166 2276 5564 2386 5661 2040 166 1630 4652 166
+4840 166 110 5329 3979 5734 2550 166 166 6007 5999 2978 4771 5360 166 4023 166
+166 5920 4065 166 3880 166 5422 1813 166 6166 73 166 166 3669 5762 5077 166
+2953 85 166 3517 166 116 166 2738 3710 166 1634 166 166 166 2290 3001 166 166
+3037 2400 3410 166 1791 4231 166 3546 5009 5299 2807 166 166 1675 1619 2374
+3093 5302 3278 2330 5301 2343 2307 3274 5017 2265 3700 2465 166 139 4292 166
+5056 3952 166 4528 2388 1886 166 166 3016 3698 5881 166 2379 3223 166 166 3847
+2407 5493 3183 3307 166 265 166 2421 6161 2057 5363 3863 2474 166 166 5427 166
+2140 2955 166 3070 4237 5018 5988 5570 275 4862 2357 166 195 166 2593 6047 166
+2878 166 166 2781 3004 4180 166 5593 166 5973 2544 5064 166 4324 4701 166 3084
+166 166 5372 4725 166 5650 166 166 2786 166 3781 3583 3682 1850 4420 3296 5173
+4461 166 166 166 2984 166 93 166 166 4336 5943 2922 3300 166 4843 166 166 166
+166 2094 166 2939 166 4656 166 5146 166 166 166 166 2104 3977 4660 5312 166
+1865 166 5487 5558 3380 166 1957 3162 3281 166 3588 3268 2099 166 166 2319 4913
+4187 5503 5782 150 166 52 5450 166 166 166 2941 5877 166 4031 5393 166 3931
+4166 3135 3445 166 5053 5430 4836 166 5315 3389 4636 166 166 3441 166 166 3767
+2961 166 4761 4604 3179 166 166 4751 2148 2015 166 123 5013 166 2936 166 2063
+166 5823 166 5096 166 166 4198 166 166 166 3845 166 166 238 166 2703 3541 166
+4813 166 4477 2349 4197 5996 3324 4789 3063 166 166 5504 5273 2805 13 166 5601
+5402 4119 5206 166 166 4251 3704 4176 1963 2882 166 202 3125 3318 112 166 3362
+4835 3420 3974 5099 166 4433 166 166 166 1766 2663 166 166 4683 166 166 5485 47
+5101 5341 5765 3390 1648 4341 3945 6045 1645 166 5578 2594 166 166 3772 166 166
+3196 3603 166 5399 166 5075 166 5911 4632 4781 5313 270 166 2346 166 166 166
+1986 166 166 4958 166 166 166 4048 166 3076 166 166 4891 166 166 57 166 220 166
+166 166 4117 166 166 166 166 5194 2658 166 166 2942 6071 4182 166 2976 5816 166
+166 166 166 3985 4211 2514 166 166 166 2504 3446 1711 166 166 2107 5190 166 34
+166 3912 5382 3003 166 166 166 2999 2404 4734 4455 2087 166 2405 156 166 2830
+3303 296 3295 2067 4268 166 166 5642 166 166 1901 166 5133 166 166 166 166 3176
+2973 4677 166 166 6164 3000 2396 2734 5697 5989 166 2823 5265 5852 166 166 2623
+2625 2287 4844 1758 166 166 166 166 166 6073 166 5379 2389 5279 2444 5515 166
+4038 166 4948 5640 166 166 3572 4258 166 166 166 5204 166 4603 5797 166 166 166
+1725 4600 166 166 5498 166 4152 166 172 4758 166 2598 2489 2076 4366 2568 166
+4352 3782 166 166 3059 3946 5138 5727 4484 5694 166 3796 166 166 166 166 5334
+1778 2245 166 4517 4419 2250 182 5856 166 2835 4495 1858 2033 6014 6086 3211
+166 166 154 2145 166 129 3661 2661 5860 6143 2640 3890 6160 166 166 2747 166
+166 2291 282 2476 166 166 3825 166 1925 166 4489 166 166 166 4034 166 166 166
+166 166 166 122 4708 4919 2373 2453 5419 5954 297 5290 166 1978 166 4932 3501
+166 3085 3386 166 5405 4512 166 3209 5740 4020 5495 5815 314 166 3190 4824 166
+166 3448 207 1623 6096 5878 166 1836 166 166 2728 166 5278 3419 3012 5618 5266
+3078 166 166 2244 166 4569 6068 166 3336 166 5677 6052 5079 166 5453 5245 5799
+166 1982 166 5958 4619 5821 166 5285 284 1631 5710 6070 5365 2189 3242 166 2752
+5483 5297 6150 5522 166 1815 166 166 166 5801 166 166 5398 166 166 166 2967
+2515 3169 166 166 2562 166 1617 2069 166 166 6154 166 3721 166 5327 166 166 166
+5592 166 166 2286 1716 3903 166 2395 286 3587 6146 3286 4186 5882 5894 5737
+6032 5879 2761 4829 3788 166 166 3233 5356 5693 166 2429 2449 141 3444 5186 166
+166 3477 4080 4584 166 166 3670 1851 3824 4337 3886 2792 166 5867 166 166 3557
+3147 166 166 2200 166 2505 166 4310 4865 5656 5992 5672 166 5199 135 3023 2994
+4472 166 166 166 2019 4319 3472 166 166 166 29 206 3944 3027 5804 4731 5449 166
+2825 3310 166 6172 5202 166 2516 3644 4557 166 166 166 166 2671 4427 3432 3276
+5584 5536 4645 3202 166 2612 166 4249 2425 3259 4622 166 2411 4303 4206 166 166
+166 3734 6063 118 166 166 3641 166 166 166 4937 1871 3421 2208 166 166 166 166
+4881 166 166 166 166 3298 166 61 166 166 166 3293 6145 71 3619 166 166 3383
+1624 320 2187 4113 166 166 166 166 166 5080 2344 5625 2358 1621 4230 5579 5359
+295 4248 5267 3883 6124 187 5112 2122 166 166 166 5142 6004 166 5322 6175 3639
+3182 4425 166 175 166 166 166 5778 3939 3484 166 166 5832 5248 5935 4467 5858
+166 5038 166 166 3102 166 4880 166 166 166 166 3418 1666 5338 3680 5291 4441
+3385 166 5733 4503 2774 166 2631 4153 166 2000 166 166 5345 166 166 4298 1804
+4707 166 1613 1952 2111 166 166 166 166 166 2897 166 166 4044 166 166 166 166
+2863 5475 166 166 166 1704 166 3609 2782 2018 166 5361 166 3694 3733 166 2785
+1969 166 166 2834 1868 3779 1877 60 166 4143 3902 166 4361 3188 2498 6009 166
+115 166 3138 166 4575 6080 133 2030 166 166 166 2306 2136 3043 3447 2142 166
+3799 1646 5269 3640 166 2674 5502 166 5467 166 5069 166 166 4654 4581 5274 5036
+4364 166 3115 166 2128 4544 5433 2086 2584 4413 166 166 5385 166 234 166 1625
+166 166 166 5139 2511 4974 2766 166 166 166 2095 3990 217 166 2988 4061 166 209
+4883 166 166 166 166 166 4326 166 5465 2859 166 2887 166 2231 166 1658 166 2246
+166 1844 166 166 3087 2871 3872 1660 48 166 166 3622 166 1709 166 166 6177 6173
+166 3569 166 166 166 241 3660 3631 166 166 5319 5141 174 166 166 4412 166 5145
+166 1919 166 5276 166 2385 166 1618 166 166 2501 166 166 1734 5966 3145 166
+1690 4025 1664 4559 2433 2392 3552 4006 1896 166 166 2546 4450 5396 4221 4046
+166 166 2642 166 4448 166 2784 3480 4807 166 166 3534 166 166 5272 166 166 2831
+4263 166 166 166 166 4414 5628 3486 166 3748 166 4598 3719 3598 3611 166 4792
+5059 4110 166 2656 166 166 84 5429 166 166 166 281 1955 166 166 166 3616 4997
+166 166 166 166 3230 166 166 166 166 166 166 77 166 166 166 1800 166 4236 166
+166 166 166 166 5757 2530 1662 166 4607 1659 166 1685 3341 166 1699 4058 3407
+1854 4417 3034 166 166 166 166 5568 166 3206 166 5529 166 166 166 2116 3487 144
+166 166 166 5523 5373 5321 166 6064 2921 166 1696 2473 166 166 3716 5689 166
+4608 3879 166 166 166 2156 166 4358 2446 166 3958 166 5520 4340 4848 166 3285
+166 2665 166 3459 1905 5115 68 5730 166 3127 5029 4370 166 3753 166 3674 6025
+4490 166 4183 166 94 166 166 4051 3766 3140 4907 3857 166 166 4596 166 3888
+3040 2507 5643 166 166 4311 2618 5582 166 166 3678 166 1988 166 166 4464 166
+166 166 166 4278 3677 2173 5256 166 166 5162 166 5178 1644 5094 166 2557 5506
+166 166 166 4927 5348 1797 166 166 39 166 3866 3655 236 5403 2175 3361 166 1976
+5993 226 166 4643 166 5339 4098 2653 4969 166 3346 4984 4635 166 166 166 166
+4981 188 166 166 28 4088 166 166 166 25 3663 2696 166 4679 5114 5802 166 166
+166 166 166 3810 5749 166 1673 4276 166 3756 4184 166 5630 166 166 166 4531 212
+5663 166 166 2746 166 5386 3618 3594 1887 166 166 5443 166 1726 4094 5065 4756
+166 166 5308 5225 2081 166 166 3064 166 166 1981 3637 4355 1626 166 166 4686
+166 5793 180 5066 2938 3819 4904 3601 166 166 2495 5025 5768 2621 4650 3041 166
+5897 3633 166 166 4375 166 5714 1667 3273 3950 1668 166 5855 166 2364 166 1881
+166 2646 5460 166 2770 4951 5414 166 4442 2113 5726 298 5934 2053 166 166 4053
+166 166 4514 4697 166 166 5198 2707 166 5605 166 166 5218 2596 166 2110 166
+1806 2160 166 166 2212 166 3636 166 166 4377 4021 3707 4502 166 4195 166 166
+166 4108 3725 3676 166 2084 166 166 166 166 4216 166 166 6156 166 2896 166 166
+166 166 166 166 3826 2870 3793 166 166 5927 166 2759 166 4613 2297 5638 166
+2842 5031 4793 5184 166 166 2008 166 257 2881 117 6051 3044 4079 2833 166 6117
+166 3236 5469 166 166 2874 6076 166 1799 80 41 166 1864 166 5709 1611 5026 5176
+168 3269 4081 166 166 1970 4550 166 4250 4101 4565 5950 5845 97 4064 166 5394
+4374 4343 166 166 4658 3248 166 208 1735 4047 2843 166 166 166 166 2794 166 166
+5844 166 166 3094 2177 5436 3646 166 3564 4682 166 5948 5835 162 2059 5151 2034
+1926 5941 5903 5177 166 166 166 4801 3439 1780 166 166 3280 3434 166 166 4498
+5565 4043 166 4432 4722 3959 166 3746 166 166 177 166 166 2748 166 4483 166 166
+4144 166 166 166 166 2066 2915 166 2049 2130 4684 166 49 3506 5391 166 2590
+6103 1714 2410 3053 3837 4301 166 3255 2644 166 166 4014 166 2475 4788 2876 166
+166 166 166 166 166 4140 166 166 321 166 1966 166 166 2855 3111 3800 166 4446
+2551 166 166 166 2824 166 166 166 2164 3010 2226 166 4857 166 2582 5118 4582
+5917 166 166 3338 3482 3328 166 4817 166 5371 3830 166 3009 1633 3329 4052 166
+3701 4983 4500 4487 4878 166 166 5482 3544 166 3057 2026 4398 2847 3532 3262
+3399 166 166 166 4478 4167 166 3411 2599 5362 166 2711 166 166 166 166 3452
+2522 5586 5548 3279 2538 166 166 166 4161 166 2123 166 166 2660 166 166 1706
+166 15 3537 5051 5869 166 3025 166 4447 3744 120 166 166 166 204 2810 166 5124
+2376 5306 166 166 4493 166 166 166 5289 6046 166 2762 2541 1857 2467 5163 166
+166 166 166 5830 166 2172 3359 166 2928 166 166 166 6129 166 5445 166 166 5924
+6144 166 102 166 166 1678 166 4491 5705 166 1753 166 3873 5725 4145 1909 166
+2155 166 166 1848 3315 1874 166 4945 2524 166 3263 2362 1785 166 166 166 152
+2102 5723 5131 5754 4032 4029 166 4295 3391 166 166 166 5282 1747 3159 2235
+5583 1786 3630 6111 2974 4797 3623 166 2071 4929 166 2603 3964 3378 166 166
+2654 151 3940 4527 4518 166 2430 1884 3812 166 2867 166 166 166 2756 5418 166
+2354 4606 166 2153 166 4855 166 166 1720 166 3213 3926 166 5158 4349 166 4828
+166 166 2031 166 2300 166 166 166 2211 4954 3121 4754 2485 166 166 166 3593 166
+2718 5317 2765 5120 166 2527 166 1994 5947 166 166 166 6085 2302 100 79 2982
+3705 2180 2043 166 1872 1671 166 3729 166 4944 3665 2217 2119 166 5615 166 1620
+166 166 166 166 35 3913 2760 166 3688 3672 4042 166 166 5117 4227 166 4445 2458
+3803 4554 4988 166 166 3141 3491 166 166 166 166 5095 4668 5567 166 166 2885
+1790 2996 166 166 166 166 3737 166 2470 166 166 4339 166 166 166 4920 166 166
+3697 5471 166 166 3538 4558 3467 5262 5609 3858 166 166 5007 2780 2791 2236
+5668 3134 166 166 5776 3470 3291 166 2532 166 166 166 3805 264 166 3227 166 166
+166 2334 166 5087 101 166 3634 58 2813 166 166 166 3222 4704 4488 4508 5459
+2117 5873 166 1828 166 166 166 166 166 2105 166 5613 5761 2920 3098 166 166
+3277 166 166 166 166 83 166 166 166 3967 166 5574 166 4985 30 3426 166 179 3014
+4015 246 2556 4449 3723 5611 3436 166 4240 3642 166 4536 2048 5810 166 1971 166
+5557 5323 5022 191 5492 166 4837 4426 2537 2271 3177 5674 166 2796 1995 166
+3906 166 4403 3862 4716 2406 3948 4670 4309 166 2575 5358 2951 166 3666 3612
+5577 4579 4743 166 6072 6036 4563 2586 166 5836 166 166 5752 166 3563 166 2909
+3251 92 166 4711 4149 166 166 3052 5122 2904 2635 1990 166 166 166 166 166 166
+166 166 4213 166 3103 3142 2683 6105 2209 3175 4215 166 166 166 166 166 166 166
+5303 4075 5374 166 4174 4154 1895 4538 2764 166 5817 6113 4033 166 6090 166
+2990 166 3164 166 166 166 247 166 6083 3412 166 5738 166 3599 166 1904 2162
+2547 3960 166 166 3154 55 166 5991 4921 2879 166 166 5347 166 166 166 2712 4787
+166 1908 166 166 166 3184 166 166 166 4572 3846 3657 166 166 5481 166 166 3397
+1856 4978 166 3900 3570 3802 166 166 2075 4408 166 6079 2313 166 166 5756 166
+166 2070 166 166 3137 166 166 3686 166 166 166 166 67 5019 166 1742 166 5354
+166 5149 166 2931 4946 6006 166 166 2865 4902 3029 1722 3449 166 1987 166 62
+5626 166 166 166 2670 1657 5599 3056 166 3791 5020 166 1979 4437 1899 166 166
+196 2636 166 143 3475 4317 2512 2415 5033 5024 2112 2864 3551 166 1688 33 4585
+3648 4399 166 166 166 166 166 1824 166 166 166 166 166 166 4513 166 2478 4407
+166 166 2492 4130 4318 2980 5746 166 2606 4063 4123 166 255 166 166 4680 166
+3586 5975 3935 166 5528 166 3158 166 166 2614 5035 166 3488 3214 166 166 166
+5413 3713 166 5875 4329 5250 166 166 3741 166 54 1885 3839 166 4924 166 166 166
+4158 166 166 2152 1661 166 166 4327 166 3933 166 5666 166 166 2580 166 3404
+4111 2862 4438 166 166 4072 166 166 3938 2958 4302 166 3851 166 268 166 166
+1975 222 3204 3438 4616 166 4275 3101 2648 3989 5215 166 4229 166 5440 166 5093
+2639 166 166 4439 166 2316 4239 166 166 166 166 166 1817 4486 166 3272 166 166
+4085 2078 2902 166 166 166 4381 1853 3054 166 166 5005 2669 166 2856 2706 166
+166 166 4185 166 1748 166 166 166 5771 166 166 3915 166 166 2205 6122 166 166
+1632 5400 166 2477 4740 166 166 166 1802 166 2472 3953 166 1849 2604 3780 2560
+4786 2566 3576 166 4768 166 1951 251 5068 166 166 166 2619 166 166 166 5432 166
+166 5260 5758 3908 166 4141 166 5777 166 166 166 166 166 3961 5143 166 3889
+3747 3743 166 2818 166 166 166 3867 166 166 3742 4763 2948 5533 166 3966 3555
+3843 3503 6005 166 4687 2790 4479 5828 3769 5688 166 166 166 166 3109 166 166
+166 166 4574 81 166 166 4576 3369 166 166 166 4207 166 5072 2210 166 184 166
+4673 166 166 166 166 166 166 1628 3590 1916 4784 4970 166 1832 166 166 3584
+3384 166 166 2880 1783 166 166 166 166 6115 6121 2157 5428 5859 4861 5635 4331
+5839 4223 313 166 166 6152 2168 166 4112 6089 6012 166 5294 3207 166 166 4884
+166 4655 166 166 166 1743 166 4077 166 4631 166 166 2957 1945 4936 166 166 5389
+166 166 5955 166 166 1639 2207 4129 166 3582 5560 6147 3088 166 166 4529 5259
+3118 166 3106 2853 166 1845 5660 166 3325 3973 2461 2163 166 3083 4190 166 166
+5505 166 166 3226 5507 109 6141 3991 166 4939 166 166 5889 3986 166 3664 4353
+2056 166 5071 166 166 4376 166 1958 2028 166 166 1793 166 5252 3536 166 166
+3525 3580 166 166 166 1782 5174 2011 1826 3352 3231 166 166 4986 2068 2801 166
+2500 166 5061 166 2263 2632 1993 166 2715 4424 166 166 6042 4661 166 5074 5479
+4822 166 166 166 166 5600 5853 166 1907 166 166 166 3808 166 5997 5032 4605 166
+1732 166 166 166 3015 5454 166 166 166 3806 5444 2238 1946 166 166 3221 4922
+166 6092 166 166 4007 166 3425 4282 2571 166 1749 166 166 38 4744 4900 4257 214
+5687 166 2490 2979 2924 166 4714 219 5344 3836 3302 78 1984 2986 2960 166 2869
+3507 3335 4967 2892 2723 4849 5070 166 166 4629 3815 166 4453 4760 166 3224 130
+166 166 166 166 166 3408 2494 2691 166 4325 2932 5165 5573 166 4769 166 5411
+5637 2050 166 166 2305 166 166 4834 24 4693 3554 2491 1738 166 166 166 23 2758
+3072 2564 4800 5537 3545 4133 166 166 166 5982 166 203 166 166 290 185 166 3774
+1929 3379 166 166 166 166 3002 166 3738 166 166 3344 4942 5353 2777 2839 4712
+1830 2664 166 5884 3516 166 5494 4169 2391 3319 166 166 5918 2597 166 4821 2787
+5719 166 166 166 1687 6148 3257 254 166 5180 6153 5964 306 166 6123 166 5208
+166 3163 5938 1736 166 2502 4910 166 166 2549 166 2900 3632 3270 166 2082 5953
+166 107 5750 166 166 166 5527 1751 4168 2950 166 2659 166 4189 1943 2595 166
+4191 166 166 166 166 2998 2296 5221 3617 166 5435 2451 2009 3005 2242 3768 3658
+166 166 166 166 166 2481 2256 166 166 4074 166 3120 166 4409 1759 166 166 1679
+3659 3499 5219 4501 3082 2047 166 166 166 4560 2768 5251 166 166 166 2437 3993
+3215 2447 166 166 166 2993 4963 166 3045 166 166 166 166 166 166 166 5521 166
+166 4868 166 3895 166 6131 3949 3306 3785 166 166 4895 4831 166 1772 166 166
+5928 166 2137 4805 2462 310 2667 3561 166 166 2312 4931 5255 166 166 166 5670
+166 2285 166 4672 5310 166 2103 2174 166 166 166 166 5417 166 4726 4203 166 166
+166 5581 166 5665 166 166 5747 166 166 2509 1973 2749 5463 166 166 4567 5014
+166 3322 3051 166 4090 166 3709 3887 3478 166 166 166 166 3565 3934 166 32 166
+166 166 2239 166 3947 3849 166 2022 166 2169 166 4691 98 166 3804 4155 1640
+4002 166 2138 1739 3730 5970 2274 4873 3119 166 4925 3577 3699 4049 3982 166
+5161 1744 166 166 166 5704 4979 2686 5383 5744 2289 166 166 166 3927 2539 166
+166 166 2585 166 4723 3755 4509 166 4961 2194 2535 166 176 166 4494 166 4171
+166 266 166 3454 5369 166 166 5899 5284 166 3607 3566 5514 166 1843 166 3997
+4599 2743 166 2857 2497 2751 166 166 166 3511 5742 166 166 166 4504 166 166 166
+5082 4401 166 166 5431 166 166 1949 4539 166 166 4852 166 166 3457 166 3433
+4669 166 1692 2454 3258 6159 166 166 166 166 166 2788 4350 3249 3816 4893 166
+4846 166 4993 1708 4138 166 2895 2891 166 1860 166 2480 1927 3853 166 166 166
+5100 166 3143 5159 166 4286 5182 5246 4975 166 2905 166 4917 5102 2044 6016
+5673 2005 5090 166 4634 3333 166 5702 3413 1762 6094 4284 4431 2641 166 4463
+5691 166 166 3442 3473 4192 2046 166 3838 166 3217 3349 166 2243 166 3490 166
+166 166 5922 166 166 166 4885 1798 2884 2750 5004 2741 166 166 5649 166 4410
+166 166 3382 166 166 1913 1703 5532 3770 166 5116 2645 2634 4357 5901 166 166
+5538 166 166 166 6028 166 166 5840 4102 2704 2091 5287 166 4757 2282 166 2650
+3528 64 253 3732 166 166 166 166 166 3465 166 166 166 5848 3110 111 166 166
+3403 2926 6030 3366 1948 4430 5509 3250 3972 2587 3579 166 6048 250 5275 4242
+2615 3112 3558 166 166 2342 166 5157 1917 2733 5647 1934 5675 166 3981 2923
+5213 5326 37 166 5288 3069 166 1923 5755 166 166 166 1888 166 6041 5895 5376
+3727 3901 166 5589 166 166 4609 166 166 166 4706 166 4482 1622 166 171 166 166
+4646 4151 2755 4614 166 2072 5409 4469 1647 4434 4633 1915 166 3615 4808 166
+3388 166 5280 2731 166 166 2417 166 14 166 4533 5126 166 2778 3022 166 166 166
+4830 4764 166 166 166 4982 166 4265 166 2466 5678 147 1883 166 166 166 114 4000
+2427 3597 166 4853 5981 166 2023 2519 166 1937 2221 4676 166 4522 5716 166 2432
+5731 166 6020 6163 4351 2442 4380 166 4390 1882 6139 4246 262 166 1676 5781
+2352 1956 200 166 166 5800 6184 166 2355 149 5962 5524 4238 166 5150 166 5888
+2423 166 5739 3192 4142 166 166 166 3201 161 4460 2459 158 166 166 166 166 2689
+166 166 166 166 1889 166 166 3374 166 70 166 2772 166 2995 166 2384 4989 166
+3299 166 166 166 166 3614 3645 3415 3160 1727 3735 5201 1693 3531 166 166 1776
+3871 166 166 166 166 86 3553 166 166 166 3392 166 166 2232 166 4977 2333 3394
+2875 2027 5736 166 1719 166 4952 2061 2150 5526 166 4637 166 4333 166 166 4733
+4809 3911 166 3460 166 5355 3126 4181 4436 300 166 3841 166 4770 126 5654 166
+166 166 1730 166 166 166 5610 166 6002 2197 3807 6109 166 166 166 166 166 5395
+4004 166 46 166 166 2570 4736 5318 4247 166 166 166 2293 3031 4591 166 245 166
+5510 1616 3117 4163 166 166 4759 3462 4819 4947 166 3128 5946 2278 2969 166 166
+5183 166 166 1729 173 2448 166 230 2971 166 166 5397 166 4093 3348 1866 4280
+166 6067 3794 166 166 166 4729 166 3456 166 2394 166 4953 166 166 2258 4863 166
+166 4060 166 5468 305 166 6134 166 166 2326 166 3453 2167 2845 166 166 166 5597
+166 166 166 166 5462 2809 5994 2899 166 166 166 5153 166 166 1638 166 166 4938
+3795 166 3842 166 166 166 2769 3194 166 4745 5508 5604 3910 166 166 4147 3239
+166 166 3548 3859 2092 166 2705 166 166 3625 4131 166 3513 166 166 2987 4555
+3107 166 166 166 166 5713 4698 3079 166 5342 166 166 2673 2517 2745 1795 166
+166 166 166 166 166 2463 166 166 2445 5425 6138 166 2687 3254 5871 166 2387
+4300 166 166 3529 1996 166 2369 3818 6126 1615 2643 65 4297 166 5324 3311 3852
+166 3868 4199 3978 166 166 166 5466 166 166 244 166 5929 6157 2390 5639 2267
+2073 4610 5774 2521 4556 166 4545 4307 2426 2450 166 5783 4968 6176 4156 166
+166 4126 3549 166 3581 5701 3234 166 4013 1879 166 6104 5874 166 166 3485 4279
+2528 5576 166 3992 166 3980 4934 166 2176 4228 5164 3784 1933 4120 5055 166 166
+5015 166 166 166 2310 1754 166 6087 166 166 4548 5268 2930 166 3656 166 3042
+5229 166 4016 2195 166 166 166 199 1745 3717 166 166 74 2668 252 4124 4657 5223
+166 2186 3628 166 166 166 4222 3114 2841 5103 3171 5135 166 166 2273 166 3899
+5332 5842 3575 2579 2431 2464 2229 3604 4561 2977 2815 166 3916 166 5825 166
+1694 166 4030 166 5841 166 3881 1831 166 5525 3011 166 5535 5217 316 4116 166
+166 2204 166 3136 3650 166 5813 1875 4511 4475 166 1999 166 2277 166 3024 5484
+5546 166 3988 5676 166 2213 2264 5214 166 4940 5974 166 4750 6077 166 1652 3148
+166 166 166 166 2554 166 6167 5257 5300 166 166 166 166 5408 166 166 3402 2141
+166 4663 5633 3312 166 2814 4930 1959 166 166 166 3861 166 166 302 2624 166 166
+166 1629 1724 166 3909 5281 166 2001 4395 5352 4428 2694 4850 166 166 5242 5910
+166 166 166 166 166 3212 166 2045 166 166 166 166 166 166 3017 4960 4456 166
+5616 6093 2151 166 166 166 315 3381 166 166 166 4330 166 6158 4721 6075 166 166
+166 4543 2303 166 166 3301 166 5000 3929 2543 3437 166 166 166 3422 166 5987
+5729 2428 166 4035 5588 3714 3834 5264 5743 166 3305 4886 6107 5156 166 166 166
+166 166 1672 5849 5827 5049 6101 2178 2420 3289 166 166 4274 6017 2257 166 4172
+3451 2367 2382 166 2964 4918 3241 2347 6082 99 2383 166 4454 163 2460 165 304
+1818 5580 166 312 5790 293 5794 5519 5083 3360 5748 166 3750 5034 166 166 166
+1863 3168 166 166 166 5111 166 166 166 166 2183 4510 166 166 3495 4382 4235
+4462 166 4056 5885 17 5028 1614 6038 166 2488 5632 3089 166 1940 66 4039 3999
+235 166 166 3829 3954 166 2365 269 166 166 166 166 166 166 4418 1796 4709 2004
+166 3596 5786 166 2819 4624 3152 2968 2838 166 5575 1767 5603 166 4386 5890 166
+1768 4201 3560 166 166 166 2184 2262 2966 2716 1765 2611 2983 166 4164 4084 142
+5314 166 166 4071 166 2578 2849 3600 166 166 166 166 5401 4814 3431 166 5088
+5084 198 166 3578 3764 166 2097 166 166 5390 4443 166 3166 166 4816 166 166 166
+166 3130 5963 1788 2129 1837 4100 6128 166 4586 5945 4772 166 5741 3151 3247
+5645 4507 5833 3904 6013 2506 3050 4175 1705 3019 166 5942 166 2418 3430 2230
+5745 166 2093 166 166 166 166 4666 3246 192 2010 4003 3533 5851 166 3621 3684
+3066 166 166 166 5073 3856 166 166 2224 166 2637 4270 166 166 5679 166 5792
+5850 166 2589 3060 2196 3476 3150 2025 166 166 166 2657 166 3685 3790 5587 2817
+3692 166 166 166 2359 2260 5896 2158 119 2816 5753 166 2739 5772 166 2919 2147
+1985 4271 4838 4991 166 166 166 5244 166 319 166 166 2779 4732 4994 5424 166
+166 3968 3049 3393 4473 4959 5967 5864 5170 4209 166 4810 4815 4205 2339 5023
+2279 5050 166 5837 132 166 166 166 2247 21 4775 166 166 5286 166 4170 4099 4803
+5767 166 166 166 5811 2240 5699 2499 166 4802 166 5785 166 166 166 3181 3435
+166 3339 166 5669 3865 2249 5002 166 4694 5461 4753 166 3157 166 1960 166 166
+166 2440 166 5818 5534 2439 1717 166 3789 2959 166 2943 166 2576 166 2002 2007
+1819 3256 4402 5311 3832 160 166 166 2803 166 3264 166 5863 166 2017 166 2798
+166 166 166 166 5607 4965 166 166 166 4537 4378 5944 3494 5457 5602 1942 5900
+5780 4411 5147 166 4966 2115 155 2827 1980 5063 166 285 5912 3304 2963 5179
+3220 166 166 166 2190 3708 5476 1944 2366 3893 166 166 166 3759 166 5434 2740
+1707 4244 5426 166 166 166 3155 166 4285 166 166 166 166 5721 166 3833 6001 301
+166 166 2574 186 2724 166 1873 3667 166 5216 166 2935 2100 4987 166 2284 166
+166 2911 3828 4009 166 2065 166 5496 6130 5563 4387 166 3771 3469 2989 2222
+4577 3965 4296 2975 3813 3240 166 4780 4481 3387 2338 166 6183 166 166 166 166
+166 2675 1761 2600 5167 3170 4773 2165 5166 166 2223 4642 166 166 4540 166 166
+166 3897 166 2483 1809 5477 3844 4067 2508 2275 166 166 166 166 166 3497 5458
+166 249 2956 166 4651 166 283 166 166 4955 4062 2315 2304 3261 2361 4791 4389
+1997 166 3455 166 166 166 166 166 166 4746 5695 5296 105 1841 3368 166 166 166
+5228 166 3496 4423 2024 3907 4774 166 166 166 166 166 2294 2193 166 166 166 166
+166 166 166 166 4393 166 166 2127 166 4573 166 5350 166 5016 3372 166 5653 166
+5972 4719 166 166 166 166 166 5370 166 6142 166 166 3691 2828 166 2601 166 2937
+2060 3654 3097 2341 5325 4568 4096 2776 166 2946 166 166 166 5843 1777 5295
+2837 4261 4397 5006 5808 4866 166 1713 5732 2954 166 166 27 166 4308 5629 2652
+2434 4474 166 4928 166 4727 3811 166 166 5234 166 6010 166 4911 166 4570 166
+6000 3450 5304 3919 166 166 4008 3942 166 272 2363 2064 3595 3505 166 166 3957
+1695 2452 4659 166 1792 166 131 5968 166 3731 3905 4115 166 166 2468 166 2727
+166 3526 4724 166 4388 3149 5539 5092 4440 6162 166 166 193 4429 2493 166 166
+3683 166 6029 166 277 166 166 166 5240 2408 166 309 2561 210 166 5200 166 166
+166 1930 5692 2697 166 166 166 3330 5331 3860 166 166 4335 166 50 3605 4289
+1763 166 166 166 166 3521 166 166 166 3668 166 166 166 166 166 3271 1656 166
+166 4782 166 2962 166 5907 166 3245 3375 2944 5933 166 166 5406 5655 3139 5423
+166 4359 5231 2548 166 3831 2858 5488 166 5824 166 166 166 3885 4372 166 166
+4024 166 4811 2970 166 4219 211 166 3471 166 166 166 166 3854 166 3358 2877 166
+166 5205 2804 166 166 166 4452 166 166 166 166 3776 166 166 3075 4208 166 5623
+1974 166 2647 166 3235 166 166 166 5211 166 166 4304 2206 166 4157 2182 166
+1816 2626 166 2893 2248 166 166 166 166 1983 5648 166 194 166 2106 4328 166
+4742 166 166 5572 2329 3314 166 6181 166 166 26 166 6026 166 166 2114 1669 4735
+166 166 4256 166 1861 166 5470 2317 166 4404 2482 166 5305 4415 5986 4949 5412
+166 1728 166 1898 166 166 4909 1989 166 166 166 2836 2051 274 166 2799 166 5865
+1663 4705 5121 2555 166 4316 4287 1880 1825 166 3689 166 1733 5012 166 166 2237
+4471 1682 2910 166 5366 166 166 166 166 4532 166 2802 166 166 166 4057 2471 166
+2889 166 166 4026 5682 3091 166 1977 166 2901 6137 5658 88 2318 1965 166 5914
+166 166 4468 1822 166 6050 5956 2201 166 4644 2918 166 3703 166 166 3524 4220
+2913 4210 166 166 2090 166 1906 1911 166 166 3671 2370 166 2552 166 3763 2259
+1924 166 5940 166 166 166 3185 3821 4069 261 2381 3244 166 166 5715 166 2052
+5905 166 2403 166 3030 2199 166 3550 166 166 1846 166 166 95 166 289 3208 2559
+5195 5091 1654 166 1781 1892 166 4516 2629 166 1700 3067 166 166 166 2080 1680
+166 166 166 5700 166 1820 5491 166 4226 166 166 166 166 4653 166 3508 227 5364
+166 2098 166 299 166 5795 166 166 166 166 3690 4134 5517 4534 5042 4874 5798
+4234 166 166 166 166 3702 166 166 3638 3108 3850 166 166 166 16 166 1775 166
+4022 166 223 4095 166 5127 4266 166 189 166 166 5203 166 1805 3884 3778 166 166
+2146 4818 166 2848 3440 4506 5886 3006 218 166 2377 166 4091 5925 166 4320 166
+2701 3036 166 166 166 4715 166 3801 166 3161 166 2077 166 4254 3032 243 1814
+166 166 166 166 166 166 166 166 1835 166 4394 166 5769 4923 166 2917 166 166
+178 166 166 1723 166 5887 166 4956 2952 166 4665 3925 3443 3123 166 166 166 166
+166 166 5144 166 4288 2074 2192 5442 6043 1746 2016 5995 2203 166 5686 5659
+3193 166 4055 166 166 2233 3571 5809 5984 2323 166 166 1740 89 4356 6053 6106
+3282 4796 166 6116 6056 2353 2829 166 5807 2042 166 166 166 1670 5937 4465 5646
+166 5562 3008 166 2419 3736 166 4132 169 166 166 166 2402 166 166 1968 2398 166
+1684 1827 4551 2679 3875 166 5585 3835 2295 166 1991 1803 2992 166 166 5847
+2649 166 76 5415 166 2269 2397 5387 5337 4422 166 2672 4832 4617 166 166 166
+166 4552 166 4612 1750 166 1931 166 1691 2424 4194 6018 166 166 4458 4856 166
+2089 3814 166 2844 166 3592 166 4867 5128 166 2685 166 166 2616 1972 2617 3943
+4664 166 4999 166 166 145 3635 166 166 4851 166 3483 5039 166 3649 3924 166 166
+166 3105 4260 166 6098 166 3568 267 2456 3653 2096 166 166 166 3512 166 3405
+166 3504 166 166 166 4005 2144 1769 166 5474 1920 5554 215 2443 3351 166 5961
+166 166 166 166 242 2331 166 166 5931 166 166 5862 166 1710 166 166 166 3321
+166 4139 166 166 3515 2732 2510 5544 166 166 2783 166 166 166 4018 4649 5789
+166 166 166 166 166 2726 6074 166 166 166 5684 166 166 3395 166 3100 166 5763
+3757 1992 166 3198 2003 166 166 4675 166 1893 5621 166 2270 166 166 166 5421
+5590 5664 4045 166 3687 4406 2699 1811 167 4036 5384 166 166 4601 1823 4041 239
+1954 166 146 166 166 3077 5152 5814 1649 5681 166 5868 166 166 3792 4860 166
+5335 5110 1718 166 166 166 166 3718 3365 2826 166 166 5021 4783 166 5569 5812
+166 166 1876 166 3260 166 1789 5667 4224 166 166 4385 166 166 2620 166 4162
+2883 2143 5497 166 166 5316 5680 166 166 248 4050 166 6021 166 2898 4618 166
+166 166 166 166 5368 166 5378 1842 1914 3696 3962 166 4345 2581 1773 2109 166
+4371 166 166 3761 5277 5870 3146 166 166 166 5764 127 3058 4059 4718 166 5097
+5040 5351 3205 166 166 4996 2991 2014 166 5846 2558 2688 5595 4027 3347 2125
+5696 5608 166 166 3228 3745 5775 166 1757 4647 166 5977 3020 166 240 2565 166
+4459 166 3367 166 166 166 3104 166 166 166 166 166 166 259 5486 2846 166 166
+166 4778 2713 166 3955 5683 2682 2914 5898 166 166 166 4400 317 166 5185 3021
+5983 4332 3891 166 3095 5003 166 166 166 5367 166 279 1784 4019 2736 4905 2651
+5346 166 4841 166 5606 166 166 2806 166 5239 166 166 3237 5490 166 225 166 166
+2254 166 2742 4587 22 166 166 166 5555 166 108 2927 2218 166 2120 166 5452 4087
+4369 166 166 166 166 166 4583 4338 6035 2840 4365 3624 11 1770 166 4630 166
+3216 166 166 166 4638 4699 3535 2536 4627 166 166 5760 1935 166 166 5210 166
+2219 2484 4597 5193 4799 3706 166 166 166 166 3337 3113 5951 4294 166 4040 3200
+4217 5861 2767 3530 4499 2775 4121 134 5939 5880 5908 3869 166 166 3316 6095
+2441 3288 166 3751 4794 166 166 5803 6169 2356 6182 6135 6127 166 3018 166 1674
+166 166 4097 166 5923 287 5965 5129 166 4078 166 166 6114 6015 5990 3573 166
+4146 2681 90 6055 4864 166 166 6119 3284 6054 5456 5113 6125 166 6057 166 3292
+166 166 166 166 166 6185 5105 1760 166 166 166 2720 166 2695 5448 166 1936 166
+1807 3406 166 166 2161 1642 166 5030 166 2036 5451 3427 166 166 166 166 3797
+166 1627 166 4515 166 166 166 4241 166 166 166 2771 166 31 5197 2638 3035 166
+166 3914 166 166 4546 166 166 166 4253 3500 166 166 2526 166 2698 166 3726 2744
+137 166 166 2676 166 5594 166 166 166 4842 166 63 2888 3585 4798 166 5011 166
+5634 5464 166 166 5620 3894 4070 166 2730 166 166 1810 2503 5957 1721 6066 5188
+166 166 1890 4505 1771 5455 166 3132 3984 166 166 2811 1962 166 166 4872 106
+3898 3267 166 2085 166 4950 6040 4525 6044 5866 3613 2907 4615 2135 258 166
+1681 1941 4888 166 4859 6178 6174 4858 5209 1912 3340 166 4640 5706 166 2763
+3153 3951 166 5542 5596 5819 5330 5048 4037 166 6033 4625 3326 2013 5283 136
+3373 2154 166 166 166 4421 166 5438 2627 2266 2320 166 2588 4790 4290 166 4767
+5829 2925 5916 2133 166 }
diff --git a/extra/poker/authors.txt b/extra/poker/authors.txt
new file mode 100644 (file)
index 0000000..fbbb745
--- /dev/null
@@ -0,0 +1 @@
+Aaron Schaefer
\ No newline at end of file
diff --git a/extra/poker/poker-docs.factor b/extra/poker/poker-docs.factor
new file mode 100644 (file)
index 0000000..09019a2
--- /dev/null
@@ -0,0 +1,30 @@
+USING: help.markup help.syntax strings ;
+IN: poker
+
+HELP: <hand>
+{ $values { "str" string } { "hand" "a new hand" } }
+{ $description "Creates a new poker hand containing the cards specified in " { $snippet "str" } "." }
+{ $examples
+    { $example "USING: kernel math.order poker prettyprint ;"
+        "\"AC KC QC JC TC\" \"7C 6D 5H 4S 2C\" [ <hand> ] bi@ <=> ." "+lt+" }
+    { $example "USING: kernel poker prettyprint ;"
+        "\"TC 9C 8C 7C 6C\" \"TH 9H 8H 7H 6H\" [ <hand> ] bi@ = ." "t" }
+}
+{ $notes "Cards may be specified in any order. Hands are directly comparable to each other on the basis of their computed value. Two hands are considered equal when they would tie in a game (despite being composed of different cards)." } ;
+
+HELP: >cards
+{ $values { "hand" "a hand" } { "str" string } }
+{ $description "Outputs a string representation of a hand's cards." }
+{ $examples
+    { $example "USING: poker prettyprint ;"
+        "\"AC KC QC JC TC\" <hand> >cards ." "\"AC KC QC JC TC\"" }
+} ;
+
+HELP: >value
+{ $values { "hand" "a hand" } { "str" string } }
+{ $description "Outputs a string representation of a hand's value." }
+{ $examples
+    { $example "USING: poker prettyprint ;"
+        "\"AC KC QC JC TC\" <hand> >value ." "\"Straight Flush\"" }
+}
+{ $notes "This should not be used as a basis for hand comparison." } ;
diff --git a/extra/poker/poker-tests.factor b/extra/poker/poker-tests.factor
new file mode 100644 (file)
index 0000000..ad371a6
--- /dev/null
@@ -0,0 +1,28 @@
+USING: accessors poker poker.private tools.test math.order kernel ;
+IN: poker.tests
+
+[ 134236965 ] [ "KD" >ckf ] unit-test
+[ 529159 ] [ "5s" >ckf ] unit-test
+[ 33589533 ] [ "jc" >ckf ] unit-test
+
+[ 7462 ] [ "7C 5D 4H 3S 2C" <hand> value>> ] unit-test
+[ 1601 ] [ "KD QS JC TH 9S" <hand> value>> ] unit-test
+[ 11 ] [ "AC AD AH AS KC" <hand> value>> ] unit-test
+[ 9 ] [ "6C 5C 4C 3C 2C" <hand> value>> ] unit-test
+[ 1 ] [ "AC KC QC JC TC" <hand> value>> ] unit-test
+
+[ "High Card" ] [ "7C 5D 4H 3S 2C" <hand> >value ] unit-test
+[ "Straight" ] [ "KD QS JC TH 9S" <hand> >value ] unit-test
+[ "Four of a Kind" ] [ "AC AD AH AS KC" <hand> >value ] unit-test
+[ "Straight Flush" ] [ "6C 5C 4C 3C 2C" <hand> >value ] unit-test
+
+[ "6C 5C 4C 3C 2C" ] [ "6C 5C 4C 3C 2C" <hand> >cards ] unit-test
+
+[ +gt+ ] [ "7C 5D 4H 3S 2C" "KD QS JC TH 9S" [ <hand> ] bi@ <=> ] unit-test
+[ +lt+ ] [ "AC AD AH AS KC" "KD QS JC TH 9S" [ <hand> ] bi@ <=> ] unit-test
+[ +eq+ ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ <hand> ] bi@ <=> ] unit-test
+
+[ t ] [ "7C 5D 4H 3S 2C" "2C 3S 4H 5D 7C" [ <hand> ] bi@ = ] unit-test
+
+[ t ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ <hand> ] bi@ = ] unit-test
+[ f ] [ "7C 5D 4H 3S 2C" "7D 5D 4D 3C 2S" [ <hand> ] bi@ eq? ] unit-test
diff --git a/extra/poker/poker.factor b/extra/poker/poker.factor
new file mode 100644 (file)
index 0000000..2a7fe73
--- /dev/null
@@ -0,0 +1,191 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors ascii binary-search combinators kernel locals math
+    math.bitwise math.order poker.arrays sequences splitting ;
+IN: poker
+
+! The algorithm used is based on Cactus Kev's Poker Hand Evaluator with
+! the Senzee Perfect Hash Optimization:
+!     http://www.suffecool.net/poker/evaluator.html
+!     http://www.senzee5.com/2006/06/some-perfect-hash.html
+
+<PRIVATE
+
+! Bitfield Format for Card Values:
+
+!     +-------------------------------------+
+!     | xxxbbbbb bbbbbbbb ssssrrrr xxpppppp |
+!     +-------------------------------------+
+!       xxxAKQJT 98765432 CDHSrrrr xxpppppp
+!     +-------------------------------------+
+!     | 00001000 00000000 01001011 00100101 |  King of Diamonds
+!     | 00000000 00001000 00010011 00000111 |  Five of Spades
+!     | 00000010 00000000 10001001 00011101 |  Jack of Clubs
+
+! p = prime number value of rank (deuce = 2, trey = 3, four = 5, ..., ace = 41)
+! r = rank of card (deuce = 0, trey = 1, four = 2, ..., ace = 12)
+! s = bit turned on depending on suit of card
+! b = bit turned on depending on rank of card
+! x = bit turned off, not used
+
+CONSTANT: CLUB     8
+CONSTANT: DIAMOND  4
+CONSTANT: HEART    2
+CONSTANT: SPADE    1
+
+CONSTANT: DEUCE  0
+CONSTANT: TREY   1
+CONSTANT: FOUR   2
+CONSTANT: FIVE   3
+CONSTANT: SIX    4
+CONSTANT: SEVEN  5
+CONSTANT: EIGHT  6
+CONSTANT: NINE   7
+CONSTANT: TEN    8
+CONSTANT: JACK   9
+CONSTANT: QUEEN  10
+CONSTANT: KING   11
+CONSTANT: ACE    12
+
+CONSTANT: STRAIGHT_FLUSH   1
+CONSTANT: FOUR_OF_A_KIND   2
+CONSTANT: FULL_HOUSE       3
+CONSTANT: FLUSH            4
+CONSTANT: STRAIGHT         5
+CONSTANT: THREE_OF_A_KIND  6
+CONSTANT: TWO_PAIR         7
+CONSTANT: ONE_PAIR         8
+CONSTANT: HIGH_CARD        9
+
+CONSTANT: RANK_STR { "2" "3" "4" "5" "6" "7" "8" "9" "T" "J" "Q" "K" "A" }
+
+CONSTANT: VALUE_STR { "" "Straight Flush" "Four of a Kind" "Full House" "Flush"
+    "Straight" "Three of a Kind" "Two Pair" "One Pair" "High Card" }
+
+: card-rank-prime ( rank -- n )
+    RANK_STR index { 2 3 5 7 11 13 17 19 23 29 31 37 41 } nth ;
+
+: card-rank ( rank -- n )
+    {
+        { "2" [ DEUCE ] }
+        { "3" [ TREY  ] }
+        { "4" [ FOUR  ] }
+        { "5" [ FIVE  ] }
+        { "6" [ SIX   ] }
+        { "7" [ SEVEN ] }
+        { "8" [ EIGHT ] }
+        { "9" [ NINE  ] }
+        { "T" [ TEN   ] }
+        { "J" [ JACK  ] }
+        { "Q" [ QUEEN ] }
+        { "K" [ KING  ] }
+        { "A" [ ACE   ] }
+    } case ;
+
+: card-suit ( suit -- n )
+    {
+        { "C" [ CLUB    ] }
+        { "D" [ DIAMOND ] }
+        { "H" [ HEART   ] }
+        { "S" [ SPADE   ] }
+    } case ;
+
+: card-rank-bit ( rank -- n )
+    RANK_STR index 1 swap shift ;
+
+: card-bitfield ( rank rank suit rank -- n )
+    {
+        { card-rank-bit 16 }
+        { card-suit 12 }
+        { card-rank 8 }
+        { card-rank-prime 0 }
+    } bitfield ;
+
+:: (>ckf) ( rank suit -- n )
+    rank rank suit rank card-bitfield ;
+
+: >ckf ( str -- n )
+    #! Cactus Kev Format
+    >upper 1 cut (>ckf) ;
+
+: flush? ( cards -- ? )
+    HEX: F000 [ bitand ] reduce 0 = not ;
+
+: rank-bits ( cards -- q )
+    0 [ bitor ] reduce -16 shift ;
+
+: lookup ( cards table -- value )
+    [ rank-bits ] dip nth ;
+
+: unique5? ( cards -- ? )
+    unique5-table lookup 0 > ;
+
+: map-product ( seq quot -- n )
+    [ 1 ] 2dip [ dip * ] curry [ swap ] prepose each ; inline
+
+: prime-bits ( cards -- q )
+    [ HEX: FF bitand ] map-product ;
+
+: perfect-hash-find ( q -- value )
+    #! magic to convert a hand's unique identifying bits to the
+    #! proper index for fast lookup in a table of hand values
+    HEX: E91AAA35 +
+    dup -16 shift bitxor
+    dup   8 shift w+
+    dup  -4 shift bitxor
+    [ -8 shift HEX: 1FF bitand adjustments-table nth ]
+    [ dup 2 shift w+ -19 shift ] bi
+    bitxor values-table nth ;
+
+: hand-value ( cards -- value )
+    {
+        { [ dup flush?   ] [ flushes-table lookup ] }
+        { [ dup unique5? ] [ unique5-table lookup ] }
+        [ prime-bits perfect-hash-find ]
+    } cond ;
+
+: >card-rank ( card -- str )
+    -8 shift HEX: F bitand RANK_STR nth ;
+
+: >card-suit ( card -- str )
+    {
+        { [ dup 15 bit? ] [ drop "C" ] }
+        { [ dup 14 bit? ] [ drop "D" ] }
+        { [ dup 13 bit? ] [ drop "H" ] }
+        [ drop "S" ]
+    } cond ;
+
+: hand-rank ( hand -- rank )
+    value>> {
+        { [ dup 6185 > ] [ drop HIGH_CARD ] }        ! 1277 high card
+        { [ dup 3325 > ] [ drop ONE_PAIR ] }         ! 2860 one pair
+        { [ dup 2467 > ] [ drop TWO_PAIR ] }         !  858 two pair
+        { [ dup 1609 > ] [ drop THREE_OF_A_KIND ] }  !  858 three-kind
+        { [ dup 1599 > ] [ drop STRAIGHT ] }         !   10 straights
+        { [ dup 322 > ]  [ drop FLUSH ] }            ! 1277 flushes
+        { [ dup 166 > ]  [ drop FULL_HOUSE ] }       !  156 full house
+        { [ dup 10 > ]   [ drop FOUR_OF_A_KIND ] }   !  156 four-kind
+        [ drop STRAIGHT_FLUSH ]                      !   10 straight-flushes
+    } cond ;
+
+PRIVATE>
+
+TUPLE: hand
+    { cards sequence }
+    { value integer } ;
+
+M: hand <=> [ value>> ] compare ;
+M: hand equal?
+    over hand? [ [ value>> ] bi@ = ] [ 2drop f ] if ;
+
+: <hand> ( str -- hand )
+    " " split [ >ckf ] map
+    dup hand-value hand boa ;
+
+: >cards ( hand -- str )
+    cards>> [
+        [ >card-rank ] [ >card-suit ] bi append
+    ] map " " join ;
+
+: >value ( hand -- str )
+    hand-rank VALUE_STR nth ;
diff --git a/extra/poker/summary.txt b/extra/poker/summary.txt
new file mode 100644 (file)
index 0000000..c8efe85
--- /dev/null
@@ -0,0 +1 @@
+5-card poker hand evaluator
index 8d2461a510972947306a36688820cddb34c25124..1cab2756192b690b3ded1aa9fb4a207714873760 100644 (file)
@@ -4,3 +4,4 @@ IN: project-euler.001.tests
 [ 233168 ] [ euler001 ] unit-test
 [ 233168 ] [ euler001a ] unit-test
 [ 233168 ] [ euler001b ] unit-test
+[ 233168 ] [ euler001c ] unit-test
index de4345db689e8f3dfc5b5b395c007a46c20f5042..20e08242c5e3a0f00091f7e6a5d6e36a0cd5a20a 100644 (file)
@@ -1,6 +1,6 @@
-! Copyright (c) 2007 Aaron Schaefer.
+! Copyright (c) 2007, 2008 Aaron Schaefer, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math math.ranges sequences project-euler.common ;
+USING: kernel math math.functions math.ranges sequences project-euler.common ;
 IN: project-euler.001
 
 ! http://projecteuler.net/index.php?section=problems&id=1
@@ -51,4 +51,11 @@ PRIVATE>
 ! [ euler001b ] 100 ave-time
 ! 0 ms run / 0 ms GC ave time - 100 trials
 
+
+: euler001c ( -- answer )
+    1000 [ { 3 5 } [ divisor? ] with any? ] filter sum ;
+
+! [ euler001c ] 100 ave-time
+! 0 ms ave run time - 0.06 SD (100 trials)
+
 SOLUTION: euler001
index ff62b4e18151485d8d263f498063dfb35de497f3..fe09914d9f2edc125dd065df911e0383b825eab2 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (c) 2007 Aaron Schaefer, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: hashtables kernel math math.ranges project-euler.common sequences
-    sorting sets ;
+USING: hashtables kernel math math.functions math.ranges project-euler.common
+    sequences sorting sets ;
 IN: project-euler.004
 
 ! http://projecteuler.net/index.php?section=problems&id=4
@@ -21,7 +21,7 @@ IN: project-euler.004
 <PRIVATE
 
 : source-004 ( -- seq )
-    100 999 [a,b] [ 10 mod 0 = not ] filter ;
+    100 999 [a,b] [ 10 divisor? not ] filter ;
 
 : max-palindrome ( seq -- palindrome )
     natural-sort [ palindrome? ] find-last nip ;
index f9208e11b3a7fb3a613ceca976a9efe018cb3901..1827d0fa069709428ef0a2ebd0e75e0a97aee388 100644 (file)
@@ -17,9 +17,6 @@ IN: project-euler.007
 ! SOLUTION
 ! --------
 
-: nth-prime ( n -- n )
-    1- lprimes lnth ;
-
 : euler007 ( -- answer )
     10001 nth-prime ;
 
index a9a8dbce3f16fd7682dc46718dc6ace7b19e0a30..b0305d5c3941daeb3154244dc6677e7e34068e90 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (c) 2007 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: combinators.short-circuit kernel make math math.ranges
-sequences project-euler.common ;
+USING: combinators.short-circuit kernel make math math.functions math.ranges
+    sequences project-euler.common ;
 IN: project-euler.014
 
 ! http://projecteuler.net/index.php?section=problems&id=14
@@ -59,7 +59,7 @@ PRIVATE>
 <PRIVATE
 
 : worth-calculating? ( n -- ? )
-    1- 3 { [ mod 0 = ] [ / even? ] } 2&& ;
+    1- 3 { [ divisor? ] [ / even? ] } 2&& ;
 
 PRIVATE>
 
index c7c3fea5da7d52e6e100776d2f03e131e1202e98..780015ab77b8b6e90a96559036c2d69b0c4a20f8 100644 (file)
@@ -33,7 +33,7 @@ IN: project-euler.033
     10 99 [a,b] dup cartesian-product [ first2 < ] filter ;
 
 : safe? ( ax xb -- ? )
-    [ 10 /mod ] bi@ -roll = rot zero? not and nip ;
+    [ 10 /mod ] bi@ [ = ] dip zero? not and nip ;
 
 : ax/xb ( ax xb -- z/f )
     2dup safe? [ [ 10 /mod ] bi@ 2nip / ] [ 2drop f ] if ;
index 7edcd14364724815a3fbd478b717082819894f9d..75241499e11fc90387fd3944d4ec2c3b68f33fd4 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (c) 2008 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: combinators.short-circuit kernel math math.combinatorics math.parser
-    math.ranges project-euler.common sequences sets sorting ;
+USING: combinators.short-circuit kernel math math.functions math.combinatorics
+    math.parser math.ranges project-euler.common sequences sets sorting ;
 IN: project-euler.043
 
 ! http://projecteuler.net/index.php?section=problems&id=43
@@ -36,7 +36,7 @@ IN: project-euler.043
 <PRIVATE
 
 : subseq-divisible? ( n index seq -- ? )
-    [ 1- dup 3 + ] dip subseq 10 digits>integer swap mod zero? ;
+    [ 1- dup 3 + ] dip subseq 10 digits>integer swap divisor? ;
 
 : interesting? ( seq -- ? )
     {
diff --git a/extra/project-euler/049/049-tests.factor b/extra/project-euler/049/049-tests.factor
new file mode 100644 (file)
index 0000000..679647a
--- /dev/null
@@ -0,0 +1,4 @@
+USING: project-euler.049 tools.test ;
+IN: project-euler.049.tests
+
+[ 296962999629 ] [ euler049 ] unit-test
diff --git a/extra/project-euler/049/049.factor b/extra/project-euler/049/049.factor
new file mode 100644 (file)
index 0000000..15dd7ed
--- /dev/null
@@ -0,0 +1,74 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays byte-arrays fry hints kernel math math.combinatorics
+    math.functions math.parser math.primes project-euler.common sequences sets ;
+IN: project-euler.049
+
+! http://projecteuler.net/index.php?section=problems&id=49
+
+! DESCRIPTION
+! -----------
+
+! The arithmetic sequence, 1487, 4817, 8147, in which each of the terms
+! increases by 3330, is unusual in two ways: (i) each of the three terms are
+! prime, and, (ii) each of the 4-digit numbers are permutations of one another.
+
+! There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes,
+! exhibiting this property, but there is one other 4-digit increasing sequence.
+
+! What 12-digit number do you form by concatenating the three terms in this
+! sequence?
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: count-digits ( n -- byte-array )
+    10 <byte-array> [
+        '[ 10 /mod _ [ 1+ ] change-nth dup 0 > ] loop drop
+    ] keep ;
+
+HINTS: count-digits fixnum ;
+
+: permutations? ( n m -- ? )
+    [ count-digits ] bi@ = ;
+
+: collect-permutations ( seq -- seq )
+    [ V{ } clone ] [ dup ] bi* [
+        dupd '[ _ permutations? ] filter
+        [ diff ] keep pick push
+    ] each drop ;
+
+: potential-sequences ( -- seq )
+    1000 9999 primes-between
+    collect-permutations [ length 3 >= ] filter ;
+
+: arithmetic-terms ( m n -- seq )
+    2dup [ swap - ] keep + 3array ;
+
+: (find-unusual-terms) ( n seq -- seq/f )
+    [ [ arithmetic-terms ] with map ] keep
+    '[ _ [ peek ] dip member? ] find nip ;
+
+: find-unusual-terms ( seq -- seq/? )
+    unclip-slice over (find-unusual-terms) [
+        nip
+    ] [
+        dup length 3 >= [ find-unusual-terms ] [ drop f ] if
+    ] if* ;
+
+: 4digit-concat ( seq -- str )
+    0 [ [ 10000 * ] dip + ] reduce ;
+
+PRIVATE>
+
+: euler049 ( -- answer )
+    potential-sequences [ find-unusual-terms ] map sift
+    [ { 1487 4817 8147 } = not ] find nip 4digit-concat ;
+
+! [ euler049 ] 100 ave-time
+! 206 ms ave run time - 10.25 SD (100 trials)
+
+SOLUTION: euler049
index 1b3b9ba1f11abb108413db3b5f5705d91f8d153a..c25b1adcc073c3c7e2cdbd100af456307bc58bc9 100644 (file)
@@ -1,8 +1,7 @@
 ! Copyright (c) 2008 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: combinators.short-circuit kernel math
-    project-euler.common sequences sorting
-    grouping ;
+USING: combinators.short-circuit kernel math math.functions
+    project-euler.common sequences sorting grouping ;
 IN: project-euler.052
 
 ! http://projecteuler.net/index.php?section=problems&id=52
@@ -31,7 +30,7 @@ IN: project-euler.052
     [ number>digits natural-sort ] map all-equal? ;
 
 : candidate? ( n -- ? )
-    { [ odd? ] [ 3 mod 0 = ] } 1&& ;
+    { [ odd? ] [ 3 divisor? ] } 1&& ;
 
 : next-all-same ( x n -- n )
     dup candidate? [
diff --git a/extra/project-euler/054/054-tests.factor b/extra/project-euler/054/054-tests.factor
new file mode 100644 (file)
index 0000000..31e915c
--- /dev/null
@@ -0,0 +1,4 @@
+USING: project-euler.054 tools.test ;
+IN: project-euler.054.tests
+
+[ 376 ] [ euler054 ] unit-test
diff --git a/extra/project-euler/054/054.factor b/extra/project-euler/054/054.factor
new file mode 100644 (file)
index 0000000..5cf4273
--- /dev/null
@@ -0,0 +1,84 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays io.encodings.ascii io.files kernel math.order poker
+    project-euler.common sequences ;
+IN: project-euler.054
+
+! http://projecteuler.net/index.php?section=problems&id=54
+
+! DESCRIPTION
+! -----------
+
+! In the card game poker, a hand consists of five cards and are ranked, from
+! lowest to highest, in the following way:
+
+!     * High Card: Highest value card.
+!     * One Pair: Two cards of the same value.
+!     * Two Pairs: Two different pairs.
+!     * Three of a Kind: Three cards of the same value.
+!     * Straight: All cards are consecutive values.
+!     * Flush: All cards of the same suit.
+!     * Full House: Three of a kind and a pair.
+!     * Four of a Kind: Four cards of the same value.
+!     * Straight Flush: All cards are consecutive values of same suit.
+!     * Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
+
+! The cards are valued in the order:
+!     2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
+
+! If two players have the same ranked hands then the rank made up of the
+! highest value wins; for example, a pair of eights beats a pair of fives (see
+! example 1 below). But if two ranks tie, for example, both players have a pair
+! of queens, then highest cards in each hand are compared (see example 4
+! below); if the highest cards tie then the next highest cards are compared,
+! and so on.
+
+! Consider the following five hands dealt to two players:
+
+!     Hand   Player 1            Player 2              Winner
+!     ---------------------------------------------------------
+!     1      5H 5C 6S 7S KD      2C 3S 8S 8D TD
+!            Pair of Fives       Pair of Eights        Player 2
+
+!     2      5D 8C 9S JS AC      2C 5C 7D 8S QH
+!            Highest card Ace    Highest card Queen    Player 1
+
+!     3      2D 9C AS AH AC      3D 6D 7D TD QD
+!            Three Aces          Flush with Diamonds   Player 2
+
+!     4      4D 6S 9H QH QC      3D 6D 7H QD QS
+!            Pair of Queens      Pair of Queens
+!            Highest card Nine   Highest card Seven    Player 1
+
+!     5      2H 2D 4C 4D 4S      3C 3D 3S 9S 9D
+!            Full House          Full House
+!            With Three Fours    With Three Threes     Player 1
+
+! The file, poker.txt, contains one-thousand random hands dealt to two players.
+! Each line of the file contains ten cards (separated by a single space): the
+! first five are Player 1's cards and the last five are Player 2's cards. You
+! can assume that all hands are valid (no invalid characters or repeated
+! cards), each player's hand is in no specific order, and in each hand there is
+! a clear winner.
+
+! How many hands does Player 1 win?
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: source-054 ( -- seq )
+    "resource:extra/project-euler/054/poker.txt" ascii file-lines
+    [ [ 14 head-slice ] [ 14 tail-slice* ] bi 2array ] map ;
+
+PRIVATE>
+
+: euler054 ( -- answer )
+    source-054 [ [ <hand> ] map first2 before? ] count ;
+
+! [ euler054 ] 100 ave-time
+! 34 ms ave run time - 2.65 SD (100 trials)
+
+SOLUTION: euler054
diff --git a/extra/project-euler/054/poker.txt b/extra/project-euler/054/poker.txt
new file mode 100644 (file)
index 0000000..231e249
--- /dev/null
@@ -0,0 +1,1000 @@
+8C TS KC 9H 4S 7D 2S 5D 3S AC\r
+5C AD 5D AC 9C 7C 5H 8D TD KS\r
+3H 7H 6S KC JS QH TD JC 2D 8S\r
+TH 8H 5C QS TC 9H 4D JC KS JS\r
+7C 5H KC QH JD AS KH 4C AD 4S\r
+5H KS 9C 7D 9H 8D 3S 5D 5C AH\r
+6H 4H 5C 3H 2H 3S QH 5S 6S AS\r
+TD 8C 4H 7C TC KC 4C 3H 7S KS\r
+7C 9C 6D KD 3H 4C QS QC AC KH\r
+JC 6S 5H 2H 2D KD 9D 7C AS JS\r
+AD QH TH 9D 8H TS 6D 3S AS AC\r
+2H 4S 5C 5S TC KC JD 6C TS 3C\r
+QD AS 6H JS 2C 3D 9H KC 4H 8S\r
+KD 8S 9S 7C 2S 3S 6D 6S 4H KC\r
+3C 8C 2D 7D 4D 9S 4S QH 4H JD\r
+8C KC 7S TC 2D TS 8H QD AC 5C\r
+3D KH QD 6C 6S AD AS 8H 2H QS\r
+6S 8D 4C 8S 6C QH TC 6D 7D 9D\r
+2S 8D 8C 4C TS 9S 9D 9C AC 3D\r
+3C QS 2S 4H JH 3D 2D TD 8S 9H\r
+5H QS 8S 6D 3C 8C JD AS 7H 7D\r
+6H TD 9D AS JH 6C QC 9S KD JC\r
+AH 8S QS 4D TH AC TS 3C 3D 5C\r
+5S 4D JS 3D 8H 6C TS 3S AD 8C\r
+6D 7C 5D 5H 3S 5C JC 2H 5S 3D\r
+5H 6H 2S KS 3D 5D JD 7H JS 8H\r
+KH 4H AS JS QS QC TC 6D 7C KS\r
+3D QS TS 2H JS 4D AS 9S JC KD\r
+QD 5H 4D 5D KH 7H 3D JS KD 4H\r
+2C 9H 6H 5C 9D 6C JC 2D TH 9S\r
+7D 6D AS QD JH 4D JS 7C QS 5C\r
+3H KH QD AD 8C 8H 3S TH 9D 5S\r
+AH 9S 4D 9D 8S 4H JS 3C TC 8D\r
+2C KS 5H QD 3S TS 9H AH AD 8S\r
+5C 7H 5D KD 9H 4D 3D 2D KS AD\r
+KS KC 9S 6D 2C QH 9D 9H TS TC\r
+9C 6H 5D QH 4D AD 6D QC JS KH\r
+9S 3H 9D JD 5C 4D 9H AS TC QH\r
+2C 6D JC 9C 3C AD 9S KH 9D 7D\r
+KC 9C 7C JC JS KD 3H AS 3C 7D\r
+QD KH QS 2C 3S 8S 8H 9H 9C JC\r
+QH 8D 3C KC 4C 4H 6D AD 9H 9D\r
+3S KS QS 7H KH 7D 5H 5D JD AD\r
+2H 2C 6H TH TC 7D 8D 4H 8C AS\r
+4S 2H AC QC 3S 6D TH 4D 4C KH\r
+4D TC KS AS 7C 3C 6D 2D 9H 6C\r
+8C TD 5D QS 2C 7H 4C 9C 3H 9H\r
+5H JH TS 7S TD 6H AD QD 8H 8S\r
+5S AD 9C 8C 7C 8D 5H 9D 8S 2S\r
+4H KH KS 9S 2S KC 5S AD 4S 7D\r
+QS 9C QD 6H JS 5D AC 8D 2S AS\r
+KH AC JC 3S 9D 9S 3C 9C 5S JS\r
+AD 3C 3D KS 3S 5C 9C 8C TS 4S\r
+JH 8D 5D 6H KD QS QD 3D 6C KC\r
+8S JD 6C 3S 8C TC QC 3C QH JS\r
+KC JC 8H 2S 9H 9C JH 8S 8C 9S\r
+8S 2H QH 4D QC 9D KC AS TH 3C\r
+8S 6H TH 7C 2H 6S 3C 3H AS 7S\r
+QH 5S JS 4H 5H TS 8H AH AC JC\r
+9D 8H 2S 4S TC JC 3C 7H 3H 5C\r
+3D AD 3C 3S 4C QC AS 5D TH 8C\r
+6S 9D 4C JS KH AH TS JD 8H AD\r
+4C 6S 9D 7S AC 4D 3D 3S TC JD\r
+AD 7H 6H 4H JH KC TD TS 7D 6S\r
+8H JH TC 3S 8D 8C 9S 2C 5C 4D\r
+2C 9D KC QH TH QS JC 9C 4H TS\r
+QS 3C QD 8H KH 4H 8D TD 8S AC\r
+7C 3C TH 5S 8H 8C 9C JD TC KD\r
+QC TC JD TS 8C 3H 6H KD 7C TD\r
+JH QS KS 9C 6D 6S AS 9H KH 6H\r
+2H 4D AH 2D JH 6H TD 5D 4H JD\r
+KD 8C 9S JH QD JS 2C QS 5C 7C\r
+4S TC 7H 8D 2S 6H 7S 9C 7C KC\r
+8C 5D 7H 4S TD QC 8S JS 4H KS\r
+AD 8S JH 6D TD KD 7C 6C 2D 7D\r
+JC 6H 6S JS 4H QH 9H AH 4C 3C\r
+6H 5H AS 7C 7S 3D KH KC 5D 5C\r
+JC 3D TD AS 4D 6D 6S QH JD KS\r
+8C 7S 8S QH 2S JD 5C 7H AH QD\r
+8S 3C 6H 6C 2C 8D TD 7D 4C 4D\r
+5D QH KH 7C 2S 7H JS 6D QC QD\r
+AD 6C 6S 7D TH 6H 2H 8H KH 4H\r
+KS JS KD 5D 2D KH 7D 9C 8C 3D\r
+9C 6D QD 3C KS 3S 7S AH JD 2D\r
+AH QH AS JC 8S 8H 4C KC TH 7D\r
+JC 5H TD 7C 5D KD 4C AD 8H JS\r
+KC 2H AC AH 7D JH KH 5D 7S 6D\r
+9S 5S 9C 6H 8S TD JD 9H 6C AC\r
+7D 8S 6D TS KD 7H AC 5S 7C 5D\r
+AH QC JC 4C TC 8C 2H TS 2C 7D\r
+KD KC 6S 3D 7D 2S 8S 3H 5S 5C\r
+8S 5D 8H 4C 6H KC 3H 7C 5S KD\r
+JH 8C 3D 3C 6C KC TD 7H 7C 4C\r
+JC KC 6H TS QS TD KS 8H 8C 9S\r
+6C 5S 9C QH 7D AH KS KC 9S 2C\r
+4D 4S 8H TD 9C 3S 7D 9D AS TH\r
+6S 7D 3C 6H 5D KD 2C 5C 9D 9C\r
+2H KC 3D AD 3H QD QS 8D JC 4S\r
+8C 3H 9C 7C AD 5D JC 9D JS AS\r
+5D 9H 5C 7H 6S 6C QC JC QD 9S\r
+JC QS JH 2C 6S 9C QC 3D 4S TC\r
+4H 5S 8D 3D 4D 2S KC 2H JS 2C\r
+TD 3S TH KD 4D 7H JH JS KS AC\r
+7S 8C 9S 2D 8S 7D 5C AD 9D AS\r
+8C 7H 2S 6C TH 3H 4C 3S 8H AC\r
+KD 5H JC 8H JD 2D 4H TD JH 5C\r
+3D AS QH KS 7H JD 8S 5S 6D 5H\r
+9S 6S TC QS JC 5C 5D 9C TH 8C\r
+5H 3S JH 9H 2S 2C 6S 7S AS KS\r
+8C QD JC QS TC QC 4H AC KH 6C\r
+TC 5H 7D JH 4H 2H 8D JC KS 4D\r
+5S 9C KH KD 9H 5C TS 3D 7D 2D\r
+5H AS TC 4D 8C 2C TS 9D 3H 8D\r
+6H 8D 2D 9H JD 6C 4S 5H 5S 6D\r
+AD 9C JC 7D 6H 9S 6D JS 9H 3C\r
+AD JH TC QS 4C 5D 9S 7C 9C AH\r
+KD 6H 2H TH 8S QD KS 9D 9H AS\r
+4H 8H 8D 5H 6C AH 5S AS AD 8S\r
+QS 5D 4S 2H TD KS 5H AC 3H JC\r
+9C 7D QD KD AC 6D 5H QH 6H 5S\r
+KC AH QH 2H 7D QS 3H KS 7S JD\r
+6C 8S 3H 6D KS QD 5D 5C 8H TC\r
+9H 4D 4S 6S 9D KH QC 4H 6C JD\r
+TD 2D QH 4S 6H JH KD 3C QD 8C\r
+4S 6H 7C QD 9D AS AH 6S AD 3C\r
+2C KC TH 6H 8D AH 5C 6D 8S 5D\r
+TD TS 7C AD JC QD 9H 3C KC 7H\r
+5D 4D 5S 8H 4H 7D 3H JD KD 2D\r
+JH TD 6H QS 4S KD 5C 8S 7D 8H\r
+AC 3D AS 8C TD 7H KH 5D 6C JD\r
+9D KS 7C 6D QH TC JD KD AS KC\r
+JH 8S 5S 7S 7D AS 2D 3D AD 2H\r
+2H 5D AS 3C QD KC 6H 9H 9S 2C\r
+9D 5D TH 4C JH 3H 8D TC 8H 9H\r
+6H KD 2C TD 2H 6C 9D 2D JS 8C\r
+KD 7S 3C 7C AS QH TS AD 8C 2S\r
+QS 8H 6C JS 4C 9S QC AD TD TS\r
+2H 7C TS TC 8C 3C 9H 2D 6D JC\r
+TC 2H 8D JH KS 6D 3H TD TH 8H\r
+9D TD 9H QC 5D 6C 8H 8C KC TS\r
+2H 8C 3D AH 4D TH TC 7D 8H KC\r
+TS 5C 2D 8C 6S KH AH 5H 6H KC\r
+5S 5D AH TC 4C JD 8D 6H 8C 6C\r
+KC QD 3D 8H 2D JC 9H 4H AD 2S\r
+TD 6S 7D JS KD 4H QS 2S 3S 8C\r
+4C 9H JH TS 3S 4H QC 5S 9S 9C\r
+2C KD 9H JS 9S 3H JC TS 5D AC\r
+AS 2H 5D AD 5H JC 7S TD JS 4C\r
+2D 4S 8H 3D 7D 2C AD KD 9C TS\r
+7H QD JH 5H JS AC 3D TH 4C 8H\r
+6D KH KC QD 5C AD 7C 2D 4H AC\r
+3D 9D TC 8S QD 2C JC 4H JD AH\r
+6C TD 5S TC 8S AH 2C 5D AS AC\r
+TH 7S 3D AS 6C 4C 7H 7D 4H AH\r
+5C 2H KS 6H 7S 4H 5H 3D 3C 7H\r
+3C 9S AC 7S QH 2H 3D 6S 3S 3H\r
+2D 3H AS 2C 6H TC JS 6S 9C 6C\r
+QH KD QD 6D AC 6H KH 2C TS 8C\r
+8H 7D 3S 9H 5D 3H 4S QC 9S 5H\r
+2D 9D 7H 6H 3C 8S 5H 4D 3S 4S\r
+KD 9S 4S TC 7S QC 3S 8S 2H 7H\r
+TC 3D 8C 3H 6C 2H 6H KS KD 4D\r
+KC 3D 9S 3H JS 4S 8H 2D 6C 8S\r
+6H QS 6C TC QD 9H 7D 7C 5H 4D\r
+TD 9D 8D 6S 6C TC 5D TS JS 8H\r
+4H KC JD 9H TC 2C 6S 5H 8H AS\r
+JS 9C 5C 6S 9D JD 8H KC 4C 6D\r
+4D 8D 8S 6C 7C 6H 7H 8H 5C KC\r
+TC 3D JC 6D KS 9S 6H 7S 9C 2C\r
+6C 3S KD 5H TS 7D 9H 9S 6H KH\r
+3D QD 4C 6H TS AC 3S 5C 2H KD\r
+4C AS JS 9S 7C TS 7H 9H JC KS\r
+4H 8C JD 3H 6H AD 9S 4S 5S KS\r
+4C 2C 7D 3D AS 9C 2S QS KC 6C\r
+8S 5H 3D 2S AC 9D 6S 3S 4D TD\r
+QD TH 7S TS 3D AC 7H 6C 5D QC\r
+TC QD AD 9C QS 5C 8D KD 3D 3C\r
+9D 8H AS 3S 7C 8S JD 2D 8D KC\r
+4C TH AC QH JS 8D 7D 7S 9C KH\r
+9D 8D 4C JH 2C 2S QD KD TS 4H\r
+4D 6D 5D 2D JH 3S 8S 3H TC KH\r
+AD 4D 2C QS 8C KD JH JD AH 5C\r
+5C 6C 5H 2H JH 4H KS 7C TC 3H\r
+3C 4C QC 5D JH 9C QD KH 8D TC\r
+3H 9C JS 7H QH AS 7C 9H 5H JC\r
+2D 5S QD 4S 3C KC 6S 6C 5C 4C\r
+5D KH 2D TS 8S 9C AS 9S 7C 4C\r
+7C AH 8C 8D 5S KD QH QS JH 2C\r
+8C 9D AH 2H AC QC 5S 8H 7H 2C\r
+QD 9H 5S QS QC 9C 5H JC TH 4H\r
+6C 6S 3H 5H 3S 6H KS 8D AC 7S\r
+AC QH 7H 8C 4S KC 6C 3D 3S TC\r
+9D 3D JS TH AC 5H 3H 8S 3S TC\r
+QD KH JS KS 9S QC 8D AH 3C AC\r
+5H 6C KH 3S 9S JH 2D QD AS 8C\r
+6C 4D 7S 7H 5S JC 6S 9H 4H JH\r
+AH 5S 6H 9S AD 3S TH 2H 9D 8C\r
+4C 8D 9H 7C QC AD 4S 9C KC 5S\r
+9D 6H 4D TC 4C JH 2S 5D 3S AS\r
+2H 6C 7C KH 5C AD QS TH JD 8S\r
+3S 4S 7S AH AS KC JS 2S AD TH\r
+JS KC 2S 7D 8C 5C 9C TS 5H 9D\r
+7S 9S 4D TD JH JS KH 6H 5D 2C\r
+JD JS JC TH 2D 3D QD 8C AC 5H\r
+7S KH 5S 9D 5D TD 4S 6H 3C 2D\r
+4S 5D AC 8D 4D 7C AD AS AH 9C\r
+6S TH TS KS 2C QC AH AS 3C 4S\r
+2H 8C 3S JC 5C 7C 3H 3C KH JH\r
+7S 3H JC 5S 6H 4C 2S 4D KC 7H\r
+4D 7C 4H 9S 8S 6S AD TC 6C JC\r
+KH QS 3S TC 4C 8H 8S AC 3C TS\r
+QD QS TH 3C TS 7H 7D AH TD JC\r
+TD JD QC 4D 9S 7S TS AD 7D AC\r
+AH 7H 4S 6D 7C 2H 9D KS JC TD\r
+7C AH JD 4H 6D QS TS 2H 2C 5C\r
+TC KC 8C 9S 4C JS 3C JC 6S AH\r
+AS 7D QC 3D 5S JC JD 9D TD KH\r
+TH 3C 2S 6H AH AC 5H 5C 7S 8H\r
+QC 2D AC QD 2S 3S JD QS 6S 8H\r
+KC 4H 3C 9D JS 6H 3S 8S AS 8C\r
+7H KC 7D JD 2H JC QH 5S 3H QS\r
+9H TD 3S 8H 7S AC 5C 6C AH 7C\r
+8D 9H AH JD TD QS 7D 3S 9C 8S\r
+AH QH 3C JD KC 4S 5S 5D TD KS\r
+9H 7H 6S JH TH 4C 7C AD 5C 2D\r
+7C KD 5S TC 9D 6S 6C 5D 2S TH\r
+KC 9H 8D 5H 7H 4H QC 3D 7C AS\r
+6S 8S QC TD 4S 5C TH QS QD 2S\r
+8S 5H TH QC 9H 6S KC 7D 7C 5C\r
+7H KD AH 4D KH 5C 4S 2D KC QH\r
+6S 2C TD JC AS 4D 6C 8C 4H 5S\r
+JC TC JD 5S 6S 8D AS 9D AD 3S\r
+6D 6H 5D 5S TC 3D 7D QS 9D QD\r
+4S 6C 8S 3S 7S AD KS 2D 7D 7C\r
+KC QH JC AC QD 5D 8D QS 7H 7D\r
+JS AH 8S 5H 3D TD 3H 4S 6C JH\r
+4S QS 7D AS 9H JS KS 6D TC 5C\r
+2D 5C 6H TC 4D QH 3D 9H 8S 6C\r
+6D 7H TC TH 5S JD 5C 9C KS KD\r
+8D TD QH 6S 4S 6C 8S KC 5C TC\r
+5S 3D KS AC 4S 7D QD 4C TH 2S\r
+TS 8H 9S 6S 7S QH 3C AH 7H 8C\r
+4C 8C TS JS QC 3D 7D 5D 7S JH\r
+8S 7S 9D QC AC 7C 6D 2H JH KC\r
+JS KD 3C 6S 4S 7C AH QC KS 5H\r
+KS 6S 4H JD QS TC 8H KC 6H AS\r
+KH 7C TC 6S TD JC 5C 7D AH 3S\r
+3H 4C 4H TC TH 6S 7H 6D 9C QH\r
+7D 5H 4S 8C JS 4D 3D 8S QH KC\r
+3H 6S AD 7H 3S QC 8S 4S 7S JS\r
+3S JD KH TH 6H QS 9C 6C 2D QD\r
+4S QH 4D 5H KC 7D 6D 8D TH 5S\r
+TD AD 6S 7H KD KH 9H 5S KC JC\r
+3H QC AS TS 4S QD KS 9C 7S KC\r
+TS 6S QC 6C TH TC 9D 5C 5D KD\r
+JS 3S 4H KD 4C QD 6D 9S JC 9D\r
+8S JS 6D 4H JH 6H 6S 6C KS KH\r
+AC 7D 5D TC 9S KH 6S QD 6H AS\r
+AS 7H 6D QH 8D TH 2S KH 5C 5H\r
+4C 7C 3D QC TC 4S KH 8C 2D JS\r
+6H 5D 7S 5H 9C 9H JH 8S TH 7H\r
+AS JS 2S QD KH 8H 4S AC 8D 8S\r
+3H 4C TD KD 8C JC 5C QS 2D JD\r
+TS 7D 5D 6C 2C QS 2H 3C AH KS\r
+4S 7C 9C 7D JH 6C 5C 8H 9D QD\r
+2S TD 7S 6D 9C 9S QS KH QH 5C\r
+JC 6S 9C QH JH 8D 7S JS KH 2H\r
+8D 5H TH KC 4D 4S 3S 6S 3D QS\r
+2D JD 4C TD 7C 6D TH 7S JC AH\r
+QS 7S 4C TH 9D TS AD 4D 3H 6H\r
+2D 3H 7D JD 3D AS 2S 9C QC 8S\r
+4H 9H 9C 2C 7S JH KD 5C 5D 6H\r
+TC 9H 8H JC 3C 9S 8D KS AD KC\r
+TS 5H JD QS QH QC 8D 5D KH AH\r
+5D AS 8S 6S 4C AH QC QD TH 7H\r
+3H 4H 7D 6S 4S 9H AS 8H JS 9D\r
+JD 8C 2C 9D 7D 5H 5S 9S JC KD\r
+KD 9C 4S QD AH 7C AD 9D AC TD\r
+6S 4H 4S 9C 8D KS TC 9D JH 7C\r
+5S JC 5H 4S QH AC 2C JS 2S 9S\r
+8C 5H AS QD AD 5C 7D 8S QC TD\r
+JC 4C 8D 5C KH QS 4D 6H 2H 2C\r
+TH 4S 2D KC 3H QD AC 7H AD 9D\r
+KH QD AS 8H TH KC 8D 7S QH 8C\r
+JC 6C 7D 8C KH AD QS 2H 6S 2D\r
+JC KH 2D 7D JS QC 5H 4C 5D AD\r
+TS 3S AD 4S TD 2D TH 6S 9H JH\r
+9H 2D QS 2C 4S 3D KH AS AC 9D\r
+KH 6S 8H 4S KD 7D 9D TS QD QC\r
+JH 5H AH KS AS AD JC QC 5S KH\r
+5D 7D 6D KS KD 3D 7C 4D JD 3S\r
+AC JS 8D 5H 9C 3H 4H 4D TS 2C\r
+6H KS KH 9D 7C 2S 6S 8S 2H 3D\r
+6H AC JS 7S 3S TD 8H 3H 4H TH\r
+9H TC QC KC 5C KS 6H 4H AC 8S\r
+TC 7D QH 4S JC TS 6D 6C AC KH\r
+QH 7D 7C JH QS QD TH 3H 5D KS\r
+3D 5S 8D JS 4C 2C KS 7H 9C 4H\r
+5H 8S 4H TD 2C 3S QD QC 3H KC\r
+QC JS KD 9C AD 5S 9D 7D 7H TS\r
+8C JC KH 7C 7S 6C TS 2C QD TH\r
+5S 9D TH 3C 7S QH 8S 9C 2H 5H\r
+5D 9H 6H 2S JS KH 3H 7C 2H 5S\r
+JD 5D 5S 2C TC 2S 6S 6C 3C 8S\r
+4D KH 8H 4H 2D KS 3H 5C 2S 9H\r
+3S 2D TD 7H 8S 6H JD KC 9C 8D\r
+6S QD JH 7C 9H 5H 8S 8H TH TD\r
+QS 7S TD 7D TS JC KD 7C 3C 2C\r
+3C JD 8S 4H 2D 2S TD AS 4D AC\r
+AH KS 6C 4C 4S 7D 8C 9H 6H AS\r
+5S 3C 9S 2C QS KD 4D 4S AC 5D\r
+2D TS 2C JS KH QH 5D 8C AS KC\r
+KD 3H 6C TH 8S 7S KH 6H 9S AC\r
+6H 7S 6C QS AH 2S 2H 4H 5D 5H\r
+5H JC QD 2C 2S JD AS QC 6S 7D\r
+6C TC AS KD 8H 9D 2C 7D JH 9S\r
+2H 4C 6C AH 8S TD 3H TH 7C TS\r
+KD 4S TS 6C QH 8D 9D 9C AH 7D\r
+6D JS 5C QD QC 9C 5D 8C 2H KD\r
+3C QH JH AD 6S AH KC 8S 6D 6H\r
+3D 7C 4C 7S 5S 3S 6S 5H JC 3C\r
+QH 7C 5H 3C 3S 8C TS 4C KD 9C\r
+QD 3S 7S 5H 7H QH JC 7C 8C KD\r
+3C KD KH 2S 4C TS AC 6S 2C 7C\r
+2C KH 3C 4C 6H 4D 5H 5S 7S QD\r
+4D 7C 8S QD TS 9D KS 6H KD 3C\r
+QS 4D TS 7S 4C 3H QD 8D 9S TC\r
+TS QH AC 6S 3C 9H 9D QS 8S 6H\r
+3S 7S 5D 4S JS 2D 6C QH 6S TH\r
+4C 4H AS JS 5D 3D TS 9C AC 8S\r
+6S 9C 7C 3S 5C QS AD AS 6H 3C\r
+9S 8C 7H 3H 6S 7C AS 9H JD KH\r
+3D 3H 7S 4D 6C 7C AC 2H 9C TH\r
+4H 5S 3H AC TC TH 9C 9H 9S 8D\r
+8D 9H 5H 4D 6C 2H QD 6S 5D 3S\r
+4C 5C JD QS 4D 3H TH AC QH 8C\r
+QC 5S 3C 7H AD 4C KS 4H JD 6D\r
+QS AH 3H KS 9H 2S JS JH 5H 2H\r
+2H 5S TH 6S TS 3S KS 3C 5H JS\r
+2D 9S 7H 3D KC JH 6D 7D JS TD\r
+AC JS 8H 2C 8C JH JC 2D TH 7S\r
+5D 9S 8H 2H 3D TC AH JC KD 9C\r
+9D QD JC 2H 6D KH TS 9S QH TH\r
+2C 8D 4S JD 5H 3H TH TC 9C KC\r
+AS 3D 9H 7D 4D TH KH 2H 7S 3H\r
+4H 7S KS 2S JS TS 8S 2H QD 8D\r
+5S 6H JH KS 8H 2S QC AC 6S 3S\r
+JC AS AD QS 8H 6C KH 4C 4D QD\r
+2S 3D TS TD 9S KS 6S QS 5C 8D\r
+3C 6D 4S QC KC JH QD TH KH AD\r
+9H AH 4D KS 2S 8D JH JC 7C QS\r
+2D 6C TH 3C 8H QD QH 2S 3S KS\r
+6H 5D 9S 4C TS TD JS QD 9D JD\r
+5H 8H KH 8S KS 7C TD AD 4S KD\r
+2C 7C JC 5S AS 6C 7D 8S 5H 9C\r
+6S QD 9S TS KH QS 5S QH 3C KC\r
+7D 3H 3C KD 5C AS JH 7H 6H JD\r
+9D 5C 9H KC 8H KS 4S AD 4D 2S\r
+3S JD QD 8D 2S 7C 5S 6S 5H TS\r
+6D 9S KC TD 3S 6H QD JD 5C 8D\r
+5H 9D TS KD 8D 6H TD QC 4C 7D\r
+6D 4S JD 9D AH 9S AS TD 9H QD\r
+2D 5S 2H 9C 6H 9S TD QC 7D TC\r
+3S 2H KS TS 2C 9C 8S JS 9D 7D\r
+3C KC 6D 5D 6C 6H 8S AS 7S QS\r
+JH 9S 2H 8D 4C 8H 9H AD TH KH\r
+QC AS 2S JS 5C 6H KD 3H 7H 2C\r
+QD 8H 2S 8D 3S 6D AH 2C TC 5C\r
+JD JS TS 8S 3H 5D TD KC JC 6H\r
+6S QS TC 3H 5D AH JC 7C 7D 4H\r
+7C 5D 8H 9C 2H 9H JH KH 5S 2C\r
+9C 7H 6S TH 3S QC QD 4C AC JD\r
+2H 5D 9S 7D KC 3S QS 2D AS KH\r
+2S 4S 2H 7D 5C TD TH QH 9S 4D\r
+6D 3S TS 6H 4H KS 9D 8H 5S 2D\r
+9H KS 4H 3S 5C 5D KH 6H 6S JS\r
+KC AS 8C 4C JC KH QC TH QD AH\r
+6S KH 9S 2C 5H TC 3C 7H JC 4D\r
+JD 4S 6S 5S 8D 7H 7S 4D 4C 2H\r
+7H 9H 5D KH 9C 7C TS TC 7S 5H\r
+4C 8D QC TS 4S 9H 3D AD JS 7C\r
+8C QS 5C 5D 3H JS AH KC 4S 9D\r
+TS JD 8S QS TH JH KH 2D QD JS\r
+JD QC 5D 6S 9H 3S 2C 8H 9S TS\r
+2S 4C AD 7H JC 5C 2D 6D 4H 3D\r
+7S JS 2C 4H 8C AD QD 9C 3S TD\r
+JD TS 4C 6H 9H 7D QD 6D 3C AS\r
+AS 7C 4C 6S 5D 5S 5C JS QC 4S\r
+KD 6S 9S 7C 3C 5S 7D JH QD JS\r
+4S 7S JH 2C 8S 5D 7H 3D QH AD\r
+TD 6H 2H 8D 4H 2D 7C AD KH 5D\r
+TS 3S 5H 2C QD AH 2S 5C KH TD\r
+KC 4D 8C 5D AS 6C 2H 2S 9H 7C\r
+KD JS QC TS QS KH JH 2C 5D AD\r
+3S 5H KC 6C 9H 3H 2H AD 7D 7S\r
+7S JS JH KD 8S 7D 2S 9H 7C 2H\r
+9H 2D 8D QC 6S AD AS 8H 5H 6C\r
+2S 7H 6C 6D 7D 8C 5D 9D JC 3C\r
+7C 9C 7H JD 2H KD 3S KH AD 4S\r
+QH AS 9H 4D JD KS KD TS KH 5H\r
+4C 8H 5S 3S 3D 7D TD AD 7S KC\r
+JS 8S 5S JC 8H TH 9C 4D 5D KC\r
+7C 5S 9C QD 2C QH JS 5H 8D KH\r
+TD 2S KS 3D AD KC 7S TC 3C 5D\r
+4C 2S AD QS 6C 9S QD TH QH 5C\r
+8C AD QS 2D 2S KC JD KS 6C JC\r
+8D 4D JS 2H 5D QD 7S 7D QH TS\r
+6S 7H 3S 8C 8S 9D QS 8H 6C 9S\r
+4S TC 2S 5C QD 4D QS 6D TH 6S\r
+3S 5C 9D 6H 8D 4C 7D TC 7C TD\r
+AH 6S AS 7H 5S KD 3H 5H AC 4C\r
+8D 8S AH KS QS 2C AD 6H 7D 5D\r
+6H 9H 9S 2H QS 8S 9C 5D 2D KD\r
+TS QC 5S JH 7D 7S TH 9S 9H AC\r
+7H 3H 6S KC 4D 6D 5C 4S QD TS\r
+TD 2S 7C QD 3H JH 9D 4H 7S 7H\r
+KS 3D 4H 5H TC 2S AS 2D 6D 7D\r
+8H 3C 7H TD 3H AD KC TH 9C KH\r
+TC 4C 2C 9S 9D 9C 5C 2H JD 3C\r
+3H AC TS 5D AD 8D 6H QC 6S 8C\r
+2S TS 3S JD 7H 8S QH 4C 5S 8D\r
+AC 4S 6C 3C KH 3D 7C 2D 8S 2H\r
+4H 6C 8S TH 2H 4S 8H 9S 3H 7S\r
+7C 4C 9C 2C 5C AS 5D KD 4D QH\r
+9H 4H TS AS 7D 8D 5D 9S 8C 2H\r
+QC KD AC AD 2H 7S AS 3S 2D 9S\r
+2H QC 8H TC 6D QD QS 5D KH 3C\r
+TH JD QS 4C 2S 5S AD 7H 3S AS\r
+7H JS 3D 6C 3S 6D AS 9S AC QS\r
+9C TS AS 8C TC 8S 6H 9D 8D 6C\r
+4D JD 9C KC 7C 6D KS 3S 8C AS\r
+3H 6S TC 8D TS 3S KC 9S 7C AS\r
+8C QC 4H 4S 8S 6C 3S TC AH AC\r
+4D 7D 5C AS 2H 6S TS QC AD TC\r
+QD QC 8S 4S TH 3D AH TS JH 4H\r
+5C 2D 9S 2C 3H 3C 9D QD QH 7D\r
+KC 9H 6C KD 7S 3C 4D AS TC 2D\r
+3D JS 4D 9D KS 7D TH QC 3H 3C\r
+8D 5S 2H 9D 3H 8C 4C 4H 3C TH\r
+JC TH 4S 6S JD 2D 4D 6C 3D 4C\r
+TS 3S 2D 4H AC 2C 6S 2H JH 6H\r
+TD 8S AD TC AH AC JH 9S 6S 7S\r
+6C KC 4S JD 8D 9H 5S 7H QH AH\r
+KD 8D TS JH 5C 5H 3H AD AS JS\r
+2D 4H 3D 6C 8C 7S AD 5D 5C 8S\r
+TD 5D 7S 9C 4S 5H 6C 8C 4C 8S\r
+JS QH 9C AS 5C QS JC 3D QC 7C\r
+JC 9C KH JH QS QC 2C TS 3D AD\r
+5D JH AC 5C 9S TS 4C JD 8C KS\r
+KC AS 2D KH 9H 2C 5S 4D 3D 6H\r
+TH AH 2D 8S JC 3D 8C QH 7S 3S\r
+8H QD 4H JC AS KH KS 3C 9S 6D\r
+9S QH 7D 9C 4S AC 7H KH 4D KD\r
+AH AD TH 6D 9C 9S KD KS QH 4H\r
+QD 6H 9C 7C QS 6D 6S 9D 5S JH\r
+AH 8D 5H QD 2H JC KS 4H KH 5S\r
+5C 2S JS 8D 9C 8C 3D AS KC AH\r
+JD 9S 2H QS 8H 5S 8C TH 5C 4C\r
+QC QS 8C 2S 2C 3S 9C 4C KS KH\r
+2D 5D 8S AH AD TD 2C JS KS 8C\r
+TC 5S 5H 8H QC 9H 6H JD 4H 9S\r
+3C JH 4H 9H AH 4S 2H 4C 8D AC\r
+8S TH 4D 7D 6D QD QS 7S TC 7C\r
+KH 6D 2D JD 5H JS QD JH 4H 4S\r
+9C 7S JH 4S 3S TS QC 8C TC 4H\r
+QH 9D 4D JH QS 3S 2C 7C 6C 2D\r
+4H 9S JD 5C 5H AH 9D TS 2D 4C\r
+KS JH TS 5D 2D AH JS 7H AS 8D\r
+JS AH 8C AD KS 5S 8H 2C 6C TH\r
+2H 5D AD AC KS 3D 8H TS 6H QC\r
+6D 4H TS 9C 5H JS JH 6S JD 4C\r
+JH QH 4H 2C 6D 3C 5D 4C QS KC\r
+6H 4H 6C 7H 6S 2S 8S KH QC 8C\r
+3H 3D 5D KS 4H TD AD 3S 4D TS\r
+5S 7C 8S 7D 2C KS 7S 6C 8C JS\r
+5D 2H 3S 7C 5C QD 5H 6D 9C 9H\r
+JS 2S KD 9S 8D TD TS AC 8C 9D\r
+5H QD 2S AC 8C 9H KS 7C 4S 3C\r
+KH AS 3H 8S 9C JS QS 4S AD 4D\r
+AS 2S TD AD 4D 9H JC 4C 5H QS\r
+5D 7C 4H TC 2D 6C JS 4S KC 3S\r
+4C 2C 5D AC 9H 3D JD 8S QS QH\r
+2C 8S 6H 3C QH 6D TC KD AC AH\r
+QC 6C 3S QS 4S AC 8D 5C AD KH\r
+5S 4C AC KH AS QC 2C 5C 8D 9C\r
+8H JD 3C KH 8D 5C 9C QD QH 9D\r
+7H TS 2C 8C 4S TD JC 9C 5H QH\r
+JS 4S 2C 7C TH 6C AS KS 7S JD\r
+JH 7C 9H 7H TC 5H 3D 6D 5D 4D\r
+2C QD JH 2H 9D 5S 3D TD AD KS\r
+JD QH 3S 4D TH 7D 6S QS KS 4H\r
+TC KS 5S 8D 8H AD 2S 2D 4C JH\r
+5S JH TC 3S 2D QS 9D 4C KD 9S\r
+AC KH 3H AS 9D KC 9H QD 6C 6S\r
+9H 7S 3D 5C 7D KC TD 8H 4H 6S\r
+3C 7H 8H TC QD 4D 7S 6S QH 6C\r
+6D AD 4C QD 6C 5D 7D 9D KS TS\r
+JH 2H JD 9S 7S TS KH 8D 5D 8H\r
+2D 9S 4C 7D 9D 5H QD 6D AC 6S\r
+7S 6D JC QD JH 4C 6S QS 2H 7D\r
+8C TD JH KD 2H 5C QS 2C JS 7S\r
+TC 5H 4H JH QD 3S 5S 5D 8S KH\r
+KS KH 7C 2C 5D JH 6S 9C 6D JC\r
+5H AH JD 9C JS KC 2H 6H 4D 5S\r
+AS 3C TH QC 6H 9C 8S 8C TD 7C\r
+KC 2C QD 9C KH 4D 7S 3C TS 9H\r
+9C QC 2S TS 8C TD 9S QD 3S 3C\r
+4D 9D TH JH AH 6S 2S JD QH JS\r
+QD 9H 6C KD 7D 7H 5D 6S 8H AH\r
+8H 3C 4S 2H 5H QS QH 7S 4H AC\r
+QS 3C 7S 9S 4H 3S AH KS 9D 7C\r
+AD 5S 6S 2H 2D 5H TC 4S 3C 8C\r
+QH TS 6S 4D JS KS JH AS 8S 6D\r
+2C 8S 2S TD 5H AS TC TS 6C KC\r
+KC TS 8H 2H 3H 7C 4C 5S TH TD\r
+KD AD KH 7H 7S 5D 5H 5S 2D 9C\r
+AD 9S 3D 7S 8C QC 7C 9C KD KS\r
+3C QC 9S 8C 4D 5C AS QD 6C 2C\r
+2H KC 8S JD 7S AC 8D 5C 2S 4D\r
+9D QH 3D 2S TC 3S KS 3C 9H TD\r
+KD 6S AC 2C 7H 5H 3S 6C 6H 8C\r
+QH TC 8S 6S KH TH 4H 5D TS 4D\r
+8C JS 4H 6H 2C 2H 7D AC QD 3D\r
+QS KC 6S 2D 5S 4H TD 3H JH 4C\r
+7S 5H 7H 8H KH 6H QS TH KD 7D\r
+5H AD KD 7C KH 5S TD 6D 3C 6C\r
+8C 9C 5H JD 7C KC KH 7H 2H 3S\r
+7S 4H AD 4D 8S QS TH 3D 7H 5S\r
+8D TC KS KD 9S 6D AD JD 5C 2S\r
+7H 8H 6C QD 2H 6H 9D TC 9S 7C\r
+8D 6D 4C 7C 6C 3C TH KH JS JH\r
+5S 3S 8S JS 9H AS AD 8H 7S KD\r
+JH 7C 2C KC 5H AS AD 9C 9S JS\r
+AD AC 2C 6S QD 7C 3H TH KS KD\r
+9D JD 4H 8H 4C KH 7S TS 8C KC\r
+3S 5S 2H 7S 6H 7D KS 5C 6D AD\r
+5S 8C 9H QS 7H 7S 2H 6C 7D TD\r
+QS 5S TD AC 9D KC 3D TC 2D 4D\r
+TD 2H 7D JD QD 4C 7H 5D KC 3D\r
+4C 3H 8S KD QH 5S QC 9H TC 5H\r
+9C QD TH 5H TS 5C 9H AH QH 2C\r
+4D 6S 3C AC 6C 3D 2C 2H TD TH\r
+AC 9C 5D QC 4D AD 8D 6D 8C KC\r
+AD 3C 4H AC 8D 8H 7S 9S TD JC\r
+4H 9H QH JS 2D TH TD TC KD KS\r
+5S 6S 9S 8D TH AS KH 5H 5C 8S\r
+JD 2S 9S 6S 5S 8S 5D 7S 7H 9D\r
+5D 8C 4C 9D AD TS 2C 7D KD TC\r
+8S QS 4D KC 5C 8D 4S KH JD KD\r
+AS 5C AD QH 7D 2H 9S 7H 7C TC\r
+2S 8S JD KH 7S 6C 6D AD 5D QC\r
+9H 6H 3S 8C 8H AH TC 4H JS TD\r
+2C TS 4D 7H 2D QC 9C 5D TH 7C\r
+6C 8H QC 5D TS JH 5C 5H 9H 4S\r
+2D QC 7H AS JS 8S 2H 4C 4H 8D\r
+JS 6S AC KD 3D 3C 4S 7H TH KC\r
+QH KH 6S QS 5S 4H 3C QD 3S 3H\r
+7H AS KH 8C 4H 9C 5S 3D 6S TS\r
+9C 7C 3H 5S QD 2C 3D AD AC 5H\r
+JH TD 2D 4C TS 3H KH AD 3S 7S\r
+AS 4C 5H 4D 6S KD JC 3C 6H 2D\r
+3H 6S 8C 2D TH 4S AH QH AD 5H\r
+7C 2S 9H 7H KC 5C 6D 5S 3H JC\r
+3C TC 9C 4H QD TD JH 6D 9H 5S\r
+7C 6S 5C 5D 6C 4S 7H 9H 6H AH\r
+AD 2H 7D KC 2C 4C 2S 9S 7H 3S\r
+TH 4C 8S 6S 3S AD KS AS JH TD\r
+5C TD 4S 4D AD 6S 5D TC 9C 7D\r
+8H 3S 4D 4S 5S 6H 5C AC 3H 3D\r
+9H 3C AC 4S QS 8S 9D QH 5H 4D\r
+JC 6C 5H TS AC 9C JD 8C 7C QD\r
+8S 8H 9C JD 2D QC QH 6H 3C 8D\r
+KS JS 2H 6H 5H QH QS 3H 7C 6D\r
+TC 3H 4S 7H QC 2H 3S 8C JS KH\r
+AH 8H 5S 4C 9H JD 3H 7S JC AC\r
+3C 2D 4C 5S 6C 4S QS 3S JD 3D\r
+5H 2D TC AH KS 6D 7H AD 8C 6H\r
+6C 7S 3C JD 7C 8H KS KH AH 6D\r
+AH 7D 3H 8H 8S 7H QS 5H 9D 2D\r
+JD AC 4H 7S 8S 9S KS AS 9D QH\r
+7S 2C 8S 5S JH QS JC AH KD 4C\r
+AH 2S 9H 4H 8D TS TD 6H QH JD\r
+4H JC 3H QS 6D 7S 9C 8S 9D 8D\r
+5H TD 4S 9S 4C 8C 8D 7H 3H 3D\r
+QS KH 3S 2C 2S 3C 7S TD 4S QD\r
+7C TD 4D 5S KH AC AS 7H 4C 6C\r
+2S 5H 6D JD 9H QS 8S 2C 2H TD\r
+2S TS 6H 9H 7S 4H JC 4C 5D 5S\r
+2C 5H 7D 4H 3S QH JC JS 6D 8H\r
+4C QH 7C QD 3S AD TH 8S 5S TS\r
+9H TC 2S TD JC 7D 3S 3D TH QH\r
+7D 4C 8S 5C JH 8H 6S 3S KC 3H\r
+JC 3H KH TC QH TH 6H 2C AC 5H\r
+QS 2H 9D 2C AS 6S 6C 2S 8C 8S\r
+9H 7D QC TH 4H KD QS AC 7S 3C\r
+4D JH 6S 5S 8H KS 9S QC 3S AS\r
+JD 2D 6S 7S TC 9H KC 3H 7D KD\r
+2H KH 7C 4D 4S 3H JS QD 7D KC\r
+4C JC AS 9D 3C JS 6C 8H QD 4D\r
+AH JS 3S 6C 4C 3D JH 6D 9C 9H\r
+9H 2D 8C 7H 5S KS 6H 9C 2S TC\r
+6C 8C AD 7H 6H 3D KH AS 5D TH\r
+KS 8C 3S TS 8S 4D 5S 9S 6C 4H\r
+9H 4S 4H 5C 7D KC 2D 2H 9D JH\r
+5C JS TC 9D 9H 5H 7S KH JC 6S\r
+7C 9H 8H 4D JC KH JD 2H TD TC\r
+8H 6C 2H 2C KH 6H 9D QS QH 5H\r
+AC 7D 2S 3D QD JC 2D 8D JD JH\r
+2H JC 2D 7H 2C 3C 8D KD TD 4H\r
+3S 4H 6D 8D TS 3H TD 3D 6H TH\r
+JH JC 3S AC QH 9H 7H 8S QC 2C\r
+7H TD QS 4S 8S 9C 2S 5D 4D 2H\r
+3D TS 3H 2S QC 8H 6H KC JC KS\r
+5D JD 7D TC 8C 6C 9S 3D 8D AC\r
+8H 6H JH 6C 5D 8D 8S 4H AD 2C\r
+9D 4H 2D 2C 3S TS AS TC 3C 5D\r
+4D TH 5H KS QS 6C 4S 2H 3D AD\r
+5C KC 6H 2C 5S 3C 4D 2D 9H 9S\r
+JD 4C 3H TH QH 9H 5S AH 8S AC\r
+7D 9S 6S 2H TD 9C 4H 8H QS 4C\r
+3C 6H 5D 4H 8C 9C KC 6S QD QS\r
+3S 9H KD TC 2D JS 8C 6S 4H 4S\r
+2S 4C 8S QS 6H KH 3H TH 8C 5D\r
+2C KH 5S 3S 7S 7H 6C 9D QD 8D\r
+8H KS AC 2D KH TS 6C JS KC 7H\r
+9C KS 5C TD QC AH 6C 5H 9S 7C\r
+5D 4D 3H 4H 6S 7C 7S AH QD TD\r
+2H 7D QC 6S TC TS AH 7S 9D 3H\r
+TH 5H QD 9S KS 7S 7C 6H 8C TD\r
+TH 2D 4D QC 5C 7D JD AH 9C 4H\r
+4H 3H AH 8D 6H QC QH 9H 2H 2C\r
+2D AD 4C TS 6H 7S TH 4H QS TD\r
+3C KD 2H 3H QS JD TC QC 5D 8H\r
+KS JC QD TH 9S KD 8D 8C 2D 9C\r
+3C QD KD 6D 4D 8D AH AD QC 8S\r
+8H 3S 9D 2S 3H KS 6H 4C 7C KC\r
+TH 9S 5C 3D 7D 6H AC 7S 4D 2C\r
+5C 3D JD 4D 2D 6D 5H 9H 4C KH\r
+AS 7H TD 6C 2H 3D QD KS 4C 4S\r
+JC 3C AC 7C JD JS 8H 9S QC 5D\r
+JD 6S 5S 2H AS 8C 7D 5H JH 3D\r
+8D TC 5S 9S 8S 3H JC 5H 7S AS\r
+5C TD 3D 7D 4H 8D 7H 4D 5D JS\r
+QS 9C KS TD 2S 8S 5C 2H 4H AS\r
+TH 7S 4H 7D 3H JD KD 5D 2S KC\r
+JD 7H 4S 8H 4C JS 6H QH 5S 4H\r
+2C QS 8C 5S 3H QC 2S 6C QD AD\r
+8C 3D JD TC 4H 2H AD 5S AC 2S\r
+5D 2C JS 2D AD 9D 3D 4C 4S JH\r
+8D 5H 5D 6H 7S 4D KS 9D TD JD\r
+3D 6D 9C 2S AS 7D 5S 5C 8H JD\r
+7C 8S 3S 6S 5H JD TC AD 7H 7S\r
+2S 9D TS 4D AC 8D 6C QD JD 3H\r
+9S KH 2C 3C AC 3D 5H 6H 8D 5D\r
+KS 3D 2D 6S AS 4C 2S 7C 7H KH\r
+AC 2H 3S JC 5C QH 4D 2D 5H 7S\r
+TS AS JD 8C 6H JC 8S 5S 2C 5D\r
+7S QH 7H 6C QC 8H 2D 7C JD 2S\r
+2C QD 2S 2H JC 9C 5D 2D JD JH\r
+7C 5C 9C 8S 7D 6D 8D 6C 9S JH\r
+2C AD 6S 5H 3S KS 7S 9D KH 4C\r
+7H 6C 2C 5C TH 9D 8D 3S QC AH\r
+5S KC 6H TC 5H 8S TH 6D 3C AH\r
+9C KD 4H AD TD 9S 4S 7D 6H 5D\r
+7H 5C 5H 6D AS 4C KD KH 4H 9D\r
+3C 2S 5C 6C JD QS 2H 9D 7D 3H\r
+AC 2S 6S 7S JS QD 5C QS 6H AD\r
+5H TH QC 7H TC 3S 7C 6D KC 3D\r
+4H 3D QC 9S 8H 2C 3S JC KS 5C\r
+4S 6S 2C 6H 8S 3S 3D 9H 3H JS\r
+4S 8C 4D 2D 8H 9H 7D 9D AH TS\r
+9S 2C 9H 4C 8D AS 7D 3D 6D 5S\r
+6S 4C 7H 8C 3H 5H JC AH 9D 9C\r
+2S 7C 5S JD 8C 3S 3D 4D 7D 6S\r
+3C KC 4S 5D 7D 3D JD 7H 3H 4H\r
+9C 9H 4H 4D TH 6D QD 8S 9S 7S\r
+2H AC 8S 4S AD 8C 2C AH 7D TC\r
+TS 9H 3C AD KS TC 3D 8C 8H JD\r
+QC 8D 2C 3C 7D 7C JD 9H 9C 6C\r
+AH 6S JS JH 5D AS QC 2C JD TD\r
+9H KD 2H 5D 2D 3S 7D TC AH TS\r
+TD 8H AS 5D AH QC AC 6S TC 5H\r
+KS 4S 7H 4D 8D 9C TC 2H 6H 3H\r
+3H KD 4S QD QH 3D 8H 8C TD 7S\r
+8S JD TC AH JS QS 2D KH KS 4D\r
+3C AD JC KD JS KH 4S TH 9H 2C\r
+QC 5S JS 9S KS AS 7C QD 2S JD\r
+KC 5S QS 3S 2D AC 5D 9H 8H KS\r
+6H 9C TC AD 2C 6D 5S JD 6C 7C\r
+QS KH TD QD 2C 3H 8S 2S QC AH\r
+9D 9H JH TC QH 3C 2S JS 5C 7H\r
+6C 3S 3D 2S 4S QD 2D TH 5D 2C\r
+2D 6H 6D 2S JC QH AS 7H 4H KH\r
+5H 6S KS AD TC TS 7C AC 4S 4H\r
+AD 3C 4H QS 8C 9D KS 2H 2D 4D\r
+4S 9D 6C 6D 9C AC 8D 3H 7H KD\r
+JC AH 6C TS JD 6D AD 3S 5D QD\r
+JC JH JD 3S 7S 8S JS QC 3H 4S\r
+JD TH 5C 2C AD JS 7H 9S 2H 7S\r
+8D 3S JH 4D QC AS JD 2C KC 6H\r
+2C AC 5H KD 5S 7H QD JH AH 2D\r
+JC QH 8D 8S TC 5H 5C AH 8C 6C\r
+3H JS 8S QD JH 3C 4H 6D 5C 3S\r
+6D 4S 4C AH 5H 5S 3H JD 7C 8D\r
+8H AH 2H 3H JS 3C 7D QC 4H KD\r
+6S 2H KD 5H 8H 2D 3C 8S 7S QD\r
+2S 7S KC QC AH TC QS 6D 4C 8D\r
+5S 9H 2C 3S QD 7S 6C 2H 7C 9D\r
+3C 6C 5C 5S JD JC KS 3S 5D TS\r
+7C KS 6S 5S 2S 2D TC 2H 5H QS\r
+AS 7H 6S TS 5H 9S 9D 3C KD 2H\r
+4S JS QS 3S 4H 7C 2S AC 6S 9D\r
+8C JH 2H 5H 7C 5D QH QS KH QC\r
+3S TD 3H 7C KC 8D 5H 8S KH 8C\r
+4H KH JD TS 3C 7H AS QC JS 5S\r
+AH 9D 2C 8D 4D 2D 6H 6C KC 6S\r
+2S 6H 9D 3S 7H 4D KH 8H KD 3D\r
+9C TC AC JH KH 4D JD 5H TD 3S\r
+7S 4H 9D AS 4C 7D QS 9S 2S KH\r
+3S 8D 8S KS 8C JC 5C KH 2H 5D\r
+8S QH 2C 4D KC JS QC 9D AC 6H\r
+8S 8C 7C JS JD 6S 4C 9C AC 4S\r
+QH 5D 2C 7D JC 8S 2D JS JH 4C\r
+JS 4C 7S TS JH KC KH 5H QD 4S\r
+QD 8C 8D 2D 6S TD 9D AC QH 5S\r
+QH QC JS 3D 3C 5C 4H KH 8S 7H\r
+7C 2C 5S JC 8S 3H QC 5D 2H KC\r
+5S 8D KD 6H 4H QD QH 6D AH 3D\r
+7S KS 6C 2S 4D AC QS 5H TS JD\r
+7C 2D TC 5D QS AC JS QC 6C KC\r
+2C KS 4D 3H TS 8S AD 4H 7S 9S\r
+QD 9H QH 5H 4H 4D KH 3S JC AD\r
+4D AC KC 8D 6D 4C 2D KH 2C JD\r
+2C 9H 2D AH 3H 6D 9C 7D TC KS\r
+8C 3H KD 7C 5C 2S 4S 5H AS AH\r
+TH JD 4H KD 3H TC 5C 3S AC KH\r
+6D 7H AH 7S QC 6H 2D TD JD AS\r
+JH 5D 7H TC 9S 7D JC AS 5S KH\r
+2H 8C AD TH 6H QD KD 9H 6S 6C\r
+QH KC 9D 4D 3S JS JH 4H 2C 9H\r
+TC 7H KH 4H JC 7D 9S 3H QS 7S\r
+AD 7D JH 6C 7H 4H 3S 3H 4D QH\r
+JD 2H 5C AS 6C QC 4D 3C TC JH\r
+AC JD 3H 6H 4C JC AD 7D 7H 9H\r
+4H TC TS 2C 8C 6S KS 2H JD 9S\r
+4C 3H QS QC 9S 9H 6D KC 9D 9C\r
+5C AD 8C 2C QH TH QD JC 8D 8H\r
+QC 2C 2S QD 9C 4D 3S 8D JH QS\r
+9D 3S 2C 7S 7C JC TD 3C TC 9H\r
+3C TS 8H 5C 4C 2C 6S 8D 7C 4H\r
+KS 7H 2H TC 4H 2C 3S AS AH QS\r
+8C 2D 2H 2C 4S 4C 6S 7D 5S 3S\r
+TH QC 5D TD 3C QS KD KC KS AS\r
+4D AH KD 9H KS 5C 4C 6H JC 7S\r
+KC 4H 5C QS TC 2H JC 9S AH QH\r
+4S 9H 3H 5H 3C QD 2H QC JH 8H\r
+5D AS 7H 2C 3D JH 6H 4C 6S 7D\r
+9C JD 9H AH JS 8S QH 3H KS 8H\r
+3S AC QC TS 4D AD 3D AH 8S 9H\r
+7H 3H QS 9C 9S 5H JH JS AH AC\r
+8D 3C JD 2H AC 9C 7H 5S 4D 8H\r
+7C JH 9H 6C JS 9S 7H 8C 9D 4H\r
+2D AS 9S 6H 4D JS JH 9H AD QD\r
+6H 7S JH KH AH 7H TD 5S 6S 2C\r
+8H JH 6S 5H 5S 9D TC 4C QC 9S\r
+7D 2C KD 3H 5H AS QD 7H JS 4D\r
+TS QH 6C 8H TH 5H 3C 3H 9C 9D\r
+AD KH JS 5D 3H AS AC 9S 5C KC\r
+2C KH 8C JC QS 6D AH 2D KC TC\r
+9D 3H 2S 7C 4D 6D KH KS 8D 7D\r
+9H 2S TC JH AC QC 3H 5S 3S 8H\r
+3S AS KD 8H 4C 3H 7C JH QH TS\r
+7S 6D 7H 9D JH 4C 3D 3S 6C AS\r
+4S 2H 2C 4C 8S 5H KC 8C QC QD\r
+3H 3S 6C QS QC 2D 6S 5D 2C 9D\r
+2H 8D JH 2S 3H 2D 6C 5C 7S AD\r
+9H JS 5D QH 8S TS 2H 7S 6S AD\r
+6D QC 9S 7H 5H 5C 7D KC JD 4H\r
+QC 5S 9H 9C 4D 6S KS 2S 4C 7C\r
+9H 7C 4H 8D 3S 6H 5C 8H JS 7S\r
+2D 6H JS TD 4H 4D JC TH 5H KC\r
+AC 7C 8D TH 3H 9S 2D 4C KC 4D\r
+KD QS 9C 7S 3D KS AD TS 4C 4H\r
+QH 9C 8H 2S 7D KS 7H 5D KD 4C\r
+9C 2S 2H JC 6S 6C TC QC JH 5C\r
+7S AC 8H KC 8S 6H QS JC 3D 6S\r
+JS 2D JH 8C 4S 6H 8H 6D 5D AD\r
+6H 7D 2S 4H 9H 7C AS AC 8H 5S\r
+3C JS 4S 6D 5H 2S QH 6S 9C 2C\r
+3D 5S 6S 9S 4C QS 8D QD 8S TC\r
+9C 3D AH 9H 5S 2C 7D AD JC 3S\r
+7H TC AS 3C 6S 6D 7S KH KC 9H\r
+3S TC 8H 6S 5H JH 8C 7D AC 2S\r
+QD 9D 9C 3S JC 8C KS 8H 5D 4D\r
+JS AH JD 6D 9D 8C 9H 9S 8H 3H\r
+2D 6S 4C 4D 8S AD 4S TC AH 9H\r
+TS AC QC TH KC 6D 4H 7S 8C 2H\r
+3C QD JS 9D 5S JC AH 2H TS 9H\r
+3H 4D QH 5D 9C 5H 7D 4S JC 3S\r
+8S TH 3H 7C 2H JD JS TS AC 8D\r
+9C 2H TD KC JD 2S 8C 5S AD 2C\r
+3D KD 7C 5H 4D QH QD TC 6H 7D\r
+7H 2C KC 5S KD 6H AH QC 7S QH\r
+6H 5C AC 5H 2C 9C 2D 7C TD 2S\r
+4D 9D AH 3D 7C JD 4H 8C 4C KS\r
+TH 3C JS QH 8H 4C AS 3D QS QC\r
+4D 7S 5H JH 6D 7D 6H JS KH 3C\r
+QD 8S 7D 2H 2C 7C JC 2S 5H 8C\r
+QH 8S 9D TC 2H AD 7C 8D QD 6S\r
+3S 7C AD 9H 2H 9S JD TS 4C 2D\r
+3S AS 4H QC 2C 8H 8S 7S TD TC\r
+JH TH TD 3S 4D 4H 5S 5D QS 2C\r
+8C QD QH TC 6D 4S 9S 9D 4H QC\r
+8C JS 9D 6H JD 3H AD 6S TD QC\r
+KC 8S 3D 7C TD 7D 8D 9H 4S 3S\r
+6C 4S 3D 9D KD TC KC KS AC 5S\r
+7C 6S QH 3D JS KD 6H 6D 2D 8C\r
+JD 2S 5S 4H 8S AC 2D 6S TS 5C\r
+5H 8C 5S 3C 4S 3D 7C 8D AS 3H\r
+AS TS 7C 3H AD 7D JC QS 6C 6H\r
+3S 9S 4C AC QH 5H 5D 9H TS 4H\r
+6C 5C 7H 7S TD AD JD 5S 2H 2S\r
+7D 6C KC 3S JD 8D 8S TS QS KH\r
+8S QS 8D 6C TH AC AH 2C 8H 9S\r
+7H TD KH QH 8S 3D 4D AH JD AS\r
+TS 3D 2H JC 2S JH KH 6C QC JS\r
+KC TH 2D 6H 7S 2S TC 8C 9D QS\r
+3C 9D 6S KH 8H 6D 5D TH 2C 2H\r
+6H TC 7D AD 4D 8S TS 9H TD 7S\r
+JS 6D JD JC 2H AC 6C 3D KH 8D\r
+KH JD 9S 5D 4H 4C 3H 7S QS 5C\r
+4H JD 5D 3S 3C 4D KH QH QS 7S\r
+JD TS 8S QD AH 4C 6H 3S 5S 2C\r
+QS 3D JD AS 8D TH 7C 6S QC KS\r
+7S 2H 8C QC 7H AC 6D 2D TH KH\r
+5S 6C 7H KH 7D AH 8C 5C 7S 3D\r
+3C KD AD 7D 6C 4D KS 2D 8C 4S\r
+7C 8D 5S 2D 2S AH AD 2C 9D TD\r
+3C AD 4S KS JH 7C 5C 8C 9C TH\r
+AS TD 4D 7C JD 8C QH 3C 5H 9S\r
+3H 9C 8S 9S 6S QD KS AH 5H JH\r
+QC 9C 5S 4H 2H TD 7D AS 8C 9D\r
+8C 2C 9D KD TC 7S 3D KH QC 3C\r
+4D AS 4C QS 5S 9D 6S JD QH KS\r
+6D AH 6C 4C 5H TS 9H 7D 3D 5S\r
+QS JD 7C 8D 9C AC 3S 6S 6C KH\r
+8H JH 5D 9S 6D AS 6S 3S QC 7H\r
+QD AD 5C JH 2H AH 4H AS KC 2C\r
+JH 9C 2C 6H 2D JS 5D 9H KC 6D\r
+7D 9D KD TH 3H AS 6S QC 6H AD\r
+JD 4H 7D KC 3H JS 3C TH 3D QS\r
+4C 3H 8C QD 5H 6H AS 8H AD JD\r
+TH 8S KD 5D QC 7D JS 5S 5H TS\r
+7D KC 9D QS 3H 3C 6D TS 7S AH\r
+7C 4H 7H AH QC AC 4D 5D 6D TH\r
+3C 4H 2S KD 8H 5H JH TC 6C JD\r
+4S 8C 3D 4H JS TD 7S JH QS KD\r
+7C QC KD 4D 7H 6S AD TD TC KH\r
+5H 9H KC 3H 4D 3D AD 6S QD 6H\r
+TH 7C 6H TS QH 5S 2C KC TD 6S\r
+7C 4D 5S JD JH 7D AC KD KH 4H\r
+7D 6C 8D 8H 5C JH 8S QD TH JD\r
+8D 7D 6C 7C 9D KD AS 5C QH JH\r
+9S 2C 8C 3C 4C KS JH 2D 8D 4H\r
+7S 6C JH KH 8H 3H 9D 2D AH 6D\r
+4D TC 9C 8D 7H TD KS TH KD 3C\r
+JD 9H 8D QD AS KD 9D 2C 2S 9C\r
+8D 3H 5C 7H KS 5H QH 2D 8C 9H\r
+2D TH 6D QD 6C KC 3H 3S AD 4C\r
+4H 3H JS 9D 3C TC 5H QH QC JC\r
+3D 5C 6H 3S 3C JC 5S 7S 2S QH\r
+AC 5C 8C 4D 5D 4H 2S QD 3C 3H\r
+2C TD AH 9C KD JS 6S QD 4C QC\r
+QS 8C 3S 4H TC JS 3H 7C JC AD\r
+5H 4D 9C KS JC TD 9S TS 8S 9H\r
+QD TS 7D AS AC 2C TD 6H 8H AH\r
+6S AD 8C 4S 9H 8D 9D KH 8S 3C\r
+QS 4D 2D 7S KH JS JC AD 4C 3C\r
+QS 9S 7H KC TD TH 5H JS AC JH\r
+6D AC 2S QS 7C AS KS 6S KH 5S\r
+6D 8H KH 3C QS 2H 5C 9C 9D 6C\r
+JS 2C 4C 6H 7D JC AC QD TD 3H\r
+4H QC 8H JD 4C KD KS 5C KC 7S\r
+6D 2D 3H 2S QD 5S 7H AS TH 6S\r
+AS 6D 8D 2C 8S TD 8H QD JC AH\r
+9C 9H 2D TD QH 2H 5C TC 3D 8H\r
+KC 8S 3D KH 2S TS TC 6S 4D JH\r
+9H 9D QS AC KC 6H 5D 4D 8D AH\r
+9S 5C QS 4H 7C 7D 2H 8S AD JS\r
+3D AC 9S AS 2C 2D 2H 3H JC KH\r
+7H QH KH JD TC KS 5S 8H 4C 8D\r
+2H 7H 3S 2S 5H QS 3C AS 9H KD\r
+AD 3D JD 6H 5S 9C 6D AC 9S 3S\r
+3D 5D 9C 2D AC 4S 2S AD 6C 6S\r
+QC 4C 2D 3H 6S KC QH QD 2H JH\r
+QC 3C 8S 4D 9S 2H 5C 8H QS QD\r
+6D KD 6S 7H 3S KH 2H 5C JC 6C\r
+3S 9S TC 6S 8H 2D AD 7S 8S TS\r
+3C 6H 9C 3H 5C JC 8H QH TD QD\r
+3C JS QD 5D TD 2C KH 9H TH AS\r
+9S TC JD 3D 5C 5H AD QH 9H KC\r
+TC 7H 4H 8H 3H TD 6S AC 7C 2S\r
+QS 9D 5D 3C JC KS 4D 6C JH 2S\r
+9S 6S 3C 7H TS 4C KD 6D 3D 9C\r
+2D 9H AH AC 7H 2S JH 3S 7C QC\r
+QD 9H 3C 2H AC AS 8S KD 8C KH\r
+2D 7S TD TH 6D JD 8D 4D 2H 5S\r
+8S QH KD JD QS JH 4D KC 5H 3S\r
+3C KH QC 6D 8H 3S AH 7D TD 2D\r
+5S 9H QH 4S 6S 6C 6D TS TH 7S\r
+6C 4C 6D QS JS 9C TS 3H 8D 8S\r
+JS 5C 7S AS 2C AH 2H AD 5S TC\r
+KD 6C 9C 9D TS 2S JC 4H 2C QD\r
+QS 9H TC 3H KC KS 4H 3C AD TH\r
+KH 9C 2H KD 9D TC 7S KC JH 2D\r
+7C 3S KC AS 8C 5D 9C 9S QH 3H\r
+2D 8C TD 4C 2H QC 5D TC 2C 7D\r
+KS 4D 6C QH TD KH 5D 7C AD 8D\r
+2S 9S 8S 4C 8C 3D 6H QD 7C 7H\r
+6C 8S QH 5H TS 5C 3C 4S 2S 2H\r
+8S 6S 2H JC 3S 3H 9D 8C 2S 7H\r
+QC 2C 8H 9C AC JD 4C 4H 6S 3S\r
+3H 3S 7D 4C 9S 5H 8H JC 3D TC\r
+QH 2S 2D 9S KD QD 9H AD 6D 9C\r
+8D 2D KS 9S JC 4C JD KC 4S TH\r
+KH TS 6D 4D 5C KD 5H AS 9H AD\r
+QD JS 7C 6D 5D 5C TH 5H QH QS\r
+9D QH KH 5H JH 4C 4D TC TH 6C\r
+KH AS TS 9D KD 9C 7S 4D 8H 5S\r
+KH AS 2S 7D 9D 4C TS TH AH 7C\r
+KS 4D AC 8S 9S 8D TH QH 9D 5C\r
+5D 5C 8C QS TC 4C 3D 3S 2C 8D\r
+9D KS 2D 3C KC 4S 8C KH 6C JC\r
+8H AH 6H 7D 7S QD 3C 4C 6C KC\r
+3H 2C QH 8H AS 7D 4C 8C 4H KC\r
+QD 5S 4H 2C TD AH JH QH 4C 8S\r
+3H QS 5S JS 8H 2S 9H 9C 3S 2C\r
+6H TS 7S JC QD AC TD KC 5S 3H\r
+QH AS QS 7D JC KC 2C 4C 5C 5S\r
+QH 3D AS JS 4H 8D 7H JC 2S 9C\r
+5D 4D 2S 4S 9D 9C 2D QS 8H 7H\r
+6D 7H 3H JS TS AC 2D JH 7C 8S\r
+JH 5H KC 3C TC 5S 9H 4C 8H 9D\r
+8S KC 5H 9H AD KS 9D KH 8D AH\r
+JC 2H 9H KS 6S 3H QC 5H AH 9C\r
+5C KH 5S AD 6C JC 9H QC 9C TD\r
+5S 5D JC QH 2D KS 8H QS 2H TS\r
+JH 5H 5S AH 7H 3C 8S AS TD KH\r
+6H 3D JD 2C 4C KC 7S AH 6C JH\r
+4C KS 9D AD 7S KC 7D 8H 3S 9C\r
+7H 5C 5H 3C 8H QC 3D KH 6D JC\r
+2D 4H 5D 7D QC AD AH 9H QH 8H\r
+KD 8C JS 9D 3S 3C 2H 5D 6D 2S\r
+8S 6S TS 3C 6H 8D 5S 3H TD 6C\r
+KS 3D JH 9C 7C 9S QS 5S 4H 6H\r
+7S 6S TH 4S KC KD 3S JC JH KS\r
+7C 3C 2S 6D QH 2C 7S 5H 8H AH\r
+KC 8D QD 6D KH 5C 7H 9D 3D 9C\r
+6H 2D 8S JS 9S 2S 6D KC 7C TC\r
+KD 9C JH 7H KC 8S 2S 7S 3D 6H\r
+4H 9H 2D 4C 8H 7H 5S 8S 2H 8D\r
+AD 7C 3C 7S 5S 4D 9H 3D JC KH\r
+5D AS 7D 6D 9C JC 4C QH QS KH\r
+KD JD 7D 3D QS QC 8S 6D JS QD\r
+6S 8C 5S QH TH 9H AS AC 2C JD\r
+QC KS QH 7S 3C 4C 5C KC 5D AH\r
+6C 4H 9D AH 2C 3H KD 3D TS 5C\r
+TD 8S QS AS JS 3H KD AC 4H KS\r
+7D 5D TS 9H 4H 4C 9C 2H 8C QC\r
+2C 7D 9H 4D KS 4C QH AD KD JS\r
+QD AD AH KH 9D JS 9H JC KD JD\r
+8S 3C 4S TS 7S 4D 5C 2S 6H 7C\r
+JS 7S 5C KD 6D QH 8S TD 2H 6S\r
+QH 6C TC 6H TD 4C 9D 2H QC 8H\r
+3D TS 4D 2H 6H 6S 2C 7H 8S 6C\r
+9H 9D JD JH 3S AH 2C 6S 3H 8S\r
+2C QS 8C 5S 3H 2S 7D 3C AD 4S\r
+5C QC QH AS TS 4S 6S 4C 5H JS\r
+JH 5C TD 4C 6H JS KD KH QS 4H\r
+TC KH JC 4D 9H 9D 8D KC 3C 8H\r
+2H TC 8S AD 9S 4H TS 7H 2C 5C\r
+4H 2S 6C 5S KS AH 9C 7C 8H KD\r
+TS QH TD QS 3C JH AH 2C 8D 7D\r
+5D KC 3H 5S AC 4S 7H QS 4C 2H\r
+3D 7D QC KH JH 6D 6C TD TH KD\r
+5S 8D TH 6C 9D 7D KH 8C 9S 6D\r
+JD QS 7S QC 2S QH JC 4S KS 8D\r
+7S 5S 9S JD KD 9C JC AD 2D 7C\r
+4S 5H AH JH 9C 5D TD 7C 2D 6S\r
+KC 6C 7H 6S 9C QD 5S 4H KS TD\r
+6S 8D KS 2D TH TD 9H JD TS 3S\r
+KH JS 4H 5D 9D TC TD QC JD TS\r
+QS QD AC AD 4C 6S 2D AS 3H KC\r
+4C 7C 3C TD QS 9C KC AS 8D AD\r
+KC 7H QC 6D 8H 6S 5S AH 7S 8C\r
+3S AD 9H JC 6D JD AS KH 6S JH\r
+AD 3D TS KS 7H JH 2D JS QD AC\r
+9C JD 7C 6D TC 6H 6C JC 3D 3S\r
+QC KC 3S JC KD 2C 8D AH QS TS\r
+AS KD 3D JD 8H 7C 8C 5C QD 6C\r
diff --git a/extra/project-euler/058/058-tests.factor b/extra/project-euler/058/058-tests.factor
new file mode 100644 (file)
index 0000000..13a2aaf
--- /dev/null
@@ -0,0 +1,3 @@
+USING: project-euler.058 tools.test ;
+
+{ 26241 } [ euler058 ] unit-test
diff --git a/extra/project-euler/058/058.factor b/extra/project-euler/058/058.factor
new file mode 100644 (file)
index 0000000..133175f
--- /dev/null
@@ -0,0 +1,68 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: fry kernel math math.primes math.ranges project-euler.common sequences ;
+IN: project-euler.058
+
+! http://projecteuler.net/index.php?section=problems&id=58
+
+! DESCRIPTION
+! -----------
+
+! Starting with 1 and solveling anticlockwise in the following way, a square
+! solve with side length 7 is formed.
+
+!     37 36 35 34 33 32 31
+!     38 17 16 15 14 13 30
+!     39 18  5  4  3 12 29
+!     40 19  6  1  2 11 28
+!     41 20  7  8  9 10 27
+!     42 21 22 23 24 25 26
+!     43 44 45 46 47 48 49
+
+! It is interesting to note that the odd squares lie along the bottom right
+! diagonal, but what is more interesting is that 8 out of the 13 numbers lying
+! along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.
+
+! If one complete new layer is wrapped around the solve above, a square solve
+! with side length 9 will be formed. If this process is continued, what is the
+! side length of the square solve for which the ratio of primes along both
+! diagonals first falls below 10%?
+
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+CONSTANT: PERCENT_PRIME 0.1
+
+! The corners of a square of side length n are:
+!    (n-2)² + 1(n-1)
+!    (n-2)² + 2(n-1)
+!    (n-2)² + 3(n-1)
+!    (n-2)² + 4(n-1) = odd squares, no need to calculate
+
+: prime-corners ( n -- m )
+    3 [1,b] swap '[ _ [ 1- * ] keep 2 - sq + prime? ] count ;
+
+: total-corners ( n -- m )
+    1- 2 * ; foldable
+
+: ratio-below? ( count length -- ? )
+    total-corners 1+ / PERCENT_PRIME < ;
+
+: next-layer ( count length -- count' length' )
+    2 + [ prime-corners + ] keep ;
+
+: solve ( count length -- length )
+    2dup ratio-below? [ nip ] [ next-layer solve ] if ;
+
+PRIVATE>
+
+: euler058 ( -- answer )
+    8 7 solve ;
+
+! [ euler058 ] 10 ave-time
+! 12974 ms ave run time - 284.46 SD (10 trials)
+
+SOLUTION: euler058
diff --git a/extra/project-euler/063/063-tests.factor b/extra/project-euler/063/063-tests.factor
new file mode 100644 (file)
index 0000000..0cff44d
--- /dev/null
@@ -0,0 +1,3 @@
+USING: project-euler.063 tools.test ;
+
+{ 49 } [ euler063 ] unit-test
diff --git a/extra/project-euler/063/063.factor b/extra/project-euler/063/063.factor
new file mode 100644 (file)
index 0000000..80e3990
--- /dev/null
@@ -0,0 +1,37 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions math.ranges project-euler.common sequences ;
+IN: project-euler.063
+
+! http://projecteuler.net/index.php?section=problems&id=63
+
+! DESCRIPTION
+! -----------
+
+! The 5-digit number, 16807 = 7^5, is also a fifth power. Similarly, the
+! 9-digit number, 134217728 = 8^9, is a ninth power.
+
+! How many n-digit positive integers exist which are also an nth power?
+
+
+! SOLUTION
+! --------
+
+! Only have to check from 1 to 9 because 10^n already has too many digits.
+! In general, x^n has n digits when:
+
+!     10^(n-1) <= x^n < 10^n
+
+! ...take the left side of that equation, solve for n to see where they meet:
+
+!     n = log(10) / [ log(10) - log(x) ]
+
+! Round down since we already know that particular value of n is no good.
+
+: euler063 ( -- answer )
+    9 [1,b] [ log [ 10 log dup ] dip - /i ] sigma ;
+
+! [ euler063 ] 100 ave-time
+! 0 ms ave run time - 0.0 SD (100 trials)
+
+SOLUTION: euler063
diff --git a/extra/project-euler/069/069-tests.factor b/extra/project-euler/069/069-tests.factor
new file mode 100644 (file)
index 0000000..97741c0
--- /dev/null
@@ -0,0 +1,4 @@
+USING: project-euler.069 tools.test ;
+
+{ 510510 } [ euler069 ] unit-test
+{ 510510 } [ euler069a ] unit-test
diff --git a/extra/project-euler/069/069.factor b/extra/project-euler/069/069.factor
new file mode 100644 (file)
index 0000000..eae1d82
--- /dev/null
@@ -0,0 +1,87 @@
+! Copyright (c) 2009 Aaron Schaefer.
+! See http://factorcode.org/license.txt for BSD license.
+USING: combinators fry kernel math math.primes math.primes.factors math.ranges
+    project-euler.common sequences ;
+IN: project-euler.069
+
+! http://projecteuler.net/index.php?section=problems&id=69
+
+! DESCRIPTION
+! -----------
+
+! Euler's Totient function, φ(n) [sometimes called the phi function], is used
+! to determine the number of numbers less than n which are relatively prime to
+! n. For example, as 1, 2, 4, 5, 7, and 8, are all less than nine and
+! relatively prime to nine, φ(9)=6.
+
+!     +----+------------------+------+-----------+
+!     | n  | Relatively Prime | φ(n) | n / φ(n)  |
+!     +----+------------------+------+-----------+
+!     | 2  | 1                | 1    | 2         |
+!     | 3  | 1,2              | 2    | 1.5       |
+!     | 4  | 1,3              | 2    | 2         |
+!     | 5  | 1,2,3,4          | 4    | 1.25      |
+!     | 6  | 1,5              | 2    | 3         |
+!     | 7  | 1,2,3,4,5,6      | 6    | 1.1666... |
+!     | 8  | 1,3,5,7          | 4    | 2         |
+!     | 9  | 1,2,4,5,7,8      | 6    | 1.5       |
+!     | 10 | 1,3,7,9          | 4    | 2.5       |
+!     +----+------------------+------+-----------+
+
+! It can be seen that n = 6 produces a maximum n / φ(n) for n ≤ 10.
+
+! Find the value of n ≤ 1,000,000 for which n / φ(n) is a maximum.
+
+
+! SOLUTION
+! --------
+
+! Brute force
+
+<PRIVATE
+
+: totient-ratio ( n -- m )
+    dup totient / ;
+
+PRIVATE>
+
+: euler069 ( -- answer )
+    2 1000000 [a,b] [ totient-ratio ] map
+    [ supremum ] keep index 2 + ;
+
+! [ euler069 ] 10 ave-time
+! 25210 ms ave run time - 115.37 SD (10 trials)
+
+
+! ALTERNATE SOLUTIONS
+! -------------------
+
+! In order to obtain maximum n / φ(n), φ(n) needs to be low and n needs to be
+! high. Hence we need a number that has the most factors. A number with the
+! most unique factors would have fewer relatively prime.
+
+<PRIVATE
+
+: primorial ( n -- m )
+    {
+        { [ dup 0 = ] [ drop V{ 1 } ] }
+        { [ dup 1 = ] [ drop V{ 2 } ] }
+        [ nth-prime primes-upto ]
+    } cond product ;
+
+: (primorial-upto) ( count limit -- m )
+    '[ dup primorial _ <= ] [ 1+ dup primorial ] produce
+    nip penultimate ;
+
+: primorial-upto ( limit -- m )
+    1 swap (primorial-upto) ;
+
+PRIVATE>
+
+: euler069a ( -- answer )
+    1000000 primorial-upto ;
+
+! [ euler069a ] 100 ave-time
+! 0 ms ave run time - 0.01 SD (100 trials)
+
+SOLUTION: euler069a
index cccf6bf708d75735c750d85e4b5d7d2014261a5f..0fd93a8f2d0fb9afa4b226374c0409f3f1d54f4a 100644 (file)
@@ -32,13 +32,6 @@ IN: project-euler.071
 ! repeatedly until the denominator is as close to 1000000 as possible without
 ! going over.
 
-<PRIVATE
-
-: penultimate ( seq -- elt )
-    dup length 2 - swap nth ;
-
-PRIVATE>
-
 : euler071 ( -- answer )
     2/5 [ dup denominator 1000000 <= ] [ 3/7 mediant dup ] produce
     nip penultimate numerator ;
index 423512465eda8cf7d1d0fa312411c046f6c8db84..c2ffe26d949cbdbeefaf594651d0a4966d7f4d61 100644 (file)
@@ -1,9 +1,10 @@
-! Copyright (c) 2007-2008 Aaron Schaefer.
+! Copyright (c) 2007-2009 Aaron Schaefer.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays kernel make math math.functions math.matrices math.miller-rabin
-    math.order math.parser math.primes.factors math.ranges math.ratios
-    sequences sorting strings unicode.case parser accessors vocabs.parser
-    namespaces vocabs words quotations prettyprint ;
+USING: accessors arrays kernel lists make math math.functions math.matrices
+    math.miller-rabin math.order math.parser math.primes.factors
+    math.primes.lists math.ranges math.ratios namespaces parser prettyprint
+    quotations sequences sorting strings unicode.case vocabs vocabs.parser
+    words ;
 IN: project-euler.common
 
 ! A collection of words used by more than one Project Euler solution
@@ -16,11 +17,13 @@ IN: project-euler.common
 ! log10 - #25, #134
 ! max-path - #18, #67
 ! mediant - #71, #73
+! nth-prime - #7, #69
 ! nth-triangle - #12, #42
 ! number>digits - #16, #20, #30, #34, #35, #38, #43, #52, #55, #56, #92
 ! palindrome? - #4, #36, #55
 ! pandigital? - #32, #38
 ! pentagonal? - #44, #45
+! penultimate - #69, #71
 ! propagate-all - #18, #67
 ! sum-proper-divisors - #21
 ! tau* - #12
@@ -44,7 +47,7 @@ IN: project-euler.common
 
 : (sum-divisors) ( n -- sum )
     dup sqrt >integer [1,b] [
-        [ 2dup mod 0 = [ 2dup / + , ] [ drop ] if ] each
+        [ 2dup divisor? [ 2dup / + , ] [ drop ] if ] each
         dup perfect-square? [ sqrt >fixnum neg , ] [ drop ] if
     ] { } make sum ;
 
@@ -57,7 +60,7 @@ PRIVATE>
     >lower [ CHAR: a - 1+ ] sigma ;
 
 : cartesian-product ( seq1 seq2 -- seq1xseq2 )
-    swap [ swap [ 2array ] with map ] with map concat ;
+    [ [ 2array ] with map ] curry map concat ;
 
 : log10 ( m -- n )
     log 10 log / ;
@@ -75,6 +78,12 @@ PRIVATE>
 : number>digits ( n -- seq )
     [ dup 0 = not ] [ 10 /mod ] produce reverse nip ;
 
+: number-length ( n -- m )
+    log10 floor 1+ >integer ;
+
+: nth-prime ( n -- n )
+    1- lprimes lnth ;
+
 : nth-triangle ( n -- n )
     dup 1+ * 2 / ;
 
@@ -87,6 +96,9 @@ PRIVATE>
 : pentagonal? ( n -- ? )
     dup 0 > [ 24 * 1+ sqrt 1+ 6 / 1 mod zero? ] [ drop f ] if ;
 
+: penultimate ( seq -- elt )
+    dup length 2 - swap nth ;
+
 ! Not strictly needed, but it is nice to be able to dump the triangle after the
 ! propagation
 : propagate-all ( triangle -- new-triangle )
@@ -117,7 +129,7 @@ PRIVATE>
     factor-2s dup [ 1+ ]
     [ perfect-square? -1 0 ? ]
     [ dup sqrt >fixnum [1,b] ] tri* [
-        dupd mod 0 = [ [ 2 + ] dip ] when
+        dupd divisor? [ [ 2 + ] dip ] when
     ] each drop * ;
 
 ! These transforms are for generating primitive Pythagorean triples
@@ -134,4 +146,3 @@ SYNTAX: SOLUTION:
     [ drop in get vocab (>>main) ]
     [ [ . ] swap prefix (( -- )) define-declared ]
     2bi ;
-
index 3d10dbcfbdcc5966d7220b08a51d8d63b78a2596..95d364421500c6c50c315db2c6180d2256040e10 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (c) 2007, 2008 Aaron Schaefer, Samuel Tardieu.
+! Copyright (c) 2007-2009 Aaron Schaefer, Samuel Tardieu.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: definitions io io.files io.pathnames kernel math math.parser
     prettyprint project-euler.ave-time sequences vocabs vocabs.loader
@@ -14,14 +14,15 @@ USING: definitions io io.files io.pathnames kernel math math.parser
     project-euler.037 project-euler.038 project-euler.039 project-euler.040
     project-euler.041 project-euler.042 project-euler.043 project-euler.044
     project-euler.045 project-euler.046 project-euler.047 project-euler.048
-    project-euler.052 project-euler.053 project-euler.055 project-euler.056
-    project-euler.057 project-euler.059 project-euler.067 project-euler.071
-    project-euler.073 project-euler.075 project-euler.076 project-euler.079
-    project-euler.092 project-euler.097 project-euler.099 project-euler.100
-    project-euler.116 project-euler.117 project-euler.134 project-euler.148
-    project-euler.150 project-euler.151 project-euler.164 project-euler.169
-    project-euler.173 project-euler.175 project-euler.186 project-euler.190
-    project-euler.203 project-euler.215 ;
+    project-euler.049 project-euler.052 project-euler.053 project-euler.054
+    project-euler.055 project-euler.056 project-euler.057 project-euler.058
+    project-euler.059 project-euler.063 project-euler.067 project-euler.069
+    project-euler.071 project-euler.073 project-euler.075 project-euler.076
+    project-euler.079 project-euler.092 project-euler.097 project-euler.099
+    project-euler.100 project-euler.116 project-euler.117 project-euler.134
+    project-euler.148 project-euler.150 project-euler.151 project-euler.164
+    project-euler.169 project-euler.173 project-euler.175 project-euler.186
+    project-euler.190 project-euler.203 project-euler.215 ;
 IN: project-euler
 
 <PRIVATE
index a590d9eee0d6b377c12b11353da68eedc544779d..54b489268018b6d339121ad82e21d17e3d3dd397 100644 (file)
 ! Copyright (C) 2009 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: calendar io.encodings.utf8 io.files robots tools.test ;
+USING: calendar io.encodings.utf8 io.files robots tools.test
+urls ;
 IN: robots.tests
 
 [
-{ "http://www.chiplist.com/sitemap.txt" }
-{
-    T{ rules
-        { user-agents V{ "*" } }
-        { allows V{ } }
-        { disallows
-            V{
-                "/cgi-bin/"
-                "/scripts/"
-                "/ChipList2/scripts/"
-                "/ChipList2/styles/"
-                "/ads/"
-                "/ChipList2/ads/"
-                "/advertisements/"
-                "/ChipList2/advertisements/"
-                "/graphics/"
-                "/ChipList2/graphics/"
+    { "http://www.chiplist.com/sitemap.txt" }
+    {
+        T{ rules
+            { user-agents V{ "*" } }
+            { allows V{ } }
+            { disallows
+                V{
+                    URL" /cgi-bin/"
+                    URL" /scripts/"
+                    URL" /ChipList2/scripts/"
+                    URL" /ChipList2/styles/"
+                    URL" /ads/"
+                    URL" /ChipList2/ads/"
+                    URL" /advertisements/"
+                    URL" /ChipList2/advertisements/"
+                    URL" /graphics/"
+                    URL" /ChipList2/graphics/"
+                }
             }
-        }
-        { visit-time
-            {
-                T{ timestamp { hour 2 } }
-                T{ timestamp { hour 5 } }
+            { visit-time
+                {
+                    T{ timestamp { hour 2 } }
+                    T{ timestamp { hour 5 } }
+                }
             }
+            { request-rate 1 }
+            { crawl-delay 1 }
+            { unknowns H{ } }
         }
-        { request-rate 1 }
-        { crawl-delay 1 }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "UbiCrawler" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "DOC" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Zao" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "sitecheck.internetseer.com" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Zealbot" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "MSIECrawler" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "SiteSnagger" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "WebStripper" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "WebCopier" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Fetch" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Offline Explorer" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Teleport" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "TeleportPro" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "WebZIP" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "linko" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "HTTrack" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Microsoft.URL.Control" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Xenu" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "larbin" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "libwww" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "ZyBORG" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "Download Ninja" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "wget" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "grub-client" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "k2spider" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "NPBot" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents V{ "WebReaper" } }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
-    }
-    T{ rules
-        { user-agents
-            V{
-                "abot"
-                "ALeadSoftbot"
-                "BeijingCrawler"
-                "BilgiBot"
-                "bot"
-                "botlist"
-                "BOTW Spider"
-                "bumblebee"
-                "Bumblebee"
-                "BuzzRankingBot"
-                "Charlotte"
-                "Clushbot"
-                "Crawler"
-                "CydralSpider"
-                "DataFountains"
-                "DiamondBot"
-                "Dulance bot"
-                "DYNAMIC"
-                "EARTHCOM.info"
-                "EDI"
-                "envolk"
-                "Exabot"
-                "Exabot-Images"
-                "Exabot-Test"
-                "exactseek-pagereaper"
-                "Exalead NG"
-                "FANGCrawl"
-                "Feed::Find"
-                "flatlandbot"
-                "Gigabot"
-                "GigabotSiteSearch"
-                "GurujiBot"
-                "Hatena Antenna"
-                "Hatena Bookmark"
-                "Hatena RSS"
-                "HatenaScreenshot"
-                "Helix"
-                "HiddenMarket"
-                "HyperEstraier"
-                "iaskspider"
-                "IIITBOT"
-                "InfociousBot"
-                "iVia"
-                "iVia Page Fetcher"
-                "Jetbot"
-                "Kolinka Forum Search"
-                "KRetrieve"
-                "LetsCrawl.com"
-                "Lincoln State Web Browser"
-                "Links4US-Crawler"
-                "LOOQ"
-                "Lsearch/sondeur"
-                "MapoftheInternet.com"
-                "NationalDirectory"
-                "NetCarta_WebMapper"
-                "NewsGator"
-                "NextGenSearchBot"
-                "ng"
-                "nicebot"
-                "NP"
-                "NPBot"
-                "Nudelsalat"
-                "Nutch"
-                "OmniExplorer_Bot"
-                "OpenIntelligenceData"
-                "Oracle Enterprise Search"
-                "Pajaczek"
-                "panscient.com"
-                "PeerFactor 404 crawler"
-                "PeerFactor Crawler"
-                "PlantyNet"
-                "PlantyNet_WebRobot"
-                "plinki"
-                "PMAFind"
-                "Pogodak!"
-                "QuickFinder Crawler"
-                "Radiation Retriever"
-                "Reaper"
-                "RedCarpet"
-                "ScorpionBot"
-                "Scrubby"
-                "Scumbot"
-                "searchbot"
-                "Seeker.lookseek.com"
-                "SeznamBot"
-                "ShowXML"
-                "snap.com"
-                "snap.com beta crawler"
-                "Snapbot"
-                "SnapPreviewBot"
-                "sohu"
-                "SpankBot"
-                "Speedy Spider"
-                "Speedy_Spider"
-                "SpeedySpider"
-                "spider"
-                "SquigglebotBot"
-                "SurveyBot"
-                "SynapticSearch"
-                "T-H-U-N-D-E-R-S-T-O-N-E"
-                "Talkro Web-Shot"
-                "Tarantula"
-                "TerrawizBot"
-                "TheInformant"
-                "TMCrawler"
-                "TridentSpider"
-                "Tutorial Crawler"
-                "Twiceler"
-                "unwrapbot"
-                "URI::Fetch"
-                "VengaBot"
-                "Vonna.com b o t"
-                "Vortex"
-                "Votay bot"
-                "WebAlta Crawler"
-                "Webbot"
-                "Webclipping.com"
-                "WebCorp"
-                "Webinator"
-                "WIRE"
-                "WISEbot"
-                "Xerka WebBot"
-                "XSpider"
-                "YodaoBot"
-                "Yoono"
-                "yoono"
+        T{ rules
+            { user-agents V{ "UbiCrawler" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "DOC" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Zao" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "sitecheck.internetseer.com" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Zealbot" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "MSIECrawler" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "SiteSnagger" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "WebStripper" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "WebCopier" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Fetch" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Offline Explorer" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Teleport" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "TeleportPro" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "WebZIP" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "linko" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "HTTrack" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Microsoft.URL.Control" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Xenu" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "larbin" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "libwww" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "ZyBORG" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "Download Ninja" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "wget" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "grub-client" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "k2spider" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "NPBot" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents V{ "WebReaper" } }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
+        }
+        T{ rules
+            { user-agents
+                V{
+                    "abot"
+                    "ALeadSoftbot"
+                    "BeijingCrawler"
+                    "BilgiBot"
+                    "bot"
+                    "botlist"
+                    "BOTW Spider"
+                    "bumblebee"
+                    "Bumblebee"
+                    "BuzzRankingBot"
+                    "Charlotte"
+                    "Clushbot"
+                    "Crawler"
+                    "CydralSpider"
+                    "DataFountains"
+                    "DiamondBot"
+                    "Dulance bot"
+                    "DYNAMIC"
+                    "EARTHCOM.info"
+                    "EDI"
+                    "envolk"
+                    "Exabot"
+                    "Exabot-Images"
+                    "Exabot-Test"
+                    "exactseek-pagereaper"
+                    "Exalead NG"
+                    "FANGCrawl"
+                    "Feed::Find"
+                    "flatlandbot"
+                    "Gigabot"
+                    "GigabotSiteSearch"
+                    "GurujiBot"
+                    "Hatena Antenna"
+                    "Hatena Bookmark"
+                    "Hatena RSS"
+                    "HatenaScreenshot"
+                    "Helix"
+                    "HiddenMarket"
+                    "HyperEstraier"
+                    "iaskspider"
+                    "IIITBOT"
+                    "InfociousBot"
+                    "iVia"
+                    "iVia Page Fetcher"
+                    "Jetbot"
+                    "Kolinka Forum Search"
+                    "KRetrieve"
+                    "LetsCrawl.com"
+                    "Lincoln State Web Browser"
+                    "Links4US-Crawler"
+                    "LOOQ"
+                    "Lsearch/sondeur"
+                    "MapoftheInternet.com"
+                    "NationalDirectory"
+                    "NetCarta_WebMapper"
+                    "NewsGator"
+                    "NextGenSearchBot"
+                    "ng"
+                    "nicebot"
+                    "NP"
+                    "NPBot"
+                    "Nudelsalat"
+                    "Nutch"
+                    "OmniExplorer_Bot"
+                    "OpenIntelligenceData"
+                    "Oracle Enterprise Search"
+                    "Pajaczek"
+                    "panscient.com"
+                    "PeerFactor 404 crawler"
+                    "PeerFactor Crawler"
+                    "PlantyNet"
+                    "PlantyNet_WebRobot"
+                    "plinki"
+                    "PMAFind"
+                    "Pogodak!"
+                    "QuickFinder Crawler"
+                    "Radiation Retriever"
+                    "Reaper"
+                    "RedCarpet"
+                    "ScorpionBot"
+                    "Scrubby"
+                    "Scumbot"
+                    "searchbot"
+                    "Seeker.lookseek.com"
+                    "SeznamBot"
+                    "ShowXML"
+                    "snap.com"
+                    "snap.com beta crawler"
+                    "Snapbot"
+                    "SnapPreviewBot"
+                    "sohu"
+                    "SpankBot"
+                    "Speedy Spider"
+                    "Speedy_Spider"
+                    "SpeedySpider"
+                    "spider"
+                    "SquigglebotBot"
+                    "SurveyBot"
+                    "SynapticSearch"
+                    "T-H-U-N-D-E-R-S-T-O-N-E"
+                    "Talkro Web-Shot"
+                    "Tarantula"
+                    "TerrawizBot"
+                    "TheInformant"
+                    "TMCrawler"
+                    "TridentSpider"
+                    "Tutorial Crawler"
+                    "Twiceler"
+                    "unwrapbot"
+                    "URI::Fetch"
+                    "VengaBot"
+                    "Vonna.com b o t"
+                    "Vortex"
+                    "Votay bot"
+                    "WebAlta Crawler"
+                    "Webbot"
+                    "Webclipping.com"
+                    "WebCorp"
+                    "Webinator"
+                    "WIRE"
+                    "WISEbot"
+                    "Xerka WebBot"
+                    "XSpider"
+                    "YodaoBot"
+                    "Yoono"
+                    "yoono"
+                }
             }
+            { allows V{ } }
+            { disallows V{ URL" /" } }
+            { unknowns H{ } }
         }
-        { allows V{ } }
-        { disallows V{ "/" } }
-        { unknowns H{ } }
     }
-}
 ] [ "vocab:robots/robots.txt" utf8 file-contents parse-robots.txt ] unit-test
index 1b2422f06ea33d6ccd585ae5be3cecabe0a93220..3c0eb045f7598046f8dee75b212a9cf0d06232c7 100644 (file)
@@ -3,11 +3,21 @@
 USING: accessors http.client kernel unicode.categories
 sequences urls splitting combinators splitting.monotonic
 combinators.short-circuit assocs unicode.case arrays
-math.parser calendar.format make ;
+math.parser calendar.format make fry present globs
+multiline regexp.combinators regexp ;
 IN: robots
 
 ! visit-time is GMT, request-rate is pages/second 
 ! crawl-rate is seconds
+
+TUPLE: robots site sitemap rules rules-quot ;
+
+: <robots> ( site sitemap rules -- robots )
+    \ robots new
+        swap >>rules
+        swap >>sitemap
+        swap >>site ;
+
 TUPLE: rules user-agents allows disallows
 visit-time request-rate crawl-delay unknowns ;
 
@@ -40,8 +50,8 @@ visit-time request-rate crawl-delay unknowns ;
         H{ } clone >>unknowns ;
 
 : add-user-agent ( rules agent -- rules ) over user-agents>> push ;
-: add-allow ( rules allow -- rules ) over allows>> push ;
-: add-disallow ( rules disallow -- rules ) over disallows>> push ;
+: add-allow ( rules allow -- rules ) >url over allows>> push ;
+: add-disallow ( rules disallow -- rules ) >url over disallows>> push ;
 
 : parse-robots.txt-line ( rules seq -- rules )
     first2 swap {
@@ -57,6 +67,19 @@ visit-time request-rate crawl-delay unknowns ;
         [ pick unknowns>> push-at ]
     } case ;
 
+: derive-urls ( url seq -- seq' )
+    [ derive-url present ] with { } map-as ;
+
+: robot-rules-quot ( robots -- quot )
+    [
+        [ site>> ] [ rules>> allows>> ] bi
+        derive-urls [ <glob> ] map
+        <or>
+    ] [
+        [ site>> ] [ rules>> disallows>> ] bi
+        derive-urls [ <glob> ] map <and> <not>
+    ] bi 2array <or> '[ _ matches? ] ;
+
 PRIVATE>
 
 : parse-robots.txt ( string -- sitemaps rules-seq )
@@ -64,5 +87,6 @@ PRIVATE>
         [ <rules> dup ] dip [ parse-robots.txt-line drop ] with each
     ] map ;
 
-: robots ( url -- sitemaps rules-seq )
-    get-robots.txt nip parse-robots.txt ;
+: robots ( url -- robots )
+    >url
+    dup get-robots.txt nip parse-robots.txt <robots> ;
diff --git a/extra/sequence-parser/sequence-parser-tests.factor b/extra/sequence-parser/sequence-parser-tests.factor
new file mode 100644 (file)
index 0000000..da097f4
--- /dev/null
@@ -0,0 +1,204 @@
+USING: tools.test sequence-parser unicode.categories kernel
+accessors ;
+IN: sequence-parser.tests
+
+[ "hello" ]
+[ "hello" [ take-rest ] parse-sequence ] unit-test
+
+[ "hi" " how are you?" ]
+[
+    "hi how are you?"
+    [ [ [ current blank? ] take-until ] [ take-rest ] bi ] parse-sequence
+] unit-test
+
+[ "foo" ";bar" ]
+[
+    "foo;bar" [
+        [ CHAR: ; take-until-object ] [ take-rest ] bi
+    ] parse-sequence
+] unit-test
+
+[ "foo " "and bar" ]
+[
+    "foo and bar" [
+        [ "and" take-until-sequence ] [ take-rest ] bi 
+    ] parse-sequence
+] unit-test
+
+[ "foo " " bar" ]
+[
+    "foo and bar" [
+        [ "and" take-until-sequence ]
+        [ "and" take-sequence drop ]
+        [ take-rest ] tri
+    ] parse-sequence
+] unit-test
+
+[ "foo " " bar" ]
+[
+    "foo and bar" [
+        [ "and" take-until-sequence* ]
+        [ take-rest ] bi
+    ] parse-sequence
+] unit-test
+
+[ { 1 2 } ]
+[ { 1 2 3 4 } <sequence-parser> { 3 4 } take-until-sequence ] unit-test
+
+[ f "aaaa" ]
+[
+    "aaaa" <sequence-parser>
+    [ "b" take-until-sequence ] [ take-rest ] bi
+] unit-test
+
+[ 6 ]
+[
+    "      foo   " [ skip-whitespace n>> ] parse-sequence
+] unit-test
+
+[ { 1 2 } ]
+[ { 1 2 3 } <sequence-parser> [ current 3 = ] take-until ] unit-test
+
+[ "ab" ]
+[ "abcd" <sequence-parser> "ab" take-sequence ] unit-test
+
+[ f ]
+[ "abcd" <sequence-parser> "lol" take-sequence ] unit-test
+
+[ "ab" ]
+[
+    "abcd" <sequence-parser>
+    [ "lol" take-sequence drop ] [ "ab" take-sequence ] bi
+] unit-test
+
+[ "" ]
+[ "abcd" <sequence-parser> "" take-sequence ] unit-test
+
+[ "cd" ]
+[ "abcd" <sequence-parser> [ "ab" take-sequence drop ] [ "cd" take-sequence ] bi ] unit-test
+
+[ f ]
+[
+    "\"abc\" asdf" <sequence-parser>
+    [ CHAR: \ CHAR: " take-quoted-string drop ] [ "asdf" take-sequence ] bi
+] unit-test
+
+[ "abc\\\"def" ]
+[
+    "\"abc\\\"def\" asdf" <sequence-parser>
+    CHAR: \ CHAR: " take-quoted-string
+] unit-test
+
+[ "asdf" ]
+[
+    "\"abc\" asdf" <sequence-parser>
+    [ CHAR: \ CHAR: " take-quoted-string drop ]
+    [ skip-whitespace "asdf" take-sequence ] bi
+] unit-test
+
+[ f ]
+[
+    "\"abc asdf" <sequence-parser>
+    CHAR: \ CHAR: " take-quoted-string
+] unit-test
+
+[ "\"abc" ]
+[
+    "\"abc asdf" <sequence-parser>
+    [ CHAR: \ CHAR: " take-quoted-string drop ]
+    [ "\"abc" take-sequence ] bi
+] unit-test
+
+[ "c" ]
+[ "c" <sequence-parser> take-token ] unit-test
+
+[ f ]
+[ "" <sequence-parser> take-token ] unit-test
+
+[ "abcd e \\\"f g" ]
+[ "\"abcd e \\\"f g\"" <sequence-parser> CHAR: \ CHAR: " take-token* ] unit-test
+
+[ "" ]
+[ "" <sequence-parser> take-rest ] unit-test
+
+[ "" ]
+[ "abc" <sequence-parser> dup "abc" take-sequence drop take-rest ] unit-test
+
+[ f ]
+[ "abc" <sequence-parser> "abcdefg" take-sequence ] unit-test
+
+[ "1234" ]
+[ "1234f" <sequence-parser> take-integer ] unit-test
+
+[ "yes" ]
+[
+    "yes1234f" <sequence-parser>
+    [ take-integer drop ] [ "yes" take-sequence ] bi 
+] unit-test
+
+[ f ] [ "" <sequence-parser> 4 take-n ] unit-test
+[ "abcd" ] [ "abcd" <sequence-parser> 4 take-n ] unit-test
+[ "abcd" "efg" ] [ "abcdefg" <sequence-parser> [ 4 take-n ] [ take-rest ] bi ] unit-test
+
+[ "asdfasdf" ] [
+    "/*asdfasdf*/" <sequence-parser> take-c-comment 
+] unit-test
+
+[ "k" ] [
+    "/*asdfasdf*/k" <sequence-parser> [ take-c-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "omg" ] [
+    "//asdfasdf\nomg" <sequence-parser>
+    [ take-c++-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "omg" ] [
+    "omg" <sequence-parser>
+    [ take-c++-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "/*asdfasdf" ] [
+    "/*asdfasdf" <sequence-parser> [ take-c-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "asdf" "eoieoei" ] [
+    "//asdf\neoieoei" <sequence-parser>
+    [ take-c++-comment ] [ take-rest ] bi
+] unit-test
+
+[ f "33asdf" ]
+[ "33asdf" <sequence-parser> [ take-c-identifier ] [ take-rest ] bi ] unit-test
+
+[ "asdf" ]
+[ "asdf" <sequence-parser> take-c-identifier ] unit-test
+
+[ "_asdf" ]
+[ "_asdf" <sequence-parser> take-c-identifier ] unit-test
+
+[ "_asdf400" ]
+[ "_asdf400" <sequence-parser> take-c-identifier ] unit-test
+
+[ "123" ]
+[ "123jjj" <sequence-parser> take-c-integer ] unit-test
+
+[ "123uLL" ]
+[ "123uLL" <sequence-parser> take-c-integer ] unit-test
+
+[ "123ull" ]
+[ "123ull" <sequence-parser> take-c-integer ] unit-test
+
+[ "123u" ]
+[ "123u" <sequence-parser> take-c-integer ] unit-test
+
+[ 36 ]
+[
+    "    //jofiejoe\n    //eoieow\n/*asdf*/\n      "
+    <sequence-parser> skip-whitespace/comments n>>
+] unit-test
+
+[ f ]
+[ "\n" <sequence-parser> take-integer ] unit-test
+
+[ "\n" ] [ "\n" <sequence-parser> [ ] take-while ] unit-test
+[ f ] [ "\n" <sequence-parser> [ not ] take-while ] unit-test
diff --git a/extra/sequence-parser/sequence-parser.factor b/extra/sequence-parser/sequence-parser.factor
new file mode 100644 (file)
index 0000000..4cc10fd
--- /dev/null
@@ -0,0 +1,259 @@
+! Copyright (C) 2005, 2009 Daniel Ehrenberg, Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: namespaces math kernel sequences accessors fry circular
+unicode.case unicode.categories locals combinators.short-circuit
+make combinators io splitting math.parser math.ranges
+generalizations sorting.functor math.order sorting.slots ;
+IN: sequence-parser
+
+TUPLE: sequence-parser sequence n ;
+
+: <sequence-parser> ( sequence -- sequence-parser )
+    sequence-parser new
+        swap >>sequence
+        0 >>n ;
+
+:: with-sequence-parser ( sequence-parser quot -- seq/f )
+    sequence-parser n>> :> n
+    sequence-parser quot call [
+        n sequence-parser (>>n) f
+    ] unless* ; inline
+
+: offset  ( sequence-parser offset -- char/f )
+    swap
+    [ n>> + ] [ sequence>> ?nth ] bi ; inline
+
+: current ( sequence-parser -- char/f ) 0 offset ; inline
+
+: previous ( sequence-parser -- char/f ) -1 offset ; inline
+
+: peek-next ( sequence-parser -- char/f ) 1 offset ; inline
+
+: advance ( sequence-parser -- sequence-parser )
+    [ 1 + ] change-n ; inline
+
+: advance* ( sequence-parser -- )
+    advance drop ; inline
+
+: get+increment ( sequence-parser -- char/f )
+    [ current ] [ advance drop ] bi ; inline
+
+:: skip-until ( sequence-parser quot: ( obj -- ? ) -- )
+    sequence-parser current [
+        sequence-parser quot call
+        [ sequence-parser advance quot skip-until ] unless
+    ] when ; inline recursive
+
+: sequence-parse-end? ( sequence-parser -- ? ) current not ;
+
+: take-until ( sequence-parser quot: ( obj -- ? ) -- sequence/f )
+    over sequence-parse-end? [
+        2drop f
+    ] [
+        [ drop n>> ]
+        [ skip-until ]
+        [ drop [ n>> ] [ sequence>> ] bi ] 2tri subseq f like
+    ] if ; inline
+
+: take-while ( sequence-parser quot: ( obj -- ? ) -- sequence/f )
+    [ not ] compose take-until ; inline
+
+: <safe-slice> ( from to seq -- slice/f )
+    3dup {
+        [ 2drop 0 < ]
+        [ [ drop ] 2dip length > ]
+        [ drop > ]
+    } 3|| [ 3drop f ] [ slice boa ] if ; inline
+
+:: take-sequence ( sequence-parser sequence -- obj/f )
+    sequence-parser [ n>> dup sequence length + ] [ sequence>> ] bi
+    <safe-slice> sequence sequence= [
+        sequence
+        sequence-parser [ sequence length + ] change-n drop
+    ] [
+        f
+    ] if ;
+
+: take-sequence* ( sequence-parser sequence -- )
+    take-sequence drop ;
+
+:: take-until-sequence ( sequence-parser sequence -- sequence'/f )
+    sequence-parser n>> :> saved
+    sequence length <growing-circular> :> growing
+    sequence-parser
+    [
+        current growing push-growing-circular
+        sequence growing sequence=
+    ] take-until :> found
+    growing sequence sequence= [
+        found dup length
+        growing length 1- - head
+        sequence-parser [ growing length - 1 + ] change-n drop
+        ! sequence-parser advance drop
+    ] [
+        saved sequence-parser (>>n)
+        f
+    ] if ;
+
+:: take-until-sequence* ( sequence-parser sequence -- sequence'/f )
+    sequence-parser sequence take-until-sequence :> out
+    out [
+        sequence-parser [ sequence length + ] change-n drop
+    ] when out ;
+
+: skip-whitespace ( sequence-parser -- sequence-parser )
+    [ [ current blank? not ] take-until drop ] keep ;
+
+: skip-whitespace-eol ( sequence-parser -- sequence-parser )
+    [ [ current " \t\r" member? not ] take-until drop ] keep ;
+
+: take-c-comment ( sequence-parser -- seq/f )
+    [
+        dup "/*" take-sequence [
+            "*/" take-until-sequence*
+        ] [
+            drop f
+        ] if
+    ] with-sequence-parser ;
+
+: take-c++-comment ( sequence-parser -- seq/f )
+    [
+        dup "//" take-sequence [
+            [
+                [
+                    { [ current CHAR: \n = ] [ sequence-parse-end? ] } 1||
+                ] take-until
+            ] [
+                advance drop
+            ] bi
+        ] [
+            drop f
+        ] if
+    ] with-sequence-parser ;
+
+: skip-whitespace/comments ( sequence-parser -- sequence-parser )
+    skip-whitespace-eol
+    {
+        { [ dup take-c-comment ] [ skip-whitespace/comments ] }
+        { [ dup take-c++-comment ] [ skip-whitespace/comments ] }
+        [ ]
+    } cond ;
+
+: take-define-identifier ( sequence-parser -- string )
+    skip-whitespace/comments
+    [ current { [ blank? ] [ CHAR: ( = ] } 1|| ] take-until ;
+
+: take-rest-slice ( sequence-parser -- sequence/f )
+    [ sequence>> ] [ n>> ] bi
+    2dup [ length ] dip < [ 2drop f ] [ tail-slice ] if ; inline
+
+: take-rest ( sequence-parser -- sequence )
+    [ take-rest-slice ] [ sequence>> like ] bi ;
+
+: take-until-object ( sequence-parser obj -- sequence )
+    '[ current _ = ] take-until ;
+
+: parse-sequence ( sequence quot -- )
+    [ <sequence-parser> ] dip call ; inline
+
+:: take-quoted-string ( sequence-parser escape-char quote-char -- string )
+    sequence-parser n>> :> start-n
+    sequence-parser advance
+    [
+        {
+            [ { [ previous escape-char = ] [ current quote-char = ] } 1&& ]
+            [ current quote-char = not ]
+        } 1||
+    ] take-while :> string
+    sequence-parser current quote-char = [
+        sequence-parser advance* string
+    ] [
+        start-n sequence-parser (>>n) f
+    ] if ;
+
+: (take-token) ( sequence-parser -- string )
+    skip-whitespace [ current { [ blank? ] [ f = ] } 1|| ] take-until ;
+
+:: take-token* ( sequence-parser escape-char quote-char -- string/f )
+    sequence-parser skip-whitespace
+    dup current {
+        { quote-char [ escape-char quote-char take-quoted-string ] }
+        { f [ drop f ] }
+        [ drop (take-token) ]
+    } case ;
+
+: take-token ( sequence-parser -- string/f )
+    CHAR: \ CHAR: " take-token* ;
+
+: take-integer ( sequence-parser -- n/f )
+    [ current digit? ] take-while ;
+
+:: take-n ( sequence-parser n -- seq/f )
+    n sequence-parser [ n>> + ] [ sequence>> length ] bi > [
+        f
+    ] [
+        sequence-parser n>> dup n + sequence-parser sequence>> subseq
+        sequence-parser [ n + ] change-n drop
+    ] if ;
+
+: c-identifier-begin? ( ch -- ? )
+    CHAR: a CHAR: z [a,b]
+    CHAR: A CHAR: Z [a,b]
+    { CHAR: _ } 3append member? ;
+
+: c-identifier-ch? ( ch -- ? )
+    CHAR: a CHAR: z [a,b]
+    CHAR: A CHAR: Z [a,b]
+    CHAR: 0 CHAR: 9 [a,b]
+    { CHAR: _ } 4 nappend member? ;
+
+: (take-c-identifier) ( sequence-parser -- string/f )
+    dup current c-identifier-begin? [
+        [ current c-identifier-ch? ] take-while
+    ] [
+        drop f
+    ] if ;
+
+: take-c-identifier ( sequence-parser -- string/f )
+    [ (take-c-identifier) ] with-sequence-parser ;
+
+<< "length" [ length ] define-sorting >>
+
+: sort-tokens ( seq -- seq' )
+    { length>=< <=> } sort-by ;
+
+: take-first-matching ( sequence-parser seq -- seq )
+    swap
+    '[ _ [ swap take-sequence ] with-sequence-parser ] find nip ;
+
+
+: take-longest ( sequence-parser seq -- seq )
+    sort-tokens take-first-matching ;
+
+: take-c-integer ( sequence-parser -- string/f )
+    [
+        dup take-integer [
+            swap
+            { "ull" "uLL" "Ull" "ULL" "ll" "LL" "l" "L" "u" "U" }
+            take-longest [ append ] when*
+        ] [
+            drop f
+        ] if*
+    ] with-sequence-parser ;
+
+CONSTANT: c-punctuators
+    {
+        "[" "]" "(" ")" "{" "}" "." "->"
+        "++" "--" "&" "*" "+" "-" "~" "!"
+        "/" "%" "<<" ">>" "<" ">" "<=" ">=" "==" "!=" "^" "|" "&&" "||"
+        "?" ":" ";" "..."
+        "=" "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" "&=" "^=" "|="
+        "," "#" "##"
+        "<:" ":>" "<%" "%>" "%:" "%:%:"
+    }
+
+: take-c-punctuator ( sequence-parser -- string/f )
+    c-punctuators take-longest ;
+
+: write-full ( sequence-parser -- ) sequence>> write ;
+: write-rest ( sequence-parser -- ) take-rest write ;
index 148e5b96f95ae8749c49a7f465d8f001dd589966..003b6bb58bd295df1eb142cdf0dd8b46b8cd3473 100644 (file)
@@ -2,10 +2,10 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors continuations db db.sqlite db.tuples db.types
 io.directories io.files.temp kernel io.streams.string calendar
-debugger combinators.smart sequences ;
+debugger combinators.smart sequences arrays ;
 IN: site-watcher.db
 
-TUPLE: account account-id account-name email twitter sms ;
+TUPLE: account account-name email twitter sms ;
 
 : <account> ( account-name email -- account )
     account new
@@ -25,6 +25,12 @@ TUPLE: site site-id url up? changed? last-up error last-error ;
     site new
         swap >>url ;
 
+: site-with-url ( url -- site )
+    <site> select-tuple ;
+
+: site-with-id ( id -- site )
+    site new swap >>site-id select-tuple ;
+
 site "SITE" {
     { "site-id" "SITE_ID" INTEGER +db-assigned-id+ }
     { "url" "URL" VARCHAR }
@@ -47,9 +53,41 @@ watching-site "WATCHING_SITE" {
     { "site-id" "SITE_ID" INTEGER +user-assigned-id+ }
 } define-persistent
 
-TUPLE: reporting-site email url up? changed? last-up? error last-error ;
+TUPLE: spidering-site < watching-site max-depth max-count ;
+
+C: <spidering-site> spidering-site
+
+SLOT: site
 
-<PRIVATE
+M: watching-site site>>
+    site-id>> site-with-id ;
+
+SLOT: account
+
+M: watching-site account>>
+    account-name>> account new swap >>account-name select-tuple ;
+
+spidering-site "SPIDERING_SITE" {
+    { "max-depth" "MAX_DEPTH" INTEGER }
+    { "max-count" "MAX_COUNT" INTEGER }
+} define-persistent
+
+: spidering-sites ( username -- sites )
+    spidering-site new swap >>account-name select-tuples ;
+
+: insert-site ( url -- site )
+    <site> dup select-tuple [ ] [ dup t >>up? insert-tuple ] ?if ;
+
+: select-account/site ( username url -- account site )
+    insert-site site-id>> ;
+
+: add-spidered-site ( username url -- )
+    select-account/site 10 10 <spidering-site> insert-tuple ;
+
+: remove-spidered-site ( username url -- )
+    select-account/site 10 10 <spidering-site> delete-tuples ;
+
+TUPLE: reporting-site site-id email url up? changed? last-up? error last-error ;
 
 : set-notify-site-watchers ( site new-up? -- site )
     [ over up?>> = [ t >>changed? ] unless ] keep >>up? ;
@@ -72,18 +110,10 @@ TUPLE: reporting-site email url up? changed? last-up? error last-error ;
     [ [ reporting-site boa ] input<sequence ] map
     "update site set changed = 0;" sql-command ;
 
-: insert-site ( url -- site )
-    <site> dup select-tuple [ ] [ dup t >>up? insert-tuple ] ?if ;
-
 : insert-account ( account-name email -- ) <account> insert-tuple ;
 
 : find-sites ( -- seq ) f <site> select-tuples ;
 
-: select-account/site ( username url -- account site )
-    insert-site site-id>> ;
-
-PRIVATE>
-
 : watch-site ( username url -- )
     select-account/site <watching-site> insert-tuple ;
 
diff --git a/extra/site-watcher/email/authors.txt b/extra/site-watcher/email/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/site-watcher/email/email.factor b/extra/site-watcher/email/email.factor
new file mode 100644 (file)
index 0000000..d028788
--- /dev/null
@@ -0,0 +1,14 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: smtp namespaces accessors kernel arrays ;
+IN: site-watcher.email
+
+SYMBOL: site-watcher-from
+site-watcher-from [ "factor-site-watcher@gmail.com" ] initialize
+
+: send-site-email ( watching-site body subject -- )
+    [ account>> email>> ] 2dip
+    pick [
+        [ <email> site-watcher-from get >>from ] 3dip
+        [ 1array >>to ] [ >>body ] [ >>subject ] tri* send-email 
+    ] [ 3drop ] if ;
\ No newline at end of file
index b067504e2efb1f6139d91f4f42f9e26fc8947b64..e58d5a79d5fa7d8c5f556994b4a1a53b30314ec0 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: db.tuples locals site-watcher site-watcher.db
 site-watcher.private kernel db io.directories io.files.temp
-continuations site-watcher.db.private db.sqlite
+continuations db.sqlite
 sequences tools.test ;
 IN: site-watcher.tests
 
index 114cdf32591da1a5fe7c2dde9ceb91f542c3d587..535c8cd6261e942548cd35f027b07ed5fc475114 100644 (file)
@@ -3,13 +3,9 @@
 USING: accessors alarms arrays calendar combinators
 combinators.smart continuations debugger http.client fry
 init io.streams.string kernel locals math math.parser db
-namespaces sequences site-watcher.db site-watcher.db.private
-smtp ;
+namespaces sequences site-watcher.db site-watcher.email ;
 IN: site-watcher
 
-SYMBOL: site-watcher-from
-"factor-site-watcher@gmail.com" site-watcher-from set-global
-
 SYMBOL: site-watcher-frequency
 5 minutes site-watcher-frequency set-global
  
@@ -23,34 +19,31 @@ SYMBOL: running-site-watcher
         [ dup url>> http-get 2drop site-good ] [ site-bad ] recover
     ] each ;
 
-: site-up-email ( email site -- email )
+: site-up-email ( site -- body )
     last-up>> now swap time- duration>minutes 60 /mod
     [ >integer number>string ] bi@
     [ " hours, " append ] [ " minutes" append ] bi* append
-    "Site was down for (at least): " prepend >>body ;
+    "Site was down for (at least): " prepend ;
 
-: site-down-email ( email site -- email ) error>> >>body ;
+: site-down-email ( site -- body ) error>> ;
 
 : send-report ( site -- )
-    [ <email> ] dip
-    {
-        [ email>> 1array >>to ]
-        [ drop site-watcher-from get "factor.site.watcher@gmail.com" or >>from ]
-        [ dup up?>> [ site-up-email ] [ site-down-email ] if ]
-        [ [ url>> ] [ up?>> "up" "down" ? ] bi " is " glue >>subject ]
-    } cleave send-email ;
+    [ ]
+    [ dup up?>> [ site-up-email ] [ site-down-email ] if ]
+    [ [ url>> ] [ up?>> "up" "down" ? ] bi " is " glue ] tri
+    send-site-email ;
 
 : send-reports ( seq -- )
     [ ] [ [ send-report ] each ] if-empty ;
 
 PRIVATE>
 
-: watch-sites ( db -- )
-    [ find-sites check-sites sites-to-report send-reports ] with-db ;
+: watch-sites ( -- )
+    find-sites check-sites sites-to-report send-reports ;
 
 : run-site-watcher ( db -- )
     [ running-site-watcher get ] dip '[ 
-        [ _ watch-sites ] site-watcher-frequency get every
+        [ _ [ watch-sites ] with-db ] site-watcher-frequency get every
         running-site-watcher set
     ] unless ;
 
diff --git a/extra/site-watcher/spider/authors.txt b/extra/site-watcher/spider/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/site-watcher/spider/spider.factor b/extra/site-watcher/spider/spider.factor
new file mode 100644 (file)
index 0000000..335f1f1
--- /dev/null
@@ -0,0 +1,25 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: site-watcher.db site-watcher.email site-watcher.spider
+spider spider.report
+accessors kernel sequences
+xml.writer concurrency.combinators ;
+IN: site-watcher.spider
+
+: <site-spider> ( spidering-site -- spider )
+    [ max-depth>> ]
+    [ max-count>> ]
+    [ site>> url>> ]
+    tri
+    <spider>
+        swap >>max-count
+        swap >>max-depth ;
+
+: spider-and-email ( spidering-site -- )
+    [ ]
+    [ <site-spider> run-spider spider-report xml>string ]
+    [ site>> url>> "Spidered " prefix ] tri
+    send-site-email ;
+
+: spider-sites ( -- )
+    f spidering-sites [ spider-and-email ] parallel-each ;
\ No newline at end of file
diff --git a/extra/spider/report/authors.txt b/extra/spider/report/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/spider/report/report.factor b/extra/spider/report/report.factor
new file mode 100644 (file)
index 0000000..7779b23
--- /dev/null
@@ -0,0 +1,124 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs combinators kernel math
+math.statistics namespaces sequences sorting xml.syntax
+spider urls html ;
+IN: spider.report
+
+SYMBOL: network-failures
+SYMBOL: broken-pages
+SYMBOL: timings
+
+: record-broken-page ( url spider-result -- )
+    headers>> [ code>> ] [ message>> ] bi 2array 2array
+    broken-pages push ;
+
+: record-page-timings ( url spider-result -- )
+    fetched-in>> 2array timings get push ;
+
+: record-network-failure ( url -- )
+    network-failures get push ;
+
+: process-result ( url spider-result -- )
+    {
+        { f [ record-network-failure ] }
+        [
+            dup headers>> code>> 200 =
+            [ record-page-timings ] [ record-broken-page ] if
+        ]
+    } case ;
+
+CONSTANT: slowest 5
+
+SYMBOL: slowest-pages
+SYMBOL: mean-time
+SYMBOL: median-time
+SYMBOL: time-std
+
+: process-timings ( -- )
+    timings get sort-values
+    [ slowest short tail* reverse slowest-pages set ]
+    [
+        values [
+            [ mean 1000000 /f mean-time set ]
+            [ median 1000000 /f median-time set ]
+            [ std 1000000 /f time-std set ] tri
+        ] unless-empty
+    ] bi ;
+
+: process-results ( results -- )
+    V{ } clone network-failures set
+    V{ } clone broken-pages set
+    V{ } clone timings set
+    [ process-result ] assoc-each
+    process-timings ;
+
+: info-table ( alist -- html )
+    [
+        first2 dupd 1000000 /f
+        [XML
+        <tr><td><a href=<->><-></a></td><td><-> seconds</td></tr>
+        XML]
+    ] map [XML <table border="1"><-></table> XML] ;
+
+: report-broken-pages ( -- html )
+    broken-pages get info-table ;
+
+: report-network-failures ( -- html )
+    network-failures get [
+        dup [XML <li><a href=<->><-></a></li> XML]
+    ] map [XML <ul><-></ul> XML] ;
+
+: slowest-pages-table ( -- html )
+    slowest-pages get info-table ;
+
+: timing-summary-table ( -- html )
+    mean-time get
+    median-time get
+    time-std get
+    [XML
+    <table border="1">
+    <tr><th>Mean</th><td><-> seconds</td></tr>
+    <tr><th>Median</th><td><-> seconds</td></tr>
+    <tr><th>Standard deviation</th><td><-> seconds</td></tr>
+    </table>
+    XML] ;
+
+: report-timings ( -- html )
+    slowest-pages-table
+    timing-summary-table
+    [XML
+    <h3>Slowest pages</h3>
+    <->
+
+    <h3>Summary</h3>
+    <->
+    XML] ;
+
+: generate-report ( -- html )
+    url get dup
+    report-broken-pages
+    report-network-failures
+    report-timings
+    [XML
+    <h1>Spider report</h1>
+    URL: <a href=<->><-></a>
+
+    <h2>Broken pages</h2>
+    <->
+
+    <h2>Network failures</h2>
+    <->
+
+    <h2>Load times</h2>
+    <->
+    XML] ;
+
+: spider-report ( spider -- html )
+    [ "Spider report" f ] dip
+    [
+        [ base>> url set ]
+        [ spidered>> process-results ] bi
+        generate-report
+    ] with-scope
+    simple-page ;
index d08276a9bbe1ebcfa3d364646bfcd2c9b476c7f6..17e91473c3795df9be7dfd2f75f0705b1a1873b4 100644 (file)
@@ -4,46 +4,34 @@ USING: accessors fry html.parser html.parser.analyzer
 http.client kernel tools.time sets assocs sequences
 concurrency.combinators io threads namespaces math multiline
 math.parser inspector urls logging combinators.short-circuit
-continuations calendar prettyprint dlists deques locals ;
+continuations calendar prettyprint dlists deques locals
+spider.unique-deque combinators concurrency.semaphores ;
 IN: spider
 
 TUPLE: spider base count max-count sleep max-depth initial-links
-filters spidered todo nonmatching quiet ;
+filters spidered todo nonmatching quiet currently-spidering
+#threads semaphore follow-robots? robots ;
 
-TUPLE: spider-result url depth headers fetch-time parsed-html
-links processing-time timestamp ;
-
-TUPLE: todo-url url depth ;
-
-: <todo-url> ( url depth -- todo-url )
-    todo-url new
-        swap >>depth
-        swap >>url ;
-
-TUPLE: unique-deque assoc deque ;
-
-: <unique-deque> ( -- unique-deque )
-    H{ } clone <dlist> unique-deque boa ;
-
-: push-url ( url depth unique-deque -- )
-    [ <todo-url> ] dip
-    [ [ [ t ] dip url>> ] [ assoc>> ] bi* set-at ]
-    [ deque>> push-back ] 2bi ;
-
-: pop-url ( unique-deque -- todo-url ) deque>> pop-front ;
-
-: peek-url ( unique-deque -- todo-url ) deque>> peek-front ;
+TUPLE: spider-result url depth headers
+fetched-in parsed-html links processed-in fetched-at ;
 
 : <spider> ( base -- spider )
     >url
     spider new
         over >>base
+        over >>currently-spidering
         swap 0 <unique-deque> [ push-url ] keep >>todo
         <unique-deque> >>nonmatching
         0 >>max-depth
         0 >>count
         1/0. >>max-count
-        H{ } clone >>spidered ;
+        H{ } clone >>spidered
+        1 [ >>#threads ] [ <semaphore> >>semaphore ] bi ;
+
+: <spider-result> ( url depth -- spider-result )
+    spider-result new
+        swap >>depth
+        swap >>url ;
 
 <PRIVATE
 
@@ -71,36 +59,44 @@ TUPLE: unique-deque assoc deque ;
     [ add-nonmatching ]
     [ tuck [ apply-filters ] 2dip add-todo ] 2bi ;
 
-: normalize-hrefs ( links spider -- links' )
-    [ [ >url ] map ] dip
-    base>> swap [ derive-url ] with map ;
+: normalize-hrefs ( base links -- links' )
+    [ derive-url ] with map ;
 
-: print-spidering ( url depth -- )
+: print-spidering ( spider-result -- )
+    [ url>> ] [ depth>> ] bi
     "depth: " write number>string write
     ", spidering: " write . yield ;
 
-:: new-spidered-result ( spider url depth -- spider-result )
-    f url spider spidered>> set-at
-    [ url http-get ] benchmark :> fetch-time :> html :> headers
+:: fill-spidered-result ( spider spider-result -- )
+    f spider-result url>> spider spidered>> set-at
+    [ spider-result url>> http-get ] benchmark :> fetched-in :> html :> headers
     [
-        html parse-html [ ] [ find-hrefs spider normalize-hrefs ] bi
-    ] benchmark :> processing-time :> links :> parsed-html
-    url depth headers fetch-time parsed-html links processing-time
-    now spider-result boa ;
-
-:: spider-page ( spider url depth -- )
-    spider quiet>> [ url depth print-spidering ] unless
-    spider url depth new-spidered-result :> spidered-result
-    spider quiet>> [ spidered-result describe ] unless
-    spider spidered-result add-spidered ;
+        html parse-html
+        spider currently-spidering>>
+        over find-all-links normalize-hrefs
+    ] benchmark :> processed-in :> links :> parsed-html
+    spider-result
+        headers >>headers
+        fetched-in >>fetched-in
+        parsed-html >>parsed-html
+        links >>links
+        processed-in >>processed-in
+        now >>fetched-at drop ;
+
+:: spider-page ( spider spider-result -- )
+    spider quiet>> [ spider-result print-spidering ] unless
+    spider spider-result fill-spidered-result
+    spider quiet>> [ spider-result describe ] unless
+    spider spider-result add-spidered ;
 
 \ spider-page ERROR add-error-logging
 
-: spider-sleep ( spider -- )
-    sleep>> [ sleep ] when* ;
+: spider-sleep ( spider -- ) sleep>> [ sleep ] when* ;
 
-:: queue-initial-links ( spider -- spider )
-    spider initial-links>> spider normalize-hrefs 0 spider add-todo spider ;
+: queue-initial-links ( spider -- )
+    [
+        [ currently-spidering>> ] [ initial-links>> ] bi normalize-hrefs 0
+    ] keep add-todo ;
 
 : spider-page? ( spider -- ? )
     {
@@ -109,8 +105,9 @@ TUPLE: unique-deque assoc deque ;
         [ [ count>> ] [ max-count>> ] bi < ]
     } 1&& ;
 
-: setup-next-url ( spider -- spider url depth )
-    dup todo>> pop-url [ url>> ] [ depth>> ] bi ;
+: setup-next-url ( spider -- spider spider-result )
+    dup todo>> peek-url url>> >>currently-spidering
+    dup todo>> pop-url [ url>> ] [ depth>> ] bi <spider-result> ;
 
 : spider-next-page ( spider -- )
     setup-next-url spider-page ;
@@ -119,12 +116,12 @@ PRIVATE>
 
 : run-spider-loop ( spider -- )
     dup spider-page? [
-        [ spider-next-page ] [ run-spider-loop ] bi
+        [ spider-next-page ] [ spider-sleep ] [ run-spider-loop ] tri
     ] [
         drop
     ] if ;
 
 : run-spider ( spider -- spider )
     "spider" [
-        queue-initial-links [ run-spider-loop ] keep
+        dup queue-initial-links [ run-spider-loop ] keep
     ] with-logging ;
diff --git a/extra/spider/unique-deque/authors.txt b/extra/spider/unique-deque/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/spider/unique-deque/unique-deque.factor b/extra/spider/unique-deque/unique-deque.factor
new file mode 100644 (file)
index 0000000..b26797f
--- /dev/null
@@ -0,0 +1,37 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs deques dlists kernel spider ;
+IN: spider.unique-deque
+
+TUPLE: todo-url url depth ;
+
+: <todo-url> ( url depth -- todo-url )
+    todo-url new
+        swap >>depth
+        swap >>url ;
+
+TUPLE: unique-deque assoc deque ;
+
+: <unique-deque> ( -- unique-deque )
+    H{ } clone <dlist> unique-deque boa ;
+
+: url-exists? ( url unique-deque -- ? )
+    [ url>> ] [ assoc>> ] bi* key? ;
+
+: push-url ( url depth unique-deque -- )
+    [ <todo-url> ] dip 2dup url-exists? [
+        2drop
+    ] [
+        [ [ [ t ] dip url>> ] [ assoc>> ] bi* set-at ]
+        [ deque>> push-back ] 2bi
+    ] if ;
+
+: pop-url ( unique-deque -- todo-url ) deque>> pop-front ;
+
+: peek-url ( unique-deque -- todo-url ) deque>> peek-front ;
+
+: slurp-deque-when ( deque quot1 quot2: ( value -- ) -- )
+    pick deque-empty? [ 3drop ] [
+        [ [ pop-front dup ] 2dip slip [ t ] compose [ drop f ] if ]
+        [ roll [ slurp-deque-when ] [ 3drop ] if ] 3bi
+    ] if ; inline recursive
index 37c022fe43382c9b26b3f89d2e4ab3294afe6cab..297157c08bd88248d8d2bd71c8b1a6549ef90b8b 100755 (executable)
@@ -1,8 +1,10 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
 USING: combinators io io.files io.files.links io.directories
 io.pathnames io.streams.string kernel math math.parser
 continuations namespaces pack prettyprint sequences strings
 system tools.hexdump io.encodings.binary summary accessors
-io.backend byte-arrays ;
+io.backend byte-arrays io.streams.byte-array splitting ;
 IN: tar
 
 CONSTANT: zero-checksum 256
@@ -10,37 +12,35 @@ CONSTANT: block-size 512
 
 TUPLE: tar-header name mode uid gid size mtime checksum typeflag
 linkname magic version uname gname devmajor devminor prefix ;
-ERROR: checksum-error ;
 
-SYMBOLS: base-dir filename ;
+ERROR: checksum-error ;
 
-: tar-trim ( seq -- newseq ) [ "\0 " member? ] trim ;
+: trim-string ( seq -- newseq ) [ "\0 " member? ] trim ;
 
-: read-c-string* ( n -- str/f )
+: read-c-string ( n -- str/f )
     read [ zero? ] trim-tail [ f ] when-empty ;
 
 : read-tar-header ( -- obj )
     \ tar-header new
-    100 read-c-string* >>name
-    8 read-c-string* tar-trim oct> >>mode
-    8 read-c-string* tar-trim oct> >>uid
-    8 read-c-string* tar-trim oct> >>gid
-    12 read-c-string* tar-trim oct> >>size
-    12 read-c-string* tar-trim oct> >>mtime
-    8 read-c-string* tar-trim oct> >>checksum
-    read1 >>typeflag
-    100 read-c-string* >>linkname
-    6 read >>magic
-    2 read >>version
-    32 read-c-string* >>uname
-    32 read-c-string* >>gname
-    8 read tar-trim oct> >>devmajor
-    8 read tar-trim oct> >>devminor
-    155 read-c-string* >>prefix ;
-
-: header-checksum ( seq -- x )
-    148 cut-slice 8 tail-slice
-    [ sum ] bi@ + 256 + ;
+        100 read-c-string >>name
+        8 read-c-string trim-string oct> >>mode
+        8 read-c-string trim-string oct> >>uid
+        8 read-c-string trim-string oct> >>gid
+        12 read-c-string trim-string oct> >>size
+        12 read-c-string trim-string oct> >>mtime
+        8 read-c-string trim-string oct> >>checksum
+        read1 >>typeflag
+        100 read-c-string >>linkname
+        6 read >>magic
+        2 read >>version
+        32 read-c-string >>uname
+        32 read-c-string >>gname
+        8 read trim-string oct> >>devmajor
+        8 read trim-string oct> >>devminor
+        155 read-c-string >>prefix ;
+
+: checksum-header ( seq -- n )
+    148 cut-slice 8 tail-slice [ sum ] bi@ + 256 + ;
 
 : read-data-blocks ( tar-header -- )
     dup size>> 0 > [
@@ -60,29 +60,34 @@ SYMBOLS: base-dir filename ;
     ] if ;
 
 : parse-tar-header ( seq -- obj )
-    [ header-checksum ] keep over zero-checksum = [
+    [ checksum-header ] keep over zero-checksum = [
         2drop
         \ tar-header new
             0 >>size
             0 >>checksum
     ] [
-        [ read-tar-header ] with-string-reader
+        binary [ read-tar-header ] with-byte-reader
         [ checksum>> = [ checksum-error ] unless ] keep
     ] if ;
 
 ERROR: unknown-typeflag ch ;
-M: unknown-typeflag summary ( obj -- str )
-    ch>> 1string "Unknown typeflag: " prepend ;
 
-: tar-prepend-path ( path -- newpath )
-    base-dir get prepend-path ;
+M: unknown-typeflag summary ( obj -- str )
+    ch>> [ "Unknown typeflag: " ] dip prefix ;
 
 : read/write-blocks ( tar-header path -- )
     binary [ read-data-blocks ] with-file-writer ;
 
+: prepend-current-directory ( path -- path' )
+    current-directory get prepend-path ;
+
 ! Normal file
 : typeflag-0 ( header -- )
-    dup name>> tar-prepend-path read/write-blocks ;
+    dup name>> dup "global_pax_header" = [
+        drop [ read-data-blocks ] with-string-writer drop
+    ] [
+        prepend-current-directory read/write-blocks
+    ] if ;
 
 ! Hard link
 : typeflag-1 ( header -- ) unknown-typeflag ;
@@ -99,7 +104,7 @@ M: unknown-typeflag summary ( obj -- str )
 
 ! Directory
 : typeflag-5 ( header -- )
-    name>> tar-prepend-path make-directories ;
+    name>> prepend-current-directory make-directories ;
 
 ! FIFO
 : typeflag-6 ( header -- ) unknown-typeflag ;
@@ -139,7 +144,7 @@ M: unknown-typeflag summary ( obj -- str )
     drop ;
     ! <string-writer> [ read-data-blocks ] keep
     ! >string [ zero? ] trim-tail filename set
-    ! filename get tar-prepend-path make-directories ;
+    ! filename get prepend-current-directory make-directories ;
 
 ! Multi volume continuation entry
 : typeflag-M ( header -- ) unknown-typeflag ;
@@ -157,7 +162,7 @@ M: unknown-typeflag summary ( obj -- str )
 : typeflag-X ( header -- ) unknown-typeflag ;
 
 : (parse-tar) ( -- )
-    block-size read dup length 512 = [
+    block-size read dup length block-size = [
         parse-tar-header
         dup typeflag>>
         {
@@ -189,7 +194,7 @@ M: unknown-typeflag summary ( obj -- str )
         drop
     ] if ;
 
-: parse-tar ( path -- )
-    normalize-path dup parent-directory base-dir [
+: untar ( path -- )
+    normalize-path [ ] [ parent-directory ] bi [
          binary [ (parse-tar) ] with-file-reader
-    ] with-variable ;
+    ] with-directory ;
index d1f398994efadf92c3ae6e0ab7f74a7e85e7362d..0169249e81952ffe15cf1f86394d798c8721a5b4 100644 (file)
@@ -37,7 +37,7 @@ IN: tetris.gl
 
 : draw-tetris ( width height tetris -- )
     #! width and height are in pixels
-    GL_MODELVIEW [
+    [
         {
             [ board>> scale-board ]
             [ board>> draw-board ]
index 4123a836750a8a32d1a8daa49c05c937299296b8..b9d68ffaeb48eaa9336c92003c6678de00e259f7 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: help.markup help.syntax kernel quotations ui.gadgets
-images.bitmap strings ui.gadgets.worlds ;
+images strings ui.gadgets.worlds ;
 IN: ui.offscreen
 
 HELP: <offscreen-world>
@@ -26,9 +26,9 @@ HELP: do-offscreen
 HELP: gadget>bitmap
 { $values
      { "gadget" gadget }
-     { "bitmap" bitmap }
+     { "image" image }
 }
-{ $description "Renders " { $snippet "gadget" } " to an " { $link offscreen-world } " and creates a " { $link bitmap } " from its contents." } ;
+{ $description "Renders " { $snippet "gadget" } " to an " { $link offscreen-world } " and creates an " { $link image } " from its contents." } ;
 
 HELP: offscreen-world
 { $class-description "The class of " { $link world } " objects that render to an offscreen buffer." } ;
@@ -36,9 +36,9 @@ HELP: offscreen-world
 HELP: offscreen-world>bitmap
 { $values
      { "world" offscreen-world }
-     { "bitmap" bitmap }
+     { "image" image }
 }
-{ $description "Saves a copy of the contents of " { $snippet "world" } " to a " { $link bitmap } " object." } ;
+{ $description "Saves a copy of the contents of " { $snippet "world" } " to a " { $link image } " object." } ;
 
 HELP: open-offscreen
 { $values
index cf9370ed7fa6b050fe9e373bf33124743f165445..8d197eb844e7eba490fdfbb93a862ffc4fb4c4ec 100755 (executable)
@@ -1,7 +1,7 @@
 ! (c) 2008 Joe Groff, see license for details
-USING: accessors continuations images.bitmap kernel math
-sequences ui.gadgets ui.gadgets.worlds ui ui.backend
-destructors ;
+USING: accessors alien.c-types continuations images kernel math
+sequences ui.gadgets ui.gadgets.private ui.gadgets.worlds
+ui.private ui ui.backend destructors locals ;
 IN: ui.offscreen
 
 TUPLE: offscreen-world < world ;
@@ -19,18 +19,24 @@ M: offscreen-world ungraft*
 
 : open-offscreen ( gadget -- world )
     "" f <offscreen-world>
-    [ open-world-window dup relayout-1 ] keep
+    [ open-world-window ] [ relayout-1 ] [ ] tri
     notify-queued ;
 
 : close-offscreen ( world -- )
     ungraft notify-queued ;
 
-: offscreen-world>bitmap ( world -- bitmap )
-    offscreen-pixels bgra>bitmap ;
+:: bgrx>bitmap ( alien w h -- image )
+    <image>
+        { w h } >>dim
+        alien w h * 4 * memory>byte-array >>bitmap
+        BGRX >>component-order ;
+
+: offscreen-world>bitmap ( world -- image )
+    offscreen-pixels bgrx>bitmap ;
 
 : do-offscreen ( gadget quot: ( offscreen-world -- ) -- )
     [ open-offscreen ] dip
     over [ slip ] [ close-offscreen ] [ ] cleanup ; inline
 
-: gadget>bitmap ( gadget -- bitmap )
+: gadget>bitmap ( gadget -- image )
     [ offscreen-world>bitmap ] do-offscreen ;
index b796ebde9124cd1beac6a69bd42032703dbafcb2..46f6dcd8de25f6a27fec35e7dee247082d16f364 100644 (file)
@@ -1,3 +1,2 @@
-unportable
 ui
 graphics
diff --git a/extra/webapps/site-watcher/common/authors.txt b/extra/webapps/site-watcher/common/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/webapps/site-watcher/common/common.factor b/extra/webapps/site-watcher/common/common.factor
new file mode 100644 (file)
index 0000000..b27cbf3
--- /dev/null
@@ -0,0 +1,6 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: http.server.dispatchers ;
+IN: webapps.site-watcher.common
+
+TUPLE: site-watcher-app < dispatcher ;
diff --git a/extra/webapps/site-watcher/common/main.xml b/extra/webapps/site-watcher/common/main.xml
new file mode 100644 (file)
index 0000000..35a0ccb
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+<p>SiteWatcher is a free service for web masters. It periodically tries fetching your web site via HTTP, and sends you an e-mail, SMS or Tweet if this fails. <t:a t:href="$site-watcher-app/login">Sign up now!</t:a></p>
+
+<ul>
+  <li><t:a t:href="$site-watcher-app/update-notify">Your contact info</t:a></li>
+  <li><t:a t:href="$site-watcher-app/watch-list">Watched sites</t:a></li>
+  <li><t:a t:href="$site-watcher-app/spider-list">Spidered sites</t:a></li>
+</ul>
+
+</t:chloe>
diff --git a/extra/webapps/site-watcher/common/site-list.xml b/extra/webapps/site-watcher/common/site-list.xml
new file mode 100644 (file)
index 0000000..765381a
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+<h1>Add some sites to watch</h1>
+
+<t:form t:action="$site-watcher-app/add-watch">
+<table>
+  <tr><th>URL:</th><td> <t:field t:name="url" t:size="80" /> <button type="submit">Done</button> </td></tr>
+</table>
+</t:form>
+
+<h1>Keep track of your sites</h1>
+
+<table border="2">
+  <tr> <th>URL</th><th></th> </tr>
+  <t:bind-each t:name="sites">
+    <tr>
+      <td> <t:label t:name="url" /> </td>
+      <td> <t:button t:action="$site-watcher-app/remove-watch" t:for="url">Remove</t:button> </td>
+    </tr>
+  </t:bind-each>
+</table>
+<p>
+  <t:button t:action="$site-watcher-app/check">Check now</t:button>
+</p>
+
+</t:chloe>
diff --git a/extra/webapps/site-watcher/common/site-watcher.xml b/extra/webapps/site-watcher/common/site-watcher.xml
new file mode 100644 (file)
index 0000000..5b2b129
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+<html>
+  <head>
+    <title>SiteWatcher</title>
+  </head>
+  <body>
+    <h1>SiteWatcher</h1>
+    <h2>It tells you if your web site goes down.</h2>
+    <t:call-next-template />
+  </body>
+</html>
+
+</t:chloe>
diff --git a/extra/webapps/site-watcher/common/spider-list.xml b/extra/webapps/site-watcher/common/spider-list.xml
new file mode 100644 (file)
index 0000000..89d191a
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+<h1>Add a site to spider</h1>
+
+<t:form t:action="$site-watcher-app/add-spider">
+<table>
+  <tr><th>URL:</th><td> <t:field t:name="url" t:size="80" /> <button type="submit">Done</button> </td></tr>
+</table>
+</t:form>
+
+<h1>Spidered sites</h1>
+
+<table border="2">
+  <tr> <th>URL</th><th></th> </tr>
+  <t:bind-each t:name="sites">
+    <tr>
+      <td> <t:label t:name="url" /> </td>
+      <td> <t:button t:action="$site-watcher-app/remove-spider" t:for="url">Remove</t:button> </td>
+    </tr>
+  </t:bind-each>
+</table>
+<p>
+  <t:button t:action="$site-watcher-app/spider">Spider now</t:button>
+</p>
+
+</t:chloe>
diff --git a/extra/webapps/site-watcher/common/update-notify.xml b/extra/webapps/site-watcher/common/update-notify.xml
new file mode 100644 (file)
index 0000000..02075de
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+<h3>Enter your contact details</h3>
+
+<t:form t:action="$site-watcher-app/update-notify">
+<table>
+  <tr><th>E-mail:</th><td><t:field t:name="email" t:size="80" /></td></tr>
+  <tr><th>Twitter:</th><td><t:field t:name="twitter" t:size="80" /></td></tr>
+  <tr><th>SMS:</th><td><t:field t:name="sms" t:size="80" /></td></tr>
+</table>
+<p> <button type="submit">Done</button> </p>
+</t:form>
+
+</t:chloe>
diff --git a/extra/webapps/site-watcher/main.xml b/extra/webapps/site-watcher/main.xml
deleted file mode 100644 (file)
index 938ff09..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version='1.0' ?>
-
-<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
-
-<p>SiteWatcher is a free service for web masters. It periodically tries fetching your web site via HTTP, and sends you an e-mail, SMS or Tweet if this fails. <t:a t:href="$site-watcher-app/list">Sign up now!</t:a></p>
-
-</t:chloe>
diff --git a/extra/webapps/site-watcher/site-list.xml b/extra/webapps/site-watcher/site-list.xml
deleted file mode 100644 (file)
index c96a25f..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version='1.0' ?>
-
-<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
-
-<p> Don't you hate it when your web site goes down, and all your users go buy that <a href="http://en.wikipedia.org/wiki/Slanket">slanket</a> from your competitor instead. Now using SiteWatcher, you can ensure this will never happen again! </p>
-
-<t:a t:href="$site-watcher-app/update-notify">Contact info</t:a>
-
-<h3>Step 2: add some sites to watch</h3>
-
-<t:form t:action="$site-watcher-app/add">
-<table>
-  <tr><th>URL:</th><td> <t:field t:name="url" t:size="80" /> <button type="submit">Done</button> </td></tr>
-</table>
-</t:form>
-
-<h3>Step 3: keep track of your sites</h3>
-
-<table border="2">
-  <tr> <th>URL</th><th></th> </tr>
-  <t:bind-each t:name="sites">
-    <tr>
-      <td> <t:label t:name="url" /> </td>
-      <td> <t:button t:action="$site-watcher-app/remove" t:for="url">Remove</t:button> </td>
-    </tr>
-  </t:bind-each>
-</table>
-<p>
-  <t:button t:action="$site-watcher-app/check">Check now</t:button>
-</p>
-
-</t:chloe>
index f173edb8149cd4ca7b96ab23c731c83f85157e2b..b60f1b1b6a59abf7cff73eecd95f3cf7a96c7cc7 100644 (file)
@@ -1,72 +1,22 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs db.sqlite furnace furnace.actions furnace.alloy
-furnace.auth furnace.auth.features.deactivate-user
+USING: accessors assocs db.sqlite furnace furnace.actions
+furnace.alloy furnace.auth furnace.auth.features.deactivate-user
 furnace.auth.features.edit-profile
 furnace.auth.features.recover-password
 furnace.auth.features.registration furnace.auth.login
 furnace.boilerplate furnace.redirection html.forms http.server
 http.server.dispatchers kernel namespaces site-watcher site-watcher.db
 site-watcher.private urls validators io.sockets.secure.unix.debug
-io.servers.connection db db.tuples sequences ;
+io.servers.connection io.files.temp db db.tuples sequences
+webapps.site-watcher.common webapps.site-watcher.watching
+webapps.site-watcher.spidering ;
 QUALIFIED: assocs
 IN: webapps.site-watcher
 
-TUPLE: site-watcher-app < dispatcher ;
-
-CONSTANT: site-list-url URL" $site-watcher-app/"
-
 : <main-action> ( -- action )
     <page-action>
-        [
-            logged-in?
-            [ URL" $site-watcher-app/list" <redirect> ]
-            [ { site-watcher-app "main" } <chloe-content> ] if
-        ] >>display ;
-
-: <site-list-action> ( -- action )
-    <page-action>
-        { site-watcher-app "site-list" } >>template
-        [
-            ! Silly query
-            username watching-sites
-            "sites" set-value
-        ] >>init
-    <protected>
-        "list watched sites" >>description ;
-
-: <add-site-action> ( -- action )
-    <action>
-        [
-            { { "url" [ v-url ] } } validate-params
-        ] >>validate
-        [
-            username "url" value watch-site
-            site-list-url <redirect>
-        ] >>submit
-    <protected>
-        "add a watched site" >>description ;
-
-: <remove-site-action> ( -- action )
-    <action>
-        [
-            { { "url" [ v-url ] } } validate-params
-        ] >>validate
-        [
-            username "url" value unwatch-site
-            site-list-url <redirect>
-        ] >>submit
-    <protected>
-        "remove a watched site" >>description ;
-
-: <check-sites-action> ( -- action )
-    <action>
-        [
-            watch-sites
-            site-list-url <redirect>
-        ] >>submit
-    <protected>
-        "check watched sites" >>description ;
+        { site-watcher-app "main" } >>template ;
 
 : <update-notify-action> ( -- action )
     <page-action>
@@ -95,10 +45,14 @@ CONSTANT: site-list-url URL" $site-watcher-app/"
 : <site-watcher-app> ( -- dispatcher )
     site-watcher-app new-dispatcher
         <main-action> "" add-responder
-        <site-list-action> "list" add-responder
-        <add-site-action> "add" add-responder
-        <remove-site-action> "remove" add-responder
+        <watch-list-action> "watch-list" add-responder
+        <add-watched-site-action> "add-watch" add-responder
+        <remove-watched-site-action> "remove-watch" add-responder
         <check-sites-action> "check" add-responder
+        <spider-list-action> "spider-list" add-responder
+        <add-spidered-site-action> "add-spider" add-responder
+        <remove-spidered-site-action> "remove-spider" add-responder
+        <spider-sites-action> "spider" add-responder
         <update-notify-action> "update-notify" add-responder ;
 
 : <login-config> ( responder -- responder' )
@@ -116,7 +70,7 @@ CONSTANT: site-list-url URL" $site-watcher-app/"
         8431 >>secure ;
 
 : site-watcher-db ( -- db )
-    "resource:test.db" <sqlite-db> ;
+    "test.db" temp-file <sqlite-db> ;
 
 <site-watcher-app>
 <login-config>
@@ -125,12 +79,13 @@ site-watcher-db <alloy>
 main-responder set-global
 
 M: site-watcher-app init-user-profile
-    drop
+    drop B
     "username" value "email" value <account> insert-tuple ;
 
 : init-db ( -- )
     site-watcher-db [
-        { site account watching-site } [ ensure-table ] each
+        { site account watching-site spidering-site }
+        [ ensure-table ] each
     ] with-db ;
 
 : start-site-watcher ( -- )
diff --git a/extra/webapps/site-watcher/site-watcher.xml b/extra/webapps/site-watcher/site-watcher.xml
deleted file mode 100644 (file)
index 5b2b129..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version='1.0' ?>
-
-<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
-
-<html>
-  <head>
-    <title>SiteWatcher</title>
-  </head>
-  <body>
-    <h1>SiteWatcher</h1>
-    <h2>It tells you if your web site goes down.</h2>
-    <t:call-next-template />
-  </body>
-</html>
-
-</t:chloe>
diff --git a/extra/webapps/site-watcher/spidering/authors.txt b/extra/webapps/site-watcher/spidering/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/webapps/site-watcher/spidering/spidering.factor b/extra/webapps/site-watcher/spidering/spidering.factor
new file mode 100644 (file)
index 0000000..d0116a7
--- /dev/null
@@ -0,0 +1,52 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors furnace.actions furnace.auth
+furnace.redirection html.forms validators webapps.site-watcher.common
+site-watcher.db site-watcher.spider kernel urls sequences ;
+IN: webapps.site-watcher.spidering
+
+CONSTANT: site-list-url URL" $site-watcher-app/spider-list"
+
+: <spider-list-action> ( -- action )
+    <page-action>
+        { site-watcher-app "spider-list" } >>template
+        [
+            ! Silly query
+            username B spidering-sites [ site>> ] map
+            "sites" set-value
+        ] >>init
+    <protected>
+        "list spidered sites" >>description ;
+
+: <add-spidered-site-action> ( -- action )
+    <action>
+        [
+            { { "url" [ v-url ] } } validate-params
+        ] >>validate
+        [
+            username "url" value add-spidered-site
+            site-list-url <redirect>
+        ] >>submit
+    <protected>
+        "add a spidered site" >>description ;
+
+: <remove-spidered-site-action> ( -- action )
+    <action>
+        [
+            { { "url" [ v-url ] } } validate-params
+        ] >>validate
+        [
+            username "url" value remove-spidered-site
+            site-list-url <redirect>
+        ] >>submit
+    <protected>
+        "remove a spidered site" >>description ;
+
+: <spider-sites-action> ( -- action )
+    <action>
+        [
+            spider-sites
+            site-list-url <redirect>
+        ] >>submit
+    <protected>
+        "spider sites" >>description ;
\ No newline at end of file
diff --git a/extra/webapps/site-watcher/update-notify.xml b/extra/webapps/site-watcher/update-notify.xml
deleted file mode 100644 (file)
index 02075de..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version='1.0' ?>
-
-<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
-
-<h3>Enter your contact details</h3>
-
-<t:form t:action="$site-watcher-app/update-notify">
-<table>
-  <tr><th>E-mail:</th><td><t:field t:name="email" t:size="80" /></td></tr>
-  <tr><th>Twitter:</th><td><t:field t:name="twitter" t:size="80" /></td></tr>
-  <tr><th>SMS:</th><td><t:field t:name="sms" t:size="80" /></td></tr>
-</table>
-<p> <button type="submit">Done</button> </p>
-</t:form>
-
-</t:chloe>
diff --git a/extra/webapps/site-watcher/watching/authors.txt b/extra/webapps/site-watcher/watching/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/webapps/site-watcher/watching/watching.factor b/extra/webapps/site-watcher/watching/watching.factor
new file mode 100644 (file)
index 0000000..414595a
--- /dev/null
@@ -0,0 +1,52 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors furnace.actions furnace.auth
+furnace.redirection html.forms site-watcher site-watcher.db
+validators webapps.site-watcher.common urls ;
+IN: webapps.site-watcher.watching
+
+CONSTANT: site-list-url URL" $site-watcher-app/watch-list"
+
+: <watch-list-action> ( -- action )
+    <page-action>
+        { site-watcher-app "site-list" } >>template
+        [
+            ! Silly query
+            username watching-sites
+            "sites" set-value
+        ] >>init
+    <protected>
+        "list watched sites" >>description ;
+
+: <add-watched-site-action> ( -- action )
+    <action>
+        [
+            { { "url" [ v-url ] } } validate-params
+        ] >>validate
+        [
+            username "url" value watch-site
+            site-list-url <redirect>
+        ] >>submit
+    <protected>
+        "add a watched site" >>description ;
+
+: <remove-watched-site-action> ( -- action )
+    <action>
+        [
+            { { "url" [ v-url ] } } validate-params
+        ] >>validate
+        [
+            username "url" value unwatch-site
+            site-list-url <redirect>
+        ] >>submit
+    <protected>
+        "remove a watched site" >>description ;
+
+: <check-sites-action> ( -- action )
+    <action>
+        [
+            watch-sites
+            site-list-url <redirect>
+        ] >>submit
+    <protected>
+        "check watched sites" >>description ;
\ No newline at end of file
index 5961d9e86fbddacbc5d1080c2020ebc7e59d92df..aa7d25ebbd138c504184f42df11de3892bd0573b 100644 (file)
@@ -58,7 +58,9 @@
   (number constant  "integers and floats")
   (ratio constant  "ratios")
   (declaration keyword "declaration words")
+  (ebnf-form constant "EBNF: ... ;EBNF form")
   (parsing-word keyword  "parsing words")
+  (postpone-body comment "postponed form")
   (setter-word function-name "setter words (>>foo)")
   (getter-word function-name "getter words (foo>>)")
   (stack-effect comment "stack effect specifications")
 (defun fuel-font-lock--syntactic-face (state)
   (if (nth 3 state) 'factor-font-lock-string
     (let ((c (char-after (nth 8 state))))
-      (cond ((or (char-equal c ?\ ) (char-equal c ?\n))
+      (cond ((memq c '(?\  ?\n ?E ?P))
              (save-excursion
                (goto-char (nth 8 state))
                (beginning-of-line)
-               (cond ((looking-at-p "USING: ")
+               (cond ((looking-at "E") 'factor-font-lock-ebnf-form)
+                     ((looking-at "P") 'factor-font-lock-postpone-body)
+                     ((looking-at-p "USING: ")
                       'factor-font-lock-vocabulary-name)
-                     ((looking-at-p "\\(TUPLE\\|SYMBOLS\\|VARS\\|SINGLETONS\\):")
+                     ((looking-at-p
+                       "\\(TUPLE\\|SYMBOLS\\|VARS\\|SINGLETONS\\):")
                       'factor-font-lock-symbol)
                      ((looking-at-p "C-ENUM:\\( \\|\n\\)")
                       'factor-font-lock-constant)
     (,fuel-syntax--alien-function-regex (1 'factor-font-lock-type-name)
                                         (2 'factor-font-lock-word))
     (,fuel-syntax--vocab-ref-regexp  2 'factor-font-lock-vocabulary-name)
-    (,fuel-syntax--constructor-decl-regex (1 'factor-font-lock-word)
-                                          (2 'factor-font-lock-type-name)
-                                          (3 'factor-font-lock-invalid-syntax nil t))
+    (,fuel-syntax--constructor-decl-regex
+     (1 'factor-font-lock-word)
+     (2 'factor-font-lock-type-name)
+     (3 'factor-font-lock-invalid-syntax nil t))
     (,fuel-syntax--typedef-regex (1 'factor-font-lock-type-name)
                                  (2 'factor-font-lock-type-name)
                                  (3 'factor-font-lock-invalid-syntax nil t))
index 942d4394662fc28a0b7c1769a2ceb3f259fd4cc9..a410bb504716432469768fa8c52fad528ce3ed1d 100644 (file)
@@ -36,7 +36,7 @@
       (let ((name (match-string-no-properties 2))
             (body (match-string-no-properties 4))
             (end (match-end 0)))
-        (list (split-string body nil t) name pos end)))))
+        (list (split-string (or body "") nil t) name pos end)))))
 
 (defun fuel-refactor--find (code to)
   (let ((candidate) (result))
@@ -88,7 +88,7 @@
 (defun fuel-refactor--insert-word (word stack-effect code)
   (let ((start (goto-char (fuel-refactor--insertion-point))))
     (open-line 1)
-    (insert ": " word " " stack-effect "\n" code " ;\n")
+    (insert ": " word " " stack-effect "\n" (or code " ") " ;\n")
     (indent-region start (point))
     (move-overlay fuel-stack--overlay start (point))))
 
     (delete-overlay fuel-stack--overlay)))
 
 (defun fuel-refactor--extract (begin end)
-  (unless (< begin end) (error "No proper region to extract"))
-  (let* ((code (buffer-substring begin end))
-         (existing (fuel-refactor--reuse-existing code))
-         (code-str (or existing (fuel--region-to-string begin end)))
+  (let* ((rp (< begin end))
+         (code (and rp (buffer-substring begin end)))
+         (existing (and code (fuel-refactor--reuse-existing code)))
+         (code-str (and code (or existing (fuel--region-to-string begin end))))
          (word (or (car existing) (read-string "New word name: ")))
          (stack-effect (or existing
-                           (fuel-stack--infer-effect code-str)
+                           (and code-str (fuel-stack--infer-effect code-str))
                            (read-string "Stack effect: "))))
-    (goto-char begin)
-    (delete-region begin end)
-    (insert word)
-    (indent-region begin (point))
+    (when rp
+      (goto-char begin)
+      (delete-region begin end)
+      (insert word)
+      (indent-region begin (point)))
     (save-excursion
       (let ((start (or (cadr existing) (point))))
         (unless existing
           (fuel-refactor--insert-word word stack-effect code))
-        (fuel-refactor--extract-other start
-                                      (or (car (cddr existing)) (point))
-                                      code)))))
+        (if rp
+            (fuel-refactor--extract-other start
+                                          (or (car (cddr existing)) (point))
+                                          code)
+          (unwind-protect
+              (sit-for fuel-stack-highlight-period)
+            (delete-overlay fuel-stack--overlay)))))))
 
 (defun fuel-refactor-extract-region (begin end)
   "Extracts current region as a separate word."
   (interactive "r")
-  (let ((begin (save-excursion
-                 (goto-char begin)
-                 (when (zerop (skip-syntax-backward "w"))
-                   (skip-syntax-forward "-"))
-                 (point)))
-        (end (save-excursion
-               (goto-char end)
-               (skip-syntax-forward "w")
-               (point))))
-    (fuel-refactor--extract begin end)))
+  (if (= begin end)
+      (fuel-refactor--extract begin end)
+    (let ((begin (save-excursion
+                   (goto-char begin)
+                   (when (zerop (skip-syntax-backward "w"))
+                     (skip-syntax-forward "-"))
+                   (point)))
+          (end (save-excursion
+                 (goto-char end)
+                 (skip-syntax-forward "w")
+                 (point))))
+      (fuel-refactor--extract begin end))))
 
 (defun fuel-refactor-extract-sexp ()
   "Extracts current innermost sexp (up to point) as a separate
index 4cff58ae3b33837a0252680fce0ca75af488ebdf..6b646511ca0794887d2170321cbc8abc80d9f0b6 100644 (file)
@@ -48,7 +48,7 @@
     "B" "BIN:"
     "C:" "C-ENUM:" "C-STRUCT:" "C-UNION:" "CHAR:" "CONSTANT:" "call-next-method"
     "DEFER:"
-    "ERROR:" "EXCLUDE:"
+    "EBNF:" ";EBNF" "ERROR:" "EXCLUDE:"
     "f" "FORGET:" "FROM:" "FUNCTION:"
     "GENERIC#" "GENERIC:"
     "HELP:" "HEX:" "HOOK:"
     ;; Strings and chars
     ("CHAR: \\(\"\\) [^\\\"]*?\\(\"\\)\\([^\\\"]\\|\\\\.\\)*?\\(\"\\)"
      (1 "w") (2 "\"") (4 "\""))
-    ("\\(CHAR:\\|POSTPONE:\\|\\\\\\) \\(.\\)\\( \\|$\\)" (2 "w"))
+    ("\\(CHAR:\\|\\\\\\) \\(.\\)\\( \\|$\\)" (2 "w"))
     ("\\( \\|^\\)\\(DLL\\|P\\|SBUF\\)\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)"
      (3 "\"") (5 "\""))
     ("\\_<\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)" (1 "\"") (3 "\""))
     ("\\_<<\\(\"\\)\\_>" (1 "<b"))
     ("\\_<\\(\"\\)>\\_>" (1 ">b"))
+    ;; postpone
+    ("\\_<POSTPONE:\\( \\).*\\(\n\\)" (1 "<b") (2 ">b"))
     ;; Multiline constructs
+    ("\\_<\\(E\\)BNF:\\( \\|\n\\)" (1 "<b"))
+    ("\\_<;EBN\\(F\\)\\_>" (1 ">b"))
     ("\\_<\\(U\\)SING: \\(;\\)" (1 "<b") (2 ">b"))
     ("\\_<USING:\\( \\)" (1 "<b"))
     ("\\_<\\(C\\)-ENUM: \\(;\\)" (1 "<b") (2 ">b"))
     ("\\_<C-ENUM:\\( \\|\n\\)" (1 "<b"))
     ("\\_<TUPLE: +\\w+? +< +\\w+? *\\( \\|\n\\)\\([^;]\\|$\\)" (1 "<b"))
     ("\\_<TUPLE: +\\w+? *\\( \\|\n\\)\\([^;<\n]\\|\\_>\\)" (1 "<b"))
-    ("\\_<\\(SYMBOLS\\|VARS\\|SINGLETONS\\): *?\\( \\|\n\\)\\([^;\n]\\|\\_>\\)" (2 "<b"))
+    ("\\_<\\(SYMBOLS\\|VARS\\|SINGLETONS\\): *?\\( \\|\n\\)\\([^;\n]\\|\\_>\\)"
+     (2 "<b"))
     ("\\(\n\\| \\);\\_>" (1 ">b"))
     ;; Let and lambda:
     ("\\_<\\(!(\\) .* \\()\\)" (1 "<") (2 ">"))
     ("\\_<\\(}\\)\\_>" (1 "){"))
     ;; Parenthesis:
     ("\\_<\\((\\)\\_>" (1 "()"))
+    ("\\_<call\\((\\)\\_>" (1 "()"))
     ("\\_<\\()\\)\\_>" (1 ")("))
     ("\\_<(\\((\\)\\_>" (1 "()"))
     ("\\_<\\()\\))\\_>" (1 ")("))
index 339c3c3ffbd143c835de8b4b9b6b3b87dd787036..1f488475423178a3838c2ad5e7de940b487c0f6c 100644 (file)
@@ -14,7 +14,7 @@ PLAF_EXE_OBJS += vm/main-unix.o
 ifdef NO_UI
        X11_UI_LIBS =
 else
-       X11_UI_LIBS = -lpango-1.0 -lpangocairo-1.0 -lcairo -lglib-2.0 -lgobject-2.0 -lGL -lGLU -lX11
+       X11_UI_LIBS = -lpango-1.0 -lpangocairo-1.0 -lcairo -lglib-2.0 -lgobject-2.0 -lGL -lX11
 endif
 
 # CFLAGS += -fPIC
index d9042c945563a854a3b149dc9df24ea554b72c25..9b5d3de6020bce406b977b227e72c31c56cdfa27 100755 (executable)
@@ -132,9 +132,7 @@ void init_factor(F_PARAMETERS *p)
        userenv[CPU_ENV] = tag_object(from_char_string(FACTOR_CPU_STRING));
        userenv[OS_ENV] = tag_object(from_char_string(FACTOR_OS_STRING));
        userenv[CELL_SIZE_ENV] = tag_fixnum(sizeof(CELL));
-       userenv[STACK_TRACES_ENV] = tag_boolean(p->stack_traces);
-       userenv[EXECUTABLE_ENV] = (p->executable_path ?
-               tag_object(from_native_string(p->executable_path)) : F);
+       userenv[EXECUTABLE_ENV] = (p->executable_path ? tag_object(from_native_string(p->executable_path)) : F);
        userenv[ARGS_ENV] = F;
        userenv[EMBEDDED_ENV] = F;
 
@@ -142,7 +140,10 @@ void init_factor(F_PARAMETERS *p)
        gc_off = false;
 
        if(!stage2)
+       {
+               userenv[STACK_TRACES_ENV] = tag_boolean(p->stack_traces);
                do_stage1_init();
+       }
 }
 
 /* May allocate memory */
index 5ce7147200645c57e5d3e38e0de5ccb5a2394226..a1987180d0fa9280d3a002336a22081030a15aaf 100755 (executable)
@@ -86,7 +86,8 @@ void load_image(F_PARAMETERS *p)
        }
 
        F_HEADER h;
-       fread(&h,sizeof(F_HEADER),1,file);
+       if(fread(&h,sizeof(F_HEADER),1,file) != 1)
+               fatal_error("Cannot read image header",0);
 
        if(h.magic != IMAGE_MAGIC)
                fatal_error("Bad image: magic number check failed",h.magic);
@@ -145,27 +146,19 @@ bool save_image(const F_CHAR *filename)
                        h.userenv[i] = userenv[i];
        }
 
-       fwrite(&h,sizeof(F_HEADER),1,file);
+       bool ok = true;
 
-       if(fwrite((void*)tenured->start,h.data_size,1,file) != 1)
-       {
-               print_string("Save data heap failed: "); print_string(strerror(errno)); nl();
-               return false;
-       }
-
-       if(fwrite(first_block(&code_heap),h.code_size,1,file) != 1)
-       {
-               print_string("Save code heap failed: "); print_string(strerror(errno)); nl();
-               return false;
-       }
+       if(fwrite(&h,sizeof(F_HEADER),1,file) != 1) ok = false;
+       if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
+       if(fwrite(first_block(&code_heap),h.code_size,1,file) != 1) ok = false;
+       if(fclose(file)) ok = false;
 
-       if(fclose(file))
+       if(!ok)
        {
-               print_string("Failed to close image file: "); print_string(strerror(errno)); nl();
-               return false;
+               print_string("save-image failed: "); print_string(strerror(errno)); nl();
        }
 
-       return true;
+       return ok;
 }
 
 void primitive_save_image(void)
diff --git a/vm/io.c b/vm/io.c
index bad4854775279ea82c276268c855af9f07237164..d88f1bab504aa205720e2054092b58c708c1db7a 100755 (executable)
--- a/vm/io.c
+++ b/vm/io.c
@@ -163,6 +163,31 @@ void primitive_fwrite(void)
        }
 }
 
+void primitive_fseek(void)
+{
+       int whence = to_fixnum(dpop());
+       FILE *file = unbox_alien();
+       off_t offset = to_signed_8(dpop());
+
+       switch(whence)
+       {
+       case 0: whence = SEEK_SET; break;
+       case 1: whence = SEEK_CUR; break;
+       case 2: whence = SEEK_END; break;
+       default:
+               critical_error("Bad value for whence",whence);
+               break;
+       }
+
+       if(FSEEK(file,offset,whence) == -1)
+       {
+               io_error();
+
+               /* Still here? EINTR */
+               critical_error("Don't know what to do; EINTR from fseek()?",0);
+       }
+}
+
 void primitive_fflush(void)
 {
        FILE *file = unbox_alien();
diff --git a/vm/io.h b/vm/io.h
index dc7d69edee84779afe941438946f7d0240890b3a..63a9c35490843993fc7c5fe32a52fdd7fc707563 100755 (executable)
--- a/vm/io.h
+++ b/vm/io.h
@@ -9,6 +9,7 @@ void primitive_fread(void);
 void primitive_fputc(void);
 void primitive_fwrite(void);
 void primitive_fflush(void);
+void primitive_fseek(void);
 void primitive_fclose(void);
 
 /* Platform specific primitives */
index d2f34b4bc4c26d50a1c419ce436619ac3c833d8e..35abfee41c66737d1eb3bb13958ac1ce6d491327 100755 (executable)
@@ -23,6 +23,8 @@ typedef char F_SYMBOL;
 #define STRNCMP strncmp
 #define STRDUP strdup
 
+#define FSEEK fseeko
+
 #define FIXNUM_FORMAT "%ld"
 #define CELL_FORMAT "%lu"
 #define CELL_HEX_FORMAT "%lx"
index 0704459dd0800996c2c1abff3a847d47a83737a8..36d350f50dc81f008008adbebb7833c430425ff3 100755 (executable)
@@ -20,6 +20,7 @@ typedef wchar_t F_CHAR;
 #define STRNCMP wcsncmp
 #define STRDUP _wcsdup
 #define MIN(a,b) ((a)>(b)?(b):(a))
+#define FSEEK fseek
 
 #ifdef WIN64
        #define CELL_FORMAT "%Iu"
index 21336e88bb334247baac661822152311db9a63cb..70804542b4fc318b65a1605d396256484ec6c972 100644 (file)
@@ -96,7 +96,7 @@
                        #if defined(FACTOR_X86)
                                #include "os-solaris-x86.32.h"
                        #elif defined(FACTOR_AMD64)
-                               #incluide "os-solaris-x86.64.h"
+                               #include "os-solaris-x86.64.h"
                        #else
                                #error "Unsupported Solaris flavor"
                        #endif
index 00103ac0471c6bc31e2a369a2b5f8dc88271a53c..80b672d9d2d34d20a406bfcd4ffaf6ad6c7ef6bf 100755 (executable)
@@ -121,6 +121,7 @@ void *primitives[] = {
        primitive_fputc,
        primitive_fwrite,
        primitive_fflush,
+       primitive_fseek,
        primitive_fclose,
        primitive_wrapper,
        primitive_clone,