From a96457cecce4458d6d4d10274b6f278ae4cfdfc9 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Thu, 20 Sep 2007 18:09:08 -0400 Subject: [PATCH] Initial import --- .../Contents/Frameworks/libfreetype.6.dylib | Bin 0 -> 683652 bytes Factor.app/Contents/Info.plist | 74 + Factor.app/Contents/PkgInfo | 0 .../English.lproj/Factor.nib/classes.nib | 17 + .../English.lproj/Factor.nib/info.nib | 21 + .../English.lproj/Factor.nib/keyedobjects.nib | Bin 0 -> 11126 bytes .../English.lproj/MiniFactor.nib/classes.nib | 17 + .../English.lproj/MiniFactor.nib/info.nib | 21 + .../MiniFactor.nib/keyedobjects.nib | Bin 0 -> 9369 bytes Factor.app/Contents/Resources/FRaptorMix.icns | Bin 0 -> 53668 bytes Makefile | 154 + README.txt | 180 + core/alien/alien-docs.factor | 527 + core/alien/alien-tests.factor | 58 + core/alien/alien.factor | 83 + core/alien/arrays/arrays.factor | 38 + core/alien/arrays/authors.txt | 1 + core/alien/arrays/summary.txt | 1 + core/alien/authors.txt | 1 + core/alien/c-types/authors.txt | 1 + core/alien/c-types/c-types-docs.factor | 153 + core/alien/c-types/c-types-tests.factor | 70 + core/alien/c-types/c-types.factor | 356 + core/alien/c-types/summary.txt | 1 + core/alien/compiler/authors.txt | 1 + core/alien/compiler/compiler.factor | 366 + core/alien/compiler/summary.txt | 1 + core/alien/remote-control/authors.txt | 1 + .../remote-control/remote-control.factor | 25 + core/alien/remote-control/summary.txt | 1 + core/alien/structs/authors.txt | 1 + core/alien/structs/structs-docs.factor | 6 + core/alien/structs/structs-tests.factor | 42 + core/alien/structs/structs.factor | 99 + core/alien/structs/summary.txt | 1 + core/alien/summary.txt | 1 + core/alien/syntax/authors.txt | 1 + core/alien/syntax/summary.txt | 1 + core/alien/syntax/syntax-docs.factor | 94 + core/alien/syntax/syntax.factor | 62 + core/alien/tags.txt | 1 + core/arrays/arrays-docs.factor | 70 + core/arrays/arrays-tests.factor | 22 + core/arrays/arrays.factor | 34 + core/arrays/authors.txt | 1 + core/arrays/summary.txt | 1 + core/arrays/tags.txt | 1 + core/assocs/assocs-docs.factor | 296 + core/assocs/assocs-tests.factor | 89 + core/assocs/assocs.factor | 179 + core/assocs/authors.txt | 1 + core/assocs/summary.txt | 1 + core/assocs/tags.txt | 1 + core/bit-arrays/authors.txt | 1 + core/bit-arrays/bit-arrays-docs.factor | 49 + core/bit-arrays/bit-arrays-tests.factor | 48 + core/bit-arrays/bit-arrays.factor | 51 + core/bit-arrays/summary.txt | 1 + core/bit-arrays/tags.txt | 1 + core/bootstrap/compiler/authors.txt | 1 + core/bootstrap/compiler/compiler.factor | 50 + core/bootstrap/compiler/summary.txt | 1 + core/bootstrap/help/authors.txt | 1 + core/bootstrap/help/help.factor | 24 + core/bootstrap/help/summary.txt | 1 + core/bootstrap/image/authors.txt | 1 + core/bootstrap/image/image-docs.factor | 20 + core/bootstrap/image/image.factor | 461 + core/bootstrap/image/summary.txt | 1 + core/bootstrap/image/tags.txt | 1 + core/bootstrap/io/authors.txt | 1 + core/bootstrap/io/io.factor | 8 + core/bootstrap/io/summary.txt | 1 + core/bootstrap/layouts/authors.txt | 1 + core/bootstrap/layouts/layouts.factor | 40 + core/bootstrap/layouts/summary.txt | 1 + core/bootstrap/math/math.factor | 5 + core/bootstrap/math/summary.txt | 1 + core/bootstrap/primitives.factor | 597 + core/bootstrap/stage1.factor | 43 + core/bootstrap/stage2.factor | 83 + core/bootstrap/summary.txt | 1 + core/bootstrap/syntax.factor | 69 + core/bootstrap/tools/authors.txt | 1 + core/bootstrap/tools/summary.txt | 1 + core/bootstrap/tools/tools.factor | 19 + core/bootstrap/ui/authors.txt | 1 + core/bootstrap/ui/summary.txt | 1 + core/bootstrap/ui/tools/authors.txt | 1 + core/bootstrap/ui/tools/summary.txt | 1 + core/bootstrap/ui/tools/tools.factor | 10 + core/bootstrap/ui/ui.factor | 14 + core/byte-arrays/authors.txt | 1 + core/byte-arrays/byte-arrays-docs.factor | 31 + core/byte-arrays/byte-arrays.factor | 18 + core/byte-arrays/summary.txt | 1 + core/byte-arrays/tags.txt | 1 + core/classes/authors.txt | 1 + core/classes/classes-docs.factor | 219 + core/classes/classes-tests.factor | 179 + core/classes/classes.factor | 281 + core/classes/mixin/authors.txt | 1 + core/classes/mixin/mixin-docs.factor | 14 + core/classes/mixin/mixin.factor | 29 + core/classes/mixin/summary.txt | 1 + core/classes/predicate/authors.txt | 1 + core/classes/predicate/predicate-docs.factor | 23 + core/classes/predicate/predicate.factor | 24 + core/classes/predicate/summary.txt | 1 + core/classes/summary.txt | 1 + core/classes/tags.txt | 1 + core/classes/union/authors.txt | 1 + core/classes/union/summary.txt | 1 + core/classes/union/union-docs.factor | 25 + core/classes/union/union.factor | 27 + core/combinators/authors.txt | 1 + core/combinators/combinators-docs.factor | 132 + core/combinators/combinators-tests.factor | 71 + core/combinators/combinators.factor | 86 + core/combinators/summary.txt | 1 + core/command-line/authors.txt | 1 + core/command-line/command-line-docs.factor | 113 + core/command-line/command-line-tests.factor | 12 + core/command-line/command-line.factor | 62 + core/command-line/summary.txt | 1 + core/compiler/authors.txt | 1 + core/compiler/compiler-docs.factor | 139 + core/compiler/compiler-tests.factor | 20 + core/compiler/compiler.factor | 92 + core/compiler/summary.txt | 1 + core/compiler/tags.txt | 1 + core/compiler/test/alien.factor | 300 + core/compiler/test/curry.factor | 61 + core/compiler/test/float.factor | 85 + core/compiler/test/generic.factor | 30 + core/compiler/test/ifte.factor | 131 + core/compiler/test/intrinsics.factor | 413 + core/compiler/test/optimizer.factor | 275 + core/compiler/test/redefine.factor | 45 + core/compiler/test/simple.factor | 58 + core/compiler/test/stack-trace.factor | 39 + core/compiler/test/templates-early.factor | 131 + core/compiler/test/templates.factor | 187 + core/compiler/test/tuples.factor | 32 + core/continuations/authors.txt | 1 + core/continuations/continuations-docs.factor | 225 + core/continuations/continuations-tests.factor | 70 + core/continuations/continuations.factor | 176 + core/continuations/summary.txt | 1 + core/continuations/tags.txt | 1 + core/cpu/architecture/architecture.factor | 208 + core/cpu/architecture/authors.txt | 1 + core/cpu/architecture/summary.txt | 1 + core/cpu/arm/allot/allot.factor | 84 + core/cpu/arm/architecture/architecture.factor | 327 + core/cpu/arm/arm.factor | 50 + core/cpu/arm/assembler/assembler-tests.factor | 45 + core/cpu/arm/assembler/assembler.factor | 270 + core/cpu/arm/authors.txt | 1 + core/cpu/arm/bootstrap.factor | 4 + core/cpu/arm/intrinsics/intrinsics.factor | 462 + core/cpu/arm/summary.txt | 1 + core/cpu/arm5/arm5.factor | 4 + core/cpu/arm5/assembler/assembler.factor | 74 + core/cpu/arm5/authors.txt | 1 + core/cpu/arm5/intrinsics/intrinsics.factor | 45 + core/cpu/arm5/summary.txt | 1 + core/cpu/ppc/allot/allot.factor | 104 + core/cpu/ppc/allot/authors.txt | 1 + core/cpu/ppc/allot/summary.txt | 1 + core/cpu/ppc/architecture/architecture.factor | 357 + core/cpu/ppc/architecture/authors.txt | 1 + core/cpu/ppc/architecture/summary.txt | 1 + core/cpu/ppc/assembler/assembler.factor | 225 + core/cpu/ppc/assembler/authors.txt | 1 + core/cpu/ppc/assembler/summary.txt | 1 + core/cpu/ppc/authors.txt | 1 + core/cpu/ppc/bootstrap.factor | 128 + core/cpu/ppc/intrinsics/intrinsics.factor | 712 + core/cpu/ppc/linux/bootstrap.factor | 9 + core/cpu/ppc/macosx/bootstrap.factor | 9 + core/cpu/ppc/ppc.factor | 15 + core/cpu/ppc/summary.txt | 1 + core/cpu/summary.txt | 1 + core/cpu/tags.txt | 1 + core/cpu/x86/32/32.factor | 284 + core/cpu/x86/32/bootstrap.factor | 106 + core/cpu/x86/64/64.factor | 175 + core/cpu/x86/64/authors.txt | 1 + core/cpu/x86/64/bootstrap.factor | 4 + core/cpu/x86/64/summary.txt | 1 + core/cpu/x86/allot/allot.factor | 97 + core/cpu/x86/architecture/architecture.factor | 207 + core/cpu/x86/assembler/assembler-tests.factor | 38 + core/cpu/x86/assembler/assembler.factor | 498 + core/cpu/x86/authors.txt | 1 + core/cpu/x86/intrinsics/intrinsics.factor | 575 + core/cpu/x86/sse2/authors.txt | 1 + core/cpu/x86/sse2/sse2.factor | 113 + core/cpu/x86/sse2/summary.txt | 1 + core/cpu/x86/summary.txt | 1 + core/debugger/authors.txt | 1 + core/debugger/debugger-docs.factor | 174 + core/debugger/debugger.factor | 223 + core/debugger/summary.txt | 1 + core/definitions/authors.txt | 1 + core/definitions/definitions-docs.factor | 84 + core/definitions/definitions.factor | 43 + core/definitions/summary.txt | 1 + core/definitions/tags.txt | 2 + core/effects/authors.txt | 1 + core/effects/effects-docs.factor | 66 + core/effects/effects-tests.factor | 9 + core/effects/effects.factor | 53 + core/effects/summary.txt | 1 + core/effects/tags.txt | 1 + core/float-arrays/float-arrays-docs.factor | 54 + core/float-arrays/float-arrays-tests.factor | 4 + core/float-arrays/float-arrays.factor | 40 + core/float-arrays/summary.txt | 1 + core/float-arrays/tags.txt | 1 + core/generator/authors.txt | 1 + core/generator/fixup/authors.txt | 1 + core/generator/fixup/fixup-docs.factor | 32 + core/generator/fixup/fixup.factor | 156 + core/generator/fixup/summary.txt | 1 + core/generator/generator-docs.factor | 109 + core/generator/generator.factor | 325 + core/generator/registers/authors.txt | 1 + core/generator/registers/registers.factor | 563 + core/generator/registers/summary.txt | 1 + core/generator/summary.txt | 1 + core/generator/tags.txt | 1 + core/generic/authors.txt | 1 + core/generic/generic-docs.factor | 169 + core/generic/generic-tests.factor | 199 + core/generic/generic.factor | 107 + core/generic/math/authors.txt | 1 + core/generic/math/math-docs.factor | 44 + core/generic/math/math.factor | 86 + core/generic/math/summary.txt | 1 + core/generic/standard/authors.txt | 1 + core/generic/standard/standard-docs.factor | 33 + core/generic/standard/standard.factor | 184 + core/generic/standard/summary.txt | 1 + core/generic/summary.txt | 1 + core/generic/tags.txt | 1 + core/graphs/authors.txt | 1 + core/graphs/graphs-docs.factor | 35 + core/graphs/graphs-tests.factor | 18 + core/graphs/graphs.factor | 36 + core/graphs/summary.txt | 1 + core/graphs/tags.txt | 1 + core/growable/authors.txt | 1 + core/growable/growable-docs.factor | 48 + core/growable/growable-tests.factor | 26 + core/growable/growable.factor | 63 + core/growable/summary.txt | 1 + core/growable/tags.txt | 1 + core/hashtables/authors.txt | 1 + core/hashtables/hashtables-docs.factor | 138 + core/hashtables/hashtables-tests.factor | 162 + core/hashtables/hashtables.factor | 197 + core/hashtables/summary.txt | 1 + core/hashtables/tags.txt | 1 + core/inference/authors.txt | 1 + core/inference/backend/authors.txt | 1 + core/inference/backend/backend-docs.factor | 81 + core/inference/backend/backend.factor | 472 + core/inference/backend/summary.txt | 1 + core/inference/class/authors.txt | 1 + core/inference/class/class-tests.factor | 233 + core/inference/class/class.factor | 321 + core/inference/class/summary.txt | 1 + core/inference/dataflow/authors.txt | 1 + core/inference/dataflow/dataflow-docs.factor | 8 + core/inference/dataflow/dataflow.factor | 301 + core/inference/dataflow/summary.txt | 1 + core/inference/errors/authors.txt | 1 + core/inference/errors/errors.factor | 58 + core/inference/errors/summary.txt | 1 + core/inference/inference-docs.factor | 141 + core/inference/inference-tests.factor | 559 + core/inference/inference.factor | 27 + core/inference/known-words/authors.txt | 1 + core/inference/known-words/known-words.factor | 532 + core/inference/known-words/summary.txt | 1 + core/inference/stack/authors.txt | 1 + core/inference/stack/stack-docs.factor | 11 + core/inference/stack/stack.factor | 64 + core/inference/stack/summary.txt | 1 + core/inference/summary.txt | 1 + core/inference/tags.txt | 2 + core/inference/transforms/authors.txt | 1 + core/inference/transforms/summary.txt | 1 + .../transforms/transforms-docs.factor | 14 + .../transforms/transforms-tests.factor | 20 + core/inference/transforms/transforms.factor | 62 + core/init/authors.txt | 1 + core/init/init-docs.factor | 41 + core/init/init.factor | 22 + core/init/summary.txt | 1 + core/inspector/authors.txt | 1 + core/inspector/inspector-docs.factor | 111 + core/inspector/inspector-tests.factor | 11 + core/inspector/inspector.factor | 152 + core/inspector/summary.txt | 1 + core/inspector/tags.txt | 2 + core/io/authors.txt | 1 + core/io/backend/authors.txt | 1 + core/io/backend/backend-docs.factor | 12 + core/io/backend/backend-tests.factor | 4 + core/io/backend/backend.factor | 23 + core/io/backend/summary.txt | 1 + core/io/binary/authors.txt | 1 + core/io/binary/binary-docs.factor | 66 + core/io/binary/binary-tests.factor | 8 + core/io/binary/binary.factor | 26 + core/io/binary/summary.txt | 1 + core/io/buffers/authors.txt | 1 + core/io/buffers/buffers-docs.factor | 127 + core/io/buffers/buffers-tests.factor | 79 + core/io/buffers/buffers.factor | 96 + core/io/buffers/summary.txt | 1 + core/io/crc32/authors.txt | 1 + core/io/crc32/crc32-docs.factor | 17 + core/io/crc32/crc32-tests.factor | 5 + core/io/crc32/crc32.factor | 30 + core/io/crc32/summary.txt | 1 + core/io/encodings/encodings.factor | 25 + core/io/files/authors.txt | 1 + core/io/files/files-docs.factor | 159 + core/io/files/files-tests.factor | 67 + core/io/files/files.factor | 106 + core/io/files/summary.txt | 1 + core/io/io-docs.factor | 301 + core/io/io-tests.factor | 59 + core/io/io.factor | 94 + core/io/streams/c/authors.txt | 1 + core/io/streams/c/c-docs.factor | 73 + core/io/streams/c/c.factor | 72 + core/io/streams/c/summary.txt | 1 + core/io/streams/duplex/authors.txt | 1 + core/io/streams/duplex/duplex-docs.factor | 22 + core/io/streams/duplex/duplex-tests.factor | 40 + core/io/streams/duplex/duplex.factor | 81 + core/io/streams/duplex/summary.txt | 1 + core/io/streams/lines/authors.txt | 1 + core/io/streams/lines/lines-docs.factor | 17 + core/io/streams/lines/lines-tests.factor | 50 + core/io/streams/lines/lines.factor | 46 + core/io/streams/lines/summary.txt | 1 + core/io/streams/nested/authors.txt | 1 + core/io/streams/nested/nested-docs.factor | 2 + core/io/streams/nested/nested-tests.factor | 23 + core/io/streams/nested/nested.factor | 47 + core/io/streams/nested/summary.txt | 1 + core/io/streams/plain/authors.txt | 1 + core/io/streams/plain/plain-docs.factor | 24 + core/io/streams/plain/plain.factor | 23 + core/io/streams/plain/summary.txt | 1 + core/io/streams/string/authors.txt | 1 + core/io/streams/string/string-docs.factor | 29 + core/io/streams/string/string-tests.factor | 58 + core/io/streams/string/string.factor | 70 + core/io/streams/string/summary.txt | 1 + core/io/styles/authors.txt | 1 + core/io/styles/styles-docs.factor | 157 + core/io/styles/styles.factor | 44 + core/io/styles/summary.txt | 1 + core/io/summary.txt | 1 + core/io/test/binary.txt | 1 + core/io/test/empty-file.txt | 0 core/io/test/mac-os-eol.txt | 1 + core/io/test/no-trailing-eol.factor | 4 + core/io/test/separator-test.txt | 1 + core/io/test/unix-eol.txt | 2 + core/io/test/windows-eol.txt | 2 + core/io/utf16/authors.txt | 1 + core/io/utf16/summary.txt | 1 + core/io/utf16/utf16-docs.factor | 45 + core/io/utf16/utf16-tests.factor | 15 + core/io/utf16/utf16.factor | 113 + core/io/utf8/authors.txt | 1 + core/io/utf8/summary.txt | 1 + core/io/utf8/utf8-docs.factor | 18 + core/io/utf8/utf8-tests.factor | 16 + core/io/utf8/utf8.factor | 72 + core/kernel/authors.txt | 1 + core/kernel/kernel-docs.factor | 535 + core/kernel/kernel-tests.factor | 77 + core/kernel/kernel.factor | 153 + core/kernel/summary.txt | 1 + core/layouts/authors.txt | 1 + core/layouts/layouts-docs.factor | 37 + core/layouts/layouts.factor | 34 + core/layouts/summary.txt | 1 + core/layouts/tags.txt | 1 + core/libc/authors.txt | 1 + core/libc/libc-docs.factor | 41 + core/libc/libc.factor | 87 + core/libc/summary.txt | 1 + core/libc/tags.txt | 1 + core/listener/authors.txt | 1 + core/listener/listener-docs.factor | 49 + core/listener/listener-tests.factor | 36 + core/listener/listener.factor | 66 + core/listener/summary.txt | 1 + core/listener/tags.txt | 1 + core/math/authors.txt | 1 + core/math/bitfields/authors.txt | 1 + core/math/bitfields/bitfields-docs.factor | 37 + core/math/bitfields/bitfields-tests.factor | 8 + core/math/bitfields/bitfields.factor | 15 + core/math/bitfields/summary.txt | 1 + core/math/complex/authors.txt | 1 + core/math/complex/complex-docs.factor | 40 + core/math/complex/complex-tests.factor | 65 + core/math/complex/complex.factor | 36 + core/math/complex/summary.txt | 1 + core/math/constants/authors.txt | 1 + core/math/constants/constants-docs.factor | 30 + core/math/constants/constants.factor | 9 + core/math/constants/summary.txt | 1 + core/math/floats/authors.txt | 1 + core/math/floats/floats-docs.factor | 93 + core/math/floats/floats-tests.factor | 78 + core/math/floats/floats.factor | 34 + core/math/floats/summary.txt | 1 + core/math/functions/authors.txt | 1 + core/math/functions/functions-docs.factor | 283 + core/math/functions/functions-tests.factor | 74 + core/math/functions/functions.factor | 177 + core/math/functions/summary.txt | 1 + core/math/integers/authors.txt | 1 + core/math/integers/integers-docs.factor | 221 + core/math/integers/integers-tests.factor | 202 + core/math/integers/integers.factor | 72 + core/math/integers/summary.txt | 1 + core/math/intervals/authors.txt | 1 + core/math/intervals/intervals-docs.factor | 277 + core/math/intervals/intervals-tests.factor | 144 + core/math/intervals/intervals.factor | 201 + core/math/intervals/summary.txt | 1 + core/math/libm/authors.txt | 1 + core/math/libm/libm-docs.factor | 75 + core/math/libm/libm.factor | 52 + core/math/libm/summary.txt | 1 + core/math/libm/tags.txt | 1 + core/math/math-docs.factor | 392 + core/math/math-tests.factor | 11 + core/math/math.factor | 186 + core/math/parser/authors.txt | 1 + core/math/parser/parser-docs.factor | 126 + core/math/parser/parser-tests.factor | 130 + core/math/parser/parser.factor | 104 + core/math/parser/summary.txt | 1 + core/math/ratios/authors.txt | 1 + core/math/ratios/ratios-docs.factor | 47 + core/math/ratios/ratios-tests.factor | 81 + core/math/ratios/ratios.factor | 44 + core/math/ratios/summary.txt | 1 + core/math/summary.txt | 1 + core/math/vectors/authors.txt | 1 + core/math/vectors/summary.txt | 1 + core/math/vectors/vectors-docs.factor | 125 + core/math/vectors/vectors-tests.factor | 7 + core/math/vectors/vectors.factor | 33 + core/memory/authors.txt | 1 + core/memory/memory-docs.factor | 83 + core/memory/memory-tests.factor | 15 + core/memory/memory.factor | 16 + core/memory/summary.txt | 1 + core/memory/tags.txt | 1 + core/mirrors/authors.txt | 1 + core/mirrors/mirrors-docs.factor | 51 + core/mirrors/mirrors-tests.factor | 16 + core/mirrors/mirrors.factor | 78 + core/mirrors/summary.txt | 1 + core/mirrors/tags.txt | 2 + core/namespaces/authors.txt | 1 + core/namespaces/namespaces-docs.factor | 186 + core/namespaces/namespaces-tests.factor | 14 + core/namespaces/namespaces.factor | 65 + core/namespaces/summary.txt | 1 + core/namespaces/tags.txt | 1 + core/none/authors.txt | 1 + core/none/none-docs.factor | 4 + core/none/none.factor | 6 + core/none/summary.txt | 1 + core/optimizer/authors.txt | 1 + core/optimizer/backend/authors.txt | 1 + core/optimizer/backend/backend.factor | 366 + core/optimizer/backend/summary.txt | 1 + core/optimizer/debugger/debugger.factor | 119 + core/optimizer/def-use/authors.txt | 1 + core/optimizer/def-use/def-use-tests.factor | 130 + core/optimizer/def-use/def-use.factor | 89 + core/optimizer/def-use/summary.txt | 1 + core/optimizer/known-words/authors.txt | 1 + core/optimizer/known-words/known-words.factor | 166 + core/optimizer/known-words/summary.txt | 1 + core/optimizer/math/authors.txt | 1 + core/optimizer/math/math.factor | 455 + core/optimizer/math/summary.txt | 1 + core/optimizer/optimizer-docs.factor | 49 + core/optimizer/optimizer.factor | 60 + core/optimizer/pattern-match/authors.txt | 1 + .../pattern-match/pattern-match.factor | 32 + core/optimizer/pattern-match/summary.txt | 1 + core/optimizer/summary.txt | 1 + core/optimizer/tags.txt | 1 + core/parser/authors.txt | 1 + core/parser/parser-docs.factor | 610 + core/parser/parser-tests.factor | 346 + core/parser/parser.factor | 522 + core/parser/summary.txt | 1 + core/parser/tags.txt | 1 + core/prettyprint/authors.txt | 1 + core/prettyprint/backend/authors.txt | 1 + core/prettyprint/backend/backend-docs.factor | 56 + core/prettyprint/backend/backend.factor | 193 + core/prettyprint/backend/summary.txt | 1 + core/prettyprint/config/authors.txt | 1 + core/prettyprint/config/config-docs.factor | 35 + core/prettyprint/config/config.factor | 24 + core/prettyprint/config/summary.txt | 1 + core/prettyprint/prettyprint-docs.factor | 256 + core/prettyprint/prettyprint-tests.factor | 285 + core/prettyprint/prettyprint.factor | 240 + core/prettyprint/sections/authors.txt | 1 + .../prettyprint/sections/sections-docs.factor | 226 + core/prettyprint/sections/sections.factor | 343 + core/prettyprint/sections/summary.txt | 1 + core/prettyprint/summary.txt | 1 + core/prettyprint/tags.txt | 2 + core/queues/authors.txt | 1 + core/queues/queues-docs.factor | 77 + core/queues/queues-tests.factor | 12 + core/queues/queues.factor | 57 + core/queues/summary.txt | 1 + core/queues/tags.txt | 1 + core/quotations/authors.txt | 1 + core/quotations/quotations-docs.factor | 62 + core/quotations/quotations-tests.factor | 16 + core/quotations/quotations.factor | 52 + core/quotations/summary.txt | 1 + core/quotations/tags.txt | 1 + core/refs/refs-docs.factor | 52 + core/refs/refs.factor | 25 + core/sbufs/authors.txt | 1 + core/sbufs/sbufs-docs.factor | 33 + core/sbufs/sbufs-tests.factor | 20 + core/sbufs/sbufs.factor | 41 + core/sbufs/summary.txt | 1 + core/sbufs/tags.txt | 1 + core/sequences/authors.txt | 1 + core/sequences/sequences-docs.factor | 945 + core/sequences/sequences-tests.factor | 244 + core/sequences/sequences.factor | 657 + core/sequences/summary.txt | 1 + core/sequences/tags.txt | 1 + core/slots/authors.txt | 1 + core/slots/slots-docs.factor | 134 + core/slots/slots.factor | 105 + core/slots/summary.txt | 1 + core/sorting/authors.txt | 1 + core/sorting/sorting-docs.factor | 63 + core/sorting/sorting-tests.factor | 28 + core/sorting/sorting.factor | 83 + core/sorting/summary.txt | 1 + core/sorting/tags.txt | 1 + core/source-files/authors.txt | 1 + core/source-files/source-files-docs.factor | 82 + core/source-files/source-files.factor | 77 + core/source-files/summary.txt | 1 + core/splitting/authors.txt | 1 + core/splitting/splitting-docs.factor | 94 + core/splitting/splitting-tests.factor | 58 + core/splitting/splitting.factor | 80 + core/splitting/summary.txt | 1 + core/splitting/tags.txt | 1 + core/strings/authors.txt | 1 + core/strings/strings-docs.factor | 112 + core/strings/strings-tests.factor | 68 + core/strings/strings.factor | 76 + core/strings/summary.txt | 1 + core/strings/tags.txt | 1 + core/syntax/authors.txt | 1 + core/syntax/summary.txt | 1 + core/syntax/syntax-docs.factor | 575 + core/syntax/syntax.factor | 162 + core/system/authors.txt | 1 + core/system/summary.txt | 1 + core/system/system-docs.factor | 144 + core/system/system-tests.factor | 5 + core/system/system.factor | 57 + core/threads/authors.txt | 1 + core/threads/summary.txt | 1 + core/threads/threads-docs.factor | 67 + core/threads/threads-tests.factor | 13 + core/threads/threads.factor | 75 + core/tuples/authors.txt | 1 + core/tuples/summary.txt | 1 + core/tuples/tuples-docs.factor | 212 + core/tuples/tuples-tests.factor | 257 + core/tuples/tuples.factor | 145 + core/vectors/authors.txt | 1 + core/vectors/summary.txt | 1 + core/vectors/tags.txt | 1 + core/vectors/vectors-docs.factor | 46 + core/vectors/vectors-tests.factor | 95 + core/vectors/vectors.factor | 29 + core/vocabs/authors.txt | 1 + core/vocabs/loader/authors.txt | 1 + core/vocabs/loader/loader-docs.factor | 142 + core/vocabs/loader/loader-tests.factor | 154 + core/vocabs/loader/loader.factor | 194 + core/vocabs/loader/summary.txt | 1 + core/vocabs/loader/test/a/a.factor | 12 + core/vocabs/loader/test/b/b.factor | 7 + core/vocabs/loader/test/c/c.factor | 4 + core/vocabs/loader/test/d/d.factor | 3 + core/vocabs/loader/test/e/e.factor | 1 + core/vocabs/loader/test/f/f-docs.factor | 4 + core/vocabs/loader/test/f/f.factor | 1 + core/vocabs/summary.txt | 1 + core/vocabs/vocabs-docs.factor | 110 + core/vocabs/vocabs-tests.factor | 5 + core/vocabs/vocabs.factor | 99 + core/words/authors.txt | 1 + core/words/summary.txt | 1 + core/words/tags.txt | 1 + core/words/words-docs.factor | 407 + core/words/words-tests.factor | 145 + core/words/words.factor | 218 + cp_dir | 5 + extra/arrays/lib/lib.factor | 10 + extra/asn1/asn1-tests.factor | 51 + extra/asn1/asn1.factor | 219 + extra/asn1/authors.txt | 1 + extra/asn1/ldap/ldap.factor | 68 + extra/asn1/summary.txt | 1 + extra/automata/authors.txt | 1 + extra/automata/automata.factor | 111 + extra/automata/summary.txt | 1 + extra/automata/tags.txt | 1 + extra/automata/ui/ui.factor | 88 + extra/bake/bake.factor | 52 + extra/balloon-bomber/authors.txt | 1 + .../balloon-bomber/balloon-bomber-docs.factor | 39 + extra/balloon-bomber/balloon-bomber.factor | 23 + extra/balloon-bomber/summary.txt | 1 + extra/balloon-bomber/tags.txt | 2 + extra/base64/authors.txt | 1 + extra/base64/base64-docs.factor | 20 + extra/base64/base64-tests.factor | 8 + extra/base64/base64.factor | 47 + extra/base64/summary.txt | 1 + extra/benchmark/authors.txt | 1 + extra/benchmark/benchmark.factor | 35 + extra/benchmark/bootstrap1/bootstrap1.factor | 4 + extra/benchmark/bootstrap2/bootstrap2.factor | 8 + .../continuations/continuations.factor | 7 + extra/benchmark/dispatch1/dispatch1.factor | 77 + extra/benchmark/dispatch2/dispatch2.factor | 30 + extra/benchmark/dispatch3/dispatch3.factor | 48 + extra/benchmark/dispatch4/dispatch4.factor | 66 + extra/benchmark/empty-loop/empty-loop.factor | 18 + extra/benchmark/fib1/fib1.factor | 14 + extra/benchmark/fib2/fib2.factor | 13 + extra/benchmark/fib3/fib3.factor | 9 + extra/benchmark/fib4/fib4.factor | 22 + extra/benchmark/fib5/fib5.factor | 19 + extra/benchmark/iteration/iteration.factor | 21 + extra/benchmark/mandel/mandel.factor | 71 + .../benchmark/nsieve-bits/nsieve-bits.factor | 36 + extra/benchmark/nsieve/nsieve.factor | 35 + .../partial-sums/partial-sums.factor | 62 + extra/benchmark/raytracer/raytracer.factor | 176 + extra/benchmark/recursive/recursive.factor | 44 + .../benchmark/reverse-complement-test-in.txt | 171 + .../benchmark/reverse-complement-test-out.txt | 171 + .../reverse-complement.factor | 43 + extra/benchmark/ring/ring.factor | 25 + extra/benchmark/sort/sort.factor | 7 + .../spectral-norm/spectral-norm.factor | 55 + extra/benchmark/sum-file/sum-file.factor | 13 + extra/benchmark/summary.txt | 1 + extra/benchmark/typecheck1/typecheck1.factor | 10 + extra/benchmark/typecheck2/typecheck2.factor | 12 + extra/benchmark/typecheck3/typecheck3.factor | 12 + extra/benchmark/typecheck4/typecheck4.factor | 12 + extra/bitfields/authors.txt | 1 + extra/bitfields/bitfields-docs.factor | 16 + extra/bitfields/bitfields-tests.factor | 21 + extra/bitfields/bitfields.factor | 109 + extra/bitfields/summary.txt | 1 + extra/bitfields/tags.txt | 2 + extra/boids/authors.txt | 1 + extra/boids/boids.factor | 233 + extra/boids/summary.txt | 1 + extra/boids/tags.txt | 1 + extra/boids/ui/ui.factor | 167 + extra/browser/analyzer/analyzer.factor | 83 + extra/browser/parser/parser-tests.factor | 63 + extra/browser/parser/parser.factor | 156 + extra/browser/printer/printer.factor | 109 + extra/browser/utils/utils-tests.factor | 24 + extra/browser/utils/utils.factor | 43 + extra/bunny/authors.txt | 1 + extra/bunny/bunny.factor | 115 + extra/bunny/deploy.factor | 12 + extra/bunny/summary.txt | 1 + extra/bunny/tags.txt | 1 + extra/cabal/cabal.factor | 92 + extra/cabal/ui/ui.factor | 52 + extra/cairo/authors.txt | 1 + extra/cairo/cairo.factor | 330 + extra/cairo/summary.txt | 1 + extra/cairo/tags.txt | 1 + extra/calendar/authors.txt | 1 + extra/calendar/calendar-tests.factor | 143 + extra/calendar/calendar.factor | 338 + extra/calendar/summary.txt | 1 + extra/calendar/unix/unix-tests.factor | 13 + extra/calendar/unix/unix.factor | 32 + extra/calendar/windows/windows-tests.factor | 6 + extra/calendar/windows/windows.factor | 48 + extra/catalyst-talk/authors.txt | 1 + extra/catalyst-talk/catalyst-talk.factor | 132 + extra/catalyst-talk/summary.txt | 1 + extra/catalyst-talk/tags.txt | 1 + extra/cfdg/authors.txt | 1 + extra/cfdg/cfdg.factor | 232 + extra/cfdg/gl/gl.factor | 17 + extra/cfdg/hsv/hsv.factor | 39 + extra/cfdg/models/aqua-star/aqua-star.factor | 34 + .../models/chiaroscuro/chiaroscuro.factor | 35 + extra/cfdg/models/flower6/flower6.factor | 28 + .../models/game1-turn6/game1-turn6.factor | 48 + extra/cfdg/models/lesson/lesson.factor | 106 + .../cfdg/models/sierpinski/sierpinski.factor | 39 + extra/cfdg/models/snowflake/snowflake.factor | 35 + extra/channels/authors.txt | 1 + extra/channels/channels-docs.factor | 35 + extra/channels/channels-tests.factor | 48 + extra/channels/channels.factor | 43 + extra/channels/examples/authors.txt | 1 + extra/channels/examples/examples.factor | 51 + extra/channels/examples/summary.txt | 1 + extra/channels/examples/tags.txt | 1 + extra/channels/remote/authors.txt | 1 + extra/channels/remote/remote-docs.factor | 62 + extra/channels/remote/remote-tests.factor | 18 + extra/channels/remote/remote.factor | 64 + extra/channels/remote/summary.txt | 1 + extra/channels/remote/tags.txt | 1 + extra/channels/sniffer/bsd/bsd.factor | 12 + extra/channels/sniffer/sniffer.factor | 14 + extra/channels/summary.txt | 1 + extra/channels/tags.txt | 1 + extra/circular/authors.txt | 2 + extra/circular/circular-tests.factor | 27 + extra/circular/circular.factor | 37 + extra/circular/summary.txt | 1 + extra/circular/tags.txt | 1 + .../cocoa/application/application-docs.factor | 45 + extra/cocoa/application/application.factor | 68 + extra/cocoa/application/authors.txt | 1 + extra/cocoa/application/summary.txt | 1 + extra/cocoa/authors.txt | 1 + extra/cocoa/callbacks/authors.txt | 1 + extra/cocoa/callbacks/callbacks.factor | 33 + extra/cocoa/callbacks/summary.txt | 1 + extra/cocoa/cocoa-docs.factor | 43 + extra/cocoa/cocoa-tests.factor | 50 + extra/cocoa/cocoa.factor | 67 + extra/cocoa/dialogs/authors.txt | 1 + extra/cocoa/dialogs/dialogs-docs.factor | 28 + extra/cocoa/dialogs/dialogs.factor | 34 + extra/cocoa/dialogs/summary.txt | 1 + extra/cocoa/messages/authors.txt | 1 + extra/cocoa/messages/messages-docs.factor | 42 + extra/cocoa/messages/messages.factor | 212 + extra/cocoa/messages/summary.txt | 1 + extra/cocoa/nibs/authors.txt | 1 + extra/cocoa/nibs/nibs-docs.factor | 15 + extra/cocoa/nibs/nibs.factor | 16 + extra/cocoa/nibs/summary.txt | 1 + extra/cocoa/pasteboard/authors.txt | 1 + extra/cocoa/pasteboard/pasteboard-docs.factor | 21 + extra/cocoa/pasteboard/pasteboard.factor | 34 + extra/cocoa/pasteboard/summary.txt | 1 + extra/cocoa/plists/plists.factor | 22 + extra/cocoa/runtime/authors.txt | 1 + extra/cocoa/runtime/runtime.factor | 87 + extra/cocoa/runtime/summary.txt | 1 + extra/cocoa/subclassing/authors.txt | 1 + .../cocoa/subclassing/subclassing-docs.factor | 46 + extra/cocoa/subclassing/subclassing.factor | 117 + extra/cocoa/subclassing/summary.txt | 1 + extra/cocoa/summary.txt | 1 + extra/cocoa/tags.txt | 1 + extra/cocoa/types/authors.txt | 1 + extra/cocoa/types/summary.txt | 1 + extra/cocoa/types/types-docs.factor | 28 + extra/cocoa/types/types.factor | 66 + extra/cocoa/views/authors.txt | 1 + extra/cocoa/views/summary.txt | 1 + extra/cocoa/views/views-docs.factor | 26 + extra/cocoa/views/views.factor | 63 + extra/cocoa/windows/authors.txt | 1 + extra/cocoa/windows/summary.txt | 1 + extra/cocoa/windows/windows-docs.factor | 16 + extra/cocoa/windows/windows.factor | 35 + extra/color-picker/authors.txt | 1 + extra/color-picker/color-picker.factor | 36 + extra/color-picker/deploy.factor | 12 + extra/color-picker/summary.txt | 1 + extra/color-picker/tags.txt | 1 + extra/colors/authors.txt | 1 + extra/colors/colors.factor | 17 + extra/colors/hsv/hsv.factor | 29 + extra/combinators/lib/lib-docs.factor | 99 + extra/combinators/lib/lib-tests.factor | 59 + extra/combinators/lib/lib.factor | 184 + extra/concurrency/authors.txt | 1 + extra/concurrency/concurrency-docs.factor | 171 + extra/concurrency/concurrency-tests.factor | 131 + extra/concurrency/concurrency.factor | 354 + extra/concurrency/distributed/authors.txt | 1 + .../distributed/distributed-docs.factor | 25 + .../distributed/distributed.factor | 43 + extra/concurrency/distributed/summary.txt | 1 + extra/concurrency/distributed/tags.txt | 1 + extra/concurrency/summary.txt | 1 + extra/concurrency/tags.txt | 1 + extra/const/const.factor | 16 + extra/contributors/authors.txt | 1 + extra/contributors/contributors.factor | 33 + extra/contributors/summary.txt | 1 + extra/contributors/tags.txt | 1 + extra/core-foundation/authors.txt | 1 + .../core-foundation-docs.factor | 57 + extra/core-foundation/core-foundation.factor | 74 + extra/core-foundation/summary.txt | 1 + extra/core-foundation/tags.txt | 1 + extra/coroutines/authors.txt | 2 + extra/coroutines/coroutines-docs.factor | 54 + extra/coroutines/coroutines-tests.factor | 19 + extra/coroutines/coroutines.factor | 44 + extra/coroutines/summary.txt | 1 + extra/coroutines/tags.txt | 1 + extra/cpu/8080/8080-docs.factor | 47 + extra/cpu/8080/8080.factor | 1627 ++ extra/cryptlib/authors.txt | 1 + extra/cryptlib/cryptlib-tests.factor | 376 + extra/cryptlib/cryptlib.factor | 234 + extra/cryptlib/libcl/libcl.factor | 1057 + extra/cryptlib/notes.txt | 51 + extra/cryptlib/streams/streams.factor | 157 + extra/cryptlib/streams/tags.txt | 1 + extra/cryptlib/summary.txt | 1 + extra/cryptlib/tags.txt | 1 + extra/cryptlib/test/keys.p15 | Bin 0 -> 1394 bytes extra/cryptlib/test/large_data.txt | 4928 ++++ extra/crypto/authors.txt | 1 + extra/crypto/barrett/barrett-tests.factor | 4 + extra/crypto/barrett/barrett.factor | 8 + extra/crypto/blum-blum-shub.factor | 36 + extra/crypto/common/common-docs.factor | 29 + extra/crypto/common/common.factor | 78 + extra/crypto/hmac/hmac-tests.factor | 11 + extra/crypto/hmac/hmac.factor | 49 + extra/crypto/md5/md5-docs.factor | 17 + extra/crypto/md5/md5-tests.factor | 10 + extra/crypto/md5/md5.factor | 190 + extra/crypto/random.factor | 40 + extra/crypto/rc4.factor | 36 + extra/crypto/rsa.factor | 26 + extra/crypto/rsa/rsa-tests.factor | 7 + extra/crypto/rsa/rsa.factor | 29 + extra/crypto/sha1/sha1-tests.factor | 14 + extra/crypto/sha1/sha1.factor | 133 + extra/crypto/sha2/sha2-tests.factor | 7 + extra/crypto/sha2/sha2.factor | 142 + extra/crypto/summary.txt | 1 + extra/crypto/test/blum-blum-shub.factor | 5 + extra/crypto/test/common.factor | 15 + extra/crypto/test/rsa.factor | 7 + extra/crypto/test/xor.factor | 23 + extra/crypto/timing/timing-tests.factor | 4 + extra/crypto/timing/timing.factor | 7 + extra/crypto/xor.factor | 9 + extra/destructors/authors.txt | 1 + extra/destructors/destructors-docs.factor | 25 + extra/destructors/destructors-tests.factor | 40 + extra/destructors/destructors.factor | 75 + extra/destructors/summary.txt | 1 + extra/dlists/authors.txt | 1 + extra/dlists/dlists-tests.factor | 54 + extra/dlists/dlists.factor | 100 + extra/dlists/summary.txt | 1 + extra/dlists/tags.txt | 1 + extra/documents/authors.txt | 1 + extra/documents/documents-docs.factor | 161 + extra/documents/documents-tests.factor | 77 + extra/documents/documents.factor | 231 + extra/documents/summary.txt | 1 + extra/editors/authors.txt | 1 + extra/editors/editors-docs.factor | 38 + extra/editors/editors.factor | 37 + extra/editors/editpadpro/authors.txt | 1 + .../editors/editpadpro/editpadpro-docs.factor | 6 + extra/editors/editpadpro/editpadpro.factor | 8 + extra/editors/emacs/authors.txt | 1 + extra/editors/emacs/emacs-docs.factor | 13 + extra/editors/emacs/emacs.factor | 14 + extra/editors/gvim/authors.txt | 2 + extra/editors/gvim/gvim.factor | 12 + extra/editors/jedit/authors.txt | 1 + extra/editors/jedit/jedit.factor | 40 + extra/editors/jedit/summary.txt | 1 + extra/editors/scite/authors.txt | 1 + extra/editors/scite/scite.factor | 31 + extra/editors/summary.txt | 1 + extra/editors/tags.txt | 1 + extra/editors/textmate/authors.txt | 1 + extra/editors/textmate/textmate.factor | 9 + extra/editors/vim/authors.txt | 2 + extra/editors/vim/generate-vim-syntax.factor | 10 + extra/editors/vim/vim-docs.factor | 17 + extra/editors/vim/vim.factor | 23 + extra/eval-server/authors.txt | 1 + extra/eval-server/eval-server.factor | 11 + extra/eval-server/summary.txt | 1 + extra/eval-server/tags.txt | 4 + extra/factory/authors.txt | 1 + extra/factory/commands/commands.factor | 75 + extra/factory/deploy.factor | 12 + extra/factory/factory-menus | 121 + extra/factory/factory-rc | 25 + extra/factory/factory.factor | 37 + extra/factory/load/load.factor | 32 + extra/factory/summary.txt | 1 + extra/factory/tags.txt | 1 + extra/fjsc/authors.txt | 1 + extra/fjsc/fjsc-tests.factor | 54 + extra/fjsc/fjsc.factor | 360 + extra/fjsc/resources/bootstrap.factor | 40 + extra/fjsc/resources/bootstrap.js | 737 + extra/fjsc/resources/jquery.js | 1 + extra/fjsc/summary.txt | 1 + extra/freetype/authors.txt | 1 + extra/freetype/freetype.factor | 180 + extra/freetype/summary.txt | 1 + extra/freetype/tags.txt | 1 + extra/furnace/furnace-tests.factor | 47 + extra/furnace/furnace.factor | 143 + .../scaffold/crud-templates/edit.furnace | 21 + .../scaffold/crud-templates/list.furnace | 27 + .../scaffold/crud-templates/show.furnace | 20 + extra/furnace/scaffold/scaffold.factor | 123 + .../furnace/validator/validator-tests.factor | 30 + extra/furnace/validator/validator.factor | 43 + extra/gap-buffer/authors.txt | 1 + extra/gap-buffer/cursortree/authors.txt | 1 + .../cursortree/cursortree-tests.factor | 14 + extra/gap-buffer/cursortree/cursortree.factor | 90 + extra/gap-buffer/cursortree/summary.txt | 1 + extra/gap-buffer/gap-buffer-tests.factor | 40 + extra/gap-buffer/gap-buffer.factor | 271 + extra/gap-buffer/summary.txt | 1 + extra/gap-buffer/tags.txt | 1 + extra/generic/lib/lib.factor | 6 + extra/geom/dim/dim.factor | 16 + extra/geom/pos/pos.factor | 28 + extra/geom/rect/rect.factor | 41 + extra/gesture-logger/authors.txt | 1 + extra/gesture-logger/deploy.factor | 13 + extra/gesture-logger/gesture-logger.factor | 34 + extra/gesture-logger/summary.txt | 1 + extra/golden-section/authors.txt | 1 + extra/golden-section/deploy.factor | 12 + extra/golden-section/golden-section.factor | 67 + extra/golden-section/summary.txt | 1 + extra/golden-section/tags.txt | 1 + extra/graphics/authors.txt | 1 + extra/graphics/bitmap/bitmap.factor | 132 + extra/graphics/tags.txt | 1 + extra/graphics/viewer/viewer.factor | 26 + extra/hardware-info/authors.txt | 1 + extra/hardware-info/hardware-info.factor | 23 + extra/hardware-info/linux/linux.factor | 21 + extra/hardware-info/macosx/macosx.factor | 53 + extra/hardware-info/summary.txt | 1 + extra/hardware-info/windows/ce/ce.factor | 33 + extra/hardware-info/windows/nt/nt.factor | 49 + extra/hardware-info/windows/windows.factor | 58 + extra/hash2/authors.txt | 1 + extra/hash2/hash2-docs.factor | 25 + extra/hash2/hash2-tests.factor | 13 + extra/hash2/hash2.factor | 38 + extra/hash2/summary.txt | 1 + extra/hash2/tags.txt | 1 + extra/hashtables/lib/authors.txt | 1 + extra/hashtables/lib/lib.factor | 19 + extra/hashtables/lib/summary.txt | 1 + extra/hashtables/lib/tags.txt | 1 + extra/hello-ui/authors.txt | 1 + extra/hello-ui/deploy.factor | 12 + extra/hello-ui/hello-ui.factor | 7 + extra/hello-ui/summary.txt | 1 + extra/hello-ui/tags.txt | 1 + extra/hello-world/authors.txt | 1 + extra/hello-world/deploy.factor | 11 + extra/hello-world/hello-world.factor | 6 + extra/hello-world/summary.txt | 1 + extra/hello-world/tags.txt | 1 + extra/help/authors.txt | 1 + extra/help/cookbook/cookbook.factor | 277 + extra/help/crossref/authors.txt | 1 + extra/help/crossref/crossref-docs.factor | 26 + extra/help/crossref/crossref-tests.factor | 54 + extra/help/crossref/crossref.factor | 29 + extra/help/crossref/summary.txt | 1 + extra/help/definitions/authors.txt | 1 + .../help/definitions/definitions-tests.factor | 42 + extra/help/definitions/definitions.factor | 39 + extra/help/definitions/summary.txt | 1 + extra/help/handbook/authors.txt | 1 + extra/help/handbook/handbook.factor | 279 + extra/help/handbook/summary.txt | 1 + extra/help/help-docs.factor | 156 + extra/help/help.factor | 142 + extra/help/lint/authors.txt | 1 + extra/help/lint/lint-docs.factor | 14 + extra/help/lint/lint.factor | 121 + extra/help/lint/summary.txt | 0 extra/help/lint/tags.txt | 1 + extra/help/markup/authors.txt | 1 + extra/help/markup/markup-docs.factor | 206 + extra/help/markup/markup-tests.factor | 29 + extra/help/markup/markup.factor | 361 + extra/help/markup/summary.txt | 1 + extra/help/stylesheet/authors.txt | 1 + extra/help/stylesheet/stylesheet.factor | 98 + extra/help/stylesheet/summary.txt | 1 + extra/help/summary.txt | 1 + extra/help/syntax/authors.txt | 1 + extra/help/syntax/summary.txt | 1 + extra/help/syntax/syntax-docs.factor | 35 + extra/help/syntax/syntax-tests.factor | 23 + extra/help/syntax/syntax.factor | 21 + extra/help/topics/authors.txt | 1 + extra/help/topics/summary.txt | 1 + extra/help/topics/topics-docs.factor | 42 + extra/help/topics/topics-tests.factor | 34 + extra/help/topics/topics.factor | 70 + extra/hexdump/authors.txt | 1 + extra/hexdump/hexdump-docs.factor | 11 + extra/hexdump/hexdump-tests.factor | 8 + extra/hexdump/hexdump.factor | 27 + extra/hexdump/summary.txt | 1 + extra/hints/authors.txt | 1 + extra/hints/hints.factor | 6 + extra/hints/summary.txt | 1 + extra/hints/tags.txt | 1 + extra/html/authors.txt | 3 + extra/html/elements/elements.factor | 156 + extra/html/html-tests.factor | 46 + extra/html/html.factor | 193 + extra/html/summary.txt | 1 + extra/html/tags.txt | 1 + extra/http/authors.txt | 1 + extra/http/basic-authentication/authors.txt | 1 + .../basic-authentication-docs.factor | 68 + .../basic-authentication-tests.factor | 66 + .../basic-authentication.factor | 66 + extra/http/basic-authentication/summary.txt | 1 + extra/http/basic-authentication/tags.txt | 1 + extra/http/client/authors.txt | 1 + extra/http/client/client-tests.factor | 9 + extra/http/client/client.factor | 74 + extra/http/client/summary.txt | 1 + extra/http/client/tags.txt | 2 + extra/http/http-tests.factor | 16 + extra/http/http.factor | 70 + extra/http/mime/mime.factor | 34 + extra/http/server/resources/prototype.js | 1781 ++ extra/http/server/resources/stylesheet.css | 4 + .../responders/callback/callback.factor | 126 + .../continuation/continuation.factor | 191 + .../continuation/examples/examples.factor | 114 + .../examples/numbers/numbers.factor | 95 + extra/http/server/responders/file/file.factor | 116 + .../http/server/responders/responders.factor | 210 + extra/http/server/server-tests.factor | 42 + extra/http/server/server.factor | 65 + extra/http/server/summary.txt | 1 + extra/http/server/tags.txt | 2 + extra/http/server/templating/authors.txt | 2 + .../server/templating/templating-tests.factor | 21 + .../http/server/templating/templating.factor | 85 + extra/http/server/templating/test/bug.fhtml | 5 + extra/http/server/templating/test/bug.html | 2 + .../http/server/templating/test/example.fhtml | 8 + .../http/server/templating/test/example.html | 9 + extra/http/server/templating/test/stack.fhtml | 1 + extra/http/server/templating/test/stack.html | 2 + extra/http/summary.txt | 1 + extra/http/tags.txt | 2 + extra/icfp/2006/2006.factor | 145 + extra/icfp/2006/authors.txt | 1 + extra/icfp/2006/sandmark.umz | Bin 0 -> 56364 bytes extra/icfp/2006/summary.txt | 1 + extra/icfp/2006/tags.txt | 1 + extra/id3/authors.txt | 1 + extra/id3/id3-docs.factor | 28 + extra/id3/id3.factor | 153 + extra/id3/summary.txt | 1 + extra/inverse/authors.txt | 1 + extra/inverse/inverse-docs.factor | 52 + extra/inverse/inverse-tests.factor | 59 + extra/inverse/inverse.factor | 216 + extra/inverse/tags.txt | 1 + extra/io/launcher/authors.txt | 1 + extra/io/launcher/launcher.factor | 13 + extra/io/launcher/summary.txt | 1 + extra/io/mmap/mmap-tests.factor | 10 + extra/io/mmap/mmap.factor | 28 + extra/io/nonblocking/authors.txt | 1 + extra/io/nonblocking/nonblocking-docs.factor | 107 + extra/io/nonblocking/nonblocking.factor | 176 + extra/io/nonblocking/summary.txt | 1 + extra/io/server/server-docs.factor | 37 + extra/io/server/server.factor | 94 + extra/io/sniffer/bsd/bsd.factor | 87 + extra/io/sniffer/filter/bsd/bsd.factor | 32 + extra/io/sniffer/filter/filter.factor | 22 + extra/io/sniffer/sniffer.factor | 10 + extra/io/sockets/authors.txt | 1 + extra/io/sockets/headers/bsd/bsd.factor | 22 + extra/io/sockets/headers/headers.factor | 81 + extra/io/sockets/impl/impl-tests.factor | 45 + extra/io/sockets/impl/impl.factor | 121 + extra/io/sockets/sockets-docs.factor | 153 + extra/io/sockets/sockets.factor | 54 + extra/io/sockets/summary.txt | 1 + extra/io/sockets/tags.txt | 1 + extra/io/streams/null/null.factor | 22 + extra/io/unix/authors.txt | 1 + extra/io/unix/backend/authors.txt | 1 + extra/io/unix/backend/backend.factor | 199 + extra/io/unix/backend/summary.txt | 1 + extra/io/unix/files/authors.txt | 1 + extra/io/unix/files/files-tests.factor | 8 + extra/io/unix/files/files.factor | 43 + extra/io/unix/files/summary.txt | 1 + extra/io/unix/launcher/launcher.factor | 69 + extra/io/unix/mmap/mmap.factor | 22 + extra/io/unix/sockets/authors.txt | 1 + extra/io/unix/sockets/sockets.factor | 210 + extra/io/unix/sockets/summary.txt | 1 + extra/io/unix/summary.txt | 1 + extra/io/unix/unix-tests.factor | 146 + extra/io/unix/unix.factor | 7 + extra/io/windows/authors.txt | 2 + extra/io/windows/ce/authors.txt | 1 + extra/io/windows/ce/ce.factor | 235 + extra/io/windows/ce/summary.txt | 1 + extra/io/windows/launcher/launcher.factor | 166 + extra/io/windows/mmap/mmap.factor | 87 + extra/io/windows/nt/authors.txt | 2 + extra/io/windows/nt/backend/backend.factor | 101 + extra/io/windows/nt/files/files.factor | 70 + extra/io/windows/nt/nt.factor | 51 + extra/io/windows/nt/sockets/sockets.factor | 270 + extra/io/windows/nt/summary.txt | 1 + extra/io/windows/summary.txt | 1 + extra/io/windows/windows-tests.factor | 16 + extra/io/windows/windows.factor | 191 + extra/irc/authors.txt | 2 + extra/irc/irc.factor | 210 + extra/irc/summary.txt | 1 + extra/json/reader/authors.txt | 1 + extra/json/reader/reader-docs.factor | 7 + extra/json/reader/reader.factor | 160 + extra/json/reader/summary.txt | 1 + extra/json/writer/authors.txt | 1 + extra/json/writer/summary.txt | 1 + extra/json/writer/writer-docs.factor | 14 + extra/json/writer/writer.factor | 58 + extra/koszul/koszul-tests.factor | 74 + extra/koszul/koszul.factor | 302 + extra/lazy-lists/authors.txt | 2 + .../lazy-lists/examples/examples-tests.factor | 5 + extra/lazy-lists/examples/examples.factor | 15 + extra/lazy-lists/lazy-lists-docs.factor | 197 + extra/lazy-lists/lazy-lists-tests.factor | 25 + extra/lazy-lists/lazy-lists.factor | 464 + extra/lazy-lists/old-doc.html | 361 + extra/lazy-lists/summary.txt | 1 + extra/lazy-lists/tags.txt | 2 + extra/lcd/authors.txt | 1 + extra/lcd/lcd.factor | 19 + extra/lcd/summary.txt | 1 + extra/lcd/tags.txt | 1 + extra/ldap/authors.txt | 1 + extra/ldap/conf/addentry.ldif | 25 + extra/ldap/conf/createdit.ldif | 45 + extra/ldap/conf/slapd.conf | 67 + extra/ldap/ldap-tests.factor | 54 + extra/ldap/ldap.factor | 133 + extra/ldap/libldap/libldap.factor | 150 + extra/ldap/libldap/tags.txt | 1 + extra/ldap/summary.txt | 1 + extra/ldap/tags.txt | 1 + extra/levenshtein/authors.txt | 1 + extra/levenshtein/levenshtein-tests.factor | 9 + extra/levenshtein/levenshtein.factor | 46 + extra/levenshtein/summary.txt | 1 + extra/lint/authors.txt | 1 + extra/lint/lint-tests.factor | 18 + extra/lint/lint.factor | 158 + extra/lint/tags.txt | 1 + extra/lisp/README | 15 + extra/lisp/authors.txt | 1 + extra/lisp/lexer/lexer.factor | 13 + extra/lisp/lisp.factor | 164 + extra/lisp/listener/listener.factor | 28 + extra/lisp/listener/mod/mod.factor | 20 + extra/lisp/parser/mod/mod.factor | 38 + extra/lisp/summary.txt | 2 + extra/lisp/syntax/syntax.factor | 8 + extra/lisp/tags.txt | 2 + extra/lisppaste/authors.txt | 1 + extra/lisppaste/lisppaste.factor | 12 + extra/lisppaste/summary.txt | 1 + extra/lisppaste/tags.txt | 3 + extra/locals/authors.txt | 1 + extra/locals/locals-docs.factor | 115 + extra/locals/locals-tests.factor | 110 + extra/locals/locals.factor | 336 + extra/locals/summary.txt | 1 + extra/locals/tags.txt | 1 + extra/lsys/authors.txt | 1 + extra/lsys/strings/strings.factor | 60 + extra/lsys/summary.txt | 1 + extra/lsys/tags.txt | 1 + extra/lsys/tortoise/graphics/graphics.factor | 149 + extra/lsys/tortoise/tortoise.factor | 31 + extra/lsys/ui/ui.factor | 493 + extra/lunar-rescue/authors.txt | 1 + extra/lunar-rescue/lunar-rescue-docs.factor | 40 + extra/lunar-rescue/lunar-rescue.factor | 24 + extra/lunar-rescue/summary.txt | 1 + extra/lunar-rescue/tags.txt | 2 + extra/macros/authors.txt | 1 + extra/macros/macros-docs.factor | 39 + extra/macros/macros-tests.factor | 4 + extra/macros/macros.factor | 35 + extra/macros/summary.txt | 1 + extra/macros/tags.txt | 1 + extra/macros/zoo/zoo.factor | 38 + extra/mad/api/api.factor | 102 + extra/mad/authors.txt | 1 + extra/mad/mad-tests.factor | 12 + extra/mad/mad.factor | 159 + extra/mad/player/player.factor | 59 + extra/mad/summary.txt | 1 + extra/match/authors.txt | 1 + extra/match/match-docs.factor | 64 + extra/match/match-tests.factor | 85 + extra/match/match.factor | 61 + extra/match/summary.txt | 1 + extra/match/tags.txt | 1 + extra/math/analysis/analysis-tests.factor | 34 + extra/math/analysis/analysis.factor | 110 + extra/math/analysis/authors.txt | 1 + extra/math/analysis/summary.txt | 1 + extra/math/combinatorics/authors.txt | 2 + extra/math/combinatorics/combinatorics.factor | 21 + extra/math/combinatorics/summary.txt | 1 + extra/math/fft/authors.txt | 1 + extra/math/fft/fft.factor | 15 + extra/math/fft/summary.txt | 1 + extra/math/haar/haar.factor | 15 + extra/math/haar/summary.txt | 1 + extra/math/matrices/authors.txt | 1 + extra/math/matrices/elimination/authors.txt | 1 + .../elimination/elimination-tests.factor | 168 + .../matrices/elimination/elimination.factor | 110 + extra/math/matrices/elimination/summary.txt | 1 + extra/math/matrices/matrices-tests.factor | 104 + extra/math/matrices/matrices.factor | 61 + extra/math/matrices/summary.txt | 1 + .../miller-rabin/miller-rabin-tests.factor | 10 + extra/math/miller-rabin/miller-rabin.factor | 90 + extra/math/numerical-integration/authors.txt | 1 + .../numerical-integration-tests.factor | 9 + .../numerical-integration.factor | 18 + extra/math/numerical-integration/summary.txt | 1 + extra/math/polynomials/authors.txt | 1 + .../math/polynomials/polynomials-tests.factor | 31 + extra/math/polynomials/polynomials.factor | 86 + extra/math/polynomials/summary.txt | 1 + extra/math/primes/list/list.factor | 6421 +++++ extra/math/quadratic/authors.txt | 1 + extra/math/quadratic/quadratic.factor | 20 + extra/math/quadratic/summary.txt | 1 + extra/math/quaternions/authors.txt | 1 + .../math/quaternions/quaternions-tests.factor | 26 + extra/math/quaternions/quaternions.factor | 78 + extra/math/quaternions/summary.txt | 1 + extra/math/ranges/authors.txt | 2 + extra/math/ranges/ranges-tests.factor | 23 + extra/math/ranges/ranges.factor | 41 + extra/math/ranges/summary.txt | 1 + extra/math/statistics/authors.txt | 1 + extra/math/statistics/statistics-tests.factor | 23 + extra/math/statistics/statistics.factor | 65 + extra/math/statistics/summary.txt | 1 + extra/math/trig/trig.factor | 7 + extra/maze/authors.txt | 1 + extra/maze/deploy.factor | 13 + extra/maze/maze.factor | 67 + extra/maze/summary.txt | 1 + extra/maze/tags.txt | 1 + extra/memoize/authors.txt | 2 + extra/memoize/memoize-docs.factor | 15 + extra/memoize/memoize-tests.factor | 10 + extra/memoize/memoize.factor | 48 + extra/memoize/summary.txt | 1 + extra/memoize/tags.txt | 1 + extra/models/authors.txt | 1 + extra/models/models-docs.factor | 306 + extra/models/models-tests.factor | 108 + extra/models/models.factor | 234 + extra/models/summary.txt | 1 + extra/models/tags.txt | 1 + extra/mortar/authors.txt | 1 + extra/mortar/mortar.factor | 187 + extra/mortar/tags.txt | 1 + extra/msxml-to-csv/authors.txt | 1 + extra/msxml-to-csv/msxml-to-csv.factor | 18 + extra/msxml-to-csv/summary.txt | 1 + extra/msxml-to-csv/tags.txt | 1 + extra/namespaces/lib/authors.txt | 1 + extra/namespaces/lib/lib.factor | 19 + extra/namespaces/lib/summary.txt | 1 + extra/namespaces/lib/tags.txt | 1 + extra/nehe/2/2.factor | 46 + extra/nehe/3/3.factor | 50 + extra/nehe/4/4.factor | 74 + extra/nehe/5/5.factor | 125 + extra/nehe/authors.txt | 1 + extra/nehe/deploy.factor | 13 + extra/nehe/nehe.factor | 15 + extra/nehe/summary.txt | 1 + extra/nehe/tags.txt | 1 + extra/numbers-game/authors.txt | 1 + extra/numbers-game/numbers-game.factor | 27 + extra/numbers-game/summary.txt | 1 + extra/numbers-game/tags.txt | 1 + extra/odbc/authors.txt | 1 + extra/odbc/odbc-docs.factor | 97 + extra/odbc/odbc.factor | 270 + extra/odbc/summary.txt | 1 + extra/odbc/tags.txt | 1 + extra/ogg/authors.txt | 1 + extra/ogg/ogg.factor | 133 + extra/ogg/player/authors.txt | 1 + extra/ogg/player/player.factor | 624 + extra/ogg/player/summary.txt | 1 + extra/ogg/player/tags.txt | 2 + extra/ogg/summary.txt | 1 + extra/ogg/tags.txt | 3 + extra/ogg/theora/authors.txt | 1 + extra/ogg/theora/summary.txt | 1 + extra/ogg/theora/tags.txt | 1 + extra/ogg/theora/theora.factor | 121 + extra/ogg/vorbis/authors.txt | 1 + extra/ogg/vorbis/summary.txt | 1 + extra/ogg/vorbis/tags.txt | 1 + extra/ogg/vorbis/vorbis.factor | 142 + extra/openal/authors.txt | 1 + extra/openal/example/example.factor | 34 + extra/openal/macosx/macosx.factor | 14 + extra/openal/openal.factor | 308 + extra/openal/other/other.factor | 14 + extra/openal/summary.txt | 1 + extra/openal/tags.txt | 2 + extra/opengl/authors.txt | 1 + extra/opengl/camera/camera.factor | 16 + extra/opengl/gl/authors.txt | 1 + extra/opengl/gl/gl.factor | 1312 + extra/opengl/gl/summary.txt | 1 + extra/opengl/gl/tags.txt | 1 + extra/opengl/glu/authors.txt | 1 + extra/opengl/glu/glu.factor | 255 + extra/opengl/glu/summary.txt | 1 + extra/opengl/glu/tags.txt | 1 + extra/opengl/lib/lib.factor | 19 + extra/opengl/opengl-docs.factor | 117 + extra/opengl/opengl.factor | 152 + extra/opengl/summary.txt | 1 + extra/opengl/tags.txt | 1 + extra/openssl/authors.txt | 1 + extra/openssl/libcrypto/libcrypto.factor | 129 + extra/openssl/libssl/libssl.factor | 174 + extra/openssl/openssl-tests.factor | 144 + extra/openssl/openssl.factor | 153 + extra/openssl/tags.txt | 2 + extra/openssl/test/dh1024.pem | 5 + extra/openssl/test/errors.txt | 1 + extra/openssl/test/root.pem | 14 + extra/openssl/test/server.pem | 32 + extra/oracle/authors.txt | 1 + extra/oracle/liboci/liboci.factor | 194 + extra/oracle/oracle-tests.factor | 57 + extra/oracle/oracle.factor | 256 + extra/oracle/summary.txt | 1 + extra/oracle/tags.txt | 1 + extra/ori/authors.txt | 1 + extra/ori/ori.factor | 85 + extra/pack/authors.txt | 1 + extra/pack/pack-tests.factor | 47 + extra/pack/pack.factor | 179 + extra/parser-combinators/authors.txt | 1 + .../parser-combinators-docs.factor | 16 + .../parser-combinators-tests.factor | 153 + .../parser-combinators.factor | 254 + .../parser-combinators.html | 341 + .../replace/replace-docs.factor | 76 + .../parser-combinators/replace/replace.factor | 37 + .../simple/simple-docs.factor | 84 + extra/parser-combinators/simple/simple.factor | 32 + extra/parser-combinators/summary.txt | 1 + extra/partial-continuations/authors.txt | 1 + .../partial-continuations-docs.factor | 22 + .../partial-continuations-tests.factor | 16 + .../partial-continuations.factor | 22 + extra/partial-continuations/summary.txt | 1 + extra/partial-continuations/tags.txt | 1 + extra/pdf/authors.txt | 1 + extra/pdf/libhpdf/libhpdf.factor | 180 + extra/pdf/pdf-tests.factor | 97 + extra/pdf/pdf.factor | 97 + extra/pdf/readme.txt | 9 + extra/pdf/test/font_test.pdf | 300 + extra/porter-stemmer/authors.txt | 1 + .../porter-stemmer/porter-stemmer-docs.factor | 74 + .../porter-stemmer-tests.factor | 66 + extra/porter-stemmer/porter-stemmer.factor | 221 + extra/porter-stemmer/summary.txt | 1 + extra/porter-stemmer/test/output.txt | 23531 ++++++++++++++++ extra/porter-stemmer/test/voc.txt | 23531 ++++++++++++++++ extra/pos/authors.txt | 1 + extra/pos/pos.factor | 21 + extra/postgresql/authors.txt | 1 + extra/postgresql/libpq/libpq.factor | 362 + extra/postgresql/postgresql-tests.factor | 42 + extra/postgresql/postgresql.factor | 61 + extra/promises/authors.txt | 1 + extra/promises/promises-docs.factor | 33 + extra/promises/promises.factor | 45 + extra/promises/summary.txt | 1 + extra/promises/tags.txt | 1 + extra/qualified/authors.txt | 1 + extra/qualified/qualified-docs.factor | 7 + extra/qualified/qualified-tests.factor | 8 + extra/qualified/qualified.factor | 13 + extra/qualified/summary.txt | 1 + extra/qualified/tags.txt | 1 + extra/random-weighted/authors.txt | 1 + extra/random-weighted/random-weighted.factor | 16 + extra/random/authors.txt | 1 + extra/random/random-docs.factor | 23 + extra/random/random-tests.factor | 15 + extra/random/random.factor | 105 + extra/random/summary.txt | 1 + extra/rewrite-closures/authors.txt | 1 + .../rewrite-closures/rewrite-closures.factor | 31 + extra/rewrite-closures/summary.txt | 1 + extra/rewrite-closures/tags.txt | 1 + extra/roman/authors.txt | 1 + extra/roman/roman-docs.factor | 45 + extra/roman/roman-tests.factor | 42 + extra/roman/roman.factor | 90 + extra/roman/summary.txt | 1 + extra/roman/tags.txt | 1 + extra/rot13/authors.txt | 1 + extra/rot13/rot13.factor | 24 + extra/rot13/summary.txt | 1 + extra/rot13/tags.txt | 1 + extra/rss/atom.xml | 45 + extra/rss/reader/reader.factor | 133 + extra/rss/readme.txt | 32 + extra/rss/rss-tests.factor | 37 + extra/rss/rss.factor | 97 + extra/rss/rss1.xml | 67 + extra/self/authors.txt | 1 + extra/self/self.factor | 12 + extra/sequences/lib/authors.txt | 2 + extra/sequences/lib/lib-tests.factor | 30 + extra/sequences/lib/lib.factor | 48 + extra/sequences/lib/tags.txt | 1 + extra/sequences/next/authors.txt | 1 + extra/sequences/next/next-tests.factor | 5 + extra/sequences/next/next.factor | 20 + extra/sequences/next/tags.txt | 1 + extra/serialize/authors.txt | 2 + extra/serialize/serialize-docs.factor | 49 + extra/serialize/serialize-tests.factor | 60 + extra/serialize/serialize.factor | 273 + extra/serialize/summary.txt | 1 + extra/shuffle/authors.txt | 2 + extra/shuffle/shuffle-docs.factor | 83 + extra/shuffle/shuffle-tests.factor | 25 + extra/shuffle/shuffle.factor | 32 + extra/shuffle/summary.txt | 1 + extra/shuffle/tags.txt | 1 + extra/shufflers/authors.txt | 1 + extra/shufflers/shufflers-docs.factor | 12 + extra/shufflers/shufflers-tests.factor | 9 + extra/shufflers/shufflers.factor | 47 + extra/shufflers/summary.txt | 1 + extra/shufflers/tags.txt | 1 + extra/slides/authors.txt | 1 + extra/slides/slides.factor | 92 + extra/smtp/authors.txt | 1 + extra/smtp/smtp-server.factor | 68 + extra/smtp/smtp-tests.factor | 41 + extra/smtp/smtp.factor | 138 + extra/smtp/summary.txt | 1 + extra/smtp/tags.txt | 1 + extra/space-invaders/authors.txt | 1 + extra/space-invaders/resources/BaseHit.wav | Bin 0 -> 6592 bytes extra/space-invaders/resources/InvHit.Wav | Bin 0 -> 4124 bytes extra/space-invaders/resources/Shot.wav | Bin 0 -> 3456 bytes extra/space-invaders/resources/Ufo.wav | Bin 0 -> 1846 bytes extra/space-invaders/resources/UfoHit.wav | Bin 0 -> 25850 bytes extra/space-invaders/resources/Walk1.wav | Bin 0 -> 1176 bytes extra/space-invaders/resources/Walk2.wav | Bin 0 -> 1060 bytes extra/space-invaders/resources/Walk3.wav | Bin 0 -> 1120 bytes extra/space-invaders/resources/Walk4.wav | Bin 0 -> 1132 bytes .../space-invaders/space-invaders-docs.factor | 40 + extra/space-invaders/space-invaders.factor | 372 + extra/space-invaders/summary.txt | 1 + extra/space-invaders/tags.txt | 2 + extra/splay-trees/authors.txt | 1 + extra/splay-trees/splay-trees-tests.factor | 33 + extra/splay-trees/splay-trees.factor | 178 + extra/splay-trees/summary.txt | 1 + extra/splay-trees/tags.txt | 1 + extra/sqlite/lib/lib.factor | 121 + extra/sqlite/sqlite-docs.factor | 86 + extra/sqlite/sqlite-tests.factor | 69 + extra/sqlite/sqlite.factor | 127 + extra/sqlite/test.txt | 3 + extra/sqlite/tuple-db/tuple-db-docs.factor | 128 + extra/sqlite/tuple-db/tuple-db-tests.factor | 39 + extra/sqlite/tuple-db/tuple-db.factor | 270 + extra/state-machine/state-machine.factor | 41 + extra/state-parser/authors.txt | 1 + extra/state-parser/state-parser-docs.factor | 72 + extra/state-parser/state-parser-tests.factor | 8 + extra/state-parser/state-parser.factor | 140 + extra/state-parser/summary.txt | 1 + extra/store/authors.txt | 1 + extra/store/blob/blob.factor | 22 + extra/store/store.factor | 33 + extra/strings/lib/lib.factor | 8 + extra/strings/lib/tags.txt | 1 + extra/structs/structs.factor | 13 + extra/structs/tags.txt | 1 + extra/sudoku/authors.txt | 1 + extra/sudoku/sudoku.factor | 93 + extra/sudoku/summary.txt | 1 + extra/sudoku/tags.txt | 1 + extra/tar/tar.factor | 245 + extra/tetris/README.txt | 16 + extra/tetris/authors.txt | 1 + extra/tetris/board/board-tests.factor | 24 + extra/tetris/board/board.factor | 56 + extra/tetris/deploy.factor | 13 + extra/tetris/game/game-tests.factor | 16 + extra/tetris/game/game.factor | 113 + extra/tetris/gl/gl.factor | 47 + extra/tetris/piece/piece-tests.factor | 23 + extra/tetris/piece/piece.factor | 47 + extra/tetris/summary.txt | 1 + extra/tetris/tags.txt | 2 + extra/tetris/tetris.factor | 59 + extra/tetris/tetromino/tetromino.factor | 114 + extra/timers/authors.txt | 1 + extra/timers/summary.txt | 1 + extra/timers/timers-docs.factor | 36 + extra/timers/timers.factor | 30 + .../tools/annotations/annotations-docs.factor | 29 + .../annotations/annotations-tests.factor | 7 + extra/tools/annotations/annotations.factor | 28 + extra/tools/annotations/authors.txt | 1 + extra/tools/annotations/summary.txt | 1 + extra/tools/annotations/tags.txt | 1 + extra/tools/browser/browser-docs.factor | 30 + extra/tools/browser/browser-tests.factor | 6 + extra/tools/browser/browser.factor | 345 + extra/tools/browser/tags.txt | 1 + extra/tools/completion/authors.txt | 1 + extra/tools/completion/completion-docs.factor | 53 + extra/tools/completion/completion.factor | 76 + extra/tools/completion/summary.txt | 1 + extra/tools/crossref/authors.txt | 1 + extra/tools/crossref/crossref-docs.factor | 20 + extra/tools/crossref/crossref-tests.factor | 12 + extra/tools/crossref/crossref.factor | 38 + extra/tools/crossref/summary.txt | 1 + extra/tools/crossref/tags.txt | 1 + extra/tools/deploy/app/app.factor | 72 + extra/tools/deploy/app/summary.txt | 1 + extra/tools/deploy/app/tags.txt | 1 + extra/tools/deploy/authors.txt | 1 + extra/tools/deploy/deploy-docs.factor | 122 + extra/tools/deploy/deploy.factor | 287 + extra/tools/deploy/strip-cocoa.factor | 30 + extra/tools/deploy/strip-debugger.factor | 4 + extra/tools/deploy/summary.txt | 1 + extra/tools/deploy/tags.txt | 1 + extra/tools/interpreter/authors.txt | 1 + .../tools/interpreter/interpreter-docs.factor | 207 + .../interpreter/interpreter-tests.factor | 157 + extra/tools/interpreter/interpreter.factor | 190 + extra/tools/interpreter/summary.txt | 1 + extra/tools/memory/authors.txt | 1 + extra/tools/memory/memory-docs.factor | 25 + extra/tools/memory/memory-tests.factor | 4 + extra/tools/memory/memory.factor | 62 + extra/tools/memory/summary.txt | 1 + extra/tools/memory/tags.txt | 1 + extra/tools/profiler/authors.txt | 1 + extra/tools/profiler/profiler-docs.factor | 76 + extra/tools/profiler/profiler-tests.factor | 32 + extra/tools/profiler/profiler.factor | 83 + extra/tools/profiler/summary.txt | 1 + extra/tools/profiler/tags.txt | 1 + extra/tools/summary.txt | 1 + extra/tools/test/authors.txt | 1 + extra/tools/test/foo.factor | 4 + extra/tools/test/summary.txt | 1 + extra/tools/test/tags.txt | 1 + extra/tools/test/test-docs.factor | 25 + extra/tools/test/test.factor | 79 + extra/tools/test/tools.factor | 5 + extra/tools/time/authors.txt | 1 + extra/tools/time/summary.txt | 1 + extra/tools/time/tags.txt | 1 + extra/tools/time/time-docs.factor | 33 + extra/tools/time/time.factor | 14 + extra/tools/walker/authors.txt | 1 + extra/tools/walker/summary.txt | 1 + extra/tools/walker/tags.txt | 1 + extra/tools/walker/walker.factor | 6 + extra/trees/authors.txt | 1 + extra/trees/avl-tree/avl-tree-tests.factor | 137 + extra/trees/avl-tree/avl-tree.factor | 174 + extra/trees/bst/bst-tests.factor | 45 + extra/trees/bst/bst.factor | 87 + extra/trees/summary.txt | 1 + extra/trees/tags.txt | 1 + extra/trees/trees.factor | 193 + extra/tty-server/authors.txt | 1 + extra/tty-server/summary.txt | 1 + extra/tty-server/tags.txt | 4 + extra/tty-server/tty-server.factor | 11 + extra/tuple-arrays/authors.txt | 1 + extra/tuple-arrays/summary.txt | 1 + extra/tuple-arrays/tags.txt | 1 + extra/tuple-arrays/tuple-arrays-docs.factor | 8 + extra/tuple-arrays/tuple-arrays-tests.factor | 15 + extra/tuple-arrays/tuple-arrays.factor | 41 + extra/tuples/lib/authors.txt | 1 + extra/tuples/lib/lib-docs.factor | 25 + extra/tuples/lib/lib-tests.factor | 8 + extra/tuples/lib/lib.factor | 17 + extra/turing/authors.txt | 1 + extra/turing/summary.txt | 1 + extra/turing/tags.txt | 1 + extra/turing/turing.factor | 70 + extra/turtle/authors.txt | 1 + extra/turtle/turtle.factor | 47 + extra/ui/authors.txt | 1 + extra/ui/backend/authors.txt | 1 + extra/ui/backend/backend.factor | 20 + extra/ui/backend/summary.txt | 1 + extra/ui/clipboards/authors.txt | 1 + extra/ui/clipboards/clipboards-docs.factor | 33 + extra/ui/clipboards/clipboards.factor | 31 + extra/ui/clipboards/summary.txt | 1 + extra/ui/cocoa/authors.txt | 1 + extra/ui/cocoa/cocoa.factor | 96 + extra/ui/cocoa/summary.txt | 1 + extra/ui/cocoa/tools/authors.txt | 1 + extra/ui/cocoa/tools/summary.txt | 1 + extra/ui/cocoa/tools/tools.factor | 86 + extra/ui/cocoa/views/authors.txt | 1 + extra/ui/cocoa/views/summary.txt | 1 + extra/ui/cocoa/views/views.factor | 353 + extra/ui/commands/authors.txt | 1 + extra/ui/commands/commands-docs.factor | 129 + extra/ui/commands/commands-tests.factor | 31 + extra/ui/commands/commands.factor | 86 + extra/ui/commands/summary.txt | 1 + extra/ui/freetype/authors.txt | 1 + extra/ui/freetype/freetype-docs.factor | 54 + extra/ui/freetype/freetype.factor | 189 + extra/ui/freetype/summary.txt | 1 + extra/ui/gadgets/authors.txt | 1 + extra/ui/gadgets/books/authors.txt | 1 + extra/ui/gadgets/books/books-docs.factor | 11 + extra/ui/gadgets/books/books.factor | 29 + extra/ui/gadgets/books/summary.txt | 1 + extra/ui/gadgets/borders/authors.txt | 1 + extra/ui/gadgets/borders/borders-docs.factor | 16 + extra/ui/gadgets/borders/borders.factor | 26 + extra/ui/gadgets/borders/summary.txt | 1 + extra/ui/gadgets/buttons/authors.txt | 1 + extra/ui/gadgets/buttons/buttons-docs.factor | 84 + extra/ui/gadgets/buttons/buttons-tests.factor | 19 + extra/ui/gadgets/buttons/buttons.factor | 126 + extra/ui/gadgets/buttons/summary.txt | 1 + extra/ui/gadgets/canvas/canvas.factor | 34 + extra/ui/gadgets/controls/authors.txt | 1 + .../ui/gadgets/controls/controls-docs.factor | 51 + extra/ui/gadgets/controls/controls.factor | 37 + extra/ui/gadgets/controls/summary.txt | 1 + extra/ui/gadgets/editors/authors.txt | 1 + extra/ui/gadgets/editors/editors-docs.factor | 111 + extra/ui/gadgets/editors/editors-tests.factor | 29 + extra/ui/gadgets/editors/editors.factor | 427 + extra/ui/gadgets/editors/summary.txt | 1 + extra/ui/gadgets/frames/authors.txt | 1 + extra/ui/gadgets/frames/frames-docs.factor | 42 + extra/ui/gadgets/frames/frames-tests.factor | 4 + extra/ui/gadgets/frames/frames.factor | 46 + extra/ui/gadgets/frames/summary.txt | 1 + extra/ui/gadgets/gadgets-docs.factor | 261 + extra/ui/gadgets/gadgets-tests.factor | 110 + extra/ui/gadgets/gadgets.factor | 359 + extra/ui/gadgets/grid-lines/authors.txt | 1 + .../gadgets/grid-lines/grid-lines-docs.factor | 5 + extra/ui/gadgets/grid-lines/grid-lines.factor | 35 + extra/ui/gadgets/grid-lines/summary.txt | 1 + extra/ui/gadgets/grids/authors.txt | 1 + extra/ui/gadgets/grids/grids-docs.factor | 32 + extra/ui/gadgets/grids/grids-tests.factor | 47 + extra/ui/gadgets/grids/grids.factor | 88 + extra/ui/gadgets/grids/summary.txt | 1 + extra/ui/gadgets/handler/handler.factor | 11 + extra/ui/gadgets/incremental/authors.txt | 1 + .../incremental/incremental-docs.factor | 27 + .../ui/gadgets/incremental/incremental.factor | 55 + extra/ui/gadgets/incremental/summary.txt | 1 + extra/ui/gadgets/labelled/authors.txt | 1 + .../ui/gadgets/labelled/labelled-docs.factor | 34 + .../ui/gadgets/labelled/labelled-tests.factor | 27 + extra/ui/gadgets/labelled/labelled.factor | 63 + extra/ui/gadgets/labelled/summary.txt | 1 + extra/ui/gadgets/labels/authors.txt | 1 + extra/ui/gadgets/labels/labels-docs.factor | 35 + extra/ui/gadgets/labels/labels.factor | 49 + extra/ui/gadgets/labels/summary.txt | 1 + extra/ui/gadgets/lib/lib.factor | 6 + extra/ui/gadgets/lists/authors.txt | 1 + extra/ui/gadgets/lists/lists-docs.factor | 33 + extra/ui/gadgets/lists/lists-tests.factor | 5 + extra/ui/gadgets/lists/lists.factor | 121 + extra/ui/gadgets/lists/summary.txt | 1 + extra/ui/gadgets/menus/authors.txt | 1 + extra/ui/gadgets/menus/menus-docs.factor | 6 + extra/ui/gadgets/menus/menus.factor | 52 + extra/ui/gadgets/menus/summary.txt | 1 + extra/ui/gadgets/packs/authors.txt | 1 + extra/ui/gadgets/packs/packs-docs.factor | 60 + extra/ui/gadgets/packs/packs-tests.factor | 15 + extra/ui/gadgets/packs/packs.factor | 73 + extra/ui/gadgets/packs/summary.txt | 1 + extra/ui/gadgets/panes/authors.txt | 1 + extra/ui/gadgets/panes/panes-docs.factor | 77 + extra/ui/gadgets/panes/panes-tests.factor | 35 + extra/ui/gadgets/panes/panes.factor | 420 + extra/ui/gadgets/panes/summary.txt | 1 + extra/ui/gadgets/paragraphs/authors.txt | 1 + extra/ui/gadgets/paragraphs/paragraphs.factor | 72 + extra/ui/gadgets/paragraphs/summary.txt | 1 + extra/ui/gadgets/presentations/authors.txt | 1 + .../presentations/presentations-docs.factor | 50 + .../presentations/presentations-tests.factor | 14 + .../presentations/presentations.factor | 55 + extra/ui/gadgets/presentations/summary.txt | 1 + extra/ui/gadgets/scrollers/authors.txt | 1 + .../gadgets/scrollers/scrollers-docs.factor | 59 + .../gadgets/scrollers/scrollers-tests.factor | 76 + extra/ui/gadgets/scrollers/scrollers.factor | 127 + extra/ui/gadgets/scrollers/summary.txt | 1 + extra/ui/gadgets/slate/slate.factor | 20 + extra/ui/gadgets/sliders/authors.txt | 1 + extra/ui/gadgets/sliders/sliders-docs.factor | 62 + extra/ui/gadgets/sliders/sliders.factor | 178 + extra/ui/gadgets/sliders/summary.txt | 1 + extra/ui/gadgets/slots/authors.txt | 1 + extra/ui/gadgets/slots/slots-tests.factor | 4 + extra/ui/gadgets/slots/slots.factor | 125 + extra/ui/gadgets/slots/summary.txt | 1 + extra/ui/gadgets/status-bar/authors.txt | 1 + .../gadgets/status-bar/status-bar-docs.factor | 9 + extra/ui/gadgets/status-bar/status-bar.factor | 16 + extra/ui/gadgets/status-bar/summary.txt | 1 + extra/ui/gadgets/summary.txt | 1 + extra/ui/gadgets/theme/authors.txt | 1 + extra/ui/gadgets/theme/summary.txt | 1 + extra/ui/gadgets/theme/theme.factor | 57 + extra/ui/gadgets/tracks/authors.txt | 1 + extra/ui/gadgets/tracks/summary.txt | 1 + extra/ui/gadgets/tracks/tracks-docs.factor | 27 + extra/ui/gadgets/tracks/tracks-tests.factor | 15 + extra/ui/gadgets/tracks/tracks.factor | 66 + extra/ui/gadgets/viewports/authors.txt | 1 + extra/ui/gadgets/viewports/summary.txt | 1 + .../gadgets/viewports/viewports-docs.factor | 9 + extra/ui/gadgets/viewports/viewports.factor | 46 + extra/ui/gadgets/worlds/authors.txt | 1 + extra/ui/gadgets/worlds/summary.txt | 1 + extra/ui/gadgets/worlds/worlds-docs.factor | 60 + extra/ui/gadgets/worlds/worlds-tests.factor | 68 + extra/ui/gadgets/worlds/worlds.factor | 129 + extra/ui/gestures/authors.txt | 1 + extra/ui/gestures/gestures-docs.factor | 327 + extra/ui/gestures/gestures.factor | 262 + extra/ui/gestures/summary.txt | 1 + extra/ui/operations/authors.txt | 1 + extra/ui/operations/operations-docs.factor | 86 + extra/ui/operations/operations-tests.factor | 28 + extra/ui/operations/operations.factor | 85 + extra/ui/operations/summary.txt | 1 + extra/ui/render/authors.txt | 1 + extra/ui/render/render-docs.factor | 150 + extra/ui/render/render.factor | 185 + extra/ui/render/summary.txt | 1 + extra/ui/summary.txt | 1 + extra/ui/tools/authors.txt | 1 + extra/ui/tools/browser/authors.txt | 1 + extra/ui/tools/browser/browser.factor | 59 + extra/ui/tools/browser/summary.txt | 1 + extra/ui/tools/browser/tags.txt | 1 + extra/ui/tools/debugger/authors.txt | 1 + extra/ui/tools/debugger/debugger-docs.factor | 14 + extra/ui/tools/debugger/debugger.factor | 61 + extra/ui/tools/debugger/summary.txt | 1 + extra/ui/tools/debugger/tags.txt | 1 + extra/ui/tools/inspector/authors.txt | 1 + extra/ui/tools/inspector/inspector.factor | 47 + extra/ui/tools/inspector/summary.txt | 1 + extra/ui/tools/inspector/tags.txt | 1 + extra/ui/tools/interactor/authors.txt | 1 + .../tools/interactor/interactor-docs.factor | 9 + extra/ui/tools/interactor/interactor.factor | 164 + extra/ui/tools/interactor/summary.txt | 1 + extra/ui/tools/listener/authors.txt | 1 + extra/ui/tools/listener/listener-tests.factor | 35 + extra/ui/tools/listener/listener.factor | 165 + extra/ui/tools/listener/summary.txt | 1 + extra/ui/tools/listener/tags.txt | 1 + extra/ui/tools/operations/authors.txt | 1 + extra/ui/tools/operations/operations.factor | 207 + extra/ui/tools/operations/summary.txt | 1 + extra/ui/tools/profiler/authors.txt | 1 + extra/ui/tools/profiler/profiler.factor | 61 + extra/ui/tools/profiler/summary.txt | 1 + extra/ui/tools/profiler/tags.txt | 1 + extra/ui/tools/search/authors.txt | 1 + extra/ui/tools/search/search-tests.factor | 54 + extra/ui/tools/search/search.factor | 158 + extra/ui/tools/search/summary.txt | 1 + extra/ui/tools/summary.txt | 1 + extra/ui/tools/tags.txt | 1 + extra/ui/tools/tools-docs.factor | 142 + extra/ui/tools/tools-tests.factor | 54 + extra/ui/tools/tools.factor | 98 + extra/ui/tools/traceback/authors.txt | 1 + extra/ui/tools/traceback/summary.txt | 1 + extra/ui/tools/traceback/traceback.factor | 36 + extra/ui/tools/walker/authors.txt | 1 + extra/ui/tools/walker/summary.txt | 1 + extra/ui/tools/walker/tags.txt | 1 + extra/ui/tools/walker/walker-tests.factor | 54 + extra/ui/tools/walker/walker.factor | 99 + extra/ui/tools/workspace/authors.txt | 1 + extra/ui/tools/workspace/summary.txt | 1 + extra/ui/tools/workspace/tags.txt | 1 + extra/ui/tools/workspace/workspace.factor | 95 + extra/ui/traverse/authors.txt | 1 + extra/ui/traverse/summary.txt | 1 + extra/ui/traverse/traverse-tests.factor | 65 + extra/ui/traverse/traverse.factor | 86 + extra/ui/ui-docs.factor | 378 + extra/ui/ui.factor | 140 + extra/ui/windows/windows.factor | 464 + extra/ui/x11/x11.factor | 295 + extra/unicode/PropList.txt | 20 + extra/unicode/SpecialCasing.txt | 264 + extra/unicode/UnicodeData.txt | 17720 ++++++++++++ extra/unicode/authors.txt | 1 + extra/unicode/breaks/breaks-tests.factor | 7 + extra/unicode/breaks/breaks.factor | 129 + extra/unicode/summary.txt | 1 + extra/unicode/unicode-tests.factor | 37 + extra/unicode/unicode.factor | 503 + extra/units/constants/constants.factor | 15 + extra/units/constants/constants.txt | 336 + extra/units/imperial/imperial-tests.factor | 21 + extra/units/imperial/imperial.factor | 63 + extra/units/si/si-tests.factor | 12 + extra/units/si/si.factor | 122 + extra/units/units-tests.factor | 22 + extra/units/units.factor | 100 + extra/unix/authors.txt | 1 + extra/unix/bsd/authors.txt | 1 + extra/unix/bsd/bsd.factor | 83 + extra/unix/bsd/summary.txt | 1 + extra/unix/linux/linux.factor | 83 + extra/unix/solaris/solaris.factor | 83 + extra/unix/summary.txt | 1 + extra/unix/tags.txt | 1 + extra/unix/unix.factor | 168 + extra/vars/authors.txt | 1 + extra/vars/summary.txt | 1 + extra/vars/tags.txt | 1 + extra/vars/vars.factor | 26 + extra/visitor/authors.txt | 1 + extra/visitor/summary.txt | 1 + extra/visitor/tags.txt | 1 + extra/visitor/visitor-tests.factor | 18 + extra/visitor/visitor.factor | 63 + .../article-manager-docs.factor | 33 + .../article-manager/article-manager.factor | 160 + extra/webapps/article-manager/authors.txt | 1 + .../article-manager/database/database.factor | 118 + .../article-manager/furnace/article.furnace | 13 + .../furnace/edit-article.furnace | 41 + .../article-manager/furnace/edit-head.furnace | 12 + .../article-manager/furnace/head.furnace | 4 + .../article-manager/furnace/index.furnace | 32 + .../furnace/navigation.furnace | 9 + .../furnace/setup-site.furnace | 33 + .../article-manager/furnace/tag.furnace | 16 + .../article-manager/furnace/tags.furnace | 6 + extra/webapps/article-manager/load.factor | 18 + .../article-manager/resources/jquery.js | 1 + .../jscalendar-1.0/calendar-blue.css | 232 + .../jscalendar-1.0/calendar-blue2.css | 236 + .../jscalendar-1.0/calendar-brown.css | 225 + .../jscalendar-1.0/calendar-green.css | 229 + .../jscalendar-1.0/calendar-setup.js | 200 + .../jscalendar-1.0/calendar-setup_stripped.js | 21 + .../jscalendar-1.0/calendar-system.css | 251 + .../resources/jscalendar-1.0/calendar-tas.css | 239 + .../jscalendar-1.0/calendar-win2k-1.css | 271 + .../jscalendar-1.0/calendar-win2k-2.css | 271 + .../jscalendar-1.0/calendar-win2k-cold-1.css | 265 + .../jscalendar-1.0/calendar-win2k-cold-2.css | 271 + .../resources/jscalendar-1.0/calendar.js | 1806 ++ .../jscalendar-1.0/calendar_stripped.js | 14 + .../jscalendar-1.0/lang/calendar-af.js | 39 + .../jscalendar-1.0/lang/calendar-al.js | 101 + .../jscalendar-1.0/lang/calendar-bg.js | 124 + .../jscalendar-1.0/lang/calendar-big5-utf8.js | 123 + .../jscalendar-1.0/lang/calendar-big5.js | 123 + .../jscalendar-1.0/lang/calendar-br.js | 108 + .../jscalendar-1.0/lang/calendar-ca.js | 123 + .../jscalendar-1.0/lang/calendar-cs-utf8.js | 65 + .../jscalendar-1.0/lang/calendar-cs-win.js | 65 + .../jscalendar-1.0/lang/calendar-da.js | 123 + .../jscalendar-1.0/lang/calendar-de.js | 124 + .../jscalendar-1.0/lang/calendar-du.js | 45 + .../jscalendar-1.0/lang/calendar-el.js | 89 + .../jscalendar-1.0/lang/calendar-en.js | 127 + .../jscalendar-1.0/lang/calendar-es.js | 129 + .../jscalendar-1.0/lang/calendar-fi.js | 98 + .../jscalendar-1.0/lang/calendar-fr.js | 125 + .../jscalendar-1.0/lang/calendar-he-utf8.js | 123 + .../jscalendar-1.0/lang/calendar-hr-utf8.js | 49 + .../jscalendar-1.0/lang/calendar-hr.js | Bin 0 -> 3088 bytes .../jscalendar-1.0/lang/calendar-hu.js | 124 + .../jscalendar-1.0/lang/calendar-it.js | 124 + .../jscalendar-1.0/lang/calendar-jp.js | 45 + .../jscalendar-1.0/lang/calendar-ko-utf8.js | 120 + .../jscalendar-1.0/lang/calendar-ko.js | 120 + .../jscalendar-1.0/lang/calendar-lt-utf8.js | 114 + .../jscalendar-1.0/lang/calendar-lt.js | 114 + .../jscalendar-1.0/lang/calendar-lv.js | 123 + .../jscalendar-1.0/lang/calendar-nl.js | 73 + .../jscalendar-1.0/lang/calendar-no.js | 114 + .../jscalendar-1.0/lang/calendar-pl-utf8.js | 93 + .../jscalendar-1.0/lang/calendar-pl.js | 56 + .../jscalendar-1.0/lang/calendar-pt.js | 123 + .../jscalendar-1.0/lang/calendar-ro.js | 66 + .../jscalendar-1.0/lang/calendar-ru.js | 123 + .../jscalendar-1.0/lang/calendar-ru_win_.js | 123 + .../jscalendar-1.0/lang/calendar-si.js | 94 + .../jscalendar-1.0/lang/calendar-sk.js | 99 + .../jscalendar-1.0/lang/calendar-sp.js | 110 + .../jscalendar-1.0/lang/calendar-sv.js | 93 + .../jscalendar-1.0/lang/calendar-tr.js | 58 + .../jscalendar-1.0/lang/calendar-zh.js | 119 + .../resources/jscalendar-1.0/lang/cn_utf8.js | 123 + .../article-manager/resources/style.css | 65 + .../article-manager/resources/wiky.css | 15 + .../webapps/article-manager/resources/wiky.js | 373 + .../article-manager/resources/wiky.lang.css | 9 + .../article-manager/resources/wiky.lang.js | 40 + .../article-manager/resources/wiky.math.css | 88 + .../article-manager/resources/wiky.math.js | 374 + extra/webapps/article-manager/summary.txt | 1 + extra/webapps/article-manager/tags.txt | 1 + extra/webapps/fjsc/authors.txt | 1 + extra/webapps/fjsc/fjsc.factor | 65 + extra/webapps/fjsc/head.furnace | 7 + extra/webapps/fjsc/repl.furnace | 43 + extra/webapps/fjsc/resources/repl.js | 99 + extra/webapps/fjsc/resources/termlib/faq.html | 356 + .../webapps/fjsc/resources/termlib/index.html | 207 + .../resources/termlib/multiterm_test.html | 188 + .../fjsc/resources/termlib/parser_sample.html | 293 + .../webapps/fjsc/resources/termlib/readme.txt | 1400 + .../fjsc/resources/termlib/term_styles.css | 11 + .../webapps/fjsc/resources/termlib/termlib.js | 1633 ++ .../fjsc/resources/termlib/termlib_parser.js | 199 + extra/webapps/fjsc/summary.txt | 1 + extra/webapps/fjsc/tags.txt | 1 + extra/webapps/help/help.factor | 81 + extra/windows/advapi32/advapi32.factor | 753 + extra/windows/authors.txt | 2 + extra/windows/ce/ce.factor | 14 + extra/windows/errors/errors.factor | 8 + extra/windows/gdi32/gdi32.factor | 638 + extra/windows/kernel32/kernel32.factor | 1513 + extra/windows/messages/messages.factor | 1003 + extra/windows/nt/nt.factor | 14 + extra/windows/opengl32/opengl32.factor | 109 + extra/windows/summary.txt | 1 + extra/windows/tags.txt | 1 + extra/windows/types/types.factor | 336 + extra/windows/user32/user32.factor | 1321 + extra/windows/windows.factor | 68 + extra/windows/winsock/winsock.factor | 435 + extra/x/authors.txt | 1 + extra/x/font/font.factor | 27 + extra/x/gc/gc.factor | 27 + extra/x/keysym-table/keysym-table.factor | 45 + extra/x/pen/pen.factor | 26 + extra/x/widgets/button/button.factor | 24 + extra/x/widgets/keymenu/keymenu.factor | 65 + extra/x/widgets/label/label.factor | 16 + extra/x/widgets/widgets.factor | 38 + extra/x/widgets/wm/child/child.factor | 23 + extra/x/widgets/wm/frame/drag/drag.factor | 24 + .../x/widgets/wm/frame/drag/move/move.factor | 46 + .../x/widgets/wm/frame/drag/size/size.factor | 45 + extra/x/widgets/wm/frame/frame.factor | 176 + extra/x/widgets/wm/menu/menu.factor | 26 + extra/x/widgets/wm/root/root.factor | 103 + .../unmapped-frames-menu.factor | 41 + extra/x/widgets/wm/workspace/workspace.factor | 47 + extra/x/x.factor | 503 + extra/x11/clipboard/authors.txt | 2 + extra/x11/clipboard/clipboard.factor | 80 + extra/x11/clipboard/summary.txt | 1 + extra/x11/constants/authors.txt | 2 + extra/x11/constants/constants.factor | 404 + extra/x11/constants/summary.txt | 1 + extra/x11/events/authors.txt | 2 + extra/x11/events/events.factor | 84 + extra/x11/events/summary.txt | 1 + extra/x11/glx/authors.txt | 2 + extra/x11/glx/glx.factor | 111 + extra/x11/glx/summary.txt | 1 + extra/x11/glx/tags.txt | 1 + extra/x11/summary.txt | 1 + extra/x11/tags.txt | 1 + extra/x11/windows/authors.txt | 2 + extra/x11/windows/summary.txt | 1 + extra/x11/windows/windows.factor | 66 + extra/x11/xim/authors.txt | 1 + extra/x11/xim/summary.txt | 1 + extra/x11/xim/tags.txt | 1 + extra/x11/xim/xim.factor | 48 + extra/x11/xlib/authors.txt | 1 + extra/x11/xlib/summary.txt | 1 + extra/x11/xlib/tags.txt | 1 + extra/x11/xlib/xlib.factor | 1364 + extra/xml-rpc/authors.txt | 1 + extra/xml-rpc/example.factor | 27 + extra/xml-rpc/summary.txt | 1 + extra/xml-rpc/tags.txt | 1 + extra/xml-rpc/xml-rpc-docs.factor | 71 + extra/xml-rpc/xml-rpc-tests.factor | 5 + extra/xml-rpc/xml-rpc.factor | 171 + extra/xml/authors.txt | 1 + extra/xml/char-classes/char-classes.factor | 21 + extra/xml/data/data.factor | 115 + extra/xml/entities/entities.factor | 276 + extra/xml/errors/errors.factor | 152 + extra/xml/generator/generator-tests.factor | 3 + extra/xml/generator/generator.factor | 23 + extra/xml/summary.txt | 1 + extra/xml/tags.txt | 1 + extra/xml/test/arithmetic.factor | 30 + extra/xml/test/errors.factor | 27 + extra/xml/test/soap.factor | 14 + extra/xml/test/soap.xml | 168 + extra/xml/test/templating.factor | 43 + extra/xml/test/test.factor | 44 + extra/xml/test/test.xml | 16 + extra/xml/tokenize/tokenize.factor | 201 + extra/xml/utilities/utilities.factor | 140 + extra/xml/writer/writer.factor | 82 + extra/xml/xml-docs.factor | 475 + extra/xml/xml-tests.factor | 13 + extra/xml/xml.factor | 174 + extra/yahoo/authors.txt | 1 + extra/yahoo/summary.txt | 1 + extra/yahoo/tags.txt | 2 + extra/yahoo/test-results.xml | 15 + extra/yahoo/yahoo-docs.factor | 5 + extra/yahoo/yahoo-tests.factor | 11 + extra/yahoo/yahoo.factor | 31 + fonts/Vera.ttf | Bin 0 -> 65932 bytes fonts/VeraBI.ttf | Bin 0 -> 63208 bytes fonts/VeraBd.ttf | Bin 0 -> 58716 bytes fonts/VeraIt.ttf | Bin 0 -> 63684 bytes fonts/VeraMoBI.ttf | Bin 0 -> 55032 bytes fonts/VeraMoBd.ttf | Bin 0 -> 49052 bytes fonts/VeraMoIt.ttf | Bin 0 -> 54508 bytes fonts/VeraMono.ttf | Bin 0 -> 49224 bytes fonts/VeraSe.ttf | Bin 0 -> 60280 bytes fonts/VeraSeBd.ttf | Bin 0 -> 58736 bytes license.txt | 24 + .../Syntaxes/Factor.tmLanguage | 296 + .../Syntaxes/HTML (Factor).tmLanguage | 53 + misc/Factor.tmbundle/info.plist | 10 + misc/factor.el | 173 + misc/factor.vim | 232 + misc/factor.vim.fgen | 229 + misc/graphics/bmps/1bit.bmp | Bin 0 -> 1662 bytes misc/graphics/bmps/rgb4bit.bmp | Bin 0 -> 5318 bytes misc/graphics/bmps/rgb8bit.bmp | Bin 0 -> 11078 bytes misc/graphics/bmps/thiswayup24.bmp | Bin 0 -> 60054 bytes misc/icons/FRaptorMix.ico | Bin 0 -> 92854 bytes misc/icons/FRaptorMix_128x128.png | Bin 0 -> 12101 bytes misc/icons/FRaptorMix_16x16.png | Bin 0 -> 730 bytes misc/icons/FRaptorMix_32x32.png | Bin 0 -> 1877 bytes misc/icons/FRaptorMix_48x48.png | Bin 0 -> 3481 bytes misc/icons/license.txt | 4 + misc/integration/macosx-deploy.factor | 24 + misc/integration/macosx.sh | 43 + misc/integration/test.sh | 93 + misc/integration/unix-arm.sh | 10 + misc/integration/unix-ppc.sh | 10 + misc/integration/unix-x86.32.sh | 21 + misc/integration/unix-x86.64.sh | 10 + misc/integration/x11-deploy.factor | 8 + misc/macos-release.sh | 26 + misc/windows-release.sh | 19 + unmaintained/README.libs.txt | 88 + unmaintained/README.txt | 30 + unmaintained/alarms/alarms.factor | 89 + unmaintained/alarms/load.factor | 5 + unmaintained/enchilada/authors.txt | 1 + unmaintained/enchilada/enchilada-tests.factor | 6 + unmaintained/enchilada/enchilada.factor | 12 + unmaintained/enchilada/engine/engine.factor | 322 + unmaintained/enchilada/parser/parser.factor | 139 + unmaintained/enchilada/printer/printer.factor | 71 + unmaintained/enchilada/summary.txt | 1 + unmaintained/enchilada/tags.txt | 1 + unmaintained/factorbot.factor | 108 + unmaintained/farkup/farkup.factor | 86 + unmaintained/farkup/farkup.facts | 0 unmaintained/farkup/farkup.list | 20 + unmaintained/farkup/load.factor | 12 + unmaintained/furnace-onigiri/load.factor | 12 + unmaintained/furnace-onigiri/onigiri.factor | 166 + unmaintained/furnace-onigiri/onigiri.facts | 0 unmaintained/furnace-onigiri/onigiri.todo | 4 + .../resources/onigirihouse.css | 7 + .../furnace-onigiri/resources/wiky/wiky.css | 15 + .../furnace-onigiri/resources/wiky/wiky.js | 373 + .../resources/wiky/wiky.lang.css | 9 + .../resources/wiky/wiky.lang.js | 40 + .../resources/wiky/wiky.math.css | 88 + .../resources/wiky/wiky.math.js | 374 + .../furnace-onigiri/templates/atom.furnace | 23 + .../templates/entry-edit-plain.furnace | 19 + .../templates/entry-edit.furnace | 34 + .../templates/entry-show.furnace | 9 + .../furnace-onigiri/templates/footer.furnace | 16 + .../furnace-onigiri/templates/header.furnace | 25 + .../furnace-onigiri/templates/sitemap.furnace | 12 + .../furnace-pastebin/annotate-paste.furnace | 28 + .../furnace-pastebin/annotation.furnace | 11 + unmaintained/furnace-pastebin/load.factor | 4 + .../furnace-pastebin/new-paste.furnace | 27 + .../furnace-pastebin/paste-list.furnace | 7 + .../furnace-pastebin/paste-summary.furnace | 9 + unmaintained/furnace-pastebin/pastebin.factor | 110 + .../furnace-pastebin/show-paste.furnace | 15 + unmaintained/heap/heap.factor | 74 + unmaintained/heap/heap.facts | 76 + unmaintained/heap/human tests.factor | 100 + unmaintained/heap/load.factor | 16 + unmaintained/heap/print.factor | 51 + unmaintained/heap/tests.factor | 35 + unmaintained/io/io.factor | 8 + unmaintained/io/load.factor | 24 + unmaintained/io/os-unix-shell.factor | 46 + unmaintained/io/os-unix.factor | 237 + unmaintained/io/os-winnt-shell.factor | 55 + unmaintained/io/os-winnt.factor | 96 + unmaintained/io/shell.factor | 40 + unmaintained/io/test/io.factor | 42 + unmaintained/io/test/mmap.factor | 21 + unmaintained/irc/irc-client.factor | 264 + unmaintained/irc/load.factor | 7 + unmaintained/isequences/authors.txt | 1 + unmaintained/isequences/base/base.factor | 586 + .../interface/interface-docs.factor | 17 + .../isequences/interface/interface.factor | 110 + .../isequences/isequences-tests.factor | 47 + unmaintained/isequences/isequences.factor | 7 + .../isequences/ops/cache/cache.factor | 45 + .../isequences/ops/divide/divide.factor | 94 + unmaintained/isequences/ops/iota/iota.factor | 53 + .../isequences/ops/match/match.factor | 90 + .../isequences/ops/maximum/maximum.factor | 71 + .../isequences/ops/minimum/minimum.factor | 60 + .../isequences/ops/modulus/modulus.factor | 26 + .../isequences/ops/multiply/multiply.factor | 26 + unmaintained/isequences/ops/ops.factor | 5 + unmaintained/isequences/ops/sort/sort.factor | 36 + unmaintained/isequences/ops/wipe/wipe.factor | 26 + unmaintained/isequences/summary.txt | 1 + unmaintained/isequences/tags.txt | 1 + unmaintained/jni/jni-internals.factor | 357 + unmaintained/jni/jni.factor | 22 + unmaintained/jni/load.factor | 4 + unmaintained/lambda/TODO.txt | 15 + unmaintained/lambda/core.factor | 79 + unmaintained/lambda/lambda.factor | 28 + unmaintained/lambda/load.factor | 14 + unmaintained/lambda/nodes.factor | 130 + unmaintained/lambda/parser.factor | 70 + unmaintained/lambda/test/lambda.factor | 11 + unmaintained/mysql/libmysql.factor | 35 + unmaintained/mysql/load.factor | 11 + unmaintained/mysql/mysql.factor | 124 + unmaintained/mysql/test/create_database.sql | 17 + unmaintained/mysql/test/mysql-example.factor | 57 + unmaintained/random-tester/load.factor | 9 + .../random-tester/random-tester.factor | 301 + .../random-tester/random-tester2.factor | 186 + unmaintained/random-tester/random.factor | 87 + unmaintained/random-tester/type.factor | 218 + unmaintained/random-tester/utils.factor | 77 + unmaintained/regexp/load.factor | 10 + unmaintained/regexp/regexp.factor | 501 + unmaintained/regexp/tables.factor | 111 + unmaintained/regexp/test/regexp.factor | 30 + unmaintained/regexp/test/tables.factor | 49 + unmaintained/usb/load.factor | 13 + unmaintained/usb/usb-common.factor | 3 + unmaintained/usb/usb-macosx.factor | 61 + unmaintained/usb/usb-unix.factor | 61 + unmaintained/usb/usb-win32.factor | 61 + unmaintained/usb/usb.factor | 88 + unmaintained/usb/usb.facts | 44 + unmaintained/wee-url/load.factor | 4 + unmaintained/wee-url/responder.factor | 91 + unmaintained/wee-url/wee-url.factor | 89 + vm/Config.amd64 | 2 + vm/Config.arm | 2 + vm/Config.freebsd | 4 + vm/Config.freebsd.amd64 | 2 + vm/Config.freebsd.x86 | 2 + vm/Config.linux | 4 + vm/Config.linux.amd64 | 3 + vm/Config.linux.arm | 2 + vm/Config.linux.ppc | 3 + vm/Config.linux.x86 | 2 + vm/Config.macosx | 20 + vm/Config.macosx.ppc | 2 + vm/Config.macosx.x86 | 2 + vm/Config.openbsd | 4 + vm/Config.openbsd.amd64 | 2 + vm/Config.openbsd.x86 | 2 + vm/Config.ppc | 2 + vm/Config.solaris | 6 + vm/Config.solaris.amd64 | 2 + vm/Config.solaris.x86 | 2 + vm/Config.unix | 21 + vm/Config.windows | 7 + vm/Config.windows.ce | 5 + vm/Config.windows.ce.arm | 5 + vm/Config.windows.ce.x86 | 2 + vm/Config.windows.nt.x86 | 7 + vm/Config.x86 | 5 + vm/alien.c | 180 + vm/alien.h | 52 + vm/asm.h | 11 + vm/bignum.c | 1886 ++ vm/bignum.h | 131 + vm/bignumint.h | 100 + vm/code_gc.c | 490 + vm/code_gc.h | 116 + vm/compiler.c | 359 + vm/compiler.h | 71 + vm/cpu-amd64.S | 8 + vm/cpu-amd64.h | 20 + vm/cpu-arm.S | 8 + vm/cpu-arm.h | 17 + vm/cpu-ppc.S | 188 + vm/cpu-ppc.h | 16 + vm/cpu-x86.S | 83 + vm/cpu-x86.h | 40 + vm/data_gc.c | 799 + vm/data_gc.h | 324 + vm/debug.c | 273 + vm/debug.h | 6 + vm/factor.c | 166 + vm/factor.h | 8 + vm/factor.rs | 2 + vm/ffi_test.c | 225 + vm/ffi_test.h | 50 + vm/float_bits.h | 40 + vm/image.c | 282 + vm/image.h | 65 + vm/io.c | 168 + vm/io.h | 17 + vm/jit.c | 186 + vm/jit.h | 3 + vm/layouts.h | 241 + vm/mach_signal.c | 205 + vm/mach_signal.h | 70 + vm/main-unix.c | 7 + vm/main-windows-ce.c | 134 + vm/main-windows-nt.c | 27 + vm/master.h | 41 + vm/math.c | 615 + vm/math.h | 162 + vm/os-freebsd.c | 34 + vm/os-freebsd.h | 12 + vm/os-genunix.c | 27 + vm/os-genunix.h | 8 + vm/os-linux-arm.h | 14 + vm/os-linux-ppc.h | 29 + vm/os-linux.c | 19 + vm/os-linux.h | 2 + vm/os-macosx-ppc.h | 51 + vm/os-macosx-x86.h | 28 + vm/os-macosx.h | 13 + vm/os-macosx.m | 74 + vm/os-openbsd-amd64.h | 7 + vm/os-openbsd-x86.h | 7 + vm/os-openbsd.c | 6 + vm/os-openbsd.h | 2 + vm/os-solaris.c | 6 + vm/os-solaris.h | 2 + vm/os-unix-ucontext.h | 7 + vm/os-unix.c | 250 + vm/os-unix.h | 50 + vm/os-windows-ce-arm.S | 18 + vm/os-windows-ce.c | 46 + vm/os-windows-ce.h | 29 + vm/os-windows-nt.c | 53 + vm/os-windows-nt.h | 12 + vm/os-windows.c | 212 + vm/os-windows.h | 68 + vm/platform.h | 98 + vm/primitives.c | 194 + vm/primitives.h | 39 + vm/run.c | 286 + vm/run.h | 208 + vm/stack.c | 479 + vm/stack.h | 91 + vm/types.c | 520 + vm/types.h | 247 + vm/utilities.c | 23 + vm/utilities.h | 3 + 2400 files changed, 225317 insertions(+) create mode 100644 Factor.app/Contents/Frameworks/libfreetype.6.dylib create mode 100644 Factor.app/Contents/Info.plist create mode 100644 Factor.app/Contents/PkgInfo create mode 100644 Factor.app/Contents/Resources/English.lproj/Factor.nib/classes.nib create mode 100644 Factor.app/Contents/Resources/English.lproj/Factor.nib/info.nib create mode 100644 Factor.app/Contents/Resources/English.lproj/Factor.nib/keyedobjects.nib create mode 100644 Factor.app/Contents/Resources/English.lproj/MiniFactor.nib/classes.nib create mode 100644 Factor.app/Contents/Resources/English.lproj/MiniFactor.nib/info.nib create mode 100644 Factor.app/Contents/Resources/English.lproj/MiniFactor.nib/keyedobjects.nib create mode 100644 Factor.app/Contents/Resources/FRaptorMix.icns create mode 100644 Makefile create mode 100644 README.txt create mode 100644 core/alien/alien-docs.factor create mode 100644 core/alien/alien-tests.factor create mode 100644 core/alien/alien.factor create mode 100644 core/alien/arrays/arrays.factor create mode 100644 core/alien/arrays/authors.txt create mode 100644 core/alien/arrays/summary.txt create mode 100644 core/alien/authors.txt create mode 100644 core/alien/c-types/authors.txt create mode 100644 core/alien/c-types/c-types-docs.factor create mode 100644 core/alien/c-types/c-types-tests.factor create mode 100644 core/alien/c-types/c-types.factor create mode 100644 core/alien/c-types/summary.txt create mode 100644 core/alien/compiler/authors.txt create mode 100644 core/alien/compiler/compiler.factor create mode 100644 core/alien/compiler/summary.txt create mode 100644 core/alien/remote-control/authors.txt create mode 100644 core/alien/remote-control/remote-control.factor create mode 100644 core/alien/remote-control/summary.txt create mode 100644 core/alien/structs/authors.txt create mode 100644 core/alien/structs/structs-docs.factor create mode 100644 core/alien/structs/structs-tests.factor create mode 100644 core/alien/structs/structs.factor create mode 100644 core/alien/structs/summary.txt create mode 100644 core/alien/summary.txt create mode 100644 core/alien/syntax/authors.txt create mode 100644 core/alien/syntax/summary.txt create mode 100644 core/alien/syntax/syntax-docs.factor create mode 100644 core/alien/syntax/syntax.factor create mode 100644 core/alien/tags.txt create mode 100644 core/arrays/arrays-docs.factor create mode 100644 core/arrays/arrays-tests.factor create mode 100644 core/arrays/arrays.factor create mode 100644 core/arrays/authors.txt create mode 100644 core/arrays/summary.txt create mode 100644 core/arrays/tags.txt create mode 100644 core/assocs/assocs-docs.factor create mode 100644 core/assocs/assocs-tests.factor create mode 100644 core/assocs/assocs.factor create mode 100644 core/assocs/authors.txt create mode 100644 core/assocs/summary.txt create mode 100644 core/assocs/tags.txt create mode 100644 core/bit-arrays/authors.txt create mode 100644 core/bit-arrays/bit-arrays-docs.factor create mode 100644 core/bit-arrays/bit-arrays-tests.factor create mode 100644 core/bit-arrays/bit-arrays.factor create mode 100644 core/bit-arrays/summary.txt create mode 100644 core/bit-arrays/tags.txt create mode 100644 core/bootstrap/compiler/authors.txt create mode 100644 core/bootstrap/compiler/compiler.factor create mode 100644 core/bootstrap/compiler/summary.txt create mode 100644 core/bootstrap/help/authors.txt create mode 100644 core/bootstrap/help/help.factor create mode 100644 core/bootstrap/help/summary.txt create mode 100644 core/bootstrap/image/authors.txt create mode 100644 core/bootstrap/image/image-docs.factor create mode 100644 core/bootstrap/image/image.factor create mode 100644 core/bootstrap/image/summary.txt create mode 100644 core/bootstrap/image/tags.txt create mode 100644 core/bootstrap/io/authors.txt create mode 100644 core/bootstrap/io/io.factor create mode 100644 core/bootstrap/io/summary.txt create mode 100644 core/bootstrap/layouts/authors.txt create mode 100644 core/bootstrap/layouts/layouts.factor create mode 100644 core/bootstrap/layouts/summary.txt create mode 100644 core/bootstrap/math/math.factor create mode 100644 core/bootstrap/math/summary.txt create mode 100644 core/bootstrap/primitives.factor create mode 100644 core/bootstrap/stage1.factor create mode 100644 core/bootstrap/stage2.factor create mode 100644 core/bootstrap/summary.txt create mode 100644 core/bootstrap/syntax.factor create mode 100644 core/bootstrap/tools/authors.txt create mode 100644 core/bootstrap/tools/summary.txt create mode 100644 core/bootstrap/tools/tools.factor create mode 100644 core/bootstrap/ui/authors.txt create mode 100644 core/bootstrap/ui/summary.txt create mode 100644 core/bootstrap/ui/tools/authors.txt create mode 100644 core/bootstrap/ui/tools/summary.txt create mode 100644 core/bootstrap/ui/tools/tools.factor create mode 100644 core/bootstrap/ui/ui.factor create mode 100644 core/byte-arrays/authors.txt create mode 100644 core/byte-arrays/byte-arrays-docs.factor create mode 100644 core/byte-arrays/byte-arrays.factor create mode 100644 core/byte-arrays/summary.txt create mode 100644 core/byte-arrays/tags.txt create mode 100644 core/classes/authors.txt create mode 100644 core/classes/classes-docs.factor create mode 100644 core/classes/classes-tests.factor create mode 100644 core/classes/classes.factor create mode 100644 core/classes/mixin/authors.txt create mode 100644 core/classes/mixin/mixin-docs.factor create mode 100644 core/classes/mixin/mixin.factor create mode 100644 core/classes/mixin/summary.txt create mode 100644 core/classes/predicate/authors.txt create mode 100644 core/classes/predicate/predicate-docs.factor create mode 100644 core/classes/predicate/predicate.factor create mode 100644 core/classes/predicate/summary.txt create mode 100644 core/classes/summary.txt create mode 100644 core/classes/tags.txt create mode 100644 core/classes/union/authors.txt create mode 100644 core/classes/union/summary.txt create mode 100644 core/classes/union/union-docs.factor create mode 100644 core/classes/union/union.factor create mode 100644 core/combinators/authors.txt create mode 100644 core/combinators/combinators-docs.factor create mode 100644 core/combinators/combinators-tests.factor create mode 100644 core/combinators/combinators.factor create mode 100644 core/combinators/summary.txt create mode 100644 core/command-line/authors.txt create mode 100644 core/command-line/command-line-docs.factor create mode 100644 core/command-line/command-line-tests.factor create mode 100644 core/command-line/command-line.factor create mode 100644 core/command-line/summary.txt create mode 100644 core/compiler/authors.txt create mode 100644 core/compiler/compiler-docs.factor create mode 100644 core/compiler/compiler-tests.factor create mode 100644 core/compiler/compiler.factor create mode 100644 core/compiler/summary.txt create mode 100644 core/compiler/tags.txt create mode 100644 core/compiler/test/alien.factor create mode 100644 core/compiler/test/curry.factor create mode 100644 core/compiler/test/float.factor create mode 100644 core/compiler/test/generic.factor create mode 100644 core/compiler/test/ifte.factor create mode 100644 core/compiler/test/intrinsics.factor create mode 100644 core/compiler/test/optimizer.factor create mode 100644 core/compiler/test/redefine.factor create mode 100644 core/compiler/test/simple.factor create mode 100644 core/compiler/test/stack-trace.factor create mode 100644 core/compiler/test/templates-early.factor create mode 100644 core/compiler/test/templates.factor create mode 100644 core/compiler/test/tuples.factor create mode 100644 core/continuations/authors.txt create mode 100644 core/continuations/continuations-docs.factor create mode 100644 core/continuations/continuations-tests.factor create mode 100644 core/continuations/continuations.factor create mode 100644 core/continuations/summary.txt create mode 100644 core/continuations/tags.txt create mode 100644 core/cpu/architecture/architecture.factor create mode 100644 core/cpu/architecture/authors.txt create mode 100644 core/cpu/architecture/summary.txt create mode 100644 core/cpu/arm/allot/allot.factor create mode 100644 core/cpu/arm/architecture/architecture.factor create mode 100644 core/cpu/arm/arm.factor create mode 100644 core/cpu/arm/assembler/assembler-tests.factor create mode 100644 core/cpu/arm/assembler/assembler.factor create mode 100644 core/cpu/arm/authors.txt create mode 100644 core/cpu/arm/bootstrap.factor create mode 100644 core/cpu/arm/intrinsics/intrinsics.factor create mode 100644 core/cpu/arm/summary.txt create mode 100644 core/cpu/arm5/arm5.factor create mode 100644 core/cpu/arm5/assembler/assembler.factor create mode 100644 core/cpu/arm5/authors.txt create mode 100644 core/cpu/arm5/intrinsics/intrinsics.factor create mode 100644 core/cpu/arm5/summary.txt create mode 100644 core/cpu/ppc/allot/allot.factor create mode 100644 core/cpu/ppc/allot/authors.txt create mode 100644 core/cpu/ppc/allot/summary.txt create mode 100644 core/cpu/ppc/architecture/architecture.factor create mode 100644 core/cpu/ppc/architecture/authors.txt create mode 100644 core/cpu/ppc/architecture/summary.txt create mode 100644 core/cpu/ppc/assembler/assembler.factor create mode 100644 core/cpu/ppc/assembler/authors.txt create mode 100644 core/cpu/ppc/assembler/summary.txt create mode 100644 core/cpu/ppc/authors.txt create mode 100644 core/cpu/ppc/bootstrap.factor create mode 100644 core/cpu/ppc/intrinsics/intrinsics.factor create mode 100644 core/cpu/ppc/linux/bootstrap.factor create mode 100644 core/cpu/ppc/macosx/bootstrap.factor create mode 100644 core/cpu/ppc/ppc.factor create mode 100644 core/cpu/ppc/summary.txt create mode 100644 core/cpu/summary.txt create mode 100644 core/cpu/tags.txt create mode 100644 core/cpu/x86/32/32.factor create mode 100644 core/cpu/x86/32/bootstrap.factor create mode 100644 core/cpu/x86/64/64.factor create mode 100644 core/cpu/x86/64/authors.txt create mode 100644 core/cpu/x86/64/bootstrap.factor create mode 100644 core/cpu/x86/64/summary.txt create mode 100644 core/cpu/x86/allot/allot.factor create mode 100644 core/cpu/x86/architecture/architecture.factor create mode 100644 core/cpu/x86/assembler/assembler-tests.factor create mode 100644 core/cpu/x86/assembler/assembler.factor create mode 100644 core/cpu/x86/authors.txt create mode 100644 core/cpu/x86/intrinsics/intrinsics.factor create mode 100644 core/cpu/x86/sse2/authors.txt create mode 100644 core/cpu/x86/sse2/sse2.factor create mode 100644 core/cpu/x86/sse2/summary.txt create mode 100644 core/cpu/x86/summary.txt create mode 100644 core/debugger/authors.txt create mode 100644 core/debugger/debugger-docs.factor create mode 100644 core/debugger/debugger.factor create mode 100644 core/debugger/summary.txt create mode 100644 core/definitions/authors.txt create mode 100644 core/definitions/definitions-docs.factor create mode 100644 core/definitions/definitions.factor create mode 100644 core/definitions/summary.txt create mode 100644 core/definitions/tags.txt create mode 100644 core/effects/authors.txt create mode 100644 core/effects/effects-docs.factor create mode 100644 core/effects/effects-tests.factor create mode 100644 core/effects/effects.factor create mode 100644 core/effects/summary.txt create mode 100644 core/effects/tags.txt create mode 100644 core/float-arrays/float-arrays-docs.factor create mode 100644 core/float-arrays/float-arrays-tests.factor create mode 100644 core/float-arrays/float-arrays.factor create mode 100644 core/float-arrays/summary.txt create mode 100644 core/float-arrays/tags.txt create mode 100644 core/generator/authors.txt create mode 100644 core/generator/fixup/authors.txt create mode 100644 core/generator/fixup/fixup-docs.factor create mode 100644 core/generator/fixup/fixup.factor create mode 100644 core/generator/fixup/summary.txt create mode 100644 core/generator/generator-docs.factor create mode 100644 core/generator/generator.factor create mode 100644 core/generator/registers/authors.txt create mode 100644 core/generator/registers/registers.factor create mode 100644 core/generator/registers/summary.txt create mode 100644 core/generator/summary.txt create mode 100644 core/generator/tags.txt create mode 100644 core/generic/authors.txt create mode 100644 core/generic/generic-docs.factor create mode 100644 core/generic/generic-tests.factor create mode 100644 core/generic/generic.factor create mode 100644 core/generic/math/authors.txt create mode 100644 core/generic/math/math-docs.factor create mode 100644 core/generic/math/math.factor create mode 100644 core/generic/math/summary.txt create mode 100644 core/generic/standard/authors.txt create mode 100644 core/generic/standard/standard-docs.factor create mode 100644 core/generic/standard/standard.factor create mode 100644 core/generic/standard/summary.txt create mode 100644 core/generic/summary.txt create mode 100644 core/generic/tags.txt create mode 100644 core/graphs/authors.txt create mode 100644 core/graphs/graphs-docs.factor create mode 100644 core/graphs/graphs-tests.factor create mode 100644 core/graphs/graphs.factor create mode 100644 core/graphs/summary.txt create mode 100644 core/graphs/tags.txt create mode 100644 core/growable/authors.txt create mode 100644 core/growable/growable-docs.factor create mode 100644 core/growable/growable-tests.factor create mode 100644 core/growable/growable.factor create mode 100644 core/growable/summary.txt create mode 100644 core/growable/tags.txt create mode 100644 core/hashtables/authors.txt create mode 100644 core/hashtables/hashtables-docs.factor create mode 100644 core/hashtables/hashtables-tests.factor create mode 100644 core/hashtables/hashtables.factor create mode 100644 core/hashtables/summary.txt create mode 100644 core/hashtables/tags.txt create mode 100644 core/inference/authors.txt create mode 100644 core/inference/backend/authors.txt create mode 100644 core/inference/backend/backend-docs.factor create mode 100644 core/inference/backend/backend.factor create mode 100644 core/inference/backend/summary.txt create mode 100644 core/inference/class/authors.txt create mode 100644 core/inference/class/class-tests.factor create mode 100644 core/inference/class/class.factor create mode 100644 core/inference/class/summary.txt create mode 100644 core/inference/dataflow/authors.txt create mode 100644 core/inference/dataflow/dataflow-docs.factor create mode 100644 core/inference/dataflow/dataflow.factor create mode 100644 core/inference/dataflow/summary.txt create mode 100644 core/inference/errors/authors.txt create mode 100644 core/inference/errors/errors.factor create mode 100644 core/inference/errors/summary.txt create mode 100644 core/inference/inference-docs.factor create mode 100644 core/inference/inference-tests.factor create mode 100644 core/inference/inference.factor create mode 100644 core/inference/known-words/authors.txt create mode 100644 core/inference/known-words/known-words.factor create mode 100644 core/inference/known-words/summary.txt create mode 100644 core/inference/stack/authors.txt create mode 100644 core/inference/stack/stack-docs.factor create mode 100644 core/inference/stack/stack.factor create mode 100644 core/inference/stack/summary.txt create mode 100644 core/inference/summary.txt create mode 100644 core/inference/tags.txt create mode 100644 core/inference/transforms/authors.txt create mode 100644 core/inference/transforms/summary.txt create mode 100644 core/inference/transforms/transforms-docs.factor create mode 100644 core/inference/transforms/transforms-tests.factor create mode 100644 core/inference/transforms/transforms.factor create mode 100644 core/init/authors.txt create mode 100644 core/init/init-docs.factor create mode 100644 core/init/init.factor create mode 100644 core/init/summary.txt create mode 100644 core/inspector/authors.txt create mode 100644 core/inspector/inspector-docs.factor create mode 100644 core/inspector/inspector-tests.factor create mode 100644 core/inspector/inspector.factor create mode 100644 core/inspector/summary.txt create mode 100644 core/inspector/tags.txt create mode 100644 core/io/authors.txt create mode 100644 core/io/backend/authors.txt create mode 100644 core/io/backend/backend-docs.factor create mode 100644 core/io/backend/backend-tests.factor create mode 100644 core/io/backend/backend.factor create mode 100644 core/io/backend/summary.txt create mode 100644 core/io/binary/authors.txt create mode 100644 core/io/binary/binary-docs.factor create mode 100644 core/io/binary/binary-tests.factor create mode 100644 core/io/binary/binary.factor create mode 100644 core/io/binary/summary.txt create mode 100644 core/io/buffers/authors.txt create mode 100644 core/io/buffers/buffers-docs.factor create mode 100644 core/io/buffers/buffers-tests.factor create mode 100644 core/io/buffers/buffers.factor create mode 100644 core/io/buffers/summary.txt create mode 100644 core/io/crc32/authors.txt create mode 100644 core/io/crc32/crc32-docs.factor create mode 100644 core/io/crc32/crc32-tests.factor create mode 100644 core/io/crc32/crc32.factor create mode 100644 core/io/crc32/summary.txt create mode 100644 core/io/encodings/encodings.factor create mode 100644 core/io/files/authors.txt create mode 100644 core/io/files/files-docs.factor create mode 100644 core/io/files/files-tests.factor create mode 100644 core/io/files/files.factor create mode 100644 core/io/files/summary.txt create mode 100644 core/io/io-docs.factor create mode 100644 core/io/io-tests.factor create mode 100644 core/io/io.factor create mode 100644 core/io/streams/c/authors.txt create mode 100644 core/io/streams/c/c-docs.factor create mode 100644 core/io/streams/c/c.factor create mode 100644 core/io/streams/c/summary.txt create mode 100644 core/io/streams/duplex/authors.txt create mode 100644 core/io/streams/duplex/duplex-docs.factor create mode 100644 core/io/streams/duplex/duplex-tests.factor create mode 100644 core/io/streams/duplex/duplex.factor create mode 100644 core/io/streams/duplex/summary.txt create mode 100644 core/io/streams/lines/authors.txt create mode 100644 core/io/streams/lines/lines-docs.factor create mode 100644 core/io/streams/lines/lines-tests.factor create mode 100644 core/io/streams/lines/lines.factor create mode 100644 core/io/streams/lines/summary.txt create mode 100644 core/io/streams/nested/authors.txt create mode 100644 core/io/streams/nested/nested-docs.factor create mode 100644 core/io/streams/nested/nested-tests.factor create mode 100644 core/io/streams/nested/nested.factor create mode 100644 core/io/streams/nested/summary.txt create mode 100644 core/io/streams/plain/authors.txt create mode 100644 core/io/streams/plain/plain-docs.factor create mode 100644 core/io/streams/plain/plain.factor create mode 100644 core/io/streams/plain/summary.txt create mode 100644 core/io/streams/string/authors.txt create mode 100644 core/io/streams/string/string-docs.factor create mode 100644 core/io/streams/string/string-tests.factor create mode 100644 core/io/streams/string/string.factor create mode 100644 core/io/streams/string/summary.txt create mode 100644 core/io/styles/authors.txt create mode 100644 core/io/styles/styles-docs.factor create mode 100644 core/io/styles/styles.factor create mode 100644 core/io/styles/summary.txt create mode 100644 core/io/summary.txt create mode 100644 core/io/test/binary.txt create mode 100644 core/io/test/empty-file.txt create mode 100644 core/io/test/mac-os-eol.txt create mode 100644 core/io/test/no-trailing-eol.factor create mode 100644 core/io/test/separator-test.txt create mode 100644 core/io/test/unix-eol.txt create mode 100644 core/io/test/windows-eol.txt create mode 100644 core/io/utf16/authors.txt create mode 100644 core/io/utf16/summary.txt create mode 100644 core/io/utf16/utf16-docs.factor create mode 100644 core/io/utf16/utf16-tests.factor create mode 100644 core/io/utf16/utf16.factor create mode 100644 core/io/utf8/authors.txt create mode 100644 core/io/utf8/summary.txt create mode 100644 core/io/utf8/utf8-docs.factor create mode 100644 core/io/utf8/utf8-tests.factor create mode 100644 core/io/utf8/utf8.factor create mode 100644 core/kernel/authors.txt create mode 100644 core/kernel/kernel-docs.factor create mode 100644 core/kernel/kernel-tests.factor create mode 100644 core/kernel/kernel.factor create mode 100644 core/kernel/summary.txt create mode 100644 core/layouts/authors.txt create mode 100644 core/layouts/layouts-docs.factor create mode 100644 core/layouts/layouts.factor create mode 100644 core/layouts/summary.txt create mode 100644 core/layouts/tags.txt create mode 100644 core/libc/authors.txt create mode 100644 core/libc/libc-docs.factor create mode 100644 core/libc/libc.factor create mode 100644 core/libc/summary.txt create mode 100644 core/libc/tags.txt create mode 100644 core/listener/authors.txt create mode 100644 core/listener/listener-docs.factor create mode 100644 core/listener/listener-tests.factor create mode 100644 core/listener/listener.factor create mode 100644 core/listener/summary.txt create mode 100644 core/listener/tags.txt create mode 100644 core/math/authors.txt create mode 100644 core/math/bitfields/authors.txt create mode 100644 core/math/bitfields/bitfields-docs.factor create mode 100644 core/math/bitfields/bitfields-tests.factor create mode 100644 core/math/bitfields/bitfields.factor create mode 100644 core/math/bitfields/summary.txt create mode 100644 core/math/complex/authors.txt create mode 100644 core/math/complex/complex-docs.factor create mode 100644 core/math/complex/complex-tests.factor create mode 100644 core/math/complex/complex.factor create mode 100644 core/math/complex/summary.txt create mode 100644 core/math/constants/authors.txt create mode 100644 core/math/constants/constants-docs.factor create mode 100644 core/math/constants/constants.factor create mode 100644 core/math/constants/summary.txt create mode 100644 core/math/floats/authors.txt create mode 100644 core/math/floats/floats-docs.factor create mode 100644 core/math/floats/floats-tests.factor create mode 100644 core/math/floats/floats.factor create mode 100644 core/math/floats/summary.txt create mode 100644 core/math/functions/authors.txt create mode 100644 core/math/functions/functions-docs.factor create mode 100644 core/math/functions/functions-tests.factor create mode 100644 core/math/functions/functions.factor create mode 100644 core/math/functions/summary.txt create mode 100644 core/math/integers/authors.txt create mode 100644 core/math/integers/integers-docs.factor create mode 100644 core/math/integers/integers-tests.factor create mode 100644 core/math/integers/integers.factor create mode 100644 core/math/integers/summary.txt create mode 100644 core/math/intervals/authors.txt create mode 100644 core/math/intervals/intervals-docs.factor create mode 100644 core/math/intervals/intervals-tests.factor create mode 100644 core/math/intervals/intervals.factor create mode 100644 core/math/intervals/summary.txt create mode 100644 core/math/libm/authors.txt create mode 100644 core/math/libm/libm-docs.factor create mode 100644 core/math/libm/libm.factor create mode 100644 core/math/libm/summary.txt create mode 100644 core/math/libm/tags.txt create mode 100644 core/math/math-docs.factor create mode 100644 core/math/math-tests.factor create mode 100644 core/math/math.factor create mode 100644 core/math/parser/authors.txt create mode 100644 core/math/parser/parser-docs.factor create mode 100644 core/math/parser/parser-tests.factor create mode 100644 core/math/parser/parser.factor create mode 100644 core/math/parser/summary.txt create mode 100644 core/math/ratios/authors.txt create mode 100644 core/math/ratios/ratios-docs.factor create mode 100644 core/math/ratios/ratios-tests.factor create mode 100644 core/math/ratios/ratios.factor create mode 100644 core/math/ratios/summary.txt create mode 100644 core/math/summary.txt create mode 100644 core/math/vectors/authors.txt create mode 100644 core/math/vectors/summary.txt create mode 100644 core/math/vectors/vectors-docs.factor create mode 100644 core/math/vectors/vectors-tests.factor create mode 100644 core/math/vectors/vectors.factor create mode 100644 core/memory/authors.txt create mode 100644 core/memory/memory-docs.factor create mode 100644 core/memory/memory-tests.factor create mode 100644 core/memory/memory.factor create mode 100644 core/memory/summary.txt create mode 100644 core/memory/tags.txt create mode 100644 core/mirrors/authors.txt create mode 100644 core/mirrors/mirrors-docs.factor create mode 100644 core/mirrors/mirrors-tests.factor create mode 100644 core/mirrors/mirrors.factor create mode 100644 core/mirrors/summary.txt create mode 100644 core/mirrors/tags.txt create mode 100644 core/namespaces/authors.txt create mode 100644 core/namespaces/namespaces-docs.factor create mode 100644 core/namespaces/namespaces-tests.factor create mode 100644 core/namespaces/namespaces.factor create mode 100644 core/namespaces/summary.txt create mode 100644 core/namespaces/tags.txt create mode 100644 core/none/authors.txt create mode 100644 core/none/none-docs.factor create mode 100644 core/none/none.factor create mode 100644 core/none/summary.txt create mode 100644 core/optimizer/authors.txt create mode 100644 core/optimizer/backend/authors.txt create mode 100644 core/optimizer/backend/backend.factor create mode 100644 core/optimizer/backend/summary.txt create mode 100644 core/optimizer/debugger/debugger.factor create mode 100644 core/optimizer/def-use/authors.txt create mode 100644 core/optimizer/def-use/def-use-tests.factor create mode 100644 core/optimizer/def-use/def-use.factor create mode 100644 core/optimizer/def-use/summary.txt create mode 100644 core/optimizer/known-words/authors.txt create mode 100644 core/optimizer/known-words/known-words.factor create mode 100644 core/optimizer/known-words/summary.txt create mode 100644 core/optimizer/math/authors.txt create mode 100644 core/optimizer/math/math.factor create mode 100644 core/optimizer/math/summary.txt create mode 100644 core/optimizer/optimizer-docs.factor create mode 100644 core/optimizer/optimizer.factor create mode 100644 core/optimizer/pattern-match/authors.txt create mode 100644 core/optimizer/pattern-match/pattern-match.factor create mode 100644 core/optimizer/pattern-match/summary.txt create mode 100644 core/optimizer/summary.txt create mode 100644 core/optimizer/tags.txt create mode 100644 core/parser/authors.txt create mode 100644 core/parser/parser-docs.factor create mode 100644 core/parser/parser-tests.factor create mode 100644 core/parser/parser.factor create mode 100644 core/parser/summary.txt create mode 100644 core/parser/tags.txt create mode 100644 core/prettyprint/authors.txt create mode 100644 core/prettyprint/backend/authors.txt create mode 100644 core/prettyprint/backend/backend-docs.factor create mode 100644 core/prettyprint/backend/backend.factor create mode 100644 core/prettyprint/backend/summary.txt create mode 100644 core/prettyprint/config/authors.txt create mode 100644 core/prettyprint/config/config-docs.factor create mode 100644 core/prettyprint/config/config.factor create mode 100644 core/prettyprint/config/summary.txt create mode 100644 core/prettyprint/prettyprint-docs.factor create mode 100644 core/prettyprint/prettyprint-tests.factor create mode 100644 core/prettyprint/prettyprint.factor create mode 100644 core/prettyprint/sections/authors.txt create mode 100644 core/prettyprint/sections/sections-docs.factor create mode 100644 core/prettyprint/sections/sections.factor create mode 100644 core/prettyprint/sections/summary.txt create mode 100644 core/prettyprint/summary.txt create mode 100644 core/prettyprint/tags.txt create mode 100644 core/queues/authors.txt create mode 100644 core/queues/queues-docs.factor create mode 100644 core/queues/queues-tests.factor create mode 100644 core/queues/queues.factor create mode 100644 core/queues/summary.txt create mode 100644 core/queues/tags.txt create mode 100644 core/quotations/authors.txt create mode 100644 core/quotations/quotations-docs.factor create mode 100644 core/quotations/quotations-tests.factor create mode 100644 core/quotations/quotations.factor create mode 100644 core/quotations/summary.txt create mode 100644 core/quotations/tags.txt create mode 100644 core/refs/refs-docs.factor create mode 100644 core/refs/refs.factor create mode 100644 core/sbufs/authors.txt create mode 100644 core/sbufs/sbufs-docs.factor create mode 100644 core/sbufs/sbufs-tests.factor create mode 100644 core/sbufs/sbufs.factor create mode 100644 core/sbufs/summary.txt create mode 100644 core/sbufs/tags.txt create mode 100644 core/sequences/authors.txt create mode 100644 core/sequences/sequences-docs.factor create mode 100644 core/sequences/sequences-tests.factor create mode 100644 core/sequences/sequences.factor create mode 100644 core/sequences/summary.txt create mode 100644 core/sequences/tags.txt create mode 100644 core/slots/authors.txt create mode 100644 core/slots/slots-docs.factor create mode 100644 core/slots/slots.factor create mode 100644 core/slots/summary.txt create mode 100644 core/sorting/authors.txt create mode 100644 core/sorting/sorting-docs.factor create mode 100644 core/sorting/sorting-tests.factor create mode 100644 core/sorting/sorting.factor create mode 100644 core/sorting/summary.txt create mode 100644 core/sorting/tags.txt create mode 100644 core/source-files/authors.txt create mode 100644 core/source-files/source-files-docs.factor create mode 100644 core/source-files/source-files.factor create mode 100644 core/source-files/summary.txt create mode 100644 core/splitting/authors.txt create mode 100644 core/splitting/splitting-docs.factor create mode 100644 core/splitting/splitting-tests.factor create mode 100644 core/splitting/splitting.factor create mode 100644 core/splitting/summary.txt create mode 100644 core/splitting/tags.txt create mode 100644 core/strings/authors.txt create mode 100644 core/strings/strings-docs.factor create mode 100644 core/strings/strings-tests.factor create mode 100644 core/strings/strings.factor create mode 100644 core/strings/summary.txt create mode 100644 core/strings/tags.txt create mode 100644 core/syntax/authors.txt create mode 100644 core/syntax/summary.txt create mode 100644 core/syntax/syntax-docs.factor create mode 100644 core/syntax/syntax.factor create mode 100644 core/system/authors.txt create mode 100644 core/system/summary.txt create mode 100644 core/system/system-docs.factor create mode 100644 core/system/system-tests.factor create mode 100644 core/system/system.factor create mode 100644 core/threads/authors.txt create mode 100644 core/threads/summary.txt create mode 100644 core/threads/threads-docs.factor create mode 100644 core/threads/threads-tests.factor create mode 100644 core/threads/threads.factor create mode 100644 core/tuples/authors.txt create mode 100644 core/tuples/summary.txt create mode 100644 core/tuples/tuples-docs.factor create mode 100644 core/tuples/tuples-tests.factor create mode 100644 core/tuples/tuples.factor create mode 100644 core/vectors/authors.txt create mode 100644 core/vectors/summary.txt create mode 100644 core/vectors/tags.txt create mode 100644 core/vectors/vectors-docs.factor create mode 100644 core/vectors/vectors-tests.factor create mode 100644 core/vectors/vectors.factor create mode 100644 core/vocabs/authors.txt create mode 100644 core/vocabs/loader/authors.txt create mode 100644 core/vocabs/loader/loader-docs.factor create mode 100644 core/vocabs/loader/loader-tests.factor create mode 100644 core/vocabs/loader/loader.factor create mode 100644 core/vocabs/loader/summary.txt create mode 100644 core/vocabs/loader/test/a/a.factor create mode 100644 core/vocabs/loader/test/b/b.factor create mode 100644 core/vocabs/loader/test/c/c.factor create mode 100644 core/vocabs/loader/test/d/d.factor create mode 100644 core/vocabs/loader/test/e/e.factor create mode 100644 core/vocabs/loader/test/f/f-docs.factor create mode 100644 core/vocabs/loader/test/f/f.factor create mode 100644 core/vocabs/summary.txt create mode 100644 core/vocabs/vocabs-docs.factor create mode 100644 core/vocabs/vocabs-tests.factor create mode 100644 core/vocabs/vocabs.factor create mode 100644 core/words/authors.txt create mode 100644 core/words/summary.txt create mode 100644 core/words/tags.txt create mode 100644 core/words/words-docs.factor create mode 100644 core/words/words-tests.factor create mode 100644 core/words/words.factor create mode 100644 cp_dir create mode 100644 extra/arrays/lib/lib.factor create mode 100644 extra/asn1/asn1-tests.factor create mode 100644 extra/asn1/asn1.factor create mode 100644 extra/asn1/authors.txt create mode 100644 extra/asn1/ldap/ldap.factor create mode 100644 extra/asn1/summary.txt create mode 100644 extra/automata/authors.txt create mode 100644 extra/automata/automata.factor create mode 100644 extra/automata/summary.txt create mode 100644 extra/automata/tags.txt create mode 100644 extra/automata/ui/ui.factor create mode 100644 extra/bake/bake.factor create mode 100644 extra/balloon-bomber/authors.txt create mode 100644 extra/balloon-bomber/balloon-bomber-docs.factor create mode 100644 extra/balloon-bomber/balloon-bomber.factor create mode 100644 extra/balloon-bomber/summary.txt create mode 100644 extra/balloon-bomber/tags.txt create mode 100644 extra/base64/authors.txt create mode 100644 extra/base64/base64-docs.factor create mode 100644 extra/base64/base64-tests.factor create mode 100644 extra/base64/base64.factor create mode 100644 extra/base64/summary.txt create mode 100644 extra/benchmark/authors.txt create mode 100644 extra/benchmark/benchmark.factor create mode 100644 extra/benchmark/bootstrap1/bootstrap1.factor create mode 100644 extra/benchmark/bootstrap2/bootstrap2.factor create mode 100644 extra/benchmark/continuations/continuations.factor create mode 100644 extra/benchmark/dispatch1/dispatch1.factor create mode 100644 extra/benchmark/dispatch2/dispatch2.factor create mode 100644 extra/benchmark/dispatch3/dispatch3.factor create mode 100644 extra/benchmark/dispatch4/dispatch4.factor create mode 100644 extra/benchmark/empty-loop/empty-loop.factor create mode 100644 extra/benchmark/fib1/fib1.factor create mode 100644 extra/benchmark/fib2/fib2.factor create mode 100644 extra/benchmark/fib3/fib3.factor create mode 100644 extra/benchmark/fib4/fib4.factor create mode 100644 extra/benchmark/fib5/fib5.factor create mode 100644 extra/benchmark/iteration/iteration.factor create mode 100644 extra/benchmark/mandel/mandel.factor create mode 100644 extra/benchmark/nsieve-bits/nsieve-bits.factor create mode 100644 extra/benchmark/nsieve/nsieve.factor create mode 100644 extra/benchmark/partial-sums/partial-sums.factor create mode 100644 extra/benchmark/raytracer/raytracer.factor create mode 100644 extra/benchmark/recursive/recursive.factor create mode 100644 extra/benchmark/reverse-complement-test-in.txt create mode 100644 extra/benchmark/reverse-complement-test-out.txt create mode 100644 extra/benchmark/reverse-complement/reverse-complement.factor create mode 100644 extra/benchmark/ring/ring.factor create mode 100644 extra/benchmark/sort/sort.factor create mode 100644 extra/benchmark/spectral-norm/spectral-norm.factor create mode 100644 extra/benchmark/sum-file/sum-file.factor create mode 100644 extra/benchmark/summary.txt create mode 100644 extra/benchmark/typecheck1/typecheck1.factor create mode 100644 extra/benchmark/typecheck2/typecheck2.factor create mode 100644 extra/benchmark/typecheck3/typecheck3.factor create mode 100644 extra/benchmark/typecheck4/typecheck4.factor create mode 100644 extra/bitfields/authors.txt create mode 100644 extra/bitfields/bitfields-docs.factor create mode 100644 extra/bitfields/bitfields-tests.factor create mode 100644 extra/bitfields/bitfields.factor create mode 100644 extra/bitfields/summary.txt create mode 100644 extra/bitfields/tags.txt create mode 100644 extra/boids/authors.txt create mode 100644 extra/boids/boids.factor create mode 100644 extra/boids/summary.txt create mode 100644 extra/boids/tags.txt create mode 100644 extra/boids/ui/ui.factor create mode 100644 extra/browser/analyzer/analyzer.factor create mode 100644 extra/browser/parser/parser-tests.factor create mode 100644 extra/browser/parser/parser.factor create mode 100644 extra/browser/printer/printer.factor create mode 100644 extra/browser/utils/utils-tests.factor create mode 100644 extra/browser/utils/utils.factor create mode 100644 extra/bunny/authors.txt create mode 100644 extra/bunny/bunny.factor create mode 100644 extra/bunny/deploy.factor create mode 100644 extra/bunny/summary.txt create mode 100644 extra/bunny/tags.txt create mode 100644 extra/cabal/cabal.factor create mode 100644 extra/cabal/ui/ui.factor create mode 100644 extra/cairo/authors.txt create mode 100644 extra/cairo/cairo.factor create mode 100644 extra/cairo/summary.txt create mode 100644 extra/cairo/tags.txt create mode 100644 extra/calendar/authors.txt create mode 100644 extra/calendar/calendar-tests.factor create mode 100644 extra/calendar/calendar.factor create mode 100644 extra/calendar/summary.txt create mode 100644 extra/calendar/unix/unix-tests.factor create mode 100644 extra/calendar/unix/unix.factor create mode 100644 extra/calendar/windows/windows-tests.factor create mode 100644 extra/calendar/windows/windows.factor create mode 100644 extra/catalyst-talk/authors.txt create mode 100644 extra/catalyst-talk/catalyst-talk.factor create mode 100644 extra/catalyst-talk/summary.txt create mode 100644 extra/catalyst-talk/tags.txt create mode 100644 extra/cfdg/authors.txt create mode 100644 extra/cfdg/cfdg.factor create mode 100644 extra/cfdg/gl/gl.factor create mode 100644 extra/cfdg/hsv/hsv.factor create mode 100644 extra/cfdg/models/aqua-star/aqua-star.factor create mode 100644 extra/cfdg/models/chiaroscuro/chiaroscuro.factor create mode 100644 extra/cfdg/models/flower6/flower6.factor create mode 100644 extra/cfdg/models/game1-turn6/game1-turn6.factor create mode 100644 extra/cfdg/models/lesson/lesson.factor create mode 100644 extra/cfdg/models/sierpinski/sierpinski.factor create mode 100644 extra/cfdg/models/snowflake/snowflake.factor create mode 100644 extra/channels/authors.txt create mode 100644 extra/channels/channels-docs.factor create mode 100644 extra/channels/channels-tests.factor create mode 100644 extra/channels/channels.factor create mode 100644 extra/channels/examples/authors.txt create mode 100644 extra/channels/examples/examples.factor create mode 100644 extra/channels/examples/summary.txt create mode 100644 extra/channels/examples/tags.txt create mode 100644 extra/channels/remote/authors.txt create mode 100644 extra/channels/remote/remote-docs.factor create mode 100644 extra/channels/remote/remote-tests.factor create mode 100644 extra/channels/remote/remote.factor create mode 100644 extra/channels/remote/summary.txt create mode 100644 extra/channels/remote/tags.txt create mode 100644 extra/channels/sniffer/bsd/bsd.factor create mode 100644 extra/channels/sniffer/sniffer.factor create mode 100644 extra/channels/summary.txt create mode 100644 extra/channels/tags.txt create mode 100644 extra/circular/authors.txt create mode 100644 extra/circular/circular-tests.factor create mode 100644 extra/circular/circular.factor create mode 100644 extra/circular/summary.txt create mode 100644 extra/circular/tags.txt create mode 100644 extra/cocoa/application/application-docs.factor create mode 100644 extra/cocoa/application/application.factor create mode 100644 extra/cocoa/application/authors.txt create mode 100644 extra/cocoa/application/summary.txt create mode 100644 extra/cocoa/authors.txt create mode 100644 extra/cocoa/callbacks/authors.txt create mode 100644 extra/cocoa/callbacks/callbacks.factor create mode 100644 extra/cocoa/callbacks/summary.txt create mode 100644 extra/cocoa/cocoa-docs.factor create mode 100644 extra/cocoa/cocoa-tests.factor create mode 100644 extra/cocoa/cocoa.factor create mode 100644 extra/cocoa/dialogs/authors.txt create mode 100644 extra/cocoa/dialogs/dialogs-docs.factor create mode 100644 extra/cocoa/dialogs/dialogs.factor create mode 100644 extra/cocoa/dialogs/summary.txt create mode 100644 extra/cocoa/messages/authors.txt create mode 100644 extra/cocoa/messages/messages-docs.factor create mode 100644 extra/cocoa/messages/messages.factor create mode 100644 extra/cocoa/messages/summary.txt create mode 100644 extra/cocoa/nibs/authors.txt create mode 100644 extra/cocoa/nibs/nibs-docs.factor create mode 100644 extra/cocoa/nibs/nibs.factor create mode 100644 extra/cocoa/nibs/summary.txt create mode 100644 extra/cocoa/pasteboard/authors.txt create mode 100644 extra/cocoa/pasteboard/pasteboard-docs.factor create mode 100644 extra/cocoa/pasteboard/pasteboard.factor create mode 100644 extra/cocoa/pasteboard/summary.txt create mode 100644 extra/cocoa/plists/plists.factor create mode 100644 extra/cocoa/runtime/authors.txt create mode 100644 extra/cocoa/runtime/runtime.factor create mode 100644 extra/cocoa/runtime/summary.txt create mode 100644 extra/cocoa/subclassing/authors.txt create mode 100644 extra/cocoa/subclassing/subclassing-docs.factor create mode 100644 extra/cocoa/subclassing/subclassing.factor create mode 100644 extra/cocoa/subclassing/summary.txt create mode 100644 extra/cocoa/summary.txt create mode 100644 extra/cocoa/tags.txt create mode 100644 extra/cocoa/types/authors.txt create mode 100644 extra/cocoa/types/summary.txt create mode 100644 extra/cocoa/types/types-docs.factor create mode 100644 extra/cocoa/types/types.factor create mode 100644 extra/cocoa/views/authors.txt create mode 100644 extra/cocoa/views/summary.txt create mode 100644 extra/cocoa/views/views-docs.factor create mode 100644 extra/cocoa/views/views.factor create mode 100644 extra/cocoa/windows/authors.txt create mode 100644 extra/cocoa/windows/summary.txt create mode 100644 extra/cocoa/windows/windows-docs.factor create mode 100644 extra/cocoa/windows/windows.factor create mode 100644 extra/color-picker/authors.txt create mode 100644 extra/color-picker/color-picker.factor create mode 100644 extra/color-picker/deploy.factor create mode 100644 extra/color-picker/summary.txt create mode 100644 extra/color-picker/tags.txt create mode 100644 extra/colors/authors.txt create mode 100644 extra/colors/colors.factor create mode 100644 extra/colors/hsv/hsv.factor create mode 100644 extra/combinators/lib/lib-docs.factor create mode 100644 extra/combinators/lib/lib-tests.factor create mode 100644 extra/combinators/lib/lib.factor create mode 100644 extra/concurrency/authors.txt create mode 100644 extra/concurrency/concurrency-docs.factor create mode 100644 extra/concurrency/concurrency-tests.factor create mode 100644 extra/concurrency/concurrency.factor create mode 100644 extra/concurrency/distributed/authors.txt create mode 100644 extra/concurrency/distributed/distributed-docs.factor create mode 100644 extra/concurrency/distributed/distributed.factor create mode 100644 extra/concurrency/distributed/summary.txt create mode 100644 extra/concurrency/distributed/tags.txt create mode 100644 extra/concurrency/summary.txt create mode 100644 extra/concurrency/tags.txt create mode 100644 extra/const/const.factor create mode 100644 extra/contributors/authors.txt create mode 100644 extra/contributors/contributors.factor create mode 100644 extra/contributors/summary.txt create mode 100644 extra/contributors/tags.txt create mode 100644 extra/core-foundation/authors.txt create mode 100644 extra/core-foundation/core-foundation-docs.factor create mode 100644 extra/core-foundation/core-foundation.factor create mode 100644 extra/core-foundation/summary.txt create mode 100644 extra/core-foundation/tags.txt create mode 100644 extra/coroutines/authors.txt create mode 100644 extra/coroutines/coroutines-docs.factor create mode 100644 extra/coroutines/coroutines-tests.factor create mode 100644 extra/coroutines/coroutines.factor create mode 100644 extra/coroutines/summary.txt create mode 100644 extra/coroutines/tags.txt create mode 100644 extra/cpu/8080/8080-docs.factor create mode 100644 extra/cpu/8080/8080.factor create mode 100644 extra/cryptlib/authors.txt create mode 100644 extra/cryptlib/cryptlib-tests.factor create mode 100644 extra/cryptlib/cryptlib.factor create mode 100644 extra/cryptlib/libcl/libcl.factor create mode 100644 extra/cryptlib/notes.txt create mode 100644 extra/cryptlib/streams/streams.factor create mode 100644 extra/cryptlib/streams/tags.txt create mode 100644 extra/cryptlib/summary.txt create mode 100644 extra/cryptlib/tags.txt create mode 100644 extra/cryptlib/test/keys.p15 create mode 100644 extra/cryptlib/test/large_data.txt create mode 100644 extra/crypto/authors.txt create mode 100644 extra/crypto/barrett/barrett-tests.factor create mode 100644 extra/crypto/barrett/barrett.factor create mode 100644 extra/crypto/blum-blum-shub.factor create mode 100644 extra/crypto/common/common-docs.factor create mode 100644 extra/crypto/common/common.factor create mode 100644 extra/crypto/hmac/hmac-tests.factor create mode 100644 extra/crypto/hmac/hmac.factor create mode 100644 extra/crypto/md5/md5-docs.factor create mode 100644 extra/crypto/md5/md5-tests.factor create mode 100644 extra/crypto/md5/md5.factor create mode 100644 extra/crypto/random.factor create mode 100644 extra/crypto/rc4.factor create mode 100644 extra/crypto/rsa.factor create mode 100644 extra/crypto/rsa/rsa-tests.factor create mode 100644 extra/crypto/rsa/rsa.factor create mode 100644 extra/crypto/sha1/sha1-tests.factor create mode 100644 extra/crypto/sha1/sha1.factor create mode 100644 extra/crypto/sha2/sha2-tests.factor create mode 100644 extra/crypto/sha2/sha2.factor create mode 100644 extra/crypto/summary.txt create mode 100644 extra/crypto/test/blum-blum-shub.factor create mode 100644 extra/crypto/test/common.factor create mode 100644 extra/crypto/test/rsa.factor create mode 100644 extra/crypto/test/xor.factor create mode 100644 extra/crypto/timing/timing-tests.factor create mode 100644 extra/crypto/timing/timing.factor create mode 100644 extra/crypto/xor.factor create mode 100644 extra/destructors/authors.txt create mode 100644 extra/destructors/destructors-docs.factor create mode 100644 extra/destructors/destructors-tests.factor create mode 100644 extra/destructors/destructors.factor create mode 100644 extra/destructors/summary.txt create mode 100644 extra/dlists/authors.txt create mode 100644 extra/dlists/dlists-tests.factor create mode 100644 extra/dlists/dlists.factor create mode 100644 extra/dlists/summary.txt create mode 100644 extra/dlists/tags.txt create mode 100644 extra/documents/authors.txt create mode 100644 extra/documents/documents-docs.factor create mode 100644 extra/documents/documents-tests.factor create mode 100644 extra/documents/documents.factor create mode 100644 extra/documents/summary.txt create mode 100644 extra/editors/authors.txt create mode 100644 extra/editors/editors-docs.factor create mode 100644 extra/editors/editors.factor create mode 100644 extra/editors/editpadpro/authors.txt create mode 100644 extra/editors/editpadpro/editpadpro-docs.factor create mode 100644 extra/editors/editpadpro/editpadpro.factor create mode 100644 extra/editors/emacs/authors.txt create mode 100644 extra/editors/emacs/emacs-docs.factor create mode 100644 extra/editors/emacs/emacs.factor create mode 100644 extra/editors/gvim/authors.txt create mode 100644 extra/editors/gvim/gvim.factor create mode 100644 extra/editors/jedit/authors.txt create mode 100644 extra/editors/jedit/jedit.factor create mode 100644 extra/editors/jedit/summary.txt create mode 100644 extra/editors/scite/authors.txt create mode 100644 extra/editors/scite/scite.factor create mode 100644 extra/editors/summary.txt create mode 100644 extra/editors/tags.txt create mode 100644 extra/editors/textmate/authors.txt create mode 100644 extra/editors/textmate/textmate.factor create mode 100644 extra/editors/vim/authors.txt create mode 100644 extra/editors/vim/generate-vim-syntax.factor create mode 100644 extra/editors/vim/vim-docs.factor create mode 100644 extra/editors/vim/vim.factor create mode 100644 extra/eval-server/authors.txt create mode 100644 extra/eval-server/eval-server.factor create mode 100644 extra/eval-server/summary.txt create mode 100644 extra/eval-server/tags.txt create mode 100644 extra/factory/authors.txt create mode 100644 extra/factory/commands/commands.factor create mode 100644 extra/factory/deploy.factor create mode 100644 extra/factory/factory-menus create mode 100644 extra/factory/factory-rc create mode 100644 extra/factory/factory.factor create mode 100644 extra/factory/load/load.factor create mode 100644 extra/factory/summary.txt create mode 100644 extra/factory/tags.txt create mode 100644 extra/fjsc/authors.txt create mode 100644 extra/fjsc/fjsc-tests.factor create mode 100644 extra/fjsc/fjsc.factor create mode 100644 extra/fjsc/resources/bootstrap.factor create mode 100644 extra/fjsc/resources/bootstrap.js create mode 100644 extra/fjsc/resources/jquery.js create mode 100644 extra/fjsc/summary.txt create mode 100644 extra/freetype/authors.txt create mode 100644 extra/freetype/freetype.factor create mode 100644 extra/freetype/summary.txt create mode 100644 extra/freetype/tags.txt create mode 100644 extra/furnace/furnace-tests.factor create mode 100644 extra/furnace/furnace.factor create mode 100644 extra/furnace/scaffold/crud-templates/edit.furnace create mode 100644 extra/furnace/scaffold/crud-templates/list.furnace create mode 100644 extra/furnace/scaffold/crud-templates/show.furnace create mode 100644 extra/furnace/scaffold/scaffold.factor create mode 100644 extra/furnace/validator/validator-tests.factor create mode 100644 extra/furnace/validator/validator.factor create mode 100644 extra/gap-buffer/authors.txt create mode 100644 extra/gap-buffer/cursortree/authors.txt create mode 100644 extra/gap-buffer/cursortree/cursortree-tests.factor create mode 100644 extra/gap-buffer/cursortree/cursortree.factor create mode 100644 extra/gap-buffer/cursortree/summary.txt create mode 100644 extra/gap-buffer/gap-buffer-tests.factor create mode 100644 extra/gap-buffer/gap-buffer.factor create mode 100644 extra/gap-buffer/summary.txt create mode 100644 extra/gap-buffer/tags.txt create mode 100644 extra/generic/lib/lib.factor create mode 100644 extra/geom/dim/dim.factor create mode 100644 extra/geom/pos/pos.factor create mode 100644 extra/geom/rect/rect.factor create mode 100644 extra/gesture-logger/authors.txt create mode 100644 extra/gesture-logger/deploy.factor create mode 100644 extra/gesture-logger/gesture-logger.factor create mode 100644 extra/gesture-logger/summary.txt create mode 100644 extra/golden-section/authors.txt create mode 100644 extra/golden-section/deploy.factor create mode 100644 extra/golden-section/golden-section.factor create mode 100644 extra/golden-section/summary.txt create mode 100644 extra/golden-section/tags.txt create mode 100644 extra/graphics/authors.txt create mode 100644 extra/graphics/bitmap/bitmap.factor create mode 100644 extra/graphics/tags.txt create mode 100644 extra/graphics/viewer/viewer.factor create mode 100644 extra/hardware-info/authors.txt create mode 100644 extra/hardware-info/hardware-info.factor create mode 100644 extra/hardware-info/linux/linux.factor create mode 100644 extra/hardware-info/macosx/macosx.factor create mode 100644 extra/hardware-info/summary.txt create mode 100644 extra/hardware-info/windows/ce/ce.factor create mode 100644 extra/hardware-info/windows/nt/nt.factor create mode 100644 extra/hardware-info/windows/windows.factor create mode 100644 extra/hash2/authors.txt create mode 100644 extra/hash2/hash2-docs.factor create mode 100644 extra/hash2/hash2-tests.factor create mode 100644 extra/hash2/hash2.factor create mode 100644 extra/hash2/summary.txt create mode 100644 extra/hash2/tags.txt create mode 100644 extra/hashtables/lib/authors.txt create mode 100644 extra/hashtables/lib/lib.factor create mode 100644 extra/hashtables/lib/summary.txt create mode 100644 extra/hashtables/lib/tags.txt create mode 100644 extra/hello-ui/authors.txt create mode 100644 extra/hello-ui/deploy.factor create mode 100644 extra/hello-ui/hello-ui.factor create mode 100644 extra/hello-ui/summary.txt create mode 100644 extra/hello-ui/tags.txt create mode 100644 extra/hello-world/authors.txt create mode 100644 extra/hello-world/deploy.factor create mode 100644 extra/hello-world/hello-world.factor create mode 100644 extra/hello-world/summary.txt create mode 100644 extra/hello-world/tags.txt create mode 100644 extra/help/authors.txt create mode 100644 extra/help/cookbook/cookbook.factor create mode 100644 extra/help/crossref/authors.txt create mode 100644 extra/help/crossref/crossref-docs.factor create mode 100644 extra/help/crossref/crossref-tests.factor create mode 100644 extra/help/crossref/crossref.factor create mode 100644 extra/help/crossref/summary.txt create mode 100644 extra/help/definitions/authors.txt create mode 100644 extra/help/definitions/definitions-tests.factor create mode 100644 extra/help/definitions/definitions.factor create mode 100644 extra/help/definitions/summary.txt create mode 100644 extra/help/handbook/authors.txt create mode 100644 extra/help/handbook/handbook.factor create mode 100644 extra/help/handbook/summary.txt create mode 100644 extra/help/help-docs.factor create mode 100644 extra/help/help.factor create mode 100644 extra/help/lint/authors.txt create mode 100644 extra/help/lint/lint-docs.factor create mode 100644 extra/help/lint/lint.factor create mode 100644 extra/help/lint/summary.txt create mode 100644 extra/help/lint/tags.txt create mode 100644 extra/help/markup/authors.txt create mode 100644 extra/help/markup/markup-docs.factor create mode 100644 extra/help/markup/markup-tests.factor create mode 100644 extra/help/markup/markup.factor create mode 100644 extra/help/markup/summary.txt create mode 100644 extra/help/stylesheet/authors.txt create mode 100644 extra/help/stylesheet/stylesheet.factor create mode 100644 extra/help/stylesheet/summary.txt create mode 100644 extra/help/summary.txt create mode 100644 extra/help/syntax/authors.txt create mode 100644 extra/help/syntax/summary.txt create mode 100644 extra/help/syntax/syntax-docs.factor create mode 100644 extra/help/syntax/syntax-tests.factor create mode 100644 extra/help/syntax/syntax.factor create mode 100644 extra/help/topics/authors.txt create mode 100644 extra/help/topics/summary.txt create mode 100644 extra/help/topics/topics-docs.factor create mode 100644 extra/help/topics/topics-tests.factor create mode 100644 extra/help/topics/topics.factor create mode 100644 extra/hexdump/authors.txt create mode 100644 extra/hexdump/hexdump-docs.factor create mode 100644 extra/hexdump/hexdump-tests.factor create mode 100644 extra/hexdump/hexdump.factor create mode 100644 extra/hexdump/summary.txt create mode 100644 extra/hints/authors.txt create mode 100644 extra/hints/hints.factor create mode 100644 extra/hints/summary.txt create mode 100644 extra/hints/tags.txt create mode 100644 extra/html/authors.txt create mode 100644 extra/html/elements/elements.factor create mode 100644 extra/html/html-tests.factor create mode 100644 extra/html/html.factor create mode 100644 extra/html/summary.txt create mode 100644 extra/html/tags.txt create mode 100644 extra/http/authors.txt create mode 100644 extra/http/basic-authentication/authors.txt create mode 100644 extra/http/basic-authentication/basic-authentication-docs.factor create mode 100644 extra/http/basic-authentication/basic-authentication-tests.factor create mode 100644 extra/http/basic-authentication/basic-authentication.factor create mode 100644 extra/http/basic-authentication/summary.txt create mode 100644 extra/http/basic-authentication/tags.txt create mode 100644 extra/http/client/authors.txt create mode 100644 extra/http/client/client-tests.factor create mode 100644 extra/http/client/client.factor create mode 100644 extra/http/client/summary.txt create mode 100644 extra/http/client/tags.txt create mode 100644 extra/http/http-tests.factor create mode 100644 extra/http/http.factor create mode 100644 extra/http/mime/mime.factor create mode 100644 extra/http/server/resources/prototype.js create mode 100644 extra/http/server/resources/stylesheet.css create mode 100644 extra/http/server/responders/callback/callback.factor create mode 100644 extra/http/server/responders/continuation/continuation.factor create mode 100644 extra/http/server/responders/continuation/examples/examples.factor create mode 100644 extra/http/server/responders/continuation/examples/numbers/numbers.factor create mode 100644 extra/http/server/responders/file/file.factor create mode 100644 extra/http/server/responders/responders.factor create mode 100644 extra/http/server/server-tests.factor create mode 100644 extra/http/server/server.factor create mode 100644 extra/http/server/summary.txt create mode 100644 extra/http/server/tags.txt create mode 100644 extra/http/server/templating/authors.txt create mode 100644 extra/http/server/templating/templating-tests.factor create mode 100644 extra/http/server/templating/templating.factor create mode 100644 extra/http/server/templating/test/bug.fhtml create mode 100644 extra/http/server/templating/test/bug.html create mode 100644 extra/http/server/templating/test/example.fhtml create mode 100644 extra/http/server/templating/test/example.html create mode 100644 extra/http/server/templating/test/stack.fhtml create mode 100644 extra/http/server/templating/test/stack.html create mode 100644 extra/http/summary.txt create mode 100644 extra/http/tags.txt create mode 100644 extra/icfp/2006/2006.factor create mode 100644 extra/icfp/2006/authors.txt create mode 100644 extra/icfp/2006/sandmark.umz create mode 100644 extra/icfp/2006/summary.txt create mode 100644 extra/icfp/2006/tags.txt create mode 100644 extra/id3/authors.txt create mode 100644 extra/id3/id3-docs.factor create mode 100644 extra/id3/id3.factor create mode 100644 extra/id3/summary.txt create mode 100644 extra/inverse/authors.txt create mode 100644 extra/inverse/inverse-docs.factor create mode 100644 extra/inverse/inverse-tests.factor create mode 100644 extra/inverse/inverse.factor create mode 100644 extra/inverse/tags.txt create mode 100644 extra/io/launcher/authors.txt create mode 100644 extra/io/launcher/launcher.factor create mode 100644 extra/io/launcher/summary.txt create mode 100644 extra/io/mmap/mmap-tests.factor create mode 100644 extra/io/mmap/mmap.factor create mode 100644 extra/io/nonblocking/authors.txt create mode 100644 extra/io/nonblocking/nonblocking-docs.factor create mode 100644 extra/io/nonblocking/nonblocking.factor create mode 100644 extra/io/nonblocking/summary.txt create mode 100644 extra/io/server/server-docs.factor create mode 100644 extra/io/server/server.factor create mode 100644 extra/io/sniffer/bsd/bsd.factor create mode 100644 extra/io/sniffer/filter/bsd/bsd.factor create mode 100644 extra/io/sniffer/filter/filter.factor create mode 100644 extra/io/sniffer/sniffer.factor create mode 100644 extra/io/sockets/authors.txt create mode 100644 extra/io/sockets/headers/bsd/bsd.factor create mode 100644 extra/io/sockets/headers/headers.factor create mode 100644 extra/io/sockets/impl/impl-tests.factor create mode 100644 extra/io/sockets/impl/impl.factor create mode 100644 extra/io/sockets/sockets-docs.factor create mode 100644 extra/io/sockets/sockets.factor create mode 100644 extra/io/sockets/summary.txt create mode 100644 extra/io/sockets/tags.txt create mode 100644 extra/io/streams/null/null.factor create mode 100644 extra/io/unix/authors.txt create mode 100644 extra/io/unix/backend/authors.txt create mode 100644 extra/io/unix/backend/backend.factor create mode 100644 extra/io/unix/backend/summary.txt create mode 100644 extra/io/unix/files/authors.txt create mode 100644 extra/io/unix/files/files-tests.factor create mode 100644 extra/io/unix/files/files.factor create mode 100644 extra/io/unix/files/summary.txt create mode 100644 extra/io/unix/launcher/launcher.factor create mode 100644 extra/io/unix/mmap/mmap.factor create mode 100644 extra/io/unix/sockets/authors.txt create mode 100644 extra/io/unix/sockets/sockets.factor create mode 100644 extra/io/unix/sockets/summary.txt create mode 100644 extra/io/unix/summary.txt create mode 100644 extra/io/unix/unix-tests.factor create mode 100644 extra/io/unix/unix.factor create mode 100644 extra/io/windows/authors.txt create mode 100644 extra/io/windows/ce/authors.txt create mode 100644 extra/io/windows/ce/ce.factor create mode 100644 extra/io/windows/ce/summary.txt create mode 100644 extra/io/windows/launcher/launcher.factor create mode 100644 extra/io/windows/mmap/mmap.factor create mode 100644 extra/io/windows/nt/authors.txt create mode 100644 extra/io/windows/nt/backend/backend.factor create mode 100644 extra/io/windows/nt/files/files.factor create mode 100644 extra/io/windows/nt/nt.factor create mode 100644 extra/io/windows/nt/sockets/sockets.factor create mode 100644 extra/io/windows/nt/summary.txt create mode 100644 extra/io/windows/summary.txt create mode 100644 extra/io/windows/windows-tests.factor create mode 100644 extra/io/windows/windows.factor create mode 100644 extra/irc/authors.txt create mode 100644 extra/irc/irc.factor create mode 100644 extra/irc/summary.txt create mode 100644 extra/json/reader/authors.txt create mode 100644 extra/json/reader/reader-docs.factor create mode 100644 extra/json/reader/reader.factor create mode 100644 extra/json/reader/summary.txt create mode 100644 extra/json/writer/authors.txt create mode 100644 extra/json/writer/summary.txt create mode 100644 extra/json/writer/writer-docs.factor create mode 100644 extra/json/writer/writer.factor create mode 100644 extra/koszul/koszul-tests.factor create mode 100644 extra/koszul/koszul.factor create mode 100644 extra/lazy-lists/authors.txt create mode 100644 extra/lazy-lists/examples/examples-tests.factor create mode 100644 extra/lazy-lists/examples/examples.factor create mode 100644 extra/lazy-lists/lazy-lists-docs.factor create mode 100644 extra/lazy-lists/lazy-lists-tests.factor create mode 100644 extra/lazy-lists/lazy-lists.factor create mode 100644 extra/lazy-lists/old-doc.html create mode 100644 extra/lazy-lists/summary.txt create mode 100644 extra/lazy-lists/tags.txt create mode 100644 extra/lcd/authors.txt create mode 100644 extra/lcd/lcd.factor create mode 100644 extra/lcd/summary.txt create mode 100644 extra/lcd/tags.txt create mode 100644 extra/ldap/authors.txt create mode 100644 extra/ldap/conf/addentry.ldif create mode 100644 extra/ldap/conf/createdit.ldif create mode 100644 extra/ldap/conf/slapd.conf create mode 100644 extra/ldap/ldap-tests.factor create mode 100644 extra/ldap/ldap.factor create mode 100644 extra/ldap/libldap/libldap.factor create mode 100644 extra/ldap/libldap/tags.txt create mode 100644 extra/ldap/summary.txt create mode 100644 extra/ldap/tags.txt create mode 100644 extra/levenshtein/authors.txt create mode 100644 extra/levenshtein/levenshtein-tests.factor create mode 100644 extra/levenshtein/levenshtein.factor create mode 100644 extra/levenshtein/summary.txt create mode 100644 extra/lint/authors.txt create mode 100644 extra/lint/lint-tests.factor create mode 100644 extra/lint/lint.factor create mode 100644 extra/lint/tags.txt create mode 100644 extra/lisp/README create mode 100644 extra/lisp/authors.txt create mode 100644 extra/lisp/lexer/lexer.factor create mode 100644 extra/lisp/lisp.factor create mode 100644 extra/lisp/listener/listener.factor create mode 100644 extra/lisp/listener/mod/mod.factor create mode 100644 extra/lisp/parser/mod/mod.factor create mode 100644 extra/lisp/summary.txt create mode 100644 extra/lisp/syntax/syntax.factor create mode 100644 extra/lisp/tags.txt create mode 100644 extra/lisppaste/authors.txt create mode 100644 extra/lisppaste/lisppaste.factor create mode 100644 extra/lisppaste/summary.txt create mode 100644 extra/lisppaste/tags.txt create mode 100644 extra/locals/authors.txt create mode 100644 extra/locals/locals-docs.factor create mode 100644 extra/locals/locals-tests.factor create mode 100644 extra/locals/locals.factor create mode 100644 extra/locals/summary.txt create mode 100644 extra/locals/tags.txt create mode 100644 extra/lsys/authors.txt create mode 100644 extra/lsys/strings/strings.factor create mode 100644 extra/lsys/summary.txt create mode 100644 extra/lsys/tags.txt create mode 100644 extra/lsys/tortoise/graphics/graphics.factor create mode 100644 extra/lsys/tortoise/tortoise.factor create mode 100644 extra/lsys/ui/ui.factor create mode 100644 extra/lunar-rescue/authors.txt create mode 100644 extra/lunar-rescue/lunar-rescue-docs.factor create mode 100644 extra/lunar-rescue/lunar-rescue.factor create mode 100644 extra/lunar-rescue/summary.txt create mode 100644 extra/lunar-rescue/tags.txt create mode 100644 extra/macros/authors.txt create mode 100644 extra/macros/macros-docs.factor create mode 100644 extra/macros/macros-tests.factor create mode 100644 extra/macros/macros.factor create mode 100644 extra/macros/summary.txt create mode 100644 extra/macros/tags.txt create mode 100644 extra/macros/zoo/zoo.factor create mode 100644 extra/mad/api/api.factor create mode 100644 extra/mad/authors.txt create mode 100644 extra/mad/mad-tests.factor create mode 100644 extra/mad/mad.factor create mode 100644 extra/mad/player/player.factor create mode 100644 extra/mad/summary.txt create mode 100644 extra/match/authors.txt create mode 100644 extra/match/match-docs.factor create mode 100644 extra/match/match-tests.factor create mode 100644 extra/match/match.factor create mode 100644 extra/match/summary.txt create mode 100644 extra/match/tags.txt create mode 100644 extra/math/analysis/analysis-tests.factor create mode 100644 extra/math/analysis/analysis.factor create mode 100644 extra/math/analysis/authors.txt create mode 100644 extra/math/analysis/summary.txt create mode 100644 extra/math/combinatorics/authors.txt create mode 100644 extra/math/combinatorics/combinatorics.factor create mode 100644 extra/math/combinatorics/summary.txt create mode 100644 extra/math/fft/authors.txt create mode 100644 extra/math/fft/fft.factor create mode 100644 extra/math/fft/summary.txt create mode 100644 extra/math/haar/haar.factor create mode 100644 extra/math/haar/summary.txt create mode 100644 extra/math/matrices/authors.txt create mode 100644 extra/math/matrices/elimination/authors.txt create mode 100644 extra/math/matrices/elimination/elimination-tests.factor create mode 100644 extra/math/matrices/elimination/elimination.factor create mode 100644 extra/math/matrices/elimination/summary.txt create mode 100644 extra/math/matrices/matrices-tests.factor create mode 100644 extra/math/matrices/matrices.factor create mode 100644 extra/math/matrices/summary.txt create mode 100644 extra/math/miller-rabin/miller-rabin-tests.factor create mode 100644 extra/math/miller-rabin/miller-rabin.factor create mode 100644 extra/math/numerical-integration/authors.txt create mode 100644 extra/math/numerical-integration/numerical-integration-tests.factor create mode 100644 extra/math/numerical-integration/numerical-integration.factor create mode 100644 extra/math/numerical-integration/summary.txt create mode 100644 extra/math/polynomials/authors.txt create mode 100644 extra/math/polynomials/polynomials-tests.factor create mode 100644 extra/math/polynomials/polynomials.factor create mode 100644 extra/math/polynomials/summary.txt create mode 100644 extra/math/primes/list/list.factor create mode 100644 extra/math/quadratic/authors.txt create mode 100644 extra/math/quadratic/quadratic.factor create mode 100644 extra/math/quadratic/summary.txt create mode 100644 extra/math/quaternions/authors.txt create mode 100644 extra/math/quaternions/quaternions-tests.factor create mode 100644 extra/math/quaternions/quaternions.factor create mode 100644 extra/math/quaternions/summary.txt create mode 100644 extra/math/ranges/authors.txt create mode 100644 extra/math/ranges/ranges-tests.factor create mode 100644 extra/math/ranges/ranges.factor create mode 100644 extra/math/ranges/summary.txt create mode 100644 extra/math/statistics/authors.txt create mode 100644 extra/math/statistics/statistics-tests.factor create mode 100644 extra/math/statistics/statistics.factor create mode 100644 extra/math/statistics/summary.txt create mode 100644 extra/math/trig/trig.factor create mode 100644 extra/maze/authors.txt create mode 100644 extra/maze/deploy.factor create mode 100644 extra/maze/maze.factor create mode 100644 extra/maze/summary.txt create mode 100644 extra/maze/tags.txt create mode 100644 extra/memoize/authors.txt create mode 100644 extra/memoize/memoize-docs.factor create mode 100644 extra/memoize/memoize-tests.factor create mode 100644 extra/memoize/memoize.factor create mode 100644 extra/memoize/summary.txt create mode 100644 extra/memoize/tags.txt create mode 100644 extra/models/authors.txt create mode 100644 extra/models/models-docs.factor create mode 100644 extra/models/models-tests.factor create mode 100644 extra/models/models.factor create mode 100644 extra/models/summary.txt create mode 100644 extra/models/tags.txt create mode 100644 extra/mortar/authors.txt create mode 100644 extra/mortar/mortar.factor create mode 100644 extra/mortar/tags.txt create mode 100644 extra/msxml-to-csv/authors.txt create mode 100644 extra/msxml-to-csv/msxml-to-csv.factor create mode 100644 extra/msxml-to-csv/summary.txt create mode 100644 extra/msxml-to-csv/tags.txt create mode 100644 extra/namespaces/lib/authors.txt create mode 100644 extra/namespaces/lib/lib.factor create mode 100644 extra/namespaces/lib/summary.txt create mode 100644 extra/namespaces/lib/tags.txt create mode 100644 extra/nehe/2/2.factor create mode 100644 extra/nehe/3/3.factor create mode 100644 extra/nehe/4/4.factor create mode 100644 extra/nehe/5/5.factor create mode 100644 extra/nehe/authors.txt create mode 100644 extra/nehe/deploy.factor create mode 100644 extra/nehe/nehe.factor create mode 100644 extra/nehe/summary.txt create mode 100644 extra/nehe/tags.txt create mode 100644 extra/numbers-game/authors.txt create mode 100644 extra/numbers-game/numbers-game.factor create mode 100644 extra/numbers-game/summary.txt create mode 100644 extra/numbers-game/tags.txt create mode 100644 extra/odbc/authors.txt create mode 100644 extra/odbc/odbc-docs.factor create mode 100644 extra/odbc/odbc.factor create mode 100644 extra/odbc/summary.txt create mode 100644 extra/odbc/tags.txt create mode 100644 extra/ogg/authors.txt create mode 100644 extra/ogg/ogg.factor create mode 100644 extra/ogg/player/authors.txt create mode 100644 extra/ogg/player/player.factor create mode 100644 extra/ogg/player/summary.txt create mode 100644 extra/ogg/player/tags.txt create mode 100644 extra/ogg/summary.txt create mode 100644 extra/ogg/tags.txt create mode 100644 extra/ogg/theora/authors.txt create mode 100644 extra/ogg/theora/summary.txt create mode 100644 extra/ogg/theora/tags.txt create mode 100644 extra/ogg/theora/theora.factor create mode 100644 extra/ogg/vorbis/authors.txt create mode 100644 extra/ogg/vorbis/summary.txt create mode 100644 extra/ogg/vorbis/tags.txt create mode 100644 extra/ogg/vorbis/vorbis.factor create mode 100644 extra/openal/authors.txt create mode 100644 extra/openal/example/example.factor create mode 100644 extra/openal/macosx/macosx.factor create mode 100644 extra/openal/openal.factor create mode 100644 extra/openal/other/other.factor create mode 100644 extra/openal/summary.txt create mode 100644 extra/openal/tags.txt create mode 100644 extra/opengl/authors.txt create mode 100644 extra/opengl/camera/camera.factor create mode 100644 extra/opengl/gl/authors.txt create mode 100644 extra/opengl/gl/gl.factor create mode 100644 extra/opengl/gl/summary.txt create mode 100644 extra/opengl/gl/tags.txt create mode 100644 extra/opengl/glu/authors.txt create mode 100644 extra/opengl/glu/glu.factor create mode 100644 extra/opengl/glu/summary.txt create mode 100644 extra/opengl/glu/tags.txt create mode 100644 extra/opengl/lib/lib.factor create mode 100644 extra/opengl/opengl-docs.factor create mode 100644 extra/opengl/opengl.factor create mode 100644 extra/opengl/summary.txt create mode 100644 extra/opengl/tags.txt create mode 100644 extra/openssl/authors.txt create mode 100644 extra/openssl/libcrypto/libcrypto.factor create mode 100644 extra/openssl/libssl/libssl.factor create mode 100644 extra/openssl/openssl-tests.factor create mode 100644 extra/openssl/openssl.factor create mode 100644 extra/openssl/tags.txt create mode 100644 extra/openssl/test/dh1024.pem create mode 100644 extra/openssl/test/errors.txt create mode 100644 extra/openssl/test/root.pem create mode 100644 extra/openssl/test/server.pem create mode 100644 extra/oracle/authors.txt create mode 100644 extra/oracle/liboci/liboci.factor create mode 100644 extra/oracle/oracle-tests.factor create mode 100644 extra/oracle/oracle.factor create mode 100644 extra/oracle/summary.txt create mode 100644 extra/oracle/tags.txt create mode 100644 extra/ori/authors.txt create mode 100644 extra/ori/ori.factor create mode 100644 extra/pack/authors.txt create mode 100644 extra/pack/pack-tests.factor create mode 100644 extra/pack/pack.factor create mode 100644 extra/parser-combinators/authors.txt create mode 100644 extra/parser-combinators/parser-combinators-docs.factor create mode 100644 extra/parser-combinators/parser-combinators-tests.factor create mode 100644 extra/parser-combinators/parser-combinators.factor create mode 100644 extra/parser-combinators/parser-combinators.html create mode 100644 extra/parser-combinators/replace/replace-docs.factor create mode 100644 extra/parser-combinators/replace/replace.factor create mode 100644 extra/parser-combinators/simple/simple-docs.factor create mode 100644 extra/parser-combinators/simple/simple.factor create mode 100644 extra/parser-combinators/summary.txt create mode 100644 extra/partial-continuations/authors.txt create mode 100644 extra/partial-continuations/partial-continuations-docs.factor create mode 100644 extra/partial-continuations/partial-continuations-tests.factor create mode 100644 extra/partial-continuations/partial-continuations.factor create mode 100644 extra/partial-continuations/summary.txt create mode 100644 extra/partial-continuations/tags.txt create mode 100644 extra/pdf/authors.txt create mode 100644 extra/pdf/libhpdf/libhpdf.factor create mode 100644 extra/pdf/pdf-tests.factor create mode 100644 extra/pdf/pdf.factor create mode 100644 extra/pdf/readme.txt create mode 100644 extra/pdf/test/font_test.pdf create mode 100644 extra/porter-stemmer/authors.txt create mode 100644 extra/porter-stemmer/porter-stemmer-docs.factor create mode 100644 extra/porter-stemmer/porter-stemmer-tests.factor create mode 100644 extra/porter-stemmer/porter-stemmer.factor create mode 100644 extra/porter-stemmer/summary.txt create mode 100644 extra/porter-stemmer/test/output.txt create mode 100644 extra/porter-stemmer/test/voc.txt create mode 100644 extra/pos/authors.txt create mode 100644 extra/pos/pos.factor create mode 100644 extra/postgresql/authors.txt create mode 100644 extra/postgresql/libpq/libpq.factor create mode 100644 extra/postgresql/postgresql-tests.factor create mode 100644 extra/postgresql/postgresql.factor create mode 100644 extra/promises/authors.txt create mode 100644 extra/promises/promises-docs.factor create mode 100644 extra/promises/promises.factor create mode 100644 extra/promises/summary.txt create mode 100644 extra/promises/tags.txt create mode 100644 extra/qualified/authors.txt create mode 100644 extra/qualified/qualified-docs.factor create mode 100644 extra/qualified/qualified-tests.factor create mode 100644 extra/qualified/qualified.factor create mode 100644 extra/qualified/summary.txt create mode 100644 extra/qualified/tags.txt create mode 100644 extra/random-weighted/authors.txt create mode 100644 extra/random-weighted/random-weighted.factor create mode 100644 extra/random/authors.txt create mode 100644 extra/random/random-docs.factor create mode 100644 extra/random/random-tests.factor create mode 100644 extra/random/random.factor create mode 100644 extra/random/summary.txt create mode 100644 extra/rewrite-closures/authors.txt create mode 100644 extra/rewrite-closures/rewrite-closures.factor create mode 100644 extra/rewrite-closures/summary.txt create mode 100644 extra/rewrite-closures/tags.txt create mode 100644 extra/roman/authors.txt create mode 100644 extra/roman/roman-docs.factor create mode 100644 extra/roman/roman-tests.factor create mode 100644 extra/roman/roman.factor create mode 100644 extra/roman/summary.txt create mode 100644 extra/roman/tags.txt create mode 100644 extra/rot13/authors.txt create mode 100644 extra/rot13/rot13.factor create mode 100644 extra/rot13/summary.txt create mode 100644 extra/rot13/tags.txt create mode 100644 extra/rss/atom.xml create mode 100644 extra/rss/reader/reader.factor create mode 100644 extra/rss/readme.txt create mode 100644 extra/rss/rss-tests.factor create mode 100644 extra/rss/rss.factor create mode 100644 extra/rss/rss1.xml create mode 100644 extra/self/authors.txt create mode 100644 extra/self/self.factor create mode 100644 extra/sequences/lib/authors.txt create mode 100644 extra/sequences/lib/lib-tests.factor create mode 100644 extra/sequences/lib/lib.factor create mode 100644 extra/sequences/lib/tags.txt create mode 100644 extra/sequences/next/authors.txt create mode 100644 extra/sequences/next/next-tests.factor create mode 100644 extra/sequences/next/next.factor create mode 100644 extra/sequences/next/tags.txt create mode 100644 extra/serialize/authors.txt create mode 100644 extra/serialize/serialize-docs.factor create mode 100644 extra/serialize/serialize-tests.factor create mode 100644 extra/serialize/serialize.factor create mode 100644 extra/serialize/summary.txt create mode 100644 extra/shuffle/authors.txt create mode 100644 extra/shuffle/shuffle-docs.factor create mode 100644 extra/shuffle/shuffle-tests.factor create mode 100644 extra/shuffle/shuffle.factor create mode 100644 extra/shuffle/summary.txt create mode 100644 extra/shuffle/tags.txt create mode 100644 extra/shufflers/authors.txt create mode 100644 extra/shufflers/shufflers-docs.factor create mode 100644 extra/shufflers/shufflers-tests.factor create mode 100644 extra/shufflers/shufflers.factor create mode 100644 extra/shufflers/summary.txt create mode 100644 extra/shufflers/tags.txt create mode 100644 extra/slides/authors.txt create mode 100644 extra/slides/slides.factor create mode 100644 extra/smtp/authors.txt create mode 100644 extra/smtp/smtp-server.factor create mode 100644 extra/smtp/smtp-tests.factor create mode 100644 extra/smtp/smtp.factor create mode 100644 extra/smtp/summary.txt create mode 100644 extra/smtp/tags.txt create mode 100644 extra/space-invaders/authors.txt create mode 100644 extra/space-invaders/resources/BaseHit.wav create mode 100644 extra/space-invaders/resources/InvHit.Wav create mode 100644 extra/space-invaders/resources/Shot.wav create mode 100644 extra/space-invaders/resources/Ufo.wav create mode 100644 extra/space-invaders/resources/UfoHit.wav create mode 100644 extra/space-invaders/resources/Walk1.wav create mode 100644 extra/space-invaders/resources/Walk2.wav create mode 100644 extra/space-invaders/resources/Walk3.wav create mode 100644 extra/space-invaders/resources/Walk4.wav create mode 100644 extra/space-invaders/space-invaders-docs.factor create mode 100644 extra/space-invaders/space-invaders.factor create mode 100644 extra/space-invaders/summary.txt create mode 100644 extra/space-invaders/tags.txt create mode 100644 extra/splay-trees/authors.txt create mode 100644 extra/splay-trees/splay-trees-tests.factor create mode 100644 extra/splay-trees/splay-trees.factor create mode 100644 extra/splay-trees/summary.txt create mode 100644 extra/splay-trees/tags.txt create mode 100644 extra/sqlite/lib/lib.factor create mode 100644 extra/sqlite/sqlite-docs.factor create mode 100644 extra/sqlite/sqlite-tests.factor create mode 100644 extra/sqlite/sqlite.factor create mode 100644 extra/sqlite/test.txt create mode 100644 extra/sqlite/tuple-db/tuple-db-docs.factor create mode 100644 extra/sqlite/tuple-db/tuple-db-tests.factor create mode 100644 extra/sqlite/tuple-db/tuple-db.factor create mode 100644 extra/state-machine/state-machine.factor create mode 100644 extra/state-parser/authors.txt create mode 100644 extra/state-parser/state-parser-docs.factor create mode 100644 extra/state-parser/state-parser-tests.factor create mode 100644 extra/state-parser/state-parser.factor create mode 100644 extra/state-parser/summary.txt create mode 100644 extra/store/authors.txt create mode 100644 extra/store/blob/blob.factor create mode 100644 extra/store/store.factor create mode 100644 extra/strings/lib/lib.factor create mode 100644 extra/strings/lib/tags.txt create mode 100644 extra/structs/structs.factor create mode 100644 extra/structs/tags.txt create mode 100644 extra/sudoku/authors.txt create mode 100644 extra/sudoku/sudoku.factor create mode 100644 extra/sudoku/summary.txt create mode 100644 extra/sudoku/tags.txt create mode 100644 extra/tar/tar.factor create mode 100644 extra/tetris/README.txt create mode 100644 extra/tetris/authors.txt create mode 100644 extra/tetris/board/board-tests.factor create mode 100644 extra/tetris/board/board.factor create mode 100644 extra/tetris/deploy.factor create mode 100644 extra/tetris/game/game-tests.factor create mode 100644 extra/tetris/game/game.factor create mode 100644 extra/tetris/gl/gl.factor create mode 100644 extra/tetris/piece/piece-tests.factor create mode 100644 extra/tetris/piece/piece.factor create mode 100644 extra/tetris/summary.txt create mode 100644 extra/tetris/tags.txt create mode 100644 extra/tetris/tetris.factor create mode 100644 extra/tetris/tetromino/tetromino.factor create mode 100644 extra/timers/authors.txt create mode 100644 extra/timers/summary.txt create mode 100644 extra/timers/timers-docs.factor create mode 100644 extra/timers/timers.factor create mode 100644 extra/tools/annotations/annotations-docs.factor create mode 100644 extra/tools/annotations/annotations-tests.factor create mode 100644 extra/tools/annotations/annotations.factor create mode 100644 extra/tools/annotations/authors.txt create mode 100644 extra/tools/annotations/summary.txt create mode 100644 extra/tools/annotations/tags.txt create mode 100644 extra/tools/browser/browser-docs.factor create mode 100644 extra/tools/browser/browser-tests.factor create mode 100644 extra/tools/browser/browser.factor create mode 100644 extra/tools/browser/tags.txt create mode 100644 extra/tools/completion/authors.txt create mode 100644 extra/tools/completion/completion-docs.factor create mode 100644 extra/tools/completion/completion.factor create mode 100644 extra/tools/completion/summary.txt create mode 100644 extra/tools/crossref/authors.txt create mode 100644 extra/tools/crossref/crossref-docs.factor create mode 100644 extra/tools/crossref/crossref-tests.factor create mode 100644 extra/tools/crossref/crossref.factor create mode 100644 extra/tools/crossref/summary.txt create mode 100644 extra/tools/crossref/tags.txt create mode 100644 extra/tools/deploy/app/app.factor create mode 100644 extra/tools/deploy/app/summary.txt create mode 100644 extra/tools/deploy/app/tags.txt create mode 100644 extra/tools/deploy/authors.txt create mode 100644 extra/tools/deploy/deploy-docs.factor create mode 100644 extra/tools/deploy/deploy.factor create mode 100644 extra/tools/deploy/strip-cocoa.factor create mode 100644 extra/tools/deploy/strip-debugger.factor create mode 100644 extra/tools/deploy/summary.txt create mode 100644 extra/tools/deploy/tags.txt create mode 100644 extra/tools/interpreter/authors.txt create mode 100644 extra/tools/interpreter/interpreter-docs.factor create mode 100644 extra/tools/interpreter/interpreter-tests.factor create mode 100644 extra/tools/interpreter/interpreter.factor create mode 100644 extra/tools/interpreter/summary.txt create mode 100644 extra/tools/memory/authors.txt create mode 100644 extra/tools/memory/memory-docs.factor create mode 100644 extra/tools/memory/memory-tests.factor create mode 100644 extra/tools/memory/memory.factor create mode 100644 extra/tools/memory/summary.txt create mode 100644 extra/tools/memory/tags.txt create mode 100644 extra/tools/profiler/authors.txt create mode 100644 extra/tools/profiler/profiler-docs.factor create mode 100644 extra/tools/profiler/profiler-tests.factor create mode 100644 extra/tools/profiler/profiler.factor create mode 100644 extra/tools/profiler/summary.txt create mode 100644 extra/tools/profiler/tags.txt create mode 100644 extra/tools/summary.txt create mode 100644 extra/tools/test/authors.txt create mode 100644 extra/tools/test/foo.factor create mode 100644 extra/tools/test/summary.txt create mode 100644 extra/tools/test/tags.txt create mode 100644 extra/tools/test/test-docs.factor create mode 100644 extra/tools/test/test.factor create mode 100644 extra/tools/test/tools.factor create mode 100644 extra/tools/time/authors.txt create mode 100644 extra/tools/time/summary.txt create mode 100644 extra/tools/time/tags.txt create mode 100644 extra/tools/time/time-docs.factor create mode 100644 extra/tools/time/time.factor create mode 100644 extra/tools/walker/authors.txt create mode 100644 extra/tools/walker/summary.txt create mode 100644 extra/tools/walker/tags.txt create mode 100644 extra/tools/walker/walker.factor create mode 100644 extra/trees/authors.txt create mode 100644 extra/trees/avl-tree/avl-tree-tests.factor create mode 100644 extra/trees/avl-tree/avl-tree.factor create mode 100644 extra/trees/bst/bst-tests.factor create mode 100644 extra/trees/bst/bst.factor create mode 100644 extra/trees/summary.txt create mode 100644 extra/trees/tags.txt create mode 100644 extra/trees/trees.factor create mode 100644 extra/tty-server/authors.txt create mode 100644 extra/tty-server/summary.txt create mode 100644 extra/tty-server/tags.txt create mode 100644 extra/tty-server/tty-server.factor create mode 100644 extra/tuple-arrays/authors.txt create mode 100644 extra/tuple-arrays/summary.txt create mode 100644 extra/tuple-arrays/tags.txt create mode 100644 extra/tuple-arrays/tuple-arrays-docs.factor create mode 100644 extra/tuple-arrays/tuple-arrays-tests.factor create mode 100644 extra/tuple-arrays/tuple-arrays.factor create mode 100644 extra/tuples/lib/authors.txt create mode 100644 extra/tuples/lib/lib-docs.factor create mode 100644 extra/tuples/lib/lib-tests.factor create mode 100644 extra/tuples/lib/lib.factor create mode 100644 extra/turing/authors.txt create mode 100644 extra/turing/summary.txt create mode 100644 extra/turing/tags.txt create mode 100644 extra/turing/turing.factor create mode 100644 extra/turtle/authors.txt create mode 100644 extra/turtle/turtle.factor create mode 100644 extra/ui/authors.txt create mode 100644 extra/ui/backend/authors.txt create mode 100644 extra/ui/backend/backend.factor create mode 100644 extra/ui/backend/summary.txt create mode 100644 extra/ui/clipboards/authors.txt create mode 100644 extra/ui/clipboards/clipboards-docs.factor create mode 100644 extra/ui/clipboards/clipboards.factor create mode 100644 extra/ui/clipboards/summary.txt create mode 100644 extra/ui/cocoa/authors.txt create mode 100644 extra/ui/cocoa/cocoa.factor create mode 100644 extra/ui/cocoa/summary.txt create mode 100644 extra/ui/cocoa/tools/authors.txt create mode 100644 extra/ui/cocoa/tools/summary.txt create mode 100644 extra/ui/cocoa/tools/tools.factor create mode 100644 extra/ui/cocoa/views/authors.txt create mode 100644 extra/ui/cocoa/views/summary.txt create mode 100644 extra/ui/cocoa/views/views.factor create mode 100644 extra/ui/commands/authors.txt create mode 100644 extra/ui/commands/commands-docs.factor create mode 100644 extra/ui/commands/commands-tests.factor create mode 100644 extra/ui/commands/commands.factor create mode 100644 extra/ui/commands/summary.txt create mode 100644 extra/ui/freetype/authors.txt create mode 100644 extra/ui/freetype/freetype-docs.factor create mode 100644 extra/ui/freetype/freetype.factor create mode 100644 extra/ui/freetype/summary.txt create mode 100644 extra/ui/gadgets/authors.txt create mode 100644 extra/ui/gadgets/books/authors.txt create mode 100644 extra/ui/gadgets/books/books-docs.factor create mode 100644 extra/ui/gadgets/books/books.factor create mode 100644 extra/ui/gadgets/books/summary.txt create mode 100644 extra/ui/gadgets/borders/authors.txt create mode 100644 extra/ui/gadgets/borders/borders-docs.factor create mode 100644 extra/ui/gadgets/borders/borders.factor create mode 100644 extra/ui/gadgets/borders/summary.txt create mode 100644 extra/ui/gadgets/buttons/authors.txt create mode 100644 extra/ui/gadgets/buttons/buttons-docs.factor create mode 100644 extra/ui/gadgets/buttons/buttons-tests.factor create mode 100644 extra/ui/gadgets/buttons/buttons.factor create mode 100644 extra/ui/gadgets/buttons/summary.txt create mode 100644 extra/ui/gadgets/canvas/canvas.factor create mode 100644 extra/ui/gadgets/controls/authors.txt create mode 100644 extra/ui/gadgets/controls/controls-docs.factor create mode 100644 extra/ui/gadgets/controls/controls.factor create mode 100644 extra/ui/gadgets/controls/summary.txt create mode 100644 extra/ui/gadgets/editors/authors.txt create mode 100644 extra/ui/gadgets/editors/editors-docs.factor create mode 100644 extra/ui/gadgets/editors/editors-tests.factor create mode 100644 extra/ui/gadgets/editors/editors.factor create mode 100644 extra/ui/gadgets/editors/summary.txt create mode 100644 extra/ui/gadgets/frames/authors.txt create mode 100644 extra/ui/gadgets/frames/frames-docs.factor create mode 100644 extra/ui/gadgets/frames/frames-tests.factor create mode 100644 extra/ui/gadgets/frames/frames.factor create mode 100644 extra/ui/gadgets/frames/summary.txt create mode 100644 extra/ui/gadgets/gadgets-docs.factor create mode 100644 extra/ui/gadgets/gadgets-tests.factor create mode 100644 extra/ui/gadgets/gadgets.factor create mode 100644 extra/ui/gadgets/grid-lines/authors.txt create mode 100644 extra/ui/gadgets/grid-lines/grid-lines-docs.factor create mode 100644 extra/ui/gadgets/grid-lines/grid-lines.factor create mode 100644 extra/ui/gadgets/grid-lines/summary.txt create mode 100644 extra/ui/gadgets/grids/authors.txt create mode 100644 extra/ui/gadgets/grids/grids-docs.factor create mode 100644 extra/ui/gadgets/grids/grids-tests.factor create mode 100644 extra/ui/gadgets/grids/grids.factor create mode 100644 extra/ui/gadgets/grids/summary.txt create mode 100644 extra/ui/gadgets/handler/handler.factor create mode 100644 extra/ui/gadgets/incremental/authors.txt create mode 100644 extra/ui/gadgets/incremental/incremental-docs.factor create mode 100644 extra/ui/gadgets/incremental/incremental.factor create mode 100644 extra/ui/gadgets/incremental/summary.txt create mode 100644 extra/ui/gadgets/labelled/authors.txt create mode 100644 extra/ui/gadgets/labelled/labelled-docs.factor create mode 100644 extra/ui/gadgets/labelled/labelled-tests.factor create mode 100644 extra/ui/gadgets/labelled/labelled.factor create mode 100644 extra/ui/gadgets/labelled/summary.txt create mode 100644 extra/ui/gadgets/labels/authors.txt create mode 100644 extra/ui/gadgets/labels/labels-docs.factor create mode 100644 extra/ui/gadgets/labels/labels.factor create mode 100644 extra/ui/gadgets/labels/summary.txt create mode 100644 extra/ui/gadgets/lib/lib.factor create mode 100644 extra/ui/gadgets/lists/authors.txt create mode 100644 extra/ui/gadgets/lists/lists-docs.factor create mode 100644 extra/ui/gadgets/lists/lists-tests.factor create mode 100644 extra/ui/gadgets/lists/lists.factor create mode 100644 extra/ui/gadgets/lists/summary.txt create mode 100644 extra/ui/gadgets/menus/authors.txt create mode 100644 extra/ui/gadgets/menus/menus-docs.factor create mode 100644 extra/ui/gadgets/menus/menus.factor create mode 100644 extra/ui/gadgets/menus/summary.txt create mode 100644 extra/ui/gadgets/packs/authors.txt create mode 100644 extra/ui/gadgets/packs/packs-docs.factor create mode 100644 extra/ui/gadgets/packs/packs-tests.factor create mode 100644 extra/ui/gadgets/packs/packs.factor create mode 100644 extra/ui/gadgets/packs/summary.txt create mode 100644 extra/ui/gadgets/panes/authors.txt create mode 100644 extra/ui/gadgets/panes/panes-docs.factor create mode 100644 extra/ui/gadgets/panes/panes-tests.factor create mode 100644 extra/ui/gadgets/panes/panes.factor create mode 100644 extra/ui/gadgets/panes/summary.txt create mode 100644 extra/ui/gadgets/paragraphs/authors.txt create mode 100644 extra/ui/gadgets/paragraphs/paragraphs.factor create mode 100644 extra/ui/gadgets/paragraphs/summary.txt create mode 100644 extra/ui/gadgets/presentations/authors.txt create mode 100644 extra/ui/gadgets/presentations/presentations-docs.factor create mode 100644 extra/ui/gadgets/presentations/presentations-tests.factor create mode 100644 extra/ui/gadgets/presentations/presentations.factor create mode 100644 extra/ui/gadgets/presentations/summary.txt create mode 100644 extra/ui/gadgets/scrollers/authors.txt create mode 100644 extra/ui/gadgets/scrollers/scrollers-docs.factor create mode 100644 extra/ui/gadgets/scrollers/scrollers-tests.factor create mode 100644 extra/ui/gadgets/scrollers/scrollers.factor create mode 100644 extra/ui/gadgets/scrollers/summary.txt create mode 100644 extra/ui/gadgets/slate/slate.factor create mode 100644 extra/ui/gadgets/sliders/authors.txt create mode 100644 extra/ui/gadgets/sliders/sliders-docs.factor create mode 100644 extra/ui/gadgets/sliders/sliders.factor create mode 100644 extra/ui/gadgets/sliders/summary.txt create mode 100644 extra/ui/gadgets/slots/authors.txt create mode 100644 extra/ui/gadgets/slots/slots-tests.factor create mode 100644 extra/ui/gadgets/slots/slots.factor create mode 100644 extra/ui/gadgets/slots/summary.txt create mode 100644 extra/ui/gadgets/status-bar/authors.txt create mode 100644 extra/ui/gadgets/status-bar/status-bar-docs.factor create mode 100644 extra/ui/gadgets/status-bar/status-bar.factor create mode 100644 extra/ui/gadgets/status-bar/summary.txt create mode 100644 extra/ui/gadgets/summary.txt create mode 100644 extra/ui/gadgets/theme/authors.txt create mode 100644 extra/ui/gadgets/theme/summary.txt create mode 100644 extra/ui/gadgets/theme/theme.factor create mode 100644 extra/ui/gadgets/tracks/authors.txt create mode 100644 extra/ui/gadgets/tracks/summary.txt create mode 100644 extra/ui/gadgets/tracks/tracks-docs.factor create mode 100644 extra/ui/gadgets/tracks/tracks-tests.factor create mode 100644 extra/ui/gadgets/tracks/tracks.factor create mode 100644 extra/ui/gadgets/viewports/authors.txt create mode 100644 extra/ui/gadgets/viewports/summary.txt create mode 100644 extra/ui/gadgets/viewports/viewports-docs.factor create mode 100644 extra/ui/gadgets/viewports/viewports.factor create mode 100644 extra/ui/gadgets/worlds/authors.txt create mode 100644 extra/ui/gadgets/worlds/summary.txt create mode 100644 extra/ui/gadgets/worlds/worlds-docs.factor create mode 100644 extra/ui/gadgets/worlds/worlds-tests.factor create mode 100644 extra/ui/gadgets/worlds/worlds.factor create mode 100644 extra/ui/gestures/authors.txt create mode 100644 extra/ui/gestures/gestures-docs.factor create mode 100644 extra/ui/gestures/gestures.factor create mode 100644 extra/ui/gestures/summary.txt create mode 100644 extra/ui/operations/authors.txt create mode 100644 extra/ui/operations/operations-docs.factor create mode 100644 extra/ui/operations/operations-tests.factor create mode 100644 extra/ui/operations/operations.factor create mode 100644 extra/ui/operations/summary.txt create mode 100644 extra/ui/render/authors.txt create mode 100644 extra/ui/render/render-docs.factor create mode 100644 extra/ui/render/render.factor create mode 100644 extra/ui/render/summary.txt create mode 100644 extra/ui/summary.txt create mode 100644 extra/ui/tools/authors.txt create mode 100644 extra/ui/tools/browser/authors.txt create mode 100644 extra/ui/tools/browser/browser.factor create mode 100644 extra/ui/tools/browser/summary.txt create mode 100644 extra/ui/tools/browser/tags.txt create mode 100644 extra/ui/tools/debugger/authors.txt create mode 100644 extra/ui/tools/debugger/debugger-docs.factor create mode 100644 extra/ui/tools/debugger/debugger.factor create mode 100644 extra/ui/tools/debugger/summary.txt create mode 100644 extra/ui/tools/debugger/tags.txt create mode 100644 extra/ui/tools/inspector/authors.txt create mode 100644 extra/ui/tools/inspector/inspector.factor create mode 100644 extra/ui/tools/inspector/summary.txt create mode 100644 extra/ui/tools/inspector/tags.txt create mode 100644 extra/ui/tools/interactor/authors.txt create mode 100644 extra/ui/tools/interactor/interactor-docs.factor create mode 100644 extra/ui/tools/interactor/interactor.factor create mode 100644 extra/ui/tools/interactor/summary.txt create mode 100644 extra/ui/tools/listener/authors.txt create mode 100644 extra/ui/tools/listener/listener-tests.factor create mode 100644 extra/ui/tools/listener/listener.factor create mode 100644 extra/ui/tools/listener/summary.txt create mode 100644 extra/ui/tools/listener/tags.txt create mode 100644 extra/ui/tools/operations/authors.txt create mode 100644 extra/ui/tools/operations/operations.factor create mode 100644 extra/ui/tools/operations/summary.txt create mode 100644 extra/ui/tools/profiler/authors.txt create mode 100644 extra/ui/tools/profiler/profiler.factor create mode 100644 extra/ui/tools/profiler/summary.txt create mode 100644 extra/ui/tools/profiler/tags.txt create mode 100644 extra/ui/tools/search/authors.txt create mode 100644 extra/ui/tools/search/search-tests.factor create mode 100644 extra/ui/tools/search/search.factor create mode 100644 extra/ui/tools/search/summary.txt create mode 100644 extra/ui/tools/summary.txt create mode 100644 extra/ui/tools/tags.txt create mode 100644 extra/ui/tools/tools-docs.factor create mode 100644 extra/ui/tools/tools-tests.factor create mode 100644 extra/ui/tools/tools.factor create mode 100644 extra/ui/tools/traceback/authors.txt create mode 100644 extra/ui/tools/traceback/summary.txt create mode 100644 extra/ui/tools/traceback/traceback.factor create mode 100644 extra/ui/tools/walker/authors.txt create mode 100644 extra/ui/tools/walker/summary.txt create mode 100644 extra/ui/tools/walker/tags.txt create mode 100644 extra/ui/tools/walker/walker-tests.factor create mode 100644 extra/ui/tools/walker/walker.factor create mode 100644 extra/ui/tools/workspace/authors.txt create mode 100644 extra/ui/tools/workspace/summary.txt create mode 100644 extra/ui/tools/workspace/tags.txt create mode 100644 extra/ui/tools/workspace/workspace.factor create mode 100644 extra/ui/traverse/authors.txt create mode 100644 extra/ui/traverse/summary.txt create mode 100644 extra/ui/traverse/traverse-tests.factor create mode 100644 extra/ui/traverse/traverse.factor create mode 100644 extra/ui/ui-docs.factor create mode 100644 extra/ui/ui.factor create mode 100644 extra/ui/windows/windows.factor create mode 100644 extra/ui/x11/x11.factor create mode 100644 extra/unicode/PropList.txt create mode 100644 extra/unicode/SpecialCasing.txt create mode 100644 extra/unicode/UnicodeData.txt create mode 100644 extra/unicode/authors.txt create mode 100644 extra/unicode/breaks/breaks-tests.factor create mode 100644 extra/unicode/breaks/breaks.factor create mode 100644 extra/unicode/summary.txt create mode 100644 extra/unicode/unicode-tests.factor create mode 100644 extra/unicode/unicode.factor create mode 100644 extra/units/constants/constants.factor create mode 100644 extra/units/constants/constants.txt create mode 100644 extra/units/imperial/imperial-tests.factor create mode 100644 extra/units/imperial/imperial.factor create mode 100644 extra/units/si/si-tests.factor create mode 100644 extra/units/si/si.factor create mode 100644 extra/units/units-tests.factor create mode 100644 extra/units/units.factor create mode 100644 extra/unix/authors.txt create mode 100644 extra/unix/bsd/authors.txt create mode 100644 extra/unix/bsd/bsd.factor create mode 100644 extra/unix/bsd/summary.txt create mode 100644 extra/unix/linux/linux.factor create mode 100644 extra/unix/solaris/solaris.factor create mode 100644 extra/unix/summary.txt create mode 100644 extra/unix/tags.txt create mode 100644 extra/unix/unix.factor create mode 100644 extra/vars/authors.txt create mode 100644 extra/vars/summary.txt create mode 100644 extra/vars/tags.txt create mode 100644 extra/vars/vars.factor create mode 100644 extra/visitor/authors.txt create mode 100644 extra/visitor/summary.txt create mode 100644 extra/visitor/tags.txt create mode 100644 extra/visitor/visitor-tests.factor create mode 100644 extra/visitor/visitor.factor create mode 100644 extra/webapps/article-manager/article-manager-docs.factor create mode 100644 extra/webapps/article-manager/article-manager.factor create mode 100644 extra/webapps/article-manager/authors.txt create mode 100644 extra/webapps/article-manager/database/database.factor create mode 100644 extra/webapps/article-manager/furnace/article.furnace create mode 100644 extra/webapps/article-manager/furnace/edit-article.furnace create mode 100644 extra/webapps/article-manager/furnace/edit-head.furnace create mode 100644 extra/webapps/article-manager/furnace/head.furnace create mode 100644 extra/webapps/article-manager/furnace/index.furnace create mode 100644 extra/webapps/article-manager/furnace/navigation.furnace create mode 100644 extra/webapps/article-manager/furnace/setup-site.furnace create mode 100644 extra/webapps/article-manager/furnace/tag.furnace create mode 100644 extra/webapps/article-manager/furnace/tags.furnace create mode 100644 extra/webapps/article-manager/load.factor create mode 100644 extra/webapps/article-manager/resources/jquery.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-blue.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-blue2.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-brown.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-green.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-setup.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-setup_stripped.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-system.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-tas.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-win2k-1.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-win2k-2.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-win2k-cold-1.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar-win2k-cold-2.css create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/calendar_stripped.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-af.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-al.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-bg.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-big5-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-big5.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-br.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-ca.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-cs-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-cs-win.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-da.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-de.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-du.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-el.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-en.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-es.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-fi.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-fr.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-he-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-hr-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-hr.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-hu.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-it.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-jp.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-ko-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-ko.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-lt-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-lt.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-lv.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-nl.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-no.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-pl-utf8.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-pl.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-pt.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-ro.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-ru.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-ru_win_.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-si.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-sk.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-sp.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-sv.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-tr.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/calendar-zh.js create mode 100644 extra/webapps/article-manager/resources/jscalendar-1.0/lang/cn_utf8.js create mode 100644 extra/webapps/article-manager/resources/style.css create mode 100644 extra/webapps/article-manager/resources/wiky.css create mode 100644 extra/webapps/article-manager/resources/wiky.js create mode 100644 extra/webapps/article-manager/resources/wiky.lang.css create mode 100644 extra/webapps/article-manager/resources/wiky.lang.js create mode 100644 extra/webapps/article-manager/resources/wiky.math.css create mode 100644 extra/webapps/article-manager/resources/wiky.math.js create mode 100644 extra/webapps/article-manager/summary.txt create mode 100644 extra/webapps/article-manager/tags.txt create mode 100644 extra/webapps/fjsc/authors.txt create mode 100644 extra/webapps/fjsc/fjsc.factor create mode 100644 extra/webapps/fjsc/head.furnace create mode 100644 extra/webapps/fjsc/repl.furnace create mode 100644 extra/webapps/fjsc/resources/repl.js create mode 100644 extra/webapps/fjsc/resources/termlib/faq.html create mode 100644 extra/webapps/fjsc/resources/termlib/index.html create mode 100644 extra/webapps/fjsc/resources/termlib/multiterm_test.html create mode 100644 extra/webapps/fjsc/resources/termlib/parser_sample.html create mode 100644 extra/webapps/fjsc/resources/termlib/readme.txt create mode 100644 extra/webapps/fjsc/resources/termlib/term_styles.css create mode 100644 extra/webapps/fjsc/resources/termlib/termlib.js create mode 100644 extra/webapps/fjsc/resources/termlib/termlib_parser.js create mode 100644 extra/webapps/fjsc/summary.txt create mode 100644 extra/webapps/fjsc/tags.txt create mode 100644 extra/webapps/help/help.factor create mode 100644 extra/windows/advapi32/advapi32.factor create mode 100644 extra/windows/authors.txt create mode 100644 extra/windows/ce/ce.factor create mode 100644 extra/windows/errors/errors.factor create mode 100644 extra/windows/gdi32/gdi32.factor create mode 100644 extra/windows/kernel32/kernel32.factor create mode 100644 extra/windows/messages/messages.factor create mode 100644 extra/windows/nt/nt.factor create mode 100644 extra/windows/opengl32/opengl32.factor create mode 100644 extra/windows/summary.txt create mode 100644 extra/windows/tags.txt create mode 100644 extra/windows/types/types.factor create mode 100644 extra/windows/user32/user32.factor create mode 100644 extra/windows/windows.factor create mode 100644 extra/windows/winsock/winsock.factor create mode 100644 extra/x/authors.txt create mode 100644 extra/x/font/font.factor create mode 100644 extra/x/gc/gc.factor create mode 100644 extra/x/keysym-table/keysym-table.factor create mode 100644 extra/x/pen/pen.factor create mode 100644 extra/x/widgets/button/button.factor create mode 100644 extra/x/widgets/keymenu/keymenu.factor create mode 100644 extra/x/widgets/label/label.factor create mode 100644 extra/x/widgets/widgets.factor create mode 100644 extra/x/widgets/wm/child/child.factor create mode 100644 extra/x/widgets/wm/frame/drag/drag.factor create mode 100644 extra/x/widgets/wm/frame/drag/move/move.factor create mode 100644 extra/x/widgets/wm/frame/drag/size/size.factor create mode 100644 extra/x/widgets/wm/frame/frame.factor create mode 100644 extra/x/widgets/wm/menu/menu.factor create mode 100644 extra/x/widgets/wm/root/root.factor create mode 100644 extra/x/widgets/wm/unmapped-frames-menu/unmapped-frames-menu.factor create mode 100644 extra/x/widgets/wm/workspace/workspace.factor create mode 100644 extra/x/x.factor create mode 100644 extra/x11/clipboard/authors.txt create mode 100644 extra/x11/clipboard/clipboard.factor create mode 100644 extra/x11/clipboard/summary.txt create mode 100644 extra/x11/constants/authors.txt create mode 100644 extra/x11/constants/constants.factor create mode 100644 extra/x11/constants/summary.txt create mode 100644 extra/x11/events/authors.txt create mode 100644 extra/x11/events/events.factor create mode 100644 extra/x11/events/summary.txt create mode 100644 extra/x11/glx/authors.txt create mode 100644 extra/x11/glx/glx.factor create mode 100644 extra/x11/glx/summary.txt create mode 100644 extra/x11/glx/tags.txt create mode 100644 extra/x11/summary.txt create mode 100644 extra/x11/tags.txt create mode 100644 extra/x11/windows/authors.txt create mode 100644 extra/x11/windows/summary.txt create mode 100644 extra/x11/windows/windows.factor create mode 100644 extra/x11/xim/authors.txt create mode 100644 extra/x11/xim/summary.txt create mode 100644 extra/x11/xim/tags.txt create mode 100644 extra/x11/xim/xim.factor create mode 100644 extra/x11/xlib/authors.txt create mode 100644 extra/x11/xlib/summary.txt create mode 100644 extra/x11/xlib/tags.txt create mode 100644 extra/x11/xlib/xlib.factor create mode 100644 extra/xml-rpc/authors.txt create mode 100644 extra/xml-rpc/example.factor create mode 100644 extra/xml-rpc/summary.txt create mode 100644 extra/xml-rpc/tags.txt create mode 100644 extra/xml-rpc/xml-rpc-docs.factor create mode 100644 extra/xml-rpc/xml-rpc-tests.factor create mode 100644 extra/xml-rpc/xml-rpc.factor create mode 100644 extra/xml/authors.txt create mode 100644 extra/xml/char-classes/char-classes.factor create mode 100644 extra/xml/data/data.factor create mode 100644 extra/xml/entities/entities.factor create mode 100644 extra/xml/errors/errors.factor create mode 100644 extra/xml/generator/generator-tests.factor create mode 100644 extra/xml/generator/generator.factor create mode 100644 extra/xml/summary.txt create mode 100644 extra/xml/tags.txt create mode 100644 extra/xml/test/arithmetic.factor create mode 100644 extra/xml/test/errors.factor create mode 100644 extra/xml/test/soap.factor create mode 100644 extra/xml/test/soap.xml create mode 100644 extra/xml/test/templating.factor create mode 100644 extra/xml/test/test.factor create mode 100644 extra/xml/test/test.xml create mode 100644 extra/xml/tokenize/tokenize.factor create mode 100644 extra/xml/utilities/utilities.factor create mode 100644 extra/xml/writer/writer.factor create mode 100644 extra/xml/xml-docs.factor create mode 100644 extra/xml/xml-tests.factor create mode 100644 extra/xml/xml.factor create mode 100644 extra/yahoo/authors.txt create mode 100644 extra/yahoo/summary.txt create mode 100644 extra/yahoo/tags.txt create mode 100644 extra/yahoo/test-results.xml create mode 100644 extra/yahoo/yahoo-docs.factor create mode 100644 extra/yahoo/yahoo-tests.factor create mode 100644 extra/yahoo/yahoo.factor create mode 100644 fonts/Vera.ttf create mode 100644 fonts/VeraBI.ttf create mode 100644 fonts/VeraBd.ttf create mode 100644 fonts/VeraIt.ttf create mode 100644 fonts/VeraMoBI.ttf create mode 100644 fonts/VeraMoBd.ttf create mode 100644 fonts/VeraMoIt.ttf create mode 100644 fonts/VeraMono.ttf create mode 100644 fonts/VeraSe.ttf create mode 100644 fonts/VeraSeBd.ttf create mode 100644 license.txt create mode 100644 misc/Factor.tmbundle/Syntaxes/Factor.tmLanguage create mode 100644 misc/Factor.tmbundle/Syntaxes/HTML (Factor).tmLanguage create mode 100644 misc/Factor.tmbundle/info.plist create mode 100644 misc/factor.el create mode 100644 misc/factor.vim create mode 100644 misc/factor.vim.fgen create mode 100644 misc/graphics/bmps/1bit.bmp create mode 100644 misc/graphics/bmps/rgb4bit.bmp create mode 100644 misc/graphics/bmps/rgb8bit.bmp create mode 100644 misc/graphics/bmps/thiswayup24.bmp create mode 100644 misc/icons/FRaptorMix.ico create mode 100644 misc/icons/FRaptorMix_128x128.png create mode 100644 misc/icons/FRaptorMix_16x16.png create mode 100644 misc/icons/FRaptorMix_32x32.png create mode 100644 misc/icons/FRaptorMix_48x48.png create mode 100644 misc/icons/license.txt create mode 100644 misc/integration/macosx-deploy.factor create mode 100644 misc/integration/macosx.sh create mode 100644 misc/integration/test.sh create mode 100644 misc/integration/unix-arm.sh create mode 100644 misc/integration/unix-ppc.sh create mode 100644 misc/integration/unix-x86.32.sh create mode 100644 misc/integration/unix-x86.64.sh create mode 100644 misc/integration/x11-deploy.factor create mode 100644 misc/macos-release.sh create mode 100644 misc/windows-release.sh create mode 100644 unmaintained/README.libs.txt create mode 100644 unmaintained/README.txt create mode 100644 unmaintained/alarms/alarms.factor create mode 100644 unmaintained/alarms/load.factor create mode 100644 unmaintained/enchilada/authors.txt create mode 100644 unmaintained/enchilada/enchilada-tests.factor create mode 100644 unmaintained/enchilada/enchilada.factor create mode 100644 unmaintained/enchilada/engine/engine.factor create mode 100644 unmaintained/enchilada/parser/parser.factor create mode 100644 unmaintained/enchilada/printer/printer.factor create mode 100644 unmaintained/enchilada/summary.txt create mode 100644 unmaintained/enchilada/tags.txt create mode 100644 unmaintained/factorbot.factor create mode 100644 unmaintained/farkup/farkup.factor create mode 100644 unmaintained/farkup/farkup.facts create mode 100644 unmaintained/farkup/farkup.list create mode 100644 unmaintained/farkup/load.factor create mode 100644 unmaintained/furnace-onigiri/load.factor create mode 100644 unmaintained/furnace-onigiri/onigiri.factor create mode 100644 unmaintained/furnace-onigiri/onigiri.facts create mode 100644 unmaintained/furnace-onigiri/onigiri.todo create mode 100644 unmaintained/furnace-onigiri/resources/onigirihouse.css create mode 100644 unmaintained/furnace-onigiri/resources/wiky/wiky.css create mode 100644 unmaintained/furnace-onigiri/resources/wiky/wiky.js create mode 100644 unmaintained/furnace-onigiri/resources/wiky/wiky.lang.css create mode 100644 unmaintained/furnace-onigiri/resources/wiky/wiky.lang.js create mode 100644 unmaintained/furnace-onigiri/resources/wiky/wiky.math.css create mode 100644 unmaintained/furnace-onigiri/resources/wiky/wiky.math.js create mode 100644 unmaintained/furnace-onigiri/templates/atom.furnace create mode 100644 unmaintained/furnace-onigiri/templates/entry-edit-plain.furnace create mode 100644 unmaintained/furnace-onigiri/templates/entry-edit.furnace create mode 100644 unmaintained/furnace-onigiri/templates/entry-show.furnace create mode 100644 unmaintained/furnace-onigiri/templates/footer.furnace create mode 100644 unmaintained/furnace-onigiri/templates/header.furnace create mode 100644 unmaintained/furnace-onigiri/templates/sitemap.furnace create mode 100644 unmaintained/furnace-pastebin/annotate-paste.furnace create mode 100644 unmaintained/furnace-pastebin/annotation.furnace create mode 100644 unmaintained/furnace-pastebin/load.factor create mode 100644 unmaintained/furnace-pastebin/new-paste.furnace create mode 100644 unmaintained/furnace-pastebin/paste-list.furnace create mode 100644 unmaintained/furnace-pastebin/paste-summary.furnace create mode 100644 unmaintained/furnace-pastebin/pastebin.factor create mode 100644 unmaintained/furnace-pastebin/show-paste.furnace create mode 100644 unmaintained/heap/heap.factor create mode 100644 unmaintained/heap/heap.facts create mode 100644 unmaintained/heap/human tests.factor create mode 100644 unmaintained/heap/load.factor create mode 100644 unmaintained/heap/print.factor create mode 100644 unmaintained/heap/tests.factor create mode 100644 unmaintained/io/io.factor create mode 100644 unmaintained/io/load.factor create mode 100644 unmaintained/io/os-unix-shell.factor create mode 100644 unmaintained/io/os-unix.factor create mode 100644 unmaintained/io/os-winnt-shell.factor create mode 100644 unmaintained/io/os-winnt.factor create mode 100644 unmaintained/io/shell.factor create mode 100644 unmaintained/io/test/io.factor create mode 100644 unmaintained/io/test/mmap.factor create mode 100644 unmaintained/irc/irc-client.factor create mode 100644 unmaintained/irc/load.factor create mode 100644 unmaintained/isequences/authors.txt create mode 100644 unmaintained/isequences/base/base.factor create mode 100644 unmaintained/isequences/interface/interface-docs.factor create mode 100644 unmaintained/isequences/interface/interface.factor create mode 100644 unmaintained/isequences/isequences-tests.factor create mode 100644 unmaintained/isequences/isequences.factor create mode 100644 unmaintained/isequences/ops/cache/cache.factor create mode 100644 unmaintained/isequences/ops/divide/divide.factor create mode 100644 unmaintained/isequences/ops/iota/iota.factor create mode 100644 unmaintained/isequences/ops/match/match.factor create mode 100644 unmaintained/isequences/ops/maximum/maximum.factor create mode 100644 unmaintained/isequences/ops/minimum/minimum.factor create mode 100644 unmaintained/isequences/ops/modulus/modulus.factor create mode 100644 unmaintained/isequences/ops/multiply/multiply.factor create mode 100644 unmaintained/isequences/ops/ops.factor create mode 100644 unmaintained/isequences/ops/sort/sort.factor create mode 100644 unmaintained/isequences/ops/wipe/wipe.factor create mode 100644 unmaintained/isequences/summary.txt create mode 100644 unmaintained/isequences/tags.txt create mode 100644 unmaintained/jni/jni-internals.factor create mode 100644 unmaintained/jni/jni.factor create mode 100644 unmaintained/jni/load.factor create mode 100644 unmaintained/lambda/TODO.txt create mode 100644 unmaintained/lambda/core.factor create mode 100644 unmaintained/lambda/lambda.factor create mode 100644 unmaintained/lambda/load.factor create mode 100644 unmaintained/lambda/nodes.factor create mode 100644 unmaintained/lambda/parser.factor create mode 100644 unmaintained/lambda/test/lambda.factor create mode 100644 unmaintained/mysql/libmysql.factor create mode 100644 unmaintained/mysql/load.factor create mode 100644 unmaintained/mysql/mysql.factor create mode 100644 unmaintained/mysql/test/create_database.sql create mode 100644 unmaintained/mysql/test/mysql-example.factor create mode 100644 unmaintained/random-tester/load.factor create mode 100644 unmaintained/random-tester/random-tester.factor create mode 100644 unmaintained/random-tester/random-tester2.factor create mode 100644 unmaintained/random-tester/random.factor create mode 100644 unmaintained/random-tester/type.factor create mode 100644 unmaintained/random-tester/utils.factor create mode 100644 unmaintained/regexp/load.factor create mode 100644 unmaintained/regexp/regexp.factor create mode 100644 unmaintained/regexp/tables.factor create mode 100644 unmaintained/regexp/test/regexp.factor create mode 100644 unmaintained/regexp/test/tables.factor create mode 100644 unmaintained/usb/load.factor create mode 100644 unmaintained/usb/usb-common.factor create mode 100644 unmaintained/usb/usb-macosx.factor create mode 100644 unmaintained/usb/usb-unix.factor create mode 100644 unmaintained/usb/usb-win32.factor create mode 100644 unmaintained/usb/usb.factor create mode 100644 unmaintained/usb/usb.facts create mode 100644 unmaintained/wee-url/load.factor create mode 100644 unmaintained/wee-url/responder.factor create mode 100644 unmaintained/wee-url/wee-url.factor create mode 100644 vm/Config.amd64 create mode 100644 vm/Config.arm create mode 100644 vm/Config.freebsd create mode 100644 vm/Config.freebsd.amd64 create mode 100644 vm/Config.freebsd.x86 create mode 100644 vm/Config.linux create mode 100644 vm/Config.linux.amd64 create mode 100644 vm/Config.linux.arm create mode 100644 vm/Config.linux.ppc create mode 100644 vm/Config.linux.x86 create mode 100644 vm/Config.macosx create mode 100644 vm/Config.macosx.ppc create mode 100644 vm/Config.macosx.x86 create mode 100644 vm/Config.openbsd create mode 100644 vm/Config.openbsd.amd64 create mode 100644 vm/Config.openbsd.x86 create mode 100644 vm/Config.ppc create mode 100644 vm/Config.solaris create mode 100644 vm/Config.solaris.amd64 create mode 100644 vm/Config.solaris.x86 create mode 100644 vm/Config.unix create mode 100644 vm/Config.windows create mode 100644 vm/Config.windows.ce create mode 100644 vm/Config.windows.ce.arm create mode 100644 vm/Config.windows.ce.x86 create mode 100644 vm/Config.windows.nt.x86 create mode 100644 vm/Config.x86 create mode 100644 vm/alien.c create mode 100644 vm/alien.h create mode 100644 vm/asm.h create mode 100644 vm/bignum.c create mode 100644 vm/bignum.h create mode 100644 vm/bignumint.h create mode 100644 vm/code_gc.c create mode 100644 vm/code_gc.h create mode 100644 vm/compiler.c create mode 100644 vm/compiler.h create mode 100644 vm/cpu-amd64.S create mode 100644 vm/cpu-amd64.h create mode 100644 vm/cpu-arm.S create mode 100644 vm/cpu-arm.h create mode 100644 vm/cpu-ppc.S create mode 100644 vm/cpu-ppc.h create mode 100644 vm/cpu-x86.S create mode 100644 vm/cpu-x86.h create mode 100644 vm/data_gc.c create mode 100644 vm/data_gc.h create mode 100644 vm/debug.c create mode 100644 vm/debug.h create mode 100644 vm/factor.c create mode 100644 vm/factor.h create mode 100644 vm/factor.rs create mode 100644 vm/ffi_test.c create mode 100644 vm/ffi_test.h create mode 100644 vm/float_bits.h create mode 100644 vm/image.c create mode 100644 vm/image.h create mode 100644 vm/io.c create mode 100644 vm/io.h create mode 100644 vm/jit.c create mode 100644 vm/jit.h create mode 100644 vm/layouts.h create mode 100644 vm/mach_signal.c create mode 100644 vm/mach_signal.h create mode 100644 vm/main-unix.c create mode 100644 vm/main-windows-ce.c create mode 100644 vm/main-windows-nt.c create mode 100644 vm/master.h create mode 100644 vm/math.c create mode 100644 vm/math.h create mode 100644 vm/os-freebsd.c create mode 100644 vm/os-freebsd.h create mode 100644 vm/os-genunix.c create mode 100644 vm/os-genunix.h create mode 100644 vm/os-linux-arm.h create mode 100644 vm/os-linux-ppc.h create mode 100644 vm/os-linux.c create mode 100644 vm/os-linux.h create mode 100644 vm/os-macosx-ppc.h create mode 100644 vm/os-macosx-x86.h create mode 100644 vm/os-macosx.h create mode 100644 vm/os-macosx.m create mode 100644 vm/os-openbsd-amd64.h create mode 100644 vm/os-openbsd-x86.h create mode 100644 vm/os-openbsd.c create mode 100644 vm/os-openbsd.h create mode 100644 vm/os-solaris.c create mode 100644 vm/os-solaris.h create mode 100644 vm/os-unix-ucontext.h create mode 100644 vm/os-unix.c create mode 100644 vm/os-unix.h create mode 100644 vm/os-windows-ce-arm.S create mode 100644 vm/os-windows-ce.c create mode 100644 vm/os-windows-ce.h create mode 100644 vm/os-windows-nt.c create mode 100644 vm/os-windows-nt.h create mode 100644 vm/os-windows.c create mode 100644 vm/os-windows.h create mode 100644 vm/platform.h create mode 100644 vm/primitives.c create mode 100644 vm/primitives.h create mode 100644 vm/run.c create mode 100644 vm/run.h create mode 100644 vm/stack.c create mode 100644 vm/stack.h create mode 100644 vm/types.c create mode 100644 vm/types.h create mode 100644 vm/utilities.c create mode 100644 vm/utilities.h diff --git a/Factor.app/Contents/Frameworks/libfreetype.6.dylib b/Factor.app/Contents/Frameworks/libfreetype.6.dylib new file mode 100644 index 0000000000000000000000000000000000000000..5147d44386743c9718fb813f9bd15696d04ee79a GIT binary patch literal 683652 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 X)D@KFth%EE&PHg@oLA)hZIJ%~lHpCQ literal 0 HcmV?d00001 diff --git a/Factor.app/Contents/Info.plist b/Factor.app/Contents/Info.plist new file mode 100644 index 0000000000..c54acd7179 --- /dev/null +++ b/Factor.app/Contents/Info.plist @@ -0,0 +1,74 @@ + + + + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + * + + CFBundleTypeName + Any + CFBundleTypeOSTypes + + **** + + CFBundleTypeRole + Viewer + + + CFBundleExecutable + factor + CFBundleIconFile + FRaptorMix.icns + CFBundleIdentifier + org.factorcode.Factor + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Factor + CFBundlePackageType + APPL + NSHumanReadableCopyright + Copyright © 2003-2007, Slava Pestov and friends + NSServices + + + NSMenuItem + + default + Factor/Evaluate in Listener + + NSMessage + evalInListener + NSPortName + Factor + NSSendTypes + + NSStringPboardType + + + + NSMenuItem + + default + Factor/Evaluate Selection + + NSMessage + evalToString + NSPortName + Factor + NSReturnTypes + + NSStringPboardType + + NSSendTypes + + NSStringPboardType + + + + + diff --git a/Factor.app/Contents/PkgInfo b/Factor.app/Contents/PkgInfo new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Factor.app/Contents/Resources/English.lproj/Factor.nib/classes.nib b/Factor.app/Contents/Resources/English.lproj/Factor.nib/classes.nib new file mode 100644 index 0000000000..bf3d2a6560 --- /dev/null +++ b/Factor.app/Contents/Resources/English.lproj/Factor.nib/classes.nib @@ -0,0 +1,17 @@ +{ + IBClasses = ( + { + ACTIONS = { + newFactorWorkspace = id; + runFactorFile = id; + saveFactorImage = id; + saveFactorImageAs = id; + showFactorHelp = id; + }; + CLASS = FirstResponder; + LANGUAGE = ObjC; + SUPERCLASS = NSObject; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/Factor.app/Contents/Resources/English.lproj/Factor.nib/info.nib b/Factor.app/Contents/Resources/English.lproj/Factor.nib/info.nib new file mode 100644 index 0000000000..8e4b9eeba8 --- /dev/null +++ b/Factor.app/Contents/Resources/English.lproj/Factor.nib/info.nib @@ -0,0 +1,21 @@ + + + + + IBDocumentLocation + 557 119 525 491 0 0 2560 1578 + IBEditorPositions + + 29 + 326 905 270 44 0 0 2560 1578 + + IBFramework Version + 439.0 + IBOpenObjects + + 29 + + IBSystem Version + 8R218 + + diff --git a/Factor.app/Contents/Resources/English.lproj/Factor.nib/keyedobjects.nib b/Factor.app/Contents/Resources/English.lproj/Factor.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..8dfebba5669ffdf8e672731f7d51c4dd3320621d GIT binary patch literal 11126 zcma)C349YpxSyHKrn$38H|HkVKp9{S1mb+bVxrexogwdZF#{+km0p9oQ{mhgj%3Bs6BcBbwfSTL#Qt*K@l_=O-E0m z8R%Iw8_hw_qZiO3v;-|jE77ayEwm23jW(doXeasz?L{A>{pc_{ijJX^=sR>C{e&){ zpV1Zc2aIl@n;2sq)?)**ITHV|*`ehFjqdxFha_yWnp4A>14H!KpYM z560Oz2M@=2coZ(e#kdSd@HjjkPrwXM#?$drcm{q3&%q1v3wRM;ieJI2@M`=zUXS0w z8}R#hC*FfU!h7+@_*47^{t`xC;S=}=d>Te)@OgX%{|ck4_;-Q`CWL5606)Q19;V6BjM9WP<6%5rGePq>Sp=i$(PFfi%BX_YqIGEl`WXF;eonujU(&DWQF@FXrzhx1 z`ZfKAeoIf$@96jR2YQ;Gp+C~I^c+1;f1(%Y&-5bwgY@6m0cwaEp?gqcbT4XxnxbZ?c{EK@V=0pr zEUE}W;&}R|C*|gb!r{UZg++ytvE52bN+6|5%VSB^ttc1{hr+SD2lq`+EzAo;qJ@X_ zP462l4n@bq`leUkrv7p_r20$@U}y{=&dv8t&ng7sqR@cClDyK<;jFs3DxV4%69Y0` zokgi)PrO3%}V<527-DbKXF2MFQcxFgQe1{mBohP(MPg5;qT;o@AN50Ns6R?a z87LEFp#f+h8iWR;A!sNXhO$u(8jgZ!1jd*h4IpWw1dkn~h)(vyrTfRj^0dL^hc{$!4-SY(87eRvbp9AbS~l1eK%k zfWGN{f+Ipjs&z^$%5y`^$z06%C8|J`Xfzsw#-c~jIJkd2nt&cd6A?oSdK^sxf2V{> zD!?@^?25%k90oM4_s?r_%K0iK6I71qld70eEz={xNGJyW zB3ir*YHAm-MO=$m;4f7JF0m|B{%~n|v8qlmQc(^Xb%=-k3iQ%)^b&em70UspC>#O# z9Vss@s;M@hZR~2S_{81)3b=bU^MQ9g|K;5^;N7*VcbSQK!2zP`fE?c5Rn0;Wf-vbG3P%b{Vi`tSs;0YBpaUS#Ax2nz5TWiD(K!Dr%2feAtFeN_>cy=vG-*U>MVux^a$Hs3Us|3Q zDvv4-?k&j+mghz9>=!Hv75#(x8(=;K%#DG$;lC^Y13C@tKgN`|!?J`}BM{*p)dE8v zEX)hZsgVL`+tLbhcxM63qtiR8W4Obey8Z%;mw~Z4FgE#j#>dcAV7yjs?xsN2>@TvI zRWnthzv13O};6{)ct49kN`E98u^ zWuY8C5Gl>iFAAx7R9I3`S`m)k7JUNl?GP8p2Lc6H7Z9l9-2%x`fodU!>qJf2iFF2n z?pIA27pMUU)QBAhfsSN!D=izFmK%*D+yu4D%!N5bOPs1XP_<;;fhy^4s+jI=fU0ej zsx9jZRNYjn?7yp-)-lG=8MVvKRjXTE|2wE20IIGm8K`>RO%>Cs2T=8@)~Xj!J*ZM; z_6vq1p|r{vLken_Ri<9J1Gyg{_h)?px%b`38Bu#>);O>aOZle*hk(6?v9G{hM~9`u z7De@5aFp5)z$#r9pVYV~2z0qD9q9VqO&3$-VNj%?T9GuM>#r&Tl|7O+CZ<%kyneF+NzdhXrmF$I>_ zpm$<bM5+ zT|nH(N&#`ySO4sD@Fu)D8k$?c#@kdI;~mhrWd!qC5i17l64ll`jwkgl2+|MP>ky=C zL$LW(U7ZK6emIABRa5tbemv^qq+GRqt&w6MNU@(qK#E8HTZ)4q#o?$Fp96n6@Q0)P zWRMCgtIc;>emruH0^)Ht77#1{8}VyE{5FdCJs^$-#4%As&9Eq9zw%IJA(X(hUUAeP z0rebv3{c1YH|hmIy%8gs_+1=0Qlo7IP_o-RTP)0JxL9G+DKTEb3-Mt_}5%ZE~(xbC6$MQaq|<3 z%88au1J)^bu@apc0z?l>oH5E;#ij!56Dn)90Dqo}Ujnr-2-}GeY^#$|F^u!0<0KRYZPKB^{0C!FxP}v!C(@O@ z2%HP<=IkDI6D&_8wmdClF97GFJKfY9+?2xBgPYzN64Ob3FjQ2Qrfv|`5*)jxUaFz& z50n{fIZ!USi!xSl$N-=m6jjs2mICE6l`^wiQE51oHhNff;zy@Y^I@|}hLhlO5+oy{ z+sx`MVG^{>V__E({f=%6Ngi3amcI{;CvK8Y3UF6+nT$f4@P5)Aj`7M!S4fA|B!aD^ z5-%ZR@Nv8mn{j^}CK+TR(Gmqu!n4U_bcj^pT=E3b;d7)uX-#I}3>3yK$t*0RQ)CXA zi`S5O_&N@tEzs#tXRoq1SWni3y}|&K3tPeA?B=#BW#2T^>+2<^u?PZL0WD+|S zU6#lqXcl6p6xADPvIG^sL{u5qfWE7N!3a;i0{koPDmmnp>aFP7c+n?oVSAArP7jp@ z%Y(290F^}WNp$m~&(7(aUVS2>ZnR?Fcnei5gIwxzG*mj6Mt$xt{jZ?nC2R$x9(X1GwCa{>?Nv9BYq0|d@N;Z82!1AOW7|@)77h%O!`%zR z>ak892n3GSS9`if3Jul}G)+U&t@YOHYlP1H{R zm#EdnCPPzMBkDL1v=95DM$|8}Aj3ns1+jp63>7cKvteJA1GP9F6#wQKG+r~M2J=Z! z-^7mBV4nD2>_)n4p00UtHaxhHeO>e5H$xyWQi6pgYFtE%spdH{Vwt+I#pHWFx`IX5 z9vQ#BxcvdDeqH9klFj^-FVH5mU1nDWk-$L+}I)4KWDmp>b6v1Cx zFl}47ss`$YsG-$6)!5hysa*tDt6=mw+|d@U9f;y|ir!xY^X=*i1_!^IgQ}JS8AV!S zGir`Dsggo4kAY|%4?1dLH7yo{gWVF5+uL^ zsMc-c=s!l$HD@*FH0L!xX)b7fhVd_&OYnI`^Q-2n<~PkX&2^Za)!fkBWT)8~_9HvX z&av|_{)t_H&!5>Z>=L`ouCQNWcA8yfzg4fk@a8SL96{t$jM}BaY|?C!n>FOaDJ+O$DVh?BQ4|4i!f;)p9Emi;%_p77~lh1n=D*XZ82K!j&VcPdKoAU zABTRTKlDpFoEwe8Q8)}o?ETPZ zJ_ijZZj^~zq9IUE0uajxXOQk_7<6#gNqrQA+ENL}_?6J@^oCxi3hIm+!Sf*&+Q0#S zDwO{QP;owoqx(l8%BR5L{Q~G2>cXN>1Ti!c4)mXdsM!d|{Bz+2z#e!7PzR!HI~@Aw zL%iic{2zeB{{Y0_NvK_Z=&Lrc$xz2y!16K(dXG-fdyHV&@Zw-PyhccZ*9SeJ((Pp} zAxjp*i-axEnLNWDh8W!%xAerQbt$6?eVk6Blj#&%MW@my=rsByolc*kGw9QFCVhs^ zqR-OVbPkng6#@URIs36hk~67b}87cV2^^m3KkXYQ?Osb0R>A6mK9t}!L=1! zN5OR!Tu;IE72H6<4Heu-!S^V*v4Zbaa1#YLRd6!}H&<{A1-DdiD+RY!a2o~Rr{J~< zZl~b(3htobjtcIi;LZxZU%_1z{D6X!6x>z8-4xti!95h*Q^CCy{Gfu975tEbdn>q) zf>RXSm!0Ap@SpK6eh1I-Y5a$Ld){rsR(>CUlCQ^q&sXu!@}KjEZP?8J$|v&uZJ6gv z`Gb51einb6PvtM!u*HT={2u;s{xaW>|AwE-f6G73x8twy7x`oSPW~wW6@Qg~f*;D~ z^Sk-!Hf-Q0*|3q{%g^V3;(z21@SpG}`1AZ({uKWp|2+Q@{~iA^zl%@jpW~14Bl*+( zGyEaGH~$O&CGU^sGuH^IywOYotif*EkyT;zrb%*~G0qNlN zZ5?$3vLV6N}^AixrPeBOJg7BRSfx7^Lb}@wOY6!%4AqaOsh#iCX-KXJw_8;)J zIuYJI*MoP=t+=jSZ!Vh~&J}VIu7VrQF>We1hg-lc=f2@iao=;NxgWW6+)v!k+%Mc^ z?pN+N?mG7ecayuNMOvbzTCG;6HE2y*isXllFe?1KOar zKwGJOQv0m-1?@`h+uC=u?`yYdw`+H5cWd`(_iB%6PicSF{-V9C{Z;#$_I3hJuq5~s zq=Z@tbrKpUbWZ4*kdiPwA(EgZOiGxNFg0O8!t#Vy64oVbN;s5oB;iED_X#(3Mx9&d z)%kP*T^C)FuA8ohu9q%Z*IPGS7u1c^jn_Sfj8I6 z({R%WQ-NuuDQtSwG~P7LG~G1AG}H8k=`GXSrgu#5nl_p?nLaXoZ2H9Xsp*92yy?2> z57SN4Ewf~%=56Nf=AGu<<}>EA=JVzY=8NV_<}2n~7G%*|1dG#B$5PMIz|zR_kfo2M zuce=*za_(xWeHg#7R55jGQ~30@``1(Cq1Z`olvU^!$tV)@*1&GNhD zhUHJoZ7a5FtU9a1TH9LJTHo5xnqp12W?BbW2U&+$hgoy1L2HS%%vx@ZSSMN)>q6@* z*45V6tgl-STR*dYVg1T_%zDE5we?%;dFuu1AJ&`JTReh-)PQfqH|Cr0&G;64D?W+u z1|_FIpTTGGA(ysG=*u1s| zwnnzbwkEc|wtlw$whUXAZJ=$iE#FpX8)YlDjk8U#&9*JEEwin#y=?o?_L1#l+b6b9 zZ3k_KZO3gVZ5M2R*lyZx*^#}Ly^g(}y@9=vy|KNCy`8;-J;grQKGdFVA8uFdlk8LM zQ|;62)9o|ttL?AZKd|q&AFv;?AF*GxU$g&izhVE=emfB-S`zt0d!mpiC)Q4EotTu^ zEwM*puf&4Hk%>i#C5dH;<%yBRM-#^aY5p$#5WT+3XO!uLKC5x&_ZY>v=Q10 z?S+m)XQ7LbByyaRZbvOgeMhQekYj`+&+)LMz%kNMkOoC!|7)94hO z9;fK6>ulg`jT;yEq z{L=Y@^NjPX^StvX=g-bxoR^(fT-2p?>0Abv$<@`>+m+=S=o;)A>dJNvca3mOcg=9k zbj@e}Mk=GyMs>DukuK^ZY%+1`7yC=J=+|%82+|RieyH~qk zbHDC>!~K@~ZTCCwW9}2~uif9ezjOcKKI8t;WAh|>93Gd);}Jc6kL0Q4sqbm#Y2oSM zN%5q5(md&&OwRz%AkPrbFi(yr=&ABN;d#>Yl;>&BGoEKXvpt(UTRhu5+dVryyFGh6 zdp-L+hdswV-+I3D{NOp`<-K;V;B|W4Ua!~Z4R~d5vbVQ4#hdC)^QL<djmU`!qFywLX3;9z#6-~{x`BwYZ`PTb3__q1B`*!+1@qOw$=sV#% z?K|T;>$~i`;=Ag*lA!GFl1&mMm*kcFk}TDc>PwBJ zd!=SlOR0_2PUI_VwhJ!zA)RoX7?lJ-a+OZ%mR z(h=zk>8Nx<`bPRrIxU@*ev&Rqm!+%Hb?Jt5OGYx0sjQWCvOzY<7MYjrvO{*s9$A$A zvLx4%>&W%whVnh~y>e5zh1^PRBe#{?%N^y;au>O)+(YgqC(FI%6ggE+lhfr)d4N1f z9wHBubL60$D~IHKxlkS@7t5t`xg3#4%VXtn@&tLJtjLq(De_c#nmk>eA + + + + IBDocumentLocation + 1266 155 525 491 0 0 2560 1578 + IBEditorPositions + + 29 + 326 905 270 44 0 0 2560 1578 + + IBFramework Version + 439.0 + IBOpenObjects + + 29 + + IBSystem Version + 8R218 + + diff --git a/Factor.app/Contents/Resources/English.lproj/MiniFactor.nib/keyedobjects.nib b/Factor.app/Contents/Resources/English.lproj/MiniFactor.nib/keyedobjects.nib new file mode 100644 index 0000000000000000000000000000000000000000..34abd139a62216d6d80944a25f3cb7b027239b57 GIT binary patch literal 9369 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 literal 0 HcmV?d00001 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..dd232a75df --- /dev/null +++ b/Makefile @@ -0,0 +1,154 @@ +CC = gcc + +EXECUTABLE = factor +VERSION = 0.91 + +IMAGE = factor.image +BUNDLE = Factor.app +LIBPATH = -L/usr/X11R6/lib +CFLAGS = -Wall + +ifdef DEBUG + CFLAGS += -g +else + CFLAGS += -O3 -fomit-frame-pointer $(SITE_CFLAGS) +endif + +ifdef CONFIG + include $(CONFIG) +endif + +ENGINE = $(DLL_PREFIX)factor$(DLL_SUFFIX)$(DLL_EXTENSION) + +DLL_OBJS = $(PLAF_DLL_OBJS) \ + vm/alien.o \ + vm/bignum.o \ + vm/compiler.o \ + vm/debug.o \ + vm/factor.o \ + vm/ffi_test.o \ + vm/image.o \ + vm/io.o \ + vm/math.o \ + vm/data_gc.o \ + vm/code_gc.o \ + vm/primitives.o \ + vm/run.o \ + vm/stack.o \ + vm/types.o \ + vm/jit.o \ + vm/utilities.o + +EXE_OBJS = $(PLAF_EXE_OBJS) + +default: + @echo "Run 'make' with one of the following parameters:" + @echo "" + @echo "freebsd-x86" + @echo "freebsd-amd64" + @echo "linux-x86" + @echo "linux-amd64" + @echo "linux-ppc" + @echo "linux-arm" + @echo "openbsd-x86" + @echo "openbsd-amd64" + @echo "macosx-x86" + @echo "macosx-ppc" + @echo "solaris-x86" + @echo "solaris-amd64" + @echo "windows-ce-arm" + @echo "windows-ce-x86" + @echo "windows-nt-x86" + @echo "" + @echo "Additional modifiers:" + @echo "" + @echo "DEBUG=1 compile VM with debugging information" + @echo "SITE_CFLAGS=... additional optimization flags" + @echo "NO_UI=1 don't link with X11 libraries (ignored on Mac OS X)" + @echo "X11=1 force link with X11 libraries instead of Cocoa (only on Mac OS X)" + +openbsd-x86: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.openbsd.x86 + +openbsd-amd64: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.openbsd.amd64 + +freebsd-x86: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.freebsd.x86 + +freebsd-amd64: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.freebsd.amd64 + +macosx-freetype: + ln -sf libfreetype.6.dylib \ + Factor.app/Contents/Frameworks/libfreetype.dylib + +macosx-ppc: macosx-freetype + $(MAKE) $(EXECUTABLE) macosx.app CONFIG=vm/Config.macosx.ppc + +macosx-x86: macosx-freetype + $(MAKE) $(EXECUTABLE) macosx.app CONFIG=vm/Config.macosx.x86 + +linux-x86: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.linux.x86 + +linux-amd64: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.linux.amd64 + +linux-ppc: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.linux.ppc + +linux-arm: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.linux.arm + +solaris-x86: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.solaris.x86 + +solaris-amd64: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.solaris.amd64 + +windows-nt-x86: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.nt.x86 + +windows-ce-arm: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.ce.arm + +windows-ce-x86: + $(MAKE) $(EXECUTABLE) CONFIG=vm/Config.windows.ce.x86 + +macosx.app: factor + cp $(EXECUTABLE) $(BUNDLE)/Contents/MacOS/factor + cp $(ENGINE) $(BUNDLE)/Contents/Frameworks + + install_name_tool \ + -id @executable_path/../Frameworks/libfreetype.6.dylib \ + Factor.app/Contents/Frameworks/libfreetype.6.dylib + install_name_tool \ + -change libfactor.dylib \ + @executable_path/../Frameworks/libfactor.dylib \ + Factor.app/Contents/MacOS/factor + +factor: $(DLL_OBJS) $(EXE_OBJS) + $(LINKER) $(ENGINE) $(DLL_OBJS) + $(CC) $(LIBS) $(LIBPATH) -L. $(LINK_WITH_ENGINE) \ + $(CFLAGS) -o $@$(EXE_SUFFIX)$(EXE_EXTENSION) $(EXE_OBJS) + +pull: + darcs pull http://factorcode.org/repos/ + +clean: + rm -f vm/*.o + +vm/resources.o: + windres vm/factor.rs vm/resources.o + +.c.o: + $(CC) -c $(CFLAGS) -o $@ $< + +.S.o: + $(CC) -c $(CFLAGS) -o $@ $< + +.m.o: + $(CC) -c $(CFLAGS) -o $@ $< + +.PHONY: factor diff --git a/README.txt b/README.txt new file mode 100644 index 0000000000..d574868892 --- /dev/null +++ b/README.txt @@ -0,0 +1,180 @@ +The Factor programming language +------------------------------- + +This file covers installation and basic usage of the Factor +implementation. It is not an introduction to the language itself. + +* Contents + +- Platform support +- Compiling the Factor VM +- Bootstrapping the Factor image +- Running Factor on Unix with X11 +- Running Factor on Mac OS X - Cocoa UI +- Running Factor on Mac OS X - X11 UI +- Running Factor on Windows +- Command line usage +- Source organization +- Community + +* Platform support + +Factor supports the following platforms: + + Linux/x86 + Linux/AMD64 + Linux/PowerPC + Linux/ARM + Mac OS X/x86 + Mac OS X/PowerPC + FreeBSD/x86 + FreeBSD/AMD64 + OpenBSD/x86 + OpenBSD/AMD64 + Solaris/x86 + Solaris/AMD64 + MS Windows/x86 (XP and above) + MS Windows CE/ARM + +Please donate time or hardware if you wish to see Factor running on +other platforms. In particular, we are interested in: + + Windows/AMD64 + Mac OS X/AMD64 + Solaris/UltraSPARC + Linux/MIPS + +* Compiling the Factor VM + +The Factor runtime is written in GNU C99, and is built with GNU make and +gcc. + +Factor requires gcc 3.4 or later. On x86, it /will not/ build using gcc +3.3 or earlier. + +Run 'make' (or 'gmake' on *BSD) with no parameters to see a list of +targets and build options. Then run 'make' with the appropriate target +for your platform. + +Compilation will yield an executable named 'factor' on Unix, +'factor-nt.exe' on Windows XP/Vista, and 'factor-ce.exe' on Windows CE. + +* Bootstrapping the Factor image + +The boot images are no longer included with the Factor distribution +due to size concerns. Instead, download a boot image from: + + http://factorcode.org/images/ + +Once you have compiled the Factor runtime, you must bootstrap the Factor +system using the image that corresponds to your CPU architecture. + +Once you download the right image, bootstrap the system with the +following command line: + +./factor -i=boot..image + +Bootstrap can take a while, depending on your system. When the process +completes, a 'factor.image' file will be generated. Note that this image +is both CPU and OS-specific, so in general cannot be shared between +machines. + +* Running Factor on Unix with X11 + +On Unix, Factor can either run a graphical user interface using X11, or +a terminal listener. + +If your DISPLAY environment variable is set, the UI will start +automatically: + + ./factor + +To run an interactive terminal listener: + + ./factor -run=listener + +If you're inside a terminal session, you can start the UI with one of +the following two commands: + + ui + [ ui ] in-thread + +The latter keeps the terminal listener running. + +* Running Factor on Mac OS X - Cocoa UI + +On Mac OS X 10.4 and later, a Cocoa UI is available in addition to the +terminal listener. If you are using Mac OS X 10.3, you can only run the +X11 UI, as documented in the next section. + +The 'factor' executable runs the terminal listener: + + ./factor + +The 'Factor.app' bundle runs the Cocoa UI. Note that this is not a +self-contained bundle, it must be run from the same directory which +contains factor.image and the library sources. + +* Running Factor on Mac OS X - X11 UI + +The X11 UI is available on Mac OS X, however its use is not recommended +since it does not integrate with the host OS. However, if you are +running Mac OS X 10.3, it is your only choice. + +When compiling Factor, pass the X11=1 parameter: + + make macosx-ppc X11=1 + +Then bootstrap with the following switches: + + ./factor -i=boot.ppc.image -ui-backend=x11 + +Now if $DISPLAY is set, running ./factor will start the UI. + +* Running Factor on Windows XP/Vista + +If you did not download the binary package, you can bootstrap Factor in +the command prompt: + + factor-nt.exe -i=boot.x86.32.image + +Once bootstrapped, double-clicking factor.exe starts the Factor UI. + +To run the listener in the command prompt: + + factor-nt.exe -run=listener + +* Command line usage + +The Factor VM supports a number of command line switches. To read +command line usage documentation, either enter the following in the UI +listener: + + "command-line" about + +* Source organization + +The following two directories are managed by the module system; consult +the documentation for details: + + core/ - Factor core library and compiler + extra/ - more libraries + +The following directories contain additional files: + + misc/ - editor modes, icons, etc + vm/ - sources for the Factor runtime, written in C + fonts/ - TrueType fonts used by UI + unmaintained/ - unmaintained contributions, please help! + +* Community + +The Factor homepage is located at . + +Factor developers meet in the #concatenative channel on the +irc.freenode.net server. Drop by if you want to discuss anything related +to Factor or language design in general. + +Have fun! + +:tabSize=2:indentSize=2:noTabs=true: diff --git a/core/alien/alien-docs.factor b/core/alien/alien-docs.factor new file mode 100644 index 0000000000..259d78f67f --- /dev/null +++ b/core/alien/alien-docs.factor @@ -0,0 +1,527 @@ +USING: byte-arrays arrays help.syntax help.markup +alien.syntax alien.c-types compiler definitions math libc +debugger parser io io.backend system bit-arrays float-arrays ; +IN: alien + +HELP: alien +{ $class-description "The class of alien pointers. See " { $link "syntax-aliens" } " for syntax and " { $link "c-data" } " for general information." } ; + +HELP: dll +{ $class-description "The class of native library handles. See " { $link "syntax-aliens" } " for syntax and " { $link "dll.private" } " for general information." } ; + +HELP: expired? ( c-ptr -- ? ) +{ $values { "c-ptr" "an alien, byte array, or " { $link f } } { "?" "a boolean" } } +{ $description "Tests if the alien is a relic from an earlier session. When an image is loaded, any alien objects which persisted in the image are marked as being expired." +$nl +"A byte array is never considered to be expired, whereas passing " { $link f } " always yields true." } ; + +HELP: ( displacement c-ptr -- alien ) +{ $values { "displacement" "an integer" } { "c-ptr" "an alien, byte array, or " { $link f } } { "alien" "a new alien" } } +{ $description "Creates a new alien address object, wrapping a raw memory address. The alien points to a location in memory which is offset by " { $snippet "displacement" } " from the address of " { $snippet "c-ptr" } "." } +{ $notes "Passing a value of " { $link f } " for " { $snippet "c-ptr" } " creates an alien with an absolute address; this is how " { $link } " is implemented." +$nl +"Passing a zero absolute address does not construct a new alien object, but instead makes the word output " { $link f } "." } ; + +{ alien-address } related-words + +HELP: alien-address ( c-ptr -- addr ) +{ $values { "c-ptr" "an alien or " { $link f } } { "addr" "a non-negative integer" } } +{ $description "Outputs the address of an alien." } +{ $notes "Taking the address of a " { $link byte-array } " is explicitly prohibited since byte arrays can be moved by the garbage collector between the time the address is taken, and when it is accessed. If you need to pass pointers to C functions which will persist across alien calls, you must allocate unmanaged memory instead. See " { $link "malloc" } "." } ; + +HELP: +{ $values { "address" "a non-negative integer" } { "alien" "a new alien address" } } +{ $description "Creates an alien object, wrapping a raw memory address." } +{ $notes "Alien objects are invalidated between image saves and loads." } ; + +HELP: c-ptr +{ $class-description "Class of objects consisting of aliens, byte arrays and " { $link f } ". These objects can convert to pointer C types, which are all aliases of " { $snippet "void*" } "." } ; + +HELP: library +{ $values { "name" "a string" } { "library" "a hashtable" } } +{ $description "Looks up a library by its logical name. The library object is a hashtable with the following keys:" + { $list + { { $snippet "name" } " - the full path of the C library binary" } + { { $snippet "abi" } " - the ABI used by the library, either " { $snippet "cdecl" } " or " { $snippet "stdcall" } } + { { $snippet "dll" } " - an instance of the " { $link dll } " class; only set if the library is loaded" } + } +} ; + +HELP: dlopen ( path -- dll ) +{ $values { "path" "a pathname string" } { "dll" "a DLL handle" } } +{ $description "Opens a native library and outputs a handle which may be passed to " { $link dlsym } " or " { $link dlclose } "." } +{ $errors "Throws an error if the library could not be found, or if loading fails for some other reason." } +{ $notes "This is the low-level facility used to implement " { $link load-library } ". Use the latter instead." } ; + +HELP: dlsym ( name dll -- alien ) +{ $values { "name" "a C symbol name" } { "dll" "a DLL handle" } { "alien" "an alien pointer" } } +{ $description "Looks up a symbol in a native library. If " { $snippet "dll" } " is " { $link f } " looks for the symbol in the runtime executable." } +{ $errors "Throws an error if the symbol could not be found." } ; + +HELP: dlclose ( dll -- ) +{ $values { "dll" "a DLL handle" } } +{ $description "Closes a DLL handle created by " { $link dlopen } ". This word might not be implemented on all platforms." } ; + +HELP: load-library +{ $values { "name" "a string" } { "dll" "a DLL handle" } } +{ $description "Loads a library by logical name and outputs a handle which may be passed to " { $link dlsym } " or " { $link dlclose } ". If the library is already loaded, returns the existing handle." } +{ $errors "Throws an error if the library could not be found, or if loading fails for some other reason." } ; + +HELP: add-library +{ $values { "name" "a string" } { "path" "a string" } { "abi" "one of " { $snippet "\"cdecl\"" } " or " { $snippet "\"stdcall\"" } } } +{ $description "Defines a new logical library named " { $snippet "name" } " located in the file system at " { $snippet "path" } "and the specified ABI." } +{ $examples { $code "\"gif\" \"libgif.so\" \"cdecl\" add-library" } } ; + +HELP: alien-invoke-error +{ $error-description "Thrown if the word calling " { $link alien-invoke } " was not compiled with the optimizing compiler. This may be a result of one of several failure conditions:" + { $list + { "This can happen when experimenting with " { $link alien-invoke } " in this listener. To fix the problem, place the " { $link alien-invoke } " call in a word and then call " { $link recompile } ". See " { $link "compiler" } "." } + { "The return type or parameter list references an unknown C type." } + { "The symbol or library could not be found." } + { "One of the four inputs to " { $link alien-invoke } " is not a literal value. To call functions which are not known at compile-time, use " { $link alien-indirect } "." } + } +} ; + +HELP: alien-invoke +{ $values { "..." "zero or more objects passed to the C function" } { "return" "a C return type" } { "library" "a logical library name" } { "function" "a C function name" } { "parameters" "a sequence of C parameter types" } } +{ $description "Calls a C library function with the given name. Input parameters are taken from the data stack, and the return value is pushed on the data stack after the function returns. A return type of " { $snippet "\"void\"" } " indicates that no value is to be expected." } +{ $notes "C type names are documented in " { $link "c-types-specs" } "." } +{ $errors "Throws an " { $link alien-invoke-error } " if the word calling " { $link alien-invoke } " was not compiled with the optimizing compiler." } ; + +HELP: alien-indirect-error +{ $error-description "Thrown if the word calling " { $link alien-indirect } " was not compiled with the optimizing compiler. This may be a result of one of several failure conditions:" + { $list + { "This can happen when experimenting with " { $link alien-indirect } " in this listener. To fix the problem, place the " { $link alien-indirect } " call in a word and then call " { $link recompile } ". See " { $link "compiler" } "." } + { "The return type or parameter list references an unknown C type." } + { "One of the three inputs to " { $link alien-indirect } " is not a literal value." } + } +} ; + +HELP: alien-indirect +{ $values { "..." "zero or more objects passed to the C function" } { "funcptr" "a C function pointer" } { "return" "a C return type" } { "parameters" "a sequence of C parameter types" } { "abi" "one of " { $snippet "\"cdecl\"" } " or " { $snippet "\"stdcall\"" } } } +{ $description + "Invokes a C function pointer passed on the data stack. Input parameters are taken from the data stack following the function pointer, and the return value is pushed on the data stack after the function returns. A return type of " { $snippet "\"void\"" } " indicates that no value is to be expected." +} +{ $notes "C type names are documented in " { $link "c-types-specs" } "." } +{ $errors "Throws an " { $link alien-indirect-error } " if the word calling " { $link alien-indirect } " is not compiled." } ; + +HELP: alien-callback-error +{ $error-description "Thrown if the word calling " { $link alien-callback } " was not compiled with the optimizing compiler. This may be a result of one of several failure conditions:" + { $list + { "This can happen when experimenting with " { $link alien-callback } " in this listener. To fix the problem, place the " { $link alien-callback } " call in a word and then call " { $link recompile } ". See " { $link "compiler" } "." } + { "The return type or parameter list references an unknown C type." } + { "One of the four inputs to " { $link alien-callback } " is not a literal value." } + } +} ; + +HELP: alien-callback +{ $values { "return" "a C return type" } { "parameters" "a sequence of C parameter types" } { "abi" "one of " { $snippet "\"cdecl\"" } " or " { $snippet "\"stdcall\"" } } { "quot" "a quotation" } { "alien" c-ptr } } +{ $description + "Defines a callback from C to Factor which accepts the given set of parameters from the C caller, pushes them on the data stack, calls the quotation, and passes a return value back to the C caller. A return type of " { $snippet "\"void\"" } " indicates that no value is to be returned." + $nl + "When a compiled reference to this word is called, it pushes the callback's alien address on the data stack. This address can be passed to any C function expecting a C function pointer with the correct signature. The callback is actually generated when the word calling " { $link alien-callback } " is compiled." + $nl + "Callback quotations run with freshly-allocated stacks. This means the data stack contains the values passed by the C function, and nothing else. It also means that if the callback throws an error which is not caught, the Factor runtime will halt. See " { $link "errors" } " for error handling options." +} +{ $notes "C type names are documented in " { $link "c-types-specs" } "." } +{ $examples + "A simple example, showing a C function which returns the difference of two given integers:" + { $code + ": difference-callback ( -- alien )" + " \"int\" { \"int\" \"int\" } \"cdecl\" [ - ] alien-callback ;" + } +} +{ $errors "Throws an " { $link alien-callback-error } " if the word calling " { $link alien-callback } " is not compiled." } ; + +{ alien-invoke alien-indirect alien-callback } related-words + +ARTICLE: "aliens" "Alien addresses" +"Instances of the " { $link alien } " class represent pointers to C data outside the Factor heap:" +{ $subsection } +{ $subsection } +{ $subsection alien-address } +{ $subsection expired? } +"Anywhere that a " { $link alien } " instance is accepted, the " { $link f } " singleton may be passed in to denote a null pointer." +$nl +"Usually alien objects do not have to created and dereferenced directly; instead declaring C function parameters and return values as having a pointer type such as " { $snippet "void*" } " takes care of the details. See " { $link "c-types-specs" } "." ; + +ARTICLE: "c-structs" "C structure types" +"A " { $snippet "struct" } " in C is essentially a block of memory with the value of each structure field stored at a fixed offset from the start of the block. The C library interface provides some utilities to define words which read and write structure fields given a base address." +{ $subsection POSTPONE: C-STRUCT: } +"Great care must be taken when working with C structures since no type or bounds checking is possible." +$nl +"An example:" +{ $code + "C-STRUCT: XVisualInfo" + " { \"Visual*\" \"visual\" }" + " { \"VisualID\" \"visualid\" }" + " { \"int\" \"screen\" }" + " { \"uint\" \"depth\" }" + " { \"int\" \"class\" }" + " { \"ulong\" \"red_mask\" }" + " { \"ulong\" \"green_mask\" }" + " { \"ulong\" \"blue_mask\" }" + " { \"int\" \"colormap_size\" }" + " { \"int\" \"bits_per_rgb\" } ;" +} +"C structure objects can be allocated by calling " { $link } " or " { $link malloc-object } "." +$nl +"Arrays of C structures can be created by calling " { $link } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-STRUCT: } "." ; + +ARTICLE: "c-unions" "C unions" +"A " { $snippet "union" } " in C defines a type large enough to hold its largest member. This is usually used to allocate a block of memory which can hold one of several types of values." +{ $subsection POSTPONE: C-UNION: } +"C structure objects can be allocated by calling " { $link } " or " { $link malloc-object } "." +$nl +"Arrays of C unions can be created by calling " { $link } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-UNION: } "." ; + +ARTICLE: "reading-writing-memory" "Reading and writing memory directly" +"Numerical values can be read from memory addresses and converted to Factor objects using the various typed memory accessor words:" +{ $subsection alien-signed-1 } +{ $subsection alien-unsigned-1 } +{ $subsection alien-signed-2 } +{ $subsection alien-unsigned-2 } +{ $subsection alien-signed-4 } +{ $subsection alien-unsigned-4 } +{ $subsection alien-signed-cell } +{ $subsection alien-unsigned-cell } +{ $subsection alien-signed-8 } +{ $subsection alien-unsigned-8 } +{ $subsection alien-float } +{ $subsection alien-double } +"Factor numbers can also be converted to C values and stored to memory:" +{ $subsection set-alien-signed-1 } +{ $subsection set-alien-unsigned-1 } +{ $subsection set-alien-signed-2 } +{ $subsection set-alien-unsigned-2 } +{ $subsection set-alien-signed-4 } +{ $subsection set-alien-unsigned-4 } +{ $subsection set-alien-signed-cell } +{ $subsection set-alien-unsigned-cell } +{ $subsection set-alien-signed-8 } +{ $subsection set-alien-unsigned-8 } +{ $subsection set-alien-float } +{ $subsection set-alien-double } ; + +ARTICLE: "loading-libs" "Loading native libraries" +"Before calling a C library, you must associate its path name on disk with a logical name which Factor uses to identify the library:" +{ $subsection add-library } +"Once a library has been defined, you can try loading it to see if the path name is correct:" +{ $subsection load-library } ; + +ARTICLE: "alien-invoke" "Calling C from Factor" +"The easiest way to call into a C library is to define bindings using a pair of parsing words:" +{ $subsection POSTPONE: LIBRARY: } +{ $subsection POSTPONE: FUNCTION: } +"The above parsing words create word definitions which call a lower-level word; you can use it directly, too:" +{ $subsection alien-invoke } +"Sometimes it is necessary to invoke a C function pointer, rather than a named C function:" +{ $subsection alien-indirect } +"There are some details concerning the conversion of Factor objects to C values, and vice versa. See " { $link "c-data" } "." +$nl +"Don't forget to compile your binding word after defining it; C library calls cannot be made from an interpreted definition. Words defined in source files are automatically compiled when the source file is loaded, but words defined in the listener are not; when interactively testing C libraries, use " { $link compile } " or " { $link recompile } " to compile binding words." ; + +ARTICLE: "alien-callback-gc" "Callbacks and code GC" +"A callback consits of two parts; the callback word, which pushes the address of the callback on the stack when executed, and the callback body itself. If the callback word is redefined, removed from the dictionary using " { $link forget } ", or recompiled, the callback body will not be reclaimed by the garbage collector, since potentially C code may be holding a reference to the callback body." +$nl +"This is the safest approach, however it can lead to code heap leaks when repeatedly reloading code which defines callbacks. If you are " { $emphasis "completely sure" } " that no running C code is holding a reference to any callbacks, you can blow them all away:" +{ $code "USE: alien callbacks get clear-hash code-gc" } +"This will reclaim all callback bodies which are otherwise unreachable from the dictionary (that is, their associated callback words have since been redefined, recompiled or forgotten)." ; + +ARTICLE: "alien-callback" "Calling Factor from C" +"Callbacks can be defined and passed to C code as function pointers; the C code can then invoke the callback and run Factor code:" +{ $subsection alien-callback } +"There are some details concerning the conversion of Factor objects to C values, and vice versa. See " { $link "c-data" } "." +{ $subsection "alien-callback-gc" } ; + +ARTICLE: "dll.private" "DLL handles" +"DLL handles are a built-in class of objects which represent loaded native libraries. DLL handles are instances of the " { $link dll } " class, and have a literal syntax used for debugging prinouts; see " { $link "syntax-aliens" } "." +$nl +"Usually one never has to deal with DLL handles directly; the C library interface creates them as required. However if direct access to these operating system facilities is required, the following primitives can be used:" +{ $subsection dlopen } +{ $subsection dlsym } +{ $subsection dlclose } ; + +ARTICLE: "c-types-specs" "C type specifiers" +"C types are identified by strings, and type names occur as parameters to the " { $link alien-invoke } ", " { $link alien-indirect } " and " { $link alien-callback } " words, as well as " { $link POSTPONE: C-STRUCT: } ", " { $link POSTPONE: C-UNION: } " and " { $link POSTPONE: TYPEDEF: } "." +$nl +"The following numerical types are available; a " { $snippet "u" } " prefix denotes an unsigned type:" +{ $table + { "C type" "Notes" } + { { $snippet "char" } "always 1 byte" } + { { $snippet "uchar" } { } } + { { $snippet "short" } "always 2 bytes" } + { { $snippet "ushort" } { } } + { { $snippet "int" } "always 4 bytes" } + { { $snippet "uint" } { } } + { { $snippet "long" } { "same size as CPU word size and " { $snippet "void*" } ", except on 64-bit Windows, where it is 4 bytes" } } + { { $snippet "ulong" } { } } + { { $snippet "longlong" } "always 8 bytes" } + { { $snippet "ulonglong" } { } } + { { $snippet "float" } { } } + { { $snippet "double" } { "same format as " { $link float } " objects" } } +} +"When making alien calls, Factor numbers are converted to and from the above types in a canonical way. Converting a Factor number to a C value may result in a loss of precision." +$nl +"Pointer types are specified by suffixing a C type with " { $snippet "*" } ", for example " { $snippet "float*" } ". One special case is " { $snippet "void*" } ", which denotes a generic pointer; " { $snippet "void" } " by itself is not a valid C type specifier. With the exception of strings (see " { $link "c-strings" } "), all pointer types are identical to " { $snippet "void*" } " as far as the C library interface is concerned." +$nl +"Fixed-size array types are supported; the syntax consists of a C type name followed by dimension sizes in brackets; the following denotes a 3 by 4 array of integers:" +{ $code "int[3][4]" } +"Fixed-size arrays differ from pointers in that they are allocated inside structures and unions; however when used as function parameters they behave exactly like pointers and thus the dimensions only serve as documentation." +$nl +"Structure and union types are specified by the name of the structure or union." ; + +ARTICLE: "c-byte-arrays" "Passing data in byte arrays" +"Instances of the " { $link byte-array } ", " { $link bit-array } " and " { $link float-array } " class can be passed to C functions; the C function receives a pointer to the first element of the array." +$nl +"Byte arrays can be allocated directly with a byte count using the " { $link } " word. However in most cases, instead of computing a size in bytes directly, it is easier to use a higher-level word which expects C type and outputs a byte array large enough to hold that type:" +{ $subsection } +{ $subsection } +{ $warning +"The Factor garbage collector can move byte arrays around, and it is only safe to pass byte arrays to C functions if the function does not store a pointer to the byte array in some global structure, or retain it in any way after returning." +$nl +"Long-lived data for use by C libraries can be allocated manually, just as when programming in C. See " { $link "malloc" } "." } +{ $see-also "c-arrays" } ; + +ARTICLE: "malloc" "Manual memory management" +"Sometimes data passed to C functions must be allocated at a fixed address, and so garbage collector managed byte arrays cannot be used. See the warning at the bottom of " { $link "c-byte-arrays" } " for a description of when this is the case." +$nl +"Allocating a C datum with a fixed address:" +{ $subsection malloc-object } +{ $subsection malloc-array } +{ $subsection malloc-byte-array } +"There is a set of words in the " { $vocab-link "libc" } " vocabulary which directly call C standard library memory management functions:" +{ $subsection malloc } +{ $subsection calloc } +{ $subsection realloc } +"The return value of the above three words must always be checked for a memory allocation failure:" +{ $subsection check-ptr } +"You must always free pointers returned by any of the above words when the block of memory is no longer in use:" +{ $subsection free } +"You can unsafely copy a range of bytes from one memory location to another:" +{ $subsection memcpy } +"A wrapper for temporarily allocating a block of memory:" +{ $subsection with-malloc } ; + +ARTICLE: "c-strings" "C strings" +"The C library interface defines two types of C strings:" +{ $table + { "C type" "Notes" } + { { $snippet "char*" } "8-bit per character null-terminated ASCII" } + { { $snippet "ushort*" } "16-bit per character null-terminated UCS-2" } +} +"Passing a Factor string to a C function expecting a C string allocates a " { $link byte-array } " in the Factor heap; the string is then converted to the requested format and a raw pointer is passed to the function. If the conversion fails, for example if the string contains null bytes or characters with values higher than 255, a " { $link c-string-error. } " is thrown." +"Sometimes a C function has a parameter type of " { $snippet "void*" } ", and various data types, among them strings, can be passed in. In this case, strings are not automatically converted to aliens, and instead you must call one of these words:" +{ $subsection string>char-alien } +{ $subsection string>u16-alien } +{ $subsection malloc-char-string } +{ $subsection malloc-u16-string } +"The first two allocate " { $link byte-array } "s, and the latter allocates manually-managed memory which is not moved by the garbage collector and has to be explicitly freed by calling " { $link free } "." +$nl +"Finally, a set of words can be used to read and write " { $snippet "char*" } " and " { $snippet "ushort*" } " strings at arbitrary addresses:" +{ $subsection alien>char-string } +{ $subsection alien>u16-string } +{ $subsection memory>string } +{ $subsection string>memory } ; + +ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays" +"Each primitive C type has a pair of words, " { $snippet ">" { $emphasis "type" } "-array" } " and " { $snippet { $emphasis "type" } "-array>" } ", for converting an array of Factor objects to and from a " { $link byte-array } " of C values. This set of words consists of:" +{ $subsection >c-bool-array } +{ $subsection >c-char-array } +{ $subsection >c-double-array } +{ $subsection >c-float-array } +{ $subsection >c-int-array } +{ $subsection >c-long-array } +{ $subsection >c-longlong-array } +{ $subsection >c-short-array } +{ $subsection >c-uchar-array } +{ $subsection >c-uint-array } +{ $subsection >c-ulong-array } +{ $subsection >c-ulonglong-array } +{ $subsection >c-ushort-array } +{ $subsection >c-void*-array } +{ $subsection c-bool-array> } +{ $subsection c-char*-array> } +{ $subsection c-char-array> } +{ $subsection c-double-array> } +{ $subsection c-float-array> } +{ $subsection c-int-array> } +{ $subsection c-long-array> } +{ $subsection c-longlong-array> } +{ $subsection c-short-array> } +{ $subsection c-uchar-array> } +{ $subsection c-uint-array> } +{ $subsection c-ulong-array> } +{ $subsection c-ulonglong-array> } +{ $subsection c-ushort*-array> } +{ $subsection c-ushort-array> } +{ $subsection c-void*-array> } ; + +ARTICLE: "c-arrays-get/set" "Reading and writing elements in C arrays" +"Each C type has a pair of words, " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } ", for reading and writing values of this type stored in an array. This set of words includes but is not limited to:" +{ $subsection char-nth } +{ $subsection set-char-nth } +{ $subsection uchar-nth } +{ $subsection set-uchar-nth } +{ $subsection short-nth } +{ $subsection set-short-nth } +{ $subsection ushort-nth } +{ $subsection set-ushort-nth } +{ $subsection int-nth } +{ $subsection set-int-nth } +{ $subsection uint-nth } +{ $subsection set-uint-nth } +{ $subsection long-nth } +{ $subsection set-long-nth } +{ $subsection ulong-nth } +{ $subsection set-ulong-nth } +{ $subsection longlong-nth } +{ $subsection set-longlong-nth } +{ $subsection ulonglong-nth } +{ $subsection set-ulonglong-nth } +{ $subsection float-nth } +{ $subsection set-float-nth } +{ $subsection double-nth } +{ $subsection set-double-nth } +{ $subsection void*-nth } +{ $subsection set-void*-nth } +{ $subsection char*-nth } +{ $subsection ushort*-nth } ; + +ARTICLE: "c-arrays" "C arrays" +"C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "." +$nl +"C type specifiers for array types are documented in " { $link "c-types-specs" } "." +{ $subsection "c-arrays-factor" } +{ $subsection "c-arrays-get/set" } ; + +ARTICLE: "c-out-params" "Output parameters in C" +"A frequently-occurring idiom in C code is the \"out parameter\". If a C function returns more than one value, the caller passes pointers of the correct type, and the C function writes its return values to those locations." +$nl +"Each numerical C type, together with " { $snippet "void*" } ", has an associated " { $emphasis "out parameter constructor" } " word which takes a Factor object as input, constructs a byte array of the correct size, and converts the Factor object to a C value stored into the byte array:" +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +{ $subsection } +"You call the out parameter constructor with the required initial value, then pass the byte array to the C function, which receives a pointer to the start of the byte array's data area. The C function then returns, leaving the result in the byte array; you read it back using the next set of words:" +{ $subsection *char } +{ $subsection *uchar } +{ $subsection *short } +{ $subsection *ushort } +{ $subsection *int } +{ $subsection *uint } +{ $subsection *long } +{ $subsection *ulong } +{ $subsection *longlong } +{ $subsection *ulonglong } +{ $subsection *float } +{ $subsection *double } +{ $subsection *void* } +{ $subsection *char* } +{ $subsection *ushort* } +"Note that while structure and union types do not get these words defined for them, there is no loss of generality since " { $link } " and " { $link *void* } " may be used." ; + +ARTICLE: "c-data" "Passing data between Factor and C" +"Two defining characteristics of Factor are dynamic typing and automatic memory management, which are somewhat incompatible with the machine-level data model exposed by C. Factor's C library interface defines its own set of C data types, distinct from Factor language types, together with automatic conversion between Factor values and C types. For example, C integer types must be declared and are fixed-width, whereas Factor supports arbitrary-precision integers. Also Factor's garbage collector can move objects in memory, which means that special support has to be provided for passing blocks of memory to C code." +{ $subsection "c-types-specs" } +{ $subsection "c-byte-arrays" } +{ $subsection "malloc" } +{ $subsection "c-strings" } +{ $subsection "c-arrays" } +{ $subsection "c-out-params" } +"C-style enumerated types are supported:" +{ $subsection POSTPONE: C-ENUM: } +"C types can be aliased for convenience and consitency with native library documentation:" +{ $subsection POSTPONE: TYPEDEF: } +"New C types can be defined:" +{ $subsection "c-structs" } +{ $subsection "c-unions" } +{ $subsection "reading-writing-memory" } ; + +ARTICLE: "embedding-api" "Factor embedding API" +"The Factor embedding API is defined in " { $snippet "vm/master.h" } "." +$nl +"The " { $snippet "F_CHAR" } " type is an alias for the character type used for path names by the operating system; " { $snippet "char" } " on Unix and " { $snippet "wchar_t" } " on Windows." +$nl +"Including this header file into a C compilation unit will declare the following functions:" +{ $table + { { + { $code "void init_factor_from_args(" + " F_CHAR *image, int argc, F_CHAR **argv, bool embedded" + ")" } + "Initializes Factor." + $nl + "If " { $snippet "image" } " is " { $snippet "NULL" } ", Factor will load an image file whose name is obtained by suffixing the executable name with " { $snippet ".image" } "." + $nl + "The " { $snippet "argc" } " and " { $snippet "argv" } " parameters are interpreted just like normal command line arguments when running Factor stand-alone; see " { $link "cli" } "." + $nl + "The " { $snippet "embedded" } " flag ensures that this function returns as soon as Factor has been initialized. Otherwise, Factor will start up normally." + } } + { { + { $code "char *factor_eval_string(char *string)" } + "Evaluates a piece of code in the embedded Factor instance by passing the string to " { $link eval>string } " and returning the result. The result must be explicitly freed by a call to " { $snippet "factor_eval_free" } "." + } } + { { + { $code "void factor_eval_free(char *result)" } + "Frees a string returned by " { $snippet "factor_eval_string()" } "." + } } + { { + { $code "void factor_yield(void)" } + "Gives all Factor threads a chance to run." + } } + { { + { $code "void factor_sleep(long ms)" } + "Gives all Factor threads a chance to run for " { $snippet "ms" } " milliseconds." + } } +} ; + +ARTICLE: "embedding-restrictions" "Embedding API restrictions" +"The Factor VM is not thread safe, and does not support multiple instances. There must only be one Factor instance per process, and this instance must be consistently accessed from the same thread for its entire lifetime. Once initialized, a Factor instance cannot be destroyed other than by exiting the process." ; + +ARTICLE: "embedding-factor" "What embedding looks like from Factor" +"Factor code will run inside an embedded instance in the same way it would run in a stand-alone instance." +$nl +"One exception is the global " { $link stdio } " stream, which is by default not bound to the terminal where the process is running, to avoid conflicting with any I/O the host process might perform. To initialize the terminal stream, " { $link init-stdio } " must be called explicitly." +$nl +"There is a word which can detect when Factor is embedded:" +{ $subsection embedded? } +"No special support is provided for calling out from Factor into the owner process. The C library inteface works fine for this task - see " { $link "alien" } "." ; + +ARTICLE: "embedding" "Embedding Factor into C applications" +"The Factor " { $snippet "Makefile" } " builds the Factor VM both as an executable and a library. The library can be used by other applications. File names for the library on various operating systems:" +{ $table + { "OS" "Library name" "Shared?" } + { "Windows XP/Vista" { $snippet "factor-nt.dll" } "Yes" } + { "Windows CE" { $snippet "factor-ce.dll" } "Yes" } + { "Mac OS X" { $snippet "libfactor.dylib" } "Yes" } + { "Other Unix" { $snippet "libfactor.a" } "No" } +} +"An image file must be supplied; a minimal image can be built, however the compiler must be included for the embedding API to work (see " { $link "bootstrap-cli-args" } ")." +{ $subsection "embedding-api" } +{ $subsection "embedding-factor" } +{ $subsection "embedding-restrictions" } ; + +ARTICLE: "alien" "C library interface" +"Factor can directly call C functions in native libraries. It is also possible to compile callbacks which run Factor code, and pass them to native libraries as function pointers." +$nl +"The C library interface is entirely self-contained; there is no C code which one must write in order to wrap a library." +$nl +"C library interface words are found in the " { $vocab-link "alien" } " vocabulary." +{ $warning "Since C does not retain runtime type information or do any kind of runtime type checking, any C library interface is not pointer safe. Improper use of C functions can crash the runtime or corrupt memory in unpredictible ways." } +{ $subsection "loading-libs" } +{ $subsection "alien-invoke" } +{ $subsection "alien-callback" } +{ $subsection "c-data" } +{ $subsection "dll.private" } +{ $subsection "embedding" } ; + +ABOUT: "alien" diff --git a/core/alien/alien-tests.factor b/core/alien/alien-tests.factor new file mode 100644 index 0000000000..0adc5f08ef --- /dev/null +++ b/core/alien/alien-tests.factor @@ -0,0 +1,58 @@ +IN: temporary +USING: alien byte-arrays +arrays kernel kernel.private namespaces tools.test sequences +libc math system prettyprint ; + +[ t ] [ -1 alien-address 0 > ] unit-test + +[ t ] [ 0 0 = ] unit-test +[ f ] [ 0 1024 = ] unit-test +[ f ] [ "hello" 1024 = ] unit-test +[ f ] [ 0 ] unit-test +[ f ] [ 0 f ] unit-test + +! Testing the various bignum accessor +10 "dump" set + +[ "dump" get alien-address ] unit-test-fails + +[ 123 ] [ + 123 "dump" get 0 set-alien-signed-1 + "dump" get 0 alien-signed-1 +] unit-test + +[ 12345 ] [ + 12345 "dump" get 0 set-alien-signed-2 + "dump" get 0 alien-signed-2 +] unit-test + +[ 12345678 ] [ + 12345678 "dump" get 0 set-alien-signed-4 + "dump" get 0 alien-signed-4 +] unit-test + +[ 12345678901234567 ] [ + 12345678901234567 "dump" get 0 set-alien-signed-8 + "dump" get 0 alien-signed-8 +] unit-test + +[ -1 ] [ + -1 "dump" get 0 set-alien-signed-8 + "dump" get 0 alien-signed-8 +] unit-test + +cell 8 = [ + [ HEX: 123412341234 ] [ + 8 + HEX: 123412341234 over 0 set-alien-signed-8 + 0 alien-signed-8 + ] unit-test + + [ HEX: 123412341234 ] [ + 8 + HEX: 123412341234 over 0 set-alien-signed-cell + 0 alien-signed-cell + ] unit-test +] when + +[ "ALIEN: 1234" ] [ 1234 unparse ] unit-test diff --git a/core/alien/alien.factor b/core/alien/alien.factor new file mode 100644 index 0000000000..5af9e9ff98 --- /dev/null +++ b/core/alien/alien.factor @@ -0,0 +1,83 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: alien +USING: assocs kernel math namespaces sequences system +byte-arrays bit-arrays float-arrays kernel.private tuples ; + +PREDICATE: alien simple-alien + underlying-alien not ; + +UNION: simple-c-ptr + simple-alien byte-array bit-array float-array POSTPONE: f ; + +UNION: c-ptr + alien bit-array byte-array float-array POSTPONE: f ; + +M: f expired? drop t ; + +: ( address -- alien ) + f { simple-c-ptr } declare ; inline + +: alien>native-string ( alien -- string ) + windows? [ alien>u16-string ] [ alien>char-string ] if ; + +: dll-path ( dll -- string ) + (dll-path) alien>native-string ; + +M: alien equal? + over alien? [ + 2dup [ expired? ] either? [ + [ expired? ] both? + ] [ + [ alien-address ] 2apply = + ] if + ] [ + 2drop f + ] if ; + +SYMBOL: libraries + +global [ + libraries [ H{ } assoc-like ] change +] bind + +TUPLE: library path abi dll ; + +: library ( name -- library ) libraries get at ; + +: ( path abi -- library ) f \ library construct-boa ; + +: load-library ( name -- dll ) + library dup [ + dup library-dll [ ] [ + dup library-path dup [ + dlopen dup rot set-library-dll + ] [ + 2drop f + ] if + ] ?if + ] when ; + +: add-library ( name path abi -- ) + swap libraries get set-at ; + +TUPLE: alien-callback return parameters abi quot xt ; + +TUPLE: alien-callback-error ; + +: alien-callback ( return parameters abi quot -- alien ) + \ alien-callback-error construct-empty throw ; + +TUPLE: alien-indirect return parameters abi ; + +TUPLE: alien-indirect-error ; + +: alien-indirect ( ... funcptr return parameters abi -- ) + \ alien-indirect-error construct-empty throw ; + +TUPLE: alien-invoke library function return parameters ; + +TUPLE: alien-invoke-error library symbol ; + +: alien-invoke ( ... return library function parameters -- ... ) + pick pick \ alien-invoke-error construct-boa throw ; diff --git a/core/alien/arrays/arrays.factor b/core/alien/arrays/arrays.factor new file mode 100644 index 0000000000..c9b9d838dd --- /dev/null +++ b/core/alien/arrays/arrays.factor @@ -0,0 +1,38 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien arrays alien.c-types alien.structs +sequences math kernel generator.registers +namespaces libc ; +IN: alien.arrays + +UNION: value-type array struct-type ; + +M: array c-type ; + +M: array heap-size unclip heap-size [ * ] reduce ; + +M: array c-type-align first c-type c-type-align ; + +M: array c-type-stack-align? drop f ; + +M: array unbox-parameter drop "void*" unbox-parameter ; + +M: array unbox-return drop "void*" unbox-return ; + +M: array box-parameter drop "void*" box-parameter ; + +M: array box-return drop "void*" box-return ; + +M: array stack-size drop "void*" stack-size ; + +M: value-type c-type-reg-class drop T{ int-regs } ; + +M: value-type c-type-prep drop f ; + +M: value-type c-type-getter + drop [ swap ] ; + +M: value-type c-type-setter ( type -- quot ) + [ + dup c-type-getter % \ swap , heap-size , \ memcpy , + ] [ ] make ; diff --git a/core/alien/arrays/authors.txt b/core/alien/arrays/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/arrays/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/arrays/summary.txt b/core/alien/arrays/summary.txt new file mode 100644 index 0000000000..9d8297db40 --- /dev/null +++ b/core/alien/arrays/summary.txt @@ -0,0 +1 @@ +C array support diff --git a/core/alien/authors.txt b/core/alien/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/c-types/authors.txt b/core/alien/c-types/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/c-types/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/c-types/c-types-docs.factor b/core/alien/c-types/c-types-docs.factor new file mode 100644 index 0000000000..55b788d5e3 --- /dev/null +++ b/core/alien/c-types/c-types-docs.factor @@ -0,0 +1,153 @@ +USING: alien alien.c-types help.syntax help.markup libc +kernel.private byte-arrays math strings ; + +HELP: +{ $values { "type" "a hashtable" } } +{ $description "Creates a prototypical C type. User code should use higher-level facilities to define C types; see " { $link "c-data" } "." } ; + +HELP: no-c-type +{ $values { "type" string } } +{ $description "Throws a " { $link no-c-type } " error." } +{ $error-description "Thrown by " { $link c-type } " if a given string does not name a C type. When thrown during compile time, indicates a typo in an " { $link alien-invoke } " or " { $link alien-callback } " form." } ; + +HELP: c-types +{ $var-description "Global variable holding a hashtable mapping C type names to C types. Use the " { $link c-type } " word to look up C types." } ; + +HELP: c-type +{ $values { "name" string } { "type" "a hashtable" } } +{ $description "Looks up a C type by name." } +{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ; + +HELP: heap-size +{ $values { "type" string } { "size" "an integer" } } +{ $description "Outputs the number of bytes needed for a heap-allocated value of this C type." } +{ $examples + "On a 32-bit system, you will get the following output:" + { $unchecked-example "USE: alien\n\"void*\" heap-size ." "4" } +} +{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ; + +HELP: stack-size +{ $values { "type" string } { "size" "an integer" } } +{ $description "Outputs the number of bytes to reserve on the C stack by a value of this C type. In most cases this is equal to " { $link heap-size } ", except on some platforms where C structs are passed by invisible reference, in which case a C struct type only uses as much space as a pointer on the C stack." } +{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ; + +HELP: c-getter +{ $values { "name" string } { "quot" "a quotation with stack effect " { $snippet "( c-ptr n -- obj )" } } } +{ $description "Outputs a quotation which reads values of this C type from a C structure." } +{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ; + +HELP: c-setter +{ $values { "name" string } { "quot" "a quotation with stack effect " { $snippet "( obj c-ptr n -- )" } } } +{ $description "Outputs a quotation which writes values of this C type to a C structure." } +{ $errors "Throws an error if the type does not exist." } ; + +HELP: +{ $values { "n" "a non-negative integer" } { "type" "a C type" } { "array" byte-array } } +{ $description "Creates a byte array large enough to hold " { $snippet "n" } " values of a C type." } +{ $errors "Throws an error if the type does not exist or the requested size is negative." } ; + +{ malloc-array } related-words + +HELP: +{ $values { "type" "a C type" } { "array" byte-array } } +{ $description "Creates a byte array suitable for holding a value with the given C type." } +{ $errors "Throws an " { $link no-c-type } " error if the type does not exist." } ; + +{ malloc-object } related-words + +HELP: string>char-alien ( string -- array ) +{ $values { "string" string } { "array" byte-array } } +{ $description "Copies the string to a new byte array, converting it to 8-bit ASCII and adding a trailing null byte." } +{ $errors "Throws an error if the string contains null characters, or characters beyond the 8-bit range." } ; + +{ string>char-alien alien>char-string malloc-char-string } related-words + +HELP: alien>char-string ( c-ptr -- string ) +{ $values { "c-ptr" c-ptr } { "string" string } } +{ $description "Reads a null-terminated 8-bit C string from the specified address." } ; + +HELP: string>u16-alien ( string -- array ) +{ $values { "string" string } { "array" byte-array } } +{ $description "Copies the string to a new byte array in UCS-2 format with a trailing null byte." } +{ $errors "Throws an error if the string contains null characters." } ; + +{ string>u16-alien alien>u16-string malloc-u16-string } related-words + +HELP: alien>u16-string ( c-ptr -- string ) +{ $values { "c-ptr" c-ptr } { "string" string } } +{ $description "Reads a null-terminated UCS-2 string from the specified address." } ; + +HELP: memory>string ( base len -- string ) +{ $values { "base" c-ptr } { "len" "a non-negative integer" } { "string" string } } +{ $description "Reads " { $snippet "len" } " bytes starting from " { $snippet "base" } " and stores them in a new Factor string." } ; + +HELP: string>memory ( string base -- ) +{ $values { "string" string } { "base" c-ptr } } +{ $description "Writes the string to memory starting from the " { $snippet "base" } " address." } +{ $warning "This word is unsafe. Improper use can corrupt memory." } ; + +HELP: malloc-array +{ $values { "n" "a non-negative integer" } { "type" "a C type" } { "alien" alien } } +{ $description "Allocates an unmanaged memory block large enough to hold " { $snippet "n" } " values of a C type." } +{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." } +{ $errors "Throws an error if the type does not exist, if the requested size is negative, or if memory allocation fails." } ; + +HELP: malloc-object +{ $values { "type" "a C type" } { "alien" alien } } +{ $description "Allocates an unmanaged memory block large enough to hold a value of a C type." } +{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." } +{ $errors "Throws an error if the type does not exist or if memory allocation fails." } ; + +HELP: malloc-byte-array +{ $values { "byte-array" byte-array } { "alien" alien } } +{ $description "Allocates an unmanaged memory block of the same size as the byte array, and copies the contents of the byte array there." } +{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." } +{ $errors "Throws an error if memory allocation fails." } ; + +HELP: malloc-char-string +{ $values { "string" string } { "alien" c-ptr } } +{ $description "Allocates an unmanaged memory block, and stores a string in 8-bit ASCII encoding with a trailing null byte to the block." } +{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." } +{ $errors "Throws an error if memory allocation fails." } ; + +HELP: malloc-u16-string +{ $values { "string" string } { "alien" c-ptr } } +{ $description "Allocates an unmanaged memory block, and stores a string in UCS2 encoding with a trailing null character to the block." } +{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." } +{ $errors "Throws an error if memory allocation fails." } ; + +HELP: define-nth +{ $values { "name" "a word name" } { "vocab" "a vocabulary name" } } +{ $description "Defines a word " { $snippet { $emphasis "name" } "-nth" } " with stack effect " { $snippet "( n c-ptr -- value )" } " for reading the value with C type " { $snippet "name" } " stored at an alien pointer, displaced by a multiple of the C type's size." } +{ $notes "This is an internal word called when defining C types, there is no need to call it on your own." } ; + +HELP: define-set-nth +{ $values { "name" "a word name" } { "vocab" "a vocabulary name" } } +{ $description "Defines a word " { $snippet "set-" { $emphasis "name" } "-nth" } " with stack effect " { $snippet "( value n c-ptr -- )" } " for writing the value with C type " { $snippet "name" } " to an alien pointer, displaced by a multiple of the C type's size." } +{ $notes "This is an internal word called when defining C types, there is no need to call it on your own." } ; + +HELP: box-parameter +{ $values { "n" integer } { "ctype" string } } +{ $description "Generates code for converting a C value stored at offset " { $snippet "n" } " from the top of the stack into a Factor object to be pushed on the data stack." } +{ $notes "This is an internal word used by the compiler when compiling callbacks." } ; + +HELP: box-return +{ $values { "ctype" string } } +{ $description "Generates code for converting a C value stored in return registers into a Factor object to be pushed on the data stack." } +{ $notes "This is an internal word used by the compiler when compiling alien calls." } ; + +HELP: unbox-return +{ $values { "ctype" string } } +{ $description "Generates code for converting a Factor value on the data stack into a C value to be stored in the return registers." } +{ $notes "This is an internal word used by the compiler when compiling callbacks." } ; + +HELP: define-deref +{ $values { "name" "a word name" } { "vocab" "a vocabulary name" } } +{ $description "Defines a word " { $snippet "*name" } " with stack effect " { $snippet "( c-ptr -- value )" } " for reading a value with C type " { $snippet "name" } " stored at an alien pointer." } +{ $notes "This is an internal word called when defining C types, there is no need to call it on your own." } ; + +HELP: define-out +{ $values { "name" "a word name" } { "vocab" "a vocabulary name" } } +{ $description "Defines a word " { $snippet "<" { $emphasis "name" } ">" } " with stack effect " { $snippet "( value -- array )" } ". This word allocates a byte array large enough to hold a value with C type " { $snippet "name" } ", and writes the value at the top of the stack to the array." } +{ $notes "This is an internal word called when defining C types, there is no need to call it on your own." } ; diff --git a/core/alien/c-types/c-types-tests.factor b/core/alien/c-types/c-types-tests.factor new file mode 100644 index 0000000000..ee2d8b309b --- /dev/null +++ b/core/alien/c-types/c-types-tests.factor @@ -0,0 +1,70 @@ +IN: temporary +USING: alien alien.syntax alien.c-types kernel tools.test +sequences system libc ; + +[ "\u00ff" ] +[ "\u00ff" string>char-alien alien>char-string ] +unit-test + +[ "hello world" ] +[ "hello world" string>char-alien alien>char-string ] +unit-test + +[ "hello\uabcdworld" ] +[ "hello\uabcdworld" string>u16-alien alien>u16-string ] +unit-test + +[ t ] [ f expired? ] unit-test + +[ "hello world" ] [ + "hello world" malloc-char-string + dup alien>char-string swap free +] unit-test + +[ "hello world" ] [ + "hello world" malloc-u16-string + dup alien>u16-string swap free +] unit-test + +: foo ( -- n ) "fdafd" f dlsym [ 123 ] unless* ; + +[ 123 ] [ foo ] unit-test + +[ -1 ] [ -1 *char ] unit-test +[ -1 ] [ -1 *short ] unit-test +[ -1 ] [ -1 *int ] unit-test + +C-UNION: foo + "int" + "int" ; + +[ f ] [ "char*" c-type "void*" c-type eq? ] unit-test +[ t ] [ "char**" c-type "void*" c-type eq? ] unit-test + +[ t ] [ "foo" heap-size "int" heap-size = ] unit-test + +TYPEDEF: int MyInt + +[ t ] [ "int" c-type "MyInt" c-type eq? ] unit-test +[ t ] [ "void*" c-type "MyInt*" c-type eq? ] unit-test + +TYPEDEF: char MyChar + +[ t ] [ "char" c-type "MyChar" c-type eq? ] unit-test +[ f ] [ "void*" c-type "MyChar*" c-type eq? ] unit-test +[ t ] [ "char*" c-type "MyChar*" c-type eq? ] unit-test + +[ 32 ] [ { "int" 8 } heap-size ] unit-test + +TYPEDEF: char* MyString + +[ t ] [ "char*" c-type "MyString" c-type eq? ] unit-test +[ t ] [ "void*" c-type "MyString*" c-type eq? ] unit-test + +TYPEDEF: int* MyIntArray + +[ t ] [ "void*" c-type "MyIntArray" c-type eq? ] unit-test + +TYPEDEF: uchar* MyLPBYTE + +[ t ] [ "char*" c-type "MyLPBYTE" c-type eq? ] unit-test diff --git a/core/alien/c-types/c-types.factor b/core/alien/c-types/c-types.factor new file mode 100644 index 0000000000..234e6ef65b --- /dev/null +++ b/core/alien/c-types/c-types.factor @@ -0,0 +1,356 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: byte-arrays arrays generator.registers assocs +kernel kernel.private libc math namespaces parser sequences +strings words assocs splitting math.parser cpu.architecture +alien quotations system ; +IN: alien.c-types + +TUPLE: c-type +boxer prep unboxer +getter setter +reg-class size align stack-align? ; + +: ( -- type ) + T{ int-regs } { set-c-type-reg-class } \ c-type construct ; + +SYMBOL: c-types + +global [ + c-types [ H{ } assoc-like ] change +] bind + +TUPLE: no-c-type name ; + +: no-c-type ( type -- * ) \ no-c-type construct-boa throw ; + +: (c-type) ( name -- type/f ) + c-types get-global at dup [ + dup string? [ (c-type) ] when + ] when ; + +GENERIC: c-type ( name -- type ) + +: resolve-pointer-type ( name -- name ) + c-types get at dup string? + [ "*" append ] [ drop "void*" ] if + c-type ; + +: resolve-typedef ( name -- type ) + dup string? [ c-type ] when ; + +: parse-array-type ( name -- array ) + "[" split unclip + >r [ "]" ?tail drop string>number ] map r> add* ; + +M: string c-type ( name -- type ) + CHAR: ] over member? [ + parse-array-type + ] [ + dup c-types get at [ + resolve-typedef + ] [ + "*" ?tail [ resolve-pointer-type ] [ no-c-type ] if + ] ?if + ] if ; + +: c-type-box ( n type -- ) + dup c-type-reg-class + swap c-type-boxer [ "No boxer" throw ] unless* + %box ; + +: c-type-unbox ( n ctype -- ) + dup c-type-reg-class + swap c-type-unboxer [ "No unboxer" throw ] unless* + %unbox ; + +M: string c-type-align c-type c-type-align ; + +M: string c-type-stack-align? c-type c-type-stack-align? ; + +GENERIC: box-parameter ( n ctype -- ) + +M: c-type box-parameter c-type-box ; + +M: string box-parameter c-type box-parameter ; + +GENERIC: box-return ( ctype -- ) + +M: c-type box-return f swap c-type-box ; + +M: string box-return c-type box-return ; + +GENERIC: unbox-parameter ( n ctype -- ) + +M: c-type unbox-parameter c-type-unbox ; + +M: string unbox-parameter c-type unbox-parameter ; + +GENERIC: unbox-return ( ctype -- ) + +M: c-type unbox-return f swap c-type-unbox ; + +M: string unbox-return c-type unbox-return ; + +! These words being foldable means that words need to be +! recompiled if a C type is redefined. Even so, folding the +! size facilitates some optimizations. +GENERIC: heap-size ( type -- size ) foldable + +M: string heap-size c-type heap-size ; + +M: c-type heap-size c-type-size ; + +GENERIC: stack-size ( type -- size ) foldable + +M: string stack-size c-type stack-size ; + +M: c-type stack-size c-type-size ; + +: c-getter ( name -- quot ) + c-type c-type-getter [ + [ "Cannot read struct fields with type" throw ] + ] unless* ; + +: c-setter ( name -- quot ) + c-type c-type-setter [ + [ "Cannot write struct fields with type" throw ] + ] unless* ; + +: ( n type -- array ) + heap-size * ; inline + +: ( type -- array ) + 1 swap ; inline + +: malloc-array ( n type -- alien ) + heap-size calloc ; inline + +: malloc-object ( type -- alien ) + 1 swap malloc-array ; inline + +: malloc-byte-array ( byte-array -- alien ) + dup length dup malloc [ -rot memcpy ] keep ; + +: malloc-char-string ( string -- alien ) + string>char-alien malloc-byte-array ; + +: malloc-u16-string ( string -- alien ) + string>u16-alien malloc-byte-array ; + +: (define-nth) ( word type quot -- ) + >r heap-size [ rot * ] swap add* r> append define-inline ; + +: nth-word ( name vocab -- word ) + >r "-nth" append r> create ; + +: define-nth ( name vocab -- ) + dupd nth-word swap dup c-getter (define-nth) ; + +: set-nth-word ( name vocab -- word ) + >r "set-" swap "-nth" 3append r> create ; + +: define-set-nth ( name vocab -- ) + dupd set-nth-word swap dup c-setter (define-nth) ; + +: typedef ( old new -- ) c-types get set-at ; + +: define-c-type ( type name vocab -- ) + >r tuck typedef r> [ define-nth ] 2keep define-set-nth ; + +TUPLE: long-long-type ; + +: ( type -- type ) + long-long-type construct-delegate ; + +M: long-long-type unbox-parameter ( n type -- ) + c-type-unboxer %unbox-long-long ; + +M: long-long-type unbox-return ( type -- ) + f swap unbox-parameter ; + +M: long-long-type box-parameter ( n type -- ) + c-type-boxer %box-long-long ; + +M: long-long-type box-return ( type -- ) + f swap box-parameter ; + +: define-deref ( name vocab -- ) + >r dup CHAR: * add* r> create + swap c-getter 0 add* define-inline ; + +: define-out ( name vocab -- ) + over [ tuck 0 ] over c-setter append swap + >r >r constructor-word r> r> add* define-inline ; + +: >c-array ( seq type word -- ) + >r >r dup length dup r> dup -roll r> + [ execute ] 2curry 2each ; inline + +: >c-array-quot ( type vocab -- quot ) + dupd set-nth-word [ >c-array ] 2curry ; + +: to-array-word ( name vocab -- word ) + >r ">c-" swap "-array" 3append r> create ; + +: define-to-array ( type vocab -- ) + [ to-array-word ] 2keep >c-array-quot define-compound ; + +: c-array>quot ( type vocab -- quot ) + [ + \ swap , + nth-word 1quotation , + [ curry map ] % + ] [ ] make ; + +: from-array-word ( name vocab -- word ) + >r "c-" swap "-array>" 3append r> create ; + +: define-from-array ( type vocab -- ) + [ from-array-word ] 2keep c-array>quot define-compound ; + +: ( getter setter width boxer unboxer -- type ) + + [ set-c-type-unboxer ] keep + [ set-c-type-boxer ] keep + [ set-c-type-size ] 2keep + [ set-c-type-align ] keep + [ set-c-type-setter ] keep + [ set-c-type-getter ] keep ; + +: define-primitive-type ( type name -- ) + "alien.c-types" + [ define-c-type ] 2keep + [ define-deref ] 2keep + [ define-to-array ] 2keep + [ define-from-array ] 2keep + define-out ; + +: expand-constants ( c-type -- c-type' ) + dup array? [ + unclip >r [ dup word? [ execute ] when ] map r> add* + ] when ; + +[ alien-cell ] +[ set-alien-cell ] +bootstrap-cell +"box_alien" +"alien_offset" +"void*" define-primitive-type + +[ alien-signed-8 ] +[ set-alien-signed-8 ] +8 +"box_signed_8" +"to_signed_8" +"longlong" define-primitive-type + +[ alien-unsigned-8 ] +[ set-alien-unsigned-8 ] +8 +"box_unsigned_8" +"to_unsigned_8" +"ulonglong" define-primitive-type + +[ alien-signed-cell ] +[ set-alien-signed-cell ] +bootstrap-cell +"box_signed_cell" +"to_fixnum" +"long" define-primitive-type + +[ alien-unsigned-cell ] +[ set-alien-unsigned-cell ] +bootstrap-cell +"box_unsigned_cell" +"to_cell" +"ulong" define-primitive-type + +[ alien-signed-4 ] +[ set-alien-signed-4 ] +4 +"box_signed_4" +"to_fixnum" +"int" define-primitive-type + +[ alien-unsigned-4 ] +[ set-alien-unsigned-4 ] +4 +"box_unsigned_4" +"to_cell" +"uint" define-primitive-type + +[ alien-signed-2 ] +[ set-alien-signed-2 ] +2 +"box_signed_2" +"to_fixnum" +"short" define-primitive-type + +[ alien-unsigned-2 ] +[ set-alien-unsigned-2 ] +2 +"box_unsigned_2" +"to_cell" +"ushort" define-primitive-type + +[ alien-signed-1 ] +[ set-alien-signed-1 ] +1 +"box_signed_1" +"to_fixnum" +"char" define-primitive-type + +[ alien-unsigned-1 ] +[ set-alien-unsigned-1 ] +1 +"box_unsigned_1" +"to_cell" +"uchar" define-primitive-type + +[ alien-unsigned-4 zero? not ] +[ 1 0 ? set-alien-unsigned-4 ] +4 +"box_boolean" +"to_boolean" +"bool" define-primitive-type + +[ alien-float ] +[ >r >r >float r> r> set-alien-float ] +4 +"box_float" +"to_float" +"float" define-primitive-type + +T{ float-regs f 4 } "float" c-type set-c-type-reg-class +[ >float ] "float" c-type set-c-type-prep + +[ alien-double ] +[ >r >r >float r> r> set-alien-double ] +8 +"box_double" +"to_double" +"double" define-primitive-type + +T{ float-regs f 8 } "double" c-type set-c-type-reg-class +[ >float ] "double" c-type set-c-type-prep + +[ alien-cell alien>char-string ] +[ set-alien-cell ] +bootstrap-cell +"box_char_string" +"alien_offset" +"char*" define-primitive-type + +"char*" "uchar*" typedef + +[ string>char-alien ] "char*" c-type set-c-type-prep + +[ alien-cell alien>u16-string ] +[ set-alien-cell ] +4 +"box_u16_string" +"alien_offset" +"ushort*" define-primitive-type + +[ string>u16-alien ] "ushort*" c-type set-c-type-prep diff --git a/core/alien/c-types/summary.txt b/core/alien/c-types/summary.txt new file mode 100644 index 0000000000..da909c746d --- /dev/null +++ b/core/alien/c-types/summary.txt @@ -0,0 +1 @@ +C data type support diff --git a/core/alien/compiler/authors.txt b/core/alien/compiler/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/compiler/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/compiler/compiler.factor b/core/alien/compiler/compiler.factor new file mode 100644 index 0000000000..b63a110d85 --- /dev/null +++ b/core/alien/compiler/compiler.factor @@ -0,0 +1,366 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generator generator.registers generator.fixup +hashtables kernel math namespaces sequences words +inference.backend inference.dataflow system math.functions +math.parser classes alien.arrays alien.c-types alien.structs +alien.syntax cpu.architecture alien inspector quotations assocs +kernel.private threads continuations.private libc combinators ; +IN: alien.compiler + +! Common protocol for alien-invoke/alien-callback/alien-indirect +GENERIC: alien-node-parameters ( node -- seq ) +GENERIC: alien-node-return ( node -- ctype ) +GENERIC: alien-node-abi ( node -- str ) + +: large-struct? ( ctype -- ? ) + dup c-struct? [ + heap-size struct-small-enough? not + ] [ + drop f + ] if ; + +: alien-node-parameters* ( node -- seq ) + dup alien-node-parameters + swap alien-node-return large-struct? [ "void*" add* ] when ; + +: alien-node-return* ( node -- ctype ) + alien-node-return dup large-struct? [ drop "void" ] when ; + +: parameter-align ( n type -- n delta ) + over >r + dup c-type-stack-align? [ c-type-align ] [ drop cell ] if + align + dup r> - ; + +: parameter-sizes ( types -- total offsets ) + #! Compute stack frame locations. + [ + 0 [ + [ parameter-align drop dup , ] keep stack-size + + ] reduce cell align + ] { } make ; + +: return-size ( ctype -- n ) + #! Amount of space we reserve for a return value. + dup large-struct? [ heap-size ] [ drop 0 ] if ; + +: alien-stack-frame ( node -- n ) + alien-node-parameters* parameter-sizes drop ; + +: alien-invoke-frame ( node -- n ) + #! One cell is temporary storage, temp@ + dup alien-node-return return-size + swap alien-stack-frame + + cell + ; + +: set-stack-frame ( n -- ) + dup [ frame-required ] when* \ stack-frame set ; + +: with-stack-frame ( n quot -- ) + swap set-stack-frame + call + f set-stack-frame ; inline + +: reg-class-full? ( class -- ? ) + dup class get swap param-regs length >= ; + +: spill-param ( reg-class -- n reg-class ) + reg-size stack-params dup get -rot +@ T{ stack-params } ; + +: fastcall-param ( reg-class -- n reg-class ) + [ dup class get swap inc-reg-class ] keep ; + +: alloc-parameter ( parameter -- reg reg-class ) + c-type c-type-reg-class dup reg-class-full? + [ spill-param ] [ fastcall-param ] if + [ param-reg ] keep ; + +: (flatten-int-type) ( size -- ) + cell /i "void*" % ; + +: flatten-int-type ( n type -- n ) + [ parameter-align (flatten-int-type) ] keep + stack-size cell align dup (flatten-int-type) + ; + +: flatten-value-type ( n type -- n ) + dup c-type c-type-reg-class T{ int-regs } = + [ flatten-int-type ] [ , ] if ; + +: flatten-value-types ( params -- params ) + #! Convert value type structs to consecutive void*s. + [ 0 [ flatten-value-type ] reduce drop ] { } make ; + +: each-parameter ( parameters quot -- ) + >r [ parameter-sizes nip ] keep r> 2each ; inline + +: reverse-each-parameter ( parameters quot -- ) + >r [ parameter-sizes nip ] keep r> 2reverse-each ; inline + +: reset-freg-counts ( -- ) + { int-regs float-regs stack-params } [ 0 swap set ] each ; + +: with-param-regs ( quot -- ) + #! In quot you can call alloc-parameter + [ reset-freg-counts call ] with-scope ; inline + +: move-parameters ( node word -- ) + #! Moves values from C stack to registers (if word is + #! %load-param-reg) and registers to C stack (if word is + #! %save-param-reg). + swap + alien-node-parameters* + flatten-value-types + [ pick >r alloc-parameter r> execute ] each-parameter + drop ; inline + +: if-void ( type true false -- ) + pick "void" = [ drop nip call ] [ nip call ] if ; inline + +: alien-invoke-stack ( node extra -- ) + over alien-node-parameters length + dup reify-curries + over consume-values + dup alien-node-return "void" = 0 1 ? + swap produce-values ; + +: (make-prep-quot) ( parameters -- ) + dup empty? [ + drop + ] [ + unclip c-type c-type-prep % + \ >r , (make-prep-quot) \ r> , + ] if ; + +: make-prep-quot ( node -- quot ) + alien-node-parameters + [ (make-prep-quot) ] [ ] make ; + +: unbox-parameters ( offset node -- ) + alien-node-parameters [ + %prepare-unbox >r over + r> unbox-parameter + ] reverse-each-parameter drop ; + +: prepare-box-struct ( node -- offset ) + #! Return offset on C stack where to store unboxed + #! parameters. If the C function is returning a structure, + #! the first parameter is an implicit target area pointer, + #! so we need to use a different offset. + alien-node-return dup large-struct? + [ heap-size %prepare-box-struct cell ] [ drop 0 ] if ; + +: objects>registers ( node -- ) + #! Generate code for unboxing a list of C types, then + #! generate code for moving these parameters to register on + #! architectures where parameters are passed in registers. + [ + [ prepare-box-struct ] keep + [ unbox-parameters ] keep + \ %load-param-reg move-parameters + ] with-param-regs ; + +: box-return* ( node -- ) + alien-node-return [ ] [ box-return ] if-void ; + +M: alien-invoke alien-node-parameters alien-invoke-parameters ; +M: alien-invoke alien-node-return alien-invoke-return ; + +M: alien-invoke alien-node-abi + alien-invoke-library library + [ library-abi ] [ "cdecl" ] if* ; + +: stdcall-mangle ( symbol node -- symbol ) + "@" + swap alien-node-parameters parameter-sizes drop + number>string 3append ; + +: (alien-invoke-dlsym) ( node -- symbol dll ) + dup alien-invoke-function + swap alien-invoke-library load-library ; + +TUPLE: no-such-symbol ; + +M: no-such-symbol summary + drop "Symbol not found" ; + +: no-such-symbol ( -- ) + \ no-such-symbol inference-error ; + +: alien-invoke-dlsym ( node -- symbol dll ) + dup (alien-invoke-dlsym) 2dup dlsym [ + >r over stdcall-mangle r> 2dup dlsym + [ no-such-symbol ] unless + ] unless rot drop ; + +M: alien-invoke-error summary + drop "Words calling ``alien-invoke'' cannot run in the interpreter. Compile the caller word and try again." ; + +: pop-parameters pop-literal nip [ expand-constants ] map ; + +\ alien-invoke [ + ! Four literals + 4 ensure-values + \ alien-invoke empty-node + ! Compile-time parameters + pop-parameters over set-alien-invoke-parameters + pop-literal nip over set-alien-invoke-function + pop-literal nip over set-alien-invoke-library + pop-literal nip over set-alien-invoke-return + ! Quotation which coerces parameters to required types + dup make-prep-quot infer-quot + ! If symbol doesn't resolve, no stack effect, no compile + dup alien-invoke-dlsym 2drop + ! Add node to IR + dup node, + ! Magic #: consume exactly the number of inputs + 0 alien-invoke-stack +] "infer" set-word-prop + +M: alien-invoke generate-node + dup alien-invoke-frame [ + end-basic-block + %prepare-alien-invoke + dup objects>registers + dup alien-invoke-dlsym %alien-invoke + dup %cleanup + box-return* + iterate-next + ] with-stack-frame ; + +M: alien-indirect alien-node-parameters alien-indirect-parameters ; +M: alien-indirect alien-node-return alien-indirect-return ; +M: alien-indirect alien-node-abi alien-indirect-abi ; + +M: alien-indirect-error summary + drop "Words calling ``alien-indirect'' cannot run in the interpreter. Compile the caller word and try again." ; + +\ alien-indirect [ + ! Three literals and function pointer + 4 ensure-values + 4 reify-curries + \ alien-indirect empty-node + ! Compile-time parameters + pop-literal nip over set-alien-indirect-abi + pop-parameters over set-alien-indirect-parameters + pop-literal nip over set-alien-indirect-return + ! Quotation which coerces parameters to required types + dup make-prep-quot 1 make-dip infer-quot + ! Add node to IR + dup node, + ! Magic #: consume the function pointer, too + 1 alien-invoke-stack +] "infer" set-word-prop + +M: alien-indirect generate-node + dup alien-invoke-frame [ + ! Flush registers + end-basic-block + ! Save registers for GC + %prepare-alien-invoke + ! Save alien at top of stack to temporary storage + %prepare-alien-indirect + dup objects>registers + ! Call alien in temporary storage + %alien-indirect + dup %cleanup + box-return* + iterate-next + ] with-stack-frame ; + +! Callbacks are registered in a global hashtable. If you clear +! this hashtable, they will all be blown away by code GC, beware +SYMBOL: callbacks + +H{ } clone callbacks set-global + +: register-callback ( word -- ) dup callbacks get set-at ; + +M: alien-callback alien-node-parameters alien-callback-parameters ; +M: alien-callback alien-node-return alien-callback-return ; +M: alien-callback alien-node-abi alien-callback-abi ; + +M: alien-callback-error summary + drop "Words calling ``alien-callback'' cannot run in the interpreter. Compile the caller word and try again." ; + +: callback-bottom ( node -- ) + alien-callback-xt [ word-xt ] curry infer-quot ; + +\ alien-callback [ + 4 ensure-values + \ alien-callback empty-node dup node, + pop-literal nip over set-alien-callback-quot + pop-literal nip over set-alien-callback-abi + pop-parameters over set-alien-callback-parameters + pop-literal nip over set-alien-callback-return + gensym dup register-callback over set-alien-callback-xt + callback-bottom +] "infer" set-word-prop + +: box-parameters ( node -- ) + alien-node-parameters* [ box-parameter ] each-parameter ; + +: registers>objects ( node -- ) + [ + dup \ %save-param-reg move-parameters + "nest_stacks" f %alien-invoke + box-parameters + ] with-param-regs ; + +TUPLE: callback-context ; + +: current-callback 2 getenv ; + +: wait-to-return ( token -- ) + dup current-callback eq? [ + drop + ] [ + yield wait-to-return + ] if ; + +: do-callback ( quot token -- ) + init-error-handler + dup 2 setenv + slip + wait-to-return ; inline + +: prepare-callback-return ( ctype -- quot ) + alien-node-return { + { [ dup "void" = ] [ drop [ ] ] } + { [ dup large-struct? ] [ heap-size [ memcpy ] curry ] } + { [ t ] [ c-type c-type-prep ] } + } cond ; + +: wrap-callback-quot ( node -- quot ) + [ + dup alien-callback-quot + swap prepare-callback-return append , + [ callback-context construct-empty do-callback ] % + ] [ ] make ; + +: %unnest-stacks ( -- ) "unnest_stacks" f %alien-invoke ; + +: callback-unwind ( node -- n ) + { + { [ dup alien-node-abi "stdcall" = ] [ alien-stack-frame ] } + { [ dup alien-node-return large-struct? ] [ drop 4 ] } + { [ t ] [ drop 0 ] } + } cond ; + +: %callback-return ( node -- ) + #! All the extra book-keeping for %unwind is only for x86. + #! On other platforms its an alias for %return. + dup alien-node-return* + [ %unnest-stacks ] [ %callback-value ] if-void + callback-unwind %unwind ; + +: generate-callback ( node -- ) + dup alien-callback-xt dup rot [ + dup alien-stack-frame [ + init-templates + dup registers>objects + dup wrap-callback-quot %alien-callback + %callback-return + ] with-stack-frame + ] generate-1 ; + +M: alien-callback generate-node + end-basic-block generate-callback iterate-next ; diff --git a/core/alien/compiler/summary.txt b/core/alien/compiler/summary.txt new file mode 100644 index 0000000000..f5a0c6deb9 --- /dev/null +++ b/core/alien/compiler/summary.txt @@ -0,0 +1 @@ +C library interface implementation diff --git a/core/alien/remote-control/authors.txt b/core/alien/remote-control/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/remote-control/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/remote-control/remote-control.factor b/core/alien/remote-control/remote-control.factor new file mode 100644 index 0000000000..b7700c0ff1 --- /dev/null +++ b/core/alien/remote-control/remote-control.factor @@ -0,0 +1,25 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien alien.c-types parser threads words kernel.private +kernel ; +IN: alien.remote-control + +: eval-callback + "void*" { "char*" } "cdecl" + [ eval>string malloc-char-string ] alien-callback ; + +: yield-callback + "void" { } "cdecl" [ yield ] alien-callback ; + +: sleep-callback + "void" { "long" } "cdecl" [ sleep ] alien-callback ; + +: ?callback ( word -- alien ) + dup compiled? [ execute ] [ drop f ] if ; inline + +: init-remote-control ( -- ) + \ eval-callback ?callback 16 setenv + \ yield-callback ?callback 17 setenv + \ sleep-callback ?callback 18 setenv ; + +MAIN: init-remote-control diff --git a/core/alien/remote-control/summary.txt b/core/alien/remote-control/summary.txt new file mode 100644 index 0000000000..a65a66bec5 --- /dev/null +++ b/core/alien/remote-control/summary.txt @@ -0,0 +1 @@ +Support for embedding Factor in other applications diff --git a/core/alien/structs/authors.txt b/core/alien/structs/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/structs/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/structs/structs-docs.factor b/core/alien/structs/structs-docs.factor new file mode 100644 index 0000000000..704a260825 --- /dev/null +++ b/core/alien/structs/structs-docs.factor @@ -0,0 +1,6 @@ +USING: alien.structs alien.c-types strings help.markup +sequences io arrays ; + +M: string slot-specs c-type struct-type-fields ; + +M: array ($instance) first ($instance) " array" write ; diff --git a/core/alien/structs/structs-tests.factor b/core/alien/structs/structs-tests.factor new file mode 100644 index 0000000000..b2da0e8392 --- /dev/null +++ b/core/alien/structs/structs-tests.factor @@ -0,0 +1,42 @@ +IN: temporary +USING: alien alien.syntax alien.c-types kernel tools.test +sequences system libc words vocabs namespaces ; + +C-STRUCT: bar + { "int" "x" } + { { "int" 8 } "y" } ; + +[ 36 ] [ "bar" heap-size ] unit-test +[ t ] [ \ "bar" c-type c-type-getter memq? ] unit-test + +C-STRUCT: align-test + { "int" "x" } + { "double" "y" } ; + +[ 16 ] [ "align-test" heap-size ] unit-test + +cell 4 = [ + C-STRUCT: one + { "long" "a" } { "double" "b" } { "int" "c" } ; + + [ 24 ] [ "one" heap-size ] unit-test +] when + +: MAX_FOOS 30 ; + +C-STRUCT: foox + { { "int" MAX_FOOS } "x" } ; + +[ 120 ] [ "foox" heap-size ] unit-test + +C-UNION: barx + { "int" MAX_FOOS } + "float" ; + +[ 120 ] [ "barx" heap-size ] unit-test + +"help" vocab [ + "help" "help" lookup "help" set + [ ] [ \ foox-x "help" get execute ] unit-test + [ ] [ \ set-foox-x "help" get execute ] unit-test +] when diff --git a/core/alien/structs/structs.factor b/core/alien/structs/structs.factor new file mode 100644 index 0000000000..0afa9eafcb --- /dev/null +++ b/core/alien/structs/structs.factor @@ -0,0 +1,99 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generic hashtables kernel kernel.private math +namespaces parser sequences strings words libc slots +alien.c-types math.functions math.vectors cpu.architecture ; +IN: alien.structs + +: align-offset ( offset type -- offset ) + c-type c-type-align align ; + +: struct-offsets ( specs -- size ) + 0 [ + [ slot-spec-type align-offset ] keep + [ set-slot-spec-offset ] 2keep + slot-spec-type heap-size + + ] reduce ; + +: define-struct-slot-word ( spec word quot -- ) + rot slot-spec-offset add* define-inline ; + +: define-getter ( type spec -- ) + [ set-reader-props ] keep + dup slot-spec-reader + over slot-spec-type c-getter + define-struct-slot-word ; + +: define-setter ( type spec -- ) + [ set-writer-props ] keep + dup slot-spec-writer + over slot-spec-type c-setter + define-struct-slot-word ; + +: define-field ( type spec -- ) + 2dup define-getter define-setter ; + +: if-value-structs? ( ctype true false -- ) + value-structs? + [ drop call ] [ >r 2drop "void*" r> call ] if ; inline + +TUPLE: struct-type size align fields ; + +M: struct-type heap-size struct-type-size ; + +M: struct-type c-type-align struct-type-align ; + +M: struct-type c-type-stack-align? drop f ; + +M: struct-type unbox-parameter + [ heap-size %unbox-struct ] + [ unbox-parameter ] + if-value-structs? ; + +M: struct-type unbox-return + f swap heap-size %unbox-struct ; + +M: struct-type box-parameter + [ heap-size %box-struct ] + [ box-parameter ] + if-value-structs? ; + +M: struct-type box-return + f swap heap-size %box-struct ; + +M: struct-type stack-size + [ heap-size ] [ stack-size ] if-value-structs? ; + +: c-struct? ( type -- ? ) (c-type) struct-type? ; + +: (define-struct) ( name vocab size align fields -- ) + >r [ align ] keep r> + struct-type construct-boa + -rot define-c-type ; + +: make-field ( struct-name vocab type field-name -- spec ) + [ + -rot expand-constants , + over , + 3dup reader-word , + writer-word , + ] { } make + first4 0 -rot ; + +: define-struct-early ( name vocab fields -- fields ) + -rot [ rot first2 make-field ] 2curry map ; + +: compute-struct-align ( types -- n ) + [ c-type-align ] map supremum ; + +: define-struct ( name vocab fields -- ) + pick >r + [ struct-offsets ] keep + [ [ slot-spec-type ] map compute-struct-align ] keep + [ (define-struct) ] keep + r> [ swap define-field ] curry each ; + +: define-union ( name vocab members -- ) + [ expand-constants ] map + [ [ heap-size ] map supremum ] keep + compute-struct-align f (define-struct) ; diff --git a/core/alien/structs/summary.txt b/core/alien/structs/summary.txt new file mode 100644 index 0000000000..4825c5b781 --- /dev/null +++ b/core/alien/structs/summary.txt @@ -0,0 +1 @@ +C structure support diff --git a/core/alien/summary.txt b/core/alien/summary.txt new file mode 100644 index 0000000000..5ad1a8e80f --- /dev/null +++ b/core/alien/summary.txt @@ -0,0 +1 @@ +C library interface diff --git a/core/alien/syntax/authors.txt b/core/alien/syntax/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/alien/syntax/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/alien/syntax/summary.txt b/core/alien/syntax/summary.txt new file mode 100644 index 0000000000..35868441a2 --- /dev/null +++ b/core/alien/syntax/summary.txt @@ -0,0 +1 @@ +C library interface parsing words diff --git a/core/alien/syntax/syntax-docs.factor b/core/alien/syntax/syntax-docs.factor new file mode 100644 index 0000000000..eda7cc6b9f --- /dev/null +++ b/core/alien/syntax/syntax-docs.factor @@ -0,0 +1,94 @@ +USING: alien alien.c-types alien.structs alien.syntax +alien.syntax.private help.markup help.syntax ; + +HELP: DLL" +{ $syntax "DLL\" path\"" } +{ $values { "path" "a pathname string" } } +{ $description "Constructs a DLL handle at parse time." } ; + +HELP: ALIEN: +{ $syntax "ALIEN: address" } +{ $values { "address" "a non-negative integer" } } +{ $description "Creates an alien object at parse time." } +{ $notes "Alien objects are invalidated between image saves and loads." } ; + +ARTICLE: "syntax-aliens" "Alien object literal syntax" +{ $subsection POSTPONE: ALIEN: } +{ $subsection POSTPONE: DLL" } ; + +HELP: LIBRARY: +{ $syntax "LIBRARY: name" } +{ $values { "name" "a logical library name" } } +{ $description "Sets the logical library for consequent " { $link POSTPONE: FUNCTION: } " definitions that follow." } ; + +HELP: FUNCTION: +{ $syntax "FUNCTION: return name ( parameters )" } +{ $values { "return" "a C return type" } { "name" "a C function name" } { "parameters" "a comma-separated sequence of type/name pairs; " { $snippet "type1 arg1, type2 arg2, ..." } } } +{ $description "Defines a new word " { $snippet "name" } " which calls a C library function with the same name, in the logical library given by the most recent " { $link POSTPONE: LIBRARY: } " declaration." +$nl +"The new word must be compiled before being executed." } +{ $examples +"For example, suppose the " { $snippet "foo" } " library exports the following function:" +{ $code + "void the_answer(char* question, int value) {" + " printf(\"The answer to %s is %d.\n\",question,value);" + "}" +} +"You can define a word for invoking it:" +{ $unchecked-example + "LIBRARY: foo\nFUNCTION: void the_answer ( char* question, int value ) ;" + "USE: compiler" + "\\ the_answer compile" + "\"the question\" 42 the_answer" + "The answer to the question is 42." +} } +{ $notes "Note that the parentheses and commas are only syntax sugar and can be omitted; they serve no purpose other than to make the declaration slightly easier to read:" +{ $code + "FUNCTION: void glHint ( GLenum target, GLenum mode ) ;" + "FUNCTION: void glHint GLenum target GLenum mode ;" +} } ; + +HELP: TYPEDEF: +{ $syntax "TYPEDEF: old new" } +{ $values { "old" "a C type" } { "new" "a C type" } } +{ $description "Alises the C type " { $snippet "old" } " under the name " { $snippet "new" } "." } +{ $notes "This word differs from " { $link typedef } " in that it runs at parse time, to ensure correct ordering of operations when loading source files. Words defined in source files are compiled before top-level forms are run, so if a source file defines C binding words and uses " { $link typedef } ", the type alias won't be available at compile time." } ; + +HELP: C-STRUCT: +{ $syntax "C-STRUCT: name pairs... ;" } +{ $values { "name" "a new C type name" } { "pairs" "C type / field name string pairs" } } +{ $description "Defines a C struct layout and accessor words." } +{ $notes "C type names are documented in " { $link "c-types-specs" } "." } ; + +HELP: C-UNION: +{ $syntax "C-UNION: name members... ;" } +{ $values { "name" "a new C type name" } { "members" "a sequence of C types" } } +{ $description "Defines a new C type sized to fit its largest member." } +{ $notes "C type names are documented in " { $link "c-types-specs" } "." } +{ $examples { $code "C-UNION: event \"active-event\" \"keyboard-event\" \"mouse-event\" ;" } } ; + +HELP: C-ENUM: +{ $syntax "C-ENUM: words... ;" } +{ $values { "words" "a sequence of word names" } } +{ $description "Creates a sequence of compound definitions in the current vocabulary. Each word pushes an integer according to its index in the enumeration definition. The first word pushes 0." } +{ $notes "This word emulates a C-style " { $snippet "enum" } " in Factor. While this feature can be used for any purpose, using integer constants is discouraged unless it is for interfacing with C libraries. Factor code should use symbolic constants instead." } +{ $examples + "The following two lines are equivalent:" + { $code "C-ENUM: red green blue ;" ": red 0 ; : green 1 ; : blue 2 ;" } +} ; + +HELP: typedef +{ $values { "old" "a string" } { "new" "a string" } } +{ $description "Alises the C type " { $snippet "old" } " under the name " { $snippet "new" } "." } +{ $notes "Using this word in the same source file which defines C bindings can cause problems, because words are compiled before top-level forms are run. Use the " { $link POSTPONE: TYPEDEF: } " word instead." } ; + +{ typedef POSTPONE: TYPEDEF: } related-words + +HELP: c-struct? +{ $values { "type" "a string" } { "?" "a boolean" } } +{ $description "Tests if a C type is a structure defined by " { $link POSTPONE: C-STRUCT: } "." } ; + +HELP: define-function +{ $values { "return" "a C return type" } { "library" "a logical library name" } { "function" "a C function name" } { "parameters" "a sequence of C parameter types" } } +{ $description "Defines a word named " { $snippet "function" } " in the current vocabulary (see " { $link "vocabularies" } "). The word calls " { $link alien-invoke } " with the specified parameters." } +{ $notes "This word is used to implement the " { $link POSTPONE: FUNCTION: } " parsing word." } ; diff --git a/core/alien/syntax/syntax.factor b/core/alien/syntax/syntax.factor new file mode 100644 index 0000000000..d204390d00 --- /dev/null +++ b/core/alien/syntax/syntax.factor @@ -0,0 +1,62 @@ +! Copyright (C) 2005, 2007 Slava Pestov, Alex Chapman. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays alien alien.c-types alien.structs kernel math +namespaces parser sequences words quotations math.parser +splitting effects prettyprint prettyprint.sections +prettyprint.backend assocs ; +IN: alien.syntax + + ; + +: function-quot ( type lib func types -- quot ) + [ alien-invoke ] 2curry 2curry ; + +: define-function ( return library function parameters -- ) + >r pick r> parse-arglist + pick create-in dup reset-generic + >r >r function-quot r> r> + -rot define-declared ; + +PRIVATE> + +: DLL" skip-blank parse-string dlopen parsed ; parsing + +: ALIEN: scan string>number parsed ; parsing + +: LIBRARY: scan "c-library" set ; parsing + +: FUNCTION: + scan "c-library" get scan ";" parse-tokens + [ "()" subseq? not ] subset + define-function ; parsing + +: TYPEDEF: + scan scan typedef ; parsing + +: C-STRUCT: + scan in get + parse-definition + >r 2dup r> define-struct-early + define-struct ; parsing + +: C-UNION: + scan in get parse-definition define-union ; parsing + +: C-ENUM: + ";" parse-tokens + dup length + [ >r create-in r> 1quotation define-compound ] 2each ; + parsing + +M: alien pprint* + dup expired? [ + drop "( alien expired )" text + ] [ + \ ALIEN: [ alien-address pprint* ] pprint-prefix + ] if ; + +M: dll pprint* dll-path dup "DLL\" " pprint-string ; diff --git a/core/alien/tags.txt b/core/alien/tags.txt new file mode 100644 index 0000000000..86a7c8e637 --- /dev/null +++ b/core/alien/tags.txt @@ -0,0 +1 @@ +compiler diff --git a/core/arrays/arrays-docs.factor b/core/arrays/arrays-docs.factor new file mode 100644 index 0000000000..83a948a939 --- /dev/null +++ b/core/arrays/arrays-docs.factor @@ -0,0 +1,70 @@ +USING: byte-arrays bit-arrays help.markup help.syntax +kernel kernel.private prettyprint strings sbufs vectors +quotations sequences.private ; +IN: arrays + +ARTICLE: "arrays" "Arrays" +"Arrays are fixed-size mutable sequences (" { $link "sequence-protocol" } "). The literal syntax is covered in " { $link "syntax-arrays" } ". Resizable arrays also exist and are called vectors; see " { $link "vectors" } "." +$nl +"Array words are in the " { $vocab-link "arrays" } " vocabulary. Unsafe implementation words are in the " { $vocab-link "sequences.private" } " vocabulary." +$nl +"Arrays form a class of objects:" +{ $subsection array } +{ $subsection array? } +"Creating new arrays:" +{ $subsection >array } +{ $subsection } +"Creating an array from several elements on the stack:" +{ $subsection 1array } +{ $subsection 2array } +{ $subsection 3array } +{ $subsection 4array } +"Arrays can be accessed without bounds checks in a pointer unsafe way." +{ $subsection array-nth } +{ $subsection set-array-nth } +"The class of two-element arrays:" +{ $subsection pair } ; + +ABOUT: "arrays" + +HELP: array +{ $description "The class of fixed-length arrays. See " { $link "syntax-arrays" } " for syntax and " { $link "arrays" } " for general information." } ; + +HELP: ( n elt -- array ) +{ $values { "n" "a non-negative integer" } { "elt" "an initial element" } { "array" "a new array" } } +{ $description "Creates a new array with the given length and all elements initially set to " { $snippet "elt" } "." } ; + +{ } +related-words + +HELP: >array +{ $values { "seq" "a sequence" } { "array" array } } +{ $description "Outputs a freshly-allocated array with the same elements as a given sequence." } ; + +{ >array >quotation >string >sbuf >vector >byte-array >bit-array } +related-words + +HELP: 1array +{ $values { "x" object } { "array" array } } +{ $description "Create a new array with one element." } ; + +{ 1array 2array 3array 4array } related-words + +HELP: 2array +{ $values { "x" object } { "y" object } { "array" array } } +{ $description "Create a new array with two elements, with " { $snippet "x" } " appearing first." } ; + +HELP: 3array +{ $values { "x" object } { "y" object } { "z" object } { "array" array } } +{ $description "Create a new array with three elements, with " { $snippet "x" } " appearing first." } ; + +HELP: 4array +{ $values { "w" object } { "x" object } { "y" object } { "z" object } { "array" array } } +{ $description "Create a new array with four elements, with " { $snippet "w" } " appearing first." } ; + +HELP: resize-array ( n array -- newarray ) +{ $values { "n" "a non-negative integer" } { "array" array } { "newarray" "a new array" } } +{ $description "Creates a new array of " { $snippet "n" } " elements. The contents of the existing array are copied into the new array; if the new array is shorter, only an initial segment is copied, and if the new array is longer the remaining space is filled in with "{ $link f } "." } ; + +HELP: pair +{ $class-description "The class of two-element arrays, known as pairs." } ; diff --git a/core/arrays/arrays-tests.factor b/core/arrays/arrays-tests.factor new file mode 100644 index 0000000000..2c550fe724 --- /dev/null +++ b/core/arrays/arrays-tests.factor @@ -0,0 +1,22 @@ +USING: arrays kernel sequences sequences.private growable +tools.test vectors layouts system math math.functions +vectors.private ; +IN: temporary + +[ -2 { "a" "b" "c" } nth ] unit-test-fails +[ 10 { "a" "b" "c" } nth ] unit-test-fails +[ "hi" -2 { "a" "b" "c" } set-nth ] unit-test-fails +[ "hi" 10 { "a" "b" "c" } set-nth ] unit-test-fails +[ f ] [ { "a" "b" "c" } dup clone eq? ] unit-test +[ "hi" ] [ "hi" 1 { "a" "b" "c" } clone [ set-nth ] keep second ] unit-test +[ V{ "a" "b" "c" } ] [ { "a" "b" "c" } >vector ] unit-test +[ f ] [ { "a" "b" "c" } dup >array eq? ] unit-test +[ t ] [ { "a" "b" "c" } dup { } like eq? ] unit-test +[ t ] [ { "a" "b" "c" } dup dup length array>vector underlying eq? ] unit-test +[ V{ "a" "b" "c" } ] [ { "a" "b" "c" } V{ } like ] unit-test +[ { "a" "b" "c" } ] [ { "a" } { "b" "c" } append ] unit-test +[ { "a" "b" "c" "d" "e" } ] +[ { "a" } { "b" "c" } { "d" "e" } 3append ] unit-test + +[ -1 f ] unit-test-fails +[ cell-bits cell log2 - 2^ f ] unit-test-fails diff --git a/core/arrays/arrays.factor b/core/arrays/arrays.factor new file mode 100644 index 0000000000..714973e7ca --- /dev/null +++ b/core/arrays/arrays.factor @@ -0,0 +1,34 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel kernel.private math math.private sequences +sequences.private ; +IN: arrays + +M: array clone (clone) ; +M: array length array-capacity ; +M: array nth-unsafe >r >fixnum r> array-nth ; +M: array set-nth-unsafe >r >fixnum r> set-array-nth ; +M: array resize resize-array ; + +: >array ( seq -- array ) { } clone-like ; + +M: object new drop f ; + +M: f new drop dup zero? [ drop f ] [ f ] if ; + +M: array like drop dup array? [ >array ] unless ; + +M: array equal? + over array? [ sequence= ] [ 2drop f ] if ; + +INSTANCE: array sequence + +: 1array ( x -- array ) 1 swap ; flushable + +: 2array ( x y -- array ) { } 2sequence ; flushable + +: 3array ( x y z -- array ) { } 3sequence ; flushable + +: 4array ( w x y z -- array ) { } 4sequence ; flushable + +PREDICATE: array pair length 2 number= ; diff --git a/core/arrays/authors.txt b/core/arrays/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/arrays/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/arrays/summary.txt b/core/arrays/summary.txt new file mode 100644 index 0000000000..82a1e04f42 --- /dev/null +++ b/core/arrays/summary.txt @@ -0,0 +1 @@ +Fixed-size arrays diff --git a/core/arrays/tags.txt b/core/arrays/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/core/arrays/tags.txt @@ -0,0 +1 @@ +collections diff --git a/core/assocs/assocs-docs.factor b/core/assocs/assocs-docs.factor new file mode 100644 index 0000000000..1805ee05b5 --- /dev/null +++ b/core/assocs/assocs-docs.factor @@ -0,0 +1,296 @@ +! Copyright (C) 2007 Daniel Ehrenberg and Slava Pestov +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax kernel sequences +sequences.private namespaces classes math ; +IN: assocs + +ARTICLE: "alists" "Association lists" +"An " { $emphasis "association list" } ", abbreviated " { $emphasis "alist" } ", is an association represented as a sequence where all elements are key/value pairs. The " { $link sequence } " mixin is an instance of the " { $link assoc } " mixin, hence all sequences support the " { $link "assocs-protocol" } " in this way." +$nl +"While not an association list, note that " { $link f } " also implements the associative mapping protocol in a trivial way; it is an immutable assoc with no entries." +$nl +"An alist is slower to search than a hashtable for a large set of associations. The main advantage of an association list is that the elements are ordered; also sometimes it is more convenient to construct an association list with sequence words than to construct a hashtable with association words. Much of the time, hashtables are more appropriate. See " { $link "hashtables" } "." +$nl +"There is no special syntax for literal alists since they are just sequences; in practice, literals look like so:" +{ $code "{" " { key1 value1 }" " { key2 value2 }" "}" } +"To make an assoc into an alist:" +{ $subsection >alist } ; + +ARTICLE: "assocs-protocol" "Associative mapping protocol" +"All associative mappings must be instances of a mixin class:" +{ $subsection assoc } +{ $subsection assoc? } +"All associative mappings must implement methods on the following generic words:" +{ $subsection at* } +{ $subsection assoc-size } +"At least one of the following two generic words must have a method; the " { $link assoc } " mixin has default definitions which are mutually recursive:" +{ $subsection >alist } +{ $subsection assoc-find } +"Mutable assocs should implement the following additional words:" +{ $subsection set-at } +{ $subsection delete-at } +{ $subsection clear-assoc } +"The following two words are optional:" +{ $subsection new-assoc } +{ $subsection assoc-like } +"Assocs should also implement methods on the " { $link clone } ", " { $link equal? } " and " { $link hashcode } " generic words. Two utility words will help with the implementation of the last two:" +{ $subsection assoc= } +{ $subsection assoc-hashcode } +"Finally, assoc classes should define a word for converting other types of assocs; conventionally, such words are named " { $snippet ">" { $emphasis "class" } } " where " { $snippet { $emphasis "class" } } " is the class name. Such a word can be implemented using a utility:" +{ $subsection assoc-clone-like } ; + +ARTICLE: "assocs-lookup" "Lookup and querying of assocs" +"Utility operations built up from the " { $link "assocs-protocol" } ":" +{ $subsection key? } +{ $subsection at } +{ $subsection value-at } +{ $subsection assoc-empty? } +{ $subsection keys } +{ $subsection values } +{ $subsection assoc-stack } +{ $see-also at* assoc-size } ; + +ARTICLE: "assocs-sets" "Set-theoretic operations on assocs" +"It is often useful to use the keys of an associative mapping as a set, exploiting the constant or logarithmic lookup time of most implementations (" { $link "alists" } " being a notable exception)." +{ $subsection subassoc? } +{ $subsection intersect } +{ $subsection update } +{ $subsection union } +{ $subsection diff } +{ $subsection remove-all } +{ $subsection substitute } +{ $see-also key? } ; + +ARTICLE: "assocs-mutation" "Storing keys and values in assocs" +"Utility operations built up from the " { $link "assocs-protocol" } ":" +{ $subsection delete-at* } +{ $subsection rename-at } +{ $subsection change-at } +{ $subsection at+ } +{ $see-also set-at delete-at clear-assoc } ; + +ARTICLE: "assocs-combinators" "Associative mapping combinators" +"The following combinators can be used on any associative mapping." +$nl +"The " { $link assoc-find } " combinator is part of the " { $link "assocs-protocol" } " and must be implemented once for each class of assoc. All other combinators are implemented in terms of this combinator." +$nl +"The standard functional programming idioms:" +{ $subsection assoc-each } +{ $subsection assoc-map } +{ $subsection assoc-push-if } +{ $subsection assoc-subset } +{ $subsection assoc-all? } +"Three additional combinators:" +{ $subsection cache } +{ $subsection map>assoc } +{ $subsection assoc>map } ; + +ARTICLE: "assocs" "Associative mapping operations" +"An " { $emphasis "associative mapping" } ", abbreviated " { $emphasis "assoc" } ", is a collection of key/value pairs which provides efficient lookup and storage indexed by key." +$nl +"Words used for working with assocs are in the " { $vocab-link "assocs" } " vocabulary." +$nl +"Associative mappings implement a protocol:" +{ $subsection "assocs-protocol" } +"A large set of utility words work on any object whose class implements the associative mapping protocol." +{ $subsection "assocs-lookup" } +{ $subsection "assocs-mutation" } +{ $subsection "assocs-combinators" } +{ $subsection "assocs-sets" } ; + +ABOUT: "assocs" + +HELP: assoc +{ $class-description "A mixin class whose instances are associative mappings. Custom implementations of the assoc protocol should be declared as instances of this mixin for all assoc functionality to work correctly:" + { $code "INSTANCE: avl-tree assoc" } +} ; + +HELP: at* +{ $values { "key" "an object to look up in the assoc" } { "assoc" assoc } { "value/f" "the value associated to the key, or " { $link f } " if the key is not present in the assoc" } { "?" "a boolean indicating if the key was present" } } +{ $contract "Looks up the value associated with a key. The boolean flag can decide between the case of a missing value, and a value of " { $link f } "." } ; + +HELP: set-at +{ $values { "value" "a value" } { "key" "a key to add" } { "assoc" assoc } } +{ $contract "Stores the key/value pair into the assoc." } +{ $side-effects "assoc" } ; + +HELP: new-assoc +{ $values { "capacity" "a non-negative integer" } { "exemplar" assoc } { "newassoc" assoc } } +{ $contract "Creates a new assoc of the same size as " { $snippet "exemplar" } " which can hold " { $snippet "capacity" } " entries before growing." } ; + +HELP: assoc-find +{ $values { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "key" "the successful key, or f" } { "value" "the successful value, or f" } { "?" "a boolean" } } +{ $contract "Applies a predicate quotation to each entry in the assoc. Returns the key or value that the quotation succeeds on, or " { $link f } " for both if the quotation fails. It also returns a boolean describing whether there was anything found." } +{ $notes "The " { $link assoc } " mixin has a default implementation for this generic word which first converts the assoc to an association list, then iterates over that with the " { $link find } " combinator for sequences." } ; + +HELP: clear-assoc +{ $values { "assoc" assoc } } +{ $contract "Removes all entries from the assoc." } +{ $side-effects "assoc" } ; + +HELP: delete-at +{ $values { "key" "a key" } { "assoc" assoc } } +{ $contract "Removes an entry from the assoc." } +{ $side-effects "assoc" } ; + +HELP: assoc-size +{ $values { "assoc" assoc } { "n" "a non-negative integer" } } +{ $contract "Outputs the number of entries stored in the assoc." } ; + +HELP: assoc-like +{ $values { "assoc" assoc } { "exemplar" assoc } { "newassoc" "a new assoc" } } +{ $contract "Creates a new assoc having the same entries as "{ $snippet "assoc" } " and the same type as " { $snippet "exemplar" } "." } ; + +HELP: assoc-empty? +{ $values { "assoc" assoc } { "?" "a boolean" } } +{ $description "Tests if the assoc contains no entries." } ; + +HELP: key? +{ $values { "key" object } { "assoc" assoc } { "?" "a boolean" } } +{ $description "Tests if an assoc contains a key." } ; + +{ at at* key? } related-words + +HELP: at +{ $values { "key" "an object" } { "assoc" assoc } { "value/f" "the value associated to the key, or " { $link f } " if the key is not present in the assoc" } } +{ $description "Looks up the value associated with a key. This word makes no distinction between a missing value and a value set to " { $link f } "; if the difference is important, use " { $link at* } "." } ; + +HELP: assoc-each +{ $values { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key value -- )" } } } +{ $description "Applies a quotation to each entry in the assoc." } +{ $examples + { $example + "H{ { \"bananas\" 5 } { \"apples\" 42 } { \"pears\" 17 } }" + "0 swap [ nip + ] assoc-each ." + "64" + } +} ; + +HELP: assoc-map +{ $values { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key value -- newkey newvalue )" } } { "newassoc" "a new assoc" } } +{ $description "Applies the quotation to each entry in the input assoc and collects the results in a new assoc of the same type as the input." } +{ $examples + { $unchecked-example + ": discount ( prices n -- newprices )" + " [ - ] curry assoc-each ;" + "H{ { \"bananas\" 5 } { \"apples\" 42 } { \"pears\" 17 } }" + "2 discount ." + "H{ { \"bananas\" 3 } { \"apples\" 39 } { \"pears\" 15 } }" + } +} ; + +HELP: assoc-push-if +{ $values { "accum" "a resizable mutable sequence" } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "key" object } { "value" object } } +{ $description "If the quotation yields true when applied to the key/value pair, adds the key/value pair at the end of " { $snippet "accum" } "." } ; + +HELP: assoc-subset +{ $values { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "subassoc" "a new assoc" } } +{ $description "Outputs an assoc of the same type as " { $snippet "assoc" } " consisting of all entries for which the predicate quotation yields true." } ; + +HELP: assoc-all? +{ $values { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key value -- ? )" } } { "?" "a boolean" } } +{ $description "Applies a predicate quotation to entry in the assoc. Outputs true if the assoc yields true for each entry (which includes the case where the assoc is empty)." } ; + +HELP: subassoc? +{ $values { "assoc1" assoc } { "assoc2" assoc } { "?" "a new assoc" } } +{ $description "Tests if " { $snippet "assoc2" } " contains all key/value pairs of " { $snippet "assoc1" } "." } ; + +HELP: assoc= +{ $values { "assoc1" assoc } { "assoc2" assoc } { "?" "a boolean" } } +{ $description "Tests if two assocs contain the same entries. Unlike " { $link = } ", the two assocs may be of different types." } +{ $notes "Assoc implementations should define a method for the " { $link equal? } " generic word which calls this word after checking that both inputs have the same type." } ; + +HELP: assoc-hashcode +{ $values { "n" "a non-negative integer" } { "assoc" assoc } { "code" integer } } +{ $description "Computes a hashcode for an assoc, such that equal assocs will have the same hashcode." } +{ $notes "Custom assoc implementations should use this word to implement a method for the " { $link hashcode* } " generic word." } ; + +HELP: assoc-stack +{ $values { "key" "a key" } { "seq" "a sequence of assocs" } { "value" "a value or " { $link f } } } +{ $description "Searches for the key in successive elements of the sequence, starting from the end. If an assoc containing the key is found, the associated value is output. If no assoc contains the key, outputs " { $link f } "." } +{ $notes "This word is used to implement abstractions such as nested scopes; if the sequence is a stack represented by a vector, then the most recently pushed assoc -- the innermost scope -- will be searched first." } ; + +HELP: value-at +{ $values { "value" "an object" } { "assoc" assoc } { "key/f" "the key associated to the value, or " { $link f } } } +{ $description "Looks up the key associated with a value. No distinction is made between a missing key and a key set to " { $link f } "." } +{ $notes "This word runs in linear time, proportional to the number of entries in the assoc." } ; + +HELP: delete-at* +{ $values { "key" "a key" } { "assoc" assoc } { "old" "the previous value or " { $link f } } { "?" "a boolean" } } +{ $description "Removes an entry from the assoc and outputs the previous value together with a boolean indicating whether it was present." } +{ $side-effects "assoc" } ; + +HELP: rename-at +{ $values { "newkey" object } { "key" object } { "assoc" assoc } } +{ $description "Removes the values associated to " { $snippet "key" } " and re-adds it as " { $snippet "newkey" } ". Does nothing if the assoc does not contain " { $snippet "key" } "." } +; + +HELP: keys +{ $values { "assoc" assoc } { "keys" "an array of keys" } } +{ $description "Outputs an array of all keys in the assoc." } ; + +HELP: values +{ $values { "assoc" assoc } { "values" "an array of values" } } +{ $description "Outputs an array of all values in the assoc." } ; + +{ keys values } related-words + +HELP: intersect +{ $values { "assoc1" assoc } { "assoc2" assoc } { "intersection" "a new assoc" } } +{ $description "Outputs an assoc consisting of all entries from " { $snippet "assoc2" } " such that the key is also present in " { $snippet "assoc1" } "." } +{ $notes "The values of the keys in " { $snippet "assoc1" } " are disregarded, so this word is usually used for set-theoretic calculations where the assoc in question either has dummy sentinels as values, or the values equal the keys." } ; + +HELP: update +{ $values { "assoc1" assoc } { "assoc2" assoc } } +{ $description "Adds all entries from " { $snippet "assoc2" } " to " { $snippet "assoc1" } "." } +{ $side-effects "assoc1" } ; + +HELP: union +{ $values { "assoc1" assoc } { "assoc2" assoc } { "union" "a new assoc" } } +{ $description "Outputs a assoc consisting of all entries from " { $snippet "assoc1" } " and " { $snippet "assoc2" } ", with entries from " { $snippet "assoc2" } " taking precedence in case the corresponding values are not equal." } ; + +HELP: diff +{ $values { "assoc1" assoc } { "assoc2" assoc } { "diff" "a new assoc" } } +{ $description "Outputs an assoc consisting of all entries from " { $snippet "assoc2" } " whose key is not contained in " { $snippet "assoc1" } "." } +; +HELP: remove-all +{ $values { "assoc" assoc } { "seq" "a sequence" } { "subseq" "a new sequence" } } +{ $description "Constructs a sequence consisting of all elements in " { $snippet "seq" } " which do not appear as keys in " { $snippet "assoc" } "." } +{ $notes "The values of the keys in the assoc are disregarded, so this word is usually used for set-theoretic calculations where the assoc in question either has dummy sentinels as values, or the values equal the keys." } +{ $side-effects "assoc" } ; + +HELP: substitute +{ $values { "assoc" assoc } { "seq" "a mutable sequence" } } +{ $description "Replaces elements of " { $snippet "seq" } " which appear in as keys in " { $snippet "assoc" } " with the corresponding values, acting as the identity on all other elements." } +{ $errors "Throws an error if " { $snippet "assoc" } " contains values whose types are not permissible in " { $snippet "seq" } "." } +{ $side-effects "seq" } ; + +HELP: cache +{ $values { "key" "a key" } { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key -- value )" } } { "value" "a previously-retained or freshly-computed value" } } +{ $description "If the key is present in the assoc, outputs the associated value, otherwise calls the quotation to produce a value and stores the key/value pair into the assoc." } +{ $side-effects "assoc" } ; + +HELP: map>assoc +{ $values { "seq" "a sequence" } { "quot" "a quotation with stack effect " { $snippet "( elt -- key value )" } } { "exemplar" assoc } { "assoc" "a new assoc" } } +{ $description "Applies the quotation to each element of the sequence, and collects the keys and values into a new assoc having the same type as " { $snippet "exemplar" } "." } ; + +HELP: assoc>map +{ $values { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( key value -- elt )" } } { "exemplar" "a sequence" } { "seq" "a new sequence" } } +{ $description "Applies the quotation to each entry of the assoc and collects the results into a new sequence of the same type as the exemplar." } ; + +HELP: change-at +{ $values { "key" object } { "assoc" assoc } { "quot" "a quotation with stack effect " { $snippet "( value -- newvalue )" } } } +{ $description "Applies the quotation to the value associated with " { $snippet "key" } ", storing the new value back in the assoc." } +{ $side-effects "assoc" } ; + +{ change-at change-nth change } related-words + +HELP: at+ +{ $values { "n" number } { "key" object } { "assoc" assoc } } +{ $description "Adds " { $snippet "n" } " to the value associated with " { $snippet "key" } "; if there is no value, stores " { $snippet "n" } ", thus behaving as if the value was 0." } +{ $side-effects "assoc" } ; + +HELP: >alist +{ $values { "assoc" assoc } { "newassoc" "an array of key/value pairs" } } +{ $contract "Converts an associative structure into an association list." } +{ $notes "The " { $link assoc } " mixin has a default implementation for this generic word which constructs the association list by iterating over the assoc with " { $link assoc-find } "." } ; diff --git a/core/assocs/assocs-tests.factor b/core/assocs/assocs-tests.factor new file mode 100644 index 0000000000..b38ce82052 --- /dev/null +++ b/core/assocs/assocs-tests.factor @@ -0,0 +1,89 @@ +IN: temporary +USING: kernel math namespaces tools.test vectors sequences +sequences.private hashtables io prettyprint assocs +continuations ; + +[ t ] [ H{ } dup subassoc? ] unit-test +[ f ] [ H{ { 1 3 } } H{ } subassoc? ] unit-test +[ t ] [ H{ } H{ { 1 3 } } subassoc? ] unit-test +[ t ] [ H{ { 1 3 } } H{ { 1 3 } } subassoc? ] unit-test +[ f ] [ H{ { 1 3 } } H{ { 1 "hey" } } subassoc? ] unit-test +[ f ] [ H{ { 1 f } } H{ } subassoc? ] unit-test +[ t ] [ H{ { 1 f } } H{ { 1 f } } subassoc? ] unit-test + +! Test some combinators +[ + { 4 14 32 } +] [ + [ + H{ + { 1 2 } + { 3 4 } + { 5 6 } + } [ * 2 + , ] assoc-each + ] { } make +] unit-test + +[ t ] [ H{ } [ 2drop f ] assoc-all? ] unit-test +[ t ] [ H{ { 1 1 } } [ = ] assoc-all? ] unit-test +[ f ] [ H{ { 1 2 } } [ = ] assoc-all? ] unit-test +[ t ] [ H{ { 1 1 } { 2 2 } } [ = ] assoc-all? ] unit-test +[ f ] [ H{ { 1 2 } { 2 2 } } [ = ] assoc-all? ] unit-test + +[ H{ } ] [ H{ { t f } { f t } } [ 2drop f ] assoc-subset ] unit-test +[ H{ { 3 4 } { 4 5 } { 6 7 } } ] [ + H{ { 1 2 } { 2 3 } { 3 4 } { 4 5 } { 6 7 } } + [ drop 3 >= ] assoc-subset +] unit-test + +[ 21 ] [ + 0 H{ + { 1 2 } + { 3 4 } + { 5 6 } + } [ + + + + ] assoc-each +] unit-test + +H{ } clone "cache-test" set + +[ 4 ] [ 1 "cache-test" get [ 3 + ] cache ] unit-test +[ 5 ] [ 2 "cache-test" get [ 3 + ] cache ] unit-test +[ 4 ] [ 1 "cache-test" get [ 3 + ] cache ] unit-test +[ 5 ] [ 2 "cache-test" get [ 3 + ] cache ] unit-test + +[ + H{ { "factor" "rocks" } { 3 4 } } +] [ + H{ { "factor" "rocks" } { "dup" "sq" } { 3 4 } } + H{ { "factor" "rocks" } { 1 2 } { 2 3 } { 3 4 } } + intersect +] unit-test + +[ + H{ { 1 2 } { 2 3 } { 6 5 } } +] [ + H{ { 2 4 } { 6 5 } } H{ { 1 2 } { 2 3 } } + union +] unit-test + +[ H{ { 1 2 } { 2 3 } } t ] [ + f H{ { 1 2 } { 2 3 } } [ union ] 2keep swap union dupd = +] unit-test + +[ + H{ { 1 f } } +] [ + H{ { 1 f } } H{ { 1 f } } intersect +] unit-test + +[ { 1 3 } ] [ H{ { 2 2 } } { 1 2 3 } remove-all ] unit-test + +[ H{ { "hi" 2 } { 3 4 } } ] +[ "hi" 1 H{ { 1 2 } { 3 4 } } clone [ rename-at ] keep ] +unit-test + +[ H{ { 1 2 } { 3 4 } } ] +[ "hi" 5 H{ { 1 2 } { 3 4 } } clone [ rename-at ] keep ] +unit-test diff --git a/core/assocs/assocs.factor b/core/assocs/assocs.factor new file mode 100644 index 0000000000..95b5dd9600 --- /dev/null +++ b/core/assocs/assocs.factor @@ -0,0 +1,179 @@ +! Copyright (C) 2007 Daniel Ehrenberg +! See http://factorcode.org/license.txt for BSD license. +USING: kernel sequences arrays math sequences.private vectors ; +IN: assocs + +MIXIN: assoc + +GENERIC: at* ( key assoc -- value/f ? ) +GENERIC: set-at ( value key assoc -- ) +GENERIC: new-assoc ( capacity exemplar -- newassoc ) +GENERIC: delete-at ( key assoc -- ) +GENERIC: clear-assoc ( assoc -- ) +GENERIC: assoc-size ( assoc -- n ) +GENERIC: assoc-like ( assoc exemplar -- newassoc ) + +M: assoc assoc-like drop ; + +GENERIC: assoc-clone-like ( assoc exemplar -- newassoc ) + +GENERIC: >alist ( assoc -- newassoc ) + +GENERIC# assoc-find 1 ( assoc quot -- key value ? ) inline + +M: assoc assoc-find + >r >alist [ first2 ] r> compose find swap + [ first2 t ] [ drop f f f ] if ; + +: key? ( key assoc -- ? ) at* nip ; inline + +: assoc-each ( assoc quot -- ) + [ f ] compose assoc-find 3drop ; inline + +: (assoc>map) ( quot accum -- quot' ) + [ push ] curry compose ; inline + +: assoc>map ( assoc quot exemplar -- seq ) + >r over assoc-size + [ (assoc>map) assoc-each ] keep + r> like ; inline + +: assoc-map ( assoc quot -- newassoc ) + over >r [ 2array ] compose V{ } assoc>map r> assoc-like ; + inline + +: assoc-push-if ( key value quot accum -- ) + >r pick pick 2slip r> roll + [ >r 2array r> push ] [ 3drop ] if ; inline + +: assoc-pusher ( quot -- quot' accum ) + V{ } clone [ [ assoc-push-if ] 2curry ] keep ; inline + +: assoc-subset ( assoc quot -- subassoc ) + over >r assoc-pusher >r assoc-each r> r> assoc-like ; inline + +: assoc-all? ( assoc quot -- ? ) + [ not ] compose assoc-find 2nip not ; inline + +: assoc-contains? ( assoc quot -- ? ) + assoc-find 2nip ; inline + +: at ( key assoc -- value/f ) + at* drop ; inline + +M: assoc assoc-clone-like ( assoc exemplar -- newassoc ) + over assoc-size swap new-assoc + swap [ swap pick set-at ] assoc-each ; + +: keys ( assoc -- keys ) + [ drop ] { } assoc>map ; + +: values ( assoc -- values ) + [ nip ] { } assoc>map ; + +: delete-at* ( key assoc -- old ? ) + [ at* ] 2keep delete-at ; + +: rename-at ( newkey key assoc -- ) + tuck delete-at* [ -rot set-at ] [ 3drop ] if ; + +: assoc-empty? ( assoc -- ? ) + assoc-size zero? ; + +: (assoc-stack) ( key i seq -- value ) + over 0 < [ + 3drop f + ] [ + 3dup nth-unsafe at* + [ >r 3drop r> ] [ drop >r 1- r> (assoc-stack) ] if + ] if ; inline + +: assoc-stack ( key seq -- value ) + dup length 1- swap (assoc-stack) ; + +: subassoc? ( assoc1 assoc2 -- ? ) + [ swapd at* [ = ] [ 2drop f ] if ] curry assoc-all? ; + +: assoc= ( assoc1 assoc2 -- ? ) + 2dup subassoc? >r swap subassoc? r> and ; + +: assoc-hashcode ( n assoc -- code ) + swap [ + tuck swap hashcode* >r swap hashcode* 2/ r> bitxor + ] curry { } assoc>map hashcode ; + +: intersect ( assoc1 assoc2 -- intersection ) + swap [ nip key? ] curry assoc-subset ; + +: update ( assoc1 assoc2 -- ) + swap [ swapd set-at ] curry assoc-each ; + +: union ( assoc1 assoc2 -- union ) + 2dup [ assoc-size ] 2apply + pick new-assoc + [ rot update ] keep [ swap update ] keep ; + +: diff ( assoc1 assoc2 -- diff ) + swap [ nip key? not ] curry assoc-subset ; + +: remove-all ( assoc seq -- subseq ) + swap [ key? not ] curry subset ; + +: substitute ( assoc seq -- ) + swap [ dupd at* [ nip ] [ drop ] if ] curry change-each ; + +: cache ( key assoc quot -- value ) + pick pick at [ + >r 3drop r> + ] [ + pick rot >r >r call dup r> r> set-at + ] if* ; inline + +: change-at ( key assoc quot -- ) + [ >r at r> call ] 3keep drop set-at ; inline + +: at+ ( n key assoc -- ) + [ 0 or + ] change-at ; + +: map>assoc ( seq quot exemplar -- assoc ) + >r [ 2array ] compose map r> assoc-like ; inline + +M: assoc >alist [ 2array ] { } assoc>map ; + +: value-at ( value assoc -- key/f ) + swap [ = nip ] curry assoc-find 2drop ; + +: search-alist ( key alist -- pair i ) + [ first = ] curry* find swap ; inline + +M: sequence at* + search-alist [ second t ] [ f ] if ; + +M: sequence set-at + 2dup search-alist + [ 2nip set-second ] + [ drop >r swap 2array r> push ] if ; + +M: sequence new-assoc drop ; + +M: sequence clear-assoc delete-all ; + +M: sequence delete-at + tuck search-alist nip + [ swap delete-nth ] [ drop ] if* ; + +M: sequence assoc-size length ; + +M: sequence assoc-clone-like + >r >alist r> clone-like ; + +M: sequence assoc-like + over sequence? [ like ] [ assoc-clone-like ] if ; + +M: sequence >alist ; + +! Override sequence => assoc instance for f +M: f clear-assoc drop ; + +M: f assoc-like drop dup assoc-empty? [ drop f ] when ; + +INSTANCE: sequence assoc diff --git a/core/assocs/authors.txt b/core/assocs/authors.txt new file mode 100644 index 0000000000..f990dd0ed2 --- /dev/null +++ b/core/assocs/authors.txt @@ -0,0 +1 @@ +Daniel Ehrenberg diff --git a/core/assocs/summary.txt b/core/assocs/summary.txt new file mode 100644 index 0000000000..e7b3b51e57 --- /dev/null +++ b/core/assocs/summary.txt @@ -0,0 +1 @@ +Associative structure protocol diff --git a/core/assocs/tags.txt b/core/assocs/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/core/assocs/tags.txt @@ -0,0 +1 @@ +collections diff --git a/core/bit-arrays/authors.txt b/core/bit-arrays/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bit-arrays/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bit-arrays/bit-arrays-docs.factor b/core/bit-arrays/bit-arrays-docs.factor new file mode 100644 index 0000000000..f804ed21f4 --- /dev/null +++ b/core/bit-arrays/bit-arrays-docs.factor @@ -0,0 +1,49 @@ +USING: arrays help.markup help.syntax kernel +kernel.private prettyprint strings vectors sbufs ; +IN: bit-arrays + +ARTICLE: "bit-arrays" "Bit arrays" +"Bit array are a fixed-size mutable sequences (" { $link "sequence-protocol" } ") whose elements are either " { $link t } " or " { $link f } ". Each element only uses one bit of storage, hence the name. The literal syntax is covered in " { $link "syntax-bit-arrays" } "." +$nl +"Bit array words are in the " { $vocab-link "bit-arrays" } " vocabulary." +$nl +"Bit arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-byte-arrays" } "." +$nl +"Bit arrays form a class of objects:" +{ $subsection bit-array } +{ $subsection bit-array? } +"Creating new bit arrays:" +{ $subsection >bit-array } +{ $subsection } +"Efficiently setting and clearing all bits in a bit array:" +{ $subsection set-bits } +{ $subsection clear-bits } ; + +ABOUT: "bit-arrays" + +HELP: bit-array +{ $description "The class of fixed-length bit arrays. See " { $link "syntax-bit-arrays" } " for syntax and " { $link "bit-arrays" } " for general information." } ; + +HELP: ( n -- bit-array ) +{ $values { "n" "a non-negative integer" } { "bit-array" "a new " { $link bit-array } } } +{ $description "Creates a new bit array with the given length and all elements initially set to " { $link f } "." } ; + +HELP: >bit-array +{ $values { "seq" "a sequence" } { "bit-array" bit-array } } +{ $description "Outputs a freshly-allocated bit array whose elements have the same boolean values as a given sequence." } ; + +HELP: clear-bits +{ $values { "bit-array" bit-array } } +{ $description "Sets all elements of the bit array to " { $link f } "." } +{ $notes "Calling this word is more efficient than the following:" + { $code "[ drop f ] change-each" } +} +{ $side-effects "bit-array" } ; + +HELP: set-bits +{ $values { "bit-array" bit-array } } +{ $description "Sets all elements of the bit array to " { $link t } "." } +{ $notes "Calling this word is more efficient than the following:" + { $code "[ drop t ] change-each" } +} +{ $side-effects "bit-array" } ; diff --git a/core/bit-arrays/bit-arrays-tests.factor b/core/bit-arrays/bit-arrays-tests.factor new file mode 100644 index 0000000000..48698ad91d --- /dev/null +++ b/core/bit-arrays/bit-arrays-tests.factor @@ -0,0 +1,48 @@ +USING: sequences arrays bit-arrays kernel tools.test math +random ; +IN: temporary + +[ 100 ] [ 100 length ] unit-test + +[ + { t f t } +] [ + 3 t 0 pick set-nth t 2 pick set-nth + >array +] unit-test + +[ + { t f t } +] [ + { t f t } >bit-array >array +] unit-test + +[ + { t f t } { f t f } +] [ + { t f t } >bit-array dup clone dup [ not ] change-each + [ >array ] 2apply +] unit-test + +[ + { f f f f f } +] [ + { t f t t f } >bit-array dup clear-bits >array +] unit-test + +[ + { t t t t t } +] [ + { t f t t f } >bit-array dup set-bits >array +] unit-test + +[ t ] [ + 100 [ + drop 100 [ drop 2 random zero? ] map + dup >bit-array >array = + ] all? +] unit-test + +[ ?{ f } ] [ + 1 2 { t f t f } >bit-array +] unit-test diff --git a/core/bit-arrays/bit-arrays.factor b/core/bit-arrays/bit-arrays.factor new file mode 100644 index 0000000000..185ca0c2d2 --- /dev/null +++ b/core/bit-arrays/bit-arrays.factor @@ -0,0 +1,51 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: math alien kernel kernel.private sequences +sequences.private ; +IN: bit-arrays + +cell -5 shift 4 * ; inline + +: cell/bit ( n alien -- byte bit ) + over n>cell alien-unsigned-4 swap 31 bitand ; inline + +: set-bit ( ? byte bit -- byte ) + 2^ rot [ bitor ] [ bitnot bitand ] if ; inline + +: bits>bytes 7 + -3 shift ; inline + +: bits>cells 31 + -5 shift ; inline + +: (set-bits) ( bit-array n -- ) + over length bits>cells -rot [ + swap rot 4 * set-alien-unsigned-4 + ] 2curry each ; inline + +PRIVATE> + +M: bit-array length array-capacity ; + +M: bit-array nth-unsafe cell/bit bit? ; + +M: bit-array set-nth-unsafe + [ cell/bit set-bit ] 2keep + swap n>cell set-alien-unsigned-4 ; + +: clear-bits ( bit-array -- ) 0 (set-bits) ; + +: set-bits ( bit-array -- ) -1 (set-bits) ; + +M: bit-array clone (clone) ; + +: >bit-array ( seq -- bit-array ) ?{ } clone-like ; inline + +M: bit-array like drop dup bit-array? [ >bit-array ] unless ; + +M: bit-array new drop ; + +M: bit-array equal? + over bit-array? [ sequence= ] [ 2drop f ] if ; + +INSTANCE: bit-array sequence diff --git a/core/bit-arrays/summary.txt b/core/bit-arrays/summary.txt new file mode 100644 index 0000000000..8844bfc933 --- /dev/null +++ b/core/bit-arrays/summary.txt @@ -0,0 +1 @@ +Fixed-size bit arrays diff --git a/core/bit-arrays/tags.txt b/core/bit-arrays/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/core/bit-arrays/tags.txt @@ -0,0 +1 @@ +collections diff --git a/core/bootstrap/compiler/authors.txt b/core/bootstrap/compiler/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/compiler/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/compiler/compiler.factor b/core/bootstrap/compiler/compiler.factor new file mode 100644 index 0000000000..c550923907 --- /dev/null +++ b/core/bootstrap/compiler/compiler.factor @@ -0,0 +1,50 @@ +USING: compiler vocabs.loader system sequences namespaces +parser kernel kernel.private classes classes.private +arrays hashtables vectors tuples sbufs inference.dataflow +hashtables.private sequences.private math tuples.private +growable namespaces.private alien.remote-control assocs +words generator command-line vocabs io prettyprint ; + +"bootstrap.math" vocab [ + "cpu." cpu append require + + global [ { "compiler" } add-use ] bind + + "-no-stack-traces" cli-args member? [ + f compiled-stack-traces set-global + ] when + + ! Compile a set of words ahead of our general + ! compile-all. This set of words was determined + ! semi-empirically using the profiler. It improves + ! bootstrap time significantly, because frequenly + ! called words which are also quick to compile + ! are replaced by compiled definitions as soon as + ! possible. + { + roll -roll declare not + + tuple-class-eq? array? hashtable? vector? + tuple? sbuf? node? tombstone? + + array-capacity array-nth set-array-nth + + wrap probe + + delegate + + underlying + + find-pair-next namestack* + + bitand bitor bitxor bitnot + + + 1+ 1- 2/ < <= > >= shift min + + new nth push pop peek hashcode* = get set + + . lines + } [ compile ] each + + [ recompile ] parse-hook set-global +] when diff --git a/core/bootstrap/compiler/summary.txt b/core/bootstrap/compiler/summary.txt new file mode 100644 index 0000000000..2dda03e33e --- /dev/null +++ b/core/bootstrap/compiler/summary.txt @@ -0,0 +1 @@ +Loading the compiler in stage 2 bootstrap diff --git a/core/bootstrap/help/authors.txt b/core/bootstrap/help/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/help/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/help/help.factor b/core/bootstrap/help/help.factor new file mode 100644 index 0000000000..003c3a9855 --- /dev/null +++ b/core/bootstrap/help/help.factor @@ -0,0 +1,24 @@ +USING: help help.topics help.syntax help.crossref +help.definitions io io.files kernel namespaces vocabs sequences +parser vocabs.loader ; +IN: bootstrap.help + +: load-help + t load-help? set-global + + vocabs + [ vocab-root ] subset + [ vocab-source-loaded? ] subset + [ + dup vocab-docs-loaded? [ + drop + ] [ + dup vocab-root swap load-docs + ] if + ] each + + "help.handbook" require + + global [ "help" use+ ] bind ; + +load-help diff --git a/core/bootstrap/help/summary.txt b/core/bootstrap/help/summary.txt new file mode 100644 index 0000000000..009a02b2bd --- /dev/null +++ b/core/bootstrap/help/summary.txt @@ -0,0 +1 @@ +Loading the help system in stage 2 bootstrap diff --git a/core/bootstrap/image/authors.txt b/core/bootstrap/image/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/image/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/image/image-docs.factor b/core/bootstrap/image/image-docs.factor new file mode 100644 index 0000000000..868e49deeb --- /dev/null +++ b/core/bootstrap/image/image-docs.factor @@ -0,0 +1,20 @@ +USING: help.markup help.syntax io io.files ; +IN: bootstrap.image + +ARTICLE: "bootstrap.image" "Bootstrapping new images" +"A new image can be built from source; this is known as " { $emphasis "bootstrap" } ". Bootstrap is a two-step process. The first stage is the creation of a bootstrap image from a running Factor instance:" +{ $subsection make-image } +"The second bootstrapping stage is initiated by running the resulting bootstrap image:" +{ $code "./factor -i=boot.x86.32.image" } +"This stage loads additional code, compiles all words, and dumps a final " { $snippet "factor.image" } "." +$nl +"The bootstrap process can be customized with command-line switches." +{ $see-also "runtime-cli-args" "bootstrap-cli-args" } ; + +ABOUT: "bootstrap.image" + +HELP: make-image +{ $values { "architecture" "a string" } } +{ $description "Creates a bootstrap image from sources, where " { $snippet "architecture" } " is one of the following:" +{ $code "x86.32" "x86.64" "ppc" "arm" } +"The new image file is written to the " { $link resource-path } " and is named " { $snippet "boot." { $emphasis "architecture" } ".image" } "." } ; diff --git a/core/bootstrap/image/image.factor b/core/bootstrap/image/image.factor new file mode 100644 index 0000000000..36d2f7f1de --- /dev/null +++ b/core/bootstrap/image/image.factor @@ -0,0 +1,461 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien arrays bit-arrays byte-arrays generic assocs +hashtables assocs hashtables.private io kernel kernel.private +math namespaces parser prettyprint sequences sequences.private +strings sbufs vectors words quotations assocs system layouts +splitting growable math.functions classes tuples words.private +io.binary io.files vocabs vocabs.loader source-files +definitions debugger float-arrays quotations.private +combinators.private combinators ; +IN: bootstrap.image + +w/w big-endian get [ swap ] unless emit emit + ] if ; + +: emit-seq ( seq -- ) image get push-all ; + +: fixup ( value offset -- ) image get set-nth ; + +: heap-size ( -- size ) + image get length header-size - userenv-size - + bootstrap-cells ; + +: here ( -- size ) heap-size data-base + ; + +: here-as ( tag -- pointer ) here swap bitor ; + +: align-here ( -- ) + here 8 mod 4 = [ 0 emit ] when ; + +: emit-fixnum ( n -- ) tag-bits get shift emit ; + +: emit-object ( header tag quot -- addr ) + swap here-as >r swap tag-header emit call align-here r> ; + inline + +! Write an object to the image. +GENERIC: ' ( obj -- ptr ) + +! Image header + +: emit-header ( -- ) + image-magic emit + image-version emit + data-base emit ! relocation base at end of header + 0 emit ! size of data heap set later + 0 emit ! reloc base of code heap is 0 + 0 emit ! size of code heap is 0 + 0 emit ! pointer to t object + 0 emit ! pointer to bignum 0 + 0 emit ! pointer to bignum 1 + 0 emit ! pointer to bignum -1 + userenv-size [ f ' emit ] times ; + +: emit-userenv ( symbol -- ) + dup get ' swap userenv-offset fixup ; + +! Bignums + +: bignum-bits bootstrap-cell-bits 2 - ; + +: bignum-radix bignum-bits 2^ 1- ; + +: (bignum>seq) ( n -- ) + dup zero? [ + drop + ] [ + dup bignum-radix bitand , + bignum-bits neg shift (bignum>seq) + ] if ; + +: bignum>seq ( n -- seq ) + #! n is positive or zero. + [ (bignum>seq) ] { } make ; + +: emit-bignum ( n -- ) + [ 0 < 1 0 ? ] keep abs bignum>seq + dup length 1+ emit-fixnum + swap emit emit-seq ; + +M: bignum ' + bignum tag-number dup [ emit-bignum ] emit-object ; + +! Fixnums + +M: fixnum ' + #! When generating a 32-bit image on a 64-bit system, + #! some fixnums should be bignums. + dup most-negative-fixnum most-positive-fixnum between? + [ tag-bits get shift ] [ >bignum ' ] if ; + +! Floats + +M: float ' + float tag-number dup [ + align-here double>bits emit-64 + ] emit-object ; + +! Special objects + +! Padded with fixnums for 8-byte alignment + +: t, t t-offset fixup ; + +M: f ' + #! f is #define F RETAG(0,F_TYPE) + drop \ f tag-number ; + +: 0, 0 >bignum ' 0-offset fixup ; +: 1, 1 >bignum ' 1-offset fixup ; +: -1, -1 >bignum ' -1-offset fixup ; + +! Beginning of the image + +: begin-image ( -- ) emit-header t, 0, 1, -1, ; + +! Words + +: emit-word ( word -- ) + [ + dup hashcode ' , + dup word-name ' , + dup word-vocabulary ' , + dup word-def ' , + dup word-props ' , + f ' , + 0 , + 0 , + ] { } make + \ word type-number object tag-number + [ emit-seq ] emit-object + swap objects get set-at ; + +: word-error ( word msg -- * ) + [ % dup word-vocabulary % " " % word-name % ] "" make throw ; + +: transfer-word ( word -- word ) + dup target-word [ ] [ word-name no-word ] ?if ; + +: fixup-word ( word -- offset ) + transfer-word dup objects get at + [ ] [ "Not in image: " word-error ] ?if ; + +: fixup-words ( -- ) + image get [ dup word? [ fixup-word ] when ] change-each ; + +M: word ' ; + +! Wrappers + +M: wrapper ' + wrapped ' wrapper type-number object tag-number + [ emit ] emit-object ; + +! Strings +: 16be> 0 [ swap 16 shift bitor ] reduce ; +: 16le> 16be> ; + +: emit-chars ( seq -- ) + char + big-endian get [ [ 16be> ] map ] [ [ 16le> ] map ] if + emit-seq ; + +: pack-string ( string -- newstr ) + dup length 1+ char align 0 pad-right ; + +: emit-string ( string -- ptr ) + string type-number object tag-number [ + dup length emit-fixnum + f ' emit + pack-string emit-chars + ] emit-object ; + +M: string ' + #! We pool strings so that each string is only written once + #! to the image + objects get [ emit-string ] cache ; + +: assert-empty ( seq -- ) + length 0 assert= ; + +: emit-dummy-array ( obj type -- ptr ) + swap assert-empty + type-number object tag-number + [ 0 emit-fixnum ] emit-object ; + +M: byte-array ' byte-array emit-dummy-array ; + +M: bit-array ' bit-array emit-dummy-array ; + +M: float-array ' float-array emit-dummy-array ; + +! Arrays +: emit-array ( list type tag -- pointer ) + >r >r [ ' ] map r> r> [ + dup length emit-fixnum + emit-seq + ] emit-object ; + +: emit-tuple ( obj -- pointer ) + objects get [ + [ tuple>array unclip transfer-word , % ] { } make + tuple type-number dup emit-array + ] cache ; inline + +M: tuple ' emit-tuple ; + +M: tombstone ' + delegate + "((tombstone))" "((empty))" ? "hashtables.private" lookup + word-def first emit-tuple ; + +M: array ' + array type-number object tag-number emit-array ; + +! Quotations + +M: quotation ' + objects get [ + quotation-array ' + quotation type-number object tag-number [ + emit ! array + 0 emit ! XT + ] emit-object + ] cache ; + +! Vectors and sbufs + +M: vector ' + dup underlying ' swap length + vector type-number object tag-number [ + emit-fixnum ! length + emit ! array ptr + ] emit-object ; + +M: sbuf ' + dup underlying ' swap length + sbuf type-number object tag-number [ + emit-fixnum ! length + emit ! array ptr + ] emit-object ; + +! Hashes + +M: hashtable ' + [ hash-array ' ] keep + hashtable type-number object tag-number [ + dup hash-count emit-fixnum + hash-deleted emit-fixnum + emit ! array ptr + ] emit-object ; + +! Curries + +M: curry ' + dup curry-quot ' swap curry-obj ' + \ curry type-number object tag-number + [ emit emit ] emit-object ; + +! End of the image + +: emit-words ( -- ) + all-words [ emit-word ] each ; + +: emit-global ( -- ) + [ + { + dictionary source-files + typemap builtins classbe write ] curry each + ] [ + [ >le write ] curry each + ] if ; + +: image-name + "boot." architecture get ".image" 3append resource-path ; + +: write-image ( image filename -- ) + "Writing image to " write dup write "..." print flush + [ (write-image) ] with-stream ; + +: prepare-profile ( arch -- ) + "resource:core/bootstrap/layouts/layouts.factor" run-file + "resource:core/cpu/" swap { + { "x86.32" "x86/32" } + { "x86.64" "x86/64" } + { "linux-ppc" "ppc/linux" } + { "macosx-ppc" "ppc/macosx" } + { "arm" "arm" } + } at "/bootstrap.factor" 3append ?resource-path run-file ; + +: prepare-image ( arch -- ) + dup architecture set prepare-profile + bootstrapping? on + load-help? off + 800000 image set 20000 objects set ; + +PRIVATE> + +: make-image ( architecture -- ) + [ + parse-hook off + prepare-image + begin-image + "resource:/core/bootstrap/stage1.factor" run-file + end-image + image get image-name write-image + ] with-scope ; + +: make-images ( -- ) + { + "x86.32" "x86.64" "linux-ppc" "macosx-ppc" "arm" + } [ make-image ] each ; diff --git a/core/bootstrap/image/summary.txt b/core/bootstrap/image/summary.txt new file mode 100644 index 0000000000..208332eb9c --- /dev/null +++ b/core/bootstrap/image/summary.txt @@ -0,0 +1 @@ +Bootstrap image generation diff --git a/core/bootstrap/image/tags.txt b/core/bootstrap/image/tags.txt new file mode 100644 index 0000000000..ef1aab0d0e --- /dev/null +++ b/core/bootstrap/image/tags.txt @@ -0,0 +1 @@ +tools diff --git a/core/bootstrap/io/authors.txt b/core/bootstrap/io/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/io/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/io/io.factor b/core/bootstrap/io/io.factor new file mode 100644 index 0000000000..8aa7861d5a --- /dev/null +++ b/core/bootstrap/io/io.factor @@ -0,0 +1,8 @@ +USING: system vocabs vocabs.loader kernel ; +IN: bootstrap.io + +"bootstrap.compiler" vocab [ + unix? [ "io.unix" require ] when + winnt? [ "io.windows.nt" require ] when + wince? [ "io.windows.ce" require ] when +] when diff --git a/core/bootstrap/io/summary.txt b/core/bootstrap/io/summary.txt new file mode 100644 index 0000000000..d65964315a --- /dev/null +++ b/core/bootstrap/io/summary.txt @@ -0,0 +1 @@ +Loading native I/O in stage 2 bootstrap diff --git a/core/bootstrap/layouts/authors.txt b/core/bootstrap/layouts/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/layouts/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/layouts/layouts.factor b/core/bootstrap/layouts/layouts.factor new file mode 100644 index 0000000000..189233e2d4 --- /dev/null +++ b/core/bootstrap/layouts/layouts.factor @@ -0,0 +1,40 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: namespaces math words kernel alien byte-arrays +hashtables vectors strings sbufs arrays bit-arrays +float-arrays quotations assocs layouts tuples ; + +BIN: 111 tag-mask set +8 num-tags set +3 tag-bits set + +23 num-types set + +H{ + { fixnum BIN: 000 } + { bignum BIN: 001 } + { tuple BIN: 010 } + { object BIN: 011 } + { ratio BIN: 100 } + { float BIN: 101 } + { complex BIN: 110 } + { POSTPONE: f BIN: 111 } +} tag-numbers set + +tag-numbers get H{ + { array 8 } + { wrapper 9 } + { hashtable 10 } + { vector 11 } + { string 12 } + { sbuf 13 } + { quotation 14 } + { dll 15 } + { alien 16 } + { word 17 } + { byte-array 18 } + { bit-array 19 } + { float-array 20 } + { curry 21 } + { callstack 22 } +} union type-numbers set diff --git a/core/bootstrap/layouts/summary.txt b/core/bootstrap/layouts/summary.txt new file mode 100644 index 0000000000..8f4f749b0c --- /dev/null +++ b/core/bootstrap/layouts/summary.txt @@ -0,0 +1 @@ +Description of low-level object layout for image generation diff --git a/core/bootstrap/math/math.factor b/core/bootstrap/math/math.factor new file mode 100644 index 0000000000..a293efd33e --- /dev/null +++ b/core/bootstrap/math/math.factor @@ -0,0 +1,5 @@ +USE: vocabs.loader + +"math.ratios" require +"math.floats" require +"math.complex" require diff --git a/core/bootstrap/math/summary.txt b/core/bootstrap/math/summary.txt new file mode 100644 index 0000000000..680c447df5 --- /dev/null +++ b/core/bootstrap/math/summary.txt @@ -0,0 +1 @@ +Loading number tower in stage 2 bootstrap diff --git a/core/bootstrap/primitives.factor b/core/bootstrap/primitives.factor new file mode 100644 index 0000000000..5e7bc1f338 --- /dev/null +++ b/core/bootstrap/primitives.factor @@ -0,0 +1,597 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: bootstrap.primitives +USING: alien arrays byte-arrays generic hashtables +hashtables.private io kernel math namespaces parser sequences +strings vectors words quotations assocs layouts classes tuples +kernel.private vocabs vocabs.loader source-files definitions +slots classes.union words.private ; + +! Some very tricky code creating a bootstrap embryo in the +! host image. + +"Creating primitives and basic runtime structures..." print flush + +load-help? off +crossref off +changed-words off + +! Bring up a bare cross-compiling vocabulary. +"syntax" vocab vocab-words bootstrap-syntax set + +"resource:core/bootstrap/syntax.factor" parse-file +H{ } clone dictionary set +call + +! Create some empty vocabs where the below primitives and +! classes will go +{ + "alien" + "arrays" + "bit-arrays" + "byte-arrays" + "classes.private" + "continuations.private" + "float-arrays" + "generator" + "growable" + "hashtables" + "hashtables.private" + "io" + "io.files" + "io.files.private" + "io.streams.c" + "kernel" + "kernel.private" + "math" + "math.private" + "memory" + "quotations" + "quotations.private" + "sbufs" + "sbufs.private" + "scratchpad" + "sequences" + "sequences.private" + "slots.private" + "strings" + "strings.private" + "system" + "threads.private" + "tools.profiler.private" + "tuples" + "tuples.private" + "words" + "words.private" + "vectors" + "vectors.private" +} [ + dup find-vocab-root swap create-vocab + [ set-vocab-root ] keep + f swap set-vocab-source-loaded? +] each + +H{ } clone source-files set +H{ } clone classr create r> define ; + +{ + { "(execute)" "words.private" } + { "(call)" "kernel.private" } + { "uncurry" "kernel.private" } + { "string>sbuf" "sbufs.private" } + { "bignum>fixnum" "math.private" } + { "float>fixnum" "math.private" } + { "fixnum>bignum" "math.private" } + { "float>bignum" "math.private" } + { "fixnum>float" "math.private" } + { "bignum>float" "math.private" } + { "" "math.private" } + { "string>float" "math.private" } + { "float>string" "math.private" } + { "float>bits" "math" } + { "double>bits" "math" } + { "bits>float" "math" } + { "bits>double" "math" } + { "" "math.private" } + { "fixnum+" "math.private" } + { "fixnum+fast" "math.private" } + { "fixnum-" "math.private" } + { "fixnum-fast" "math.private" } + { "fixnum*" "math.private" } + { "fixnum*fast" "math.private" } + { "fixnum/i" "math.private" } + { "fixnum-mod" "math.private" } + { "fixnum/mod" "math.private" } + { "fixnum-bitand" "math.private" } + { "fixnum-bitor" "math.private" } + { "fixnum-bitxor" "math.private" } + { "fixnum-bitnot" "math.private" } + { "fixnum-shift" "math.private" } + { "fixnum<" "math.private" } + { "fixnum<=" "math.private" } + { "fixnum>" "math.private" } + { "fixnum>=" "math.private" } + { "bignum=" "math.private" } + { "bignum+" "math.private" } + { "bignum-" "math.private" } + { "bignum*" "math.private" } + { "bignum/i" "math.private" } + { "bignum-mod" "math.private" } + { "bignum/mod" "math.private" } + { "bignum-bitand" "math.private" } + { "bignum-bitor" "math.private" } + { "bignum-bitxor" "math.private" } + { "bignum-bitnot" "math.private" } + { "bignum-shift" "math.private" } + { "bignum<" "math.private" } + { "bignum<=" "math.private" } + { "bignum>" "math.private" } + { "bignum>=" "math.private" } + { "bignum-bit?" "math.private" } + { "bignum-log2" "math.private" } + { "byte-array>bignum" "math" } + { "float=" "math.private" } + { "float+" "math.private" } + { "float-" "math.private" } + { "float*" "math.private" } + { "float/f" "math.private" } + { "float-mod" "math.private" } + { "float<" "math.private" } + { "float<=" "math.private" } + { "float>" "math.private" } + { "float>=" "math.private" } + { "" "words" } + { "update-xt" "words" } + { "word-xt" "words" } + { "drop" "kernel" } + { "2drop" "kernel" } + { "3drop" "kernel" } + { "dup" "kernel" } + { "2dup" "kernel" } + { "3dup" "kernel" } + { "rot" "kernel" } + { "-rot" "kernel" } + { "dupd" "kernel" } + { "swapd" "kernel" } + { "nip" "kernel" } + { "2nip" "kernel" } + { "tuck" "kernel" } + { "over" "kernel" } + { "pick" "kernel" } + { "swap" "kernel" } + { ">r" "kernel" } + { "r>" "kernel" } + { "eq?" "kernel" } + { "getenv" "kernel.private" } + { "setenv" "kernel.private" } + { "(stat)" "io.files.private" } + { "(directory)" "io.files.private" } + { "data-gc" "memory" } + { "code-gc" "memory" } + { "gc-time" "memory" } + { "save-image" "memory" } + { "save-image-and-exit" "memory" } + { "datastack" "kernel" } + { "retainstack" "kernel" } + { "callstack" "kernel" } + { "set-datastack" "kernel" } + { "set-retainstack" "kernel" } + { "set-callstack" "kernel" } + { "exit" "system" } + { "data-room" "memory" } + { "code-room" "memory" } + { "os-env" "system" } + { "millis" "system" } + { "type" "kernel.private" } + { "tag" "kernel.private" } + { "cwd" "io.files" } + { "cd" "io.files" } + { "add-compiled-block" "generator" } + { "dlopen" "alien" } + { "dlsym" "alien" } + { "dlclose" "alien" } + { "" "byte-arrays" } + { "" "bit-arrays" } + { "" "alien" } + { "alien-signed-cell" "alien" } + { "set-alien-signed-cell" "alien" } + { "alien-unsigned-cell" "alien" } + { "set-alien-unsigned-cell" "alien" } + { "alien-signed-8" "alien" } + { "set-alien-signed-8" "alien" } + { "alien-unsigned-8" "alien" } + { "set-alien-unsigned-8" "alien" } + { "alien-signed-4" "alien" } + { "set-alien-signed-4" "alien" } + { "alien-unsigned-4" "alien" } + { "set-alien-unsigned-4" "alien" } + { "alien-signed-2" "alien" } + { "set-alien-signed-2" "alien" } + { "alien-unsigned-2" "alien" } + { "set-alien-unsigned-2" "alien" } + { "alien-signed-1" "alien" } + { "set-alien-signed-1" "alien" } + { "alien-unsigned-1" "alien" } + { "set-alien-unsigned-1" "alien" } + { "alien-float" "alien" } + { "set-alien-float" "alien" } + { "alien-double" "alien" } + { "set-alien-double" "alien" } + { "alien-cell" "alien" } + { "set-alien-cell" "alien" } + { "alien>char-string" "alien" } + { "string>char-alien" "alien" } + { "alien>u16-string" "alien" } + { "string>u16-alien" "alien" } + { "(throw)" "kernel.private" } + { "string>memory" "alien" } + { "memory>string" "alien" } + { "alien-address" "alien" } + { "slot" "slots.private" } + { "set-slot" "slots.private" } + { "char-slot" "strings.private" } + { "set-char-slot" "strings.private" } + { "resize-array" "arrays" } + { "resize-string" "strings" } + { "(hashtable)" "hashtables.private" } + { "" "arrays" } + { "begin-scan" "memory" } + { "next-object" "memory" } + { "end-scan" "memory" } + { "size" "memory" } + { "die" "kernel" } + { "finalize-compile" "generator" } + { "fopen" "io.streams.c" } + { "fgetc" "io.streams.c" } + { "fread" "io.streams.c" } + { "fwrite" "io.streams.c" } + { "fflush" "io.streams.c" } + { "fclose" "io.streams.c" } + { "" "kernel" } + { "(clone)" "kernel" } + { "array>vector" "vectors.private" } + { "" "strings" } + { "(>tuple)" "tuples.private" } + { "array>quotation" "quotations.private" } + { "quotation-xt" "quotations" } + { "" "tuples.private" } + { "tuple>array" "tuples" } + { "profiling" "tools.profiler.private" } + { "become" "tuples.private" } + { "(sleep)" "threads.private" } + { "" "float-arrays" } + { "curry" "kernel" } + { "" "tuples.private" } + { "class-hash" "kernel.private" } + { "callstack>array" "kernel" } + { "array>callstack" "kernel" } +} +dup length [ >r first2 r> make-primitive ] 2each + +! Okay, now we have primitives fleshed out. Bring up the generic +! word system. +: builtin-predicate ( class predicate -- ) + [ + over "type" word-prop dup + \ tag-mask get < \ tag \ type ? , , \ eq? , + ] [ ] make define-predicate ; + +: register-builtin ( class -- ) + dup "type" word-prop builtins get set-nth ; + +: intern-slots ( spec -- spec ) + [ + [ dup array? [ first2 create ] when ] map + { slot-spec f } swap append >tuple + ] map ; + +: lookup-type-number ( word -- n ) + global [ target-word ] bind type-number ; + +: define-builtin ( symbol predicate slotspec -- ) + >r dup make-inline >r + dup dup lookup-type-number "type" set-word-prop + dup f f builtin-class define-class + dup r> builtin-predicate + dup r> intern-slots 2dup "slots" set-word-prop + define-slots + register-builtin ; + +H{ } clone typemap set +num-types get f builtins set + +! These symbols are needed by the code that executes below +{ + { "object" "kernel" } + { "null" "kernel" } +} [ create drop ] assoc-each + +"fixnum" "math" create "fixnum?" "math" create { } define-builtin +"fixnum" "math" create ">fixnum" "math" create 1quotation "coercer" set-word-prop + +"bignum" "math" create "bignum?" "math" create { } define-builtin +"bignum" "math" create ">bignum" "math" create 1quotation "coercer" set-word-prop + +"tuple" "kernel" create "tuple?" "kernel" create +{ } define-builtin + +"ratio" "math" create "ratio?" "math" create +{ + { + { "integer" "math" } + "numerator" + 1 + { "numerator" "math" } + f + } + { + { "integer" "math" } + "denominator" + 2 + { "denominator" "math" } + f + } +} define-builtin + +"float" "math" create "float?" "math" create { } define-builtin +"float" "math" create ">float" "math" create 1quotation "coercer" set-word-prop + +"complex" "math" create "complex?" "math" create +{ + { + { "real" "math" } + "real" + 1 + { "real" "math" } + f + } + { + { "real" "math" } + "imaginary" + 2 + { "imaginary" "math" } + f + } +} define-builtin + +"f" "syntax" lookup "not" "kernel" create +{ } define-builtin + +"array" "arrays" create "array?" "arrays" create +{ } define-builtin + +"wrapper" "kernel" create "wrapper?" "kernel" create +{ + { + { "object" "kernel" } + "wrapped" + 1 + { "wrapped" "kernel" } + f + } +} define-builtin + +"hashtable" "hashtables" create "hashtable?" "hashtables" create +{ + { + { "array-capacity" "sequences.private" } + "count" + 1 + { "hash-count" "hashtables.private" } + { "set-hash-count" "hashtables.private" } + } { + { "array-capacity" "sequences.private" } + "deleted" + 2 + { "hash-deleted" "hashtables.private" } + { "set-hash-deleted" "hashtables.private" } + } { + { "array" "arrays" } + "array" + 3 + { "hash-array" "hashtables.private" } + { "set-hash-array" "hashtables.private" } + } +} define-builtin + +"vector" "vectors" create "vector?" "vectors" create +{ + { + { "array-capacity" "sequences.private" } + "fill" + 1 + { "length" "sequences" } + { "set-fill" "growable" } + } { + { "array" "arrays" } + "underlying" + 2 + { "underlying" "growable" } + { "set-underlying" "growable" } + } +} define-builtin + +"string" "strings" create "string?" "strings" create +{ + { + { "array-capacity" "sequences.private" } + "length" + 1 + { "length" "sequences" } + f + } +} define-builtin + +"sbuf" "sbufs" create "sbuf?" "sbufs" create +{ + { + { "array-capacity" "sequences.private" } + "length" + 1 + { "length" "sequences" } + { "set-fill" "growable" } + } + { + { "string" "strings" } + "underlying" + 2 + { "underlying" "growable" } + { "set-underlying" "growable" } + } +} define-builtin + +"quotation" "quotations" create "quotation?" "quotations" create +{ + { + { "object" "kernel" } + "array" + 1 + { "quotation-array" "quotations.private" } + f + } +} define-builtin + +"dll" "alien" create "dll?" "alien" create +{ + { + { "byte-array" "byte-arrays" } + "path" + 1 + { "(dll-path)" "alien" } + f + } +} +define-builtin + +"alien" "alien" create "alien?" "alien" create +{ + { + { "c-ptr" "alien" } + "alien" + 1 + { "underlying-alien" "alien" } + f + } { + { "object" "kernel" } + "expired?" + 2 + { "expired?" "alien" } + f + } +} +define-builtin + +"word" "words" create "word?" "words" create +{ + { + { "object" "kernel" } + "name" + 2 + { "word-name" "words" } + { "set-word-name" "words" } + } + { + { "object" "kernel" } + "vocabulary" + 3 + { "word-vocabulary" "words" } + { "set-word-vocabulary" "words" } + } + { + { "object" "kernel" } + "def" + 4 + { "word-def" "words" } + { "set-word-def" "words.private" } + } + { + { "object" "kernel" } + "props" + 5 + { "word-props" "words" } + { "set-word-props" "words" } + } + { + { "object" "kernel" } + "?" + 6 + { "compiled?" "words" } + f + } + { + { "fixnum" "math" } + "counter" + 7 + { "profile-counter" "tools.profiler.private" } + { "set-profile-counter" "tools.profiler.private" } + } +} define-builtin + +"byte-array" "byte-arrays" create +"byte-array?" "byte-arrays" create +{ } define-builtin + +"bit-array" "bit-arrays" create +"bit-array?" "bit-arrays" create +{ } define-builtin + +"float-array" "float-arrays" create +"float-array?" "float-arrays" create +{ } define-builtin + +"curry" "kernel" create +"curry?" "kernel" create +{ + { + { "object" "kernel" } + "obj" + 1 + { "curry-obj" "kernel" } + f + } + { + { "object" "kernel" } + "obj" + 2 + { "curry-quot" "kernel" } + f + } +} define-builtin + +"callstack" "kernel" create "callstack?" "kernel" create +{ } define-builtin + +! Define general-t type, which is any object that is not f. +"general-t" "kernel" create +"f" "syntax" lookup builtins get remove [ ] subset f union-class +define-class + +! Catch-all class for providing a default method. +"object" "kernel" create [ drop t ] "predicate" set-word-prop +"object" "kernel" create +builtins get [ ] subset f union-class define-class + +! Class of objects with object tag +"hi-tag" "classes.private" create +builtins get num-tags get tail f union-class define-class + +! Null class with no instances. +"null" "kernel" create [ drop f ] "predicate" set-word-prop +"null" "kernel" create { } f union-class define-class + +! Create special tombstone values +"tombstone" "hashtables.private" create { } define-tuple-class + +"((empty))" "hashtables.private" create +"tombstone" "hashtables.private" lookup f +2array >tuple 1quotation define-inline + +"((tombstone))" "hashtables.private" create +"tombstone" "hashtables.private" lookup t +2array >tuple 1quotation define-inline + +! Bump build number +"build" "kernel" create build 1+ 1quotation define-compound diff --git a/core/bootstrap/stage1.factor b/core/bootstrap/stage1.factor new file mode 100644 index 0000000000..bb8c9a57e8 --- /dev/null +++ b/core/bootstrap/stage1.factor @@ -0,0 +1,43 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: bootstrap.stage1 +USING: arrays debugger generic hashtables io assocs +kernel.private kernel math memory namespaces parser +prettyprint sequences vectors words system splitting +init io.files bootstrap.image bootstrap.image.private vocabs +vocabs.loader system ; + +{ "resource:core" } vocab-roots set + +"Bootstrap stage 1..." print flush + +"resource:core/bootstrap/primitives.factor" run-file + +! Create a boot quotation +[ + ! Rehash hashtables, since core/tools/image creates them + ! using the host image's hashing algorithms + + [ [ hashtable? ] instances [ rehash ] each ] % + + \ boot , + + "math.integers" require + "memory" require + "io.streams.c" require + "vocabs.loader" require + "syntax" require + "bootstrap.layouts" require + + [ + "resource:core/bootstrap/stage2.factor" + dup ?resource-path exists? [ + run-file + ] [ + "Cannot find " write write "." print + "Please move " write image write " to the same directory as the Factor sources," print + "and try again." print + 1 exit + ] if + ] % +] [ ] make bootstrap-boot-quot set diff --git a/core/bootstrap/stage2.factor b/core/bootstrap/stage2.factor new file mode 100644 index 0000000000..298e905595 --- /dev/null +++ b/core/bootstrap/stage2.factor @@ -0,0 +1,83 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: init command-line namespaces words debugger io +kernel.private math memory continuations kernel io.files +io.backend system parser vocabs sequences prettyprint +vocabs.loader combinators splitting source-files strings +definitions assocs ; +IN: bootstrap.stage2 + +! Wrap everything in a catch which starts a listener so +! you can see what went wrong, instead of dealing with a +! fep +[ + vm file-name windows? [ >lower ".exe" ?tail drop ] when + ".image" append "output-image" set-global + + "math compiler tools help ui ui.tools io" "include" set-global + "" "exclude" set-global + + parse-command-line + + "Cross-referencing..." print flush + H{ } clone changed-words set-global + H{ } clone crossref set-global + xref-words + xref-sources + + ! Set dll paths + wince? [ "windows.ce" require ] when + winnt? [ "windows.nt" require ] when + + [ + ! Compile everything if compiler is loaded + all-words [ changed-word ] each + + "exclude" "include" + [ get-global " " split [ empty? not ] subset ] 2apply + seq-diff + [ "bootstrap." swap append require ] each + ] no-parse-hook + + init-io + init-stdio + + changed-words get clear-assoc + + "compile-errors" "generator" lookup [ + f swap set-global + ] when* + + run-bootstrap-init + + f error set-global + f error-continuation set-global + + "deploy-vocab" get [ + "tools.deploy" run + ] [ + "listener" require + "none" require + + [ + boot + do-init-hooks + [ parse-command-line ] try + [ run-user-init ] try + [ "run" get run ] try + stdio get [ stream-flush ] when* + ] set-boot-quot + + : count-words all-words swap subset length pprint ; + + [ compiled? ] 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 -i=" write + "output-image" get print flush + + "output-image" get resource-path save-image-and-exit + ] if +] [ error-hook get call "listener" run ] recover diff --git a/core/bootstrap/summary.txt b/core/bootstrap/summary.txt new file mode 100644 index 0000000000..208332eb9c --- /dev/null +++ b/core/bootstrap/summary.txt @@ -0,0 +1 @@ +Bootstrap image generation diff --git a/core/bootstrap/syntax.factor b/core/bootstrap/syntax.factor new file mode 100644 index 0000000000..136745f52b --- /dev/null +++ b/core/bootstrap/syntax.factor @@ -0,0 +1,69 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: words sequences vocabs kernel ; +IN: bootstrap.syntax + +"syntax" create-vocab +"resource:core" over set-vocab-root +f swap set-vocab-source-loaded? + +{ + "!" + "\"" + "#!" + "(" + ":" + ";" + "" + "SBUF\"" + "SYMBOL:" + "TUPLE:" + "T{" + "UNION:" + "USE-IF:" + "USE:" + "USING:" + "V{" + "W{" + "[" + "\\" + "]" + "delimiter" + "f" + "flushable" + "foldable" + "inline" + "parsing" + "t" + "{" + "}" + "CS{" +} [ "syntax" create drop ] each + +"t" "syntax" lookup define-symbol diff --git a/core/bootstrap/tools/authors.txt b/core/bootstrap/tools/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/tools/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/tools/summary.txt b/core/bootstrap/tools/summary.txt new file mode 100644 index 0000000000..9c1fad46a2 --- /dev/null +++ b/core/bootstrap/tools/summary.txt @@ -0,0 +1 @@ +Loading terminal-based developer tools in stage 2 bootstrap diff --git a/core/bootstrap/tools/tools.factor b/core/bootstrap/tools/tools.factor new file mode 100644 index 0000000000..f3ec0a88e8 --- /dev/null +++ b/core/bootstrap/tools/tools.factor @@ -0,0 +1,19 @@ +USING: kernel vocabs vocabs.loader sequences namespaces parser ; + +{ + "bootstrap.image" + "tools.annotations" + "tools.crossref" + "tools.deploy" + "tools.memory" + "tools.test" + "tools.time" + "tools.walker" + "editors" +} dup [ require ] each + +global [ add-use ] bind + +"bootstrap.compiler" vocab [ + "tools.profiler" dup require use+ +] when diff --git a/core/bootstrap/ui/authors.txt b/core/bootstrap/ui/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/ui/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/ui/summary.txt b/core/bootstrap/ui/summary.txt new file mode 100644 index 0000000000..5902a00391 --- /dev/null +++ b/core/bootstrap/ui/summary.txt @@ -0,0 +1 @@ +Loading graphical user interface in stage 2 bootstrap diff --git a/core/bootstrap/ui/tools/authors.txt b/core/bootstrap/ui/tools/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/bootstrap/ui/tools/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/bootstrap/ui/tools/summary.txt b/core/bootstrap/ui/tools/summary.txt new file mode 100644 index 0000000000..fb45fcb56e --- /dev/null +++ b/core/bootstrap/ui/tools/summary.txt @@ -0,0 +1 @@ +Loading graphical developer tools in stage 2 bootstrap diff --git a/core/bootstrap/ui/tools/tools.factor b/core/bootstrap/ui/tools/tools.factor new file mode 100644 index 0000000000..c469aedcff --- /dev/null +++ b/core/bootstrap/ui/tools/tools.factor @@ -0,0 +1,10 @@ +USING: kernel vocabs vocabs.loader sequences ; + +{ "ui" "help" "tools" } +[ "bootstrap." swap append vocab ] all? [ + "ui.tools" require + + "ui.cocoa" vocab [ + "ui.cocoa.tools" require + ] when +] when diff --git a/core/bootstrap/ui/ui.factor b/core/bootstrap/ui/ui.factor new file mode 100644 index 0000000000..86538e0000 --- /dev/null +++ b/core/bootstrap/ui/ui.factor @@ -0,0 +1,14 @@ +USING: alien namespaces system combinators kernel sequences +vocabs vocabs.loader ; + +"bootstrap.compiler" vocab [ + "ui-backend" get [ + { + { [ macosx? ] [ "cocoa" ] } + { [ windows? ] [ "windows" ] } + { [ unix? ] [ "x11" ] } + } cond + ] unless* "ui." swap append require + + "ui.freetype" require +] when diff --git a/core/byte-arrays/authors.txt b/core/byte-arrays/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/byte-arrays/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/byte-arrays/byte-arrays-docs.factor b/core/byte-arrays/byte-arrays-docs.factor new file mode 100644 index 0000000000..d26ab68a9c --- /dev/null +++ b/core/byte-arrays/byte-arrays-docs.factor @@ -0,0 +1,31 @@ +USING: arrays bit-arrays vectors strings sbufs +kernel help.markup help.syntax ; +IN: byte-arrays + +ARTICLE: "byte-arrays" "Byte arrays" +"Byte arrays are fixed-size mutable sequences (" { $link "sequence-protocol" } ") whose elements are integers in the range 0-255, inclusive. Each element only uses one byte of storage, hence the name. The literal syntax is covered in " { $link "syntax-byte-arrays" } "." +$nl +"Byte array words are in the " { $vocab-link "byte-arrays" } " vocabulary." +$nl +"Byte arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-byte-arrays" } "." +$nl +"Byte arrays form a class of objects." +{ $subsection byte-array } +{ $subsection byte-array? } +"There are several ways to construct byte arrays." +{ $subsection >byte-array } +{ $subsection } ; + +ABOUT: "byte-arrays" + +HELP: byte-array +{ $description "The class of byte arrays. See " { $link "syntax-byte-arrays" } " for syntax and " { $link "byte-arrays" } " for general information." } ; + +HELP: ( n -- byte-array ) +{ $values { "n" "a non-negative integer" } { "byte-array" "a new byte array" } } +{ $description "Creates a new byte array holding " { $snippet "n" } " bytes." } ; + +HELP: >byte-array +{ $values { "seq" "a sequence" } { "byte-array" byte-array } } +{ $description "Outputs a freshly-allocated byte array whose elements have the same boolean values as a given sequence." } +{ $errors "Throws an error if the sequence contains elements other than integers." } ; diff --git a/core/byte-arrays/byte-arrays.factor b/core/byte-arrays/byte-arrays.factor new file mode 100644 index 0000000000..0d4eda138d --- /dev/null +++ b/core/byte-arrays/byte-arrays.factor @@ -0,0 +1,18 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: byte-arrays +USING: kernel kernel.private alien sequences +sequences.private math ; + +M: byte-array clone (clone) ; +M: byte-array length array-capacity ; +M: byte-array nth-unsafe swap >fixnum alien-unsigned-1 ; +M: byte-array set-nth-unsafe swap >fixnum set-alien-unsigned-1 ; +: >byte-array ( seq -- byte-array ) B{ } clone-like ; inline +M: byte-array like drop dup byte-array? [ >byte-array ] unless ; +M: byte-array new drop ; + +M: byte-array equal? + over byte-array? [ sequence= ] [ 2drop f ] if ; + +INSTANCE: byte-array sequence diff --git a/core/byte-arrays/summary.txt b/core/byte-arrays/summary.txt new file mode 100644 index 0000000000..b5b09a0ecb --- /dev/null +++ b/core/byte-arrays/summary.txt @@ -0,0 +1 @@ +Efficient fixed-length byte arrays diff --git a/core/byte-arrays/tags.txt b/core/byte-arrays/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/core/byte-arrays/tags.txt @@ -0,0 +1 @@ +collections diff --git a/core/classes/authors.txt b/core/classes/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/classes/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/classes/classes-docs.factor b/core/classes/classes-docs.factor new file mode 100644 index 0000000000..e637c47933 --- /dev/null +++ b/core/classes/classes-docs.factor @@ -0,0 +1,219 @@ +USING: generic help.markup help.syntax kernel kernel.private +namespaces sequences words arrays layouts help effects math +layouts classes.private classes.union classes.mixin +classes.predicate ; +IN: classes + +ARTICLE: "builtin-classes" "Built-in classes" +"Every object is an instance of to exactly one canonical " { $emphasis "built-in class" } " which defines its layout in memory and basic behavior." +$nl +"Corresponding to every built-in class is a built-in type number. An object can be asked for its built-in type number:" +{ $subsection type } +"Built-in type numbers can be converted to classes, and vice versa:" +{ $subsection type>class } +{ $subsection type-number } +"The set of built-in classes is a class:" +{ $subsection builtin-class } +{ $subsection builtin-class? } +"See " { $link "type-index" } " for a list of built-in classes." ; + +ARTICLE: "class-operations" "Class operations" +"Set-theoretic operations on classes:" +{ $subsection class< } +{ $subsection class-and } +{ $subsection class-or } +{ $subsection classes-intersect? } +"Topological sort:" +{ $subsection sort-classes } +{ $subsection min-class } +"Low-level implementation detail:" +{ $subsection types } +{ $subsection flatten-class } +{ $subsection flatten-builtin-class } +{ $subsection flatten-union-class } ; + +ARTICLE: "class-predicates" "Class predicate words" +"With a handful of exceptions, each class has a membership predicate word, named " { $snippet { $emphasis "class" } "?" } " . A quotation calling this predicate is stored in the " { $snippet "\"predicate\"" } " word property." +$nl +"When it comes to predicates, the exceptional classes are:" +{ $table + { "Class" "Predicate" "Explanation" } + { { $link f } { $snippet "[ not ]" } { "The conventional name for a word which outputs true when given false is " { $link not } "; " { $snippet "f?" } " would be confusing." } } + { { $link object } { $snippet "[ drop t ]" } { "All objects are instances of " { $link object } } } + { { $link null } { $snippet "[ drop f ]" } { "No object is an instance of " { $link null } } } + { { $link general-t } { $snippet "[ ]" } { "All objects with a true value are instances of " { $link general-t } } } +} +"The set of class predicate words is a class:" +{ $subsection predicate } +{ $subsection predicate? } +"A predicate word holds a reference to the class it is predicating over in the " { $snippet "\"predicating\"" } " word property." ; + +ARTICLE: "classes" "Classes" +"Conceptually, a " { $snippet "class" } " is a set of objects whose members can be identified with a predicate, and on which generic words can specialize methods. Classes are organized into a general partial order, and an object may be an instance of more than one class." +$nl +"At the implementation level, a class is a word with certain word properties set." +$nl +"Words for working with classes are found in the " { $vocab-link "classes" } " vocabulary." +$nl +"Classes themselves form a class:" +{ $subsection class? } +"You can ask an object for its class:" +{ $subsection class } +"There is a universal class which all objects are an instance of, and an empty class with no instances:" +{ $subsection object } +{ $subsection null } +"Obtaining a list of all defined classes:" +{ $subsection classes } +"Other sorts of classes:" +{ $subsection "builtin-classes" } +{ $subsection "unions" } +{ $subsection "mixins" } +{ $subsection "predicates" } +"Classes can be inspected and operated upon:" +{ $subsection "class-operations" } +{ $see-also "class-index" } ; + +ABOUT: "classes" + +HELP: class +{ $values { "object" object } { "class" class } } +{ $description "Outputs an object's canonical class. While an object may be an instance of more than one class, the canonical class is either its built-in class, or if the object is a tuple, its tuple class." } +{ $class-description "The class of all class words. Subclasses include " { $link builtin-class } ", " { $link union-class } ", " { $link mixin-class } ", " { $link predicate-class } " and " { $link tuple-class } "." } +{ $examples { $example "USE: classes" "1.0 class ." "float" } { $example "USE: classes" "TUPLE: point x y z ;\nT{ point f 1 2 3 } class ." "point" } } ; + +HELP: classes +{ $values { "seq" "a sequence of class words" } } +{ $description "Finds all class words in the dictionary." } ; + +HELP: builtin-class +{ $class-description "The class of built-in classes." } +{ $examples + "The class of arrays is a built-in class:" + { $example "USE: classes" "array builtin-class? ." "t" } + "However, a literal array is not a built-in class; it is not even a class:" + { $example "USE: classes" "{ 1 2 3 } builtin-class? ." "f" } +} ; + +HELP: tuple-class +{ $class-description "The class of tuple class words." } +{ $examples { $example "USE: classes\nTUPLE: name title first last ;\nname tuple-class? ." "t" } } ; + +HELP: typemap +{ $var-description "Hashtable mapping unions to class words, used to implement " { $link class-and } " and " { $link class-or } "." } ; + +HELP: builtins +{ $var-description "Vector mapping type numbers to builtin class words." } ; + +HELP: classclass +{ $values { "n" "a non-negative integer" } { "class" class } } +{ $description "Outputs a builtin class whose instances are precisely those having a given pointer tag." } +{ $notes "The parameter " { $snippet "n" } " must be between 0 and the return value of " { $link num-types } "." } ; + +HELP: predicate-word +{ $values { "word" "a word" } { "predicate" "a predicate word" } } +{ $description "Suffixes the word's name with \"?\" and creates a word with that name in the same vocabulary as the word itself." } ; + +HELP: define-predicate +{ $values { "class" class } { "predicate" "a predicate word" } { "quot" "a quotation" } } +{ $description + "Defines a predicate word. This is identical to a compound definition associating " { $snippet "quot" } " with " { $snippet "predicate" } " with the added perk that three word properties are set:" + { $list + { "the class word's " { $snippet "\"predicate\"" } " property is set to a quotation that calls the predicate" } + { "the predicate word's " { $snippet "\"predicating\"" } " property is set to the class word" } + { "the predicate word's " { $snippet "\"declared-effect\"" } " word property is set to a descriptive " { $link effect } } + } + "These properties are used by method dispatch and the help system." +} +$low-level-note ; + +HELP: superclass +{ $values { "class" class } { "super" class } } +{ $description "Outputs the superclass of a class. All instances of this class are also instances of the superclass." } +{ $notes "If " { $link class< } " yields that one class is a subtype of another, it does not imply that a superclass relation is involved. The superclass relation is a technical implementation detail of predicate and tuple classes." } ; + +HELP: members +{ $values { "class" class } { "seq" "a sequence of union members, or " { $link f } } } +{ $description "If " { $snippet "class" } " is a union class, outputs a sequence of its member classes, otherwise outputs " { $link f } "." } ; + +HELP: flatten-union-class +{ $values { "class" class } { "assoc" "an assoc whose keys are classes" } } +{ $description "Outputs the set of classes whose union is equal to " { $snippet "class" } ". Unions are expanded recursively so the output assoc does not contain any union classes. However, it may contain predicate classes whose superclasses are unions." } ; + +HELP: flatten-builtin-class +{ $values { "class" class } { "assoc" "an assoc whose keys are classes" } } +{ $description "Outputs a set of tuple classes whose union is the smallest cover of " { $snippet "class" } " intersected with " { $link tuple } "." } ; + +HELP: flatten-class +{ $values { "class" class } { "assoc" "an assoc whose keys are classes" } } +{ $description "Outputs a set of builtin and tuple classes whose union is the smallest cover of " { $snippet "class" } "." } ; + +HELP: types +{ $values { "class" class } { "seq" "an increasing sequence of integers" } } +{ $description "Outputs a sequence of builtin type numbers whose instances can possibly be instances of the given class." } ; + +HELP: class-empty? +{ $values { "class" "a class" } { "?" "a boolean" } } +{ $description "Tests if a class is a union class with no members." } +{ $examples { $example "USE: classes" "null class-empty? ." "t" } } ; + +HELP: (class<) +{ $values { "class1" "a class" } { "class2" "a class" } { "?" "a boolean" } } +{ $description "Performs the calculation for " { $link class< } ". There is never any reason to call this word from user code since " { $link class< } " outputs identical values and caches results for better performance." } ; + +HELP: class< +{ $values { "class1" "a class" } { "class2" "a class" } { "?" "a boolean" } } +{ $description "Tests if all instances of " { $snippet "class1" } " are also instances of " { $snippet "class2" } "." } +{ $notes "Classes are partially ordered. This means that if " { $snippet "class1 <= class2" } " and " { $snippet "class2 <= class1" } ", then " { $snippet "class1 = class2" } ". Also, if " { $snippet "class1 <= class2" } " and " { $snippet "class2 <= class3" } ", then " { $snippet "class1 <= class3" } "." } ; + +HELP: sort-classes +{ $values { "seq" "a sequence of class" } { "newseq" "a new seqence of classes" } } +{ $description "Outputs a topological sort of a sequence of classes. Larger classes come before their subclasses." } ; + +{ sort-classes methods order } related-words + +HELP: lookup-union +{ $values { "classes" "a hashtable mapping class words to themselves" } { "class" class } } +{ $description "Given a set of classes represented as a hashtable with equal keys and values, looks up a previously-defined union class having those members. If no union is defined, outputs " { $link object } "." } ; + +{ class-and class-or lookup-union } related-words + +HELP: class-or +{ $values { "class1" class } { "class2" class } { "class" class } } +{ $description "Outputs the smallest known class containing both " { $snippet "class1" } " and " { $snippet "class2" } "." } ; + +HELP: class-and +{ $values { "class1" class } { "class2" class } { "class" class } } +{ $description "Outputs the largest known class contained in both " { $snippet "class1" } " and " { $snippet "class2" } ". If the intersection is non-empty but no union class with those exact members is defined, outputs " { $link object } ". If the intersection is empty, outputs " { $link null } "." } ; + +HELP: classes-intersect? +{ $values { "class1" class } { "class2" class } { "?" "a boolean" } } +{ $description "Tests if two classes have a non-empty intersection. If the intersection is empty, no object can be an instance of both classes at once." } ; + +HELP: min-class +{ $values { "class" class } { "seq" "a sequence of class words" } { "class/f" "a class word or " { $link f } } } +{ $description "If all classes in " { $snippet "seq" } " that intersect " { $snippet "class" } " are subtypes of " { $snippet "class" } ", outputs the last such element of " { $snippet "seq" } ". If any conditions fail to hold, outputs " { $link f } "." } ; + +HELP: define-class +{ $values { "word" word } { "members" "a sequence of class words" } { "superclass" class } { "metaclass" class } } +{ $description "Sets a property indicating this word is a class word, thus making it an instance of " { $link class } ", and registers it with " { $link typemap } " and " { $link classclass ( n -- class ) builtins get nth ; + +: predicate-word ( word -- predicate ) + [ word-name "?" append ] keep word-vocabulary create ; + +: predicate-effect 1 { "?" } ; + +PREDICATE: compound predicate + "predicating" word-prop >boolean ; + +: define-predicate ( class predicate quot -- ) + over [ + dupd predicate-effect define-declared + 2dup 1quotation "predicate" set-word-prop + swap "predicating" set-word-prop + ] [ + 3drop + ] if ; + +: superclass ( class -- super ) + "superclass" word-prop ; + +: members ( class -- seq ) "members" word-prop ; + +: class-empty? ( class -- ? ) members dup [ empty? ] when ; + +: (flatten-union-class) ( class -- ) + dup members [ + [ (flatten-union-class) ] each + ] [ + dup set + ] ?if ; + +: flatten-union-class ( class -- assoc ) + [ (flatten-union-class) ] H{ } make-assoc ; + +: (flatten-class) ( class -- ) + { + { [ dup tuple-class? ] [ dup set ] } + { [ dup builtin-class? ] [ dup set ] } + { [ dup members ] [ members [ (flatten-class) ] each ] } + { [ dup superclass ] [ superclass (flatten-class) ] } + } cond ; + +: flatten-class ( class -- assoc ) + [ (flatten-class) ] H{ } make-assoc ; + +: class-hashes ( class -- seq ) + flatten-class keys [ + dup builtin-class? + [ "type" word-prop ] [ hashcode ] if + ] map ; + +: (flatten-builtin-class) ( class -- ) + { + { [ dup members ] [ members [ (flatten-builtin-class) ] each ] } + { [ dup superclass ] [ superclass (flatten-builtin-class) ] } + { [ t ] [ dup set ] } + } cond ; + +: flatten-builtin-class ( class -- assoc ) + [ (flatten-builtin-class) ] H{ } make-assoc ; + +: types ( class -- seq ) + flatten-builtin-class keys + [ "type" word-prop ] map natural-sort ; + +: class< ( class1 class2 -- ? ) swap classr superclass r> 2dup and [ (class<) ] [ 2drop f ] if ; + +: union-class< ( cls1 cls2 -- ? ) + [ flatten-union-class ] 2apply keys + [ nip [ (class<) ] curry* contains? ] curry assoc-all? ; + +: (class<) ( class1 class2 -- ? ) + { + { [ 2dup eq? ] [ 2drop t ] } + { [ over class-empty? ] [ 2drop t ] } + { [ 2dup superclass< ] [ 2drop t ] } + { [ 2dup [ members not ] both? ] [ 2drop f ] } + { [ t ] [ union-class< ] } + } cond ; + +: lookup-union ( classes -- class ) + typemap get at dup empty? [ drop object ] [ first ] if ; + +: (class-or) ( class class -- class ) + [ flatten-builtin-class ] 2apply union lookup-union ; + +: (class-and) ( class class -- class ) + [ flatten-builtin-class ] 2apply intersect lookup-union ; + +: tuple-class-and ( class1 class2 -- class ) + dupd eq? [ drop null ] unless ; + +: largest-class ( seq -- n elt ) + dup [ + [ 2dup class< >r swap class< not r> and ] + curry* subset empty? + ] curry find [ "Topological sort failed" throw ] unless* ; + +: (sort-classes) ( vec -- ) + dup empty? + [ drop ] + [ dup largest-class , over delete-nth (sort-classes) ] if ; + +PRIVATE> + +: sort-classes ( seq -- newseq ) + [ >vector (sort-classes) ] { } make ; + +: class-or ( class1 class2 -- class ) + { + { [ 2dup class< ] [ nip ] } + { [ 2dup swap class< ] [ drop ] } + { [ t ] [ (class-or) ] } + } cond ; + +: class-and ( class1 class2 -- class ) + { + { [ 2dup class< ] [ drop ] } + { [ 2dup swap class< ] [ nip ] } + { [ 2dup [ tuple-class? ] both? ] [ tuple-class-and ] } + { [ t ] [ (class-and) ] } + } cond ; + +: classes-intersect? ( class1 class2 -- ? ) + class-and class-empty? not ; + +: min-class ( class seq -- class/f ) + [ dupd classes-intersect? ] subset dup empty? [ + 2drop f + ] [ + tuck [ class< ] curry* all? [ peek ] [ drop f ] if + ] if ; + +GENERIC: reset-class ( class -- ) + +M: word reset-class drop ; + +assoc ] keep + classr >r 1vector r> r> set-at + ] if ; + +: typemap+ ( class -- ) + dup flatten-builtin-class typemap get push-at ; + +: pop-at ( value key assoc -- ) + at* [ delete ] [ 2drop ] if ; + +: typemap- ( class -- ) + dup flatten-builtin-class typemap get pop-at ; + +! Class definition +: cache-class ( class -- ) + dup typemap+ dup class + +: define-class-props ( members superclass metaclass -- assoc ) + [ + "metaclass" set + dup [ bootstrap-word ] when "superclass" set + [ bootstrap-word ] map "members" set + ] H{ } make-assoc ; + +: (define-class) ( word props -- ) + over reset-class + >r dup word-props r> union over set-word-props + dup intern-symbol + t "class" set-word-prop ; + +: define-class ( word members superclass metaclass -- ) + #! If it was already a class, update methods after. + define-class-props + over class? >r + over class-usages [ + uncache-classes + dupd (define-class) + ] keep cache-classes + r> [ update-methods ] [ drop ] if ; + +GENERIC: class ( object -- class ) inline + +M: object class type type>class ; + + diff --git a/core/classes/mixin/authors.txt b/core/classes/mixin/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/classes/mixin/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/classes/mixin/mixin-docs.factor b/core/classes/mixin/mixin-docs.factor new file mode 100644 index 0000000000..fedf7c3a29 --- /dev/null +++ b/core/classes/mixin/mixin-docs.factor @@ -0,0 +1,14 @@ +USING: help.markup help.syntax ; +IN: classes.mixin + +ARTICLE: "mixins" "Mixin classes" +"An object is an instance of a union class if it is an instance of one of its members. In this respect, mixin classes are identical to union classes. However, new classes can be made into instances of a mixin class after the original definition of the mixin." +{ $subsection POSTPONE: MIXIN: } +{ $subsection POSTPONE: INSTANCE: } +{ $subsection define-mixin-class } +{ $subsection add-mixin-instance } +"The set of mixin classes is a class:" +{ $subsection mixin-class } +{ $subsection mixin-class? } ; + +ABOUT: "mixins" diff --git a/core/classes/mixin/mixin.factor b/core/classes/mixin/mixin.factor new file mode 100644 index 0000000000..4ea6f430b3 --- /dev/null +++ b/core/classes/mixin/mixin.factor @@ -0,0 +1,29 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: classes classes.union words kernel sequences ; +IN: classes.mixin + +PREDICATE: union-class mixin-class "mixin" word-prop ; + +M: mixin-class reset-class + { "metaclass" "members" "mixin" } reset-props ; + +: redefine-mixin-class ( class members -- ) + dupd define-union-class + t "mixin" set-word-prop ; + +: define-mixin-class ( class -- ) + dup mixin-class? [ + drop + ] [ + { } redefine-mixin-class + ] if ; + +: add-mixin-instance ( class mixin -- ) + dup mixin-class? [ "Not a mixin class" throw ] unless + 2dup members memq? [ + 2drop + ] [ + [ members swap bootstrap-word add ] keep swap + redefine-mixin-class + ] if ; diff --git a/core/classes/mixin/summary.txt b/core/classes/mixin/summary.txt new file mode 100644 index 0000000000..9e93a91f0e --- /dev/null +++ b/core/classes/mixin/summary.txt @@ -0,0 +1 @@ +Mixin classes (extensible unions) diff --git a/core/classes/predicate/authors.txt b/core/classes/predicate/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/classes/predicate/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/classes/predicate/predicate-docs.factor b/core/classes/predicate/predicate-docs.factor new file mode 100644 index 0000000000..4657671f7f --- /dev/null +++ b/core/classes/predicate/predicate-docs.factor @@ -0,0 +1,23 @@ +USING: generic help.markup help.syntax kernel kernel.private +namespaces sequences words arrays layouts help effects math +layouts classes.private classes ; +IN: classes.predicate + +ARTICLE: "predicates" "Predicate classes" +"Predicate classes allow fine-grained control over method dispatch." +{ $subsection POSTPONE: PREDICATE: } +{ $subsection define-predicate-class } +"The set of predicate classes is a class:" +{ $subsection predicate-class } +{ $subsection predicate-class? } ; + +ABOUT: "predicates" + +HELP: define-predicate-class +{ $values { "superclass" class } { "class" class } { "definition" "a quotation with stack effect " { $snippet "( superclass -- ? )" } } } +{ $description "Defines a predicate class." } ; + +{ predicate-class define-predicate-class POSTPONE: PREDICATE: } related-words + +HELP: predicate-class +{ $class-description "The class of predicate class words, defined by " { $link POSTPONE: PREDICATE: } " and documented in " { $link "predicates" } "." } ; diff --git a/core/classes/predicate/predicate.factor b/core/classes/predicate/predicate.factor new file mode 100644 index 0000000000..a7270869c5 --- /dev/null +++ b/core/classes/predicate/predicate.factor @@ -0,0 +1,24 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: classes kernel namespaces words ; +IN: classes.predicate + +PREDICATE: class predicate-class + "metaclass" word-prop predicate-class eq? ; + +: predicate-quot ( class -- quot ) + [ + \ dup , + dup superclass "predicate" word-prop % + "predicate-definition" word-prop , [ drop f ] , \ if , + ] [ ] make ; + +: define-predicate-class ( superclass class definition -- ) + >r dup f roll predicate-class define-class r> + dupd "predicate-definition" set-word-prop + dup predicate-word over predicate-quot define-predicate ; + +M: predicate-class reset-class + { + "metaclass" "predicate-definition" "superclass" + } reset-props ; diff --git a/core/classes/predicate/summary.txt b/core/classes/predicate/summary.txt new file mode 100644 index 0000000000..2a55d634f0 --- /dev/null +++ b/core/classes/predicate/summary.txt @@ -0,0 +1 @@ +Predicate classes diff --git a/core/classes/summary.txt b/core/classes/summary.txt new file mode 100644 index 0000000000..4dbb64316b --- /dev/null +++ b/core/classes/summary.txt @@ -0,0 +1 @@ +Object system implementation diff --git a/core/classes/tags.txt b/core/classes/tags.txt new file mode 100644 index 0000000000..abf53a421b --- /dev/null +++ b/core/classes/tags.txt @@ -0,0 +1 @@ +reflection diff --git a/core/classes/union/authors.txt b/core/classes/union/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/classes/union/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/classes/union/summary.txt b/core/classes/union/summary.txt new file mode 100644 index 0000000000..7f4e818334 --- /dev/null +++ b/core/classes/union/summary.txt @@ -0,0 +1 @@ +Union classes diff --git a/core/classes/union/union-docs.factor b/core/classes/union/union-docs.factor new file mode 100644 index 0000000000..41e761955e --- /dev/null +++ b/core/classes/union/union-docs.factor @@ -0,0 +1,25 @@ +USING: generic help.markup help.syntax kernel kernel.private +namespaces sequences words arrays layouts help effects math +layouts classes.private classes ; +IN: classes.union + +ARTICLE: "unions" "Union classes" +"An object is an instance of a union class if it is an instance of one of its members. Union classes are used to associate the same method with several different classes, as well as to conveniently define predicates." +{ $subsection POSTPONE: UNION: } +{ $subsection define-union-class } +"Union classes can be introspected:" +{ $subsection members } +"The set of union classes is a class:" +{ $subsection union-class } +{ $subsection union-class? } ; + +ABOUT: "unions" + +HELP: define-union-class +{ $values { "class" class } { "members" "a sequence of classes" } } +{ $description "Defines a union class with specified members." } ; + +{ union-class define-union-class POSTPONE: UNION: } related-words + +HELP: union-class +{ $class-description "The class of union classes." } ; diff --git a/core/classes/union/union.factor b/core/classes/union/union.factor new file mode 100644 index 0000000000..e95c08b507 --- /dev/null +++ b/core/classes/union/union.factor @@ -0,0 +1,27 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: words sequences kernel assocs combinators classes +generic.standard namespaces arrays ; +IN: classes.union + +PREDICATE: class union-class + "metaclass" word-prop union-class eq? ; + +! Union classes for dispatch on multiple classes. +: union-predicate-quot ( members -- quot ) + 0 (dispatch#) [ + [ [ drop t ] ] { } map>assoc + object bootstrap-word [ drop f ] 2array add* + single-combination + ] with-variable ; + +: define-union-predicate ( class -- ) + dup predicate-word + over members union-predicate-quot + define-predicate ; + +: define-union-class ( class members -- ) + dupd f union-class define-class define-union-predicate ; + +M: union-class reset-class + { "metaclass" "members" } reset-props ; diff --git a/core/combinators/authors.txt b/core/combinators/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/combinators/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/combinators/combinators-docs.factor b/core/combinators/combinators-docs.factor new file mode 100644 index 0000000000..731b12b0b4 --- /dev/null +++ b/core/combinators/combinators-docs.factor @@ -0,0 +1,132 @@ +USING: arrays help.markup help.syntax strings sbufs vectors +kernel quotations generic generic.standard classes +math assocs sequences combinators.private ; +IN: combinators + +ARTICLE: "combinators-quot" "Quotation construction utilities" +"Some words for creating quotations which can be useful for implementing method combinations and compiler transforms:" +{ $subsection make-dip } +{ $subsection cond>quot } +{ $subsection case>quot } +{ $subsection alist>quot } +"A powerful tool used to optimize code in several places is open-coded hashtable dispatch:" +{ $subsection hash-case>quot } +{ $subsection distribute-buckets } +{ $subsection hash-dispatch-quot } ; + +ARTICLE: "combinators" "Additional combinators" +"The " { $vocab-link "combinators" } " vocabulary is usually used because it provides two combinators which abstract out nested chains of " { $link if } ":" +{ $subsection cond } +{ $subsection case } +"A combinator which can help with implementing methods on " { $link hashcode* } ":" +{ $subsection recursive-hashcode } +"An oddball combinator:" +{ $subsection with-datastack } +{ $subsection "combinators-quot" } +{ $see-also "quotations" "basic-combinators" } ; + +ABOUT: "combinators" + +HELP: make-dip +{ $values { "quot" "a quotation" } { "n" "a non-negative integer" } { "newquot" "a new quotation" } } +{ $description "Constructs a quotation which retains the top " { $snippet "n" } " stack items, and applies " { $snippet "quot" } " to what is underneath." } +{ $examples + { $example "USE: quotations" "[ 3 + ] 2 make-dip ." "[ >r >r 3 + r> r> ]" } +} ; + +HELP: alist>quot +{ $values { "default" "a quotation" } { "assoc" "a sequence of quotation pairs" } { "quot" "a new quotation" } } +{ $description "Constructs a quotation which calls the first quotation in each pair of " { $snippet "assoc" } " until one of them outputs a true value, and then calls the second quotation in the corresponding pair. Quotations are called in reverse order, and if no quotation outputs a true value then " { $snippet "default" } " is called." } +{ $notes "This word is used to implement compile-time behavior for " { $link cond } ", and it is also used by the generic word system. Note that unlike " { $link cond } ", the constructed quotation performs the tests starting from the end and not the beginning." } ; + +HELP: cond +{ $values { "assoc" "a sequence of quotation pairs" } } +{ $description + "Calls the second quotation in the first pair whose first quotation yields a true value." + $nl + "The following two phrases are equivalent:" + { $code "{ { [ X ] [ Y ] } { [ Z ] [ T ] } } cond" } + { $code "X [ Y ] [ Z [ T ] [ no-cond ] if ] if" } +} +{ $errors "Throws a " { $link no-cond } " error if none of the test quotations yield a true value." } +{ $examples + { $code + "{" + " { [ dup 0 > ] [ \"positive\" ] }" + " { [ dup 0 < ] [ \"negative\" ] }" + " { [ dup zero? ] [ \"zero\" ] }" + "} cond" + } +} ; + +HELP: no-cond +{ $description "Throws a " { $link no-cond } " error." } +{ $error-description "Thrown by " { $link cond } " if none of the test quotations yield a true value. Some uses of " { $link cond } " include a default case where the test quotation is " { $snippet "[ t ]" } "; such a " { $link cond } " form will never throw this error." } ; + +HELP: case +{ $values { "obj" object } { "assoc" "a sequence of object/quotation pairs, with an optional quotation at the end" } } +{ $description + "Compares " { $snippet "obj" } " against the first element of every pair. If some pair matches, removes " { $snippet "obj" } " from the stack and calls the second element of that pair, which must be a quotation." + $nl + "If there is no case matching " { $snippet "obj" } ", the default case is taken. If the last element of " { $snippet "cases" } " is a quotation, the quotation is called with " { $snippet "obj" } " on the stack. Otherwise, a " { $link no-cond } " error is rasied." + $nl + "The following two phrases are equivalent:" + { $code "{ { X [ Y ] } { Y [ T ] } } case" } + { $code "dup X = [ drop Y ] [ dup Z = [ drop T ] [ no-case ] if ] if" } +} +{ $examples + { $code + "SYMBOL: yes SYMBOL: no SYMBOL: maybe" + "maybe {" + " { yes [ ] } ! Do nothing" + " { no [ \"No way!\" throw ] }" + " { maybe [ \"Make up your mind!\" print ] }" + " [ \"Invalid input; try again.\" print ]" + "} case" + } +} ; + +HELP: no-case +{ $description "Throws a " { $link no-case } " error." } +{ $error-description "Thrown by " { $link case } " if the object at the top of the stack does not match any case, and no default case is given." } ; + +HELP: with-datastack +{ $values { "stack" sequence } { "quot" quotation } { "newstack" sequence } } +{ $description "Executes the quotation with the given data stack contents, and outputs the new data stack after the word returns. The input sequence is not modified. Does not affect the data stack in surrounding code, other than consuming the two inputs and pushing the output." } +{ $examples + { $example "{ 3 7 } [ + ] with-datastack ." "{ 10 }" } +} ; + +HELP: recursive-hashcode +{ $values { "n" integer } { "obj" object } { "quot" "a quotation with stack effect " { $snippet "( n obj -- code )" } } { "code" integer } } +{ $description "A combinator used to implement methods for the " { $link hashcode* } " generic word. If " { $snippet "n" } " is less than or equal to zero, outputs 0, otherwise calls the quotation." } ; + +HELP: cond>quot +{ $values { "assoc" "a sequence of pairs of quotations" } { "quot" quotation } } +{ $description "Creates a quotation that when called, has the same effect as applying " { $link cond } " to " { $snippet "assoc" } "." +$nl +"the generated quotation is more efficient than the naive implementation of " { $link cond } ", though, since it expands into a series of conditionals, and no iteration through " { $snippet "assoc" } " has to be performed." } +{ $notes "This word is used behind the scenes to compile " { $link cond } " forms efficiently; it can also be called directly, which is useful for meta-programming." } ; + +HELP: case>quot +{ $values { "assoc" "a sequence of pairs of quotations" } { "default" quotation } { "quot" quotation } } +{ $description "Creates a quotation that when called, has the same effect as applying " { $link case } " to " { $snippet "assoc" } "." +$nl +"The quotation actually tests each possible case in order;" { $link hash-case>quot } " produces more efficient code." } ; + +HELP: distribute-buckets +{ $values { "assoc" "an alist" } { "initial" object } { "quot" "a quotation with stack effect " { $snippet "( obj -- assoc )" } } { "buckets" "a new array" } } +{ $description "Sorts the entries of " { $snippet "assoc" } " into buckets, using the quotation to yield a set of keys for each entry. The hashcode of each key is computed, and the entry is placed in all corresponding buckets. Each bucket is initially cloned from " { $snippet "initial" } "; this should either be an empty vector or a one-element vector containing a pair." } +{ $notes "This word is used in the implemention of " { $link hash-case>quot } " and " { $link standard-combination } "." } ; + +HELP: hash-case>quot +{ $values { "default" quotation } { "assoc" "an association list mapping quotations to quotations" } { "quot" quotation } } +{ $description "Creates a quotation that when called, has the same effect as applying " { $link case } " to " { $snippet "assoc" } "." +$nl +"The quotation uses an efficient hash-based search to avoid testing the object against all possible keys." } +{ $notes "This word is used behind the scenes to compile " { $link case } " forms efficiently; it can also be called directly, which is useful for meta-programming." } ; + +HELP: dispatch ( n array -- ) +{ $values { "n" "a fixnum" } { "array" "an array of quotations" } } +{ $description "Calls the " { $snippet "n" } "th quotation in the array." } +{ $warning "This word is in the " { $vocab-link "kernel.private" } " vocabulary because it is an implementation detail used by the generic word system to accelerate method dispatch. It does not perform type or bounds checks, and user code should not need to call it directly." } ; diff --git a/core/combinators/combinators-tests.factor b/core/combinators/combinators-tests.factor new file mode 100644 index 0000000000..208f8c0c84 --- /dev/null +++ b/core/combinators/combinators-tests.factor @@ -0,0 +1,71 @@ +IN: temporary +USING: alien strings kernel math tools.test io prettyprint +namespaces combinators words ; + +[ "even" ] [ + 2 { + { [ dup 2 mod 0 = ] [ drop "even" ] } + { [ dup 2 mod 1 = ] [ drop "odd" ] } + } cond +] unit-test + +[ "odd" ] [ + 3 { + { [ dup 2 mod 0 = ] [ drop "even" ] } + { [ dup 2 mod 1 = ] [ drop "odd" ] } + } cond +] unit-test + +[ "neither" ] [ + 3 { + { [ dup string? ] [ drop "string" ] } + { [ dup float? ] [ drop "float" ] } + { [ dup alien? ] [ drop "alien" ] } + { [ t ] [ drop "neither" ] } + } cond +] unit-test + +: case-test-1 + { + { 1 [ "one" ] } + { 2 [ "two" ] } + { 3 [ "three" ] } + { 4 [ "four" ] } + } case ; + +[ "two" ] [ 2 case-test-1 ] unit-test + +! Interpreted +[ "two" ] [ 2 \ case-test-1 word-def call ] unit-test + +[ "x" case-test-1 ] unit-test-fails + +: case-test-2 + { + { 1 [ "one" ] } + { 2 [ "two" ] } + { 3 [ "three" ] } + { 4 [ "four" ] } + [ sq ] + } case ; + +[ 25 ] [ 5 case-test-2 ] unit-test + +! Interpreted +[ 25 ] [ 5 \ case-test-2 word-def call ] unit-test + +: case-test-3 + { + { 1 [ "one" ] } + { 2 [ "two" ] } + { 3 [ "three" ] } + { 4 [ "four" ] } + { H{ } [ "a hashtable" ] } + { { 1 2 3 } [ "an array" ] } + [ sq ] + } case ; + +[ "an array" ] [ { 1 2 3 } case-test-3 ] unit-test + +! Interpreted +[ "a hashtable" ] [ H{ } \ case-test-3 word-def call ] unit-test diff --git a/core/combinators/combinators.factor b/core/combinators/combinators.factor new file mode 100644 index 0000000000..cda1d41960 --- /dev/null +++ b/core/combinators/combinators.factor @@ -0,0 +1,86 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: combinators +USING: arrays sequences sequences.private math.private +kernel kernel.private math assocs quotations vectors ; + + + +TUPLE: no-cond ; + +: no-cond ( -- * ) \ no-cond construct-empty throw ; + +: cond ( assoc -- ) + [ first call ] find nip dup [ second call ] [ no-cond ] if ; + +TUPLE: no-case ; + +: no-case ( -- * ) \ no-case construct-empty throw ; + +: case ( obj assoc -- ) + [ dup array? [ dupd first = ] [ quotation? ] if ] find nip + { + { [ dup array? ] [ nip second call ] } + { [ dup quotation? ] [ call ] } + { [ dup not ] [ no-case ] } + } cond ; + +: with-datastack ( stack quot -- newstack ) + datastack >r + >r >array set-datastack r> call + datastack r> swap add set-datastack 2nip ; inline + +: recursive-hashcode ( n obj quot -- code ) + pick 0 <= [ 3drop 0 ] [ rot 1- -rot call ] if ; inline + +M: sequence hashcode* + [ + 0 -rot [ hashcode* bitxor ] curry* each + ] recursive-hashcode ; + +: alist>quot ( default assoc -- quot ) + [ rot \ if 3array append [ ] like ] assoc-each ; + +: cond>quot ( assoc -- quot ) + reverse [ no-cond ] swap alist>quot ; + +: case>quot ( default assoc -- quot ) + [ >r [ dupd = ] curry r> \ drop add* ] assoc-map + alist>quot ; + +: (distribute-buckets) ( buckets pair keys -- ) + dup t eq? [ + drop [ swap push-new ] curry each + ] [ + [ + >r 2dup r> hashcode pick length rem rot nth push-new + ] each 2drop + ] if ; + +: ( initial length -- array ) + next-power-of-2 swap [ nip clone ] curry map ; + +: distribute-buckets ( assoc initial quot -- buckets ) + swap rot [ length ] keep + [ >r 2dup r> dup first roll call (distribute-buckets) ] each + nip ; inline + +: hash-case-table ( default assoc -- array ) + V{ } [ 1array ] distribute-buckets + [ case>quot ] curry* map ; + +: hash-dispatch-quot ( table -- quot ) + [ length 1- [ fixnum-bitand ] curry ] keep + [ dispatch ] curry append ; + +: hash-case>quot ( default assoc -- quot ) + dup empty? [ + drop + ] [ + hash-case-table hash-dispatch-quot + [ dup hashcode >fixnum ] swap append + ] if ; diff --git a/core/combinators/summary.txt b/core/combinators/summary.txt new file mode 100644 index 0000000000..9346bba6b9 --- /dev/null +++ b/core/combinators/summary.txt @@ -0,0 +1 @@ +Complex conditionals (cond, case) and support words for quotation construction diff --git a/core/command-line/authors.txt b/core/command-line/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/command-line/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/command-line/command-line-docs.factor b/core/command-line/command-line-docs.factor new file mode 100644 index 0000000000..0c9bbd131a --- /dev/null +++ b/core/command-line/command-line-docs.factor @@ -0,0 +1,113 @@ +USING: help.markup help.syntax parser vocabs.loader strings ; +IN: command-line + +ARTICLE: "runtime-cli-args" "Command line switches for the VM" +"A handful of command line switches are processed by the VM and not the library. They control low-level features." +{ $table + { { $snippet "-i=" { $emphasis "image" } } "Specifies the image file to use" } + { { $snippet "-datastack=" { $emphasis "n" } } "Data stack size, kilobytes" } + { { $snippet "-retainstack=" { $emphasis "n" } } "Retain stack size, kilobytes" } + { { $snippet "-generations=" { $emphasis "n" } } "Number of generations, must be >= 2" } + { { $snippet "-young=" { $emphasis "n" } } { "Size of " { $snippet { $emphasis "n" } "-1" } " youngest generations, megabytes" } } + { { $snippet "-aging=" { $emphasis "n" } } "Size of tenured and semi-spaces, megabytes" } + { { $snippet "-codeheap=" { $emphasis "n" } } "Code heap size, megabytes" } + { { $snippet "-securegc" } "If specified, unused portions of the data heap will be zeroed out after every garbage collection" } +} +"If an " { $snippet "-i=" } " switch is not present, the default image file is used, which is usually a file named " { $snippet "factor.image" } " in the same directory as the runtime executable (on Windows and Mac OS X) or the current directory (on Unix)." ; + +ARTICLE: "bootstrap-cli-args" "Command line switches for bootstrap" +"A number of command line switches can be passed to a bootstrap image to modify the behavior of the resulting image:" +{ $table + { { $snippet "-output-image=" { $emphasis "image" } } { "Save the result to " { $snippet "image" } ". The default is " { $snippet "factor.image" } "." } } + { { $snippet "-no-user-init" } { "Inhibits the running of the " { $snippet ".factor-boot-rc" } " file in the user's home directory." } } + { { $snippet "-include=" { $emphasis "components..." } } "A list of components to include (see below)." } + { { $snippet "-exclude=" { $emphasis "components..." } } "A list of components to exclude." } + { { $snippet "-ui-backend=" { $emphasis "backend" } } { "One of " { $snippet "x11" } ", " { $snippet "windows" } ", or " { $snippet "cocoa" } ". The default is platform-specific." } } +} +"Bootstrap can load various optional components:" +{ $table + { { $snippet "compiler" } "The compiler." } + { { $snippet "tools" } "Terminal-based developer tools." } + { { $snippet "help" } "The help system." } + { { $snippet "ui" } "The graphical user interface." } + { { $snippet "ui.tools" } "Graphical developer tools." } + { { $snippet "io" } "Non-blocking I/O and networking." } +} +"By default, all optional components are loaded. To load all optional components except for a given list, use the " { $snippet "-exclude=" } " switch; to only load specified optional components, use the " { $snippet "-include=" } "." +$nl +"For example, to build an image with the compiler but no other components, you could do:" +{ $code "./factor -i=boot.ppc.image -include=compiler" } +"To build an image with everything except for the user interface and graphical tools," +{ $code "./factor -i=boot.ppc.image -exclude=\"ui ui.tools\"" } +"To generate a bootstrap image in the first place, see " { $link "bootstrap.image" } "." ; + +ARTICLE: "standard-cli-args" "Command line switches for general usage" +"The following command line switches can be passed to a bootstrapped Factor image:" +{ $table + { { $snippet "-e=" { $emphasis "code" } } { "This specifies a code snippet to evaluate. If you want Factor to exit immediately after, also specify " { $snippet "-run=none" } "." } } + { { $snippet "-run=" { $emphasis "vocab" } } { { $snippet { $emphasis "vocab" } } " is the name of a vocabulary with a " { $link POSTPONE: MAIN: } " hook to run on startup, for example " { $vocab-link "listener" } ", " { $vocab-link "ui" } " or " { $vocab-link "none" } "." } } + { { $snippet "-no-user-init" } { "Inhibits the running of the " { $snippet ".factor-rc" } " file in the user's home directory on startup." } } + { { $snippet "-quiet" } { "If set, " { $link run-file } " and " { $link require } " will not print load messages." } } + { { $snippet "-script" } { "Equivalent to " { $snippet "-quiet -run=none" } "." $nl "On Unix systems, Factor can be used for scripting - just create an executable text file whose first line is:" { $code "#! /usr/local/bin/factor -script" } "The space after " { $snippet "#!" } " is necessary because of Factor syntax." } } +} ; + +ARTICLE: "cli" "Command line usage" +"Unless the " { $snippet "-no-user-init" } " command line switch is specified, The startup routine runs the " { $snippet ".factor-rc" } " file in the user's home directory, if it exists. This file can contain initialization and customization for your development environment." +$nl +"Zero or more command line arguments may be passed to the Factor runtime. Command line arguments starting with a dash (" { $snippet "-" } ") is interpreted as switches. All other arguments are taken to be file names to be run by " { $link run-file } "." +$nl +"Switches can take one of the following three forms:" +{ $list + { { $snippet "-" { $emphasis "foo" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $link t } } + { { $snippet "-no-" { $emphasis "foo" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $link f } } + { { $snippet "-" { $emphasis "foo" } "=" { $emphasis "bar" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $snippet "\"" { $emphasis "bar" } "\"" } } +} +{ $subsection "runtime-cli-args" } +{ $subsection "bootstrap-cli-args" } +{ $subsection "standard-cli-args" } +"The list of command line arguments can be obtained and inspected directly:" +{ $subsection cli-args } +"The " { $snippet ".factor-rc" } " and " { $snippet ".factor-boot-rc" } " files can be run explicitly:" +{ $subsection run-user-init } +{ $subsection run-bootstrap-init } +"There is a way to override the default vocabulary to run on startup:" +{ $subsection main-vocab-hook } ; + +ABOUT: "cli" + +HELP: run-bootstrap-init +{ $description "Runs the " { $snippet ".factor-boot-rc" } " file in the user's home directory unless the " { $snippet "-no-user-init" } " command line switch was given." } ; + +HELP: run-user-init +{ $description "Runs the " { $snippet ".factor-rc" } " file in the user's home directory unless the " { $snippet "-no-user-init" } " command line switch was given." } ; + +HELP: cli-param +{ $values { "param" string } } +{ $description "Process a command-line switch." +$nl +"If the parameter contains " { $snippet "=" } ", the global variable named by the string before the equals sign is set to the string after the equals sign." +$nl +"If the parameter begins with " { $snippet "no-" } ", sets the global variable named by the parameter with the prefix removed to " { $link f } "." +$nl +"Otherwise, sets the global variable named by the parameter to " { $link t } "." } ; + +HELP: cli-args +{ $values { "args" "a sequence of strings" } } +{ $description "Outputs the command line parameters which were passed to the Factor VM on startup." } ; + +HELP: main-vocab-hook +{ $var-description "Global variable holding a quotation which outputs a vocabulary name. UI backends set this so that the UI can automatically start if the prerequisites are met (for example, " { $snippet "$DISPLAY" } " being set on X11)." } ; + +HELP: main-vocab +{ $values { "vocab" string } } +{ $description "Outputs the name of the vocabulary which is to be run on startup using the " { $link run } " word. The " { $snippet "-run" } " command line switch overrides this setting." } ; + +HELP: default-cli-args +{ $description "Sets global variables corresponding to default command line arguments." } ; + +HELP: ignore-cli-args? +{ $values { "?" "a boolean" } } +{ $description "On Mac OS X, source files to run are supplied by the Cocoa API, so to avoid running them twice the startup code has to call this word." } ; + +HELP: parse-command-line +{ $description "Called on startup to process command line arguments. This sets global variables with " { $link cli-param } ", runs source files, and evaluates the string given by the " { $snippet "-e" } " switch, if there is one." } ; diff --git a/core/command-line/command-line-tests.factor b/core/command-line/command-line-tests.factor new file mode 100644 index 0000000000..c4221b0d06 --- /dev/null +++ b/core/command-line/command-line-tests.factor @@ -0,0 +1,12 @@ +USING: namespaces tools.test kernel command-line ; +IN: temporary + +[ + [ f ] [ "-no-user-init" cli-arg ] unit-test + [ f ] [ "user-init" get ] unit-test + + [ f ] [ "-user-init" cli-arg ] unit-test + [ t ] [ "user-init" get ] unit-test + + [ "sdl.factor" ] [ "sdl.factor" cli-arg ] unit-test +] with-scope diff --git a/core/command-line/command-line.factor b/core/command-line/command-line.factor new file mode 100644 index 0000000000..ed4fb9f606 --- /dev/null +++ b/core/command-line/command-line.factor @@ -0,0 +1,62 @@ +! Copyright (C) 2003, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: command-line +USING: init continuations debugger hashtables io kernel +kernel.private namespaces parser sequences strings system +splitting io.files ; + +: run-bootstrap-init ( -- ) + "user-init" get [ + home ".factor-boot-rc" path+ ?run-file + ] when ; + +: run-user-init ( -- ) + "user-init" get [ + home ".factor-rc" path+ ?run-file + ] when ; + +: cli-var-param ( name value -- ) swap set-global ; + +: cli-bool-param ( name -- ) "no-" ?head not cli-var-param ; + +: cli-param ( param -- ) + "=" split1 [ cli-var-param ] [ cli-bool-param ] if* ; + +: cli-arg ( argument -- argument ) + "-" ?head [ cli-param f ] when ; + +: cli-args ( -- args ) 10 getenv ; + +SYMBOL: main-vocab-hook + +: main-vocab ( -- vocab ) + embedded? [ + "alien.remote-control" + ] [ + main-vocab-hook get [ call ] [ "listener" ] if* + ] if ; + +: default-cli-args + global [ + "quiet" off + "script" off + "e" off + "user-init" on + embedded? "quiet" set + main-vocab "run" set + ] bind ; + +: ignore-cli-args? ( -- ? ) + macosx? "run" get "ui" = and ; + +: script-mode ( -- ) + t "quiet" set-global + "none" "run" set-global ; + +: parse-command-line ( -- ) + cli-args [ cli-arg ] subset + "script" get [ script-mode ] when + ignore-cli-args? [ drop ] [ [ run-file ] each ] if + "e" get [ eval ] when* ; + +[ default-cli-args ] "command-line" add-init-hook diff --git a/core/command-line/summary.txt b/core/command-line/summary.txt new file mode 100644 index 0000000000..3f1ff8703f --- /dev/null +++ b/core/command-line/summary.txt @@ -0,0 +1 @@ +Command line argument parsing diff --git a/core/compiler/authors.txt b/core/compiler/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/compiler/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/compiler/compiler-docs.factor b/core/compiler/compiler-docs.factor new file mode 100644 index 0000000000..29744d31a6 --- /dev/null +++ b/core/compiler/compiler-docs.factor @@ -0,0 +1,139 @@ +USING: generator help.markup help.syntax words io parser +assocs words.private sequences ; +IN: compiler + +ARTICLE: "compiler-usage" "Calling the optimizing compiler" +"The main entry point to the optimizing compiler is a single word taking a word as input:" +{ $subsection compile } +"The above word throws an error if the word did not compile. Another variant simply prints the error and returns:" +{ $subsection try-compile } +"The optimizing compiler can also compile a single quotation:" +{ $subsection compile-quot } +{ $subsection compile-1 } +"Three utility words for bulk compilation:" +{ $subsection compile-batch } +{ $subsection compile-vocabs } +{ $subsection compile-all } +"Bulk compilation saves compile warnings and errors in a global variable, instead of printing them as they arise:" +{ $subsection compile-errors } +"The warnings and errors can be viewed later:" +{ $subsection :warnings } +{ $subsection :errors } +{ $subsection forget-errors } ; + +ARTICLE: "recompile" "Automatic recompilation" +"When a word is redefined, you can recompile all affected words automatically:" +{ $subsection recompile } +"Normally loading a source file or a module also calls " { $link recompile } ". This can be disabled by wrapping file loading in a combinator:" +{ $subsection no-parse-hook } ; + +ARTICLE: "compiler" "Optimizing compiler" +"Factor is a fully compiled language implementation with two distinct compilers:" +{ $list + { "The " { $emphasis "non-optimizing quotation compiler" } " compiles quotations to naive machine code very quickly. The non-optimizing quotation compiler is part of the VM." } + { "The " { $emphasis "optimizing word compiler" } " compiles whole words at a time while performing extensive data and control flow analysis. This provides greater performance for generated code, but incurs a much longer compile time. The optimizing compiler is written in Factor." } +} +"While the quotation compiler is transparent to the developer, the optimizing compiler is invoked explicitly. It differs in two important ways from the non-optimizing compiler:" +{ $list + { "The optimizing compiler only compiles words which have a static stack effect. This means that methods defined on fundamental generic words such as " { $link nth } " should have a static stack effect; for otherwise, most of the system would be compiled with the non-optimizing compiler. See " { $link "inference" } " and " { $link "cookbook-pitfalls" } "." } + { "The optimizing compiler performs " { $emphasis "early binding" } "; if a compiled word " { $snippet "A" } " calls another compiled word " { $snippet "B" } " and " { $snippet "B" } " is subsequently redefined, the compiled definition of " { $snippet "A" } " will still refer to the earlier compiled definition of " { $snippet "B" } ", until " { $snippet "A" } " explicitly recompiled." } +} +{ $subsection "compiler-usage" } +{ $subsection "recompile" } ; + +ABOUT: "compiler" + +HELP: compile-error +{ $values { "word" word } { "error" "an error" } } +{ $description "If inside a " { $link compile-batch } ", saves the error for future persual via " { $link :errors } " and " { $link :warnings } ", otherwise reports the error to the " { $link stdio } " stream." } ; + +HELP: begin-batch +{ $values { "seq" "a sequence of words" } } +{ $description "Begins batch compilation. Any compile errors reported until a call to " { $link end-batch } " are stored in the " { $link compile-errors } " global variable." } +$low-level-note ; + +HELP: compile-error. +{ $values { "pair" "a " { $snippet "{ word error }" } " pair" } } +{ $description "Prints a compiler error to the " { $link stdio } " stream." } ; + +HELP: (:errors) +{ $values { "seq" "an alist" } } +{ $description "Outputs all serious compiler errors from the most recent compile batch as a sequence of " { $snippet "{ word error }" } " pairs." } ; + +HELP: :errors +{ $description "Prints all serious compiler errors from the most recent compile batch to the " { $link stdio } " stream." } ; + +HELP: (:warnings) +{ $values { "seq" "an alist" } } +{ $description "Outputs all ignorable compiler warnings from the most recent compile batch as a sequence of " { $snippet "{ word error }" } " pairs." } ; + +HELP: :warnings +{ $description "Prints all ignorable compiler warnings from the most recent compile batch to the " { $link stdio } " stream." } ; + +HELP: end-batch +{ $description "Ends batch compilation, printing a summary of the errors and warnings produced to the " { $link stdio } " stream." } +$low-level-note ; + +HELP: compile +{ $values { "word" word } } +{ $description "Compiles a word together with any uncompiled dependencies. Does nothing if the word is already compiled." } +{ $errors "If compilation fails, this word can throw an error. In particular, if the word's stack effect cannot be inferred, this word will throw an error. The related " { $link try-compile } " word logs errors and returns rather than throwing." } ; + +HELP: compile-failed +{ $values { "word" word } { "error" "an error" } } +{ $description "Called when the optimizing compiler fails to compile a word. The word is removed from the set of words pending compilation, and it's un-optimized compiled definition will be used. The error is reported by calling " { $link compile-error } "." } ; + +HELP: try-compile +{ $values { "word" word } } +{ $description "Compiles a word together with any uncompiled dependencies. Does nothing if the word is already compiled." } +{ $errors "If compilation fails, this calls " { $link compile-failed } "." } ; + +HELP: forget-errors +{ $values { "seq" "a sequence of words" } } +{ $description "If any of the words in the sequence previously failed to compile, removes the marker indicating such." +$nl +"The compiler remembers which words failed to compile as an optimization, so that it does not try to infer the stack effect of words which do not have one over and over again." } +{ $notes "Usually this word does not need to be called directly; if a word failed to compile because of a stack effect error, fixing the word definition clears the flag automatically. However, if words failed to compile due to external factors which were subsequently rectified, such as an unavailable C library or a missing or broken compiler transform, this flag can be cleared for all words:" +{ $code "all-words forget-errors" } +"Subsequent invocations of the compiler will consider all words for compilation." } ; + +HELP: compile-batch +{ $values { "seq" "a sequence of words" } } +{ $description "Compiles a batch of words. Any compile errors are summarized at the end and can be viewed with " { $link :warnings } " and " { $link :errors } "." } ; + +{ :errors (:errors) :warnings (:warnings) } related-words + +HELP: compile-vocabs +{ $values { "seq" "a sequence of strings" } } +{ $description "Compiles all words which have not been compiled yet from the given vocabularies." } ; + +HELP: compile-quot +{ $values { "quot" "a quotation" } { "word" "a new, uninterned word" } } +{ $description "Creates a new uninterned word having the given quotation as its definition, and compiles it. The returned word can be passed to " { $link execute } "." } +{ $errors "Throws an error if the stack effect of the quotation cannot be inferred." } ; + +HELP: compile-1 +{ $values { "quot" "a quotation" } } +{ $description "Compiles and runs a quotation." } +{ $errors "Throws an error if the stack effect of the quotation cannot be inferred." } ; + +HELP: recompile +{ $description "Recompiles words whose compiled definitions have become out of date as a result of dependent words being redefined." } ; + +HELP: compile-all +{ $description "Compiles all words which have not been compiled yet." } ; + +HELP: recompile-all +{ $description "Recompiles all words." } ; + +HELP: changed-words +{ $var-description "Global variable holding words which need to be recompiled. Implemented as a hashtable where a key equals its value. This hashtable is updated by " { $link define } " when words are redefined, and inspected and cleared by " { $link recompile } "." } ; + +HELP: compile-begins +{ $values { "word" word } } +{ $description "Prints a message stating the word is being compiled, unless we are inside a " { $link compile-batch } "." } ; + +HELP: (compile) +{ $values { "word" word } } +{ $description "Compile a word. This word recursively calls itself to compile all dependencies." } +{ $notes "This is an internal word, and user code should call " { $link compile } " instead." } ; diff --git a/core/compiler/compiler-tests.factor b/core/compiler/compiler-tests.factor new file mode 100644 index 0000000000..59e2aaace0 --- /dev/null +++ b/core/compiler/compiler-tests.factor @@ -0,0 +1,20 @@ +USING: io.files tools.test sequences namespaces kernel ; + +{ + "templates-early" + "simple" + "intrinsics" + "float" + "generic" + "ifte" + "templates" + "optimizer" + "redefine" + "stack-trace" + "alien" + "curry" + "tuples" +} +[ "resource:core/compiler/test/" swap ".factor" 3append ] map +[ run-test ] map +[ failures get push-all ] each diff --git a/core/compiler/compiler.factor b/core/compiler/compiler.factor new file mode 100644 index 0000000000..76b4d49636 --- /dev/null +++ b/core/compiler/compiler.factor @@ -0,0 +1,92 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel namespaces arrays sequences io inference.backend +generator debugger math.parser prettyprint words continuations +vocabs assocs alien.compiler ; +IN: compiler + +M: object inference-error-major? drop t ; + +: compile-error ( word error -- ) + batch-mode get [ + 2array compile-errors get push + ] [ + "quiet" get [ drop ] [ print-error flush ] if drop + ] if ; + +: begin-batch ( seq -- ) + batch-mode on + [ + "Compiling " % length # " words..." % + ] "" make print flush + V{ } clone compile-errors set-global ; + +: compile-error. ( pair -- ) + nl + "While compiling " write dup first pprint ": " print + nl + second print-error ; + +: (:errors) ( -- seq ) + compile-errors get-global + [ second inference-error-major? ] subset ; + +: :errors (:errors) [ compile-error. ] each ; + +: (:warnings) ( -- seq ) + compile-errors get-global + [ second inference-error-major? not ] subset ; + +: :warnings (:warnings) [ compile-error. ] each ; + +: end-batch ( -- ) + batch-mode off + "quiet" get [ + "Compile finished." print + nl + ":errors - print " write (:errors) length pprint + " compiler errors." print + ":warnings - print " write (:warnings) length pprint + " compiler warnings." print + nl + ] unless ; + +: compile ( word -- ) + H{ } clone [ + compiled-xts [ (compile) ] with-variable + ] keep >alist finalize-compile ; + +: compile-failed ( word error -- ) + dupd compile-error dup update-xt unchanged-word ; + +: try-compile ( word -- ) + [ compile ] [ compile-failed ] recover ; + +: forget-errors ( seq -- ) + [ f "no-effect" set-word-prop ] each ; + +: compile-batch ( seq -- ) + dup empty? [ + drop + ] [ + dup begin-batch + dup forget-errors + [ try-compile ] each + end-batch + ] if ; + +: compile-vocabs ( seq -- ) [ words ] map concat compile-batch ; + +: compile-all ( -- ) vocabs compile-vocabs ; + +: compile-quot ( quot -- word ) define-temp dup compile ; + +: compile-1 ( quot -- ) compile-quot execute ; + +: recompile ( -- ) + changed-words get [ + dup keys compile-batch clear-assoc + ] when* ; + +: recompile-all ( -- ) + all-words [ changed-word ] each recompile ; diff --git a/core/compiler/summary.txt b/core/compiler/summary.txt new file mode 100644 index 0000000000..09cfea36ae --- /dev/null +++ b/core/compiler/summary.txt @@ -0,0 +1 @@ +Factor's optimizing machine code compiler diff --git a/core/compiler/tags.txt b/core/compiler/tags.txt new file mode 100644 index 0000000000..86a7c8e637 --- /dev/null +++ b/core/compiler/tags.txt @@ -0,0 +1 @@ +compiler diff --git a/core/compiler/test/alien.factor b/core/compiler/test/alien.factor new file mode 100644 index 0000000000..edb5de0940 --- /dev/null +++ b/core/compiler/test/alien.factor @@ -0,0 +1,300 @@ +IN: temporary +USING: alien alien.c-types alien.syntax compiler kernel +namespaces namespaces tools.test sequences inference words +arrays parser quotations continuations inference.backend effects +namespaces.private io io.streams.string memory system threads ; + +FUNCTION: void ffi_test_0 ; +[ ] [ ffi_test_0 ] unit-test + +FUNCTION: int ffi_test_1 ; +[ 3 ] [ ffi_test_1 ] unit-test + +FUNCTION: int ffi_test_2 int x int y ; +[ 5 ] [ 2 3 ffi_test_2 ] unit-test +[ "hi" 3 ffi_test_2 ] unit-test-fails + +FUNCTION: int ffi_test_3 int x int y int z int t ; +[ 25 ] [ 2 3 4 5 ffi_test_3 ] unit-test + +FUNCTION: float ffi_test_4 ; +[ 1.5 ] [ ffi_test_4 ] unit-test + +FUNCTION: double ffi_test_5 ; +[ 1.5 ] [ ffi_test_5 ] unit-test + +FUNCTION: int ffi_test_9 int a int b int c int d int e int f int g ; +[ 28 ] [ 1 2 3 4 5 6 7 ffi_test_9 ] unit-test +[ "a" 2 3 4 5 6 7 ffi_test_9 ] unit-test-fails +[ 1 2 3 4 5 6 "a" ffi_test_9 ] unit-test-fails + +C-STRUCT: foo + { "int" "x" } + { "int" "y" } +; + +: make-foo ( x y -- foo ) + "foo" [ set-foo-y ] keep [ set-foo-x ] keep ; + +FUNCTION: int ffi_test_11 int a foo b int c ; + +[ 14 ] [ 1 2 3 make-foo 4 ffi_test_11 ] unit-test + +FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ; + +[ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test + +FUNCTION: foo ffi_test_14 int x int y ; + +[ 11 6 ] [ 11 6 ffi_test_14 dup foo-x swap foo-y ] unit-test + +FUNCTION: char* ffi_test_15 char* x char* y ; + +[ "foo" ] [ "xy" "zt" ffi_test_15 ] unit-test +[ "bar" ] [ "xy" "xy" ffi_test_15 ] unit-test +[ 1 2 ffi_test_15 ] unit-test-fails + +C-STRUCT: bar + { "long" "x" } + { "long" "y" } + { "long" "z" } +; + +FUNCTION: bar ffi_test_16 long x long y long z ; + +[ 11 6 -7 ] [ + 11 6 -7 ffi_test_16 dup bar-x over bar-y rot bar-z +] unit-test + +C-STRUCT: tiny + { "int" "x" } +; + +FUNCTION: tiny ffi_test_17 int x ; + +[ 11 ] [ 11 ffi_test_17 tiny-x ] unit-test + +[ t ] [ [ [ alien-indirect ] infer ] catch inference-error? ] unit-test + +: indirect-test-1 + "int" { } "cdecl" alien-indirect ; + +: short-effect + dup effect-in length swap effect-out length 2array ; + +[ { 1 1 } ] [ [ indirect-test-1 ] infer short-effect ] unit-test + +[ 3 ] [ "ffi_test_1" f dlsym indirect-test-1 ] unit-test + +[ -1 indirect-test-1 ] unit-test-fails + +: indirect-test-2 + "int" { "int" "int" } "cdecl" alien-indirect data-gc ; + +[ { 3 1 } ] [ [ indirect-test-2 ] infer short-effect ] unit-test + +[ 5 ] +[ 2 3 "ffi_test_2" f dlsym indirect-test-2 ] +unit-test + +: indirect-test-3 + "int" { "int" "int" "int" "int" } "stdcall" alien-indirect + data-gc ; + +! This is a hack -- words are compiled before top-level forms +! run. + +DEFER: >> delimiter +: << \ >> parse-until >quotation call ; parsing + +<< "f-stdcall" f "stdcall" add-library >> + +[ f ] [ "f-stdcall" load-library ] unit-test +[ "stdcall" ] [ "f-stdcall" library library-abi ] unit-test + +: ffi_test_18 ( w x y z -- int ) + "int" "f-stdcall" "ffi_test_18" { "int" "int" "int" "int" } + alien-invoke data-gc ; + +[ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test + +: ffi_test_19 ( x y z -- bar ) + "bar" "f-stdcall" "ffi_test_19" { "long" "long" "long" } + alien-invoke data-gc ; + +[ 11 6 -7 ] [ + 11 6 -7 ffi_test_19 dup bar-x over bar-y rot bar-z +] unit-test + +FUNCTION: double ffi_test_6 float x float y ; +[ 6.0 ] [ 3.0 2.0 ffi_test_6 ] unit-test +[ "a" "b" ffi_test_6 ] unit-test-fails + +FUNCTION: double ffi_test_7 double x double y ; +[ 6.0 ] [ 3.0 2.0 ffi_test_7 ] unit-test + +FUNCTION: double ffi_test_8 double x float y double z float t int w ; +[ 19.0 ] [ 3.0 2.0 1.0 6.0 7 ffi_test_8 ] unit-test + +FUNCTION: int ffi_test_10 int a int b double c int d float e int f int g int h ; +[ -34 ] [ 1 2 3.0 4 5.0 6 7 8 ffi_test_10 ] unit-test + +FUNCTION: void ffi_test_20 double x1, double x2, double x3, + double y1, double y2, double y3, + double z1, double z2, double z3 ; + +[ ] [ 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 ffi_test_20 ] unit-test + +FUNCTION: longlong ffi_test_21 long x long y ; + +[ 121932631112635269 ] +[ 123456789 987654321 ffi_test_21 ] unit-test + +FUNCTION: long ffi_test_22 long x longlong y longlong z ; + +[ 987655432 ] +[ 1111 121932631112635269 123456789 ffi_test_22 ] unit-test + +[ 1111 f 123456789 ffi_test_22 ] unit-test-fails + +C-STRUCT: rect + { "float" "x" } + { "float" "y" } + { "float" "w" } + { "float" "h" } +; + +: + "rect" + [ set-rect-h ] keep + [ set-rect-w ] keep + [ set-rect-y ] keep + [ set-rect-x ] keep ; + +FUNCTION: int ffi_test_12 int a int b rect c int d int e int f ; + +[ 45 ] [ 1 2 3.0 4.0 5.0 6.0 7 8 9 ffi_test_12 ] unit-test + +[ 1 2 { 1 2 3 } 7 8 9 ffi_test_12 ] unit-test-fails + +FUNCTION: float ffi_test_23 ( float[3] x, float[3] y ) ; + +[ 32.0 ] [ { 1.0 2.0 3.0 } >c-float-array { 4.0 5.0 6.0 } >c-float-array ffi_test_23 ] unit-test + +! Test odd-size structs +C-STRUCT: test-struct-1 { { "char" 1 } "x" } ; + +FUNCTION: test-struct-1 ffi_test_24 ; + +[ B{ 1 } ] [ ffi_test_24 ] unit-test + +C-STRUCT: test-struct-2 { { "char" 2 } "x" } ; + +FUNCTION: test-struct-2 ffi_test_25 ; + +[ B{ 1 2 } ] [ ffi_test_25 ] unit-test + +C-STRUCT: test-struct-3 { { "char" 3 } "x" } ; + +FUNCTION: test-struct-3 ffi_test_26 ; + +[ B{ 1 2 3 } ] [ ffi_test_26 ] unit-test + +C-STRUCT: test-struct-4 { { "char" 4 } "x" } ; + +FUNCTION: test-struct-4 ffi_test_27 ; + +[ B{ 1 2 3 4 } ] [ ffi_test_27 ] unit-test + +C-STRUCT: test-struct-5 { { "char" 5 } "x" } ; + +FUNCTION: test-struct-5 ffi_test_28 ; + +[ B{ 1 2 3 4 5 } ] [ ffi_test_28 ] unit-test + +C-STRUCT: test-struct-6 { { "char" 6 } "x" } ; + +FUNCTION: test-struct-6 ffi_test_29 ; + +[ B{ 1 2 3 4 5 6 } ] [ ffi_test_29 ] unit-test + +C-STRUCT: test-struct-7 { { "char" 7 } "x" } ; + +FUNCTION: test-struct-7 ffi_test_30 ; + +[ B{ 1 2 3 4 5 6 7 } ] [ ffi_test_30 ] unit-test + +! Test callbacks + +: callback-1 "void" { } "cdecl" [ ] alien-callback ; + +[ 0 1 ] [ [ callback-1 ] infer dup effect-in swap effect-out ] unit-test + +[ t ] [ callback-1 alien? ] unit-test + +: callback_test_1 "void" { } "cdecl" alien-indirect ; + +[ ] [ callback-1 callback_test_1 ] unit-test + +: callback-2 "void" { } "cdecl" [ [ 5 throw ] catch drop ] alien-callback ; + +[ ] [ callback-2 callback_test_1 ] unit-test + +: callback-3 "void" { } "cdecl" [ 5 "x" set ] alien-callback ; + +[ t ] [ + namestack* + 3 "x" set callback-3 callback_test_1 + namestack* eq? +] unit-test + +[ 5 ] [ + [ + 3 "x" set callback-3 callback_test_1 "x" get + ] with-scope +] unit-test + +: callback-4 + "void" { } "cdecl" [ "Hello world" write ] alien-callback + data-gc ; + +[ "Hello world" ] [ + [ callback-4 callback_test_1 ] string-out +] unit-test + +: callback-5 + "void" { } "cdecl" [ data-gc ] alien-callback ; + +[ "testing" ] [ + "testing" callback-5 callback_test_1 +] unit-test + +: callback-5a + "void" { } "cdecl" [ 8000000 f drop ] alien-callback ; + +! Hack; if we're on ARM, we probably don't have much RAM, so +! skip this test. +cpu "arm" = [ + [ "testing" ] [ + "testing" callback-5a callback_test_1 + ] unit-test +] unless + +: callback-6 + "void" { } "cdecl" [ [ continue ] callcc0 ] alien-callback ; + +[ 1 2 3 ] [ callback-6 callback_test_1 1 2 3 ] unit-test + +: callback-7 + "void" { } "cdecl" [ 1000 sleep ] alien-callback ; + +[ 1 2 3 ] [ callback-7 callback_test_1 1 2 3 ] unit-test + +[ f ] [ namespace global eq? ] unit-test + +: callback-8 + "void" { } "cdecl" [ + [ continue ] callcc0 + ] alien-callback ; + +[ ] [ callback-8 callback_test_1 ] unit-test diff --git a/core/compiler/test/curry.factor b/core/compiler/test/curry.factor new file mode 100644 index 0000000000..e7401fbe9b --- /dev/null +++ b/core/compiler/test/curry.factor @@ -0,0 +1,61 @@ +USING: tools.test compiler quotations math kernel sequences +assocs namespaces ; +IN: temporary + +[ 3 ] [ 5 [ [ 2 - ] curry call ] compile-1 ] unit-test +[ 3 ] [ [ 5 [ 2 - ] curry call ] compile-1 ] unit-test +[ 3 ] [ [ 5 2 [ - ] 2curry call ] compile-1 ] unit-test +[ 3 ] [ 5 [ 2 [ - ] 2curry call ] compile-1 ] unit-test +[ 3 ] [ 5 2 [ [ - ] 2curry call ] compile-1 ] unit-test +[ 1/3 ] [ 5 2 [ [ - ] 2curry 1 swap call / ] compile-1 ] unit-test +[ 1/3 ] [ 5 2 [ [ - ] 2curry >r 1 r> call / ] compile-1 ] unit-test + +[ -10 -20 ] [ 10 20 -1 [ [ * ] curry 2apply ] compile-1 ] unit-test + +[ [ 5 2 - ] ] [ 5 [ [ 2 - ] curry ] compile-1 >quotation ] unit-test +[ [ 5 2 - ] ] [ [ 5 [ 2 - ] curry ] compile-1 >quotation ] unit-test +[ [ 5 2 - ] ] [ [ 5 2 [ - ] 2curry ] compile-1 >quotation ] unit-test +[ [ 5 2 - ] ] [ 5 [ 2 [ - ] 2curry ] compile-1 >quotation ] unit-test +[ [ 5 2 - ] ] [ 5 2 [ [ - ] 2curry ] compile-1 >quotation ] unit-test + +[ [ 6 2 + ] ] +[ + 2 5 + [ >r [ + ] curry r> 0 < [ -2 ] [ 6 ] if swap curry ] + compile-1 >quotation +] unit-test + +[ 8 ] +[ + 2 5 + [ >r [ + ] curry r> 0 < [ -2 ] [ 6 ] if swap curry call ] + compile-1 +] unit-test + +: foobar ( quot -- ) + dup slip swap [ foobar ] [ drop ] if ; inline + +[ ] [ [ [ f ] foobar ] compile-1 ] unit-test + +[ { 6 7 8 } ] [ { 1 2 3 } 5 [ [ + ] curry map ] compile-1 ] unit-test +[ { 6 7 8 } ] [ { 1 2 3 } [ 5 [ + ] curry map ] compile-1 ] unit-test + +: funky-assoc>map + [ + [ call f ] curry assoc-find 3drop + ] { } make ; inline + +[ t ] [ + global [ [ drop , ] funky-assoc>map ] compile-1 + global keys = +] unit-test + +[ 3 ] [ 1 2 [ curry [ 3 ] [ 4 ] if ] compile-1 ] unit-test + +[ 3 ] [ t [ 3 [ ] curry 4 [ ] curry if ] compile-1 ] unit-test + +[ 3 ] [ t [ 3 [ ] curry [ 4 ] if ] compile-1 ] unit-test + +[ 4 ] [ f [ 3 [ ] curry 4 [ ] curry if ] compile-1 ] unit-test + +[ 4 ] [ f [ [ 3 ] 4 [ ] curry if ] compile-1 ] unit-test diff --git a/core/compiler/test/float.factor b/core/compiler/test/float.factor new file mode 100644 index 0000000000..404626dd36 --- /dev/null +++ b/core/compiler/test/float.factor @@ -0,0 +1,85 @@ +IN: temporary +USING: compiler kernel kernel.private memory math +math.private tools.test math.floats.private ; + +[ 5.0 ] [ [ 5.0 ] compile-1 data-gc data-gc data-gc ] unit-test +[ 2.0 3.0 ] [ 3.0 [ 2.0 swap ] compile-1 ] unit-test + +[ 1 2 3 4.0 ] [ [ 1 2 3 4.0 ] compile-1 ] unit-test + +[ 3.0 1 2 3 ] [ 1.0 2.0 [ float+ 1 2 3 ] compile-1 ] unit-test + +[ 5 ] [ 1.0 [ 2.0 float+ tag ] compile-1 ] unit-test + +[ 3.0 ] [ 1.0 [ 2.0 float+ ] compile-1 ] unit-test +[ 3.0 ] [ 1.0 [ 2.0 swap float+ ] compile-1 ] unit-test +[ 3.0 ] [ 1.0 2.0 [ float+ ] compile-1 ] unit-test +[ 3.0 ] [ 1.0 2.0 [ swap float+ ] compile-1 ] unit-test + +[ -1.0 ] [ 1.0 [ 2.0 float- ] compile-1 ] unit-test +[ 1.0 ] [ 1.0 [ 2.0 swap float- ] compile-1 ] unit-test +[ -1.0 ] [ 1.0 2.0 [ float- ] compile-1 ] unit-test +[ 1.0 ] [ 1.0 2.0 [ swap float- ] compile-1 ] unit-test + +[ 6.0 ] [ 3.0 [ 2.0 float* ] compile-1 ] unit-test +[ 6.0 ] [ 3.0 [ 2.0 swap float* ] compile-1 ] unit-test +[ 6.0 ] [ 3.0 2.0 [ float* ] compile-1 ] unit-test +[ 6.0 ] [ 3.0 2.0 [ swap float* ] compile-1 ] unit-test + +[ 0.5 ] [ 1.0 [ 2.0 float/f ] compile-1 ] unit-test +[ 2.0 ] [ 1.0 [ 2.0 swap float/f ] compile-1 ] unit-test +[ 0.5 ] [ 1.0 2.0 [ float/f ] compile-1 ] unit-test +[ 2.0 ] [ 1.0 2.0 [ swap float/f ] compile-1 ] unit-test + +[ t ] [ 1.0 2.0 [ float< ] compile-1 ] unit-test +[ t ] [ 1.0 [ 2.0 float< ] compile-1 ] unit-test +[ f ] [ 1.0 [ 2.0 swap float< ] compile-1 ] unit-test +[ f ] [ 1.0 1.0 [ float< ] compile-1 ] unit-test +[ f ] [ 1.0 [ 1.0 float< ] compile-1 ] unit-test +[ f ] [ 1.0 [ 1.0 swap float< ] compile-1 ] unit-test +[ f ] [ 3.0 1.0 [ float< ] compile-1 ] unit-test +[ f ] [ 3.0 [ 1.0 float< ] compile-1 ] unit-test +[ t ] [ 3.0 [ 1.0 swap float< ] compile-1 ] unit-test + +[ t ] [ 1.0 2.0 [ float<= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 2.0 float<= ] compile-1 ] unit-test +[ f ] [ 1.0 [ 2.0 swap float<= ] compile-1 ] unit-test +[ t ] [ 1.0 1.0 [ float<= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 1.0 float<= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 1.0 swap float<= ] compile-1 ] unit-test +[ f ] [ 3.0 1.0 [ float<= ] compile-1 ] unit-test +[ f ] [ 3.0 [ 1.0 float<= ] compile-1 ] unit-test +[ t ] [ 3.0 [ 1.0 swap float<= ] compile-1 ] unit-test + +[ f ] [ 1.0 2.0 [ float> ] compile-1 ] unit-test +[ f ] [ 1.0 [ 2.0 float> ] compile-1 ] unit-test +[ t ] [ 1.0 [ 2.0 swap float> ] compile-1 ] unit-test +[ f ] [ 1.0 1.0 [ float> ] compile-1 ] unit-test +[ f ] [ 1.0 [ 1.0 float> ] compile-1 ] unit-test +[ f ] [ 1.0 [ 1.0 swap float> ] compile-1 ] unit-test +[ t ] [ 3.0 1.0 [ float> ] compile-1 ] unit-test +[ t ] [ 3.0 [ 1.0 float> ] compile-1 ] unit-test +[ f ] [ 3.0 [ 1.0 swap float> ] compile-1 ] unit-test + +[ f ] [ 1.0 2.0 [ float>= ] compile-1 ] unit-test +[ f ] [ 1.0 [ 2.0 float>= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 2.0 swap float>= ] compile-1 ] unit-test +[ t ] [ 1.0 1.0 [ float>= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 1.0 float>= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 1.0 swap float>= ] compile-1 ] unit-test +[ t ] [ 3.0 1.0 [ float>= ] compile-1 ] unit-test +[ t ] [ 3.0 [ 1.0 float>= ] compile-1 ] unit-test +[ f ] [ 3.0 [ 1.0 swap float>= ] compile-1 ] unit-test + +[ f ] [ 1.0 2.0 [ float= ] compile-1 ] unit-test +[ t ] [ 1.0 1.0 [ float= ] compile-1 ] unit-test +[ f ] [ 1.0 [ 2.0 float= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 1.0 float= ] compile-1 ] unit-test +[ f ] [ 1.0 [ 2.0 swap float= ] compile-1 ] unit-test +[ t ] [ 1.0 [ 1.0 swap float= ] compile-1 ] unit-test + +[ t ] [ 0.0 [ dup 0.0 float= swap -0.0 float= or ] compile-1 ] unit-test +[ t ] [ -0.0 [ dup 0.0 float= swap -0.0 float= or ] compile-1 ] unit-test +[ f ] [ 3.0 [ dup 0.0 float= swap -0.0 float= or ] compile-1 ] unit-test + +[ 315 315.0 ] [ 313 [ 2 fixnum+fast dup fixnum>float ] compile-1 ] unit-test diff --git a/core/compiler/test/generic.factor b/core/compiler/test/generic.factor new file mode 100644 index 0000000000..c54dbd753d --- /dev/null +++ b/core/compiler/test/generic.factor @@ -0,0 +1,30 @@ +IN: temporary +USING: compiler generic tools.test math kernel words arrays +sequences quotations ; + +GENERIC: single-combination-test + +M: object single-combination-test drop ; +M: f single-combination-test nip ; +M: array single-combination-test drop ; +M: integer single-combination-test drop ; + +[ 2 3 ] [ 2 3 t single-combination-test ] unit-test +[ 2 3 ] [ 2 3 4 single-combination-test ] unit-test +[ 2 f ] [ 2 3 f single-combination-test ] unit-test + +DEFER: single-combination-test-2 + +: single-combination-test-4 + dup [ single-combination-test-2 ] when ; + +: single-combination-test-3 + drop 3 ; + +GENERIC: single-combination-test-2 +M: object single-combination-test-2 single-combination-test-3 ; +M: f single-combination-test-2 single-combination-test-4 ; + +[ 3 ] [ t single-combination-test-2 ] unit-test +[ 3 ] [ 3 single-combination-test-2 ] unit-test +[ f ] [ f single-combination-test-2 ] unit-test diff --git a/core/compiler/test/ifte.factor b/core/compiler/test/ifte.factor new file mode 100644 index 0000000000..c2ccc43cc5 --- /dev/null +++ b/core/compiler/test/ifte.factor @@ -0,0 +1,131 @@ +IN: temporary +USING: alien strings compiler tools.test math kernel words +math.private combinators ; + +: dummy-if-1 t [ ] [ ] if ; + +[ ] [ dummy-if-1 ] unit-test + +: dummy-if-2 f [ ] [ ] if ; + +[ ] [ dummy-if-2 ] unit-test + +: dummy-if-3 t [ 1 ] [ 2 ] if ; + +[ 1 ] [ dummy-if-3 ] unit-test + +: dummy-if-4 f [ 1 ] [ 2 ] if ; + +[ 2 ] [ dummy-if-4 ] unit-test + +: dummy-if-5 0 dup 1 fixnum<= [ drop 1 ] [ ] if ; + +[ 1 ] [ dummy-if-5 ] unit-test + +: dummy-if-6 + dup 1 fixnum<= [ + drop 1 + ] [ + 1 fixnum- dup 1 fixnum- fixnum+ + ] if ; + +[ 17 ] [ 10 dummy-if-6 ] unit-test + +: dead-code-rec + t [ + C{ 3 2 } + ] [ + dead-code-rec + ] if ; + +[ C{ 3 2 } ] [ dead-code-rec ] unit-test + +: one-rec [ f one-rec ] [ "hi" ] if ; + +[ "hi" ] [ t one-rec ] unit-test + +: after-if-test + t [ ] [ ] if 5 ; + +[ 5 ] [ after-if-test ] unit-test + +DEFER: countdown-b + +: countdown-a ( n -- ) dup 0 eq? [ drop ] [ 1 fixnum- countdown-b ] if ; +: countdown-b ( n -- ) dup 0 eq? [ drop ] [ 1 fixnum- countdown-a ] if ; + +[ ] [ 10 countdown-b ] unit-test + +: dummy-when-1 t [ ] when ; + +[ ] [ dummy-when-1 ] unit-test + +: dummy-when-2 f [ ] when ; + +[ ] [ dummy-when-2 ] unit-test + +: dummy-when-3 dup [ dup fixnum* ] when ; + +[ 16 ] [ 4 dummy-when-3 ] unit-test +[ f ] [ f dummy-when-3 ] unit-test + +: dummy-when-4 dup [ dup dup fixnum* fixnum* ] when swap ; + +[ 64 f ] [ f 4 dummy-when-4 ] unit-test +[ f t ] [ t f dummy-when-4 ] unit-test + +: dummy-when-5 f [ dup fixnum* ] when ; + +[ f ] [ f dummy-when-5 ] unit-test + +: dummy-unless-1 t [ ] unless ; + +[ ] [ dummy-unless-1 ] unit-test + +: dummy-unless-2 f [ ] unless ; + +[ ] [ dummy-unless-2 ] unit-test + +: dummy-unless-3 dup [ drop 3 ] unless ; + +[ 3 ] [ f dummy-unless-3 ] unit-test +[ 4 ] [ 4 dummy-unless-3 ] unit-test + +! Test cond expansion +[ "even" ] [ + [ + 2 { + { [ dup 2 mod 0 = ] [ drop "even" ] } + { [ dup 2 mod 1 = ] [ drop "odd" ] } + } cond + ] compile-1 +] unit-test + +[ "odd" ] [ + [ + 3 { + { [ dup 2 mod 0 = ] [ drop "even" ] } + { [ dup 2 mod 1 = ] [ drop "odd" ] } + } cond + ] compile-1 +] unit-test + +[ "neither" ] [ + [ + 3 { + { [ dup string? ] [ drop "string" ] } + { [ dup float? ] [ drop "float" ] } + { [ dup alien? ] [ drop "alien" ] } + { [ t ] [ drop "neither" ] } + } cond + ] compile-1 +] unit-test + +[ 3 ] [ + [ + 3 { + { [ dup fixnum? ] [ ] } + { [ t ] [ drop t ] } + } cond + ] compile-1 +] unit-test diff --git a/core/compiler/test/intrinsics.factor b/core/compiler/test/intrinsics.factor new file mode 100644 index 0000000000..23e94a7974 --- /dev/null +++ b/core/compiler/test/intrinsics.factor @@ -0,0 +1,413 @@ +IN: temporary +USING: arrays compiler kernel kernel.private math +math.private sequences strings tools.test words continuations +sequences.private hashtables.private byte-arrays +strings.private system random math.vectors layouts +vectors.private sbufs.private strings.private slots.private +alien alien.c-types alien.syntax namespaces libc math.constants +math.functions ; + +! Make sure that intrinsic ops compile to correct code. +[ ] [ 1 [ drop ] compile-1 ] unit-test +[ ] [ 1 2 [ 2drop ] compile-1 ] unit-test +[ ] [ 1 2 3 [ 3drop ] compile-1 ] unit-test +[ 1 1 ] [ 1 [ dup ] compile-1 ] unit-test +[ 1 2 1 2 ] [ 1 2 [ 2dup ] compile-1 ] unit-test +[ 1 2 3 1 2 3 ] [ 1 2 3 [ 3dup ] compile-1 ] unit-test +[ 2 3 1 ] [ 1 2 3 [ rot ] compile-1 ] unit-test +[ 3 1 2 ] [ 1 2 3 [ -rot ] compile-1 ] unit-test +[ 1 1 2 ] [ 1 2 [ dupd ] compile-1 ] unit-test +[ 2 1 3 ] [ 1 2 3 [ swapd ] compile-1 ] unit-test +[ 2 ] [ 1 2 [ nip ] compile-1 ] unit-test +[ 3 ] [ 1 2 3 [ 2nip ] compile-1 ] unit-test +[ 2 1 2 ] [ 1 2 [ tuck ] compile-1 ] unit-test +[ 1 2 1 ] [ 1 2 [ over ] compile-1 ] unit-test +[ 1 2 3 1 ] [ 1 2 3 [ pick ] compile-1 ] unit-test +[ 2 1 ] [ 1 2 [ swap ] compile-1 ] unit-test + +[ 1 ] [ { 1 2 } [ 2 slot ] compile-1 ] unit-test +[ 1 ] [ [ { 1 2 } 2 slot ] compile-1 ] unit-test +[ 3 ] [ 3 1 2 2array [ [ 2 set-slot ] keep ] compile-1 first ] unit-test +[ 3 ] [ 3 1 2 [ 2array [ 2 set-slot ] keep ] compile-1 first ] unit-test +[ 3 ] [ [ 3 1 2 2array [ 2 set-slot ] keep ] compile-1 first ] unit-test +[ 3 ] [ 3 1 2 2array [ [ 3 set-slot ] keep ] compile-1 second ] unit-test +[ 3 ] [ 3 1 2 [ 2array [ 3 set-slot ] keep ] compile-1 second ] unit-test +[ 3 ] [ [ 3 1 2 2array [ 3 set-slot ] keep ] compile-1 second ] unit-test + +! Write barrier hits on the wrong value were causing segfaults +[ -3 ] [ -3 1 2 [ 2array [ 3 set-slot ] keep ] compile-1 second ] unit-test + +[ CHAR: b ] [ 1 "abc" [ char-slot ] compile-1 ] unit-test +[ CHAR: b ] [ 1 [ "abc" char-slot ] compile-1 ] unit-test +[ CHAR: b ] [ [ 1 "abc" char-slot ] compile-1 ] unit-test + +[ "axc" ] [ CHAR: x 1 "abc" [ [ set-char-slot ] keep { string } declare dup rehash-string ] compile-1 ] unit-test +[ "axc" ] [ CHAR: x 1 [ "abc" [ set-char-slot ] keep { string } declare dup rehash-string ] compile-1 ] unit-test +[ "axc" ] [ CHAR: x [ 1 "abc" [ set-char-slot ] keep { string } declare dup rehash-string ] compile-1 ] unit-test + +[ ] [ [ 0 getenv ] compile-1 drop ] unit-test +[ ] [ 1 getenv [ 1 setenv ] compile-1 ] unit-test + +[ ] [ 1 [ drop ] compile-1 ] unit-test +[ ] [ [ 1 drop ] compile-1 ] unit-test +[ ] [ [ 1 2 2drop ] compile-1 ] unit-test +[ ] [ 1 [ 2 2drop ] compile-1 ] unit-test +[ ] [ 1 2 [ 2drop ] compile-1 ] unit-test +[ 2 1 ] [ [ 1 2 swap ] compile-1 ] unit-test +[ 2 1 ] [ 1 [ 2 swap ] compile-1 ] unit-test +[ 2 1 ] [ 1 2 [ swap ] compile-1 ] unit-test +[ 1 1 ] [ 1 [ dup ] compile-1 ] unit-test +[ 1 1 ] [ [ 1 dup ] compile-1 ] unit-test +[ 1 2 1 ] [ [ 1 2 over ] compile-1 ] unit-test +[ 1 2 1 ] [ 1 [ 2 over ] compile-1 ] unit-test +[ 1 2 1 ] [ 1 2 [ over ] compile-1 ] unit-test +[ 1 2 3 1 ] [ [ 1 2 3 pick ] compile-1 ] unit-test +[ 1 2 3 1 ] [ 1 [ 2 3 pick ] compile-1 ] unit-test +[ 1 2 3 1 ] [ 1 2 [ 3 pick ] compile-1 ] unit-test +[ 1 2 3 1 ] [ 1 2 3 [ pick ] compile-1 ] unit-test +[ 1 1 2 ] [ [ 1 2 dupd ] compile-1 ] unit-test +[ 1 1 2 ] [ 1 [ 2 dupd ] compile-1 ] unit-test +[ 1 1 2 ] [ 1 2 [ dupd ] compile-1 ] unit-test +[ 2 ] [ [ 1 2 nip ] compile-1 ] unit-test +[ 2 ] [ 1 [ 2 nip ] compile-1 ] unit-test +[ 2 ] [ 1 2 [ nip ] compile-1 ] unit-test + +[ 2 1 "hi" ] [ 1 2 [ swap "hi" ] compile-1 ] unit-test + +[ 4 ] [ 12 7 [ fixnum-bitand ] compile-1 ] unit-test +[ 4 ] [ 12 [ 7 fixnum-bitand ] compile-1 ] unit-test +[ 4 ] [ [ 12 7 fixnum-bitand ] compile-1 ] unit-test + +[ 15 ] [ 12 7 [ fixnum-bitor ] compile-1 ] unit-test +[ 15 ] [ 12 [ 7 fixnum-bitor ] compile-1 ] unit-test +[ 15 ] [ [ 12 7 fixnum-bitor ] compile-1 ] unit-test + +[ 11 ] [ 12 7 [ fixnum-bitxor ] compile-1 ] unit-test +[ 11 ] [ 12 [ 7 fixnum-bitxor ] compile-1 ] unit-test +[ 11 ] [ [ 12 7 fixnum-bitxor ] compile-1 ] unit-test + +[ f ] [ 12 7 [ fixnum< [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 12 [ 7 fixnum< [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 7 fixnum< [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 12 fixnum< [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 12 12 [ fixnum< [ t ] [ f ] if ] compile-1 ] unit-test + +[ t ] [ 12 70 [ fixnum< [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 12 [ 70 fixnum< [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 70 fixnum< [ t ] [ f ] if ] compile-1 ] unit-test + +[ f ] [ 12 7 [ fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 12 [ 7 fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 7 fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 12 fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 12 fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 12 12 [ fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test + +[ t ] [ 12 70 [ fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 12 [ 70 fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 70 fixnum<= [ t ] [ f ] if ] compile-1 ] unit-test + +[ t ] [ 12 7 [ fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 12 [ 7 fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 7 fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 12 fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 12 fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 12 12 [ fixnum> [ t ] [ f ] if ] compile-1 ] unit-test + +[ f ] [ 12 70 [ fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 12 [ 70 fixnum> [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 70 fixnum> [ t ] [ f ] if ] compile-1 ] unit-test + +[ t ] [ 12 7 [ fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 12 [ 7 fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 7 fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 12 12 fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 12 12 [ fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test + +[ f ] [ 12 70 [ fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 12 [ 70 fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 12 70 fixnum>= [ t ] [ f ] if ] compile-1 ] unit-test + +[ f ] [ 1 2 [ eq? [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ 1 [ 2 eq? [ t ] [ f ] if ] compile-1 ] unit-test +[ f ] [ [ 1 2 eq? [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 3 3 [ eq? [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ 3 [ 3 eq? [ t ] [ f ] if ] compile-1 ] unit-test +[ t ] [ [ 3 3 eq? [ t ] [ f ] if ] compile-1 ] unit-test + +[ -1 ] [ 0 [ fixnum-bitnot ] compile-1 ] unit-test +[ -1 ] [ [ 0 fixnum-bitnot ] compile-1 ] unit-test + +[ 3 ] [ 13 10 [ fixnum-mod ] compile-1 ] unit-test +[ 3 ] [ 13 [ 10 fixnum-mod ] compile-1 ] unit-test +[ 3 ] [ [ 13 10 fixnum-mod ] compile-1 ] unit-test +[ -3 ] [ -13 10 [ fixnum-mod ] compile-1 ] unit-test +[ -3 ] [ -13 [ 10 fixnum-mod ] compile-1 ] unit-test +[ -3 ] [ [ -13 10 fixnum-mod ] compile-1 ] unit-test + +[ 2 ] [ 4 2 [ fixnum/i ] compile-1 ] unit-test +[ 2 ] [ 4 [ 2 fixnum/i ] compile-1 ] unit-test +[ -2 ] [ 4 [ -2 fixnum/i ] compile-1 ] unit-test +[ 3 1 ] [ 10 3 [ fixnum/mod ] compile-1 ] unit-test + +[ 4 ] [ 1 3 [ fixnum+ ] compile-1 ] unit-test +[ 4 ] [ 1 [ 3 fixnum+ ] compile-1 ] unit-test +[ 4 ] [ [ 1 3 fixnum+ ] compile-1 ] unit-test + +[ 4 ] [ 1 3 [ fixnum+fast ] compile-1 ] unit-test +[ 4 ] [ 1 [ 3 fixnum+fast ] compile-1 ] unit-test +[ 4 ] [ [ 1 3 fixnum+fast ] compile-1 ] unit-test + +[ 30001 ] [ 1 [ 30000 fixnum+fast ] compile-1 ] unit-test + +[ 6 ] [ 2 3 [ fixnum*fast ] compile-1 ] unit-test +[ 6 ] [ 2 [ 3 fixnum*fast ] compile-1 ] unit-test +[ 6 ] [ [ 2 3 fixnum*fast ] compile-1 ] unit-test +[ -6 ] [ 2 -3 [ fixnum*fast ] compile-1 ] unit-test +[ -6 ] [ 2 [ -3 fixnum*fast ] compile-1 ] unit-test +[ -6 ] [ [ 2 -3 fixnum*fast ] compile-1 ] unit-test + +[ 6 ] [ 2 3 [ fixnum* ] compile-1 ] unit-test +[ 6 ] [ 2 [ 3 fixnum* ] compile-1 ] unit-test +[ 6 ] [ [ 2 3 fixnum* ] compile-1 ] unit-test +[ -6 ] [ 2 -3 [ fixnum* ] compile-1 ] unit-test +[ -6 ] [ 2 [ -3 fixnum* ] compile-1 ] unit-test +[ -6 ] [ [ 2 -3 fixnum* ] compile-1 ] unit-test + +[ t ] [ 3 type 3 [ type ] compile-1 eq? ] unit-test +[ t ] [ 3 >bignum type 3 >bignum [ type ] compile-1 eq? ] unit-test +[ t ] [ "hey" type "hey" [ type ] compile-1 eq? ] unit-test +[ t ] [ f type f [ type ] compile-1 eq? ] unit-test + +[ 5 ] [ 1 2 [ eq? [ 3 ] [ 5 ] if ] compile-1 ] unit-test +[ 3 ] [ 2 2 [ eq? [ 3 ] [ 5 ] if ] compile-1 ] unit-test +[ 3 ] [ 1 2 [ fixnum< [ 3 ] [ 5 ] if ] compile-1 ] unit-test +[ 5 ] [ 2 2 [ fixnum< [ 3 ] [ 5 ] if ] compile-1 ] unit-test + +[ 8 ] [ 1 3 [ fixnum-shift ] compile-1 ] unit-test +[ 8 ] [ 1 [ 3 fixnum-shift ] compile-1 ] unit-test +[ 8 ] [ [ 1 3 fixnum-shift ] compile-1 ] unit-test +[ -8 ] [ -1 3 [ fixnum-shift ] compile-1 ] unit-test +[ -8 ] [ -1 [ 3 fixnum-shift ] compile-1 ] unit-test +[ -8 ] [ [ -1 3 fixnum-shift ] compile-1 ] unit-test + +[ 2 ] [ 8 -2 [ fixnum-shift ] compile-1 ] unit-test +[ 2 ] [ 8 [ -2 fixnum-shift ] compile-1 ] unit-test + +[ 0 ] [ [ 123 -64 fixnum-shift ] compile-1 ] unit-test +[ 0 ] [ 123 -64 [ fixnum-shift ] compile-1 ] unit-test +[ -1 ] [ [ -123 -64 fixnum-shift ] compile-1 ] unit-test +[ -1 ] [ -123 -64 [ fixnum-shift ] compile-1 ] unit-test + +[ HEX: 10000000 ] [ HEX: -10000000 >fixnum [ 0 swap fixnum- ] compile-1 ] unit-test +[ HEX: 10000000 ] [ HEX: -fffffff >fixnum [ 1 swap fixnum- ] compile-1 ] unit-test + +[ t ] [ 1 27 fixnum-shift dup [ fixnum+ ] compile-1 1 28 fixnum-shift = ] unit-test +[ -268435457 ] [ 1 28 shift neg >fixnum [ -1 fixnum+ ] compile-1 ] unit-test + +[ 4294967296 ] [ 1 32 [ fixnum-shift ] compile-1 ] unit-test +[ 4294967296 ] [ 1 [ 32 fixnum-shift ] compile-1 ] unit-test +[ 4294967296 ] [ 1 [ 16 fixnum-shift 16 fixnum-shift ] compile-1 ] unit-test +[ -4294967296 ] [ -1 32 [ fixnum-shift ] compile-1 ] unit-test +[ -4294967296 ] [ -1 [ 32 fixnum-shift ] compile-1 ] unit-test +[ -4294967296 ] [ -1 [ 16 fixnum-shift 16 fixnum-shift ] compile-1 ] unit-test + +[ t ] [ 1 20 shift 1 20 shift [ fixnum* ] compile-1 1 40 shift = ] unit-test +[ t ] [ 1 20 shift neg 1 20 shift [ fixnum* ] compile-1 1 40 shift neg = ] unit-test +[ t ] [ 1 20 shift neg 1 20 shift neg [ fixnum* ] compile-1 1 40 shift = ] unit-test +[ -351382792 ] [ -43922849 [ 3 fixnum-shift ] compile-1 ] unit-test + +[ 268435456 ] [ -268435456 >fixnum -1 [ fixnum/i ] compile-1 ] unit-test + +[ 268435456 0 ] [ -268435456 >fixnum -1 [ fixnum/mod ] compile-1 ] unit-test + +[ t ] [ f [ f eq? ] compile-1 ] unit-test + +! regression +[ t ] [ { 1 2 3 } { 1 2 3 } [ over type over type eq? ] compile-1 2nip ] unit-test + +! regression +[ 3 ] [ + 100001 f 3 100000 pick set-nth + [ 100000 swap array-nth ] compile-1 +] unit-test + +! 64-bit overflow +cell 8 = [ + [ t ] [ 1 59 fixnum-shift dup [ fixnum+ ] compile-1 1 60 fixnum-shift = ] unit-test + [ -1152921504606846977 ] [ 1 60 shift neg >fixnum [ -1 fixnum+ ] compile-1 ] unit-test + + [ t ] [ 1 40 shift 1 40 shift [ fixnum* ] compile-1 1 80 shift = ] unit-test + [ t ] [ 1 40 shift neg 1 40 shift [ fixnum* ] compile-1 1 80 shift neg = ] unit-test + [ t ] [ 1 40 shift neg 1 40 shift neg [ fixnum* ] compile-1 1 80 shift = ] unit-test + [ t ] [ 1 30 shift neg 1 50 shift neg [ fixnum* ] compile-1 1 80 shift = ] unit-test + [ t ] [ 1 50 shift neg 1 30 shift neg [ fixnum* ] compile-1 1 80 shift = ] unit-test + + [ 18446744073709551616 ] [ 1 64 [ fixnum-shift ] compile-1 ] unit-test + [ 18446744073709551616 ] [ 1 [ 64 fixnum-shift ] compile-1 ] unit-test + [ 18446744073709551616 ] [ 1 [ 32 fixnum-shift 32 fixnum-shift ] compile-1 ] unit-test + [ -18446744073709551616 ] [ -1 64 [ fixnum-shift ] compile-1 ] unit-test + [ -18446744073709551616 ] [ -1 [ 64 fixnum-shift ] compile-1 ] unit-test + [ -18446744073709551616 ] [ -1 [ 32 fixnum-shift 32 fixnum-shift ] compile-1 ] unit-test + + [ 1152921504606846976 ] [ -1152921504606846976 >fixnum -1 [ fixnum/i ] compile-1 ] unit-test + + [ 1152921504606846976 0 ] [ -1152921504606846976 >fixnum -1 [ fixnum/mod ] compile-1 ] unit-test + + [ -268435457 ] [ 28 2^ [ fixnum-bitnot ] compile-1 ] unit-test +] when + +! Some randomized tests +: compiled-fixnum* fixnum* ; +\ compiled-fixnum* compile + +: test-fixnum* + (random) >fixnum (random) >fixnum + 2dup + [ fixnum* ] 2keep compiled-fixnum* = + [ 2drop ] [ "Oops" throw ] if ; + +[ ] [ 10000 [ test-fixnum* ] times ] unit-test + +: compiled-fixnum>bignum fixnum>bignum ; +\ compiled-fixnum>bignum compile + +: test-fixnum>bignum + (random) >fixnum + dup [ fixnum>bignum ] keep compiled-fixnum>bignum = + [ drop ] [ "Oops" throw ] if ; + +[ ] [ 10000 [ test-fixnum>bignum ] times ] unit-test + +: compiled-bignum>fixnum bignum>fixnum ; +\ compiled-bignum>fixnum compile + +: test-bignum>fixnum + 5 random [ drop (random) ] map product >bignum + dup [ bignum>fixnum ] keep compiled-bignum>fixnum = + [ drop ] [ "Oops" throw ] if ; + +[ ] [ 10000 [ test-bignum>fixnum ] times ] unit-test + +! Test overflow check removal +[ t ] [ + most-positive-fixnum 100 - >fixnum + 200 + [ [ fixnum+ ] compile-1 [ bignum>fixnum ] compile-1 ] 2keep + [ fixnum+ >fixnum ] compile-1 + = +] unit-test + +[ t ] [ + most-negative-fixnum 100 + >fixnum + -200 + [ [ fixnum+ ] compile-1 [ bignum>fixnum ] compile-1 ] 2keep + [ fixnum+ >fixnum ] compile-1 + = +] unit-test + +[ t ] [ + most-negative-fixnum 100 + >fixnum + 200 + [ [ fixnum- ] compile-1 [ bignum>fixnum ] compile-1 ] 2keep + [ fixnum- >fixnum ] compile-1 + = +] unit-test + +! Test inline allocators +[ { 1 1 1 } ] [ + [ 3 1 ] compile-1 +] unit-test + +[ B{ 0 0 0 } ] [ + [ 3 ] compile-1 +] unit-test + +[ 500 ] [ + [ 500 length ] compile-1 +] unit-test + +[ C{ 1 2 } ] [ 1 2 [ ] compile-1 ] unit-test + +[ 1/2 ] [ 1 2 [ ] compile-1 ] unit-test + +[ \ + ] [ \ + [ ] compile-1 ] unit-test + +[ H{ } ] [ + 100 [ (hashtable) ] compile-1 [ reset-hash ] keep +] unit-test + +[ B{ 0 0 0 0 0 } ] [ + [ 5 ] compile-1 +] unit-test + +[ V{ 1 2 } ] [ + { 1 2 3 } 2 [ array>vector ] compile-1 +] unit-test + +[ SBUF" hello" ] [ + "hello world" 5 [ string>sbuf ] compile-1 +] unit-test + +[ [ 3 + ] ] [ + 3 [ + ] [ curry ] compile-1 +] unit-test + +! Alien intrinsics +[ 3 ] [ B{ 1 2 3 4 5 } 2 [ alien-unsigned-1 ] compile-1 ] unit-test +[ 3 ] [ [ B{ 1 2 3 4 5 } 2 alien-unsigned-1 ] compile-1 ] unit-test +[ 3 ] [ B{ 1 2 3 4 5 } 2 [ { byte-array fixnum } declare alien-unsigned-1 ] compile-1 ] unit-test +[ 3 ] [ B{ 1 2 3 4 5 } 2 [ { simple-c-ptr fixnum } declare alien-unsigned-1 ] compile-1 ] unit-test + +[ ] [ B{ 1 2 3 4 5 } malloc-byte-array "b" set ] unit-test + +[ 3 ] [ "b" get 2 [ alien-unsigned-1 ] compile-1 ] unit-test +[ 3 ] [ "b" get [ { simple-alien } declare 2 alien-unsigned-1 ] compile-1 ] unit-test +[ 3 ] [ "b" get 2 [ { simple-alien fixnum } declare alien-unsigned-1 ] compile-1 ] unit-test +[ 3 ] [ "b" get 2 [ { simple-c-ptr fixnum } declare alien-unsigned-1 ] compile-1 ] unit-test + +[ ] [ "b" get free ] unit-test + +[ ] [ "hello world" malloc-char-string "s" set ] unit-test + +[ "hello world" ] [ "s" get [ { byte-array } declare *void* ] compile-1 alien>char-string ] unit-test +[ "hello world" ] [ "s" get [ { simple-c-ptr } declare *void* ] compile-1 alien>char-string ] unit-test + +[ ] [ "s" get free ] unit-test + +[ ALIEN: 1234 ] [ ALIEN: 1234 [ { simple-alien } declare ] compile-1 *void* ] unit-test +[ ALIEN: 1234 ] [ ALIEN: 1234 [ { simple-c-ptr } declare ] compile-1 *void* ] unit-test +[ f ] [ f [ { POSTPONE: f } declare ] compile-1 *void* ] unit-test + +[ 252 ] [ B{ 1 2 3 -4 5 } 3 [ { byte-array fixnum } declare alien-unsigned-1 ] compile-1 ] unit-test +[ -4 ] [ B{ 1 2 3 -4 5 } 3 [ { byte-array fixnum } declare alien-signed-1 ] compile-1 ] unit-test + +: xword-def word-def [ { fixnum } declare ] swap append ; + +[ -100 ] [ -100 [ { byte-array } declare *char ] compile-1 ] unit-test +[ 156 ] [ -100 [ { byte-array } declare *uchar ] compile-1 ] unit-test + +[ -100 ] [ -100 \ xword-def compile-1 *char ] unit-test +[ 156 ] [ -100 \ xword-def compile-1 *uchar ] unit-test + +[ -1000 ] [ -1000 [ { byte-array } declare *short ] compile-1 ] unit-test +[ 64536 ] [ -1000 [ { byte-array } declare *ushort ] compile-1 ] unit-test + +[ -1000 ] [ -1000 \ xword-def compile-1 *short ] unit-test +[ 64536 ] [ -1000 \ xword-def compile-1 *ushort ] unit-test + +[ -100000 ] [ -100000 [ { byte-array } declare *int ] compile-1 ] unit-test +[ 4294867296 ] [ -100000 [ { byte-array } declare *uint ] compile-1 ] unit-test + +[ -100000 ] [ -100000 \ xword-def compile-1 *int ] unit-test +[ 4294867296 ] [ -100000 \ xword-def compile-1 *uint ] unit-test + +[ t ] [ pi pi *double = ] unit-test + +[ t ] [ pi [ { byte-array } declare *double ] compile-1 pi = ] unit-test + +! Silly +[ t ] [ pi 4 [ [ { float byte-array } declare 0 set-alien-float ] compile-1 ] keep *float pi - abs 0.001 < ] unit-test +[ t ] [ pi [ { byte-array } declare *float ] compile-1 pi - abs 0.001 < ] unit-test + +[ t ] [ pi 8 [ [ { float byte-array } declare 0 set-alien-double ] compile-1 ] keep *double pi = ] unit-test diff --git a/core/compiler/test/optimizer.factor b/core/compiler/test/optimizer.factor new file mode 100644 index 0000000000..496c6f24ec --- /dev/null +++ b/core/compiler/test/optimizer.factor @@ -0,0 +1,275 @@ +USING: arrays compiler generic hashtables inference kernel +kernel.private math optimizer prettyprint sequences sbufs +strings tools.test vectors words sequences.private quotations +optimizer.backend classes inference.dataflow tuples.private ; +IN: temporary + +[ H{ { 1 5 } { 3 4 } { 2 5 } } ] [ + H{ { 1 2 } { 3 4 } } H{ { 2 5 } } union* +] unit-test + +[ H{ { 1 4 } { 2 4 } { 3 4 } } ] [ + H{ { 1 2 } { 3 4 } } H{ { 2 3 } } union* +] unit-test + +! Test method inlining +[ f ] [ fixnum { } min-class ] unit-test + +[ string ] [ + \ string + [ integer string array reversed sbuf + slice vector quotation ] + sort-classes min-class +] unit-test + +[ fixnum ] [ + \ fixnum + [ fixnum integer object ] + sort-classes min-class +] unit-test + +[ integer ] [ + \ fixnum + [ integer float object ] + sort-classes min-class +] unit-test + +[ object ] [ + \ word + [ integer float object ] + sort-classes min-class +] unit-test + +[ reversed ] [ + \ reversed + [ integer reversed slice ] + sort-classes min-class +] unit-test + +FORGET: xyz +GENERIC: xyz ( obj -- obj ) +M: array xyz xyz ; + +[ ] [ \ xyz compile ] unit-test + +! Test predicate inlining +: pred-test-1 + dup fixnum? [ + dup integer? [ "integer" ] [ "nope" ] if + ] [ + "not a fixnum" + ] if ; + +[ 1 "integer" ] [ 1 pred-test-1 ] unit-test + +TUPLE: pred-test ; + +: pred-test-2 + dup tuple? [ + dup pred-test? [ "pred-test" ] [ "nope" ] if + ] [ + "not a tuple" + ] if ; + +[ T{ pred-test } "pred-test" ] [ T{ pred-test } pred-test-2 ] unit-test + +: pred-test-3 + dup pred-test? [ + dup tuple? [ "pred-test" ] [ "nope" ] if + ] [ + "not a tuple" + ] if ; + +[ T{ pred-test } "pred-test" ] [ T{ pred-test } pred-test-3 ] unit-test + +: inline-test + "nom" = ; + +[ t ] [ "nom" inline-test ] unit-test +[ f ] [ "shayin" inline-test ] unit-test +[ f ] [ 3 inline-test ] unit-test + +: fixnum-declarations >fixnum 24 shift 1234 bitxor ; + +[ ] [ 1000000 fixnum-declarations . ] unit-test + +! regression + +: literal-not-branch 0 not [ ] [ ] if ; + +[ ] [ literal-not-branch ] unit-test + +! regression + +: bad-kill-1 [ 3 f ] [ dup bad-kill-1 ] if ; inline +: bad-kill-2 bad-kill-1 drop ; + +[ 3 ] [ t bad-kill-2 ] unit-test + +! regression +: (the-test) ( n -- ) dup 0 > [ 1- (the-test) ] when ; inline +: the-test ( -- n ) 2 dup (the-test) ; + +[ 2 0 ] [ the-test ] unit-test + +! regression +: (double-recursion) ( start end -- ) + < [ + 6 1 (double-recursion) + 3 2 (double-recursion) + ] when ; inline + +: double-recursion 0 2 (double-recursion) ; + +[ ] [ double-recursion ] unit-test + +! regression +: double-label-1 ( a b c -- d ) + [ f double-label-1 ] [ swap nth-unsafe ] if ; inline + +: double-label-2 ( a -- b ) + dup array? [ ] [ ] if 0 t double-label-1 ; + +[ 0 ] [ 10 double-label-2 ] unit-test + +! regression +GENERIC: void-generic ( obj -- * ) +: breakage "hi" void-generic ; +[ ] [ \ breakage compile ] unit-test +[ breakage ] unit-test-fails + +! regression +: test-0 ( n -- ) dup 0 = [ drop ] [ 1- test-0 ] if ; inline +: test-1 ( n -- ) t [ test-0 ] [ delegate dup [ test-1 ] [ drop ] if ] if ; inline +: test-2 ( -- ) 5 test-1 ; + +[ f ] [ f test-2 ] unit-test + +: branch-fold-regression-0 ( n -- ) + t [ ] [ 1+ branch-fold-regression-0 ] if ; inline + +: branch-fold-regression-1 ( -- ) + 10 branch-fold-regression-0 ; + +[ 10 ] [ branch-fold-regression-1 ] unit-test + +! another regression +: constant-branch-fold-0 "hey" ; foldable +: constant-branch-fold-1 constant-branch-fold-0 "hey" = ; inline +[ 1 ] [ [ constant-branch-fold-1 [ 1 ] [ 2 ] if ] compile-1 ] unit-test + +! another regression +: foo f ; +: bar foo 4 4 = and ; +[ f ] [ bar ] unit-test + +! ensure identities are working in some form +[ t ] [ + [ { number } declare 0 + ] dataflow optimize + [ #push? ] node-exists? not +] unit-test + +! compiling with a non-literal class failed +[ t ] [ [ ] compile-quot word? ] unit-test + +GENERIC: foozul +M: reversed foozul ; +M: integer foozul ; +M: slice foozul ; + +[ reversed ] [ reversed \ foozul specific-method ] unit-test + +! regression +: constant-fold-2 f ; foldable +: constant-fold-3 4 ; foldable + +[ f t ] [ + [ constant-fold-2 constant-fold-3 4 = ] compile-1 +] unit-test + +: constant-fold-4 f ; foldable +: constant-fold-5 f ; foldable + +[ f ] [ + [ constant-fold-4 constant-fold-5 or ] compile-1 +] unit-test + +[ 5 ] [ 5 [ 0 + ] compile-1 ] unit-test +[ 5 ] [ 5 [ 0 swap + ] compile-1 ] unit-test + +[ 5 ] [ 5 [ 0 - ] compile-1 ] unit-test +[ -5 ] [ 5 [ 0 swap - ] compile-1 ] unit-test +[ 0 ] [ 5 [ dup - ] compile-1 ] unit-test + +[ 5 ] [ 5 [ 1 * ] compile-1 ] unit-test +[ 5 ] [ 5 [ 1 swap * ] compile-1 ] unit-test +[ 0 ] [ 5 [ 0 * ] compile-1 ] unit-test +[ 0 ] [ 5 [ 0 swap * ] compile-1 ] unit-test +[ -5 ] [ 5 [ -1 * ] compile-1 ] unit-test +[ -5 ] [ 5 [ -1 swap * ] compile-1 ] unit-test + +[ 5 ] [ 5 [ 1 / ] compile-1 ] unit-test +[ 1/5 ] [ 5 [ 1 swap / ] compile-1 ] unit-test +[ -5 ] [ 5 [ -1 / ] compile-1 ] unit-test + +[ 0 ] [ 5 [ 1 mod ] compile-1 ] unit-test +[ 0 ] [ 5 [ 1 rem ] compile-1 ] unit-test + +[ 5 ] [ 5 [ -1 bitand ] compile-1 ] unit-test +[ 0 ] [ 5 [ 0 bitand ] compile-1 ] unit-test +[ 5 ] [ 5 [ -1 swap bitand ] compile-1 ] unit-test +[ 0 ] [ 5 [ 0 swap bitand ] compile-1 ] unit-test +[ 5 ] [ 5 [ dup bitand ] compile-1 ] unit-test + +[ 5 ] [ 5 [ 0 bitor ] compile-1 ] unit-test +[ -1 ] [ 5 [ -1 bitor ] compile-1 ] unit-test +[ 5 ] [ 5 [ 0 swap bitor ] compile-1 ] unit-test +[ -1 ] [ 5 [ -1 swap bitor ] compile-1 ] unit-test +[ 5 ] [ 5 [ dup bitor ] compile-1 ] unit-test + +[ 5 ] [ 5 [ 0 bitxor ] compile-1 ] unit-test +[ 5 ] [ 5 [ 0 swap bitxor ] compile-1 ] unit-test +[ -6 ] [ 5 [ -1 bitxor ] compile-1 ] unit-test +[ -6 ] [ 5 [ -1 swap bitxor ] compile-1 ] unit-test +[ 0 ] [ 5 [ dup bitxor ] compile-1 ] unit-test + +[ 0 ] [ 5 [ 0 swap shift ] compile-1 ] unit-test +[ 5 ] [ 5 [ 0 shift ] compile-1 ] unit-test + +[ f ] [ 5 [ dup < ] compile-1 ] unit-test +[ t ] [ 5 [ dup <= ] compile-1 ] unit-test +[ f ] [ 5 [ dup > ] compile-1 ] unit-test +[ t ] [ 5 [ dup >= ] compile-1 ] unit-test + +[ t ] [ 5 [ dup eq? ] compile-1 ] unit-test +[ t ] [ 5 [ dup = ] compile-1 ] unit-test +[ t ] [ 5 [ dup number= ] compile-1 ] unit-test +[ t ] [ \ vector [ \ vector = ] compile-1 ] unit-test + +[ 3 ] [ 10/3 [ { ratio } declare 1 /i ] compile-1 ] unit-test + +GENERIC: detect-number ( obj -- obj ) +M: number detect-number ; + +[ 10 f [ 0 + detect-number ] compile-1 ] unit-test-fails + +! Regression +[ 4 [ + ] ] [ 2 2 [ [ + ] [ call ] keep ] compile-1 ] unit-test + +! Regression +USE: sorting +USE: sorting.private + +: old-binsearch ( elt quot seq -- elt quot i ) + dup length 1 <= [ + slice-from + ] [ + [ midpoint swap call ] 3keep roll dup zero? + [ drop dup slice-from swap midpoint@ + ] + [ partition old-binsearch ] if + ] if ; inline + +[ 10 ] [ + 10 20 >vector + [ [ - ] swap old-binsearch ] compile-1 2nip +] unit-test diff --git a/core/compiler/test/redefine.factor b/core/compiler/test/redefine.factor new file mode 100644 index 0000000000..df2f3c3915 --- /dev/null +++ b/core/compiler/test/redefine.factor @@ -0,0 +1,45 @@ +USING: compiler definitions generic assocs inference math +namespaces parser tools.test words kernel sequences arrays io +effects ; +IN: temporary + +parse-hook get [ + DEFER: foo \ foo reset-generic + DEFER: bar \ bar reset-generic + + : short-effect + dup effect-in length swap effect-out length 2array ; + + [ ] [ \ foo [ 1 2 ] define-compound ] unit-test + [ { 0 2 } ] [ [ foo ] infer short-effect ] unit-test + [ ] [ \ foo compile ] unit-test + [ ] [ \ bar [ foo foo ] define-compound ] unit-test + [ ] [ \ bar compile ] unit-test + [ ] [ \ foo [ 1 2 3 ] define-compound ] unit-test + [ t ] [ \ bar changed-words get key? ] unit-test + [ ] [ recompile ] unit-test + [ { 0 3 } ] [ [ foo ] infer short-effect ] unit-test + [ f ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ bar [ 1 2 ] define-compound ] unit-test + [ t ] [ \ bar changed-words get key? ] unit-test + [ ] [ recompile ] unit-test + [ { 0 2 } ] [ [ bar ] infer short-effect ] unit-test + [ f ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ foo [ 1 2 3 ] define-compound ] unit-test + [ f ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ bar [ 1 2 3 ] define-compound ] unit-test + [ t ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ bar forget ] unit-test + [ f ] [ \ bar changed-words get key? ] unit-test + + : xy ; + : yx xy ; + + \ yx compile + + \ xy [ 1 ] define-compound + + [ ] [ recompile ] unit-test + + [ 1 ] [ yx ] unit-test +] when diff --git a/core/compiler/test/simple.factor b/core/compiler/test/simple.factor new file mode 100644 index 0000000000..594bb844a1 --- /dev/null +++ b/core/compiler/test/simple.factor @@ -0,0 +1,58 @@ +USING: compiler tools.test kernel kernel.private +combinators.private ; +IN: temporary + +! Test empty word +[ ] [ [ ] compile-1 ] unit-test + +! Test literals +[ 1 ] [ [ 1 ] compile-1 ] unit-test +[ 31 ] [ [ 31 ] compile-1 ] unit-test +[ 255 ] [ [ 255 ] compile-1 ] unit-test +[ -1 ] [ [ -1 ] compile-1 ] unit-test +[ 65536 ] [ [ 65536 ] compile-1 ] unit-test +[ -65536 ] [ [ -65536 ] compile-1 ] unit-test +[ "hey" ] [ [ "hey" ] compile-1 ] unit-test + +! Calls +: no-op ; + +[ ] [ [ no-op ] compile-1 ] unit-test +[ 3 ] [ [ no-op 3 ] compile-1 ] unit-test +[ 3 ] [ [ 3 no-op ] compile-1 ] unit-test + +: bar 4 ; + +[ 4 ] [ [ bar no-op ] compile-1 ] unit-test +[ 4 3 ] [ [ no-op bar 3 ] compile-1 ] unit-test +[ 3 4 ] [ [ 3 no-op bar ] compile-1 ] unit-test + +[ ] [ no-op ] unit-test + +! Conditionals + +[ 1 ] [ t [ [ 1 ] [ 2 ] if ] compile-1 ] unit-test +[ 2 ] [ f [ [ 1 ] [ 2 ] if ] compile-1 ] unit-test +[ 1 3 ] [ t [ [ 1 ] [ 2 ] if 3 ] compile-1 ] unit-test +[ 2 3 ] [ f [ [ 1 ] [ 2 ] if 3 ] compile-1 ] unit-test + +[ "hi" ] [ 0 [ { [ "hi" ] [ "bye" ] } dispatch ] compile-1 ] unit-test +[ "bye" ] [ 1 [ { [ "hi" ] [ "bye" ] } dispatch ] compile-1 ] unit-test + +[ "hi" 3 ] [ 0 [ { [ "hi" ] [ "bye" ] } dispatch 3 ] compile-1 ] unit-test +[ "bye" 3 ] [ 1 [ { [ "hi" ] [ "bye" ] } dispatch 3 ] compile-1 ] unit-test + +[ 4 1 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch ] compile-1 ] unit-test +[ 3 1 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch ] compile-1 ] unit-test +[ 4 1 3 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-1 ] unit-test +[ 3 1 3 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-1 ] unit-test + +! Labels + +: recursive ( ? -- ) [ f recursive ] when ; inline + +[ ] [ t [ recursive ] compile-1 ] unit-test + +\ recursive compile + +[ ] [ t recursive ] unit-test diff --git a/core/compiler/test/stack-trace.factor b/core/compiler/test/stack-trace.factor new file mode 100644 index 0000000000..ee94f0c9a2 --- /dev/null +++ b/core/compiler/test/stack-trace.factor @@ -0,0 +1,39 @@ +IN: temporary +USING: compiler tools.test namespaces sequences +kernel.private kernel math continuations continuations.private +words ; + +: symbolic-stack-trace ( -- newseq ) + error-continuation get continuation-call callstack>array ; + +: foo 3 throw 7 ; +: bar foo 4 ; +: baz bar 5 ; +\ baz compile +[ 3 ] [ [ baz ] catch ] unit-test +[ { baz bar foo throw } ] [ + symbolic-stack-trace [ word? ] subset +] unit-test + +: bleh [ 3 + ] map [ 0 > ] subset ; +\ bleh compile + +: stack-trace-contains? symbolic-stack-trace memq? ; + +[ t ] [ + [ { 1 "hi" } bleh ] catch drop \ + stack-trace-contains? +] unit-test + +[ f t ] [ + [ { C{ 1 2 } } bleh ] catch drop + \ + stack-trace-contains? + \ > stack-trace-contains? +] unit-test + +: quux [ t [ "hi" throw ] when ] times ; +\ quux compile + +[ t ] [ + [ 10 quux ] catch drop + \ (each-integer) stack-trace-contains? +] unit-test diff --git a/core/compiler/test/templates-early.factor b/core/compiler/test/templates-early.factor new file mode 100644 index 0000000000..5f6ece5d68 --- /dev/null +++ b/core/compiler/test/templates-early.factor @@ -0,0 +1,131 @@ +! Testing templates machinery without compiling anything +IN: temporary +USING: compiler generator generator.registers tools.test +namespaces sequences words kernel math effects ; + +[ + [ ] [ init-templates ] unit-test + + [ V{ 3 } ] [ 3 fresh-object fresh-objects get ] unit-test + + [ ] [ 0 phantom-d get phantom-push ] unit-test + + [ ] [ compute-free-vregs ] unit-test + + [ f ] [ 0 T{ int-regs } free-vregs member? ] unit-test + + [ f ] [ + [ + copy-templates + 1 phantom-d get phantom-push + compute-free-vregs + 1 T{ int-regs } free-vregs member? + ] with-scope + ] unit-test + + [ t ] [ 1 T{ int-regs } free-vregs member? ] unit-test +] with-scope + +[ + [ ] [ init-templates ] unit-test + + [ ] [ T{ effect f 3 { 1 2 0 } f } phantom-shuffle ] unit-test + + [ 3 ] [ live-locs length ] unit-test + + [ ] [ T{ effect f 2 { 1 0 } f } phantom-shuffle ] unit-test + + [ 2 ] [ live-locs length ] unit-test +] with-scope + +[ + [ ] [ init-templates ] unit-test + + [ ] [ init-generator ] unit-test + + [ t ] [ [ end-basic-block ] { } make empty? ] unit-test + + 3 fresh-object + + [ f ] [ [ end-basic-block ] { } make empty? ] unit-test +] with-scope + +[ + [ ] [ init-templates ] unit-test + + H{ + { +input+ { { f "x" } } } + } clone [ + [ 1 0 ] [ +input+ get { } { } guess-vregs ] unit-test + [ ] [ 1 0 ensure-vregs ] unit-test + ! [ t ] [ +input+ get phantom-d get compatible? ] unit-test + [ ] [ finalize-contents ] unit-test + [ ] [ [ template-inputs ] { } make drop ] unit-test + ] bind +] with-scope + +! Test template picking strategy +SYMBOL: template-chosen + +: template-test ( a b -- c ) + ; + +\ template-test { + { + [ + 1 template-chosen get push + ] H{ + { +input+ { { f "obj" } { [ ] "n" } } } + { +output+ { "obj" } } + } + } + { + [ + 2 template-chosen get push + ] H{ + { +input+ { { f "obj" } { f "n" } } } + { +output+ { "obj" } } + } + } +} define-intrinsics + +[ V{ 2 } ] [ + V{ } clone template-chosen set + [ template-test ] compile-quot drop + template-chosen get +] unit-test + +[ V{ 1 } ] [ + V{ } clone template-chosen set + [ dup 0 template-test ] compile-quot drop + template-chosen get +] unit-test + +[ V{ 1 } ] [ + V{ } clone template-chosen set + [ 0 template-test ] compile-quot drop + template-chosen get +] unit-test + +! Regression +[ + [ ] [ init-templates ] unit-test + + ! dup dup + [ ] [ + T{ effect f { "x" } { "x" "x" } } phantom-shuffle + T{ effect f { "x" } { "x" "x" } } phantom-shuffle + ] unit-test + + ! This is not empty since a load instruction is emitted + [ f ] [ + [ { { f "x" } } fast-input ] { } make empty? + ] unit-test + + ! This is empty since we already loaded the value + [ t ] [ + [ { { f "x" } } fast-input ] { } make empty? + ] unit-test + + ! This is empty since we didn't change the stack + [ t ] [ [ end-basic-block ] { } make empty? ] unit-test +] with-scope diff --git a/core/compiler/test/templates.factor b/core/compiler/test/templates.factor new file mode 100644 index 0000000000..8877126902 --- /dev/null +++ b/core/compiler/test/templates.factor @@ -0,0 +1,187 @@ +! Black box testing of templater optimization + +USING: arrays compiler kernel kernel.private math +hashtables.private math.private math.ratios.private namespaces +sequences sequences.private tools.test namespaces.private +slots.private combinators.private ; +IN: temporary + +! Oops! +[ 5000 ] [ [ 5000 ] compile-1 ] unit-test +[ "hi" ] [ [ "hi" ] compile-1 ] unit-test + +[ 1 2 3 4 ] [ [ 1 2 3 4 ] compile-1 ] unit-test + +[ 1 1 ] [ 1 [ dup ] compile-1 ] unit-test +[ 0 ] [ 3 [ tag ] compile-1 ] unit-test +[ 0 3 ] [ 3 [ [ tag ] keep ] compile-1 ] unit-test + +[ 2 3 ] [ 3 [ 2 swap ] compile-1 ] unit-test + +[ 2 1 3 4 ] [ 1 2 [ swap 3 4 ] compile-1 ] unit-test + +[ 2 3 4 ] [ 3 [ 2 swap 4 ] compile-1 ] unit-test + +[ { 1 2 3 } { 1 4 3 } 3 3 ] +[ { 1 2 3 } { 1 4 3 } [ over tag over tag ] compile-1 ] +unit-test + +[ { 1 2 3 } { 1 4 3 } 8 8 ] +[ { 1 2 3 } { 1 4 3 } [ over type over type ] compile-1 ] +unit-test + +! Test literals in either side of a shuffle +[ 4 1 ] [ 1 [ [ 3 fixnum+ ] keep ] compile-1 ] unit-test + +[ 2 ] [ 1 2 [ swap fixnum/i ] compile-1 ] unit-test + +: foo ; + +[ 4 4 ] +[ 1/2 [ tag [ foo ] keep ] compile-1 ] +unit-test + +[ 1 2 2 ] +[ 1/2 [ dup 1 slot swap 2 slot [ foo ] keep ] compile-1 ] +unit-test + +[ 41 5 4 ] [ + 5/4 4/5 [ + dup ratio? [ + over ratio? [ + 2dup 2>fraction >r * swap r> * swap + + -rot denominator swap denominator + ] [ + 2drop f f f + ] if + ] [ + 2drop f f f + ] if + ] compile-1 +] unit-test + +: jxyz + over bignum? [ + dup ratio? [ + [ >fraction ] 2apply swapd + >r 2array swap r> 2array swap + ] when + ] when ; + +\ jxyz compile + +[ { 1 2 } { 1 1 } ] [ 1 >bignum 1/2 jxyz ] unit-test + +[ 3 ] +[ + global [ 3 \ foo set ] bind + \ foo [ global >n get ndrop ] compile-1 +] unit-test + +: blech drop ; + +[ 3 ] +[ + global [ 3 \ foo set ] bind + \ foo [ global [ get ] swap blech call ] compile-1 +] unit-test + +[ 3 ] +[ + global [ 3 \ foo set ] bind + \ foo [ global [ get ] swap >n call ndrop ] compile-1 +] unit-test + +[ 3 ] +[ + global [ 3 \ foo set ] bind + \ foo [ global [ get ] bind ] compile-1 +] unit-test + +[ 12 13 ] [ + -12 -13 [ [ 0 swap fixnum-fast ] 2apply ] compile-1 +] unit-test + +[ -1 2 ] [ 1 2 [ >r 0 swap fixnum- r> ] compile-1 ] unit-test + +[ 12 13 ] [ + -12 -13 [ [ 0 swap fixnum- ] 2apply ] compile-1 +] unit-test + +[ 2 ] [ + SBUF" " [ 2 slot 2 [ slot ] keep ] compile-1 nip +] unit-test + +! Test slow shuffles +[ 3 1 2 3 4 5 6 7 8 9 ] [ + 1 2 3 4 5 6 7 8 9 + [ >r >r >r >r >r >r >r >r >r 3 r> r> r> r> r> r> r> r> r> ] + compile-1 +] unit-test + +[ 2 2 2 2 2 2 2 2 2 2 1 ] [ + 1 2 + [ swap >r dup dup dup dup dup dup dup dup dup r> ] compile-1 +] unit-test + +[ ] [ [ 9 [ ] times ] compile-1 ] unit-test + +[ ] [ + [ + [ 200 dup [ 200 3array ] curry map drop ] times + ] compile-quot drop +] unit-test + + +! Test how dispatch handles the end of a basic block +: try-breaking-dispatch + float+ swap { [ "hey" ] [ "bye" ] } dispatch ; + +: try-breaking-dispatch-2 + 1 1.0 2.5 try-breaking-dispatch "bye" = >r 3.5 = r> and ; + +[ t ] [ + 10000000 [ drop try-breaking-dispatch-2 ] all? +] unit-test + +! Regression +: (broken) ( x -- y ) ; + +[ 2.0 { 2.0 0.0 } ] [ + 2.0 1.0 + [ float/f 0.0 [ drop (broken) ] 2keep 2array ] compile-1 +] unit-test + +! Regression +: hellish-bug-1 2drop ; + +: hellish-bug-2 ( i array x -- x ) + 2dup 1 slot eq? [ 2drop ] [ + 2dup array-nth tombstone? [ + [ + [ array-nth ] 2keep >r 1 fixnum+fast r> array-nth + pick 2dup hellish-bug-1 3drop + ] 2keep + ] unless >r 2 fixnum+fast r> hellish-bug-2 + ] if ; inline + +: hellish-bug-3 ( hash array -- ) + 0 swap hellish-bug-2 drop ; + +[ ] [ + H{ { 1 2 } { 3 4 } } dup hash-array + [ 0 swap hellish-bug-2 drop ] compile-1 +] unit-test + +! Regression +: foox + dup not + [ drop 3 ] [ dup tuple? [ drop 4 ] [ drop 5 ] if ] if ; + +[ 3 ] [ f foox ] unit-test + +TUPLE: my-tuple ; + +[ 4 ] [ T{ my-tuple } foox ] unit-test + +[ 5 ] [ "hi" foox ] unit-test diff --git a/core/compiler/test/tuples.factor b/core/compiler/test/tuples.factor new file mode 100644 index 0000000000..1a469ea3d9 --- /dev/null +++ b/core/compiler/test/tuples.factor @@ -0,0 +1,32 @@ +IN: temporary +USING: kernel tools.test compiler ; + +TUPLE: color red green blue ; + +[ T{ color f 1 2 3 } ] +[ 1 2 3 [ color construct-boa ] compile-1 ] unit-test + +[ 1 3 ] [ + 1 2 3 color construct-boa + [ { color-red color-blue } get-slots ] compile-1 +] unit-test + +[ T{ color f 10 2 20 } ] [ + 10 20 + 1 2 3 color construct-boa [ + [ + { set-color-red set-color-blue } set-slots + ] compile-1 + ] keep +] unit-test + +[ T{ color f f f f } ] +[ [ color construct-empty ] compile-1 ] unit-test + +[ T{ color "a" f "b" f } ] [ + "a" "b" + [ { set-delegate set-color-green } color construct ] + compile-1 +] unit-test + +[ T{ color f f f f } ] [ [ { } color construct ] compile-1 ] unit-test diff --git a/core/continuations/authors.txt b/core/continuations/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/continuations/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/continuations/continuations-docs.factor b/core/continuations/continuations-docs.factor new file mode 100644 index 0000000000..16752d3085 --- /dev/null +++ b/core/continuations/continuations-docs.factor @@ -0,0 +1,225 @@ +USING: help.markup help.syntax kernel kernel.private +continuations.private parser vectors arrays namespaces +threads assocs words quotations ; +IN: continuations + +ARTICLE: "errors-restartable" "Restartable error handling" +"Support for restartable errors is built on top of the basic error handling facility. The following words signals recoverable errors:" +{ $subsection throw-restarts } +{ $subsection rethrow-restarts } +"The list of restarts from the most recently-thrown error is stored in a global variable:" +{ $subsection restarts } +"To invoke restarts, see " { $link "debugger" } "." ; + +ARTICLE: "errors-post-mortem" "Post-mortem error inspection" +"The most recently thrown error, together with the continuation at that point, are stored in a pair of global variables:" +{ $subsection error } +{ $subsection error-continuation } +"Developer tools for inspecting these values are found in " { $link "debugger" } "." ; + +ARTICLE: "errors" "Error handling" +"Support for handling exceptional situations such as bad user input, implementation bugs, and input/output errors is provided by a set of words built using continuations." +$nl +"Two words raise an error in the innermost error handler for the current dynamic extent:" +{ $subsection throw } +{ $subsection rethrow } +"A set of words establish an error handler:" +{ $subsection cleanup } +{ $subsection recover } +{ $subsection catch } +"Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "." +{ $subsection "errors-restartable" } +{ $subsection "errors-post-mortem" } ; + +ARTICLE: "continuations.private" "Continuation implementation details" +"A continuation is simply a tuple holding the contents of the five stacks:" +{ $subsection continuation } +{ $subsection >continuation< } +"The five stacks can be read and written:" +{ $subsection datastack } +{ $subsection set-datastack } +{ $subsection retainstack } +{ $subsection set-retainstack } +{ $subsection callstack } +{ $subsection set-callstack } +{ $subsection namestack } +{ $subsection set-namestack } +{ $subsection catchstack } +{ $subsection set-catchstack } +"The continuations implementation has hooks for single-steppers:" +{ $subsection walker-hook } +{ $subsection set-walker-hook } +{ $subsection (continue) } +{ $subsection (continue-with) } ; + +ARTICLE: "continuations" "Continuations" +"At any point in the execution of a program, the " { $emphasis "current continuation" } " represents the future of the computation." +$nl +"Words for working with continuations are found in the " { $vocab-link "continuations" } " vocabulary; implementation details are in " { $vocab-link "continuations.private" } "." +$nl +"Continuations can be reified with the following two words:" +{ $subsection callcc0 } +{ $subsection callcc1 } +"Another two words resume continuations:" +{ $subsection continue } +{ $subsection continue-with } +"Continuations serve as the building block for a number of higher-level abstractions." +{ $subsection "errors" } +{ $subsection "continuations.private" } ; + +ABOUT: "continuations" + +HELP: catchstack* +{ $values { "catchstack" "a vector of continuations" } } +{ $description "Outputs the current catchstack." } ; + +HELP: catchstack +{ $values { "catchstack" "a vector of continuations" } } +{ $description "Outputs a copy of the current catchstack." } ; + +HELP: set-catchstack +{ $values { "catchstack" "a vector of continuations" } } +{ $description "Replaces the catchstack with a copy of the given vector." } ; + +HELP: continuation +{ $values { "continuation" continuation } } +{ $description "Reifies the current continuation from the point immediately after which the caller returns." } ; + +HELP: >continuation< +{ $values { "continuation" continuation } { "data" vector } { "retain" vector } { "call" vector } { "name" vector } { "catch" vector } { "c" array } } +{ $description "Takes a continuation apart into its constituents." } ; + +HELP: ifcc0 +{ $values { "capture" "a quotation with stack effect " { $snippet "( continuation -- )" } } { "restore" quotation } } +{ $description "Reifies a continuation from the point immediately after which this word returns, and passes it to " { $snippet "capture" } ". When the continuation is restored, execution resumes and "{ $snippet "restore" } " is called." } ; + +HELP: ifcc1 +{ $values { "capture" "a quotation with stack effect " { $snippet "( continuation -- )" } } { "restore" quotation } } +{ $description "Reifies a continuation from the point immediately after which this word returns, and passes it to " { $snippet "capture" } ". When the continuation is restored, execution resumes and "{ $snippet "restore" } " is called." } ; + +{ callcc0 continue callcc1 continue-with ifcc0 ifcc1 } related-words + +HELP: callcc0 +{ $values { "quot" "a quotation with stack effect " { $snippet "( continuation -- )" } } } +{ $description "Applies the quotation to the current continuation, which is reified from the point immediately after which the caller returns. The " { $link continue } " word resumes the continuation." } ; + +HELP: callcc1 +{ $values { "quot" "a quotation with stack effect " { $snippet "( continuation -- )" } } { "obj" "an object provided when resuming the continuation" } } +{ $description "Applies the quotation to the current continuation, which is reified from the point immediately after which the caller returns. The " { $link continue-with } " word resumes the continuation, passing a value back to the original execution context." } ; + +HELP: set-walker-hook +{ $values { "quot" "a quotation with stack effect " { $snippet "( continuation -- )" } ", or " { $link f } } } +{ $description "Sets a quotation to be called when a continuation is resumed." } +{ $notes "The single-stepper uses this hook to support single-stepping through code which makes use of continuations." } ; + +HELP: walker-hook +{ $values { "quot" "a quotation with stack effect " { $snippet "( obj -- )" } ", or " { $link f } } } +{ $description "Outputs a quotation to be called when a continuation is resumed, or " { $link f } " if no hook is set. If a hook was set prior to this word being called, it will be reset to " { $link f } "." +$nl +"The following words do not perform their usual action and instead just call the walker hook if one is set:" + { $list + { { $link callcc0 } " will call the hook, passing it the continuation to resume." } + { { $link callcc1 } " will call the hook, passing it a " { $snippet "{ obj continuation }" } " pair." } + { { $link stop } " will call the hook, passing it " { $link f } "." } + } +"The walker hook must take appropriate action so that the callers of these words see the behavior that they expect." } +{ $notes "The single-stepper uses this hook to support single-stepping through code which makes use of continuations." } ; + +HELP: (continue) +{ $values { "continuation" continuation } } +{ $description "Resumes a continuation reified by " { $link callcc0 } " without invoking " { $link walker-hook } "." } ; + +HELP: (continue-with) +{ $values { "obj" "an object to pass to the continuation's execution context" } { "continuation" continuation } } +{ $description "Resumes a continuation reified by " { $link callcc1 } " without invoking " { $link walker-hook } ". The object will be placed on the data stack when the continuation resumes." } ; + +HELP: continue +{ $values { "continuation" continuation } } +{ $description "Resumes a continuation reified by " { $link callcc0 } "." } ; + +HELP: continue-with +{ $values { "obj" "an object to pass to the continuation's execution context" } { "continuation" continuation } } +{ $description "Resumes a continuation reified by " { $link callcc1 } ". The object will be placed on the data stack when the continuation resumes." } ; + +HELP: error +{ $description "Global variable holding most recently thrown error." } +{ $notes "Only updated by " { $link throw } ", not " { $link rethrow } "." } ; + +HELP: error-continuation +{ $description "Global variable holding current continuation of most recently thrown error." } +{ $notes "Only updated by " { $link throw } ", not " { $link rethrow } "." } ; + +HELP: restarts +{ $var-description "Global variable holding the set of possible restarts for the most recently thrown error." } +{ $notes "Only updated by " { $link throw } ", not " { $link rethrow } "." } ; + +HELP: >c +{ $values { "continuation" continuation } } +{ $description "Pushes an exception handler continuation on the catch stack. The continuation must have been reified by " { $link callcc1 } "." } ; + +HELP: c> +{ $values { "continuation" continuation } } +{ $description "Pops an exception handler continuation from the catch stack." } ; + +HELP: throw +{ $values { "error" object } } +{ $description "Saves the current continuation in the " { $link error-continuation } " global variable and throws an error. Execution does not continue at the point after the " { $link throw } " call. Rather, the innermost catch block is invoked, and execution continues at that point." } ; + +HELP: catch +{ $values { "try" quotation } { "error/f" object } } +{ $description "Calls the " { $snippet "try" } " quotation. If an error is thrown in the dynamic extent of the quotation, restores the data stack and pushes the error. If the quotation returns successfully, outputs " { $link f } " without restoring the data stack." } +{ $notes "This word cannot differentiate between the case of " { $link f } " being thrown, and no error being thrown. You should never throw " { $link f } ", and you should also use other error handling combinators where possible." } ; + +{ catch cleanup recover } related-words + +HELP: cleanup +{ $values { "try" quotation } { "cleanup-always" quotation } { "cleanup-error" quotation } } +{ $description "Calls the " { $snippet "try" } " quotation. If no error is thrown, calls " { $snippet "cleanup-always" } " without restoring the data stack. If an error is thrown, restores the data stack, calls " { $snippet "cleanup-always" } " followed by " { $snippet "cleanup-error" } ", and rethrows the error." } ; + +HELP: recover +{ $values { "try" quotation } { "recovery" "a quotation with stack effect " { $snippet "( error -- )" } } } +{ $description "Calls the " { $snippet "try" } " quotation. If an exception is thrown in the dynamic extent of the " { $snippet "try" } " quotation, restores the data stack and calls the " { $snippet "recovery" } " quotation to handle the error." } ; + +HELP: rethrow +{ $values { "error" object } } +{ $description "Throws an error without saving the current continuation in the " { $link error-continuation } " global variable. This is done so that inspecting the error stacks sheds light on the original cause of the exception, rather than the point where it was rethrown." } +{ $notes + "This word is intended to be used in conjunction with " { $link recover } " or " { $link catch } " to implement error handlers which perform an action and pass the error to the next outermost error handler." +} +{ $examples + "The " { $link with-parser } " catches errors, annotates them with file name and line number information, and rethrows them:" + { $see with-parser } +} ; + +HELP: throw-restarts +{ $values { "error" object } { "restarts" "a sequence of " { $snippet "{ string object }" } " pairs" } { "restart" object } } +{ $description "Throws a restartable error using " { $link throw } ". The " { $snippet "restarts" } " parameter is a sequence of pairs where the first element in each pair is a human-readable description and the second is an arbitrary object. If the error reaches the top-level error handler, the user will be presented with the list of possible restarts, and upon invoking one, execution will continue after the call to " { $link condition } " with the object associated to the chosen restart on the stack." } +{ $examples + "Try invoking one of the two restarts which are offered after the below code throws an error:" + { $code + ": restart-test" + " \"Oops!\" { { \"One\" 1 } { \"Two\" 2 } } condition" + " \"You restarted: \" write . ;" + "restart-test" + } +} ; + +HELP: rethrow-restarts +{ $values { "error" object } { "restarts" "a sequence of " { $snippet "{ string object }" } " pairs" } { "restart" object } } +{ $description "Throws a restartable error using " { $link rethrow } ". Otherwise, this word is identical to " { $link throw-restarts } "." } ; + +{ throw rethrow throw-restarts rethrow-restarts } related-words + +HELP: compute-restarts +{ $values { "error" object } { "seq" "a sequence" } } +{ $description "Outputs a sequence of triples, where each triple consists of a human-readable string, an object, and a continuation. Resuming a continuation with the corresponding object restarts execution immediately after the corresponding call to " { $link condition } "." +$nl +"This word recursively travels up the delegation chain to collate restarts from nested and wrapped conditions." } ; + +HELP: save-error +{ $values { "error" "an error" } } +{ $description "Called by the error handler to set the " { $link error } " and " { $link restarts } " global variables after an error was thrown." } +$low-level-note ; + +HELP: init-error-handler +{ $description "Called on startup to initialize the catch stack and set a pair of hooks which allow the Factor VM to signal errors to library code." } ; diff --git a/core/continuations/continuations-tests.factor b/core/continuations/continuations-tests.factor new file mode 100644 index 0000000000..602efe9d94 --- /dev/null +++ b/core/continuations/continuations-tests.factor @@ -0,0 +1,70 @@ +USING: kernel math namespaces io tools.test sequences vectors +continuations debugger parser memory arrays ; +IN: temporary + +! [ "hello" ] [ +! [ +! callstack [ set-callstack ] curry [ ] like -1 2array +! array>callstack set-callstack +! ] call "hello" +! ] unit-test + +: (callcc1-test) + swap 1- tuck swap ?push + over 0 = [ "test-cc" get continue-with ] when + (callcc1-test) ; + +: callcc1-test ( x -- list ) + [ + "test-cc" set V{ } clone (callcc1-test) + ] callcc1 nip ; + +: callcc-namespace-test ( -- ? ) + [ + "test-cc" set + 5 "x" set + [ + 6 "x" set "test-cc" get continue + ] with-scope + ] callcc0 "x" get 5 = ; + +[ t ] [ 10 callcc1-test 10 reverse >vector = ] unit-test +[ t ] [ callcc-namespace-test ] unit-test + +[ f ] [ [ ] catch ] unit-test + +[ 5 ] [ [ 5 throw ] catch ] unit-test + +[ t ] [ + [ "Hello" throw ] catch drop + global [ error get ] bind + "Hello" = +] unit-test + +"!!! The following error is part of the test" print + +[ ] [ [ 6 [ 12 [ "2 car" ] ] ] print-error ] unit-test + +"!!! The following error is part of the test" print + +[ [ "2 car" ] parse ] catch print-error + +[ f throw ] unit-test-fails + +! Weird PowerPC bug. +[ ] [ + [ "4" throw ] catch drop + data-gc + data-gc +] unit-test + +[ f ] [ { } kernel-error? ] unit-test +[ f ] [ { "A" "B" } kernel-error? ] unit-test + +! ! See how well callstack overflow is handled +! [ clear drop ] unit-test-fails +! +! : callstack-overflow callstack-overflow f ; +! [ callstack-overflow ] unit-test-fails +! +! diff --git a/core/continuations/continuations.factor b/core/continuations/continuations.factor new file mode 100644 index 0000000000..063b9e7419 --- /dev/null +++ b/core/continuations/continuations.factor @@ -0,0 +1,176 @@ +! Copyright (C) 2003, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays vectors kernel kernel.private sequences +namespaces tuples math splitting sorting quotations assocs ; +IN: continuations + +SYMBOL: error +SYMBOL: error-continuation +SYMBOL: restarts + +c ( continuation -- ) catchstack* push ; + +: c> ( -- continuation ) catchstack* pop ; + +: (catch) ( quot -- newquot ) + [ swap >c call c> drop ] curry ; inline + +: (callcc1) 4 getenv f 4 setenv ; inline + +PRIVATE> + +: catchstack ( -- catchstack ) catchstack* clone ; inline + +: set-catchstack ( catchstack -- ) >vector 1 setenv ; inline + +TUPLE: continuation data call retain name catch ; + +C: continuation + +: continuation ( -- continuation ) + datastack callstack retainstack namestack catchstack + ; + +: >continuation< ( continuation -- data call retain name catch ) + { + continuation-data + continuation-call + continuation-retain + continuation-name + continuation-catch + } get-slots ; + +: ifcc0 ( capture restore -- ) + #! After continuation is being captured, the stacks looks + #! like: + #! ( continuation r:capture r:restore ) + #! so the 'capture' branch is taken. + #! + #! Note that the continuation itself is not captured as part + #! of the datastack. + #! + #! BUT... + #! + #! After the continuation is resumed, (continue) pushes f, + #! so now, the stacks looks like: + #! ( f r:capture r:restore ) + #! Execution begins right after the call to 'continuation'. + #! The 'restore' branch is taken. + >r >r continuation r> r> if* ; inline + +: ifcc1 ( capture restore -- ) + [ (callcc1) ] swap compose ifcc0 ; inline + +: callcc0 ( quot -- ) [ ] ifcc0 ; inline + +: callcc1 ( quot -- obj ) [ ] ifcc1 ; inline + +: set-walker-hook ( quot -- ) 3 setenv ; inline + +: walker-hook ( -- quot ) 3 getenv f set-walker-hook ; inline + +continuation< + set-catchstack + set-namestack + set-retainstack + >r set-datastack f r> + set-callstack ; + +: (continue-with) ( obj continuation -- ) + swap 4 setenv (continue) ; + +PRIVATE> + +: continue ( continuation -- ) + [ + walker-hook [ (continue-with) ] [ (continue) ] if* + ] curry (throw) ; + +: continue-with ( obj continuation -- ) + [ + walker-hook [ >r 2array r> ] when* (continue-with) + ] 2curry (throw) ; + +GENERIC: compute-restarts ( error -- seq ) + + + +: rethrow ( error -- * ) + catchstack* empty? [ die ] when + dup save-error c> continue-with ; + +: catch ( try -- error/f ) + (catch) [ f ] compose callcc1 ; inline + +: recover ( try recovery -- ) + >r (catch) r> ifcc1 ; inline + +: cleanup ( try cleanup-always cleanup-error -- ) + >r [ compose (catch) ] keep r> compose + [ dip rethrow ] curry ifcc1 ; inline + +: attempt-all ( seq quot -- obj ) + [ + [ [ , f ] compose [ , drop t ] recover ] curry all? + ] { } make peek swap [ rethrow ] when ; inline + +TUPLE: condition restarts continuation ; + +: ( error restarts cc -- condition ) + { + set-delegate + set-condition-restarts + set-condition-continuation + } condition construct ; + +: throw-restarts ( error restarts -- restart ) + [ throw ] callcc1 2nip ; + +: rethrow-restarts ( error restarts -- restart ) + [ rethrow ] callcc1 2nip ; + +TUPLE: restart name obj continuation ; + +C: restart + +: restart ( restart -- ) + dup restart-obj swap restart-continuation continue-with ; + +M: object compute-restarts drop { } ; + +M: tuple compute-restarts delegate compute-restarts ; + +M: condition compute-restarts + [ delegate compute-restarts ] keep + [ condition-restarts ] keep + condition-continuation + [ ] curry { } assoc>map + append ; + + diff --git a/core/continuations/summary.txt b/core/continuations/summary.txt new file mode 100644 index 0000000000..f8980d7cd8 --- /dev/null +++ b/core/continuations/summary.txt @@ -0,0 +1 @@ +Capturing and restorating continuations, catching errors diff --git a/core/continuations/tags.txt b/core/continuations/tags.txt new file mode 100644 index 0000000000..abf53a421b --- /dev/null +++ b/core/continuations/tags.txt @@ -0,0 +1 @@ +reflection diff --git a/core/cpu/architecture/architecture.factor b/core/cpu/architecture/architecture.factor new file mode 100644 index 0000000000..e501d548b3 --- /dev/null +++ b/core/cpu/architecture/architecture.factor @@ -0,0 +1,208 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generic kernel kernel.private math memory +namespaces sequences layouts system hashtables classes alien +byte-arrays bit-arrays float-arrays combinators words ; +IN: cpu.architecture + +SYMBOL: compiler-backend + +! A pseudo-register class for parameters spilled on the stack +TUPLE: stack-params ; + +! Return values of this class go here +GENERIC: return-reg ( register-class -- reg ) + +! Sequence of registers used for parameter passing in class +GENERIC: param-regs ( register-class -- regs ) + +GENERIC: param-reg ( n register-class -- reg ) + +M: object param-reg param-regs nth ; + +! Sequence mapping vreg-n to native assembler registers +GENERIC: vregs ( register-class -- regs ) + +! Load a literal (immediate or indirect) +GENERIC# load-literal 1 ( obj vreg -- ) + +HOOK: load-indirect compiler-backend ( obj reg -- ) + +HOOK: stack-frame compiler-backend ( frame-size -- n ) + +: stack-frame* ( -- n ) + \ stack-frame get stack-frame ; + +! Set up caller stack frame +HOOK: %prologue compiler-backend ( n -- ) + +: %prologue-later \ %prologue-later , ; + +! Tear down stack frame +HOOK: %epilogue compiler-backend ( n -- ) + +: %epilogue-later \ %epilogue-later , ; + +! Bump profiling counter +HOOK: %profiler-prologue compiler-backend ( word -- ) + +! Store word XT in stack frame +HOOK: %save-xt compiler-backend ( -- ) + +! Call another label +HOOK: %call-label compiler-backend ( label -- ) + +! Call C primitive +HOOK: %call-primitive compiler-backend ( label -- ) + +! Local jump for branches +HOOK: %jump-label compiler-backend ( label -- ) + +! Far jump to C primitive +HOOK: %jump-primitive compiler-backend ( label -- ) + +! Test if vreg is 'f' or not +HOOK: %jump-t compiler-backend ( label -- ) + +! We pass the offset of the jump table start in the world table +HOOK: %call-dispatch compiler-backend ( word-table# -- ) + +HOOK: %jump-dispatch compiler-backend ( word-table# -- ) + +! Return to caller +HOOK: %return compiler-backend ( -- ) + +! Change datastack height +HOOK: %inc-d compiler-backend ( n -- ) + +! Change callstack height +HOOK: %inc-r compiler-backend ( n -- ) + +! Load stack into vreg +GENERIC: (%peek) ( vreg loc reg-class -- ) +: %peek ( vreg loc -- ) over (%peek) ; + +! Store vreg to stack +GENERIC: (%replace) ( vreg loc reg-class -- ) +: %replace ( vreg loc -- ) over (%replace) ; + +! Move one vreg to another +HOOK: %move-int>int compiler-backend ( dst src -- ) +HOOK: %move-int>float compiler-backend ( dst src -- ) +HOOK: %move-float>int compiler-backend ( dst src -- ) + +! FFI stuff + +! Is this integer small enough to appear in value template +! slots? +HOOK: small-enough? compiler-backend ( n -- ? ) + +! Is this structure small enough to be returned in registers? +HOOK: struct-small-enough? compiler-backend ( size -- ? ) + +! Do we pass explode value structs? +HOOK: value-structs? compiler-backend ( -- ? ) + +! If t, fp parameters are shadowed by dummy int parameters +HOOK: fp-shadows-int? compiler-backend ( -- ? ) + +HOOK: %prepare-unbox compiler-backend ( -- ) + +HOOK: %unbox compiler-backend ( n reg-class func -- ) + +HOOK: %unbox-long-long compiler-backend ( n func -- ) + +HOOK: %unbox-small-struct compiler-backend ( size -- ) + +HOOK: %unbox-large-struct compiler-backend ( n size -- ) + +HOOK: %box compiler-backend ( n reg-class func -- ) + +HOOK: %box-long-long compiler-backend ( n func -- ) + +HOOK: %prepare-box-struct compiler-backend ( size -- ) + +HOOK: %box-small-struct compiler-backend ( size -- ) + +HOOK: %box-large-struct compiler-backend ( n size -- ) + +GENERIC: %save-param-reg ( stack reg reg-class -- ) + +GENERIC: %load-param-reg ( stack reg reg-class -- ) + +HOOK: %prepare-alien-invoke compiler-backend ( -- ) + +HOOK: %alien-invoke compiler-backend ( library function -- ) + +HOOK: %cleanup compiler-backend ( alien-node -- ) + +HOOK: %alien-callback compiler-backend ( quot -- ) + +HOOK: %callback-value compiler-backend ( ctype -- ) + +! Return to caller with stdcall unwinding (only for x86) +HOOK: %unwind compiler-backend ( n -- ) + +HOOK: %prepare-alien-indirect compiler-backend ( -- ) + +HOOK: %alien-indirect compiler-backend ( -- ) + +M: stack-params param-reg drop ; + +GENERIC: v>operand ( obj -- operand ) + +M: integer v>operand tag-bits get shift ; + +M: f v>operand drop \ f tag-number ; + +M: object load-literal v>operand load-indirect ; + +PREDICATE: integer small-slot cells small-enough? ; + +PREDICATE: integer small-tagged v>operand small-enough? ; + +PREDICATE: integer inline-array 32 < ; + +: if-small-struct ( n size true false -- ? ) + >r >r over not over struct-small-enough? and + [ nip r> call r> drop ] [ r> drop r> call ] if ; + inline + +: %unbox-struct ( n size -- ) + [ + %unbox-small-struct + ] [ + %unbox-large-struct + ] if-small-struct ; + +: %box-struct ( n size -- ) + [ + %box-small-struct + ] [ + %box-large-struct + ] if-small-struct ; + +! Alien accessors +HOOK: %unbox-byte-array compiler-backend ( quot src -- ) inline + +HOOK: %unbox-alien compiler-backend ( quot src -- ) inline + +HOOK: %unbox-f compiler-backend ( quot src -- ) inline + +HOOK: %complex-alien-accessor compiler-backend ( quot src -- ) +inline + +: %alien-accessor ( quot src class -- ) + { + { [ dup \ f class< ] [ drop %unbox-f ] } + { [ dup simple-alien class< ] [ drop %unbox-alien ] } + { [ dup byte-array class< ] [ drop %unbox-byte-array ] } + { [ dup bit-array class< ] [ drop %unbox-byte-array ] } + { [ dup float-array class< ] [ drop %unbox-byte-array ] } + { [ t ] [ drop %complex-alien-accessor ] } + } cond ; inline + +: operand ( var -- op ) get v>operand ; inline + +: unique-operands ( operands quot -- ) + >r [ operand ] map prune r> each ; inline diff --git a/core/cpu/architecture/authors.txt b/core/cpu/architecture/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/architecture/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/architecture/summary.txt b/core/cpu/architecture/summary.txt new file mode 100644 index 0000000000..80524d8bfc --- /dev/null +++ b/core/cpu/architecture/summary.txt @@ -0,0 +1 @@ +Compiler's abstract CPU architecture description model diff --git a/core/cpu/arm/allot/allot.factor b/core/cpu/arm/allot/allot.factor new file mode 100644 index 0000000000..ce07e1ea5a --- /dev/null +++ b/core/cpu/arm/allot/allot.factor @@ -0,0 +1,84 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel cpu.architecture cpu.arm.assembler +cpu.arm.architecture namespaces math math.functions sequences +generator generator.registers generator.fixup system layouts +alien ; +IN: cpu.arm.allot + +: load-zone-ptr ( reg -- ) "nursery" f rot %alien-global ; + +: object@ "allot-tmp" operand swap cells <+> ; + +: %allot ( header size -- ) + #! Store a pointer to 'size' bytes allocated from the + #! nursery in allot-tmp. + 8 align ! align the size + R12 load-zone-ptr ! nusery -> r12 + "allot-tmp" operand R12 cell <+> LDR ! nursery.here -> allot-tmp + "allot-tmp" operand dup pick ADD ! increment allot-tmp + "allot-tmp" operand R12 cell <+> STR ! allot-tmp -> nursery.here + "allot-tmp" operand dup rot SUB ! old value + R12 swap type-number tag-header MOV ! compute header + R12 0 object@ STR ! store header + ; + +: %tag-allot ( tag -- ) + "allot-tmp" operand dup rot tag-number ORR + "allot-tmp" get fresh-object ; + +: %allot-bignum ( #digits -- ) + #! 1 cell header, 1 cell length, 1 cell sign, + digits + #! length is the # of digits + sign + bignum over 3 + cells %allot + R12 swap 1+ v>operand MOV ! compute the length + R12 1 object@ STR ! store the length + ; + +: %allot-bignum-signed-1 ( reg -- ) + #! on entry, reg is a 30-bit quantity sign-extended to + #! 32-bits. + #! exits with tagged ptr to bignum in allot-tmp. + [ + "end" define-label + ! is it zero? + dup v>operand 0 CMP + 0 >bignum "allot-tmp" operand EQ load-indirect + "end" get EQ B + ! ! it is non-zero + 1 %allot-bignum + ! is the fixnum negative? + dup v>operand 0 CMP + ! negative sign + R12 1 LT MOV + ! negate fixnum + dup v>operand dup 0 LT RSB + ! positive sign + R12 0 GE MOV + ! store sign + R12 2 object@ STR + ! store the number + v>operand 3 object@ STR + ! tag the bignum, store it in reg + bignum %tag-allot + "end" resolve-label + ] with-scope ; + +: %allot-alien ( ptr -- ) + #! Tagged pointer to alien is in allot-tmp on exit. + [ + "temp" set + "end" define-label + "temp" operand 0 CMP + "allot-tmp" operand f v>operand EQ MOV + "end" get EQ B + alien 4 cells %allot + "temp" operand 2 object@ STR + "temp" operand f v>operand MOV + "temp" operand 1 object@ STR + "temp" operand 0 MOV + "temp" operand 3 object@ STR + ! Store tagged ptr in reg + object %tag-allot + "end" resolve-label + ] with-scope ; diff --git a/core/cpu/arm/architecture/architecture.factor b/core/cpu/arm/architecture/architecture.factor new file mode 100644 index 0000000000..5a4a2bda3f --- /dev/null +++ b/core/cpu/arm/architecture/architecture.factor @@ -0,0 +1,327 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien alien.c-types arrays cpu.arm.assembler compiler +kernel kernel.private math math.functions namespaces words +words.private generator.registers generator.fixup generator +cpu.architecture system layouts ; +IN: cpu.arm.architecture + +TUPLE: arm-backend ; + +! ARM register assignments: +! R0, R1, R2, R3 integer vregs +! R12 temporary +! R5 data stack +! R6 retain stack +! R7 primitives + +: ds-reg R5 ; inline +: rs-reg R6 ; inline + +M: temp-reg v>operand drop R12 ; + +M: int-regs return-reg drop R0 ; +M: int-regs param-regs drop { R0 R1 R2 R3 } ; +M: int-regs vregs drop { R0 R1 R2 R3 } ; + +! No FPU support yet +M: float-regs param-regs drop { } ; +M: float-regs vregs drop { } ; + +: <+/-> dup 0 < [ neg <-> ] [ <+> ] if ; + +GENERIC: loc>operand ( loc -- reg addressing ) +M: ds-loc loc>operand ds-loc-n cells neg ds-reg swap <+/-> ; +M: rs-loc loc>operand rs-loc-n cells neg rs-reg swap <+/-> ; + +M: arm-backend load-indirect ( obj reg -- ) + PC 0 <+> LDR rc-indirect-arm-pc rel-literal ; + +M: immediate load-literal + over v>operand small-enough? [ + [ v>operand ] 2apply swap MOV + ] [ + v>operand load-indirect + ] if ; + +M: arm-backend stack-frame ( n -- i ) 4 + 8 align ; + +M: arm-backend %prologue ( n -- ) + LR SP 4 <-> STR + SP SP rot stack-frame SUB ; + +M: arm-backend %epilogue ( n -- ) + SP SP rot stack-frame ADD + LR SP 4 <-> LDR ; + +: compile-dlsym ( symbol dll reg -- ) + [ + "end" define-label + ! Load target address + PC 0 <+> LDR + ! Skip an instruction + "end" get B + ! The target address + 0 , rc-absolute rel-dlsym + ! Continue here + "end" resolve-label + ] with-scope ; + +: %alien-global ( symbol dll reg -- ) + [ compile-dlsym ] keep dup 0 <+> LDR ; + +M: arm-backend %profiler-prologue ( word -- ) + #! We can clobber R0 here since it is undefined at the start + #! of a word. + "end" define-label + "profiling" f R12 %alien-global + R12 0 CMP + "end" get EQ B + R12 load-indirect + R0 R12 profile-count-offset <+> LDR + R0 R0 1 v>operand ADD + R0 R12 profile-count-offset <+> STR + "end" resolve-label ; + +: primitive-addr ( word dst -- ) + #! Load a word address into dst. + R7 rot word-primitive cells <+> LDR ; + +M: arm-backend %call ( label -- ) + #! Far C call for primitives, near C call for compiled defs. + dup primitive? [ R0 primitive-addr R0 BLX ] [ BL ] if ; + +M: arm-backend %jump-label ( label -- ) + #! For tail calls. IP not saved on C stack. + #! WARNING: don't clobber LR here! + dup primitive? [ PC primitive-addr ] [ B ] if ; + +M: arm-backend %jump-t ( label -- ) + "flag" operand object tag-number CMP NE B ; + +: (%dispatch) ( word-table# reg -- ) + #! Load jump table target address into reg. + "n" operand PC "n" operand 1 ADD + "n" operand 0 <+> LDR + rc-indirect-arm rel-dispatch ; + +M: arm-backend %call-dispatch ( word-table# -- ) + [ + "scratch" operand (%dispatch) + "scratch" operand BLX + ] H{ + { +input+ { { f "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "n" } } + } with-template ; + +M: arm-backend %jump-dispatch ( word-table# -- ) + [ + %epilogue-later + PC (%dispatch) + ] H{ + { +input+ { { f "n" } } } + { +clobber+ { "n" } } + } with-template ; + +M: arm-backend %return ( -- ) %epilogue-later PC LR MOV ; + +M: arm-backend %unwind drop %return ; + +: (%peek/replace) + >r drop >r v>operand r> loc>operand r> execute ; + +M: int-regs (%peek) \ LDR (%peek/replace) ; +M: int-regs (%replace) \ STR (%peek/replace) ; + +M: arm-backend %move-int>int ( dst src -- ) + [ v>operand ] 2apply MOV ; + +: (%inc) ( n reg -- ) + dup rot cells dup 0 < [ neg SUB ] [ ADD ] if ; + +M: arm-backend %inc-d ( n -- ) ds-reg (%inc) ; + +M: arm-backend %inc-r ( n -- ) rs-reg (%inc) ; + +: stack@ SP swap <+> ; + +M: int-regs %save-param-reg drop swap stack@ STR ; + +M: int-regs %load-param-reg drop swap stack@ LDR ; + +M: stack-params %save-param-reg + drop + R12 swap stack-frame* + stack@ LDR + R12 swap stack@ STR ; + +M: stack-params %load-param-reg + drop + R12 rot stack@ LDR + R12 swap stack@ STR ; + +M: arm-backend %prepare-unbox ( -- ) + ! First parameter is top of stack + R0 R5 4 <-!> LDR ; + +M: arm-backend %unbox ( n reg-class func -- ) + ! Value must be in R0. + ! Call the unboxer + f %alien-invoke + ! Store the return value on the C stack + over [ [ return-reg ] keep %save-param-reg ] [ 2drop ] if ; + +M: arm-backend %unbox-long-long ( n func -- ) + ! Value must be in R0:R1. + ! Call the unboxer + f %alien-invoke + ! Store the return value on the C stack + [ + R0 over stack@ STR + R1 swap cell + stack@ STR + ] when* ; + +M: arm-backend %unbox-small-struct ( size -- ) + #! Alien must be in R0. + drop + "alien_offset" f %alien-invoke + ! Load first cell + R0 R0 0 <+> LDR ; + +M: arm-backend %unbox-large-struct ( n size -- ) + #! Alien must be in R0. + ! Compute destination address + R1 SP roll ADD + R2 swap MOV + ! Copy the struct to the stack + "to_value_struct" f %alien-invoke ; + +M: arm-backend %box ( n reg-class func -- ) + ! If the source is a stack location, load it into freg #0. + ! If the source is f, then we assume the value is already in + ! freg #0. + >r + over [ 0 over param-reg swap %load-param-reg ] [ 2drop ] if + r> f %alien-invoke ; + +M: arm-backend %box-long-long ( n func -- ) + >r [ + R0 over stack@ LDR + R1 swap cell + stack@ LDR + ] when* r> f %alien-invoke ; + +M: arm-backend %box-small-struct ( size -- ) + #! Box a 4-byte struct returned in R0. + R2 swap MOV + "box_small_struct" f %alien-invoke ; + +: struct-return@ ( size n -- n ) + [ + stack-frame* + + ] [ + stack-frame* swap - cell - + ] ?if ; + +M: arm-backend %prepare-box-struct ( size -- ) + ! Compute target address for value struct return + R0 SP rot f struct-return@ ADD + ! Store it as the first parameter + R0 0 stack@ STR ; + +M: arm-backend %box-large-struct ( n size -- ) + ! Compute destination address + [ swap struct-return@ ] keep + R0 SP roll ADD + R1 swap MOV + ! Copy the struct from the C stack + "box_value_struct" f %alien-invoke ; + +M: arm-backend struct-small-enough? ( size -- ? ) + wince? [ drop f ] [ 4 <= ] if ; + +M: arm-backend %alien-invoke ( symbol dll -- ) + ! Load target address + R12 PC 4 <+> LDR + ! Store address of next instruction in LR + LR PC 4 ADD + ! Jump to target address + R12 BX + ! The target address + 0 , rc-absolute rel-dlsym ; + +: temp@ SP stack-frame* 2 cells - <+> ; + +M: arm-backend %prepare-alien-indirect ( -- ) + "unbox_alien" f %alien-invoke + R0 temp@ STR ; + +M: arm-backend %alien-indirect ( -- ) + IP temp@ LDR + IP BLX ; + +M: arm-backend %alien-callback ( quot -- ) + R0 load-indirect + "run_callback" f %alien-invoke ; + +M: arm-backend %callback-value ( ctype -- ) + ! Save top of data stack + %prepare-unbox + R0 temp@ STR + ! Restore data/call/retain stacks + "unnest_stacks" f %alien-invoke + ! Place former top of data stack in R0 + R0 temp@ LDR + ! Unbox R0 + unbox-return ; + +M: arm-backend %cleanup ( alien-node -- ) drop ; + +: %untag ( dest src -- ) BIN: 111 BIC ; + +: %untag-fixnum ( dest src -- ) tag-bits get MOV ; + +: %tag-fixnum ( dest src -- ) tag-bits get MOV ; + +M: arm-backend value-structs? t ; + +M: arm-backend small-enough? ( n -- ? ) 0 255 between? ; + +M: long-long-type c-type-stack-align? drop wince? not ; + +M: arm-backend fp-shadows-int? ( -- ? ) f ; + +! Alien intrinsics +: add-alien-offset "offset" operand tag-bits get ADD ; + +: (%unbox-alien) <+> roll call ; inline + +M: arm-backend %unbox-byte-array ( quot src -- ) + "address" operand "alien" operand add-alien-offset + "address" operand alien-offset (%unbox-alien) ; + +M: arm-backend %unbox-alien ( quot src -- ) + "address" operand "alien" operand alien-offset <+> LDR + "address" operand dup add-alien-offset + "address" operand 0 (%unbox-alien) ; + +M: arm-backend %unbox-f ( quot src -- ) + "offset" operand dup %untag-fixnum + "offset" operand 0 (%unbox-alien) ; + +M: arm-backend %complex-alien-accessor ( quot src -- ) + "is-f" define-label + "is-alien" define-label + "end" define-label + "alien" operand f v>operand CMP + "is-f" get EQ B + "address" operand "alien" operand header-offset neg <-> LDR + "address" operand alien type-number tag-header CMP + "is-alien" get EQ B + [ %unbox-byte-array ] 2keep + "end" get B + "is-alien" resolve-label + [ %unbox-alien ] 2keep + "end" get B + "is-f" resolve-label + %unbox-f + "end" resolve-label ; diff --git a/core/cpu/arm/arm.factor b/core/cpu/arm/arm.factor new file mode 100644 index 0000000000..111044a552 --- /dev/null +++ b/core/cpu/arm/arm.factor @@ -0,0 +1,50 @@ +USING: alien alien.c-types kernel math namespaces +cpu.architecture cpu.arm.architecture cpu.arm.intrinsics +generator generator.registers continuations compiler io +vocabs.loader ; + +! EABI passes floats in integer registers. +[ alien-float ] +[ >r >r >float r> r> set-alien-float ] +4 +"box_float" +"to_float" +"float" define-primitive-type + +[ >float ] "float" c-type set-c-type-prep + +[ alien-double ] +[ >r >r >float r> r> set-alien-double ] +8 +"box_double" +"to_double" +"double" define-primitive-type + +[ >float ] "double" c-type set-c-type-prep + +T{ arm-backend } compiler-backend set-global + +: (detect-arm5) ; + +\ (detect-arm5) [ + ! The LDRH word is defined in the module we conditionally + ! load below... + ! R0 PC 0 <+> LDRH + HEX: e1df00b0 , +] H{ + { +scratch+ { { 0 "scratch" } } } +} define-intrinsic + +: detect-arm5 (detect-arm5) ; + +: arm5? ( -- ? ) [ detect-arm5 ] catch not ; + +"arm-variant" get [ + \ detect-arm5 compile + "Detecting ARM architecture variant..." print + arm5? "arm5" "arm3" ? "arm-variant" set +] unless + +"ARM architecture variant: " write "arm-variant" get print + +"arm-variant" "arm5" = [ "cpu.arm5" require ] when diff --git a/core/cpu/arm/assembler/assembler-tests.factor b/core/cpu/arm/assembler/assembler-tests.factor new file mode 100644 index 0000000000..219015fae9 --- /dev/null +++ b/core/cpu/arm/assembler/assembler-tests.factor @@ -0,0 +1,45 @@ +IN: temporary +USING: assembler-arm math test namespaces sequences kernel +quotations ; + +: test-opcode [ { } make first ] curry unit-test ; + +[ HEX: ea000000 ] [ 0 B ] test-opcode +[ HEX: eb000000 ] [ 0 BL ] test-opcode +! [ HEX: e12fff30 ] [ R0 BLX ] test-opcode + +[ HEX: e24cc004 ] [ IP IP 4 SUB ] test-opcode +[ HEX: e24cb004 ] [ FP IP 4 SUB ] test-opcode +[ HEX: e087e3ac ] [ LR R7 IP 7 ADD ] test-opcode +[ HEX: e08c0109 ] [ R0 IP R9 2 ADD ] test-opcode +[ HEX: 02850004 ] [ R0 R5 4 EQ ADD ] test-opcode +[ HEX: 00000000 ] [ R0 R0 R0 EQ AND ] test-opcode + +[ HEX: e1a0c00c ] [ IP IP MOV ] test-opcode +[ HEX: e1a0c00d ] [ IP SP MOV ] test-opcode +[ HEX: e3a03003 ] [ R3 3 MOV ] test-opcode +[ HEX: e1a00003 ] [ R0 R3 MOV ] test-opcode +[ HEX: e1e01c80 ] [ R1 R0 25 MVN ] test-opcode +[ HEX: e1e00ca1 ] [ R0 R1 25 MVN ] test-opcode +[ HEX: 11a021ac ] [ R2 IP 3 NE MOV ] test-opcode + +[ HEX: e3530007 ] [ R3 7 CMP ] test-opcode + +[ HEX: e008049a ] [ R8 SL R4 MUL ] test-opcode + +[ HEX: e5151004 ] [ R1 R5 4 <-> LDR ] test-opcode +[ HEX: e41c2004 ] [ R2 IP 4 <-!> LDR ] test-opcode +[ HEX: e50e2004 ] [ R2 LR 4 <-> STR ] test-opcode + +[ HEX: e7910002 ] [ R0 R1 R2 <+> LDR ] test-opcode +[ HEX: e7910102 ] [ R0 R1 R2 2 <+> LDR ] test-opcode + +[ HEX: e1d310bc ] [ R1 R3 12 <+> LDRH ] test-opcode +[ HEX: e1d310fc ] [ R1 R3 12 <+> LDRSH ] test-opcode +[ HEX: e1d310dc ] [ R1 R3 12 <+> LDRSB ] test-opcode +[ HEX: e1c310bc ] [ R1 R3 12 <+> STRH ] test-opcode +[ HEX: e19310b4 ] [ R1 R3 R4 <+> LDRH ] test-opcode +[ HEX: e1f310fc ] [ R1 R3 12 LDRSH ] test-opcode +[ HEX: e1b310d4 ] [ R1 R3 R4 LDRSB ] test-opcode +[ HEX: e0c317bb ] [ R1 R3 123 <+!> STRH ] test-opcode +[ HEX: e08310b4 ] [ R1 R3 R4 <+!> STRH ] test-opcode diff --git a/core/cpu/arm/assembler/assembler.factor b/core/cpu/arm/assembler/assembler.factor new file mode 100644 index 0000000000..0152380547 --- /dev/null +++ b/core/cpu/arm/assembler/assembler.factor @@ -0,0 +1,270 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generator generator.fixup kernel sequences words +namespaces math math.bitfields ; +IN: cpu.arm.assembler + +SYMBOL: arm-variant + +: define-registers ( seq -- ) + dup length [ "register" set-word-prop ] 2each ; + +SYMBOL: R0 +SYMBOL: R1 +SYMBOL: R2 +SYMBOL: R3 +SYMBOL: R4 +SYMBOL: R5 +SYMBOL: R6 +SYMBOL: R7 +SYMBOL: R8 +SYMBOL: R9 +SYMBOL: R10 +SYMBOL: R11 +SYMBOL: R12 +SYMBOL: R13 +SYMBOL: R14 +SYMBOL: R15 + +{ R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 } +define-registers + +PREDICATE: word register register >boolean ; + +GENERIC: register ( register -- n ) +M: word register "register" word-prop ; +M: f register drop 0 ; + +: SL R10 ; inline : FP R11 ; inline : IP R12 ; inline +: SP R13 ; inline : LR R14 ; inline : PC R15 ; inline + +! Condition codes +SYMBOL: cond-code + +: >CC ( n -- ) + cond-code set ; + +: CC> ( -- n ) + #! Default value is BIN: 1110 AL (= always) + cond-code [ f ] change BIN: 1110 or ; + +: EQ BIN: 0000 >CC ; +: NE BIN: 0001 >CC ; +: CS BIN: 0010 >CC ; +: CC BIN: 0011 >CC ; +: LO BIN: 0100 >CC ; +: PL BIN: 0101 >CC ; +: VS BIN: 0110 >CC ; +: VC BIN: 0111 >CC ; +: HI BIN: 1000 >CC ; +: LS BIN: 1001 >CC ; +: GE BIN: 1010 >CC ; +: LT BIN: 1011 >CC ; +: GT BIN: 1100 >CC ; +: LE BIN: 1101 >CC ; +: AL BIN: 1110 >CC ; +: NV BIN: 1111 >CC ; + +: (insn) ( n -- ) CC> 28 shift bitor , ; + +: insn ( bitspec -- ) bitfield (insn) ; inline + +! Branching instructions +GENERIC# (B) 1 ( signed-imm-24 l -- ) + +M: integer (B) { 24 { 1 25 } { 0 26 } { 1 27 } 0 } insn ; +M: word (B) 0 swap (B) rc-relative-arm-3 rel-word ; +M: label (B) 0 swap (B) rc-relative-arm-3 label-fixup ; + +: B 0 (B) ; : BL 1 (B) ; + +! Data processing instructions +SYMBOL: updates-cond-code + +: S ( -- ) updates-cond-code on ; + +: S> ( -- ? ) updates-cond-code [ f ] change ; + +: sinsn ( bitspec -- ) + bitfield S> [ 20 2^ bitor ] when (insn) ; inline + +GENERIC# shift-imm/reg 2 ( shift-imm/Rs Rm shift -- n ) + +M: integer shift-imm/reg ( shift-imm Rm shift -- n ) + { { 0 4 } 5 { register 0 } 7 } bitfield ; + +M: register shift-imm/reg ( Rs Rm shift -- n ) + { + { 1 4 } + { 0 7 } + 5 + { register 8 } + { register 0 } + } bitfield ; + +GENERIC: shifter-op ( shifter-op -- n ) + +TUPLE: IMM immed rotate ; +C: IMM + +M: IMM shifter-op + dup IMM-immed swap IMM-rotate + { { 1 25 } 8 0 } bitfield ; + +TUPLE: shifter Rm by shift ; +C: shifter + +M: shifter shifter-op + dup shifter-by over shifter-Rm rot shifter-shift + shift-imm/reg ; + +: ( Rm shift-imm/Rs -- shifter-op ) BIN: 00 ; +: ( Rm shift-imm/Rs -- shifter-op ) BIN: 01 ; +: ( Rm shift-imm/Rs -- shifter-op ) BIN: 10 ; +: ( Rm shift-imm/Rs -- shifter-op ) BIN: 11 ; +: ( Rm -- shifter-op ) 0 ; + +M: register shifter-op 0 shifter-op ; + +M: integer shifter-op 0 shifter-op ; + +: addr1 ( Rd Rn shifter-op opcode -- ) + { + 21 ! opcode + { shifter-op 0 } + { register 16 } ! Rn + { register 12 } ! Rd + } sinsn ; + +: AND BIN: 0000 addr1 ; +: EOR BIN: 0001 addr1 ; +: SUB BIN: 0010 addr1 ; +: RSB BIN: 0011 addr1 ; +: ADD BIN: 0100 addr1 ; +: ADC BIN: 0101 addr1 ; +: SBC BIN: 0110 addr1 ; +: RSC BIN: 0111 addr1 ; +: ORR BIN: 1100 addr1 ; +: BIC BIN: 1110 addr1 ; + +: MOV f swap BIN: 1101 addr1 ; +: MVN f swap BIN: 1111 addr1 ; + +! These always update the condition code flags +: (CMP) >r f -rot r> S addr1 ; + +: TST BIN: 1000 (CMP) ; +: TEQ BIN: 1001 (CMP) ; +: CMP BIN: 1010 (CMP) ; +: CMN BIN: 1011 (CMP) ; + +! Multiply instructions +: (MLA) ( Rd Rm Rs Rn a -- ) + { + 21 + { register 12 } + { register 8 } + { register 0 } + { register 16 } + { 1 7 } + { 1 4 } + } sinsn ; + +: MUL ( Rd Rm Rs -- ) f 0 (MLA) ; +: MLA ( Rd Rm Rs Rn -- ) 1 (MLA) ; + +: (S/UMLAL) ( RdLo RdHi Rm Rs s a -- ) + { + { 1 23 } + 22 + 21 + { register 8 } + { register 0 } + { register 16 } + { register 12 } + { 1 7 } + { 1 4 } + } sinsn ; + +: SMLAL 1 1 (S/UMLAL) ; : SMULL 1 0 (S/UMLAL) ; +: UMLAL 0 1 (S/UMLAL) ; : UMULL 0 0 (S/UMLAL) ; + +! Miscellaneous arithmetic instructions +: CLZ ( Rd Rm -- ) + { + { 1 24 } + { 1 22 } + { 1 21 } + { BIN: 111 16 } + { BIN: 1111 8 } + { 1 4 } + { register 0 } + { register 12 } + } sinsn ; + +! Status register acess instructions + +! Load and store instructions +GENERIC: addressing-mode-2 ( addressing-mode -- n ) + +TUPLE: addressing p u w ; +: ( delegate p u w -- addressing ) + { + set-delegate + set-addressing-p + set-addressing-u + set-addressing-w + } addressing construct ; + +M: addressing addressing-mode-2 + { + addressing-p addressing-u addressing-w delegate + } get-slots addressing-mode-2 + { 0 21 23 24 } bitfield ; + +M: integer addressing-mode-2 ; + +M: object addressing-mode-2 shifter-op { { 1 25 } 0 } bitfield ; + +! Offset +: <+> 1 1 0 ; +: <-> 1 0 0 ; + +! Pre-indexed +: 1 1 1 ; +: 1 0 1 ; + +! Post-indexed +: <+!> 0 1 0 ; +: <-!> 0 0 0 ; + +: addr2 ( Rd Rn addressing-mode b l -- ) + { + { 1 26 } + 20 + 22 + { addressing-mode-2 0 } + { register 16 } + { register 12 } + } insn ; + +: LDR 0 1 addr2 ; +: LDRB 1 1 addr2 ; +: STR 0 0 addr2 ; +: STRB 1 0 addr2 ; + +HOOK: BX arm-variant ( operand -- ) + +HOOK: BLX arm-variant ( operand -- ) + +! We might have to simulate these instructions since older ARM +! chips don't have them. +M: f BX PC swap MOV ; + +M: f BLX LR PC MOV BX ; + +! Load and store multiple instructions + +! Semaphore instructions + +! Exception-generating instructions diff --git a/core/cpu/arm/authors.txt b/core/cpu/arm/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/arm/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/arm/bootstrap.factor b/core/cpu/arm/bootstrap.factor new file mode 100644 index 0000000000..3ef3ffcee5 --- /dev/null +++ b/core/cpu/arm/bootstrap.factor @@ -0,0 +1,4 @@ +USING: bootstrap.image.private kernel namespaces system ; + +4 \ cell set +big-endian off diff --git a/core/cpu/arm/intrinsics/intrinsics.factor b/core/cpu/arm/intrinsics/intrinsics.factor new file mode 100644 index 0000000000..5af55cf8bd --- /dev/null +++ b/core/cpu/arm/intrinsics/intrinsics.factor @@ -0,0 +1,462 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien arrays cpu.architecture cpu.arm.assembler +cpu.arm.architecture cpu.arm.allot kernel kernel.private math +math.functions math.private namespaces sequences words +quotations byte-arrays hashtables.private hashtables generator +generator.registers generator.fixup sequences.private sbufs +sbufs.private vectors vectors.private system tuples.private +layouts strings.private slots.private ; +IN: cpu.arm.intrinsics + +\ slot { + ! Slot number is literal + { + [ + "out" operand "obj" operand %untag + "out" operand dup "n" get cells <+> LDR + ] H{ + { +input+ { { f "obj" } { [ small-slot? ] "n" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } + } + ! Slot number in a register + { + [ + "out" operand "obj" operand %untag + "out" operand dup "n" operand 1 <+> LDR + ] H{ + { +input+ { { f "obj" } { f "n" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } + } +} define-intrinsics + +: generate-write-barrier ( -- ) + "val" operand-immediate? "obj" get fresh-object? or [ + "cards_offset" f R12 %alien-global + "scratch" operand R12 "scratch" operand card-bits ADD + "val" operand "scratch" operand 0 LDRB + "val" operand dup card-mark ORR + "val" operand "scratch" operand 0 STRB + ] unless ; + +\ set-slot { + ! Slot number is literal + { + [ + "scratch" operand "obj" operand %untag + "val" operand "scratch" operand "n" get cells <+> STR + generate-write-barrier + ] H{ + { +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "val" } } + } + } + ! Slot number is in a register + { + [ + "scratch" operand "obj" operand %untag + "n" operand "scratch" operand "n" operand 1 ADD + "val" operand "n" operand 0 STR + generate-write-barrier + ] H{ + { +input+ { { f "val" } { f "obj" } { f "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "val" "n" } } + } + } +} define-intrinsics + +: fixnum-op ( op -- quot ) + [ "out" operand "x" operand "y" operand ] swap add ; + +: fixnum-register-op ( op -- pair ) + fixnum-op H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } 2array ; + +: fixnum-value-op ( op -- pair ) + fixnum-op H{ + { +input+ { { f "x" } { [ small-tagged? ] "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } 2array ; + +: define-fixnum-op ( word op -- ) + [ fixnum-value-op ] keep fixnum-register-op 2array + define-intrinsics ; + +{ + { fixnum+fast ADD } + { fixnum-fast SUB } + { fixnum-bitand AND } + { fixnum-bitor ORR } + { fixnum-bitxor EOR } +} [ + first2 define-fixnum-op +] each + +\ fixnum-bitnot [ + "x" operand dup MVN + "x" operand dup %untag +] H{ + { +input+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +\ fixnum*fast [ + "out" operand "y" operand %untag-fixnum + "out" operand "x" operand "out" operand MUL +] H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +\ fixnum-shift [ + "out" operand "x" operand "y" get neg MOV + ! Mask off low bits + "out" operand dup %untag +] H{ + { +input+ { { f "x" } { [ -31 0 between? ] "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +: %untag-fixnums ( seq -- ) + [ dup %untag-fixnum ] unique-operands ; + +: overflow-check ( insn -- ) + [ + "end" define-label + [ "allot-tmp" operand "x" operand "y" operand roll S execute ] keep + "end" get VC B + { "x" "y" } %untag-fixnums + "x" operand "x" operand "y" operand roll execute + "x" get %allot-bignum-signed-1 + "end" resolve-label + ] with-scope ; inline + +: overflow-template ( word insn -- ) + [ overflow-check ] curry H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } + { +clobber+ { "x" "y" } } + } define-intrinsic ; + +\ fixnum+ \ ADD overflow-template +\ fixnum- \ SUB overflow-template + +\ fixnum>bignum [ + "x" operand dup %untag-fixnum + "x" get %allot-bignum-signed-1 +] H{ + { +input+ { { f "x" } } } + { +scratch+ { { f "allot-tmp" } } } + { +clobber+ { "x" } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ bignum>fixnum [ + "end" define-label + "x" operand dup %untag + "y" operand "x" operand cell <+> LDR + ! if the length is 1, its just the sign and nothing else, + ! so output 0 + "y" operand 1 v>operand CMP + "y" operand 0 EQ MOV + "end" get EQ B + ! load the value + "y" operand "x" operand 3 cells <+> LDR + ! load the sign + "x" operand "x" operand 2 cells <+> LDR + ! is the sign negative? + "x" operand 0 CMP + ! Negate the value + "y" operand "y" operand 0 NE RSB + "y" operand dup %tag-fixnum + "end" resolve-label +] H{ + { +input+ { { f "x" } } } + { +scratch+ { { f "y" } } } + { +clobber+ { "x" } } + { +output+ { "y" } } +} define-intrinsic + +: fixnum-jump ( op -- quo ) + [ "x" operand "y" operand CMP ] swap + 1quotation [ B ] 3append ; + +: fixnum-register-jump ( op -- pair ) + fixnum-jump { { f "x" } { f "y" } } 2array ; + +: fixnum-value-jump ( op -- pair ) + fixnum-jump { { f "x" } { [ small-tagged? ] "y" } } 2array ; + +: define-fixnum-jump ( word op -- ) + [ fixnum-value-jump ] keep fixnum-register-jump + 2array define-if-intrinsics ; + +{ + { fixnum< LT } + { fixnum<= LE } + { fixnum> GT } + { fixnum>= GE } + { eq? EQ } +} [ + first2 define-fixnum-jump +] each + +\ tag [ + "out" operand "in" operand tag-mask get AND + "out" operand dup %tag-fixnum +] H{ + { +input+ { { f "in" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +\ type [ + "end" define-label + ! Get the tag + "y" operand "obj" operand tag-mask get AND + ! Compare with object tag number (3). + "y" operand object tag-number CMP + ! Tag the tag if it is not equal to 3 + "x" operand "y" operand NE %tag-fixnum + ! Jump to end if it is not equal to 3 + "end" get NE B + ! Is the pointer itself equal to 3? Then its F_TYPE (9). + "obj" operand object tag-number CMP + ! Load F_TYPE (9) if it is equal + "x" operand f type v>operand EQ MOV + ! Load the object header if it is not equal + "x" operand "obj" operand object tag-number <-> NE LDR + ! Turn the header into a fixnum + "x" operand dup NE %untag + "end" resolve-label +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "x" } { f "y" } } } + { +output+ { "x" } } +} define-intrinsic + +: userenv ( reg -- ) + #! Load the userenv pointer in a register. + "userenv" f rot compile-dlsym ; + +\ getenv [ + "n" operand dup 1 MOV + "x" operand userenv + "x" operand "x" operand "n" operand <+> LDR +] H{ + { +input+ { { f "n" } } } + { +scratch+ { { f "x" } } } + { +output+ { "x" } } + { +clobber+ { "n" } } +} define-intrinsic + +\ setenv [ + "n" operand dup 1 MOV + "x" operand userenv + "val" operand "x" operand "n" operand <+> STR +] H{ + { +input+ { { f "val" } { f "n" } } } + { +scratch+ { { f "x" } } } + { +clobber+ { "n" } } +} define-intrinsic + +: %set-slot "allot-tmp" operand swap cells <+> STR ; + +: %store-length + R12 "n" operand MOV + R12 1 %set-slot ; + +: %fill-array swap 2 + %set-slot ; + +\ [ + tuple "n" get 2 + cells %allot + %store-length + ! Store class + "class" operand 2 %set-slot + ! Zero out the rest of the tuple + R12 f v>operand MOV + "n" get 1- [ 1+ R12 %fill-array ] each + object %tag-allot +] H{ + { +input+ { { f "class" } { [ inline-array? ] "n" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ [ + array "n" get 2 + cells %allot + %store-length + ! Store initial element + "n" get [ "initial" operand %fill-array ] each + object %tag-allot +] H{ + { +input+ { { [ inline-array? ] "n" } { f "initial" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ [ + byte-array "n" get 2 cells + %allot + %store-length + ! Store initial element + R12 0 MOV + "n" get cell align cell /i [ R12 %fill-array ] each + object %tag-allot +] H{ + { +input+ { { [ inline-array? ] "n" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ [ + ratio 3 cells %allot + "numerator" operand 1 %set-slot + "denominator" operand 2 %set-slot + ratio %tag-allot +] H{ + { +input+ { { f "numerator" } { f "denominator" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ [ + complex 3 cells %allot + "real" operand 1 %set-slot + "imaginary" operand 2 %set-slot + ! Store tagged ptr in reg + complex %tag-allot +] H{ + { +input+ { { f "real" } { f "imaginary" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ [ + wrapper 2 cells %allot + "obj" operand 1 %set-slot + ! Store tagged ptr in reg + wrapper %tag-allot +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ (hashtable) [ + hashtable 4 cells %allot + R12 f v>operand MOV + R12 1 %set-slot + R12 2 %set-slot + R12 3 %set-slot + ! Store tagged ptr in reg + object %tag-allot +] H{ + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ string>sbuf [ + sbuf 3 cells %allot + "length" operand 1 %set-slot + "string" operand 2 %set-slot + object %tag-allot +] H{ + { +input+ { { f "string" } { f "length" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ array>vector [ + vector 3 cells %allot + "length" operand 1 %set-slot + "array" operand 2 %set-slot + object %tag-allot +] H{ + { +input+ { { f "array" } { f "length" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +\ curry [ + \ curry 3 cells %allot + "obj" operand 1 %set-slot + "quot" operand 2 %set-slot + object %tag-allot +] H{ + { +input+ { { f "obj" } { f "quot" } } } + { +scratch+ { { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } +} define-intrinsic + +! Alien intrinsics +: alien-integer-get-template + H{ + { +input+ { + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { f "output" } } } + { +output+ { "output" } } + { +clobber+ { "offset" } } + } ; + +: %alien-get ( quot -- ) + "output" get "address" set + "output" operand "alien" operand-class %alien-accessor ; + +: %alien-integer-get ( quot -- ) + %alien-get + "output" operand dup %tag-fixnum ; inline + +: %alien-integer-set ( quot -- ) + "value" operand dup %untag-fixnum + "value" operand "alien" operand-class %alien-accessor ; inline + +: alien-integer-set-template + H{ + { +input+ { + { f "value" fixnum } + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { f "address" } } } + { +clobber+ { "value" "offset" } } + } ; + +: define-alien-integer-intrinsics ( word get-quot word set-quot -- ) + [ %alien-integer-set ] curry + alien-integer-set-template + define-intrinsic + [ %alien-integer-get ] curry + alien-integer-get-template + define-intrinsic ; + +\ alien-unsigned-1 [ LDRB ] +\ set-alien-unsigned-1 [ STRB ] +define-alien-integer-intrinsics + +\ alien-cell [ + [ LDR ] %alien-get + "output" get %allot-alien +] H{ + { +input+ { + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { f "output" } { f "allot-tmp" } } } + { +output+ { "allot-tmp" } } + { +clobber+ { "offset" } } +} define-intrinsic diff --git a/core/cpu/arm/summary.txt b/core/cpu/arm/summary.txt new file mode 100644 index 0000000000..f3e46d9f43 --- /dev/null +++ b/core/cpu/arm/summary.txt @@ -0,0 +1 @@ +ARM3 compiler backend diff --git a/core/cpu/arm5/arm5.factor b/core/cpu/arm5/arm5.factor new file mode 100644 index 0000000000..11675f106a --- /dev/null +++ b/core/cpu/arm5/arm5.factor @@ -0,0 +1,4 @@ +USING: cpu.arm.assembler cpu.arm5.assembler cpu.arm5.intrinsics +namespaces ; + +T{ arm5-variant } arm-variant set-global diff --git a/core/cpu/arm5/assembler/assembler.factor b/core/cpu/arm5/assembler/assembler.factor new file mode 100644 index 0000000000..237394af11 --- /dev/null +++ b/core/cpu/arm5/assembler/assembler.factor @@ -0,0 +1,74 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generator generator.fixup kernel sequences words +namespaces math math.bitfields cpu.arm.assembler ; +IN: cpu.arm5.assembler + +TUPLE: arm5-variant ; + +GENERIC# (BX) 1 ( Rm l -- ) + +M: register (BX) ( Rm l -- ) + { + { 1 24 } + { 1 21 } + { BIN: 1111 16 } + { BIN: 1111 12 } + { BIN: 1111 8 } + 5 + { 1 4 } + { register 0 } + } insn ; + +M: word (BX) 0 swap (BX) rc-relative-arm-3 rel-word ; + +M: label (BX) 0 swap (BX) rc-relative-arm-3 label-fixup ; + +M: arm5-variant BX 0 (BX) ; + +M: arm5-variant BLX 1 (BX) ; + +! More load and store instructions +GENERIC: addressing-mode-3 ( addressing-mode -- n ) + +: b>n/n ( b -- n n ) dup -4 shift swap HEX: f bitand ; + +M: addressing addressing-mode-3 + [ addressing-p ] keep + [ addressing-u ] keep + [ addressing-w ] keep + delegate addressing-mode-3 + { 0 21 23 24 } bitfield ; + +M: integer addressing-mode-3 + b>n/n { + ! { 1 24 } + { 1 22 } + { 1 7 } + { 1 4 } + 0 + 8 + } bitfield ; + +M: object addressing-mode-3 + shifter-op { + ! { 1 24 } + { 1 7 } + { 1 4 } + 0 + } bitfield ; + +: addr3 ( Rn Rd addressing-mode h l s -- ) + { + 6 + 20 + 5 + { addressing-mode-3 0 } + { register 16 } + { register 12 } + } insn ; + +: LDRH 1 1 0 addr3 ; +: LDRSB 0 1 1 addr3 ; +: LDRSH 1 1 1 addr3 ; +: STRH 1 0 0 addr3 ; diff --git a/core/cpu/arm5/authors.txt b/core/cpu/arm5/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/arm5/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/arm5/intrinsics/intrinsics.factor b/core/cpu/arm5/intrinsics/intrinsics.factor new file mode 100644 index 0000000000..d6f651b0e2 --- /dev/null +++ b/core/cpu/arm5/intrinsics/intrinsics.factor @@ -0,0 +1,45 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien arrays cpu.architecture cpu.arm.assembler +cpu.arm.architecture cpu.arm5.assembler kernel kernel.private +math math.private namespaces sequences words quotations +byte-arrays hashtables.private hashtables generator +generator.registers generator.fixup sequences.private +strings.private ; +IN: cpu.arm5.intrinsics + +: (%char-slot) + "out" operand string-offset MOV + "out" operand dup "n" operand 2 ADD ; + +\ char-slot [ + (%char-slot) + "out" operand "obj" operand "out" operand <+> LDRH + "out" operand dup %tag-fixnum +] H{ + { +input+ { { f "n" } { f "obj" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +\ set-char-slot [ + "val" operand dup %untag-fixnum + (%char-slot) + "val" operand "obj" operand "out" operand <+> STRH +] H{ + { +input+ { { f "val" } { f "n" } { f "obj" } } } + { +scratch+ { { f "out" } } } + { +clobber+ { "val" } } +} define-intrinsic + +\ alien-signed-1 [ LDRSB ] +\ set-alien-signed-1 [ STRB ] +define-alien-integer-intrinsics + +\ alien-unsigned-2 [ LDRH ] +\ set-alien-unsigned-2 [ STRH ] +define-alien-integer-intrinsics + +\ alien-signed-2 [ LDRSH ] +\ set-alien-signed-2 [ STRH ] +define-alien-integer-intrinsics diff --git a/core/cpu/arm5/summary.txt b/core/cpu/arm5/summary.txt new file mode 100644 index 0000000000..5c697fe27e --- /dev/null +++ b/core/cpu/arm5/summary.txt @@ -0,0 +1 @@ +Additional compiler intrinsics for ARM5 diff --git a/core/cpu/ppc/allot/allot.factor b/core/cpu/ppc/allot/allot.factor new file mode 100644 index 0000000000..a31e4b7836 --- /dev/null +++ b/core/cpu/ppc/allot/allot.factor @@ -0,0 +1,104 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel cpu.ppc.architecture cpu.ppc.assembler +kernel.private namespaces math sequences generic arrays +generator generator.registers generator.fixup system layouts +math.functions cpu.architecture alien ; +IN: cpu.ppc.allot + +: load-zone-ptr ( reg -- ) + "nursery" f pick %load-dlsym dup 0 LWZ ; + +: %allot ( header size -- ) + #! Store a pointer to 'size' bytes allocated from the + #! nursery in r11. + 8 align ! align the size + 12 load-zone-ptr ! nusery -> r12 + 11 12 cell LWZ ! nursery.here -> r11 + 11 11 pick ADDI ! increment r11 + 11 12 cell STW ! r11 -> nursery.here + 11 11 rot SUBI ! old value + type-number tag-header 12 LI ! compute header + 12 11 0 STW ! store header + ; + +: %store-tagged ( reg tag -- ) + >r dup fresh-object v>operand 11 r> tag-number ORI ; + +: %allot-float ( reg -- ) + #! exits with tagged ptr to object in r12, untagged in r11 + float 16 %allot + 11 8 STFD + 12 11 float tag-number ORI + f fresh-object ; + +M: float-regs (%replace) + drop + swap v>operand %allot-float + 12 swap loc>operand STW ; + +M: ppc-backend %move-float>int ( dst src -- ) + [ v>operand ] 2apply %allot-float 12 MR ; + +: %allot-bignum ( #digits -- ) + #! 1 cell header, 1 cell length, 1 cell sign, + digits + #! length is the # of digits + sign + bignum over 3 + cells %allot + 1+ v>operand 12 LI ! compute the length + 12 11 cell STW ! store the length + ; + +: %allot-bignum-signed-1 ( reg -- ) + #! on entry, reg is a 30-bit quantity sign-extended to + #! 32-bits. + #! exits with tagged ptr to bignum in reg + [ + { "end" "non-zero" "pos" "store" } [ define-label ] each + ! is it zero? + 0 over v>operand 0 CMPI + "non-zero" get BNE + 0 >bignum over load-literal + "end" get B + ! it is non-zero + "non-zero" resolve-label + 1 %allot-bignum + ! is the fixnum negative? + 0 over v>operand 0 CMPI + "pos" get BGE + 1 12 LI + ! store negative sign + 12 11 2 cells STW + ! negate fixnum + dup v>operand dup -1 MULI + "store" get B + "pos" resolve-label + 0 12 LI + ! store positive sign + 12 11 2 cells STW + "store" resolve-label + ! store the number + dup v>operand 11 3 cells STW + ! tag the bignum, store it in reg + bignum %store-tagged + "end" resolve-label + ] with-scope ; + +: %allot-alien ( ptr -- ) + "temp" set + "f" define-label + "end" define-label + 0 "temp" operand 0 CMPI + "f" get BEQ + alien 4 cells %allot + "temp" operand 11 3 cells STW + f v>operand "temp" operand LI + ! Store expired slot + "temp" operand 11 1 cells STW + ! Store underlying-alien slot + "temp" operand 11 2 cells STW + ! Store tagged ptr in reg + "temp" get object %store-tagged + "end" get B + "f" resolve-label + f v>operand "temp" operand LI + "end" resolve-label ; diff --git a/core/cpu/ppc/allot/authors.txt b/core/cpu/ppc/allot/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/ppc/allot/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/ppc/allot/summary.txt b/core/cpu/ppc/allot/summary.txt new file mode 100644 index 0000000000..3c4941ea1d --- /dev/null +++ b/core/cpu/ppc/allot/summary.txt @@ -0,0 +1 @@ +PowerPC inline memory allocation diff --git a/core/cpu/ppc/architecture/architecture.factor b/core/cpu/ppc/architecture/architecture.factor new file mode 100644 index 0000000000..d12139c550 --- /dev/null +++ b/core/cpu/ppc/architecture/architecture.factor @@ -0,0 +1,357 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien.c-types cpu.ppc.assembler cpu.architecture generic +kernel kernel.private math memory namespaces sequences words +assocs generator generator.registers generator.fixup system +layouts math.functions classes words.private alien combinators ; +IN: cpu.ppc.architecture + +TUPLE: ppc-backend ; + +! PowerPC register assignments +! r3-r10, r17-r31: integer vregs +! f0-f13: float vregs +! r11, r12: scratch +! r14: data stack +! r15: retain stack + +! For stack frame layout, see vm/os-{macosx,linux}-ppc.h. + +: ds-reg 14 ; +: rs-reg 15 ; +: stack-chain-reg 16 ; + +: reserved-area-size + os { + { "linux" [ 2 ] } + { "macosx" [ 6 ] } + } case cells ; foldable + +: lr-save + os { + { "linux" [ 1 ] } + { "macosx" [ 2 ] } + } case cells ; foldable + +: param@ ( n -- x ) reserved-area-size + ; inline + +: param-save-size 8 cells ; foldable + +: xt-save reserved-area-size param-save-size + 2 cells + ; foldable + +: local-area-start xt-save cell + ; foldable + +: local@ ( n -- x ) local-area-start + ; inline + +M: ppc-backend stack-frame ( n -- i ) local@ 4 cells align ; + +M: temp-reg v>operand drop 11 ; + +M: int-regs return-reg drop 3 ; +M: int-regs param-regs drop { 3 4 5 6 7 8 9 10 } ; +M: int-regs vregs + drop { + 3 4 5 6 7 8 9 10 + 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 + } ; + +M: float-regs return-reg drop 1 ; + +M: float-regs param-regs + drop os H{ + { "macosx" { 1 2 3 4 5 6 7 8 9 10 11 12 13 } } + { "linux" { 1 2 3 4 5 6 7 8 } } + } at ; + +M: float-regs vregs drop { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 } ; + +GENERIC: loc>operand ( loc -- reg n ) + +M: ds-loc loc>operand ds-loc-n cells neg ds-reg swap ; +M: rs-loc loc>operand rs-loc-n cells neg rs-reg swap ; + +M: immediate load-literal + [ v>operand ] 2apply LOAD ; + +M: ppc-backend load-indirect ( obj reg -- ) + [ 0 swap LOAD32 rc-absolute-ppc-2/2 rel-literal ] keep + dup 0 LWZ ; + +: %load-xt ( word reg -- ) + 0 swap LOAD32 rc-absolute-ppc-2/2 rel-word ; + +M: ppc-backend %save-xt ( -- ) + compiling-label get 11 %load-xt ; + +M: ppc-backend %prologue ( n -- ) + 0 MFLR + 1 1 pick stack-frame neg STWU + 11 1 xt-save STW + 0 1 rot stack-frame lr-save + STW ; + +M: ppc-backend %epilogue ( n -- ) + #! At the end of each word that calls a subroutine, we store + #! the previous link register value in r0 by popping it off + #! the stack, set the link register to the contents of r0, + #! and jump to the link register. + 0 1 pick stack-frame lr-save + LWZ + 1 1 rot stack-frame ADDI + 0 MTLR ; + +: %load-dlsym ( symbol dll register -- ) + 0 swap LOAD32 rc-absolute-ppc-2/2 rel-dlsym ; + +M: ppc-backend %profiler-prologue ( word -- ) + "end" define-label + "profiling" f 3 %load-dlsym + 3 3 0 LWZ + 0 3 0 CMPI + "end" get BEQ + 3 load-indirect + 4 3 profile-count-offset LWZ + 4 4 1 v>operand ADDI + 4 3 profile-count-offset STW + "end" resolve-label ; + +M: ppc-backend %call-label ( label -- ) BL ; + +M: ppc-backend %jump-label ( label -- ) B ; + +: %prepare-primitive ( word -- ) + ! Save stack pointer to stack_chain->callstack_top, load XT + 4 1 MR 11 %load-xt ; + +: (%call) 11 MTLR BLRL ; + +M: ppc-backend %call-primitive ( word -- ) + %prepare-primitive (%call) ; + +: (%jump) 11 MTCTR BCTR ; + +M: ppc-backend %jump-primitive ( word -- ) + %prepare-primitive (%jump) ; + +M: ppc-backend %jump-t ( label -- ) + 0 "flag" operand \ f tag-number CMPI BNE ; + +: dispatch-template ( word-table# quot -- ) + [ + >r + "offset" operand "n" operand 1 SRAWI + 0 11 LOAD32 rc-absolute-ppc-2/2 rel-dispatch + 11 dup "offset" operand LWZX + r> call + ] H{ + { +input+ { { f "n" } } } + { +scratch+ { { f "offset" } } } + } with-template ; inline + +M: ppc-backend %call-dispatch ( word-table# -- ) + [ (%call) ] dispatch-template ; + +M: ppc-backend %jump-dispatch ( word-table# -- ) + [ %epilogue-later (%jump) ] dispatch-template ; + +M: ppc-backend %return ( -- ) %epilogue-later BLR ; + +M: ppc-backend %unwind drop %return ; + +M: int-regs (%peek) + drop >r v>operand r> loc>operand LWZ ; + +M: float-regs (%peek) + drop + 11 swap loc>operand LWZ + v>operand 11 float-offset LFD ; + +M: int-regs (%replace) + drop >r v>operand r> loc>operand STW ; + +M: ppc-backend %move-int>int ( dst src -- ) + [ v>operand ] 2apply MR ; + +M: ppc-backend %move-int>float ( dst src -- ) + [ v>operand ] 2apply float-offset LFD ; + +M: ppc-backend %inc-d ( n -- ) ds-reg dup rot cells ADDI ; + +M: ppc-backend %inc-r ( n -- ) rs-reg dup rot cells ADDI ; + +M: int-regs %save-param-reg drop 1 rot local@ STW ; + +M: int-regs %load-param-reg drop 1 rot local@ LWZ ; + +: STF float-regs-size 4 = [ STFS ] [ STFD ] if ; + +M: float-regs %save-param-reg >r 1 rot local@ r> STF ; + +: LF float-regs-size 4 = [ LFS ] [ LFD ] if ; + +M: float-regs %load-param-reg >r 1 rot local@ r> LF ; + +M: stack-params %load-param-reg ( stack reg reg-class -- ) + drop >r 0 1 rot local@ LWZ 0 1 r> param@ STW ; + +M: stack-params %save-param-reg ( stack reg reg-class -- ) + #! Funky. Read the parameter from the caller's stack frame. + #! This word is used in callbacks + drop + 0 1 rot param@ stack-frame* + LWZ + 0 1 rot local@ STW ; + +M: ppc-backend %prepare-unbox ( -- ) + ! First parameter is top of stack + 3 ds-reg 0 LWZ + ds-reg dup cell SUBI ; + +M: ppc-backend %unbox ( n reg-class func -- ) + ! Value must be in r3 + ! Call the unboxer + f %alien-invoke + ! Store the return value on the C stack + over [ [ return-reg ] keep %save-param-reg ] [ 2drop ] if ; + +M: ppc-backend %unbox-long-long ( n func -- ) + ! Value must be in r3:r4 + ! Call the unboxer + f %alien-invoke + ! Store the return value on the C stack + [ + 3 1 pick local@ STW + 4 1 rot cell + local@ STW + ] when* ; + +M: ppc-backend %unbox-large-struct ( n size -- ) + ! Value must be in r3 + ! Compute destination address + 4 1 roll local@ ADDI + ! Load struct size + 5 LI + ! Call the function + "to_value_struct" f %alien-invoke ; + +M: ppc-backend %box ( n reg-class func -- ) + ! If the source is a stack location, load it into freg #0. + ! If the source is f, then we assume the value is already in + ! freg #0. + >r + over [ 0 over param-reg swap %load-param-reg ] [ 2drop ] if + r> f %alien-invoke ; + +M: ppc-backend %box-long-long ( n func -- ) + >r [ + 3 1 pick local@ LWZ + 4 1 rot cell + local@ LWZ + ] when* r> f %alien-invoke ; + +: temp@ stack-frame* swap - ; + +: struct-return@ ( size n -- n ) [ local@ ] [ temp@ ] ?if ; + +M: ppc-backend %prepare-box-struct ( size -- ) + #! Compute target address for value struct return + 3 1 rot f struct-return@ ADDI + 3 1 0 local@ STW ; + +M: ppc-backend %box-large-struct ( n size -- ) + #! If n = f, then we're boxing a returned struct + [ swap struct-return@ ] keep + ! Compute destination address + 3 1 roll ADDI + ! Load struct size + 4 LI + ! Call the function + "box_value_struct" f %alien-invoke ; + +M: ppc-backend %prepare-alien-invoke + #! Save Factor stack pointers in case the C code calls a + #! callback which does a GC, which must reliably trace + #! all roots. + "stack_chain" f 11 %load-dlsym + 11 11 0 LWZ + 1 11 0 STW + ds-reg 11 8 STW + rs-reg 11 12 STW ; + +M: ppc-backend %alien-invoke ( symbol dll -- ) + 11 %load-dlsym (%call) ; + +M: ppc-backend %alien-callback ( quot -- ) + 0 load-literal "c_to_factor" f %alien-invoke ; + +M: ppc-backend %prepare-alien-indirect ( -- ) + "unbox_alien" f %alien-invoke + 3 1 cell temp@ STW ; + +M: ppc-backend %alien-indirect ( -- ) + 11 1 cell temp@ LWZ (%call) ; + +M: ppc-backend %callback-value ( ctype -- ) + ! Save top of data stack + 3 ds-reg 0 LWZ + 3 1 0 local@ STW + ! Restore data/call/retain stacks + "unnest_stacks" f %alien-invoke + ! Restore top of data stack + 3 1 0 local@ LWZ + ! Unbox former top of data stack to return registers + unbox-return ; + +M: ppc-backend %cleanup ( alien-node -- ) drop ; + +: %untag ( src dest -- ) 0 0 31 tag-bits get - RLWINM ; + +: %tag-fixnum ( src dest -- ) tag-bits get SLWI ; + +: %untag-fixnum ( src dest -- ) tag-bits get SRAWI ; + +M: ppc-backend value-structs? + #! On Linux/PPC, value structs are passed in the same way + #! as reference structs, we just have to make a copy first. + os "linux" = not ; + +M: ppc-backend fp-shadows-int? ( -- ? ) macosx? ; + +M: ppc-backend small-enough? ( n -- ? ) -32768 32767 between? ; + +M: ppc-backend struct-small-enough? ( size -- ? ) drop f ; + +M: ppc-backend %box-small-struct + drop "No small structs" throw ; + +M: ppc-backend %unbox-small-struct + drop "No small structs" throw ; + +! Alien intrinsics +M: ppc-backend %unbox-byte-array ( quot src -- ) + "address" operand "alien" operand "offset" operand ADD + "address" operand byte-array-offset + roll call ; + +M: ppc-backend %unbox-alien ( quot src -- ) + "address" operand "alien" operand alien-offset LWZ + "address" operand dup "offset" operand ADD + "address" operand 0 + roll call ; + +M: ppc-backend %unbox-f ( quot src -- ) + "offset" operand 0 + roll call ; + +M: ppc-backend %complex-alien-accessor ( quot src -- ) + "is-f" define-label + "is-alien" define-label + "end" define-label + 0 "alien" operand f v>operand CMPI + "is-f" get BEQ + "address" operand "alien" operand header-offset LWZ + 0 "address" operand alien type-number tag-header CMPI + "is-alien" get BEQ + [ %unbox-byte-array ] 2keep + "end" get B + "is-alien" resolve-label + [ %unbox-alien ] 2keep + "end" get B + "is-f" resolve-label + %unbox-f + "end" resolve-label ; diff --git a/core/cpu/ppc/architecture/authors.txt b/core/cpu/ppc/architecture/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/ppc/architecture/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/ppc/architecture/summary.txt b/core/cpu/ppc/architecture/summary.txt new file mode 100644 index 0000000000..76fe694abe --- /dev/null +++ b/core/cpu/ppc/architecture/summary.txt @@ -0,0 +1 @@ +PowerPC architecture description diff --git a/core/cpu/ppc/assembler/assembler.factor b/core/cpu/ppc/assembler/assembler.factor new file mode 100644 index 0000000000..2ea5595bc9 --- /dev/null +++ b/core/cpu/ppc/assembler/assembler.factor @@ -0,0 +1,225 @@ +! Copyright (C) 2005, 2006 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: cpu.ppc.assembler +USING: generator.fixup generic kernel math memory namespaces +words math.bitfields math.functions io.binary ; + +! See the Motorola or IBM documentation for details. The opcode +! names are standard, and the operand order is the same as in +! the docs, except a few differences, namely, in IBM/Motorola +! assembler syntax, loads and stores are written like: +! +! stw r14,10(r15) +! +! In Factor, we write: +! +! 14 15 10 STW + +: insn ( operand opcode -- ) { 26 0 } bitfield , ; +: a-form ( d a b c xo rc -- n ) { 0 1 6 11 16 21 } bitfield ; +: b-form ( bo bi bd aa lk -- n ) { 0 1 2 16 21 } bitfield ; +: s>u16 ( s -- u ) HEX: ffff bitand ; +: d-form ( d a simm -- n ) s>u16 { 0 16 21 } bitfield ; +: sd-form ( d a simm -- n ) s>u16 { 0 21 16 } bitfield ; +: i-form ( li aa lk -- n ) { 0 1 0 } bitfield ; +: x-form ( a s b rc xo -- n ) { 1 0 11 21 16 } bitfield ; +: xfx-form ( d spr xo -- n ) { 1 11 21 } bitfield ; +: xo-form ( d a b oe rc xo -- n ) { 1 0 10 11 16 21 } bitfield ; + +: ADDI d-form 14 insn ; : LI 0 rot ADDI ; : SUBI neg ADDI ; +: ADDIS d-form 15 insn ; : LIS 0 rot ADDIS ; + +: ADDIC d-form 12 insn ; : SUBIC neg ADDIC ; + +: ADDIC. d-form 13 insn ; : SUBIC. neg ADDIC. ; + +: MULI d-form 7 insn ; + +: (ADD) 266 xo-form 31 insn ; +: ADD 0 0 (ADD) ; : ADD. 0 1 (ADD) ; +: ADDO 1 0 (ADD) ; : ADDO. 1 1 (ADD) ; + +: (ADDC) 10 xo-form 31 insn ; +: ADDC 0 0 (ADDC) ; : ADDC. 0 1 (ADDC) ; +: ADDCO 1 0 (ADDC) ; : ADDCO. 1 1 (ADDC) ; + +: (ADDE) 138 xo-form 31 insn ; +: ADDE 0 0 (ADDE) ; : ADDE. 0 1 (ADDE) ; +: ADDEO 1 0 (ADDE) ; : ADDEO. 1 1 (ADDE) ; + +: ANDI sd-form 28 insn ; +: ANDIS sd-form 29 insn ; + +: (AND) 28 x-form 31 insn ; +: AND 0 (AND) ; : AND. 0 (AND) ; + +: (DIVW) 491 xo-form 31 insn ; +: DIVW 0 0 (DIVW) ; : DIVW. 0 1 (DIVW) ; +: DIVWO 1 0 (DIVW) ; : DIVWO. 1 1 (DIVW) ; + +: (DIVWU) 459 xo-form 31 insn ; +: DIVWU 0 0 (DIVWU) ; : DIVWU. 0 1 (DIVWU) ; +: DIVWUO 1 0 (DIVWU) ; : DIVWUO. 1 1 (DIVWU) ; + +: (EQV) 284 x-form 31 insn ; +: EQV 0 (EQV) ; : EQV. 1 (EQV) ; + +: (NAND) 476 x-form 31 insn ; +: NAND 0 (NAND) ; : NAND. 1 (NAND) ; + +: (NOR) 124 x-form 31 insn ; +: NOR 0 (NOR) ; : NOR. 1 (NOR) ; + +: NOT dup NOR ; : NOT. dup NOR. ; + +: ORI sd-form 24 insn ; : ORIS sd-form 25 insn ; + +: (OR) 444 x-form 31 insn ; +: OR 0 (OR) ; : OR. 1 (OR) ; + +: (ORC) 412 x-form 31 insn ; +: ORC 0 (ORC) ; : ORC. 1 (ORC) ; + +: MR dup OR ; : MR. dup OR. ; + +: (MULHW) 75 xo-form 31 insn ; +: MULHW 0 0 (MULHW) ; : MULHW. 0 1 (MULHW) ; + +: MULLI d-form 7 insn ; + +: (MULHWU) 11 xo-form 31 insn ; +: MULHWU 0 0 (MULHWU) ; : MULHWU. 0 1 (MULHWU) ; + +: (MULLW) 235 xo-form 31 insn ; +: MULLW 0 0 (MULLW) ; : MULLW. 0 1 (MULLW) ; +: MULLWO 1 0 (MULLW) ; : MULLWO. 1 1 (MULLW) ; + +: (SLW) 24 x-form 31 insn ; +: SLW 0 (SLW) ; : SLW. 1 (SLW) ; + +: (SRAW) 792 x-form 31 insn ; +: SRAW 0 (SRAW) ; : SRAW. 1 (SRAW) ; + +: (SRW) 536 x-form 31 insn ; +: SRW 0 (SRW) ; : SRW. 1 (SRW) ; + +: SRAWI 0 824 x-form 31 insn ; + +: (SUBF) 40 xo-form 31 insn ; +: SUBF 0 0 (SUBF) ; : SUBF. 0 1 (SUBF) ; +: SUBFO 1 0 (SUBF) ; : SUBFO. 1 1 (SUBF) ; + +: (SUBFC) 8 xo-form 31 insn ; +: SUBFC 0 0 (SUBFC) ; : SUBFC. 0 1 (SUBFC) ; +: SUBFCO 1 0 (SUBFC) ; : SUBFCO. 1 1 (SUBFC) ; + +: (SUBFE) 136 xo-form 31 insn ; +: SUBFE 0 0 (SUBFE) ; : SUBFE. 0 1 (SUBFE) ; +: SUBFEO 1 0 (SUBFE) ; : SUBFEO. 1 1 (SUBFE) ; + +: (EXTSB) 0 swap 954 x-form 31 insn ; +: EXTSB 0 (EXTSB) ; +: EXTSB. 1 (EXTSB) ; + +: XORI sd-form 26 insn ; : XORIS sd-form 27 insn ; + +: (XOR) 316 x-form 31 insn ; +: XOR 0 (XOR) ; : XOR. 1 (XOR) ; + +: CMPI d-form 11 insn ; +: CMPLI d-form 10 insn ; + +: CMP 0 0 x-form 31 insn ; +: CMPL 0 32 x-form 31 insn ; + +: (RLWINM) a-form 21 insn ; +: RLWINM 0 (RLWINM) ; : RLWINM. 1 (RLWINM) ; + +: (SLWI) 0 31 pick - ; +: SLWI (SLWI) RLWINM ; : SLWI. (SLWI) RLWINM. ; +: (SRWI) 32 over - swap 31 ; +: SRWI (SRWI) RLWINM ; : SRWI. (SRWI) RLWINM. ; + +: LBZ d-form 34 insn ; : LBZU d-form 35 insn ; +: LHA d-form 42 insn ; : LHAU d-form 43 insn ; +: LHZ d-form 40 insn ; : LHZU d-form 41 insn ; +: LWZ d-form 32 insn ; : LWZU d-form 33 insn ; + +: LBZX 0 87 x-form 31 insn ; : LBZUX 0 119 x-form 31 insn ; +: LHAX 0 343 x-form 31 insn ; : LHAUX 0 375 x-form 31 insn ; +: LHZX 0 279 x-form 31 insn ; : LHZUX 0 311 x-form 31 insn ; +: LWZX 0 23 x-form 31 insn ; : LWZUX 0 55 x-form 31 insn ; + +: STB d-form 38 insn ; : STBU d-form 39 insn ; +: STH d-form 44 insn ; : STHU d-form 45 insn ; +: STW d-form 36 insn ; : STWU d-form 37 insn ; + +: STBX 0 215 x-form 31 insn ; : STBUX 247 x-form 31 insn ; +: STHX 0 407 x-form 31 insn ; : STHUX 439 x-form 31 insn ; +: STWX 0 151 x-form 31 insn ; : STWUX 183 x-form 31 insn ; + +GENERIC# (B) 2 ( dest aa lk -- ) +M: integer (B) i-form 18 insn ; +M: word (B) 0 -rot (B) rc-relative-ppc-3 rel-word ; +M: label (B) 0 -rot (B) rc-relative-ppc-3 label-fixup ; + +: B 0 0 (B) ; : BL 0 1 (B) ; + +GENERIC: BC ( a b c -- ) +M: integer BC 0 0 b-form 16 insn ; +M: word BC >r 0 BC r> rc-relative-ppc-2 rel-word ; +M: label BC >r 0 BC r> rc-relative-ppc-2 label-fixup ; + +: BLT 12 0 rot BC ; : BGE 4 0 rot BC ; +: BGT 12 1 rot BC ; : BLE 4 1 rot BC ; +: BEQ 12 2 rot BC ; : BNE 4 2 rot BC ; +: BO 12 3 rot BC ; : BNO 4 3 rot BC ; + +: BCLR 0 8 0 0 b-form 19 insn ; +: BLR 20 BCLR ; +: BCLRL 0 8 0 1 b-form 19 insn ; +: BLRL 20 BCLRL ; +: BCCTR 0 264 0 0 b-form 19 insn ; +: BCTR 20 BCCTR ; + +: MFSPR 5 shift 339 xfx-form 31 insn ; +: MFXER 1 MFSPR ; : MFLR 8 MFSPR ; : MFCTR 9 MFSPR ; + +: MTSPR 5 shift 467 xfx-form 31 insn ; +: MTXER 1 MTSPR ; : MTLR 8 MTSPR ; : MTCTR 9 MTSPR ; + +: LOAD32 >r w>h/h r> tuck LIS dup rot ORI ; + +: LOAD ( n r -- ) + #! PowerPC cannot load a 32 bit literal in one instruction. + >r dup -32768 32767 between? [ r> LI ] [ r> LOAD32 ] if ; + +! Floating point +: LFS d-form 48 insn ; : LFSU d-form 49 insn ; +: LFD d-form 50 insn ; : LFDU d-form 51 insn ; +: STFS d-form 52 insn ; : STFSU d-form 53 insn ; +: STFD d-form 54 insn ; : STFDU d-form 55 insn ; + +: (FMR) >r 0 -rot 72 r> x-form 63 insn ; +: FMR 0 (FMR) ; : FMR. 1 (FMR) ; + +: (FCTIWZ) >r 0 -rot r> 15 x-form 63 insn ; +: FCTIWZ 0 (FCTIWZ) ; : FCTIWZ. 1 (FCTIWZ) ; + +: (FADD) >r 0 21 r> a-form 63 insn ; +: FADD 0 (FADD) ; : FADD. 1 (FADD) ; + +: (FSUB) >r 0 20 r> a-form 63 insn ; +: FSUB 0 (FSUB) ; : FSUB. 1 (FSUB) ; + +: (FMUL) >r 0 swap 25 r> a-form 63 insn ; +: FMUL 0 (FMUL) ; : FMUL. 1 (FMUL) ; + +: (FDIV) >r 0 18 r> a-form 63 insn ; +: FDIV 0 (FDIV) ; : FDIV. 1 (FDIV) ; + +: (FSQRT) >r 0 swap 0 22 r> a-form 63 insn ; +: FSQRT 0 (FSQRT) ; : FSQRT. 1 (FSQRT) ; + +: FCMPU 0 0 x-form 63 insn ; +: FCMPO 0 32 x-form 63 insn ; diff --git a/core/cpu/ppc/assembler/authors.txt b/core/cpu/ppc/assembler/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/ppc/assembler/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/ppc/assembler/summary.txt b/core/cpu/ppc/assembler/summary.txt new file mode 100644 index 0000000000..336eaf9f5a --- /dev/null +++ b/core/cpu/ppc/assembler/summary.txt @@ -0,0 +1 @@ +PowerPC assembler diff --git a/core/cpu/ppc/authors.txt b/core/cpu/ppc/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/ppc/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/ppc/bootstrap.factor b/core/cpu/ppc/bootstrap.factor new file mode 100644 index 0000000000..7caaabc16a --- /dev/null +++ b/core/cpu/ppc/bootstrap.factor @@ -0,0 +1,128 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: bootstrap.image.private kernel namespaces system +cpu.ppc.assembler math math.functions layouts words vocabs ; +IN: bootstrap.ppc + +4 \ cell set +big-endian on + +4 jit-code-format set + +: ds-reg 14 ; + +: word-reg 3 ; +: quot-reg 3 ; +: scan-reg 5 ; +: temp-reg 6 ; +: xt-reg 11 ; + +: param-save-size 8 bootstrap-cells ; + +: local@ + bootstrap-cells reserved-area-size param-save-size + + ; + +: array-save 0 local@ ; +: scan-save 1 local@ ; +: xt-save 2 local@ ; + +: stack-frame + 3 local@ 4 bootstrap-cells align ; + +[ + temp-reg quot-reg quot-array@ LWZ ! load array + scan-reg temp-reg scan@ ADDI ! initialize scan pointer +] { } make jit-setup set + +[ + 1 1 stack-frame neg STWU ! store back link + 0 MFLR ! load return address into r0 + temp-reg 1 array-save STW ! save array + xt-reg 1 xt-save STW ! save XT + 0 1 lr-save stack-frame + STW ! save return address +] { } make jit-prolog set + +[ + temp-reg scan-reg 4 LWZU ! load literal and advance + temp-reg ds-reg 4 STWU ! push literal +] { } make jit-push-literal set + +[ + temp-reg scan-reg 4 LWZU ! load wrapper and advance + temp-reg dup wrapper@ LWZ ! load wrapped object + temp-reg ds-reg 4 STWU ! push wrapped object +] { } make jit-push-wrapper set + +[ + 4 1 MR ! pass stack pointer to primitive +] { } make jit-word-primitive-jump set + +[ + 4 1 MR ! pass stack pointer to primitive +] { } make jit-word-primitive-call set + +: load-xt ( -- ) + xt-reg word-reg word-xt@ LWZ ; + +: jit-call + scan-reg 1 scan-save STW ! save scan pointer + xt-reg MTLR ! pass XT to callee + BLRL ! call + scan-reg 1 scan-save LWZ ! restore scan pointer + ; + +: jit-jump + xt-reg MTCTR BCTR ; + +[ + word-reg scan-reg 4 LWZU ! load word and advance + load-xt + jit-call +] { } make jit-word-call set + +[ + word-reg scan-reg 4 LWZ ! load word + load-xt ! jump to word XT + jit-jump +] { } make jit-word-jump set + +: load-branch + temp-reg ds-reg 0 LWZ ! load boolean + 0 temp-reg \ f tag-number CMPI ! compare it with f + quot-reg scan-reg MR ! point quot-reg at false branch + 2 BNE ! skip next insn if its not f + quot-reg dup 4 ADDI ! point quot-reg at true branch + quot-reg dup 4 LWZ ! load the branch + ds-reg dup 4 SUBI ! pop boolean + scan-reg dup 12 ADDI ! advance scan pointer + xt-reg quot-reg quot-xt@ LWZ ! load quotation-xt + ; + +[ + load-branch jit-jump +] { } make jit-if-jump set + +[ + load-branch jit-call +] { } make jit-if-call set + +[ + temp-reg ds-reg 0 LWZ ! load index + temp-reg dup 1 SRAWI ! turn it into an array offset + ds-reg dup 4 SUBI ! pop index + scan-reg dup 4 LWZ ! load array + temp-reg dup scan-reg ADD ! compute quotation location + quot-reg temp-reg array-start LWZ ! load quotation + xt-reg quot-reg quot-xt@ LWZ ! load quotation-xt + jit-jump ! execute quotation +] { } make jit-dispatch set + +[ + 0 1 lr-save stack-frame + LWZ ! load return address + 1 1 stack-frame ADDI ! pop stack frame + 0 MTLR ! get ready to return +] { } make jit-epilog set + +[ BLR ] { } make jit-return set + +"bootstrap.ppc" forget-vocab diff --git a/core/cpu/ppc/intrinsics/intrinsics.factor b/core/cpu/ppc/intrinsics/intrinsics.factor new file mode 100644 index 0000000000..97d866d883 --- /dev/null +++ b/core/cpu/ppc/intrinsics/intrinsics.factor @@ -0,0 +1,712 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien alien.c-types arrays cpu.ppc.assembler +cpu.ppc.architecture cpu.ppc.allot cpu.architecture kernel +kernel.private math math.private namespaces sequences words +generic quotations byte-arrays hashtables hashtables.private +generator generator.registers generator.fixup sequences.private +sbufs vectors system layouts math.functions math.floats.private +classes tuples tuples.private sbufs.private vectors.private +strings.private slots.private combinators bit-arrays +float-arrays ; +IN: cpu.ppc.intrinsics + +: %slot-literal-known-tag + "val" operand + "obj" operand + "n" get cells + "obj" operand-tag - ; + +: %slot-literal-any-tag + "obj" operand "scratch" operand %untag + "val" operand "scratch" operand "n" get cells ; + +: %slot-any + "obj" operand "scratch" operand %untag + "n" operand dup 1 SRAWI + "scratch" operand "val" operand "n" operand ; + +\ slot { + ! Slot number is literal and the tag is known + { + [ %slot-literal-known-tag LWZ ] H{ + { +input+ { { f "obj" known-tag } { [ small-slot? ] "n" } } } + { +scratch+ { { f "val" } } } + { +output+ { "val" } } + } + } + ! Slot number is literal + { + [ %slot-literal-any-tag LWZ ] H{ + { +input+ { { f "obj" } { [ small-slot? ] "n" } } } + { +scratch+ { { f "scratch" } { f "val" } } } + { +output+ { "val" } } + } + } + ! Slot number in a register + { + [ %slot-any LWZX ] H{ + { +input+ { { f "obj" } { f "n" } } } + { +scratch+ { { f "val" } { f "scratch" } } } + { +output+ { "val" } } + { +clobber+ { "n" } } + } + } +} define-intrinsics + +: load-cards-offset ( dest -- ) + "cards_offset" f pick %load-dlsym dup 0 LWZ ; + +: %write-barrier ( -- ) + "val" operand-immediate? "obj" get fresh-object? or [ + "obj" operand "scratch" operand card-bits SRWI + "val" operand load-cards-offset + "scratch" operand dup "val" operand ADD + "val" operand "scratch" operand 0 LBZ + "val" operand dup card-mark ORI + "val" operand "scratch" operand 0 STB + ] unless ; + +\ set-slot { + ! Slot number is literal and tag is known + { + [ %slot-literal-known-tag STW %write-barrier ] H{ + { +input+ { { f "val" } { f "obj" known-tag } { [ small-slot? ] "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "val" } } + } + } + ! Slot number is literal + { + [ %slot-literal-any-tag STW %write-barrier ] H{ + { +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "val" } } + } + } + ! Slot number is in a register + { + [ %slot-any STWX %write-barrier ] H{ + { +input+ { { f "val" } { f "obj" } { f "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "val" "n" } } + } + } +} define-intrinsics + +\ char-slot [ + "out" operand "obj" operand MR + "n" operand dup 2 SRAWI + "n" operand "obj" operand "n" operand ADD + "out" operand "n" operand string-offset LHZ + "out" operand dup %tag-fixnum +] H{ + { +input+ { { f "n" } { f "obj" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + { +clobber+ { "n" } } +} define-intrinsic + +\ set-char-slot [ + "val" operand dup %untag-fixnum + "slot" operand dup 2 SRAWI + "slot" operand dup "obj" operand ADD + "val" operand "slot" operand string-offset STH +] H{ + { +input+ { { f "val" } { f "slot" } { f "obj" } } } + { +clobber+ { "val" "slot" } } +} define-intrinsic + +: fixnum-register-op ( op -- pair ) + [ "out" operand "y" operand "x" operand ] swap add H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } 2array ; + +: fixnum-value-op ( op -- pair ) + [ "out" operand "x" operand "y" operand ] swap add H{ + { +input+ { { f "x" } { [ small-tagged? ] "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } 2array ; + +: define-fixnum-op ( word imm-op reg-op -- ) + >r fixnum-value-op r> fixnum-register-op 2array + define-intrinsics ; + +{ + { fixnum+fast ADDI ADD } + { fixnum-fast SUBI SUBF } + { fixnum-bitand ANDI AND } + { fixnum-bitor ORI OR } + { fixnum-bitxor XORI XOR } +} [ + first3 define-fixnum-op +] each + +\ fixnum*fast { + { + [ + "out" operand "x" operand "y" get MULLI + ] H{ + { +input+ { { f "x" } { [ small-tagged? ] "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } + } { + [ + "out" operand "x" operand %untag-fixnum + "out" operand "y" operand "out" operand MULLW + ] H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } + } +} define-intrinsics + +\ fixnum-shift [ + "out" operand "x" operand "y" get neg SRAWI + ! Mask off low bits + "out" operand dup %untag +] H{ + { +input+ { { f "x" } { [ -31 0 between? ] "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +: generate-fixnum-mod + #! PowerPC doesn't have a MOD instruction; so we compute + #! x-(x/y)*y. Puts the result in "s" operand. + "s" operand "r" operand "y" operand MULLW + "s" operand "s" operand "x" operand SUBF ; + +\ fixnum-mod [ + ! divide x by y, store result in x + "r" operand "x" operand "y" operand DIVW + generate-fixnum-mod +] H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "r" } { f "s" } } } + { +output+ { "s" } } +} define-intrinsic + +\ fixnum-bitnot [ + "x" operand dup NOT + "x" operand dup %untag +] H{ + { +input+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +: fixnum-register-jump ( op -- pair ) + [ "x" operand 0 "y" operand CMP ] swap add + { { f "x" } { f "y" } } 2array ; + +: fixnum-value-jump ( op -- pair ) + [ 0 "x" operand "y" operand CMPI ] swap add + { { f "x" } { [ small-tagged? ] "y" } } 2array ; + +: define-fixnum-jump ( word op -- ) + [ fixnum-value-jump ] keep fixnum-register-jump + 2array define-if-intrinsics ; + +{ + { fixnum< BLT } + { fixnum<= BLE } + { fixnum> BGT } + { fixnum>= BGE } + { eq? BEQ } +} [ + first2 define-fixnum-jump +] each + +: %untag-fixnums ( seq -- ) + [ dup %untag-fixnum ] unique-operands ; + +: overflow-check ( insn1 insn2 -- ) + [ + >r 0 0 LI + 0 MTXER + "r" operand "y" operand "x" operand r> execute + >r + "end" define-label + "end" get BNO + { "x" "y" } %untag-fixnums + "r" operand "y" operand "x" operand r> execute + "r" get %allot-bignum-signed-1 + "end" resolve-label + ] with-scope ; inline + +: overflow-template ( word insn1 insn2 -- ) + [ overflow-check ] 2curry H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "r" } } } + { +output+ { "r" } } + { +clobber+ { "x" "y" } } + } define-intrinsic ; + +\ fixnum+ \ ADD \ ADDO. overflow-template +\ fixnum- \ SUBF \ SUBFO. overflow-template + +: generate-fixnum/i + #! This VOP is funny. If there is an overflow, it falls + #! through to the end, and the result is in "x" operand. + #! Otherwise it jumps to the "no-overflow" label and the + #! result is in "r" operand. + "end" define-label + "no-overflow" define-label + "r" operand "x" operand "y" operand DIVW + ! if the result is greater than the most positive fixnum, + ! which can only ever happen if we do + ! most-negative-fixnum -1 /i, then the result is a bignum. + most-positive-fixnum "s" operand LOAD + "r" operand 0 "s" operand CMP + "no-overflow" get BLE + most-negative-fixnum neg "x" operand LOAD + "x" get %allot-bignum-signed-1 ; + +\ fixnum/i [ + generate-fixnum/i + "end" get B + "no-overflow" resolve-label + "r" operand "x" operand %tag-fixnum + "end" resolve-label +] H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "r" } { f "s" } } } + { +output+ { "x" } } + { +clobber+ { "y" } } +} define-intrinsic + +\ fixnum/mod [ + generate-fixnum/i + 0 "s" operand LI + "end" get B + "no-overflow" resolve-label + generate-fixnum-mod + "r" operand "x" operand %tag-fixnum + "end" resolve-label +] H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "r" } { f "s" } } } + { +output+ { "x" "s" } } + { +clobber+ { "y" } } +} define-intrinsic + +\ fixnum>bignum [ + "x" operand dup %untag-fixnum + "x" get %allot-bignum-signed-1 +] H{ + { +input+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +\ bignum>fixnum [ + "nonzero" define-label + "positive" define-label + "end" define-label + "x" operand dup %untag + "y" operand "x" operand cell LWZ + ! if the length is 1, its just the sign and nothing else, + ! so output 0 + 0 "y" operand 1 v>operand CMPI + "nonzero" get BNE + 0 "y" operand LI + "end" get B + "nonzero" resolve-label + ! load the value + "y" operand "x" operand 3 cells LWZ + ! load the sign + "x" operand "x" operand 2 cells LWZ + ! is the sign negative? + 0 "x" operand 0 CMPI + "positive" get BEQ + "y" operand dup -1 MULI + "positive" resolve-label + "y" operand dup %tag-fixnum + "end" resolve-label +] H{ + { +input+ { { f "x" } } } + { +scratch+ { { f "y" } } } + { +clobber+ { "x" } } + { +output+ { "y" } } +} define-intrinsic + +: define-float-op ( word op -- ) + [ "x" operand "x" operand "y" operand ] swap add H{ + { +input+ { { float "x" } { float "y" } } } + { +output+ { "x" } } + } define-intrinsic ; + +{ + { float+ FADD } + { float- FSUB } + { float* FMUL } + { float/f FDIV } +} [ + first2 define-float-op +] each + +: define-float-jump ( word op -- ) + [ "x" operand 0 "y" operand FCMPU ] swap add + { { float "x" } { float "y" } } define-if-intrinsic ; + +{ + { float< BLT } + { float<= BLE } + { float> BGT } + { float>= BGE } + { float= BEQ } +} [ + first2 define-float-jump +] each + +\ float>fixnum [ + "scratch" operand "in" operand FCTIWZ + "scratch" operand 1 0 param@ STFD + "out" operand 1 cell param@ LWZ + "out" operand dup %tag-fixnum +] H{ + { +input+ { { float "in" } } } + { +scratch+ { { float "scratch" } { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +! \ fsqrt [ +! "y" operand "x" operand FSQRT +! ] H{ +! { +input+ { { float "x" } } } +! { +scratch+ { { float "y" } } } +! { +output+ { "y" } } +! } define-intrinsic + +\ tag [ + "out" operand "in" operand tag-mask get ANDI + "out" operand dup %tag-fixnum +] H{ + { +input+ { { f "in" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +\ type [ + "end" define-label + ! Get the tag + "y" operand "obj" operand tag-mask get ANDI + ! Tag the tag + "y" operand "x" operand %tag-fixnum + ! Compare with object tag number (3). + 0 "y" operand object tag-number CMPI + ! Jump if the object doesn't store type info in its header + "end" get BNE + ! It does store type info in its header + "x" operand "obj" operand header-offset LWZ + "end" resolve-label +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "x" } { f "y" } } } + { +output+ { "x" } } +} define-intrinsic + +\ class-hash [ + "end" define-label + "tuple" define-label + "object" define-label + ! Get the tag + "y" operand "obj" operand tag-mask get ANDI + ! Compare with tuple tag number (2). + 0 "y" operand tuple tag-number CMPI + "tuple" get BEQ + ! Compare with object tag number (3). + 0 "y" operand object tag-number CMPI + "object" get BEQ + ! Tag the tag + "y" operand "x" operand %tag-fixnum + "end" get B + "object" get resolve-label + ! Load header type + "x" operand "obj" operand header-offset LWZ + "end" get B + "tuple" get resolve-label + ! Load class hash + "x" operand "obj" operand tuple-class-offset LWZ + "x" operand dup class-hash-offset LWZ + "end" resolve-label +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "x" } { f "y" } } } + { +output+ { "x" } } +} define-intrinsic + +: userenv ( reg -- ) + #! Load the userenv pointer in a register. + "userenv" f rot %load-dlsym ; + +\ getenv [ + "n" operand dup 1 SRAWI + "x" operand userenv + "x" operand "n" operand "x" operand ADD + "x" operand dup 0 LWZ +] H{ + { +input+ { { f "n" } } } + { +scratch+ { { f "x" } } } + { +output+ { "x" } } + { +clobber+ { "n" } } +} define-intrinsic + +\ setenv [ + "n" operand dup 1 SRAWI + "x" operand userenv + "x" operand "n" operand "x" operand ADD + "val" operand "x" operand 0 STW +] H{ + { +input+ { { f "val" } { f "n" } } } + { +scratch+ { { f "x" } } } + { +clobber+ { "n" } } +} define-intrinsic + +\ [ + tuple "n" get 2 + cells %allot + ! Store length + "n" operand 12 LI + 12 11 cell STW + ! Store class + "class" operand 11 2 cells STW + ! Zero out the rest of the tuple + f v>operand 12 LI + "n" get 1- [ 12 11 rot 3 + cells STW ] each + ! Store tagged ptr in reg + "tuple" get tuple %store-tagged +] H{ + { +input+ { { f "class" } { [ inline-array? ] "n" } } } + { +scratch+ { { f "tuple" } } } + { +output+ { "tuple" } } +} define-intrinsic + +\ [ + array "n" get 2 + cells %allot + ! Store length + "n" operand 12 LI + 12 11 cell STW + ! Store initial element + "n" get [ "initial" operand 11 rot 2 + cells STW ] each + ! Store tagged ptr in reg + "array" get object %store-tagged +] H{ + { +input+ { { [ inline-array? ] "n" } { f "initial" } } } + { +scratch+ { { f "array" } } } + { +output+ { "array" } } +} define-intrinsic + +\ [ + byte-array "n" get 2 cells + %allot + ! Store length + "n" operand 12 LI + 12 11 cell STW + ! Store initial element + 0 12 LI + "n" get cell align cell /i [ 12 11 rot 2 + cells STW ] each + ! Store tagged ptr in reg + "array" get object %store-tagged +] H{ + { +input+ { { [ inline-array? ] "n" } } } + { +scratch+ { { f "array" } } } + { +output+ { "array" } } +} define-intrinsic + +\ [ + ratio 3 cells %allot + "numerator" operand 11 1 cells STW + "denominator" operand 11 2 cells STW + ! Store tagged ptr in reg + "ratio" get ratio %store-tagged +] H{ + { +input+ { { f "numerator" } { f "denominator" } } } + { +scratch+ { { f "ratio" } } } + { +output+ { "ratio" } } +} define-intrinsic + +\ [ + complex 3 cells %allot + "real" operand 11 1 cells STW + "imaginary" operand 11 2 cells STW + ! Store tagged ptr in reg + "complex" get complex %store-tagged +] H{ + { +input+ { { f "real" } { f "imaginary" } } } + { +scratch+ { { f "complex" } } } + { +output+ { "complex" } } +} define-intrinsic + +\ [ + wrapper 2 cells %allot + "obj" operand 11 1 cells STW + ! Store tagged ptr in reg + "wrapper" get object %store-tagged +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "wrapper" } } } + { +output+ { "wrapper" } } +} define-intrinsic + +\ (hashtable) [ + hashtable 4 cells %allot + f v>operand 12 LI + 12 11 1 cells STW + 12 11 2 cells STW + 12 11 3 cells STW + ! Store tagged ptr in reg + "hashtable" get object %store-tagged +] H{ + { +scratch+ { { f "hashtable" } } } + { +output+ { "hashtable" } } +} define-intrinsic + +\ string>sbuf [ + sbuf 3 cells %allot + "length" operand 11 1 cells STW + "string" operand 11 2 cells STW + ! Store tagged ptr in reg + "sbuf" get object %store-tagged +] H{ + { +input+ { { f "string" } { f "length" } } } + { +scratch+ { { f "sbuf" } } } + { +output+ { "sbuf" } } +} define-intrinsic + +\ array>vector [ + vector 3 cells %allot + "length" operand 11 1 cells STW + "array" operand 11 2 cells STW + ! Store tagged ptr in reg + "vector" get object %store-tagged +] H{ + { +input+ { { f "array" } { f "length" } } } + { +scratch+ { { f "vector" } } } + { +output+ { "vector" } } +} define-intrinsic + +\ curry [ + \ curry 3 cells %allot + "obj" operand 11 1 cells STW + "quot" operand 11 2 cells STW + ! Store tagged ptr in reg + "curry" get object %store-tagged +] H{ + { +input+ { { f "obj" } { f "quot" } } } + { +scratch+ { { f "curry" } } } + { +output+ { "curry" } } +} define-intrinsic + +! Alien intrinsics +: alien-integer-get-template + H{ + { +input+ { + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { f "output" } } } + { +output+ { "output" } } + { +clobber+ { "offset" } } + } ; + +: %alien-get ( quot -- ) + "output" get "address" set + "offset" operand dup %untag-fixnum + "output" operand "alien" operand-class %alien-accessor ; + +: %alien-integer-get ( quot -- ) + %alien-get + "output" operand dup %tag-fixnum ; inline + +: %alien-integer-set ( quot -- ) + { "offset" "value" } %untag-fixnums + "value" operand "alien" operand-class %alien-accessor ; inline + +: alien-integer-set-template + H{ + { +input+ { + { f "value" fixnum } + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { f "address" } } } + { +clobber+ { "value" "offset" } } + } ; + +: define-alien-integer-intrinsics ( word get-quot word set-quot -- ) + [ %alien-integer-set ] curry + alien-integer-set-template + define-intrinsic + [ %alien-integer-get ] curry + alien-integer-get-template + define-intrinsic ; + +\ alien-unsigned-1 [ LBZ ] +\ set-alien-unsigned-1 [ STB ] +define-alien-integer-intrinsics + +\ alien-signed-1 [ pick >r LBZ r> dup EXTSB ] +\ set-alien-signed-1 [ STB ] +define-alien-integer-intrinsics + +\ alien-unsigned-2 [ LHZ ] +\ set-alien-unsigned-2 [ STH ] +define-alien-integer-intrinsics + +\ alien-signed-2 [ LHA ] +\ set-alien-signed-2 [ STH ] +define-alien-integer-intrinsics + +: %alien-float-get ( quot -- ) + "offset" operand dup %untag-fixnum + "output" operand "alien" operand-class %alien-accessor ; inline + +: alien-float-get-template + H{ + { +input+ { + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { float "output" } { f "address" } } } + { +output+ { "output" } } + { +clobber+ { "offset" } } + } ; + +: %alien-float-set ( quot -- ) + "offset" operand dup %untag-fixnum + "value" operand "alien" operand-class %alien-accessor ; inline + +: alien-float-set-template + H{ + { +input+ { + { float "value" float } + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { f "address" } } } + { +clobber+ { "offset" } } + } ; + +: define-alien-float-intrinsics ( word get-quot word set-quot -- ) + [ %alien-float-set ] curry + alien-float-set-template + define-intrinsic + [ %alien-float-get ] curry + alien-float-get-template + define-intrinsic ; + +\ alien-double [ LFD ] +\ set-alien-double [ STFD ] +define-alien-float-intrinsics + +\ alien-float [ LFS ] +\ set-alien-float [ STFS ] +define-alien-float-intrinsics + +\ alien-cell [ + [ LWZ ] %alien-get + "output" get %allot-alien +] alien-integer-get-template define-intrinsic diff --git a/core/cpu/ppc/linux/bootstrap.factor b/core/cpu/ppc/linux/bootstrap.factor new file mode 100644 index 0000000000..32491f90a2 --- /dev/null +++ b/core/cpu/ppc/linux/bootstrap.factor @@ -0,0 +1,9 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: parser layouts system ; +IN: bootstrap.ppc + +: reserved-area-size 2 bootstrap-cells ; +: lr-save bootstrap-cell ; + +"resource:core/cpu/ppc/bootstrap.factor" run-file diff --git a/core/cpu/ppc/macosx/bootstrap.factor b/core/cpu/ppc/macosx/bootstrap.factor new file mode 100644 index 0000000000..4909c8649c --- /dev/null +++ b/core/cpu/ppc/macosx/bootstrap.factor @@ -0,0 +1,9 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: parser layouts system ; +IN: bootstrap.ppc + +: reserved-area-size 6 bootstrap-cells ; +: lr-save 2 bootstrap-cells ; + +"resource:core/cpu/ppc/bootstrap.factor" run-file diff --git a/core/cpu/ppc/ppc.factor b/core/cpu/ppc/ppc.factor new file mode 100644 index 0000000000..460ce26333 --- /dev/null +++ b/core/cpu/ppc/ppc.factor @@ -0,0 +1,15 @@ +USING: cpu.ppc.architecture cpu.ppc.intrinsics cpu.architecture +namespaces alien.c-types kernel system combinators ; + +{ + { [ macosx? ] [ + 4 "longlong" c-type set-c-type-align + 4 "ulonglong" c-type set-c-type-align + ] } + { [ os "linux" = ] [ + t "longlong" c-type set-c-type-stack-align? + t "ulonglong" c-type set-c-type-stack-align? + ] } +} cond + +T{ ppc-backend } compiler-backend set-global diff --git a/core/cpu/ppc/summary.txt b/core/cpu/ppc/summary.txt new file mode 100644 index 0000000000..9850905e2f --- /dev/null +++ b/core/cpu/ppc/summary.txt @@ -0,0 +1 @@ +32-bit PowerPC compiler backend diff --git a/core/cpu/summary.txt b/core/cpu/summary.txt new file mode 100644 index 0000000000..e2dcc9897f --- /dev/null +++ b/core/cpu/summary.txt @@ -0,0 +1 @@ +Compiler backends, emulators, and other process-specific code diff --git a/core/cpu/tags.txt b/core/cpu/tags.txt new file mode 100644 index 0000000000..86a7c8e637 --- /dev/null +++ b/core/cpu/tags.txt @@ -0,0 +1 @@ +compiler diff --git a/core/cpu/x86/32/32.factor b/core/cpu/x86/32/32.factor new file mode 100644 index 0000000000..9b7597d248 --- /dev/null +++ b/core/cpu/x86/32/32.factor @@ -0,0 +1,284 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien.c-types arrays cpu.x86.assembler +cpu.x86.architecture cpu.x86.intrinsics cpu.x86.allot +cpu.architecture kernel kernel.private math namespaces sequences +generator.registers generator.fixup generator system +math.functions alien.compiler combinators command-line +compiler io vocabs.loader ; +IN: cpu.x86.32 + +! We implement the FFI for Linux, OS X and Windows all at once. +! OS X requires that the stack be 16-byte aligned, and we do +! this on all platforms, sacrificing some stack space for +! code simplicity. + +M: x86-backend ds-reg ESI ; +M: x86-backend rs-reg EDI ; +M: x86-backend stack-reg ESP ; +M: x86-backend frame-reg EBP ; +M: x86-backend xt-reg EDX ; +M: x86-backend stack-save-reg EDX ; + +M: temp-reg v>operand drop EBX ; + +M: x86-backend %alien-invoke ( symbol dll -- ) + (CALL) rel-dlsym ; + +! On x86, parameters are never passed in registers. +M: int-regs return-reg drop EAX ; +M: int-regs param-regs drop { } ; +M: int-regs vregs drop { EAX ECX EDX EBP } ; +M: int-regs push-return-reg return-reg PUSH ; +: load/store-int-return return-reg stack-reg rot [+] ; +M: int-regs load-return-reg load/store-int-return MOV ; +M: int-regs store-return-reg load/store-int-return swap MOV ; + +M: float-regs param-regs drop { } ; +M: float-regs vregs drop { XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 } ; + +: FSTP 4 = [ FSTPS ] [ FSTPL ] if ; + +M: float-regs push-return-reg + stack-reg swap reg-size [ SUB stack-reg [] ] keep FSTP ; + +: FLD 4 = [ FLDS ] [ FLDL ] if ; + +: load/store-float-return reg-size >r stack-reg swap [+] r> ; +M: float-regs load-return-reg load/store-float-return FLD ; +M: float-regs store-return-reg load/store-float-return FSTP ; + +: align-sub ( n -- ) + dup 16 align swap - ESP swap SUB ; + +: align-add ( n -- ) + 16 align ESP swap ADD ; + +: with-aligned-stack ( n quot -- ) + swap dup align-sub slip align-add ; inline + +! On x86, we can always use an address as an operand +! directly. +M: x86-backend address-operand ; + +M: x86-backend fixnum>slot@ 1 SHR ; + +M: x86-backend prepare-division CDQ ; + +M: x86-backend load-indirect + 0 [] MOV rc-absolute-cell rel-literal ; + +M: object %load-param-reg 3drop ; + +M: object %save-param-reg 3drop ; + +M: x86-backend %prepare-unbox ( -- ) + #! Move top of data stack to EAX. + EAX ESI [] MOV + ESI 4 SUB ; + +: (%unbox) ( func -- ) + 4 [ + ! Push parameter + EAX PUSH + ! Call the unboxer + f %alien-invoke + ] with-aligned-stack ; + +M: x86-backend %unbox ( n reg-class func -- ) + #! The value being unboxed must already be in EAX. + #! If n is f, we're unboxing a return value about to be + #! returned by the callback. Otherwise, we're unboxing + #! a parameter to a C function about to be called. + (%unbox) + ! Store the return value on the C stack + over [ store-return-reg ] [ 2drop ] if ; + +M: x86-backend %unbox-long-long ( n func -- ) + (%unbox) + ! Store the return value on the C stack + [ + dup stack@ EAX MOV + cell + stack@ EDX MOV + ] when* ; + +M: x86-backend %unbox-struct-2 + #! Alien must be in EAX. + 4 [ + EAX PUSH + "alien_offset" f %alien-invoke + ! Load second cell + EDX EAX 4 [+] MOV + ! Load first cell + EAX EAX [] MOV + ] with-aligned-stack ; + +M: x86-backend %unbox-large-struct ( n size -- ) + #! Alien must be in EAX. + ! Compute destination address + ECX ESP roll [+] LEA + 12 [ + ! Push struct size + PUSH + ! Push destination address + ECX PUSH + ! Push source address + EAX PUSH + ! Copy the struct to the stack + "to_value_struct" f %alien-invoke + ] with-aligned-stack ; + +: box@ ( n reg-class -- stack@ ) + #! Used for callbacks; we want to box the values given to + #! us by the C function caller. Computes stack location of + #! nth parameter; note that we must go back one more stack + #! frame, since %box sets one up to call the one-arg boxer + #! function. The size of this stack frame so far depends on + #! the reg-class of the boxer's arg. + reg-size neg + stack-frame* + 20 + ; + +: (%box) ( n reg-class -- ) + #! If n is f, push the return register onto the stack; we + #! are boxing a return value of a C function. If n is an + #! integer, push [ESP+n] on the stack; we are boxing a + #! parameter being passed to a callback from C. + over [ [ box@ ] keep [ load-return-reg ] keep ] [ nip ] if + push-return-reg ; + +M: x86-backend %box ( n reg-class func -- ) + over reg-size [ + >r (%box) r> f %alien-invoke + ] with-aligned-stack ; + +: (%box-long-long) + #! If n is f, push the return registers onto the stack; we + #! are boxing a return value of a C function. If n is an + #! integer, push [ESP+n]:[ESP+n+4] on the stack; we are + #! boxing a parameter being passed to a callback from C. + [ + T{ int-regs } box@ + EDX over stack@ MOV + EAX swap cell - stack@ MOV + ] when* + EDX PUSH + EAX PUSH ; + +M: x86-backend %box-long-long ( n func -- ) + 8 [ + >r (%box-long-long) r> f %alien-invoke + ] with-aligned-stack ; + +M: x86-backend %box-large-struct ( n size -- ) + ! Compute destination address + [ swap struct-return@ ] keep + ECX ESP roll [+] LEA + 8 [ + ! Push struct size + PUSH + ! Push destination address + ECX PUSH + ! Copy the struct from the C stack + "box_value_struct" f %alien-invoke + ] with-aligned-stack ; + +M: x86-backend %prepare-box-struct ( size -- ) + ! Compute target address for value struct return + EAX ESP rot f struct-return@ [+] LEA + ! Store it as the first parameter + ESP [] EAX MOV ; + +M: x86-backend %unbox-struct-1 + #! Alien must be in EAX. + 4 [ + EAX PUSH + "alien_offset" f %alien-invoke + ! Load first cell + EAX EAX [] MOV + ] with-aligned-stack ; + +M: x86-backend %box-small-struct ( size -- ) + #! Box a <= 8-byte struct returned in EAX:DX. OS X only. + 12 [ + PUSH + EDX PUSH + EAX PUSH + "box_small_struct" f %alien-invoke + ] with-aligned-stack ; + +M: x86-backend %prepare-alien-indirect ( -- ) + "unbox_alien" f %alien-invoke + ESP cell temp@ [+] EAX MOV ; + +M: x86-backend %alien-indirect ( -- ) + ESP cell temp@ [+] CALL ; + +M: x86-backend %alien-callback ( quot -- ) + 4 [ + EAX load-indirect + EAX PUSH + "c_to_factor" f %alien-invoke + ] with-aligned-stack ; + +M: x86-backend %callback-value ( ctype -- ) + ! Align C stack + ESP 12 SUB + ! Save top of data stack + %prepare-unbox + EAX PUSH + ! Restore data/call/retain stacks + "unnest_stacks" f %alien-invoke + ! Place top of data stack in EAX + EAX POP + ! Restore C stack + ESP 12 ADD + ! Unbox EAX + unbox-return ; + +M: x86-backend %cleanup ( alien-node -- ) + #! a) If we just called an stdcall function in Windows, it + #! cleaned up the stack frame for us. But we don't want that + #! so we 'undo' the cleanup since we do that in %epilogue. + #! b) If we just called a function returning a struct, we + #! have to fix ESP. + { + { + [ dup alien-node-abi "stdcall" = ] + [ alien-stack-frame ESP swap SUB ] + } { + [ dup alien-node-return large-struct? ] + [ drop EAX PUSH ] + } { + [ t ] [ drop ] + } + } cond ; + +M: x86-backend %unwind ( n -- ) %epilogue-later RET ; + +windows? [ + cell "longlong" c-type set-c-type-align + cell "ulonglong" c-type set-c-type-align +] unless + +T{ x86-backend f 4 } compiler-backend set-global + +: sse2? "Intrinsic" throw ; + +\ sse2? [ + { EAX EBX ECX EDX } [ PUSH ] each + EAX 1 MOV + CPUID + EDX 26 SHR + EDX 1 AND + { EAX EBX ECX EDX } [ POP ] each + JNE +] { } define-if-intrinsic + +"-no-sse2" cli-args member? [ + "Checking if your CPU supports SSE2..." print flush + [ sse2? ] compile-1 [ + " - yes" print + "cpu.x86.sse2" require + ] [ + " - no" print + ] if +] unless diff --git a/core/cpu/x86/32/bootstrap.factor b/core/cpu/x86/32/bootstrap.factor new file mode 100644 index 0000000000..71478f4277 --- /dev/null +++ b/core/cpu/x86/32/bootstrap.factor @@ -0,0 +1,106 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: bootstrap.image.private kernel namespaces system +cpu.x86.assembler layouts vocabs ; +IN: bootstrap.x86.32 + +4 \ cell set +big-endian off + +1 jit-code-format set + +: ds-reg ESI ; +: scan-reg EBX ; +: xt-reg ECX ; +: scan-save ESP 12 [+] ; + +[ + EAX EAX quot-array@ [+] MOV ! load array + scan-reg EAX 1 [+] LEA ! initialize scan pointer +] { } make jit-setup set + +[ + EBP ESP -48 [+] LEA ! compute forward chain pointer + EBP PUSH ! save forward chain pointer + xt-reg PUSH ! save XT + EAX PUSH ! save array + ESP 16 SUB ! reserve space for scan-save +] { } make jit-prolog set + +: advance-scan scan-reg 4 ADD ; + +[ + advance-scan + ds-reg 4 ADD ! increment datastack pointer + EAX scan-reg [] MOV ! load literal + ds-reg [] EAX MOV ! store literal on datastack +] { } make jit-push-literal set + +[ + advance-scan + ds-reg 4 ADD ! increment datastack pointer + EAX scan-reg [] MOV ! load wrapper + EAX dup wrapper@ [+] MOV ! load wrapper-obj slot + ds-reg [] EAX MOV ! store literal on datastack +] { } make jit-push-wrapper set + +[ + EDX ESP MOV ! pass callstack pointer as arg 2 +] { } make jit-word-primitive-jump set + +[ + EDX ESP -4 [+] LEA ! pass callstack pointer as arg 2 +] { } make jit-word-primitive-call set + +[ + EAX scan-reg 4 [+] MOV ! load word + EAX word-xt@ [+] JMP ! jump to word XT +] { } make jit-word-jump set + +[ + advance-scan + scan-save scan-reg MOV ! save scan pointer + EAX scan-reg [] MOV ! load word + EAX word-xt@ [+] CALL ! call word XT + scan-reg scan-save MOV ! restore scan pointer +] { } make jit-word-call set + +: load-branch + EAX ds-reg [] MOV ! load boolean + ds-reg 4 SUB ! pop boolean + EAX \ f tag-number CMP ! compare it with f + EAX scan-reg 8 [+] CMOVE ! load false branch if equal + EAX scan-reg 4 [+] CMOVNE ! load true branch if not equal + scan-reg 12 ADD ! advance scan pointer + xt-reg EAX quot-xt@ [+] MOV ! load quotation-xt + ; + +[ + load-branch + xt-reg JMP +] { } make jit-if-jump set + +[ + load-branch + ESP [] scan-reg MOV ! save scan pointer + xt-reg CALL ! call quotation + scan-reg ESP [] MOV ! restore scan pointer +] { } make jit-if-call set + +[ + EAX ds-reg [] MOV ! load index + EAX 1 SAR ! turn it into an array offset + ds-reg 4 SUB ! pop index + EAX scan-reg 4 [+] ADD ! compute quotation location + EAX EAX array-start [+] MOV ! load quotation + xt-reg EAX quot-xt@ [+] MOV ! load quotation-xt + xt-reg JMP ! execute quotation +] { } make jit-dispatch set + +[ + ESP 28 ADD ! unwind stack frame +] { } make jit-epilog set + +[ 0 RET ] { } make jit-return set + +"bootstrap.x86.32" forget-vocab diff --git a/core/cpu/x86/64/64.factor b/core/cpu/x86/64/64.factor new file mode 100644 index 0000000000..1625a563f2 --- /dev/null +++ b/core/cpu/x86/64/64.factor @@ -0,0 +1,175 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien.c-types arrays cpu.x86.assembler +cpu.x86.architecture cpu.x86.intrinsics cpu.x86.sse2 +cpu.x86.allot cpu.architecture kernel kernel.private math +namespaces sequences generator.registers generator.fixup system +alien ; +IN: cpu.x86.64 + +PREDICATE: x86-backend amd64-backend + x86-backend-cell 8 = ; + +M: amd64-backend ds-reg R14 ; +M: amd64-backend rs-reg R15 ; +M: amd64-backend stack-reg RSP ; + +M: temp-reg v>operand drop R11 ; + +M: int-regs return-reg drop RAX ; +M: int-regs vregs drop { RAX RCX RDX RSI RDI RBP R8 R9 R10 } ; +M: int-regs param-regs drop { RDI RSI RDX RCX R8 R9 } ; + +M: float-regs return-reg drop XMM0 ; + +M: float-regs vregs + drop { + XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 + XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15 + } ; + +M: float-regs param-regs + drop { XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 } ; + +M: amd64-backend address-operand ( address -- operand ) + #! On AMD64, we have to load 64-bit addresses into a + #! scratch register first. The usage of R11 here is a hack. + #! This word can only be called right before a subroutine + #! call, where all vregs have been flushed anyway. + temp-reg v>operand [ swap MOV ] keep ; + +: compile-c-call ( symbol dll -- ) + 0 address-operand >r rc-absolute-cell rel-dlsym r> CALL ; + +M: amd64-backend fixnum>slot@ drop ; + +M: amd64-backend prepare-division CQO ; + +M: amd64-backend load-indirect ( literal reg -- ) + 0 [] MOV rc-relative rel-literal ; + +M: stack-params %load-param-reg + drop + >r temp-reg v>operand swap stack@ MOV + r> stack@ temp-reg v>operand MOV ; + +M: stack-params %save-param-reg + >r stack-frame* + cell + swap r> %load-param-reg ; + +M: amd64-backend %prepare-unbox ( -- ) + ! First parameter is top of stack + RDI R14 [] MOV + R14 cell SUB ; + +M: amd64-backend %unbox ( n reg-class func -- ) + ! Call the unboxer + f compile-c-call + ! Store the return value on the C stack + over [ [ return-reg ] keep %save-param-reg ] [ 2drop ] if ; + +M: amd64-backend %unbox-long-long ( n func -- ) + T{ int-regs } swap %unbox ; + +M: amd64-backend %unbox-struct-1 ( -- ) + #! Alien must be in RDI. + "alien_offset" f compile-c-call + ! Load first cell + RAX RAX [] MOV ; + +M: amd64-backend %unbox-struct-2 ( -- ) + #! Alien must be in RDI. + "alien_offset" f compile-c-call + ! Load second cell + RDX RAX cell [+] MOV + ! Load first cell + RAX RAX [] MOV ; + +M: amd64-backend %unbox-large-struct ( n size -- ) + ! Source is in RDI + ! Load destination address + RSI RSP roll [+] LEA + ! Load structure size + RDX swap MOV + ! Copy the struct to the C stack + "to_value_struct" f compile-c-call ; + +: load-return-value ( reg-class -- ) + 0 over param-reg swap return-reg + 2dup eq? [ 2drop ] [ MOV ] if ; + +M: amd64-backend %box ( n reg-class func -- ) + rot [ + rot [ 0 swap param-reg ] keep %load-param-reg + ] [ + swap load-return-value + ] if* + f compile-c-call ; + +M: amd64-backend %box-long-long ( n func -- ) + T{ int-regs } swap %box ; + +M: amd64-backend struct-small-enough? ( size -- ? ) 2 cells <= ; + +M: amd64-backend %box-small-struct ( size -- ) + #! Box a <= 16-byte struct returned in RAX:RDX. + RDI RAX MOV + RSI RDX MOV + RDX swap MOV + "box_small_struct" f compile-c-call ; + +M: amd64-backend %box-large-struct ( n size -- ) + ! Struct size is parameter 2 + RSI over MOV + ! Compute destination address + swap struct-return@ RDI RSP rot [+] LEA + ! Copy the struct from the C stack + "box_value_struct" f compile-c-call ; + +M: amd64-backend %prepare-box-struct ( size -- ) + ! Compute target address for value struct return + RAX RSP rot f struct-return@ [+] LEA + RSP 0 [+] RAX MOV ; + +: reset-sse RAX RAX XOR ; + +M: amd64-backend %alien-invoke ( symbol dll -- ) + reset-sse compile-c-call ; + +M: amd64-backend %prepare-alien-indirect ( -- ) + "unbox_alien" f compile-c-call + cell temp@ RAX MOV ; + +M: amd64-backend %alien-indirect ( -- ) + reset-sse + cell temp@ CALL ; + +M: amd64-backend %alien-callback ( quot -- ) + RDI load-indirect "run_callback" f compile-c-call ; + +M: amd64-backend %callback-value ( ctype -- ) + ! Save top of data stack + %prepare-unbox + ! Put former top of data stack in RDI + temp@ RDI MOV + ! Restore data/call/retain stacks + "unnest_stacks" f %alien-invoke + ! Put former top of data stack in RDI + RDI temp@ MOV + ! Unbox former top of data stack to return registers + unbox-return ; + +M: amd64-backend %cleanup ( alien-node -- ) drop ; + +M: amd64-backend %unwind ( n -- ) drop %epilogue-later 0 RET ; + +USE: cpu.x86.intrinsics + +! On 64-bit systems, the result of reading 4 bytes from memory +! is a fixnum. +\ alien-unsigned-4 small-reg-32 define-unsigned-getter +\ set-alien-unsigned-4 small-reg-32 define-setter + +\ alien-signed-4 small-reg-32 define-signed-getter +\ set-alien-signed-4 small-reg-32 define-setter + +T{ x86-backend f 8 } compiler-backend set-global diff --git a/core/cpu/x86/64/authors.txt b/core/cpu/x86/64/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/x86/64/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/x86/64/bootstrap.factor b/core/cpu/x86/64/bootstrap.factor new file mode 100644 index 0000000000..bccdcbd7f1 --- /dev/null +++ b/core/cpu/x86/64/bootstrap.factor @@ -0,0 +1,4 @@ +USING: bootstrap.image.private kernel namespaces system ; + +8 \ cell set +big-endian off diff --git a/core/cpu/x86/64/summary.txt b/core/cpu/x86/64/summary.txt new file mode 100644 index 0000000000..81fce29cbb --- /dev/null +++ b/core/cpu/x86/64/summary.txt @@ -0,0 +1 @@ +64-bit x86 compiler backend diff --git a/core/cpu/x86/allot/allot.factor b/core/cpu/x86/allot/allot.factor new file mode 100644 index 0000000000..c6989615b2 --- /dev/null +++ b/core/cpu/x86/allot/allot.factor @@ -0,0 +1,97 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel cpu.architecture cpu.x86.assembler +cpu.x86.architecture kernel.private namespaces math +math.functions sequences generic arrays generator +generator.fixup generator.registers system layouts alien ; +IN: cpu.x86.allot + +: (object@) ( n -- operand ) temp-reg v>operand swap [+] ; + +: object@ ( n -- operand ) cells (object@) ; + +: load-zone-ptr ( -- ) + #! Load pointer to start of zone array + "nursery" f %alien-global ; + +: load-allot-ptr ( -- ) + load-zone-ptr + temp-reg v>operand dup cell [+] MOV ; + +: inc-allot-ptr ( n -- ) + load-zone-ptr + temp-reg v>operand cell [+] swap 8 align ADD ; + +: store-header ( header -- ) + 0 object@ swap type-number tag-header MOV ; + +: %allot ( header size quot -- ) + swap >r >r + load-allot-ptr + store-header + r> call + r> inc-allot-ptr ; inline + +: %store-tagged ( reg tag -- ) + >r dup fresh-object v>operand r> + temp-reg v>operand swap tag-number OR + temp-reg v>operand MOV ; + +M: x86-backend %move-float>int ( dst src -- ) + #! Only called by pentium4 backend, uses SSE2 instruction + #! dest is a loc or a vreg + float 16 [ + 8 (object@) swap v>operand MOVSD + float %store-tagged + ] %allot ; + +: %allot-bignum-signed-1 ( outreg inreg -- ) + #! on entry, inreg is a signed 32-bit quantity + #! exits with tagged ptr to bignum in outreg + #! 1 cell header, 1 cell length, 1 cell sign, + digits + #! length is the # of digits + sign + [ + { "end" "nonzero" "positive" "store" } + [ define-label ] each + dup v>operand 0 CMP ! is it zero? + "nonzero" get JNE + 0 >bignum pick load-literal ! this is our result + "end" get JMP + "nonzero" resolve-label + bignum 4 cells [ + ! Write length + 1 object@ 2 v>operand MOV + ! Test sign + dup v>operand 0 CMP + "positive" get JGE + 2 object@ 1 MOV ! negative sign + dup v>operand NEG + "store" get JMP + "positive" resolve-label + 2 object@ 0 MOV ! positive sign + "store" resolve-label + 3 object@ swap v>operand MOV + ! Store tagged ptr in reg + bignum %store-tagged + ] %allot + "end" resolve-label + ] with-scope ; + +: %allot-alien ( ptr -- ) + [ + "temp" set + { "end" "f" } [ define-label ] each + "temp" operand 0 CMP + "f" get JE + alien 4 cells [ + 1 object@ f v>operand MOV + 2 object@ f v>operand MOV + 3 object@ "temp" operand MOV + ! Store tagged ptr in reg + "temp" get object %store-tagged + ] %allot + "end" get JMP + "f" resolve-label + "temp" operand f v>operand MOV + "end" resolve-label + ] with-scope ; diff --git a/core/cpu/x86/architecture/architecture.factor b/core/cpu/x86/architecture/architecture.factor new file mode 100644 index 0000000000..df570c67e4 --- /dev/null +++ b/core/cpu/x86/architecture/architecture.factor @@ -0,0 +1,207 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien alien.c-types alien.compiler arrays +cpu.x86.assembler cpu.architecture kernel kernel.private math +math.functions memory namespaces sequences words generator +generator.registers generator.fixup system layouts combinators ; +IN: cpu.x86.architecture + +TUPLE: x86-backend cell ; + +HOOK: ds-reg compiler-backend +HOOK: rs-reg compiler-backend +HOOK: stack-reg compiler-backend +HOOK: frame-reg compiler-backend +HOOK: xt-reg compiler-backend +HOOK: stack-save-reg compiler-backend + +: stack@ stack-reg swap [+] ; + +: reg-stack ( n reg -- op ) swap cells neg [+] ; + +M: ds-loc v>operand ds-loc-n ds-reg reg-stack ; +M: rs-loc v>operand rs-loc-n rs-reg reg-stack ; + +M: int-regs %save-param-reg drop >r stack@ r> MOV ; +M: int-regs %load-param-reg drop swap stack@ MOV ; + +: MOVSS/D float-regs-size 4 = [ MOVSS ] [ MOVSD ] if ; + +M: float-regs %save-param-reg >r >r stack@ r> r> MOVSS/D ; +M: float-regs %load-param-reg >r swap stack@ r> MOVSS/D ; + +GENERIC: push-return-reg ( reg-class -- ) +GENERIC: load-return-reg ( stack@ reg-class -- ) +GENERIC: store-return-reg ( stack@ reg-class -- ) + +HOOK: address-operand compiler-backend ( address -- operand ) + +HOOK: fixnum>slot@ compiler-backend + +HOOK: prepare-division compiler-backend + +M: immediate load-literal v>operand swap v>operand MOV ; + +M: x86-backend stack-frame ( n -- i ) + 3 cells + 16 align cell - ; + +M: x86-backend %save-xt ( -- ) + xt-reg compiling-label get MOV ; + +M: x86-backend %prologue ( n -- ) + frame-reg stack-reg pick stack-frame 5 cells + neg [+] LEA + frame-reg PUSH + xt-reg PUSH + stack-reg swap stack-frame 2 cells - SUB ; + +M: x86-backend %epilogue ( n -- ) + stack-reg swap stack-frame ADD ; + +: %alien-global ( symbol dll -- ) + temp-reg v>operand 0 MOV rc-absolute-cell rel-dlsym + temp-reg v>operand dup [] MOV ; + +M: x86-backend %prepare-alien-invoke + #! Save Factor stack pointers in case the C code calls a + #! callback which does a GC, which must reliably trace + #! all roots. + "stack_chain" f %alien-global + temp-reg v>operand [] stack-reg MOV + temp-reg v>operand 2 cells [+] ds-reg MOV + temp-reg v>operand 3 cells [+] rs-reg MOV ; + +M: x86-backend %profiler-prologue ( word -- ) + "end" define-label + "profiling" f %alien-global + temp-reg v>operand 0 CMP + "end" get JE + temp-reg load-literal + temp-reg v>operand profile-count-offset [+] 1 v>operand ADD + "end" resolve-label ; + +M: x86-backend %call-label ( label -- ) CALL ; + +M: x86-backend %jump-label ( label -- ) JMP ; + +: %prepare-primitive ( word -- operand ) + ! Save stack pointer to stack_chain->callstack_top, load XT + ! in register + stack-save-reg stack-reg MOV address-operand ; + +M: x86-backend %call-primitive ( word -- ) + stack-save-reg stack-reg cell neg [+] LEA + address-operand CALL ; + +M: x86-backend %jump-primitive ( word -- ) + stack-save-reg stack-reg MOV + address-operand JMP ; + +M: x86-backend %jump-t ( label -- ) + "flag" operand f v>operand CMP JNE ; + +: (%dispatch) ( word-table# -- ) + ! Untag and multiply to get a jump table offset + "n" operand fixnum>slot@ + ! Add to jump table base. We use a temporary register + ! since on AMD64 we have to load a 64-bit immediate. On + ! x86, this is redundant. + "scratch" operand HEX: ffffffff MOV rc-absolute-cell rel-dispatch + "n" operand "scratch" operand ADD ; + +: dispatch-template ( word-table# quot -- ) + [ + >r (%dispatch) "n" operand [] r> call + ] H{ + { +input+ { { f "n" } } } + { +scratch+ { { f "scratch" } } } + } with-template ; inline + +M: x86-backend %call-dispatch ( word-table# -- ) + [ CALL ] dispatch-template ; + +M: x86-backend %jump-dispatch ( word-table# -- ) + [ %epilogue-later JMP ] dispatch-template ; + +M: x86-backend %move-int>int ( dst src -- ) + [ v>operand ] 2apply MOV ; + +M: x86-backend %move-int>float ( dst src -- ) + [ v>operand ] 2apply float-offset [+] MOVSD ; + +M: int-regs (%peek) drop %move-int>int ; + +M: int-regs (%replace) drop swap %move-int>int ; + +: (%inc) swap cells dup 0 > [ ADD ] [ neg SUB ] if ; + +M: x86-backend %inc-d ( n -- ) ds-reg (%inc) ; + +M: x86-backend %inc-r ( n -- ) rs-reg (%inc) ; + +M: x86-backend fp-shadows-int? ( -- ? ) f ; + +M: x86-backend value-structs? t ; + +M: x86-backend small-enough? ( n -- ? ) + HEX: -80000000 HEX: 7fffffff between? ; + +: %untag ( reg -- ) tag-mask get bitnot AND ; + +: %untag-fixnum ( reg -- ) tag-bits get SAR ; + +: %tag-fixnum ( reg -- ) tag-bits get SHL ; + +: temp@ \ stack-frame get swap - ; + +: struct-return@ ( size n -- n ) + [ + stack-frame* cell + + + ] [ + temp@ + ] ?if ; + +HOOK: %unbox-struct-1 compiler-backend ( -- ) + +HOOK: %unbox-struct-2 compiler-backend ( -- ) + +M: x86-backend %unbox-small-struct ( size -- ) + #! Alien must be in EAX. + cell align cell / { + { 1 [ %unbox-struct-1 ] } + { 2 [ %unbox-struct-2 ] } + } case ; + +M: x86-backend struct-small-enough? ( size -- ? ) + { 1 2 4 8 } member? + os { "linux" "solaris" } member? not and ; + +M: x86-backend %return ( -- ) 0 %unwind ; + +! Alien intrinsics +M: x86-backend %unbox-byte-array ( quot src -- ) + "alien" operand "offset" operand ADD + "alien" operand byte-array-offset [+] + rot call ; + +M: x86-backend %unbox-alien ( quot src -- ) + "alien" operand dup alien-offset [+] MOV + "alien" operand "offset" operand [+] + rot call ; + +M: x86-backend %unbox-f ( quot src -- ) + "offset" operand rot call ; + +M: x86-backend %complex-alien-accessor ( quot src -- ) + { "is-f" "is-alien" "end" } [ define-label ] each + "alien" operand f v>operand CMP + "is-f" get JE + "alien" operand header-offset [+] alien type-number tag-header CMP + "is-alien" get JE + [ %unbox-byte-array ] 2keep + "end" get JMP + "is-alien" resolve-label + [ %unbox-alien ] 2keep + "end" get JMP + "is-f" resolve-label + %unbox-f + "end" resolve-label ; diff --git a/core/cpu/x86/assembler/assembler-tests.factor b/core/cpu/x86/assembler/assembler-tests.factor new file mode 100644 index 0000000000..256bc57578 --- /dev/null +++ b/core/cpu/x86/assembler/assembler-tests.factor @@ -0,0 +1,38 @@ +USING: cpu.x86.assembler kernel tools.test namespaces ; +IN: temporary + +[ { HEX: 49 HEX: 89 HEX: 04 HEX: 24 } ] [ [ R12 [] RAX MOV ] { } make ] unit-test +[ { HEX: 49 HEX: 8b HEX: 06 } ] [ [ RAX R14 [] MOV ] { } make ] unit-test + +! [ { HEX: 89 HEX: ca } ] [ [ EDX ECX MOV ] { } make ] unit-test +! [ { HEX: 4c HEX: 89 HEX: e2 } ] [ [ RDX R12 MOV ] { } make ] unit-test +! [ { HEX: 49 HEX: 89 HEX: d4 } ] [ [ R12 RDX MOV ] { } make ] unit-test + +[ { HEX: f2 HEX: 0f HEX: 2c HEX: c0 } ] [ [ EAX XMM0 CVTTSD2SI ] { } make ] unit-test +[ { HEX: f2 HEX: 48 HEX: 0f HEX: 2c HEX: c0 } ] [ [ RAX XMM0 CVTTSD2SI ] { } make ] unit-test +[ { HEX: f2 HEX: 4c HEX: 0f HEX: 2c HEX: e0 } ] [ [ R12 XMM0 CVTTSD2SI ] { } make ] unit-test +[ { HEX: f2 HEX: 0f HEX: 2a HEX: c0 } ] [ [ XMM0 EAX CVTSI2SD ] { } make ] unit-test +[ { HEX: f2 HEX: 48 HEX: 0f HEX: 2a HEX: c0 } ] [ [ XMM0 RAX CVTSI2SD ] { } make ] unit-test +[ { HEX: f2 HEX: 48 HEX: 0f HEX: 2a HEX: c1 } ] [ [ XMM0 RCX CVTSI2SD ] { } make ] unit-test +[ { HEX: f2 HEX: 48 HEX: 0f HEX: 2a HEX: d9 } ] [ [ XMM3 RCX CVTSI2SD ] { } make ] unit-test +[ { HEX: f2 HEX: 48 HEX: 0f HEX: 2a HEX: c0 } ] [ [ XMM0 RAX CVTSI2SD ] { } make ] unit-test +[ { HEX: f2 HEX: 49 HEX: 0f HEX: 2a HEX: c4 } ] [ [ XMM0 R12 CVTSI2SD ] { } make ] unit-test + +! [ { HEX: f2 HEX: 49 HEX: 0f HEX: 2c HEX: c1 } ] [ [ XMM9 RAX CVTSI2SD ] { } make ] unit-test + +! [ { HEX: f2 HEX: 0f HEX: 10 HEX: 00 } ] [ [ XMM0 RAX [] MOVSD ] { } make ] unit-test +! [ { HEX: f2 HEX: 41 HEX: 0f HEX: 10 HEX: 04 HEX: 24 } ] [ [ XMM0 R12 [] MOVSD ] { } make ] unit-test +! [ { HEX: f2 HEX: 0f HEX: 11 HEX: 00 } ] [ [ RAX [] XMM0 MOVSD ] { } make ] unit-test +! [ { HEX: f2 HEX: 41 HEX: 0f HEX: 11 HEX: 04 HEX: 24 } ] [ [ R12 [] XMM0 MOVSD ] { } make ] unit-test + +[ { HEX: 8a HEX: 18 } ] [ [ BL RAX [] MOV ] { } make ] unit-test +[ { HEX: 66 HEX: 8b HEX: 18 } ] [ [ BX RAX [] MOV ] { } make ] unit-test +[ { HEX: 8b HEX: 18 } ] [ [ EBX RAX [] MOV ] { } make ] unit-test +[ { HEX: 48 HEX: 8b HEX: 18 } ] [ [ RBX RAX [] MOV ] { } make ] unit-test +[ { HEX: 88 HEX: 18 } ] [ [ RAX [] BL MOV ] { } make ] unit-test +[ { HEX: 66 HEX: 89 HEX: 18 } ] [ [ RAX [] BX MOV ] { } make ] unit-test +[ { HEX: 89 HEX: 18 } ] [ [ RAX [] EBX MOV ] { } make ] unit-test +[ { HEX: 48 HEX: 89 HEX: 18 } ] [ [ RAX [] RBX MOV ] { } make ] unit-test + +[ { HEX: 0f HEX: be HEX: c3 } ] [ [ EAX BL MOVSX ] { } make ] unit-test +[ { HEX: 0f HEX: bf HEX: c3 } ] [ [ EAX BX MOVSX ] { } make ] unit-test diff --git a/core/cpu/x86/assembler/assembler.factor b/core/cpu/x86/assembler/assembler.factor new file mode 100644 index 0000000000..5e40fe4f49 --- /dev/null +++ b/core/cpu/x86/assembler/assembler.factor @@ -0,0 +1,498 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generator generator.fixup io.binary kernel +combinators kernel.private math namespaces parser sequences +words system ; +IN: cpu.x86.assembler + +! A postfix assembler for x86 and AMD64. + +! In 32-bit mode, { 1234 } is absolute indirect addressing. +! In 64-bit mode, { 1234 } is RIP-relative. +! Beware! + +! Register operands -- eg, ECX +: define-register ( symbol num size -- ) + >r dupd "register" set-word-prop r> + "register-size" set-word-prop ; + +! x86 registers +SYMBOL: AL \ AL 0 8 define-register +SYMBOL: CL \ CL 1 8 define-register +SYMBOL: DL \ DL 2 8 define-register +SYMBOL: BL \ BL 3 8 define-register + +SYMBOL: AX \ AX 0 16 define-register +SYMBOL: CX \ CX 1 16 define-register +SYMBOL: DX \ DX 2 16 define-register +SYMBOL: BX \ BX 3 16 define-register +SYMBOL: SP \ SP 4 16 define-register +SYMBOL: BP \ BP 5 16 define-register +SYMBOL: SI \ SI 6 16 define-register +SYMBOL: DI \ DI 7 16 define-register + +SYMBOL: EAX \ EAX 0 32 define-register +SYMBOL: ECX \ ECX 1 32 define-register +SYMBOL: EDX \ EDX 2 32 define-register +SYMBOL: EBX \ EBX 3 32 define-register +SYMBOL: ESP \ ESP 4 32 define-register +SYMBOL: EBP \ EBP 5 32 define-register +SYMBOL: ESI \ ESI 6 32 define-register +SYMBOL: EDI \ EDI 7 32 define-register + +SYMBOL: XMM0 \ XMM0 0 128 define-register +SYMBOL: XMM1 \ XMM1 1 128 define-register +SYMBOL: XMM2 \ XMM2 2 128 define-register +SYMBOL: XMM3 \ XMM3 3 128 define-register +SYMBOL: XMM4 \ XMM4 4 128 define-register +SYMBOL: XMM5 \ XMM5 5 128 define-register +SYMBOL: XMM6 \ XMM6 6 128 define-register +SYMBOL: XMM7 \ XMM7 7 128 define-register + +! AMD64 registers +SYMBOL: RAX \ RAX 0 64 define-register +SYMBOL: RCX \ RCX 1 64 define-register +SYMBOL: RDX \ RDX 2 64 define-register +SYMBOL: RBX \ RBX 3 64 define-register +SYMBOL: RSP \ RSP 4 64 define-register +SYMBOL: RBP \ RBP 5 64 define-register +SYMBOL: RSI \ RSI 6 64 define-register +SYMBOL: RDI \ RDI 7 64 define-register +SYMBOL: R8 \ R8 8 64 define-register +SYMBOL: R9 \ R9 9 64 define-register +SYMBOL: R10 \ R10 10 64 define-register +SYMBOL: R11 \ R11 11 64 define-register +SYMBOL: R12 \ R12 12 64 define-register +SYMBOL: R13 \ R13 13 64 define-register +SYMBOL: R14 \ R14 14 64 define-register +SYMBOL: R15 \ R15 15 64 define-register + +SYMBOL: XMM8 \ XMM8 8 128 define-register +SYMBOL: XMM9 \ XMM9 9 128 define-register +SYMBOL: XMM10 \ XMM10 10 128 define-register +SYMBOL: XMM11 \ XMM11 11 128 define-register +SYMBOL: XMM12 \ XMM12 12 128 define-register +SYMBOL: XMM13 \ XMM13 13 128 define-register +SYMBOL: XMM14 \ XMM14 14 128 define-register +SYMBOL: XMM15 \ XMM15 15 128 define-register + +le % ; inline +: 4, 4 n, ; inline +: 2, 2 n, ; inline +: cell, cell n, ; inline + +#! Extended AMD64 registers (R8-R15) return true. +GENERIC: extended? ( op -- ? ) + +M: object extended? drop f ; + +PREDICATE: word register "register" word-prop ; + +PREDICATE: register register-8 "register-size" word-prop 8 = ; +PREDICATE: register register-16 "register-size" word-prop 16 = ; +PREDICATE: register register-32 "register-size" word-prop 32 = ; +PREDICATE: register register-64 "register-size" word-prop 64 = ; +PREDICATE: register register-128 "register-size" word-prop 128 = ; + +M: register extended? "register" word-prop 7 > ; + +! Addressing modes +TUPLE: indirect base index scale displacement ; + +M: indirect extended? indirect-base extended? ; + +: canonicalize-EBP + #! { EBP } ==> { EBP 0 } + dup indirect-base { EBP RBP R13 } memq? [ + dup indirect-displacement [ + drop + ] [ + 0 swap set-indirect-displacement + ] if + ] [ + drop + ] if ; + +: canonicalize-ESP + #! { ESP } ==> { ESP ESP } + dup indirect-base { ESP RSP R12 } memq? [ + ESP swap set-indirect-index + ] [ + drop + ] if ; + +: canonicalize ( indirect -- ) + #! Modify the indirect to work around certain addressing mode + #! quirks. + dup canonicalize-EBP + canonicalize-ESP ; + +: ( base index scale displacement -- indirect ) + indirect construct-boa dup canonicalize ; + +: reg-code "register" word-prop 7 bitand ; + +: indirect-base* indirect-base EBP or reg-code ; + +: indirect-index* indirect-index ESP or reg-code ; + +: indirect-scale* indirect-scale 0 or ; + +GENERIC: sib-present? ( op -- ? ) + +M: indirect sib-present? + dup indirect-base { ESP RSP } memq? + over indirect-index rot indirect-scale or or ; + +M: register sib-present? drop f ; + +GENERIC: r/m ( operand -- n ) + +M: indirect r/m + dup sib-present? + [ drop ESP reg-code ] [ indirect-base* ] if ; + +M: register r/m reg-code ; + +: byte? -128 127 between? ; + +GENERIC: modifier ( op -- n ) + +M: indirect modifier + dup indirect-base [ + indirect-displacement { + { [ dup not ] [ BIN: 00 ] } + { [ dup byte? ] [ BIN: 01 ] } + { [ dup integer? ] [ BIN: 10 ] } + } cond nip + ] [ + drop BIN: 00 + ] if ; + +M: register modifier drop BIN: 11 ; + +: mod-r/m, ( reg# indirect -- ) + dup modifier 6 shift rot 3 shift rot r/m bitor bitor , ; + +: sib, ( indirect -- ) + dup sib-present? [ + dup indirect-base* + over indirect-index* 3 shift bitor + swap indirect-scale* 6 shift bitor , + ] [ + drop + ] if ; + +GENERIC: displacement, ( op -- ) + +M: indirect displacement, + dup indirect-displacement dup [ + swap indirect-base + [ dup byte? [ , ] [ 4, ] if ] [ 4, ] if + ] [ + 2drop + ] if ; + +M: register displacement, drop ; + +: addressing ( reg# indirect -- ) + [ mod-r/m, ] keep [ sib, ] keep displacement, ; + +! Utilities +UNION: operand register indirect ; + +: operand-64? ( operand -- ? ) + dup indirect? [ + dup indirect-base register-64? + swap indirect-index register-64? or + ] [ + register-64? + ] if ; + +: rex.w? ( rex.w reg r/m -- ? ) + { + { [ dup register-128? ] [ drop operand-64? ] } + { [ dup not ] [ drop operand-64? ] } + { [ t ] [ nip operand-64? ] } + } cond and ; + +: rex.r + extended? [ BIN: 00000100 bitor ] when ; + +: rex.b + [ extended? [ BIN: 00000001 bitor ] when ] keep + dup indirect? [ + indirect-index extended? + [ BIN: 00000010 bitor ] when + ] [ + drop + ] if ; + +: rex-prefix ( reg r/m rex.w -- ) + #! Compile an AMD64 REX prefix. + pick pick rex.w? BIN: 01001000 BIN: 01000000 ? + swap rex.r swap rex.b + dup BIN: 01000000 = [ drop ] [ , ] if ; + +: 16-prefix ( reg r/m -- ) + [ register-16? ] either? [ HEX: 66 , ] when ; + +: prefix ( reg r/m rex.w -- ) pick pick 16-prefix rex-prefix ; + +: prefix-1 ( reg rex.w -- ) f swap prefix ; + +: short-operand ( reg rex.w n -- ) + #! Some instructions encode their single operand as part of + #! the opcode. + >r dupd prefix-1 reg-code r> + , ; + +: opcode, dup array? [ % ] [ , ] if ; + +: extended-opcode ( opcode -- opcode' ) OCT: 17 swap 2array ; + +: extended-opcode, ( opcode -- ) extended-opcode opcode, ; + +: opcode-or ( opcode mask -- opcode' ) + over array? + [ 1 rot cut* first rot bitor add ] + [ bitor ] if ; + +: 1-operand ( op reg rex.w opcode -- ) + #! The 'reg' is not really a register, but a value for the + #! 'reg' field of the mod-r/m byte. + >r >r over r> prefix-1 r> opcode, swap addressing ; + +: immediate-1 ( imm dst reg rex.w opcode -- ) + 1-operand , ; + +: immediate-1/4 ( imm dst reg rex.w opcode -- ) + #! If imm is a byte, compile the opcode and the byte. + #! Otherwise, set the 32-bit operand flag in the opcode, and + #! compile the cell. The 'reg' is not really a register, but + #! a value for the 'reg' field of the mod-r/m byte. + >r >r pick byte? [ + r> r> BIN: 10 opcode-or immediate-1 + ] [ + r> r> 1-operand 4, + ] if ; + +: (2-operand) ( dst src op -- ) + >r 2dup t rex-prefix r> opcode, + reg-code swap addressing ; + +: direction-bit ( dst src op -- dst' src' op' ) + pick register? [ BIN: 10 opcode-or swapd ] when ; + +: operand-size-bit ( dst src op -- dst' src' op' ) + over register-8? [ BIN: 1 opcode-or ] unless ; + +: 2-operand ( dst src op -- ) + #! Sets the opcode's direction bit. It is set if the + #! destination is a direct register operand. + pick pick 16-prefix + direction-bit + operand-size-bit + (2-operand) ; + +PRIVATE> + +: [] ( reg/displacement -- indirect ) + dup integer? [ >r f f f r> ] [ f f f ] if ; + +: [+] ( reg displacement -- indirect ) + dup integer? + [ dup zero? [ drop f ] when >r f f r> ] + [ f f ] if + ; + +! Moving stuff +GENERIC: PUSH ( op -- ) +M: register PUSH f HEX: 50 short-operand ; +M: integer PUSH HEX: 68 , 4, ; +M: operand PUSH BIN: 110 f HEX: ff 1-operand ; + +GENERIC: POP ( op -- ) +M: register POP f HEX: 58 short-operand ; +M: operand POP BIN: 000 f HEX: 8f 1-operand ; + +! MOV where the src is immediate. +GENERIC: (MOV-I) ( src dst -- ) +M: register (MOV-I) t HEX: b8 short-operand cell, ; +M: operand (MOV-I) BIN: 000 t HEX: c7 1-operand 4, ; + +PREDICATE: word callable register? not ; + +GENERIC: MOV ( dst src -- ) +M: integer MOV swap (MOV-I) ; +M: callable MOV 0 rot (MOV-I) rc-absolute-cell rel-word ; +M: operand MOV HEX: 88 2-operand ; + +: LEA ( dst src -- ) swap HEX: 8d 2-operand ; + +! Control flow +GENERIC: JMP ( op -- ) +: (JMP) HEX: e9 , 0 4, rc-relative ; +M: callable JMP (JMP) rel-word ; +M: label JMP (JMP) label-fixup ; +M: operand JMP BIN: 100 t HEX: ff 1-operand ; + +GENERIC: CALL ( op -- ) +: (CALL) HEX: e8 , 0 4, rc-relative ; +M: callable CALL (CALL) rel-word ; +M: label CALL (CALL) label-fixup ; +M: operand CALL BIN: 010 t HEX: ff 1-operand ; + +GENERIC# JUMPcc 1 ( addr opcode -- ) +: (JUMPcc) extended-opcode, 0 4, rc-relative ; +M: callable JUMPcc (JUMPcc) rel-word ; +M: label JUMPcc (JUMPcc) label-fixup ; + +: JO HEX: 80 JUMPcc ; +: JNO HEX: 81 JUMPcc ; +: JB HEX: 82 JUMPcc ; +: JAE HEX: 83 JUMPcc ; +: JE HEX: 84 JUMPcc ; ! aka JZ +: JNE HEX: 85 JUMPcc ; +: JBE HEX: 86 JUMPcc ; +: JA HEX: 87 JUMPcc ; +: JS HEX: 88 JUMPcc ; +: JNS HEX: 89 JUMPcc ; +: JP HEX: 8a JUMPcc ; +: JNP HEX: 8b JUMPcc ; +: JL HEX: 8c JUMPcc ; +: JGE HEX: 8d JUMPcc ; +: JLE HEX: 8e JUMPcc ; +: JG HEX: 8f JUMPcc ; + +: LEAVE ( -- ) HEX: c9 , ; + +: RET ( n -- ) + dup zero? [ drop HEX: c3 , ] [ HEX: C2 , 2, ] if ; + +! Arithmetic + +GENERIC: ADD ( dst src -- ) +M: integer ADD swap BIN: 000 t HEX: 81 immediate-1/4 ; +M: operand ADD OCT: 000 2-operand ; + +GENERIC: OR ( dst src -- ) +M: integer OR swap BIN: 001 t HEX: 81 immediate-1/4 ; +M: operand OR OCT: 010 2-operand ; + +GENERIC: ADC ( dst src -- ) +M: integer ADC swap BIN: 010 t HEX: 81 immediate-1/4 ; +M: operand ADC OCT: 020 2-operand ; + +GENERIC: SBB ( dst src -- ) +M: integer SBB swap BIN: 011 t HEX: 81 immediate-1/4 ; +M: operand SBB OCT: 030 2-operand ; + +GENERIC: AND ( dst src -- ) +M: integer AND swap BIN: 100 t HEX: 81 immediate-1/4 ; +M: operand AND OCT: 040 2-operand ; + +GENERIC: SUB ( dst src -- ) +M: integer SUB swap BIN: 101 t HEX: 81 immediate-1/4 ; +M: operand SUB OCT: 050 2-operand ; + +GENERIC: XOR ( dst src -- ) +M: integer XOR swap BIN: 110 t HEX: 81 immediate-1/4 ; +M: operand XOR OCT: 060 2-operand ; + +GENERIC: CMP ( dst src -- ) +M: integer CMP swap BIN: 111 t HEX: 81 immediate-1/4 ; +M: operand CMP OCT: 070 2-operand ; + +: NOT ( dst -- ) BIN: 010 t HEX: f7 1-operand ; +: NEG ( dst -- ) BIN: 011 t HEX: f7 1-operand ; +: MUL ( dst -- ) BIN: 100 t HEX: f7 1-operand ; +: IMUL ( src -- ) BIN: 101 t HEX: f7 1-operand ; +: DIV ( dst -- ) BIN: 110 t HEX: f7 1-operand ; +: IDIV ( src -- ) BIN: 111 t HEX: f7 1-operand ; + +: CDQ HEX: 99 , ; +: CQO HEX: 48 , CDQ ; + +: ROL ( dst n -- ) swap BIN: 000 t HEX: c1 immediate-1 ; +: ROR ( dst n -- ) swap BIN: 001 t HEX: c1 immediate-1 ; +: RCL ( dst n -- ) swap BIN: 010 t HEX: c1 immediate-1 ; +: RCR ( dst n -- ) swap BIN: 011 t HEX: c1 immediate-1 ; +: SHL ( dst n -- ) swap BIN: 100 t HEX: c1 immediate-1 ; +: SHR ( dst n -- ) swap BIN: 101 t HEX: c1 immediate-1 ; +: SAR ( dst n -- ) swap BIN: 111 t HEX: c1 immediate-1 ; + +GENERIC: IMUL2 ( dst src -- ) +M: integer IMUL2 swap dup reg-code t HEX: 69 immediate-1/4 ; +M: operand IMUL2 OCT: 257 extended-opcode (2-operand) ; + +: MOVSX ( dst src -- ) + dup register-32? OCT: 143 OCT: 276 extended-opcode ? + over register-16? [ BIN: 1 opcode-or ] when + swapd + (2-operand) ; + +! Conditional move +: MOVcc ( dst src cc -- ) extended-opcode swapd (2-operand) ; + +: CMOVO HEX: 40 MOVcc ; +: CMOVNO HEX: 41 MOVcc ; +: CMOVB HEX: 42 MOVcc ; +: CMOVAE HEX: 43 MOVcc ; +: CMOVE HEX: 44 MOVcc ; ! aka CMOVZ +: CMOVNE HEX: 45 MOVcc ; +: CMOVBE HEX: 46 MOVcc ; +: CMOVA HEX: 47 MOVcc ; +: CMOVS HEX: 48 MOVcc ; +: CMOVNS HEX: 49 MOVcc ; +: CMOVP HEX: 4a MOVcc ; +: CMOVNP HEX: 4b MOVcc ; +: CMOVL HEX: 4c MOVcc ; +: CMOVGE HEX: 4d MOVcc ; +: CMOVLE HEX: 4e MOVcc ; +: CMOVG HEX: 4f MOVcc ; + +! CPU Identification + +: CPUID HEX: a2 extended-opcode, ; + +! x87 Floating Point Unit + +: FSTPS ( operand -- ) BIN: 011 f HEX: d9 1-operand ; +: FSTPL ( operand -- ) BIN: 011 f HEX: dd 1-operand ; + +: FLDS ( operand -- ) BIN: 000 f HEX: d9 1-operand ; +: FLDL ( operand -- ) BIN: 000 f HEX: dd 1-operand ; + +! SSE multimedia instructions + + + +: MOVSS ( dest src -- ) HEX: 10 HEX: f3 2-operand-sse ; +: MOVSD ( dest src -- ) HEX: 10 HEX: f2 2-operand-sse ; +: ADDSD ( dest src -- ) HEX: 58 HEX: f2 2-operand-sse ; +: MULSD ( dest src -- ) HEX: 59 HEX: f2 2-operand-sse ; +: SUBSD ( dest src -- ) HEX: 5c HEX: f2 2-operand-sse ; +: DIVSD ( dest src -- ) HEX: 5e HEX: f2 2-operand-sse ; +: SQRTSD ( dest src -- ) HEX: 51 HEX: f2 2-operand-sse ; +: UCOMISD ( dest src -- ) HEX: 2e HEX: 66 2-operand-sse ; +: COMISD ( dest src -- ) HEX: 2f HEX: 66 2-operand-sse ; + +: CVTSS2SD ( dest src -- ) HEX: 5a HEX: f3 2-operand-sse ; +: CVTSD2SS ( dest src -- ) HEX: 5a HEX: f2 2-operand-sse ; + +: CVTSI2SD ( dest src -- ) HEX: 2a HEX: f2 2-operand-int/sse ; +: CVTSD2SI ( dest src -- ) HEX: 2d HEX: f2 2-operand-int/sse ; +: CVTTSD2SI ( dest src -- ) HEX: 2c HEX: f2 2-operand-int/sse ; diff --git a/core/cpu/x86/authors.txt b/core/cpu/x86/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/x86/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/x86/intrinsics/intrinsics.factor b/core/cpu/x86/intrinsics/intrinsics.factor new file mode 100644 index 0000000000..fc4d7388bf --- /dev/null +++ b/core/cpu/x86/intrinsics/intrinsics.factor @@ -0,0 +1,575 @@ +! Copyright (C) 2005, 2006 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien arrays cpu.x86.assembler cpu.x86.allot +cpu.x86.architecture cpu.architecture kernel kernel.private math +math.functions math.private namespaces quotations sequences +words generic byte-arrays hashtables hashtables.private +generator generator.registers generator.fixup sequences.private +sbufs sbufs.private vectors vectors.private layouts system +tuples.private strings.private slots.private ; +IN: cpu.x86.intrinsics + +! Type checks +\ tag [ + "in" operand tag-mask get AND + "in" operand %tag-fixnum +] H{ + { +input+ { { f "in" } } } + { +output+ { "in" } } +} define-intrinsic + +\ type [ + "end" define-label + ! Make a copy + "x" operand "obj" operand MOV + ! Get the tag + "x" operand tag-mask get AND + ! Tag the tag + "x" operand %tag-fixnum + ! Compare with object tag number (3). + "x" operand object tag-number tag-bits get shift CMP + "end" get JNE + ! If we have equality, load type from header + "x" operand "obj" operand -3 [+] MOV + "end" resolve-label +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +\ class-hash [ + "end" define-label + "tuple" define-label + "object" define-label + ! Make a copy + "x" operand "obj" operand MOV + ! Get the tag + "x" operand tag-mask get AND + ! Tag the tag + "x" operand %tag-fixnum + ! Compare with tuple tag number (2). + "x" operand tuple tag-number tag-bits get shift CMP + "tuple" get JE + ! Compare with object tag number (3). + "x" operand object tag-number tag-bits get shift CMP + "object" get JE + "end" get JMP + "object" get resolve-label + ! Load header type + "x" operand "obj" operand header-offset [+] MOV + "end" get JMP + "tuple" get resolve-label + ! Load class hash + "x" operand "obj" operand tuple-class-offset [+] MOV + "x" operand dup class-hash-offset [+] MOV + "end" resolve-label +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +! Slots + +\ slot { + ! Slot number is literal + { + [ + "obj" operand %untag + ! load slot value + "obj" operand dup "n" get cells [+] MOV + ] H{ + { +input+ { { f "obj" } { [ small-slot? ] "n" } } } + { +output+ { "obj" } } + } + } + ! Slot number in a register + { + [ + "obj" operand %untag + ! turn tagged fixnum slot # into an offset, + ! multiple of 4 + "n" operand fixnum>slot@ + ! load slot value + "obj" operand dup "n" operand [+] MOV + ] H{ + { +input+ { { f "obj" } { f "n" } } } + { +output+ { "obj" } } + { +clobber+ { "n" } } + } + } +} define-intrinsics + +: generate-write-barrier ( -- ) + #! Mark the card pointed to by vreg. + "val" operand-immediate? "obj" get fresh-object? or [ + "obj" operand card-bits SHR + "scratch" operand HEX: ffffffff MOV + "cards_offset" f rc-absolute-cell rel-dlsym + "scratch" operand dup [] MOV + "scratch" operand "obj" operand [+] card-mark OR + ] unless ; + +\ set-slot { + ! Slot number is literal + { + [ + "obj" operand %untag + ! store new slot value + "obj" operand "n" get cells [+] "val" operand MOV + generate-write-barrier + ] H{ + { +input+ { { f "val" } { f "obj" } { [ small-slot? ] "n" } } } + { +scratch+ { { f "scratch" } } } + { +clobber+ { "obj" } } + } + } + ! Slot number in a register + { + [ + ! turn tagged fixnum slot # into an offset + "n" operand fixnum>slot@ + "obj" operand %untag + ! store new slot value + "obj" operand "n" operand [+] "val" operand MOV + ! reuse register + "n" get "scratch" set + generate-write-barrier + ] H{ + { +input+ { { f "val" } { f "obj" } { f "n" } } } + { +clobber+ { "obj" "n" } } + } + } +} define-intrinsics + +! Sometimes, we need to do stuff with operands which are +! less than the word size. Instead of teaching the register +! allocator about the different sized registers, with all +! the complexity this entails, we just push/pop a register +! which is guaranteed to be unused (the tempreg) +: small-reg cell 8 = RBX EBX ? ; inline +: small-reg-8 BL ; inline +: small-reg-16 BX ; inline +: small-reg-32 EBX ; inline + +\ char-slot [ + small-reg PUSH + "n" operand 2 SHR + small-reg dup XOR + "obj" operand "n" operand ADD + small-reg-16 "obj" operand string-offset [+] MOV + small-reg %tag-fixnum + "obj" operand small-reg MOV + small-reg POP +] H{ + { +input+ { { f "n" } { f "obj" } } } + { +output+ { "obj" } } + { +clobber+ { "obj" "n" } } +} define-intrinsic + +\ set-char-slot [ + small-reg PUSH + "val" operand %untag-fixnum + "slot" operand 2 SHR + "obj" operand "slot" operand ADD + small-reg "val" operand MOV + "obj" operand string-offset [+] small-reg-16 MOV + small-reg POP +] H{ + { +input+ { { f "val" } { f "slot" } { f "obj" } } } + { +clobber+ { "val" "slot" "obj" } } +} define-intrinsic + +! Fixnums +: fixnum-op ( op hash -- pair ) + >r [ "x" operand "y" operand ] swap add r> 2array ; + +: fixnum-value-op ( op -- pair ) + H{ + { +input+ { { f "x" } { [ small-tagged? ] "y" } } } + { +output+ { "x" } } + } fixnum-op ; + +: fixnum-register-op ( op -- pair ) + H{ + { +input+ { { f "x" } { f "y" } } } + { +output+ { "x" } } + } fixnum-op ; + +: define-fixnum-op ( word op -- ) + [ fixnum-value-op ] keep fixnum-register-op + 2array define-intrinsics ; + +{ + { fixnum+fast ADD } + { fixnum-fast SUB } + { fixnum-bitand AND } + { fixnum-bitor OR } + { fixnum-bitxor XOR } +} [ + first2 define-fixnum-op +] each + +\ fixnum-bitnot [ + "x" operand NOT + "x" operand tag-mask get XOR +] H{ + { +input+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +\ fixnum*fast { + { + [ + "x" operand "y" get IMUL2 + ] H{ + { +input+ { { f "x" } { [ small-tagged? ] "y" } } } + { +output+ { "x" } } + } + } { + [ + "out" operand "x" operand MOV + "out" operand %untag-fixnum + "y" operand "out" operand IMUL2 + ] H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } + } + } +} define-intrinsics + +\ fixnum-shift [ + "x" operand "y" get neg SAR + ! Mask off low bits + "x" operand %untag +] H{ + { +input+ { { f "x" } { [ -31 0 between? ] "y" } } } + { +output+ { "x" } } +} define-intrinsic + +: %untag-fixnums ( seq -- ) + [ %untag-fixnum ] unique-operands ; + +: overflow-check ( word -- ) + "end" define-label + "z" operand "x" operand MOV + "z" operand "y" operand pick execute + ! If the previous arithmetic operation overflowed, then we + ! turn the result into a bignum and leave it in EAX. + "end" get JNO + ! There was an overflow. Recompute the original operand. + { "y" "x" } %untag-fixnums + "x" operand "y" operand rot execute + "z" get "x" get %allot-bignum-signed-1 + "end" resolve-label ; inline + +: overflow-template ( word insn -- ) + [ overflow-check ] curry H{ + { +input+ { { f "x" } { f "y" } } } + { +scratch+ { { f "z" } } } + { +output+ { "z" } } + { +clobber+ { "x" "y" } } + } define-intrinsic ; + +\ fixnum+ \ ADD overflow-template +\ fixnum- \ SUB overflow-template + +: fixnum-jump ( op inputs -- pair ) + >r [ "x" operand "y" operand CMP ] swap add r> 2array ; + +: fixnum-value-jump ( op -- pair ) + { { f "x" } { [ small-tagged? ] "y" } } fixnum-jump ; + +: fixnum-register-jump ( op -- pair ) + { { f "x" } { f "y" } } fixnum-jump ; + +: define-fixnum-jump ( word op -- ) + [ fixnum-value-jump ] keep fixnum-register-jump + 2array define-if-intrinsics ; + +{ + { fixnum< JL } + { fixnum<= JLE } + { fixnum> JG } + { fixnum>= JGE } + { eq? JE } +} [ + first2 define-fixnum-jump +] each + +\ fixnum>bignum [ + "x" operand %untag-fixnum + "x" get dup %allot-bignum-signed-1 +] H{ + { +input+ { { f "x" } } } + { +output+ { "x" } } +} define-intrinsic + +\ bignum>fixnum [ + "nonzero" define-label + "positive" define-label + "end" define-label + "x" operand %untag + "y" operand "x" operand cell [+] MOV + ! if the length is 1, its just the sign and nothing else, + ! so output 0 + "y" operand 1 v>operand CMP + "nonzero" get JNE + "y" operand 0 MOV + "end" get JMP + "nonzero" resolve-label + ! load the value + "y" operand "x" operand 3 cells [+] MOV + ! load the sign + "x" operand "x" operand 2 cells [+] MOV + ! is the sign negative? + "x" operand 0 CMP + "positive" get JE + "y" operand -1 IMUL2 + "positive" resolve-label + "y" operand 3 SHL + "end" resolve-label +] H{ + { +input+ { { f "x" } } } + { +scratch+ { { f "y" } } } + { +clobber+ { "x" } } + { +output+ { "y" } } +} define-intrinsic + +! User environment +: %userenv ( -- ) + "x" operand 0 MOV + "userenv" f rc-absolute-cell rel-dlsym + "n" operand fixnum>slot@ + "n" operand "x" operand ADD ; + +\ getenv [ + %userenv "n" operand dup [] MOV +] H{ + { +input+ { { f "n" } } } + { +scratch+ { { f "x" } } } + { +output+ { "n" } } +} define-intrinsic + +\ setenv [ + %userenv "n" operand [] "val" operand MOV +] H{ + { +input+ { { f "val" } { f "n" } } } + { +scratch+ { { f "x" } } } + { +clobber+ { "n" } } +} define-intrinsic + +\ [ + tuple "n" get 2 + cells [ + ! Store length + 1 object@ "n" operand MOV + ! Store class + 2 object@ "class" operand MOV + ! Zero out the rest of the tuple + "n" operand 1- [ 3 + object@ f v>operand MOV ] each + ! Store tagged ptr in reg + "tuple" get tuple %store-tagged + ] %allot +] H{ + { +input+ { { f "class" } { [ inline-array? ] "n" } } } + { +scratch+ { { f "tuple" } } } + { +output+ { "tuple" } } +} define-intrinsic + +\ [ + array "n" get 2 + cells [ + ! Store length + 1 object@ "n" operand MOV + ! Zero out the rest of the tuple + "n" get [ 2 + object@ "initial" operand MOV ] each + ! Store tagged ptr in reg + "array" get object %store-tagged + ] %allot +] H{ + { +input+ { { [ inline-array? ] "n" } { f "initial" } } } + { +scratch+ { { f "array" } } } + { +output+ { "array" } } +} define-intrinsic + +\ [ + byte-array "n" get 2 cells + [ + ! Store length + 1 object@ "n" operand MOV + ! Store initial element + "n" get cell align cell /i [ 2 + object@ 0 MOV ] each + ! Store tagged ptr in reg + "array" get object %store-tagged + ] %allot +] H{ + { +input+ { { [ inline-array? ] "n" } } } + { +scratch+ { { f "array" } } } + { +output+ { "array" } } +} define-intrinsic + +\ [ + ratio 3 cells [ + 1 object@ "numerator" operand MOV + 2 object@ "denominator" operand MOV + ! Store tagged ptr in reg + "ratio" get ratio %store-tagged + ] %allot +] H{ + { +input+ { { f "numerator" } { f "denominator" } } } + { +scratch+ { { f "ratio" } } } + { +output+ { "ratio" } } +} define-intrinsic + +\ [ + complex 3 cells [ + 1 object@ "real" operand MOV + 2 object@ "imaginary" operand MOV + ! Store tagged ptr in reg + "complex" get complex %store-tagged + ] %allot +] H{ + { +input+ { { f "real" } { f "imaginary" } } } + { +scratch+ { { f "complex" } } } + { +output+ { "complex" } } +} define-intrinsic + +\ [ + wrapper 2 cells [ + 1 object@ "obj" operand MOV + ! Store tagged ptr in reg + "wrapper" get object %store-tagged + ] %allot +] H{ + { +input+ { { f "obj" } } } + { +scratch+ { { f "wrapper" } } } + { +output+ { "wrapper" } } +} define-intrinsic + +\ (hashtable) [ + hashtable 4 cells [ + 1 object@ f v>operand MOV + 2 object@ f v>operand MOV + 3 object@ f v>operand MOV + ! Store tagged ptr in reg + "hashtable" get object %store-tagged + ] %allot +] H{ + { +scratch+ { { f "hashtable" } } } + { +output+ { "hashtable" } } +} define-intrinsic + +\ string>sbuf [ + sbuf 3 cells [ + 1 object@ "length" operand MOV + 2 object@ "string" operand MOV + ! Store tagged ptr in reg + "sbuf" get object %store-tagged + ] %allot +] H{ + { +input+ { { f "string" } { f "length" } } } + { +scratch+ { { f "sbuf" } } } + { +output+ { "sbuf" } } +} define-intrinsic + +\ array>vector [ + vector 3 cells [ + 1 object@ "length" operand MOV + 2 object@ "array" operand MOV + ! Store tagged ptr in reg + "vector" get object %store-tagged + ] %allot +] H{ + { +input+ { { f "array" } { f "length" } } } + { +scratch+ { { f "vector" } } } + { +output+ { "vector" } } +} define-intrinsic + +\ curry [ + \ curry 3 cells [ + 1 object@ "obj" operand MOV + 2 object@ "quot" operand MOV + ! Store tagged ptr in reg + "curry" get object %store-tagged + ] %allot +] H{ + { +input+ { { f "obj" } { f "quot" } } } + { +scratch+ { { f "curry" } } } + { +output+ { "curry" } } +} define-intrinsic + +! Alien intrinsics +: %alien-integer-get ( quot reg -- ) + small-reg PUSH + "offset" operand %untag-fixnum + "alien" operand-class %alien-accessor + "offset" operand small-reg MOV + "offset" operand %tag-fixnum + small-reg POP ; inline + +: alien-integer-get-template + H{ + { +input+ { + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +output+ { "offset" } } + { +clobber+ { "alien" "offset" } } + } ; + +: define-getter + [ %alien-integer-get ] 2curry + alien-integer-get-template + define-intrinsic ; + +: define-unsigned-getter + [ small-reg dup XOR MOV ] swap define-getter ; + +: define-signed-getter + [ [ >r MOV small-reg r> MOVSX ] curry ] keep define-getter ; + +: %alien-integer-set ( quot reg -- ) + small-reg PUSH + { "offset" "value" } %untag-fixnums + small-reg "value" operand MOV + "alien" operand-class %alien-accessor + small-reg POP ; inline + +: alien-integer-set-template + H{ + { +input+ { + { f "value" fixnum } + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +clobber+ { "value" "alien" "offset" } } + } ; + +: define-setter + [ swap MOV ] swap + [ %alien-integer-set ] 2curry + alien-integer-set-template + define-intrinsic ; + +\ alien-unsigned-1 small-reg-8 define-unsigned-getter +\ set-alien-unsigned-1 small-reg-8 define-setter + +\ alien-signed-1 small-reg-8 define-signed-getter +\ set-alien-signed-1 small-reg-8 define-setter + +\ alien-unsigned-2 small-reg-16 define-unsigned-getter +\ set-alien-unsigned-2 small-reg-16 define-setter + +\ alien-signed-2 small-reg-16 define-signed-getter +\ set-alien-signed-2 small-reg-16 define-setter + +\ alien-cell [ + "offset" operand %untag-fixnum + + [ MOV ] + "offset" operand + "alien" operand-class + %alien-accessor + + "offset" get %allot-alien +] alien-integer-get-template define-intrinsic diff --git a/core/cpu/x86/sse2/authors.txt b/core/cpu/x86/sse2/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/cpu/x86/sse2/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/cpu/x86/sse2/sse2.factor b/core/cpu/x86/sse2/sse2.factor new file mode 100644 index 0000000000..3fa83a4ed7 --- /dev/null +++ b/core/cpu/x86/sse2/sse2.factor @@ -0,0 +1,113 @@ +! Copyright (C) 2005, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: alien arrays cpu.x86.assembler cpu.x86.architecture +generic kernel kernel.private math math.private memory +namespaces sequences words generator generator.registers +cpu.architecture math.floats.private layouts quotations ; +IN: cpu.x86.sse2 + +M: float-regs (%peek) + drop + temp-reg swap %move-int>int + temp-reg %move-int>float ; + +M: float-regs (%replace) drop swap %move-float>int ; + +: define-float-op ( word op -- ) + [ "x" operand "y" operand ] swap add H{ + { +input+ { { float "x" } { float "y" } } } + { +output+ { "x" } } + } define-intrinsic ; + +{ + { float+ ADDSD } + { float- SUBSD } + { float* MULSD } + { float/f DIVSD } +} [ + first2 define-float-op +] each + +: define-float-jump ( word op -- ) + [ "x" operand "y" operand UCOMISD ] swap add + { { float "x" } { float "y" } } define-if-intrinsic ; + +{ + { float< JB } + { float<= JBE } + { float> JA } + { float>= JAE } + { float= JE } +} [ + first2 define-float-jump +] each + +\ float>fixnum [ + "out" operand "in" operand CVTTSD2SI + "out" operand tag-bits get SHL +] H{ + { +input+ { { float "in" } } } + { +scratch+ { { f "out" } } } + { +output+ { "out" } } +} define-intrinsic + +\ fixnum>float [ + "in" operand %untag-fixnum + "out" operand "in" operand CVTSI2SD +] H{ + { +input+ { { f "in" } } } + { +scratch+ { { float "out" } } } + { +output+ { "out" } } + { +clobber+ { "in" } } +} define-intrinsic + +: %alien-float-get ( quot -- ) + "offset" operand %untag-fixnum + "output" operand "alien" operand-class %alien-accessor ; + inline + +: alien-float-get-template + H{ + { +input+ { + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +scratch+ { { float "output" } } } + { +output+ { "output" } } + { +clobber+ { "alien" "offset" } } + } ; + +: %alien-float-set ( quot -- ) + "offset" operand %untag-fixnum + "value" operand "alien" operand-class %alien-accessor ; + inline + +: alien-float-set-template + H{ + { +input+ { + { float "value" float } + { f "alien" simple-c-ptr } + { f "offset" fixnum } + } } + { +clobber+ { "value" "alien" "offset" } } + } ; + +: define-alien-float-intrinsics ( word get-quot word set-quot -- ) + [ %alien-float-set ] curry + alien-float-set-template + define-intrinsic + [ %alien-float-get ] curry + alien-float-get-template + define-intrinsic ; + +\ alien-double +[ MOVSD ] +\ set-alien-double +[ swap MOVSD ] +define-alien-float-intrinsics + +\ alien-float +[ dupd MOVSS dup CVTSS2SD ] +\ set-alien-float +[ swap dup dup CVTSD2SS MOVSS ] +define-alien-float-intrinsics diff --git a/core/cpu/x86/sse2/summary.txt b/core/cpu/x86/sse2/summary.txt new file mode 100644 index 0000000000..dd2d309b1e --- /dev/null +++ b/core/cpu/x86/sse2/summary.txt @@ -0,0 +1 @@ +SSE2 floating point intrinsics for Pentium 4 and above diff --git a/core/cpu/x86/summary.txt b/core/cpu/x86/summary.txt new file mode 100644 index 0000000000..ecaa508c7d --- /dev/null +++ b/core/cpu/x86/summary.txt @@ -0,0 +1 @@ +32-bit x86 compiler backend diff --git a/core/debugger/authors.txt b/core/debugger/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/debugger/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/debugger/debugger-docs.factor b/core/debugger/debugger-docs.factor new file mode 100644 index 0000000000..d5c7ecfeb1 --- /dev/null +++ b/core/debugger/debugger-docs.factor @@ -0,0 +1,174 @@ +USING: alien arrays generic generic.math help.markup help.syntax +kernel math memory strings sbufs vectors io io.files classes +help generic.standard continuations system ; +IN: debugger + +ARTICLE: "errors-assert" "Assertions" +"Some words to make assertions easier to enforce:" +{ $subsection assert } +{ $subsection assert= } +"Runtime stack depth checking:" +{ $subsection depth } +{ $subsection assert-depth } ; + +ARTICLE: "debugger" "The debugger" +"Caught errors can be logged in human-readable form:" +{ $subsection print-error } +{ $subsection try } +"User-defined errors can have customized printed representation by implementing a generic word:" +{ $subsection error. } +"A number of words facilitate interactive debugging of errors:" +{ $subsection :s } +{ $subsection :r } +{ $subsection :c } +{ $subsection :get } +"Most types of errors are documented, and the documentation is instantly accessible:" +{ $subsection :help } +"If the error was restartable, a list of restarts is also printed, and a numbered restart can be invoked:" +{ $subsection :1 } +{ $subsection :2 } +{ $subsection :3 } +{ $subsection :res } +"Assertions:" +{ $subsection "errors-assert" } +"You can read more about error handling in " { $link "errors" } "." ; + +ABOUT: "debugger" + +HELP: :s +{ $description "Prints the data stack at the time of the most recent error. Used for interactive debugging." } ; + +HELP: :r +{ $description "Prints the retain stack at the time of the most recent error. Used for interactive debugging." } ; + +HELP: :c +{ $description "Prints the call stack at the time of the most recent error. Used for interactive debugging." } ; + +HELP: :get +{ $values { "variable" "an object" } { "value" "the value, or f" } } +{ $description "Looks up the value of a variable at the time of the most recent error." } ; + +HELP: :res +{ $values { "n" "a positive integer" } } +{ $description "Continues executing the " { $snippet "n" } "th restart. Since restarts may only be invoked once, this resets the " { $link restarts } " global variable." } ; + +HELP: :1 +{ $description "A shortcut for invoking the first restart." } ; + +HELP: :2 +{ $description "A shortcut for invoking the second restart." } ; + +HELP: :3 +{ $description "A shortcut for invoking the third restart." } ; + +HELP: error. +{ $values { "error" "an error" } } +{ $contract "Print an error to the " { $link stdio } " stream. You can define methods on this generic word to print human-readable messages for custom errors." } +{ $notes "Code should call " { $link print-error } " instead, which handles the case where the printing of the error itself throws an error." } ; + +HELP: error-help +{ $values { "error" "an error" } { "topic" "an article name or word" } } +{ $contract "Outputs a help article which explains the error." } ; + +{ error-help :help } related-words + +HELP: print-error +{ $values { "error" "an error" } } +{ $description "Print an error to the " { $link stdio } " stream." } +{ $notes "This word is called by the listener and other tools which report caught errors to the user." } ; + +HELP: restarts. +{ $description "Print a list of restarts for the most recently thrown error to the " { $link stdio } " stream." } ; + +HELP: debug-help +{ $description "Print a synopsis of useful debugger words." } ; + +HELP: error-hook +{ $var-description "A quotation with stack effect " { $snippet "( error -- )" } " which is used by " { $link try } " to report the error to the user." } +{ $examples "The default value prints the error with " { $link print-error } ", followed by a list of restarts and a help message. The graphical listener sets this variable to display a popup instead." } ; + +HELP: try +{ $values { "quot" "a quotation" } } +{ $description "Calls the quotation. If it throws an error, calls " { $link error-hook } " with the error and restores the data stack." } ; + +HELP: expired-error. +{ $error-description "Thrown by " { $link alien-address } " and " { $link alien-invoke } " if an " { $link alien } " object passed in as a parameter has expired. Alien objects expire if they are saved an image which is subsequently loaded; this prevents a certain class of programming errors, usually attempts to use uninitialized objects, since holding a C address is meaningless between sessions." } +{ $notes "You can check if an alien object has expired by calling " { $link expired? } "." } ; + +HELP: io-error. +{ $error-description "Thrown by the C streams I/O primitives if an I/O error occurs." } ; + +HELP: undefined-word-error. +{ $error-description "Thrown if an attempt is made to call a word which was defined by " { $link POSTPONE: DEFER: } "." } ; + +HELP: type-check-error. +{ $error-description "Thrown by various primitives if one of the inputs does not have the expected type. Generic words throw " { $link no-method } " and " { $link no-math-method } " errors in such cases instead." } ; + +HELP: divide-by-zero-error. +{ $error-description "This error is thrown when " { $link / } " or " { $link /i } " is called with with a zero denominator." } +{ $see-also "division-by-zero" } ; + +HELP: signal-error. +{ $error-description + "Thrown by the Factor VM when a Unix signal is received. While signal numbers are system-specific, the following are relatively standard:" + { $list + { "4 - Illegal instruction. If you see this error, it is a bug in Factor's compiler and should be reported." } + { "8 - Arithmetic exception. Most likely a divide by zero in " { $link /i } "." } + { "10, 11 - Memory protection fault. This error suggests invalid values are being passed to C functions by an " { $link alien-invoke } ". Factor also uses memory protection to trap stack underflows and overflows, but usually these are reported as their own errors. Sometimes they'll show up as a generic signal 11, though." } + } + "The Windows equivalent of a signal 11 is a SEH fault. When one occurs, the runtime throws a singal error, even though it does not correspond to a Unix signal." +} ; + +HELP: array-size-error. +{ $error-description "Thrown by " { $link } ", " { $link } ", " { $link } " and " { $link } " if the specified capacity is negative or too large." } ; + +HELP: c-string-error. +{ $error-description "Thrown by " { $link alien-invoke } " and various primitives if a string containing null bytes, or characters with values higher than 255 is passed in where a C string is expected. See " { $link "c-strings" } "." } ; + +HELP: ffi-error. +{ $error-description "Thrown by " { $link dlopen } " and " { $link dlsym } " if a problem occurs while loading a native library or looking up a symbol. See " { $link "alien" } "." } ; + +HELP: heap-scan-error. +{ $error-description "Thrown if " { $link next-object } " is called outside of a " { $link begin-scan } "/" { $link end-scan } " pair." } ; + +HELP: undefined-symbol-error. +{ $error-description "Thrown if a previously-compiled " { $link alien-invoke } " call refers to a native library symbol which no longer exists." } ; + +HELP: datastack-underflow. +{ $error-description "Thrown by the Factor VM if an attempt is made to pop elements from an empty data stack." } +{ $notes "You can use the stack effect tool to statically check stack effects of quotations. See " { $link "inference" } "." } ; + +HELP: datastack-overflow. +{ $error-description "Thrown by the Factor VM if an attempt is made to push elements on a full data stack." } +{ $notes "This error usually indicates a run-away recursion, however if you legitimately need a data stack larger than the default, see " { $link "runtime-cli-args" } "." } ; + +HELP: retainstack-underflow. +{ $error-description "Thrown by the Factor VM if " { $link r> } " is called while the retain stack is empty." } +{ $notes "You can use the stack effect tool to statically check stack effects of quotations. See " { $link "inference" } "." } ; + +HELP: retainstack-overflow. +{ $error-description "Thrown by the Factor VM if " { $link >r } " is called when the retain stack is full." } +{ $notes "This error usually indicates a run-away recursion, however if you legitimately need a retain stack larger than the default, see " { $link "runtime-cli-args" } "." } ; + +HELP: memory-error. +{ $error-description "Thrown by the Factor VM if an invalid memory access occurs." } +{ $notes "This can be a result of incorrect usage of C library interface words, a bug in the compiler, or a bug in the VM." } ; + +HELP: primitive-error. +{ $error-description "Thrown by the Factor VM if an unsupported primitive word is called." } +{ $notes "This word is only ever thrown on Windows CE, where the " { $link cwd } ", " { $link cd } ", and " { $link os-env } " primitives are unsupported." } ; + +HELP: assert +{ $values { "got" "the obtained value" } { "expect" "the expected value" } } +{ $description "Throws an " { $link assert } " error." } +{ $error-description "Thrown when a unit test or other assertion fails." } ; + +{ assert assert-depth } related-words + +HELP: depth +{ $values { "n" "a non-negative integer" } } +{ $description "Outputs the number of elements on the data stack." } ; + +HELP: assert-depth +{ $values { "quot" "a quotation" } } +{ $description "Runs a quotation. Throws an error if the total number of elements on the stack is not the same before and after the quotation runs." } ; diff --git a/core/debugger/debugger.factor b/core/debugger/debugger.factor new file mode 100644 index 0000000000..bdeeb0483b --- /dev/null +++ b/core/debugger/debugger.factor @@ -0,0 +1,223 @@ +! Copyright (C) 2004, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays definitions generic hashtables inspector io kernel +math namespaces prettyprint sequences assocs sequences.private +strings io.styles vectors words system splitting math.parser +tuples continuations continuations.private combinators +generic.math io.streams.duplex classes +generic.standard ; +IN: debugger + +GENERIC: error. ( error -- ) +GENERIC: error-help ( error -- topic ) + +M: object error. . ; +M: object error-help drop f ; + +M: tuple error. describe ; +M: tuple error-help class ; + +M: string error. print ; + +: :s ( -- ) + error-continuation get continuation-data stack. ; + +: :r ( -- ) + error-continuation get continuation-retain stack. ; + +: :c ( -- ) + error-continuation get continuation-call callstack. ; + +: :get ( variable -- value ) + error-continuation get continuation-name assoc-stack ; + +: :res ( n -- ) + 1- restarts get-global nth f restarts set-global restart ; + +: :1 1 :res ; +: :2 2 :res ; +: :3 3 :res ; + +: restart. ( restart n -- ) + [ + 1+ dup 3 <= [ ":" % # " " % ] [ # " :res " % ] if + restart-name % + ] "" make print ; + +: restarts. ( -- ) + restarts get dup empty? [ + drop + ] [ + nl + "The following restarts are available:" print + nl + dup length [ restart. ] 2each + ] if ; + +: debug-help ( -- ) + nl + "Debugger commands:" print + nl + ":help - documentation for this error" print + ":s - data stack at exception time" print + ":r - retain stack at exception time" print + ":c - call stack at exception time" print + ":edit - jump to source location (parse errors only)" print + + ":get ( var -- value ) accesses variables at time of the error" print + flush ; + +: print-error ( error -- ) + [ error. flush ] curry + [ global [ "Error in print-error!" print drop ] bind ] + recover ; + +SYMBOL: error-hook + +[ print-error restarts. debug-help ] error-hook set-global + +: try ( quot -- ) + [ error-hook get call ] recover ; + +TUPLE: assert got expect ; + +: assert ( got expect -- * ) \ assert construct-boa throw ; + +: assert= ( a b -- ) 2dup = [ 2drop ] [ assert ] if ; + +: depth ( -- n ) datastack length ; + +: assert-depth ( quot -- ) depth slip depth swap assert= ; + +: expired-error. ( obj -- ) + "Object did not survive image save/load: " write third . ; + +: undefined-word-error. ( obj -- ) + "Undefined word: " write third . ; + +: io-error. ( error -- ) + "I/O error: " write third print ; + +: type-check-error. ( obj -- ) + "Type check error" print + "Object: " write dup fourth short. + "Object type: " write dup fourth class . + "Expected type: " write third type>class . ; + +: divide-by-zero-error. ( obj -- ) + "Division by zero" print drop ; + +: signal-error. ( obj -- ) + "Operating system signal " write third . ; + +: array-size-error. ( obj -- ) + "Invalid array size: " write dup third . + "Maximum: " write fourth 1- . ; + +: c-string-error. ( obj -- ) + "Cannot convert to C string: " write third . ; + +: ffi-error. ( obj -- ) + "FFI: " write + dup third [ write ": " write ] when* + fourth print ; + +: heap-scan-error. ( obj -- ) + "Cannot do next-object outside begin/end-scan" print drop ; + +: undefined-symbol-error. ( obj -- ) + "The image refers to a library or symbol that was not found" + " at load time" append print drop ; + +: stack-underflow. ( obj name -- ) + write " stack underflow" print drop ; + +: stack-overflow. ( obj name -- ) + write " stack overflow" print drop ; + +: datastack-underflow. "Data" stack-underflow. ; +: datastack-overflow. "Data" stack-overflow. ; +: retainstack-underflow. "Retain" stack-underflow. ; +: retainstack-overflow. "Retain" stack-overflow. ; + +: memory-error. + "Memory protection fault at address " write third .h ; + +: primitive-error. + "Unimplemented primitive" print drop ; + +PREDICATE: array kernel-error ( obj -- ? ) + { + { [ dup empty? ] [ drop f ] } + { [ dup first "kernel-error" = not ] [ drop f ] } + { [ t ] [ second 0 16 between? ] } + } cond ; + +: kernel-errors + second { + { 0 [ expired-error. ] } + { 1 [ io-error. ] } + { 2 [ undefined-word-error. ] } + { 3 [ type-check-error. ] } + { 4 [ divide-by-zero-error. ] } + { 5 [ signal-error. ] } + { 6 [ array-size-error. ] } + { 7 [ c-string-error. ] } + { 8 [ ffi-error. ] } + { 9 [ heap-scan-error. ] } + { 10 [ undefined-symbol-error. ] } + { 11 [ datastack-underflow. ] } + { 12 [ datastack-overflow. ] } + { 13 [ retainstack-underflow. ] } + { 14 [ retainstack-overflow. ] } + { 15 [ memory-error. ] } + { 16 [ primitive-error. ] } + } ; inline + +M: kernel-error error. dup kernel-errors case ; + +M: kernel-error error-help kernel-errors at first ; + +M: no-method summary + drop "No suitable method" ; + +M: no-method error. + "Generic word " write + dup no-method-generic pprint + " does not define a method for the " write + dup no-method-object class pprint + " class." print + "Allowed classes: " write dup no-method-generic order . + "Dispatching on object: " write no-method-object short. ; + +M: no-math-method summary + drop "No suitable arithmetic method" ; + +M: check-closed summary + drop "Attempt to perform I/O on closed stream" ; + +M: check-method summary + drop "Invalid parameters for define-method" ; + +M: check-tuple summary + drop "Invalid class for define-constructor" ; + +M: no-cond summary + drop "Fall-through in cond" ; + +M: no-case summary + drop "Fall-through in case" ; + +M: slice-error error. + "Cannot create slice because " write + slice-error-reason print ; + +M: bounds-error summary drop "Sequence index out of bounds" ; + +M: condition error. delegate error. ; + +M: condition error-help drop f ; + +M: assert summary drop "Assertion failed" ; + +M: immutable summary drop "Sequence is immutable" ; diff --git a/core/debugger/summary.txt b/core/debugger/summary.txt new file mode 100644 index 0000000000..75c13e3364 --- /dev/null +++ b/core/debugger/summary.txt @@ -0,0 +1 @@ +Printing errors, inspecting tracebacks, restarts diff --git a/core/definitions/authors.txt b/core/definitions/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/definitions/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/definitions/definitions-docs.factor b/core/definitions/definitions-docs.factor new file mode 100644 index 0000000000..eeb547bb90 --- /dev/null +++ b/core/definitions/definitions-docs.factor @@ -0,0 +1,84 @@ +USING: help.markup help.syntax words math ; +IN: definitions + +ARTICLE: "definition-protocol" "Definition protocol" +"A common protocol is used to build generic tools for working with all definitions." +$nl +"Definitions must know what source file they were loaded from, and provide a way to set this:" +{ $subsection where } +{ $subsection set-where } +"Definitions can be removed:" +{ $subsection forget } +"Definitions can answer a sequence of definitions they directly depend on:" +{ $subsection uses } +"When a definition is changed, all definitions which depend on it are notified via a hook:" +{ $subsection redefined* } +"Definitions must implement a few operations used for printing them in human and computer-readable form:" +{ $subsection synopsis* } +{ $subsection definer } +{ $subsection definition } ; + +ARTICLE: "definitions" "Definitions" +"A " { $emphasis "definition" } " is an artifact read from a source file. This includes words, methods, and help articles. Words for working with definitions are found in the " { $vocab-link "definitions" } " vocabulary." +{ $subsection "definition-protocol" } +"A common cross-referencing system is used to track definition usages:" +{ $subsection crossref } +{ $subsection xref } +{ $subsection unxref } +{ $subsection delete-xref } +{ $subsection usage } +"Implementations of the definition protocol include pathnames, words, methods, and help articles." +{ $see-also "source-files" "words" "generic" "help-impl" } ; + +ABOUT: "definitions" + +HELP: where +{ $values { "defspec" "a definition specifier" } { "loc" "a " { $snippet "{ path line# }" } " pair" } } +{ $description "Outputs the location of a definition. If the location is not known, will output " { $link f } "." } ; + +HELP: set-where +{ $values { "loc" "a " { $snippet "{ path line# }" } " pair" } { "defspec" "a definition specifier" } } +{ $description "Sets the definition's location." } +{ $notes "This word is used by the parser." } ; + +HELP: forget +{ $values { "defspec" "a definition specifier" } } +{ $description "Forgets about a definition. For example, if it is a word, it will be removed from its vocabulary." } ; + +HELP: uses +{ $values { "defspec" "a definition specifier" } { "seq" "a sequence of definition specifiers" } } +{ $description "Outputs a sequence of definitions directory called by the given definition." } +{ $notes "The sequence might include the definition itself, if it is a recursive word." } +{ $examples + "We can ask the " { $link sq } " word to produce a list of words it calls:" + { $unchecked-example "\ sq uses ." "{ dup * }" } +} ; + +HELP: crossref +{ $var-description "A graph whose vertices are definition specifiers and edges are usages. See " { $link "graphs" } "." } ; + +HELP: xref +{ $values { "defspec" "a definition specifier" } } +{ $description "Adds a vertex representing this definition, along with edges representing dependencies to the " { $link crossref } " graph." } +$low-level-note ; + +HELP: usage +{ $values { "defspec" "a definition specifier" } { "seq" "a sequence of definition specifiers" } } +{ $description "Outputs a sequence of definitions that directly call the given definition." } +{ $notes "The sequence might include the definition itself, if it is a recursive word." } ; + +HELP: redefined* +{ $values { "defspec" "a definition specifier" } } +{ $contract "Updates the definition to cope with a callee being redefined." } +$low-level-note ; + +HELP: unxref +{ $values { "defspec" "a definition specifier" } } +{ $description "Remove edges leaving the vertex which represents the definition from the " { $link crossref } " graph." } +{ $notes "This word is called before a word is redefined." } ; + +HELP: delete-xref +{ $values { "defspec" "a definition specifier" } } +{ $description "Remove the vertex which represents the definition from the " { $link crossref } " graph." } +{ $notes "This word is called before a word is forgotten." } +{ $see-also forget } ; diff --git a/core/definitions/definitions.factor b/core/definitions/definitions.factor new file mode 100644 index 0000000000..9d31c8d87d --- /dev/null +++ b/core/definitions/definitions.factor @@ -0,0 +1,43 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: definitions +USING: kernel sequences namespaces assocs graphs ; + +GENERIC: where ( defspec -- loc ) + +M: object where drop f ; + +GENERIC: set-where ( loc defspec -- ) + +GENERIC: forget ( defspec -- ) + +M: object forget drop ; + +GENERIC: synopsis* ( defspec -- ) + +GENERIC: definer ( defspec -- start end ) + +GENERIC: definition ( defspec -- seq ) + +SYMBOL: crossref + +GENERIC: uses ( defspec -- seq ) + +M: object uses drop f ; + +: xref ( defspec -- ) dup uses crossref get add-vertex ; + +: usage ( defspec -- seq ) crossref get at keys ; + +GENERIC: redefined* ( defspec -- ) + +M: object redefined* drop ; + +: redefined ( defspec -- ) + [ crossref get at ] closure [ drop redefined* ] assoc-each ; + +: unxref ( defspec -- ) + dup uses crossref get remove-vertex ; + +: delete-xref ( defspec -- ) + dup unxref crossref get delete-at ; diff --git a/core/definitions/summary.txt b/core/definitions/summary.txt new file mode 100644 index 0000000000..79a7ba484c --- /dev/null +++ b/core/definitions/summary.txt @@ -0,0 +1 @@ +Definition protocol and cross-referencing diff --git a/core/definitions/tags.txt b/core/definitions/tags.txt new file mode 100644 index 0000000000..8ba7ae8503 --- /dev/null +++ b/core/definitions/tags.txt @@ -0,0 +1,2 @@ +tools +reflection diff --git a/core/effects/authors.txt b/core/effects/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/effects/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/effects/effects-docs.factor b/core/effects/effects-docs.factor new file mode 100644 index 0000000000..f473eb58c8 --- /dev/null +++ b/core/effects/effects-docs.factor @@ -0,0 +1,66 @@ +USING: help.markup help.syntax math strings words ; +IN: effects + +ARTICLE: "effect-declaration" "Stack effect declaration" +"It is good practice to declare the stack effects of words using the following syntax:" +{ $code ": sq ( x -- y ) dup * ;" } +"A stack effect declaration is written in parentheses and lists word inputs and outputs, separated by " { $snippet "--" } ". Stack effect declarations are read in using a parsing word:" +{ $subsection POSTPONE: ( } +"Stack elements in a stack effect are ordered so that the top of the stack is on the right side. Each value can be named by a data type or description. The following are some examples of value names:" +{ $table + { { { $snippet "?" } } "a boolean" } + { { { $snippet "elt" } } "an object which is an element of a sequence" } + { { { $snippet "m" } ", " { $snippet "n" } } "an integer" } + { { { $snippet "obj" } } "an object" } + { { { $snippet "quot" } } "a quotation" } + { { { $snippet "seq" } } "a sequence" } + { { { $snippet "assoc" } } "an associative mapping" } + { { { $snippet "str" } } "a string" } + { { { $snippet "x" } ", " { $snippet "y" } ", " { $snippet "z" } } "a number" } + { { $snippet "loc" } "a screen location specified as a two-element array holding x and y co-ordinates" } + { { $snippet "dim" } "a screen dimension specified as a two-element array holding width and height values" } + { { $snippet "*" } "when this symbol appears by itself in the list of outputs, it means the word unconditionally throws an error" } +} +"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." +$nl +"Recursive words must declare a stack effect in order to compile. This includes all generic words, due to how delegation is implemented." ; + +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." +$nl +"Stack effects are first-class, and words for working with them are found in the " { $vocab-link "effects" } " vocabulary." +{ $subsection effect } +{ $subsection effect? } +"Stack effects of words can be declared." +{ $subsection "effect-declaration" } +"Getting a word's declared stack effect:" +{ $subsection stack-effect } +"Converting a stack effect to a string form:" +{ $subsection effect>string } +"Comparing effects:" +{ $subsection effect-height } +{ $subsection effect<= } ; + +ABOUT: "effects" + +HELP: effect +{ $class-description "An object representing a stack effect. Holds a sequence of inputs, a sequence of outputs and a flag indicating if an error is thrown unconditionally." } ; + +HELP: effect-height +{ $values { "effect" effect } { "n" integer } } +{ $description "Outputs the number of objects added to the data stack by the stack effect. This will be negative if the stack effect only removes objects from the stack." } ; + +HELP: effect<= +{ $values { "eff1" effect } { "eff2" effect } { "?" "a boolean" } } +{ $description "Tests if " { $snippet "eff1" } " is substitutable for " { $snippet "eff2" } ". What this means is that both stack effects change the stack height by the same amount, the first takes a smaller or equal number of inputs as the second, and either both or neither one terminate execution by throwing an error." } ; + +HELP: effect>string +{ $values { "effect" effect } { "string" string } } +{ $description "Turns a stack effect object into a string mnemonic." } +{ $examples + { $example "USE: effects" "1 2 effect>string print" "( object -- object object )" } +} ; + +HELP: stack-effect +{ $values { "word" word } { "effect/f" "an " { $link effect } " or " { $link f } } } +{ $description "Outputs the stack effect of a word; either a stack effect declared with " { $link POSTPONE: ( } ", or an inferred stack effect (see " { $link "inference" } "." } ; diff --git a/core/effects/effects-tests.factor b/core/effects/effects-tests.factor new file mode 100644 index 0000000000..46037ba0d4 --- /dev/null +++ b/core/effects/effects-tests.factor @@ -0,0 +1,9 @@ +IN: temporary +USING: effects tools.test ; + +[ t ] [ 1 1 2 2 effect<= ] unit-test +[ f ] [ 1 0 2 2 effect<= ] unit-test +[ t ] [ 2 2 2 2 effect<= ] unit-test +[ f ] [ 3 3 2 2 effect<= ] unit-test +[ f ] [ 2 3 2 2 effect<= ] unit-test +[ t ] [ 2 3 f effect<= ] unit-test diff --git a/core/effects/effects.factor b/core/effects/effects.factor new file mode 100644 index 0000000000..62d6afc393 --- /dev/null +++ b/core/effects/effects.factor @@ -0,0 +1,53 @@ +! Copyright (C) 2006, 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel math namespaces sequences strings words assocs +combinators ; +IN: effects + +TUPLE: effect in out terminated? ; + +: ( in out -- effect ) + dup { "*" } sequence= [ drop { } t ] [ f ] if + effect construct-boa ; + +: effect-height ( effect -- n ) + dup effect-out length swap effect-in length - ; + +: effect<= ( eff1 eff2 -- ? ) + { + { [ dup not ] [ t ] } + { [ over effect-terminated? ] [ t ] } + { [ dup effect-terminated? ] [ f ] } + { [ 2dup [ effect-in length ] 2apply > ] [ f ] } + { [ 2dup [ effect-height ] 2apply = not ] [ f ] } + { [ t ] [ t ] } + } cond 2nip ; + +GENERIC: (stack-picture) ( obj -- str ) +M: string (stack-picture) ; +M: word (stack-picture) word-name ; +M: integer (stack-picture) drop "object" ; + +: stack-picture ( seq -- string ) + [ [ (stack-picture) % CHAR: \s , ] each ] "" make ; + +: effect>string ( effect -- string ) + [ + "( " % + dup effect-in stack-picture % + "-- " % + dup effect-out stack-picture % + effect-terminated? [ "* " % ] when + ")" % + ] "" make ; + +: stack-effect ( word -- effect/f ) + dup symbol? [ + drop 0 1 + ] [ + { "declared-effect" "inferred-effect" } + swap word-props [ at ] curry map [ ] find nip + ] if ; + +M: effect clone + [ effect-in clone ] keep effect-out clone ; diff --git a/core/effects/summary.txt b/core/effects/summary.txt new file mode 100644 index 0000000000..54cd9d6e59 --- /dev/null +++ b/core/effects/summary.txt @@ -0,0 +1 @@ +Stack effects as first-class data types diff --git a/core/effects/tags.txt b/core/effects/tags.txt new file mode 100644 index 0000000000..abf53a421b --- /dev/null +++ b/core/effects/tags.txt @@ -0,0 +1 @@ +reflection diff --git a/core/float-arrays/float-arrays-docs.factor b/core/float-arrays/float-arrays-docs.factor new file mode 100644 index 0000000000..70bbfe296f --- /dev/null +++ b/core/float-arrays/float-arrays-docs.factor @@ -0,0 +1,54 @@ +USING: arrays bit-arrays vectors strings sbufs +kernel help.markup help.syntax math ; +IN: float-arrays + +ARTICLE: "float-arrays" "Float arrays" +"Float arrays are fixed-size mutable sequences (" { $link "sequence-protocol" } ") whose elements are instances of " { $link float } ". Elements are unboxed, hence the memory usage is lower than an equivalent " { $link array } " of floats. The literal syntax is covered in " { $link "syntax-float-arrays" } "." +$nl +"Float array words are in the " { $vocab-link "float-arrays" } " vocabulary." +$nl +"Float arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-byte-arrays" } "." +$nl +"Float arrays form a class of objects." +{ $subsection float-array } +{ $subsection float-array? } +"There are several ways to construct float arrays." +{ $subsection >float-array } +{ $subsection } +"Creating a float array from several elements on the stack:" +{ $subsection 1float-array } +{ $subsection 2float-array } +{ $subsection 3float-array } +{ $subsection 4float-array } ; + +ABOUT: "float-arrays" + +HELP: float-array +{ $description "The class of float arrays. See " { $link "syntax-float-arrays" } " for syntax and " { $link "float-arrays" } " for general information." } ; + +HELP: ( n initial -- float-array ) +{ $values { "n" "a non-negative integer" } { "initial" float } { "float-array" "a new float array" } } +{ $description "Creates a new float array holding " { $snippet "n" } " floats with the specified initial element." } ; + +HELP: >float-array +{ $values { "seq" "a sequence" } { "float-array" float-array } } +{ $description "Outputs a freshly-allocated float array whose elements have the same boolean values as a given sequence." } +{ $errors "Throws an error if the sequence contains elements other than real numbers." } ; + +HELP: 1float-array +{ $values { "x" object } { "array" float-array } } +{ $description "Create a new float array with one element." } ; + +{ 1array 2array 3array 4array } related-words + +HELP: 2float-array +{ $values { "x" object } { "y" object } { "array" float-array } } +{ $description "Create a new float array with two elements, with " { $snippet "x" } " appearing first." } ; + +HELP: 3float-array +{ $values { "x" object } { "y" object } { "z" object } { "array" float-array } } +{ $description "Create a new float array with three elements, with " { $snippet "x" } " appearing first." } ; + +HELP: 4float-array +{ $values { "w" object } { "x" object } { "y" object } { "z" object } { "array" float-array } } +{ $description "Create a new float array with four elements, with " { $snippet "w" } " appearing first." } ; diff --git a/core/float-arrays/float-arrays-tests.factor b/core/float-arrays/float-arrays-tests.factor new file mode 100644 index 0000000000..811c380e41 --- /dev/null +++ b/core/float-arrays/float-arrays-tests.factor @@ -0,0 +1,4 @@ +IN: temporary +USING: float-arrays tools.test ; + +[ F{ 1.0 1.0 1.0 } ] [ 3 1.0 ] unit-test diff --git a/core/float-arrays/float-arrays.factor b/core/float-arrays/float-arrays.factor new file mode 100644 index 0000000000..36ffabb611 --- /dev/null +++ b/core/float-arrays/float-arrays.factor @@ -0,0 +1,40 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +IN: float-arrays +USING: kernel kernel.private alien sequences +sequences.private math math.private ; + +fixnum 8 fixnum*fast ; inline + +PRIVATE> + +M: float-array clone (clone) ; +M: float-array length array-capacity ; + +M: float-array nth-unsafe + float-array@ alien-double ; + +M: float-array set-nth-unsafe + >r >r >float r> r> float-array@ set-alien-double ; + +: >float-array ( seq -- float-array ) F{ } clone-like ; inline + +M: float-array like + drop dup float-array? [ >float-array ] unless ; + +M: float-array new drop 0.0 ; + +M: float-array equal? + over float-array? [ sequence= ] [ 2drop f ] if ; + +INSTANCE: float-array sequence + +: 1float-array ( x -- array ) 1 swap ; flushable + +: 2float-array ( x y -- array ) F{ } 2sequence ; flushable + +: 3float-array ( x y z -- array ) F{ } 3sequence ; flushable + +: 4float-array ( w x y z -- array ) F{ } 4sequence ; flushable diff --git a/core/float-arrays/summary.txt b/core/float-arrays/summary.txt new file mode 100644 index 0000000000..0eac3b0b1a --- /dev/null +++ b/core/float-arrays/summary.txt @@ -0,0 +1 @@ +Efficient fixed-length floating point number arrays diff --git a/core/float-arrays/tags.txt b/core/float-arrays/tags.txt new file mode 100644 index 0000000000..42d711b32b --- /dev/null +++ b/core/float-arrays/tags.txt @@ -0,0 +1 @@ +collections diff --git a/core/generator/authors.txt b/core/generator/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/generator/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/generator/fixup/authors.txt b/core/generator/fixup/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/core/generator/fixup/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/core/generator/fixup/fixup-docs.factor b/core/generator/fixup/fixup-docs.factor new file mode 100644 index 0000000000..284af26a9b --- /dev/null +++ b/core/generator/fixup/fixup-docs.factor @@ -0,0 +1,32 @@ +USING: help.syntax help.markup generator.fixup math kernel +words strings alien ; + +HELP: frame-required +{ $values { "n" "a non-negative integer" } } +{ $description "Notify the code generator that the currently compiling code block needs a stack frame with room for at least " { $snippet "n" } " parameters." } ; + +HELP: (rel-fixup) +{ $values { "arg" integer } { "class" "a relocation class" } { "type" "a relocation type" } { "offset" integer } { "pair" "a pair of integers" } } +{ $description "Creates a relocation instruction for the VM's runtime compiled code linker." } ; + +HELP: add-literal +{ $values { "obj" object } { "n" integer } } +{ $description "Adds a literal to the " { $link literal-table } ", if it is not already there, and outputs the index of the literal in the table. This literal can then be used as an argument for a " { $link rt-literal } " relocation with " { $link rel-fixup } "." } ; + +HELP: word-table +{ $var-description "Holds a vector of words called from the currently compiling word." } ; + +HELP: add-word +{ $values { "word" word } { "n" integer } } +{ $description "Adds a word to the " { $link word-table } ", if it is not already there, and outputs the index of the word in the table. This literal can then be used as an argument for a " { $link rt-xt } " relocation with " { $link rel-fixup } "." } ; + +HELP: string>symbol +{ $values { "str" string } { "alien" alien } } +{ $description "Converts the string to a format which is a valid symbol name for the Factor VM's compiled code linker. By performing this conversion ahead of time, the image loader can run without allocating memory." +$nl +"On Windows CE, symbols are represented as UCS2 strings, and on all other platforms they are ASCII strings." } ; + +HELP: rel-dlsym +{ $values { "name" string } { "dll" "a " { $link dll } " or " { $link f } } { "class" "a relocation class" } } +{ $description "Records that the most recently assembled instruction contains a reference to the " { $snippet "name" } " symbol from " { $snippet "dll" } ". The correct " { $snippet "class" } " to use depends on instruction formats." +} ; diff --git a/core/generator/fixup/fixup.factor b/core/generator/fixup/fixup.factor new file mode 100644 index 0000000000..a339f950b4 --- /dev/null +++ b/core/generator/fixup/fixup.factor @@ -0,0 +1,156 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: arrays generic assocs hashtables +kernel kernel.private math namespaces sequences words +quotations strings alien system combinators math.bitfields +words.private cpu.architecture ; +IN: generator.fixup + +: no-stack-frame -1 ; inline + +TUPLE: frame-required n ; + +: frame-required ( n -- ) \ frame-required construct-boa , ; + +: stack-frame-size ( code -- n ) + no-stack-frame [ + dup frame-required? [ frame-required-n max ] [ drop ] if + ] reduce ; + +GENERIC: fixup* ( frame-size obj -- frame-size ) + +: code-format 22 getenv ; + +: compiled-offset ( -- n ) building get length code-format * ; + +TUPLE: label offset ; + +: