Merge branch 'master' of http://factorcode.org/git/factor into morse

Conflicts:

	extra/semantic-db/semantic-db.factor
db4
Alex Chapman 2008-04-23 22:30:00 +10:00
commit 2f48f21eaf
303 changed files with 5780 additions and 2507 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
_darcs _darcs
*.obj *.obj
*.o *.o
*.s
*.exe *.exe
Factor/factor Factor/factor
*.a *.a

View File

@ -439,7 +439,7 @@ install_build_system_port() {
} }
usage() { usage() {
echo "usage: $0 install|install-x11|install-macosx|self-update|quick-update|update|bootstrap|net-bootstrap|make-target" echo "usage: $0 install|install-x11|install-macosx|self-update|quick-update|update|bootstrap|dlls|net-bootstrap|make-target"
echo "If you are behind a firewall, invoke as:" echo "If you are behind a firewall, invoke as:"
echo "env GIT_PROTOCOL=http $0 <command>" echo "env GIT_PROTOCOL=http $0 <command>"
} }

View File

@ -28,12 +28,6 @@ M: f expired? drop t ;
: <alien> ( address -- alien ) : <alien> ( address -- alien )
f <displaced-alien> { simple-c-ptr } declare ; inline f <displaced-alien> { simple-c-ptr } declare ; inline
: alien>native-string ( alien -- string )
os windows? [ alien>u16-string ] [ alien>char-string ] if ;
: dll-path ( dll -- string )
(dll-path) alien>native-string ;
M: alien equal? M: alien equal?
over alien? [ over alien? [
2dup [ expired? ] either? [ 2dup [ expired? ] either? [

View File

@ -18,7 +18,6 @@ ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays"
{ $subsection >c-ushort-array } { $subsection >c-ushort-array }
{ $subsection >c-void*-array } { $subsection >c-void*-array }
{ $subsection c-bool-array> } { $subsection c-bool-array> }
{ $subsection c-char*-array> }
{ $subsection c-char-array> } { $subsection c-char-array> }
{ $subsection c-double-array> } { $subsection c-double-array> }
{ $subsection c-float-array> } { $subsection c-float-array> }
@ -30,7 +29,6 @@ ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays"
{ $subsection c-uint-array> } { $subsection c-uint-array> }
{ $subsection c-ulong-array> } { $subsection c-ulong-array> }
{ $subsection c-ulonglong-array> } { $subsection c-ulonglong-array> }
{ $subsection c-ushort*-array> }
{ $subsection c-ushort-array> } { $subsection c-ushort-array> }
{ $subsection c-void*-array> } ; { $subsection c-void*-array> } ;
@ -61,9 +59,7 @@ ARTICLE: "c-arrays-get/set" "Reading and writing elements in C arrays"
{ $subsection double-nth } { $subsection double-nth }
{ $subsection set-double-nth } { $subsection set-double-nth }
{ $subsection void*-nth } { $subsection void*-nth }
{ $subsection set-void*-nth } { $subsection set-void*-nth } ;
{ $subsection char*-nth }
{ $subsection ushort*-nth } ;
ARTICLE: "c-arrays" "C arrays" 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" } "." "C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "."

View File

@ -1,8 +1,7 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays alien.c-types alien.structs USING: alien arrays alien.c-types alien.structs
sequences math kernel generator.registers sequences math kernel namespaces libc cpu.architecture ;
namespaces libc ;
IN: alien.arrays IN: alien.arrays
UNION: value-type array struct-type ; UNION: value-type array struct-type ;
@ -27,7 +26,9 @@ M: array stack-size drop "void*" stack-size ;
M: value-type c-type-reg-class drop int-regs ; M: value-type c-type-reg-class drop int-regs ;
M: value-type c-type-prep drop f ; M: value-type c-type-boxer-quot drop f ;
M: value-type c-type-unboxer-quot drop f ;
M: value-type c-type-getter M: value-type c-type-getter
drop [ swap <displaced-alien> ] ; drop [ swap <displaced-alien> ] ;

View File

@ -62,28 +62,6 @@ HELP: <c-object>
{ <c-object> malloc-object } related-words { <c-object> 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>byte-array HELP: memory>byte-array
{ $values { "alien" c-ptr } { "len" "a non-negative integer" } { "byte-array" byte-array } } { $values { "alien" c-ptr } { "len" "a non-negative integer" } { "byte-array" byte-array } }
{ $description "Reads " { $snippet "len" } " bytes starting from " { $snippet "base" } " and stores them in a new byte array." } ; { $description "Reads " { $snippet "len" } " bytes starting from " { $snippet "base" } " and stores them in a new byte array." } ;
@ -111,18 +89,6 @@ HELP: malloc-byte-array
{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." } { $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
{ $errors "Throws an error if memory allocation fails." } ; { $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 HELP: define-nth
{ $values { "name" "a word name" } { "vocab" "a vocabulary name" } } { $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." } { $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." }
@ -202,8 +168,6 @@ $nl
{ $subsection *float } { $subsection *float }
{ $subsection *double } { $subsection *double }
{ $subsection *void* } { $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 <void*> } " and " { $link *void* } " may be used." ; "Note that while structure and union types do not get these words defined for them, there is no loss of generality since " { $link <void*> } " and " { $link *void* } " may be used." ;
ARTICLE: "c-types-specs" "C type specifiers" ARTICLE: "c-types-specs" "C type specifiers"
@ -267,26 +231,6 @@ $nl
"A wrapper for temporarily allocating a block of memory:" "A wrapper for temporarily allocating a block of memory:"
{ $subsection with-malloc } ; { $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 } ". See " { $link "byte-arrays-gc" } " for a discussion of the two approaches."
$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 }
"For example, if a C function returns a " { $snippet "char*" } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $snippet "void*" } ", and call one of the above words before passing the pointer to " { $link free } "." ;
ARTICLE: "c-data" "Passing data between Factor and C" 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." "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."
$nl $nl

View File

@ -1,30 +1,6 @@
IN: alien.c-types.tests IN: alien.c-types.tests
USING: alien alien.syntax alien.c-types kernel tools.test USING: alien alien.syntax alien.c-types kernel tools.test
sequences system libc ; sequences system libc alien.strings io.encodings.utf8 ;
[ "\u0000ff" ]
[ "\u0000ff" string>char-alien alien>char-string ]
unit-test
[ "hello world" ]
[ "hello world" string>char-alien alien>char-string ]
unit-test
[ "hello\u00abcdworld" ]
[ "hello\u00abcdworld" 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* ; : foo ( -- n ) "fdafd" f dlsym [ 123 ] unless* ;
@ -67,7 +43,7 @@ TYPEDEF: int* MyIntArray
TYPEDEF: uchar* MyLPBYTE TYPEDEF: uchar* MyLPBYTE
[ t ] [ "char*" c-type "MyLPBYTE" c-type eq? ] unit-test [ t ] [ { "char*" utf8 } c-type "MyLPBYTE" c-type = ] unit-test
[ [
0 B{ 1 2 3 4 } <displaced-alien> <void*> 0 B{ 1 2 3 4 } <displaced-alien> <void*>

View File

@ -1,7 +1,7 @@
! Copyright (C) 2004, 2008 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: bit-arrays byte-arrays float-arrays arrays USING: bit-arrays byte-arrays float-arrays arrays
generator.registers assocs kernel kernel.private libc math assocs kernel kernel.private libc math
namespaces parser sequences strings words assocs splitting namespaces parser sequences strings words assocs splitting
math.parser cpu.architecture alien alien.accessors quotations math.parser cpu.architecture alien alien.accessors quotations
layouts system compiler.units io.files io.encodings.binary layouts system compiler.units io.files io.encodings.binary
@ -14,7 +14,7 @@ DEFER: *char
: little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable : little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable
TUPLE: c-type TUPLE: c-type
boxer prep unboxer boxer boxer-quot unboxer unboxer-quot
getter setter getter setter
reg-class size align stack-align? ; reg-class size align stack-align? ;
@ -149,23 +149,12 @@ M: float-array byte-length length "double" heap-size * ;
: malloc-byte-array ( byte-array -- alien ) : malloc-byte-array ( byte-array -- alien )
dup length dup malloc [ -rot memcpy ] keep ; 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 ;
: memory>byte-array ( alien len -- byte-array ) : memory>byte-array ( alien len -- byte-array )
dup <byte-array> [ -rot memcpy ] keep ; dup <byte-array> [ -rot memcpy ] keep ;
: byte-array>memory ( byte-array base -- ) : byte-array>memory ( byte-array base -- )
swap dup length memcpy ; swap dup length memcpy ;
DEFER: >c-ushort-array
: string>u16-memory ( string base -- )
>r >c-ushort-array r> byte-array>memory ;
: (define-nth) ( word type quot -- ) : (define-nth) ( word type quot -- )
>r heap-size [ rot * ] swap prefix r> append define-inline ; >r heap-size [ rot * ] swap prefix r> append define-inline ;
@ -378,7 +367,7 @@ M: long-long-type box-return ( type -- )
"box_float" >>boxer "box_float" >>boxer
"to_float" >>unboxer "to_float" >>unboxer
single-float-regs >>reg-class single-float-regs >>reg-class
[ >float ] >>prep [ >float ] >>unboxer-quot
"float" define-primitive-type "float" define-primitive-type
<c-type> <c-type>
@ -389,30 +378,8 @@ M: long-long-type box-return ( type -- )
"box_double" >>boxer "box_double" >>boxer
"to_double" >>unboxer "to_double" >>unboxer
double-float-regs >>reg-class double-float-regs >>reg-class
[ >float ] >>prep [ >float ] >>unboxer-quot
"double" define-primitive-type "double" define-primitive-type
<c-type>
[ alien-cell alien>char-string ] >>getter
[ set-alien-cell ] >>setter
bootstrap-cell >>size
bootstrap-cell >>align
"box_char_string" >>boxer
"alien_offset" >>unboxer
[ string>char-alien ] >>prep
"char*" define-primitive-type
"char*" "uchar*" typedef
<c-type>
[ alien-cell alien>u16-string ] >>getter
[ set-alien-cell ] >>setter
4 >>size
4 >>align
"box_u16_string" >>boxer
"alien_offset" >>unboxer
[ string>u16-alien ] >>prep
"ushort*" define-primitive-type
os winnt? cpu x86.64? and "longlong" "long" ? "ptrdiff_t" typedef os winnt? cpu x86.64? and "longlong" "long" ? "ptrdiff_t" typedef
] with-compilation-unit ] with-compilation-unit

View File

@ -3,7 +3,7 @@ USING: alien alien.c-types alien.syntax compiler kernel
namespaces namespaces tools.test sequences inference words namespaces namespaces tools.test sequences inference words
arrays parser quotations continuations inference.backend effects arrays parser quotations continuations inference.backend effects
namespaces.private io io.streams.string memory system threads namespaces.private io io.streams.string memory system threads
tools.test ; tools.test math ;
FUNCTION: void ffi_test_0 ; FUNCTION: void ffi_test_0 ;
[ ] [ ffi_test_0 ] unit-test [ ] [ ffi_test_0 ] unit-test
@ -280,6 +280,10 @@ FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
[ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test [ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test
FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;
[ t ] [ 31 2^ 32 2^ ffi_test_38 63 2^ = ] unit-test
! Test callbacks ! Test callbacks
: callback-1 "void" { } "cdecl" [ ] alien-callback ; : callback-1 "void" { } "cdecl" [ ] alien-callback ;
@ -354,3 +358,18 @@ FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
] alien-callback ; ] alien-callback ;
[ ] [ callback-8 callback_test_1 ] unit-test [ ] [ callback-8 callback_test_1 ] unit-test
: callback-9
"int" { "int" "int" "int" } "cdecl" [
+ + 1+
] alien-callback ;
FUNCTION: void ffi_test_36_point_5 ( ) ;
[ ] [ ffi_test_36_point_5 ] unit-test
FUNCTION: int ffi_test_37 ( void* func ) ;
[ 1 ] [ callback-9 ffi_test_37 ] unit-test
[ 7 ] [ callback-9 ffi_test_37 ] unit-test

View File

@ -3,10 +3,11 @@
USING: arrays generator generator.registers generator.fixup USING: arrays generator generator.registers generator.fixup
hashtables kernel math namespaces sequences words hashtables kernel math namespaces sequences words
inference.state inference.backend inference.dataflow system inference.state inference.backend inference.dataflow system
math.parser classes alien.arrays alien.c-types alien.structs math.parser classes alien.arrays alien.c-types alien.strings
alien.syntax cpu.architecture alien inspector quotations assocs alien.structs alien.syntax cpu.architecture alien inspector
kernel.private threads continuations.private libc combinators quotations assocs kernel.private threads continuations.private
compiler.errors continuations layouts accessors ; libc combinators compiler.errors continuations layouts accessors
;
IN: alien.compiler IN: alien.compiler
TUPLE: #alien-node < node return parameters abi ; TUPLE: #alien-node < node return parameters abi ;
@ -20,9 +21,7 @@ TUPLE: #alien-invoke < #alien-node library function ;
: large-struct? ( ctype -- ? ) : large-struct? ( ctype -- ? )
dup c-struct? [ dup c-struct? [
heap-size struct-small-enough? not heap-size struct-small-enough? not
] [ ] [ drop f ] if ;
drop f
] if ;
: alien-node-parameters* ( node -- seq ) : alien-node-parameters* ( node -- seq )
dup parameters>> dup parameters>>
@ -162,17 +161,16 @@ M: long-long-type flatten-value-type ( type -- )
dup return>> "void" = 0 1 ? dup return>> "void" = 0 1 ?
swap produce-values ; swap produce-values ;
: (make-prep-quot) ( parameters -- ) : (param-prep-quot) ( parameters -- )
dup empty? [ dup empty? [
drop drop
] [ ] [
unclip c-type c-type-prep % unclip c-type c-type-unboxer-quot %
\ >r , (make-prep-quot) \ r> , \ >r , (param-prep-quot) \ r> ,
] if ; ] if ;
: make-prep-quot ( node -- quot ) : param-prep-quot ( node -- quot )
parameters>> parameters>> [ <reversed> (param-prep-quot) ] [ ] make ;
[ <reversed> (make-prep-quot) ] [ ] make ;
: unbox-parameters ( offset node -- ) : unbox-parameters ( offset node -- )
parameters>> [ parameters>> [
@ -200,6 +198,20 @@ M: long-long-type flatten-value-type ( type -- )
: box-return* ( node -- ) : box-return* ( node -- )
return>> [ ] [ box-return ] if-void ; return>> [ ] [ box-return ] if-void ;
: (return-prep-quot) ( parameters -- )
dup empty? [
drop
] [
unclip c-type c-type-boxer-quot %
\ >r , (return-prep-quot) \ r> ,
] if ;
: callback-prep-quot ( node -- quot )
parameters>> [ <reversed> (return-prep-quot) ] [ ] make ;
: return-prep-quot ( node -- quot )
[ return>> [ ] [ 1array (return-prep-quot) ] if-void ] [ ] make ;
M: alien-invoke-error summary M: alien-invoke-error summary
drop drop
"Words calling ``alien-invoke'' must be compiled with the optimizing compiler." ; "Words calling ``alien-invoke'' must be compiled with the optimizing compiler." ;
@ -258,15 +270,15 @@ M: no-such-symbol compiler-error-type
pop-literal nip >>library pop-literal nip >>library
pop-literal nip >>return pop-literal nip >>return
! Quotation which coerces parameters to required types ! Quotation which coerces parameters to required types
dup make-prep-quot recursive-state get infer-quot dup param-prep-quot f infer-quot
! Set ABI ! Set ABI
dup library>> dup library>> library [ abi>> ] [ "cdecl" ] if* >>abi
library [ abi>> ] [ "cdecl" ] if*
>>abi
! Add node to IR ! Add node to IR
dup node, dup node,
! Magic #: consume exactly the number of inputs ! Magic #: consume exactly the number of inputs
0 alien-invoke-stack dup 0 alien-invoke-stack
! Quotation which coerces return value to required type
return-prep-quot f infer-quot
] "infer" set-word-prop ] "infer" set-word-prop
M: #alien-invoke generate-node M: #alien-invoke generate-node
@ -294,11 +306,13 @@ M: alien-indirect-error summary
pop-parameters >>parameters pop-parameters >>parameters
pop-literal nip >>return pop-literal nip >>return
! Quotation which coerces parameters to required types ! Quotation which coerces parameters to required types
dup make-prep-quot [ dip ] curry recursive-state get infer-quot dup param-prep-quot [ dip ] curry f infer-quot
! Add node to IR ! Add node to IR
dup node, dup node,
! Magic #: consume the function pointer, too ! Magic #: consume the function pointer, too
1 alien-invoke-stack dup 1 alien-invoke-stack
! Quotation which coerces return value to required type
return-prep-quot f infer-quot
] "infer" set-word-prop ] "infer" set-word-prop
M: #alien-indirect generate-node M: #alien-indirect generate-node
@ -331,7 +345,7 @@ M: alien-callback-error summary
: callback-bottom ( node -- ) : callback-bottom ( node -- )
xt>> [ word-xt drop <alien> ] curry xt>> [ word-xt drop <alien> ] curry
recursive-state get infer-quot ; f infer-quot ;
\ alien-callback [ \ alien-callback [
4 ensure-values 4 ensure-values
@ -371,16 +385,18 @@ TUPLE: callback-context ;
slip slip
wait-to-return ; inline wait-to-return ; inline
: prepare-callback-return ( ctype -- quot ) : callback-return-quot ( ctype -- quot )
return>> { return>> {
{ [ dup "void" = ] [ drop [ ] ] } { [ dup "void" = ] [ drop [ ] ] }
{ [ dup large-struct? ] [ heap-size [ memcpy ] curry ] } { [ dup large-struct? ] [ heap-size [ memcpy ] curry ] }
[ c-type c-type-prep ] [ c-type c-type-unboxer-quot ]
} cond ; } cond ;
: wrap-callback-quot ( node -- quot ) : wrap-callback-quot ( node -- quot )
[ [
[ quot>> ] [ prepare-callback-return ] bi append , [ callback-prep-quot ]
[ quot>> ]
[ callback-return-quot ] tri 3append ,
[ callback-context new do-callback ] % [ callback-context new do-callback ] %
] [ ] make ; ] [ ] make ;
@ -403,12 +419,12 @@ TUPLE: callback-context ;
: generate-callback ( node -- ) : generate-callback ( node -- )
dup xt>> dup [ dup xt>> dup [
init-templates init-templates
%save-word-xt
%prologue-later %prologue-later
dup alien-stack-frame [ dup alien-stack-frame [
dup registers>objects [ registers>objects ]
dup wrap-callback-quot %alien-callback [ wrap-callback-quot %alien-callback ]
%callback-return [ %callback-return ]
tri
] with-stack-frame ] with-stack-frame
] with-generator ; ] with-generator ;

View File

@ -1,12 +1,12 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types parser threads words kernel.private USING: alien alien.c-types alien.strings parser threads words
kernel ; kernel.private kernel io.encodings.utf8 ;
IN: alien.remote-control IN: alien.remote-control
: eval-callback : eval-callback
"void*" { "char*" } "cdecl" "void*" { "char*" } "cdecl"
[ eval>string malloc-char-string ] alien-callback ; [ eval>string utf8 malloc-string ] alien-callback ;
: yield-callback : yield-callback
"void" { } "cdecl" [ yield ] alien-callback ; "void" { } "cdecl" [ yield ] alien-callback ;

View File

@ -0,0 +1,52 @@
USING: help.markup help.syntax strings byte-arrays alien libc
debugger ;
IN: alien.strings
HELP: string>alien
{ $values { "string" string } { "encoding" "an encoding descriptor" } { "byte-array" byte-array } }
{ $description "Encodes a string together with a trailing null code point using the given encoding, and stores the resulting bytes in a freshly-allocated byte array." }
{ $errors "Throws an error if the string contains null characters, or characters not representable in the given encoding." } ;
{ string>alien alien>string malloc-string } related-words
HELP: alien>string
{ $values { "c-ptr" c-ptr } { "encoding" "an encoding descriptor" } { "string/f" "a string or " { $link f } } }
{ $description "Reads a null-terminated C string from the specified address with the given encoding." } ;
HELP: malloc-string
{ $values { "string" string } { "encoding" "an encoding descriptor" } { "alien" c-ptr } }
{ $description "Encodes a string together with a trailing null code point using the given encoding, and stores the resulting bytes in a freshly-allocated unmanaged memory block." }
{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
{ $errors "Throws an error if one of the following conditions occurs:"
{ $list
"the string contains null code points"
"the string contains characters not representable using the encoding specified"
"memory allocation fails"
}
} ;
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: utf16n
{ $class-description "The encoding descriptor for UTF-16 without a byte order mark in native endian order. This is useful mostly for FFI calls which take input of strings of the type wchar_t*" }
{ $see-also "encodings-introduction" } ;
ARTICLE: "c-strings" "C strings"
"C string types are arrays with shape " { $snippet "{ \"char*\" encoding }" } ", where " { $snippet "encoding" } " is an encoding descriptor. The type " { $snippet "\"char*\"" } " is an alias for " { $snippet "{ \"char*\" utf8 }" } ". See " { $link "encodings-descriptors" } " for information about encoding descriptors."
$nl
"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."
$nl
"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>alien }
{ $subsection malloc-string }
"The first allocates " { $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 } ". See " { $link "byte-arrays-gc" } " for a discussion of the two approaches."
$nl
"A word to read strings from arbitrary addresses:"
{ $subsection alien>string }
"For example, if a C function returns a " { $snippet "char*" } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $snippet "void*" } ", and call one of the above words before passing the pointer to " { $link free } "." ;
ABOUT: "c-strings"

View File

@ -0,0 +1,30 @@
USING: alien.strings tools.test kernel libc
io.encodings.8-bit io.encodings.utf8 io.encodings.utf16
io.encodings.ascii alien ;
IN: alien.strings.tests
[ "\u0000ff" ]
[ "\u0000ff" latin1 string>alien latin1 alien>string ]
unit-test
[ "hello world" ]
[ "hello world" latin1 string>alien latin1 alien>string ]
unit-test
[ "hello\u00abcdworld" ]
[ "hello\u00abcdworld" utf16le string>alien utf16le alien>string ]
unit-test
[ t ] [ f expired? ] unit-test
[ "hello world" ] [
"hello world" ascii malloc-string
dup ascii alien>string swap free
] unit-test
[ "hello world" ] [
"hello world" utf16n malloc-string
dup utf16n alien>string swap free
] unit-test
[ f ] [ f utf8 alien>string ] unit-test

View File

@ -0,0 +1,111 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays sequences kernel accessors math alien.accessors
alien.c-types byte-arrays words io io.encodings
io.streams.byte-array io.streams.memory io.encodings.utf8
io.encodings.utf16 system alien strings cpu.architecture ;
IN: alien.strings
GENERIC# alien>string 1 ( c-ptr encoding -- string/f )
M: c-ptr alien>string
>r <memory-stream> r> <decoder>
"\0" swap stream-read-until drop ;
M: f alien>string
drop ;
ERROR: invalid-c-string string ;
: check-string ( string -- )
0 over memq? [ invalid-c-string ] [ drop ] if ;
GENERIC# string>alien 1 ( string encoding -- byte-array )
M: c-ptr string>alien drop ;
M: string string>alien
over check-string
<byte-writer>
[ stream-write ]
[ 0 swap stream-write1 ]
[ stream>> >byte-array ]
tri ;
: malloc-string ( string encoding -- alien )
string>alien malloc-byte-array ;
PREDICATE: string-type < pair
first2 [ "char*" = ] [ word? ] bi* and ;
M: string-type c-type ;
M: string-type heap-size
drop "void*" heap-size ;
M: string-type c-type-align
drop "void*" c-type-align ;
M: string-type c-type-stack-align?
drop "void*" c-type-stack-align? ;
M: string-type unbox-parameter
drop "void*" unbox-parameter ;
M: string-type unbox-return
drop "void*" unbox-return ;
M: string-type box-parameter
drop "void*" box-parameter ;
M: string-type box-return
drop "void*" box-return ;
M: string-type stack-size
drop "void*" stack-size ;
M: string-type c-type-reg-class
drop int-regs ;
M: string-type c-type-boxer
drop "void*" c-type-boxer ;
M: string-type c-type-unboxer
drop "void*" c-type-unboxer ;
M: string-type c-type-boxer-quot
second [ alien>string ] curry [ ] like ;
M: string-type c-type-unboxer-quot
second [ string>alien ] curry [ ] like ;
M: string-type c-type-getter
drop [ alien-cell ] ;
M: string-type c-type-setter
drop [ set-alien-cell ] ;
TUPLE: utf16n ;
! Native-order UTF-16
: utf16n ( -- descriptor )
little-endian? utf16le utf16be ? ; foldable
M: utf16n <decoder> drop utf16n <decoder> ;
M: utf16n <encoder> drop utf16n <encoder> ;
: alien>native-string ( alien -- string )
os windows? [ utf16n ] [ utf8 ] if alien>string ;
: dll-path ( dll -- string )
(dll-path) alien>native-string ;
: string>symbol ( str -- alien )
[ os wince? [ utf16n ] [ utf8 ] if string>alien ]
over string? [ call ] [ map ] if ;
{ "char*" utf8 } "char*" typedef
{ "char*" utf16n } "wchar_t*" typedef
"char*" "uchar*" typedef

View File

@ -1,6 +1,6 @@
IN: alien.structs.tests IN: alien.structs.tests
USING: alien alien.syntax alien.c-types kernel tools.test USING: alien alien.syntax alien.c-types kernel tools.test
sequences system libc words vocabs namespaces ; sequences system libc words vocabs namespaces layouts ;
C-STRUCT: bar C-STRUCT: bar
{ "int" "x" } { "int" "x" }
@ -9,20 +9,20 @@ C-STRUCT: bar
[ 36 ] [ "bar" heap-size ] unit-test [ 36 ] [ "bar" heap-size ] unit-test
[ t ] [ \ <displaced-alien> "bar" c-type c-type-getter memq? ] unit-test [ t ] [ \ <displaced-alien> "bar" c-type c-type-getter memq? ] unit-test
! This was actually only correct on Windows/x86: C-STRUCT: align-test
{ "int" "x" }
{ "double" "y" } ;
! C-STRUCT: align-test os winnt? cpu x86? and [
! { "int" "x" } [ 16 ] [ "align-test" heap-size ] unit-test
! { "double" "y" } ;
! cell 4 = [
! [ 16 ] [ "align-test" heap-size ] unit-test C-STRUCT: one
! { "long" "a" } { "double" "b" } { "int" "c" } ;
! cell 4 = [
! C-STRUCT: one [ 24 ] [ "one" heap-size ] unit-test
! { "long" "a" } { "double" "b" } { "int" "c" } ; ] when
! ] when
! [ 24 ] [ "one" heap-size ] unit-test
! ] when
: MAX_FOOS 30 ; : MAX_FOOS 30 ;

View File

@ -20,14 +20,19 @@ IN: alien.structs
: define-getter ( type spec -- ) : define-getter ( type spec -- )
[ set-reader-props ] keep [ set-reader-props ] keep
dup slot-spec-reader [ ]
over slot-spec-type c-getter [ slot-spec-reader ]
[
slot-spec-type
[ c-getter ] [ c-type c-type-boxer-quot ] bi append
] tri
define-struct-slot-word ; define-struct-slot-word ;
: define-setter ( type spec -- ) : define-setter ( type spec -- )
[ set-writer-props ] keep [ set-writer-props ] keep
dup slot-spec-writer [ ]
over slot-spec-type c-setter [ slot-spec-writer ]
[ slot-spec-type c-setter ] tri
define-struct-slot-word ; define-struct-slot-word ;
: define-field ( type spec -- ) : define-field ( type spec -- )

View File

@ -1,9 +1,9 @@
! Copyright (C) 2005, 2008 Slava Pestov, Alex Chapman. ! Copyright (C) 2005, 2008 Slava Pestov, Alex Chapman.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays alien alien.c-types alien.structs alien.arrays USING: arrays alien alien.c-types alien.structs alien.arrays
kernel math namespaces parser sequences words quotations alien.strings kernel math namespaces parser sequences words
math.parser splitting effects prettyprint prettyprint.sections quotations math.parser splitting effects prettyprint
prettyprint.backend assocs combinators ; prettyprint.sections prettyprint.backend assocs combinators ;
IN: alien.syntax IN: alien.syntax
<PRIVATE <PRIVATE

View File

@ -58,16 +58,13 @@ num-types get f <array> builtins set
"alien.accessors" "alien.accessors"
"arrays" "arrays"
"bit-arrays" "bit-arrays"
"bit-vectors"
"byte-arrays" "byte-arrays"
"byte-vectors"
"classes.private" "classes.private"
"classes.tuple" "classes.tuple"
"classes.tuple.private" "classes.tuple.private"
"compiler.units" "compiler.units"
"continuations.private" "continuations.private"
"float-arrays" "float-arrays"
"float-vectors"
"generator" "generator"
"growable" "growable"
"hashtables" "hashtables"
@ -455,54 +452,6 @@ tuple
} }
} define-tuple-class } define-tuple-class
"byte-vector" "byte-vectors" create
tuple
{
{
{ "byte-array" "byte-arrays" }
"underlying"
{ "underlying" "growable" }
{ "set-underlying" "growable" }
} {
{ "array-capacity" "sequences.private" }
"fill"
{ "length" "sequences" }
{ "set-fill" "growable" }
}
} define-tuple-class
"bit-vector" "bit-vectors" create
tuple
{
{
{ "bit-array" "bit-arrays" }
"underlying"
{ "underlying" "growable" }
{ "set-underlying" "growable" }
} {
{ "array-capacity" "sequences.private" }
"fill"
{ "length" "sequences" }
{ "set-fill" "growable" }
}
} define-tuple-class
"float-vector" "float-vectors" create
tuple
{
{
{ "float-array" "float-arrays" }
"underlying"
{ "underlying" "growable" }
{ "set-underlying" "growable" }
} {
{ "array-capacity" "sequences.private" }
"fill"
{ "length" "sequences" }
{ "set-fill" "growable" }
}
} define-tuple-class
"curry" "kernel" create "curry" "kernel" create
tuple tuple
{ {
@ -689,10 +638,6 @@ tuple
{ "set-alien-double" "alien.accessors" } { "set-alien-double" "alien.accessors" }
{ "alien-cell" "alien.accessors" } { "alien-cell" "alien.accessors" }
{ "set-alien-cell" "alien.accessors" } { "set-alien-cell" "alien.accessors" }
{ "alien>char-string" "alien" }
{ "string>char-alien" "alien" }
{ "alien>u16-string" "alien" }
{ "string>u16-alien" "alien" }
{ "(throw)" "kernel.private" } { "(throw)" "kernel.private" }
{ "alien-address" "alien" } { "alien-address" "alien" }
{ "slot" "slots.private" } { "slot" "slots.private" }

View File

@ -27,10 +27,6 @@ SYMBOL: bootstrap-time
diff diff
[ "bootstrap." prepend require ] each ; [ "bootstrap." prepend require ] each ;
! : compile-remaining ( -- )
! "Compiling remaining words..." print flush
! vocabs [ words [ compiled? not ] subset compile ] each ;
: count-words ( pred -- ) : count-words ( pred -- )
all-words swap subset length number>string write ; all-words swap subset length number>string write ;

View File

@ -14,16 +14,13 @@ IN: bootstrap.syntax
";" ";"
"<PRIVATE" "<PRIVATE"
"?{" "?{"
"?V{"
"BIN:" "BIN:"
"B{" "B{"
"BV{"
"C:" "C:"
"CHAR:" "CHAR:"
"DEFER:" "DEFER:"
"ERROR:" "ERROR:"
"F{" "F{"
"FV{"
"FORGET:" "FORGET:"
"GENERIC#" "GENERIC#"
"GENERIC:" "GENERIC:"

View File

@ -4,7 +4,7 @@ kernel math namespaces parser prettyprint sequences strings
tools.test vectors words quotations classes classes.algebra tools.test vectors words quotations classes classes.algebra
classes.private classes.union classes.mixin classes.predicate classes.private classes.union classes.mixin classes.predicate
vectors definitions source-files compiler.units growable vectors definitions source-files compiler.units growable
random inference effects kernel.private ; random inference effects kernel.private sbufs ;
: class= [ class< ] 2keep swap class< and ; : class= [ class< ] 2keep swap class< and ;
@ -144,6 +144,48 @@ UNION: z1 b1 c1 ;
[ f ] [ null class-not null class= ] unit-test [ f ] [ null class-not null class= ] unit-test
[ t ] [
fixnum class-not
fixnum fixnum class-not class-or
class<
] 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
[ f ] [ null { number fixnum null } min-class ] unit-test
! Test for hangs? ! Test for hangs?
: random-class classes random ; : random-class classes random ;

View File

@ -77,10 +77,10 @@ C: <anonymous-complement> anonymous-complement
{ [ 2dup [ anonymous-complement? ] both? ] [ anonymous-complement< ] } { [ 2dup [ anonymous-complement? ] both? ] [ anonymous-complement< ] }
{ [ over anonymous-union? ] [ left-anonymous-union< ] } { [ over anonymous-union? ] [ left-anonymous-union< ] }
{ [ over anonymous-intersection? ] [ left-anonymous-intersection< ] } { [ over anonymous-intersection? ] [ left-anonymous-intersection< ] }
{ [ over anonymous-complement? ] [ 2drop f ] }
{ [ over members ] [ left-union-class< ] } { [ over members ] [ left-union-class< ] }
{ [ dup anonymous-union? ] [ right-anonymous-union< ] } { [ dup anonymous-union? ] [ right-anonymous-union< ] }
{ [ dup anonymous-intersection? ] [ right-anonymous-intersection< ] } { [ dup anonymous-intersection? ] [ right-anonymous-intersection< ] }
{ [ over anonymous-complement? ] [ 2drop f ] }
{ [ dup anonymous-complement? ] [ class>> classes-intersect? not ] } { [ dup anonymous-complement? ] [ class>> classes-intersect? not ] }
{ [ dup members ] [ right-union-class< ] } { [ dup members ] [ right-union-class< ] }
{ [ over superclass ] [ superclass< ] } { [ over superclass ] [ superclass< ] }
@ -193,9 +193,8 @@ C: <anonymous-complement> anonymous-complement
[ ] unfold nip ; [ ] unfold nip ;
: min-class ( class seq -- class/f ) : min-class ( class seq -- class/f )
[ dupd classes-intersect? ] subset dup empty? [ over [ classes-intersect? ] curry subset
2drop f dup empty? [ 2drop f ] [
] [
tuck [ class< ] with all? [ peek ] [ drop f ] if tuck [ class< ] with all? [ peek ] [ drop f ] if
] if ; ] if ;

View File

@ -3,7 +3,8 @@ math.constants parser sequences tools.test words assocs
namespaces quotations sequences.private classes continuations namespaces quotations sequences.private classes continuations
generic.standard effects classes.tuple classes.tuple.private generic.standard effects classes.tuple classes.tuple.private
arrays vectors strings compiler.units accessors classes.algebra arrays vectors strings compiler.units accessors classes.algebra
calendar prettyprint io.streams.string splitting inspector ; calendar prettyprint io.streams.string splitting inspector
columns ;
IN: classes.tuple.tests IN: classes.tuple.tests
TUPLE: rect x y w h ; TUPLE: rect x y w h ;

View File

@ -150,7 +150,7 @@ M: hashtable hashcode*
drop drop
] [ ] [
dup length 4 <= dup length 4 <=
over keys [ word? ] contains? or over keys [ [ word? ] [ wrapper? ] bi or ] contains? or
[ [
linear-case-quot linear-case-quot
] [ ] [

View File

@ -4,8 +4,8 @@ math.constants math.private sequences strings tools.test words
continuations sequences.private hashtables.private byte-arrays continuations sequences.private hashtables.private byte-arrays
strings.private system random layouts vectors.private strings.private system random layouts vectors.private
sbufs.private strings.private slots.private alien sbufs.private strings.private slots.private alien
alien.accessors alien.c-types alien.syntax namespaces libc alien.accessors alien.c-types alien.syntax alien.strings
sequences.private ; namespaces libc sequences.private io.encodings.ascii ;
! Make sure that intrinsic ops compile to correct code. ! Make sure that intrinsic ops compile to correct code.
[ ] [ 1 [ drop ] compile-call ] unit-test [ ] [ 1 [ drop ] compile-call ] unit-test
@ -361,11 +361,11 @@ cell 8 = [
[ ] [ "b" get free ] unit-test [ ] [ "b" get free ] unit-test
] when ] when
[ ] [ "hello world" malloc-char-string "s" set ] unit-test [ ] [ "hello world" ascii malloc-string "s" set ] unit-test
"s" get [ "s" get [
[ "hello world" ] [ "s" get <void*> [ { byte-array } declare *void* ] compile-call alien>char-string ] unit-test [ "hello world" ] [ "s" get <void*> [ { byte-array } declare *void* ] compile-call ascii alien>string ] unit-test
[ "hello world" ] [ "s" get <void*> [ { c-ptr } declare *void* ] compile-call alien>char-string ] unit-test [ "hello world" ] [ "s" get <void*> [ { c-ptr } declare *void* ] compile-call ascii alien>string ] unit-test
[ ] [ "s" get free ] unit-test [ ] [ "s" get free ] unit-test
] when ] when

View File

@ -1,6 +1,6 @@
USING: compiler.units tools.test kernel kernel.private USING: compiler.units tools.test kernel kernel.private
sequences.private math.private math combinators strings sequences.private math.private math combinators strings
alien arrays memory ; alien arrays memory vocabs parser ;
IN: compiler.tests IN: compiler.tests
! Test empty word ! Test empty word
@ -230,3 +230,11 @@ M: f single-combination-test-2 single-combination-test-4 ;
! Regression ! Regression
[ 100 ] [ [ 100 [ [ ] times ] keep ] compile-call ] unit-test [ 100 ] [ [ 100 [ [ ] times ] keep ] compile-call ] unit-test
! Regression
10 [
[ "compiler.tests.foo" forget-vocab ] with-compilation-unit
[ t ] [
"USING: prettyprint words ; IN: compiler.tests.foo : (recursive) ( -- ) (recursive) (recursive) ; inline : recursive ( -- ) (recursive) ; \\ (recursive) compiled?" eval
] unit-test
] times

View File

@ -2,7 +2,8 @@
IN: compiler.tests IN: compiler.tests
USING: compiler generator generator.registers USING: compiler generator generator.registers
generator.registers.private tools.test namespaces sequences generator.registers.private tools.test namespaces sequences
words kernel math effects definitions compiler.units accessors ; words kernel math effects definitions compiler.units accessors
cpu.architecture ;
: <int-vreg> ( n -- vreg ) int-regs <vreg> ; : <int-vreg> ( n -- vreg ) int-regs <vreg> ;

View File

@ -3,7 +3,7 @@ USING: arrays compiler kernel kernel.private math
hashtables.private math.private namespaces sequences hashtables.private math.private namespaces sequences
sequences.private tools.test namespaces.private slots.private sequences.private tools.test namespaces.private slots.private
sequences.private byte-arrays alien alien.accessors layouts sequences.private byte-arrays alien alien.accessors layouts
words definitions compiler.units io combinators ; words definitions compiler.units io combinators vectors ;
IN: compiler.tests IN: compiler.tests
! Oops! ! Oops!
@ -246,3 +246,12 @@ TUPLE: my-tuple ;
} cleave ; } cleave ;
[ t ] [ \ float-spill-bug compiled? ] unit-test [ t ] [ \ float-spill-bug compiled? ] unit-test
! Regression
: dispatch-alignment-regression ( -- c )
{ tuple vector } 3 slot { word } declare
dup 1 slot 0 fixnum-bitand { [ ] } dispatch ;
[ t ] [ \ dispatch-alignment-regression compiled? ] unit-test
[ vector ] [ dispatch-alignment-regression ] unit-test

View File

@ -1,10 +1,17 @@
! Copyright (C) 2006, 2007 Slava Pestov. ! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays generic kernel kernel.private math memory USING: arrays generic kernel kernel.private math memory
namespaces sequences layouts system hashtables classes alien namespaces sequences layouts system hashtables classes alien
byte-arrays bit-arrays float-arrays combinators words sets ; byte-arrays bit-arrays float-arrays combinators words sets ;
IN: cpu.architecture IN: cpu.architecture
! Register classes
SINGLETON: int-regs
SINGLETON: single-float-regs
SINGLETON: double-float-regs
UNION: float-regs single-float-regs double-float-regs ;
UNION: reg-class int-regs float-regs ;
! A pseudo-register class for parameters spilled on the stack ! A pseudo-register class for parameters spilled on the stack
SINGLETON: stack-params SINGLETON: stack-params
@ -56,7 +63,7 @@ HOOK: %call cpu ( word -- )
HOOK: %jump-label cpu ( label -- ) HOOK: %jump-label cpu ( label -- )
! Test if vreg is 'f' or not ! Test if vreg is 'f' or not
HOOK: %jump-t cpu ( label -- ) HOOK: %jump-f cpu ( label -- )
HOOK: %dispatch cpu ( -- ) HOOK: %dispatch cpu ( -- )
@ -187,6 +194,9 @@ HOOK: %unbox-any-c-ptr cpu ( dst src -- )
HOOK: %box-alien cpu ( dst src -- ) HOOK: %box-alien cpu ( dst src -- )
! GC check
HOOK: %gc cpu
: operand ( var -- op ) get v>operand ; inline : operand ( var -- op ) get v>operand ; inline
: unique-operands ( operands quot -- ) : unique-operands ( operands quot -- )

View File

@ -1,4 +1,4 @@
! Copyright (C) 2006, 2007 Slava Pestov. ! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel cpu.ppc.architecture cpu.ppc.assembler USING: kernel cpu.ppc.architecture cpu.ppc.assembler
kernel.private namespaces math sequences generic arrays kernel.private namespaces math sequences generic arrays
@ -7,7 +7,7 @@ cpu.architecture alien ;
IN: cpu.ppc.allot IN: cpu.ppc.allot
: load-zone-ptr ( reg -- ) : load-zone-ptr ( reg -- )
"nursery" f pick %load-dlsym dup 0 LWZ ; >r "nursery" f r> %load-dlsym ;
: %allot ( header size -- ) : %allot ( header size -- )
#! Store a pointer to 'size' bytes allocated from the #! Store a pointer to 'size' bytes allocated from the
@ -25,6 +25,19 @@ IN: cpu.ppc.allot
: %store-tagged ( reg tag -- ) : %store-tagged ( reg tag -- )
>r dup fresh-object v>operand 11 r> tag-number ORI ; >r dup fresh-object v>operand 11 r> tag-number ORI ;
M: ppc %gc
"end" define-label
12 load-zone-ptr
11 12 cell LWZ ! nursery.here -> r11
12 12 3 cells LWZ ! nursery.end -> r12
11 11 1024 ADDI ! add ALLOT_BUFFER_ZONE to here
11 0 12 CMP ! is here >= end?
"end" get BLE
0 frame-required
%prepare-alien-invoke
"minor_gc" f %alien-invoke
"end" resolve-label ;
: %allot-float ( reg -- ) : %allot-float ( reg -- )
#! exits with tagged ptr to object in r12, untagged in r11 #! exits with tagged ptr to object in r12, untagged in r11
float 16 %allot float 16 %allot

View File

@ -106,8 +106,8 @@ M: ppc %call ( label -- ) BL ;
M: ppc %jump-label ( label -- ) B ; M: ppc %jump-label ( label -- ) B ;
M: ppc %jump-t ( label -- ) M: ppc %jump-f ( label -- )
0 "flag" operand f v>operand CMPI BNE ; 0 "flag" operand f v>operand CMPI BEQ ;
M: ppc %dispatch ( -- ) M: ppc %dispatch ( -- )
[ [

View File

@ -217,11 +217,11 @@ IN: cpu.ppc.intrinsics
2array define-if-intrinsics ; 2array define-if-intrinsics ;
{ {
{ fixnum< BLT } { fixnum< BGE }
{ fixnum<= BLE } { fixnum<= BGT }
{ fixnum> BGT } { fixnum> BLE }
{ fixnum>= BGE } { fixnum>= BLT }
{ eq? BEQ } { eq? BNE }
} [ } [
first2 define-fixnum-jump first2 define-fixnum-jump
] each ] each
@ -356,11 +356,11 @@ IN: cpu.ppc.intrinsics
{ { float "x" } { float "y" } } define-if-intrinsic ; { { float "x" } { float "y" } } define-if-intrinsic ;
{ {
{ float< BLT } { float< BGE }
{ float<= BLE } { float<= BGT }
{ float> BGT } { float> BLE }
{ float>= BGE } { float>= BLT }
{ float= BEQ } { float= BNE }
} [ } [
first2 define-float-jump first2 define-float-jump
] each ] each

View File

@ -16,8 +16,9 @@ IN: cpu.x86.32
M: x86.32 ds-reg ESI ; M: x86.32 ds-reg ESI ;
M: x86.32 rs-reg EDI ; M: x86.32 rs-reg EDI ;
M: x86.32 stack-reg ESP ; M: x86.32 stack-reg ESP ;
M: x86.32 xt-reg ECX ;
M: x86.32 stack-save-reg EDX ; M: x86.32 stack-save-reg EDX ;
M: x86.32 temp-reg-1 EAX ;
M: x86.32 temp-reg-2 ECX ;
M: temp-reg v>operand drop EBX ; M: temp-reg v>operand drop EBX ;
@ -267,7 +268,7 @@ os windows? [
EDX 26 SHR EDX 26 SHR
EDX 1 AND EDX 1 AND
{ EAX EBX ECX EDX } [ POP ] each { EAX EBX ECX EDX } [ POP ] each
JNE JE
] { } define-if-intrinsic ] { } define-if-intrinsic
"-no-sse2" cli-args member? [ "-no-sse2" cli-args member? [

View File

@ -11,8 +11,9 @@ IN: cpu.x86.64
M: x86.64 ds-reg R14 ; M: x86.64 ds-reg R14 ;
M: x86.64 rs-reg R15 ; M: x86.64 rs-reg R15 ;
M: x86.64 stack-reg RSP ; M: x86.64 stack-reg RSP ;
M: x86.64 xt-reg RCX ;
M: x86.64 stack-save-reg RSI ; M: x86.64 stack-save-reg RSI ;
M: x86.64 temp-reg-1 RAX ;
M: x86.64 temp-reg-2 RCX ;
M: temp-reg v>operand drop RBX ; M: temp-reg v>operand drop RBX ;

View File

@ -16,12 +16,12 @@ IN: cpu.x86.allot
: object@ ( n -- operand ) cells (object@) ; : object@ ( n -- operand ) cells (object@) ;
: load-zone-ptr ( -- ) : load-zone-ptr ( reg -- )
#! Load pointer to start of zone array #! Load pointer to start of zone array
"nursery" f allot-reg %alien-global ; 0 MOV "nursery" f rc-absolute-cell rel-dlsym ;
: load-allot-ptr ( -- ) : load-allot-ptr ( -- )
load-zone-ptr allot-reg load-zone-ptr
allot-reg PUSH allot-reg PUSH
allot-reg dup cell [+] MOV ; allot-reg dup cell [+] MOV ;
@ -29,6 +29,19 @@ IN: cpu.x86.allot
allot-reg POP allot-reg POP
allot-reg cell [+] swap 8 align ADD ; allot-reg cell [+] swap 8 align ADD ;
M: x86 %gc ( -- )
"end" define-label
temp-reg-1 load-zone-ptr
temp-reg-2 temp-reg-1 cell [+] MOV
temp-reg-2 1024 ADD
temp-reg-1 temp-reg-1 3 cells [+] MOV
temp-reg-2 temp-reg-1 CMP
"end" get JLE
0 frame-required
%prepare-alien-invoke
"minor_gc" f %alien-invoke
"end" resolve-label ;
: store-header ( header -- ) : store-header ( header -- )
0 object@ swap type-number tag-fixnum MOV ; 0 object@ swap type-number tag-fixnum MOV ;

View File

@ -9,7 +9,6 @@ IN: cpu.x86.architecture
HOOK: ds-reg cpu HOOK: ds-reg cpu
HOOK: rs-reg cpu HOOK: rs-reg cpu
HOOK: stack-reg cpu HOOK: stack-reg cpu
HOOK: xt-reg cpu
HOOK: stack-save-reg cpu HOOK: stack-save-reg cpu
: stack@ stack-reg swap [+] ; : stack@ stack-reg swap [+] ;
@ -35,6 +34,10 @@ GENERIC: push-return-reg ( reg-class -- )
GENERIC: load-return-reg ( stack@ reg-class -- ) GENERIC: load-return-reg ( stack@ reg-class -- )
GENERIC: store-return-reg ( stack@ reg-class -- ) GENERIC: store-return-reg ( stack@ reg-class -- )
! Only used by inline allocation
HOOK: temp-reg-1 cpu
HOOK: temp-reg-2 cpu
HOOK: address-operand cpu ( address -- operand ) HOOK: address-operand cpu ( address -- operand )
HOOK: fixnum>slot@ cpu HOOK: fixnum>slot@ cpu
@ -47,13 +50,13 @@ M: x86 stack-frame ( n -- i )
3 cells + 16 align cell - ; 3 cells + 16 align cell - ;
M: x86 %save-word-xt ( -- ) M: x86 %save-word-xt ( -- )
xt-reg 0 MOV rc-absolute-cell rel-this ; temp-reg v>operand 0 MOV rc-absolute-cell rel-this ;
: factor-area-size 4 cells ; : factor-area-size 4 cells ;
M: x86 %prologue ( n -- ) M: x86 %prologue ( n -- )
dup cell + PUSH dup cell + PUSH
xt-reg PUSH temp-reg v>operand PUSH
stack-reg swap 2 cells - SUB ; stack-reg swap 2 cells - SUB ;
M: x86 %epilogue ( n -- ) M: x86 %epilogue ( n -- )
@ -76,8 +79,8 @@ M: x86 %call ( label -- ) CALL ;
M: x86 %jump-label ( label -- ) JMP ; M: x86 %jump-label ( label -- ) JMP ;
M: x86 %jump-t ( label -- ) M: x86 %jump-f ( label -- )
"flag" operand f v>operand CMP JNE ; "flag" operand f v>operand CMP JE ;
: code-alignment ( -- n ) : code-alignment ( -- n )
building get length dup cell align swap - ; building get length dup cell align swap - ;

View File

@ -212,11 +212,11 @@ IN: cpu.x86.intrinsics
2array define-if-intrinsics ; 2array define-if-intrinsics ;
{ {
{ fixnum< JL } { fixnum< JGE }
{ fixnum<= JLE } { fixnum<= JG }
{ fixnum> JG } { fixnum> JLE }
{ fixnum>= JGE } { fixnum>= JL }
{ eq? JE } { eq? JNE }
} [ } [
first2 define-fixnum-jump first2 define-fixnum-jump
] each ] each

View File

@ -27,11 +27,11 @@ IN: cpu.x86.sse2
{ { float "x" } { float "y" } } define-if-intrinsic ; { { float "x" } { float "y" } } define-if-intrinsic ;
{ {
{ float< JB } { float< JAE }
{ float<= JBE } { float<= JA }
{ float> JA } { float> JBE }
{ float>= JAE } { float>= JB }
{ float= JE } { float= JNE }
} [ } [
first2 define-float-jump first2 define-float-jump
] each ] each

View File

@ -13,12 +13,6 @@ HELP: add-literal
{ $values { "obj" object } { "n" integer } } { $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 } "." } ; { $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: 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 HELP: rel-dlsym
{ $values { "name" string } { "dll" "a " { $link dll } " or " { $link f } } { "class" "a relocation class" } } { $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." { $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."

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays generic assocs hashtables USING: arrays generic assocs hashtables
kernel kernel.private math namespaces sequences words kernel kernel.private math namespaces sequences words
quotations strings alien layouts system combinators quotations strings alien.strings layouts system combinators
math.bitfields words.private cpu.architecture ; math.bitfields words.private cpu.architecture ;
IN: generator.fixup IN: generator.fixup
@ -110,10 +110,6 @@ SYMBOL: literal-table
: add-literal ( obj -- n ) literal-table get push-new* ; : add-literal ( obj -- n ) literal-table get push-new* ;
: string>symbol ( str -- alien )
[ os wince? [ string>u16-alien ] [ string>char-alien ] if ]
over string? [ call ] [ map ] if ;
: add-dlsym-literals ( symbol dll -- ) : add-dlsym-literals ( symbol dll -- )
>r string>symbol r> 2array literal-table get push-all ; >r string>symbol r> 2array literal-table get push-all ;

View File

@ -40,16 +40,16 @@ SYMBOL: current-label-start
compiled-stack-traces? compiled-stack-traces?
compiling-word get f ? compiling-word get f ?
1vector literal-table set 1vector literal-table set
f compiling-word get compiled get set-at ; f compiling-label get compiled get set-at ;
: finish-compiling ( literals relocation labels code -- ) : save-machine-code ( literals relocation labels code -- )
4array compiling-label get compiled get set-at ; 4array compiling-label get compiled get set-at ;
: with-generator ( node word label quot -- ) : with-generator ( node word label quot -- )
[ [
>r begin-compiling r> >r begin-compiling r>
{ } make fixup { } make fixup
finish-compiling save-machine-code
] with-scope ; inline ] with-scope ; inline
GENERIC: generate-node ( node -- next ) GENERIC: generate-node ( node -- next )
@ -73,6 +73,7 @@ GENERIC: generate-node ( node -- next )
: word-dataflow ( word -- effect dataflow ) : word-dataflow ( word -- effect dataflow )
[ [
dup "no-effect" word-prop [ no-effect ] when dup "no-effect" word-prop [ no-effect ] when
dup "no-compile" word-prop [ no-effect ] when
dup specialized-def over dup 2array 1array infer-quot dup specialized-def over dup 2array 1array infer-quot
finish-word finish-word
] with-infer ; ] with-infer ;
@ -131,14 +132,14 @@ M: #loop generate-node
: generate-if ( node label -- next ) : generate-if ( node label -- next )
<label> [ <label> [
>r >r node-children first2 generate-branch >r >r node-children first2 swap generate-branch
r> r> end-false-branch resolve-label r> r> end-false-branch resolve-label
generate-branch generate-branch
init-templates init-templates
] keep resolve-label iterate-next ; ] keep resolve-label iterate-next ;
M: #if generate-node M: #if generate-node
[ <label> dup %jump-t ] [ <label> dup %jump-f ]
H{ { +input+ { { f "flag" } } } } H{ { +input+ { { f "flag" } } } }
with-template with-template
generate-if ; generate-if ;
@ -189,13 +190,13 @@ M: #dispatch generate-node
"if-intrinsics" set-word-prop ; "if-intrinsics" set-word-prop ;
: if>boolean-intrinsic ( quot -- ) : if>boolean-intrinsic ( quot -- )
"true" define-label "false" define-label
"end" define-label "end" define-label
"true" get swap call "false" get swap call
f "if-scratch" get load-literal
"end" get %jump-label
"true" resolve-label
t "if-scratch" get load-literal t "if-scratch" get load-literal
"end" get %jump-label
"false" resolve-label
f "if-scratch" get load-literal
"end" resolve-label "end" resolve-label
"if-scratch" get phantom-push ; inline "if-scratch" get phantom-push ; inline

View File

@ -13,13 +13,6 @@ SYMBOL: +scratch+
SYMBOL: +clobber+ SYMBOL: +clobber+
SYMBOL: known-tag SYMBOL: known-tag
! Register classes
SINGLETON: int-regs
SINGLETON: single-float-regs
SINGLETON: double-float-regs
UNION: float-regs single-float-regs double-float-regs ;
UNION: reg-class int-regs float-regs ;
<PRIVATE <PRIVATE
! Value protocol ! Value protocol
@ -65,9 +58,7 @@ M: float-regs move-spec drop float ;
M: float-regs operand-class* drop float ; M: float-regs operand-class* drop float ;
! Temporary register for stack shuffling ! Temporary register for stack shuffling
TUPLE: temp-reg reg-class>> ; SINGLETON: temp-reg
: temp-reg T{ temp-reg f int-regs } ;
M: temp-reg move-spec drop f ; M: temp-reg move-spec drop f ;
@ -470,11 +461,6 @@ M: loc lazy-store
: finalize-contents ( -- ) : finalize-contents ( -- )
finalize-locs finalize-vregs reset-phantoms ; finalize-locs finalize-vregs reset-phantoms ;
: %gc ( -- )
0 frame-required
%prepare-alien-invoke
"simple_gc" f %alien-invoke ;
! Loading stacks to vregs ! Loading stacks to vregs
: free-vregs? ( int# float# -- ? ) : free-vregs? ( int# float# -- ? )
double-float-regs free-vregs length <= double-float-regs free-vregs length <=

View File

@ -29,6 +29,9 @@ PREDICATE: method-spec < pair
: order ( generic -- seq ) : order ( generic -- seq )
"methods" word-prop keys sort-classes ; "methods" word-prop keys sort-classes ;
: specific-method ( class word -- class )
order min-class ;
GENERIC: effective-method ( ... generic -- method ) GENERIC: effective-method ( ... generic -- method )
: next-method-class ( class generic -- class/f ) : next-method-class ( class generic -- class/f )

View File

@ -1,8 +1,11 @@
IN: generic.standard.engines.tuple ! Copyright (c) 2008 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: kernel classes.tuple.private hashtables assocs sorting USING: kernel classes.tuple.private hashtables assocs sorting
accessors combinators sequences slots.private math.parser words accessors combinators sequences slots.private math.parser words
effects namespaces generic generic.standard.engines effects namespaces generic generic.standard.engines
classes.algebra math math.private quotations arrays ; classes.algebra math math.private kernel.private
quotations arrays ;
IN: generic.standard.engines.tuple
TUPLE: echelon-dispatch-engine n methods ; TUPLE: echelon-dispatch-engine n methods ;
@ -27,14 +30,7 @@ TUPLE: tuple-dispatch-engine echelons ;
: <tuple-dispatch-engine> ( methods -- engine ) : <tuple-dispatch-engine> ( methods -- engine )
echelon-sort echelon-sort
[ [ dupd <echelon-dispatch-engine> ] assoc-map
over zero? [
dup assoc-empty?
[ drop f ] [ values first ] if
] [
dupd <echelon-dispatch-engine>
] if
] assoc-map [ nip ] assoc-subset
\ tuple-dispatch-engine boa ; \ tuple-dispatch-engine boa ;
: convert-tuple-methods ( assoc -- assoc' ) : convert-tuple-methods ( assoc -- assoc' )
@ -48,52 +44,51 @@ M: trivial-tuple-dispatch-engine engine>quot
>alist V{ } clone [ hashcode 1array ] distribute-buckets >alist V{ } clone [ hashcode 1array ] distribute-buckets
[ <trivial-tuple-dispatch-engine> ] map ; [ <trivial-tuple-dispatch-engine> ] map ;
: word-hashcode% [ 1 slot ] % ;
: class-hash-dispatch-quot ( methods -- quot ) : class-hash-dispatch-quot ( methods -- quot )
#! 1 slot == word hashcode
[ [
[ dup 1 slot ] % \ dup ,
word-hashcode%
hash-methods [ engine>quot ] map hash-dispatch-quot % hash-methods [ engine>quot ] map hash-dispatch-quot %
] [ ] make ; ] [ ] make ;
: tuple-dispatch-engine-word-name ( engine -- string ) : engine-word-name ( -- string )
[ generic get word-name "/tuple-dispatch-engine" append ;
generic get word-name %
"/tuple-dispatch-engine/" %
n>> #
] "" make ;
PREDICATE: tuple-dispatch-engine-word < word PREDICATE: engine-word < word
"tuple-dispatch-generic" word-prop generic? ; "tuple-dispatch-generic" word-prop generic? ;
M: tuple-dispatch-engine-word stack-effect M: engine-word stack-effect
"tuple-dispatch-generic" word-prop "tuple-dispatch-generic" word-prop
[ extra-values ] [ stack-effect ] bi [ extra-values ] [ stack-effect ] bi
dup [ clone [ length + ] change-in ] [ 2drop f ] if ; dup [ clone [ length + ] change-in ] [ 2drop f ] if ;
M: tuple-dispatch-engine-word compiled-crossref? M: engine-word compiled-crossref?
drop t ; drop t ;
: remember-engine ( word -- ) : remember-engine ( word -- )
generic get "engines" word-prop push ; generic get "engines" word-prop push ;
: <tuple-dispatch-engine-word> ( engine -- word ) : <engine-word> ( -- word )
tuple-dispatch-engine-word-name f <word> engine-word-name f <word>
[ generic get "tuple-dispatch-generic" set-word-prop ] dup generic get "tuple-dispatch-generic" set-word-prop ;
[ remember-engine ]
[ ]
tri ;
: define-tuple-dispatch-engine-word ( engine quot -- word ) : define-engine-word ( quot -- word )
>r <tuple-dispatch-engine-word> dup r> define ; >r <engine-word> dup r> define ;
: array-nth% 2 + , [ slot { word } declare ] % ;
: tuple-layout-superclasses ( obj -- array )
{ tuple } declare
1 slot { tuple-layout } declare
4 slot { array } declare ; inline
: tuple-dispatch-engine-body ( engine -- quot ) : tuple-dispatch-engine-body ( engine -- quot )
#! 1 slot == tuple-layout
#! 2 slot == 0 array-nth
#! 4 slot == layout-superclasses
[ [
picker % picker %
[ 1 slot 4 slot ] % [ tuple-layout-superclasses ] %
[ n>> 2 + , [ slot ] % ] [ n>> array-nth% ]
[ [
methods>> [ methods>> [
<trivial-tuple-dispatch-engine> engine>quot <trivial-tuple-dispatch-engine> engine>quot
@ -104,25 +99,54 @@ M: tuple-dispatch-engine-word compiled-crossref?
] [ ] make ; ] [ ] make ;
M: echelon-dispatch-engine engine>quot M: echelon-dispatch-engine engine>quot
dup tuple-dispatch-engine-body dup n>> zero? [
define-tuple-dispatch-engine-word methods>> dup assoc-empty?
1quotation ; [ drop default get ] [ values first engine>quot ] if
] [
[
picker %
[ tuple-layout-superclasses ] %
[ n>> array-nth% ]
[
methods>> [
<trivial-tuple-dispatch-engine> engine>quot
] [
class-hash-dispatch-quot
] if-small? %
] bi
] [ ] make
] if ;
: >=-case-quot ( alist -- quot ) : >=-case-quot ( alist -- quot )
default get [ drop ] prepend swap default get [ drop ] prepend swap
[ >r [ dupd fixnum>= ] curry r> \ drop prefix ] assoc-map [ >r [ dupd fixnum>= ] curry r> \ drop prefix ] assoc-map
alist>quot ; alist>quot ;
: tuple-layout-echelon ( obj -- array )
{ tuple } declare
1 slot { tuple-layout } declare
5 slot ; inline
: unclip-last [ 1 head* ] [ peek ] bi ;
M: tuple-dispatch-engine engine>quot M: tuple-dispatch-engine engine>quot
#! 1 slot == tuple-layout
#! 5 slot == layout-echelon
[ [
picker % picker %
[ 1 slot 5 slot ] % [ tuple-layout-echelon ] %
echelons>>
[ [
tuple assumed set tuple assumed set
[ engine>quot dup default set ] assoc-map echelons>> dup empty? [
unclip-last
[
[
engine>quot define-engine-word
[ remember-engine ] [ 1quotation ] bi
dup default set
] assoc-map
]
[ first2 engine>quot 2array ] bi*
suffix
] unless
] with-scope ] with-scope
>=-case-quot % >=-case-quot %
] [ ] make ; ] [ ] make ;

View File

@ -3,7 +3,7 @@ USING: tools.test math math.functions math.constants
generic.standard strings sequences arrays kernel accessors generic.standard strings sequences arrays kernel accessors
words float-arrays byte-arrays bit-arrays parser namespaces words float-arrays byte-arrays bit-arrays parser namespaces
quotations inference vectors growable hashtables sbufs quotations inference vectors growable hashtables sbufs
prettyprint ; prettyprint byte-vectors bit-vectors float-vectors ;
GENERIC: lo-tag-test GENERIC: lo-tag-test
@ -251,6 +251,14 @@ HOOK: my-tuple-hook my-var ( -- x )
M: sequence my-tuple-hook my-hook ; M: sequence my-tuple-hook my-hook ;
TUPLE: m-t-h-a ;
M: m-t-h-a my-tuple-hook "foo" ;
TUPLE: m-t-h-b < m-t-h-a ;
M: m-t-h-b my-tuple-hook "bar" ;
[ f ] [ [ f ] [
\ my-tuple-hook [ "engines" word-prop ] keep prefix \ my-tuple-hook [ "engines" word-prop ] keep prefix
[ 1quotation infer ] map all-equal? [ 1quotation infer ] map all-equal?

View File

@ -48,10 +48,6 @@ HELP: no-effect
{ $description "Throws a " { $link no-effect } " error." } { $description "Throws a " { $link no-effect } " error." }
{ $error-description "Thrown when inference encounters a call to a word which is already known not to have a static stack effect, due to a prior inference attempt failing." } ; { $error-description "Thrown when inference encounters a call to a word which is already known not to have a static stack effect, due to a prior inference attempt failing." } ;
HELP: collect-recursion
{ $values { "#label" "a " { $link #label } " node" } { "seq" "a new sequence" } }
{ $description "Collect the input stacks of all child " { $link #call-label } " nodes that call the given label." } ;
HELP: inline-word HELP: inline-word
{ $values { "word" word } } { $values { "word" word } }
{ $description "Called during inference to infer stack effects of inline words." { $description "Called during inference to infer stack effects of inline words."

View File

@ -15,7 +15,7 @@ GENERIC: inline? ( word -- ? )
M: method-body inline? M: method-body inline?
"method-generic" word-prop inline? ; "method-generic" word-prop inline? ;
M: tuple-dispatch-engine-word inline? M: engine-word inline?
"tuple-dispatch-generic" word-prop inline? ; "tuple-dispatch-generic" word-prop inline? ;
M: word inline? M: word inline?
@ -130,25 +130,27 @@ TUPLE: too-many->r ;
TUPLE: too-many-r> ; TUPLE: too-many-r> ;
: check-r> ( -- ) : check-r> ( n -- )
meta-r get empty? meta-r get length >
[ \ too-many-r> inference-error ] when ; [ \ too-many-r> inference-error ] when ;
: infer->r ( -- ) : infer->r ( n -- )
1 ensure-values dup ensure-values
#>r #>r
1 0 pick node-inputs over 0 pick node-inputs
pop-d push-r over [ drop pop-d ] map reverse [ push-r ] each
0 1 pick node-outputs 0 pick pick node-outputs
node, ; node,
drop ;
: infer-r> ( -- ) : infer-r> ( n -- )
check-r> dup check-r>
#r> #r>
0 1 pick node-inputs 0 pick pick node-inputs
pop-r push-d over [ drop pop-r ] map reverse [ push-d ] each
1 0 pick node-outputs over 0 pick node-outputs
node, ; node,
drop ;
: undo-infer ( -- ) : undo-infer ( -- )
recorded get [ f "inferred-effect" set-word-prop ] each ; recorded get [ f "inferred-effect" set-word-prop ] each ;
@ -199,18 +201,18 @@ M: object constructor drop f ;
dup infer-uncurry dup infer-uncurry
constructor [ constructor [
peek-d reify-curry peek-d reify-curry
infer->r 1 infer->r
peek-d reify-curry peek-d reify-curry
infer-r> 1 infer-r>
2 1 <effect> swap #call consume/produce 2 1 <effect> swap #call consume/produce
] when* ; ] when* ;
: reify-curries ( n -- ) : reify-curries ( n -- )
meta-d get reverse [ meta-d get reverse [
dup special? [ dup special? [
over [ infer->r ] times over infer->r
dup reify-curry dup reify-curry
over [ infer-r> ] times over infer-r>
] when 2drop ] when 2drop
] 2each ; ] 2each ;
@ -407,6 +409,25 @@ TUPLE: recursive-declare-error word ;
\ recursive-declare-error inference-error \ recursive-declare-error inference-error
] if* ; ] if* ;
GENERIC: collect-label-info* ( label node -- )
M: node collect-label-info* 2drop ;
: (collect-label-info) ( label node vector -- )
>r tuck [ param>> ] bi@ eq? r> [ push ] curry [ drop ] if ;
inline
M: #call-label collect-label-info*
over calls>> (collect-label-info) ;
M: #return collect-label-info*
over returns>> (collect-label-info) ;
: collect-label-info ( #label -- )
V{ } clone >>calls
V{ } clone >>returns
dup [ collect-label-info* ] with each-node ;
: nest-node ( -- ) #entry node, ; : nest-node ( -- ) #entry node, ;
: unnest-node ( new-node -- new-node ) : unnest-node ( new-node -- new-node )
@ -417,27 +438,17 @@ TUPLE: recursive-declare-error word ;
: <inlined-block> gensym dup t "inlined-block" set-word-prop ; : <inlined-block> gensym dup t "inlined-block" set-word-prop ;
: inline-block ( word -- node-block data ) : inline-block ( word -- #label data )
[ [
copy-inference nest-node copy-inference nest-node
dup word-def swap <inlined-block> dup word-def swap <inlined-block>
[ infer-quot-recursive ] 2keep [ infer-quot-recursive ] 2keep
#label unnest-node #label unnest-node
dup collect-label-info
] H{ } make-assoc ; ] H{ } make-assoc ;
GENERIC: collect-recursion* ( label node -- ) : join-values ( #label -- )
calls>> [ node-in-d ] map meta-d get suffix
M: node collect-recursion* 2drop ;
M: #call-label collect-recursion*
tuck node-param eq? [ , ] [ drop ] if ;
: collect-recursion ( #label -- seq )
dup node-param
[ [ swap collect-recursion* ] curry each-node ] { } make ;
: join-values ( node -- )
collect-recursion [ node-in-d ] map meta-d get suffix
unify-lengths unify-stacks unify-lengths unify-stacks
meta-d [ length tail* ] change ; meta-d [ length tail* ] change ;
@ -458,7 +469,7 @@ M: #call-label collect-recursion*
drop join-values inline-block apply-infer drop join-values inline-block apply-infer
r> over set-node-in-d r> over set-node-in-d
dup node, dup node,
collect-recursion [ calls>> [
[ flatten-curries ] modify-values [ flatten-curries ] modify-values
] each ] each
] [ ] [

View File

@ -4,7 +4,12 @@ inference.dataflow optimizer tools.test kernel.private generic
sequences words inference.class quotations alien sequences words inference.class quotations alien
alien.c-types strings sbufs sequences.private alien.c-types strings sbufs sequences.private
slots.private combinators definitions compiler.units slots.private combinators definitions compiler.units
system layouts vectors ; system layouts vectors optimizer.math.partial accessors
optimizer.inlining ;
[ t ] [ T{ literal-constraint f 1 2 } T{ literal-constraint f 1 2 } equal? ] unit-test
[ f ] [ T{ literal-constraint f 1 3 } T{ literal-constraint f 1 2 } equal? ] unit-test
! Make sure these compile even though this is invalid code ! Make sure these compile even though this is invalid code
[ ] [ [ 10 mod 3.0 /i ] dataflow optimize drop ] unit-test [ ] [ [ 10 mod 3.0 /i ] dataflow optimize drop ] unit-test
@ -13,9 +18,15 @@ system layouts vectors ;
! Ensure type inference works as it is supposed to by checking ! Ensure type inference works as it is supposed to by checking
! if various methods get inlined ! if various methods get inlined
: inlined? ( quot word -- ? ) : inlined? ( quot seq/word -- ? )
dup word? [ 1array ] when
swap dataflow optimize swap dataflow optimize
[ node-param eq? ] with node-exists? not ; [ node-param swap member? ] with node-exists? not ;
[ f ] [
[ { integer } declare >fixnum ]
\ >fixnum inlined?
] unit-test
GENERIC: mynot ( x -- y ) GENERIC: mynot ( x -- y )
@ -109,12 +120,17 @@ M: object xyz ;
[ { fixnum } declare [ ] times ] \ fixnum+ inlined? [ { fixnum } declare [ ] times ] \ fixnum+ inlined?
] unit-test ] unit-test
[ f ] [ [ t ] [
[ { integer fixnum } declare dupd < [ 1 + ] when ] [ { integer fixnum } declare dupd < [ 1 + ] when ]
\ + inlined? \ + inlined?
] unit-test ] unit-test
[ f ] [ [ dup 0 < [ neg ] when ] \ neg inlined? ] unit-test [ f ] [
[ { integer fixnum } declare dupd < [ 1 + ] when ]
\ +-integer-fixnum inlined?
] unit-test
[ f ] [ [ dup 0 < [ neg ] when ] \ - inlined? ] unit-test
[ f ] [ [ f ] [
[ [
@ -137,13 +153,13 @@ M: object xyz ;
DEFER: blah DEFER: blah
[ t ] [ [ ] [
[ [
\ blah \ blah
[ dup V{ } eq? [ foo ] when ] dup second dup push define [ dup V{ } eq? [ foo ] when ] dup second dup push define
] with-compilation-unit ] with-compilation-unit
\ blah compiled? \ blah word-def dataflow optimize drop
] unit-test ] unit-test
GENERIC: detect-fx ( n -- n ) GENERIC: detect-fx ( n -- n )
@ -158,14 +174,20 @@ M: fixnum detect-fx ;
] \ detect-fx inlined? ] \ detect-fx inlined?
] unit-test ] unit-test
[ t ] [
[
1000000000000000000000000000000000 [ ] times
] \ + inlined?
] unit-test
[ f ] [ [ f ] [
[ [
1000000000000000000000000000000000 [ ] times 1000000000000000000000000000000000 [ ] times
] \ 1+ inlined? ] \ +-integer-fixnum inlined?
] unit-test ] unit-test
[ f ] [ [ f ] [
[ { bignum } declare [ ] times ] \ 1+ inlined? [ { bignum } declare [ ] times ]
\ +-integer-fixnum inlined?
] unit-test ] unit-test
@ -251,19 +273,24 @@ M: float detect-float ;
[ 3 + = ] \ equal? inlined? [ 3 + = ] \ equal? inlined?
] unit-test ] unit-test
[ t ] [ [ f ] [
[ { fixnum fixnum } declare 7 bitand neg shift ] [ { fixnum fixnum } declare 7 bitand neg shift ]
\ shift inlined? \ fixnum-shift-fast inlined?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ { fixnum fixnum } declare 7 bitand neg shift ] [ { fixnum fixnum } declare 7 bitand neg shift ]
\ fixnum-shift inlined? { shift fixnum-shift } inlined?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ { fixnum fixnum } declare 1 swap 7 bitand shift ] [ { fixnum fixnum } declare 1 swap 7 bitand shift ]
\ fixnum-shift inlined? { shift fixnum-shift } inlined?
] unit-test
[ f ] [
[ { fixnum fixnum } declare 1 swap 7 bitand shift ]
{ fixnum-shift-fast } inlined?
] unit-test ] unit-test
cell-bits 32 = [ cell-bits 32 = [
@ -278,6 +305,11 @@ cell-bits 32 = [
] unit-test ] unit-test
] when ] when
[ f ] [
[ { integer } declare -63 shift 4095 bitand ]
\ shift inlined?
] unit-test
[ t ] [ [ t ] [
[ B{ 1 0 } *short 0 number= ] [ B{ 1 0 } *short 0 number= ]
\ number= inlined? \ number= inlined?
@ -323,3 +355,228 @@ cell-bits 32 = [
] when ] when
] \ + inlined? ] \ + inlined?
] unit-test ] unit-test
[ f ] [
[
256 mod
] { mod fixnum-mod } inlined?
] unit-test
[ f ] [
[
dup 0 >= [ 256 mod ] when
] { mod fixnum-mod } inlined?
] unit-test
[ t ] [
[
{ integer } declare dup 0 >= [ 256 mod ] when
] { mod fixnum-mod } inlined?
] unit-test
[ t ] [
[
{ integer } declare 256 rem
] { mod fixnum-mod } inlined?
] unit-test
[ t ] [
[
{ integer } declare [ 256 rem ] map
] { mod fixnum-mod rem } inlined?
] unit-test
[ t ] [
[ 1000 [ 1+ ] map ] { 1+ fixnum+ } inlined?
] unit-test
: rec ( a -- b )
dup 0 > [ 1 - rec ] when ; inline
[ t ] [
[ { fixnum } declare rec 1 + ]
{ > - + } inlined?
] unit-test
: fib ( m -- n )
dup 2 < [ drop 1 ] [ dup 1 - fib swap 2 - fib + ] if ; inline
[ t ] [
[ 27.0 fib ] { < - + } inlined?
] unit-test
[ f ] [
[ 27.0 fib ] { +-integer-integer } inlined?
] unit-test
[ t ] [
[ 27 fib ] { < - + } inlined?
] unit-test
[ t ] [
[ 27 >bignum fib ] { < - + } inlined?
] unit-test
[ f ] [
[ 27/2 fib ] { < - } inlined?
] unit-test
: hang-regression ( m n -- x )
over 0 number= [
nip
] [
dup [
drop 1 hang-regression
] [
dupd hang-regression hang-regression
] if
] if ; inline
[ t ] [
[ dup fixnum? [ 3 over hang-regression ] [ 3 over hang-regression ] if
] { } inlined? ] unit-test
: detect-null ( a -- b ) dup drop ;
\ detect-null {
{ [ dup dup in-d>> first node-class null eq? ] [ [ ] f splice-quot ] }
} define-optimizers
[ t ] [
[ { null } declare detect-null ] \ detect-null inlined?
] unit-test
[ t ] [
[ { null null } declare + detect-null ] \ detect-null inlined?
] unit-test
[ f ] [
[ { null fixnum } declare + detect-null ] \ detect-null inlined?
] unit-test
GENERIC: detect-integer ( a -- b )
M: integer detect-integer ;
[ t ] [
[ { null fixnum } declare + detect-integer ] \ detect-integer inlined?
] unit-test
[ t ] [
[ { fixnum } declare 10 [ -1 shift ] times ] \ shift inlined?
] unit-test
[ f ] [
[ { integer } declare 10 [ -1 shift ] times ] \ shift inlined?
] unit-test
[ f ] [
[ { fixnum } declare 1048575 fixnum-bitand 524288 fixnum- ]
\ fixnum-bitand inlined?
] unit-test
[ t ] [
[ { integer } declare 127 bitand 3 + ]
{ + +-integer-fixnum +-integer-fixnum-fast bitand } inlined?
] unit-test
[ f ] [
[ { integer } declare 127 bitand 3 + ]
{ >fixnum } inlined?
] unit-test
[ t ] [
[ { fixnum } declare [ drop ] each-integer ]
{ < <-integer-fixnum +-integer-fixnum + } inlined?
] unit-test
[ t ] [
[ { fixnum } declare length [ drop ] each-integer ]
{ < <-integer-fixnum +-integer-fixnum + } inlined?
] unit-test
[ t ] [
[ { fixnum } declare [ drop ] each ]
{ < <-integer-fixnum +-integer-fixnum + } inlined?
] unit-test
[ t ] [
[ { fixnum } declare 0 [ + ] reduce ]
{ < <-integer-fixnum } inlined?
] unit-test
[ f ] [
[ { fixnum } declare 0 [ + ] reduce ]
\ +-integer-fixnum inlined?
] unit-test
[ t ] [
[
{ integer } declare
dup 0 >= [
615949 * 797807 + 20 2^ mod dup 19 2^ -
] [ dup ] if
] { * + shift mod fixnum-mod fixnum* fixnum+ fixnum- } inlined?
] unit-test
[ t ] [
[
{ fixnum } declare
615949 * 797807 + 20 2^ mod dup 19 2^ -
] { >fixnum } inlined?
] unit-test
[ f ] [
[
{ integer } declare [ ] map
] \ >fixnum inlined?
] unit-test
[ f ] [
[
{ integer } declare { } set-nth-unsafe
] \ >fixnum inlined?
] unit-test
[ f ] [
[
{ integer } declare 1 + { } set-nth-unsafe
] \ >fixnum inlined?
] unit-test
[ t ] [
[
{ integer } declare 0 swap
[
drop 615949 * 797807 + 20 2^ rem dup 19 2^ -
] map
] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- } inlined?
] unit-test
[ t ] [
[
{ fixnum } declare 0 swap
[
drop 615949 * 797807 + 20 2^ rem dup 19 2^ -
] map
] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- >fixnum } inlined?
] unit-test
[ t ] [
[ { integer } declare bitnot detect-integer ]
\ detect-integer inlined?
] unit-test
! Later
! [ t ] [
! [
! { integer } declare [ 256 mod ] map
! ] { mod fixnum-mod } inlined?
! ] unit-test
!
! [ t ] [
! [
! { integer } declare [ 0 >= ] map
! ] { >= fixnum>= } inlined?
! ] unit-test

View File

@ -1,9 +1,9 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays generic assocs hashtables inference kernel USING: arrays generic assocs hashtables inference kernel
math namespaces sequences words parser math.intervals math namespaces sequences words parser math.intervals
effects classes classes.algebra inference.dataflow effects classes classes.algebra inference.dataflow
inference.backend combinators ; inference.backend combinators accessors ;
IN: inference.class IN: inference.class
! Class inference ! Class inference
@ -25,12 +25,10 @@ C: <literal-constraint> literal-constraint
M: literal-constraint equal? M: literal-constraint equal?
over literal-constraint? [ over literal-constraint? [
2dup [ [ literal>> ] bi@ eql? ]
[ literal-constraint-literal ] bi@ eql? >r [ [ value>> ] bi@ = ]
[ literal-constraint-value ] bi@ = r> and 2bi and
] [ ] [ 2drop f ] if ;
2drop f
] if ;
TUPLE: class-constraint class value ; TUPLE: class-constraint class value ;
@ -43,8 +41,8 @@ C: <interval-constraint> interval-constraint
GENERIC: apply-constraint ( constraint -- ) GENERIC: apply-constraint ( constraint -- )
GENERIC: constraint-satisfied? ( constraint -- ? ) GENERIC: constraint-satisfied? ( constraint -- ? )
: `input node get node-in-d nth ; : `input node get in-d>> nth ;
: `output node get node-out-d nth ; : `output node get out-d>> nth ;
: class, <class-constraint> , ; : class, <class-constraint> , ;
: literal, <literal-constraint> , ; : literal, <literal-constraint> , ;
: interval, <interval-constraint> , ; : interval, <interval-constraint> , ;
@ -84,14 +82,12 @@ SYMBOL: value-classes
set-value-interval* ; set-value-interval* ;
M: interval-constraint apply-constraint M: interval-constraint apply-constraint
dup interval-constraint-interval [ interval>> ] [ value>> ] bi intersect-value-interval ;
swap interval-constraint-value intersect-value-interval ;
: set-class-interval ( class value -- ) : set-class-interval ( class value -- )
over class? [ over class? [
over "interval" word-prop [ >r "interval" word-prop r> over
>r "interval" word-prop r> set-value-interval* [ set-value-interval* ] [ 2drop ] if
] [ 2drop ] if
] [ 2drop ] if ; ] [ 2drop ] if ;
: value-class* ( value -- class ) : value-class* ( value -- class )
@ -110,18 +106,21 @@ M: interval-constraint apply-constraint
[ value-class* class-and ] keep set-value-class* ; [ value-class* class-and ] keep set-value-class* ;
M: class-constraint apply-constraint M: class-constraint apply-constraint
dup class-constraint-class [ class>> ] [ value>> ] bi intersect-value-class ;
swap class-constraint-value intersect-value-class ;
: literal-interval ( value -- interval/f )
dup real? [ [a,a] ] [ drop f ] if ;
: set-value-literal* ( literal value -- ) : set-value-literal* ( literal value -- )
over class over set-value-class* {
over real? [ over [a,a] over set-value-interval* ] when [ >r class r> set-value-class* ]
2dup <literal-constraint> assume [ >r literal-interval r> set-value-interval* ]
value-literals get set-at ; [ <literal-constraint> assume ]
[ value-literals get set-at ]
} 2cleave ;
M: literal-constraint apply-constraint M: literal-constraint apply-constraint
dup literal-constraint-literal [ literal>> ] [ value>> ] bi set-value-literal* ;
swap literal-constraint-value set-value-literal* ;
! For conditionals, an assoc of child node # --> constraint ! For conditionals, an assoc of child node # --> constraint
GENERIC: child-constraints ( node -- seq ) GENERIC: child-constraints ( node -- seq )
@ -133,19 +132,18 @@ GENERIC: infer-classes-around ( node -- )
M: node infer-classes-before drop ; M: node infer-classes-before drop ;
M: node child-constraints M: node child-constraints
node-children length children>> length
dup zero? [ drop f ] [ f <repetition> ] if ; dup zero? [ drop f ] [ f <repetition> ] if ;
: value-literal* ( value -- obj ? ) : value-literal* ( value -- obj ? )
value-literals get at* ; value-literals get at* ;
M: literal-constraint constraint-satisfied? M: literal-constraint constraint-satisfied?
dup literal-constraint-value value-literal* dup value>> value-literal*
[ swap literal-constraint-literal eql? ] [ 2drop f ] if ; [ swap literal>> eql? ] [ 2drop f ] if ;
M: class-constraint constraint-satisfied? M: class-constraint constraint-satisfied?
dup class-constraint-value value-class* [ value>> value-class* ] [ class>> ] bi class< ;
swap class-constraint-class class< ;
M: pair apply-constraint M: pair apply-constraint
first2 2dup constraints get set-at first2 2dup constraints get set-at
@ -154,19 +152,18 @@ M: pair apply-constraint
M: pair constraint-satisfied? M: pair constraint-satisfied?
first constraint-satisfied? ; first constraint-satisfied? ;
: extract-keys ( assoc seq -- newassoc ) : extract-keys ( seq assoc -- newassoc )
dup length <hashtable> swap [ [ dupd at ] curry H{ } map>assoc [ nip ] assoc-subset f assoc-like ;
dup >r pick at* [ r> pick set-at ] [ r> 2drop ] if
] each nip f assoc-like ;
: annotate-node ( node -- ) : annotate-node ( node -- )
#! Annotate the node with the currently-inferred set of #! Annotate the node with the currently-inferred set of
#! value classes. #! value classes.
dup node-values dup node-values {
value-intervals get over extract-keys pick set-node-intervals [ value-intervals get extract-keys >>intervals ]
value-classes get over extract-keys pick set-node-classes [ value-classes get extract-keys >>classes ]
value-literals get over extract-keys pick set-node-literals [ value-literals get extract-keys >>literals ]
2drop ; [ 2drop ]
} cleave ;
: intersect-classes ( classes values -- ) : intersect-classes ( classes values -- )
[ intersect-value-class ] 2each ; [ intersect-value-class ] 2each ;
@ -190,31 +187,29 @@ M: pair constraint-satisfied?
] 2bi ; ] 2bi ;
: compute-constraints ( #call -- ) : compute-constraints ( #call -- )
dup node-param "constraints" word-prop [ dup param>> "constraints" word-prop [
call call
] [ ] [
dup node-param "predicating" word-prop dup dup param>> "predicating" word-prop dup
[ swap predicate-constraints ] [ 2drop ] if [ swap predicate-constraints ] [ 2drop ] if
] if* ; ] if* ;
: compute-output-classes ( node word -- classes intervals ) : compute-output-classes ( node word -- classes intervals )
dup node-param "output-classes" word-prop dup param>> "output-classes" word-prop
dup [ call ] [ 2drop f f ] if ; dup [ call ] [ 2drop f f ] if ;
: output-classes ( node -- classes intervals ) : output-classes ( node -- classes intervals )
dup compute-output-classes >r dup compute-output-classes >r
[ ] [ node-param "default-output-classes" word-prop ] ?if [ ] [ param>> "default-output-classes" word-prop ] ?if
r> ; r> ;
M: #call infer-classes-before M: #call infer-classes-before
dup compute-constraints [ compute-constraints ] keep
dup node-out-d swap output-classes [ output-classes ] [ out-d>> ] bi
>r over intersect-classes tuck [ intersect-classes ] [ intersect-intervals ] 2bi* ;
r> swap intersect-intervals ;
M: #push infer-classes-before M: #push infer-classes-before
node-out-d out-d>> [ [ value-literal ] keep set-value-literal* ] each ;
[ [ value-literal ] keep set-value-literal* ] each ;
M: #if child-constraints M: #if child-constraints
[ [
@ -224,19 +219,17 @@ M: #if child-constraints
M: #dispatch child-constraints M: #dispatch child-constraints
dup [ dup [
node-children length [ children>> length [ 0 `input literal, ] each
0 `input literal,
] each
] make-constraints ; ] make-constraints ;
M: #declare infer-classes-before M: #declare infer-classes-before
dup node-param swap node-in-d [ param>> ] [ in-d>> ] bi
[ intersect-value-class ] 2each ; [ intersect-value-class ] 2each ;
DEFER: (infer-classes) DEFER: (infer-classes)
: infer-children ( node -- ) : infer-children ( node -- )
dup node-children swap child-constraints [ [ children>> ] [ child-constraints ] bi [
[ [
value-classes [ clone ] change value-classes [ clone ] change
value-literals [ clone ] change value-literals [ clone ] change
@ -251,27 +244,27 @@ DEFER: (infer-classes)
>r dup [ length ] map supremum r> [ pad-left ] 2curry map ; >r dup [ length ] map supremum r> [ pad-left ] 2curry map ;
: (merge-classes) ( nodes -- seq ) : (merge-classes) ( nodes -- seq )
[ node-input-classes ] map dup length 1 = [
null pad-all flip [ null [ class-or ] reduce ] map ; first node-input-classes
] [
[ node-input-classes ] map null pad-all flip
[ null [ class-or ] reduce ] map
] if ;
: set-classes ( seq node -- ) : set-classes ( seq node -- )
node-out-d [ set-value-class* ] 2reverse-each ; out-d>> [ set-value-class* ] 2reverse-each ;
: merge-classes ( nodes node -- ) : merge-classes ( nodes node -- )
>r (merge-classes) r> set-classes ; >r (merge-classes) r> set-classes ;
: (merge-intervals) ( nodes quot -- seq )
>r
[ node-input-intervals ] map
f pad-all flip
r> map ; inline
: set-intervals ( seq node -- ) : set-intervals ( seq node -- )
node-out-d [ set-value-interval* ] 2reverse-each ; out-d>> [ set-value-interval* ] 2reverse-each ;
: merge-intervals ( nodes node -- ) : merge-intervals ( nodes node -- )
>r [ dup first [ interval-union ] reduce ] >r
(merge-intervals) r> set-intervals ; [ node-input-intervals ] map f pad-all flip
[ dup first [ interval-union ] reduce ] map
r> set-intervals ;
: annotate-merge ( nodes #merge/#entry -- ) : annotate-merge ( nodes #merge/#entry -- )
[ merge-classes ] [ merge-intervals ] 2bi ; [ merge-classes ] [ merge-intervals ] 2bi ;
@ -280,28 +273,68 @@ DEFER: (infer-classes)
dup node-successor dup #merge? [ dup node-successor dup #merge? [
swap active-children dup empty? swap active-children dup empty?
[ 2drop ] [ swap annotate-merge ] if [ 2drop ] [ swap annotate-merge ] if
] [ ] [ 2drop ] if ;
2drop
] if ; : classes= ( inferred current -- ? )
2dup min-length [ tail* ] curry bi@ sequence= ;
SYMBOL: fixed-point?
SYMBOL: nested-labels
: annotate-entry ( nodes #label -- ) : annotate-entry ( nodes #label -- )
node-child merge-classes ; >r (merge-classes) r> node-child
2dup node-output-classes classes=
[ 2drop ] [ set-classes fixed-point? off ] if ;
: init-recursive-calls ( #label -- )
#! We set recursive calls to output the empty type, then
#! repeat inference until a fixed point is reached.
#! Hopefully, our type functions are monotonic so this
#! will always converge.
returns>> [ dup in-d>> [ null ] { } map>assoc >>classes drop ] each ;
M: #label infer-classes-before ( #label -- ) M: #label infer-classes-before ( #label -- )
#! First, infer types under the hypothesis which hold on [ init-recursive-calls ]
#! entry to the recursive label. [ [ 1array ] keep annotate-entry ] bi ;
[ 1array ] keep annotate-entry ;
: infer-label-loop ( #label -- )
fixed-point? on
dup node-child (infer-classes)
dup [ calls>> ] [ suffix ] [ annotate-entry ] tri
fixed-point? get [ drop ] [ infer-label-loop ] if ;
M: #label infer-classes-around ( #label -- ) M: #label infer-classes-around ( #label -- )
#! Now merge the types at every recursion point with the #! Now merge the types at every recursion point with the
#! entry types. #! entry types.
[
{ {
[ nested-labels get push ]
[ annotate-node ] [ annotate-node ]
[ infer-classes-before ] [ infer-classes-before ]
[ infer-children ] [ infer-label-loop ]
[ [ collect-recursion ] [ suffix ] [ annotate-entry ] tri ] [ drop nested-labels get pop* ]
[ node-child (infer-classes) ] } cleave
} cleave ; ] with-scope ;
: find-label ( param -- #label )
param>> nested-labels get [ param>> eq? ] with find nip ;
M: #call-label infer-classes-before ( #call-label -- )
[ find-label returns>> (merge-classes) ] [ out-d>> ] bi
[ set-value-class* ] 2each ;
M: #return infer-classes-around
nested-labels get length 0 > [
dup param>> nested-labels get peek param>> eq? [
[ ] [ node-input-classes ] [ in-d>> [ value-class* ] map ] tri
classes= not [
fixed-point? off
[ in-d>> value-classes get extract-keys ] keep
set-node-classes
] [ drop ] if
] [ call-next-method ] if
] [ call-next-method ] if ;
M: object infer-classes-around M: object infer-classes-around
{ {
@ -314,11 +347,13 @@ M: object infer-classes-around
: (infer-classes) ( node -- ) : (infer-classes) ( node -- )
[ [
[ infer-classes-around ] [ infer-classes-around ]
[ node-successor (infer-classes) ] bi [ node-successor ] bi
(infer-classes)
] when* ; ] when* ;
: infer-classes-with ( node classes literals intervals -- ) : infer-classes-with ( node classes literals intervals -- )
[ [
V{ } clone nested-labels set
H{ } assoc-like value-intervals set H{ } assoc-like value-intervals set
H{ } assoc-like value-literals set H{ } assoc-like value-literals set
H{ } assoc-like value-classes set H{ } assoc-like value-classes set
@ -326,13 +361,11 @@ M: object infer-classes-around
(infer-classes) (infer-classes)
] with-scope ; ] with-scope ;
: infer-classes ( node -- ) : infer-classes ( node -- node )
f f f infer-classes-with ; dup f f f infer-classes-with ;
: infer-classes/node ( node existing -- ) : infer-classes/node ( node existing -- )
#! Infer classes, using the existing node's class info as a #! Infer classes, using the existing node's class info as a
#! starting point. #! starting point.
dup node-classes [ classes>> ] [ literals>> ] [ intervals>> ] tri
over node-literals
rot node-intervals
infer-classes-with ; infer-classes-with ;

View File

@ -90,7 +90,7 @@ M: object flatten-curry , ;
: node-child node-children first ; : node-child node-children first ;
TUPLE: #label < node word loop? ; TUPLE: #label < node word loop? returns calls ;
: #label ( word label -- node ) : #label ( word label -- node )
\ #label param-node swap >>word ; \ #label param-node swap >>word ;
@ -290,6 +290,9 @@ SYMBOL: node-stack
: node-input-classes ( node -- seq ) : node-input-classes ( node -- seq )
dup in-d>> [ node-class ] with map ; dup in-d>> [ node-class ] with map ;
: node-output-classes ( node -- seq )
dup out-d>> [ node-class ] with map ;
: node-input-intervals ( node -- seq ) : node-input-intervals ( node -- seq )
dup in-d>> [ node-interval ] with map ; dup in-d>> [ node-interval ] with map ;

View File

@ -54,9 +54,9 @@ IN: inference.known-words
{ swap T{ effect f 2 { 1 0 } } } { swap T{ effect f 2 { 1 0 } } }
} [ define-shuffle ] assoc-each } [ define-shuffle ] assoc-each
\ >r [ infer->r ] "infer" set-word-prop \ >r [ 1 infer->r ] "infer" set-word-prop
\ r> [ infer-r> ] "infer" set-word-prop \ r> [ 1 infer-r> ] "infer" set-word-prop
\ declare [ \ declare [
1 ensure-values 1 ensure-values
@ -81,8 +81,8 @@ M: curried infer-call
M: composed infer-call M: composed infer-call
infer-uncurry infer-uncurry
infer->r peek-d infer-call 1 infer->r peek-d infer-call
terminated? get [ infer-r> peek-d infer-call ] unless ; terminated? get [ 1 infer-r> peek-d infer-call ] unless ;
M: object infer-call M: object infer-call
\ literal-expected inference-warning ; \ literal-expected inference-warning ;
@ -92,6 +92,8 @@ M: object infer-call
peek-d infer-call peek-d infer-call
] "infer" set-word-prop ] "infer" set-word-prop
\ call t "no-compile" set-word-prop
\ execute [ \ execute [
1 ensure-values 1 ensure-values
pop-literal nip pop-literal nip
@ -471,18 +473,6 @@ set-primitive-effect
\ set-alien-cell { c-ptr c-ptr integer } { } <effect> set-primitive-effect \ set-alien-cell { c-ptr c-ptr integer } { } <effect> set-primitive-effect
\ alien>char-string { c-ptr } { string } <effect> set-primitive-effect
\ alien>char-string make-flushable
\ string>char-alien { string } { byte-array } <effect> set-primitive-effect
\ string>char-alien make-flushable
\ alien>u16-string { c-ptr } { string } <effect> set-primitive-effect
\ alien>u16-string make-flushable
\ string>u16-alien { string } { byte-array } <effect> set-primitive-effect
\ string>u16-alien make-flushable
\ alien-address { alien } { integer } <effect> set-primitive-effect \ alien-address { alien } { integer } <effect> set-primitive-effect
\ alien-address make-flushable \ alien-address make-flushable

View File

@ -41,12 +41,13 @@ $low-level-note ;
ARTICLE: "encodings-descriptors" "Encoding descriptors" ARTICLE: "encodings-descriptors" "Encoding descriptors"
"An encoding descriptor is something which can be used for input or output streams to encode or decode files. It must conform to the " { $link "encodings-protocol" } ". Encodings which you can use are defined in the following vocabularies:" "An encoding descriptor is something which can be used for input or output streams to encode or decode files. It must conform to the " { $link "encodings-protocol" } ". Encodings which you can use are defined in the following vocabularies:"
{ $vocab-subsection "ASCII" "io.encodings.ascii" } { $subsection "io.encodings.binary" }
{ $vocab-subsection "Binary" "io.encodings.binary" } { $subsection "io.encodings.utf8" }
{ $subsection "io.encodings.utf16" }
{ $vocab-subsection "Strict encodings" "io.encodings.strict" } { $vocab-subsection "Strict encodings" "io.encodings.strict" }
"Legacy encodings:"
{ $vocab-subsection "8-bit encodings" "io.encodings.8-bit" } { $vocab-subsection "8-bit encodings" "io.encodings.8-bit" }
{ $vocab-subsection "UTF-8" "io.encodings.utf8" } { $vocab-subsection "ASCII" "io.encodings.ascii" }
{ $vocab-subsection "UTF-16" "io.encodings.utf16" }
{ $see-also "encodings-introduction" } ; { $see-also "encodings-introduction" } ;
ARTICLE: "encodings-protocol" "Encoding protocol" ARTICLE: "encodings-protocol" "Encoding protocol"

View File

@ -5,8 +5,7 @@ ARTICLE: "io.encodings.utf16" "UTF-16"
"The UTF-16 encoding is a variable-width encoding. Unicode code points are encoded as 2 or 4 byte sequences. There are three encoding descriptor classes for working with UTF-16, depending on endianness or the presence of a BOM:" "The UTF-16 encoding is a variable-width encoding. Unicode code points are encoded as 2 or 4 byte sequences. There are three encoding descriptor classes for working with UTF-16, depending on endianness or the presence of a BOM:"
{ $subsection utf16 } { $subsection utf16 }
{ $subsection utf16le } { $subsection utf16le }
{ $subsection utf16be } { $subsection utf16be } ;
{ $subsection utf16n } ;
ABOUT: "io.encodings.utf16" ABOUT: "io.encodings.utf16"
@ -22,8 +21,4 @@ HELP: utf16
{ $class-description "The encoding descriptor for UTF-16, that is, UTF-16 with a byte order mark. This is the most useful for general input and output in UTF-16. Streams can be made which read or write wth this encoding." } { $class-description "The encoding descriptor for UTF-16, that is, UTF-16 with a byte order mark. This is the most useful for general input and output in UTF-16. Streams can be made which read or write wth this encoding." }
{ $see-also "encodings-introduction" } ; { $see-also "encodings-introduction" } ;
HELP: utf16n { utf16 utf16le utf16be } related-words
{ $class-description "The encoding descriptor for UTF-16 without a byte order mark in native endian order. This is useful mostly for FFI calls which take input of strings of the type wchar_t*" }
{ $see-also "encodings-introduction" } ;
{ utf16 utf16le utf16be utf16n } related-words

View File

@ -1,6 +1,6 @@
USING: kernel tools.test io.encodings.utf16 arrays sbufs USING: kernel tools.test io.encodings.utf16 arrays sbufs
io.streams.byte-array sequences io.encodings io unicode io.streams.byte-array sequences io.encodings io unicode
io.encodings.string alien.c-types accessors classes ; io.encodings.string alien.c-types alien.strings accessors classes ;
IN: io.encodings.utf16.tests IN: io.encodings.utf16.tests
[ { CHAR: x } ] [ { 0 CHAR: x } utf16be decode >array ] unit-test [ { CHAR: x } ] [ { 0 CHAR: x } utf16be decode >array ] unit-test

View File

@ -1,8 +1,7 @@
! Copyright (C) 2006, 2008 Daniel Ehrenberg. ! Copyright (C) 2006, 2008 Daniel Ehrenberg.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: math kernel sequences sbufs vectors namespaces io.binary USING: math kernel sequences sbufs vectors namespaces io.binary
io.encodings combinators splitting io byte-arrays inspector io.encodings combinators splitting io byte-arrays inspector ;
alien.c-types ;
IN: io.encodings.utf16 IN: io.encodings.utf16
TUPLE: utf16be ; TUPLE: utf16be ;
@ -11,8 +10,6 @@ TUPLE: utf16le ;
TUPLE: utf16 ; TUPLE: utf16 ;
TUPLE: utf16n ;
<PRIVATE <PRIVATE
! UTF-16BE decoding ! UTF-16BE decoding
@ -124,13 +121,4 @@ M: utf16 <decoder> ( stream utf16 -- decoder )
M: utf16 <encoder> ( stream utf16 -- encoder ) M: utf16 <encoder> ( stream utf16 -- encoder )
drop bom-le over stream-write utf16le <encoder> ; drop bom-le over stream-write utf16le <encoder> ;
! Native-order UTF-16
: native-utf16 ( -- descriptor )
little-endian? utf16le utf16be ? ;
M: utf16n <decoder> drop native-utf16 <decoder> ;
M: utf16n <encoder> drop native-utf16 <encoder> ;
PRIVATE> PRIVATE>

View File

@ -0,0 +1,13 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors alien.accessors math io ;
IN: io.streams.memory
TUPLE: memory-stream alien index ;
: <memory-stream> ( alien -- stream )
0 memory-stream boa ;
M: memory-stream stream-read1
[ [ alien>> ] [ index>> ] bi alien-unsigned-1 ]
[ [ 1+ ] change-index drop ] bi ;

View File

@ -184,3 +184,10 @@ unit-test
[ HEX: 988a259c3433f237 ] [ [ HEX: 988a259c3433f237 ] [
B{ HEX: 37 HEX: f2 HEX: 33 HEX: 34 HEX: 9c HEX: 25 HEX: 8a HEX: 98 } byte-array>bignum B{ HEX: 37 HEX: f2 HEX: 33 HEX: 34 HEX: 9c HEX: 25 HEX: 8a HEX: 98 } byte-array>bignum
] unit-test ] unit-test
[ t ] [ 256 power-of-2? ] unit-test
[ f ] [ 123 power-of-2? ] unit-test
[ f ] [ -128 power-of-2? ] unit-test
[ f ] [ 0 power-of-2? ] unit-test
[ t ] [ 1 power-of-2? ] unit-test

View File

@ -96,6 +96,8 @@ C: <interval> interval
: interval-bitnot ( i1 -- i2 ) interval-neg interval-1- ; : interval-bitnot ( i1 -- i2 ) interval-neg interval-1- ;
: interval-sq ( i1 -- i2 ) dup interval* ;
: make-interval ( from to -- int ) : make-interval ( from to -- int )
over first over first { over first over first {
{ [ 2dup > ] [ 2drop 2drop f ] } { [ 2dup > ] [ 2drop 2drop f ] }

View File

@ -1,5 +1,5 @@
USING: help.markup help.syntax kernel sequences quotations USING: help.markup help.syntax kernel sequences quotations
math.private math.functions ; math.private ;
IN: math IN: math
ARTICLE: "division-by-zero" "Division by zero" ARTICLE: "division-by-zero" "Division by zero"
@ -26,17 +26,13 @@ $nl
{ $subsection < } { $subsection < }
{ $subsection <= } { $subsection <= }
{ $subsection > } { $subsection > }
{ $subsection >= } { $subsection >= } ;
"Inexact comparison:"
{ $subsection ~ } ;
ARTICLE: "modular-arithmetic" "Modular arithmetic" ARTICLE: "modular-arithmetic" "Modular arithmetic"
{ $subsection mod } { $subsection mod }
{ $subsection rem } { $subsection rem }
{ $subsection /mod } { $subsection /mod }
{ $subsection /i } { $subsection /i }
{ $subsection mod-inv }
{ $subsection ^mod }
{ $see-also "integer-functions" } ; { $see-also "integer-functions" } ;
ARTICLE: "bitwise-arithmetic" "Bitwise arithmetic" ARTICLE: "bitwise-arithmetic" "Bitwise arithmetic"
@ -363,6 +359,10 @@ HELP: next-power-of-2
{ $values { "m" "a non-negative integer" } { "n" "an integer" } } { $values { "m" "a non-negative integer" } { "n" "an integer" } }
{ $description "Outputs the smallest power of 2 greater than " { $snippet "m" } ". The output value is always at least 1." } ; { $description "Outputs the smallest power of 2 greater than " { $snippet "m" } ". The output value is always at least 1." } ;
HELP: power-of-2?
{ $values { "n" integer } { "?" "a boolean" } }
{ $description "Tests if " { $snippet "n" } " is a power of 2." } ;
HELP: each-integer HELP: each-integer
{ $values { "n" integer } { "quot" "a quotation with stack effect " { $snippet "( i -- )" } } } { $values { "n" integer } { "quot" "a quotation with stack effect " { $snippet "( i -- )" } } }
{ $description "Applies the quotation to each integer from 0 up to " { $snippet "n" } ", excluding " { $snippet "n" } "." } { $description "Applies the quotation to each integer from 0 up to " { $snippet "n" } ", excluding " { $snippet "n" } "." }

View File

@ -55,26 +55,26 @@ GENERIC: zero? ( x -- ? ) foldable
M: object zero? drop f ; M: object zero? drop f ;
: 1+ ( x -- y ) 1 + ; foldable : 1+ ( x -- y ) 1 + ; inline
: 1- ( x -- y ) 1 - ; foldable : 1- ( x -- y ) 1 - ; inline
: 2/ ( x -- y ) -1 shift ; foldable : 2/ ( x -- y ) -1 shift ; inline
: sq ( x -- y ) dup * ; foldable : sq ( x -- y ) dup * ; inline
: neg ( x -- -x ) 0 swap - ; foldable : neg ( x -- -x ) 0 swap - ; inline
: recip ( x -- y ) 1 swap / ; foldable : recip ( x -- y ) 1 swap / ; inline
: ?1+ [ 1+ ] [ 0 ] if* ; inline : ?1+ [ 1+ ] [ 0 ] if* ; inline
: /f ( x y -- z ) >r >float r> >float float/f ; inline : /f ( x y -- z ) >r >float r> >float float/f ; inline
: max ( x y -- z ) [ > ] most ; foldable : max ( x y -- z ) [ > ] most ; inline
: min ( x y -- z ) [ < ] most ; foldable : min ( x y -- z ) [ < ] most ; inline
: between? ( x y z -- ? ) : between? ( x y z -- ? )
pick >= [ >= ] [ 2drop f ] if ; inline pick >= [ >= ] [ 2drop f ] if ; inline
: rem ( x y -- z ) tuck mod over + swap mod ; foldable : rem ( x y -- z ) tuck mod over + swap mod ; foldable
: sgn ( x -- n ) dup 0 < -1 0 ? swap 0 > 1 0 ? bitor ; foldable : sgn ( x -- n ) dup 0 < [ drop -1 ] [ 0 > 1 0 ? ] if ; inline
: [-] ( x y -- z ) - 0 max ; inline : [-] ( x y -- z ) - 0 max ; inline
@ -121,7 +121,11 @@ M: float fp-nan?
: next-power-of-2 ( m -- n ) 2 swap (next-power-of-2) ; foldable : next-power-of-2 ( m -- n ) 2 swap (next-power-of-2) ; foldable
: align ( m w -- n ) 1- [ + ] keep bitnot bitand ; inline : power-of-2? ( n -- ? )
dup 0 <= [ drop f ] [ dup 1- bitand zero? ] if ; foldable
: align ( m w -- n )
1- [ + ] keep bitnot bitand ; inline
<PRIVATE <PRIVATE

View File

@ -3,7 +3,7 @@
USING: arrays generic assocs inference inference.class USING: arrays generic assocs inference inference.class
inference.dataflow inference.backend inference.state io kernel inference.dataflow inference.backend inference.state io kernel
math namespaces sequences vectors words quotations hashtables math namespaces sequences vectors words quotations hashtables
combinators classes optimizer.def-use ; combinators classes optimizer.def-use accessors ;
IN: optimizer.backend IN: optimizer.backend
SYMBOL: class-substitutions SYMBOL: class-substitutions
@ -16,37 +16,32 @@ SYMBOL: optimizer-changed
GENERIC: optimize-node* ( node -- node/t changed? ) GENERIC: optimize-node* ( node -- node/t changed? )
: ?union ( assoc/f assoc -- hash ) : ?union ( assoc assoc/f -- assoc' )
over [ assoc-union ] [ nip ] if ; dup assoc-empty? [ drop ] [ swap assoc-union ] if ;
: add-node-literals ( assoc node -- ) : add-node-literals ( node assoc -- )
over assoc-empty? [ [ ?union ] curry change-literals drop ;
: add-node-classes ( node assoc -- )
[ ?union ] curry change-classes drop ;
: substitute-values ( node assoc -- )
dup assoc-empty? [
2drop 2drop
] [ ] [
[ node-literals ?union ] keep set-node-literals {
] if ; [ >r in-d>> r> substitute-here ]
[ >r in-r>> r> substitute-here ]
: add-node-classes ( assoc node -- ) [ >r out-d>> r> substitute-here ]
over assoc-empty? [ [ >r out-r>> r> substitute-here ]
2drop } 2cleave
] [
[ node-classes ?union ] keep set-node-classes
] if ;
: substitute-values ( assoc node -- )
over assoc-empty? [
2drop
] [
2dup node-in-d swap substitute-here
2dup node-in-r swap substitute-here
2dup node-out-d swap substitute-here
node-out-r swap substitute-here
] if ; ] if ;
: perform-substitutions ( node -- ) : perform-substitutions ( node -- )
class-substitutions get over add-node-classes [ class-substitutions get add-node-classes ]
literal-substitutions get over add-node-literals [ literal-substitutions get add-node-literals ]
value-substitutions get swap substitute-values ; [ value-substitutions get substitute-values ]
tri ;
DEFER: optimize-nodes DEFER: optimize-nodes
@ -90,18 +85,21 @@ M: node optimize-node* drop t f ;
#! Not very efficient. #! Not very efficient.
dupd union* update ; dupd union* update ;
: compute-value-substitutions ( #return/#values #call/#merge -- assoc ) : compute-value-substitutions ( #call/#merge #return/#values -- assoc )
node-out-d swap node-in-d 2array unify-lengths flip [ out-d>> ] [ in-d>> ] bi* 2array unify-lengths flip
[ = not ] assoc-subset >hashtable ; [ = not ] assoc-subset >hashtable ;
: cleanup-inlining ( #return/#values -- newnode changed? ) : cleanup-inlining ( #return/#values -- newnode changed? )
dup node-successor dup [ dup node-successor [
class-substitutions get pick node-classes update [ node-successor ] keep
literal-substitutions get pick node-literals update {
tuck compute-value-substitutions value-substitutions get swap update* [ nip classes>> class-substitutions get swap update ]
node-successor t [ nip literals>> literal-substitutions get swap update ]
[ compute-value-substitutions value-substitutions get swap update* ]
[ drop node-successor ]
} 2cleave t
] [ ] [
2drop t f drop t f
] if ; ] if ;
! #return ! #return

View File

@ -0,0 +1,10 @@
! Copyright (C) 2006, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: inference.dataflow inference.backend kernel ;
IN: optimizer
: collect-label-infos ( node -- node )
dup [
dup #label? [ collect-label-info ] [ drop ] if
] each-node ;

View File

@ -27,22 +27,22 @@ optimizer ;
dup [ 1+ loop-test-1 ] [ drop ] if ; inline dup [ 1+ loop-test-1 ] [ drop ] if ; inline
[ t ] [ [ t ] [
[ loop-test-1 ] dataflow dup detect-loops [ loop-test-1 ] dataflow detect-loops
\ loop-test-1 label-is-loop? \ loop-test-1 label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ loop-test-1 1 2 3 ] dataflow dup detect-loops [ loop-test-1 1 2 3 ] dataflow detect-loops
\ loop-test-1 label-is-loop? \ loop-test-1 label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ [ loop-test-1 ] each ] dataflow dup detect-loops [ [ loop-test-1 ] each ] dataflow detect-loops
\ loop-test-1 label-is-loop? \ loop-test-1 label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ [ loop-test-1 ] each ] dataflow dup detect-loops [ [ loop-test-1 ] each ] dataflow detect-loops
\ (each-integer) label-is-loop? \ (each-integer) label-is-loop?
] unit-test ] unit-test
@ -50,7 +50,7 @@ optimizer ;
dup [ 1+ loop-test-2 1- ] [ drop ] if ; inline dup [ 1+ loop-test-2 1- ] [ drop ] if ; inline
[ t ] [ [ t ] [
[ loop-test-2 ] dataflow dup detect-loops [ loop-test-2 ] dataflow detect-loops
\ loop-test-2 label-is-not-loop? \ loop-test-2 label-is-not-loop?
] unit-test ] unit-test
@ -58,7 +58,7 @@ optimizer ;
dup [ [ loop-test-3 ] each ] [ drop ] if ; inline dup [ [ loop-test-3 ] each ] [ drop ] if ; inline
[ t ] [ [ t ] [
[ loop-test-3 ] dataflow dup detect-loops [ loop-test-3 ] dataflow detect-loops
\ loop-test-3 label-is-not-loop? \ loop-test-3 label-is-not-loop?
] unit-test ] unit-test
@ -73,7 +73,7 @@ optimizer ;
dup #label? [ node-successor find-label ] unless ; dup #label? [ node-successor find-label ] unless ;
: test-loop-exits : test-loop-exits
dataflow dup detect-loops find-label dataflow detect-loops find-label
dup node-param swap dup node-param swap
[ node-child find-tail find-loop-exits [ class ] map ] keep [ node-child find-tail find-loop-exits [ class ] map ] keep
#label-loop? ; #label-loop? ;
@ -113,7 +113,7 @@ optimizer ;
] unit-test ] unit-test
[ f ] [ [ f ] [
[ [ [ ] map ] map ] dataflow dup detect-loops [ [ [ ] map ] map ] dataflow detect-loops
[ dup #label? swap #loop? not and ] node-exists? [ dup #label? swap #loop? not and ] node-exists?
] unit-test ] unit-test
@ -128,22 +128,22 @@ DEFER: a
blah [ b ] [ a ] if ; inline blah [ b ] [ a ] if ; inline
[ t ] [ [ t ] [
[ a ] dataflow dup detect-loops [ a ] dataflow detect-loops
\ a label-is-loop? \ a label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ a ] dataflow dup detect-loops [ a ] dataflow detect-loops
\ b label-is-loop? \ b label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ b ] dataflow dup detect-loops [ b ] dataflow detect-loops
\ a label-is-loop? \ a label-is-loop?
] unit-test ] unit-test
[ t ] [ [ t ] [
[ a ] dataflow dup detect-loops [ a ] dataflow detect-loops
\ b label-is-loop? \ b label-is-loop?
] unit-test ] unit-test
@ -156,12 +156,12 @@ DEFER: a'
blah [ b' ] [ a' ] if ; inline blah [ b' ] [ a' ] if ; inline
[ f ] [ [ f ] [
[ a' ] dataflow dup detect-loops [ a' ] dataflow detect-loops
\ a' label-is-loop? \ a' label-is-loop?
] unit-test ] unit-test
[ f ] [ [ f ] [
[ b' ] dataflow dup detect-loops [ b' ] dataflow detect-loops
\ b' label-is-loop? \ b' label-is-loop?
] unit-test ] unit-test
@ -171,11 +171,11 @@ DEFER: a'
! a standard iterative dataflow problem after all -- so I'm ! a standard iterative dataflow problem after all -- so I'm
! tempted to believe the computer here ! tempted to believe the computer here
[ t ] [ [ t ] [
[ b' ] dataflow dup detect-loops [ b' ] dataflow detect-loops
\ a' label-is-loop? \ a' label-is-loop?
] unit-test ] unit-test
[ f ] [ [ f ] [
[ a' ] dataflow dup detect-loops [ a' ] dataflow detect-loops
\ b' label-is-loop? \ b' label-is-loop?
] unit-test ] unit-test

View File

@ -109,8 +109,9 @@ SYMBOL: potential-loops
] [ 2drop ] if ] [ 2drop ] if
] assoc-each [ remove-non-loop-calls ] when ; ] assoc-each [ remove-non-loop-calls ] when ;
: detect-loops ( nodes -- ) : detect-loops ( node -- node )
[ [
dup
collect-label-info collect-label-info
remove-non-tail-calls remove-non-tail-calls
remove-non-loop-calls remove-non-loop-calls

View File

@ -3,12 +3,12 @@ USING: inference inference.dataflow optimizer optimizer.def-use
namespaces assocs kernel sequences math tools.test words ; namespaces assocs kernel sequences math tools.test words ;
[ 3 { 1 1 1 } ] [ [ 3 { 1 1 1 } ] [
[ 1 2 3 ] dataflow compute-def-use [ 1 2 3 ] dataflow compute-def-use drop
def-use get values dup length swap [ length ] map def-use get values dup length swap [ length ] map
] unit-test ] unit-test
: kill-set ( quot -- seq ) : kill-set ( quot -- seq )
dataflow compute-def-use compute-dead-literals keys dataflow compute-def-use drop compute-dead-literals keys
[ value-literal ] map ; [ value-literal ] map ;
: subset? [ member? ] curry all? ; : subset? [ member? ] curry all? ;

View File

@ -1,8 +1,9 @@
! Copyright (C) 2004, 2007 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: optimizer.def-use
USING: namespaces assocs sequences inference.dataflow USING: namespaces assocs sequences inference.dataflow
inference.backend kernel generic assocs classes vectors ; inference.backend kernel generic assocs classes vectors
accessors combinators ;
IN: optimizer.def-use
SYMBOL: def-use SYMBOL: def-use
@ -21,17 +22,20 @@ SYMBOL: def-use
GENERIC: node-def-use ( node -- ) GENERIC: node-def-use ( node -- )
: compute-def-use ( node -- ) : compute-def-use ( node -- node )
H{ } clone def-use set [ node-def-use ] each-node ; H{ } clone def-use set
dup [ node-def-use ] each-node ;
: nest-def-use ( node -- def-use ) : nest-def-use ( node -- def-use )
[ compute-def-use def-use get ] with-scope ; [ compute-def-use drop def-use get ] with-scope ;
: (node-def-use) ( node -- ) : (node-def-use) ( node -- )
dup dup node-in-d uses-values {
dup dup node-in-r uses-values [ dup in-d>> uses-values ]
dup node-out-d defs-values [ dup in-r>> uses-values ]
node-out-r defs-values ; [ out-d>> defs-values ]
[ out-r>> defs-values ]
} cleave ;
M: object node-def-use (node-def-use) ; M: object node-def-use (node-def-use) ;
@ -43,7 +47,7 @@ M: #passthru node-def-use drop ;
M: #return node-def-use M: #return node-def-use
#! Values returned by local labels can be killed. #! Values returned by local labels can be killed.
dup node-param [ drop ] [ (node-def-use) ] if ; dup param>> [ drop ] [ (node-def-use) ] if ;
! nodes that don't use their values directly ! nodes that don't use their values directly
UNION: #killable UNION: #killable
@ -56,13 +60,13 @@ UNION: #killable
M: #label node-def-use M: #label node-def-use
[ [
dup node-in-d , dup in-d>> ,
dup node-child node-out-d , dup node-child out-d>> ,
dup collect-recursion [ node-in-d , ] each dup calls>> [ in-d>> , ] each
] { } make purge-invariants uses-values ; ] { } make purge-invariants uses-values ;
: branch-def-use ( #branch -- ) : branch-def-use ( #branch -- )
active-children [ node-in-d ] map active-children [ in-d>> ] map
purge-invariants t swap uses-values ; purge-invariants t swap uses-values ;
M: #branch node-def-use M: #branch node-def-use
@ -85,16 +89,16 @@ M: node kill-node* drop t ;
inline inline
M: #shuffle kill-node* M: #shuffle kill-node*
[ [ [ in-d>> empty? ] [ out-d>> empty? ] bi and ] prune-if ;
dup node-in-d empty? swap node-out-d empty? and
] prune-if ;
M: #push kill-node* M: #push kill-node*
[ node-out-d empty? ] prune-if ; [ out-d>> empty? ] prune-if ;
M: #>r kill-node* [ node-in-d empty? ] prune-if ; M: #>r kill-node*
[ in-d>> empty? ] prune-if ;
M: #r> kill-node* [ node-in-r empty? ] prune-if ; M: #r> kill-node*
[ in-r>> empty? ] prune-if ;
: kill-node ( node -- node ) : kill-node ( node -- node )
dup [ dup [
@ -116,7 +120,7 @@ M: #r> kill-node* [ node-in-r empty? ] prune-if ;
] if ; ] if ;
: sole-consumer ( #call -- node/f ) : sole-consumer ( #call -- node/f )
node-out-d first used-by out-d>> first used-by
dup length 1 = [ first ] [ drop f ] if ; dup length 1 = [ first ] [ drop f ] if ;
: splice-def-use ( node -- ) : splice-def-use ( node -- )
@ -128,5 +132,5 @@ M: #r> kill-node* [ node-in-r empty? ] prune-if ;
#! degree of accuracy; the new values should be marked as #! degree of accuracy; the new values should be marked as
#! having _some_ usage, so that flushing doesn't erronously #! having _some_ usage, so that flushing doesn't erronously
#! flush them away. #! flush them away.
[ compute-def-use def-use get keys ] with-scope nest-def-use keys
def-use get [ [ t swap ?push ] change-at ] curry each ; def-use get [ [ t swap ?push ] change-at ] curry each ;

View File

@ -0,0 +1,10 @@
IN: optimizer.inlining.tests
USING: tools.test optimizer.inlining ;
\ word-flat-length must-infer
\ inlining-math-method must-infer
\ optimistic-inline? must-infer
\ find-identity must-infer

View File

@ -3,10 +3,11 @@
USING: arrays generic assocs inference inference.class USING: arrays generic assocs inference inference.class
inference.dataflow inference.backend inference.state io kernel inference.dataflow inference.backend inference.state io kernel
math namespaces sequences vectors words quotations hashtables math namespaces sequences vectors words quotations hashtables
combinators classes classes.algebra generic.math continuations combinators classes classes.algebra generic.math
optimizer.def-use optimizer.backend generic.standard optimizer.math.partial continuations optimizer.def-use
optimizer.specializers optimizer.def-use optimizer.pattern-match optimizer.backend generic.standard optimizer.specializers
generic.standard optimizer.control kernel.private ; optimizer.def-use optimizer.pattern-match generic.standard
optimizer.control kernel.private ;
IN: optimizer.inlining IN: optimizer.inlining
: remember-inlining ( node history -- ) : remember-inlining ( node history -- )
@ -53,8 +54,6 @@ DEFER: (flat-length)
[ word-def (flat-length) ] with-scope ; [ word-def (flat-length) ] with-scope ;
! Single dispatch method inlining optimization ! Single dispatch method inlining optimization
: specific-method ( class word -- class ) order min-class ;
: node-class# ( node n -- class ) : node-class# ( node n -- class )
over node-in-d <reversed> ?nth node-class ; over node-in-d <reversed> ?nth node-class ;
@ -72,6 +71,7 @@ DEFER: (flat-length)
! Partial dispatch of math-generic words ! Partial dispatch of math-generic words
: normalize-math-class ( class -- class' ) : normalize-math-class ( class -- class' )
{ {
null
fixnum bignum integer fixnum bignum integer
ratio rational ratio rational
float real float real
@ -79,21 +79,31 @@ DEFER: (flat-length)
object object
} [ class< ] with find nip ; } [ class< ] with find nip ;
: math-both-known? ( word left right -- ? ) : inlining-math-method ( #call word -- quot/f )
math-class-max swap specific-method ; swap node-input-classes
: inline-math-method ( #call word -- node )
over node-input-classes
[ first normalize-math-class ] [ first normalize-math-class ]
[ second normalize-math-class ] bi [ second normalize-math-class ] bi
3dup math-both-known? 3dup math-both-known? [ math-method* ] [ 3drop f ] if ;
[ math-method f splice-quot ]
[ 2drop 2drop t ] if ; : inline-math-method ( #call word -- node/t )
[ drop ] [ inlining-math-method ] 2bi
dup [ f splice-quot ] [ 2drop t ] if ;
: inline-math-partial ( #call word -- node/t )
[ drop ]
[
"derived-from" word-prop first
inlining-math-method dup
]
[ nip 1quotation ] 2tri
[ = not ] [ drop ] 2bi and
[ f splice-quot ] [ 2drop t ] if ;
: inline-method ( #call -- node ) : inline-method ( #call -- node )
dup node-param { dup node-param {
{ [ dup standard-generic? ] [ inline-standard-method ] } { [ dup standard-generic? ] [ inline-standard-method ] }
{ [ dup math-generic? ] [ inline-math-method ] } { [ dup math-generic? ] [ inline-math-method ] }
{ [ dup math-partial? ] [ inline-math-partial ] }
[ 2drop t ] [ 2drop t ]
} cond ; } cond ;
@ -183,7 +193,7 @@ DEFER: (flat-length)
nip dup [ second ] when ; nip dup [ second ] when ;
: apply-identities ( node -- node/f ) : apply-identities ( node -- node/f )
dup find-identity dup [ f splice-quot ] [ 2drop f ] if ; dup find-identity f splice-quot ;
: optimistic-inline? ( #call -- ? ) : optimistic-inline? ( #call -- ? )
dup node-param "specializer" word-prop dup [ dup node-param "specializer" word-prop dup [

View File

@ -60,7 +60,8 @@ sequences.private combinators ;
[ value-literal sequence? ] [ drop f ] if ; [ value-literal sequence? ] [ drop f ] if ;
: member-quot ( seq -- newquot ) : member-quot ( seq -- newquot )
[ [ t ] ] { } map>assoc [ drop f ] suffix [ nip case ] curry ; [ literalize [ t ] ] { } map>assoc
[ drop f ] suffix [ nip case ] curry ;
: expand-member ( #call -- ) : expand-member ( #call -- )
dup node-in-d peek value-literal member-quot f splice-quot ; dup node-in-d peek value-literal member-quot f splice-quot ;
@ -83,21 +84,11 @@ sequences.private combinators ;
] "constraints" set-word-prop ] "constraints" set-word-prop
! eq? on the same object is always t ! eq? on the same object is always t
{ eq? bignum= float= number= = } { { eq? = } {
{ { @ @ } [ 2drop t ] } { { @ @ } [ 2drop t ] }
} define-identities } define-identities
! Specializers ! Specializers
{ 1+ 1- sq neg recip sgn } [
{ number } "specializer" set-word-prop
] each
\ 2/ { fixnum } "specializer" set-word-prop
{ min max } [
{ number number } "specializer" set-word-prop
] each
{ first first2 first3 first4 } { first first2 first3 first4 }
[ { array } "specializer" set-word-prop ] each [ { array } "specializer" set-word-prop ] each

View File

@ -8,103 +8,104 @@ namespaces assocs quotations math.intervals sequences.private
combinators splitting layouts math.parser classes combinators splitting layouts math.parser classes
classes.algebra generic.math optimizer.pattern-match classes.algebra generic.math optimizer.pattern-match
optimizer.backend optimizer.def-use optimizer.inlining optimizer.backend optimizer.def-use optimizer.inlining
generic.standard system ; optimizer.math.partial generic.standard system accessors ;
{ + bignum+ float+ fixnum+fast } { : define-math-identities ( word identities -- )
>r all-derived-ops r> define-identities ;
\ number= {
{ { @ @ } [ 2drop t ] }
} define-math-identities
\ + {
{ { number 0 } [ drop ] } { { number 0 } [ drop ] }
{ { 0 number } [ nip ] } { { 0 number } [ nip ] }
} define-identities } define-math-identities
{ fixnum+ } { \ - {
{ { number 0 } [ drop ] }
{ { 0 number } [ nip ] }
} define-identities
{ - fixnum- bignum- float- fixnum-fast } {
{ { number 0 } [ drop ] } { { number 0 } [ drop ] }
{ { @ @ } [ 2drop 0 ] } { { @ @ } [ 2drop 0 ] }
} define-identities } define-math-identities
{ < fixnum< bignum< float< } { \ < {
{ { @ @ } [ 2drop f ] } { { @ @ } [ 2drop f ] }
} define-identities } define-math-identities
{ <= fixnum<= bignum<= float<= } { \ <= {
{ { @ @ } [ 2drop t ] } { { @ @ } [ 2drop t ] }
} define-identities } define-math-identities
{ > fixnum> bignum> float>= } { \ > {
{ { @ @ } [ 2drop f ] } { { @ @ } [ 2drop f ] }
} define-identities } define-math-identities
{ >= fixnum>= bignum>= float>= } { \ >= {
{ { @ @ } [ 2drop t ] } { { @ @ } [ 2drop t ] }
} define-identities } define-math-identities
{ * fixnum* bignum* float* } { \ * {
{ { number 1 } [ drop ] } { { number 1 } [ drop ] }
{ { 1 number } [ nip ] } { { 1 number } [ nip ] }
{ { number 0 } [ nip ] } { { number 0 } [ nip ] }
{ { 0 number } [ drop ] } { { 0 number } [ drop ] }
{ { number -1 } [ drop 0 swap - ] } { { number -1 } [ drop 0 swap - ] }
{ { -1 number } [ nip 0 swap - ] } { { -1 number } [ nip 0 swap - ] }
} define-identities } define-math-identities
{ / fixnum/i bignum/i float/f } { \ / {
{ { number 1 } [ drop ] } { { number 1 } [ drop ] }
{ { number -1 } [ drop 0 swap - ] } { { number -1 } [ drop 0 swap - ] }
} define-identities } define-math-identities
{ fixnum-mod bignum-mod } { \ mod {
{ { number 1 } [ 2drop 0 ] } { { integer 1 } [ 2drop 0 ] }
} define-identities } define-math-identities
{ bitand fixnum-bitand bignum-bitand } { \ rem {
{ { integer 1 } [ 2drop 0 ] }
} define-math-identities
\ bitand {
{ { number -1 } [ drop ] } { { number -1 } [ drop ] }
{ { -1 number } [ nip ] } { { -1 number } [ nip ] }
{ { @ @ } [ drop ] } { { @ @ } [ drop ] }
{ { number 0 } [ nip ] } { { number 0 } [ nip ] }
{ { 0 number } [ drop ] } { { 0 number } [ drop ] }
} define-identities } define-math-identities
{ bitor fixnum-bitor bignum-bitor } { \ bitor {
{ { number 0 } [ drop ] } { { number 0 } [ drop ] }
{ { 0 number } [ nip ] } { { 0 number } [ nip ] }
{ { @ @ } [ drop ] } { { @ @ } [ drop ] }
{ { number -1 } [ nip ] } { { number -1 } [ nip ] }
{ { -1 number } [ drop ] } { { -1 number } [ drop ] }
} define-identities } define-math-identities
{ bitxor fixnum-bitxor bignum-bitxor } { \ bitxor {
{ { number 0 } [ drop ] } { { number 0 } [ drop ] }
{ { 0 number } [ nip ] } { { 0 number } [ nip ] }
{ { number -1 } [ drop bitnot ] } { { number -1 } [ drop bitnot ] }
{ { -1 number } [ nip bitnot ] } { { -1 number } [ nip bitnot ] }
{ { @ @ } [ 2drop 0 ] } { { @ @ } [ 2drop 0 ] }
} define-identities } define-math-identities
{ shift fixnum-shift fixnum-shift-fast bignum-shift } { \ shift {
{ { 0 number } [ drop ] } { { 0 number } [ drop ] }
{ { number 0 } [ drop ] } { { number 0 } [ drop ] }
} define-identities } define-math-identities
: math-closure ( class -- newclass ) : math-closure ( class -- newclass )
{ fixnum integer rational real } { null fixnum bignum integer rational float real number }
[ class< ] with find nip number or ; [ class< ] with find nip number or ;
: fits? ( interval class -- ? ) : fits? ( interval class -- ? )
"interval" word-prop dup "interval" word-prop dup
[ interval-subset? ] [ 2drop t ] if ; [ interval-subset? ] [ 2drop t ] if ;
: math-output-class ( node min -- newclass ) : math-output-class ( node upgrades -- newclass )
#! if min is f, it means we just want to use the declared >r
#! output class from the "infer-effect". in-d>> null [ value-class* math-closure math-class-max ] reduce
dup [ dup r> at swap or ;
swap node-in-d
[ value-class* math-closure math-class-max ] each
] [
2drop f
] if ;
: won't-overflow? ( interval node -- ? ) : won't-overflow? ( interval node -- ? )
node-in-d [ value-class* fixnum class< ] all? node-in-d [ value-class* fixnum class< ] all?
@ -123,28 +124,18 @@ generic.standard system ;
2drop f 2drop f
] if ; inline ] if ; inline
: math-output-class/interval-1 ( node min word -- classes intervals ) : math-output-class/interval-1 ( node word -- classes intervals )
pick >r [ drop { } math-output-class 1array ]
>r over r> [ math-output-interval-1 1array ] 2bi ;
math-output-interval-1
>r math-output-class r>
r> post-process ; inline
{ {
{ 1+ integer interval-1+ } { bitnot interval-bitnot }
{ 1- integer interval-1- } { fixnum-bitnot interval-bitnot }
{ neg integer interval-neg } { bignum-bitnot interval-bitnot }
{ shift integer interval-recip }
{ bitnot fixnum interval-bitnot }
{ fixnum-bitnot f interval-bitnot }
{ bignum-bitnot f interval-bitnot }
{ 2/ fixnum interval-2/ }
{ sq integer f }
} [ } [
first3 [ [ math-output-class/interval-1 ] curry
math-output-class/interval-1 "output-classes" set-word-prop
] 2curry "output-classes" set-word-prop ] assoc-each
] each
: intervals ( node -- i1 i2 ) : intervals ( node -- i1 i2 )
node-in-d first2 [ value-interval* ] bi@ ; node-in-d first2 [ value-interval* ] bi@ ;
@ -156,7 +147,7 @@ generic.standard system ;
2drop f 2drop f
] if ; inline ] if ; inline
: math-output-class/interval-2 ( node min word -- classes intervals ) : math-output-class/interval-2 ( node upgrades word -- classes intervals )
pick >r pick >r
>r over r> >r over r>
math-output-interval-2 math-output-interval-2
@ -164,47 +155,18 @@ generic.standard system ;
r> post-process ; inline r> post-process ; inline
{ {
{ + integer interval+ } { + { { fixnum integer } } interval+ }
{ - integer interval- } { - { { fixnum integer } } interval- }
{ * integer interval* } { * { { fixnum integer } } interval* }
{ / rational interval/ } { / { { fixnum rational } { integer rational } } interval/ }
{ /i integer interval/i } { /i { { fixnum integer } } interval/i }
{ shift { { fixnum integer } } interval-shift-safe }
{ fixnum+ f interval+ }
{ fixnum+fast f interval+ }
{ fixnum- f interval- }
{ fixnum-fast f interval- }
{ fixnum* f interval* }
{ fixnum*fast f interval* }
{ fixnum/i f interval/i }
{ bignum+ f interval+ }
{ bignum- f interval- }
{ bignum* f interval* }
{ bignum/i f interval/i }
{ bignum-shift f interval-shift-safe }
{ float+ f interval+ }
{ float- f interval- }
{ float* f interval* }
{ float/f f interval/ }
{ min fixnum interval-min }
{ max fixnum interval-max }
} [ } [
first3 [ first3 [
[
math-output-class/interval-2 math-output-class/interval-2
] 2curry "output-classes" set-word-prop ] 2curry "output-classes" set-word-prop
] each ] 2curry each-derived-op
{ fixnum-shift fixnum-shift-fast shift } [
[
dup
node-in-d second value-interval*
-1./0. 0 [a,b] interval-subset? fixnum integer ?
\ interval-shift-safe
math-output-class/interval-2
] "output-classes" set-word-prop
] each ] each
: real-value? ( value -- n ? ) : real-value? ( value -- n ? )
@ -235,22 +197,18 @@ generic.standard system ;
r> post-process ; inline r> post-process ; inline
{ {
{ mod fixnum mod-range } { mod { } mod-range }
{ fixnum-mod f mod-range } { rem { { fixnum integer } } rem-range }
{ bignum-mod f mod-range }
{ float-mod f mod-range }
{ rem integer rem-range } { bitand { } bitand-range }
{ bitor { } f }
{ bitand fixnum bitand-range } { bitxor { } f }
{ fixnum-bitand f bitand-range }
{ bitor fixnum f }
{ bitxor fixnum f }
} [ } [
first3 [ first3 [
[
math-output-class/interval-special math-output-class/interval-special
] 2curry "output-classes" set-word-prop ] 2curry "output-classes" set-word-prop
] 2curry each-derived-op
] each ] each
: twiddle-interval ( i1 -- i2 ) : twiddle-interval ( i1 -- i2 )
@ -280,26 +238,12 @@ generic.standard system ;
{ <= assume<= assume> } { <= assume<= assume> }
{ > assume> assume<= } { > assume> assume<= }
{ >= assume>= assume< } { >= assume>= assume< }
{ fixnum< assume< assume>= }
{ fixnum<= assume<= assume> }
{ fixnum> assume> assume<= }
{ fixnum>= assume>= assume< }
{ bignum< assume< assume>= }
{ bignum<= assume<= assume> }
{ bignum> assume> assume<= }
{ bignum>= assume>= assume< }
{ float< assume< assume>= }
{ float<= assume<= assume> }
{ float> assume> assume<= }
{ float>= assume>= assume< }
} [ } [
first3 first3 [
[ [
[ comparison-constraints ] with-scope [ comparison-constraints ] with-scope
] 2curry "constraints" set-word-prop ] 2curry "constraints" set-word-prop
] 2curry each-derived-op
] each ] each
{ {
@ -348,22 +292,20 @@ most-negative-fixnum most-positive-fixnum [a,b]
! Removing overflow checks ! Removing overflow checks
: remove-overflow-check? ( #call -- ? ) : remove-overflow-check? ( #call -- ? )
dup node-out-d first node-class fixnum class< ; dup out-d>> first node-class
[ fixnum class< ] [ null eq? not ] bi and ;
{ {
{ + [ fixnum+fast ] } { + [ fixnum+fast ] }
{ +-integer-fixnum [ fixnum+fast ] }
{ - [ fixnum-fast ] } { - [ fixnum-fast ] }
{ * [ fixnum*fast ] } { * [ fixnum*fast ] }
{ *-integer-fixnum [ fixnum*fast ] }
{ shift [ fixnum-shift-fast ] }
{ fixnum+ [ fixnum+fast ] } { fixnum+ [ fixnum+fast ] }
{ fixnum- [ fixnum-fast ] } { fixnum- [ fixnum-fast ] }
{ fixnum* [ fixnum*fast ] } { fixnum* [ fixnum*fast ] }
! these are here as an optimization. if they weren't given { fixnum-shift [ fixnum-shift-fast ] }
! explicitly, the same would be inferred after an extra
! optimization step (see optimistic-inline?)
{ 1+ [ 1 fixnum+fast ] }
{ 1- [ 1 fixnum-fast ] }
{ 2/ [ -1 fixnum-shift ] }
{ neg [ 0 swap fixnum-fast ] }
} [ } [
[ [
[ dup remove-overflow-check? ] , [ dup remove-overflow-check? ] ,
@ -397,26 +339,13 @@ most-negative-fixnum most-positive-fixnum [a,b]
{ <= interval<= } { <= interval<= }
{ > interval> } { > interval> }
{ >= interval>= } { >= interval>= }
{ fixnum< interval< }
{ fixnum<= interval<= }
{ fixnum> interval> }
{ fixnum>= interval>= }
{ bignum< interval< }
{ bignum<= interval<= }
{ bignum> interval> }
{ bignum>= interval>= }
{ float< interval< }
{ float<= interval<= }
{ float> interval> }
{ float>= interval>= }
} [ } [
[
[ [
dup [ dupd foldable-comparison? ] curry , dup [ dupd foldable-comparison? ] curry ,
[ fold-comparison ] curry , [ fold-comparison ] curry ,
] { } make 1array define-optimizers ] { } make 1array define-optimizers
] curry each-derived-op
] assoc-each ] assoc-each
! The following words are handled in a similar way except if ! The following words are handled in a similar way except if
@ -426,44 +355,68 @@ most-negative-fixnum most-positive-fixnum [a,b]
swap sole-consumer swap sole-consumer
dup #call? [ node-param eq? ] [ 2drop f ] if ; dup #call? [ node-param eq? ] [ 2drop f ] if ;
: coereced-to-fixnum? ( #call -- ? ) : coerced-to-fixnum? ( #call -- ? )
\ >fixnum consumed-by? ; dup dup node-in-d [ node-class integer class< ] with all?
[ \ >fixnum consumed-by? ] [ drop f ] if ;
{ {
{ fixnum+ [ fixnum+fast ] } { + [ [ >fixnum ] bi@ fixnum+fast ] }
{ fixnum- [ fixnum-fast ] } { - [ [ >fixnum ] bi@ fixnum-fast ] }
{ fixnum* [ fixnum*fast ] } { * [ [ >fixnum ] bi@ fixnum*fast ] }
} [ } [
>r derived-ops r> [
[ [
[ [
dup remove-overflow-check? dup remove-overflow-check?
over coereced-to-fixnum? or over coerced-to-fixnum? or
] , ] ,
[ f splice-quot ] curry , [ f splice-quot ] curry ,
] { } make 1array define-optimizers ] { } make 1array define-optimizers
] curry each
] assoc-each ] assoc-each
: fixnum-shift-fast-pos? ( node -- ? ) : convert-rem-to-and? ( #call -- ? )
#! Shifting 1 to the left won't overflow if the shift dup node-in-d {
#! count is small enough { [ 2dup first node-class integer class< not ] [ f ] }
dup dup node-in-d first node-literal 1 = [ { [ 2dup second node-literal integer? not ] [ f ] }
dup node-in-d second node-interval { [ 2dup second node-literal power-of-2? not ] [ f ] }
0 cell-bits tag-bits get - 2 - [a,b] interval-subset? [ t ]
] [ drop f ] if ; } cond 2nip ;
: fixnum-shift-fast-neg? ( node -- ? ) : convert-mod-to-and? ( #call -- ? )
#! Shifting any number to the right won't overflow if the dup dup node-in-d first node-interval 0 [a,inf] interval-subset?
#! shift count is small enough [ convert-rem-to-and? ] [ drop f ] if ;
dup node-in-d second node-interval
cell-bits 1- neg 0 [a,b] interval-subset? ;
: fixnum-shift-fast? ( node -- ? ) : convert-mod-to-and ( #call -- node )
dup fixnum-shift-fast-pos? dup
[ drop t ] [ fixnum-shift-fast-neg? ] if ; dup node-in-d second node-literal 1-
[ nip bitand ] curry f splice-quot ;
\ fixnum-shift { \ mod [
{ {
[ dup fixnum-shift-fast? ] {
[ [ fixnum-shift-fast ] f splice-quot ] [ dup convert-mod-to-and? ]
[ convert-mod-to-and ]
}
} define-optimizers
] each-derived-op
\ rem {
{
[ dup convert-rem-to-and? ]
[ convert-mod-to-and ]
}
} define-optimizers
: fixnumify-bitand? ( #call -- ? )
dup node-in-d second node-interval fixnum fits? ;
: fixnumify-bitand ( #call -- node )
[ [ >fixnum ] bi@ fixnum-bitand ] f splice-quot ;
\ bitand {
{
[ dup fixnumify-bitand? ]
[ fixnumify-bitand ]
} }
} define-optimizers } define-optimizers

View File

@ -0,0 +1,13 @@
IN: optimizer.math.partial.tests
USING: optimizer.math.partial tools.test math kernel
sequences ;
[ t ] [ \ + integer fixnum math-both-known? ] unit-test
[ t ] [ \ + bignum fixnum math-both-known? ] unit-test
[ t ] [ \ + integer bignum math-both-known? ] unit-test
[ t ] [ \ + float fixnum math-both-known? ] unit-test
[ f ] [ \ + real fixnum math-both-known? ] unit-test
[ f ] [ \ + object number math-both-known? ] unit-test
[ f ] [ \ number= fixnum object math-both-known? ] unit-test
[ t ] [ \ number= integer fixnum math-both-known? ] unit-test
[ f ] [ \ >fixnum \ shift derived-ops memq? ] unit-test

View File

@ -0,0 +1,172 @@
! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel kernel.private math math.private words
sequences parser namespaces assocs quotations arrays
generic generic.math hashtables effects ;
IN: optimizer.math.partial
! Partial dispatch.
! This code will be overhauled and generalized when
! multi-methods go into the core.
PREDICATE: math-partial < word
"derived-from" word-prop >boolean ;
: fixnum-integer-op ( a b fix-word big-word -- c )
pick tag 0 eq? [
drop execute
] [
>r drop >r fixnum>bignum r> r> execute
] if ; inline
: integer-fixnum-op ( a b fix-word big-word -- c )
>r pick tag 0 eq? [
r> drop execute
] [
drop fixnum>bignum r> execute
] if ; inline
: integer-integer-op ( a b fix-word big-word -- c )
pick tag 0 eq? [
integer-fixnum-op
] [
>r drop over tag 0 eq? [
>r fixnum>bignum r> r> execute
] [
r> execute
] if
] if ; inline
<<
: integer-op-combinator ( triple -- word )
[
[ second word-name % "-" % ]
[ third word-name % "-op" % ]
bi
] "" make in get lookup ;
: integer-op-word ( triple fix-word big-word -- word )
[
drop
word-name "fast" tail? >r
[ "-" % ] [ word-name % ] interleave
r> [ "-fast" % ] when
] "" make in get create ;
: integer-op-quot ( word fix-word big-word -- quot )
rot integer-op-combinator 1quotation 2curry ;
: define-integer-op-word ( word fix-word big-word -- )
[
[ integer-op-word ] [ integer-op-quot ] 3bi
2 1 <effect> define-declared
]
[
[ integer-op-word ] [ 2drop ] 3bi
"derived-from" set-word-prop
] 3bi ;
: define-integer-op-words ( words fix-word big-word -- )
[ define-integer-op-word ] 2curry each ;
: integer-op-triples ( word -- triples )
{
{ fixnum integer }
{ integer fixnum }
{ integer integer }
} swap [ prefix ] curry map ;
: define-integer-ops ( word fix-word big-word -- )
>r >r integer-op-triples r> r>
[ define-integer-op-words ]
[ [ 2drop ] [ [ integer-op-word ] 2curry map ] 3bi zip % ]
3bi ;
: define-math-ops ( op -- )
{ fixnum bignum float }
[ [ dup 3array ] [ swap method ] 2bi ] with { } map>assoc
[ nip ] assoc-subset
[ word-def peek ] assoc-map % ;
SYMBOL: math-ops
[
\ + define-math-ops
\ - define-math-ops
\ * define-math-ops
\ shift define-math-ops
\ mod define-math-ops
\ /i define-math-ops
\ bitand define-math-ops
\ bitor define-math-ops
\ bitxor define-math-ops
\ < define-math-ops
\ <= define-math-ops
\ > define-math-ops
\ >= define-math-ops
\ number= define-math-ops
\ + \ fixnum+ \ bignum+ define-integer-ops
\ - \ fixnum- \ bignum- define-integer-ops
\ * \ fixnum* \ bignum* define-integer-ops
\ shift \ fixnum-shift \ bignum-shift define-integer-ops
\ mod \ fixnum-mod \ bignum-mod define-integer-ops
\ /i \ fixnum/i \ bignum/i define-integer-ops
\ bitand \ fixnum-bitand \ bignum-bitand define-integer-ops
\ bitor \ fixnum-bitor \ bignum-bitor define-integer-ops
\ bitxor \ fixnum-bitxor \ bignum-bitxor define-integer-ops
\ < \ fixnum< \ bignum< define-integer-ops
\ <= \ fixnum<= \ bignum<= define-integer-ops
\ > \ fixnum> \ bignum> define-integer-ops
\ >= \ fixnum>= \ bignum>= define-integer-ops
\ number= \ eq? \ bignum= define-integer-ops
] { } make >hashtable math-ops set-global
SYMBOL: fast-math-ops
[
{ { + fixnum fixnum } fixnum+fast } ,
{ { - fixnum fixnum } fixnum-fast } ,
{ { * fixnum fixnum } fixnum*fast } ,
{ { shift fixnum fixnum } fixnum-shift-fast } ,
\ + \ fixnum+fast \ bignum+ define-integer-ops
\ - \ fixnum-fast \ bignum- define-integer-ops
\ * \ fixnum*fast \ bignum* define-integer-ops
\ shift \ fixnum-shift-fast \ bignum-shift define-integer-ops
] { } make >hashtable fast-math-ops set-global
>>
: math-op ( word left right -- word' ? )
3array math-ops get at* ;
: math-method* ( word left right -- quot )
3dup math-op
[ >r 3drop r> 1quotation ] [ drop math-method ] if ;
: math-both-known? ( word left right -- ? )
3dup math-op
[ 2drop 2drop t ]
[ drop math-class-max swap specific-method >boolean ] if ;
: (derived-ops) ( word assoc -- words )
swap [ rot first eq? nip ] curry assoc-subset values ;
: derived-ops ( word -- words )
[ 1array ]
[ math-ops get (derived-ops) ]
bi append ;
: fast-derived-ops ( word -- words )
fast-math-ops get (derived-ops) ;
: all-derived-ops ( word -- words )
[ derived-ops ] [ fast-derived-ops ] bi append ;
: each-derived-op ( word quot -- )
>r derived-ops r> each ; inline

View File

@ -1,9 +1,9 @@
USING: arrays compiler.units generic hashtables inference kernel USING: arrays compiler.units generic hashtables inference kernel
kernel.private math optimizer prettyprint sequences sbufs kernel.private math optimizer generator prettyprint sequences
strings tools.test vectors words sequences.private quotations sbufs strings tools.test vectors words sequences.private
optimizer.backend classes classes.algebra inference.dataflow quotations optimizer.backend classes classes.algebra
classes.tuple.private continuations growable optimizer.inlining inference.dataflow classes.tuple.private continuations growable
namespaces hints ; optimizer.inlining namespaces hints ;
IN: optimizer.tests IN: optimizer.tests
[ H{ { 1 5 } { 3 4 } { 2 5 } } ] [ [ H{ { 1 5 } { 3 4 } { 2 5 } } ] [
@ -14,40 +14,6 @@ IN: optimizer.tests
H{ { 1 2 } { 3 4 } } H{ { 2 3 } } union* H{ { 1 2 } { 3 4 } } H{ { 2 3 } } union*
] unit-test ] 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
GENERIC: xyz ( obj -- obj ) GENERIC: xyz ( obj -- obj )
M: array xyz xyz ; M: array xyz xyz ;
@ -325,7 +291,6 @@ TUPLE: silly-tuple a b ;
[ 1 2 3 ] [ lift-loop-tail-test-2 ] unit-test [ 1 2 3 ] [ lift-loop-tail-test-2 ] unit-test
! Make sure we don't lose
GENERIC: generic-inline-test ( x -- y ) GENERIC: generic-inline-test ( x -- y )
M: integer generic-inline-test ; M: integer generic-inline-test ;
@ -342,6 +307,7 @@ M: integer generic-inline-test ;
generic-inline-test generic-inline-test
generic-inline-test ; generic-inline-test ;
! Inlining all of the above should only take two passes
[ { t f } ] [ [ { t f } ] [
\ generic-inline-test-1 word-def dataflow \ generic-inline-test-1 word-def dataflow
[ optimize-1 , optimize-1 , drop ] { } make [ optimize-1 , optimize-1 , drop ] { } make
@ -374,3 +340,19 @@ HINTS: recursive-inline-hang-3 array ;
USE: sequences.private USE: sequences.private
[ ] [ { (3append) } compile ] unit-test [ ] [ { (3append) } compile ] unit-test
! Wow
: counter-example ( a b c d -- a' b' c' d' )
dup 0 > [ 1 - >r rot 2 * r> counter-example ] when ; inline
: counter-example' ( -- a' b' c' d' )
1 2 3.0 3 counter-example ;
[ 2 4 6.0 0 ] [ counter-example' ] unit-test
: member-test { + - * / /i } member? ;
\ member-test must-infer
[ ] [ \ member-test word-dataflow optimize 2drop ] unit-test
[ t ] [ \ + member-test ] unit-test
[ f ] [ \ append member-test ] unit-test

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: kernel namespaces optimizer.backend optimizer.def-use USING: kernel namespaces optimizer.backend optimizer.def-use
optimizer.known-words optimizer.math optimizer.control optimizer.known-words optimizer.math optimizer.control
optimizer.inlining inference.class ; optimizer.collect optimizer.inlining inference.class ;
IN: optimizer IN: optimizer
: optimize-1 ( node -- newnode ? ) : optimize-1 ( node -- newnode ? )
@ -10,10 +10,13 @@ IN: optimizer
H{ } clone class-substitutions set H{ } clone class-substitutions set
H{ } clone literal-substitutions set H{ } clone literal-substitutions set
H{ } clone value-substitutions set H{ } clone value-substitutions set
dup compute-def-use
collect-label-infos
compute-def-use
kill-values kill-values
dup detect-loops detect-loops
dup infer-classes infer-classes
optimizer-changed off optimizer-changed off
optimize-nodes optimize-nodes
optimizer-changed get optimizer-changed get

View File

@ -1,11 +1,10 @@
! Copyright (C) 2003, 2008 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays byte-arrays byte-vectors bit-arrays bit-vectors USING: arrays byte-arrays bit-arrays generic hashtables io
generic hashtables io assocs kernel math namespaces sequences assocs kernel math namespaces sequences strings sbufs io.styles
strings sbufs io.styles vectors words prettyprint.config vectors words prettyprint.config prettyprint.sections quotations
prettyprint.sections quotations io io.files math.parser effects io io.files math.parser effects classes.tuple
classes.tuple classes.tuple.private classes float-arrays classes.tuple.private classes float-arrays ;
float-vectors ;
IN: prettyprint.backend IN: prettyprint.backend
GENERIC: pprint* ( obj -- ) GENERIC: pprint* ( obj -- )
@ -140,11 +139,8 @@ M: curry pprint-delims drop \ [ \ ] ;
M: compose pprint-delims drop \ [ \ ] ; M: compose pprint-delims drop \ [ \ ] ;
M: array pprint-delims drop \ { \ } ; M: array pprint-delims drop \ { \ } ;
M: byte-array pprint-delims drop \ B{ \ } ; M: byte-array pprint-delims drop \ B{ \ } ;
M: byte-vector pprint-delims drop \ BV{ \ } ;
M: bit-array pprint-delims drop \ ?{ \ } ; M: bit-array pprint-delims drop \ ?{ \ } ;
M: bit-vector pprint-delims drop \ ?V{ \ } ;
M: float-array pprint-delims drop \ F{ \ } ; M: float-array pprint-delims drop \ F{ \ } ;
M: float-vector pprint-delims drop \ FV{ \ } ;
M: vector pprint-delims drop \ V{ \ } ; M: vector pprint-delims drop \ V{ \ } ;
M: hashtable pprint-delims drop \ H{ \ } ; M: hashtable pprint-delims drop \ H{ \ } ;
M: tuple pprint-delims drop \ T{ \ } ; M: tuple pprint-delims drop \ T{ \ } ;
@ -156,9 +152,6 @@ GENERIC: >pprint-sequence ( obj -- seq )
M: object >pprint-sequence ; M: object >pprint-sequence ;
M: vector >pprint-sequence ; M: vector >pprint-sequence ;
M: bit-vector >pprint-sequence ;
M: byte-vector >pprint-sequence ;
M: float-vector >pprint-sequence ;
M: curry >pprint-sequence ; M: curry >pprint-sequence ;
M: compose >pprint-sequence ; M: compose >pprint-sequence ;
M: hashtable >pprint-sequence >alist ; M: hashtable >pprint-sequence >alist ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2003, 2007 Slava Pestov. ! Copyright (C) 2003, 2007 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: prettyprint.config IN: prettyprint.config
USING: alien arrays generic assocs io kernel math USING: arrays generic assocs io kernel math
namespaces sequences strings io.styles vectors words namespaces sequences strings io.styles vectors words
continuations ; continuations ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2003, 2008 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
IN: prettyprint IN: prettyprint
USING: alien arrays generic generic.standard assocs io kernel USING: arrays generic generic.standard assocs io kernel
math namespaces sequences strings io.styles io.streams.string math namespaces sequences strings io.styles io.streams.string
vectors words prettyprint.backend prettyprint.sections vectors words prettyprint.backend prettyprint.sections
prettyprint.config sorting splitting math.parser vocabs prettyprint.config sorting splitting math.parser vocabs

View File

@ -1,6 +1,6 @@
! Copyright (C) 2003, 2008 Slava Pestov. ! Copyright (C) 2003, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays generic hashtables io kernel math assocs USING: arrays generic hashtables io kernel math assocs
namespaces sequences strings io.styles vectors words namespaces sequences strings io.styles vectors words
prettyprint.config splitting classes continuations prettyprint.config splitting classes continuations
io.streams.nested accessors ; io.streams.nested accessors ;

View File

@ -76,10 +76,7 @@ ARTICLE: "sequences-reshape" "Reshaping sequences"
{ $subsection reversed } { $subsection reversed }
{ $subsection <reversed> } { $subsection <reversed> }
"Transposing a matrix:" "Transposing a matrix:"
{ $subsection flip } { $subsection flip } ;
"A " { $emphasis "column" } " presents a column of a matrix represented as a sequence of rows:"
{ $subsection column }
{ $subsection <column> } ;
ARTICLE: "sequences-appending" "Appending sequences" ARTICLE: "sequences-appending" "Appending sequences"
{ $subsection append } { $subsection append }
@ -785,23 +782,6 @@ HELP: <slice>
{ <slice> subseq } related-words { <slice> subseq } related-words
HELP: column
{ $class-description "A virtual sequence which presents a fixed column of a matrix represented as a sequence of rows. New instances can be created by calling " { $link <column> } "." } ;
HELP: <column> ( seq n -- column )
{ $values { "seq" sequence } { "n" "a non-negative integer" } { "column" column } }
{ $description "Outputs a new virtual sequence which presents a fixed column of a matrix represented as a sequence of rows." "The " { $snippet "i" } "th element of a column is the " { $snippet "n" } "th element of the " { $snippet "i" } "th element of" { $snippet "seq" } ". Every element of " { $snippet "seq" } " must be a sequence, and all sequences must have equal length." }
{ $examples
{ $example
"USING: arrays prettyprint sequences ;"
"{ { 1 2 3 } { 4 5 6 } { 7 8 9 } } 0 <column> >array ."
"{ 1 4 7 }"
}
}
{ $notes
"In the same sense that " { $link <reversed> } " is a virtual variant of " { $link reverse } ", " { $link <column> } " is a virtual variant of " { $snippet "swap [ nth ] curry map" } "."
} ;
HELP: repetition HELP: repetition
{ $class-description "A virtual sequence consisting of " { $link repetition-elt } " repeated " { $link repetition-len } " times. Repetitions are created by calling " { $link <repetition> } "." } ; { $class-description "A virtual sequence consisting of " { $link repetition-elt } " repeated " { $link repetition-len } " times. Repetitions are created by calling " { $link <repetition> } "." } ;

View File

@ -224,13 +224,6 @@ unit-test
[ V{ 1 2 3 } ] [ V{ 1 2 3 } ]
[ 3 V{ 1 3 2 } clone [ push-new ] keep ] unit-test [ 3 V{ 1 3 2 } clone [ push-new ] keep ] unit-test
! Columns
{ { 1 2 3 } { 4 5 6 } { 7 8 9 } } [ clone ] map "seq" set
[ { 1 4 7 } ] [ "seq" get 0 <column> >array ] unit-test
[ ] [ "seq" get 1 <column> [ sq ] change-each ] unit-test
[ { 4 25 64 } ] [ "seq" get 1 <column> >array ] unit-test
! erg's random tester found this one ! erg's random tester found this one
[ SBUF" 12341234" ] [ [ SBUF" 12341234" ] [
9 <sbuf> dup "1234" swap push-all dup dup swap push-all 9 <sbuf> dup "1234" swap push-all dup dup swap push-all

View File

@ -215,18 +215,6 @@ M: slice length dup slice-to swap slice-from - ;
INSTANCE: slice virtual-sequence INSTANCE: slice virtual-sequence
! A column of a matrix
TUPLE: column seq col ;
C: <column> column
M: column virtual-seq column-seq ;
M: column virtual@
dup column-col -rot column-seq nth bounds-check ;
M: column length column-seq length ;
INSTANCE: column virtual-sequence
! One element repeated many times ! One element repeated many times
TUPLE: repetition len elt ; TUPLE: repetition len elt ;
@ -703,5 +691,5 @@ PRIVATE>
: flip ( matrix -- newmatrix ) : flip ( matrix -- newmatrix )
dup empty? [ dup empty? [
dup [ length ] map infimum dup [ length ] map infimum
[ <column> dup like ] with map swap [ [ nth-unsafe ] with { } map-as ] curry { } map-as
] unless ; ] unless ;

View File

@ -150,18 +150,6 @@ ARTICLE: "syntax-byte-arrays" "Byte array syntax"
{ $subsection POSTPONE: B{ } { $subsection POSTPONE: B{ }
"Byte arrays are documented in " { $link "byte-arrays" } "." ; "Byte arrays are documented in " { $link "byte-arrays" } "." ;
ARTICLE: "syntax-bit-vectors" "Bit vector syntax"
{ $subsection POSTPONE: ?V{ }
"Bit vectors are documented in " { $link "bit-vectors" } "." ;
ARTICLE: "syntax-float-vectors" "Float vector syntax"
{ $subsection POSTPONE: FV{ }
"Float vectors are documented in " { $link "float-vectors" } "." ;
ARTICLE: "syntax-byte-vectors" "Byte vector syntax"
{ $subsection POSTPONE: BV{ }
"Byte vectors are documented in " { $link "byte-vectors" } "." ;
ARTICLE: "syntax-pathnames" "Pathname syntax" ARTICLE: "syntax-pathnames" "Pathname syntax"
{ $subsection POSTPONE: P" } { $subsection POSTPONE: P" }
"Pathnames are documented in " { $link "pathnames" } "." ; "Pathnames are documented in " { $link "pathnames" } "." ;
@ -182,9 +170,6 @@ $nl
{ $subsection "syntax-float-arrays" } { $subsection "syntax-float-arrays" }
{ $subsection "syntax-vectors" } { $subsection "syntax-vectors" }
{ $subsection "syntax-sbufs" } { $subsection "syntax-sbufs" }
{ $subsection "syntax-bit-vectors" }
{ $subsection "syntax-byte-vectors" }
{ $subsection "syntax-float-vectors" }
{ $subsection "syntax-hashtables" } { $subsection "syntax-hashtables" }
{ $subsection "syntax-tuples" } { $subsection "syntax-tuples" }
{ $subsection "syntax-pathnames" } ; { $subsection "syntax-pathnames" } ;
@ -291,30 +276,12 @@ HELP: B{
{ $description "Marks the beginning of a literal byte array. Literal byte arrays are terminated by " { $link POSTPONE: } } "." } { $description "Marks the beginning of a literal byte array. Literal byte arrays are terminated by " { $link POSTPONE: } } "." }
{ $examples { $code "B{ 1 2 3 }" } } ; { $examples { $code "B{ 1 2 3 }" } } ;
HELP: BV{
{ $syntax "BV{ elements... }" }
{ $values { "elements" "a list of bytes" } }
{ $description "Marks the beginning of a literal byte vector. Literal byte vectors are terminated by " { $link POSTPONE: } } "." }
{ $examples { $code "BV{ 1 2 3 12 }" } } ;
HELP: ?{ HELP: ?{
{ $syntax "?{ elements... }" } { $syntax "?{ elements... }" }
{ $values { "elements" "a list of booleans" } } { $values { "elements" "a list of booleans" } }
{ $description "Marks the beginning of a literal bit array. Literal bit arrays are terminated by " { $link POSTPONE: } } "." } { $description "Marks the beginning of a literal bit array. Literal bit arrays are terminated by " { $link POSTPONE: } } "." }
{ $examples { $code "?{ t f t }" } } ; { $examples { $code "?{ t f t }" } } ;
HELP: ?V{
{ $syntax "?V{ elements... }" }
{ $values { "elements" "a list of booleans" } }
{ $description "Marks the beginning of a literal bit vector. Literal bit vectors are terminated by " { $link POSTPONE: } } "." }
{ $examples { $code "?V{ t f t }" } } ;
HELP: FV{
{ $syntax "FV{ elements... }" }
{ $values { "elements" "a list of real numbers" } }
{ $description "Marks the beginning of a literal float vector. Literal float vectors are terminated by " { $link POSTPONE: } } "." }
{ $examples { $code "FV{ 1.0 2.0 3.0 }" } } ;
HELP: F{ HELP: F{
{ $syntax "F{ elements... }" } { $syntax "F{ elements... }" }
{ $values { "elements" "a list of real numbers" } } { $values { "elements" "a list of real numbers" } }

View File

@ -1,10 +1,10 @@
! Copyright (C) 2004, 2008 Slava Pestov. ! Copyright (C) 2004, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien arrays bit-arrays bit-vectors byte-arrays USING: alien arrays bit-arrays byte-arrays
byte-vectors definitions generic hashtables kernel math definitions generic hashtables kernel math
namespaces parser sequences strings sbufs vectors words namespaces parser sequences strings sbufs vectors words
quotations io assocs splitting classes.tuple generic.standard quotations io assocs splitting classes.tuple generic.standard
generic.math classes io.files vocabs float-arrays float-vectors generic.math classes io.files vocabs float-arrays
classes.union classes.mixin classes.predicate classes.singleton classes.union classes.mixin classes.predicate classes.singleton
compiler.units combinators debugger ; compiler.units combinators debugger ;
IN: bootstrap.syntax IN: bootstrap.syntax
@ -79,11 +79,8 @@ IN: bootstrap.syntax
"{" [ \ } [ >array ] parse-literal ] define-syntax "{" [ \ } [ >array ] parse-literal ] define-syntax
"V{" [ \ } [ >vector ] parse-literal ] define-syntax "V{" [ \ } [ >vector ] parse-literal ] define-syntax
"B{" [ \ } [ >byte-array ] parse-literal ] define-syntax "B{" [ \ } [ >byte-array ] parse-literal ] define-syntax
"BV{" [ \ } [ >byte-vector ] parse-literal ] define-syntax
"?{" [ \ } [ >bit-array ] parse-literal ] define-syntax "?{" [ \ } [ >bit-array ] parse-literal ] define-syntax
"?V{" [ \ } [ >bit-vector ] parse-literal ] define-syntax
"F{" [ \ } [ >float-array ] parse-literal ] define-syntax "F{" [ \ } [ >float-array ] parse-literal ] define-syntax
"FV{" [ \ } [ >float-vector ] parse-literal ] define-syntax
"H{" [ \ } [ >hashtable ] parse-literal ] define-syntax "H{" [ \ } [ >hashtable ] parse-literal ] define-syntax
"T{" [ \ } [ >tuple ] parse-literal ] define-syntax "T{" [ \ } [ >tuple ] parse-literal ] define-syntax
"W{" [ \ } [ first <wrapper> ] parse-literal ] define-syntax "W{" [ \ } [ first <wrapper> ] parse-literal ] define-syntax

View File

@ -26,7 +26,7 @@ ARTICLE: "threads-yield" "Yielding and suspending threads"
{ $subsection resume } { $subsection resume }
{ $subsection resume-with } ; { $subsection resume-with } ;
ARTICLE: "thread-state" "Thread-local state" ARTICLE: "thread-state" "Thread-local state and variables"
"Threads form a class of objects:" "Threads form a class of objects:"
{ $subsection thread } { $subsection thread }
"The current thread:" "The current thread:"
@ -36,6 +36,8 @@ ARTICLE: "thread-state" "Thread-local state"
{ $subsection tget } { $subsection tget }
{ $subsection tset } { $subsection tset }
{ $subsection tchange } { $subsection tchange }
"Each thread has its own independent set of thread-local variables and newly-spawned threads begin with an empty set."
$nl
"Global hashtable of all threads, keyed by " { $link thread-id } ":" "Global hashtable of all threads, keyed by " { $link thread-id } ":"
{ $subsection threads } { $subsection threads }
"Threads have an identity independent of continuations. If a continuation is refied in one thread and then resumed in another thread, the code running in that continuation will observe a change in the value output by " { $link self } "." ; "Threads have an identity independent of continuations. If a continuation is refied in one thread and then resumed in another thread, the code running in that continuation will observe a change in the value output by " { $link self } "." ;

View File

@ -1,4 +1,5 @@
USING: namespaces io tools.test threads kernel ; USING: namespaces io tools.test threads kernel
concurrency.combinators math ;
IN: threads.tests IN: threads.tests
3 "x" set 3 "x" set
@ -16,3 +17,13 @@ yield
] unit-test ] unit-test
[ f ] [ f get-global ] unit-test [ f ] [ f get-global ] unit-test
{ { 0 3 6 9 12 15 18 21 24 27 } } [
10 [
0 "i" tset
[
"i" [ yield 3 + ] tchange
] times yield
"i" tget
] parallel-map
] unit-test

View File

@ -27,7 +27,7 @@ mailbox variables sleep-entry ;
tnamespace set-at ; tnamespace set-at ;
: tchange ( key quot -- ) : tchange ( key quot -- )
tnamespace change-at ; inline tnamespace swap change-at ; inline
: threads 41 getenv ; : threads 41 getenv ;

View File

@ -0,0 +1,55 @@
USING: kernel math accessors prettyprint io locals sequences
math.ranges ;
IN: benchmark.binary-trees
TUPLE: tree-node item left right ;
C: <tree-node> tree-node
: bottom-up-tree ( item depth -- tree )
dup 0 > [
1 -
[ drop ]
[ >r 2 * 1 - r> bottom-up-tree ]
[ >r 2 * r> bottom-up-tree ] 2tri
] [
drop f f
] if <tree-node> ;
GENERIC: item-check ( node -- n )
M: tree-node item-check
[ item>> ] [ left>> ] [ right>> ] tri [ item-check ] bi@ - + ;
M: f item-check drop 0 ;
: min-depth 4 ; inline
: stretch-tree ( max-depth -- )
1 + 0 over bottom-up-tree item-check
[ "stretch tree of depth " write pprint ]
[ "\t check: " write . ] bi* ;
:: long-lived-tree ( max-depth -- )
0 max-depth bottom-up-tree
min-depth max-depth 2 <range> [| depth |
max-depth depth - min-depth + 2^ [
[1,b] 0 [
dup neg
[ depth bottom-up-tree item-check + ] bi@
] reduce
]
[ 2 * ] bi
pprint "\t trees of depth " write depth pprint
"\t check: " write .
] each
"long lived tree of depth " write max-depth pprint
"\t check: " write item-check . ;
: binary-trees ( n -- )
min-depth 2 + max [ stretch-tree ] [ long-lived-tree ] bi ;
: binary-trees-main ( -- )
16 binary-trees ;

View File

@ -1,4 +1,4 @@
USING: namespaces math sequences splitting kernel ; USING: namespaces math sequences splitting kernel columns ;
IN: benchmark.dispatch2 IN: benchmark.dispatch2
: sequences : sequences

View File

@ -1,5 +1,5 @@
USING: sequences math mirrors splitting kernel namespaces USING: sequences math mirrors splitting kernel namespaces
assocs alien.syntax ; assocs alien.syntax columns ;
IN: benchmark.dispatch3 IN: benchmark.dispatch3
GENERIC: g ( obj -- str ) GENERIC: g ( obj -- str )

View File

@ -1,38 +1,37 @@
USING: math kernel hints prettyprint io combinators ;
IN: benchmark.recursive IN: benchmark.recursive
USING: math kernel hints prettyprint io ;
: fib ( m -- n ) : fib ( m -- n )
dup 2 < [ drop 1 ] [ dup 1 - fib swap 2 - fib + ] if ; dup 2 < [ drop 1 ] [ [ 1 - fib ] [ 2 - fib ] bi + ] if ;
inline
: ack ( m n -- x ) : ack ( m n -- x )
over zero? [ {
nip 1+ { [ over zero? ] [ nip 1+ ] }
] [ { [ dup zero? ] [ drop 1- 1 ack ] }
dup zero? [ [ [ drop 1- ] [ 1- ack ] 2bi ack ]
drop 1- 1 ack } cond ; inline
] [
dupd 1- ack >r 1- r> ack
] if
] if ;
: tak ( x y z -- t ) : tak ( x y z -- t )
2over swap < [ 2over <= [
[ rot 1- -rot tak ] 3keep
[ -rot 1- -rot tak ] 3keep
1- -rot tak
tak
] [
2nip 2nip
] if ; ] [
[ rot 1- -rot tak ]
[ -rot 1- -rot tak ]
[ 1- -rot tak ]
3tri
tak
] if ; inline
: recursive ( n -- ) : recursive ( n -- )
3 over ack . flush [ 3 swap ack . flush ]
dup 27.0 + fib . flush [ 27.0 + fib . flush ]
1- [ 1- [ 3 * ] [ 2 * ] [ ] tri tak . flush ] tri
dup 3 * over 2 * rot tak . flush
3 fib . flush 3 fib . flush
3.0 2.0 1.0 tak . flush ; 3.0 2.0 1.0 tak . flush ;
HINTS: recursive fixnum ;
: recursive-main 11 recursive ; : recursive-main 11 recursive ;
MAIN: recursive-main MAIN: recursive-main

View File

@ -1,48 +1,44 @@
! Factor port of ! Factor port of
! http://shootout.alioth.debian.org/gp4/benchmark.php?test=spectralnorm&lang=all ! http://shootout.alioth.debian.org/gp4/benchmark.php?test=spectralnorm&lang=all
USING: float-arrays kernel math math.functions math.vectors USING: float-arrays kernel math math.functions math.vectors
sequences sequences.private prettyprint words tools.time hints ; sequences sequences.private prettyprint words
hints locals ;
IN: benchmark.spectral-norm IN: benchmark.spectral-norm
: fast-truncate >fixnum >float ; inline :: inner-loop ( u n quot -- seq )
n [| i |
n 0.0 [| j |
u i j quot call +
] reduce
] F{ } map-as ; inline
: eval-A ( i j -- n ) : eval-A ( i j -- n )
[ >float ] bi@ [ >float ] bi@
dupd + dup 1+ * 2 /f fast-truncate + 1+ [ drop ] [ + [ ] [ 1 + ] bi * 0.5 * ] 2bi
recip ; inline + 1 + recip ; inline
: (eval-A-times-u) ( u i j -- x ) : (eval-A-times-u) ( u i j -- x )
tuck eval-A >r swap nth-unsafe r> * ; inline tuck [ swap nth-unsafe ] [ eval-A ] 2bi* * ; inline
: eval-A-times-u ( n u -- seq ) : eval-A-times-u ( n u -- seq )
over [ [ (eval-A-times-u) ] inner-loop ; inline
pick 0.0 [
swap >r >r 2dup r> (eval-A-times-u) r> +
] reduce nip
] F{ } map-as 2nip ; inline
: (eval-At-times-u) ( u i j -- x ) : (eval-At-times-u) ( u i j -- x )
tuck swap eval-A >r swap nth-unsafe r> * ; inline tuck [ swap nth-unsafe ] [ swap eval-A ] 2bi* * ; inline
: eval-At-times-u ( n u -- seq ) : eval-At-times-u ( u n -- seq )
over [ [ (eval-At-times-u) ] inner-loop ; inline
pick 0.0 [
swap >r >r 2dup r> (eval-At-times-u) r> +
] reduce nip
] F{ } map-as 2nip ; inline
: eval-AtA-times-u ( n u -- seq ) : eval-AtA-times-u ( u n -- seq )
dupd eval-A-times-u eval-At-times-u ; inline [ eval-A-times-u ] [ eval-At-times-u ] bi ; inline
: u/v ( n -- u v ) :: u/v ( n -- u v )
dup 1.0 <float-array> dup n 1.0 <float-array> dup
10 [ 10 [
drop drop
dupd eval-AtA-times-u n eval-AtA-times-u
2dup eval-AtA-times-u [ n eval-AtA-times-u ] keep
swap ] times ; inline
] times
rot drop ; inline
: spectral-norm ( n -- norm ) : spectral-norm ( n -- norm )
u/v [ v. ] keep norm-sq /f sqrt ; u/v [ v. ] keep norm-sq /f sqrt ;
@ -50,6 +46,6 @@ IN: benchmark.spectral-norm
HINTS: spectral-norm fixnum ; HINTS: spectral-norm fixnum ;
: spectral-norm-main ( -- ) : spectral-norm-main ( -- )
2000 spectral-norm . ; 5500 spectral-norm . ;
MAIN: spectral-norm-main MAIN: spectral-norm-main

View File

@ -3,7 +3,7 @@ bit-vectors.private combinators ;
IN: bit-vectors IN: bit-vectors
ARTICLE: "bit-vectors" "Bit vectors" ARTICLE: "bit-vectors" "Bit vectors"
"A bit vector is a resizable mutable sequence of bits. The literal syntax is covered in " { $link "syntax-bit-vectors" } ". Bit vector words are found in the " { $vocab-link "bit-vectors" } " vocabulary." "A bit vector is a resizable mutable sequence of bits. Bit vector words are found in the " { $vocab-link "bit-vectors" } " vocabulary."
$nl $nl
"Bit vectors form a class:" "Bit vectors form a class:"
{ $subsection bit-vector } { $subsection bit-vector }
@ -11,13 +11,15 @@ $nl
"Creating bit vectors:" "Creating bit vectors:"
{ $subsection >bit-vector } { $subsection >bit-vector }
{ $subsection <bit-vector> } { $subsection <bit-vector> }
"Literal syntax:"
{ $subsection POSTPONE: ?V{ }
"If you don't care about initial capacity, a more elegant way to create a new bit vector is to write:" "If you don't care about initial capacity, a more elegant way to create a new bit vector is to write:"
{ $code "?V{ } clone" } ; { $code "?V{ } clone" } ;
ABOUT: "bit-vectors" ABOUT: "bit-vectors"
HELP: bit-vector HELP: bit-vector
{ $description "The class of resizable bit vectors. See " { $link "syntax-bit-vectors" } " for syntax and " { $link "bit-vectors" } " for general information." } ; { $description "The class of resizable bit vectors. See " { $link "bit-vectors" } " for information." } ;
HELP: <bit-vector> HELP: <bit-vector>
{ $values { "n" "a positive integer specifying initial capacity" } { "bit-vector" bit-vector } } { $values { "n" "a positive integer specifying initial capacity" } { "bit-vector" bit-vector } }
@ -31,3 +33,10 @@ HELP: bit-array>vector
{ $values { "bit-array" "an array" } { "length" "a non-negative integer" } { "bit-vector" bit-vector } } { $values { "bit-array" "an array" } { "length" "a non-negative integer" } { "bit-vector" bit-vector } }
{ $description "Creates a new bit vector using the array for underlying storage with the specified initial length." } { $description "Creates a new bit vector using the array for underlying storage with the specified initial length." }
{ $warning "This word is in the " { $vocab-link "bit-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >bit-vector } " instead." } ; { $warning "This word is in the " { $vocab-link "bit-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >bit-vector } " instead." } ;
HELP: ?V{
{ $syntax "?V{ elements... }" }
{ $values { "elements" "a list of booleans" } }
{ $description "Marks the beginning of a literal bit vector. Literal bit vectors are terminated by " { $link POSTPONE: } } "." }
{ $examples { $code "?V{ t f t }" } } ;

View File

@ -1,9 +1,20 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays kernel kernel.private math sequences USING: arrays kernel kernel.private math sequences
sequences.private growable bit-arrays ; sequences.private growable bit-arrays prettyprint.backend
parser accessors ;
IN: bit-vectors IN: bit-vectors
TUPLE: bit-vector underlying fill ;
M: bit-vector underlying underlying>> { bit-array } declare ;
M: bit-vector set-underlying (>>underlying) ;
M: bit-vector length fill>> { array-capacity } declare ;
M: bit-vector set-fill (>>fill) ;
<PRIVATE <PRIVATE
: bit-array>vector ( bit-array length -- bit-vector ) : bit-array>vector ( bit-array length -- bit-vector )
@ -14,7 +25,8 @@ PRIVATE>
: <bit-vector> ( n -- bit-vector ) : <bit-vector> ( n -- bit-vector )
<bit-array> 0 bit-array>vector ; inline <bit-array> 0 bit-array>vector ; inline
: >bit-vector ( seq -- bit-vector ) ?V{ } clone-like ; : >bit-vector ( seq -- bit-vector )
T{ bit-vector f ?{ } 0 } clone-like ;
M: bit-vector like M: bit-vector like
drop dup bit-vector? [ drop dup bit-vector? [
@ -31,3 +43,9 @@ M: bit-vector equal?
M: bit-array new-resizable drop <bit-vector> ; M: bit-array new-resizable drop <bit-vector> ;
INSTANCE: bit-vector growable INSTANCE: bit-vector growable
: ?V{ \ } [ >bit-vector ] parse-literal ; parsing
M: bit-vector >pprint-sequence ;
M: bit-vector pprint-delims drop \ ?V{ \ } ;

Some files were not shown because too many files have changed in this diff Show More