Merge commit 'slava/master'
commit
cb5c100f7c
|
@ -1,5 +1,5 @@
|
|||
USING: byte-arrays arrays help.syntax help.markup
|
||||
alien.syntax alien.c-types compiler definitions math libc
|
||||
alien.syntax compiler definitions math libc
|
||||
debugger parser io io.backend system bit-arrays float-arrays ;
|
||||
IN: alien
|
||||
|
||||
|
@ -156,36 +156,6 @@ ARTICLE: "aliens" "Alien addresses"
|
|||
$nl
|
||||
"Usually alien objects do not have to created and dereferenced directly; instead declaring C function parameters and return values as having a pointer type such as " { $snippet "void*" } " takes care of the details. See " { $link "c-types-specs" } "." ;
|
||||
|
||||
ARTICLE: "c-structs" "C structure types"
|
||||
"A " { $snippet "struct" } " in C is essentially a block of memory with the value of each structure field stored at a fixed offset from the start of the block. The C library interface provides some utilities to define words which read and write structure fields given a base address."
|
||||
{ $subsection POSTPONE: C-STRUCT: }
|
||||
"Great care must be taken when working with C structures since no type or bounds checking is possible."
|
||||
$nl
|
||||
"An example:"
|
||||
{ $code
|
||||
"C-STRUCT: XVisualInfo"
|
||||
" { \"Visual*\" \"visual\" }"
|
||||
" { \"VisualID\" \"visualid\" }"
|
||||
" { \"int\" \"screen\" }"
|
||||
" { \"uint\" \"depth\" }"
|
||||
" { \"int\" \"class\" }"
|
||||
" { \"ulong\" \"red_mask\" }"
|
||||
" { \"ulong\" \"green_mask\" }"
|
||||
" { \"ulong\" \"blue_mask\" }"
|
||||
" { \"int\" \"colormap_size\" }"
|
||||
" { \"int\" \"bits_per_rgb\" } ;"
|
||||
}
|
||||
"C structure objects can be allocated by calling " { $link <c-object> } " or " { $link malloc-object } "."
|
||||
$nl
|
||||
"Arrays of C structures can be created by calling " { $link <c-array> } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-STRUCT: } "." ;
|
||||
|
||||
ARTICLE: "c-unions" "C unions"
|
||||
"A " { $snippet "union" } " in C defines a type large enough to hold its largest member. This is usually used to allocate a block of memory which can hold one of several types of values."
|
||||
{ $subsection POSTPONE: C-UNION: }
|
||||
"C structure objects can be allocated by calling " { $link <c-object> } " or " { $link malloc-object } "."
|
||||
$nl
|
||||
"Arrays of C unions can be created by calling " { $link <c-array> } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-UNION: } "." ;
|
||||
|
||||
ARTICLE: "reading-writing-memory" "Reading and writing memory directly"
|
||||
"Numerical values can be read from memory addresses and converted to Factor objects using the various typed memory accessor words:"
|
||||
{ $subsection alien-signed-1 }
|
||||
|
@ -253,211 +223,6 @@ $nl
|
|||
{ $subsection dlsym }
|
||||
{ $subsection dlclose } ;
|
||||
|
||||
ARTICLE: "c-types-specs" "C type specifiers"
|
||||
"C types are identified by strings, and type names occur as parameters to the " { $link alien-invoke } ", " { $link alien-indirect } " and " { $link alien-callback } " words, as well as " { $link POSTPONE: C-STRUCT: } ", " { $link POSTPONE: C-UNION: } " and " { $link POSTPONE: TYPEDEF: } "."
|
||||
$nl
|
||||
"The following numerical types are available; a " { $snippet "u" } " prefix denotes an unsigned type:"
|
||||
{ $table
|
||||
{ "C type" "Notes" }
|
||||
{ { $snippet "char" } "always 1 byte" }
|
||||
{ { $snippet "uchar" } { } }
|
||||
{ { $snippet "short" } "always 2 bytes" }
|
||||
{ { $snippet "ushort" } { } }
|
||||
{ { $snippet "int" } "always 4 bytes" }
|
||||
{ { $snippet "uint" } { } }
|
||||
{ { $snippet "long" } { "same size as CPU word size and " { $snippet "void*" } ", except on 64-bit Windows, where it is 4 bytes" } }
|
||||
{ { $snippet "ulong" } { } }
|
||||
{ { $snippet "longlong" } "always 8 bytes" }
|
||||
{ { $snippet "ulonglong" } { } }
|
||||
{ { $snippet "float" } { } }
|
||||
{ { $snippet "double" } { "same format as " { $link float } " objects" } }
|
||||
}
|
||||
"When making alien calls, Factor numbers are converted to and from the above types in a canonical way. Converting a Factor number to a C value may result in a loss of precision."
|
||||
$nl
|
||||
"Pointer types are specified by suffixing a C type with " { $snippet "*" } ", for example " { $snippet "float*" } ". One special case is " { $snippet "void*" } ", which denotes a generic pointer; " { $snippet "void" } " by itself is not a valid C type specifier. With the exception of strings (see " { $link "c-strings" } "), all pointer types are identical to " { $snippet "void*" } " as far as the C library interface is concerned."
|
||||
$nl
|
||||
"Fixed-size array types are supported; the syntax consists of a C type name followed by dimension sizes in brackets; the following denotes a 3 by 4 array of integers:"
|
||||
{ $code "int[3][4]" }
|
||||
"Fixed-size arrays differ from pointers in that they are allocated inside structures and unions; however when used as function parameters they behave exactly like pointers and thus the dimensions only serve as documentation."
|
||||
$nl
|
||||
"Structure and union types are specified by the name of the structure or union." ;
|
||||
|
||||
ARTICLE: "c-byte-arrays" "Passing data in byte arrays"
|
||||
"Instances of the " { $link byte-array } ", " { $link bit-array } " and " { $link float-array } " class can be passed to C functions; the C function receives a pointer to the first element of the array."
|
||||
$nl
|
||||
"Byte arrays can be allocated directly with a byte count using the " { $link <byte-array> } " word. However in most cases, instead of computing a size in bytes directly, it is easier to use a higher-level word which expects C type and outputs a byte array large enough to hold that type:"
|
||||
{ $subsection <c-object> }
|
||||
{ $subsection <c-array> }
|
||||
{ $warning
|
||||
"The Factor garbage collector can move byte arrays around, and it is only safe to pass byte arrays to C functions if the function does not store a pointer to the byte array in some global structure, or retain it in any way after returning."
|
||||
$nl
|
||||
"Long-lived data for use by C libraries can be allocated manually, just as when programming in C. See " { $link "malloc" } "." }
|
||||
{ $see-also "c-arrays" } ;
|
||||
|
||||
ARTICLE: "malloc" "Manual memory management"
|
||||
"Sometimes data passed to C functions must be allocated at a fixed address, and so garbage collector managed byte arrays cannot be used. See the warning at the bottom of " { $link "c-byte-arrays" } " for a description of when this is the case."
|
||||
$nl
|
||||
"Allocating a C datum with a fixed address:"
|
||||
{ $subsection malloc-object }
|
||||
{ $subsection malloc-array }
|
||||
{ $subsection malloc-byte-array }
|
||||
"There is a set of words in the " { $vocab-link "libc" } " vocabulary which directly call C standard library memory management functions:"
|
||||
{ $subsection malloc }
|
||||
{ $subsection calloc }
|
||||
{ $subsection realloc }
|
||||
"The return value of the above three words must always be checked for a memory allocation failure:"
|
||||
{ $subsection check-ptr }
|
||||
"You must always free pointers returned by any of the above words when the block of memory is no longer in use:"
|
||||
{ $subsection free }
|
||||
"You can unsafely copy a range of bytes from one memory location to another:"
|
||||
{ $subsection memcpy }
|
||||
"A wrapper for temporarily allocating a block of memory:"
|
||||
{ $subsection with-malloc } ;
|
||||
|
||||
ARTICLE: "c-strings" "C strings"
|
||||
"The C library interface defines two types of C strings:"
|
||||
{ $table
|
||||
{ "C type" "Notes" }
|
||||
{ { $snippet "char*" } "8-bit per character null-terminated ASCII" }
|
||||
{ { $snippet "ushort*" } "16-bit per character null-terminated UCS-2" }
|
||||
}
|
||||
"Passing a Factor string to a C function expecting a C string allocates a " { $link byte-array } " in the Factor heap; the string is then converted to the requested format and a raw pointer is passed to the function. If the conversion fails, for example if the string contains null bytes or characters with values higher than 255, a " { $link c-string-error. } " is thrown."
|
||||
"Sometimes a C function has a parameter type of " { $snippet "void*" } ", and various data types, among them strings, can be passed in. In this case, strings are not automatically converted to aliens, and instead you must call one of these words:"
|
||||
{ $subsection string>char-alien }
|
||||
{ $subsection string>u16-alien }
|
||||
{ $subsection malloc-char-string }
|
||||
{ $subsection malloc-u16-string }
|
||||
"The first two allocate " { $link byte-array } "s, and the latter allocates manually-managed memory which is not moved by the garbage collector and has to be explicitly freed by calling " { $link free } "."
|
||||
$nl
|
||||
"Finally, a set of words can be used to read and write " { $snippet "char*" } " and " { $snippet "ushort*" } " strings at arbitrary addresses:"
|
||||
{ $subsection alien>char-string }
|
||||
{ $subsection alien>u16-string }
|
||||
{ $subsection memory>string }
|
||||
{ $subsection string>memory } ;
|
||||
|
||||
ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays"
|
||||
"Each primitive C type has a pair of words, " { $snippet ">" { $emphasis "type" } "-array" } " and " { $snippet { $emphasis "type" } "-array>" } ", for converting an array of Factor objects to and from a " { $link byte-array } " of C values. This set of words consists of:"
|
||||
{ $subsection >c-bool-array }
|
||||
{ $subsection >c-char-array }
|
||||
{ $subsection >c-double-array }
|
||||
{ $subsection >c-float-array }
|
||||
{ $subsection >c-int-array }
|
||||
{ $subsection >c-long-array }
|
||||
{ $subsection >c-longlong-array }
|
||||
{ $subsection >c-short-array }
|
||||
{ $subsection >c-uchar-array }
|
||||
{ $subsection >c-uint-array }
|
||||
{ $subsection >c-ulong-array }
|
||||
{ $subsection >c-ulonglong-array }
|
||||
{ $subsection >c-ushort-array }
|
||||
{ $subsection >c-void*-array }
|
||||
{ $subsection c-bool-array> }
|
||||
{ $subsection c-char*-array> }
|
||||
{ $subsection c-char-array> }
|
||||
{ $subsection c-double-array> }
|
||||
{ $subsection c-float-array> }
|
||||
{ $subsection c-int-array> }
|
||||
{ $subsection c-long-array> }
|
||||
{ $subsection c-longlong-array> }
|
||||
{ $subsection c-short-array> }
|
||||
{ $subsection c-uchar-array> }
|
||||
{ $subsection c-uint-array> }
|
||||
{ $subsection c-ulong-array> }
|
||||
{ $subsection c-ulonglong-array> }
|
||||
{ $subsection c-ushort*-array> }
|
||||
{ $subsection c-ushort-array> }
|
||||
{ $subsection c-void*-array> } ;
|
||||
|
||||
ARTICLE: "c-arrays-get/set" "Reading and writing elements in C arrays"
|
||||
"Each C type has a pair of words, " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } ", for reading and writing values of this type stored in an array. This set of words includes but is not limited to:"
|
||||
{ $subsection char-nth }
|
||||
{ $subsection set-char-nth }
|
||||
{ $subsection uchar-nth }
|
||||
{ $subsection set-uchar-nth }
|
||||
{ $subsection short-nth }
|
||||
{ $subsection set-short-nth }
|
||||
{ $subsection ushort-nth }
|
||||
{ $subsection set-ushort-nth }
|
||||
{ $subsection int-nth }
|
||||
{ $subsection set-int-nth }
|
||||
{ $subsection uint-nth }
|
||||
{ $subsection set-uint-nth }
|
||||
{ $subsection long-nth }
|
||||
{ $subsection set-long-nth }
|
||||
{ $subsection ulong-nth }
|
||||
{ $subsection set-ulong-nth }
|
||||
{ $subsection longlong-nth }
|
||||
{ $subsection set-longlong-nth }
|
||||
{ $subsection ulonglong-nth }
|
||||
{ $subsection set-ulonglong-nth }
|
||||
{ $subsection float-nth }
|
||||
{ $subsection set-float-nth }
|
||||
{ $subsection double-nth }
|
||||
{ $subsection set-double-nth }
|
||||
{ $subsection void*-nth }
|
||||
{ $subsection set-void*-nth }
|
||||
{ $subsection char*-nth }
|
||||
{ $subsection ushort*-nth } ;
|
||||
|
||||
ARTICLE: "c-arrays" "C arrays"
|
||||
"C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "."
|
||||
$nl
|
||||
"C type specifiers for array types are documented in " { $link "c-types-specs" } "."
|
||||
{ $subsection "c-arrays-factor" }
|
||||
{ $subsection "c-arrays-get/set" } ;
|
||||
|
||||
ARTICLE: "c-out-params" "Output parameters in C"
|
||||
"A frequently-occurring idiom in C code is the \"out parameter\". If a C function returns more than one value, the caller passes pointers of the correct type, and the C function writes its return values to those locations."
|
||||
$nl
|
||||
"Each numerical C type, together with " { $snippet "void*" } ", has an associated " { $emphasis "out parameter constructor" } " word which takes a Factor object as input, constructs a byte array of the correct size, and converts the Factor object to a C value stored into the byte array:"
|
||||
{ $subsection <char> }
|
||||
{ $subsection <uchar> }
|
||||
{ $subsection <short> }
|
||||
{ $subsection <ushort> }
|
||||
{ $subsection <int> }
|
||||
{ $subsection <uint> }
|
||||
{ $subsection <long> }
|
||||
{ $subsection <ulong> }
|
||||
{ $subsection <longlong> }
|
||||
{ $subsection <ulonglong> }
|
||||
{ $subsection <float> }
|
||||
{ $subsection <double> }
|
||||
{ $subsection <void*> }
|
||||
"You call the out parameter constructor with the required initial value, then pass the byte array to the C function, which receives a pointer to the start of the byte array's data area. The C function then returns, leaving the result in the byte array; you read it back using the next set of words:"
|
||||
{ $subsection *char }
|
||||
{ $subsection *uchar }
|
||||
{ $subsection *short }
|
||||
{ $subsection *ushort }
|
||||
{ $subsection *int }
|
||||
{ $subsection *uint }
|
||||
{ $subsection *long }
|
||||
{ $subsection *ulong }
|
||||
{ $subsection *longlong }
|
||||
{ $subsection *ulonglong }
|
||||
{ $subsection *float }
|
||||
{ $subsection *double }
|
||||
{ $subsection *void* }
|
||||
{ $subsection *char* }
|
||||
{ $subsection *ushort* }
|
||||
"Note that while structure and union types do not get these words defined for them, there is no loss of generality since " { $link <void*> } " and " { $link *void* } " may be used." ;
|
||||
|
||||
ARTICLE: "c-data" "Passing data between Factor and C"
|
||||
"Two defining characteristics of Factor are dynamic typing and automatic memory management, which are somewhat incompatible with the machine-level data model exposed by C. Factor's C library interface defines its own set of C data types, distinct from Factor language types, together with automatic conversion between Factor values and C types. For example, C integer types must be declared and are fixed-width, whereas Factor supports arbitrary-precision integers. Also Factor's garbage collector can move objects in memory, which means that special support has to be provided for passing blocks of memory to C code."
|
||||
{ $subsection "c-types-specs" }
|
||||
{ $subsection "c-byte-arrays" }
|
||||
{ $subsection "malloc" }
|
||||
{ $subsection "c-strings" }
|
||||
{ $subsection "c-arrays" }
|
||||
{ $subsection "c-out-params" }
|
||||
"C-style enumerated types are supported:"
|
||||
{ $subsection POSTPONE: C-ENUM: }
|
||||
"C types can be aliased for convenience and consitency with native library documentation:"
|
||||
{ $subsection POSTPONE: TYPEDEF: }
|
||||
"New C types can be defined:"
|
||||
{ $subsection "c-structs" }
|
||||
{ $subsection "c-unions" }
|
||||
{ $subsection "reading-writing-memory" } ;
|
||||
|
||||
ARTICLE: "embedding-api" "Factor embedding API"
|
||||
"The Factor embedding API is defined in " { $snippet "vm/master.h" } "."
|
||||
$nl
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
IN: alien.arrays
|
||||
USING: help.syntax help.markup byte-arrays alien.c-types ;
|
||||
|
||||
ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays"
|
||||
"Each primitive C type has a pair of words, " { $snippet ">" { $emphasis "type" } "-array" } " and " { $snippet { $emphasis "type" } "-array>" } ", for converting an array of Factor objects to and from a " { $link byte-array } " of C values. This set of words consists of:"
|
||||
{ $subsection >c-bool-array }
|
||||
{ $subsection >c-char-array }
|
||||
{ $subsection >c-double-array }
|
||||
{ $subsection >c-float-array }
|
||||
{ $subsection >c-int-array }
|
||||
{ $subsection >c-long-array }
|
||||
{ $subsection >c-longlong-array }
|
||||
{ $subsection >c-short-array }
|
||||
{ $subsection >c-uchar-array }
|
||||
{ $subsection >c-uint-array }
|
||||
{ $subsection >c-ulong-array }
|
||||
{ $subsection >c-ulonglong-array }
|
||||
{ $subsection >c-ushort-array }
|
||||
{ $subsection >c-void*-array }
|
||||
{ $subsection c-bool-array> }
|
||||
{ $subsection c-char*-array> }
|
||||
{ $subsection c-char-array> }
|
||||
{ $subsection c-double-array> }
|
||||
{ $subsection c-float-array> }
|
||||
{ $subsection c-int-array> }
|
||||
{ $subsection c-long-array> }
|
||||
{ $subsection c-longlong-array> }
|
||||
{ $subsection c-short-array> }
|
||||
{ $subsection c-uchar-array> }
|
||||
{ $subsection c-uint-array> }
|
||||
{ $subsection c-ulong-array> }
|
||||
{ $subsection c-ulonglong-array> }
|
||||
{ $subsection c-ushort*-array> }
|
||||
{ $subsection c-ushort-array> }
|
||||
{ $subsection c-void*-array> } ;
|
||||
|
||||
ARTICLE: "c-arrays-get/set" "Reading and writing elements in C arrays"
|
||||
"Each C type has a pair of words, " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } ", for reading and writing values of this type stored in an array. This set of words includes but is not limited to:"
|
||||
{ $subsection char-nth }
|
||||
{ $subsection set-char-nth }
|
||||
{ $subsection uchar-nth }
|
||||
{ $subsection set-uchar-nth }
|
||||
{ $subsection short-nth }
|
||||
{ $subsection set-short-nth }
|
||||
{ $subsection ushort-nth }
|
||||
{ $subsection set-ushort-nth }
|
||||
{ $subsection int-nth }
|
||||
{ $subsection set-int-nth }
|
||||
{ $subsection uint-nth }
|
||||
{ $subsection set-uint-nth }
|
||||
{ $subsection long-nth }
|
||||
{ $subsection set-long-nth }
|
||||
{ $subsection ulong-nth }
|
||||
{ $subsection set-ulong-nth }
|
||||
{ $subsection longlong-nth }
|
||||
{ $subsection set-longlong-nth }
|
||||
{ $subsection ulonglong-nth }
|
||||
{ $subsection set-ulonglong-nth }
|
||||
{ $subsection float-nth }
|
||||
{ $subsection set-float-nth }
|
||||
{ $subsection double-nth }
|
||||
{ $subsection set-double-nth }
|
||||
{ $subsection void*-nth }
|
||||
{ $subsection set-void*-nth }
|
||||
{ $subsection char*-nth }
|
||||
{ $subsection ushort*-nth } ;
|
||||
|
||||
ARTICLE: "c-arrays" "C arrays"
|
||||
"C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "."
|
||||
$nl
|
||||
"C type specifiers for array types are documented in " { $link "c-types-specs" } "."
|
||||
{ $subsection "c-arrays-factor" }
|
||||
{ $subsection "c-arrays-get/set" } ;
|
|
@ -1,8 +1,10 @@
|
|||
USING: alien alien.c-types help.syntax help.markup libc
|
||||
kernel.private byte-arrays math strings ;
|
||||
IN: alien.c-types
|
||||
USING: alien help.syntax help.markup libc kernel.private
|
||||
byte-arrays math strings hashtables alien.syntax
|
||||
bit-arrays float-arrays debugger ;
|
||||
|
||||
HELP: <c-type>
|
||||
{ $values { "type" "a hashtable" } }
|
||||
{ $values { "type" hashtable } }
|
||||
{ $description "Creates a prototypical C type. User code should use higher-level facilities to define C types; see " { $link "c-data" } "." } ;
|
||||
|
||||
HELP: no-c-type
|
||||
|
@ -14,12 +16,12 @@ HELP: c-types
|
|||
{ $var-description "Global variable holding a hashtable mapping C type names to C types. Use the " { $link c-type } " word to look up C types." } ;
|
||||
|
||||
HELP: c-type
|
||||
{ $values { "name" string } { "type" "a hashtable" } }
|
||||
{ $values { "name" string } { "type" hashtable } }
|
||||
{ $description "Looks up a C type by name." }
|
||||
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
|
||||
|
||||
HELP: heap-size
|
||||
{ $values { "type" string } { "size" "an integer" } }
|
||||
{ $values { "type" string } { "size" integer } }
|
||||
{ $description "Outputs the number of bytes needed for a heap-allocated value of this C type." }
|
||||
{ $examples
|
||||
"On a 32-bit system, you will get the following output:"
|
||||
|
@ -28,7 +30,7 @@ HELP: heap-size
|
|||
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
|
||||
|
||||
HELP: stack-size
|
||||
{ $values { "type" string } { "size" "an integer" } }
|
||||
{ $values { "type" string } { "size" integer } }
|
||||
{ $description "Outputs the number of bytes to reserve on the C stack by a value of this C type. In most cases this is equal to " { $link heap-size } ", except on some platforms where C structs are passed by invisible reference, in which case a C struct type only uses as much space as a pointer on the C stack." }
|
||||
{ $errors "Throws a " { $link no-c-type } " error if the type does not exist." } ;
|
||||
|
||||
|
@ -78,13 +80,31 @@ HELP: alien>u16-string ( c-ptr -- string )
|
|||
{ $values { "c-ptr" c-ptr } { "string" string } }
|
||||
{ $description "Reads a null-terminated UCS-2 string from the specified address." } ;
|
||||
|
||||
HELP: memory>string ( base len -- string )
|
||||
{ $values { "base" c-ptr } { "len" "a non-negative integer" } { "string" string } }
|
||||
{ $description "Reads " { $snippet "len" } " bytes starting from " { $snippet "base" } " and stores them in a new Factor string." } ;
|
||||
HELP: memory>byte-array ( base len -- string )
|
||||
{ $values { "base" 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." } ;
|
||||
|
||||
HELP: string>memory ( string base -- )
|
||||
HELP: memory>char-string ( base len -- string )
|
||||
{ $values { "base" c-ptr } { "len" "a non-negative integer" } { "string" string } }
|
||||
{ $description "Reads " { $snippet "len" } " bytes starting from " { $snippet "base" } " and stores them in a new string." } ;
|
||||
|
||||
HELP: memory>u16-string ( base len -- string )
|
||||
{ $values { "base" c-ptr } { "len" "a non-negative integer" } { "string" string } }
|
||||
{ $description "Reads " { $snippet "len" } " UCS2 characters starting from " { $snippet "base" } " and stores them in a new string." } ;
|
||||
|
||||
HELP: byte-array>memory ( string base -- )
|
||||
{ $values { "byte-array" byte-array } { "base" c-ptr } }
|
||||
{ $description "Writes a byte array to memory starting from the " { $snippet "base" } " address." }
|
||||
{ $warning "This word is unsafe. Improper use can corrupt memory." } ;
|
||||
|
||||
HELP: string>char-memory ( string base -- )
|
||||
{ $values { "string" string } { "base" c-ptr } }
|
||||
{ $description "Writes the string to memory starting from the " { $snippet "base" } " address." }
|
||||
{ $description "Writes a string to memory starting from the " { $snippet "base" } " address." }
|
||||
{ $warning "This word is unsafe. Improper use can corrupt memory." } ;
|
||||
|
||||
HELP: string>u16-memory ( string base -- )
|
||||
{ $values { "string" string } { "base" c-ptr } }
|
||||
{ $description "Writes a string to memory starting from the " { $snippet "base" } " address." }
|
||||
{ $warning "This word is unsafe. Improper use can corrupt memory." } ;
|
||||
|
||||
HELP: malloc-array
|
||||
|
@ -151,3 +171,143 @@ HELP: define-out
|
|||
{ $values { "name" "a word name" } { "vocab" "a vocabulary name" } }
|
||||
{ $description "Defines a word " { $snippet "<" { $emphasis "name" } ">" } " with stack effect " { $snippet "( value -- array )" } ". This word allocates a byte array large enough to hold a value with C type " { $snippet "name" } ", and writes the value at the top of the stack to the array." }
|
||||
{ $notes "This is an internal word called when defining C types, there is no need to call it on your own." } ;
|
||||
|
||||
ARTICLE: "c-out-params" "Output parameters in C"
|
||||
"A frequently-occurring idiom in C code is the \"out parameter\". If a C function returns more than one value, the caller passes pointers of the correct type, and the C function writes its return values to those locations."
|
||||
$nl
|
||||
"Each numerical C type, together with " { $snippet "void*" } ", has an associated " { $emphasis "out parameter constructor" } " word which takes a Factor object as input, constructs a byte array of the correct size, and converts the Factor object to a C value stored into the byte array:"
|
||||
{ $subsection <char> }
|
||||
{ $subsection <uchar> }
|
||||
{ $subsection <short> }
|
||||
{ $subsection <ushort> }
|
||||
{ $subsection <int> }
|
||||
{ $subsection <uint> }
|
||||
{ $subsection <long> }
|
||||
{ $subsection <ulong> }
|
||||
{ $subsection <longlong> }
|
||||
{ $subsection <ulonglong> }
|
||||
{ $subsection <float> }
|
||||
{ $subsection <double> }
|
||||
{ $subsection <void*> }
|
||||
"You call the out parameter constructor with the required initial value, then pass the byte array to the C function, which receives a pointer to the start of the byte array's data area. The C function then returns, leaving the result in the byte array; you read it back using the next set of words:"
|
||||
{ $subsection *char }
|
||||
{ $subsection *uchar }
|
||||
{ $subsection *short }
|
||||
{ $subsection *ushort }
|
||||
{ $subsection *int }
|
||||
{ $subsection *uint }
|
||||
{ $subsection *long }
|
||||
{ $subsection *ulong }
|
||||
{ $subsection *longlong }
|
||||
{ $subsection *ulonglong }
|
||||
{ $subsection *float }
|
||||
{ $subsection *double }
|
||||
{ $subsection *void* }
|
||||
{ $subsection *char* }
|
||||
{ $subsection *ushort* }
|
||||
"Note that while structure and union types do not get these words defined for them, there is no loss of generality since " { $link <void*> } " and " { $link *void* } " may be used." ;
|
||||
|
||||
ARTICLE: "c-types-specs" "C type specifiers"
|
||||
"C types are identified by strings, and type names occur as parameters to the " { $link alien-invoke } ", " { $link alien-indirect } " and " { $link alien-callback } " words, as well as " { $link POSTPONE: C-STRUCT: } ", " { $link POSTPONE: C-UNION: } " and " { $link POSTPONE: TYPEDEF: } "."
|
||||
$nl
|
||||
"The following numerical types are available; a " { $snippet "u" } " prefix denotes an unsigned type:"
|
||||
{ $table
|
||||
{ "C type" "Notes" }
|
||||
{ { $snippet "char" } "always 1 byte" }
|
||||
{ { $snippet "uchar" } { } }
|
||||
{ { $snippet "short" } "always 2 bytes" }
|
||||
{ { $snippet "ushort" } { } }
|
||||
{ { $snippet "int" } "always 4 bytes" }
|
||||
{ { $snippet "uint" } { } }
|
||||
{ { $snippet "long" } { "same size as CPU word size and " { $snippet "void*" } ", except on 64-bit Windows, where it is 4 bytes" } }
|
||||
{ { $snippet "ulong" } { } }
|
||||
{ { $snippet "longlong" } "always 8 bytes" }
|
||||
{ { $snippet "ulonglong" } { } }
|
||||
{ { $snippet "float" } { } }
|
||||
{ { $snippet "double" } { "same format as " { $link float } " objects" } }
|
||||
}
|
||||
"When making alien calls, Factor numbers are converted to and from the above types in a canonical way. Converting a Factor number to a C value may result in a loss of precision."
|
||||
$nl
|
||||
"Pointer types are specified by suffixing a C type with " { $snippet "*" } ", for example " { $snippet "float*" } ". One special case is " { $snippet "void*" } ", which denotes a generic pointer; " { $snippet "void" } " by itself is not a valid C type specifier. With the exception of strings (see " { $link "c-strings" } "), all pointer types are identical to " { $snippet "void*" } " as far as the C library interface is concerned."
|
||||
$nl
|
||||
"Fixed-size array types are supported; the syntax consists of a C type name followed by dimension sizes in brackets; the following denotes a 3 by 4 array of integers:"
|
||||
{ $code "int[3][4]" }
|
||||
"Fixed-size arrays differ from pointers in that they are allocated inside structures and unions; however when used as function parameters they behave exactly like pointers and thus the dimensions only serve as documentation."
|
||||
$nl
|
||||
"Structure and union types are specified by the name of the structure or union." ;
|
||||
|
||||
ARTICLE: "c-byte-arrays" "Passing data in byte arrays"
|
||||
"Instances of the " { $link byte-array } ", " { $link bit-array } " and " { $link float-array } " class can be passed to C functions; the C function receives a pointer to the first element of the array."
|
||||
$nl
|
||||
"Byte arrays can be allocated directly with a byte count using the " { $link <byte-array> } " word. However in most cases, instead of computing a size in bytes directly, it is easier to use a higher-level word which expects C type and outputs a byte array large enough to hold that type:"
|
||||
{ $subsection <c-object> }
|
||||
{ $subsection <c-array> }
|
||||
{ $warning
|
||||
"The Factor garbage collector can move byte arrays around, and it is only safe to pass byte arrays to C functions if the function does not store a pointer to the byte array in some global structure, or retain it in any way after returning."
|
||||
$nl
|
||||
"Long-lived data for use by C libraries can be allocated manually, just as when programming in C. See " { $link "malloc" } "." }
|
||||
{ $see-also "c-arrays" } ;
|
||||
|
||||
ARTICLE: "malloc" "Manual memory management"
|
||||
"Sometimes data passed to C functions must be allocated at a fixed address, and so garbage collector managed byte arrays cannot be used. See the warning at the bottom of " { $link "c-byte-arrays" } " for a description of when this is the case."
|
||||
$nl
|
||||
"Allocating a C datum with a fixed address:"
|
||||
{ $subsection malloc-object }
|
||||
{ $subsection malloc-array }
|
||||
{ $subsection malloc-byte-array }
|
||||
"There is a set of words in the " { $vocab-link "libc" } " vocabulary which directly call C standard library memory management functions:"
|
||||
{ $subsection malloc }
|
||||
{ $subsection calloc }
|
||||
{ $subsection realloc }
|
||||
"The return value of the above three words must always be checked for a memory allocation failure:"
|
||||
{ $subsection check-ptr }
|
||||
"You must always free pointers returned by any of the above words when the block of memory is no longer in use:"
|
||||
{ $subsection free }
|
||||
"You can unsafely copy a range of bytes from one memory location to another:"
|
||||
{ $subsection memcpy }
|
||||
"You can copy a range of bytes from memory into a byte array:"
|
||||
{ $subsection memory>byte-array }
|
||||
"You can copy a byte array to memory unsafely:"
|
||||
{ $subsection byte-array>memory }
|
||||
"A wrapper for temporarily allocating a block of memory:"
|
||||
{ $subsection with-malloc } ;
|
||||
|
||||
ARTICLE: "c-strings" "C strings"
|
||||
"The C library interface defines two types of C strings:"
|
||||
{ $table
|
||||
{ "C type" "Notes" }
|
||||
{ { $snippet "char*" } "8-bit per character null-terminated ASCII" }
|
||||
{ { $snippet "ushort*" } "16-bit per character null-terminated UCS-2" }
|
||||
}
|
||||
"Passing a Factor string to a C function expecting a C string allocates a " { $link byte-array } " in the Factor heap; the string is then converted to the requested format and a raw pointer is passed to the function. If the conversion fails, for example if the string contains null bytes or characters with values higher than 255, a " { $link c-string-error. } " is thrown."
|
||||
"Sometimes a C function has a parameter type of " { $snippet "void*" } ", and various data types, among them strings, can be passed in. In this case, strings are not automatically converted to aliens, and instead you must call one of these words:"
|
||||
{ $subsection string>char-alien }
|
||||
{ $subsection string>u16-alien }
|
||||
{ $subsection malloc-char-string }
|
||||
{ $subsection malloc-u16-string }
|
||||
"The first two allocate " { $link byte-array } "s, and the latter allocates manually-managed memory which is not moved by the garbage collector and has to be explicitly freed by calling " { $link free } "."
|
||||
$nl
|
||||
"Finally, a set of words can be used to read and write " { $snippet "char*" } " and " { $snippet "ushort*" } " strings at arbitrary addresses:"
|
||||
{ $subsection alien>char-string }
|
||||
{ $subsection alien>u16-string }
|
||||
{ $subsection memory>char-string }
|
||||
{ $subsection memory>u16-string }
|
||||
{ $subsection string>char-memory }
|
||||
{ $subsection string>u16-memory } ;
|
||||
|
||||
ARTICLE: "c-data" "Passing data between Factor and C"
|
||||
"Two defining characteristics of Factor are dynamic typing and automatic memory management, which are somewhat incompatible with the machine-level data model exposed by C. Factor's C library interface defines its own set of C data types, distinct from Factor language types, together with automatic conversion between Factor values and C types. For example, C integer types must be declared and are fixed-width, whereas Factor supports arbitrary-precision integers. Also Factor's garbage collector can move objects in memory, which means that special support has to be provided for passing blocks of memory to C code."
|
||||
{ $subsection "c-types-specs" }
|
||||
{ $subsection "c-byte-arrays" }
|
||||
{ $subsection "malloc" }
|
||||
{ $subsection "c-strings" }
|
||||
{ $subsection "c-arrays" }
|
||||
{ $subsection "c-out-params" }
|
||||
"C-style enumerated types are supported:"
|
||||
{ $subsection POSTPONE: C-ENUM: }
|
||||
"C types can be aliased for convenience and consitency with native library documentation:"
|
||||
{ $subsection POSTPONE: TYPEDEF: }
|
||||
"New C types can be defined:"
|
||||
{ $subsection "c-structs" }
|
||||
{ $subsection "c-unions" }
|
||||
{ $subsection "reading-writing-memory" } ;
|
||||
|
|
|
@ -138,6 +138,28 @@ M: c-type stack-size c-type-size ;
|
|||
: malloc-u16-string ( string -- alien )
|
||||
string>u16-alien malloc-byte-array ;
|
||||
|
||||
: memory>byte-array ( alien len -- byte-array )
|
||||
dup <byte-array> [ -rot memcpy ] keep ;
|
||||
|
||||
: memory>char-string ( alien len -- string )
|
||||
memory>byte-array >string ;
|
||||
|
||||
DEFER: c-ushort-array>
|
||||
|
||||
: memory>u16-string ( alien len -- string )
|
||||
[ memory>byte-array ] keep 2/ c-ushort-array> >string ;
|
||||
|
||||
: byte-array>memory ( byte-array base -- )
|
||||
swap dup length memcpy ;
|
||||
|
||||
: string>char-memory ( string base -- )
|
||||
>r >byte-array r> byte-array>memory ;
|
||||
|
||||
DEFER: >c-ushort-array
|
||||
|
||||
: string>u16-memory ( string base -- )
|
||||
>r >c-ushort-array r> byte-array>memory ;
|
||||
|
||||
: (define-nth) ( word type quot -- )
|
||||
>r heap-size [ rot * ] swap add* r> append define-inline ;
|
||||
|
||||
|
|
|
@ -1,6 +1,37 @@
|
|||
USING: alien.structs alien.c-types strings help.markup
|
||||
sequences io arrays ;
|
||||
IN: alien.structs
|
||||
USING: alien.c-types strings help.markup help.syntax
|
||||
alien.syntax sequences io arrays ;
|
||||
|
||||
M: string slot-specs c-type struct-type-fields ;
|
||||
|
||||
M: array ($instance) first ($instance) " array" write ;
|
||||
|
||||
ARTICLE: "c-structs" "C structure types"
|
||||
"A " { $snippet "struct" } " in C is essentially a block of memory with the value of each structure field stored at a fixed offset from the start of the block. The C library interface provides some utilities to define words which read and write structure fields given a base address."
|
||||
{ $subsection POSTPONE: C-STRUCT: }
|
||||
"Great care must be taken when working with C structures since no type or bounds checking is possible."
|
||||
$nl
|
||||
"An example:"
|
||||
{ $code
|
||||
"C-STRUCT: XVisualInfo"
|
||||
" { \"Visual*\" \"visual\" }"
|
||||
" { \"VisualID\" \"visualid\" }"
|
||||
" { \"int\" \"screen\" }"
|
||||
" { \"uint\" \"depth\" }"
|
||||
" { \"int\" \"class\" }"
|
||||
" { \"ulong\" \"red_mask\" }"
|
||||
" { \"ulong\" \"green_mask\" }"
|
||||
" { \"ulong\" \"blue_mask\" }"
|
||||
" { \"int\" \"colormap_size\" }"
|
||||
" { \"int\" \"bits_per_rgb\" } ;"
|
||||
}
|
||||
"C structure objects can be allocated by calling " { $link <c-object> } " or " { $link malloc-object } "."
|
||||
$nl
|
||||
"Arrays of C structures can be created by calling " { $link <c-array> } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-STRUCT: } "." ;
|
||||
|
||||
ARTICLE: "c-unions" "C unions"
|
||||
"A " { $snippet "union" } " in C defines a type large enough to hold its largest member. This is usually used to allocate a block of memory which can hold one of several types of values."
|
||||
{ $subsection POSTPONE: C-UNION: }
|
||||
"C structure objects can be allocated by calling " { $link <c-object> } " or " { $link malloc-object } "."
|
||||
$nl
|
||||
"Arrays of C unions can be created by calling " { $link <c-array> } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-UNION: } "." ;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
USING: alien alien.c-types alien.structs help.markup help.syntax ;
|
||||
IN: alien.syntax
|
||||
USE: alien.syntax.private
|
||||
USING: alien alien.c-types alien.structs alien.syntax.private
|
||||
help.markup help.syntax ;
|
||||
|
||||
HELP: DLL"
|
||||
{ $syntax "DLL\" path\"" }
|
||||
|
@ -88,8 +88,6 @@ HELP: typedef
|
|||
{ $description "Alises the C type " { $snippet "old" } " under the name " { $snippet "new" } "." }
|
||||
{ $notes "Using this word in the same source file which defines C bindings can cause problems, because words are compiled before top-level forms are run. Use the " { $link POSTPONE: TYPEDEF: } " word instead." } ;
|
||||
|
||||
{ typedef POSTPONE: TYPEDEF: POSTPONE: TYPEDEF-IF: } related-words
|
||||
{ POSTPONE: TYPEDEF: typedef POSTPONE: TYPEDEF-IF: } related-words
|
||||
{ POSTPONE: TYPEDEF-IF: POSTPONE: TYPEDEF: typedef } related-words
|
||||
|
||||
HELP: c-struct?
|
||||
|
|
|
@ -64,6 +64,7 @@ ARTICLE: "assocs-sets" "Set-theoretic operations on assocs"
|
|||
ARTICLE: "assocs-mutation" "Storing keys and values in assocs"
|
||||
"Utility operations built up from the " { $link "assocs-protocol" } ":"
|
||||
{ $subsection delete-at* }
|
||||
{ $subsection delete-any }
|
||||
{ $subsection rename-at }
|
||||
{ $subsection change-at }
|
||||
{ $subsection at+ }
|
||||
|
@ -220,6 +221,12 @@ HELP: delete-at*
|
|||
{ $description "Removes an entry from the assoc and outputs the previous value together with a boolean indicating whether it was present." }
|
||||
{ $side-effects "assoc" } ;
|
||||
|
||||
HELP: delete-any
|
||||
{ $values { "assoc" assoc } { "key" "a key" } { "value" "a value" } }
|
||||
{ $description "Removes an undetermined entry from the assoc and outputs it." }
|
||||
{ $errors "Throws an error if the assoc is empty." }
|
||||
{ $notes "This word is useful when using an assoc as an unordered queue which requires constant-time membership tests. Entries are enqueued with " { $link set-at } " and dequeued with " { $link delete-any } "." } ;
|
||||
|
||||
HELP: rename-at
|
||||
{ $values { "newkey" object } { "key" object } { "assoc" assoc } }
|
||||
{ $description "Removes the values associated to " { $snippet "key" } " and re-adds it as " { $snippet "newkey" } ". Does nothing if the assoc does not contain " { $snippet "key" } "." }
|
||||
|
|
|
@ -77,6 +77,12 @@ M: assoc assoc-clone-like ( assoc exemplar -- newassoc )
|
|||
: rename-at ( newkey key assoc -- )
|
||||
tuck delete-at* [ -rot set-at ] [ 3drop ] if ;
|
||||
|
||||
: delete-any ( assoc -- key value )
|
||||
[
|
||||
[ 2drop t ] assoc-find
|
||||
[ "Assoc is empty" throw ] unless over
|
||||
] keep delete-at ;
|
||||
|
||||
: assoc-empty? ( assoc -- ? )
|
||||
assoc-size zero? ;
|
||||
|
||||
|
|
|
@ -427,32 +427,22 @@ M: curry '
|
|||
"Writing image to " write dup write "..." print flush
|
||||
<file-writer> [ (write-image) ] with-stream ;
|
||||
|
||||
: prepare-profile ( arch -- )
|
||||
"resource:core/bootstrap/layouts/layouts.factor" run-file
|
||||
"resource:core/cpu/" swap {
|
||||
{ "x86.32" "x86/32" }
|
||||
{ "x86.64" "x86/64" }
|
||||
{ "linux-ppc" "ppc/linux" }
|
||||
{ "macosx-ppc" "ppc/macosx" }
|
||||
{ "arm" "arm" }
|
||||
} at "/bootstrap.factor" 3append ?resource-path run-file ;
|
||||
|
||||
: prepare-image ( arch -- )
|
||||
dup architecture set prepare-profile
|
||||
: prepare-image ( -- )
|
||||
bootstrapping? on
|
||||
load-help? off
|
||||
800000 <vector> image set 20000 <hashtable> objects set ;
|
||||
800000 <vector> image set
|
||||
20000 <hashtable> objects set ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: make-image ( arch -- )
|
||||
[
|
||||
architecture [
|
||||
prepare-image
|
||||
begin-image
|
||||
"resource:/core/bootstrap/stage1.factor" run-file
|
||||
end-image
|
||||
image get image-name write-image
|
||||
] with-scope ;
|
||||
] with-variable ;
|
||||
|
||||
: my-arch ( -- arch )
|
||||
cpu dup "ppc" = [ os "-" rot 3append ] when ;
|
||||
|
@ -460,7 +450,7 @@ PRIVATE>
|
|||
: make-images ( -- )
|
||||
{
|
||||
"x86.32"
|
||||
! "x86.64"
|
||||
"x86.64"
|
||||
"linux-ppc" "macosx-ppc"
|
||||
! "arm"
|
||||
} [ make-image ] each ;
|
||||
|
|
|
@ -5,22 +5,32 @@ USING: alien arrays byte-arrays generic hashtables
|
|||
hashtables.private io kernel math namespaces parser sequences
|
||||
strings vectors words quotations assocs layouts classes tuples
|
||||
kernel.private vocabs vocabs.loader source-files definitions
|
||||
slots classes.union compiler.units ;
|
||||
slots classes.union compiler.units bootstrap.image.private
|
||||
io.files ;
|
||||
|
||||
"Creating primitives and basic runtime structures..." print flush
|
||||
|
||||
load-help? off
|
||||
crossref off
|
||||
|
||||
! Bring up a bare cross-compiling vocabulary.
|
||||
"syntax" vocab vocab-words bootstrap-syntax set
|
||||
|
||||
"resource:core/bootstrap/syntax.factor" parse-file
|
||||
|
||||
"resource:core/cpu/" architecture get {
|
||||
{ "x86.32" "x86/32" }
|
||||
{ "x86.64" "x86/64" }
|
||||
{ "linux-ppc" "ppc/linux" }
|
||||
{ "macosx-ppc" "ppc/macosx" }
|
||||
{ "arm" "arm" }
|
||||
} at "/bootstrap.factor" 3append parse-file
|
||||
|
||||
! Now we have ( syntax-quot arch-quot ) on the stack
|
||||
|
||||
! Bring up a bare cross-compiling vocabulary.
|
||||
"syntax" vocab vocab-words bootstrap-syntax set
|
||||
H{ } clone dictionary set
|
||||
H{ } clone changed-words set
|
||||
[ drop ] recompile-hook set
|
||||
|
||||
call
|
||||
call
|
||||
|
||||
! Create some empty vocabs where the below primitives and
|
||||
|
@ -558,8 +568,6 @@ builtins get num-tags get tail f union-class define-class
|
|||
{ "alien>u16-string" "alien" }
|
||||
{ "string>u16-alien" "alien" }
|
||||
{ "(throw)" "kernel.private" }
|
||||
{ "string>memory" "alien" }
|
||||
{ "memory>string" "alien" }
|
||||
{ "alien-address" "alien" }
|
||||
{ "slot" "slots.private" }
|
||||
{ "set-slot" "slots.private" }
|
||||
|
|
|
@ -48,8 +48,13 @@ IN: bootstrap.stage2
|
|||
|
||||
"Compiling remaining words..." print flush
|
||||
|
||||
all-words [ compiled? not ] subset recompile-hook get call
|
||||
"bootstrap.compiler" vocab [
|
||||
vocabs [
|
||||
words "compile" "compiler" lookup execute
|
||||
] each
|
||||
] when
|
||||
] with-compiler-errors
|
||||
:errors
|
||||
|
||||
f error set-global
|
||||
f error-continuation set-global
|
||||
|
|
|
@ -7,21 +7,6 @@ optimizer definitions math compiler.errors threads graphs
|
|||
generic ;
|
||||
IN: compiler
|
||||
|
||||
SYMBOL: compiled-crossref
|
||||
|
||||
compiled-crossref global [ H{ } assoc-like ] change-at
|
||||
|
||||
: compiled-xref ( word dependencies -- )
|
||||
2dup "compiled-uses" set-word-prop
|
||||
compiled-crossref get add-vertex* ;
|
||||
|
||||
: compiled-unxref ( word -- )
|
||||
dup "compiled-uses" word-prop
|
||||
compiled-crossref get remove-vertex* ;
|
||||
|
||||
: compiled-usage ( word -- assoc )
|
||||
compiled-crossref get at ;
|
||||
|
||||
: compiled-usages ( words -- seq )
|
||||
[ [ dup ] H{ } map>assoc dup ] keep [
|
||||
compiled-usage [ nip +inlined+ eq? ] assoc-subset update
|
||||
|
@ -41,7 +26,7 @@ compiled-crossref global [ H{ } assoc-like ] change-at
|
|||
>r dupd save-effect r>
|
||||
f pick compiler-error
|
||||
over compiled-unxref
|
||||
compiled-xref ;
|
||||
over word-vocabulary [ compiled-xref ] [ 2drop ] if ;
|
||||
|
||||
: compile-succeeded ( word -- effect dependencies )
|
||||
[
|
||||
|
@ -57,12 +42,9 @@ compiled-crossref global [ H{ } assoc-like ] change-at
|
|||
[ dupd compile-failed f save-effect ]
|
||||
recover ;
|
||||
|
||||
: delete-any ( assoc -- element )
|
||||
[ [ 2drop t ] assoc-find 2drop dup ] keep delete-at ;
|
||||
|
||||
: compile-loop ( assoc -- )
|
||||
dup assoc-empty? [ drop ] [
|
||||
dup delete-any (compile)
|
||||
dup delete-any drop (compile)
|
||||
yield
|
||||
compile-loop
|
||||
] if ;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
VM memory layout constants
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Compiler warning and error reporting
|
|
@ -287,3 +287,7 @@ TUPLE: silly-tuple a b ;
|
|||
[ 3 throw ] [ empty-compound ] compose [ 3 throw ] if ;
|
||||
|
||||
[ t ] [ \ node-successor-f-bug compiled? ] unit-test
|
||||
|
||||
: construct-empty-bug construct-empty ;
|
||||
|
||||
[ ] [ [ construct-empty ] dataflow optimize drop ] unit-test
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
USING: compiler definitions generic assocs inference math
|
||||
namespaces parser tools.test words kernel sequences arrays io
|
||||
effects tools.test.inference compiler.units ;
|
||||
effects tools.test.inference compiler.units inference.state ;
|
||||
IN: temporary
|
||||
|
||||
DEFER: x-1
|
||||
|
@ -205,3 +205,36 @@ DEFER: generic-then-not-generic-test-2
|
|||
[ ] [ "IN: temporary USE: math : generic-then-not-generic-test-1 1 + ;" eval ] unit-test
|
||||
|
||||
[ 4 ] [ generic-then-not-generic-test-2 ] unit-test
|
||||
|
||||
DEFER: foldable-test-1
|
||||
DEFER: foldable-test-2
|
||||
|
||||
[ ] [ "IN: temporary : foldable-test-1 3 ; foldable" eval ] unit-test
|
||||
|
||||
[ ] [ "IN: temporary : foldable-test-2 foldable-test-1 ;" eval ] unit-test
|
||||
|
||||
[ +inlined+ ] [ \ foldable-test-2 \ foldable-test-1 compiled-usage at ] unit-test
|
||||
|
||||
[ 3 ] [ foldable-test-2 ] unit-test
|
||||
|
||||
[ ] [ "IN: temporary : foldable-test-1 4 ; foldable" eval ] unit-test
|
||||
|
||||
[ 4 ] [ foldable-test-2 ] unit-test
|
||||
|
||||
DEFER: flushable-test-2
|
||||
|
||||
[ ] [ "IN: temporary USE: kernel : flushable-test-1 drop 3 ; flushable" eval ] unit-test
|
||||
|
||||
[ ] [ "IN: temporary USE: kernel : flushable-test-2 V{ } dup flushable-test-1 drop ;" eval ] unit-test
|
||||
|
||||
[ V{ } ] [ flushable-test-2 ] unit-test
|
||||
|
||||
[ ] [ "IN: temporary USING: kernel sequences ; : flushable-test-1 3 over push ;" eval ] unit-test
|
||||
|
||||
[ V{ 3 } ] [ flushable-test-2 ] unit-test
|
||||
|
||||
: ax ;
|
||||
: bx ax ;
|
||||
[ \ bx forget ] with-compilation-unit
|
||||
|
||||
[ t ] [ \ ax compiled-usage [ drop interned? ] assoc-all? ] unit-test
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Compilation units group word definitions for compilation
|
|
@ -51,14 +51,8 @@ HOOK: %save-dispatch-xt compiler-backend ( -- )
|
|||
|
||||
M: object %save-dispatch-xt %save-word-xt ;
|
||||
|
||||
! Call C primitive
|
||||
HOOK: %call-primitive compiler-backend ( label -- )
|
||||
|
||||
! Call another label
|
||||
HOOK: %call-label compiler-backend ( label -- )
|
||||
|
||||
! Far jump to C primitive
|
||||
HOOK: %jump-primitive compiler-backend ( label -- )
|
||||
! Call another word
|
||||
HOOK: %call compiler-backend ( word -- )
|
||||
|
||||
! Local jump for branches
|
||||
HOOK: %jump-label compiler-backend ( label -- )
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -97,26 +97,14 @@ M: ppc-backend %epilogue ( n -- )
|
|||
1 1 rot ADDI
|
||||
0 MTLR ;
|
||||
|
||||
: %prepare-primitive ( word -- )
|
||||
#! Save stack pointer to stack_chain->callstack_top, load XT
|
||||
4 1 MR
|
||||
0 11 LOAD32
|
||||
rc-absolute-ppc-2/2 rel-primitive ;
|
||||
|
||||
: (%call) 11 MTLR BLRL ;
|
||||
|
||||
M: ppc-backend %call-primitive ( word -- )
|
||||
%prepare-primitive (%call) ;
|
||||
|
||||
: (%jump) 11 MTCTR BCTR ;
|
||||
|
||||
M: ppc-backend %jump-primitive ( word -- )
|
||||
%prepare-primitive (%jump) ;
|
||||
|
||||
: %load-dlsym ( symbol dll register -- )
|
||||
0 swap LOAD32 rc-absolute-ppc-2/2 rel-dlsym ;
|
||||
|
||||
M: ppc-backend %call-label ( label -- ) BL ;
|
||||
M: ppc-backend %call ( label -- ) BL ;
|
||||
|
||||
M: ppc-backend %jump-label ( label -- ) B ;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -1,9 +1,10 @@
|
|||
! Copyright (C) 2007 Slava Pestov.
|
||||
! Copyright (C) 2007, 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: parser layouts system ;
|
||||
USING: parser layouts system kernel ;
|
||||
IN: bootstrap.ppc
|
||||
|
||||
: c-area-size 10 bootstrap-cells ;
|
||||
: lr-save bootstrap-cell ;
|
||||
|
||||
"resource:core/cpu/ppc/bootstrap.factor" run-file
|
||||
<< "resource:core/cpu/ppc/bootstrap.factor" parse-file parsed >>
|
||||
call
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
! Copyright (C) 2007 Slava Pestov.
|
||||
! Copyright (C) 2007, 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: parser layouts system ;
|
||||
USING: parser layouts system kernel ;
|
||||
IN: bootstrap.ppc
|
||||
|
||||
: c-area-size 14 bootstrap-cells ;
|
||||
: lr-save 2 bootstrap-cells ;
|
||||
|
||||
"resource:core/cpu/ppc/bootstrap.factor" run-file
|
||||
<< "resource:core/cpu/ppc/bootstrap.factor" parse-file parsed >>
|
||||
call
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -14,4 +14,5 @@ IN: bootstrap.x86
|
|||
: fixnum>slot@ arg0 1 SAR ;
|
||||
: rex-length 0 ;
|
||||
|
||||
"resource:core/cpu/x86/bootstrap.factor" run-file
|
||||
<< "resource:core/cpu/x86/bootstrap.factor" parse-file parsed >>
|
||||
call
|
||||
|
|
|
@ -14,4 +14,5 @@ IN: bootstrap.x86
|
|||
: fixnum>slot@ ;
|
||||
: rex-length 1 ;
|
||||
|
||||
"resource:core/cpu/x86/bootstrap.factor" run-file
|
||||
<< "resource:core/cpu/x86/bootstrap.factor" parse-file parsed >>
|
||||
call
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -70,15 +70,7 @@ M: x86-backend %prepare-alien-invoke
|
|||
temp-reg v>operand 2 cells [+] ds-reg MOV
|
||||
temp-reg v>operand 3 cells [+] rs-reg MOV ;
|
||||
|
||||
M: x86-backend %call-primitive ( word -- )
|
||||
stack-save-reg stack-reg cell neg [+] LEA
|
||||
address-operand CALL ;
|
||||
|
||||
M: x86-backend %jump-primitive ( word -- )
|
||||
stack-save-reg stack-reg MOV
|
||||
address-operand JMP ;
|
||||
|
||||
M: x86-backend %call-label ( label -- ) CALL ;
|
||||
M: x86-backend %call ( label -- ) CALL ;
|
||||
|
||||
M: x86-backend %jump-label ( label -- ) JMP ;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -78,7 +78,8 @@ PRIVATE>
|
|||
|
||||
: pop-front ( dlist -- obj )
|
||||
dup dlist-front [
|
||||
dlist-node-next
|
||||
dup dlist-node-next
|
||||
f rot set-dlist-node-next
|
||||
f over set-prev-when
|
||||
swap set-dlist-front
|
||||
] 2keep dlist-node-obj
|
||||
|
@ -87,13 +88,13 @@ PRIVATE>
|
|||
: pop-front* ( dlist -- ) pop-front drop ;
|
||||
|
||||
: pop-back ( dlist -- obj )
|
||||
[
|
||||
dlist-back dup dlist-node-prev f over set-next-when
|
||||
] keep
|
||||
[ set-dlist-back ] keep
|
||||
[ normalize-front ] keep
|
||||
dec-length
|
||||
dlist-node-obj ;
|
||||
dup dlist-back [
|
||||
dup dlist-node-prev
|
||||
f rot set-dlist-node-prev
|
||||
f over set-next-when
|
||||
swap set-dlist-back
|
||||
] 2keep dlist-node-obj
|
||||
swap [ normalize-front ] keep dec-length ;
|
||||
|
||||
: pop-back* ( dlist -- ) pop-back drop ;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -100,21 +100,10 @@ UNION: #terminal
|
|||
! node
|
||||
M: node generate-node drop iterate-next ;
|
||||
|
||||
: %call ( word -- )
|
||||
dup primitive? [ %call-primitive ] [ %call-label ] if ;
|
||||
|
||||
: %jump ( word -- )
|
||||
{
|
||||
{ [ dup compiling-label get eq? ] [
|
||||
drop current-label-start get %jump-label
|
||||
] }
|
||||
{ [ dup primitive? ] [
|
||||
%epilogue-later %jump-primitive
|
||||
] }
|
||||
{ [ t ] [
|
||||
%epilogue-later %jump-label
|
||||
] }
|
||||
} cond ;
|
||||
dup compiling-label get eq?
|
||||
[ drop current-label-start get ] [ %epilogue-later ] if
|
||||
%jump-label ;
|
||||
|
||||
: generate-call ( label -- next )
|
||||
dup maybe-compile
|
||||
|
|
|
@ -35,8 +35,10 @@ $nl
|
|||
"Utility words to create a new hashtable from a single key/value pair:"
|
||||
{ $subsection associate }
|
||||
{ $subsection ?set-at }
|
||||
"Removing duplicate elements from a sequence in linear time, using a hashtable:"
|
||||
"The final two words pertain to sequences but use a hashtable internally. Removing duplicate elements from a sequence in linear time, using a hashtable:"
|
||||
{ $subsection prune }
|
||||
"Test if a sequence contains duplicates in linear time:"
|
||||
{ $subsection all-unique? }
|
||||
{ $subsection "hashtables.private" } ;
|
||||
|
||||
ABOUT: "hashtables"
|
||||
|
@ -133,6 +135,15 @@ HELP: prune
|
|||
{ $example "USE: hashtables" "{ 1 1 t 3 t } prune ." "V{ 1 t 3 }" }
|
||||
} ;
|
||||
|
||||
HELP: all-unique?
|
||||
{ $values { "seq" sequence } { "?" "a boolean" } }
|
||||
{ $description "Tests whether a sequence contains any repeated elements." }
|
||||
{ $example
|
||||
"USE: combinators.lib"
|
||||
"{ 0 1 1 2 3 5 } all-unique? ."
|
||||
"f"
|
||||
} ;
|
||||
|
||||
HELP: rehash
|
||||
{ $values { "hash" hashtable } }
|
||||
{ $description "Rebuild the hashtable. This word should be called if the hashcodes of the hashtable's keys have changed, or if the hashing algorithms themselves have changed, neither of which should occur during normal operation." } ;
|
||||
|
|
|
@ -160,3 +160,6 @@ H{ } "x" set
|
|||
H{ { 1 "one" } { 2 "two" } }
|
||||
{ 1 2 3 } clone [ substitute ] keep
|
||||
] unit-test
|
||||
|
||||
[ f ] [ { 0 1 1 2 3 5 } all-unique? ] unit-test
|
||||
[ t ] [ { 0 1 2 3 4 5 } all-unique? ] unit-test
|
||||
|
|
|
@ -195,4 +195,7 @@ M: hashtable assoc-like
|
|||
dup length <hashtable> over length <vector>
|
||||
rot [ >r 2dup r> (prune) ] each nip ;
|
||||
|
||||
: all-unique? ( seq -- ? )
|
||||
dup prune [ length ] 2apply = ;
|
||||
|
||||
INSTANCE: hashtable assoc
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Doug Coleman
|
||||
Ryan Murphy
|
|
@ -0,0 +1 @@
|
|||
Maxheap and minheap implementations of priority queues
|
|
@ -2,7 +2,8 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: arrays generic assocs hashtables inference kernel
|
||||
math namespaces sequences words parser math.intervals
|
||||
effects classes inference.dataflow inference.backend ;
|
||||
effects classes inference.dataflow inference.backend
|
||||
combinators ;
|
||||
IN: inference.class
|
||||
|
||||
! Class inference
|
||||
|
@ -181,8 +182,11 @@ M: pair constraint-satisfied?
|
|||
] if* ;
|
||||
|
||||
: default-output-classes ( word -- classes )
|
||||
"inferred-effect" word-prop effect-out
|
||||
dup [ class? ] all? [ drop f ] unless ;
|
||||
"inferred-effect" word-prop {
|
||||
{ [ dup not ] [ drop f ] }
|
||||
{ [ dup effect-out [ class? ] all? not ] [ drop f ] }
|
||||
{ [ t ] [ effect-out ] }
|
||||
} cond ;
|
||||
|
||||
: compute-output-classes ( node word -- classes intervals )
|
||||
dup node-param "output-classes" word-prop dup
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
USING: help.syntax help.markup kernel sequences words io
|
||||
effects inference.dataflow inference.backend
|
||||
effects inference.dataflow inference.backend classes
|
||||
math combinators inference.transforms inference.state ;
|
||||
IN: inference
|
||||
|
||||
|
@ -93,8 +93,8 @@ $nl
|
|||
ABOUT: "inference"
|
||||
|
||||
HELP: inference-error
|
||||
{ $values { "msg" "an object" } }
|
||||
{ $description "Throws an " { $link inference-error } "." }
|
||||
{ $values { "class" class } }
|
||||
{ $description "Creates an instance of " { $snippet "class" } ", wraps it in an " { $link inference-error } " and throws the result." }
|
||||
{ $error-description
|
||||
"Thrown by " { $link infer } " and " { $link dataflow } " when the stack effect of a quotation cannot be inferred."
|
||||
$nl
|
||||
|
|
|
@ -475,10 +475,6 @@ t over set-effect-terminated?
|
|||
|
||||
\ string>u16-alien { string } { byte-array } <effect> "inferred-effect" set-word-prop
|
||||
|
||||
\ string>memory { string c-ptr } { } <effect> "inferred-effect" set-word-prop
|
||||
|
||||
\ memory>string { c-ptr integer } { string } <effect> "inferred-effect" set-word-prop
|
||||
|
||||
\ alien-address { alien } { integer } <effect> "inferred-effect" set-word-prop
|
||||
\ alien-address make-flushable
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Variables for holding stack effect inference state
|
|
@ -1,5 +1,5 @@
|
|||
USING: help.markup help.syntax inference.transforms
|
||||
combinators words ;
|
||||
IN: inference.transforms
|
||||
USING: help.markup help.syntax combinators words kernel ;
|
||||
|
||||
HELP: define-transform
|
||||
{ $values { "word" word } { "quot" "a quotation taking " { $snippet "n" } " inputs from the stack and producing another quotation as output" } { "n" "a non-negative integer" } }
|
||||
|
@ -12,3 +12,8 @@ HELP: define-transform
|
|||
$nl
|
||||
"The " { $link cond } " word compiles to efficient code because it is transformed using " { $link cond>quot } ":"
|
||||
{ $code "\\ cond [ cond>quot ] 1 define-transform" } } ;
|
||||
|
||||
HELP: duplicated-slots-error
|
||||
{ $values { "names" "a sequence of setter words" } }
|
||||
{ $description "Throws a " { $link duplicated-slots-error } "." }
|
||||
{ $error-description "Thrown by stack effect inference if a " { $link set-slots } " form is given an array of slot setters that includes duplicates. Since writing to the same slot multiple times has no useful effect, this is a programmer error, so it is caught at compile time." } ;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
IN: temporary
|
||||
USING: sequences inference.transforms tools.test math kernel
|
||||
quotations ;
|
||||
quotations tools.test.inference inference ;
|
||||
|
||||
: compose-n-quot <repetition> >quotation ;
|
||||
: compose-n compose-n-quot call ;
|
||||
|
@ -18,3 +18,17 @@ quotations ;
|
|||
[ 268 ] [ 1 { 8 { 3 2 } } bitfield-quot call ] unit-test
|
||||
|
||||
[ 512 ] [ 1 { { 1+ 8 } } bitfield-quot call ] unit-test
|
||||
|
||||
\ construct-empty must-infer
|
||||
|
||||
TUPLE: a-tuple x y z ;
|
||||
|
||||
: set-slots-test ( x y z -- )
|
||||
{ set-a-tuple-x set-a-tuple-y } set-slots ;
|
||||
|
||||
\ set-slots-test must-infer
|
||||
|
||||
: set-slots-test-2
|
||||
{ set-a-tuple-x set-a-tuple-x } set-slots ;
|
||||
|
||||
[ [ set-slots-test-2 ] infer ] unit-test-fails
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
! Copyright (C) 2007 Slava Pestov.
|
||||
! Copyright (C) 2007, 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: arrays kernel words sequences generic math namespaces
|
||||
quotations assocs combinators math.bitfields inference.backend
|
||||
inference.dataflow inference.state tuples.private ;
|
||||
inference.dataflow inference.state tuples.private effects
|
||||
inspector hashtables ;
|
||||
IN: inference.transforms
|
||||
|
||||
: pop-literals ( n -- rstate seq )
|
||||
|
@ -59,13 +60,34 @@ M: pair (bitfield-quot) ( spec -- quot )
|
|||
|
||||
\ get-slots [ [get-slots] ] 1 define-transform
|
||||
|
||||
\ set-slots [ <reversed> [get-slots] ] 1 define-transform
|
||||
TUPLE: duplicated-slots-error names ;
|
||||
|
||||
: [construct] ( word quot -- newquot )
|
||||
>r dup +inlined+ depends-on dup tuple-size r> 2curry ;
|
||||
M: duplicated-slots-error summary
|
||||
drop "Calling set-slots with duplicate slot setters" ;
|
||||
|
||||
\ construct-boa
|
||||
[ [ <tuple-boa> ] [construct] ] 1 define-transform
|
||||
: duplicated-slots-error ( names -- * )
|
||||
\ duplicated-slots-error construct-boa throw ;
|
||||
|
||||
\ construct-empty
|
||||
[ [ <tuple> ] [construct] ] 1 define-transform
|
||||
\ set-slots [
|
||||
dup all-unique?
|
||||
[ <reversed> [get-slots] ] [ duplicated-slots-error ] if
|
||||
] 1 define-transform
|
||||
|
||||
\ construct-boa [
|
||||
dup +inlined+ depends-on
|
||||
dup tuple-size [ <tuple-boa> ] 2curry
|
||||
] 1 define-transform
|
||||
|
||||
\ construct-empty [
|
||||
1 ensure-values
|
||||
peek-d value? [
|
||||
pop-literal
|
||||
dup +inlined+ depends-on
|
||||
dup tuple-size [ <tuple> ] 2curry
|
||||
swap infer-quot
|
||||
] [
|
||||
\ construct-empty 1 1 <effect> make-call-node
|
||||
] if
|
||||
] "infer" set-word-prop
|
||||
|
||||
\ construct-empty 1 1 <effect> "inferred-effect" set-word-prop
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
! Copyright (C) 2007 Slava Pestov.
|
||||
! Copyright (C) 2007, 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: init kernel system ;
|
||||
USING: init kernel system namespaces ;
|
||||
IN: io.backend
|
||||
|
||||
SYMBOL: io-backend
|
||||
|
@ -21,3 +21,6 @@ M: object normalize-pathname ;
|
|||
|
||||
[ init-io embedded? [ init-stdio ] unless ]
|
||||
"io.backend" add-init-hook
|
||||
|
||||
: set-io-backend ( backend -- )
|
||||
io-backend set-global init-io init-stdio ;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Common support for ASCII, UTF8 and UTF16 character encodings
|
|
@ -29,7 +29,6 @@ ARTICLE: "stdio" "The default stream"
|
|||
"Various words take an implicit stream parameter from a variable to reduce stack shuffling."
|
||||
{ $subsection stdio }
|
||||
"Unless rebound in a child namespace, this variable will be set to a console stream for interacting with the user."
|
||||
{ $subsection close }
|
||||
{ $subsection read1 }
|
||||
{ $subsection read }
|
||||
{ $subsection read-until }
|
||||
|
@ -178,10 +177,6 @@ $io-error ;
|
|||
HELP: stdio
|
||||
{ $var-description "Holds a stream, used for various implicit stream operations. Rebound using " { $link with-stream } " and " { $link with-stream* } "." } ;
|
||||
|
||||
HELP: close
|
||||
{ $contract "Closes the " { $link stdio } " stream." }
|
||||
$io-error ;
|
||||
|
||||
HELP: readln
|
||||
{ $values { "str/f" "a string or " { $link f } } }
|
||||
{ $contract "Reads a line of input from the " { $link stdio } " stream. Outputs " { $link f } " on stream exhaustion." }
|
||||
|
|
|
@ -35,7 +35,8 @@ GENERIC: stream-write-table ( table-cells style stream -- )
|
|||
! Default stream
|
||||
SYMBOL: stdio
|
||||
|
||||
: close ( -- ) stdio get stream-close ;
|
||||
! Default error stream
|
||||
SYMBOL: stderr
|
||||
|
||||
: readln ( -- str/f ) stdio get stream-readln ;
|
||||
: read1 ( -- ch/f ) stdio get stream-read1 ;
|
||||
|
@ -53,7 +54,9 @@ SYMBOL: stdio
|
|||
stdio swap with-variable ; inline
|
||||
|
||||
: with-stream ( stream quot -- )
|
||||
swap [ [ close ] [ ] cleanup ] with-stream* ; inline
|
||||
swap [
|
||||
[ stdio get stream-close ] [ ] cleanup
|
||||
] with-stream* ; inline
|
||||
|
||||
: tabular-output ( style quot -- )
|
||||
swap >r { } make r> stdio get stream-write-table ; inline
|
||||
|
|
|
@ -14,9 +14,10 @@ ARTICLE: "io.streams.c" "ANSI C streams"
|
|||
{ $subsection fclose }
|
||||
{ $subsection fgetc }
|
||||
{ $subsection fread }
|
||||
"Two standard file handles:"
|
||||
{ $subsection stdin }
|
||||
{ $subsection stdout } ;
|
||||
"The three standard file handles:"
|
||||
{ $subsection stdin-handle }
|
||||
{ $subsection stdout-handle }
|
||||
{ $subsection stderr-handle } ;
|
||||
|
||||
ABOUT: "io.streams.c"
|
||||
|
||||
|
@ -64,10 +65,14 @@ HELP: fread ( n alien -- str/f )
|
|||
{ $description "Reads a sequence of characters from a C FILE* handle, and outputs " { $link f } " on end of file." }
|
||||
{ $errors "Throws an error if the input operation failed." } ;
|
||||
|
||||
HELP: stdin
|
||||
HELP: stdin-handle
|
||||
{ $values { "in" "a C FILE* handle" } }
|
||||
{ $description "Outputs the console standard input file handle." } ;
|
||||
|
||||
HELP: stdout
|
||||
HELP: stdout-handle
|
||||
{ $values { "out" "a C FILE* handle" } }
|
||||
{ $description "Outputs the console standard output file handle." } ;
|
||||
|
||||
HELP: stderr-handle
|
||||
{ $values { "out" "a C FILE* handle" } }
|
||||
{ $description "Outputs the console standard error file handle." } ;
|
||||
|
|
|
@ -56,12 +56,13 @@ M: c-reader stream-close
|
|||
|
||||
M: object init-io ;
|
||||
|
||||
: stdin 11 getenv ;
|
||||
|
||||
: stdout 12 getenv ;
|
||||
: stdin-handle 11 getenv ;
|
||||
: stdout-handle 12 getenv ;
|
||||
: stderr-handle 38 getenv ;
|
||||
|
||||
M: object init-stdio
|
||||
stdin stdout <duplex-c-stream> stdio set-global ;
|
||||
stdin-handle stdout-handle <duplex-c-stream> stdio set-global
|
||||
stderr-handle <c-writer> <plain-writer> stderr set-global ;
|
||||
|
||||
M: object io-multiplex (sleep) ;
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ ARTICLE: "basic-combinators" "Basic combinators"
|
|||
{ $subsection execute }
|
||||
"These words are used to implement " { $emphasis "combinators" } ", which are words that take code from the stack. Note that combinator definitions must be followed by the " { $link POSTPONE: inline } " declaration in order to compile in the optimizing compiler; for example:"
|
||||
{ $code
|
||||
": keep ( x quot -- x | quot: x -- )"
|
||||
": keep ( x quot -- x )"
|
||||
" over >r call r> ; inline"
|
||||
}
|
||||
"Word inlining is documented in " { $link "declarations" } "."
|
||||
|
@ -372,7 +372,7 @@ HELP: 2keep
|
|||
{ $description "Call a quotation with two values on the stack, restoring the values when the quotation returns." } ;
|
||||
|
||||
HELP: 3keep
|
||||
{ $values { "quot" "a quotation with stack effect " { $snippet "( x y -- )" } } { "x" object } { "y" object } { "z" object } }
|
||||
{ $values { "quot" "a quotation with stack effect " { $snippet "( x y z -- )" } } { "x" object } { "y" object } { "z" object } }
|
||||
{ $description "Call a quotation with three values on the stack, restoring the values when the quotation returns." } ;
|
||||
|
||||
HELP: 2apply
|
||||
|
@ -557,7 +557,7 @@ HELP: dip
|
|||
|
||||
HELP: while
|
||||
{ $values { "pred" "a quotation with stack effect " { $snippet "( -- ? )" } } { "body" "a quotation" } { "tail" "a quotation" } }
|
||||
{ $description "Repeatedly calls " { $snippet "pred" } ". If it yields " { $link f } ", iteration stops, otherwise " { $snippet "quot" } " is called. After iteration stops, " { $snippet "tail" } " is called." }
|
||||
{ $description "Repeatedly calls " { $snippet "pred" } ". If it yields " { $link f } ", iteration stops, otherwise " { $snippet "body" } " is called. After iteration stops, " { $snippet "tail" } " is called." }
|
||||
{ $notes "In most cases, tail recursion should be used, because it is simpler both in terms of implementation and conceptually. However in some cases this combinator expresses intent better and should be used."
|
||||
$nl
|
||||
"Strictly speaking, the " { $snippet "tail" } " is not necessary, since the following are equivalent:"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! Copyright (C) 2007 Slava Pestov
|
||||
! Copyright (C) 2007 Doug Coleman
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: alien assocs init inspector kernel namespaces ;
|
||||
USING: alien assocs continuations init inspector kernel namespaces ;
|
||||
IN: libc
|
||||
|
||||
<PRIVATE
|
||||
|
@ -84,4 +84,4 @@ PRIVATE>
|
|||
"void" "libc" "memcpy" { "void*" "void*" "ulong" } alien-invoke ;
|
||||
|
||||
: with-malloc ( size quot -- )
|
||||
swap 1 calloc swap keep free ; inline
|
||||
swap 1 calloc [ swap keep ] [ free ] [ ] cleanup ; inline
|
||||
|
|
|
@ -209,7 +209,7 @@ HELP: bitxor
|
|||
|
||||
HELP: shift
|
||||
{ $values { "x" integer } { "n" integer } { "y" integer } }
|
||||
{ $description "Shifts " { $snippet "x" } " to the left by " { $snippet "y" } " bits if " { $snippet "y" } " is positive, or " { $snippet "-y" } " bits to the right if " { $snippet "y" } " is negative. A left shift of a fixnum may overflow, yielding a bignum. A right shift may result in bits ``falling off'' the right hand side and being discarded." }
|
||||
{ $description "Shifts " { $snippet "x" } " to the left by " { $snippet "n" } " bits if " { $snippet "n" } " is positive, or " { $snippet "-n" } " bits to the right if " { $snippet "n" } " is negative. A left shift of a fixnum may overflow, yielding a bignum. A right shift may result in bits ``falling off'' the right hand side and being discarded." }
|
||||
{ $examples { $example "BIN: 101 5 shift .b" "10100000" } { $example "BIN: 11111 -2 shift .b" "111" } } ;
|
||||
|
||||
HELP: bitnot
|
||||
|
|
|
@ -15,16 +15,16 @@ IN: namespaces
|
|||
PRIVATE>
|
||||
|
||||
: namespace ( -- namespace ) namestack* peek ;
|
||||
: namestack ( -- namestack ) namestack* clone ; inline
|
||||
: set-namestack ( namestack -- ) >vector 0 setenv ; inline
|
||||
: namestack ( -- namestack ) namestack* clone ;
|
||||
: set-namestack ( namestack -- ) >vector 0 setenv ;
|
||||
: global ( -- g ) 21 getenv { hashtable } declare ; inline
|
||||
: init-namespaces ( -- ) global 1array set-namestack ;
|
||||
: get ( variable -- value ) namestack* assoc-stack ; flushable
|
||||
: set ( value variable -- ) namespace set-at ;
|
||||
: on ( variable -- ) t swap set ; inline
|
||||
: off ( variable -- ) f swap set ; inline
|
||||
: get-global ( variable -- value ) global at ; inline
|
||||
: set-global ( value variable -- ) global set-at ; inline
|
||||
: get-global ( variable -- value ) global at ;
|
||||
: set-global ( value variable -- ) global set-at ;
|
||||
|
||||
: change ( variable quot -- )
|
||||
>r dup get r> rot slip set ; inline
|
||||
|
|
|
@ -17,17 +17,17 @@ SYMBOL: optimizer-changed
|
|||
|
||||
GENERIC: optimize-node* ( node -- node/t changed? )
|
||||
|
||||
: ?union ( hash/f hash -- hash )
|
||||
: ?union ( assoc/f assoc -- hash )
|
||||
over [ union ] [ nip ] if ;
|
||||
|
||||
: add-node-literals ( hash node -- )
|
||||
: add-node-literals ( assoc node -- )
|
||||
over assoc-empty? [
|
||||
2drop
|
||||
] [
|
||||
[ node-literals ?union ] keep set-node-literals
|
||||
] if ;
|
||||
|
||||
: add-node-classes ( hash node -- )
|
||||
: add-node-classes ( assoc node -- )
|
||||
over assoc-empty? [
|
||||
2drop
|
||||
] [
|
||||
|
@ -324,6 +324,7 @@ M: #dispatch optimize-node*
|
|||
] if ;
|
||||
|
||||
: flush-eval ( #call -- node )
|
||||
dup node-param +inlined+ depends-on
|
||||
dup node-out-d length f <repetition> inline-literals ;
|
||||
|
||||
: partial-eval? ( #call -- ? )
|
||||
|
@ -337,9 +338,9 @@ M: #dispatch optimize-node*
|
|||
dup node-in-d [ node-literal ] with map ;
|
||||
|
||||
: partial-eval ( #call -- node )
|
||||
dup node-param +inlined+ depends-on
|
||||
dup literal-in-d over node-param 1quotation
|
||||
[ with-datastack ] catch
|
||||
[ 3drop t ] [ inline-literals ] if ;
|
||||
[ with-datastack inline-literals ] [ 2drop 2drop t ] recover ;
|
||||
|
||||
: define-identities ( words identities -- )
|
||||
[ "identities" set-word-prop ] curry each ;
|
||||
|
|
|
@ -44,8 +44,7 @@ ARTICLE: "vocabulary-search-errors" "Word lookup errors"
|
|||
"If the parser cannot not find a word in the current vocabulary search path, it attempts to look for the word in all loaded vocabularies. Then, one of three things happen:"
|
||||
{ $list
|
||||
{ "If there are no words having this name at all, an error is thrown and parsing stops." }
|
||||
{ "If there is exactly one vocabulary having a word with this name, the vocabulary is automatically added to the search path. This behavior is intended for interactive use and exploratory programming only, and production code should contain full " { $link POSTPONE: USING: } " declarations." }
|
||||
{ "If there is more than one vocabulary which contains a word with this name, a restartable error is thrown, with a restart for each vocabulary in question. The restarts add the vocabulary to the search path and continue parsing." }
|
||||
{ "If there are vocabularies which contain words with this name, a restartable error is thrown, with a restart for each vocabulary in question. The restarts add the vocabulary to the search path and continue parsing." }
|
||||
}
|
||||
"When writing a new vocabulary, one approach is to ignore " { $link POSTPONE: USING: } " declarations altogether, then to load the vocabulary and observe any parser notes and restarts and use this information to write the correct " { $link POSTPONE: USING: } " declaration." ;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
USING: prettyprint.backend prettyprint.config
|
||||
prettyprint.sections help.markup help.syntax io kernel words
|
||||
definitions quotations strings ;
|
||||
prettyprint.sections prettyprint.private help.markup help.syntax
|
||||
io kernel words definitions quotations strings ;
|
||||
IN: prettyprint
|
||||
|
||||
ARTICLE: "prettyprint-numbers" "Prettyprinting numbers"
|
||||
|
|
|
@ -86,14 +86,14 @@ combinators quotations ;
|
|||
: .s ( -- ) datastack stack. ;
|
||||
: .r ( -- ) retainstack stack. ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
SYMBOL: ->
|
||||
|
||||
\ ->
|
||||
{ { foreground { 1 1 1 1 } } { background { 0 0 0 1 } } }
|
||||
"word-style" set-word-prop
|
||||
|
||||
<PRIVATE
|
||||
|
||||
! This code is ugly and could probably be simplified
|
||||
: remove-step-into
|
||||
building get dup empty? [
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
References to keys and values in assocs
|
|
@ -175,3 +175,14 @@ SYMBOL: quot-uses-b
|
|||
|
||||
[ t ] [ "symbol-generic" "temporary" lookup symbol? ] unit-test
|
||||
[ f ] [ "symbol-generic" "temporary" lookup generic? ] unit-test
|
||||
|
||||
! Regressions
|
||||
[ ] [ "IN: temporary : decl-forget-test ; foldable" eval ] unit-test
|
||||
[ t ] [ "decl-forget-test" "temporary" lookup "foldable" word-prop ] unit-test
|
||||
[ ] [ "IN: temporary : decl-forget-test ;" eval ] unit-test
|
||||
[ f ] [ "decl-forget-test" "temporary" lookup "foldable" word-prop ] unit-test
|
||||
|
||||
[ ] [ "IN: temporary : decl-forget-test ; flushable" eval ] unit-test
|
||||
[ t ] [ "decl-forget-test" "temporary" lookup "flushable" word-prop ] unit-test
|
||||
[ ] [ "IN: temporary : decl-forget-test ;" eval ] unit-test
|
||||
[ f ] [ "decl-forget-test" "temporary" lookup "flushable" word-prop ] unit-test
|
||||
|
|
|
@ -87,6 +87,25 @@ M: wrapper (quot-uses) >r wrapped r> (quot-uses) ;
|
|||
M: word uses ( word -- seq )
|
||||
word-def quot-uses keys ;
|
||||
|
||||
SYMBOL: compiled-crossref
|
||||
|
||||
compiled-crossref global [ H{ } assoc-like ] change-at
|
||||
|
||||
: compiled-xref ( word dependencies -- )
|
||||
2dup "compiled-uses" set-word-prop
|
||||
compiled-crossref get add-vertex* ;
|
||||
|
||||
: compiled-unxref ( word -- )
|
||||
dup "compiled-uses" word-prop
|
||||
compiled-crossref get remove-vertex* ;
|
||||
|
||||
: delete-compiled-xref ( word -- )
|
||||
dup compiled-unxref
|
||||
compiled-crossref get delete-at ;
|
||||
|
||||
: compiled-usage ( word -- assoc )
|
||||
compiled-crossref get at ;
|
||||
|
||||
M: word redefined* ( word -- )
|
||||
{ "inferred-effect" "base-case" "no-effect" } reset-props ;
|
||||
|
||||
|
@ -127,7 +146,7 @@ SYMBOL: changed-words
|
|||
: reset-word ( word -- )
|
||||
{
|
||||
"unannotated-def"
|
||||
"parsing" "inline" "foldable"
|
||||
"parsing" "inline" "foldable" "flushable"
|
||||
"predicating"
|
||||
"reading" "writing"
|
||||
"constructing"
|
||||
|
@ -187,6 +206,7 @@ M: word (forget-word)
|
|||
|
||||
: forget-word ( word -- )
|
||||
dup delete-xref
|
||||
dup delete-compiled-xref
|
||||
(forget-word) ;
|
||||
|
||||
M: word forget* forget-word ;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Doug Coleman
|
|
@ -0,0 +1 @@
|
|||
Eduardo Cavazos
|
|
@ -0,0 +1 @@
|
|||
Elie Chaftari
|
|
@ -0,0 +1 @@
|
|||
Doug Coleman
|
|
@ -0,0 +1 @@
|
|||
Priority search queues
|
|
@ -9,7 +9,7 @@ IN: assocs.lib
|
|||
|
||||
: ref-at ( table key -- value ) swap at ;
|
||||
|
||||
! set-hash with alternative stack effects
|
||||
! set-at with alternative stack effects
|
||||
|
||||
: put-at* ( table key value -- ) swap rot set-at ;
|
||||
|
||||
|
@ -22,3 +22,6 @@ IN: assocs.lib
|
|||
|
||||
: at-default ( key assoc -- value/key )
|
||||
dupd at [ nip ] when* ;
|
||||
|
||||
: at-peek ( key assoc -- value ? )
|
||||
at* dup >r [ peek ] when r> ;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Eduardo Cavazos
|
|
@ -14,7 +14,7 @@ USING: kernel namespaces math quotations arrays hashtables sequences threads
|
|||
ui.gadgets.packs
|
||||
ui.gadgets.grids
|
||||
ui.gadgets.theme
|
||||
namespaces.lib hashtables.lib vars
|
||||
namespaces.lib assocs.lib vars
|
||||
rewrite-closures automata ;
|
||||
|
||||
IN: automata.ui
|
||||
|
@ -85,4 +85,4 @@ over @center grid-add
|
|||
|
||||
: automata-window ( -- ) [ [ automata-window* ] with-scope ] with-ui ;
|
||||
|
||||
MAIN: automata-window
|
||||
MAIN: automata-window
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
|
@ -0,0 +1 @@
|
|||
Slava Pestov
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue