Merge branch 'klazuka'
commit
cb308e8cc8
|
@ -24,10 +24,12 @@ HELP: every
|
||||||
|
|
||||||
ARTICLE: "alarms" "Alarms"
|
ARTICLE: "alarms" "Alarms"
|
||||||
"The " { $vocab-link "alarms" } " vocabulary provides a lightweight way to schedule one-time and recurring tasks without spawning a new thread."
|
"The " { $vocab-link "alarms" } " vocabulary provides a lightweight way to schedule one-time and recurring tasks without spawning a new thread."
|
||||||
{ $subsection alarm }
|
{ $subsections
|
||||||
{ $subsection add-alarm }
|
alarm
|
||||||
{ $subsection later }
|
add-alarm
|
||||||
{ $subsection cancel-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." ;
|
"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"
|
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."
|
"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
|
$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:"
|
"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> }
|
{ $subsections
|
||||||
{ $subsection <uchar> }
|
<char>
|
||||||
{ $subsection <short> }
|
<uchar>
|
||||||
{ $subsection <ushort> }
|
<short>
|
||||||
{ $subsection <int> }
|
<ushort>
|
||||||
{ $subsection <uint> }
|
<int>
|
||||||
{ $subsection <long> }
|
<uint>
|
||||||
{ $subsection <ulong> }
|
<long>
|
||||||
{ $subsection <longlong> }
|
<ulong>
|
||||||
{ $subsection <ulonglong> }
|
<longlong>
|
||||||
{ $subsection <float> }
|
<ulonglong>
|
||||||
{ $subsection <double> }
|
<float>
|
||||||
{ $subsection <void*> }
|
<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:"
|
"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 }
|
{ $subsections
|
||||||
{ $subsection *uchar }
|
*char
|
||||||
{ $subsection *short }
|
*uchar
|
||||||
{ $subsection *ushort }
|
*short
|
||||||
{ $subsection *int }
|
*ushort
|
||||||
{ $subsection *uint }
|
*int
|
||||||
{ $subsection *long }
|
*uint
|
||||||
{ $subsection *ulong }
|
*long
|
||||||
{ $subsection *longlong }
|
*ulong
|
||||||
{ $subsection *ulonglong }
|
*longlong
|
||||||
{ $subsection *float }
|
*ulonglong
|
||||||
{ $subsection *double }
|
*float
|
||||||
{ $subsection *void* }
|
*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." ;
|
"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"
|
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" } "." ;
|
"Struct and union types are identified by their class word. See " { $link "classes.struct" } "." ;
|
||||||
|
|
||||||
ARTICLE: "c-types-specs" "C type specifiers"
|
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: } "."
|
"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."
|
||||||
{ $subsection "c-types.primitives" }
|
$nl
|
||||||
{ $subsection "c-types.pointers" }
|
"Defining new C types:"
|
||||||
{ $subsection "c-types.ambiguity" }
|
{ $subsections
|
||||||
{ $subsection "c-types.structs" }
|
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"
|
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."
|
"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
|
$nl
|
||||||
"Allocating a C datum with a fixed address:"
|
"Allocating a C datum with a fixed address:"
|
||||||
{ $subsection malloc-object }
|
{ $subsections
|
||||||
{ $subsection malloc-byte-array }
|
malloc-object
|
||||||
{ $subsection malloc-file-contents }
|
malloc-byte-array
|
||||||
"There is a set of words in the " { $vocab-link "libc" } " vocabulary which directly call C standard library memory management functions:"
|
malloc-file-contents
|
||||||
{ $subsection malloc }
|
}
|
||||||
{ $subsection calloc }
|
"The " { $vocab-link "libc" } " vocabulary defines several words which directly call C standard library memory management functions:"
|
||||||
{ $subsection realloc }
|
{ $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:"
|
"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 } ":"
|
"Utilities for automatically freeing memory in conjunction with " { $link with-destructors } ":"
|
||||||
{ $subsection &free }
|
{ $subsections
|
||||||
{ $subsection |free }
|
&free
|
||||||
|
|free
|
||||||
|
}
|
||||||
"The " { $link &free } " and " { $link |free } " words are generated using " { $link "alien.destructors" } "."
|
"The " { $link &free } " and " { $link |free } " words are generated using " { $link "alien.destructors" } "."
|
||||||
$nl
|
$nl
|
||||||
"You can unsafely copy a range of bytes from one memory location to another:"
|
"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:"
|
"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:"
|
"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"
|
ARTICLE: "c-pointers" "Passing pointers to C functions"
|
||||||
"The following Factor objects may be passed to C function parameters with pointer types:"
|
"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" } "." }
|
{ "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:"
|
"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:"
|
"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:"
|
"More about the " { $link alien } " type:"
|
||||||
{ $subsection "aliens" }
|
{ $subsections "aliens" }
|
||||||
{ $warning
|
{ $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" } "." } ;
|
"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."
|
"Two defining characteristics of Factor are dynamic typing and automatic memory management, which are somewhat incompatible with the machine-level data model exposed by C. Factor's C library interface defines its own set of C data types, distinct from Factor language types, together with automatic conversion between Factor values and C types. For example, C integer types must be declared and are fixed-width, whereas Factor supports arbitrary-precision integers."
|
||||||
$nl
|
$nl
|
||||||
"Furthermore, Factor's garbage collector can move objects in memory; for a discussion of the consequences, see " { $link "byte-arrays-gc" } "."
|
"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" }
|
{ $subsections
|
||||||
{ $subsection "c-pointers" }
|
"c-types-specs"
|
||||||
{ $subsection "malloc" }
|
"c-pointers"
|
||||||
{ $subsection "c-strings" }
|
"malloc"
|
||||||
{ $subsection "c-out-params" }
|
"c-strings"
|
||||||
|
"c-out-params"
|
||||||
|
}
|
||||||
"Important guidelines for passing data in byte arrays:"
|
"Important guidelines for passing data in byte arrays:"
|
||||||
{ $subsection "byte-arrays-gc" }
|
{ $subsections "byte-arrays-gc" }
|
||||||
"C-style enumerated types are supported:"
|
"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:"
|
"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:"
|
"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." ;
|
"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
|
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."
|
"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
|
$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:"
|
"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 }
|
{ $subsections
|
||||||
{ $subsection malloc-string }
|
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."
|
"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
|
$nl
|
||||||
"A word to read strings from arbitrary addresses:"
|
"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 } "." ;
|
"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"
|
ARTICLE: "alien.destructors" "Alien destructors"
|
||||||
"The " { $vocab-link "alien.destructors" } " vocabulary defines a utility parsing word for defining new disposable classes."
|
"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"
|
ABOUT: "alien.destructors"
|
|
@ -56,13 +56,14 @@ HELP: fortran-invoke
|
||||||
|
|
||||||
ARTICLE: "alien.fortran" "Fortran FFI"
|
ARTICLE: "alien.fortran" "Fortran FFI"
|
||||||
"The " { $vocab-link "alien.fortran" } " vocabulary provides an interface to code in shared libraries written in Fortran."
|
"The " { $vocab-link "alien.fortran" } " vocabulary provides an interface to code in shared libraries written in Fortran."
|
||||||
{ $subsection "alien.fortran-types" }
|
{ $subsections
|
||||||
{ $subsection "alien.fortran-abis" }
|
"alien.fortran-types"
|
||||||
{ $subsection add-fortran-library }
|
"alien.fortran-abis"
|
||||||
{ $subsection POSTPONE: LIBRARY: }
|
add-fortran-library
|
||||||
{ $subsection POSTPONE: FUNCTION: }
|
POSTPONE: LIBRARY:
|
||||||
{ $subsection POSTPONE: SUBROUTINE: }
|
POSTPONE: FUNCTION:
|
||||||
{ $subsection fortran-invoke }
|
POSTPONE: SUBROUTINE:
|
||||||
;
|
fortran-invoke
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "alien.fortran"
|
ABOUT: "alien.fortran"
|
||||||
|
|
|
@ -65,8 +65,10 @@ HELP: remove-library
|
||||||
|
|
||||||
ARTICLE: "loading-libs" "Loading native libraries"
|
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:"
|
"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 }
|
{ $subsections
|
||||||
{ $subsection remove-library }
|
add-library
|
||||||
|
remove-library
|
||||||
|
}
|
||||||
"Once a library has been defined, you can try loading it to see if the path name is correct:"
|
"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." ;
|
"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." } ;
|
{ $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"
|
ARTICLE: "syntax-aliens" "Alien object literal syntax"
|
||||||
{ $subsection POSTPONE: ALIEN: }
|
{ $subsections
|
||||||
{ $subsection POSTPONE: DLL" } ;
|
POSTPONE: ALIEN:
|
||||||
|
POSTPONE: DLL"
|
||||||
|
} ;
|
||||||
|
|
||||||
HELP: LIBRARY:
|
HELP: LIBRARY:
|
||||||
{ $syntax "LIBRARY: name" }
|
{ $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."
|
"The " { $vocab-link "ascii" } " vocabulary implements support for the legacy ASCII character set. Most applications should use " { $link "unicode" } " instead."
|
||||||
$nl
|
$nl
|
||||||
"ASCII character classes:"
|
"ASCII character classes:"
|
||||||
{ $subsection blank? }
|
{ $subsections
|
||||||
{ $subsection letter? }
|
blank?
|
||||||
{ $subsection LETTER? }
|
letter?
|
||||||
{ $subsection digit? }
|
LETTER?
|
||||||
{ $subsection printable? }
|
digit?
|
||||||
{ $subsection control? }
|
printable?
|
||||||
{ $subsection quotable? }
|
control?
|
||||||
{ $subsection ascii? }
|
quotable?
|
||||||
|
ascii?
|
||||||
|
}
|
||||||
"ASCII case conversion:"
|
"ASCII case conversion:"
|
||||||
{ $subsection ch>lower }
|
{ $subsections
|
||||||
{ $subsection ch>upper }
|
ch>lower
|
||||||
{ $subsection >lower }
|
ch>upper
|
||||||
{ $subsection >upper } ;
|
>lower
|
||||||
|
>upper
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "ascii"
|
ABOUT: "ascii"
|
||||||
|
|
|
@ -36,12 +36,16 @@ HELP: encode-base64-lines
|
||||||
ARTICLE: "base64" "Base 64 conversions"
|
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
|
"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:"
|
"Converting to and from base64 as strings:"
|
||||||
{ $subsection >base64 }
|
{ $subsections
|
||||||
{ $subsection >base64-lines }
|
>base64
|
||||||
{ $subsection base64> }
|
>base64-lines
|
||||||
|
base64>
|
||||||
|
}
|
||||||
"Using base64 from streams:"
|
"Using base64 from streams:"
|
||||||
{ $subsection encode-base64 }
|
{ $subsections
|
||||||
{ $subsection encode-base64-lines }
|
encode-base64
|
||||||
{ $subsection decode-base64 } ;
|
encode-base64-lines
|
||||||
|
decode-base64
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "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."
|
"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
|
$nl
|
||||||
"The class of biassocs:"
|
"The class of biassocs:"
|
||||||
{ $subsection biassoc }
|
{ $subsections
|
||||||
{ $subsection biassoc? }
|
biassoc
|
||||||
|
biassoc?
|
||||||
|
}
|
||||||
"Creating new biassocs:"
|
"Creating new biassocs:"
|
||||||
{ $subsection <biassoc> }
|
{ $subsections
|
||||||
{ $subsection <bihash> }
|
<biassoc>
|
||||||
|
<bihash>
|
||||||
|
}
|
||||||
"Converting existing assocs to biassocs:"
|
"Converting existing assocs to biassocs:"
|
||||||
{ $subsection >biassoc } ;
|
{ $subsections >biassoc } ;
|
||||||
|
|
||||||
ABOUT: "biassocs"
|
ABOUT: "biassocs"
|
||||||
|
|
|
@ -33,11 +33,13 @@ HELP: sorted-memq?
|
||||||
|
|
||||||
ARTICLE: "binary-search" "Binary search"
|
ARTICLE: "binary-search" "Binary search"
|
||||||
"The " { $emphasis "binary search" } " algorithm allows elements to be located in sorted sequence in " { $snippet "O(log n)" } " time."
|
"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:"
|
"Variants of sequence words optimized for sorted sequences:"
|
||||||
{ $subsection sorted-index }
|
{ $subsections
|
||||||
{ $subsection sorted-member? }
|
sorted-index
|
||||||
{ $subsection sorted-memq? }
|
sorted-member?
|
||||||
|
sorted-memq?
|
||||||
|
}
|
||||||
{ $see-also "order-specifiers" "sequences-sorting" } ;
|
{ $see-also "order-specifiers" "sequences-sorting" } ;
|
||||||
|
|
||||||
ABOUT: "binary-search"
|
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" } "."
|
"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
|
$nl
|
||||||
"Bit arrays form a class of objects:"
|
"Bit arrays form a class of objects:"
|
||||||
{ $subsection bit-array }
|
{ $subsections
|
||||||
{ $subsection bit-array? }
|
bit-array
|
||||||
|
bit-array?
|
||||||
|
}
|
||||||
"Creating new bit arrays:"
|
"Creating new bit arrays:"
|
||||||
{ $subsection >bit-array }
|
{ $subsections
|
||||||
{ $subsection <bit-array> }
|
>bit-array
|
||||||
|
<bit-array>
|
||||||
|
}
|
||||||
"Efficiently setting and clearing all bits in a bit array:"
|
"Efficiently setting and clearing all bits in a bit array:"
|
||||||
{ $subsection set-bits }
|
{ $subsections
|
||||||
{ $subsection clear-bits }
|
set-bits
|
||||||
|
clear-bits
|
||||||
|
}
|
||||||
"Converting between unsigned integers and their binary representation:"
|
"Converting between unsigned integers and their binary representation:"
|
||||||
{ $subsection integer>bit-array }
|
{ $subsections
|
||||||
{ $subsection bit-array>integer }
|
integer>bit-array
|
||||||
|
bit-array>integer
|
||||||
|
}
|
||||||
"Bit array literal syntax:"
|
"Bit array literal syntax:"
|
||||||
{ $subsection POSTPONE: ?{ } ;
|
{ $subsections POSTPONE: ?{ } ;
|
||||||
|
|
||||||
ABOUT: "bit-arrays"
|
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."
|
"A bit vector is a resizable mutable sequence of bits. Bit vector words are found in the " { $vocab-link "bit-vectors" } " vocabulary."
|
||||||
$nl
|
$nl
|
||||||
"Bit vectors form a class:"
|
"Bit vectors form a class:"
|
||||||
{ $subsection bit-vector }
|
{ $subsections
|
||||||
{ $subsection bit-vector? }
|
bit-vector
|
||||||
|
bit-vector?
|
||||||
|
}
|
||||||
"Creating bit vectors:"
|
"Creating bit vectors:"
|
||||||
{ $subsection >bit-vector }
|
{ $subsections
|
||||||
{ $subsection <bit-vector> }
|
>bit-vector
|
||||||
|
<bit-vector>
|
||||||
|
}
|
||||||
"Literal syntax:"
|
"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:"
|
"If you don't care about initial capacity, a more elegant way to create a new bit vector is to write:"
|
||||||
{ $code "?V{ } clone" } ;
|
{ $code "?V{ } clone" } ;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ IN: bootstrap.image
|
||||||
|
|
||||||
ARTICLE: "bootstrap.image" "Bootstrapping new images"
|
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:"
|
"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:"
|
"The second bootstrapping stage is initiated by running the resulting bootstrap image:"
|
||||||
{ $code "./factor -i=boot.x86.32.image" }
|
{ $code "./factor -i=boot.x86.32.image" }
|
||||||
"This stage loads additional code, compiles all words, and dumps a final " { $snippet "factor.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"
|
ARTICLE: "boxes" "Boxes"
|
||||||
"A " { $emphasis "box" } " is a container which can either be empty or hold a single value."
|
"A " { $emphasis "box" } " is a container which can either be empty or hold a single value."
|
||||||
{ $subsection box }
|
{ $subsections box }
|
||||||
"Creating an empty box:"
|
"Creating an empty box:"
|
||||||
{ $subsection <box> }
|
{ $subsections <box> }
|
||||||
"Storing a value and removing a value from a box:"
|
"Storing a value and removing a value from a box:"
|
||||||
{ $subsection >box }
|
{ $subsections
|
||||||
{ $subsection box> }
|
>box
|
||||||
|
box>
|
||||||
|
}
|
||||||
"Safely removing a value:"
|
"Safely removing a value:"
|
||||||
{ $subsection ?box }
|
{ $subsections ?box }
|
||||||
"Testing if a box is full can be done by reading the " { $snippet "occupied" } " slot." ;
|
"Testing if a box is full can be done by reading the " { $snippet "occupied" } " slot." ;
|
||||||
|
|
||||||
ABOUT: "boxes"
|
ABOUT: "boxes"
|
||||||
|
|
|
@ -520,125 +520,142 @@ HELP: since-1970
|
||||||
|
|
||||||
ARTICLE: "calendar" "Calendar"
|
ARTICLE: "calendar" "Calendar"
|
||||||
"The two data types used throughout the calendar library:"
|
"The two data types used throughout the calendar library:"
|
||||||
{ $subsection timestamp }
|
{ $subsections
|
||||||
{ $subsection duration }
|
timestamp
|
||||||
|
duration
|
||||||
|
}
|
||||||
"Durations represent spans of time:"
|
"Durations represent spans of time:"
|
||||||
{ $subsection "using-durations" }
|
{ $subsections "using-durations" }
|
||||||
"Arithmetic on timestamps and durations:"
|
"Arithmetic on timestamps and durations:"
|
||||||
{ $subsection "timestamp-arithmetic" }
|
{ $subsections "timestamp-arithmetic" }
|
||||||
"Getting the current timestamp:"
|
"Getting the current timestamp:"
|
||||||
{ $subsection now }
|
{ $subsections
|
||||||
{ $subsection gmt }
|
now
|
||||||
|
gmt
|
||||||
|
}
|
||||||
"Converting between timestamps:"
|
"Converting between timestamps:"
|
||||||
{ $subsection >local-time }
|
{ $subsections
|
||||||
{ $subsection >gmt }
|
>local-time
|
||||||
|
>gmt
|
||||||
|
}
|
||||||
"Converting between timezones:"
|
"Converting between timezones:"
|
||||||
{ $subsection convert-timezone }
|
{ $subsections convert-timezone }
|
||||||
"Timestamps relative to each other:"
|
"Timestamps relative to each other:"
|
||||||
{ $subsection "relative-timestamps" }
|
{ $subsections "relative-timestamps" }
|
||||||
"Operations on units of time:"
|
"Operations on units of time:"
|
||||||
{ $subsection "years" }
|
{ $subsections
|
||||||
{ $subsection "months" }
|
"years"
|
||||||
{ $subsection "days" }
|
"months"
|
||||||
|
"days"
|
||||||
|
}
|
||||||
"Meta-data about the calendar:"
|
"Meta-data about the calendar:"
|
||||||
{ $subsection "calendar-facts" }
|
{ $subsections "calendar-facts" }
|
||||||
;
|
;
|
||||||
|
|
||||||
ARTICLE: "timestamp-arithmetic" "Timestamp arithmetic"
|
ARTICLE: "timestamp-arithmetic" "Timestamp arithmetic"
|
||||||
"Adding timestamps and durations, or durations and durations:"
|
"Adding timestamps and durations, or durations and durations:"
|
||||||
{ $subsection time+ }
|
{ $subsections time+ }
|
||||||
"Subtracting:"
|
"Subtracting:"
|
||||||
{ $subsection time- }
|
{ $subsections time- }
|
||||||
"Element-wise multiplication:"
|
"Element-wise multiplication:"
|
||||||
{ $subsection time* } ;
|
{ $subsections time* } ;
|
||||||
|
|
||||||
ARTICLE: "using-durations" "Using durations"
|
ARTICLE: "using-durations" "Using durations"
|
||||||
"Creating a duration object:"
|
"Creating a duration object:"
|
||||||
{ $subsection years }
|
{ $subsections
|
||||||
{ $subsection months }
|
years
|
||||||
{ $subsection weeks }
|
months
|
||||||
{ $subsection days }
|
weeks
|
||||||
{ $subsection hours }
|
days
|
||||||
{ $subsection minutes }
|
hours
|
||||||
{ $subsection seconds }
|
minutes
|
||||||
{ $subsection milliseconds }
|
seconds
|
||||||
{ $subsection microseconds }
|
milliseconds
|
||||||
{ $subsection nanoseconds }
|
microseconds
|
||||||
{ $subsection instant }
|
nanoseconds
|
||||||
|
instant
|
||||||
|
}
|
||||||
"Converting a duration to a number:"
|
"Converting a duration to a number:"
|
||||||
{ $subsection duration>years }
|
{ $subsections
|
||||||
{ $subsection duration>months }
|
duration>years
|
||||||
{ $subsection duration>days }
|
duration>months
|
||||||
{ $subsection duration>hours }
|
duration>days
|
||||||
{ $subsection duration>minutes }
|
duration>hours
|
||||||
{ $subsection duration>seconds }
|
duration>minutes
|
||||||
{ $subsection duration>milliseconds }
|
duration>seconds
|
||||||
{ $subsection duration>microseconds }
|
duration>milliseconds
|
||||||
{ $subsection duration>nanoseconds } ;
|
duration>microseconds
|
||||||
|
duration>nanoseconds
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "relative-timestamps" "Relative timestamps"
|
ARTICLE: "relative-timestamps" "Relative timestamps"
|
||||||
"In the future:"
|
"In the future:"
|
||||||
{ $subsection hence }
|
{ $subsections hence }
|
||||||
"In the past:"
|
"In the past:"
|
||||||
{ $subsection ago }
|
{ $subsections ago }
|
||||||
"Invert a duration:"
|
"Invert a duration:"
|
||||||
{ $subsection before }
|
{ $subsections before }
|
||||||
"Days of the week relative to " { $link now } ":"
|
"Days of the week relative to " { $link now } ":"
|
||||||
{ $subsection sunday }
|
{ $subsections
|
||||||
{ $subsection monday }
|
sunday
|
||||||
{ $subsection tuesday }
|
monday
|
||||||
{ $subsection wednesday }
|
tuesday
|
||||||
{ $subsection thursday }
|
wednesday
|
||||||
{ $subsection friday }
|
thursday
|
||||||
{ $subsection saturday }
|
friday
|
||||||
|
saturday
|
||||||
|
}
|
||||||
"New timestamps relative to calendar events:"
|
"New timestamps relative to calendar events:"
|
||||||
{ $subsection beginning-of-year }
|
{ $subsections
|
||||||
{ $subsection beginning-of-month }
|
beginning-of-year
|
||||||
{ $subsection beginning-of-week }
|
beginning-of-month
|
||||||
{ $subsection midnight }
|
beginning-of-week
|
||||||
{ $subsection noon }
|
midnight
|
||||||
;
|
noon
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "days" "Day operations"
|
ARTICLE: "days" "Day operations"
|
||||||
"Naming days:"
|
"Naming days:"
|
||||||
{ $subsection day-abbreviation2 }
|
{ $subsections
|
||||||
{ $subsection day-abbreviations2 }
|
day-abbreviation2
|
||||||
{ $subsection day-abbreviation3 }
|
day-abbreviations2
|
||||||
{ $subsection day-abbreviations3 }
|
day-abbreviation3
|
||||||
{ $subsection day-name }
|
day-abbreviations3
|
||||||
{ $subsection day-names }
|
day-name
|
||||||
|
day-names
|
||||||
|
}
|
||||||
"Calculating a Julian day number:"
|
"Calculating a Julian day number:"
|
||||||
{ $subsection julian-day-number }
|
{ $subsections julian-day-number }
|
||||||
"Calculate a timestamp:"
|
"Calculate a timestamp:"
|
||||||
{ $subsection julian-day-number>date }
|
{ $subsections julian-day-number>date } ;
|
||||||
;
|
|
||||||
|
|
||||||
ARTICLE: "calendar-facts" "Calendar facts"
|
ARTICLE: "calendar-facts" "Calendar facts"
|
||||||
"Calendar facts:"
|
"Calendar facts:"
|
||||||
{ $subsection average-month }
|
{ $subsections
|
||||||
{ $subsection months-per-year }
|
average-month
|
||||||
{ $subsection days-per-year }
|
months-per-year
|
||||||
{ $subsection hours-per-year }
|
days-per-year
|
||||||
{ $subsection minutes-per-year }
|
hours-per-year
|
||||||
{ $subsection seconds-per-year }
|
minutes-per-year
|
||||||
{ $subsection days-in-month }
|
seconds-per-year
|
||||||
{ $subsection day-of-year }
|
days-in-month
|
||||||
{ $subsection day-of-week }
|
day-of-year
|
||||||
;
|
day-of-week
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "years" "Year operations"
|
ARTICLE: "years" "Year operations"
|
||||||
"Leap year predicate:"
|
"Leap year predicate:"
|
||||||
{ $subsection leap-year? }
|
{ $subsections leap-year? }
|
||||||
"Find the number of days in a year:"
|
"Find the number of days in a year:"
|
||||||
{ $subsection days-in-year }
|
{ $subsections days-in-year } ;
|
||||||
;
|
|
||||||
|
|
||||||
ARTICLE: "months" "Month operations"
|
ARTICLE: "months" "Month operations"
|
||||||
"Naming months:"
|
"Naming months:"
|
||||||
{ $subsection month-name }
|
{ $subsections
|
||||||
{ $subsection month-names }
|
month-name
|
||||||
{ $subsection month-abbreviation }
|
month-names
|
||||||
{ $subsection month-abbreviations }
|
month-abbreviation
|
||||||
;
|
month-abbreviations
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "calendar"
|
ABOUT: "calendar"
|
||||||
|
|
|
@ -37,10 +37,10 @@ HELP: from
|
||||||
ARTICLE: "channels" "Channels"
|
ARTICLE: "channels" "Channels"
|
||||||
"The " { $vocab-link "channels" } " vocabulary provides a simple abstraction to send and receive objects." $nl
|
"The " { $vocab-link "channels" } " vocabulary provides a simple abstraction to send and receive objects." $nl
|
||||||
"Opening a channel:"
|
"Opening a channel:"
|
||||||
{ $subsection <channel> }
|
{ $subsections <channel> }
|
||||||
"Sending a message:"
|
"Sending a message:"
|
||||||
{ $subsection to }
|
{ $subsections to }
|
||||||
"Receiving a message:"
|
"Receiving a message:"
|
||||||
{ $subsection from } ;
|
{ $subsections from } ;
|
||||||
|
|
||||||
ABOUT: "channels"
|
ABOUT: "channels"
|
||||||
|
|
|
@ -6,6 +6,6 @@ HELP: adler-32
|
||||||
|
|
||||||
ARTICLE: "checksums.adler-32" "Adler-32 checksum"
|
ARTICLE: "checksums.adler-32" "Adler-32 checksum"
|
||||||
"The Adler-32 checksum algorithm implements simple and fast checksum. It is used in zlib and rsync."
|
"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"
|
ABOUT: "checksums.adler-32"
|
||||||
|
|
|
@ -44,24 +44,29 @@ HELP: fnv1a-1024
|
||||||
|
|
||||||
ARTICLE: "checksums.fnv1" "Fowler-Noll-Vo checksum"
|
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."
|
"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."
|
||||||
|
{ $subsections
|
||||||
{ $subsection fnv1-32 }
|
fnv1-32
|
||||||
{ $subsection fnv1a-32 }
|
fnv1a-32
|
||||||
|
}
|
||||||
{ $subsection fnv1-64 }
|
{ $subsections
|
||||||
{ $subsection fnv1a-64 }
|
fnv1-64
|
||||||
|
fnv1a-64
|
||||||
{ $subsection fnv1-128 }
|
}
|
||||||
{ $subsection fnv1a-128 }
|
{ $subsections
|
||||||
|
fnv1-128
|
||||||
{ $subsection fnv1-256 }
|
fnv1a-128
|
||||||
{ $subsection fnv1a-256 }
|
}
|
||||||
|
{ $subsections
|
||||||
{ $subsection fnv1-512 }
|
fnv1-256
|
||||||
{ $subsection fnv1a-512 }
|
fnv1a-256
|
||||||
|
}
|
||||||
{ $subsection fnv1-1024 }
|
{ $subsections
|
||||||
{ $subsection fnv1a-1024 }
|
fnv1-512
|
||||||
;
|
fnv1a-512
|
||||||
|
}
|
||||||
|
{ $subsections
|
||||||
|
fnv1-1024
|
||||||
|
fnv1a-1024
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "checksums.fnv1"
|
ABOUT: "checksums.fnv1"
|
||||||
|
|
|
@ -6,6 +6,6 @@ HELP: md5
|
||||||
|
|
||||||
ARTICLE: "checksums.md5" "MD5 checksum"
|
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" } ")."
|
"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"
|
ABOUT: "checksums.md5"
|
||||||
|
|
|
@ -21,14 +21,16 @@ HELP: unknown-digest
|
||||||
|
|
||||||
ARTICLE: "checksums.openssl" "OpenSSL checksums"
|
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."
|
"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:"
|
"Constructing a checksum from a known name:"
|
||||||
{ $subsection <openssl-checksum> }
|
{ $subsections <openssl-checksum> }
|
||||||
"Two utility words:"
|
"Two utility words:"
|
||||||
{ $subsection openssl-md5 }
|
{ $subsections
|
||||||
{ $subsection openssl-sha1 }
|
openssl-md5
|
||||||
|
openssl-sha1
|
||||||
|
}
|
||||||
"An error thrown if the digest name is unrecognized:"
|
"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:"
|
"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\"" }
|
{ $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:"
|
"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"
|
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
|
"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:"
|
"SHA-2 checksums:"
|
||||||
{ $subsection sha-224 }
|
{ $subsections
|
||||||
{ $subsection sha-256 }
|
sha-224
|
||||||
|
sha-256
|
||||||
|
}
|
||||||
"SHA-1 checksum:"
|
"SHA-1 checksum:"
|
||||||
{ $subsection sha1 } ;
|
{ $subsections sha1 } ;
|
||||||
|
|
||||||
ABOUT: "checksums.sha"
|
ABOUT: "checksums.sha"
|
||||||
|
|
|
@ -51,14 +51,20 @@ HELP: rotate-circular
|
||||||
ARTICLE: "circular" "Circular sequences"
|
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
|
"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:"
|
"Creating a new circular object:"
|
||||||
{ $subsection <circular> }
|
{ $subsections
|
||||||
{ $subsection <circular-string> }
|
<circular>
|
||||||
{ $subsection <growing-circular> }
|
<circular-string>
|
||||||
|
<growing-circular>
|
||||||
|
}
|
||||||
"Changing the start index:"
|
"Changing the start index:"
|
||||||
{ $subsection change-circular-start }
|
{ $subsections
|
||||||
{ $subsection rotate-circular }
|
change-circular-start
|
||||||
|
rotate-circular
|
||||||
|
}
|
||||||
"Pushing new elements:"
|
"Pushing new elements:"
|
||||||
{ $subsection push-circular }
|
{ $subsections
|
||||||
{ $subsection push-growing-circular } ;
|
push-circular
|
||||||
|
push-growing-circular
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "circular"
|
ABOUT: "circular"
|
||||||
|
|
|
@ -120,21 +120,25 @@ ARTICLE: "classes.struct.examples" "Struct class examples"
|
||||||
|
|
||||||
ARTICLE: "classes.struct.define" "Defining struct classes"
|
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:"
|
"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."
|
"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"
|
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:"
|
"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> }
|
{ $subsections
|
||||||
{ $subsection <struct-boa> }
|
<struct>
|
||||||
{ $subsection malloc-struct }
|
<struct-boa>
|
||||||
{ $subsection memory>struct }
|
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:"
|
"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) }
|
{ $subsections
|
||||||
{ $subsection (malloc-struct) }
|
(struct)
|
||||||
|
(malloc-struct)
|
||||||
|
}
|
||||||
"Structs have literal syntax, similar to " { $link POSTPONE: T{ } " for tuples:"
|
"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"
|
ARTICLE: "classes.struct.c" "Passing structs to C functions"
|
||||||
"Structs can be passed and returned by value, or by reference."
|
"Structs can be passed and returned by value, or by reference."
|
||||||
|
@ -164,9 +168,11 @@ $nl
|
||||||
|
|
||||||
ARTICLE: "classes.struct" "Struct classes"
|
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" } "."
|
"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" }
|
{ $subsections
|
||||||
{ $subsection "classes.struct.define" }
|
"classes.struct.examples"
|
||||||
{ $subsection "classes.struct.create" }
|
"classes.struct.define"
|
||||||
{ $subsection "classes.struct.c" } ;
|
"classes.struct.create"
|
||||||
|
"classes.struct.c"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "classes.struct"
|
ABOUT: "classes.struct"
|
||||||
|
|
|
@ -41,14 +41,18 @@ HELP: objc-error
|
||||||
|
|
||||||
ARTICLE: "cocoa-application-utils" "Cocoa application utilities"
|
ARTICLE: "cocoa-application-utils" "Cocoa application utilities"
|
||||||
"Utilities:"
|
"Utilities:"
|
||||||
{ $subsection NSApp }
|
{ $subsections
|
||||||
{ $subsection add-observer }
|
NSApp
|
||||||
{ $subsection remove-observer }
|
add-observer
|
||||||
{ $subsection install-delegate }
|
remove-observer
|
||||||
|
install-delegate
|
||||||
|
}
|
||||||
"Combinators:"
|
"Combinators:"
|
||||||
{ $subsection cocoa-app }
|
{ $subsections
|
||||||
{ $subsection with-autorelease-pool }
|
cocoa-app
|
||||||
{ $subsection with-cocoa } ;
|
with-autorelease-pool
|
||||||
|
with-cocoa
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: cocoa.application
|
IN: cocoa.application
|
||||||
ABOUT: "cocoa-application-utils"
|
ABOUT: "cocoa-application-utils"
|
||||||
|
|
|
@ -25,15 +25,19 @@ HELP: IMPORT:
|
||||||
|
|
||||||
ARTICLE: "objc-calling" "Calling Objective C code"
|
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."
|
"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."
|
"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
|
$nl
|
||||||
"Messages can be sent to classes and instances using a pair of parsing words:"
|
"Messages can be sent to classes and instances using a pair of parsing words:"
|
||||||
{ $subsection POSTPONE: -> }
|
{ $subsections
|
||||||
{ $subsection POSTPONE: SUPER-> }
|
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:"
|
"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 }
|
{ $subsections
|
||||||
{ $subsection super-send } ;
|
send
|
||||||
|
super-send
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "cocoa" "Cocoa bridge"
|
ARTICLE: "cocoa" "Cocoa bridge"
|
||||||
"The " { $vocab-link "cocoa" } " vocabulary implements a Factor-Cocoa bridge for Mac OS X (GNUstep is not supported)."
|
"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."
|
"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
|
$nl
|
||||||
"On top of this, a dynamic message send facility is built:"
|
"On top of this, a dynamic message send facility is built:"
|
||||||
{ $subsection "objc-calling" }
|
{ $subsections
|
||||||
{ $subsection "objc-subclassing" }
|
"objc-calling"
|
||||||
|
"objc-subclassing"
|
||||||
|
}
|
||||||
"A utility library is built to faciliate the development of Cocoa applications in Factor:"
|
"A utility library is built to faciliate the development of Cocoa applications in Factor:"
|
||||||
{ $subsection "cocoa-application-utils" }
|
{ $subsections
|
||||||
{ $subsection "cocoa-dialogs" }
|
"cocoa-application-utils"
|
||||||
{ $subsection "cocoa-pasteboard-utils" }
|
"cocoa-dialogs"
|
||||||
{ $subsection "cocoa-view-utils" }
|
"cocoa-pasteboard-utils"
|
||||||
{ $subsection "cocoa-window-utils" } ;
|
"cocoa-view-utils"
|
||||||
|
"cocoa-window-utils"
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: cocoa
|
IN: cocoa
|
||||||
ABOUT: "cocoa"
|
ABOUT: "cocoa"
|
||||||
|
|
|
@ -19,11 +19,15 @@ HELP: save-panel
|
||||||
|
|
||||||
ARTICLE: "cocoa-dialogs" "Cocoa file dialogs"
|
ARTICLE: "cocoa-dialogs" "Cocoa file dialogs"
|
||||||
"Open dialogs:"
|
"Open dialogs:"
|
||||||
{ $subsection <NSOpenPanel> }
|
{ $subsections
|
||||||
{ $subsection open-panel }
|
<NSOpenPanel>
|
||||||
|
open-panel
|
||||||
|
}
|
||||||
"Save dialogs:"
|
"Save dialogs:"
|
||||||
{ $subsection <NSSavePanel> }
|
{ $subsections
|
||||||
{ $subsection save-panel } ;
|
<NSSavePanel>
|
||||||
|
save-panel
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: cocoa.dialogs
|
IN: cocoa.dialogs
|
||||||
ABOUT: "cocoa-dialogs"
|
ABOUT: "cocoa-dialogs"
|
||||||
|
|
|
@ -14,9 +14,11 @@ HELP: set-pasteboard-string
|
||||||
{ $description "Sets the contents of the pasteboard." } ;
|
{ $description "Sets the contents of the pasteboard." } ;
|
||||||
|
|
||||||
ARTICLE: "cocoa-pasteboard-utils" "Cocoa pasteboard utilities"
|
ARTICLE: "cocoa-pasteboard-utils" "Cocoa pasteboard utilities"
|
||||||
{ $subsection pasteboard-string? }
|
{ $subsections
|
||||||
{ $subsection pasteboard-string }
|
pasteboard-string?
|
||||||
{ $subsection set-pasteboard-string } ;
|
pasteboard-string
|
||||||
|
set-pasteboard-string
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: cocoa.pasteboard
|
IN: cocoa.pasteboard
|
||||||
ABOUT: "cocoa-pasteboard-utils"
|
ABOUT: "cocoa-pasteboard-utils"
|
||||||
|
|
|
@ -37,9 +37,9 @@ HELP: CLASS:
|
||||||
|
|
||||||
ARTICLE: "objc-subclassing" "Subclassing Objective C classes"
|
ARTICLE: "objc-subclassing" "Subclassing Objective C classes"
|
||||||
"Objective C classes can be subclassed, with new methods defined in Factor, using a parsing word:"
|
"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:"
|
"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." ;
|
"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
|
IN: cocoa.subclassing
|
||||||
|
|
|
@ -14,9 +14,11 @@ HELP: mouse-location
|
||||||
{ $description "Outputs the current mouse location." } ;
|
{ $description "Outputs the current mouse location." } ;
|
||||||
|
|
||||||
ARTICLE: "cocoa-view-utils" "Cocoa view utilities"
|
ARTICLE: "cocoa-view-utils" "Cocoa view utilities"
|
||||||
{ $subsection <GLView> }
|
{ $subsections
|
||||||
{ $subsection view-dim }
|
<GLView>
|
||||||
{ $subsection mouse-location } ;
|
view-dim
|
||||||
|
mouse-location
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: cocoa.views
|
IN: cocoa.views
|
||||||
ABOUT: "cocoa-view-utils"
|
ABOUT: "cocoa-view-utils"
|
||||||
|
|
|
@ -10,8 +10,10 @@ HELP: <ViewWindow>
|
||||||
{ $description "Creates a new " { $snippet "NSWindow" } " with the specified dimensions, containing the given view." } ;
|
{ $description "Creates a new " { $snippet "NSWindow" } " with the specified dimensions, containing the given view." } ;
|
||||||
|
|
||||||
ARTICLE: "cocoa-window-utils" "Cocoa window utilities"
|
ARTICLE: "cocoa-window-utils" "Cocoa window utilities"
|
||||||
{ $subsection <NSWindow> }
|
{ $subsections
|
||||||
{ $subsection <ViewWindow> } ;
|
<NSWindow>
|
||||||
|
<ViewWindow>
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: cocoa.windows
|
IN: cocoa.windows
|
||||||
ABOUT: "cocoa-window-utils"
|
ABOUT: "cocoa-window-utils"
|
||||||
|
|
|
@ -13,7 +13,7 @@ HELP: >rgba
|
||||||
|
|
||||||
ARTICLE: "colors.protocol" "Color protocol"
|
ARTICLE: "colors.protocol" "Color protocol"
|
||||||
"Abstract superclass for colors:"
|
"Abstract superclass for colors:"
|
||||||
{ $subsection color }
|
{ $subsections color }
|
||||||
"All color objects must are required to implement a method on the " { $link >rgba } " generic word."
|
"All color objects must are required to implement a method on the " { $link >rgba } " generic word."
|
||||||
$nl
|
$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."
|
"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."
|
"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
|
$nl
|
||||||
"RGBA colors with floating point components in the range " { $snippet "[0,1]" } ":"
|
"RGBA colors with floating point components in the range " { $snippet "[0,1]" } ":"
|
||||||
{ $subsection rgba }
|
{ $subsections
|
||||||
{ $subsection <rgba> }
|
rgba
|
||||||
|
<rgba>
|
||||||
|
}
|
||||||
"Converting a color to RGBA:"
|
"Converting a color to RGBA:"
|
||||||
{ $subsection >rgba }
|
{ $subsections >rgba }
|
||||||
"Extracting RGBA components of colors:"
|
"Extracting RGBA components of colors:"
|
||||||
{ $subsection >rgba-components }
|
{ $subsections >rgba-components }
|
||||||
"Further topics:"
|
"Further topics:"
|
||||||
{ $subsection "colors.protocol" }
|
{ $subsections
|
||||||
{ $subsection "colors.constants" }
|
"colors.protocol"
|
||||||
|
"colors.constants"
|
||||||
|
}
|
||||||
{ $vocab-subsection "Grayscale colors" "colors.gray" }
|
{ $vocab-subsection "Grayscale colors" "colors.gray" }
|
||||||
{ $vocab-subsection "HSV colors" "colors.hsv" } ;
|
{ $vocab-subsection "HSV colors" "colors.hsv" } ;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,10 @@ HELP: COLOR:
|
||||||
|
|
||||||
ARTICLE: "colors.constants" "Standard color database"
|
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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection named-colors }
|
named-color
|
||||||
{ $subsection POSTPONE: COLOR: } ;
|
named-colors
|
||||||
|
POSTPONE: COLOR:
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "colors.constants"
|
ABOUT: "colors.constants"
|
|
@ -3,7 +3,9 @@ IN: colors.gray
|
||||||
|
|
||||||
ARTICLE: "colors.gray" "Grayscale colors"
|
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>> } "."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <gray> } ;
|
gray
|
||||||
|
<gray>
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "colors.gray"
|
ABOUT: "colors.gray"
|
|
@ -6,8 +6,10 @@ HELP: hsva
|
||||||
|
|
||||||
ARTICLE: "colors.hsv" "HSV colors"
|
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."
|
"The " { $vocab-link "colors.hsv" } " vocabulary implements colors specified by their hue, saturation, and value, together with an alpha channel."
|
||||||
{ $subsection hsva }
|
{ $subsections
|
||||||
{ $subsection <hsva> }
|
hsva
|
||||||
|
<hsva>
|
||||||
|
}
|
||||||
{ $see-also "colors" } ;
|
{ $see-also "colors" } ;
|
||||||
|
|
||||||
ABOUT: "colors.hsv"
|
ABOUT: "colors.hsv"
|
|
@ -25,9 +25,11 @@ HELP: <flipped>
|
||||||
|
|
||||||
ARTICLE: "columns" "Column sequences"
|
ARTICLE: "columns" "Column sequences"
|
||||||
"A " { $emphasis "column" } " presents a column of a matrix represented as a sequence of rows:"
|
"A " { $emphasis "column" } " presents a column of a matrix represented as a sequence of rows:"
|
||||||
{ $subsection column }
|
{ $subsections
|
||||||
{ $subsection <column> }
|
column
|
||||||
|
<column>
|
||||||
|
}
|
||||||
"A utility word:"
|
"A utility word:"
|
||||||
{ $subsection <flipped> } ;
|
{ $subsections <flipped> } ;
|
||||||
|
|
||||||
ABOUT: "columns"
|
ABOUT: "columns"
|
||||||
|
|
|
@ -51,18 +51,24 @@ HELP: n||
|
||||||
ARTICLE: "combinators.short-circuit" "Short-circuit combinators"
|
ARTICLE: "combinators.short-circuit" "Short-circuit combinators"
|
||||||
"The " { $vocab-link "combinators.short-circuit" } " vocabulary stops a computation early once a condition is met." $nl
|
"The " { $vocab-link "combinators.short-circuit" } " vocabulary stops a computation early once a condition is met." $nl
|
||||||
"AND combinators:"
|
"AND combinators:"
|
||||||
{ $subsection 0&& }
|
{ $subsections
|
||||||
{ $subsection 1&& }
|
0&&
|
||||||
{ $subsection 2&& }
|
1&&
|
||||||
{ $subsection 3&& }
|
2&&
|
||||||
|
3&&
|
||||||
|
}
|
||||||
"OR combinators:"
|
"OR combinators:"
|
||||||
{ $subsection 0|| }
|
{ $subsections
|
||||||
{ $subsection 1|| }
|
0||
|
||||||
{ $subsection 2|| }
|
1||
|
||||||
{ $subsection 3|| }
|
2||
|
||||||
|
3||
|
||||||
|
}
|
||||||
"Generalized combinators:"
|
"Generalized combinators:"
|
||||||
{ $subsection n&& }
|
{ $subsections
|
||||||
{ $subsection n|| }
|
n&&
|
||||||
|
n||
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
ABOUT: "combinators.short-circuit"
|
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."
|
"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
|
$nl
|
||||||
"Generalized AND:"
|
"Generalized AND:"
|
||||||
{ $subsection && }
|
{ $subsections && }
|
||||||
"Generalized OR:"
|
"Generalized OR:"
|
||||||
{ $subsection || } ;
|
{ $subsections || } ;
|
||||||
|
|
||||||
ABOUT: "combinators.short-circuit.smart"
|
ABOUT: "combinators.short-circuit.smart"
|
||||||
|
|
|
@ -119,20 +119,26 @@ HELP: keep-inputs
|
||||||
ARTICLE: "combinators.smart" "Smart combinators"
|
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
|
"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:"
|
"Call a quotation and discard all output values or preserve all input values:"
|
||||||
{ $subsection drop-outputs }
|
{ $subsections
|
||||||
{ $subsection keep-inputs }
|
drop-outputs
|
||||||
|
keep-inputs
|
||||||
|
}
|
||||||
"Take all input values from a sequence:"
|
"Take all input values from a sequence:"
|
||||||
{ $subsection input<sequence }
|
{ $subsections input<sequence }
|
||||||
"Store all output values to a sequence:"
|
"Store all output values to a sequence:"
|
||||||
{ $subsection output>sequence }
|
{ $subsections
|
||||||
{ $subsection output>array }
|
output>sequence
|
||||||
|
output>array
|
||||||
|
}
|
||||||
"Reducing the set of output values:"
|
"Reducing the set of output values:"
|
||||||
{ $subsection reduce-outputs }
|
{ $subsections reduce-outputs }
|
||||||
"Summing output values:"
|
"Summing output values:"
|
||||||
{ $subsection sum-outputs }
|
{ $subsections sum-outputs }
|
||||||
"Concatenating output values:"
|
"Concatenating output values:"
|
||||||
{ $subsection append-outputs }
|
{ $subsections
|
||||||
{ $subsection append-outputs-as }
|
append-outputs
|
||||||
|
append-outputs-as
|
||||||
|
}
|
||||||
"New smart combinators can be created by defining " { $link "macros" } " which call " { $link infer } "." ;
|
"New smart combinators can be created by defining " { $link "macros" } " which call " { $link infer } "." ;
|
||||||
|
|
||||||
ABOUT: "combinators.smart"
|
ABOUT: "combinators.smart"
|
||||||
|
|
|
@ -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."
|
"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
|
$nl
|
||||||
"A word to run this file from an existing Factor session:"
|
"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." ;
|
"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"
|
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."
|
"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
|
$nl
|
||||||
"A word to run this file from an existing Factor session:"
|
"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"
|
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" } "."
|
"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
|
$nl
|
||||||
"A word to run this file from an existing Factor session:"
|
"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"
|
ARTICLE: "rc-files" "Running code on startup"
|
||||||
"Factor looks for three optional files in your home directory."
|
"Factor looks for three optional files in your home directory."
|
||||||
{ $subsection "factor-boot-rc" }
|
{ $subsections
|
||||||
{ $subsection "factor-rc" }
|
"factor-boot-rc"
|
||||||
{ $subsection "factor-roots" }
|
"factor-rc"
|
||||||
|
"factor-roots"
|
||||||
|
}
|
||||||
"The " { $snippet "-no-user-init" } " command line switch will inhibit loading running of these files."
|
"The " { $snippet "-no-user-init" } " command line switch will inhibit loading running of these files."
|
||||||
$nl
|
$nl
|
||||||
"If you are unsure where the files should be located, evaluate the following code:"
|
"If you are unsure where the files should be located, evaluate the following code:"
|
||||||
|
@ -139,7 +141,7 @@ ARTICLE: "cli" "Command line arguments"
|
||||||
"Factor command line usage:"
|
"Factor command line usage:"
|
||||||
{ $code "factor [system switches...] [script args...]" }
|
{ $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:"
|
"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 }
|
{ $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:"
|
"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>" }
|
{ $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."
|
"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 +154,14 @@ $nl
|
||||||
{ { $snippet "-no-" { $emphasis "foo" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $link f } }
|
{ { $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" } "\"" } }
|
{ { $snippet "-" { $emphasis "foo" } "=" { $emphasis "bar" } } " - sets the global variable " { $snippet "\"" { $emphasis "foo" } "\"" } " to " { $snippet "\"" { $emphasis "bar" } "\"" } }
|
||||||
}
|
}
|
||||||
{ $subsection "runtime-cli-args" }
|
{ $subsections
|
||||||
{ $subsection "bootstrap-cli-args" }
|
"runtime-cli-args"
|
||||||
{ $subsection "standard-cli-args" }
|
"bootstrap-cli-args"
|
||||||
|
"standard-cli-args"
|
||||||
|
}
|
||||||
"The raw list of command line arguments can also be obtained and inspected directly:"
|
"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:"
|
"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"
|
ABOUT: "cli"
|
||||||
|
|
|
@ -12,19 +12,21 @@ HELP: disable-optimizer
|
||||||
|
|
||||||
ARTICLE: "compiler-usage" "Calling the optimizing compiler"
|
ARTICLE: "compiler-usage" "Calling the optimizing compiler"
|
||||||
"Normally, new word definitions are recompiled automatically. This can be changed:"
|
"Normally, new word definitions are recompiled automatically. This can be changed:"
|
||||||
{ $subsection disable-optimizer }
|
{ $subsections
|
||||||
{ $subsection enable-optimizer }
|
disable-optimizer
|
||||||
|
enable-optimizer
|
||||||
|
}
|
||||||
"Removing a word's optimized definition:"
|
"Removing a word's optimized definition:"
|
||||||
{ $subsection decompile }
|
{ $subsections decompile }
|
||||||
"Compiling a single quotation:"
|
"Compiling a single quotation:"
|
||||||
{ $subsection compile-call }
|
{ $subsections compile-call }
|
||||||
"Higher-level words can be found in " { $link "compilation-units" } "." ;
|
"Higher-level words can be found in " { $link "compilation-units" } "." ;
|
||||||
|
|
||||||
ARTICLE: "compiler-impl" "Compiler implementation"
|
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."
|
"The " { $vocab-link "compiler" } "vocabulary, in addition to providing the user-visible words of the compiler, implements the main compilation loop."
|
||||||
$nl
|
$nl
|
||||||
"Words are added to the " { $link compile-queue } " variable as needed and compiled."
|
"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 } "."
|
"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
|
$nl
|
||||||
"The " { $link compile-word } " word performs the actual task of compiling an individual word. The process proceeds as follows:"
|
"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."
|
"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
|
$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( } "."
|
"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" }
|
{ $subsections
|
||||||
{ $subsection "hints" }
|
"compiler-errors"
|
||||||
{ $subsection "compiler-usage" }
|
"hints"
|
||||||
{ $subsection "compiler-impl" } ;
|
"compiler-usage"
|
||||||
|
"compiler-impl"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "compiler"
|
ABOUT: "compiler"
|
||||||
|
|
||||||
|
|
|
@ -71,13 +71,15 @@ ARTICLE: "compression.lzw" "LZW Compression"
|
||||||
$nl
|
$nl
|
||||||
"Implements both the TIFF and GIF variations of the LZW algorithm."
|
"Implements both the TIFF and GIF variations of the LZW algorithm."
|
||||||
{ $heading "Decompression" }
|
{ $heading "Decompression" }
|
||||||
{ $subsection tiff-lzw-uncompress }
|
{ $subsections
|
||||||
{ $subsection gif-lzw-uncompress }
|
tiff-lzw-uncompress
|
||||||
|
gif-lzw-uncompress
|
||||||
|
}
|
||||||
{ $heading "Compression" }
|
{ $heading "Compression" }
|
||||||
"Compression has not yet been implemented."
|
"Compression has not yet been implemented."
|
||||||
$nl
|
$nl
|
||||||
"Implementation details:"
|
"Implementation details:"
|
||||||
{ $subsection "compression.lzw.differences" }
|
{ $subsections "compression.lzw.differences" }
|
||||||
;
|
;
|
||||||
|
|
||||||
ABOUT: "compression.lzw"
|
ABOUT: "compression.lzw"
|
||||||
|
|
|
@ -30,14 +30,18 @@ ARTICLE: "concurrency.combinators" "Concurrent combinators"
|
||||||
"The " { $vocab-link "concurrency.combinators" } " vocabulary provides concurrent variants of various combinators."
|
"The " { $vocab-link "concurrency.combinators" } " vocabulary provides concurrent variants of various combinators."
|
||||||
$nl
|
$nl
|
||||||
"Concurrent sequence combinators:"
|
"Concurrent sequence combinators:"
|
||||||
{ $subsection parallel-each }
|
{ $subsections
|
||||||
{ $subsection 2parallel-each }
|
parallel-each
|
||||||
{ $subsection parallel-map }
|
2parallel-each
|
||||||
{ $subsection 2parallel-map }
|
parallel-map
|
||||||
{ $subsection parallel-filter }
|
2parallel-map
|
||||||
|
parallel-filter
|
||||||
|
}
|
||||||
"Concurrent cleave combinators:"
|
"Concurrent cleave combinators:"
|
||||||
{ $subsection parallel-cleave }
|
{ $subsections
|
||||||
{ $subsection parallel-spread }
|
parallel-cleave
|
||||||
{ $subsection parallel-napply } ;
|
parallel-spread
|
||||||
|
parallel-napply
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.combinators"
|
ABOUT: "concurrency.combinators"
|
||||||
|
|
|
@ -17,9 +17,11 @@ HELP: await
|
||||||
|
|
||||||
ARTICLE: "concurrency.count-downs" "Count-down latches"
|
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."
|
"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> }
|
{ $subsections
|
||||||
{ $subsection count-down }
|
<count-down>
|
||||||
{ $subsection await }
|
count-down
|
||||||
|
await
|
||||||
|
}
|
||||||
"The vocabulary was modelled after a similar feature in Java's " { $snippet "java.util.concurrent" } " library." ;
|
"The vocabulary was modelled after a similar feature in Java's " { $snippet "java.util.concurrent" } " library." ;
|
||||||
|
|
||||||
ABOUT: "concurrency.count-downs"
|
ABOUT: "concurrency.count-downs"
|
||||||
|
|
|
@ -10,9 +10,9 @@ HELP: start-node
|
||||||
|
|
||||||
ARTICLE: "concurrency.distributed" "Distributed message passing"
|
ARTICLE: "concurrency.distributed" "Distributed message passing"
|
||||||
"The " { $vocab-link "concurrency.distributed" } " implements transparent distributed message passing, inspired by Erlang and Termite."
|
"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:"
|
"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." ;
|
"The " { $vocab-link "serialize" } " vocabulary is used to convert Factor objects to byte arrays for transfer over a socket." ;
|
||||||
|
|
||||||
ABOUT: "concurrency.distributed"
|
ABOUT: "concurrency.distributed"
|
||||||
|
|
|
@ -14,9 +14,11 @@ HELP: exchange
|
||||||
|
|
||||||
ARTICLE: "concurrency.exchangers" "Object exchange points"
|
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."
|
"The " { $vocab-link "concurrency.exchangers" } " vocabulary implements " { $emphasis "object exchange points" } ", which are rendezvous points where two threads can exchange objects."
|
||||||
{ $subsection exchanger }
|
{ $subsections
|
||||||
{ $subsection <exchanger> }
|
exchanger
|
||||||
{ $subsection exchange }
|
<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."
|
"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
|
$nl
|
||||||
"The vocabulary was modelled after a similar feature in Java's " { $snippet "java.util.concurrent" } " library." ;
|
"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."
|
"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
|
$nl
|
||||||
"Essentially, a flag can be thought of as a counting semaphore where the count never goes above one."
|
"Essentially, a flag can be thought of as a counting semaphore where the count never goes above one."
|
||||||
{ $subsection flag }
|
{ $subsections
|
||||||
{ $subsection flag? }
|
flag
|
||||||
|
flag?
|
||||||
|
}
|
||||||
"Waiting for a flag to be raised:"
|
"Waiting for a flag to be raised:"
|
||||||
{ $subsection raise-flag }
|
{ $subsections
|
||||||
{ $subsection wait-for-flag }
|
raise-flag
|
||||||
{ $subsection lower-flag } ;
|
wait-for-flag
|
||||||
|
lower-flag
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.flags"
|
ABOUT: "concurrency.flags"
|
||||||
|
|
|
@ -22,8 +22,10 @@ HELP: ?future
|
||||||
|
|
||||||
ARTICLE: "concurrency.futures" "Futures"
|
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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection ?future }
|
future
|
||||||
{ $subsection ?future-timeout } ;
|
?future
|
||||||
|
?future-timeout
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.futures"
|
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."
|
"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
|
$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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <lock> }
|
lock
|
||||||
{ $subsection <reentrant-lock> }
|
<lock>
|
||||||
{ $subsection with-lock }
|
<reentrant-lock>
|
||||||
{ $subsection with-lock-timeout } ;
|
with-lock
|
||||||
|
with-lock-timeout
|
||||||
|
} ;
|
||||||
|
|
||||||
HELP: rw-lock
|
HELP: rw-lock
|
||||||
{ $class-description "The class of reader/writer locks." } ;
|
{ $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."
|
"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
|
$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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <rw-lock> }
|
rw-lock
|
||||||
{ $subsection with-read-lock }
|
<rw-lock>
|
||||||
{ $subsection with-write-lock }
|
with-read-lock
|
||||||
|
with-write-lock
|
||||||
|
}
|
||||||
"Versions of the above that take a timeout duration:"
|
"Versions of the above that take a timeout duration:"
|
||||||
{ $subsection with-read-lock-timeout }
|
{ $subsections
|
||||||
{ $subsection with-write-lock-timeout } ;
|
with-read-lock-timeout
|
||||||
|
with-write-lock-timeout
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "concurrency.locks" "Locks"
|
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:"
|
"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" }
|
{ $subsections
|
||||||
{ $subsection "concurrency.locks.rw" } ;
|
"concurrency.locks.mutex"
|
||||||
|
"concurrency.locks.rw"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.locks"
|
ABOUT: "concurrency.locks"
|
||||||
|
|
|
@ -53,20 +53,28 @@ HELP: mailbox-get?
|
||||||
|
|
||||||
ARTICLE: "concurrency.mailboxes" "Mailboxes"
|
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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <mailbox> }
|
mailbox
|
||||||
|
<mailbox>
|
||||||
|
}
|
||||||
"Removing the first element:"
|
"Removing the first element:"
|
||||||
{ $subsection mailbox-get }
|
{ $subsections
|
||||||
{ $subsection mailbox-get-timeout }
|
mailbox-get
|
||||||
|
mailbox-get-timeout
|
||||||
|
}
|
||||||
"Removing the first element matching a predicate:"
|
"Removing the first element matching a predicate:"
|
||||||
{ $subsection mailbox-get? }
|
{ $subsections
|
||||||
{ $subsection mailbox-get-timeout? }
|
mailbox-get?
|
||||||
|
mailbox-get-timeout?
|
||||||
|
}
|
||||||
"Emptying out a mailbox:"
|
"Emptying out a mailbox:"
|
||||||
{ $subsection mailbox-get-all }
|
{ $subsections mailbox-get-all }
|
||||||
"Adding an element:"
|
"Adding an element:"
|
||||||
{ $subsection mailbox-put }
|
{ $subsections mailbox-put }
|
||||||
"Testing if a mailbox is empty:"
|
"Testing if a mailbox is empty:"
|
||||||
{ $subsection mailbox-empty? }
|
{ $subsections
|
||||||
{ $subsection while-mailbox-empty } ;
|
mailbox-empty?
|
||||||
|
while-mailbox-empty
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.mailboxes"
|
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."
|
"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
|
$nl
|
||||||
"The " { $link spawn } " word pushes the newly-created thread on the calling thread's stack; this thread object can then be sent messages:"
|
"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:"
|
"A thread can get a message from its queue:"
|
||||||
{ $subsection receive }
|
{ $subsections
|
||||||
{ $subsection receive-timeout }
|
receive
|
||||||
{ $subsection receive-if }
|
receive-timeout
|
||||||
{ $subsection receive-if-timeout }
|
receive-if
|
||||||
|
receive-if-timeout
|
||||||
|
}
|
||||||
{ $see-also "concurrency.mailboxes" } ;
|
{ $see-also "concurrency.mailboxes" } ;
|
||||||
|
|
||||||
ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends"
|
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:"
|
"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:"
|
"To reply to a synchronous message:"
|
||||||
{ $subsection reply-synchronous }
|
{ $subsections reply-synchronous }
|
||||||
"An example:"
|
"An example:"
|
||||||
{ $example
|
{ $example
|
||||||
"USING: concurrency.messaging threads ;"
|
"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:"
|
"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" }
|
{ $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."
|
"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:"
|
"This will create a unidirectional link, such that if an uncaught exception causes the child to terminate, the parent thread can catch it:"
|
||||||
{ $code "["
|
{ $code "["
|
||||||
" [ 1 0 / \"This will not print\" print ] \"linked-division\" spawn-linked drop"
|
" [ 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."
|
"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
|
$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."
|
"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" } }
|
{ $subsections
|
||||||
{ $subsection { "concurrency" "synchronous-sends" } }
|
{ "concurrency" "messaging" }
|
||||||
{ $subsection { "concurrency" "exceptions" } } ;
|
{ "concurrency" "synchronous-sends" }
|
||||||
|
{ "concurrency" "exceptions" }
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.messaging"
|
ABOUT: "concurrency.messaging"
|
||||||
|
|
|
@ -31,10 +31,12 @@ HELP: fulfill
|
||||||
|
|
||||||
ARTICLE: "concurrency.promises" "Promises"
|
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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <promise> }
|
promise
|
||||||
{ $subsection fulfill }
|
<promise>
|
||||||
{ $subsection ?promise }
|
fulfill
|
||||||
{ $subsection ?promise-timeout } ;
|
?promise
|
||||||
|
?promise-timeout
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.promises"
|
ABOUT: "concurrency.promises"
|
||||||
|
|
|
@ -43,14 +43,20 @@ $nl
|
||||||
"] parallel-map"
|
"] parallel-map"
|
||||||
}
|
}
|
||||||
"Creating semaphores:"
|
"Creating semaphores:"
|
||||||
{ $subsection semaphore }
|
{ $subsections
|
||||||
{ $subsection <semaphore> }
|
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:"
|
"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 }
|
{ $subsections
|
||||||
{ $subsection acquire-timeout }
|
acquire
|
||||||
{ $subsection release }
|
acquire-timeout
|
||||||
|
release
|
||||||
|
}
|
||||||
"Combinators which pair acquisition and release:"
|
"Combinators which pair acquisition and release:"
|
||||||
{ $subsection with-semaphore }
|
{ $subsections
|
||||||
{ $subsection with-semaphore-timeout } ;
|
with-semaphore
|
||||||
|
with-semaphore-timeout
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "concurrency.semaphores"
|
ABOUT: "concurrency.semaphores"
|
||||||
|
|
|
@ -21,9 +21,11 @@ ARTICLE: "core-graphics.types" "Core Graphics types"
|
||||||
"CGSize"
|
"CGSize"
|
||||||
}
|
}
|
||||||
"Some words for working with the above:"
|
"Some words for working with the above:"
|
||||||
{ $subsection <CGRect> }
|
{ $subsections
|
||||||
{ $subsection <CGPoint> }
|
<CGRect>
|
||||||
{ $subsection <CGSize> } ;
|
<CGPoint>
|
||||||
|
<CGSize>
|
||||||
|
} ;
|
||||||
|
|
||||||
IN: core-graphics.types
|
IN: core-graphics.types
|
||||||
ABOUT: "core-graphics.types"
|
ABOUT: "core-graphics.types"
|
||||||
|
|
|
@ -39,14 +39,14 @@ HELP: with-delimiter
|
||||||
ARTICLE: "csv" "Comma-separated-values parsing and writing"
|
ARTICLE: "csv" "Comma-separated-values parsing and writing"
|
||||||
"The " { $vocab-link "csv" } " vocabulary can read and write CSV (comma-separated-value) files." $nl
|
"The " { $vocab-link "csv" } " vocabulary can read and write CSV (comma-separated-value) files." $nl
|
||||||
"Reading a csv file:"
|
"Reading a csv file:"
|
||||||
{ $subsection file>csv }
|
{ $subsections file>csv }
|
||||||
"Writing a csv file:"
|
"Writing a csv file:"
|
||||||
{ $subsection csv>file }
|
{ $subsections csv>file }
|
||||||
"Changing the delimiter from a comma:"
|
"Changing the delimiter from a comma:"
|
||||||
{ $subsection with-delimiter }
|
{ $subsections with-delimiter }
|
||||||
"Reading from a stream:"
|
"Reading from a stream:"
|
||||||
{ $subsection csv }
|
{ $subsections csv }
|
||||||
"Writing to a stream:"
|
"Writing to a stream:"
|
||||||
{ $subsection write-csv } ;
|
{ $subsections write-csv } ;
|
||||||
|
|
||||||
ABOUT: "csv"
|
ABOUT: "csv"
|
||||||
|
|
|
@ -31,8 +31,10 @@ HELP: statement
|
||||||
|
|
||||||
HELP: result-set
|
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."
|
{ $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" }
|
{ $subsections
|
||||||
{ $subsection "db-sequential-result-set" }
|
"db-random-access-result-set"
|
||||||
|
"db-sequential-result-set"
|
||||||
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
HELP: new-result-set
|
HELP: new-result-set
|
||||||
|
@ -177,14 +179,16 @@ HELP: with-transaction
|
||||||
|
|
||||||
ARTICLE: "db" "Database library"
|
ARTICLE: "db" "Database library"
|
||||||
"Accessing a database:"
|
"Accessing a database:"
|
||||||
{ $subsection "db-custom-database-combinators" }
|
{ $subsections "db-custom-database-combinators" }
|
||||||
"Higher-level database help:"
|
"Higher-level database help:"
|
||||||
{ $vocab-subsection "Database types" "db.types" }
|
{ $vocab-subsection "Database types" "db.types" }
|
||||||
{ $vocab-subsection "High-level tuple/database integration" "db.tuples" }
|
{ $vocab-subsection "High-level tuple/database integration" "db.tuples" }
|
||||||
"Low-level database help:"
|
"Low-level database help:"
|
||||||
{ $subsection "db-protocol" }
|
{ $subsections
|
||||||
{ $subsection "db-result-sets" }
|
"db-protocol"
|
||||||
{ $subsection "db-lowlevel-tutorial" }
|
"db-result-sets"
|
||||||
|
"db-lowlevel-tutorial"
|
||||||
|
}
|
||||||
"Supported database backends:"
|
"Supported database backends:"
|
||||||
{ $vocab-subsection "SQLite" "db.sqlite" }
|
{ $vocab-subsection "SQLite" "db.sqlite" }
|
||||||
{ $vocab-subsection "PostgreSQL" "db.postgresql" } ;
|
{ $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."
|
"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
|
$nl
|
||||||
"Databases which work in this way must provide methods for the following traversal words:"
|
"Databases which work in this way must provide methods for the following traversal words:"
|
||||||
{ $subsection #rows }
|
{ $subsections
|
||||||
{ $subsection #columns }
|
#rows
|
||||||
{ $subsection row-column }
|
#columns
|
||||||
{ $subsection row-column-typed } ;
|
row-column
|
||||||
|
row-column-typed
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "db-sequential-result-set" "Sequential result sets"
|
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."
|
"Sequential result sets can be iterated one element after the next. SQLite's result sets offer this method of traversal."
|
||||||
$nl
|
$nl
|
||||||
"Databases which work in this way must provide methods for the following traversal words:"
|
"Databases which work in this way must provide methods for the following traversal words:"
|
||||||
{ $subsection more-rows? }
|
{ $subsections
|
||||||
{ $subsection advance-row }
|
more-rows?
|
||||||
{ $subsection row-column }
|
advance-row
|
||||||
{ $subsection row-column-typed } ;
|
row-column
|
||||||
|
row-column-typed
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "db-result-sets" "Result sets"
|
ARTICLE: "db-result-sets" "Result sets"
|
||||||
"Result sets are the encapsulated, database-specific results from a SQL query."
|
"Result sets are the encapsulated, database-specific results from a SQL query."
|
||||||
$nl
|
$nl
|
||||||
"Two possible protocols for iterating over result sets exist:"
|
"Two possible protocols for iterating over result sets exist:"
|
||||||
{ $subsection "db-random-access-result-set" }
|
{ $subsections
|
||||||
{ $subsection "db-sequential-result-set" }
|
"db-random-access-result-set"
|
||||||
|
"db-sequential-result-set"
|
||||||
|
}
|
||||||
"Query the number of rows or columns:"
|
"Query the number of rows or columns:"
|
||||||
{ $subsection #rows }
|
{ $subsections
|
||||||
{ $subsection #columns }
|
#rows
|
||||||
|
#columns
|
||||||
|
}
|
||||||
"Traversing a result set:"
|
"Traversing a result set:"
|
||||||
{ $subsection advance-row }
|
{ $subsections
|
||||||
{ $subsection more-rows? }
|
advance-row
|
||||||
|
more-rows?
|
||||||
|
}
|
||||||
"Pulling out a single row of results:"
|
"Pulling out a single row of results:"
|
||||||
{ $subsection row-column }
|
{ $subsections
|
||||||
{ $subsection row-column-typed } ;
|
row-column
|
||||||
|
row-column-typed
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "db-protocol" "Low-level database protocol"
|
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
|
"The high-level protocol (see " { $vocab-link "db.tuples" } ") uses this low-level protocol for executing statements and queries." $nl
|
||||||
"Opening a database:"
|
"Opening a database:"
|
||||||
{ $subsection db-open }
|
{ $subsections db-open }
|
||||||
"Closing a database:"
|
"Closing a database:"
|
||||||
{ $subsection db-close }
|
{ $subsections db-close }
|
||||||
"Creating statements:"
|
"Creating statements:"
|
||||||
{ $subsection <simple-statement> }
|
{ $subsections
|
||||||
{ $subsection <prepared-statement> }
|
<simple-statement>
|
||||||
|
<prepared-statement>
|
||||||
|
}
|
||||||
"Using statements with the database:"
|
"Using statements with the database:"
|
||||||
{ $subsection prepare-statement }
|
{ $subsections
|
||||||
{ $subsection bind-statement* }
|
prepare-statement
|
||||||
{ $subsection low-level-bind }
|
bind-statement*
|
||||||
|
low-level-bind
|
||||||
|
}
|
||||||
"Performing a query:"
|
"Performing a query:"
|
||||||
{ $subsection query-results }
|
{ $subsections query-results }
|
||||||
"Handling query results:"
|
"Handling query results:"
|
||||||
{ $subsection "db-result-sets" }
|
{ $subsections "db-result-sets" }
|
||||||
;
|
;
|
||||||
! { $subsection bind-tuple }
|
! { $subsection bind-tuple }
|
||||||
|
|
||||||
ARTICLE: "db-lowlevel-tutorial" "Low-level database tutorial"
|
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
|
"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:"
|
"Executing a SQL command:"
|
||||||
{ $subsection sql-command }
|
{ $subsections sql-command }
|
||||||
"Executing a query directly:"
|
"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
|
"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."
|
"First, let's set up a custom combinator for using our database. See " { $link "db-custom-database-combinators" } " for more details."
|
||||||
{ $code """
|
{ $code """
|
||||||
|
|
|
@ -154,52 +154,58 @@ HELP: count-tuples
|
||||||
|
|
||||||
ARTICLE: "db-tuples" "High-level tuple/database integration"
|
ARTICLE: "db-tuples" "High-level tuple/database integration"
|
||||||
"Start with a tutorial:"
|
"Start with a tutorial:"
|
||||||
{ $subsection "db-tuples-tutorial" }
|
{ $subsections "db-tuples-tutorial" }
|
||||||
"Database types supported:"
|
"Database types supported:"
|
||||||
{ $subsection "db.types" }
|
{ $subsections "db.types" }
|
||||||
"Useful words:"
|
"Useful words:"
|
||||||
{ $subsection "db-tuples-words" }
|
{ $subsections "db-tuples-words" }
|
||||||
"For porting db.tuples to other databases:"
|
"For porting db.tuples to other databases:"
|
||||||
{ $subsection "db-tuples-protocol" }
|
{ $subsections "db-tuples-protocol" }
|
||||||
;
|
;
|
||||||
|
|
||||||
ARTICLE: "db-tuples-words" "High-level tuple/database words"
|
ARTICLE: "db-tuples-words" "High-level tuple/database words"
|
||||||
"Making tuples work with a database:"
|
"Making tuples work with a database:"
|
||||||
{ $subsection define-persistent }
|
{ $subsections define-persistent }
|
||||||
"Creating tables:"
|
"Creating tables:"
|
||||||
{ $subsection create-table }
|
{ $subsections
|
||||||
{ $subsection ensure-table }
|
create-table
|
||||||
{ $subsection ensure-tables }
|
ensure-table
|
||||||
{ $subsection recreate-table }
|
ensure-tables
|
||||||
|
recreate-table
|
||||||
|
}
|
||||||
"Dropping tables:"
|
"Dropping tables:"
|
||||||
{ $subsection drop-table }
|
{ $subsections drop-table }
|
||||||
"Inserting a tuple:"
|
"Inserting a tuple:"
|
||||||
{ $subsection insert-tuple }
|
{ $subsections insert-tuple }
|
||||||
"Updating a tuple:"
|
"Updating a tuple:"
|
||||||
{ $subsection update-tuple }
|
{ $subsections update-tuple }
|
||||||
"Deleting tuples:"
|
"Deleting tuples:"
|
||||||
{ $subsection delete-tuples }
|
{ $subsections delete-tuples }
|
||||||
"Querying tuples:"
|
"Querying tuples:"
|
||||||
{ $subsection select-tuple }
|
{ $subsections
|
||||||
{ $subsection select-tuples }
|
select-tuple
|
||||||
{ $subsection count-tuples } ;
|
select-tuples
|
||||||
|
count-tuples
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "db-tuples-protocol" "Tuple database protocol"
|
ARTICLE: "db-tuples-protocol" "Tuple database protocol"
|
||||||
"Creating a table:"
|
"Creating a table:"
|
||||||
{ $subsection create-sql-statement }
|
{ $subsections create-sql-statement }
|
||||||
"Dropping a table:"
|
"Dropping a table:"
|
||||||
{ $subsection drop-sql-statement }
|
{ $subsections drop-sql-statement }
|
||||||
"Inserting a tuple:"
|
"Inserting a tuple:"
|
||||||
{ $subsection <insert-db-assigned-statement> }
|
{ $subsections
|
||||||
{ $subsection <insert-user-assigned-statement> }
|
<insert-db-assigned-statement>
|
||||||
|
<insert-user-assigned-statement>
|
||||||
|
}
|
||||||
"Updating a tuple:"
|
"Updating a tuple:"
|
||||||
{ $subsection <update-tuple-statement> }
|
{ $subsections <update-tuple-statement> }
|
||||||
"Deleting tuples:"
|
"Deleting tuples:"
|
||||||
{ $subsection <delete-tuples-statement> }
|
{ $subsections <delete-tuples-statement> }
|
||||||
"Selecting tuples:"
|
"Selecting tuples:"
|
||||||
{ $subsection <select-by-slots-statement> }
|
{ $subsections <select-by-slots-statement> }
|
||||||
"Counting tuples:"
|
"Counting tuples:"
|
||||||
{ $subsection <count-statement> } ;
|
{ $subsections <count-statement> } ;
|
||||||
|
|
||||||
ARTICLE: "db-tuples-tutorial" "Tuple database tutorial"
|
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
|
"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"
|
ARTICLE: "db.types" "Database types"
|
||||||
"The " { $vocab-link "db.types" } " vocabulary maps Factor types to database types." $nl
|
"The " { $vocab-link "db.types" } " vocabulary maps Factor types to database types." $nl
|
||||||
"Primary keys:"
|
"Primary keys:"
|
||||||
{ $subsection +db-assigned-id+ }
|
{ $subsections
|
||||||
{ $subsection +user-assigned-id+ }
|
+db-assigned-id+
|
||||||
{ $subsection +random-id+ }
|
+user-assigned-id+
|
||||||
|
+random-id+
|
||||||
|
}
|
||||||
"Null and boolean types:"
|
"Null and boolean types:"
|
||||||
{ $subsection NULL }
|
{ $subsections
|
||||||
{ $subsection BOOLEAN }
|
NULL
|
||||||
|
BOOLEAN
|
||||||
|
}
|
||||||
"Text types:"
|
"Text types:"
|
||||||
{ $subsection VARCHAR }
|
{ $subsections
|
||||||
{ $subsection TEXT }
|
VARCHAR
|
||||||
|
TEXT
|
||||||
|
}
|
||||||
"Number types:"
|
"Number types:"
|
||||||
{ $subsection INTEGER }
|
{ $subsections
|
||||||
{ $subsection BIG-INTEGER }
|
INTEGER
|
||||||
{ $subsection SIGNED-BIG-INTEGER }
|
BIG-INTEGER
|
||||||
{ $subsection UNSIGNED-BIG-INTEGER }
|
SIGNED-BIG-INTEGER
|
||||||
{ $subsection DOUBLE }
|
UNSIGNED-BIG-INTEGER
|
||||||
{ $subsection REAL }
|
DOUBLE
|
||||||
|
REAL
|
||||||
|
}
|
||||||
"Calendar types:"
|
"Calendar types:"
|
||||||
{ $subsection DATE }
|
{ $subsections
|
||||||
{ $subsection DATETIME }
|
DATE
|
||||||
{ $subsection TIME }
|
DATETIME
|
||||||
{ $subsection TIMESTAMP }
|
TIME
|
||||||
|
TIMESTAMP
|
||||||
|
}
|
||||||
"Factor byte-arrays:"
|
"Factor byte-arrays:"
|
||||||
{ $subsection BLOB }
|
{ $subsections BLOB }
|
||||||
"Arbitrary Factor objects:"
|
"Arbitrary Factor objects:"
|
||||||
{ $subsection FACTOR-BLOB }
|
{ $subsections FACTOR-BLOB }
|
||||||
"Factor URLs:"
|
"Factor URLs:"
|
||||||
{ $subsection URL } ;
|
{ $subsections URL } ;
|
||||||
|
|
||||||
ABOUT: "db.types"
|
ABOUT: "db.types"
|
||||||
|
|
|
@ -6,23 +6,29 @@ IN: debugger
|
||||||
|
|
||||||
ARTICLE: "debugger" "The debugger"
|
ARTICLE: "debugger" "The debugger"
|
||||||
"Caught errors can be logged in human-readable form:"
|
"Caught errors can be logged in human-readable form:"
|
||||||
{ $subsection print-error }
|
{ $subsections
|
||||||
{ $subsection try }
|
print-error
|
||||||
|
try
|
||||||
|
}
|
||||||
"User-defined errors can have customized printed representation by implementing a generic word:"
|
"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:"
|
"A number of words facilitate interactive debugging of errors:"
|
||||||
{ $subsection :error }
|
{ $subsections
|
||||||
{ $subsection :s }
|
:error
|
||||||
{ $subsection :r }
|
:s
|
||||||
{ $subsection :c }
|
:r
|
||||||
{ $subsection :get }
|
:c
|
||||||
|
:get
|
||||||
|
}
|
||||||
"Most types of errors are documented, and the documentation is instantly accessible:"
|
"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:"
|
"If the error was restartable, a list of restarts is also printed, and a numbered restart can be invoked:"
|
||||||
{ $subsection :1 }
|
{ $subsections
|
||||||
{ $subsection :2 }
|
:1
|
||||||
{ $subsection :3 }
|
:2
|
||||||
{ $subsection :res }
|
:3
|
||||||
|
:res
|
||||||
|
}
|
||||||
"You can read more about error handling in " { $link "errors" } "."
|
"You can read more about error handling in " { $link "errors" } "."
|
||||||
$nl
|
$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" } "." ;
|
"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."
|
"The " { $vocab-link "definitions.icons" } " vocabulary associates common definition types with icons."
|
||||||
{ $definition-icons }
|
{ $definition-icons }
|
||||||
"Looking up the icon associated with a definition:"
|
"Looking up the icon associated with a definition:"
|
||||||
{ $subsection definition-icon }
|
{ $subsections definition-icon }
|
||||||
"Defining new icons:"
|
"Defining new icons:"
|
||||||
{ $subsection POSTPONE: ICON: } ;
|
{ $subsections POSTPONE: ICON: } ;
|
||||||
|
|
||||||
ABOUT: "definitions.icons"
|
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."
|
"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
|
$nl
|
||||||
"Defining new protocols:"
|
"Defining new protocols:"
|
||||||
{ $subsection POSTPONE: PROTOCOL: }
|
{ $subsections
|
||||||
{ $subsection define-protocol }
|
POSTPONE: PROTOCOL:
|
||||||
|
define-protocol
|
||||||
|
}
|
||||||
"Defining new protocols consisting of slot accessors:"
|
"Defining new protocols consisting of slot accessors:"
|
||||||
{ $subsection POSTPONE: SLOT-PROTOCOL: }
|
{ $subsections POSTPONE: SLOT-PROTOCOL: }
|
||||||
"Defining consultation:"
|
"Defining consultation:"
|
||||||
{ $subsection POSTPONE: CONSULT: }
|
{ $subsections
|
||||||
{ $subsection define-consult }
|
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" } ;
|
"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"
|
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."
|
"The " { $vocab-link "deques" } " vocabulary implements the deque data structure which has constant-time insertion and removal of elements at both ends."
|
||||||
$nl
|
$nl
|
||||||
"Deques must be instances of a mixin class:"
|
"Deques must be instances of a mixin class:"
|
||||||
{ $subsection deque }
|
{ $subsections deque }
|
||||||
"Deques must implement a protocol."
|
"Deques must implement a protocol."
|
||||||
$nl
|
$nl
|
||||||
"Querying the deque:"
|
"Querying the deque:"
|
||||||
{ $subsection peek-front }
|
{ $subsections
|
||||||
{ $subsection peek-back }
|
peek-front
|
||||||
{ $subsection deque-empty? }
|
peek-back
|
||||||
{ $subsection deque-member? }
|
deque-empty?
|
||||||
|
deque-member?
|
||||||
|
}
|
||||||
"Adding and removing elements:"
|
"Adding and removing elements:"
|
||||||
{ $subsection push-front* }
|
{ $subsections
|
||||||
{ $subsection push-back* }
|
push-front*
|
||||||
{ $subsection pop-front* }
|
push-back*
|
||||||
{ $subsection pop-back* }
|
pop-front*
|
||||||
{ $subsection clear-deque }
|
pop-back*
|
||||||
|
clear-deque
|
||||||
|
}
|
||||||
"Working with node objects output by " { $link push-front* } " and " { $link push-back* } ":"
|
"Working with node objects output by " { $link push-front* } " and " { $link push-back* } ":"
|
||||||
{ $subsection delete-node }
|
{ $subsections
|
||||||
{ $subsection node-value }
|
delete-node
|
||||||
|
node-value
|
||||||
|
}
|
||||||
"Utility operations built in terms of the above:"
|
"Utility operations built in terms of the above:"
|
||||||
{ $subsection push-front }
|
{ $subsections
|
||||||
{ $subsection push-all-front }
|
push-front
|
||||||
{ $subsection push-back }
|
push-all-front
|
||||||
{ $subsection push-all-back }
|
push-back
|
||||||
{ $subsection pop-front }
|
push-all-back
|
||||||
{ $subsection pop-back }
|
pop-front
|
||||||
{ $subsection slurp-deque }
|
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 } "." ;
|
"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"
|
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."
|
"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
|
$nl
|
||||||
"The class of disjoint sets:"
|
"The class of disjoint sets:"
|
||||||
{ $subsection disjoint-set }
|
{ $subsections disjoint-set }
|
||||||
"Creating new disjoint sets:"
|
"Creating new disjoint sets:"
|
||||||
{ $subsection <disjoint-set> }
|
{ $subsections
|
||||||
{ $subsection assoc>disjoint-set }
|
<disjoint-set>
|
||||||
|
assoc>disjoint-set
|
||||||
|
}
|
||||||
"Queries:"
|
"Queries:"
|
||||||
{ $subsection equiv? }
|
{ $subsections
|
||||||
{ $subsection equiv-set-size }
|
equiv?
|
||||||
|
equiv-set-size
|
||||||
|
}
|
||||||
"Adding elements:"
|
"Adding elements:"
|
||||||
{ $subsection add-atom }
|
{ $subsections add-atom }
|
||||||
"Equating elements:"
|
"Equating elements:"
|
||||||
{ $subsection equate }
|
{ $subsections equate }
|
||||||
"Additionally, disjoint sets implement the " { $link clone } " generic word." ;
|
"Additionally, disjoint sets implement the " { $link clone } " generic word." ;
|
||||||
|
|
||||||
ABOUT: "disjoint-sets"
|
ABOUT: "disjoint-sets"
|
||||||
|
|
|
@ -6,22 +6,28 @@ ARTICLE: "dlists" "Double-linked lists"
|
||||||
"A double-linked list is the canonical implementation of a " { $link deque } "."
|
"A double-linked list is the canonical implementation of a " { $link deque } "."
|
||||||
$nl
|
$nl
|
||||||
"Double-linked lists form a class:"
|
"Double-linked lists form a class:"
|
||||||
{ $subsection dlist }
|
{ $subsections
|
||||||
{ $subsection dlist? }
|
dlist
|
||||||
|
dlist?
|
||||||
|
}
|
||||||
"Constructing a double-linked list:"
|
"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."
|
"Double-linked lists support all the operations of the deque protocol (" { $link "deques" } ") as well as the following."
|
||||||
$nl
|
$nl
|
||||||
"Iterating over elements:"
|
"Iterating over elements:"
|
||||||
{ $subsection dlist-each }
|
{ $subsections
|
||||||
{ $subsection dlist-find }
|
dlist-each
|
||||||
{ $subsection dlist-filter }
|
dlist-find
|
||||||
{ $subsection dlist-any? }
|
dlist-filter
|
||||||
|
dlist-any?
|
||||||
|
}
|
||||||
"Deleting a node matching a predicate:"
|
"Deleting a node matching a predicate:"
|
||||||
{ $subsection delete-node-if* }
|
{ $subsections
|
||||||
{ $subsection delete-node-if }
|
delete-node-if*
|
||||||
|
delete-node-if
|
||||||
|
}
|
||||||
"Search deque implementation:"
|
"Search deque implementation:"
|
||||||
{ $subsection <hashed-dlist> } ;
|
{ $subsections <hashed-dlist> } ;
|
||||||
|
|
||||||
ABOUT: "dlists"
|
ABOUT: "dlists"
|
||||||
|
|
||||||
|
|
|
@ -93,32 +93,45 @@ HELP: clear-doc
|
||||||
|
|
||||||
ARTICLE: "documents" "Documents"
|
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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <document> }
|
document
|
||||||
|
<document>
|
||||||
|
}
|
||||||
"Getting and setting the contents of the entire document:"
|
"Getting and setting the contents of the entire document:"
|
||||||
{ $subsection doc-string }
|
{ $subsections
|
||||||
{ $subsection set-doc-string }
|
doc-string
|
||||||
{ $subsection clear-doc }
|
set-doc-string
|
||||||
|
clear-doc
|
||||||
|
}
|
||||||
"Getting and setting subranges:"
|
"Getting and setting subranges:"
|
||||||
{ $subsection doc-line }
|
{ $subsections
|
||||||
{ $subsection doc-lines }
|
doc-line
|
||||||
{ $subsection doc-range }
|
doc-lines
|
||||||
{ $subsection set-doc-range }
|
doc-range
|
||||||
{ $subsection remove-doc-range }
|
set-doc-range
|
||||||
|
remove-doc-range
|
||||||
|
}
|
||||||
"A combinator:"
|
"A combinator:"
|
||||||
{ $subsection each-line }
|
{ $subsections each-line }
|
||||||
{ $subsection "document-locs" }
|
"More info:"
|
||||||
{ $subsection "documents.elements" }
|
{ $subsections
|
||||||
|
"document-locs"
|
||||||
|
"documents.elements"
|
||||||
|
}
|
||||||
{ $see-also "ui.gadgets.editors" } ;
|
{ $see-also "ui.gadgets.editors" } ;
|
||||||
|
|
||||||
ARTICLE: "document-locs" "Document locations"
|
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:"
|
"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 }
|
{ $subsections
|
||||||
{ $subsection +line }
|
+col
|
||||||
{ $subsection =col }
|
+line
|
||||||
{ $subsection =line }
|
=col
|
||||||
|
=line
|
||||||
|
}
|
||||||
"Miscellaneous words for working with locations:"
|
"Miscellaneous words for working with locations:"
|
||||||
{ $subsection lines-equal? }
|
{ $subsections
|
||||||
{ $subsection validate-loc } ;
|
lines-equal?
|
||||||
|
validate-loc
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "documents"
|
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."
|
"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
|
$nl
|
||||||
"The different types of document elements correspond to the standard editing taxonomy:"
|
"The different types of document elements correspond to the standard editing taxonomy:"
|
||||||
{ $subsection char-elt }
|
{ $subsections
|
||||||
{ $subsection one-word-elt }
|
char-elt
|
||||||
{ $subsection word-elt }
|
one-word-elt
|
||||||
{ $subsection one-line-elt }
|
word-elt
|
||||||
{ $subsection line-elt }
|
one-line-elt
|
||||||
{ $subsection doc-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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection next-elt } ;
|
prev-elt
|
||||||
|
next-elt
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "documents.elements"
|
ABOUT: "documents.elements"
|
|
@ -4,15 +4,15 @@ IN: editors
|
||||||
|
|
||||||
ARTICLE: "editor" "Editor integration"
|
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."
|
"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" } ":"
|
"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" }
|
{ $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" } "."
|
"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
|
$nl
|
||||||
"Editor integration vocabularies store a quotation in a global variable when loaded:"
|
"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:"
|
"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"
|
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
|
"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
|
"Windows CE has no concept of environment variables, so these words are undefined on that platform." $nl
|
||||||
"Reading environment variables:"
|
"Reading environment variables:"
|
||||||
{ $subsection os-env }
|
{ $subsections
|
||||||
{ $subsection os-envs }
|
os-env
|
||||||
|
os-envs
|
||||||
|
}
|
||||||
"Writing environment variables:"
|
"Writing environment variables:"
|
||||||
{ $subsection set-os-env }
|
{ $subsections
|
||||||
{ $subsection unset-os-env }
|
set-os-env
|
||||||
{ $subsection set-os-envs } ;
|
unset-os-env
|
||||||
|
set-os-envs
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "environment"
|
ABOUT: "environment"
|
||||||
|
|
|
@ -17,7 +17,9 @@ HELP: eval>string
|
||||||
|
|
||||||
ARTICLE: "eval" "Evaluating strings at runtime"
|
ARTICLE: "eval" "Evaluating strings at runtime"
|
||||||
"The " { $vocab-link "eval" } " vocabulary implements support for evaluating strings at runtime."
|
"The " { $vocab-link "eval" } " vocabulary implements support for evaluating strings at runtime."
|
||||||
{ $subsection POSTPONE: eval( }
|
{ $subsections
|
||||||
{ $subsection eval>string } ;
|
POSTPONE: eval(
|
||||||
|
eval>string
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "eval"
|
ABOUT: "eval"
|
||||||
|
|
|
@ -19,34 +19,40 @@ HELP: (write-farkup)
|
||||||
|
|
||||||
ARTICLE: "farkup-ast" "Farkup syntax tree nodes"
|
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 } "."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection heading2 }
|
heading1
|
||||||
{ $subsection heading3 }
|
heading2
|
||||||
{ $subsection heading4 }
|
heading3
|
||||||
{ $subsection strong }
|
heading4
|
||||||
{ $subsection emphasis }
|
strong
|
||||||
{ $subsection superscript }
|
emphasis
|
||||||
{ $subsection subscript }
|
superscript
|
||||||
{ $subsection inline-code }
|
subscript
|
||||||
{ $subsection paragraph }
|
inline-code
|
||||||
{ $subsection list-item }
|
paragraph
|
||||||
{ $subsection unordered-list }
|
list-item
|
||||||
{ $subsection ordered-list }
|
unordered-list
|
||||||
{ $subsection table }
|
ordered-list
|
||||||
{ $subsection table-row }
|
table
|
||||||
{ $subsection link }
|
table-row
|
||||||
{ $subsection image }
|
link
|
||||||
{ $subsection code } ;
|
image
|
||||||
|
code
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "farkup" "Farkup"
|
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" } "."
|
"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
|
$nl
|
||||||
"The main entry points for converting Farkup to HTML:"
|
"The main entry points for converting Farkup to HTML:"
|
||||||
{ $subsection convert-farkup }
|
{ $subsections
|
||||||
{ $subsection write-farkup }
|
convert-farkup
|
||||||
|
write-farkup
|
||||||
|
}
|
||||||
"The syntax tree of a piece of Farkup can also be inspected and modified:"
|
"The syntax tree of a piece of Farkup can also be inspected and modified:"
|
||||||
{ $subsection parse-farkup }
|
{ $subsections
|
||||||
{ $subsection (write-farkup) }
|
parse-farkup
|
||||||
{ $subsection "farkup-ast" } ;
|
(write-farkup)
|
||||||
|
"farkup-ast"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "farkup"
|
ABOUT: "farkup"
|
||||||
|
|
|
@ -26,16 +26,22 @@ HELP: font-with-foreground
|
||||||
|
|
||||||
ARTICLE: "fonts" "Fonts"
|
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."
|
"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 }
|
{ $subsections
|
||||||
{ $subsection <font> }
|
font
|
||||||
|
<font>
|
||||||
|
}
|
||||||
"Modifying fonts:"
|
"Modifying fonts:"
|
||||||
{ $subsection font-with-foreground }
|
{ $subsections
|
||||||
{ $subsection font-with-background }
|
font-with-foreground
|
||||||
|
font-with-background
|
||||||
|
}
|
||||||
"Useful constants:"
|
"Useful constants:"
|
||||||
{ $subsection monospace-font }
|
{ $subsections
|
||||||
{ $subsection sans-serif-font }
|
monospace-font
|
||||||
{ $subsection serif-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:"
|
"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"
|
ABOUT: "fonts"
|
||||||
|
|
|
@ -129,10 +129,11 @@ HELP: strftime
|
||||||
|
|
||||||
ARTICLE: "formatting" "Formatted printing"
|
ARTICLE: "formatting" "Formatted printing"
|
||||||
"The " { $vocab-link "formatting" } " vocabulary is used for formatted printing."
|
"The " { $vocab-link "formatting" } " vocabulary is used for formatted printing."
|
||||||
{ $subsection printf }
|
{ $subsections
|
||||||
{ $subsection sprintf }
|
printf
|
||||||
{ $subsection strftime }
|
sprintf
|
||||||
;
|
strftime
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "formatting"
|
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."
|
"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
|
$nl
|
||||||
"Fried quotations are started by a special parsing word:"
|
"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:"
|
"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 _ }
|
{ $subsections
|
||||||
{ $subsection @ }
|
_
|
||||||
|
@
|
||||||
|
}
|
||||||
"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."
|
"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" }
|
{ $subsections
|
||||||
{ $subsection "fry.philosophy" }
|
"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)."
|
"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
|
$nl
|
||||||
"Fried quotations can also be constructed without using a parsing word; this is useful when meta-programming:"
|
"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." ;
|
"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"
|
ABOUT: "fry"
|
||||||
|
|
|
@ -81,12 +81,14 @@ ARTICLE: "furnace.actions.page.example" "Furnace page action example"
|
||||||
|
|
||||||
ARTICLE: "furnace.actions.page" "Furnace page actions"
|
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."
|
"Page actions implement the common case of an action that simply serves a Chloe template in response to a GET request."
|
||||||
{ $subsection page-action }
|
{ $subsections
|
||||||
{ $subsection <page-action> }
|
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."
|
"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
|
$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."
|
"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"
|
ARTICLE: "furnace.actions.config" "Furnace action configuration"
|
||||||
"Actions have the following slots:"
|
"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."
|
"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
|
$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:"
|
"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 "
|
"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:"
|
"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." ;
|
"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"
|
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"
|
ARTICLE: "furnace.actions.impl" "Furnace actions implementation"
|
||||||
"The following parametrized constructor should be called from constructors for subclasses of " { $link action } ":"
|
"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"
|
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."
|
"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)."
|
"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
|
$nl
|
||||||
"The class of actions:"
|
"The class of actions:"
|
||||||
{ $subsection action }
|
{ $subsections action }
|
||||||
"Creating a new 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:"
|
"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:"
|
"Validating forms with actions:"
|
||||||
{ $subsection "furnace.actions.validation" }
|
{ $subsections "furnace.actions.validation" }
|
||||||
"More about the form validation lifecycle:"
|
"More about the form validation lifecycle:"
|
||||||
{ $subsection "furnace.actions.lifecycle" }
|
{ $subsections "furnace.actions.lifecycle" }
|
||||||
"A convenience class:"
|
"A convenience class:"
|
||||||
{ $subsection "furnace.actions.page" }
|
{ $subsections "furnace.actions.page" }
|
||||||
"Low-level features:"
|
"Low-level features:"
|
||||||
{ $subsection "furnace.actions.impl" } ;
|
{ $subsections "furnace.actions.impl" } ;
|
||||||
|
|
||||||
ABOUT: "furnace.actions"
|
ABOUT: "furnace.actions"
|
||||||
|
|
|
@ -33,10 +33,10 @@ ARTICLE: "furnace.alloy" "Furnace alloy responder"
|
||||||
{ $link "furnace.db" }
|
{ $link "furnace.db" }
|
||||||
}
|
}
|
||||||
"A word to wrap a responder in an alloy:"
|
"A word to wrap a responder in an alloy:"
|
||||||
{ $subsection <alloy> }
|
{ $subsections <alloy> }
|
||||||
"Initializing database tables for asides, conversations and sessions:"
|
"Initializing database tables for asides, conversations and sessions:"
|
||||||
{ $subsection init-furnace-tables }
|
{ $subsections init-furnace-tables }
|
||||||
"Start a timer to expire asides, conversations and sessions:"
|
"Start a timer to expire asides, conversations and sessions:"
|
||||||
{ $subsection start-expiring } ;
|
{ $subsections start-expiring } ;
|
||||||
|
|
||||||
ABOUT: "furnace.alloy"
|
ABOUT: "furnace.alloy"
|
||||||
|
|
|
@ -21,13 +21,13 @@ ARTICLE: "furnace.asides" "Furnace asides"
|
||||||
"The " { $vocab-link "furnace.asides" } " vocabulary provides support for sending a user to a page which can then return to the former location."
|
"The " { $vocab-link "furnace.asides" } " vocabulary provides support for sending a user to a page which can then return to the former location."
|
||||||
$nl
|
$nl
|
||||||
"To use asides, wrap your responder in an aside responder:"
|
"To use asides, wrap your responder in an aside responder:"
|
||||||
{ $subsection <asides> }
|
{ $subsections <asides> }
|
||||||
"The asides responder must be wrapped inside a session responder (" { $link <sessions> } "), which in turn must be wrapped inside a database persistence responder (" { $link <db-persistence> } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one."
|
"The asides responder must be wrapped inside a session responder (" { $link <sessions> } "), which in turn must be wrapped inside a database persistence responder (" { $link <db-persistence> } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one."
|
||||||
$nl
|
$nl
|
||||||
"Saving the current page in an aside which propagates through " { $link <redirect> } " responses:"
|
"Saving the current page in an aside which propagates through " { $link <redirect> } " responses:"
|
||||||
{ $subsection begin-aside }
|
{ $subsections begin-aside }
|
||||||
"Returning from an aside:"
|
"Returning from an aside:"
|
||||||
{ $subsection end-aside }
|
{ $subsections end-aside }
|
||||||
"Asides are used by " { $vocab-link "furnace.auth.login" } "; when the client requests a protected page, an aside begins and the client is redirected to a login page. Upon a successful login, the aside ends and the client returns to the protected page. If the client directly visits the login page and logs in, there is no current aside, so the client is sent to the default URL passed to " { $link end-aside } ", which in the case of login is the root URL." ;
|
"Asides are used by " { $vocab-link "furnace.auth.login" } "; when the client requests a protected page, an aside begins and the client is redirected to a login page. Upon a successful login, the aside ends and the client returns to the protected page. If the client directly visits the login page and logs in, there is no current aside, so the client is sent to the default URL passed to " { $link end-aside } ", which in the case of login is the root URL." ;
|
||||||
|
|
||||||
ABOUT: "furnace.asides"
|
ABOUT: "furnace.asides"
|
||||||
|
|
|
@ -86,15 +86,17 @@ ARTICLE: "furnace.auth.capabilities" "Authentication capabilities"
|
||||||
"Every user in the authentication framework has a set of associated capabilities."
|
"Every user in the authentication framework has a set of associated capabilities."
|
||||||
$nl
|
$nl
|
||||||
"Defining new capabilities:"
|
"Defining new capabilities:"
|
||||||
{ $subsection define-capability }
|
{ $subsections define-capability }
|
||||||
"Capabilities are stored in a global variable:"
|
"Capabilities are stored in a global variable:"
|
||||||
{ $subsection capabilities }
|
{ $subsections capabilities }
|
||||||
"Protected resources can be restricted to users possessing certain capabilities only by storing a sequence of capabilities in the " { $slot "capabilities" } " slot of a " { $link protected } " instance." ;
|
"Protected resources can be restricted to users possessing certain capabilities only by storing a sequence of capabilities in the " { $slot "capabilities" } " slot of a " { $link protected } " instance." ;
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.protected" "Protected resources"
|
ARTICLE: "furnace.auth.protected" "Protected resources"
|
||||||
"To restrict access to authenticated clients only, wrap a responder in a protected responder."
|
"To restrict access to authenticated clients only, wrap a responder in a protected responder."
|
||||||
{ $subsection protected }
|
{ $subsections
|
||||||
{ $subsection <protected> }
|
protected
|
||||||
|
<protected>
|
||||||
|
}
|
||||||
"Protected responders have the following two slots which may be set:"
|
"Protected responders have the following two slots which may be set:"
|
||||||
{ $table
|
{ $table
|
||||||
{ { $slot "description" } "A string identifying the protected resource for user interface purposes" }
|
{ { $slot "description" } "A string identifying the protected resource for user interface purposes" }
|
||||||
|
@ -114,36 +116,44 @@ ARTICLE: "furnace.auth.providers" "Authentication providers"
|
||||||
"The " { $vocab-link "furnace.auth" } " framework looks up users using an authentication provider. Different authentication providers can be swapped in to implement various authentication strategies."
|
"The " { $vocab-link "furnace.auth" } " framework looks up users using an authentication provider. Different authentication providers can be swapped in to implement various authentication strategies."
|
||||||
$nl
|
$nl
|
||||||
"Each authentication realm has a provider stored in the " { $slot "users" } " slot. The default provider is " { $link users-in-db } "."
|
"Each authentication realm has a provider stored in the " { $slot "users" } " slot. The default provider is " { $link users-in-db } "."
|
||||||
{ $subsection "furnace.auth.providers.protocol" }
|
{ $subsections
|
||||||
{ $subsection "furnace.auth.providers.null" }
|
"furnace.auth.providers.protocol"
|
||||||
{ $subsection "furnace.auth.providers.assoc" }
|
"furnace.auth.providers.null"
|
||||||
{ $subsection "furnace.auth.providers.db" } ;
|
"furnace.auth.providers.assoc"
|
||||||
|
"furnace.auth.providers.db"
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.features" "Optional authentication features"
|
ARTICLE: "furnace.auth.features" "Optional authentication features"
|
||||||
"Vocabularies having names prefixed by " { $code "furnace.auth.features" } " implement optional features which can be enabled by calling special words. These words define new actions on an authentication realm."
|
"Vocabularies having names prefixed by " { $code "furnace.auth.features" } " implement optional features which can be enabled by calling special words. These words define new actions on an authentication realm."
|
||||||
{ $subsection "furnace.auth.features.deactivate-user" }
|
{ $subsections
|
||||||
{ $subsection "furnace.auth.features.edit-profile" }
|
"furnace.auth.features.deactivate-user"
|
||||||
{ $subsection "furnace.auth.features.recover-password" }
|
"furnace.auth.features.edit-profile"
|
||||||
{ $subsection "furnace.auth.features.registration" } ;
|
"furnace.auth.features.recover-password"
|
||||||
|
"furnace.auth.features.registration"
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.realms" "Authentication realms"
|
ARTICLE: "furnace.auth.realms" "Authentication realms"
|
||||||
"The superclass of authentication realms:"
|
"The superclass of authentication realms:"
|
||||||
{ $subsection realm }
|
{ $subsections realm }
|
||||||
"There are two concrete implementations:"
|
"There are two concrete implementations:"
|
||||||
{ $subsection "furnace.auth.basic" }
|
{ $subsections
|
||||||
{ $subsection "furnace.auth.login" }
|
"furnace.auth.basic"
|
||||||
|
"furnace.auth.login"
|
||||||
|
}
|
||||||
"Authentication realms need to be configured after construction."
|
"Authentication realms need to be configured after construction."
|
||||||
{ $subsection "furnace.auth.realm-config" } ;
|
{ $subsections "furnace.auth.realm-config" } ;
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.users" "User profiles"
|
ARTICLE: "furnace.auth.users" "User profiles"
|
||||||
"A responder wrapped in an authentication realm may access the currently logged-in user,"
|
"A responder wrapped in an authentication realm may access the currently logged-in user,"
|
||||||
{ $subsection logged-in-user }
|
{ $subsections logged-in-user }
|
||||||
"as well as the logged-in username:"
|
"as well as the logged-in username:"
|
||||||
{ $subsection username }
|
{ $subsections username }
|
||||||
"Values can also be stored in user profile variables:"
|
"Values can also be stored in user profile variables:"
|
||||||
{ $subsection uget }
|
{ $subsections
|
||||||
{ $subsection uset }
|
uget
|
||||||
{ $subsection uchange }
|
uset
|
||||||
|
uchange
|
||||||
|
}
|
||||||
"User profile variables have the same restrictions on their values as session variables; see " { $link "furnace.sessions.serialize" } " for a discussion." ;
|
"User profile variables have the same restrictions on their values as session variables; see " { $link "furnace.sessions.serialize" } " for a discussion." ;
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.example" "Furnace authentication example"
|
ARTICLE: "furnace.auth.example" "Furnace authentication example"
|
||||||
|
@ -173,20 +183,20 @@ ARTICLE: "furnace.auth" "Furnace authentication"
|
||||||
"The " { $vocab-link "furnace.auth" } " vocabulary implements a pluggable authentication framework."
|
"The " { $vocab-link "furnace.auth" } " vocabulary implements a pluggable authentication framework."
|
||||||
$nl
|
$nl
|
||||||
"Usernames and passwords are verified using an " { $emphasis "authentication provider" } "."
|
"Usernames and passwords are verified using an " { $emphasis "authentication provider" } "."
|
||||||
{ $subsection "furnace.auth.providers" }
|
{ $subsections "furnace.auth.providers" }
|
||||||
"Users have capabilities assigned to them."
|
"Users have capabilities assigned to them."
|
||||||
{ $subsection "furnace.auth.capabilities" }
|
{ $subsections "furnace.auth.capabilities" }
|
||||||
"An " { $emphasis "authentication realm" } " is a responder which manages access to protected resources."
|
"An " { $emphasis "authentication realm" } " is a responder which manages access to protected resources."
|
||||||
{ $subsection "furnace.auth.realms" }
|
{ $subsections "furnace.auth.realms" }
|
||||||
"Actions contained inside an authentication realm can be protected by wrapping them with a responder."
|
"Actions contained inside an authentication realm can be protected by wrapping them with a responder."
|
||||||
{ $subsection "furnace.auth.protected" }
|
{ $subsections "furnace.auth.protected" }
|
||||||
"Actions contained inside an authentication realm can access the currently logged-in user profile."
|
"Actions contained inside an authentication realm can access the currently logged-in user profile."
|
||||||
{ $subsection "furnace.auth.users" }
|
{ $subsections "furnace.auth.users" }
|
||||||
"Authentication realms can be adorned with additional functionality."
|
"Authentication realms can be adorned with additional functionality."
|
||||||
{ $subsection "furnace.auth.features" }
|
{ $subsections "furnace.auth.features" }
|
||||||
"An administration tool."
|
"An administration tool."
|
||||||
{ $subsection "furnace.auth.user-admin" }
|
{ $subsections "furnace.auth.user-admin" }
|
||||||
"A concrete example."
|
"A concrete example."
|
||||||
{ $subsection "furnace.auth.example" } ;
|
{ $subsections "furnace.auth.example" } ;
|
||||||
|
|
||||||
ABOUT: "furnace.auth"
|
ABOUT: "furnace.auth"
|
||||||
|
|
|
@ -10,7 +10,9 @@ HELP: basic-auth-realm
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.basic" "Basic authentication"
|
ARTICLE: "furnace.auth.basic" "Basic authentication"
|
||||||
"The " { $vocab-link "furnace.auth.basic" } " vocabulary implements HTTP basic authentication."
|
"The " { $vocab-link "furnace.auth.basic" } " vocabulary implements HTTP basic authentication."
|
||||||
{ $subsection basic-auth-realm }
|
{ $subsections
|
||||||
{ $subsection <basic-auth-realm> } ;
|
basic-auth-realm
|
||||||
|
<basic-auth-realm>
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.auth.basic"
|
ABOUT: "furnace.auth.basic"
|
||||||
|
|
|
@ -13,9 +13,9 @@ ARTICLE: "furnace.auth.features.deactivate-user" "User profile deactivation"
|
||||||
"The " { $vocab-link "furnace.auth.features.deactivate-user" } " vocabulary implements an authentication feature for user profile deactivation, allowing users to voluntarily deactivate their account."
|
"The " { $vocab-link "furnace.auth.features.deactivate-user" } " vocabulary implements an authentication feature for user profile deactivation, allowing users to voluntarily deactivate their account."
|
||||||
$nl
|
$nl
|
||||||
"To enable this feature, call the following word on an authentication realm:"
|
"To enable this feature, call the following word on an authentication realm:"
|
||||||
{ $subsection allow-deactivation }
|
{ $subsections allow-deactivation }
|
||||||
"To check if deactivation is enabled:"
|
"To check if deactivation is enabled:"
|
||||||
{ $subsection allow-deactivation? }
|
{ $subsections allow-deactivation? }
|
||||||
"This feature adds a " { $snippet "deactivate-user" } " action to the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
"This feature adds a " { $snippet "deactivate-user" } " action to the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
||||||
{ $code
|
{ $code
|
||||||
"<t:if t:code=\"furnace.auth.features.deactivate-user:allow-deactivation?\">"
|
"<t:if t:code=\"furnace.auth.features.deactivate-user:allow-deactivation?\">"
|
||||||
|
|
|
@ -13,9 +13,9 @@ ARTICLE: "furnace.auth.features.edit-profile" "User profile editing"
|
||||||
"The " { $vocab-link "furnace.auth.features.edit-profile" } " vocabulary implements an authentication feature for user profile editing, allowing users to change some details of their account."
|
"The " { $vocab-link "furnace.auth.features.edit-profile" } " vocabulary implements an authentication feature for user profile editing, allowing users to change some details of their account."
|
||||||
$nl
|
$nl
|
||||||
"To enable this feature, call the following word on an authentication realm:"
|
"To enable this feature, call the following word on an authentication realm:"
|
||||||
{ $subsection allow-edit-profile }
|
{ $subsections allow-edit-profile }
|
||||||
"To check if profile editing is enabled:"
|
"To check if profile editing is enabled:"
|
||||||
{ $subsection allow-edit-profile? }
|
{ $subsections allow-edit-profile? }
|
||||||
"This feature adds an " { $snippet "edit-profile" } " action to the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
"This feature adds an " { $snippet "edit-profile" } " action to the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
||||||
{ $code
|
{ $code
|
||||||
"<t:if t:code=\"furnace.auth.features.edit-profile:allow-edit-profile?\">"
|
"<t:if t:code=\"furnace.auth.features.edit-profile:allow-edit-profile?\">"
|
||||||
|
|
|
@ -17,13 +17,13 @@ ARTICLE: "furnace.auth.features.recover-password" "User password recovery"
|
||||||
" vocabulary implements an authentication feature for user password recovery, allowing users to get a new password e-mailed to them in the event they forget their current one."
|
" vocabulary implements an authentication feature for user password recovery, allowing users to get a new password e-mailed to them in the event they forget their current one."
|
||||||
$nl
|
$nl
|
||||||
"To enable this feature, first call the following word on an authentication realm,"
|
"To enable this feature, first call the following word on an authentication realm,"
|
||||||
{ $subsection allow-password-recovery }
|
{ $subsections allow-password-recovery }
|
||||||
"Then set a global configuration variable:"
|
"Then set a global configuration variable:"
|
||||||
{ $subsection lost-password-from }
|
{ $subsections lost-password-from }
|
||||||
"In addition, the " { $link "smtp" } " may need to be configured as well."
|
"In addition, the " { $link "smtp" } " may need to be configured as well."
|
||||||
$nl
|
$nl
|
||||||
"To check if password recovery is enabled:"
|
"To check if password recovery is enabled:"
|
||||||
{ $subsection allow-password-recovery? }
|
{ $subsections allow-password-recovery? }
|
||||||
"This feature adds a " { $snippet "recover-password" } " action to the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
"This feature adds a " { $snippet "recover-password" } " action to the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
||||||
{ $code
|
{ $code
|
||||||
"<t:if t:code=\"furnace.auth.features.recover-password:allow-password-recovery?\">"
|
"<t:if t:code=\"furnace.auth.features.recover-password:allow-password-recovery?\">"
|
||||||
|
|
|
@ -13,9 +13,9 @@ ARTICLE: "furnace.auth.features.registration" "User registration"
|
||||||
"The " { $vocab-link "furnace.auth.features.registration" } " vocabulary implements an authentication feature for user registration, allowing new users to create accounts."
|
"The " { $vocab-link "furnace.auth.features.registration" } " vocabulary implements an authentication feature for user registration, allowing new users to create accounts."
|
||||||
$nl
|
$nl
|
||||||
"To enable this feature, call the following word on an authentication realm:"
|
"To enable this feature, call the following word on an authentication realm:"
|
||||||
{ $subsection allow-registration }
|
{ $subsections allow-registration }
|
||||||
"To check if user registration is enabled:"
|
"To check if user registration is enabled:"
|
||||||
{ $subsection allow-registration? }
|
{ $subsections allow-registration? }
|
||||||
"This feature adds a " { $snippet "register" } " action to the realm. A link to this action is inserted on the login page if the " { $vocab-link "furnace.auth.login" } " authentication realm is used. Links to this action can be inserted from other pages using the following Chloe XML snippet:"
|
"This feature adds a " { $snippet "register" } " action to the realm. A link to this action is inserted on the login page if the " { $vocab-link "furnace.auth.login" } " authentication realm is used. Links to this action can be inserted from other pages using the following Chloe XML snippet:"
|
||||||
{ $code
|
{ $code
|
||||||
"<t:if t:code=\"furnace.auth.features.registration:allow-registration?\">"
|
"<t:if t:code=\"furnace.auth.features.registration:allow-registration?\">"
|
||||||
|
|
|
@ -13,8 +13,10 @@ HELP: login-realm
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.login" "Login authentication"
|
ARTICLE: "furnace.auth.login" "Login authentication"
|
||||||
"The " { $vocab-link "furnace.auth.login" } " vocabulary implements an authentication realm which displays a login page with a username and password field."
|
"The " { $vocab-link "furnace.auth.login" } " vocabulary implements an authentication realm which displays a login page with a username and password field."
|
||||||
{ $subsection login-realm }
|
{ $subsections
|
||||||
{ $subsection <login-realm> }
|
login-realm
|
||||||
|
<login-realm>
|
||||||
|
}
|
||||||
"The " { $snippet "logout" } " action logs the user out of the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
"The " { $snippet "logout" } " action logs the user out of the realm, and a link to this action can be inserted in Chloe templates using the following XML snippet:"
|
||||||
{ $code
|
{ $code
|
||||||
"<t:button t:action=\"$login-realm/logout\">Logout</t:button>"
|
"<t:button t:action=\"$login-realm/logout\">Logout</t:button>"
|
||||||
|
|
|
@ -7,8 +7,10 @@ HELP: <users-in-memory>
|
||||||
|
|
||||||
ARTICLE: "furnace.auth.providers.assoc" "In-memory authentication provider"
|
ARTICLE: "furnace.auth.providers.assoc" "In-memory authentication provider"
|
||||||
"The " { $vocab-link "furnace.auth.providers.assoc" } " vocabulary implements an authentication provider which looks up usernames and passwords in an associative mapping."
|
"The " { $vocab-link "furnace.auth.providers.assoc" } " vocabulary implements an authentication provider which looks up usernames and passwords in an associative mapping."
|
||||||
{ $subsection users-in-memory }
|
{ $subsections
|
||||||
{ $subsection <users-in-memory> }
|
users-in-memory
|
||||||
|
<users-in-memory>
|
||||||
|
}
|
||||||
"The " { $slot "assoc" } " slot of the " { $link users-in-memory } " tuple maps usernames to checksums of passwords." ;
|
"The " { $slot "assoc" } " slot of the " { $link users-in-memory } " tuple maps usernames to checksums of passwords." ;
|
||||||
|
|
||||||
ABOUT: "furnace.auth.providers.assoc"
|
ABOUT: "furnace.auth.providers.assoc"
|
||||||
|
|
|
@ -8,6 +8,6 @@ ARTICLE: "furnace.auth.providers.db" "Database authentication provider"
|
||||||
"The " { $vocab-link "furnace.auth.providers.db" } " vocabulary implements an authentication provider which looks up authentication requests in the " { $snippet "USERS" } " table of the current database. The database schema is Factor-specific, and the table should be initialized by calling"
|
"The " { $vocab-link "furnace.auth.providers.db" } " vocabulary implements an authentication provider which looks up authentication requests in the " { $snippet "USERS" } " table of the current database. The database schema is Factor-specific, and the table should be initialized by calling"
|
||||||
{ $code "users create-table" }
|
{ $code "users create-table" }
|
||||||
"The authentication provider class:"
|
"The authentication provider class:"
|
||||||
{ $subsection users-in-db } ;
|
{ $subsections users-in-db } ;
|
||||||
|
|
||||||
ABOUT: "furnace.auth.providers.db"
|
ABOUT: "furnace.auth.providers.db"
|
||||||
|
|
|
@ -36,10 +36,12 @@ ARTICLE: "furnace.auth.providers.protocol" "Authentication provider protocol"
|
||||||
"The " { $vocab-link "furnace.auth.providers" } " vocabulary implements a protocol for persistence and authentication of users."
|
"The " { $vocab-link "furnace.auth.providers" } " vocabulary implements a protocol for persistence and authentication of users."
|
||||||
$nl
|
$nl
|
||||||
"The class of users:"
|
"The class of users:"
|
||||||
{ $subsection user }
|
{ $subsections user }
|
||||||
"Generic protocol:"
|
"Generic protocol:"
|
||||||
{ $subsection get-user }
|
{ $subsections
|
||||||
{ $subsection new-user }
|
get-user
|
||||||
{ $subsection update-user } ;
|
new-user
|
||||||
|
update-user
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.auth.providers.protocol"
|
ABOUT: "furnace.auth.providers.protocol"
|
||||||
|
|
|
@ -27,9 +27,11 @@ ARTICLE: "furnace.boilerplate.example" "Boilerplate example"
|
||||||
|
|
||||||
ARTICLE: "furnace.boilerplate" "Furnace boilerplate support"
|
ARTICLE: "furnace.boilerplate" "Furnace boilerplate support"
|
||||||
"The " { $vocab-link "furnace.boilerplate" } " vocabulary implements a facility for sharing a common header and footer between different pages on a web site. It builds on top of " { $link "html.templates.boilerplate" } "."
|
"The " { $vocab-link "furnace.boilerplate" } " vocabulary implements a facility for sharing a common header and footer between different pages on a web site. It builds on top of " { $link "html.templates.boilerplate" } "."
|
||||||
{ $subsection <boilerplate> }
|
{ $subsections
|
||||||
{ $subsection "furnace.boilerplate.config" }
|
<boilerplate>
|
||||||
{ $subsection "furnace.boilerplate.example" }
|
"furnace.boilerplate.config"
|
||||||
|
"furnace.boilerplate.example"
|
||||||
|
}
|
||||||
{ $see-also "html.templates.chloe.tags.boilerplate" } ;
|
{ $see-also "html.templates.chloe.tags.boilerplate" } ;
|
||||||
|
|
||||||
ABOUT: "furnace.boilerplate"
|
ABOUT: "furnace.boilerplate"
|
||||||
|
|
|
@ -37,17 +37,21 @@ $nl
|
||||||
"Conversation scope is used by form validation to pass validation errors between requests."
|
"Conversation scope is used by form validation to pass validation errors between requests."
|
||||||
$nl
|
$nl
|
||||||
"To use conversation scope, wrap your responder in an conversation responder:"
|
"To use conversation scope, wrap your responder in an conversation responder:"
|
||||||
{ $subsection <conversations> }
|
{ $subsections <conversations> }
|
||||||
"The conversations responder must be wrapped inside a session responder (" { $link <sessions> } "), which in turn must be wrapped inside a database persistence responder (" { $link <db-persistence> } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one."
|
"The conversations responder must be wrapped inside a session responder (" { $link <sessions> } "), which in turn must be wrapped inside a database persistence responder (" { $link <db-persistence> } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one."
|
||||||
$nl
|
$nl
|
||||||
"Managing conversation scopes:"
|
"Managing conversation scopes:"
|
||||||
{ $subsection begin-conversation }
|
{ $subsections
|
||||||
{ $subsection end-conversation }
|
begin-conversation
|
||||||
{ $subsection <continue-conversation> }
|
end-conversation
|
||||||
|
<continue-conversation>
|
||||||
|
}
|
||||||
"Reading and writing conversation variables:"
|
"Reading and writing conversation variables:"
|
||||||
{ $subsection cget }
|
{ $subsections
|
||||||
{ $subsection cset }
|
cget
|
||||||
{ $subsection cchange }
|
cset
|
||||||
|
cchange
|
||||||
|
}
|
||||||
"Note that conversation scope is serialized as part of the session, which means that only serializable objects can be stored there. See " { $link "furnace.sessions.serialize" } " for details." ;
|
"Note that conversation scope is serialized as part of the session, which means that only serializable objects can be stored there. See " { $link "furnace.sessions.serialize" } " for details." ;
|
||||||
|
|
||||||
ABOUT: "furnace.conversations"
|
ABOUT: "furnace.conversations"
|
||||||
|
|
|
@ -10,7 +10,7 @@ HELP: <db-persistence>
|
||||||
|
|
||||||
ARTICLE: "furnace.db" "Furnace database support"
|
ARTICLE: "furnace.db" "Furnace database support"
|
||||||
"The " { $vocab-link "furnace.db" } " vocabulary implements a responder which maintains a database connection pool and runs each request in a " { $link with-db } " scope."
|
"The " { $vocab-link "furnace.db" } " vocabulary implements a responder which maintains a database connection pool and runs each request in a " { $link with-db } " scope."
|
||||||
{ $subsection <db-persistence> }
|
{ $subsections <db-persistence> }
|
||||||
"The " { $vocab-link "furnace.alloy" } " vocabulary combines database persistence with several other features." ;
|
"The " { $vocab-link "furnace.alloy" } " vocabulary combines database persistence with several other features." ;
|
||||||
|
|
||||||
ABOUT: "furnace.db"
|
ABOUT: "furnace.db"
|
||||||
|
|
|
@ -3,25 +3,33 @@ quotations sequences strings urls xml.data http ;
|
||||||
IN: furnace
|
IN: furnace
|
||||||
|
|
||||||
ARTICLE: "furnace.persistence" "Furnace persistence layer"
|
ARTICLE: "furnace.persistence" "Furnace persistence layer"
|
||||||
{ $subsection "furnace.db" }
|
{ $subsections "furnace.db" }
|
||||||
"Server-side state:"
|
"Server-side state:"
|
||||||
{ $subsection "furnace.sessions" }
|
{ $subsections
|
||||||
{ $subsection "furnace.conversations" }
|
"furnace.sessions"
|
||||||
{ $subsection "furnace.asides" }
|
"furnace.conversations"
|
||||||
{ $subsection "furnace.presentation" } ;
|
"furnace.asides"
|
||||||
|
"furnace.presentation"
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.presentation" "Furnace presentation layer"
|
ARTICLE: "furnace.presentation" "Furnace presentation layer"
|
||||||
"HTML components:"
|
"HTML components:"
|
||||||
{ $subsection "html.components" }
|
{ $subsections
|
||||||
{ $subsection "html.forms" }
|
"html.components"
|
||||||
|
"html.forms"
|
||||||
|
}
|
||||||
"Content templates:"
|
"Content templates:"
|
||||||
{ $subsection "html.templates" }
|
{ $subsections
|
||||||
{ $subsection "html.templates.chloe" }
|
"html.templates"
|
||||||
{ $subsection "html.templates.fhtml" }
|
"html.templates.chloe"
|
||||||
{ $subsection "furnace.boilerplate" }
|
"html.templates.fhtml"
|
||||||
|
"furnace.boilerplate"
|
||||||
|
}
|
||||||
"Other types of content:"
|
"Other types of content:"
|
||||||
{ $subsection "furnace.syndication" }
|
{ $subsections
|
||||||
{ $subsection "furnace.json" } ;
|
"furnace.syndication"
|
||||||
|
"furnace.json"
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.load-balancing" "Load balancing and fail-over with Furnace"
|
ARTICLE: "furnace.load-balancing" "Load balancing and fail-over with Furnace"
|
||||||
"The Furnace session manager persists sessions to a database. This means that HTTP requests can be transparently distributed between multiple Factor HTTP server instances, running the same web app on top of the same database, as long as the web applications do not use mutable global state, such as global variables. The Furnace framework itself does not use any mutable global state." ;
|
"The Furnace session manager persists sessions to a database. This means that HTTP requests can be transparently distributed between multiple Factor HTTP server instances, running the same web app on top of the same database, as long as the web applications do not use mutable global state, such as global variables. The Furnace framework itself does not use any mutable global state." ;
|
||||||
|
@ -36,22 +44,28 @@ ARTICLE: "furnace" "Furnace framework"
|
||||||
"Conversation scope and asides for complex page flow"
|
"Conversation scope and asides for complex page flow"
|
||||||
}
|
}
|
||||||
"Major functionality:"
|
"Major functionality:"
|
||||||
{ $subsection "furnace.actions" }
|
{ $subsections
|
||||||
{ $subsection "furnace.alloy" }
|
"furnace.actions"
|
||||||
{ $subsection "furnace.persistence" }
|
"furnace.alloy"
|
||||||
{ $subsection "furnace.presentation" }
|
"furnace.persistence"
|
||||||
{ $subsection "furnace.auth" }
|
"furnace.presentation"
|
||||||
{ $subsection "furnace.load-balancing" }
|
"furnace.auth"
|
||||||
|
"furnace.load-balancing"
|
||||||
|
}
|
||||||
"Utilities:"
|
"Utilities:"
|
||||||
{ $subsection "furnace.referrer" }
|
{ $subsections
|
||||||
{ $subsection "furnace.redirection" }
|
"furnace.referrer"
|
||||||
{ $subsection "furnace.extension-points" }
|
"furnace.redirection"
|
||||||
{ $subsection "furnace.misc" }
|
"furnace.extension-points"
|
||||||
|
"furnace.misc"
|
||||||
|
}
|
||||||
"Related frameworks:"
|
"Related frameworks:"
|
||||||
{ $subsection "db" }
|
{ $subsections
|
||||||
{ $subsection "xml" }
|
"db"
|
||||||
{ $subsection "http.server" }
|
"xml"
|
||||||
{ $subsection "logging" }
|
"http.server"
|
||||||
{ $subsection "urls" } ;
|
"logging"
|
||||||
|
"urls"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace"
|
ABOUT: "furnace"
|
||||||
|
|
|
@ -7,6 +7,6 @@ HELP: <json-content>
|
||||||
|
|
||||||
ARTICLE: "furnace.json" "Furnace JSON support"
|
ARTICLE: "furnace.json" "Furnace JSON support"
|
||||||
"The " { $vocab-link "furnace.json" } " vocabulary provides a utility word for serving HTTP responses with JSON content."
|
"The " { $vocab-link "furnace.json" } " vocabulary provides a utility word for serving HTTP responses with JSON content."
|
||||||
{ $subsection <json-content> } ;
|
{ $subsections <json-content> } ;
|
||||||
|
|
||||||
ABOUT: "furnace.json"
|
ABOUT: "furnace.json"
|
||||||
|
|
|
@ -44,12 +44,14 @@ ARTICLE: "furnace.recaptcha" "Recaptcha"
|
||||||
"The recaptcha responder is a " { $link filter-responder } " that wraps another responder. Set the " { $slot "domain" } ", " { $slot "public-key" } ", and " { $slot "private-key" } " slots of this responder to your Recaptcha account information." $nl
|
"The recaptcha responder is a " { $link filter-responder } " that wraps another responder. Set the " { $slot "domain" } ", " { $slot "public-key" } ", and " { $slot "private-key" } " slots of this responder to your Recaptcha account information." $nl
|
||||||
|
|
||||||
"Wrapping a responder with Recaptcha:"
|
"Wrapping a responder with Recaptcha:"
|
||||||
{ $subsection <recaptcha> }
|
{ $subsections <recaptcha> }
|
||||||
"Validating recaptcha:"
|
"Validating recaptcha:"
|
||||||
{ $subsection validate-recaptcha }
|
{ $subsections validate-recaptcha }
|
||||||
"Symbols set after validation:"
|
"Symbols set after validation:"
|
||||||
{ $subsection recaptcha-valid? }
|
{ $subsections
|
||||||
{ $subsection recaptcha-error }
|
recaptcha-valid?
|
||||||
{ $subsection "recaptcha-example" } ;
|
recaptcha-error
|
||||||
|
"recaptcha-example"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.recaptcha"
|
ABOUT: "furnace.recaptcha"
|
||||||
|
|
|
@ -40,20 +40,24 @@ ARTICLE: "furnace.redirection.secure" "Secure redirection"
|
||||||
"The words in this section help with implementing sites which require SSL/TLS for additional security."
|
"The words in this section help with implementing sites which require SSL/TLS for additional security."
|
||||||
$nl
|
$nl
|
||||||
"Converting a HTTP URL into an HTTPS URL:"
|
"Converting a HTTP URL into an HTTPS URL:"
|
||||||
{ $subsection >secure-url }
|
{ $subsections >secure-url }
|
||||||
"Redirecting the client to an HTTPS URL:"
|
"Redirecting the client to an HTTPS URL:"
|
||||||
{ $subsection <secure-redirect> }
|
{ $subsections <secure-redirect> }
|
||||||
"Tools for writing responders which require SSL/TLS connections:"
|
"Tools for writing responders which require SSL/TLS connections:"
|
||||||
{ $subsection if-secure }
|
{ $subsections
|
||||||
{ $subsection <secure-only> } ;
|
if-secure
|
||||||
|
<secure-only>
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.redirection" "Furnace redirection support"
|
ARTICLE: "furnace.redirection" "Furnace redirection support"
|
||||||
"The " { $vocab-link "furnace.redirection" } " vocabulary builds additional functionality on top of " { $vocab-link "http.server.redirection" } ", and integrates with various Furnace features such as " { $link "furnace.asides" } " and " { $link "furnace.conversations" } "."
|
"The " { $vocab-link "furnace.redirection" } " vocabulary builds additional functionality on top of " { $vocab-link "http.server.redirection" } ", and integrates with various Furnace features such as " { $link "furnace.asides" } " and " { $link "furnace.conversations" } "."
|
||||||
$nl
|
$nl
|
||||||
"A redirection response which takes asides and conversations into account:"
|
"A redirection response which takes asides and conversations into account:"
|
||||||
{ $subsection <redirect> }
|
{ $subsections <redirect> }
|
||||||
"A responder which unconditionally redirects the client to another URL:"
|
"A responder which unconditionally redirects the client to another URL:"
|
||||||
{ $subsection <redirect-responder> }
|
{ $subsections
|
||||||
{ $subsection "furnace.redirection.secure" } ;
|
<redirect-responder>
|
||||||
|
"furnace.redirection.secure"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.redirection"
|
ABOUT: "furnace.redirection"
|
||||||
|
|
|
@ -11,9 +11,11 @@ HELP: <check-form-submissions>
|
||||||
|
|
||||||
ARTICLE: "furnace.referrer" "Form submission referrer checking"
|
ARTICLE: "furnace.referrer" "Form submission referrer checking"
|
||||||
"The " { $vocab-link "furnace.referrer" } " implements a simple security measure which can be used to thwart cross-site scripting attacks."
|
"The " { $vocab-link "furnace.referrer" } " implements a simple security measure which can be used to thwart cross-site scripting attacks."
|
||||||
{ $subsection <check-form-submissions> }
|
{ $subsections <check-form-submissions> }
|
||||||
"Explicit referrer checking:"
|
"Explicit referrer checking:"
|
||||||
{ $subsection referrer }
|
{ $subsections
|
||||||
{ $subsection same-host? } ;
|
referrer
|
||||||
|
same-host?
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.referrer"
|
ABOUT: "furnace.referrer"
|
||||||
|
|
|
@ -43,15 +43,19 @@ ARTICLE: "furnace.sessions" "Furnace sessions"
|
||||||
"The " { $vocab-link "furnace.sessions" } " vocabulary implements session management, which allows state to be maintained between HTTP requests. The session state is stored on the server; the client receives an opaque ID which is saved in a cookie (for GET requests) or a hidden form field (for POST requests)."
|
"The " { $vocab-link "furnace.sessions" } " vocabulary implements session management, which allows state to be maintained between HTTP requests. The session state is stored on the server; the client receives an opaque ID which is saved in a cookie (for GET requests) or a hidden form field (for POST requests)."
|
||||||
$nl
|
$nl
|
||||||
"To use session management, wrap your responder in an session manager:"
|
"To use session management, wrap your responder in an session manager:"
|
||||||
{ $subsection <sessions> }
|
{ $subsections <sessions> }
|
||||||
"The sessions responder must be wrapped inside a database persistence responder (" { $link <db-persistence> } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one."
|
"The sessions responder must be wrapped inside a database persistence responder (" { $link <db-persistence> } "). The " { $vocab-link "furnace.alloy" } " vocabulary combines all of these responders into one."
|
||||||
$nl
|
$nl
|
||||||
"Reading and writing session variables from a request:"
|
"Reading and writing session variables from a request:"
|
||||||
{ $subsection sget }
|
{ $subsections
|
||||||
{ $subsection sset }
|
sget
|
||||||
{ $subsection schange }
|
sset
|
||||||
|
schange
|
||||||
|
}
|
||||||
"Additional topics:"
|
"Additional topics:"
|
||||||
{ $subsection "furnace.sessions.config" }
|
{ $subsections
|
||||||
{ $subsection "furnace.sessions.serialize" } ;
|
"furnace.sessions.config"
|
||||||
|
"furnace.sessions.serialize"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.sessions"
|
ABOUT: "furnace.sessions"
|
||||||
|
|
|
@ -57,17 +57,21 @@ ARTICLE: "furnace.syndication.config" "Configuring Atom feed actions"
|
||||||
|
|
||||||
ARTICLE: "furnace.syndication.protocol" "Atom feed entry protocol"
|
ARTICLE: "furnace.syndication.protocol" "Atom feed entry protocol"
|
||||||
"An Atom feed action takes a sequence of objects and converts them into Atom feed entries. The objects must implement a protocol consisting of either a single generic word:"
|
"An Atom feed action takes a sequence of objects and converts them into Atom feed entries. The objects must implement a protocol consisting of either a single generic word:"
|
||||||
{ $subsection >entry }
|
{ $subsections >entry }
|
||||||
"Or a series of generic words, called by the default implementation of " { $link >entry } ":"
|
"Or a series of generic words, called by the default implementation of " { $link >entry } ":"
|
||||||
{ $subsection feed-entry-title }
|
{ $subsections
|
||||||
{ $subsection feed-entry-description }
|
feed-entry-title
|
||||||
{ $subsection feed-entry-date }
|
feed-entry-description
|
||||||
{ $subsection feed-entry-url } ;
|
feed-entry-date
|
||||||
|
feed-entry-url
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.syndication" "Furnace Atom syndication support"
|
ARTICLE: "furnace.syndication" "Furnace Atom syndication support"
|
||||||
"The " { $vocab-link "furnace.syndication" } " vocabulary builds on the " { $link "syndication" } " library by providing easy support for generating Atom feeds from " { $link "furnace.actions" } "."
|
"The " { $vocab-link "furnace.syndication" } " vocabulary builds on the " { $link "syndication" } " library by providing easy support for generating Atom feeds from " { $link "furnace.actions" } "."
|
||||||
{ $subsection <feed-action> }
|
{ $subsections
|
||||||
{ $subsection "furnace.syndication.config" }
|
<feed-action>
|
||||||
{ $subsection "furnace.syndication.protocol" } ;
|
"furnace.syndication.config"
|
||||||
|
"furnace.syndication.protocol"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "furnace.syndication"
|
ABOUT: "furnace.syndication"
|
||||||
|
|
|
@ -96,26 +96,38 @@ ARTICLE: "furnace.extension-points" "Furnace extension points"
|
||||||
"Furnace features such as session management, conversation scope and asides need to modify URLs in links and redirects, and insert hidden form fields, to implement state on top of the stateless HTTP protocol. In order to decouple the server-side state management code from the HTML templating code, a series of hooks are used."
|
"Furnace features such as session management, conversation scope and asides need to modify URLs in links and redirects, and insert hidden form fields, to implement state on top of the stateless HTTP protocol. In order to decouple the server-side state management code from the HTML templating code, a series of hooks are used."
|
||||||
$nl
|
$nl
|
||||||
"Responders can implement methods on the following generic words:"
|
"Responders can implement methods on the following generic words:"
|
||||||
{ $subsection modify-query }
|
{ $subsections
|
||||||
{ $subsection modify-redirect-query }
|
modify-query
|
||||||
{ $subsection link-attr }
|
modify-redirect-query
|
||||||
{ $subsection modify-form }
|
link-attr
|
||||||
|
modify-form
|
||||||
|
}
|
||||||
"Presentation-level code can call the following words:"
|
"Presentation-level code can call the following words:"
|
||||||
{ $subsection adjust-url }
|
{ $subsections
|
||||||
{ $subsection adjust-redirect-url } ;
|
adjust-url
|
||||||
|
adjust-redirect-url
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "furnace.misc" "Miscellaneous Furnace features"
|
ARTICLE: "furnace.misc" "Miscellaneous Furnace features"
|
||||||
"Inspecting the chain of responders handling the current request:"
|
"Inspecting the chain of responders handling the current request:"
|
||||||
{ $subsection nested-responders }
|
{ $subsections
|
||||||
{ $subsection each-responder }
|
nested-responders
|
||||||
{ $subsection resolve-base-path }
|
each-responder
|
||||||
|
resolve-base-path
|
||||||
|
}
|
||||||
"Vocabulary root-relative resources:"
|
"Vocabulary root-relative resources:"
|
||||||
{ $subsection vocab-path }
|
{ $subsections
|
||||||
{ $subsection resolve-template-path }
|
vocab-path
|
||||||
|
resolve-template-path
|
||||||
|
}
|
||||||
"Early return from a responder:"
|
"Early return from a responder:"
|
||||||
{ $subsection with-exit-continuation }
|
{ $subsections
|
||||||
{ $subsection exit-with }
|
with-exit-continuation
|
||||||
|
exit-with
|
||||||
|
}
|
||||||
"Other useful words:"
|
"Other useful words:"
|
||||||
{ $subsection hidden-form-field }
|
{ $subsections
|
||||||
{ $subsection client-state }
|
hidden-form-field
|
||||||
{ $subsection user-agent } ;
|
client-state
|
||||||
|
user-agent
|
||||||
|
} ;
|
||||||
|
|
|
@ -5,26 +5,34 @@ IN: game-input
|
||||||
ARTICLE: "game-input" "Game controller input"
|
ARTICLE: "game-input" "Game controller input"
|
||||||
"The " { $vocab-link "game-input" } " vocabulary provides cross-platform access to game controller devices such as joysticks and gamepads. It also provides an interface for polling raw keyboard and mouse input." $nl
|
"The " { $vocab-link "game-input" } " vocabulary provides cross-platform access to game controller devices such as joysticks and gamepads. It also provides an interface for polling raw keyboard and mouse input." $nl
|
||||||
"The game input interface must be initialized before being used:"
|
"The game input interface must be initialized before being used:"
|
||||||
{ $subsection open-game-input }
|
{ $subsections
|
||||||
{ $subsection close-game-input }
|
open-game-input
|
||||||
{ $subsection with-game-input }
|
close-game-input
|
||||||
|
with-game-input
|
||||||
|
}
|
||||||
"Once the game input interface is open, connected controller devices can be enumerated:"
|
"Once the game input interface is open, connected controller devices can be enumerated:"
|
||||||
{ $subsection get-controllers }
|
{ $subsections
|
||||||
{ $subsection find-controller-products }
|
get-controllers
|
||||||
{ $subsection find-controller-instance }
|
find-controller-products
|
||||||
|
find-controller-instance
|
||||||
|
}
|
||||||
"These " { $link controller } " objects can be queried of their identity:"
|
"These " { $link controller } " objects can be queried of their identity:"
|
||||||
{ $subsection product-string }
|
{ $subsections
|
||||||
{ $subsection product-id }
|
product-string
|
||||||
{ $subsection instance-id }
|
product-id
|
||||||
|
instance-id
|
||||||
|
}
|
||||||
"A hook is provided for invoking the system calibration tool:"
|
"A hook is provided for invoking the system calibration tool:"
|
||||||
{ $subsection calibrate-controller }
|
{ $subsections calibrate-controller }
|
||||||
"The current state of a controller, the keyboard, and the mouse can be read:"
|
"The current state of a controller, the keyboard, and the mouse can be read:"
|
||||||
{ $subsection read-controller }
|
{ $subsections
|
||||||
{ $subsection read-keyboard }
|
read-controller
|
||||||
{ $subsection read-mouse }
|
read-keyboard
|
||||||
{ $subsection controller-state }
|
read-mouse
|
||||||
{ $subsection keyboard-state }
|
controller-state
|
||||||
{ $subsection mouse-state } ;
|
keyboard-state
|
||||||
|
mouse-state
|
||||||
|
} ;
|
||||||
|
|
||||||
HELP: open-game-input
|
HELP: open-game-input
|
||||||
{ $description "Initializes the game input interface. An exception will be thrown if the initialization fails. Calls to open-game-input are reference counted; each call to open-game-input needs a corresponding call to close-game-input to close the game input interface." } ;
|
{ $description "Initializes the game input interface. An exception will be thrown if the initialization fails. Calls to open-game-input are reference counted; each call to open-game-input needs a corresponding call to close-game-input to close the game input interface." } ;
|
||||||
|
|
|
@ -304,42 +304,52 @@ HELP: ntuck
|
||||||
{ $description "A generalization of " { $link tuck } " that can work for any stack depth. The top item will be copied and placed " { $snippet "n" } " items down on the stack." } ;
|
{ $description "A generalization of " { $link tuck } " that can work for any stack depth. The top item will be copied and placed " { $snippet "n" } " items down on the stack." } ;
|
||||||
|
|
||||||
ARTICLE: "sequence-generalizations" "Generalized sequence operations"
|
ARTICLE: "sequence-generalizations" "Generalized sequence operations"
|
||||||
{ $subsection narray }
|
{ $subsections
|
||||||
{ $subsection nsequence }
|
narray
|
||||||
{ $subsection firstn }
|
nsequence
|
||||||
{ $subsection nappend }
|
firstn
|
||||||
{ $subsection nappend-as } ;
|
nappend
|
||||||
|
nappend-as
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "shuffle-generalizations" "Generalized shuffle words"
|
ARTICLE: "shuffle-generalizations" "Generalized shuffle words"
|
||||||
{ $subsection ndup }
|
{ $subsections
|
||||||
{ $subsection npick }
|
ndup
|
||||||
{ $subsection nrot }
|
npick
|
||||||
{ $subsection -nrot }
|
nrot
|
||||||
{ $subsection nnip }
|
-nrot
|
||||||
{ $subsection ndrop }
|
nnip
|
||||||
{ $subsection ntuck }
|
ndrop
|
||||||
{ $subsection mnswap }
|
ntuck
|
||||||
{ $subsection nweave } ;
|
mnswap
|
||||||
|
nweave
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "combinator-generalizations" "Generalized combinators"
|
ARTICLE: "combinator-generalizations" "Generalized combinators"
|
||||||
{ $subsection ndip }
|
{ $subsections
|
||||||
{ $subsection nkeep }
|
ndip
|
||||||
{ $subsection napply }
|
nkeep
|
||||||
{ $subsection ncleave }
|
napply
|
||||||
{ $subsection nspread } ;
|
ncleave
|
||||||
|
nspread
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "other-generalizations" "Additional generalizations"
|
ARTICLE: "other-generalizations" "Additional generalizations"
|
||||||
{ $subsection ncurry }
|
{ $subsections
|
||||||
{ $subsection nwith }
|
ncurry
|
||||||
{ $subsection nsum } ;
|
nwith
|
||||||
|
nsum
|
||||||
|
} ;
|
||||||
|
|
||||||
ARTICLE: "generalizations" "Generalized shuffle words and combinators"
|
ARTICLE: "generalizations" "Generalized shuffle words and combinators"
|
||||||
"The " { $vocab-link "generalizations" } " vocabulary defines a number of stack shuffling words and combinators for use in "
|
"The " { $vocab-link "generalizations" } " vocabulary defines a number of stack shuffling words and combinators for use in "
|
||||||
"macros where the arity of the input quotations depends on an "
|
"macros where the arity of the input quotations depends on an "
|
||||||
"input parameter."
|
"input parameter."
|
||||||
{ $subsection "sequence-generalizations" }
|
{ $subsections
|
||||||
{ $subsection "shuffle-generalizations" }
|
"sequence-generalizations"
|
||||||
{ $subsection "combinator-generalizations" }
|
"shuffle-generalizations"
|
||||||
{ $subsection "other-generalizations" } ;
|
"combinator-generalizations"
|
||||||
|
"other-generalizations"
|
||||||
|
} ;
|
||||||
|
|
||||||
ABOUT: "generalizations"
|
ABOUT: "generalizations"
|
||||||
|
|
|
@ -3,10 +3,12 @@ IN: hash2
|
||||||
|
|
||||||
ARTICLE: { "hash2" "intro" } "Hash2"
|
ARTICLE: { "hash2" "intro" } "Hash2"
|
||||||
"The hash2 vocabulary specifies a simple minimal datastructure for hash tables with two integers as keys. These hash tables are fixed size and do not conform to the associative mapping protocol. Words used in creating and manipulating these hash tables include:"
|
"The hash2 vocabulary specifies a simple minimal datastructure for hash tables with two integers as keys. These hash tables are fixed size and do not conform to the associative mapping protocol. Words used in creating and manipulating these hash tables include:"
|
||||||
{ $subsection <hash2> }
|
{ $subsections
|
||||||
{ $subsection hash2 }
|
<hash2>
|
||||||
{ $subsection set-hash2 }
|
hash2
|
||||||
{ $subsection alist>hash2 } ;
|
set-hash2
|
||||||
|
alist>hash2
|
||||||
|
} ;
|
||||||
|
|
||||||
HELP: <hash2>
|
HELP: <hash2>
|
||||||
{ $values { "size" "size of the underlying array" } { "hash2" hash2 } }
|
{ $values { "size" "size of the underlying array" } { "hash2" hash2 } }
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue