Merge branch 'master' of git://factorcode.org/git/factor into bleeding_edge
commit
d75be8defe
|
@ -24,10 +24,12 @@ HELP: every
|
|||
|
||||
ARTICLE: "alarms" "Alarms"
|
||||
"The " { $vocab-link "alarms" } " vocabulary provides a lightweight way to schedule one-time and recurring tasks without spawning a new thread."
|
||||
{ $subsection alarm }
|
||||
{ $subsection add-alarm }
|
||||
{ $subsection later }
|
||||
{ $subsection cancel-alarm }
|
||||
{ $subsections
|
||||
alarm
|
||||
add-alarm
|
||||
later
|
||||
cancel-alarm
|
||||
}
|
||||
"Alarms do not persist across image saves. Saving and restoring an image has the effect of calling " { $link cancel-alarm } " on all " { $link alarm } " instances." ;
|
||||
|
||||
ABOUT: "alarms"
|
||||
|
|
|
@ -136,33 +136,37 @@ 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*> }
|
||||
{ $subsections
|
||||
<char>
|
||||
<uchar>
|
||||
<short>
|
||||
<ushort>
|
||||
<int>
|
||||
<uint>
|
||||
<long>
|
||||
<ulong>
|
||||
<longlong>
|
||||
<ulonglong>
|
||||
<float>
|
||||
<double>
|
||||
<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* }
|
||||
{ $subsections
|
||||
*char
|
||||
*uchar
|
||||
*short
|
||||
*ushort
|
||||
*int
|
||||
*uint
|
||||
*long
|
||||
*ulong
|
||||
*longlong
|
||||
*ulonglong
|
||||
*float
|
||||
*double
|
||||
*void*
|
||||
}
|
||||
"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.primitives" "Primitive C types"
|
||||
|
@ -227,11 +231,22 @@ ARTICLE: "c-types.structs" "Struct and union types"
|
|||
"Struct and union types are identified by their class word. See " { $link "classes.struct" } "." ;
|
||||
|
||||
ARTICLE: "c-types-specs" "C type specifiers"
|
||||
"C types are identified by special words, and type names occur as parameters to the " { $link alien-invoke } ", " { $link alien-indirect } " and " { $link alien-callback } " words. New C types can be defined by the words " { $link POSTPONE: STRUCT: } ", " { $link POSTPONE: UNION-STRUCT: } ", " { $link POSTPONE: CALLBACK: } ", and " { $link POSTPONE: TYPEDEF: } "."
|
||||
{ $subsection "c-types.primitives" }
|
||||
{ $subsection "c-types.pointers" }
|
||||
{ $subsection "c-types.ambiguity" }
|
||||
{ $subsection "c-types.structs" }
|
||||
"C types are identified by special words, and type names occur as parameters to the " { $link alien-invoke } ", " { $link alien-indirect } " and " { $link alien-callback } " words."
|
||||
$nl
|
||||
"Defining new C types:"
|
||||
{ $subsections
|
||||
POSTPONE: STRUCT:
|
||||
POSTPONE: UNION-STRUCT:
|
||||
POSTPONE: CALLBACK:
|
||||
POSTPONE: TYPEDEF:
|
||||
}
|
||||
{ $heading "Related articles" }
|
||||
{ $subsections
|
||||
"c-types.primitives"
|
||||
"c-types.pointers"
|
||||
"c-types.ambiguity"
|
||||
"c-types.structs"
|
||||
}
|
||||
;
|
||||
|
||||
ABOUT: "c-types-specs"
|
||||
|
|
|
@ -53,26 +53,32 @@ ARTICLE: "malloc" "Manual memory management"
|
|||
"Sometimes data passed to C functions must be allocated at a fixed address. See " { $link "byte-arrays-gc" } " for an explanation of when this is the case."
|
||||
$nl
|
||||
"Allocating a C datum with a fixed address:"
|
||||
{ $subsection malloc-object }
|
||||
{ $subsection malloc-byte-array }
|
||||
{ $subsection malloc-file-contents }
|
||||
"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 }
|
||||
{ $subsections
|
||||
malloc-object
|
||||
malloc-byte-array
|
||||
malloc-file-contents
|
||||
}
|
||||
"The " { $vocab-link "libc" } " vocabulary defines several words which directly call C standard library memory management functions:"
|
||||
{ $subsections
|
||||
malloc
|
||||
calloc
|
||||
realloc
|
||||
}
|
||||
"You must always free pointers returned by any of the above words when the block of memory is no longer in use:"
|
||||
{ $subsection free }
|
||||
{ $subsections free }
|
||||
"Utilities for automatically freeing memory in conjunction with " { $link with-destructors } ":"
|
||||
{ $subsection &free }
|
||||
{ $subsection |free }
|
||||
{ $subsections
|
||||
&free
|
||||
|free
|
||||
}
|
||||
"The " { $link &free } " and " { $link |free } " words are generated using " { $link "alien.destructors" } "."
|
||||
$nl
|
||||
"You can unsafely copy a range of bytes from one memory location to another:"
|
||||
{ $subsection memcpy }
|
||||
{ $subsections memcpy }
|
||||
"You can copy a range of bytes from memory into a byte array:"
|
||||
{ $subsection memory>byte-array }
|
||||
{ $subsections memory>byte-array }
|
||||
"You can copy a byte array to memory unsafely:"
|
||||
{ $subsection byte-array>memory } ;
|
||||
{ $subsections byte-array>memory } ;
|
||||
|
||||
ARTICLE: "c-pointers" "Passing pointers to C functions"
|
||||
"The following Factor objects may be passed to C function parameters with pointer types:"
|
||||
|
@ -83,11 +89,11 @@ ARTICLE: "c-pointers" "Passing pointers to C functions"
|
|||
{ "Any data type which defines a method on " { $link >c-ptr } " that returns an instance of one of the above. This includes " { $link "classes.struct" } " and " { $link "specialized-arrays" } "." }
|
||||
}
|
||||
"The class of primitive C pointer types:"
|
||||
{ $subsection c-ptr }
|
||||
{ $subsections c-ptr }
|
||||
"A generic word for converting any object to a C pointer; user-defined types may add methods to this generic word:"
|
||||
{ $subsection >c-ptr }
|
||||
{ $subsections >c-ptr }
|
||||
"More about the " { $link alien } " type:"
|
||||
{ $subsection "aliens" }
|
||||
{ $subsections "aliens" }
|
||||
{ $warning
|
||||
"The Factor garbage collector can move byte arrays around, and code passing byte arrays, or objects backed by byte arrays, must obey important guidelines. See " { $link "byte-arrays-gc" } "." } ;
|
||||
|
||||
|
@ -95,19 +101,21 @@ 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."
|
||||
$nl
|
||||
"Furthermore, Factor's garbage collector can move objects in memory; for a discussion of the consequences, see " { $link "byte-arrays-gc" } "."
|
||||
{ $subsection "c-types-specs" }
|
||||
{ $subsection "c-pointers" }
|
||||
{ $subsection "malloc" }
|
||||
{ $subsection "c-strings" }
|
||||
{ $subsection "c-out-params" }
|
||||
{ $subsections
|
||||
"c-types-specs"
|
||||
"c-pointers"
|
||||
"malloc"
|
||||
"c-strings"
|
||||
"c-out-params"
|
||||
}
|
||||
"Important guidelines for passing data in byte arrays:"
|
||||
{ $subsection "byte-arrays-gc" }
|
||||
{ $subsections "byte-arrays-gc" }
|
||||
"C-style enumerated types are supported:"
|
||||
{ $subsection POSTPONE: C-ENUM: }
|
||||
{ $subsections POSTPONE: C-ENUM: }
|
||||
"C types can be aliased for convenience and consitency with native library documentation:"
|
||||
{ $subsection POSTPONE: TYPEDEF: }
|
||||
{ $subsections POSTPONE: TYPEDEF: }
|
||||
"A utility for defining " { $link "destructors" } " for deallocating memory:"
|
||||
{ $subsection "alien.destructors" }
|
||||
{ $subsections "alien.destructors" }
|
||||
"C struct and union types can be defined with " { $link POSTPONE: STRUCT: } " and " { $link POSTPONE: UNION: } ". See " { $link "classes.struct" } " for details. For passing arrays to and from C, use the " { $link "specialized-arrays" } " vocabulary." ;
|
||||
|
||||
HELP: malloc-string
|
||||
|
@ -142,11 +150,13 @@ $nl
|
|||
"Care must be taken if the C function expects a " { $link char* } " with a length in bytes, rather than a null-terminated " { $link char* } "; passing the result of calling " { $link length } " on the string object will not suffice. This is because a Factor string of " { $emphasis "n" } " characters will not necessarily encode to " { $emphasis "n" } " bytes. The correct idiom for C functions which take a string with a length is to first encode the string using " { $link encode } ", and then pass the resulting byte array together with the length of this byte array."
|
||||
$nl
|
||||
"Sometimes a C function has a parameter type of " { $link 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 }
|
||||
{ $subsections
|
||||
string>alien
|
||||
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 }
|
||||
{ $subsections alien>string }
|
||||
"For example, if a C function returns a " { $link char* } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $link void* } ", and call one of the above words before passing the pointer to " { $link free } "." ;
|
||||
|
||||
|
|
|
@ -25,6 +25,6 @@ HELP: DESTRUCTOR:
|
|||
|
||||
ARTICLE: "alien.destructors" "Alien destructors"
|
||||
"The " { $vocab-link "alien.destructors" } " vocabulary defines a utility parsing word for defining new disposable classes."
|
||||
{ $subsection POSTPONE: DESTRUCTOR: } ;
|
||||
{ $subsections POSTPONE: DESTRUCTOR: } ;
|
||||
|
||||
ABOUT: "alien.destructors"
|
|
@ -56,13 +56,14 @@ HELP: fortran-invoke
|
|||
|
||||
ARTICLE: "alien.fortran" "Fortran FFI"
|
||||
"The " { $vocab-link "alien.fortran" } " vocabulary provides an interface to code in shared libraries written in Fortran."
|
||||
{ $subsection "alien.fortran-types" }
|
||||
{ $subsection "alien.fortran-abis" }
|
||||
{ $subsection add-fortran-library }
|
||||
{ $subsection POSTPONE: LIBRARY: }
|
||||
{ $subsection POSTPONE: FUNCTION: }
|
||||
{ $subsection POSTPONE: SUBROUTINE: }
|
||||
{ $subsection fortran-invoke }
|
||||
;
|
||||
{ $subsections
|
||||
"alien.fortran-types"
|
||||
"alien.fortran-abis"
|
||||
add-fortran-library
|
||||
POSTPONE: LIBRARY:
|
||||
POSTPONE: FUNCTION:
|
||||
POSTPONE: SUBROUTINE:
|
||||
fortran-invoke
|
||||
} ;
|
||||
|
||||
ABOUT: "alien.fortran"
|
||||
|
|
|
@ -65,8 +65,10 @@ HELP: remove-library
|
|||
|
||||
ARTICLE: "loading-libs" "Loading native libraries"
|
||||
"Before calling a C library, you must associate its path name on disk with a logical name which Factor uses to identify the library:"
|
||||
{ $subsection add-library }
|
||||
{ $subsection remove-library }
|
||||
{ $subsections
|
||||
add-library
|
||||
remove-library
|
||||
}
|
||||
"Once a library has been defined, you can try loading it to see if the path name is correct:"
|
||||
{ $subsection load-library }
|
||||
{ $subsections load-library }
|
||||
"If the compiler cannot load a library, or cannot resolve a symbol in a library, a linkage error is reported using the compiler error mechanism (see " { $link "compiler-errors" } "). Once you install the right library, reload the source file containing the " { $link add-library } " form to force the compiler to try loading the library again." ;
|
||||
|
|
|
@ -13,8 +13,10 @@ HELP: ALIEN:
|
|||
{ $notes "Alien objects are invalidated between image saves and loads, and hence source files should not contain alien literals; this word is for interactive use only. See " { $link "alien-expiry" } " for details." } ;
|
||||
|
||||
ARTICLE: "syntax-aliens" "Alien object literal syntax"
|
||||
{ $subsection POSTPONE: ALIEN: }
|
||||
{ $subsection POSTPONE: DLL" } ;
|
||||
{ $subsections
|
||||
POSTPONE: ALIEN:
|
||||
POSTPONE: DLL"
|
||||
} ;
|
||||
|
||||
HELP: LIBRARY:
|
||||
{ $syntax "LIBRARY: name" }
|
||||
|
|
|
@ -61,18 +61,22 @@ ARTICLE: "ascii" "ASCII"
|
|||
"The " { $vocab-link "ascii" } " vocabulary implements support for the legacy ASCII character set. Most applications should use " { $link "unicode" } " instead."
|
||||
$nl
|
||||
"ASCII character classes:"
|
||||
{ $subsection blank? }
|
||||
{ $subsection letter? }
|
||||
{ $subsection LETTER? }
|
||||
{ $subsection digit? }
|
||||
{ $subsection printable? }
|
||||
{ $subsection control? }
|
||||
{ $subsection quotable? }
|
||||
{ $subsection ascii? }
|
||||
{ $subsections
|
||||
blank?
|
||||
letter?
|
||||
LETTER?
|
||||
digit?
|
||||
printable?
|
||||
control?
|
||||
quotable?
|
||||
ascii?
|
||||
}
|
||||
"ASCII case conversion:"
|
||||
{ $subsection ch>lower }
|
||||
{ $subsection ch>upper }
|
||||
{ $subsection >lower }
|
||||
{ $subsection >upper } ;
|
||||
{ $subsections
|
||||
ch>lower
|
||||
ch>upper
|
||||
>lower
|
||||
>upper
|
||||
} ;
|
||||
|
||||
ABOUT: "ascii"
|
||||
|
|
|
@ -36,12 +36,16 @@ HELP: encode-base64-lines
|
|||
ARTICLE: "base64" "Base 64 conversions"
|
||||
"The " { $vocab-link "base64" } " vocabulary implements conversions of sequences to printable characters in base 64. These plain-text representations of binary data may be passed around and converted back to binary data later." $nl
|
||||
"Converting to and from base64 as strings:"
|
||||
{ $subsection >base64 }
|
||||
{ $subsection >base64-lines }
|
||||
{ $subsection base64> }
|
||||
{ $subsections
|
||||
>base64
|
||||
>base64-lines
|
||||
base64>
|
||||
}
|
||||
"Using base64 from streams:"
|
||||
{ $subsection encode-base64 }
|
||||
{ $subsection encode-base64-lines }
|
||||
{ $subsection decode-base64 } ;
|
||||
{ $subsections
|
||||
encode-base64
|
||||
encode-base64-lines
|
||||
decode-base64
|
||||
} ;
|
||||
|
||||
ABOUT: "base64"
|
||||
|
|
|
@ -26,12 +26,16 @@ $nl
|
|||
"Bidirectional assocs implement the entire " { $link "assocs-protocol" } " with the exception of " { $link delete-at } ". Duplicate values are allowed, however value lookups with " { $link value-at } " only return the first key that a given value was stored with."
|
||||
$nl
|
||||
"The class of biassocs:"
|
||||
{ $subsection biassoc }
|
||||
{ $subsection biassoc? }
|
||||
{ $subsections
|
||||
biassoc
|
||||
biassoc?
|
||||
}
|
||||
"Creating new biassocs:"
|
||||
{ $subsection <biassoc> }
|
||||
{ $subsection <bihash> }
|
||||
{ $subsections
|
||||
<biassoc>
|
||||
<bihash>
|
||||
}
|
||||
"Converting existing assocs to biassocs:"
|
||||
{ $subsection >biassoc } ;
|
||||
{ $subsections >biassoc } ;
|
||||
|
||||
ABOUT: "biassocs"
|
||||
|
|
|
@ -33,11 +33,13 @@ HELP: sorted-memq?
|
|||
|
||||
ARTICLE: "binary-search" "Binary search"
|
||||
"The " { $emphasis "binary search" } " algorithm allows elements to be located in sorted sequence in " { $snippet "O(log n)" } " time."
|
||||
{ $subsection search }
|
||||
{ $subsections search }
|
||||
"Variants of sequence words optimized for sorted sequences:"
|
||||
{ $subsection sorted-index }
|
||||
{ $subsection sorted-member? }
|
||||
{ $subsection sorted-memq? }
|
||||
{ $subsections
|
||||
sorted-index
|
||||
sorted-member?
|
||||
sorted-memq?
|
||||
}
|
||||
{ $see-also "order-specifiers" "sequences-sorting" } ;
|
||||
|
||||
ABOUT: "binary-search"
|
||||
|
|
|
@ -10,19 +10,27 @@ $nl
|
|||
"Bit arrays play a special role in the C library interface; they can be used to pass binary data back and forth between Factor and C. See " { $link "c-pointers" } "."
|
||||
$nl
|
||||
"Bit arrays form a class of objects:"
|
||||
{ $subsection bit-array }
|
||||
{ $subsection bit-array? }
|
||||
{ $subsections
|
||||
bit-array
|
||||
bit-array?
|
||||
}
|
||||
"Creating new bit arrays:"
|
||||
{ $subsection >bit-array }
|
||||
{ $subsection <bit-array> }
|
||||
{ $subsections
|
||||
>bit-array
|
||||
<bit-array>
|
||||
}
|
||||
"Efficiently setting and clearing all bits in a bit array:"
|
||||
{ $subsection set-bits }
|
||||
{ $subsection clear-bits }
|
||||
{ $subsections
|
||||
set-bits
|
||||
clear-bits
|
||||
}
|
||||
"Converting between unsigned integers and their binary representation:"
|
||||
{ $subsection integer>bit-array }
|
||||
{ $subsection bit-array>integer }
|
||||
{ $subsections
|
||||
integer>bit-array
|
||||
bit-array>integer
|
||||
}
|
||||
"Bit array literal syntax:"
|
||||
{ $subsection POSTPONE: ?{ } ;
|
||||
{ $subsections POSTPONE: ?{ } ;
|
||||
|
||||
ABOUT: "bit-arrays"
|
||||
|
||||
|
|
|
@ -6,13 +6,17 @@ ARTICLE: "bit-vectors" "Bit vectors"
|
|||
"A bit vector is a resizable mutable sequence of bits. Bit vector words are found in the " { $vocab-link "bit-vectors" } " vocabulary."
|
||||
$nl
|
||||
"Bit vectors form a class:"
|
||||
{ $subsection bit-vector }
|
||||
{ $subsection bit-vector? }
|
||||
{ $subsections
|
||||
bit-vector
|
||||
bit-vector?
|
||||
}
|
||||
"Creating bit vectors:"
|
||||
{ $subsection >bit-vector }
|
||||
{ $subsection <bit-vector> }
|
||||
{ $subsections
|
||||
>bit-vector
|
||||
<bit-vector>
|
||||
}
|
||||
"Literal syntax:"
|
||||
{ $subsection POSTPONE: ?V{ }
|
||||
{ $subsections POSTPONE: ?V{ }
|
||||
"If you don't care about initial capacity, a more elegant way to create a new bit vector is to write:"
|
||||
{ $code "?V{ } clone" } ;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ IN: bootstrap.image
|
|||
|
||||
ARTICLE: "bootstrap.image" "Bootstrapping new images"
|
||||
"A new image can be built from source; this is known as " { $emphasis "bootstrap" } ". Bootstrap is a two-step process. The first stage is the creation of a bootstrap image from a running Factor instance:"
|
||||
{ $subsection make-image }
|
||||
{ $subsections make-image }
|
||||
"The second bootstrapping stage is initiated by running the resulting bootstrap image:"
|
||||
{ $code "./factor -i=boot.x86.32.image" }
|
||||
"This stage loads additional code, compiles all words, and dumps a final " { $snippet "factor.image" } "."
|
||||
|
|
|
@ -24,14 +24,16 @@ HELP: ?box
|
|||
|
||||
ARTICLE: "boxes" "Boxes"
|
||||
"A " { $emphasis "box" } " is a container which can either be empty or hold a single value."
|
||||
{ $subsection box }
|
||||
{ $subsections box }
|
||||
"Creating an empty box:"
|
||||
{ $subsection <box> }
|
||||
{ $subsections <box> }
|
||||
"Storing a value and removing a value from a box:"
|
||||
{ $subsection >box }
|
||||
{ $subsection box> }
|
||||
{ $subsections
|
||||
>box
|
||||
box>
|
||||
}
|
||||
"Safely removing a value:"
|
||||
{ $subsection ?box }
|
||||
{ $subsections ?box }
|
||||
"Testing if a box is full can be done by reading the " { $snippet "occupied" } " slot." ;
|
||||
|
||||
ABOUT: "boxes"
|
||||
|
|
|
@ -520,125 +520,142 @@ HELP: since-1970
|
|||
|
||||
ARTICLE: "calendar" "Calendar"
|
||||
"The two data types used throughout the calendar library:"
|
||||
{ $subsection timestamp }
|
||||
{ $subsection duration }
|
||||
{ $subsections
|
||||
timestamp
|
||||
duration
|
||||
}
|
||||
"Durations represent spans of time:"
|
||||
{ $subsection "using-durations" }
|
||||
{ $subsections "using-durations" }
|
||||
"Arithmetic on timestamps and durations:"
|
||||
{ $subsection "timestamp-arithmetic" }
|
||||
{ $subsections "timestamp-arithmetic" }
|
||||
"Getting the current timestamp:"
|
||||
{ $subsection now }
|
||||
{ $subsection gmt }
|
||||
{ $subsections
|
||||
now
|
||||
gmt
|
||||
}
|
||||
"Converting between timestamps:"
|
||||
{ $subsection >local-time }
|
||||
{ $subsection >gmt }
|
||||
{ $subsections
|
||||
>local-time
|
||||
>gmt
|
||||
}
|
||||
"Converting between timezones:"
|
||||
{ $subsection convert-timezone }
|
||||
{ $subsections convert-timezone }
|
||||
"Timestamps relative to each other:"
|
||||
{ $subsection "relative-timestamps" }
|
||||
{ $subsections "relative-timestamps" }
|
||||
"Operations on units of time:"
|
||||
{ $subsection "years" }
|
||||
{ $subsection "months" }
|
||||
{ $subsection "days" }
|
||||
{ $subsections
|
||||
"years"
|
||||
"months"
|
||||
"days"
|
||||
}
|
||||
"Meta-data about the calendar:"
|
||||
{ $subsection "calendar-facts" }
|
||||
{ $subsections "calendar-facts" }
|
||||
;
|
||||
|
||||
ARTICLE: "timestamp-arithmetic" "Timestamp arithmetic"
|
||||
"Adding timestamps and durations, or durations and durations:"
|
||||
{ $subsection time+ }
|
||||
{ $subsections time+ }
|
||||
"Subtracting:"
|
||||
{ $subsection time- }
|
||||
{ $subsections time- }
|
||||
"Element-wise multiplication:"
|
||||
{ $subsection time* } ;
|
||||
{ $subsections time* } ;
|
||||
|
||||
ARTICLE: "using-durations" "Using durations"
|
||||
"Creating a duration object:"
|
||||
{ $subsection years }
|
||||
{ $subsection months }
|
||||
{ $subsection weeks }
|
||||
{ $subsection days }
|
||||
{ $subsection hours }
|
||||
{ $subsection minutes }
|
||||
{ $subsection seconds }
|
||||
{ $subsection milliseconds }
|
||||
{ $subsection microseconds }
|
||||
{ $subsection nanoseconds }
|
||||
{ $subsection instant }
|
||||
{ $subsections
|
||||
years
|
||||
months
|
||||
weeks
|
||||
days
|
||||
hours
|
||||
minutes
|
||||
seconds
|
||||
milliseconds
|
||||
microseconds
|
||||
nanoseconds
|
||||
instant
|
||||
}
|
||||
"Converting a duration to a number:"
|
||||
{ $subsection duration>years }
|
||||
{ $subsection duration>months }
|
||||
{ $subsection duration>days }
|
||||
{ $subsection duration>hours }
|
||||
{ $subsection duration>minutes }
|
||||
{ $subsection duration>seconds }
|
||||
{ $subsection duration>milliseconds }
|
||||
{ $subsection duration>microseconds }
|
||||
{ $subsection duration>nanoseconds } ;
|
||||
{ $subsections
|
||||
duration>years
|
||||
duration>months
|
||||
duration>days
|
||||
duration>hours
|
||||
duration>minutes
|
||||
duration>seconds
|
||||
duration>milliseconds
|
||||
duration>microseconds
|
||||
duration>nanoseconds
|
||||
} ;
|
||||
|
||||
ARTICLE: "relative-timestamps" "Relative timestamps"
|
||||
"In the future:"
|
||||
{ $subsection hence }
|
||||
{ $subsections hence }
|
||||
"In the past:"
|
||||
{ $subsection ago }
|
||||
{ $subsections ago }
|
||||
"Invert a duration:"
|
||||
{ $subsection before }
|
||||
{ $subsections before }
|
||||
"Days of the week relative to " { $link now } ":"
|
||||
{ $subsection sunday }
|
||||
{ $subsection monday }
|
||||
{ $subsection tuesday }
|
||||
{ $subsection wednesday }
|
||||
{ $subsection thursday }
|
||||
{ $subsection friday }
|
||||
{ $subsection saturday }
|
||||
{ $subsections
|
||||
sunday
|
||||
monday
|
||||
tuesday
|
||||
wednesday
|
||||
thursday
|
||||
friday
|
||||
saturday
|
||||
}
|
||||
"New timestamps relative to calendar events:"
|
||||
{ $subsection beginning-of-year }
|
||||
{ $subsection beginning-of-month }
|
||||
{ $subsection beginning-of-week }
|
||||
{ $subsection midnight }
|
||||
{ $subsection noon }
|
||||
;
|
||||
{ $subsections
|
||||
beginning-of-year
|
||||
beginning-of-month
|
||||
beginning-of-week
|
||||
midnight
|
||||
noon
|
||||
} ;
|
||||
|
||||
ARTICLE: "days" "Day operations"
|
||||
"Naming days:"
|
||||
{ $subsection day-abbreviation2 }
|
||||
{ $subsection day-abbreviations2 }
|
||||
{ $subsection day-abbreviation3 }
|
||||
{ $subsection day-abbreviations3 }
|
||||
{ $subsection day-name }
|
||||
{ $subsection day-names }
|
||||
{ $subsections
|
||||
day-abbreviation2
|
||||
day-abbreviations2
|
||||
day-abbreviation3
|
||||
day-abbreviations3
|
||||
day-name
|
||||
day-names
|
||||
}
|
||||
"Calculating a Julian day number:"
|
||||
{ $subsection julian-day-number }
|
||||
{ $subsections julian-day-number }
|
||||
"Calculate a timestamp:"
|
||||
{ $subsection julian-day-number>date }
|
||||
;
|
||||
{ $subsections julian-day-number>date } ;
|
||||
|
||||
ARTICLE: "calendar-facts" "Calendar facts"
|
||||
"Calendar facts:"
|
||||
{ $subsection average-month }
|
||||
{ $subsection months-per-year }
|
||||
{ $subsection days-per-year }
|
||||
{ $subsection hours-per-year }
|
||||
{ $subsection minutes-per-year }
|
||||
{ $subsection seconds-per-year }
|
||||
{ $subsection days-in-month }
|
||||
{ $subsection day-of-year }
|
||||
{ $subsection day-of-week }
|
||||
;
|
||||
{ $subsections
|
||||
average-month
|
||||
months-per-year
|
||||
days-per-year
|
||||
hours-per-year
|
||||
minutes-per-year
|
||||
seconds-per-year
|
||||
days-in-month
|
||||
day-of-year
|
||||
day-of-week
|
||||
} ;
|
||||
|
||||
ARTICLE: "years" "Year operations"
|
||||
"Leap year predicate:"
|
||||
{ $subsection leap-year? }
|
||||
{ $subsections leap-year? }
|
||||
"Find the number of days in a year:"
|
||||
{ $subsection days-in-year }
|
||||
;
|
||||
{ $subsections days-in-year } ;
|
||||
|
||||
ARTICLE: "months" "Month operations"
|
||||
"Naming months:"
|
||||
{ $subsection month-name }
|
||||
{ $subsection month-names }
|
||||
{ $subsection month-abbreviation }
|
||||
{ $subsection month-abbreviations }
|
||||
;
|
||||
{ $subsections
|
||||
month-name
|
||||
month-names
|
||||
month-abbreviation
|
||||
month-abbreviations
|
||||
} ;
|
||||
|
||||
ABOUT: "calendar"
|
||||
|
|
|
@ -37,10 +37,10 @@ HELP: from
|
|||
ARTICLE: "channels" "Channels"
|
||||
"The " { $vocab-link "channels" } " vocabulary provides a simple abstraction to send and receive objects." $nl
|
||||
"Opening a channel:"
|
||||
{ $subsection <channel> }
|
||||
{ $subsections <channel> }
|
||||
"Sending a message:"
|
||||
{ $subsection to }
|
||||
{ $subsections to }
|
||||
"Receiving a message:"
|
||||
{ $subsection from } ;
|
||||
{ $subsections from } ;
|
||||
|
||||
ABOUT: "channels"
|
||||
|
|
|
@ -6,6 +6,6 @@ HELP: adler-32
|
|||
|
||||
ARTICLE: "checksums.adler-32" "Adler-32 checksum"
|
||||
"The Adler-32 checksum algorithm implements simple and fast checksum. It is used in zlib and rsync."
|
||||
{ $subsection adler-32 } ;
|
||||
{ $subsections adler-32 } ;
|
||||
|
||||
ABOUT: "checksums.adler-32"
|
||||
|
|
|
@ -44,24 +44,29 @@ HELP: fnv1a-1024
|
|||
|
||||
ARTICLE: "checksums.fnv1" "Fowler-Noll-Vo checksum"
|
||||
"The Fowler-Noll-Vo checksum algorithm is another simple and fast checksum. It comes in 32, 64, 128, 256, 512 and 1024-bit versions, each in 1 and 1a variants. The 1a variants tend to produce a slightly better result. See http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash for more details."
|
||||
|
||||
{ $subsection fnv1-32 }
|
||||
{ $subsection fnv1a-32 }
|
||||
|
||||
{ $subsection fnv1-64 }
|
||||
{ $subsection fnv1a-64 }
|
||||
|
||||
{ $subsection fnv1-128 }
|
||||
{ $subsection fnv1a-128 }
|
||||
|
||||
{ $subsection fnv1-256 }
|
||||
{ $subsection fnv1a-256 }
|
||||
|
||||
{ $subsection fnv1-512 }
|
||||
{ $subsection fnv1a-512 }
|
||||
|
||||
{ $subsection fnv1-1024 }
|
||||
{ $subsection fnv1a-1024 }
|
||||
;
|
||||
{ $subsections
|
||||
fnv1-32
|
||||
fnv1a-32
|
||||
}
|
||||
{ $subsections
|
||||
fnv1-64
|
||||
fnv1a-64
|
||||
}
|
||||
{ $subsections
|
||||
fnv1-128
|
||||
fnv1a-128
|
||||
}
|
||||
{ $subsections
|
||||
fnv1-256
|
||||
fnv1a-256
|
||||
}
|
||||
{ $subsections
|
||||
fnv1-512
|
||||
fnv1a-512
|
||||
}
|
||||
{ $subsections
|
||||
fnv1-1024
|
||||
fnv1a-1024
|
||||
} ;
|
||||
|
||||
ABOUT: "checksums.fnv1"
|
||||
|
|
|
@ -6,6 +6,6 @@ HELP: md5
|
|||
|
||||
ARTICLE: "checksums.md5" "MD5 checksum"
|
||||
"The MD5 checksum algorithm implements a one-way hash function. While it is widely used, many weaknesses are known and it should not be used in new applications (" { $url "http://www.schneier.com/blog/archives/2005/03/more_hash_funct.html" } ")."
|
||||
{ $subsection md5 } ;
|
||||
{ $subsections md5 } ;
|
||||
|
||||
ABOUT: "checksums.md5"
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
! Copyright (C) 2009 Doug Coleman.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: byte-arrays checksums checksums.md5 io.encodings.binary
|
||||
io.streams.byte-array kernel math namespaces tools.test ;
|
||||
io.streams.byte-array kernel math namespaces tools.test
|
||||
sequences ;
|
||||
IN: checksums.md5.tests
|
||||
|
||||
[ "d41d8cd98f00b204e9800998ecf8427e" ] [ "" >byte-array md5 checksum-bytes hex-string ] unit-test
|
||||
|
@ -33,3 +34,9 @@ IN: checksums.md5.tests
|
|||
<md5-state> "asdf" binary <byte-reader> add-checksum-stream
|
||||
[ get-checksum ] [ get-checksum ] bi =
|
||||
] unit-test
|
||||
|
||||
[
|
||||
t
|
||||
] [
|
||||
{ "abcd" "efg" } md5 checksum-lines length 16 =
|
||||
] unit-test
|
||||
|
|
|
@ -21,14 +21,16 @@ HELP: unknown-digest
|
|||
|
||||
ARTICLE: "checksums.openssl" "OpenSSL checksums"
|
||||
"The OpenSSL library provides a large number of efficient checksum (message digest) algorithms which may be used independently of its SSL functionality."
|
||||
{ $subsection openssl-checksum }
|
||||
{ $subsections openssl-checksum }
|
||||
"Constructing a checksum from a known name:"
|
||||
{ $subsection <openssl-checksum> }
|
||||
{ $subsections <openssl-checksum> }
|
||||
"Two utility words:"
|
||||
{ $subsection openssl-md5 }
|
||||
{ $subsection openssl-sha1 }
|
||||
{ $subsections
|
||||
openssl-md5
|
||||
openssl-sha1
|
||||
}
|
||||
"An error thrown if the digest name is unrecognized:"
|
||||
{ $subsection unknown-digest }
|
||||
{ $subsections unknown-digest }
|
||||
"An example where we compute the SHA1 checksum of a string using the OpenSSL implementation of SHA1:"
|
||||
{ $example "USING: byte-arrays checksums checksums.openssl ;" "\"hello world\" >byte-array openssl-sha1 checksum-bytes hex-string ." "\"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed\"" }
|
||||
"If we use the Factor implementation, we get the same result, just slightly slower:"
|
||||
|
|
|
@ -10,9 +10,11 @@ HELP: sha-256
|
|||
ARTICLE: "checksums.sha" "SHA-2 checksum"
|
||||
"The SHA family of checksum algorithms are one-way hashes useful for checksumming data. SHA-1 is considered insecure, while SHA-2 It is generally considered to be pretty strong." $nl
|
||||
"SHA-2 checksums:"
|
||||
{ $subsection sha-224 }
|
||||
{ $subsection sha-256 }
|
||||
{ $subsections
|
||||
sha-224
|
||||
sha-256
|
||||
}
|
||||
"SHA-1 checksum:"
|
||||
{ $subsection sha1 } ;
|
||||
{ $subsections sha1 } ;
|
||||
|
||||
ABOUT: "checksums.sha"
|
||||
|
|
|
@ -51,14 +51,20 @@ HELP: rotate-circular
|
|||
ARTICLE: "circular" "Circular sequences"
|
||||
"The " { $vocab-link "circular" } " vocabulary implements the " { $link "sequence-protocol" } " to allow an arbitrary start index and wrap-around indexing." $nl
|
||||
"Creating a new circular object:"
|
||||
{ $subsection <circular> }
|
||||
{ $subsection <circular-string> }
|
||||
{ $subsection <growing-circular> }
|
||||
{ $subsections
|
||||
<circular>
|
||||
<circular-string>
|
||||
<growing-circular>
|
||||
}
|
||||
"Changing the start index:"
|
||||
{ $subsection change-circular-start }
|
||||
{ $subsection rotate-circular }
|
||||
{ $subsections
|
||||
change-circular-start
|
||||
rotate-circular
|
||||
}
|
||||
"Pushing new elements:"
|
||||
{ $subsection push-circular }
|
||||
{ $subsection push-growing-circular } ;
|
||||
{ $subsections
|
||||
push-circular
|
||||
push-growing-circular
|
||||
} ;
|
||||
|
||||
ABOUT: "circular"
|
||||
|
|
|
@ -120,21 +120,25 @@ ARTICLE: "classes.struct.examples" "Struct class examples"
|
|||
|
||||
ARTICLE: "classes.struct.define" "Defining struct classes"
|
||||
"Struct classes are defined using a syntax similar to the " { $link POSTPONE: TUPLE: } " syntax for defining tuple classes:"
|
||||
{ $subsection POSTPONE: STRUCT: }
|
||||
{ $subsections POSTPONE: STRUCT: }
|
||||
"Union structs are also supported, which behave like structs but share the same memory for all the slots."
|
||||
{ $subsection POSTPONE: UNION-STRUCT: } ;
|
||||
{ $subsections POSTPONE: UNION-STRUCT: } ;
|
||||
|
||||
ARTICLE: "classes.struct.create" "Creating instances of structs"
|
||||
"Structs can be allocated with " { $link new } "- and " { $link boa } "-like constructor words. Additional words are provided for building structs from C memory and from existing buffers:"
|
||||
{ $subsection <struct> }
|
||||
{ $subsection <struct-boa> }
|
||||
{ $subsection malloc-struct }
|
||||
{ $subsection memory>struct }
|
||||
{ $subsections
|
||||
<struct>
|
||||
<struct-boa>
|
||||
malloc-struct
|
||||
memory>struct
|
||||
}
|
||||
"When the contents of a struct will be immediately reset, faster primitive words are available that will create a struct without initializing its contents:"
|
||||
{ $subsection (struct) }
|
||||
{ $subsection (malloc-struct) }
|
||||
{ $subsections
|
||||
(struct)
|
||||
(malloc-struct)
|
||||
}
|
||||
"Structs have literal syntax, similar to " { $link POSTPONE: T{ } " for tuples:"
|
||||
{ $subsection POSTPONE: S{ } ;
|
||||
{ $subsections POSTPONE: S{ } ;
|
||||
|
||||
ARTICLE: "classes.struct.c" "Passing structs to C functions"
|
||||
"Structs can be passed and returned by value, or by reference."
|
||||
|
@ -164,9 +168,11 @@ $nl
|
|||
|
||||
ARTICLE: "classes.struct" "Struct classes"
|
||||
"The " { $vocab-link "classes.struct" } " vocabulary implements " { $link struct } " classes. They are similar to " { $link tuple } " classes, but their slots exhibit value semantics, and they are backed by a contiguous structured block of memory. Structs can be used for space-efficient storage of data in the Factor heap, as well as for passing data to and from C libraries using the " { $link "alien" } "."
|
||||
{ $subsection "classes.struct.examples" }
|
||||
{ $subsection "classes.struct.define" }
|
||||
{ $subsection "classes.struct.create" }
|
||||
{ $subsection "classes.struct.c" } ;
|
||||
{ $subsections
|
||||
"classes.struct.examples"
|
||||
"classes.struct.define"
|
||||
"classes.struct.create"
|
||||
"classes.struct.c"
|
||||
} ;
|
||||
|
||||
ABOUT: "classes.struct"
|
||||
|
|
|
@ -41,14 +41,18 @@ HELP: objc-error
|
|||
|
||||
ARTICLE: "cocoa-application-utils" "Cocoa application utilities"
|
||||
"Utilities:"
|
||||
{ $subsection NSApp }
|
||||
{ $subsection add-observer }
|
||||
{ $subsection remove-observer }
|
||||
{ $subsection install-delegate }
|
||||
{ $subsections
|
||||
NSApp
|
||||
add-observer
|
||||
remove-observer
|
||||
install-delegate
|
||||
}
|
||||
"Combinators:"
|
||||
{ $subsection cocoa-app }
|
||||
{ $subsection with-autorelease-pool }
|
||||
{ $subsection with-cocoa } ;
|
||||
{ $subsections
|
||||
cocoa-app
|
||||
with-autorelease-pool
|
||||
with-cocoa
|
||||
} ;
|
||||
|
||||
IN: cocoa.application
|
||||
ABOUT: "cocoa-application-utils"
|
||||
|
|
|
@ -25,15 +25,19 @@ HELP: IMPORT:
|
|||
|
||||
ARTICLE: "objc-calling" "Calling Objective C code"
|
||||
"Before an Objective C class can be used, it must be imported; by default, a small set of common classes are imported automatically, but additional classes can be imported as needed."
|
||||
{ $subsection POSTPONE: IMPORT: }
|
||||
{ $subsections POSTPONE: IMPORT: }
|
||||
"Every imported Objective C class has as corresponding class word in the " { $vocab-link "cocoa.classes" } " vocabulary. Class words push the class object in the stack, allowing class methods to be invoked."
|
||||
$nl
|
||||
"Messages can be sent to classes and instances using a pair of parsing words:"
|
||||
{ $subsection POSTPONE: -> }
|
||||
{ $subsection POSTPONE: SUPER-> }
|
||||
{ $subsections
|
||||
POSTPONE: ->
|
||||
POSTPONE: SUPER->
|
||||
}
|
||||
"These parsing words are actually syntax sugar for a pair of ordinary words; they can be used instead of the parsing words if the selector name is dynamically computed:"
|
||||
{ $subsection send }
|
||||
{ $subsection super-send } ;
|
||||
{ $subsections
|
||||
send
|
||||
super-send
|
||||
} ;
|
||||
|
||||
ARTICLE: "cocoa" "Cocoa bridge"
|
||||
"The " { $vocab-link "cocoa" } " vocabulary implements a Factor-Cocoa bridge for Mac OS X (GNUstep is not supported)."
|
||||
|
@ -41,14 +45,18 @@ $nl
|
|||
"The lowest layer uses the " { $link "alien" } " to define bindings for the various functions in Apple's Objective-C runtime. This is defined in the " { $vocab-link "cocoa.runtime" } " vocabulary."
|
||||
$nl
|
||||
"On top of this, a dynamic message send facility is built:"
|
||||
{ $subsection "objc-calling" }
|
||||
{ $subsection "objc-subclassing" }
|
||||
{ $subsections
|
||||
"objc-calling"
|
||||
"objc-subclassing"
|
||||
}
|
||||
"A utility library is built to faciliate the development of Cocoa applications in Factor:"
|
||||
{ $subsection "cocoa-application-utils" }
|
||||
{ $subsection "cocoa-dialogs" }
|
||||
{ $subsection "cocoa-pasteboard-utils" }
|
||||
{ $subsection "cocoa-view-utils" }
|
||||
{ $subsection "cocoa-window-utils" } ;
|
||||
{ $subsections
|
||||
"cocoa-application-utils"
|
||||
"cocoa-dialogs"
|
||||
"cocoa-pasteboard-utils"
|
||||
"cocoa-view-utils"
|
||||
"cocoa-window-utils"
|
||||
} ;
|
||||
|
||||
IN: cocoa
|
||||
ABOUT: "cocoa"
|
||||
|
|
|
@ -19,11 +19,15 @@ HELP: save-panel
|
|||
|
||||
ARTICLE: "cocoa-dialogs" "Cocoa file dialogs"
|
||||
"Open dialogs:"
|
||||
{ $subsection <NSOpenPanel> }
|
||||
{ $subsection open-panel }
|
||||
{ $subsections
|
||||
<NSOpenPanel>
|
||||
open-panel
|
||||
}
|
||||
"Save dialogs:"
|
||||
{ $subsection <NSSavePanel> }
|
||||
{ $subsection save-panel } ;
|
||||
{ $subsections
|
||||
<NSSavePanel>
|
||||
save-panel
|
||||
} ;
|
||||
|
||||
IN: cocoa.dialogs
|
||||
ABOUT: "cocoa-dialogs"
|
||||
|
|
|
@ -14,9 +14,11 @@ HELP: set-pasteboard-string
|
|||
{ $description "Sets the contents of the pasteboard." } ;
|
||||
|
||||
ARTICLE: "cocoa-pasteboard-utils" "Cocoa pasteboard utilities"
|
||||
{ $subsection pasteboard-string? }
|
||||
{ $subsection pasteboard-string }
|
||||
{ $subsection set-pasteboard-string } ;
|
||||
{ $subsections
|
||||
pasteboard-string?
|
||||
pasteboard-string
|
||||
set-pasteboard-string
|
||||
} ;
|
||||
|
||||
IN: cocoa.pasteboard
|
||||
ABOUT: "cocoa-pasteboard-utils"
|
||||
|
|
|
@ -37,9 +37,9 @@ HELP: CLASS:
|
|||
|
||||
ARTICLE: "objc-subclassing" "Subclassing Objective C classes"
|
||||
"Objective C classes can be subclassed, with new methods defined in Factor, using a parsing word:"
|
||||
{ $subsection POSTPONE: CLASS: }
|
||||
{ $subsections POSTPONE: CLASS: }
|
||||
"This word is actually syntax sugar for an ordinary word:"
|
||||
{ $subsection define-objc-class }
|
||||
{ $subsections define-objc-class }
|
||||
"Objective C class definitions are saved in the image. If the image is saved and Factor is restarted with the saved image, custom class definitions are made available to the Objective C runtime when they are first accessed from within Factor." ;
|
||||
|
||||
IN: cocoa.subclassing
|
||||
|
|
|
@ -14,9 +14,11 @@ HELP: mouse-location
|
|||
{ $description "Outputs the current mouse location." } ;
|
||||
|
||||
ARTICLE: "cocoa-view-utils" "Cocoa view utilities"
|
||||
{ $subsection <GLView> }
|
||||
{ $subsection view-dim }
|
||||
{ $subsection mouse-location } ;
|
||||
{ $subsections
|
||||
<GLView>
|
||||
view-dim
|
||||
mouse-location
|
||||
} ;
|
||||
|
||||
IN: cocoa.views
|
||||
ABOUT: "cocoa-view-utils"
|
||||
|
|
|
@ -10,8 +10,10 @@ HELP: <ViewWindow>
|
|||
{ $description "Creates a new " { $snippet "NSWindow" } " with the specified dimensions, containing the given view." } ;
|
||||
|
||||
ARTICLE: "cocoa-window-utils" "Cocoa window utilities"
|
||||
{ $subsection <NSWindow> }
|
||||
{ $subsection <ViewWindow> } ;
|
||||
{ $subsections
|
||||
<NSWindow>
|
||||
<ViewWindow>
|
||||
} ;
|
||||
|
||||
IN: cocoa.windows
|
||||
ABOUT: "cocoa-window-utils"
|
||||
|
|
|
@ -13,7 +13,7 @@ HELP: >rgba
|
|||
|
||||
ARTICLE: "colors.protocol" "Color protocol"
|
||||
"Abstract superclass for colors:"
|
||||
{ $subsection color }
|
||||
{ $subsections color }
|
||||
"All color objects must are required to implement a method on the " { $link >rgba } " generic word."
|
||||
$nl
|
||||
"Optionally, they can provide methods on the accessors " { $link red>> } ", " { $link green>> } ", " { $link blue>> } " and " { $link alpha>> } ", either by defining slots with the appropriate names, or with methods which calculate the color component values. The accessors should return color components which are real numbers in the range between 0 and 1."
|
||||
|
@ -24,15 +24,19 @@ ARTICLE: "colors" "Colors"
|
|||
"The " { $vocab-link "colors" } " vocabulary defines a protocol for colors, with a concrete implementation for RGBA colors. This vocabulary is used by " { $vocab-link "io.styles" } ", " { $vocab-link "ui" } " and other vocabularies, but it is independent of them."
|
||||
$nl
|
||||
"RGBA colors with floating point components in the range " { $snippet "[0,1]" } ":"
|
||||
{ $subsection rgba }
|
||||
{ $subsection <rgba> }
|
||||
{ $subsections
|
||||
rgba
|
||||
<rgba>
|
||||
}
|
||||
"Converting a color to RGBA:"
|
||||
{ $subsection >rgba }
|
||||
{ $subsections >rgba }
|
||||
"Extracting RGBA components of colors:"
|
||||
{ $subsection >rgba-components }
|
||||
{ $subsections >rgba-components }
|
||||
"Further topics:"
|
||||
{ $subsection "colors.protocol" }
|
||||
{ $subsection "colors.constants" }
|
||||
{ $subsections
|
||||
"colors.protocol"
|
||||
"colors.constants"
|
||||
}
|
||||
{ $vocab-subsection "Grayscale colors" "colors.gray" }
|
||||
{ $vocab-subsection "HSV colors" "colors.hsv" } ;
|
||||
|
||||
|
|
|
@ -24,8 +24,10 @@ HELP: COLOR:
|
|||
|
||||
ARTICLE: "colors.constants" "Standard color database"
|
||||
"The " { $vocab-link "colors.constants" } " vocabulary bundles the X11 " { $snippet "rgb.txt" } " database and Factor's " { $snippet "factor-colors.txt" } " theme database to provide words for looking up color values by name."
|
||||
{ $subsection named-color }
|
||||
{ $subsection named-colors }
|
||||
{ $subsection POSTPONE: COLOR: } ;
|
||||
{ $subsections
|
||||
named-color
|
||||
named-colors
|
||||
POSTPONE: COLOR:
|
||||
} ;
|
||||
|
||||
ABOUT: "colors.constants"
|
|
@ -3,7 +3,9 @@ IN: colors.gray
|
|||
|
||||
ARTICLE: "colors.gray" "Grayscale colors"
|
||||
"The " { $vocab-link "colors.gray" } " vocabulary implements grayscale colors. These colors hold a single value, and respond to " { $link red>> } ", " { $link green>> } ", " { $link blue>> } " with that value. They also have an independent alpha channel, " { $link alpha>> } "."
|
||||
{ $subsection gray }
|
||||
{ $subsection <gray> } ;
|
||||
{ $subsections
|
||||
gray
|
||||
<gray>
|
||||
} ;
|
||||
|
||||
ABOUT: "colors.gray"
|
|
@ -6,8 +6,10 @@ HELP: hsva
|
|||
|
||||
ARTICLE: "colors.hsv" "HSV colors"
|
||||
"The " { $vocab-link "colors.hsv" } " vocabulary implements colors specified by their hue, saturation, and value, together with an alpha channel."
|
||||
{ $subsection hsva }
|
||||
{ $subsection <hsva> }
|
||||
{ $subsections
|
||||
hsva
|
||||
<hsva>
|
||||
}
|
||||
{ $see-also "colors" } ;
|
||||
|
||||
ABOUT: "colors.hsv"
|
|
@ -25,9 +25,11 @@ HELP: <flipped>
|
|||
|
||||
ARTICLE: "columns" "Column sequences"
|
||||
"A " { $emphasis "column" } " presents a column of a matrix represented as a sequence of rows:"
|
||||
{ $subsection column }
|
||||
{ $subsection <column> }
|
||||
{ $subsections
|
||||
column
|
||||
<column>
|
||||
}
|
||||
"A utility word:"
|
||||
{ $subsection <flipped> } ;
|
||||
{ $subsections <flipped> } ;
|
||||
|
||||
ABOUT: "columns"
|
||||
|
|
|
@ -51,18 +51,24 @@ HELP: n||
|
|||
ARTICLE: "combinators.short-circuit" "Short-circuit combinators"
|
||||
"The " { $vocab-link "combinators.short-circuit" } " vocabulary stops a computation early once a condition is met." $nl
|
||||
"AND combinators:"
|
||||
{ $subsection 0&& }
|
||||
{ $subsection 1&& }
|
||||
{ $subsection 2&& }
|
||||
{ $subsection 3&& }
|
||||
{ $subsections
|
||||
0&&
|
||||
1&&
|
||||
2&&
|
||||
3&&
|
||||
}
|
||||
"OR combinators:"
|
||||
{ $subsection 0|| }
|
||||
{ $subsection 1|| }
|
||||
{ $subsection 2|| }
|
||||
{ $subsection 3|| }
|
||||
{ $subsections
|
||||
0||
|
||||
1||
|
||||
2||
|
||||
3||
|
||||
}
|
||||
"Generalized combinators:"
|
||||
{ $subsection n&& }
|
||||
{ $subsection n|| }
|
||||
{ $subsections
|
||||
n&&
|
||||
n||
|
||||
}
|
||||
;
|
||||
|
||||
ABOUT: "combinators.short-circuit"
|
||||
|
|
|
@ -31,8 +31,8 @@ ARTICLE: "combinators.short-circuit.smart" "Smart short-circuit combinators"
|
|||
"The " { $vocab-link "combinators.short-circuit.smart" } " vocabulary is similar to " { $vocab-link "combinators.short-circuit" } " except the combinators here infer the number of inputs that the sequence of quotations takes."
|
||||
$nl
|
||||
"Generalized AND:"
|
||||
{ $subsection && }
|
||||
{ $subsections && }
|
||||
"Generalized OR:"
|
||||
{ $subsection || } ;
|
||||
{ $subsections || } ;
|
||||
|
||||
ABOUT: "combinators.short-circuit.smart"
|
||||
|
|
|
@ -119,20 +119,26 @@ HELP: keep-inputs
|
|||
ARTICLE: "combinators.smart" "Smart combinators"
|
||||
"A " { $emphasis "smart combinator" } " is a macro which reflects on the stack effect of an input quotation. The " { $vocab-link "combinators.smart" } " vocabulary implements a few simple smart combinators which look at the static stack effects of input quotations and generate code which produces or consumes the relevant number of stack values." $nl
|
||||
"Call a quotation and discard all output values or preserve all input values:"
|
||||
{ $subsection drop-outputs }
|
||||
{ $subsection keep-inputs }
|
||||
{ $subsections
|
||||
drop-outputs
|
||||
keep-inputs
|
||||
}
|
||||
"Take all input values from a sequence:"
|
||||
{ $subsection input<sequence }
|
||||
{ $subsections input<sequence }
|
||||
"Store all output values to a sequence:"
|
||||
{ $subsection output>sequence }
|
||||
{ $subsection output>array }
|
||||
{ $subsections
|
||||
output>sequence
|
||||
output>array
|
||||
}
|
||||
"Reducing the set of output values:"
|
||||
{ $subsection reduce-outputs }
|
||||
{ $subsections reduce-outputs }
|
||||
"Summing output values:"
|
||||
{ $subsection sum-outputs }
|
||||
{ $subsections sum-outputs }
|
||||
"Concatenating output values:"
|
||||
{ $subsection append-outputs }
|
||||
{ $subsection append-outputs-as }
|
||||
{ $subsections
|
||||
append-outputs
|
||||
append-outputs-as
|
||||
}
|
||||
"New smart combinators can be created by defining " { $link "macros" } " which call " { $link infer } "." ;
|
||||
|
||||
ABOUT: "combinators.smart"
|
||||
|
|
|
@ -25,7 +25,7 @@ HELP: (command-line)
|
|||
{ $description "Outputs the command line parameters which were passed to the Factor VM on startup." } ;
|
||||
|
||||
HELP: command-line
|
||||
{ $var-description "The command line parameters which follow the name of the script on the command line." } ;
|
||||
{ $var-description "When Factor is run with a script, this variable contains command line parameters which follow the name of the script on the command line. In deployed applications, it contains the entire command line. In all other cases it is set to " { $link f } "." } ;
|
||||
|
||||
HELP: main-vocab-hook
|
||||
{ $var-description "Global variable holding a quotation which outputs a vocabulary name. UI backends set this so that the UI can automatically start if the prerequisites are met (for example, " { $snippet "$DISPLAY" } " being set on X11)." } ;
|
||||
|
@ -99,26 +99,28 @@ ARTICLE: "factor-boot-rc" "Bootstrap initialization file"
|
|||
"The botstrap initialization file is named " { $snippet "factor-boot-rc" } " on Windows and " { $snippet ".factor-boot-rc" } " on Unix. This file can contain " { $link require } " calls for vocabularies you use frequently, and other such long-running tasks that you do not want to perform every time Factor starts."
|
||||
$nl
|
||||
"A word to run this file from an existing Factor session:"
|
||||
{ $subsection run-bootstrap-init }
|
||||
{ $subsections run-bootstrap-init }
|
||||
"For example, if you changed " { $snippet ".factor-boot-rc" } " and do not want to bootstrap again, you can just invoke " { $link run-bootstrap-init } " in the listener." ;
|
||||
|
||||
ARTICLE: "factor-rc" "Startup initialization file"
|
||||
"The startup initialization file is named " { $snippet "factor-rc" } " on Windows and " { $snippet ".factor-rc" } " on Unix. If it exists, it is run every time Factor starts."
|
||||
$nl
|
||||
"A word to run this file from an existing Factor session:"
|
||||
{ $subsection run-user-init } ;
|
||||
{ $subsections run-user-init } ;
|
||||
|
||||
ARTICLE: "factor-roots" "Additional vocabulary roots file"
|
||||
"The vocabulary roots file is named " { $snippet "factor-roots" } " on Windows and " { $snippet ".factor-roots" } " on Unix. If it exists, it is loaded every time Factor starts. It contains a newline-separated list of " { $link "vocabs.roots" } "."
|
||||
$nl
|
||||
"A word to run this file from an existing Factor session:"
|
||||
{ $subsection load-vocab-roots } ;
|
||||
{ $subsections load-vocab-roots } ;
|
||||
|
||||
ARTICLE: "rc-files" "Running code on startup"
|
||||
"Factor looks for three optional files in your home directory."
|
||||
{ $subsection "factor-boot-rc" }
|
||||
{ $subsection "factor-rc" }
|
||||
{ $subsection "factor-roots" }
|
||||
{ $subsections
|
||||
"factor-boot-rc"
|
||||
"factor-rc"
|
||||
"factor-roots"
|
||||
}
|
||||
"The " { $snippet "-no-user-init" } " command line switch will inhibit loading running of these files."
|
||||
$nl
|
||||
"If you are unsure where the files should be located, evaluate the following code:"
|
||||
|
@ -127,19 +129,17 @@ $nl
|
|||
"\"factor-rc\" rc-path print"
|
||||
"\"factor-boot-rc\" rc-path print"
|
||||
}
|
||||
"Here is an example " { $snippet ".factor-boot-rc" } " which sets up GVIM editor integration, adds an additional vocabulary root (see " { $link "vocabs.roots" } "), and increases the font size in the UI by setting the DPI (dots-per-inch) variable:"
|
||||
"Here is an example " { $snippet ".factor-boot-rc" } " which sets up GVIM editor integration:"
|
||||
{ $code
|
||||
"USING: editors.gvim vocabs.loader ui.freetype namespaces sequences ;"
|
||||
"USING: editors.gvim namespaces ;"
|
||||
"\"/opt/local/bin\" \\ gvim-path set-global"
|
||||
"\"/home/jane/src/\" vocab-roots get push"
|
||||
"100 dpi set-global"
|
||||
} ;
|
||||
|
||||
ARTICLE: "cli" "Command line arguments"
|
||||
"Factor command line usage:"
|
||||
{ $code "factor [system switches...] [script args...]" }
|
||||
"Zero or more system switches can be passed in, followed by an optional script file name. If the script file is specified, it will be run on startup, any arguments after the script file are stored in a variable, with no further processing by Factor itself:"
|
||||
{ $subsection command-line }
|
||||
{ $code "factor [VM args...] [script] [args...]" }
|
||||
"Zero or more VM arguments can be passed in, followed by an optional script file name. If the script file is specified, it will be run on startup, any arguments after the script file are stored in the following variable, with no further processing by Factor itself:"
|
||||
{ $subsections command-line }
|
||||
"Instead of running a script, it is also possible to run a vocabulary; this invokes the vocabulary's " { $link POSTPONE: MAIN: } " word:"
|
||||
{ $code "factor [system switches...] -run=<vocab name>" }
|
||||
"If no script file or " { $snippet "-run=" } " switch is specified, Factor will start " { $link "listener" } " or " { $link "ui-tools" } ", depending on the operating system."
|
||||
|
@ -152,12 +152,14 @@ $nl
|
|||
{ { $snippet "-no-" { $emphasis "foo" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $link f } }
|
||||
{ { $snippet "-" { $emphasis "foo" } "=" { $emphasis "bar" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $snippet "\"" { $emphasis "bar" } "\"" } }
|
||||
}
|
||||
{ $subsection "runtime-cli-args" }
|
||||
{ $subsection "bootstrap-cli-args" }
|
||||
{ $subsection "standard-cli-args" }
|
||||
{ $subsections
|
||||
"runtime-cli-args"
|
||||
"bootstrap-cli-args"
|
||||
"standard-cli-args"
|
||||
}
|
||||
"The raw list of command line arguments can also be obtained and inspected directly:"
|
||||
{ $subsection (command-line) }
|
||||
{ $subsections (command-line) }
|
||||
"There is a way to override the default vocabulary to run on startup, if no script name or " { $snippet "-run" } " switch is specified:"
|
||||
{ $subsection main-vocab-hook } ;
|
||||
{ $subsections main-vocab-hook } ;
|
||||
|
||||
ABOUT: "cli"
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
! Copyright (C) 2008, 2009 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel math namespaces assocs hashtables sequences arrays
|
||||
accessors vectors combinators sets classes cpu.architecture
|
||||
compiler.cfg compiler.cfg.registers compiler.cfg.instructions
|
||||
compiler.cfg.def-use compiler.cfg.copy-prop compiler.cfg.rpo
|
||||
compiler.cfg.liveness ;
|
||||
accessors words vectors combinators combinators.short-circuit
|
||||
sets classes layouts cpu.architecture
|
||||
compiler.cfg
|
||||
compiler.cfg.rpo
|
||||
compiler.cfg.def-use
|
||||
compiler.cfg.liveness
|
||||
compiler.cfg.copy-prop
|
||||
compiler.cfg.registers
|
||||
compiler.cfg.comparisons
|
||||
compiler.cfg.instructions
|
||||
compiler.cfg.representations.preferred ;
|
||||
IN: compiler.cfg.alias-analysis
|
||||
|
||||
! We try to eliminate redundant slot operations using some simple heuristics.
|
||||
|
@ -77,10 +84,15 @@ SYMBOL: acs>vregs
|
|||
|
||||
: ac>vregs ( ac -- vregs ) acs>vregs get at ;
|
||||
|
||||
: aliases ( vreg -- vregs )
|
||||
GENERIC: aliases ( vreg -- vregs )
|
||||
|
||||
M: integer aliases
|
||||
#! All vregs which may contain the same value as vreg.
|
||||
vreg>ac ac>vregs ;
|
||||
|
||||
M: word aliases
|
||||
1array ;
|
||||
|
||||
: each-alias ( vreg quot -- )
|
||||
[ aliases ] dip each ; inline
|
||||
|
||||
|
@ -181,7 +193,6 @@ SYMBOL: constants
|
|||
#! assigned by an ##load-immediate.
|
||||
resolve constants get at ;
|
||||
|
||||
! We treat slot accessors and stack traffic alike
|
||||
GENERIC: insn-slot# ( insn -- slot#/f )
|
||||
GENERIC: insn-object ( insn -- vreg )
|
||||
|
||||
|
@ -190,7 +201,7 @@ M: ##slot-imm insn-slot# slot>> ;
|
|||
M: ##set-slot insn-slot# slot>> constant ;
|
||||
M: ##set-slot-imm insn-slot# slot>> ;
|
||||
M: ##alien-global insn-slot# [ library>> ] [ symbol>> ] bi 2array ;
|
||||
M: ##vm-field-ptr insn-slot# field-name>> ; ! is this right?
|
||||
M: ##vm-field-ptr insn-slot# field-name>> ;
|
||||
|
||||
M: ##slot insn-object obj>> resolve ;
|
||||
M: ##slot-imm insn-object obj>> resolve ;
|
||||
|
@ -206,18 +217,33 @@ M: ##vm-field-ptr insn-object drop \ ##vm-field-ptr ;
|
|||
H{ } clone live-slots set
|
||||
H{ } clone constants set
|
||||
H{ } clone copies set
|
||||
|
||||
|
||||
0 ac-counter set
|
||||
next-ac heap-ac set
|
||||
|
||||
\ ##vm-field-ptr set-new-ac
|
||||
\ ##alien-global set-new-ac
|
||||
|
||||
dup local-live-in [ set-heap-ac ] each ;
|
||||
|
||||
GENERIC: analyze-aliases* ( insn -- insn' )
|
||||
|
||||
M: insn analyze-aliases*
|
||||
dup defs-vreg [ set-heap-ac ] when* ;
|
||||
! If an instruction defines a value with a non-integer
|
||||
! representation it means that the value will be boxed
|
||||
! anywhere its used as a tagged pointer. Boxing allocates
|
||||
! a new value, except boxing instructions haven't been
|
||||
! inserted yet.
|
||||
dup defs-vreg [
|
||||
over defs-vreg-rep int-rep eq?
|
||||
[ set-heap-ac ] [ set-new-ac ] if
|
||||
] when* ;
|
||||
|
||||
M: ##phi analyze-aliases*
|
||||
dup defs-vreg set-heap-ac ;
|
||||
|
||||
M: ##load-immediate analyze-aliases*
|
||||
call-next-method
|
||||
dup [ val>> ] [ dst>> ] bi constants get set-at ;
|
||||
|
||||
M: ##allocation analyze-aliases*
|
||||
|
@ -249,6 +275,19 @@ M: ##copy analyze-aliases*
|
|||
#! vreg, since they both contain the same value.
|
||||
dup record-copy ;
|
||||
|
||||
: useless-compare? ( insn -- ? )
|
||||
{
|
||||
[ cc>> cc= eq? ]
|
||||
[ [ src1>> ] [ src2>> ] bi [ resolve vreg>ac ] bi@ = not ]
|
||||
} 1&& ; inline
|
||||
|
||||
M: ##compare analyze-aliases*
|
||||
call-next-method
|
||||
dup useless-compare? [
|
||||
dst>> \ f tag-number \ ##load-immediate new-insn
|
||||
analyze-aliases*
|
||||
] when ;
|
||||
|
||||
: analyze-aliases ( insns -- insns' )
|
||||
[ insn# set analyze-aliases* ] map-index sift ;
|
||||
|
||||
|
|
|
@ -159,9 +159,12 @@ IN: compiler.cfg.builder.tests
|
|||
{ pinned-c-ptr class fixnum } \ set-alien-cell '[ _ declare _ execute ] unit-test-cfg
|
||||
] each
|
||||
|
||||
: contains-insn? ( quot insn-check -- ? )
|
||||
: count-insns ( quot insn-check -- ? )
|
||||
[ test-mr [ instructions>> ] map ] dip
|
||||
'[ _ any? ] any? ; inline
|
||||
'[ _ count ] sigma ; inline
|
||||
|
||||
: contains-insn? ( quot insn-check -- ? )
|
||||
count-insns 0 > ; inline
|
||||
|
||||
[ t ] [ [ swap ] [ ##replace? ] contains-insn? ] unit-test
|
||||
|
||||
|
@ -197,14 +200,16 @@ IN: compiler.cfg.builder.tests
|
|||
[ f t ] [
|
||||
[ { byte-array fixnum } declare alien-cell 4 alien-float ]
|
||||
[ [ ##box-alien? ] contains-insn? ]
|
||||
[ [ ##box-float? ] contains-insn? ] bi
|
||||
[ [ ##allot? ] contains-insn? ] bi
|
||||
] unit-test
|
||||
|
||||
[ f t ] [
|
||||
[ { byte-array fixnum } declare alien-cell { simple-alien } declare 4 alien-float ]
|
||||
[ [ ##box-alien? ] contains-insn? ]
|
||||
[ [ ##box-float? ] contains-insn? ] bi
|
||||
[ [ ##allot? ] contains-insn? ] bi
|
||||
] unit-test
|
||||
|
||||
[ 1 ] [ [ dup float+ ] [ ##alien-double? ] count-insns ] unit-test
|
||||
] when
|
||||
|
||||
! Regression. Make sure everything is inlined correctly
|
||||
|
|
|
@ -9,6 +9,9 @@ SYMBOLS:
|
|||
cc< cc<= cc= cc> cc>= cc<> cc<>=
|
||||
cc/< cc/<= cc/= cc/> cc/>= cc/<> cc/<>= ;
|
||||
|
||||
SYMBOLS:
|
||||
vcc-all vcc-notall vcc-any vcc-none ;
|
||||
|
||||
: negate-cc ( cc -- cc' )
|
||||
H{
|
||||
{ cc< cc/< }
|
||||
|
@ -27,6 +30,14 @@ SYMBOLS:
|
|||
{ cc/<>= cc<>= }
|
||||
} at ;
|
||||
|
||||
: negate-vcc ( cc -- cc' )
|
||||
H{
|
||||
{ vcc-all vcc-notall }
|
||||
{ vcc-any vcc-none }
|
||||
{ vcc-none vcc-any }
|
||||
{ vcc-notall vcc-all }
|
||||
} at ;
|
||||
|
||||
: swap-cc ( cc -- cc' )
|
||||
H{
|
||||
{ cc< cc> }
|
||||
|
|
|
@ -16,7 +16,7 @@ V{
|
|||
} 0 test-bb
|
||||
|
||||
V{
|
||||
T{ ##box-float f 0 1 }
|
||||
T{ ##box-alien f 0 1 }
|
||||
} 1 test-bb
|
||||
|
||||
0 1 edge
|
||||
|
|
|
@ -49,24 +49,9 @@ insn-classes get [
|
|||
[ ##load-reference ]
|
||||
} cond ;
|
||||
|
||||
: ^^unbox-c-ptr ( src class -- dst )
|
||||
[ next-vreg dup ] 2dip next-vreg ##unbox-c-ptr ;
|
||||
|
||||
: ^^allot-tuple ( n -- dst )
|
||||
2 + cells tuple ^^allot ;
|
||||
|
||||
: ^^allot-array ( n -- dst )
|
||||
2 + cells array ^^allot ;
|
||||
|
||||
: ^^allot-byte-array ( n -- dst )
|
||||
2 cells + byte-array ^^allot ;
|
||||
|
||||
: ^^offset>slot ( slot -- vreg' )
|
||||
cell 4 = [ 1 ^^shr-imm ] [ any-rep ^^copy ] if ;
|
||||
|
||||
: ^^tag-offset>slot ( slot tag -- vreg' )
|
||||
[ ^^offset>slot ] dip ^^sub-imm ;
|
||||
|
||||
: ^^tag-fixnum ( src -- dst )
|
||||
tag-bits get ^^shl-imm ;
|
||||
|
||||
|
|
|
@ -199,15 +199,6 @@ def: dst/int-rep
|
|||
use: src/int-rep ;
|
||||
|
||||
! Float arithmetic
|
||||
PURE-INSN: ##unbox-float
|
||||
def: dst/double-rep
|
||||
use: src/int-rep ;
|
||||
|
||||
PURE-INSN: ##box-float
|
||||
def: dst/int-rep
|
||||
use: src/double-rep
|
||||
temp: temp/int-rep ;
|
||||
|
||||
PURE-INSN: ##add-float
|
||||
def: dst/double-rep
|
||||
use: src1/double-rep src2/double-rep ;
|
||||
|
@ -266,19 +257,11 @@ def: dst/double-rep
|
|||
use: src/int-rep ;
|
||||
|
||||
! SIMD operations
|
||||
|
||||
PURE-INSN: ##box-vector
|
||||
def: dst/int-rep
|
||||
use: src
|
||||
literal: rep
|
||||
temp: temp/int-rep ;
|
||||
|
||||
PURE-INSN: ##unbox-vector
|
||||
PURE-INSN: ##zero-vector
|
||||
def: dst
|
||||
use: src/int-rep
|
||||
literal: rep ;
|
||||
|
||||
PURE-INSN: ##zero-vector
|
||||
PURE-INSN: ##fill-vector
|
||||
def: dst
|
||||
literal: rep ;
|
||||
|
||||
|
@ -297,6 +280,29 @@ def: dst
|
|||
use: src
|
||||
literal: shuffle rep ;
|
||||
|
||||
PURE-INSN: ##compare-vector
|
||||
def: dst
|
||||
use: src1 src2
|
||||
temp: temp
|
||||
literal: rep cc ;
|
||||
|
||||
PURE-INSN: ##test-vector
|
||||
def: dst/int-rep
|
||||
use: src1
|
||||
temp: temp/int-rep
|
||||
literal: rep vcc ;
|
||||
|
||||
INSN: ##test-vector-branch
|
||||
use: src1
|
||||
temp: temp/int-rep
|
||||
literal: rep vcc ;
|
||||
|
||||
INSN: _test-vector-branch
|
||||
literal: label
|
||||
use: src1
|
||||
temp: temp/int-rep
|
||||
literal: rep vcc ;
|
||||
|
||||
PURE-INSN: ##add-vector
|
||||
def: dst
|
||||
use: src1 src2
|
||||
|
@ -402,6 +408,11 @@ def: dst
|
|||
use: src1 src2
|
||||
literal: rep ;
|
||||
|
||||
PURE-INSN: ##not-vector
|
||||
def: dst
|
||||
use: src
|
||||
literal: rep ;
|
||||
|
||||
PURE-INSN: ##shl-vector
|
||||
def: dst
|
||||
use: src1 src2/int-scalar-rep
|
||||
|
@ -738,13 +749,11 @@ literal: n ;
|
|||
|
||||
UNION: ##allocation
|
||||
##allot
|
||||
##box-float
|
||||
##box-vector
|
||||
##box-alien
|
||||
##box-displaced-alien ;
|
||||
|
||||
! For alias analysis
|
||||
UNION: ##read ##slot ##slot-imm ;
|
||||
UNION: ##read ##slot ##slot-imm ##vm-field-ptr ##alien-global ;
|
||||
UNION: ##write ##set-slot ##set-slot-imm ;
|
||||
|
||||
! Instructions that kill all live vregs but cannot trigger GC
|
||||
|
@ -766,6 +775,8 @@ UNION: kill-vreg-insn
|
|||
UNION: def-is-use-insn
|
||||
##box-alien
|
||||
##box-displaced-alien
|
||||
##compare-vector
|
||||
##not-vector
|
||||
##string-nth
|
||||
##unbox-any-c-ptr ;
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
USING: accessors kernel sequences alien math classes.algebra fry
|
||||
locals combinators combinators.short-circuit cpu.architecture
|
||||
compiler.tree.propagation.info compiler.cfg.hats
|
||||
compiler.cfg.stacks compiler.cfg.instructions
|
||||
compiler.cfg.utilities compiler.cfg.builder.blocks ;
|
||||
compiler.cfg.registers compiler.cfg.stacks
|
||||
compiler.cfg.instructions compiler.cfg.utilities
|
||||
compiler.cfg.builder.blocks ;
|
||||
IN: compiler.cfg.intrinsics.alien
|
||||
|
||||
: emit-<displaced-alien>? ( node -- ? )
|
||||
|
@ -33,6 +34,9 @@ IN: compiler.cfg.intrinsics.alien
|
|||
[ second class>> fixnum class<= ]
|
||||
bi and ;
|
||||
|
||||
: ^^unbox-c-ptr ( src class -- dst )
|
||||
[ next-vreg dup ] 2dip next-vreg ##unbox-c-ptr ;
|
||||
|
||||
: prepare-alien-accessor ( info -- ptr-vreg offset )
|
||||
class>> [ 2inputs ^^untag-fixnum swap ] dip ^^unbox-c-ptr ^^add 0 ;
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ IN: compiler.cfg.intrinsics.allot
|
|||
: tuple-slot-regs ( layout -- vregs )
|
||||
[ second ds-load ] [ ^^load-literal ] bi prefix ;
|
||||
|
||||
: ^^allot-tuple ( n -- dst )
|
||||
2 + cells tuple ^^allot ;
|
||||
|
||||
: emit-<tuple-boa> ( node -- )
|
||||
dup node-input-infos last literal>>
|
||||
dup array? [
|
||||
|
@ -36,6 +39,9 @@ IN: compiler.cfg.intrinsics.allot
|
|||
: expand-<array>? ( obj -- ? )
|
||||
dup integer? [ 0 8 between? ] [ drop f ] if ;
|
||||
|
||||
: ^^allot-array ( n -- dst )
|
||||
2 + cells array ^^allot ;
|
||||
|
||||
:: emit-<array> ( node -- )
|
||||
[let | len [ node node-input-infos first literal>> ] |
|
||||
len expand-<array>? [
|
||||
|
@ -54,6 +60,9 @@ IN: compiler.cfg.intrinsics.allot
|
|||
|
||||
: bytes>cells ( m -- n ) cell align cell /i ;
|
||||
|
||||
: ^^allot-byte-array ( n -- dst )
|
||||
2 cells + byte-array ^^allot ;
|
||||
|
||||
: emit-allot-byte-array ( len -- dst )
|
||||
ds-drop
|
||||
dup ^^allot-byte-array
|
||||
|
|
|
@ -171,6 +171,21 @@ IN: compiler.cfg.intrinsics
|
|||
{ math.vectors.simd.intrinsics:(simd-vbitandn) [ [ ^^andn-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vbitor) [ [ ^^or-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vbitxor) [ [ ^^xor-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vbitnot) [ [ ^^not-vector ] emit-unary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vand) [ [ ^^and-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vandn) [ [ ^^andn-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vor) [ [ ^^or-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vxor) [ [ ^^xor-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vnot) [ [ ^^not-vector ] emit-unary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-v<=) [ [ cc<= ^^compare-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-v<) [ [ cc< ^^compare-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-v=) [ [ cc= ^^compare-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-v>) [ [ cc> ^^compare-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-v>=) [ [ cc>= ^^compare-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vunordered?) [ [ cc/<>= ^^compare-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vany?) [ [ vcc-any ^^test-vector ] emit-unary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vall?) [ [ vcc-all ^^test-vector ] emit-unary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vnone?) [ [ vcc-none ^^test-vector ] emit-unary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vlshift) [ [ ^^shl-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-vrshift) [ [ ^^shr-vector ] emit-binary-vector-op ] }
|
||||
{ math.vectors.simd.intrinsics:(simd-hlshift) [ [ ^^horizontal-shl-vector ] emit-horizontal-shift ] }
|
||||
|
|
|
@ -8,6 +8,9 @@ IN: compiler.cfg.intrinsics.slots
|
|||
|
||||
: value-tag ( info -- n ) class>> class-tag ; inline
|
||||
|
||||
: ^^tag-offset>slot ( slot tag -- vreg' )
|
||||
[ ^^offset>slot ] dip ^^sub-imm ;
|
||||
|
||||
: (emit-slot) ( infos -- dst )
|
||||
[ 2inputs ] [ first value-tag ] bi*
|
||||
^^tag-offset>slot ^^slot ;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel math accessors sequences namespaces make
|
||||
combinators assocs arrays locals layouts hashtables
|
||||
cpu.architecture
|
||||
cpu.architecture generalizations
|
||||
compiler.cfg
|
||||
compiler.cfg.comparisons
|
||||
compiler.cfg.stack-frame
|
||||
|
@ -42,14 +42,26 @@ M: ##branch linearize-insn
|
|||
|
||||
: successors ( bb -- first second ) successors>> first2 ; inline
|
||||
|
||||
:: conditional ( bb insn n conditional-quot negate-cc-quot -- bb successor label ... )
|
||||
bb insn
|
||||
conditional-quot
|
||||
[ drop dup successors>> second useless-branch? ] 2bi
|
||||
[ [ swap block-number ] n ndip ]
|
||||
[ [ block-number ] n ndip negate-cc-quot call ] if ; inline
|
||||
|
||||
: (binary-conditional) ( bb insn -- bb successor1 successor2 src1 src2 cc )
|
||||
[ dup successors ]
|
||||
[ [ src1>> ] [ src2>> ] [ cc>> ] tri ] bi* ; inline
|
||||
|
||||
: binary-conditional ( bb insn -- bb successor label2 src1 src2 cc )
|
||||
[ (binary-conditional) ]
|
||||
[ drop dup successors>> second useless-branch? ] 2bi
|
||||
[ [ swap block-number ] 3dip ] [ [ block-number ] 3dip negate-cc ] if ;
|
||||
3 [ (binary-conditional) ] [ negate-cc ] conditional ;
|
||||
|
||||
: (test-vector-conditional) ( bb insn -- bb successor1 successor2 src1 temp rep vcc )
|
||||
[ dup successors ]
|
||||
[ { [ src1>> ] [ temp>> ] [ rep>> ] [ vcc>> ] } cleave ] bi* ; inline
|
||||
|
||||
: test-vector-conditional ( bb insn -- bb successor label src1 temp rep vcc )
|
||||
4 [ (test-vector-conditional) ] [ negate-vcc ] conditional ;
|
||||
|
||||
M: ##compare-branch linearize-insn
|
||||
binary-conditional _compare-branch emit-branch ;
|
||||
|
@ -63,6 +75,9 @@ M: ##compare-float-ordered-branch linearize-insn
|
|||
M: ##compare-float-unordered-branch linearize-insn
|
||||
binary-conditional _compare-float-unordered-branch emit-branch ;
|
||||
|
||||
M: ##test-vector-branch linearize-insn
|
||||
test-vector-conditional _test-vector-branch emit-branch ;
|
||||
|
||||
: overflow-conditional ( bb insn -- bb successor label2 dst src1 src2 )
|
||||
[ dup successors block-number ]
|
||||
[ [ dst>> ] [ src1>> ] [ src2>> ] tri ] bi* ; inline
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
! Copyright (C) 2009 Slava Pestov
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel fry accessors sequences assocs sets namespaces
|
||||
arrays combinators combinators.short-circuit make locals deques
|
||||
dlists layouts cpu.architecture compiler.utilities
|
||||
arrays combinators combinators.short-circuit math make locals
|
||||
deques dlists layouts byte-arrays cpu.architecture
|
||||
compiler.utilities
|
||||
compiler.constants
|
||||
compiler.cfg
|
||||
compiler.cfg.rpo
|
||||
compiler.cfg.hats
|
||||
|
@ -25,24 +27,31 @@ GENERIC: emit-unbox ( dst src rep -- )
|
|||
M:: float-rep emit-box ( dst src rep -- )
|
||||
double-rep next-vreg-rep :> temp
|
||||
temp src ##single>double-float
|
||||
dst temp int-rep next-vreg-rep ##box-float ;
|
||||
dst temp double-rep emit-box ;
|
||||
|
||||
M:: float-rep emit-unbox ( dst src rep -- )
|
||||
double-rep next-vreg-rep :> temp
|
||||
temp src ##unbox-float
|
||||
temp src double-rep emit-unbox
|
||||
dst temp ##double>single-float ;
|
||||
|
||||
M: double-rep emit-box
|
||||
drop int-rep next-vreg-rep ##box-float ;
|
||||
drop
|
||||
[ drop 16 float int-rep next-vreg-rep ##allot ]
|
||||
[ float-offset swap ##set-alien-double ]
|
||||
2bi ;
|
||||
|
||||
M: double-rep emit-unbox
|
||||
drop ##unbox-float ;
|
||||
drop float-offset ##alien-double ;
|
||||
|
||||
M: vector-rep emit-box
|
||||
int-rep next-vreg-rep ##box-vector ;
|
||||
M:: vector-rep emit-box ( dst src rep -- )
|
||||
int-rep next-vreg-rep :> temp
|
||||
dst 16 2 cells + byte-array int-rep next-vreg-rep ##allot
|
||||
temp 16 tag-fixnum ##load-immediate
|
||||
temp dst 1 byte-array tag-number ##set-slot-imm
|
||||
dst byte-array-offset src rep ##set-alien-vector ;
|
||||
|
||||
M: vector-rep emit-unbox
|
||||
##unbox-vector ;
|
||||
[ byte-array-offset ] dip ##alien-vector ;
|
||||
|
||||
M:: scalar-rep emit-box ( dst src rep -- )
|
||||
int-rep next-vreg-rep :> temp
|
||||
|
@ -143,6 +152,9 @@ SYMBOL: costs
|
|||
! Insert conversions. This introduces new temporaries, so we need
|
||||
! to rename opearands too.
|
||||
|
||||
! Mapping from vreg,rep pairs to vregs
|
||||
SYMBOL: alternatives
|
||||
|
||||
:: emit-def-conversion ( dst preferred required -- new-dst' )
|
||||
! If an instruction defines a register with representation 'required',
|
||||
! but the register has preferred representation 'preferred', then
|
||||
|
@ -155,7 +167,13 @@ SYMBOL: costs
|
|||
! but the register has preferred representation 'preferred', then
|
||||
! we rename the instruction's input to a new register, which
|
||||
! becomes the output of a conversion instruction.
|
||||
required next-vreg-rep [ src required preferred emit-conversion ] keep ;
|
||||
preferred required eq? [ src ] [
|
||||
src required alternatives get [
|
||||
required next-vreg-rep :> new-src
|
||||
[ new-src ] 2dip preferred emit-conversion
|
||||
new-src
|
||||
] 2cache
|
||||
] if ;
|
||||
|
||||
SYMBOLS: renaming-set needs-renaming? ;
|
||||
|
||||
|
@ -236,6 +254,7 @@ M: insn conversions-for-insn , ;
|
|||
dup kill-block? [ drop ] [
|
||||
[
|
||||
[
|
||||
H{ } clone alternatives set
|
||||
[ conversions-for-insn ] each
|
||||
] V{ } make
|
||||
] change-instructions drop
|
||||
|
|
|
@ -40,6 +40,7 @@ M: insn rewrite drop f ;
|
|||
[ compare-imm-expr? ]
|
||||
[ compare-float-unordered-expr? ]
|
||||
[ compare-float-ordered-expr? ]
|
||||
[ test-vector-expr? ]
|
||||
} 1|| ;
|
||||
|
||||
: rewrite-boolean-comparison? ( insn -- ? )
|
||||
|
@ -53,12 +54,21 @@ M: insn rewrite drop f ;
|
|||
: >compare-imm-expr< ( expr -- in1 in2 cc )
|
||||
[ src1>> vn>vreg ] [ src2>> vn>constant ] [ cc>> ] tri ; inline
|
||||
|
||||
: >test-vector-expr< ( expr -- src1 temp rep vcc )
|
||||
{
|
||||
[ src1>> vn>vreg ]
|
||||
[ drop next-vreg ]
|
||||
[ rep>> ]
|
||||
[ vcc>> ]
|
||||
} cleave ; inline
|
||||
|
||||
: rewrite-boolean-comparison ( expr -- insn )
|
||||
src1>> vreg>expr {
|
||||
{ [ dup compare-expr? ] [ >compare-expr< \ ##compare-branch new-insn ] }
|
||||
{ [ dup compare-imm-expr? ] [ >compare-imm-expr< \ ##compare-imm-branch new-insn ] }
|
||||
{ [ dup compare-float-unordered-expr? ] [ >compare-expr< \ ##compare-float-unordered-branch new-insn ] }
|
||||
{ [ dup compare-float-ordered-expr? ] [ >compare-expr< \ ##compare-float-ordered-branch new-insn ] }
|
||||
{ [ dup test-vector-expr? ] [ >test-vector-expr< \ ##test-vector-branch new-insn ] }
|
||||
} cond ;
|
||||
|
||||
: tag-fixnum-expr? ( expr -- ? )
|
||||
|
|
|
@ -14,6 +14,8 @@ IN: compiler.cfg.value-numbering.tests
|
|||
[ ##compare-imm? ]
|
||||
[ ##compare-float-unordered? ]
|
||||
[ ##compare-float-ordered? ]
|
||||
[ ##test-vector? ]
|
||||
[ ##test-vector-branch? ]
|
||||
} 1|| [ f >>temp ] when
|
||||
] map ;
|
||||
|
||||
|
@ -107,19 +109,15 @@ IN: compiler.cfg.value-numbering.tests
|
|||
{
|
||||
T{ ##peek f 8 D 0 }
|
||||
T{ ##peek f 9 D -1 }
|
||||
T{ ##unbox-float f 10 8 }
|
||||
T{ ##unbox-float f 11 9 }
|
||||
T{ ##compare-float-unordered f 12 10 11 cc< }
|
||||
T{ ##compare-float-unordered f 14 10 11 cc/< }
|
||||
T{ ##compare-float-unordered f 12 8 9 cc< }
|
||||
T{ ##compare-float-unordered f 14 8 9 cc/< }
|
||||
T{ ##replace f 14 D 0 }
|
||||
}
|
||||
] [
|
||||
{
|
||||
T{ ##peek f 8 D 0 }
|
||||
T{ ##peek f 9 D -1 }
|
||||
T{ ##unbox-float f 10 8 }
|
||||
T{ ##unbox-float f 11 9 }
|
||||
T{ ##compare-float-unordered f 12 10 11 cc< }
|
||||
T{ ##compare-float-unordered f 12 8 9 cc< }
|
||||
T{ ##compare-imm f 14 12 5 cc= }
|
||||
T{ ##replace f 14 D 0 }
|
||||
} value-numbering-step trim-temps
|
||||
|
@ -141,6 +139,20 @@ IN: compiler.cfg.value-numbering.tests
|
|||
} value-numbering-step trim-temps
|
||||
] unit-test
|
||||
|
||||
[
|
||||
{
|
||||
T{ ##peek f 1 D -1 }
|
||||
T{ ##test-vector f 2 1 f float-4-rep vcc-any }
|
||||
T{ ##test-vector-branch f 1 f float-4-rep vcc-any }
|
||||
}
|
||||
] [
|
||||
{
|
||||
T{ ##peek f 1 D -1 }
|
||||
T{ ##test-vector f 2 1 f float-4-rep vcc-any }
|
||||
T{ ##compare-imm-branch f 2 5 cc/= }
|
||||
} value-numbering-step trim-temps
|
||||
] unit-test
|
||||
|
||||
! Immediate operand conversion
|
||||
[
|
||||
{
|
||||
|
|
|
@ -75,7 +75,7 @@ M: insn remove-dead-barrier drop t ;
|
|||
! Anticipation of this and set-slot would help too, maybe later
|
||||
FORWARD-ANALYSIS: slot
|
||||
|
||||
UNION: access ##read ##write ;
|
||||
UNION: access ##slot ##slot-imm ##set-slot ##set-slot-imm ;
|
||||
|
||||
M: slot-analysis transfer-set
|
||||
drop [ H{ } assoc-clone-like ] dip
|
||||
|
|
|
@ -146,8 +146,6 @@ CODEGEN: ##not %not
|
|||
CODEGEN: ##neg %neg
|
||||
CODEGEN: ##log2 %log2
|
||||
CODEGEN: ##copy %copy
|
||||
CODEGEN: ##unbox-float %unbox-float
|
||||
CODEGEN: ##box-float %box-float
|
||||
CODEGEN: ##add-float %add-float
|
||||
CODEGEN: ##sub-float %sub-float
|
||||
CODEGEN: ##mul-float %mul-float
|
||||
|
@ -161,12 +159,12 @@ CODEGEN: ##single>double-float %single>double-float
|
|||
CODEGEN: ##double>single-float %double>single-float
|
||||
CODEGEN: ##integer>float %integer>float
|
||||
CODEGEN: ##float>integer %float>integer
|
||||
CODEGEN: ##unbox-vector %unbox-vector
|
||||
CODEGEN: ##zero-vector %zero-vector
|
||||
CODEGEN: ##gather-vector-2 %gather-vector-2
|
||||
CODEGEN: ##gather-vector-4 %gather-vector-4
|
||||
CODEGEN: ##shuffle-vector %shuffle-vector
|
||||
CODEGEN: ##box-vector %box-vector
|
||||
CODEGEN: ##compare-vector %compare-vector
|
||||
CODEGEN: ##test-vector %test-vector
|
||||
CODEGEN: ##add-vector %add-vector
|
||||
CODEGEN: ##saturated-add-vector %saturated-add-vector
|
||||
CODEGEN: ##add-sub-vector %add-sub-vector
|
||||
|
@ -188,6 +186,7 @@ CODEGEN: ##and-vector %and-vector
|
|||
CODEGEN: ##andn-vector %andn-vector
|
||||
CODEGEN: ##or-vector %or-vector
|
||||
CODEGEN: ##xor-vector %xor-vector
|
||||
CODEGEN: ##not-vector %not-vector
|
||||
CODEGEN: ##shl-vector %shl-vector
|
||||
CODEGEN: ##shr-vector %shr-vector
|
||||
CODEGEN: ##integer>scalar %integer>scalar
|
||||
|
@ -233,6 +232,7 @@ CODEGEN: _compare-branch %compare-branch
|
|||
CODEGEN: _compare-imm-branch %compare-imm-branch
|
||||
CODEGEN: _compare-float-ordered-branch %compare-float-ordered-branch
|
||||
CODEGEN: _compare-float-unordered-branch %compare-float-unordered-branch
|
||||
CODEGEN: _test-vector-branch %test-vector-branch
|
||||
CODEGEN: _dispatch %dispatch
|
||||
CODEGEN: _spill %spill
|
||||
CODEGEN: _reload %reload
|
||||
|
|
|
@ -12,19 +12,21 @@ HELP: disable-optimizer
|
|||
|
||||
ARTICLE: "compiler-usage" "Calling the optimizing compiler"
|
||||
"Normally, new word definitions are recompiled automatically. This can be changed:"
|
||||
{ $subsection disable-optimizer }
|
||||
{ $subsection enable-optimizer }
|
||||
{ $subsections
|
||||
disable-optimizer
|
||||
enable-optimizer
|
||||
}
|
||||
"Removing a word's optimized definition:"
|
||||
{ $subsection decompile }
|
||||
{ $subsections decompile }
|
||||
"Compiling a single quotation:"
|
||||
{ $subsection compile-call }
|
||||
{ $subsections compile-call }
|
||||
"Higher-level words can be found in " { $link "compilation-units" } "." ;
|
||||
|
||||
ARTICLE: "compiler-impl" "Compiler implementation"
|
||||
"The " { $vocab-link "compiler" } "vocabulary, in addition to providing the user-visible words of the compiler, implements the main compilation loop."
|
||||
$nl
|
||||
"Words are added to the " { $link compile-queue } " variable as needed and compiled."
|
||||
{ $subsection compile-queue }
|
||||
{ $subsections compile-queue }
|
||||
"Once compiled, a word is added to the assoc stored in the " { $link compiled } " variable. When compilation is complete, this assoc is passed to " { $link modify-code-heap } "."
|
||||
$nl
|
||||
"The " { $link compile-word } " word performs the actual task of compiling an individual word. The process proceeds as follows:"
|
||||
|
@ -49,10 +51,12 @@ $nl
|
|||
"The optimizing compiler also trades off compile time for performance of generated code, so loading certain vocabularies might take a while. Saving the image after loading vocabularies can save you a lot of time that you would spend waiting for the same code to load in every coding session; see " { $link "images" } " for information."
|
||||
$nl
|
||||
"Most code you write will run with the optimizing compiler. Sometimes, the non-optimizing compiler is used, for example for listener interactions, or for running the quotation passed to " { $link POSTPONE: call( } "."
|
||||
{ $subsection "compiler-errors" }
|
||||
{ $subsection "hints" }
|
||||
{ $subsection "compiler-usage" }
|
||||
{ $subsection "compiler-impl" } ;
|
||||
{ $subsections
|
||||
"compiler-errors"
|
||||
"hints"
|
||||
"compiler-usage"
|
||||
"compiler-impl"
|
||||
} ;
|
||||
|
||||
ABOUT: "compiler"
|
||||
|
||||
|
|
|
@ -46,20 +46,6 @@ IN: compiler.tests.low-level-ir
|
|||
} compile-test-bb
|
||||
] unit-test
|
||||
|
||||
! ##copy on floats. We can only run this test if float intrinsics
|
||||
! are enabled.
|
||||
\ float+ "intrinsic" word-prop [
|
||||
[ 1.5 ] [
|
||||
V{
|
||||
T{ ##load-reference f 4 1.5 }
|
||||
T{ ##unbox-float f 1 4 }
|
||||
T{ ##copy f 2 1 double-rep }
|
||||
T{ ##box-float f 3 2 }
|
||||
T{ ##copy f 0 3 int-rep }
|
||||
} compile-test-bb
|
||||
] unit-test
|
||||
] when
|
||||
|
||||
! make sure slot access works when the destination is
|
||||
! one of the sources
|
||||
[ t ] [
|
||||
|
|
|
@ -20,11 +20,23 @@ IN: compiler.tree.propagation.simd
|
|||
(simd-vbitandn)
|
||||
(simd-vbitor)
|
||||
(simd-vbitxor)
|
||||
(simd-vbitnot)
|
||||
(simd-vand)
|
||||
(simd-vandn)
|
||||
(simd-vor)
|
||||
(simd-vxor)
|
||||
(simd-vnot)
|
||||
(simd-vlshift)
|
||||
(simd-vrshift)
|
||||
(simd-hlshift)
|
||||
(simd-hrshift)
|
||||
(simd-vshuffle)
|
||||
(simd-v<=)
|
||||
(simd-v<)
|
||||
(simd-v=)
|
||||
(simd-v>)
|
||||
(simd-v>=)
|
||||
(simd-vunordered?)
|
||||
(simd-with)
|
||||
(simd-gather-2)
|
||||
(simd-gather-4)
|
||||
|
@ -45,6 +57,12 @@ IN: compiler.tree.propagation.simd
|
|||
|
||||
\ (simd-v.) [ 2nip scalar-output-class ] "outputs" set-word-prop
|
||||
|
||||
{
|
||||
(simd-vany?)
|
||||
(simd-vall?)
|
||||
(simd-vnone?)
|
||||
} [ { boolean } "default-output-classes" set-word-prop ] each
|
||||
|
||||
\ (simd-select) [ 2nip scalar-output-class ] "outputs" set-word-prop
|
||||
|
||||
\ assert-positive [
|
||||
|
|
|
@ -71,13 +71,15 @@ ARTICLE: "compression.lzw" "LZW Compression"
|
|||
$nl
|
||||
"Implements both the TIFF and GIF variations of the LZW algorithm."
|
||||
{ $heading "Decompression" }
|
||||
{ $subsection tiff-lzw-uncompress }
|
||||
{ $subsection gif-lzw-uncompress }
|
||||
{ $subsections
|
||||
tiff-lzw-uncompress
|
||||
gif-lzw-uncompress
|
||||
}
|
||||
{ $heading "Compression" }
|
||||
"Compression has not yet been implemented."
|
||||
$nl
|
||||
"Implementation details:"
|
||||
{ $subsection "compression.lzw.differences" }
|
||||
{ $subsections "compression.lzw.differences" }
|
||||
;
|
||||
|
||||
ABOUT: "compression.lzw"
|
||||
|
|
|
@ -30,14 +30,18 @@ ARTICLE: "concurrency.combinators" "Concurrent combinators"
|
|||
"The " { $vocab-link "concurrency.combinators" } " vocabulary provides concurrent variants of various combinators."
|
||||
$nl
|
||||
"Concurrent sequence combinators:"
|
||||
{ $subsection parallel-each }
|
||||
{ $subsection 2parallel-each }
|
||||
{ $subsection parallel-map }
|
||||
{ $subsection 2parallel-map }
|
||||
{ $subsection parallel-filter }
|
||||
{ $subsections
|
||||
parallel-each
|
||||
2parallel-each
|
||||
parallel-map
|
||||
2parallel-map
|
||||
parallel-filter
|
||||
}
|
||||
"Concurrent cleave combinators:"
|
||||
{ $subsection parallel-cleave }
|
||||
{ $subsection parallel-spread }
|
||||
{ $subsection parallel-napply } ;
|
||||
{ $subsections
|
||||
parallel-cleave
|
||||
parallel-spread
|
||||
parallel-napply
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.combinators"
|
||||
|
|
|
@ -17,9 +17,11 @@ HELP: await
|
|||
|
||||
ARTICLE: "concurrency.count-downs" "Count-down latches"
|
||||
"The " { $vocab-link "concurrency.count-downs" } " vocabulary implements the " { $emphasis "count-down latch" } " data type, whichis a wrapper for a non-negative integer value which tends towards zero. A thread can either decrement the value, or wait for it to become zero."
|
||||
{ $subsection <count-down> }
|
||||
{ $subsection count-down }
|
||||
{ $subsection await }
|
||||
{ $subsections
|
||||
<count-down>
|
||||
count-down
|
||||
await
|
||||
}
|
||||
"The vocabulary was modelled after a similar feature in Java's " { $snippet "java.util.concurrent" } " library." ;
|
||||
|
||||
ABOUT: "concurrency.count-downs"
|
||||
|
|
|
@ -10,9 +10,9 @@ HELP: start-node
|
|||
|
||||
ARTICLE: "concurrency.distributed" "Distributed message passing"
|
||||
"The " { $vocab-link "concurrency.distributed" } " implements transparent distributed message passing, inspired by Erlang and Termite."
|
||||
{ $subsection start-node }
|
||||
{ $subsections start-node }
|
||||
"Instances of " { $link thread } " can be sent to remote processes, at which point they are converted to objects holding the thread ID and the current node's host name:"
|
||||
{ $subsection remote-process }
|
||||
{ $subsections remote-process }
|
||||
"The " { $vocab-link "serialize" } " vocabulary is used to convert Factor objects to byte arrays for transfer over a socket." ;
|
||||
|
||||
ABOUT: "concurrency.distributed"
|
||||
|
|
|
@ -14,9 +14,11 @@ HELP: exchange
|
|||
|
||||
ARTICLE: "concurrency.exchangers" "Object exchange points"
|
||||
"The " { $vocab-link "concurrency.exchangers" } " vocabulary implements " { $emphasis "object exchange points" } ", which are rendezvous points where two threads can exchange objects."
|
||||
{ $subsection exchanger }
|
||||
{ $subsection <exchanger> }
|
||||
{ $subsection exchange }
|
||||
{ $subsections
|
||||
exchanger
|
||||
<exchanger>
|
||||
exchange
|
||||
}
|
||||
"One use-case is two threads, where one thread reads data into a buffer and another thread processes the data. The reader thread can begin by reading the data, then passing the buffer through an exchanger, then recursing. The processing thread can begin by creating an empty buffer, and exchanging it through the exchanger. It then processes the result and recurses."
|
||||
$nl
|
||||
"The vocabulary was modelled after a similar feature in Java's " { $snippet "java.util.concurrent" } " library." ;
|
||||
|
|
|
@ -28,11 +28,15 @@ $nl
|
|||
"The flag can be raised at any time; raising a raised flag does nothing. Lowering a flag if it has not been raised yet will wait for another thread to raise the flag."
|
||||
$nl
|
||||
"Essentially, a flag can be thought of as a counting semaphore where the count never goes above one."
|
||||
{ $subsection flag }
|
||||
{ $subsection flag? }
|
||||
{ $subsections
|
||||
flag
|
||||
flag?
|
||||
}
|
||||
"Waiting for a flag to be raised:"
|
||||
{ $subsection raise-flag }
|
||||
{ $subsection wait-for-flag }
|
||||
{ $subsection lower-flag } ;
|
||||
{ $subsections
|
||||
raise-flag
|
||||
wait-for-flag
|
||||
lower-flag
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.flags"
|
||||
|
|
|
@ -22,8 +22,10 @@ HELP: ?future
|
|||
|
||||
ARTICLE: "concurrency.futures" "Futures"
|
||||
"The " { $vocab-link "concurrency.futures" } " vocabulary implements " { $emphasis "futures" } ", which are deferred computations performed in a background thread. A thread may create a future, then proceed to perform other tasks, then later wait for the future to complete."
|
||||
{ $subsection future }
|
||||
{ $subsection ?future }
|
||||
{ $subsection ?future-timeout } ;
|
||||
{ $subsections
|
||||
future
|
||||
?future
|
||||
?future-timeout
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.futures"
|
||||
|
|
|
@ -26,11 +26,13 @@ ARTICLE: "concurrency.locks.mutex" "Mutual-exclusion locks"
|
|||
"A mutual-exclusion lock ensures that only one thread executes with the lock held at a time. They are used to protect critical sections so that certain operations appear to be atomic to other threads."
|
||||
$nl
|
||||
"There are two varieties of locks: non-reentrant and reentrant. The latter may be acquired recursively by the same thread. Attempting to do so with the former will deadlock."
|
||||
{ $subsection lock }
|
||||
{ $subsection <lock> }
|
||||
{ $subsection <reentrant-lock> }
|
||||
{ $subsection with-lock }
|
||||
{ $subsection with-lock-timeout } ;
|
||||
{ $subsections
|
||||
lock
|
||||
<lock>
|
||||
<reentrant-lock>
|
||||
with-lock
|
||||
with-lock-timeout
|
||||
} ;
|
||||
|
||||
HELP: rw-lock
|
||||
{ $class-description "The class of reader/writer locks." } ;
|
||||
|
@ -61,17 +63,23 @@ $nl
|
|||
"Read/write locks allow any number of threads to hold the read lock simulateneously, however attempting to acquire a write lock blocks until all other threads release read locks and write locks."
|
||||
$nl
|
||||
"Read/write locks are reentrant. A thread holding a write lock may acquire a read lock or a write lock without blocking. However a thread holding a read lock may not acquire a write lock recursively since that could break invariants assumed by the code executing with the read lock held."
|
||||
{ $subsection rw-lock }
|
||||
{ $subsection <rw-lock> }
|
||||
{ $subsection with-read-lock }
|
||||
{ $subsection with-write-lock }
|
||||
{ $subsections
|
||||
rw-lock
|
||||
<rw-lock>
|
||||
with-read-lock
|
||||
with-write-lock
|
||||
}
|
||||
"Versions of the above that take a timeout duration:"
|
||||
{ $subsection with-read-lock-timeout }
|
||||
{ $subsection with-write-lock-timeout } ;
|
||||
{ $subsections
|
||||
with-read-lock-timeout
|
||||
with-write-lock-timeout
|
||||
} ;
|
||||
|
||||
ARTICLE: "concurrency.locks" "Locks"
|
||||
"A " { $emphasis "lock" } " is an object protecting a critical region of code, enforcing a particular mutual-exclusion policy. The " { $vocab-link "concurrency.locks" } " vocabulary implements two types of locks:"
|
||||
{ $subsection "concurrency.locks.mutex" }
|
||||
{ $subsection "concurrency.locks.rw" } ;
|
||||
{ $subsections
|
||||
"concurrency.locks.mutex"
|
||||
"concurrency.locks.rw"
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.locks"
|
||||
|
|
|
@ -53,20 +53,28 @@ HELP: mailbox-get?
|
|||
|
||||
ARTICLE: "concurrency.mailboxes" "Mailboxes"
|
||||
"A " { $emphasis "mailbox" } " is a first-in-first-out queue where the operation of removing an element blocks if the queue is empty. Mailboxes are implemented in the " { $vocab-link "concurrency.mailboxes" } " vocabulary."
|
||||
{ $subsection mailbox }
|
||||
{ $subsection <mailbox> }
|
||||
{ $subsections
|
||||
mailbox
|
||||
<mailbox>
|
||||
}
|
||||
"Removing the first element:"
|
||||
{ $subsection mailbox-get }
|
||||
{ $subsection mailbox-get-timeout }
|
||||
{ $subsections
|
||||
mailbox-get
|
||||
mailbox-get-timeout
|
||||
}
|
||||
"Removing the first element matching a predicate:"
|
||||
{ $subsection mailbox-get? }
|
||||
{ $subsection mailbox-get-timeout? }
|
||||
{ $subsections
|
||||
mailbox-get?
|
||||
mailbox-get-timeout?
|
||||
}
|
||||
"Emptying out a mailbox:"
|
||||
{ $subsection mailbox-get-all }
|
||||
{ $subsections mailbox-get-all }
|
||||
"Adding an element:"
|
||||
{ $subsection mailbox-put }
|
||||
{ $subsections mailbox-put }
|
||||
"Testing if a mailbox is empty:"
|
||||
{ $subsection mailbox-empty? }
|
||||
{ $subsection while-mailbox-empty } ;
|
||||
{ $subsections
|
||||
mailbox-empty?
|
||||
while-mailbox-empty
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.mailboxes"
|
||||
|
|
|
@ -38,19 +38,21 @@ $nl
|
|||
"The messages that are sent from thread to thread are any Factor value. Factor tuples are ideal for this sort of thing as you can send a tuple to a thread and the generic word dispatch mechanism can be used to perform actions depending on what the type of the tuple is."
|
||||
$nl
|
||||
"The " { $link spawn } " word pushes the newly-created thread on the calling thread's stack; this thread object can then be sent messages:"
|
||||
{ $subsection send }
|
||||
{ $subsections send }
|
||||
"A thread can get a message from its queue:"
|
||||
{ $subsection receive }
|
||||
{ $subsection receive-timeout }
|
||||
{ $subsection receive-if }
|
||||
{ $subsection receive-if-timeout }
|
||||
{ $subsections
|
||||
receive
|
||||
receive-timeout
|
||||
receive-if
|
||||
receive-if-timeout
|
||||
}
|
||||
{ $see-also "concurrency.mailboxes" } ;
|
||||
|
||||
ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends"
|
||||
"The " { $link send } " word sends a message asynchronously, and the sending thread continues immediately. It is also possible to send a message to a thread and block until a response is received:"
|
||||
{ $subsection send-synchronous }
|
||||
{ $subsections send-synchronous }
|
||||
"To reply to a synchronous message:"
|
||||
{ $subsection reply-synchronous }
|
||||
{ $subsections reply-synchronous }
|
||||
"An example:"
|
||||
{ $example
|
||||
"USING: concurrency.messaging threads ;"
|
||||
|
@ -66,7 +68,7 @@ ARTICLE: { "concurrency" "exceptions" } "Linked exceptions"
|
|||
"A thread can handle exceptions using the standard Factor exception handling mechanism. If an exception is uncaught the thread will terminate. For example:"
|
||||
{ $code "[ 1 0 / \"This will not print\" print ] \"division-by-zero\" spawn" }
|
||||
"Processes can be linked so that a parent thread can receive the exception that caused the child thread to terminate. In this way 'supervisor' threads can be created that are notified when child threads terminate and possibly restart them."
|
||||
{ $subsection spawn-linked }
|
||||
{ $subsections spawn-linked }
|
||||
"This will create a unidirectional link, such that if an uncaught exception causes the child to terminate, the parent thread can catch it:"
|
||||
{ $code "["
|
||||
" [ 1 0 / \"This will not print\" print ] \"linked-division\" spawn-linked drop"
|
||||
|
@ -80,8 +82,10 @@ $nl
|
|||
"A concurrency-oriented program is one in which multiple threads run simultaneously in a single Factor image or across multiple running Factor instances. The threads can communicate with each other by asynchronous message sends."
|
||||
$nl
|
||||
"Although threads can share data via Factor's mutable data structures it is not recommended to mix shared state with message passing as it can lead to confusing code."
|
||||
{ $subsection { "concurrency" "messaging" } }
|
||||
{ $subsection { "concurrency" "synchronous-sends" } }
|
||||
{ $subsection { "concurrency" "exceptions" } } ;
|
||||
{ $subsections
|
||||
{ "concurrency" "messaging" }
|
||||
{ "concurrency" "synchronous-sends" }
|
||||
{ "concurrency" "exceptions" }
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.messaging"
|
||||
|
|
|
@ -31,10 +31,12 @@ HELP: fulfill
|
|||
|
||||
ARTICLE: "concurrency.promises" "Promises"
|
||||
"The " { $vocab-link "concurrency.promises" } " vocabulary implements " { $emphasis "promises" } ", which are thread-safe write-once variables. Once a promise is created, threads may block waiting for it to be " { $emphasis "fulfilled" } "; at some point in the future, another thread may provide a value at which point all waiting threads are notified."
|
||||
{ $subsection promise }
|
||||
{ $subsection <promise> }
|
||||
{ $subsection fulfill }
|
||||
{ $subsection ?promise }
|
||||
{ $subsection ?promise-timeout } ;
|
||||
{ $subsections
|
||||
promise
|
||||
<promise>
|
||||
fulfill
|
||||
?promise
|
||||
?promise-timeout
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.promises"
|
||||
|
|
|
@ -43,14 +43,20 @@ $nl
|
|||
"] parallel-map"
|
||||
}
|
||||
"Creating semaphores:"
|
||||
{ $subsection semaphore }
|
||||
{ $subsection <semaphore> }
|
||||
{ $subsections
|
||||
semaphore
|
||||
<semaphore>
|
||||
}
|
||||
"Unlike locks, where acquisition and release are always paired by a combinator, semaphores expose these operations directly and there is no requirement that they be performed in the same thread:"
|
||||
{ $subsection acquire }
|
||||
{ $subsection acquire-timeout }
|
||||
{ $subsection release }
|
||||
{ $subsections
|
||||
acquire
|
||||
acquire-timeout
|
||||
release
|
||||
}
|
||||
"Combinators which pair acquisition and release:"
|
||||
{ $subsection with-semaphore }
|
||||
{ $subsection with-semaphore-timeout } ;
|
||||
{ $subsections
|
||||
with-semaphore
|
||||
with-semaphore-timeout
|
||||
} ;
|
||||
|
||||
ABOUT: "concurrency.semaphores"
|
||||
|
|
|
@ -21,9 +21,11 @@ ARTICLE: "core-graphics.types" "Core Graphics types"
|
|||
"CGSize"
|
||||
}
|
||||
"Some words for working with the above:"
|
||||
{ $subsection <CGRect> }
|
||||
{ $subsection <CGPoint> }
|
||||
{ $subsection <CGSize> } ;
|
||||
{ $subsections
|
||||
<CGRect>
|
||||
<CGPoint>
|
||||
<CGSize>
|
||||
} ;
|
||||
|
||||
IN: core-graphics.types
|
||||
ABOUT: "core-graphics.types"
|
||||
|
|
|
@ -197,9 +197,6 @@ HOOK: %fixnum-add cpu ( label dst src1 src2 -- )
|
|||
HOOK: %fixnum-sub cpu ( label dst src1 src2 -- )
|
||||
HOOK: %fixnum-mul cpu ( label dst src1 src2 -- )
|
||||
|
||||
HOOK: %unbox-float cpu ( dst src -- )
|
||||
HOOK: %box-float cpu ( dst src temp -- )
|
||||
|
||||
HOOK: %add-float cpu ( dst src1 src2 -- )
|
||||
HOOK: %sub-float cpu ( dst src1 src2 -- )
|
||||
HOOK: %mul-float cpu ( dst src1 src2 -- )
|
||||
|
@ -216,13 +213,14 @@ HOOK: %double>single-float cpu ( dst src -- )
|
|||
HOOK: %integer>float cpu ( dst src -- )
|
||||
HOOK: %float>integer cpu ( dst src -- )
|
||||
|
||||
HOOK: %box-vector cpu ( dst src temp rep -- )
|
||||
HOOK: %unbox-vector cpu ( dst src rep -- )
|
||||
|
||||
HOOK: %zero-vector cpu ( dst rep -- )
|
||||
HOOK: %fill-vector cpu ( dst rep -- )
|
||||
HOOK: %gather-vector-2 cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %gather-vector-4 cpu ( dst src1 src2 src3 src4 rep -- )
|
||||
HOOK: %shuffle-vector cpu ( dst src shuffle rep -- )
|
||||
HOOK: %compare-vector cpu ( dst src1 src2 temp rep cc -- )
|
||||
HOOK: %test-vector cpu ( dst src1 temp rep vcc -- )
|
||||
HOOK: %test-vector-branch cpu ( label src1 temp rep vcc -- )
|
||||
HOOK: %add-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %saturated-add-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %add-sub-vector cpu ( dst src1 src2 rep -- )
|
||||
|
@ -242,6 +240,7 @@ HOOK: %and-vector cpu ( dst src1 src2 rep -- )
|
|||
HOOK: %andn-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %or-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %xor-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %not-vector cpu ( dst src rep -- )
|
||||
HOOK: %shl-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %shr-vector cpu ( dst src1 src2 rep -- )
|
||||
HOOK: %horizontal-shl-vector cpu ( dst src1 src2 rep -- )
|
||||
|
@ -253,9 +252,12 @@ HOOK: %vector>scalar cpu ( dst src rep -- )
|
|||
HOOK: %scalar>vector cpu ( dst src rep -- )
|
||||
|
||||
HOOK: %zero-vector-reps cpu ( -- reps )
|
||||
HOOK: %fill-vector-reps cpu ( -- reps )
|
||||
HOOK: %gather-vector-2-reps cpu ( -- reps )
|
||||
HOOK: %gather-vector-4-reps cpu ( -- reps )
|
||||
HOOK: %shuffle-vector-reps cpu ( -- reps )
|
||||
HOOK: %compare-vector-reps cpu ( cc -- reps )
|
||||
HOOK: %test-vector-reps cpu ( -- reps )
|
||||
HOOK: %add-vector-reps cpu ( -- reps )
|
||||
HOOK: %saturated-add-vector-reps cpu ( -- reps )
|
||||
HOOK: %add-sub-vector-reps cpu ( -- reps )
|
||||
|
@ -275,6 +277,7 @@ HOOK: %and-vector-reps cpu ( -- reps )
|
|||
HOOK: %andn-vector-reps cpu ( -- reps )
|
||||
HOOK: %or-vector-reps cpu ( -- reps )
|
||||
HOOK: %xor-vector-reps cpu ( -- reps )
|
||||
HOOK: %not-vector-reps cpu ( -- reps )
|
||||
HOOK: %shl-vector-reps cpu ( -- reps )
|
||||
HOOK: %shr-vector-reps cpu ( -- reps )
|
||||
HOOK: %horizontal-shl-vector-reps cpu ( -- reps )
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
IN: cpu.arm.assembler.tests
|
||||
USING: assembler-arm math test namespaces sequences kernel
|
||||
quotations ;
|
||||
USING: cpu.arm.assembler math tools.test namespaces make
|
||||
sequences kernel quotations ;
|
||||
FROM: cpu.arm.assembler => B ;
|
||||
|
||||
: test-opcode [ { } make first ] curry unit-test ;
|
||||
: test-opcode ( expect quot -- ) [ { } make first ] curry unit-test ;
|
||||
|
||||
[ HEX: ea000000 ] [ 0 B ] test-opcode
|
||||
[ HEX: eb000000 ] [ 0 BL ] test-opcode
|
|
@ -1,31 +1,46 @@
|
|||
! Copyright (C) 2007 Slava Pestov.
|
||||
! Copyright (C) 2007, 2009 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: arrays generator generator.fixup kernel sequences words
|
||||
namespaces math math.bitfields ;
|
||||
USING: accessors arrays combinators kernel make math math.bitwise
|
||||
namespaces sequences words words.symbol parser ;
|
||||
IN: cpu.arm.assembler
|
||||
|
||||
: define-registers ( seq -- )
|
||||
dup length [ "register" set-word-prop ] 2each ;
|
||||
! Registers
|
||||
<<
|
||||
|
||||
SYMBOL: R0
|
||||
SYMBOL: R1
|
||||
SYMBOL: R2
|
||||
SYMBOL: R3
|
||||
SYMBOL: R4
|
||||
SYMBOL: R5
|
||||
SYMBOL: R6
|
||||
SYMBOL: R7
|
||||
SYMBOL: R8
|
||||
SYMBOL: R9
|
||||
SYMBOL: R10
|
||||
SYMBOL: R11
|
||||
SYMBOL: R12
|
||||
SYMBOL: R13
|
||||
SYMBOL: R14
|
||||
SYMBOL: R15
|
||||
SYMBOL: registers
|
||||
|
||||
{ R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 }
|
||||
define-registers
|
||||
V{ } registers set-global
|
||||
|
||||
SYNTAX: REGISTER:
|
||||
CREATE-WORD
|
||||
[ define-symbol ]
|
||||
[ registers get length "register" set-word-prop ]
|
||||
[ registers get push ]
|
||||
tri ;
|
||||
|
||||
>>
|
||||
|
||||
REGISTER: R0
|
||||
REGISTER: R1
|
||||
REGISTER: R2
|
||||
REGISTER: R3
|
||||
REGISTER: R4
|
||||
REGISTER: R5
|
||||
REGISTER: R6
|
||||
REGISTER: R7
|
||||
REGISTER: R8
|
||||
REGISTER: R9
|
||||
REGISTER: R10
|
||||
REGISTER: R11
|
||||
REGISTER: R12
|
||||
REGISTER: R13
|
||||
REGISTER: R14
|
||||
REGISTER: R15
|
||||
|
||||
ALIAS: SL R10 ALIAS: FP R11 ALIAS: IP R12
|
||||
ALIAS: SP R13 ALIAS: LR R14 ALIAS: PC R15
|
||||
|
||||
<PRIVATE
|
||||
|
||||
PREDICATE: register < word register >boolean ;
|
||||
|
||||
|
@ -33,8 +48,7 @@ GENERIC: register ( register -- n )
|
|||
M: word register "register" word-prop ;
|
||||
M: f register drop 0 ;
|
||||
|
||||
: SL R10 ; inline : FP R11 ; inline : IP R12 ; inline
|
||||
: SP R13 ; inline : LR R14 ; inline : PC R15 ; inline
|
||||
PRIVATE>
|
||||
|
||||
! Condition codes
|
||||
SYMBOL: cond-code
|
||||
|
@ -46,43 +60,52 @@ SYMBOL: cond-code
|
|||
#! Default value is BIN: 1110 AL (= always)
|
||||
cond-code [ f ] change BIN: 1110 or ;
|
||||
|
||||
: EQ BIN: 0000 >CC ;
|
||||
: NE BIN: 0001 >CC ;
|
||||
: CS BIN: 0010 >CC ;
|
||||
: CC BIN: 0011 >CC ;
|
||||
: LO BIN: 0100 >CC ;
|
||||
: PL BIN: 0101 >CC ;
|
||||
: VS BIN: 0110 >CC ;
|
||||
: VC BIN: 0111 >CC ;
|
||||
: HI BIN: 1000 >CC ;
|
||||
: LS BIN: 1001 >CC ;
|
||||
: GE BIN: 1010 >CC ;
|
||||
: LT BIN: 1011 >CC ;
|
||||
: GT BIN: 1100 >CC ;
|
||||
: LE BIN: 1101 >CC ;
|
||||
: AL BIN: 1110 >CC ;
|
||||
: NV BIN: 1111 >CC ;
|
||||
: EQ ( -- ) BIN: 0000 >CC ;
|
||||
: NE ( -- ) BIN: 0001 >CC ;
|
||||
: CS ( -- ) BIN: 0010 >CC ;
|
||||
: CC ( -- ) BIN: 0011 >CC ;
|
||||
: LO ( -- ) BIN: 0100 >CC ;
|
||||
: PL ( -- ) BIN: 0101 >CC ;
|
||||
: VS ( -- ) BIN: 0110 >CC ;
|
||||
: VC ( -- ) BIN: 0111 >CC ;
|
||||
: HI ( -- ) BIN: 1000 >CC ;
|
||||
: LS ( -- ) BIN: 1001 >CC ;
|
||||
: GE ( -- ) BIN: 1010 >CC ;
|
||||
: LT ( -- ) BIN: 1011 >CC ;
|
||||
: GT ( -- ) BIN: 1100 >CC ;
|
||||
: LE ( -- ) BIN: 1101 >CC ;
|
||||
: AL ( -- ) BIN: 1110 >CC ;
|
||||
: NV ( -- ) BIN: 1111 >CC ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: (insn) ( n -- ) CC> 28 shift bitor , ;
|
||||
|
||||
: insn ( bitspec -- ) bitfield (insn) ; inline
|
||||
|
||||
! Branching instructions
|
||||
GENERIC# (B) 1 ( signed-imm-24 l -- )
|
||||
GENERIC# (B) 1 ( target l -- )
|
||||
|
||||
M: integer (B) { 24 { 1 25 } { 0 26 } { 1 27 } 0 } insn ;
|
||||
M: word (B) 0 swap (B) rc-relative-arm-3 rel-word ;
|
||||
M: label (B) 0 swap (B) rc-relative-arm-3 label-fixup ;
|
||||
|
||||
: B 0 (B) ; : BL 1 (B) ;
|
||||
PRIVATE>
|
||||
|
||||
: B ( target -- ) 0 (B) ;
|
||||
: BL ( target -- ) 1 (B) ;
|
||||
|
||||
! Data processing instructions
|
||||
<PRIVATE
|
||||
|
||||
SYMBOL: updates-cond-code
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: S ( -- ) updates-cond-code on ;
|
||||
|
||||
: S> ( -- ? ) updates-cond-code [ f ] change ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: sinsn ( bitspec -- )
|
||||
bitfield S> [ 20 2^ bitor ] when (insn) ; inline
|
||||
|
||||
|
@ -100,21 +123,25 @@ M: register shift-imm/reg ( Rs Rm shift -- n )
|
|||
{ register 0 }
|
||||
} bitfield ;
|
||||
|
||||
GENERIC: shifter-op ( shifter-op -- n )
|
||||
PRIVATE>
|
||||
|
||||
TUPLE: IMM immed rotate ;
|
||||
C: <IMM> IMM
|
||||
|
||||
M: IMM shifter-op
|
||||
dup IMM-immed swap IMM-rotate
|
||||
{ { 1 25 } 8 0 } bitfield ;
|
||||
|
||||
TUPLE: shifter Rm by shift ;
|
||||
C: <shifter> shifter
|
||||
|
||||
<PRIVATE
|
||||
|
||||
GENERIC: shifter-op ( shifter-op -- n )
|
||||
|
||||
M: IMM shifter-op
|
||||
[ immed>> ] [ rotate>> ] bi { { 1 25 } 8 0 } bitfield ;
|
||||
|
||||
M: shifter shifter-op
|
||||
dup shifter-by over shifter-Rm rot shifter-shift
|
||||
shift-imm/reg ;
|
||||
[ by>> ] [ Rm>> ] [ shift>> ] tri shift-imm/reg ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: <LSL> ( Rm shift-imm/Rs -- shifter-op ) BIN: 00 <shifter> ;
|
||||
: <LSR> ( Rm shift-imm/Rs -- shifter-op ) BIN: 01 <shifter> ;
|
||||
|
@ -123,9 +150,10 @@ M: shifter shifter-op
|
|||
: <RRX> ( Rm -- shifter-op ) 0 <ROR> ;
|
||||
|
||||
M: register shifter-op 0 <LSL> shifter-op ;
|
||||
|
||||
M: integer shifter-op 0 <IMM> shifter-op ;
|
||||
|
||||
<PRIVATE
|
||||
|
||||
: addr1 ( Rd Rn shifter-op opcode -- )
|
||||
{
|
||||
21 ! opcode
|
||||
|
@ -134,30 +162,38 @@ M: integer shifter-op 0 <IMM> shifter-op ;
|
|||
{ register 12 } ! Rd
|
||||
} sinsn ;
|
||||
|
||||
: AND BIN: 0000 addr1 ;
|
||||
: EOR BIN: 0001 addr1 ;
|
||||
: SUB BIN: 0010 addr1 ;
|
||||
: RSB BIN: 0011 addr1 ;
|
||||
: ADD BIN: 0100 addr1 ;
|
||||
: ADC BIN: 0101 addr1 ;
|
||||
: SBC BIN: 0110 addr1 ;
|
||||
: RSC BIN: 0111 addr1 ;
|
||||
: ORR BIN: 1100 addr1 ;
|
||||
: BIC BIN: 1110 addr1 ;
|
||||
PRIVATE>
|
||||
|
||||
: MOV f swap BIN: 1101 addr1 ;
|
||||
: MVN f swap BIN: 1111 addr1 ;
|
||||
: AND ( Rd Rn shifter-op -- ) BIN: 0000 addr1 ;
|
||||
: EOR ( Rd Rn shifter-op -- ) BIN: 0001 addr1 ;
|
||||
: SUB ( Rd Rn shifter-op -- ) BIN: 0010 addr1 ;
|
||||
: RSB ( Rd Rn shifter-op -- ) BIN: 0011 addr1 ;
|
||||
: ADD ( Rd Rn shifter-op -- ) BIN: 0100 addr1 ;
|
||||
: ADC ( Rd Rn shifter-op -- ) BIN: 0101 addr1 ;
|
||||
: SBC ( Rd Rn shifter-op -- ) BIN: 0110 addr1 ;
|
||||
: RSC ( Rd Rn shifter-op -- ) BIN: 0111 addr1 ;
|
||||
: ORR ( Rd Rn shifter-op -- ) BIN: 1100 addr1 ;
|
||||
: BIC ( Rd Rn shifter-op -- ) BIN: 1110 addr1 ;
|
||||
|
||||
: MOV ( Rd shifter-op -- ) [ f ] dip BIN: 1101 addr1 ;
|
||||
: MVN ( Rd shifter-op -- ) [ f ] dip BIN: 1111 addr1 ;
|
||||
|
||||
! These always update the condition code flags
|
||||
: (CMP) >r f -rot r> S addr1 ;
|
||||
<PRIVATE
|
||||
|
||||
: TST BIN: 1000 (CMP) ;
|
||||
: TEQ BIN: 1001 (CMP) ;
|
||||
: CMP BIN: 1010 (CMP) ;
|
||||
: CMN BIN: 1011 (CMP) ;
|
||||
: (CMP) ( Rn shifter-op opcode -- ) [ f ] 3dip S addr1 ;
|
||||
|
||||
PRIVATE>
|
||||
|
||||
: TST ( Rn shifter-op -- ) BIN: 1000 (CMP) ;
|
||||
: TEQ ( Rn shifter-op -- ) BIN: 1001 (CMP) ;
|
||||
: CMP ( Rn shifter-op -- ) BIN: 1010 (CMP) ;
|
||||
: CMN ( Rn shifter-op -- ) BIN: 1011 (CMP) ;
|
||||
|
||||
! Multiply instructions
|
||||
: (MLA) ( Rd Rm Rs Rn a -- )
|
||||
<PRIVATE
|
||||
|
||||
: (MLA) ( Rd Rm Rs Rn a -- )
|
||||
{
|
||||
21
|
||||
{ register 12 }
|
||||
|
@ -168,9 +204,6 @@ M: integer shifter-op 0 <IMM> shifter-op ;
|
|||
{ 1 4 }
|
||||
} sinsn ;
|
||||
|
||||
: MUL ( Rd Rm Rs -- ) f 0 (MLA) ;
|
||||
: MLA ( Rd Rm Rs Rn -- ) 1 (MLA) ;
|
||||
|
||||
: (S/UMLAL) ( RdLo RdHi Rm Rs s a -- )
|
||||
{
|
||||
{ 1 23 }
|
||||
|
@ -184,8 +217,15 @@ M: integer shifter-op 0 <IMM> shifter-op ;
|
|||
{ 1 4 }
|
||||
} sinsn ;
|
||||
|
||||
: SMLAL 1 1 (S/UMLAL) ; : SMULL 1 0 (S/UMLAL) ;
|
||||
: UMLAL 0 1 (S/UMLAL) ; : UMULL 0 0 (S/UMLAL) ;
|
||||
PRIVATE>
|
||||
|
||||
: MUL ( Rd Rm Rs -- ) f 0 (MLA) ;
|
||||
: MLA ( Rd Rm Rs Rn -- ) 1 (MLA) ;
|
||||
|
||||
: SMLAL ( RdLo RdHi Rm Rs -- ) 1 1 (S/UMLAL) ;
|
||||
: SMULL ( RdLo RdHi Rm Rs -- ) 1 0 (S/UMLAL) ;
|
||||
: UMLAL ( RdLo RdHi Rm Rs -- ) 0 1 (S/UMLAL) ;
|
||||
: UMULL ( RdLo RdHi Rm Rs -- ) 0 0 (S/UMLAL) ;
|
||||
|
||||
! Miscellaneous arithmetic instructions
|
||||
: CLZ ( Rd Rm -- )
|
||||
|
@ -203,39 +243,21 @@ M: integer shifter-op 0 <IMM> shifter-op ;
|
|||
! Status register acess instructions
|
||||
|
||||
! Load and store instructions
|
||||
<PRIVATE
|
||||
|
||||
GENERIC: addressing-mode-2 ( addressing-mode -- n )
|
||||
|
||||
TUPLE: addressing p u w ;
|
||||
: <addressing> ( delegate p u w -- addressing )
|
||||
{
|
||||
set-delegate
|
||||
set-addressing-p
|
||||
set-addressing-u
|
||||
set-addressing-w
|
||||
} addressing construct ;
|
||||
TUPLE: addressing base p u w ;
|
||||
C: <addressing> addressing
|
||||
|
||||
M: addressing addressing-mode-2
|
||||
{
|
||||
addressing-p addressing-u addressing-w delegate
|
||||
} get-slots addressing-mode-2
|
||||
{ [ p>> ] [ u>> ] [ w>> ] [ base>> addressing-mode-2 ] } cleave
|
||||
{ 0 21 23 24 } bitfield ;
|
||||
|
||||
M: integer addressing-mode-2 ;
|
||||
|
||||
M: object addressing-mode-2 shifter-op { { 1 25 } 0 } bitfield ;
|
||||
|
||||
! Offset
|
||||
: <+> 1 1 0 <addressing> ;
|
||||
: <-> 1 0 0 <addressing> ;
|
||||
|
||||
! Pre-indexed
|
||||
: <!+> 1 1 1 <addressing> ;
|
||||
: <!-> 1 0 1 <addressing> ;
|
||||
|
||||
! Post-indexed
|
||||
: <+!> 0 1 0 <addressing> ;
|
||||
: <-!> 0 0 0 <addressing> ;
|
||||
|
||||
: addr2 ( Rd Rn addressing-mode b l -- )
|
||||
{
|
||||
{ 1 26 }
|
||||
|
@ -246,16 +268,32 @@ M: object addressing-mode-2 shifter-op { { 1 25 } 0 } bitfield ;
|
|||
{ register 12 }
|
||||
} insn ;
|
||||
|
||||
: LDR 0 1 addr2 ;
|
||||
: LDRB 1 1 addr2 ;
|
||||
: STR 0 0 addr2 ;
|
||||
: STRB 1 0 addr2 ;
|
||||
PRIVATE>
|
||||
|
||||
! Offset
|
||||
: <+> ( base -- addressing ) 1 1 0 <addressing> ;
|
||||
: <-> ( base -- addressing ) 1 0 0 <addressing> ;
|
||||
|
||||
! Pre-indexed
|
||||
: <!+> ( base -- addressing ) 1 1 1 <addressing> ;
|
||||
: <!-> ( base -- addressing ) 1 0 1 <addressing> ;
|
||||
|
||||
! Post-indexed
|
||||
: <+!> ( base -- addressing ) 0 1 0 <addressing> ;
|
||||
: <-!> ( base -- addressing ) 0 0 0 <addressing> ;
|
||||
|
||||
: LDR ( Rd Rn addressing-mode -- ) 0 1 addr2 ;
|
||||
: LDRB ( Rd Rn addressing-mode -- ) 1 1 addr2 ;
|
||||
: STR ( Rd Rn addressing-mode -- ) 0 0 addr2 ;
|
||||
: STRB ( Rd Rn addressing-mode -- ) 1 0 addr2 ;
|
||||
|
||||
! We might have to simulate these instructions since older ARM
|
||||
! chips don't have them.
|
||||
SYMBOL: have-BX?
|
||||
SYMBOL: have-BLX?
|
||||
|
||||
<PRIVATE
|
||||
|
||||
GENERIC# (BX) 1 ( Rm l -- )
|
||||
|
||||
M: register (BX) ( Rm l -- )
|
||||
|
@ -270,24 +308,21 @@ M: register (BX) ( Rm l -- )
|
|||
{ register 0 }
|
||||
} insn ;
|
||||
|
||||
M: word (BX) 0 swap (BX) rc-relative-arm-3 rel-word ;
|
||||
PRIVATE>
|
||||
|
||||
M: label (BX) 0 swap (BX) rc-relative-arm-3 label-fixup ;
|
||||
: BX ( Rm -- ) have-BX? get [ 0 (BX) ] [ [ PC ] dip MOV ] if ;
|
||||
|
||||
: BX have-BX? get [ 0 (BX) ] [ PC swap MOV ] if ;
|
||||
|
||||
: BLX have-BLX? get [ 1 (BX) ] [ LR PC MOV BX ] if ;
|
||||
: BLX ( Rm -- ) have-BLX? get [ 1 (BX) ] [ LR PC MOV BX ] if ;
|
||||
|
||||
! More load and store instructions
|
||||
<PRIVATE
|
||||
|
||||
GENERIC: addressing-mode-3 ( addressing-mode -- n )
|
||||
|
||||
: b>n/n ( b -- n n ) dup -4 shift swap HEX: f bitand ;
|
||||
: b>n/n ( b -- n n ) [ -4 shift ] [ HEX: f bitand ] bi ;
|
||||
|
||||
M: addressing addressing-mode-3
|
||||
[ addressing-p ] keep
|
||||
[ addressing-u ] keep
|
||||
[ addressing-w ] keep
|
||||
delegate addressing-mode-3
|
||||
{ [ p>> ] [ u>> ] [ w>> ] [ base>> addressing-mode-3 ] } cleave
|
||||
{ 0 21 23 24 } bitfield ;
|
||||
|
||||
M: integer addressing-mode-3
|
||||
|
@ -318,10 +353,12 @@ M: object addressing-mode-3
|
|||
{ register 12 }
|
||||
} insn ;
|
||||
|
||||
: LDRH 1 1 0 addr3 ;
|
||||
: LDRSB 0 1 1 addr3 ;
|
||||
: LDRSH 1 1 1 addr3 ;
|
||||
: STRH 1 0 0 addr3 ;
|
||||
PRIVATE>
|
||||
|
||||
: LDRH ( Rn Rd addressing-mode -- ) 1 1 0 addr3 ;
|
||||
: LDRSB ( Rn Rd addressing-mode -- ) 0 1 1 addr3 ;
|
||||
: LDRSH ( Rn Rd addressing-mode -- ) 1 1 1 addr3 ;
|
||||
: STRH ( Rn Rd addressing-mode -- ) 1 0 0 addr3 ;
|
||||
|
||||
! Load and store multiple instructions
|
||||
|
|
@ -51,8 +51,9 @@ CONSTANT: rs-reg 14
|
|||
0 3 LOAD32 rc-absolute-ppc-2/2 rt-stack-chain jit-rel
|
||||
4 3 0 LWZ
|
||||
1 4 0 STW
|
||||
0 3 LOAD32 rc-absolute-ppc-2/2 rt-primitive jit-rel
|
||||
3 MTCTR
|
||||
4 0 swap LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel
|
||||
0 5 LOAD32 rc-absolute-ppc-2/2 rt-primitive jit-rel
|
||||
5 MTCTR
|
||||
BCTR
|
||||
] jit-primitive jit-define
|
||||
|
||||
|
@ -254,8 +255,9 @@ CONSTANT: rs-reg 14
|
|||
[
|
||||
3 ds-reg 0 LWZ
|
||||
ds-reg dup 4 SUBI
|
||||
4 3 quot-xt-offset LWZ
|
||||
4 MTCTR
|
||||
4 0 swap LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel
|
||||
5 3 quot-xt-offset LWZ
|
||||
5 MTCTR
|
||||
BCTR
|
||||
] \ (call) define-sub-primitive
|
||||
|
||||
|
|
|
@ -230,12 +230,6 @@ M: ppc %copy ( dst src rep -- )
|
|||
} case
|
||||
] if ;
|
||||
|
||||
M: ppc %unbox-float ( dst src -- ) float-offset LFD ;
|
||||
|
||||
M:: ppc %box-float ( dst src temp -- )
|
||||
dst 16 float temp %allot
|
||||
src dst float-offset STFD ;
|
||||
|
||||
GENERIC: float-function-param* ( dst src -- )
|
||||
|
||||
M: spill-slot float-function-param* [ 1 ] dip n>> spill@ LFD ;
|
||||
|
@ -264,9 +258,12 @@ M: ppc %double>single-float double-rep %copy ;
|
|||
|
||||
! VMX/AltiVec not supported yet
|
||||
M: ppc %zero-vector-reps { } ;
|
||||
M: ppc %fill-vector-reps { } ;
|
||||
M: ppc %gather-vector-2-reps { } ;
|
||||
M: ppc %gather-vector-4-reps { } ;
|
||||
M: ppc %shuffle-vector-reps { } ;
|
||||
M: ppc %compare-vector-reps drop { } ;
|
||||
M: ppc %test-vector-reps { } ;
|
||||
M: ppc %add-vector-reps { } ;
|
||||
M: ppc %saturated-add-vector-reps { } ;
|
||||
M: ppc %add-sub-vector-reps { } ;
|
||||
|
@ -286,6 +283,7 @@ M: ppc %and-vector-reps { } ;
|
|||
M: ppc %andn-vector-reps { } ;
|
||||
M: ppc %or-vector-reps { } ;
|
||||
M: ppc %xor-vector-reps { } ;
|
||||
M: ppc %not-vector-reps { } ;
|
||||
M: ppc %shl-vector-reps { } ;
|
||||
M: ppc %shr-vector-reps { } ;
|
||||
M: ppc %horizontal-shl-vector-reps { } ;
|
||||
|
@ -397,13 +395,13 @@ M: ppc %alien-cell LWZ ;
|
|||
M: ppc %alien-float LFS ;
|
||||
M: ppc %alien-double LFD ;
|
||||
|
||||
M: ppc %set-alien-integer-1 swapd STB ;
|
||||
M: ppc %set-alien-integer-2 swapd STH ;
|
||||
M: ppc %set-alien-integer-1 -rot STB ;
|
||||
M: ppc %set-alien-integer-2 -rot STH ;
|
||||
|
||||
M: ppc %set-alien-cell swapd STW ;
|
||||
M: ppc %set-alien-cell -rot STW ;
|
||||
|
||||
M: ppc %set-alien-float swapd STFS ;
|
||||
M: ppc %set-alien-double swapd STFD ;
|
||||
M: ppc %set-alien-float -rot STFS ;
|
||||
M: ppc %set-alien-double -rot STFD ;
|
||||
|
||||
: load-zone-ptr ( reg -- )
|
||||
"nursery" %load-vm-field-addr ;
|
||||
|
@ -466,6 +464,7 @@ M:: ppc %load-gc-root ( gc-root register -- )
|
|||
M:: ppc %call-gc ( gc-root-count temp -- )
|
||||
3 1 gc-root-base local@ ADDI
|
||||
gc-root-count 4 LI
|
||||
5 %load-vm-addr
|
||||
"inline_gc" f %alien-invoke ;
|
||||
|
||||
M: ppc %prologue ( n -- )
|
||||
|
@ -614,13 +613,14 @@ M: ppc %prepare-unbox ( -- )
|
|||
|
||||
M: ppc %unbox ( n rep func -- )
|
||||
! Value must be in r3
|
||||
4 %load-vm-addr
|
||||
! Call the unboxer
|
||||
f %alien-invoke
|
||||
! Store the return value on the C stack
|
||||
over [ [ reg-class-of return-reg ] keep %save-param-reg ] [ 2drop ] if ;
|
||||
|
||||
M: ppc %unbox-long-long ( n func -- )
|
||||
! Value must be in r3:r4
|
||||
4 %load-vm-addr
|
||||
! Call the unboxer
|
||||
f %alien-invoke
|
||||
! Store the return value on the C stack
|
||||
|
@ -633,15 +633,17 @@ M: ppc %unbox-large-struct ( n c-type -- )
|
|||
! Value must be in r3
|
||||
! Compute destination address and load struct size
|
||||
[ [ 4 1 ] dip local@ ADDI ] [ heap-size 5 LI ] bi*
|
||||
6 %load-vm-addr
|
||||
! Call the function
|
||||
"to_value_struct" f %alien-invoke ;
|
||||
|
||||
M: ppc %box ( n rep func -- )
|
||||
M:: ppc %box ( n rep func -- )
|
||||
! If the source is a stack location, load it into freg #0.
|
||||
! If the source is f, then we assume the value is already in
|
||||
! freg #0.
|
||||
[ over [ 0 over reg-class-of param-reg swap %load-param-reg ] [ 2drop ] if ] dip
|
||||
f %alien-invoke ;
|
||||
n [ 0 rep reg-class-of param-reg rep %load-param-reg ] when*
|
||||
rep double-rep? 5 4 ? %load-vm-addr
|
||||
func f %alien-invoke ;
|
||||
|
||||
M: ppc %box-long-long ( n func -- )
|
||||
[
|
||||
|
@ -649,6 +651,7 @@ M: ppc %box-long-long ( n func -- )
|
|||
[ [ 3 1 ] dip local@ LWZ ]
|
||||
[ [ 4 1 ] dip cell + local@ LWZ ] bi
|
||||
] when*
|
||||
5 %load-vm-addr
|
||||
] dip f %alien-invoke ;
|
||||
|
||||
: struct-return@ ( n -- n )
|
||||
|
@ -663,6 +666,7 @@ M: ppc %box-large-struct ( n c-type -- )
|
|||
! If n = f, then we're boxing a returned struct
|
||||
! Compute destination address and load struct size
|
||||
[ [ 3 1 ] dip struct-return@ ADDI ] [ heap-size 4 LI ] bi*
|
||||
5 %load-vm-addr
|
||||
! Call the function
|
||||
"box_value_struct" f %alien-invoke ;
|
||||
|
||||
|
@ -682,9 +686,12 @@ M: ppc %alien-invoke ( symbol dll -- )
|
|||
[ 11 ] 2dip %alien-global 11 MTLR BLRL ;
|
||||
|
||||
M: ppc %alien-callback ( quot -- )
|
||||
3 swap %load-reference "c_to_factor" f %alien-invoke ;
|
||||
3 swap %load-reference
|
||||
4 %load-vm-addr
|
||||
"c_to_factor" f %alien-invoke ;
|
||||
|
||||
M: ppc %prepare-alien-indirect ( -- )
|
||||
3 %load-vm-addr
|
||||
"unbox_alien" f %alien-invoke
|
||||
15 3 MR ;
|
||||
|
||||
|
@ -695,6 +702,7 @@ M: ppc %callback-value ( ctype -- )
|
|||
! Save top of data stack
|
||||
3 ds-reg 0 LWZ
|
||||
3 1 0 local@ STW
|
||||
3 %load-vm-addr
|
||||
! Restore data/call/retain stacks
|
||||
"unnest_stacks" f %alien-invoke
|
||||
! Restore top of data stack
|
||||
|
@ -710,21 +718,25 @@ M: ppc return-struct-in-registers? ( c-type -- ? )
|
|||
M: ppc %box-small-struct ( c-type -- )
|
||||
#! Box a <= 16-byte struct returned in r3:r4:r5:r6
|
||||
heap-size 7 LI
|
||||
8 %load-vm-addr
|
||||
"box_medium_struct" f %alien-invoke ;
|
||||
|
||||
: %unbox-struct-1 ( -- )
|
||||
! Alien must be in r3.
|
||||
4 %load-vm-addr
|
||||
"alien_offset" f %alien-invoke
|
||||
3 3 0 LWZ ;
|
||||
|
||||
: %unbox-struct-2 ( -- )
|
||||
! Alien must be in r3.
|
||||
4 %load-vm-addr
|
||||
"alien_offset" f %alien-invoke
|
||||
4 3 4 LWZ
|
||||
3 3 0 LWZ ;
|
||||
|
||||
: %unbox-struct-4 ( -- )
|
||||
! Alien must be in r3.
|
||||
4 %load-vm-addr
|
||||
"alien_offset" f %alien-invoke
|
||||
6 3 12 LWZ
|
||||
5 3 8 LWZ
|
||||
|
@ -732,9 +744,11 @@ M: ppc %box-small-struct ( c-type -- )
|
|||
3 3 0 LWZ ;
|
||||
|
||||
M: ppc %nest-stacks ( -- )
|
||||
3 %load-vm-addr
|
||||
"nest_stacks" f %alien-invoke ;
|
||||
|
||||
M: ppc %unnest-stacks ( -- )
|
||||
3 %load-vm-addr
|
||||
"unnest_stacks" f %alien-invoke ;
|
||||
|
||||
M: ppc %unbox-small-struct ( size -- )
|
||||
|
|
|
@ -474,13 +474,6 @@ M: x86 %double>single-float CVTSD2SS ;
|
|||
M: x86 %integer>float CVTSI2SD ;
|
||||
M: x86 %float>integer CVTTSD2SI ;
|
||||
|
||||
M: x86 %unbox-float ( dst src -- )
|
||||
float-offset [+] MOVSD ;
|
||||
|
||||
M:: x86 %box-float ( dst src temp -- )
|
||||
dst 16 float temp %allot
|
||||
dst float-offset [+] src MOVSD ;
|
||||
|
||||
: %cmov-float= ( dst src -- )
|
||||
[
|
||||
"no-move" define-label
|
||||
|
@ -561,16 +554,6 @@ M: x86 %compare-float-ordered-branch ( label src1 src2 cc -- )
|
|||
M: x86 %compare-float-unordered-branch ( label src1 src2 cc -- )
|
||||
\ UCOMISD (%compare-float-branch) ;
|
||||
|
||||
M:: x86 %box-vector ( dst src rep temp -- )
|
||||
dst rep rep-size 2 cells + byte-array temp %allot
|
||||
16 tag-fixnum dst 1 byte-array tag-number %set-slot-imm
|
||||
dst byte-array-offset [+]
|
||||
src rep %copy ;
|
||||
|
||||
M:: x86 %unbox-vector ( dst src rep -- )
|
||||
dst src byte-array-offset [+]
|
||||
rep %copy ;
|
||||
|
||||
MACRO: available-reps ( alist -- )
|
||||
! Each SSE version adds new representations and supports
|
||||
! all old ones
|
||||
|
@ -592,6 +575,19 @@ M: x86 %zero-vector-reps
|
|||
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
M: x86 %fill-vector
|
||||
{
|
||||
{ double-2-rep [ dup [ XORPD ] [ CMPEQPD ] 2bi ] }
|
||||
{ float-4-rep [ dup [ XORPS ] [ CMPEQPS ] 2bi ] }
|
||||
[ drop dup PCMPEQB ]
|
||||
} case ;
|
||||
|
||||
M: x86 %fill-vector-reps
|
||||
{
|
||||
{ sse? { float-4-rep } }
|
||||
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
: unsign-rep ( rep -- rep' )
|
||||
{
|
||||
{ uint-4-rep int-4-rep }
|
||||
|
@ -725,6 +721,117 @@ M: x86 %shuffle-vector-reps
|
|||
{ sse2? { double-2-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
:: compare-float-v-operands ( dst src1 src2 temp rep cc -- dst' src' rep cc' )
|
||||
cc { cc> cc>= cc/> cc/>= } member?
|
||||
[ dst src2 src1 rep two-operand rep cc swap-cc ]
|
||||
[ dst src1 src2 rep two-operand rep cc ] if ;
|
||||
: (%compare-float-vector) ( dst src rep double single -- )
|
||||
[ double-2-rep eq? ] 2dip if ; inline
|
||||
: %compare-float-vector ( dst src1 src2 temp rep cc -- )
|
||||
compare-float-v-operands {
|
||||
{ cc< [ [ CMPLTPD ] [ CMPLTPS ] (%compare-float-vector) ] }
|
||||
{ cc<= [ [ CMPLEPD ] [ CMPLEPS ] (%compare-float-vector) ] }
|
||||
{ cc= [ [ CMPEQPD ] [ CMPEQPS ] (%compare-float-vector) ] }
|
||||
{ cc<>= [ [ CMPORDPD ] [ CMPORDPS ] (%compare-float-vector) ] }
|
||||
{ cc/< [ [ CMPNLTPD ] [ CMPNLTPS ] (%compare-float-vector) ] }
|
||||
{ cc/<= [ [ CMPNLEPD ] [ CMPNLEPS ] (%compare-float-vector) ] }
|
||||
{ cc/= [ [ CMPNEQPD ] [ CMPNEQPS ] (%compare-float-vector) ] }
|
||||
{ cc/<>= [ [ CMPUNORDPD ] [ CMPUNORDPS ] (%compare-float-vector) ] }
|
||||
} case ;
|
||||
|
||||
:: compare-int-v-operands ( dst src1 src2 temp rep cc -- not-dst/f cmp-dst src' rep cc' )
|
||||
cc order-cc :> occ
|
||||
occ {
|
||||
{ cc= [ f dst src1 src2 rep two-operand rep cc= ] }
|
||||
{ cc/= [ dst temp src1 src2 rep two-operand rep cc= ] }
|
||||
{ cc<= [ dst temp src1 src2 rep two-operand rep cc> ] }
|
||||
{ cc< [ f dst src2 src1 rep two-operand rep cc> ] }
|
||||
{ cc> [ f dst src1 src2 rep two-operand rep cc> ] }
|
||||
{ cc>= [ dst temp src2 src1 rep two-operand rep cc> ] }
|
||||
} case ;
|
||||
:: (%compare-int-vector) ( dst src rep int64 int32 int16 int8 -- )
|
||||
rep unsign-rep :> rep'
|
||||
dst src rep' {
|
||||
{ longlong-2-rep [ int64 call ] }
|
||||
{ int-4-rep [ int32 call ] }
|
||||
{ short-8-rep [ int16 call ] }
|
||||
{ char-16-rep [ int8 call ] }
|
||||
} case ; inline
|
||||
:: %compare-int-vector ( dst src1 src2 temp rep cc -- )
|
||||
dst src1 src2 temp rep cc compare-int-v-operands :> cc' :> rep :> src' :> cmp-dst :> not-dst
|
||||
cmp-dst src' rep cc' {
|
||||
{ cc= [ [ PCMPEQQ ] [ PCMPEQD ] [ PCMPEQW ] [ PCMPEQB ] (%compare-int-vector) ] }
|
||||
{ cc> [ [ PCMPGTQ ] [ PCMPGTD ] [ PCMPGTW ] [ PCMPGTB ] (%compare-int-vector) ] }
|
||||
} case
|
||||
not-dst [ cmp-dst rep %not-vector ] when* ;
|
||||
|
||||
M: x86 %compare-vector ( dst src1 src2 temp rep cc -- )
|
||||
over float-vector-rep?
|
||||
[ %compare-float-vector ]
|
||||
[ %compare-int-vector ] if ;
|
||||
|
||||
: %compare-vector-eq-reps ( -- reps )
|
||||
{
|
||||
{ sse? { float-4-rep } }
|
||||
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep } }
|
||||
{ sse4.1? { longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
: %compare-vector-unord-reps ( -- reps )
|
||||
{
|
||||
{ sse? { float-4-rep } }
|
||||
{ sse2? { double-2-rep } }
|
||||
} available-reps ;
|
||||
: %compare-vector-ord-reps ( -- reps )
|
||||
{
|
||||
{ sse? { float-4-rep } }
|
||||
{ sse2? { double-2-rep char-16-rep short-8-rep int-4-rep } }
|
||||
{ sse4.1? { longlong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
M: x86 %compare-vector-reps
|
||||
{
|
||||
{ [ dup { cc= cc/= } memq? ] [ drop %compare-vector-eq-reps ] }
|
||||
{ [ dup { cc<>= cc/<>= } memq? ] [ drop %compare-vector-unord-reps ] }
|
||||
[ drop %compare-vector-ord-reps ]
|
||||
} cond ;
|
||||
|
||||
:: %test-vector-mask ( dst temp mask vcc -- )
|
||||
vcc {
|
||||
{ vcc-any [ dst dst TEST dst temp \ CMOVNE %boolean ] }
|
||||
{ vcc-none [ dst dst TEST dst temp \ CMOVE %boolean ] }
|
||||
{ vcc-all [ dst mask CMP dst temp \ CMOVE %boolean ] }
|
||||
{ vcc-notall [ dst mask CMP dst temp \ CMOVNE %boolean ] }
|
||||
} case ;
|
||||
|
||||
: %move-vector-mask ( dst src rep -- mask )
|
||||
{
|
||||
{ double-2-rep [ MOVMSKPD HEX: 3 ] }
|
||||
{ float-4-rep [ MOVMSKPS HEX: f ] }
|
||||
[ drop PMOVMSKB HEX: ffff ]
|
||||
} case ;
|
||||
|
||||
M:: x86 %test-vector ( dst src temp rep vcc -- )
|
||||
dst src rep %move-vector-mask :> mask
|
||||
dst temp mask vcc %test-vector-mask ;
|
||||
|
||||
:: %test-vector-mask-branch ( label temp mask vcc -- )
|
||||
vcc {
|
||||
{ vcc-any [ temp temp TEST label JNE ] }
|
||||
{ vcc-none [ temp temp TEST label JE ] }
|
||||
{ vcc-all [ temp mask CMP label JE ] }
|
||||
{ vcc-notall [ temp mask CMP label JNE ] }
|
||||
} case ;
|
||||
|
||||
M:: x86 %test-vector-branch ( label src temp rep vcc -- )
|
||||
temp src rep %move-vector-mask :> mask
|
||||
label temp mask vcc %test-vector-mask-branch ;
|
||||
|
||||
M: x86 %test-vector-reps
|
||||
{
|
||||
{ sse? { float-4-rep } }
|
||||
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
M: x86 %add-vector ( dst src1 src2 rep -- )
|
||||
[ two-operand ] keep
|
||||
{
|
||||
|
@ -1011,6 +1118,16 @@ M: x86 %xor-vector-reps
|
|||
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
M:: x86 %not-vector ( dst src rep -- )
|
||||
dst rep %fill-vector
|
||||
dst dst src rep %xor-vector ;
|
||||
|
||||
M: x86 %not-vector-reps
|
||||
{
|
||||
{ sse? { float-4-rep } }
|
||||
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
|
||||
} available-reps ;
|
||||
|
||||
M: x86 %shl-vector ( dst src1 src2 rep -- )
|
||||
[ two-operand ] keep
|
||||
{
|
||||
|
|
|
@ -39,14 +39,14 @@ HELP: with-delimiter
|
|||
ARTICLE: "csv" "Comma-separated-values parsing and writing"
|
||||
"The " { $vocab-link "csv" } " vocabulary can read and write CSV (comma-separated-value) files." $nl
|
||||
"Reading a csv file:"
|
||||
{ $subsection file>csv }
|
||||
{ $subsections file>csv }
|
||||
"Writing a csv file:"
|
||||
{ $subsection csv>file }
|
||||
{ $subsections csv>file }
|
||||
"Changing the delimiter from a comma:"
|
||||
{ $subsection with-delimiter }
|
||||
{ $subsections with-delimiter }
|
||||
"Reading from a stream:"
|
||||
{ $subsection csv }
|
||||
{ $subsections csv }
|
||||
"Writing to a stream:"
|
||||
{ $subsection write-csv } ;
|
||||
{ $subsections write-csv } ;
|
||||
|
||||
ABOUT: "csv"
|
||||
|
|
|
@ -31,8 +31,10 @@ HELP: statement
|
|||
|
||||
HELP: result-set
|
||||
{ $description "An object encapsulating a raw SQL result object. There are two ways in which a result set can be accessed, but they are specific to the database backend in use."
|
||||
{ $subsection "db-random-access-result-set" }
|
||||
{ $subsection "db-sequential-result-set" }
|
||||
{ $subsections
|
||||
"db-random-access-result-set"
|
||||
"db-sequential-result-set"
|
||||
}
|
||||
} ;
|
||||
|
||||
HELP: new-result-set
|
||||
|
@ -177,14 +179,16 @@ HELP: with-transaction
|
|||
|
||||
ARTICLE: "db" "Database library"
|
||||
"Accessing a database:"
|
||||
{ $subsection "db-custom-database-combinators" }
|
||||
{ $subsections "db-custom-database-combinators" }
|
||||
"Higher-level database help:"
|
||||
{ $vocab-subsection "Database types" "db.types" }
|
||||
{ $vocab-subsection "High-level tuple/database integration" "db.tuples" }
|
||||
"Low-level database help:"
|
||||
{ $subsection "db-protocol" }
|
||||
{ $subsection "db-result-sets" }
|
||||
{ $subsection "db-lowlevel-tutorial" }
|
||||
{ $subsections
|
||||
"db-protocol"
|
||||
"db-result-sets"
|
||||
"db-lowlevel-tutorial"
|
||||
}
|
||||
"Supported database backends:"
|
||||
{ $vocab-subsection "SQLite" "db.sqlite" }
|
||||
{ $vocab-subsection "PostgreSQL" "db.postgresql" } ;
|
||||
|
@ -193,62 +197,78 @@ ARTICLE: "db-random-access-result-set" "Random access result sets"
|
|||
"Random-access result sets do not have to be traversed in order. For instance, PostgreSQL's result set object can be accessed as a matrix with i,j coordinates."
|
||||
$nl
|
||||
"Databases which work in this way must provide methods for the following traversal words:"
|
||||
{ $subsection #rows }
|
||||
{ $subsection #columns }
|
||||
{ $subsection row-column }
|
||||
{ $subsection row-column-typed } ;
|
||||
{ $subsections
|
||||
#rows
|
||||
#columns
|
||||
row-column
|
||||
row-column-typed
|
||||
} ;
|
||||
|
||||
ARTICLE: "db-sequential-result-set" "Sequential result sets"
|
||||
"Sequential result sets can be iterated one element after the next. SQLite's result sets offer this method of traversal."
|
||||
$nl
|
||||
"Databases which work in this way must provide methods for the following traversal words:"
|
||||
{ $subsection more-rows? }
|
||||
{ $subsection advance-row }
|
||||
{ $subsection row-column }
|
||||
{ $subsection row-column-typed } ;
|
||||
{ $subsections
|
||||
more-rows?
|
||||
advance-row
|
||||
row-column
|
||||
row-column-typed
|
||||
} ;
|
||||
|
||||
ARTICLE: "db-result-sets" "Result sets"
|
||||
"Result sets are the encapsulated, database-specific results from a SQL query."
|
||||
$nl
|
||||
"Two possible protocols for iterating over result sets exist:"
|
||||
{ $subsection "db-random-access-result-set" }
|
||||
{ $subsection "db-sequential-result-set" }
|
||||
{ $subsections
|
||||
"db-random-access-result-set"
|
||||
"db-sequential-result-set"
|
||||
}
|
||||
"Query the number of rows or columns:"
|
||||
{ $subsection #rows }
|
||||
{ $subsection #columns }
|
||||
{ $subsections
|
||||
#rows
|
||||
#columns
|
||||
}
|
||||
"Traversing a result set:"
|
||||
{ $subsection advance-row }
|
||||
{ $subsection more-rows? }
|
||||
{ $subsections
|
||||
advance-row
|
||||
more-rows?
|
||||
}
|
||||
"Pulling out a single row of results:"
|
||||
{ $subsection row-column }
|
||||
{ $subsection row-column-typed } ;
|
||||
{ $subsections
|
||||
row-column
|
||||
row-column-typed
|
||||
} ;
|
||||
|
||||
ARTICLE: "db-protocol" "Low-level database protocol"
|
||||
"The high-level protocol (see " { $vocab-link "db.tuples" } ") uses this low-level protocol for executing statements and queries." $nl
|
||||
"Opening a database:"
|
||||
{ $subsection db-open }
|
||||
{ $subsections db-open }
|
||||
"Closing a database:"
|
||||
{ $subsection db-close }
|
||||
{ $subsections db-close }
|
||||
"Creating statements:"
|
||||
{ $subsection <simple-statement> }
|
||||
{ $subsection <prepared-statement> }
|
||||
{ $subsections
|
||||
<simple-statement>
|
||||
<prepared-statement>
|
||||
}
|
||||
"Using statements with the database:"
|
||||
{ $subsection prepare-statement }
|
||||
{ $subsection bind-statement* }
|
||||
{ $subsection low-level-bind }
|
||||
{ $subsections
|
||||
prepare-statement
|
||||
bind-statement*
|
||||
low-level-bind
|
||||
}
|
||||
"Performing a query:"
|
||||
{ $subsection query-results }
|
||||
{ $subsections query-results }
|
||||
"Handling query results:"
|
||||
{ $subsection "db-result-sets" }
|
||||
{ $subsections "db-result-sets" }
|
||||
;
|
||||
! { $subsection bind-tuple }
|
||||
|
||||
ARTICLE: "db-lowlevel-tutorial" "Low-level database tutorial"
|
||||
"Although Factor makes integrating a database with its object system easy (see " { $vocab-link "db.tuples" } "), sometimes you may want to write SQL directly and get the results back as arrays of strings, for instance, when interfacing with a legacy database that doesn't easily map to " { $snippet "tuples" } "." $nl
|
||||
"Executing a SQL command:"
|
||||
{ $subsection sql-command }
|
||||
{ $subsections sql-command }
|
||||
"Executing a query directly:"
|
||||
{ $subsection sql-query }
|
||||
{ $subsections sql-query }
|
||||
"Here's an example usage where we'll make a book table, insert some objects, and query them." $nl
|
||||
"First, let's set up a custom combinator for using our database. See " { $link "db-custom-database-combinators" } " for more details."
|
||||
{ $code """
|
||||
|
|
|
@ -154,52 +154,58 @@ HELP: count-tuples
|
|||
|
||||
ARTICLE: "db-tuples" "High-level tuple/database integration"
|
||||
"Start with a tutorial:"
|
||||
{ $subsection "db-tuples-tutorial" }
|
||||
{ $subsections "db-tuples-tutorial" }
|
||||
"Database types supported:"
|
||||
{ $subsection "db.types" }
|
||||
{ $subsections "db.types" }
|
||||
"Useful words:"
|
||||
{ $subsection "db-tuples-words" }
|
||||
{ $subsections "db-tuples-words" }
|
||||
"For porting db.tuples to other databases:"
|
||||
{ $subsection "db-tuples-protocol" }
|
||||
{ $subsections "db-tuples-protocol" }
|
||||
;
|
||||
|
||||
ARTICLE: "db-tuples-words" "High-level tuple/database words"
|
||||
"Making tuples work with a database:"
|
||||
{ $subsection define-persistent }
|
||||
{ $subsections define-persistent }
|
||||
"Creating tables:"
|
||||
{ $subsection create-table }
|
||||
{ $subsection ensure-table }
|
||||
{ $subsection ensure-tables }
|
||||
{ $subsection recreate-table }
|
||||
{ $subsections
|
||||
create-table
|
||||
ensure-table
|
||||
ensure-tables
|
||||
recreate-table
|
||||
}
|
||||
"Dropping tables:"
|
||||
{ $subsection drop-table }
|
||||
{ $subsections drop-table }
|
||||
"Inserting a tuple:"
|
||||
{ $subsection insert-tuple }
|
||||
{ $subsections insert-tuple }
|
||||
"Updating a tuple:"
|
||||
{ $subsection update-tuple }
|
||||
{ $subsections update-tuple }
|
||||
"Deleting tuples:"
|
||||
{ $subsection delete-tuples }
|
||||
{ $subsections delete-tuples }
|
||||
"Querying tuples:"
|
||||
{ $subsection select-tuple }
|
||||
{ $subsection select-tuples }
|
||||
{ $subsection count-tuples } ;
|
||||
{ $subsections
|
||||
select-tuple
|
||||
select-tuples
|
||||
count-tuples
|
||||
} ;
|
||||
|
||||
ARTICLE: "db-tuples-protocol" "Tuple database protocol"
|
||||
"Creating a table:"
|
||||
{ $subsection create-sql-statement }
|
||||
{ $subsections create-sql-statement }
|
||||
"Dropping a table:"
|
||||
{ $subsection drop-sql-statement }
|
||||
{ $subsections drop-sql-statement }
|
||||
"Inserting a tuple:"
|
||||
{ $subsection <insert-db-assigned-statement> }
|
||||
{ $subsection <insert-user-assigned-statement> }
|
||||
{ $subsections
|
||||
<insert-db-assigned-statement>
|
||||
<insert-user-assigned-statement>
|
||||
}
|
||||
"Updating a tuple:"
|
||||
{ $subsection <update-tuple-statement> }
|
||||
{ $subsections <update-tuple-statement> }
|
||||
"Deleting tuples:"
|
||||
{ $subsection <delete-tuples-statement> }
|
||||
{ $subsections <delete-tuples-statement> }
|
||||
"Selecting tuples:"
|
||||
{ $subsection <select-by-slots-statement> }
|
||||
{ $subsections <select-by-slots-statement> }
|
||||
"Counting tuples:"
|
||||
{ $subsection <count-statement> } ;
|
||||
{ $subsections <count-statement> } ;
|
||||
|
||||
ARTICLE: "db-tuples-tutorial" "Tuple database tutorial"
|
||||
"Let's make a tuple and store it in a database. To follow along, click on each code example and run it in the listener. If you forget to run an example, just start at the top and run them all again in order." $nl
|
||||
|
|
|
@ -157,32 +157,42 @@ HELP: unknown-modifier
|
|||
ARTICLE: "db.types" "Database types"
|
||||
"The " { $vocab-link "db.types" } " vocabulary maps Factor types to database types." $nl
|
||||
"Primary keys:"
|
||||
{ $subsection +db-assigned-id+ }
|
||||
{ $subsection +user-assigned-id+ }
|
||||
{ $subsection +random-id+ }
|
||||
{ $subsections
|
||||
+db-assigned-id+
|
||||
+user-assigned-id+
|
||||
+random-id+
|
||||
}
|
||||
"Null and boolean types:"
|
||||
{ $subsection NULL }
|
||||
{ $subsection BOOLEAN }
|
||||
{ $subsections
|
||||
NULL
|
||||
BOOLEAN
|
||||
}
|
||||
"Text types:"
|
||||
{ $subsection VARCHAR }
|
||||
{ $subsection TEXT }
|
||||
{ $subsections
|
||||
VARCHAR
|
||||
TEXT
|
||||
}
|
||||
"Number types:"
|
||||
{ $subsection INTEGER }
|
||||
{ $subsection BIG-INTEGER }
|
||||
{ $subsection SIGNED-BIG-INTEGER }
|
||||
{ $subsection UNSIGNED-BIG-INTEGER }
|
||||
{ $subsection DOUBLE }
|
||||
{ $subsection REAL }
|
||||
{ $subsections
|
||||
INTEGER
|
||||
BIG-INTEGER
|
||||
SIGNED-BIG-INTEGER
|
||||
UNSIGNED-BIG-INTEGER
|
||||
DOUBLE
|
||||
REAL
|
||||
}
|
||||
"Calendar types:"
|
||||
{ $subsection DATE }
|
||||
{ $subsection DATETIME }
|
||||
{ $subsection TIME }
|
||||
{ $subsection TIMESTAMP }
|
||||
{ $subsections
|
||||
DATE
|
||||
DATETIME
|
||||
TIME
|
||||
TIMESTAMP
|
||||
}
|
||||
"Factor byte-arrays:"
|
||||
{ $subsection BLOB }
|
||||
{ $subsections BLOB }
|
||||
"Arbitrary Factor objects:"
|
||||
{ $subsection FACTOR-BLOB }
|
||||
{ $subsections FACTOR-BLOB }
|
||||
"Factor URLs:"
|
||||
{ $subsection URL } ;
|
||||
{ $subsections URL } ;
|
||||
|
||||
ABOUT: "db.types"
|
||||
|
|
|
@ -6,23 +6,29 @@ IN: debugger
|
|||
|
||||
ARTICLE: "debugger" "The debugger"
|
||||
"Caught errors can be logged in human-readable form:"
|
||||
{ $subsection print-error }
|
||||
{ $subsection try }
|
||||
{ $subsections
|
||||
print-error
|
||||
try
|
||||
}
|
||||
"User-defined errors can have customized printed representation by implementing a generic word:"
|
||||
{ $subsection error. }
|
||||
{ $subsections error. }
|
||||
"A number of words facilitate interactive debugging of errors:"
|
||||
{ $subsection :error }
|
||||
{ $subsection :s }
|
||||
{ $subsection :r }
|
||||
{ $subsection :c }
|
||||
{ $subsection :get }
|
||||
{ $subsections
|
||||
:error
|
||||
:s
|
||||
:r
|
||||
:c
|
||||
:get
|
||||
}
|
||||
"Most types of errors are documented, and the documentation is instantly accessible:"
|
||||
{ $subsection :help }
|
||||
{ $subsections :help }
|
||||
"If the error was restartable, a list of restarts is also printed, and a numbered restart can be invoked:"
|
||||
{ $subsection :1 }
|
||||
{ $subsection :2 }
|
||||
{ $subsection :3 }
|
||||
{ $subsection :res }
|
||||
{ $subsections
|
||||
:1
|
||||
:2
|
||||
:3
|
||||
:res
|
||||
}
|
||||
"You can read more about error handling in " { $link "errors" } "."
|
||||
$nl
|
||||
"Note that in Factor, the debugger is a tool for printing and inspecting errors, not for walking through code. For the latter, see " { $link "ui-walker" } "." ;
|
||||
|
|
|
@ -5,8 +5,8 @@ ARTICLE: "definitions.icons" "Definition icons"
|
|||
"The " { $vocab-link "definitions.icons" } " vocabulary associates common definition types with icons."
|
||||
{ $definition-icons }
|
||||
"Looking up the icon associated with a definition:"
|
||||
{ $subsection definition-icon }
|
||||
{ $subsections definition-icon }
|
||||
"Defining new icons:"
|
||||
{ $subsection POSTPONE: ICON: } ;
|
||||
{ $subsections POSTPONE: ICON: } ;
|
||||
|
||||
ABOUT: "definitions.icons"
|
|
@ -44,13 +44,17 @@ $nl
|
|||
"Unlike " { $link "tuple-subclassing" } ", which expresses " { $emphasis "is-a" } " relationships by statically including the methods and slots of the superclass in all subclasses, consultation forwards generic word calls to another distinct object."
|
||||
$nl
|
||||
"Defining new protocols:"
|
||||
{ $subsection POSTPONE: PROTOCOL: }
|
||||
{ $subsection define-protocol }
|
||||
{ $subsections
|
||||
POSTPONE: PROTOCOL:
|
||||
define-protocol
|
||||
}
|
||||
"Defining new protocols consisting of slot accessors:"
|
||||
{ $subsection POSTPONE: SLOT-PROTOCOL: }
|
||||
{ $subsections POSTPONE: SLOT-PROTOCOL: }
|
||||
"Defining consultation:"
|
||||
{ $subsection POSTPONE: CONSULT: }
|
||||
{ $subsection define-consult }
|
||||
{ $subsections
|
||||
POSTPONE: CONSULT:
|
||||
define-consult
|
||||
}
|
||||
"Every tuple class has an associated protocol consisting of all of its slot accessor methods. The " { $vocab-link "delegate.protocols" } " vocabulary defines formal protocols for the various informal protocols used in the Factor core, such as " { $link "sequence-protocol" } ", " { $link "assocs-protocol" } " or " { $link "stream-protocol" } ;
|
||||
|
||||
ABOUT: "delegate"
|
||||
|
|
|
@ -99,31 +99,39 @@ ARTICLE: "deques" "Deques"
|
|||
"The " { $vocab-link "deques" } " vocabulary implements the deque data structure which has constant-time insertion and removal of elements at both ends."
|
||||
$nl
|
||||
"Deques must be instances of a mixin class:"
|
||||
{ $subsection deque }
|
||||
{ $subsections deque }
|
||||
"Deques must implement a protocol."
|
||||
$nl
|
||||
"Querying the deque:"
|
||||
{ $subsection peek-front }
|
||||
{ $subsection peek-back }
|
||||
{ $subsection deque-empty? }
|
||||
{ $subsection deque-member? }
|
||||
{ $subsections
|
||||
peek-front
|
||||
peek-back
|
||||
deque-empty?
|
||||
deque-member?
|
||||
}
|
||||
"Adding and removing elements:"
|
||||
{ $subsection push-front* }
|
||||
{ $subsection push-back* }
|
||||
{ $subsection pop-front* }
|
||||
{ $subsection pop-back* }
|
||||
{ $subsection clear-deque }
|
||||
{ $subsections
|
||||
push-front*
|
||||
push-back*
|
||||
pop-front*
|
||||
pop-back*
|
||||
clear-deque
|
||||
}
|
||||
"Working with node objects output by " { $link push-front* } " and " { $link push-back* } ":"
|
||||
{ $subsection delete-node }
|
||||
{ $subsection node-value }
|
||||
{ $subsections
|
||||
delete-node
|
||||
node-value
|
||||
}
|
||||
"Utility operations built in terms of the above:"
|
||||
{ $subsection push-front }
|
||||
{ $subsection push-all-front }
|
||||
{ $subsection push-back }
|
||||
{ $subsection push-all-back }
|
||||
{ $subsection pop-front }
|
||||
{ $subsection pop-back }
|
||||
{ $subsection slurp-deque }
|
||||
{ $subsections
|
||||
push-front
|
||||
push-all-front
|
||||
push-back
|
||||
push-all-back
|
||||
pop-front
|
||||
pop-back
|
||||
slurp-deque
|
||||
}
|
||||
"When using a deque as a queue, the convention is to queue elements with " { $link push-front } " and deque them with " { $link pop-back } "." ;
|
||||
|
||||
ABOUT: "deques"
|
||||
|
|
|
@ -42,17 +42,21 @@ $nl
|
|||
"The two main supported operations are equating two elements, which joins their equivalence classes, and checking if two elements belong to the same equivalence class. Both operations have the time complexity of the inverse Ackermann function, which for all intents and purposes is constant time."
|
||||
$nl
|
||||
"The class of disjoint sets:"
|
||||
{ $subsection disjoint-set }
|
||||
{ $subsections disjoint-set }
|
||||
"Creating new disjoint sets:"
|
||||
{ $subsection <disjoint-set> }
|
||||
{ $subsection assoc>disjoint-set }
|
||||
{ $subsections
|
||||
<disjoint-set>
|
||||
assoc>disjoint-set
|
||||
}
|
||||
"Queries:"
|
||||
{ $subsection equiv? }
|
||||
{ $subsection equiv-set-size }
|
||||
{ $subsections
|
||||
equiv?
|
||||
equiv-set-size
|
||||
}
|
||||
"Adding elements:"
|
||||
{ $subsection add-atom }
|
||||
{ $subsections add-atom }
|
||||
"Equating elements:"
|
||||
{ $subsection equate }
|
||||
{ $subsections equate }
|
||||
"Additionally, disjoint sets implement the " { $link clone } " generic word." ;
|
||||
|
||||
ABOUT: "disjoint-sets"
|
||||
|
|
|
@ -6,22 +6,28 @@ ARTICLE: "dlists" "Double-linked lists"
|
|||
"A double-linked list is the canonical implementation of a " { $link deque } "."
|
||||
$nl
|
||||
"Double-linked lists form a class:"
|
||||
{ $subsection dlist }
|
||||
{ $subsection dlist? }
|
||||
{ $subsections
|
||||
dlist
|
||||
dlist?
|
||||
}
|
||||
"Constructing a double-linked list:"
|
||||
{ $subsection <dlist> }
|
||||
{ $subsections <dlist> }
|
||||
"Double-linked lists support all the operations of the deque protocol (" { $link "deques" } ") as well as the following."
|
||||
$nl
|
||||
"Iterating over elements:"
|
||||
{ $subsection dlist-each }
|
||||
{ $subsection dlist-find }
|
||||
{ $subsection dlist-filter }
|
||||
{ $subsection dlist-any? }
|
||||
{ $subsections
|
||||
dlist-each
|
||||
dlist-find
|
||||
dlist-filter
|
||||
dlist-any?
|
||||
}
|
||||
"Deleting a node matching a predicate:"
|
||||
{ $subsection delete-node-if* }
|
||||
{ $subsection delete-node-if }
|
||||
{ $subsections
|
||||
delete-node-if*
|
||||
delete-node-if
|
||||
}
|
||||
"Search deque implementation:"
|
||||
{ $subsection <hashed-dlist> } ;
|
||||
{ $subsections <hashed-dlist> } ;
|
||||
|
||||
ABOUT: "dlists"
|
||||
|
||||
|
|
|
@ -93,32 +93,45 @@ HELP: clear-doc
|
|||
|
||||
ARTICLE: "documents" "Documents"
|
||||
"The " { $vocab-link "documents" } " vocabulary implements " { $emphasis "documents" } ", which are models storing a passage of text as a sequence of lines. Operations are defined for operating on subranges of the text, and " { $link "ui.gadgets.editors" } " can display these models."
|
||||
{ $subsection document }
|
||||
{ $subsection <document> }
|
||||
{ $subsections
|
||||
document
|
||||
<document>
|
||||
}
|
||||
"Getting and setting the contents of the entire document:"
|
||||
{ $subsection doc-string }
|
||||
{ $subsection set-doc-string }
|
||||
{ $subsection clear-doc }
|
||||
{ $subsections
|
||||
doc-string
|
||||
set-doc-string
|
||||
clear-doc
|
||||
}
|
||||
"Getting and setting subranges:"
|
||||
{ $subsection doc-line }
|
||||
{ $subsection doc-lines }
|
||||
{ $subsection doc-range }
|
||||
{ $subsection set-doc-range }
|
||||
{ $subsection remove-doc-range }
|
||||
{ $subsections
|
||||
doc-line
|
||||
doc-lines
|
||||
doc-range
|
||||
set-doc-range
|
||||
remove-doc-range
|
||||
}
|
||||
"A combinator:"
|
||||
{ $subsection each-line }
|
||||
{ $subsection "document-locs" }
|
||||
{ $subsection "documents.elements" }
|
||||
{ $subsections each-line }
|
||||
"More info:"
|
||||
{ $subsections
|
||||
"document-locs"
|
||||
"documents.elements"
|
||||
}
|
||||
{ $see-also "ui.gadgets.editors" } ;
|
||||
|
||||
ARTICLE: "document-locs" "Document locations"
|
||||
"Locations in the document are represented as a line/column number pair, with both indices being zero-based. There are some words for manipulating locations:"
|
||||
{ $subsection +col }
|
||||
{ $subsection +line }
|
||||
{ $subsection =col }
|
||||
{ $subsection =line }
|
||||
{ $subsections
|
||||
+col
|
||||
+line
|
||||
=col
|
||||
=line
|
||||
}
|
||||
"Miscellaneous words for working with locations:"
|
||||
{ $subsection lines-equal? }
|
||||
{ $subsection validate-loc } ;
|
||||
{ $subsections
|
||||
lines-equal?
|
||||
validate-loc
|
||||
} ;
|
||||
|
||||
ABOUT: "documents"
|
||||
|
|
|
@ -37,14 +37,18 @@ ARTICLE: "documents.elements" "Document elements"
|
|||
"Document elements, defined in the " { $vocab-link "documents.elements" } " vocabulary, overlay a hierarchy of structure on top of the flat sequence of characters presented by the document."
|
||||
$nl
|
||||
"The different types of document elements correspond to the standard editing taxonomy:"
|
||||
{ $subsection char-elt }
|
||||
{ $subsection one-word-elt }
|
||||
{ $subsection word-elt }
|
||||
{ $subsection one-line-elt }
|
||||
{ $subsection line-elt }
|
||||
{ $subsection doc-elt }
|
||||
{ $subsections
|
||||
char-elt
|
||||
one-word-elt
|
||||
word-elt
|
||||
one-line-elt
|
||||
line-elt
|
||||
doc-elt
|
||||
}
|
||||
"New locations can be created out of existing ones by finding the start or end of a document element nearest to a given location."
|
||||
{ $subsection prev-elt }
|
||||
{ $subsection next-elt } ;
|
||||
{ $subsections
|
||||
prev-elt
|
||||
next-elt
|
||||
} ;
|
||||
|
||||
ABOUT: "documents.elements"
|
|
@ -4,15 +4,15 @@ IN: editors
|
|||
|
||||
ARTICLE: "editor" "Editor integration"
|
||||
"Factor development is best done with one of the supported editors; this allows you to quickly jump to definitions from the Factor environment."
|
||||
{ $subsection edit }
|
||||
{ $subsections edit }
|
||||
"Depending on the editor you are using, you must load one of the child vocabularies of the " { $vocab-link "editors" } " vocabulary, for example " { $vocab-link "editors.emacs" } ":"
|
||||
{ $code "USE: editors.emacs" }
|
||||
"If you intend to always use the same editor, it helps to have it load during stage 2 bootstrap. Place the code to load and possibly configure it in the " { $link "factor-boot-rc" } "."
|
||||
$nl
|
||||
"Editor integration vocabularies store a quotation in a global variable when loaded:"
|
||||
{ $subsection edit-hook }
|
||||
{ $subsections edit-hook }
|
||||
"If a syntax error was thrown while loading a source file, you can jump to the location of the error in your editor:"
|
||||
{ $subsection :edit } ;
|
||||
{ $subsections :edit } ;
|
||||
|
||||
ABOUT: "editor"
|
||||
|
||||
|
|
|
@ -60,11 +60,15 @@ ARTICLE: "environment" "Environment variables"
|
|||
"The " { $vocab-link "environment" } " vocabulary interfaces to the platform-dependent mechanism for setting environment variables." $nl
|
||||
"Windows CE has no concept of environment variables, so these words are undefined on that platform." $nl
|
||||
"Reading environment variables:"
|
||||
{ $subsection os-env }
|
||||
{ $subsection os-envs }
|
||||
{ $subsections
|
||||
os-env
|
||||
os-envs
|
||||
}
|
||||
"Writing environment variables:"
|
||||
{ $subsection set-os-env }
|
||||
{ $subsection unset-os-env }
|
||||
{ $subsection set-os-envs } ;
|
||||
{ $subsections
|
||||
set-os-env
|
||||
unset-os-env
|
||||
set-os-envs
|
||||
} ;
|
||||
|
||||
ABOUT: "environment"
|
||||
|
|
|
@ -17,7 +17,9 @@ HELP: eval>string
|
|||
|
||||
ARTICLE: "eval" "Evaluating strings at runtime"
|
||||
"The " { $vocab-link "eval" } " vocabulary implements support for evaluating strings at runtime."
|
||||
{ $subsection POSTPONE: eval( }
|
||||
{ $subsection eval>string } ;
|
||||
{ $subsections
|
||||
POSTPONE: eval(
|
||||
eval>string
|
||||
} ;
|
||||
|
||||
ABOUT: "eval"
|
||||
|
|
|
@ -19,34 +19,40 @@ HELP: (write-farkup)
|
|||
|
||||
ARTICLE: "farkup-ast" "Farkup syntax tree nodes"
|
||||
"The " { $link parse-farkup } " word outputs a tree of nodes corresponding to the Farkup syntax of the input string. This tree can be programatically traversed and mutated before being passed on to " { $link write-farkup } "."
|
||||
{ $subsection heading1 }
|
||||
{ $subsection heading2 }
|
||||
{ $subsection heading3 }
|
||||
{ $subsection heading4 }
|
||||
{ $subsection strong }
|
||||
{ $subsection emphasis }
|
||||
{ $subsection superscript }
|
||||
{ $subsection subscript }
|
||||
{ $subsection inline-code }
|
||||
{ $subsection paragraph }
|
||||
{ $subsection list-item }
|
||||
{ $subsection unordered-list }
|
||||
{ $subsection ordered-list }
|
||||
{ $subsection table }
|
||||
{ $subsection table-row }
|
||||
{ $subsection link }
|
||||
{ $subsection image }
|
||||
{ $subsection code } ;
|
||||
{ $subsections
|
||||
heading1
|
||||
heading2
|
||||
heading3
|
||||
heading4
|
||||
strong
|
||||
emphasis
|
||||
superscript
|
||||
subscript
|
||||
inline-code
|
||||
paragraph
|
||||
list-item
|
||||
unordered-list
|
||||
ordered-list
|
||||
table
|
||||
table-row
|
||||
link
|
||||
image
|
||||
code
|
||||
} ;
|
||||
|
||||
ARTICLE: "farkup" "Farkup"
|
||||
"The " { $vocab-link "farkup" } " vocabulary implements Farkup (Factor mARKUP), a simple markup language. Farkup was loosely based on the markup languages employed by MediaWiki and " { $url "http://reddit.com" } "."
|
||||
$nl
|
||||
"The main entry points for converting Farkup to HTML:"
|
||||
{ $subsection convert-farkup }
|
||||
{ $subsection write-farkup }
|
||||
{ $subsections
|
||||
convert-farkup
|
||||
write-farkup
|
||||
}
|
||||
"The syntax tree of a piece of Farkup can also be inspected and modified:"
|
||||
{ $subsection parse-farkup }
|
||||
{ $subsection (write-farkup) }
|
||||
{ $subsection "farkup-ast" } ;
|
||||
{ $subsections
|
||||
parse-farkup
|
||||
(write-farkup)
|
||||
"farkup-ast"
|
||||
} ;
|
||||
|
||||
ABOUT: "farkup"
|
||||
|
|
|
@ -26,16 +26,22 @@ HELP: font-with-foreground
|
|||
|
||||
ARTICLE: "fonts" "Fonts"
|
||||
"The " { $vocab-link "fonts" } " vocabulary implements a data type for fonts that other vocabularies, for example " { $link "ui" } ", can use. A font combines a font name, size, style, and color information into a single object."
|
||||
{ $subsection font }
|
||||
{ $subsection <font> }
|
||||
{ $subsections
|
||||
font
|
||||
<font>
|
||||
}
|
||||
"Modifying fonts:"
|
||||
{ $subsection font-with-foreground }
|
||||
{ $subsection font-with-background }
|
||||
{ $subsections
|
||||
font-with-foreground
|
||||
font-with-background
|
||||
}
|
||||
"Useful constants:"
|
||||
{ $subsection monospace-font }
|
||||
{ $subsection sans-serif-font }
|
||||
{ $subsection serif-font }
|
||||
{ $subsections
|
||||
monospace-font
|
||||
sans-serif-font
|
||||
serif-font
|
||||
}
|
||||
"A data type for font metrics. The " { $vocab-link "fonts" } " vocabulary does not provide any means of computing font metrics, it simply defines a common data type that other vocabularies, such as " { $vocab-link "ui.text" } " may use:"
|
||||
{ $subsection metrics } ;
|
||||
{ $subsections metrics } ;
|
||||
|
||||
ABOUT: "fonts"
|
||||
|
|
|
@ -129,10 +129,11 @@ HELP: strftime
|
|||
|
||||
ARTICLE: "formatting" "Formatted printing"
|
||||
"The " { $vocab-link "formatting" } " vocabulary is used for formatted printing."
|
||||
{ $subsection printf }
|
||||
{ $subsection sprintf }
|
||||
{ $subsection strftime }
|
||||
;
|
||||
{ $subsections
|
||||
printf
|
||||
sprintf
|
||||
strftime
|
||||
} ;
|
||||
|
||||
ABOUT: "formatting"
|
||||
|
||||
|
|
|
@ -78,17 +78,21 @@ ARTICLE: "fry" "Fried quotations"
|
|||
"The " { $vocab-link "fry" } " vocabulary implements " { $emphasis "fried quotation" } ". Conceptually, fried quotations are quotations with “holes” (more formally, " { $emphasis "fry specifiers" } "), and the holes are filled in when the fried quotation is pushed on the stack."
|
||||
$nl
|
||||
"Fried quotations are started by a special parsing word:"
|
||||
{ $subsection POSTPONE: '[ }
|
||||
{ $subsections POSTPONE: '[ }
|
||||
"There are two types of fry specifiers; the first can hold a value, and the second “splices” a quotation, as if it were inserted without surrounding brackets:"
|
||||
{ $subsection _ }
|
||||
{ $subsection @ }
|
||||
{ $subsections
|
||||
_
|
||||
@
|
||||
}
|
||||
"The holes are filled in with the top of stack going in the rightmost hole, the second item on the stack going in the second hole from the right, and so on."
|
||||
{ $subsection "fry.examples" }
|
||||
{ $subsection "fry.philosophy" }
|
||||
{ $subsections
|
||||
"fry.examples"
|
||||
"fry.philosophy"
|
||||
}
|
||||
"Fry is implemented as a parsing word which reads a quotation and scans for occurrences of " { $link _ } " and " { $link @ } "; these words are not actually executed, and doing so raises an error (this can happen if they're accidentally used outside of a fry)."
|
||||
$nl
|
||||
"Fried quotations can also be constructed without using a parsing word; this is useful when meta-programming:"
|
||||
{ $subsection fry }
|
||||
{ $subsections fry }
|
||||
"Fried quotations are an abstraction on top of the " { $link "compositional-combinators" } "; their use is encouraged over the combinators, because often the fry form is shorter and clearer than the combinator form." ;
|
||||
|
||||
ABOUT: "fry"
|
||||
|
|
|
@ -81,12 +81,14 @@ ARTICLE: "furnace.actions.page.example" "Furnace page action example"
|
|||
|
||||
ARTICLE: "furnace.actions.page" "Furnace page actions"
|
||||
"Page actions implement the common case of an action that simply serves a Chloe template in response to a GET request."
|
||||
{ $subsection page-action }
|
||||
{ $subsection <page-action> }
|
||||
{ $subsections
|
||||
page-action
|
||||
<page-action>
|
||||
}
|
||||
"When using a page action, instead of setting the " { $slot "display" } " slot, the " { $slot "template" } " slot is set instead. The " { $slot "init" } ", " { $slot "authorize" } ", " { $slot "validate" } " and " { $slot "submit" } " slots can still be set as usual."
|
||||
$nl
|
||||
"The " { $slot "template" } " slot of a " { $link page-action } " contains a pair with shape " { $snippet "{ responder name }" } ", where " { $snippet "responder" } " is a responder class, usually a subclass of " { $link dispatcher } ", and " { $snippet "name" } " is the name of a template file, without the " { $snippet ".xml" } " extension, relative to the directory containing the responder's vocabulary source file."
|
||||
{ $subsection "furnace.actions.page.example" } ;
|
||||
{ $subsections "furnace.actions.page.example" } ;
|
||||
|
||||
ARTICLE: "furnace.actions.config" "Furnace action configuration"
|
||||
"Actions have the following slots:"
|
||||
|
@ -104,10 +106,10 @@ ARTICLE: "furnace.actions.validation" "Form validation with actions"
|
|||
"The action code is set up so that the " { $slot "init" } " quotation can validate query parameters, and the " { $slot "validate" } " quotation can validate POST parameters."
|
||||
$nl
|
||||
"A word to validate parameters and make them available as HTML form values (see " { $link "html.forms.values" } "); typically this word is invoked from the " { $slot "init" } " and " { $slot "validate" } " quotations:"
|
||||
{ $subsection validate-params }
|
||||
{ $subsections validate-params }
|
||||
"The above word expects an association list mapping parameter names to validator quotations; validator quotations can use the words in the "
|
||||
"Custom validation logic can invoke a word when validation fails; " { $link validate-params } " invokes this word for you:"
|
||||
{ $subsection validation-failed }
|
||||
{ $subsections validation-failed }
|
||||
"If validation fails, no more action code is executed, and the client is redirected back to the originating page, where validation errors can be displayed. Note that validation errors are rendered automatically by the " { $link "html.components" } " words, and in particular, " { $link "html.templates.chloe" } " use these words." ;
|
||||
|
||||
ARTICLE: "furnace.actions.lifecycle" "Furnace action lifecycle"
|
||||
|
@ -133,7 +135,7 @@ ARTICLE: "furnace.actions.lifecycle" "Furnace action lifecycle"
|
|||
|
||||
ARTICLE: "furnace.actions.impl" "Furnace actions implementation"
|
||||
"The following parametrized constructor should be called from constructors for subclasses of " { $link action } ":"
|
||||
{ $subsection new-action } ;
|
||||
{ $subsections new-action } ;
|
||||
|
||||
ARTICLE: "furnace.actions" "Furnace actions"
|
||||
"The " { $vocab-link "furnace.actions" } " vocabulary implements a type of responder, called an " { $emphasis "action" } ", which handles the form validation lifecycle."
|
||||
|
@ -141,18 +143,18 @@ $nl
|
|||
"Other than form validation capability, actions are also often simpler to use than implementing new responders directly, since creating a new class is not required, and the action dispatches on the request type (GET, HEAD, or POST)."
|
||||
$nl
|
||||
"The class of actions:"
|
||||
{ $subsection action }
|
||||
{ $subsections action }
|
||||
"Creating a new action:"
|
||||
{ $subsection <action> }
|
||||
{ $subsections <action> }
|
||||
"Once created, an action needs to be configured; typically the creation and configuration of an action is encapsulated into a single word:"
|
||||
{ $subsection "furnace.actions.config" }
|
||||
{ $subsections "furnace.actions.config" }
|
||||
"Validating forms with actions:"
|
||||
{ $subsection "furnace.actions.validation" }
|
||||
{ $subsections "furnace.actions.validation" }
|
||||
"More about the form validation lifecycle:"
|
||||
{ $subsection "furnace.actions.lifecycle" }
|
||||
{ $subsections "furnace.actions.lifecycle" }
|
||||
"A convenience class:"
|
||||
{ $subsection "furnace.actions.page" }
|
||||
{ $subsections "furnace.actions.page" }
|
||||
"Low-level features:"
|
||||
{ $subsection "furnace.actions.impl" } ;
|
||||
{ $subsections "furnace.actions.impl" } ;
|
||||
|
||||
ABOUT: "furnace.actions"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue