Download as pdf or txt
Download as pdf or txt
You are on page 1of 603

USING: arrays help.markup help.syntax strings sbufs vectors kernel quotations generic generic.

standard classes math assocs sequences sequences.private combinators.private effects ords ! IN: combinators "#$I%&': (cleave)combinators( (%leave combinators( ($he cleave combinators apply multiple quotations to a single value or set of values.( *nl ($ o quotations:( + *subsections bi ,bi -bi . ($hree quotations:( + *subsections tri ,tri -tri . ("n array of quotations:( + *subsections cleave ,cleave -cleave /cleave . (%leave combinators provide a more readable alternative to repeated applications of the ( + *link keep . ( combinators. $he follo ing example using ( + *link keep . (:( + *code (0 1 2 3 keep( (0 1 ) 3 keep( (, 4( . (can be more clearly ritten using ( + *link tri . (:( + *code (0 1 2 3( (0 1 ) 3( (0 , 4 3 tri( . ! "#$I%&': (spread)combinators( (Spread combinators( ($he spread combinators apply multiple quotations to multiple values. $he asterisk 5( + *snippet (4( . (6 suffixed to these ords7 names signifies that they are spread combinators.( *nl ($ o quotations:( + *subsections bi4 ,bi4 . ($hree quotations:( + *subsections tri4 ,tri4 . ("n array of quotations:( + *subsections spread . (Spread combinators provide a more readable alternative to repeated applications of the ( + *link dip . ( combinators. $he follo ing example using ( + *link dip . (:( + *code (0 0 1 2 3 dip 1 ) 3 dip , 4( . (can be more clearly ritten using ( + *link tri4 . (:(

+ *code (0 1 2 3 0 1 ) 3 0 , 4 3 tri4( . (" generali8ation of the above combinators to any number of quotations can be found in ( + *link (combinators( . (.( ! "#$I%&': (apply)combinators( ("pply combinators( ($he apply combinators apply a single quotation to multiple values. $he at sign 5( + *snippet (9( . (6 suffixed to these ords7 names signifies that they are apply combinators.( + *subsections bi9 ,bi9 tri9 ,tri9 . (" pair of condition ords built from ( + *link bi9 . ( to test t o values:( + *subsections both: either: . ("ll of the apply combinators are equivalent to using the corresponding ( + *link (spread)combinators( . ( ith the same quotation supplied for every value.( ! "#$I%&': (dip)keep)combinators( (;reserving combinators( (Sometimes it is necessary to temporarily hide values on the datastack. $he ( + *snippet (dip( . ( combinators invoke the quotation at the top of the stack< hiding some number of values:( + *subsections dip ,dip -dip /dip . ($he ( + *snippet (keep( . ( combinators invoke a quotation and restore some number of values to the top of the stack:( + *subsections keep ,keep -keep . ! "#$I%&': (curried)dataflo ( (%urried dataflo (%urried cleave combinators:( + *subsections bi)curry tri)curry . (%urried spread combinators:( + *subsections bi)curry4 tri)curry4 . (%urried apply combinators:( + *subsections bi)curry9 tri)curry9 . + *see)also (dataflo )combinators( . ! combinators(

"#$I%&': (compositional)examples( ('xamples of compositional combinator usage( (%onsider printing the same message ten times:( + *code (: print)1= 5 )) 6 1= 0 >(?ello< orld.>( print 3 times !( . (if e anted to abstract out the message into a parameter< e could keep it on the stack bet een iterations:( + *code (: print)1= 5 message )) 6 1= 0 dup print 3 times drop !( . (?o ever< keeping loop)invariant values on the stack doesn7t al ays ork out nicely. @or example< a ord to subtract a value from each element of a sequence:( + *code (: subtract)n 5 seq n )) seq7 6 s ap 0 over ) 3 map nip !( . ($hree shuffle ords are required to pass the value around. Instead< the loop)invariant value can be partially applied to a quotation using ( + *link curry . (< yielding a ne quotation that is passed to ( + *link map . (:( + *example (: subtract)n 5 seq n )) seq7 6 0 ) 3 curry map !( (+ 1= ,= -= . A subtract)n .( (+ A 1A ,A .( . (No consider the ord that is dual to the one above! instead of subtracting ( + *snippet (n( . ( from each stack element< it subtracts each element from ( + *snippet (n( . (.( *nl (Bne ay to rite this is ith a pair of ( + *link s ap . (s:( + *code (: n)subtract 5 n seq )) seq7 6 s ap 0 s ap ) 3 curry map !( . (Since this pattern comes up often< ( + *link ith . ( encapsulates it:( + *example (: n)subtract 5 n seq )) seq7 6 0 ) 3 ith map !(

. + *see)also (fry.examples( . !

(-= + 1= ,= -= . n)subtract .( (+ ,= 1= = .(

"#$I%&': (compositional)combinators( (%ompositional combinators( (%ertain combinators transform quotations to produce a ne quotation.( + *subsections (compositional)examples( . (@undamental operations:( + *subsections curry compose . (Cerived operations:( + *subsections ,curry -curry ith prepose . ($hese operations run in constant time< and in many cases are optimi8ed out altogether by the ( + *link (compiler( . (. ( + *link (fry( . ( are an abstraction built on top of these operations< and code that uses this abstraction is often clearer than direct calls to the belo ords.( *nl (%urried dataflo combinators can be used to build more complex dataflo by combining cleave< spread and apply patterns in various ays.( + *subsections (curried)dataflo ( . (Duotations also implement the sequence protocol< and can be manipulated ith sequence ords! see ( + *link (quotations( . (. ?o ever< such runtime quotation manipulation ill not be optimi8ed by the optimi8ing compiler.( ! "#$I%&': (booleans( (Eooleans( (In @actor< any obFect that is not ( + *link f . ( has a true value< and ( + *link f . ( has a false value. $he ( + *link t . ( obFect is the canonical true value.( + *subsections f t . (" union class of the above:( + *subsections boolean . ($here are some logical operations on booleans:( + *subsections Gboolean not and or xor . (Eoolean values are most frequently used for ( + *link (conditionals( . (.( + *heading ($he f obFect and f class( . ($he ( + *link f . ( obFect is the unique instance of the ( + *link f . ( class! the t o are distinct obFects. $he latter is also a parsing ord hich adds the ( + *link f . ( obFect to the parse tree at parse time. $o refer to the class itself you must use ( + *link ;BS$;BN': ;BS$;BN': . ( or ( + *link ;BS$;BN': > . ( to prevent the parsing ord from executing.( *nl (?ere is the ( + *link f . ( obFect:( + *example (f .( (f( . (?ere is the ( + *link f . ( class:( + *example (>> f .( (;BS$;BN': f( . ($hey are not equal:( + *example (f >> f H .( (f( . (?ere is an array containing the ( + *link f . ( obFect:( + *example (+ f . .( (+ f .( . (?ere is an array containing the ( + *link f . ( class:( + *example (+ ;BS$;BN': f . .( (+ ;BS$;BN': f .( . ($he ( + *link f . ( obFect is an instance of the ( + *link f . ( class:( + *example (US': classes( (f class)of .( (;BS$;BN': f( . ($he ( + *link f . ( class is an instance of ( + *link ord . (:( + *example (US': classes( (>> f class)of .( ( ord( . (Bn the other hand< ( + *link t . ( is Fust a ord< and there is no class hich

it is a unique instance of.( + *example (t >> t eq: .( (t( . (Iany ords hich search collections confuse the case of no element being present ith an element being found equal to ( + *link f . (. If this distinction is important< there is usually an alternative ord hich can be used! for example< compare ( + *link at . ( ith ( + *link at4 . (.( ! "#$I%&': (conditionals)boolean)equivalence( ('xpressing conditionals ith boolean logic( (%ertain simple conditional forms can be expressed in a simpler manner using boolean logic.( *nl ($he follo ing t o lines are equivalent:( + *code (0 drop f 3 unless( (s ap and( . ($he follo ing t o lines are equivalent:( + *code (0 3 0 3 :if( (s ap or( . ($he follo ing t o lines are equivalent< here ( + *snippet (&( . ( is a literal:( + *code (0 & 3 unless4( (& or( . ! "#$I%&': (conditionals( (%onditional combinators( ($he basic conditionals:( + *subsections if hen unless . (@orms abstracting a common stack shuffle pattern:( + *subsections if4 hen4 unless4 . ("nother form abstracting a common stack shuffle pattern:( + *subsections :if . (Sometimes instead of branching< you Fust need to pick one of t o values:( + *subsections : . ($ o combinators hich abstract out nested chains of ( + *link if . (:( + *subsections cond case . + *subsections (conditionals)boolean)equivalence( . + *see)also (booleans( (bit ise)arithmetic( both: either: . ! "#$I%&': (dataflo )combinators( (Cataflo combinators( (Cataflo combinators express common dataflo patterns such as performing a operation hile preserving its inputs< applying multiple operations to a single value< applying a set of operations to a set of values< or applying a single operation to multiple values.( + *subsections (dip)keep)combinators( (cleave)combinators( (spread)combinators( (apply)combinators( . (Iore intricate dataflo can be constructed by composing ( + *link (curried)dataflo ( . (.( ! "#$I%&': (combinators)quot( (Duotation construction utilities( (Some ords for creating quotations hich can be useful for implementing method combinations and compiler transforms:( + *subsections condGquot caseGquot alistGquot . ! "#$I%&': (call)unsafe( (Unsafe combinators( (Unsafe calls declare an effect statically ithout any runtime checking:( + *subsections call)effect)unsafe execute)effect)unsafe . ! "#$I%&': (call( (@undamental combinators( ($he most basic combinators are those that take either a quotation or ord< and invoke it immediately. $here are t o sets of these fundamental combinators. $hey differ in hether the compiler is expected to determine the stack effect of the expression at compile time or the stack effect is declared and verified at run

time.( *nl + *heading (%ompile)time checked combinators( . (Jith these combinators< the compiler attempts to determine the stack effect of the expression at compile time< reFecting the program if the effect cannot be determined. See ( + *link (inference)combinators( . (.( + *subsections call execute . + *heading (#un)time checked combinators( . (Jith these combinators< the stack effect of the expression is checked at run time.( + *subsections ;BS$;BN': call5 ;BS$;BN': execute5 . (Note that the opening parenthesis is actually part of the ord name for ( + *snippet (call5( . ( and ( + *snippet (execute5( . (! they are parsing ords< and they read a stack effect until the corresponding closing parenthesis. $he underlying ords are a bit more verbose< but they can be given non)constant stack effects:( + *subsections call)effect execute)effect . + *heading (Unchecked combinators( . + *subsections (call)unsafe( . + *see)also (effects( (inference( . ! "#$I%&': (combinators( (%ombinators( (" central concept in @actor is that of a ( + *emphasis (combinator( . (< hich is a ord taking code as input.( + *subsections (call( (dataflo )combinators( (conditionals( (looping)combinators( (compositional)combinators( (combinators.short)circuit( (combinators.smart( (combinators)quot( (generali8ations( . (Iore combinators are defined for orking on data structures< such as ( + *link (sequences)combinators( . ( and ( + *link (assocs)combinators( . (.( + *see)also (quotations( . ! "EBU$: (combinators( ?'&;: call)effect + *values + (quot( quotation . + (effect( effect . . + *description (Given a quotation and a stack effect< calls the quotation< asserting at runtime that it has the given stack effect. $his is a macro hich expands given a literal effect parameter< and an arbitrary quotation hich is not required at compile time.( . + *examples ($he follo ing t o lines are equivalent:( + *code (call5 a b )) c 6( (5 a b )) c 6 call)effect( . . ! ?'&;: execute)effect + *values + ( ord( ord . + (effect( effect . . + *description (Given a ord and a stack effect< executes the ord< asserting at runtime that it has the given stack effect. $his is a macro hich expands given a literal effect parameter< and an arbitrary ord hich is not required at compile time.( . + *examples

($he follo ing t o lines are equivalent:( + *code (execute5 a b )) c 6( (5 a b )) c 6 execute)effect( . . ! ?'&;: execute)effect)unsafe + *values + ( ord( ord . + (effect( effect . . + *description (Given a ord and a stack effect< executes the ord< blindly declaring at runtime that it has the given stack effect. $his is a macro hich expands given a literal effect parameter< and an arbitrary ord hich is not required at compile time.( . + * arning (If the ord being executed has an incorrect stack effect< undefined behavior ill result. User code should use ( + *link ;BS$;BN': execute5 . ( instead.( . ! + call)effect call)effect)unsafe execute)effect execute)effect)unsafe . related) ords ?'&;: cleave + *values + (x( obFect . + (seq( (a sequence of quotations ith stack effect ( + *snippet (5 x )) ... 6( . . . + *description ("pplies each quotation to the obFect in turn.( . + *examples ($he ( + *link bi . ( combinator takes one value and t o quotations! the ( + *link tri . ( combinator takes one value and three quotations. $he ( + *link cleave . ( combinator takes one value and any number of quotations< and is essentially equivalent to a chain of ( + *link keep . ( forms:( + *code (K 'quivalent( (+ 0 p 3 0 q 3 0 r 3 0 s 3 . cleave( (0 p 3 keep 0 q 3 keep 0 r 3 keep s( . . ! ?'&;: ,cleave + *values + (x( obFect . + (y( obFect . + (seq( (a sequence of quotations ith stack effect ( + *snippet (5 x y )) ... 6( . . . + *description ("pplies each quotation to the t o obFects in turn.( . ! ?'&;: -cleave + *values + (x( obFect . + (y( obFect . + (8( obFect . + (seq( (a sequence of quotations ith stack effect ( + *snippet (5 x y 8 )) ... 6( . . . + *description ("pplies each quotation to the three obFects in turn.( . ! + bi tri cleave . related) ords ?'&;: spread + *values + (obFs...( (obFects( . + (seq( (a sequence of quotations ith stack effect ( + *snippet (5 x )) ... 6( . . . + *description ("pplies each quotation to the obFect in turn.( . + *examples ($he ( + *link bi4 . ( combinator takes t o values and t o quotations! the ( + *link tri4 . ( combinator takes three values and three quotations. $he ( + *link spread . ( combinator takes ( + *snippet (n( . ( values and ( + *snippet (n( . ( quotations< here ( + *snippet (n( . ( is the length of the input sequence< and is essentially equivalent to a nested series of ( + *link dip . (s:( + *code

(K 'quivalent( (+ 0 p 3 0 q 3 0 r 3 0 s 3 . spread( (0 0 0 p 3 dip q 3 dip r 3 dip s( . ! .

+ bi4 tri4 spread . related) ords ?'&;: to)fixed)point + *values + (obFect( obFect . + (quot( + *quotation (5 ... obFect5n6 )) ... obFect5n216 6( . . + (obFect5n6( obFect . . + *description ("pplies the quotation repeatedly ith ( + *snippet (obFect( . ( as the initial input until the output of the quotation equals the input.( . + *examples + *example (USING: combinators kernel math prettyprint sequences !( (IN: scratchpad( (: flatten 5 sequence )) sequence7 6( ( >(flatten>( over index( ( 0 0 1 2 s ap nth 3 0 nip dup , 2 3 0 drop 3 ,tri replace)slice 3 hen4 !( (( (+ >(flatten>( + 1 + , - . >(flatten>( + / A . + L . . . 0 flatten 3 to)fixed)point .( (+ 1 + , - . / A + L . .( . . ! ?'&;: alistGquot + *values + (default( (a quotation( . + (assoc( (a sequence of quotation pairs( . + (quot( (a ne quotation( . . + *description (%onstructs a quotation hich calls the first quotation in each pair of ( + *snippet (assoc( . ( until one of them outputs a true value< and then calls the second quotation in the corresponding pair. Duotations are called in reverse order< and if no quotation outputs a true value then ( + *snippet (default( . ( is called.( . + *notes ($his ord is used to implement compile)time behavior for ( + *link cond . (< and it is also used by the generic ord system. Note that unlike ( + *link cond . (< the constructed quotation performs the tests starting from the end and not the beginning.( . ! ?'&;: cond + *values + (assoc( (a sequence of quotation pairs and an optional quotation( . . + *description (%alls the second quotation in the first pair hose first quotation yields a true value. " single quotation ill al ays yield a true value.( *nl ($he follo ing t o phrases are equivalent:( + *code (+ + 0 M 3 0 N 3 . + 0 O 3 0 $ 3 . . cond( . + *code (M 0 N 3 0 O 0 $ 3 0 no)cond 3 if 3 if( . . + *errors ($hro s a ( + *link no)cond . ( error if none of the test quotations yield a true value.( . + *examples + *example (USING: combinators io kernel math !( (= +( ( + 0 dup = G 3 0 drop >(positive>( 3 .( ( + 0 dup = P 3 0 drop >(negative>( 3 .( ( 0 drop >(8ero>( 3( (. cond print(

(8ero( . ! .

?'&;: no)cond + *description ($hro s a ( + *link no)cond . ( error.( . + *error)description ($hro n by ( + *link cond . ( if none of the test quotations yield a true value. Some uses of ( + *link cond . ( include a default case here the test quotation is ( + *snippet (0 t 3( . (! such a ( + *link cond . ( form ill never thro this error.( . ! ?'&;: case + *values + (obF( obFect . + (assoc( (a sequence of obFectQ ord< quotation pairs< ith an optional quotation at the end( . . + *description (%ompares ( + *snippet (obF( . ( against the first element of every pair< first evaluating the first element if it is a ord. If some pair matches< removes ( + *snippet (obF( . ( from the stack and calls the second element of that pair< hich must be a quotation.( *nl (If there is no case matching ( + *snippet (obF( . (< the default case is taken. If the last element of ( + *snippet (assoc( . ( is a quotation< the quotation is called ith ( + *snippet (obF( . ( on the stack. Bther ise< a ( + *link no)cond . ( error is raised.( *nl ($he follo ing t o phrases are equivalent:( + *code (+ + M 0 N 3 . + O 0 $ 3 . . case( . + *code (dup M H 0 drop N 3 0 dup O H 0 drop $ 3 0 no)case 3 if 3 if( . . + *examples + *example (USING: combinators io kernel !( (IN: scratchpad( (SNIEB&S: yes no maybe !( (maybe +( ( + yes 0 3 . K Co nothing( ( + no 0 >(No ayK>( thro 3 .( ( + maybe 0 >(Iake up your mindK>( print 3 .( ( 0 drop >(Invalid input! try again.>( print 3( (. case( (Iake up your mindK( . . ! ?'&;: no)case + *description ($hro s a ( + *link no)case . ( error.( . + *error)description ($hro n by ( + *link case . ( if the obFect at the top of the stack does not match any case< and no default case is given.( . ! ?'&;: recursive)hashcode + *values + (n( integer . + (obF( obFect . + (quot( + *quotation (5 n obF )) code 6( . . + (code( integer . . + *description (" combinator used to implement methods for the ( + *link hashcode4 . ( generic ord. If ( + *snippet (n( . ( is less than or equal to 8ero< outputs =< other ise calls the quotation.( . ! ?'&;: condGquot + *values + (assoc( (a sequence of pairs of quotations( . + (quot( quotation . . + *description (%reates a quotation that hen called< has the same effect as applying ( + *link cond . ( to ( + *snippet (assoc( . (.( *nl ($he generated quotation is more efficient than the naive implementation of (

+ *link cond . (< though< since it expands into a series of conditionals< and no iteration through ( + *snippet (assoc( . ( has to be performed.( . + *notes ($his ord is used behind the scenes to compile ( + *link cond . ( forms efficiently! it can also be called directly< hich is useful for meta)programming.( . ! ?'&;: caseGquot + *values + (default( quotation . + (assoc( (a sequence of pairs of quotations( . + (quot( quotation . . + *description (%reates a quotation that hen called< has the same effect as applying ( + *link case . ( to ( + *snippet (assoc( . (.( *nl ($his ord uses three strategies:( + *list (If the assoc only has a fe keys< a linear search is generated.( + (If the assoc has a large number of keys hich form a contiguous range of integers< a direct dispatch is generated using the ( + *link dispatch . ( ord together ith a bounds check.( . (Bther ise< an open)coded hashtable dispatch is generated.( . . ! ?'&;: distribute)buckets + *values + (alist( (an alist( . + (initial( obFect . + (quot( + *quotation (5 obF )) assoc 6( . . + (buckets( (a ne array( . . + *description (Sorts the entries of ( + *snippet (assoc( . ( into buckets< using the quotation to yield a set of keys for each entry. $he hashcode of each key is computed< and the entry is placed in all corresponding buckets. 'ach bucket is initially cloned from ( + *snippet (initial( . (! this should either be an empty vector or a one)element vector containing a pair.( . + *notes ($his ord is used in the implementation of ( + *link hash)case)quot . ( and ( + *link standard)combination . (.( . ! ?'&;: dispatch + *values + (n( (a fixnum( . + (array( (an array of quotations( . . + *description (%alls the ( + *snippet (n( . (th quotation in the array.( . + * arning ($his ord is in the ( + *vocab)link (kernel.private( . ( vocabulary because it is an implementation detail used by the generic ord system to accelerate method dispatch. It does not perform type or bounds checks< and user code should not need to call it directly.( . ! USING: alien strings kernel math tools.test io prettyprint namespaces combinators ords classes sequences accessors math.functions arrays combinators.private stack)checker ! IN: combinators.tests 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 > 3 , , , 2 3 , , 2 0 0 0 3 1 , 0 2 3 2 3 call5 2 3 call5 + 1 , - / call5 x y call5 x y )) 8 6 3 unit)test )) 8 6 3 must)fail x y )) 8 a 6 3 must)fail . 3 0 1 , - / 0 datastack nip 3 call5 x )) y 6 3 unit)test )) 8 6 3 must)infer

0 1 , > 2 execute5 x y )) 8 6 3 unit)test > 2 execute5 )) 8 6 3 must)fail > 2 execute5 x y )) 8 a 6 3 must)fail execute5 x y )) 8 6 3 must)infer

: compile)execute5)test)1 5 a b )) c 6 > 2 execute5 a b )) c 6 ! 0 t 3 0 > compile)execute5)test)1 optimi8ed: 3 unit)test 0 / 3 0 1 - compile)execute5)test)1 3 unit)test : compile)execute5)test), 5 a b )) c 6 execute5 a b )) c 6 !

0 0 0 0 0

t 3 0 > compile)execute5)test), optimi8ed: 3 unit)test / 3 0 1 - > 2 compile)execute5)test), 3 unit)test A 3 0 1 / > 2 compile)execute5)test), 3 unit)test )- 3 0 1 / > ) compile)execute5)test), 3 unit)test A 3 0 1 / > 2 compile)execute5)test), 3 unit)test

: compile)call5)test)1 5 a b q )) c 6 call5 a b )) c 6 ! 0 0 0 0 0 t / R R / 3 3 3 3 3 0 0 0 0 0 > 1 1 1 1 compile)call5)test)1 optimi8ed: 3 unit)test - 0 2 3 compile)call5)test)1 3 unit)test - , 0 4 2 3 curry compile)call5)test)1 3 unit)test - 0 , 4 3 0 2 3 compose compile)call5)test)1 3 unit)test - 0 + 2 . 0 3 like call 3 compile)call5)test)1 3 unit)test

0 0 3 call5 )) 4 6 3 must)fail : compile)call5)test), 5 )) 6 0 3 call5 )) 4 6 ! 0 compile)call5)test), 3 0 rong)values: 3 must)fail) ith

: compile)call5)test)- 5 quot )) 6 call5 )) 4 6 ! 0 0 3 compile)call5)test)- 3 0 rong)values: 3 must)fail) ith

: compile)execute5)test)- 5 a )) 6 > . execute5 value )) 4 6 ! 0 1= compile)execute5)test)- 3 0 : compile)execute5)test)/ 5 a rong)values: 3 must)fail) ith

ord )) 6 execute5 value )) 4 6 ! rong)values: 3 must)fail) ith

0 1= > . compile)execute5)test)/ 3 0

K %ond : cond)test)1 5 obF )) str 6 + + 0 dup , mod = H 3 0 drop (even( 3 . + 0 dup , mod 1 H 3 0 drop (odd( 3 . . cond ! > cond)test)1 defGG must)infer 0 0 0 0 (even( 3 0 , cond)test)1 3 unit)test (even( 3 0 , > cond)test)1 defGG call 3 unit)test (odd( 3 0 - cond)test)1 3 unit)test (odd( 3 0 - > cond)test)1 defGG call 3 unit)test

: cond)test), 5 obF )) str 6 + + 0 dup t H 3 0 drop (true( 3 . + 0 dup f H 3 0 drop (false( 3 . 0 drop (something else( 3 . cond ! > cond)test), defGG must)infer 0 0 0 0 0 0 (true( 3 0 t cond)test), 3 unit)test (true( 3 0 t > cond)test), defGG call 3 unit)test (false( 3 0 f cond)test), 3 unit)test (false( 3 0 f > cond)test), defGG call 3 unit)test (something else( 3 0 (ohio( cond)test), 3 unit)test (something else( 3 0 (ohio( > cond)test), defGG call 3 unit)test

: cond)test)- 5 obF )) str 6 + 0 drop (something else( 3 + 0 dup t H 3 0 drop (true( 3 . + 0 dup f H 3 0 drop (false( 3 . . cond ! > cond)test)- defGG must)infer 0 0 0 0 0 0 (something (something (something (something (something (something else( else( else( else( else( else( 3 3 3 3 3 3 0 0 0 0 0 0 t cond)test)- 3 unit)test t > cond)test)- defGG call 3 unit)test f cond)test)- 3 unit)test f > cond)test)- defGG call 3 unit)test (ohio( cond)test)- 3 unit)test (ohio( > cond)test)- defGG call 3 unit)test

: cond)test)/ 5 )) 6 + . cond ! > cond)test)/ defGG must)infer 0 cond)test)/ 3 0 no)cond: 3 must)fail) ith 0 > cond)test)/ defGG call 3 0 no)cond: 3 must)fail) ith : cond)test)A 5 a )) b 6 + + 0 dup , mod 1 H 3 0 drop (odd( 3 . 0 drop (early( 3 + 0 dup , mod = H 3 0 drop (even( 3 . . cond ! 0 (early( 3 0 , cond)test)A 3 unit)test 0 (early( 3 0 , > cond)test)A defGG call 3 unit)test : cond)test)L 5 a )) b 6 + 0 drop (really early( 3 + 0 dup , mod 1 H 3 0 drop (odd( 3 . + 0 dup , mod = H 3 0 drop (even( 3 . . cond ! 0 (really early( 3 0 , cond)test)L 3 unit)test 0 (really early( 3 0 , > cond)test)L defGG call 3 unit)test K %ase : case)test)1 + + 1 0 + , 0 + - 0 + / 0 . case ! 5 obF )) obF7 6 (one( 3 . (t o( 3 . (three( 3 . (four( 3 .

> case)test)1 defGG must)infer 0 (t o( 3 0 , case)test)1 3 unit)test 0 (t o( 3 0 , > case)test)1 defGG call 3 unit)test 0 (x( case)test)1 3 must)fail 0 (x( > case)test)1 defGG call 3 must)fail

: case)test), 5 obF )) obF7 6 + + 1 0 (one( 3 . + , 0 (t o( 3 . + - 0 (three( 3 . + / 0 (four( 3 . 0 sq 3 . case ! > case)test), defGG must)infer 0 ,A 3 0 A case)test), 3 unit)test 0 ,A 3 0 A > case)test), defGG call 3 unit)test : case)test)- 5 obF )) obF7 6 + + 1 0 (one( 3 . + , 0 (t o( 3 . + - 0 (three( 3 . + / 0 (four( 3 . + ?+ . 0 (a hashtable( 3 . + + 1 , - . 0 (an array( 3 . 0 sq 3 . case ! > case)test)- defGG must)infer 0 (an array( 3 0 + 1 , - . case)test)- 3 unit)test 0 (an array( 3 0 + 1 , - . > case)test)- defGG call 3 unit)test %BNS$"N$: case)const)1 1 %BNS$"N$: case)const), , K %ompiled : case)test)/ 5 obF )) str 6 + + case)const)1 0 (uno( 3 . + case)const), 0 (dos( 3 . + - 0 (tres( 3 . + / 0 (cuatro( 3 . + A 0 (cinco( 3 . 0 drop (demasiado( 3 . case ! > case)test)/ defGG must)infer 0 0 0 0 0 0 0 0 (uno( 3 0 1 case)test)/ 3 unit)test (dos( 3 0 , case)test)/ 3 unit)test (tres( 3 0 - case)test)/ 3 unit)test (demasiado( 3 0 1== case)test)/ 3 unit)test (uno( 3 0 1 > case)test)/ defGG call 3 unit)test (dos( 3 0 , > case)test)/ defGG call 3 unit)test (tres( 3 0 - > case)test)/ defGG call 3 unit)test (demasiado( 3 0 1== > case)test)/ defGG call 3 unit)test

: case)test)A 5 obF )) 6 + + case)const)1 0 (uno( print 3 . + case)const), 0 (dos( print 3 . + - 0 (tres( print 3 . + / 0 (cuatro( print 3 .

+ A 0 (cinco( print 3 . 0 drop (demasiado( print 3 . case ! > case)test)A defGG must)infer 0 3 0 1 case)test)A 3 unit)test 0 3 0 1 > case)test)A defGG call 3 unit)test : do)not)call 5 )) 4 6 (do not call( thro !

: test)case)L 5 obF )) value 6 + + > do)not)call 0 (do)not)call( 3 . + - 0 (three( 3 . . case ! > test)case)L defGG must)infer 0 (three( 3 0 - test)case)L 3 unit)test 0 (do)not)call( 3 0 > do)not)call test)case)L 3 unit)test 0 0 0 0 0 0 t f f f f t 3 3 3 3 3 3 0 0 0 0 0 0 + + + + + + 1 1 2 1 1 R , = 1 L , , , R / . / . . R S contiguous)range: 3 unit)test . contiguous)range: 3 unit)test contiguous)range: 3 unit)test contiguous)range: 3 unit)test . contiguous)range: 3 unit)test A . contiguous)range: 3 unit)test

: test)case)R + + > 2 + > ) + > 4 + > Q + > T + > 0 . case !

5 obF )) str 6 0 0 0 0 0 0 (plus( 3 . (minus( 3 . (times( 3 . (divide( 3 . (po er( 3 . (obama( 3 .

> test)case)R defGG must)infer 0 (plus( 3 0 > 2 test)case)R 3 unit)test 0 (plus( 3 0 > 2 > test)case)R defGG call 3 unit)test C'@'#: corner)case)1 PP > corner)case)1 , 0 2 3 curry 1array 0 case 3 curry 5 a )) b 6 define)declared GG 0 t 3 0 > corner)case)1 optimi8ed: 3 unit)test 0 / 3 0 , corner)case)1 3 unit)test 0 / 3 0 , > corner)case)1 defGG call 3 unit)test : test)case)S 5 n )) string 6 + + 1 0 (foo( 3 . . case ! 0 - test)case)S 3 0 obFectGG - H 3 must)fail) ith 0 - > test)case)S defGG call 3 0 obFectGG - H 3 must)fail) ith

: test)case)U + + > 2 + > 2 + > ) + > ) . case !

5 a )) b 6 0 0 0 0 (plus( 3 . (plus ,( 3 . (minus( 3 . (minus ,( 3 .

0 (plus( 3 0 > 2 test)case)U 3 unit)test 0 (plus( 3 0 > 2 > test)case)U defGG call 3 unit)test 0 (minus( 3 0 > ) test)case)U 3 unit)test 0 (minus( 3 0 > ) > test)case)U defGG call 3 unit)test : test)case)1= 5 a )) b 6 + + 1 0 (uno( 3 . + , 0 (dos( 3 . + , 0 (CBS( 3 . + - 0 (tres( 3 . + / 0 (cuatro( 3 . + A 0 (cinco( 3 . . case ! 0 (dos( 3 0 , test)case)1= 3 unit)test 0 (dos( 3 0 , > test)case)1= defGG call 3 unit)test : test)case)11 + + 11 0 + ,, 0 + ,, 0 + -- 0 + // 0 + AA 0 . case ! 5 a )) b 6 (uno( 3 . (dos( 3 . (CBS( 3 . (tres( 3 . (cuatro( 3 . (cinco( 3 .

0 (dos( 3 0 ,, test)case)11 3 unit)test 0 (dos( 3 0 ,, > test)case)11 defGG call 3 unit)test : test)case)1, + + 11 0 + ,, 0 0 drop + -- 0 + // 0 + AA 0 . case ! 5 a )) b 6 (uno( 3 . (dos( 3 . (nachos( 3 (tres( 3 . (cuatro( 3 . (cinco( 3 .

0 (nachos( 3 0 -- test)case)1, 3 unit)test 0 (nachos( 3 0 -- > test)case)1, defGG call 3 unit)test 0 5 x x )) x x 6 3 0 0 + 0 3 0 3 . spread 3 infer 3 unit)test K %opyright 5%6 ,==L< ,=1= Slava ;estov< Caniel 'hrenberg. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs hashtables kernel kernel.private make math math.order math.private quotations sequences sequences.private sets sorting ords ! IN: combinators

K Iost of these combinators have compile)time expansions in K the optimi8ing compiler. See stack)checker.transforms and K compiler.tree.propagation.call)effect P;#IV"$' : call)effect)unsafe 5 quot effect )) 6 drop call ! : execute)effect)unsafe 5 ord effect )) 6 drop execute !

I: obFect thro '##B#)?"NC&'#)DUB$ special)obFect 0 die 3 or 5 error )) 4 6 call)effect)unsafe ! ;#IV"$'G '##B#: rong)values quot call)site ! e for ard reference slots instead

K Je can7t US': effects here so S&B$: in S&B$: out S&B$: terminated:

: call)effect 5 quot effect )) 6 K Con7t use fancy combinators here< since this K runs unoptimi8ed ,dup 0 0 0 datastack 3 dip dip 3 dip dup terminated:GG 0 ,drop f 3 0 dup inGG length s ap outGG length check)datastack 3 if 3 ,dip rot 0 ,drop 3 0 rong)values 3 if ! : execute)effect 5 ord effect )) 6 0 0 execute 3 curry 3 dip call)effect ! K cleave : cleave 5 x seq )) 6 0 call 3 ith each !

ord al ays

: cleaveGquot 5 seq )) quot 6 0 0 keep 3 curry 3 map concat 0 drop 3 append 0 3 like ! K ,cleave : ,cleave 5 x y seq )) 6 0 ,keep 3 each ,drop ! : ,cleaveGquot 5 seq )) quot 6 0 0 ,keep 3 curry 3 map concat 0 ,drop 3 append 0 3 like ! K -cleave : -cleave 5 x y 8 seq )) 6 0 -keep 3 each -drop ! : -cleaveGquot 5 seq )) quot 6 0 0 -keep 3 curry 3 map concat 0 -drop 3 append 0 3 like ! K /cleave : /cleave 5 x y 8 seq )) 6

0 /keep 3 each /drop ! : /cleaveGquot 5 seq )) quot 6 0 0 /keep 3 curry 3 map concat 0 /drop 3 append 0 3 like ! K spread : shallo )spreadGquot 5 seq )) quot 6 0 3 0 0 dup empty: 0 0 dip 3 curry 3 unless 3 dip append 3 reduce ! : deep)spreadGquot 5 seq )) quot 6 0 3 0 0 0 dip 3 curry 3 dip append 3 reduce ! : spread 5 obFs... seq )) 6 deep)spreadGquot call ! K cond '##B#: no)cond ! : cond 5 assoc )) 6 0 dup callable: 0 drop t 3 0 first call 3 if 3 find nip 0 dup callable: 0 call 3 0 second call 3 if 3 0 no)cond 3 if4 ! : alistGquot 5 default assoc )) quot 6 0 rot > if -array append 0 3 like 3 assoc)each ! : condGquot 5 assoc )) quot 6 0 dup pair: 0 0 t 3 s ap ,array 3 unless 3 map reverseK 0 no)cond 3 s ap alistGquot ! K case '##B#: no)case obFect ! : case)find 5 obF assoc )) obF7 6 0 dup array: 0 dupd first dup ord: 0 execute 3 0 dup rapper: 0 rappedGG 3 3 if H 3 0 callable: 3 if 3 find nip ! > case)find t (no)compile( set) ord)prop : case 5 obF assoc )) 6 case)find + + 0 dup array: 3 0 nip second call 3 . + 0 dup callable: 3 0 call 3 . + 0 dup not 3 0 drop no)case 3 . . cond ! : linear)case)quot 5 default assoc )) quot 6 0 0 1quotation > dup prefix > H suffix 3 0 > drop prefix 3 bi4 3 assoc)map alistGquot ! P;#IV"$' : 5distribute)buckets6 5 buckets pair keys )) 6

hen

dup t eq: 0 drop 0 s ap adFoin 3 curry each 3 0 0 0 ,dup 3 dip hashcode pick length rem rot nth adFoin 3 each ,drop 3 if ! : PbucketsG 5 initial length )) array 6 next)po er)of), iota s ap 0 nip clone 3 curry map ! : distribute)buckets 5 alist initial quot )) buckets 6 s apd 0 0 dup first 3 dip call ,array 3 curry map 0 length PbucketsG dup 3 keep 0 first, 5distribute)buckets6 3 ith each ! inline : hash)case)table 5 default assoc )) array 6 V+ . 0 1array 3 distribute)buckets 0 0 0 literali8e 3 dip 3 assoc)map linear)case)quot 3 : hash)dispatch)quot 5 table )) quot 6 0 length 1 ) 0 fixnum)bitand 3 curry 3 keep 0 dispatch 3 curry append ! : hash)case)quot 5 default assoc )) quot 6 hash)case)table hash)dispatch)quot 0 dup hashcode Gfixnum 3 prepend ! : contiguous)range: 5 keys )) : 6 dup 0 fixnum: 3 all: 0 dup all)unique: 0 0 length 3 0 0 supremum 3 0 infimum 3 bi ) 3 bi ) 1 H 3 0 drop f 3 if 3 0 drop f 3 if ! : dispatch)case)quot 5 default 0 > dup < dup keys 0 infimum < 3 0 dup keys infimum < sort)keys values 0 > dispatch < 3 0 3 make < < > if < 3 0 3 make ! ;#IV"$'G : caseGquot 5 default assoc )) quot 6 PreversedG dup keys + + 0 dup empty: 3 0 ,drop 3 . + 0 dup 0 length / PH 3 0 0 ord: 3 any: 3 bi or 3 0 drop linear)case)quot 3 . + 0 dup contiguous)range: 3 0 drop dispatch)case)quot 3 . + 0 dup 0 rapper: 3 any: not 3 0 drop hash)case)quot 3 . + 0 dup 0 rapper: 3 all: 3 0 drop 0 0 rappedGG 3 dip 3 assoc)map hash)case)quot 3 . 0 drop linear)case)quot 3 . cond ! assoc )) quot 6 0 supremum < 3 bi > bet een: < 0 ) Gfixnum 3 W Gquotation 3 map <

ith map !

: recursive)hashcode 5 n obF quot )) code 6 pick = PH 0 -drop = 3 0 0 1 ) 3 ,dip call 3 if ! inline K $hese go here< not in sequences and hashtables< since those K t o cannot depend on us I: sequence hashcode4 0 sequence)hashcode 3 recursive)hashcode ! I: array hashcode4 0 sequence)hashcode 3 recursive)hashcode ! I: reversed hashcode4 0 sequence)hashcode 3 recursive)hashcode ! I: slice hashcode4 0 sequence)hashcode 3 recursive)hashcode ! I: iota)tuple hashcode4 over = PH 0 ,drop = 3 0 nip length = s ap 0 sequence)hashcode)step 3 each)integer 3 if ! I: hashtable hashcode4 0 dup assoc)si8e 1 eq: 0 assoc)hashcode 3 0 nip assoc)si8e 3 if 3 recursive)hashcode ! : to)fixed)point 5 ... obFect quot: 5 ... obFect5n6 )) ... obFect5n216 6 )) ... obFect5n6 6 0 keep over H 3 keep 0 to)fixed)point 3 curry unless ! inline recursive K %opyright 5%6 ,==R< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: assocs init kernel.private namespaces ! IN: system SING&'$BNS: xSL.-, xSL.L/ arm ppc.-, ppc.L/ ! UNIBN: xSL xSL.-, xSL.L/ ! UNIBN: ppc ppc.-, ppc.L/ ! : cpu 5 )) class 6 > cpu get)global ! foldable SING&'$BNS: indo s macosx linux !

UNIBN: unix macosx linux ! : os 5 )) class 6 > os get)global ! foldable : vm)compiler 5 )) string 6 > vm)compiler get)global ! foldable P;#IV"$' : stringGcpu 5 str )) class 6 ?+ + (xSL.-,( xSL.-, . + (xSL.L/( xSL.L/ . + (arm( arm . + (ppc.-,( ppc.-, . + (ppc.L/( ppc.L/ . . at ! : stringGos 5 str )) class 6 ?+ + ( indo s( indo s . + (macosx( macosx .

+ (linux( linux . . at ! ;#IV"$'G : image 5 )) path 6 > image get)global ! : vm 5 )) path 6 > vm get)global ! : embedded: 5 )) : 6 BEX)'IE'CC'C special)obFect ! : exit 5 n )) 4 6 do)shutdo n)hooks 5exit6 ! USING: generic help.markup help.syntax kernel math memory namespaces sequences kernel.private strings classes.singleton ! IN: system "EBU$: (system( "#$I%&': (system( (System interface( + *subsections (cpu( (os( . (Getting the path to the @actor VI and image:( + *subsections vm image . (Getting a monotonically increasing nanosecond count:( + *subsections nano)count . ('xiting the @actor VI:( + *subsections exit . ! "#$I%&': (cpu( (;rocessor detection( (;rocessor detection:( + *subsections cpu . (Supported processors:( + *subsections xSL.-, xSL.L/ ppc arm . (;rocessor families:( + *subsections xSL . ! "#$I%&': (os( (Bperating system detection( (Bperating system detection:( + *subsections os . (Supported operating systems:( + *subsections linux macosx indo s . (Bperating system families:( + *subsections unix indo s . !

?'&;: cpu + *values + (class( singleton)class . . + *description (Butputs a singleton class ith the name of the current %;U architecture.( . ! ?'&;: os + *values + (class( singleton)class . . + *description (Butputs a singleton class ith the name of the current operating system family.( . ! ?'&;: embedded: + *values + (:( (a boolean( . . + *description ($ests if this @actor instance is embedded in another application.( . ! ?'&;: exit + *values + (n( (an integer exit code( . . + *description ('xits the @actor process.( . ! ?'&;: nano)count + *values + (ns( integer . . + *description (Butputs a monotonically increasing count of nanoseconds elapsed since an arbitrary starting time. $he difference of t o calls to this ord allo s timing. $his ord is unaffected by system clock changes.( . + *notes ($his is a lo )level ord. $he ( + *vocab)link (tools.time( . ( vocabulary defines ords to time code execution time.( . ! ?'&;: image + *values + (path( (a pathname string( . . + *description (Butputs the pathname of the currently running @actor image.( . ! ?'&;: vm + *values + (path( (a pathname string( . . + *description (Butputs the pathname of the currently running @actor VI.( . ! USING: help.markup help.syntax quotations strings ! IN: init ?'&;: boot + *description (%alled on startup as part of the boot quotation to initiali8e the runtime and prepare it for running user code.( . ! + boot startup)quot set)startup)quot . related) ords ?'&;: startup)quot + *values + (quot( quotation . . + *description (Butputs the initial quotation called by the VI on startup.( . ! ?'&;: set)startup)quot + *values + (quot( quotation . . + *description (Sets the initial quotation called by the VI on startup. $his quotation must begin ith a call to ( + *link boot . (. $he image must be saved for changes to the boot quotation to take effect.( . + *notes ($he ( + *link (tools.deploy( . ( tool uses this ord.( . ! ?'&;: startup)hooks + *var)description ("n association list mapping string identifiers to quotations to be run on startup.( . ! ?'&;: shutdo n)hooks

+ *var)description ("n association list mapping string identifiers to quotations to be run on shutdo n.( . ! ?'&;: do)startup)hooks + *description (%alls all initiali8ation hook quotations.( . ! ?'&;: do)shutdo n)hooks + *description (%alls all shutdo n hook quotations.( . ! ?'&;: add)startup)hook + *values + (quot( quotation . + (name( string . . + *description (#egisters a startup hook. $he hook ill al ays run hen @actor is started. If the hook as not already defined< this ord also calls it immediately.( . ! + startup)hooks do)startup)hooks add)startup)hook add)shutdo n)hook do)shutdo n)hooks shutdo n)hooks . related) ords "#$I%&': (init( (Initiali8ation and startup( (Jhen @actor starts< the first thing it does is call a + *subsections boot . (Next< initiali8ation hooks are called:( + *subsections do)startup)hooks . (Initiali8ation hooks can be defined:( + *subsections add)startup)hook . (%orresponding shutdo n hooks may also be defined:( + *subsections add)shutdo n)hook . ($he boot quotation can be changed:( + *subsections startup)quot set)startup)quot . (Jhen quitting @actor< shutdo n hooks are called:( + *subsection do)shutdo n)hooks . ! "EBU$: (init( K %opyright 5%6 ,==/< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: assocs continuations continuations.private kernel kernel.private namespaces ! IN: init SNIEB&: startup)hooks SNIEB&: shutdo n)hooks startup)hooks global 0 drop V+ . clone 3 cache drop shutdo n)hooks global 0 drop V+ . clone 3 cache drop : do)hooks 5 symbol )) 6 get 0 nip call5 )) 6 3 assoc)each ! : do)startup)hooks 5 )) 6 startup)hooks do)hooks ! : do)shutdo n)hooks 5 )) 6 shutdo n)hooks do)hooks ! : add)startup)hook 5 quot name )) 6 startup)hooks get 0 at 0 drop 3 0 call5 )) 6 3 if 3 0 set)at 3 -bi ! : add)shutdo n)hook 5 quot name )) 6 shutdo n)hooks get set)at ! ord:(

: boot 5 )) 6 init)namespaces init)catchstack init)error)handler ! : startup)quot 5 )) quot 6 BEX)S$"#$U;)DUB$ special)obFect ! : set)startup)quot 5 quot )) 6 BEX)S$"#$U;)DUB$ set)special)obFect ! : shutdo n)quot 5 )) quot 6 BEX)S?U$CBJN)DUB$ special)obFect ! : set)shutdo n)quot 5 quot )) 6 BEX)S?U$CBJN)DUB$ set)special)obFect ! 0 do)shutdo n)hooks 3 set)shutdo n)quot USING: hashtables.private help.markup help.syntax kernel prettyprint generic sequences sequences.private namespaces assocs ! IN: hashtables "#$I%&': (hashtables.private( (?ashtable implementation details( ($his hashtable implementation uses only one auxiliary array in addition to the hashtable tuple itself. $he array stores keys in even slots and values in odd slots. Values are looked up ith a hashing strategy that uses quadratic probing to resolve collisions.( *nl ($here are t o special obFects: the ( + *link 55tombstone66 . ( marker and the ( + *link 55empty66 . ( marker. Neither of these markers can be used as hashtable keys.( *nl ($he ( + *snippet (count( . ( slot is the number of entries including deleted entries< and ( + *snippet (deleted( . ( is the number of deleted entries.( + *subsections Phash)arrayG set)nth)pair . (If a hashtable7s keys are mutated< or if hashing algorithms change< hashtables can be rehashed:( + *subsections rehash . ! "#$I%&': (hashtables( (?ashtables( (" hashtable provides efficient 5expected constant time6 lookup and storage of keyQvalue pairs. Yeys are compared for equality< and a hashing function is used to reduce the number of comparisons made. $he literal syntax is covered in ( + *link (syntax)hashtables( . (.( *nl (Jords for constructing hashtables are in the ( + *vocab)link (hashtables( . ( vocabulary. ?ashtables implement the ( + *link (assocs)protocol( . (< and all ( + *link (assocs( . ( can be used on them! there are no hashtable)specific ords to access and modify keys< because associative mapping operations are generic and ork ith all associative mappings.( *nl (?ashtables are a class of obFects.( + *subsections hashtable hashtable: . (Nou can create a ne hashtable ith an initial capacity.( + *subsections PhashtableG . (If you don7t care about initial capacity< a more elegant ay to create a ne hashtable is to rite:( + *code (?+ . clone( . ($o convert an assoc to a hashtable:( + *subsections Ghashtable . (@urther topics:(

+ *subsections (hashtables.keys( (hashtables.utilities( (hashtables.private( . ! "#$I%&': (hashtables.keys( (?ashtable keys( (?ashtables rely on the ( + *link hashcode . ( ord to rapidly locate values associated ith keys. $he obFects used as keys in a hashtable must obey certain restrictions.( *nl ($he ( + *link hashcode . ( of a key is a function of its slot values< and if the hashcode changes then the hashtable ill be left in an inconsistent state. $he easiest ay to avoid this problem is to never mutate obFects used as hashtable keys.( *nl (In certain advanced applications< this cannot be avoided and the best design involves mutating hashtable keys. In this case< a custom ( + *link hashcode4 . ( method must be defined hich only depends on immutable slots.( *nl (In addition< the ( + *link equal: . ( and ( + *link hashcode4 . ( methods must be congruent< and if one is defined the other should be defined also. $his is documented in detail in the documentation for these respective ords.( + *subsections hashcode hashcode4 identity)hashcode . ! "#$I%&': (hashtables.utilities( (?ashtable utilities( (Utility ords to create a ne hashtable from a single keyQvalue pair:( + *subsections associate :set)at . ! "EBU$: (hashtables( ?'&;: hashtable + *description ($he class of hashtables. See ( + *link (syntax)hashtables( . ( for syntax and ( + *link (hashtables( . ( for general information.( . ! ?'&;: hash9 + *values + (key( (a key( . + (array( (the underlying array of a hashtable( . + (i( (the index to begin hashtable search( . . + *description (%omputes the index to begin searching from the hashcode of the key. "l ays outputs an even value since keys are stored at even indices of the underlying array.( . ! ?'&;: probe + *values + (array( (the underlying array of a hashtable( . + (i( (a search index( . + (probeZ( (an incrementing counter( . . + *description (Butputs the next hashtable search index.( . ! ?'&;: key9 + *values + (key( (a key( . + (hash( hashtable . + (array( (the underlying array of the hashtable( . + (n( (the index of the key( . + (:( (a boolean indicating hether the key as present( . . + *description (Searches the hashtable for the key using a quadratic probing strategy. Searches stop if either the key or an ( + *link 55empty66 . ( sentinel is found. Searches skip the ( + *link 55tombstone66 . ( sentinel.( . ! + key9 ne )key9 . related) ords ?'&;: ne )key9 + *values + (key( (a key( . + (hash( hashtable . + (array( (the underlying array

of the hashtable( . + (n( (the index here the key ould be stored( . . + *description (Searches the hashtable for the key using a quadratic probing strategy. If the key is not present in the hashtable< outputs the index here it should be stored.( . ! ?'&;: set)nth)pair + *values + (value( (the second element of the pair( . + (key( (the first element of the pair( . + (seq( (a sequence( . + (n( (an index in the sequence( . . + *description (Stores a pair of values into the elements ith index ( + *snippet (n( . ( and ( + *snippet (n21( . (< respectively.( . + * arning ($his ord is in the ( + *vocab)link (hashtables.private( . ( vocabulary because it does not perform bounds checks.( . + *side)effects (seq( . ! ?'&;: reset)hash + *values + (n( (a positive integer specifying hashtable capacity( . + (hash( hashtable . . + *description (#esets the underlying array of the hashtable to a ne array ith the given capacity. #emoves all entries from the hashtable.( . + *side)effects (hash( . ! ?'&;: hash)count2 + *values + (hash( hashtable . . + *description (%alled to increment the hashtable si8e ith ( + *link set)at . . + *side)effects (hash( . !

hen a ne

entry is added

?'&;: hash)deleted2 + *values + (hash( hashtable . . + *description (%alled to increment the deleted entry counter removed ith ( + *link delete)at . . + *side)effects (hash( . !

hen an entry is

?'&;: gro )hash + *values + (hash( hashtable . . + *description ('nlarges the capacity of a hashtable. User code does not need to call this ord directly.( . + *side)effects (hash( . ! ?'&;: :gro )hash + *values + (hash( hashtable . . + *description ('nlarges the capacity of a hashtable if it is almost full. User code does not need to call this ord directly.( . + *side)effects (hash( . ! ?'&;: PhashtableG + *values + (n( (a positive integer specifying hashtable capacity( . + (hash( (a ne hashtable( . . + *description (%reate a ne hashtable capable of storing ( + *snippet (n( . ( keyQvalue pairs before gro ing.( . ! ?'&;: associate + *values + (value( (a value( . + (key( (a key( . + (hash( (a ne ( + *link hashtable . . . + *description (%reate a ne hashtable holding one keyQvalue pair.( . ! ?'&;: :set)at + *values + (value( obFect . + (key( obFect . + (assocQf( (an assoc or ( + *link f . . + (assoc( assoc . .

+ *description (If the third input is an assoc< stores the keyQvalue pair into that assoc< or else creates a ne hashtable ith the keyQvalue pair as its only entry.( . ! ?'&;: Ghashtable + *values + (assoc( assoc . + (hashtable( hashtable . . + *description (%onstructs a hashtable from any assoc.( . ! ?'&;: rehash + *values + (hash( hashtable . . + *description (#ebuild the hashtable. $his ord should be called if the hashcodes of the hashtable7s keys have changed< or if the hashing algorithms themselves have changed< neither of hich should occur during normal operation.( . ! USING: accessors assocs continuations hashtables io kernel make math namespaces prettyprint sequences sequences.private tools.test vectors ! IN: hashtables.tests 0 ?+ . 3 0 + . 0 dup 3 ?+ . mapGassoc 3 unit)test 0 3 0 1=== iota 0 dup sq 3 ?+ . mapGassoc (testhash( set 3 unit)test 0 V+ . 3 0 1=== iota 0 dup sq s ap (testhash( get at H not 3 filter 3 unit)test 0 t 3 0 (testhash( get hashtable: 3 unit)test 0 f 3 0 + 1 + , - . . hashtable: 3 unit)test + t . 0 (value( (key( 0 associate 3 0 ?+ . clone 0 set)at 3 keep 3 ,bi 0 H 3 0 0 arrayGG length 3 bi9 H 3 ,bi and 3 unit)test K $est some hashcodes. 0 t 3 0 0 1 , - 3 hashcode 0 1 , - 3 hashcode H 3 unit)test 0 t 3 0 0 1 0 , - 3 / 3 hashcode 0 1 0 , - 3 / 3 hashcode H 3 unit)test 0 t 3 0 1, hashcode 1, hashcode H 3 unit)test 0 t 3 0 1, Gbignum hashcode 1, hashcode H 3 unit)test K $est various odd keys to see if they 1L PhashtableG (testhash( set t + , - . (testhash( get set)at f 1========================== (testhash( get set)at + . + 0 + . 3 . (testhash( get set)at 0 t 3 0 + , - . (testhash( get at 3 unit)test 0 f 3 0 1========================== (testhash( get at4 drop 3 unit)test 0 + . 3 0 + 0 + . 3 . clone (testhash( get at4 drop 3 unit)test K #egression ork.

- PhashtableG (broken)remove( set 1 J+ > 2 . dup (x( set (broken)remove( get set)at , J+ > H . dup (y( set (broken)remove( get set)at (x( get (broken)remove( get delete)at , (y( get (broken)remove( get set)at 0 1 3 0 (broken)remove( get keys length 3 unit)test + + (salmon( (fish( . + (crocodile( (reptile( . + (co ( (mammal( . + (visual basic( (language( . . Ghashtable (testhash( set 0 f f 3 0 (visual basic( (testhash( get delete)at (visual basic( (testhash( get at4 3 unit)test 0 0 0 0 0 0 0 t f t f f t f 3 3 3 3 3 3 3 0 0 0 0 0 0 0 ?+ . dup H 3 unit)test (xy8( ?+ . H 3 unit)test ?+ . ?+ . H 3 unit)test ?+ + 1 - . . ?+ . H 3 unit)test ?+ . ?+ + 1 - . . H 3 unit)test ?+ + 1 - . . ?+ + 1 - . . H 3 unit)test ?+ + 1 - . . ?+ + 1 (hey( . . H 3 unit)test

K $esting the hash element counting ?+ . clone (counting( set (value( (key( (counting( get set)at 0 1 3 0 (counting( get assoc)si8e 3 (value( (key( (counting( get set)at 0 1 3 0 (counting( get assoc)si8e 3 (key( (counting( get delete)at 0 = 3 0 (counting( get assoc)si8e 3 (key( (counting( get delete)at 0 = 3 0 (counting( get assoc)si8e 3 K $est rehashing , PhashtableG (rehash( set 1 , / A L 1 , / A L (rehash( (rehash( (rehash( (rehash( (rehash( (rehash( get get get get get get set)at set)at set)at set)at set)at set)at

unit)test unit)test unit)test unit)test

0 L 3 0 (rehash( get assoc)si8e 3 unit)test 0 L 3 0 (rehash( get clone assoc)si8e 3 unit)test (rehash( get clear)assoc 0 = 3 0 (rehash( get assoc)si8e 3 unit)test 0 3 0 , ?+

+ 1 , . + , - . . clone at 3 unit)test K $here as an assoc in place of assoc4 some here - PhashtableG (f)hash)test( set 1= 0 f f (f)hash)test( get set)at 3 times 0 1 3 0 (f)hash)test( get assoc)si8e 3 unit)test K #esource leak... ?+ . (x( set 1== 0 drop (x( get clear)assoc 3 each)integer K %rash discovered by erg 0 t 3 0 =.RA PhashtableG dup clone H 3 unit)test K "nother crash discovered by erg 0 3 0 ?+ . clone 0 1 s ap set)at 3 ignore)errors 0 , s ap set)at 3 ignore)errors 0 - s ap set)at 3 ignore)errors drop 3 unit)test 0 ?+ + )1 / . + )- 1L . + )A -L . . 3 0 ?+ + 1 , . + - / . + A L . . 0 0 neg 3 dip sq 3 assoc)map 3 unit)test K Eug discovered by littledan 0 + A A A A . 3 0 0 ?+ + 1 , . + , - . + - / . + / A . + A L . . clone dup keys length < dup assoc)si8e < dup rehash dup keys length < assoc)si8e < 3 + . make 3 unit)test 0 + (one( (t o( - . 3 0 + 1 , - . ?+ + 1 (one( . + , (t o( . . substitute 3 unit)test K Je ant this to ork 0 3 0 hashtable ne (h( set 3 unit)test 0 = 3 0 (h( get assoc)si8e 3 unit)test 0 f f 3 0 (goo( (h( get at4 3 unit)test

0 3 0 1 , (h( get set)at 3 unit)test 0 1 3 0 (h( get assoc)si8e 3 unit)test 0 1 3 0 , (h( get at 3 unit)test K #andom test case 0 ("( 3 0 1== iota 0 dup 3 ?+ . mapGassoc -, over delete)at ("( -, pick set)at -, of 3 unit)test K %opyright 5%6 ,==A< ,=11 Xohn Eenediktsson< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs kernel kernel.private math math.private sequences sequences.private slots.private vectors ! IN: hashtables $U;&': hashtable + count array)capacity . + deleted array)capacity . + array array . ! P;#IV"$' : rap 5 i array )) n 6 lengthGG 1 fixnum)fast fixnum)bitand ! inline rap ! inline

: hash9 5 key array )) i 6 0 hashcode Gfixnum dup fixnum2fast 3 dip

: probe 5 array i probeZ )) array i probeZ 6 , fixnum2fast 0 fixnum2fast over rap 3 keep ! inline : no)key 5 key array )) array n : 6 nip f f ! inline : 5key96 5 key array i probeZ )) array n : 6 0 -dup s ap array)nth 3 dip over 55empty66 eq: 0 /drop no)key 3 0 0 H 3 dip s ap 0 drop rot drop t 3 0 probe 5key96 3 if 3 if ! inline recursive : key9 5 key hash )) array n : 6 arrayGG dup lengthGG = eq: 0 no)key 3 0 ,dup hash9 = 5key96 3 if ! inline : Phash)arrayG 5 n )) array 6 1 2 next)po er)of), / 4 55empty66 ParrayG ! inline : init)hash 5 hash )) 6 = GGcount = GGdeleted drop ! inline : reset)hash 5 n hash )) 6 s ap Phash)arrayG GGarray init)hash ! inline : hash)count2 5 hash )) 6 0 1 fixnum2fast 3 change)count drop ! inline : hash)deleted2 5 hash )) 6 0 1 fixnum2fast 3 change)deleted drop ! inline : hash)deleted) 5 hash )) 6

0 1 fixnum)fast 3 change)deleted drop ! inline K K K K K K K K K K K i H first)empty)or)found F H first)deleted empty: H if true< key as not found if empty: is f: ) e ant to store into i if empty: is t: ) e ant to store into F if F is not f ) other ise e ant to store into i ) ... and increment count

: 5ne )key96 5 key array i probeZ F )) array i F empty: 6 0 ,dup s ap array)nth 3 ,dip pick tombstone: 0 rot 55empty66 eq: 0 nip 0 drop 3 -dip t 3 0 pick or 0 probe 3 dip 5ne )key96 3 if 3 0 0 0 pick 3 dip H 3 ,dip rot 0 nip 0 drop 3 -dip f 3 0 0 probe 3 dip 5ne )key96 3 if 3 if ! inline recursive : ne )key9 5 key hash )) array n 6 0 arrayGG ,dup hash9 = f 5ne )key96 3 keep s ap 0 over 0 hash)deleted) 3 0 hash)count2 3 if s ap or 3 0 ,drop 3 if ! inline : set)nth)pair 5 value key seq n )) 6 , fixnum2fast 0 set)slot 3 ,keep 1 fixnum2fast set)slot ! inline : 5set)at6 5 value key hash )) 6 dupd ne )key9 set)nth)pair ! inline : 5rehash6 5 alist hash )) 6 0 s apd 5set)at6 3 curry assoc)each ! inline : hash)large: 5 hash )) : 6 0 countGG - fixnum4fast 1 fixnum2fast 3 0 arrayGG lengthGG 3 bi fixnumG ! inline : each)pair 5 array quot: 5 key value )) 6 )) 6 0 0 length ,Q 3 keep 0 0 1 fixnum)shift)fast 3 dip 0 array)nth 3 ,keep pick tombstone: 0 -drop 3 3 curry 3 dip 0 0 1 fixnum2fast 3 dip array)nth 3 prepose 0 if 3 curry compose each)integer ! inline : gro )hash 5 hash )) 6 + hashtable . declare 0 0 arrayGG 3 0 assoc)si8e 1 2 3 0 reset)hash 3 tri 3 keep 0 s apd 5set)at6 3 curry each)pair !

: :gro )hash 5 hash )) 6 dup hash)large: 0 gro )hash 3 0 drop 3 if ! inline ;#IV"$'G : PhashtableG 5 n )) hash 6 hashtable ne 0 reset)hash 3 keep ! inline I: hashtable at4 key9 0 - fixnum2fast slot t 3 0 ,drop f f 3 if ! I: hashtable clear)assoc 0 init)hash 3 0 arrayGG 0 drop 55empty66 3 mapK drop 3 bi ! I: hashtable delete)at 0 nip 3 0 key9 3 ,bi 0 0 55tombstone66 dup 3 ,dip set)nth)pair hash)deleted2 3 0 -drop 3 if ! I: hashtable assoc)si8e 0 countGG 3 0 deletedGG 3 bi ) ! inline : rehash 5 hash )) 6 0 Galist 3 0 clear)assoc 3 0 5rehash6 3 tri ! I: hashtable set)at dup :gro )hash 5set)at6 ! : associate 5 value key )) hash 6 1 PhashtableG 0 set)at 3 keep ! inline P;#IV"$' : push)unsafe 5 elt seq )) 6 0 length 3 keep 0 underlyingGG set)array)nth 3 0 0 1 fixnum2fast + array)capacity . declare 3 dip lengthPP 3 ,bi ! inline : collect)pairs 5 hash quot: 5 key value )) elt 6 )) seq 6 0 0 arrayGG 3 0 assoc)si8e PvectorG 3 bi 3 dip s ap 0 0 push)unsafe 3 curry compose each)pair 3 keep + . like ! inline ;#IV"$'G I: hashtable Galist 0 ,array 3 collect)pairs ! I: hashtable keys 0 drop 3 collect)pairs ! I: hashtable values 0 nip 3 collect)pairs ! I: hashtable clone 5clone6 0 clone 3 change)array ! inline I: hashtable equal: over hashtable: 0 assocH 3 0 ,drop f 3 if ! K Cefault method

I: assoc ne )assoc drop PhashtableG ! inline I: f ne )assoc drop PhashtableG ! inline : Ghashtable 5 assoc )) hashtable 6 0 Galist 3 0 assoc)si8e PhashtableG 3 bi 0 5rehash6 3 keep ! I: hashtable assoc)like drop dup hashtable: 0 Ghashtable 3 unless ! inline : :set)at 5 value key assocQf )) assoc 6 0 0 set)at 3 keep 3 0 associate 3 if4 ! K K K : borro ed from boost::hash[combine< but the magic number is ,T,UQphi instead of ,T-,Qphi due to max fixnum value on -,)bit machines hash)combine 5 obF oldhash )) ne hash 6 0 hashcode =x1-cLef-R 2 3 dip 0 L shift 3 0 ), shift 3 bi 2 2 !

'##B#: malformed)hashtable)pair seq pair ! : check)hashtable 5 seq )) seq 6 dup 0 dup length , H 0 drop 3 0 malformed)hashtable)pair 3 if 3 each ! : parse)hashtable 5 seq )) hashtable 6 check)hashtable ?+ . assoc)clone)like ! INS$"N%': hashtable assoc USING: help.markup help.syntax generic kernel.private parser kernel quotations namespaces sequences arrays effects generic.standard classes.builtin slots.private classes strings math assocs byte)arrays alien classes.tuple ! IN: slots "#$I%&': (accessors( (Slot accessors( (@or every tuple slot< a ( + *emphasis (reader( . ( method is defined in the ( + *vocab)link (accessors( . ( vocabulary. $he reader is named ( + *snippet + *emphasis (slot( . (GG( . ( and given a tuple< pushes the slot value on the stack.( *nl (Jritable slots\that is< those not attributed ( + *link read)only . (\also have a ( + *emphasis ( riter( . (. $he riter is named ( + *snippet + *emphasis (slot( . (PP( . ( and stores a value into a slot. It has stack effect ( + *snippet (5 value obFect )) 6( . (. If the slot is speciali8ed to a specific class< the riter checks that the value being ritten into the slot is an instance of that class first. See ( + *link (tuple)declarations( . ( for details.( *nl (In addition< t o utility ords are defined for each ritable slot.( *nl ($he ( + *emphasis (setter( . ( is named ( + *snippet (GG( + *emphasis (slot( . . ( and stores a value into a slot. It has stack effect ( + *snippet (5 obFect value )) obFect 6( . (.( *nl ($he ( + *emphasis (changer( . ( is named ( + *snippet (change)( + *emphasis (slot( . . (. It applies a quotation to the current slot value and stores the result back in the slot! it has stack effect ( + *snippet (5 obFect quot )) obFect 6( . (.( *nl (Since the reader and riter are generic< ords can be ritten hich do not depend on the specific class of tuple passed in< but instead ork on any tuple

that defines slots ith certain names.( *nl (In most cases< using the setter is preferred over the riter because the stack effect is better suited to the common case here the tuple is needed again< and here the ne slot value as Fust computed and so is at the top of the stack. @or example< consider the case here you ant to create a tuple and fill in the slots ith literals. $he follo ing version uses setters:( + *code (PemailG( ( >(?appy birthday>( GGsubFect( ( + >(bob9bigcorp.com>( . GGto( ( >(alice9bigcorp.com>( GGfrom( (send)email( . ($he follo ing uses riters< and requires some stack shuffling:( + *code (PemailG( ( >(?appy birthday>( over subFectPP( ( + >(bob9bigcorp.com>( . over toPP( ( >(alice9bigcorp.com>( over fromPP( (send)email( . ('ven if some of the slot values come from the stack underneath the tuple being constructed< setters in:( + *code (PemailG( ( s ap GGsubFect( ( s ap GGto( ( >(alice9bigcorp.com>( GGfrom( (send)email( . ($he above has less shuffling than the riter version:( + *code (PemailG( ( 0 subFectPP 3 keep( ( 0 toPP 3 keep( ( >(alice9bigcorp.com>( over fromPP( (send)email( . ($he changer ord abstracts a common pattern here a slot value is read then stored again! so the follo ing is not idiomatic code:( + *code (find)manager( ( salaryGG =.RA 4 GGsalary( . ($he follo ing version is preferred:( + *code (find)manager( ( 0 =.RA 4 3 change)salary( . + *see)also (slots( (mirrors( . ! "#$I%&': (slot)initial)values( (Initial values of slots( ("n initial value for a slot can be specified ith the ( + *link initial: . ( slot declaration attribute. @or certain classes< the initial value is optional! in these cases< it does not need to be specified. @or others< it is required. Initial values can be used independently of class declaration< but if specified< the value must satisfy the class predicate.( *nl ($he follo ing classes have default initial values:( + *table + + + *link f . . + *link f . .

+ + + + +

+ + + + +

+ + + + +

*link *link *link *link *link

fixnum . . + *snippet (=( . . float . . + *snippet (=.=( . . string . . + *snippet (>(>(( . . byte)array . . + *snippet (E+ .( . . pinned)alien . . + *snippet (E"C)"&I'N( . .

. ("ll other classes are handled ith one of t o cases:( + *list + (If the class is a union or mixin class hich ( + *emphasis (contains( . ( one of the above kno n classes< then the initial value of the class is that of the kno n class< ith preference given to classes earlier in the list. @or example< if the slot is declared ( + *link obFect . ( 5this is the default6< the initial value is ( + *link f . (. Similarly for ( + *link sequence . ( and ( + *link assoc . (.( . + (If the class is a tuple class< the initial value of the slot is a ne < shared instance of the class created ith ( + *link ne . (.( . + (Bther ise< a ( + *link bad)initial)value . ( error is thro n. In this case< an initial value must be specified explicitly using ( + *link initial: . (.( . . (" ord can be used to check if a class has an initial value or not:( + *subsections initial)value . ! "#$I%&': (slots( (&o )level slot operations( ($he ( + *vocab)link (slots( . ( vocabulary contains ords for introspecting the slots of an obFect. " ( + *emphasis (slot( . ( is a component of an obFect hich can store a value.( *nl + *link (tuples( . ( are composed entirely of slots< and instances of ( + *link (builtin)classes( . ( consist of slots together ith intrinsic data.( *nl ($he ( + *snippet (>(slots>(( . ( ord property of built)in and tuple classes holds an array of ( + *emphasis (slot specifiers( . ( describing the slot layout of each instance.( + *subsections slot)spec . ($he four ords associated ith a slot can be looked up in the ( + *vocab)link (accessors( . ( vocabulary:( + *subsections reader) ord riter) ord setter) ord changer) ord . (&ooking up a slot by name:( + *subsections slot)named . (Cefining slots dynamically:( + *subsections define)reader define) riter define)setter define)changer define)slot)methods define)accessors . (Unsafe slot access:( + *subsections slot set)slot . + *see)also (accessors( (mirrors( . ! "EBU$: (slots(

?'&;: slot)spec + *class)description (" slot specification. $he ( + *snippet (>(slots>(( . ( ord property of ( + *link builtin)class . ( and ( + *link tuple)class . ( instances holds sequences of slot specifications.( *nl ($he slots of a slot specification are:( + *list + + *snippet (name( . ( ) a ( + *link string . ( identifying the slot.( . + + *snippet (offset( . ( ) an ( + *link integer . ( offset specifying here the slot value is stored inside instances of the relevant class. $his is an implementation detail.( . + + *snippet (class( . ( ) a ( + *link class . ( declaring the set of possible values for the slot.( . + + *snippet (initial( . ( ) an initial value for the slot.( . + + *snippet (read)only( . ( ) a boolean indicating hether the slot is read only or not. #ead only slots do not have a riter method associated ith them.( . . . ! ?'&;: define)typecheck + *values + (class( class . + (generic( (a generic ord( . + (quot( quotation . + (props( (an assoc of ord properties( . . + *description (Cefines a generic ord ith the ( + *link standard)combination . ( using dispatch position =< and having one method on ( + *snippet (class( . (.( *nl ($his creates a definition analogous to the follo ing code:( + *code (G'N'#I%: generic( (I: class generic quot !( . (It checks if the top of the stack is an instance of ( + *snippet (class( . (< and if so< executes the quotation.( . + *notes ($his ord is used internally to rap unsafe lo )level code in a type)checking stub.( . ! ?'&;: define)reader + *values + (class( class . + (slot)spec( slot)spec . . + *description (Cefines a reader ord to read a slot specified by ( + *snippet (slot)spec( . (.( . *lo )level)note ! ?'&;: define) riter + *values + (class( class . + (slot)spec( slot)spec . . + *description (Cefines a generic ord ( + *snippet ( riter( . ( to value to a slot specified by ( + *snippet (slot)spec( . (.( . *lo )level)note !

rite a ne

?'&;: define)slot)methods + *values + (class( class . + (slot)spec( slot)spec . . + *description (Cefines a reader< riter< setter and changer for a slot specified by ( + *snippet (slot)spec( . (.( . *lo )level)note ! ?'&;: define)accessors + *values + (class( class . + (specs( (a sequence of ( + *link slot)spec . ( instances( . . + *description (Cefines slot methods.( . *lo )level)note !

?'&;: slot + *values + (obF( obFect . + (m( (a non)negative fixnum( . + (value( obFect . . + *description (#eads the obFect stored at the ( + *snippet (n( . (th slot of ( + *snippet (obF( . (.( . + * arning ($his ord is in the ( + *vocab)link (slots.private( . ( vocabulary because it does not perform type or bounds checks< and slot numbers are implementation detail.( . ! ?'&;: set)slot + *values + (value( obFect . + (obF( obFect . + (n( (a non)negative + *description (Jrites ( + *snippet (value( . ( to the ( + *snippet slot of ( + *snippet (obF( . (.( . + * arning ($his ord is in the ( + *vocab)link (slots.private( . ( because it does not perform type or bounds checks< and slot numbers implementation detail.( . ! fixnum( . . (n( . (th vocabulary are

?'&;: slot)named + *values + (name( string . + (specs( (a sequence of ( + *link slot)spec . ( instances( . + (specQf( + *maybe slot)spec . . . + *description (Butputs the ( + *link slot)spec . ( ith the given name.( . ! USING: math accessors slots strings generic.single kernel tools.test generic ords parser eval math.functions arrays ! IN: slots.tests $U;&': rQ )test foo ! $U;&': rQo)test + foo read)only . ! 0 rQo)test ne 1,- GGfoo 3 0 no)method: 3 must)fail) ith

$U;&': decl)test + foo array . ! 0 decl)test ne (( GGfoo 3 0 bad)slot)value: 3 must)fail) ith

$U;&': hello length ! 0 - 3 0 (xy8( lengthGG 3 unit)test 0 (xy8( / GGlength 3 0 no)method: 3 must)fail) ith K $est protocol slots S&B$: my)protocol)slot)test $U;&': protocol)slot)test)tuple x ! I: protocol)slot)test)tuple my)protocol)slot)testGG xGG sq ! I: protocol)slot)test)tuple my)protocol)slot)testPP 0 sqrt 3 dip xPP ! 0 U 3 0 $+ protocol)slot)test)tuple + x - . . my)protocol)slot)testGG 3 unit)test 0 /.= 3 0 $+ protocol)slot)test)tuple + x - . . clone 0 R 2 3 change)my)protocol)slot)test xGG 3 unit)test UNIBN: comme)ci integer float ! UNIBN: comme)ca integer float ! comme)ca ,A.A (initial)value( set) ord)prop 0 = t 3 0 comme)ci initial)value 3 unit)test 0 ,A.A t 3 0 comme)ca initial)value 3 unit)test

K %opyright 5%6 ,==A< ,=11 Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors alien arrays assocs byte)arrays classes classes.algebra classes.algebra.private classes.maybe combinators generic generic.standard hashtables kernel kernel.private make math quotations sequences sequences.private slots.private strings ords ! IN: slots $U;&': slot)spec name offset class initial read)only ! ;#'CI%"$': reader P ord (reader( ord)prop ! ord)prop Gboolean !

;#'CI%"$': reader)method P method (reading( ;#'CI%"$': ;#'CI%"$': riter P ord ( riter(

ord)prop ! ord)prop Gboolean !

riter)method P method ( riting(

: Pslot)specG 5 )) slot)spec 6 slot)spec ne obFect bootstrap) ord GGclass ! : define)typecheck 5 class generic quot props )) 6 0 create)method 3 ,dip 0 0 propsGG 3 0 drop 3 0 3 tri4 assoc)unionK drop 3 0 drop define 3 0 ,drop make)inline 3 -tri ! G'N'#I%Z reader)quot 1 5 class slot)spec )) quot 6 I: obFect reader)quot nip 0 dup offsetGG < > slot < dup classGG obFect bootstrap) ord eq: 0 drop 3 0 classGG 1array < > declare < 3 if 3 0 3 make ! : reader) ord 5 name )) ord 6 (GG( append (accessors( create dup t (reader( set) ord)prop ! : reader)props 5 slot)spec )) assoc 6 (reading( associate ! : define)reader)generic 5 name )) 6 reader) ord 5 obFect )) value 6 define)simple)generic ! : define)reader 5 class slot)spec )) 6 0 nip nameGG define)reader)generic 3 0 + 0 drop 3 0 nip nameGG reader) ord 3 0 reader)quot 3 0 nip reader)props 3 . ,cleave define)typecheck 3 ,bi ! : riter) ord 5 name )) ord 6

(PP( append (accessors( create dup t ( riter( set) ord)prop ! '##B#: bad)slot)value value class ! G'N'#I%: instance)check)quot 5 obF )) quot 6 I: class instance)check)quot 5 class )) quot 6 + + 0 dup obFect bootstrap) ord eq: 3 0 drop 0 3 3 . + 0 dup (coercer( ord)prop 3 0 (coercer( ord)prop 3 . 0 call)next)method 3 . cond ! I: obFect 0 > 0 0 > 3 0 3 G'N'#I%Z instance)check)quot dup < predicate)def W 3 0 bad)slot)value 3 curry < 3 bi unless < make ! riter)quot 1 5 class slot)spec )) quot 6

I: obFect riter)quot nip 0 classGG instance)check)quot dup empty: 0 0 dip 3 curry 3 unless 3 0 offsetGG 0 set)slot 3 curry 3 bi append ! : riter)props 5 slot)spec )) assoc 6 ( riting( associate !

: define) riter)generic 5 name )) 6 riter) ord 5 value obFect )) 6 define)simple)generic ! : define) riter 5 class slot)spec )) 6 0 nip nameGG define) riter)generic 3 0 + 0 drop 3 0 nip nameGG riter) ord 3 0 riter)quot 3 0 nip riter)props 3 . ,cleave define)typecheck 3 ,bi ! : setter) ord 5 name )) ord 6 (GG( prepend (accessors( create ! : define)setter 5 name )) 6 dup setter) ord dup deferred: 0 0 > over < s ap riter) ord < 3 0 3 make 5 obFect value )) obFect 6 define)inline 3 0 ,drop 3 if ! : changer) ord 5 name )) ord 6 (change)( prepend (accessors( create ! : define)changer 5 name )) 6 dup changer) ord dup deferred: 0 0 > over <

over reader) ord 1quotation 0 dip call 3 curry 0 3 like 0 dip s ap 3 curry W s ap setter) ord < 3 0 3 make 5 obFect quot )) obFect 6 define)inline 3 0 ,drop 3 if ! : define)slot)methods 5 class slot)spec )) 6 0 define)reader 3 0 dup read)onlyGG 0 ,drop 3 0 0 nameGG define)setter drop 3 0 nameGG define)changer drop 3 0 define) riter 3 ,tri 3 if 3 ,bi ! : define)accessors 5 class specs )) 6 0 define)slot)methods 3 ith each ! : define)protocol)slot 5 name )) 6 + 0 define)reader)generic 3 0 define) riter)generic 3 0 define)setter 3 0 define)changer 3 . cleave ! C'@'#: initial)value G'N'#I%: initial)value4 5 class )) obFect : 6 I: class initial)value4 drop f f ! I: maybe initial)value4 drop f t ! K Cefault initial value is f< =< or the default initial value of K the smallest class. Special case = because float is ostensibly K smaller than integer in union+ integer float . because of K alphabetical sorting. I: anonymous)union initial)value4 + + 0 f over instance: 3 0 drop f t 3 . + 0 = over instance: 3 0 drop = t 3 . 0 membersGG sort)classes 0 initial)value 3 + . mapGassoc :last 0 second t 3 0 f f 3 if4 3 . cond ! K See if any of the initial values fit the intersection class< K or else return that none do< and leave it up to the user to K provide an initial: value. I: anonymous)intersection initial)value4 + + 0 f over instance: 3 0 drop f t 3 . + 0 = over instance: 3 0 drop = t 3 . 0 0 3 0 participantsGG sort)classes 0 initial)value 3 + . mapGassoc 3 0 3 tri

0 0 first, nip 3 dip instance: 3 curry find s ap 0 nip second t 3 0 ,drop f f 3 if 3 . cond ! : initial)value 5 class )) obFect : 6 + + 0 dup only)classoid: 3 0 dup initial)value4 3 . + 0 dup (initial)value( ord)prop 3 0 dup (initial)value( ord)prop t 3 . + 0 > f bootstrap) ord over classPH 3 0 f t 3 . + 0 > array)capacity bootstrap) ord over classPH 3 0 = t 3 . + 0 bignum bootstrap) ord over classPH 3 0 = Gbignum t 3 . + 0 float bootstrap) ord over classPH 3 0 =.= t 3 . + 0 string bootstrap) ord over classPH 3 0 (( t 3 . + 0 array bootstrap) ord over classPH 3 0 + . t 3 . + 0 byte)array bootstrap) ord over classPH 3 0 E+ . t 3 . + 0 pinned)alien bootstrap) ord over classPH 3 0 Pbad)alienG t 3 . + 0 quotation bootstrap) ord over classPH 3 0 0 3 t 3 . 0 dup initial)value4 3 . cond 0 drop 3 ,dip ! G'N'#I%: make)slot 5 desc )) slot)spec 6 I: string make)slot Pslot)specG s ap GGname ! : peel)off)name 5 slot)spec array )) slot)spec array 6 0 first GGname 3 0 rest 3 bi ! inline : init)slot)class 5 slot)spec class )) slot)spec 6 0 GGclass 3 0 initial)value 0 GGinitial 3 0 drop 3 if 3 bi ! : peel)off)class 5 slot)spec array )) slot)spec array 6 dup empty: 0 dup first classoid: 0 0 first init)slot)class 3 0 rest 3 bi 3 hen 3 unless ! '##B#: bad)slot)attribute key ! : peel)off)attributes 5 slot)spec array )) slot)spec array 6 dup empty: 0 unclip + + initial: 0 0 first GGinitial 3 0 rest 3 bi 3 . + read)only 0 0 t GGread)only 3 dip 3 . 0 bad)slot)attribute 3 . case 3 unless ! '##B#: bad)initial)value name initial)value class ! : check)initial)value 5 slot)spec )) slot)spec 6 0 3 0 0 3 0 initialGG 3 0 classGG 3 tri

,dup instance: 0 ,drop 3 0 0 nameGG 3 ,dip bad)initial)value 3 if 3 if)bootstrapping ! I: array make)slot Pslot)specG s ap peel)off)name peel)off)class 0 dup empty: 3 0 peel)off)attributes 3 until drop check)initial)value ! I: slot)spec make)slot check)initial)value ! : make)slots 5 slots )) specs 6 0 make)slot 3 map ! : finali8e)slots 5 specs base )) specs 6 over length iota 0 2 3 ith map 0 GGoffset 3 ,map ! : slot)named4 5 name specs )) offset specQf 6 0 nameGG H 3 ith find ! : slot)named 5 name specs )) specQf 6 slot)named4 nip ! K ;redefine some slots< because there are change)4 ords in other vocabs K that nondeterministically cause ambiguities hen US'd alongside K accessors S&B$: at S&B$: nth S&B$: global K %opyright 5%6 ,==R< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs checksums checksums.crc-, compiler.units continuations definitions io.encodings.utfS io.files io.pathnames kernel namespaces sequences sets source)files.errors strings ords ! @#BI: namespaces HG set ! IN: source)files SNIEB&: source)files $U;&': source)file)tuple path top)level)form checksum definitions main ! : record)top)level)form 5 quot file )) 6 top)level)formPP 0 3 0 f notify)definition)observers 3 if)bootstrapping ! : record)checksum 5 lines source)file )) 6 0 crc-, checksum)lines 3 dip checksumPP !

: record)definitions 5 file )) 6 ne )definitions get GGdefinitions drop ! : Psource)fileG 5 path )) source)file 6 > source)file)tuple ne s ap GGpath PdefinitionsG GGdefinitions ! '##B#: invalid)source)file)path path ! : source)file 5 path )) source)file 6 dup string: 0 invalid)source)file)path 3 unless source)files get 0 Psource)fileG 3 cache ! : reset)checksums 5 )) 6 source)files get 0 s ap dup exists: 0 utfS file)lines s ap record)checksum 3 0 ,drop 3 if 3 assoc)each ! I: pathname here stringGG 1 ,array !

: forget)source 5 path )) 6 source)files get delete)at4 0 definitionsGG 0 members forget)all 3 each 3 0 drop 3 if ! I: pathname forget4 stringGG forget)source ! : rollback)source)file 5 file )) 6 0 ne )definitions get 0 union 3 ,map 3 change)definitions drop ! SNIEB&: file : rap)source)file)error 5 error )) 4 6 file get rollback)source)file > source)file)error ne f GGlineZ file get pathGG GGfile s ap GGerror rethro !

ith)source)file 5 name quot )) 6 ZK Should be called from inside ith)compilation)unit. 0 0 source)file 0 file set 3 0 definitionsGG old)definitions set 3 bi 3 dip 0 rap)source)file)error 3 recover 3 ith)scope ! inline USING: assocs compiler.errors compiler.units definitions namespaces source)files.errors tools.test ords ! IN: source)files.errors.tests C'@'#: forget)test 0 3 0 0 > forget)test 0 1 3 5 )) 6 define)declared 3 unit)test ith)compilation)unit 3

0 t 3 0 > forget)test compiler)errors get key: 3 unit)test 0 3 0 0 > forget)test forget 3 ith)compilation)unit 3 unit)test 0 f 3 0 > forget)test compiler)errors get key: 3 unit)test K %opyright 5%6 ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs continuations definitions init io kernel math math.parser namespaces sequences sorting ! IN: source)files.errors G'N'#I%: error)file 5 error )) file 6 G'N'#I%: error)line 5 error )) line 6 I: obFect error)file drop f ! I: obFect error)line drop f ! I: condition error)file errorGG error)file ! I: condition error)line errorGG error)line ! $U;&': source)file)error error asset file lineZ ! I: source)file)error error)file 0 errorGG error)file 3 0 fileGG 3 bi or ! I: source)file)error error)line 0 errorGG error)line 3 0 lineZGG 3 bi or ! I: source)file)error compute)restarts errorGG compute)restarts ! : sort)errors 5 errors )) alist 6 0 0 lineZGG = or 3 sort) ith 3 + . assoc)map)as sort)keys ! : group)by)source)file 5 errors )) assoc 6 ?+ . clone 0 0 push)at 3 curry 0 dup fileGG 3 prepose each 3 keep ! $U;&': error)type)holder type initial: t . ! ord plural icon quot forget)quot + fatal:

G'N'#I%: error)type 5 error )) type 6 : Pdefinition)errorG 5 error definition class )) source)file)error 6 ne s ap 0 GGasset 3 0 here 0 first, 0 GGfile 3 0 GGlineZ 3 bi4 3 hen4 3 bi s ap GGerror ! inline SNIEB&: error)types error)types 0 V+ . clone 3 initiali8e : define)error)type 5 error)type )) 6 dup typeGG error)types get set)at ! : error)icon)path 5 type )) icon 6 error)types get at iconGG ! : error)counts 5 )) alist 6 error)types get 0 nip dup quotGG call5 )) seq 6 length 3 assoc)map 0 0 fatal:GG 3 0 = G 3 bi4 and 3 assoc)filter ! : error)summary 5 )) 6 error)counts 0 over 0 ordGG rite 3 0 ( ) sho ( rite numberGstring

rite bl 3

0 pluralGG print 3 tri4 3 assoc)each ! : all)errors 5 )) errors 6 error)types get values 0 quotGG call5 )) seq 6 3 map concat ! G'N'#I%: errors)changed 5 observer )) 6 SNIEB&: error)observers 0 V+ . clone error)observers set)global 3 (source)files.errors( add)startup)hook : add)error)observer 5 observer )) 6 error)observers get push ! : remove)error)observer 5 observer )) 6 error)observers get remove)eqK drop ! : notify)error)observers 5 )) 6 error)observers get 0 errors)changed 3 each ! : delete)file)errors 5 seq file type )) 6 0 0 s ap fileGG H 3 0 s ap error)type H 3 bi)curry4 bi and not 3 ,curry filterK drop notify)error)observers ! : delete)definition)errors 5 definition )) 6 error)types get 0 second forget)quotGG dup 0 call5 definition )) 6 3 0 ,drop 3 if 3 ith each ! IN: source)files.tests USING: source)files tools.test assocs sequences strings namespaces kernel ! 0 + . 3 0 source)files get keys 0 string: not 3 filter 3 unit)test USING: help.markup help.syntax vocabs.loader io.pathnames strings definitions quotations compiler.units ! IN: source)files "#$I%&': (source)files( (Source files( (Jords in the ( + *vocab)link (source)files( . ( vocabulary are used to keep track of loaded source files. $his is used to implement ( + *link (vocabs.refresh( . (.( *nl ($he source file database:( + *subsections source)files . ($he class of source files:( + *subsections source)file . (Jords intended for the parser:( + *subsections record)checksum record)definitions . (#emoving a source file from the database:( + *subsections forget)source . (Updating the database:( + *subsections reset)checksums . ($he ( + *link pathname . ( class implements the definition protocol by orking ith the corresponding source file! see ( + *link (definitions( . (.( !

"EBU$: (source)files( ?'&;: source)files + *var)description ("n assoc mapping pathname strings to ( + *link source)file . ( instances< representing loaded source files.( . ! ?'&;: source)file + *values + (path( (a pathname string( . + (source)file( source)file . . + *description (Butputs the source file associated to a path name< creating the source file first if it doesn7t exist. Source files are retained in the ( + *link source)files . ( variable.( . + *class)description (Instances retain information about loaded source files< and have the follo ing slots:( + *list + + *snippet (path( . ( ) a pathname string.( . + + *snippet (checksum( . ( ) the %#%-, checksum of the source file7s contents at the time it as most recently loaded.( . + + *snippet (uses( . ( ) an assoc hose keys are ords referenced from this source file7s top level form.( . + + *snippet (definitions( . ( ) a pair of assocs< containing definitions and classes defined in this source file< respectively( . . . ! ?'&;: record)checksum + *values + (lines( (a sequence of strings( . + (source)file( source)file . . + *description (#ecords the %#%-, checksum of the source file7s contents.( . *lo )level)note ! ?'&;: reset)checksums + *description (#esets recorded modification times and %#%-, checksums for all loaded source files< creating a checkpoint for ( + *link (vocabs.refresh( . (.( . ! ?'&;: forget)source + *values + (path( (a pathname string( . . + *description (@orgets all information kno n about a source file.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . ! ?'&;: record)definitions + *values + (file( source)file . . + *description (#ecords that all ( + *link ne )definitions . ( + *snippet (file( . (.( . !

ere defined in (

?'&;: rollback)source)file + *values + (file( source)file . . + *description (#ecords information to the source file after an incomplete parse hich ended ith an error.( . ! ?'&;: file + *var)description (Stores the ( + *link source)file . ( being parsed. $he ( + *snippet (path( . ( of this obFect comes from the input parameter to ( + *link ith)source)file . (.( . ! K Unit tests for vocabs vocabulary USING: vocabs tools.test ! IN: vocabs.tests 0 f 3 0 (kernel( vocab)main 3 unit)test 0 t 3 0 (( (( child)vocab: 3 unit)test 0 t 3 0 (( (io.files( child)vocab: 3 unit)test

0 t 3 0 (io( (io.files( child)vocab: 3 unit)test 0 f 3 0 (io.files( (io( child)vocab: 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (fooQbar( create)vocab 3 0 bad)vocab)name: 3 must)fail) ith (foo>>bar( create)vocab 3 0 bad)vocab)name: 3 must)fail) ith (foo:bar( create)vocab 3 0 bad)vocab)name: 3 must)fail) ith - create)vocab 3 0 bad)vocab)name: 3 must)fail) ith f create)vocab 3 0 bad)vocab)name: 3 must)fail) ith (a b( create)vocab 3 0 bad)vocab)name: 3 must)fail) ith (fooQbar( lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (foo>>bar( lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (foo:bar( lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith - lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith f lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (a b( lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (fooQbar( Gvocab)link lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (foo>>bar( Gvocab)link lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (foo:bar( Gvocab)link lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith - Gvocab)link lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith f Gvocab)link lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith (a b( Gvocab)link lookup)vocab 3 0 bad)vocab)name: 3 must)fail) ith

0 (soFoiFsaoifFsthisdoesntexistomgomgomgpl8nodontexist( require 3 0 no)vocab: 3 must)fail) ith 0 (letstrythisagainnooooooyoucantexistnoooooo( load)vocab 3 0 no)vocab: 3 must)fail) ith USING: help.markup help.syntax strings ords compiler.units vocabs.loader ! IN: vocabs "#$I%&': (vocabularies( (Vocabularies( (" ( + *emphasis (vocabulary( . ( is a named collection of ( + *link ( ords( . (. Vocabularies are defined in the ( + *vocab)link (vocabs( . ( vocabulary.( *nl (Vocabularies are stored in a global hashtable:( + *subsections dictionary . (Vocabularies form a class.( + *subsections vocab vocab: . (Various vocabulary ords are overloaded to accept a ( + *emphasis (vocabulary specifier( . (< hich is a string naming the vocabulary< the ( + *link vocab . ( instance itself< or a ( + *link vocab)link . (:( + *subsections vocab)link Gvocab)link . (&ooking up vocabularies by name:( + *subsections vocab . ("ccessors for various vocabulary attributes:( + *subsections vocab)name vocab)main vocab)help . (&ooking up existing vocabularies and creating ne vocabularies:( + *subsections lookup)vocab

. (Getting ords from a vocabulary:( + *subsections vocab) ords ords all) ords ords)named . (#emoving a vocabulary:( + *subsections forget)vocab . + *see)also ( ords( (vocabs.loader( ( ord)search( . ! "EBU$: (vocabularies( ?'&;: dictionary + *var)description (?olds a hashtable mapping vocabulary names to vocabularies.( . ! ?'&;: vocabs + *values + (seq( (a sequence of strings( . . + *description (Butputs a sequence of all defined vocabulary names.( . ! ?'&;: lookup)vocab + *values + (vocab)spec( (a vocabulary specifier( . + (vocab( vocab . . + *description (Butputs a named vocabulary< or ( + *link f . ( if no vocabulary ith this name exists.( . + *class)description (Instances represent vocabularies.( . ! ?'&;: vocab)name + *values + (vocab)spec( (a vocabulary specifier( . + (name( string . . + *description (Butputs the name of a vocabulary.( . ! ?'&;: vocab) ords + *values + (vocab)spec( (a vocabulary specifier( . + ( ords( (an assoc mapping strings to ords( . . + *description (Butputs the ords defined in a vocabulary.( . ! ?'&;: ords + *values + (vocab( string . + (seq( (a sequence of ords( . . + *description (Butputs a sequence of ords defined in the vocabulary< or ( + *link f . ( if no vocabulary ith this name exists.( . ! ?'&;: all) ords + *values + (seq( (a sequence of ords( . . + *description (Butputs a sequence of all ords in the dictionary.( . ! ?'&;: forget)vocab + *values + (vocab( string . . + *description (#emoves a vocabulary. "ll ords in the vocabulary are forgotten.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . ! ?'&;: require)hook + *var)description + *quotation (5 name )) 6( . ( hich loads a vocabulary. $his quotation is called by ( + *link require . (. $he default value should not need to be changed! this functionality is implemented via a hook stored in a variable to break a circular dependency hich ould other ise exist from ( + *vocab)link (vocabs( . ( to ( + *vocab)link (vocabs.loader( . ( to ( + *vocab)link (parser( . ( back to ( + *vocab)link (vocabs( . (.( . !

child)vocabs create)vocab

?'&;: require + *values + (obFect( (a vocabulary specifier( . . + *description (&oads a vocabulary if it has not already been loaded. $hro s an error if the vocabulary does not exist on disk or in the dictionary.( . + *notes ($o unconditionally reload a vocabulary< use ( + *link reload . (. $o reload changed source files only< use the ords in ( + *link (vocabs.refresh( . (.( . ! ?'&;: ords)named + *values + (str( string . + (seq( (a sequence of ords( . . + *description (Butputs a sequence of all ords named ( + *snippet (str( . ( from the set of currently)loaded vocabularies.( . ! ?'&;: create)vocab + *values + (name( string . + (vocab( vocab . . + *description (%reates a ne vocabulary if one does not exist name< other ise outputs an existing vocabulary.( . !

ith the given

?'&;: child)vocabs + *values + (vocab( (a vocabulary specifier( . + (seq( (a sequence of strings( . . + *description (Butputs all vocabularies hich are conceptually under ( + *snippet (vocab( . ( in the hierarchy.( . + *examples + *unchecked)example (>(io.streams>( child)vocabs .( (+ >(io.streams.c>( >(io.streams.duplex>( >(io.streams.lines>( >(io.streams.nest ed>( >(io.streams.plain>( >(io.streams.string>( .( . . ! ?'&;: vocab)link + *class)description (Instances of this class identify vocabularies hich are potentially not loaded. $he ( + *link vocab)name . ( slot is the vocabulary name.( *nl (Vocabulary links are created by calling ( + *link Gvocab)link . (.( . ! ?'&;: Gvocab)link + *values + (name( string . + (vocab( (a vocabulary specifier( . . + *description (If the vocabulary is loaded< outputs the corresponding ( + *link vocab . ( instance< other ise creates a ne ( + *link vocab)link . (.( . ! ?'&;: runnable)vocab + *class)description ($he class of vocabularies ith a ( + *slot (main( . ( ord.( . ! USING: vocabs.loader tools.test continuations vocabs math kernel arrays sequences namespaces io.streams.string sets parser source)files ords assocs classes.tuple definitions debugger compiler.units accessors eval vocabs.hierarchy combinators vocabs.parser grouping vocabs.files vocabs.refresh ! IN: vocabs.loader.tests K $his vocab should not exist< but Fust in case... 0 3 0 0 (vocabs.loader.test( forget)vocab 3 ith)compilation)unit 3 unit)test

0 $+ vocab)link f (vocabs.loader.test( . 3 0 (vocabs.loader.test( Gvocab)link 3 unit)test 0 t 3 0 (kernel( Gvocab)link (kernel( lookup)vocab H 3 unit)test IN: vocabs.loader.test., : hello 5 )) 6 ! I"IN: hello IN: vocabs.loader.tests 0 3 0 (vocabs.loader.test.,( run (vocabs.loader.test.,( lookup)vocab run (vocabs.loader.test.,( Pvocab)linkG run 3 unit)test 0 3 (resource:coreQvocabsQloaderQtestQaQa.factor( forget)source (vocabs.loader.test.a( forget)vocab ith)compilation)unit

= (count)me( set)global , 0 0 (vocabs.loader.test.a( require 3 must)fail 0 f 3 0 (vocabs.loader.test.a( lookup)vocab source)loaded:GG 3 unit)test 0 t 3 0 (resource:coreQvocabsQloaderQtestQaQa.factor( source)file definitionsGG dup US': prettyprint . (v)l)t)a)hello( (vocabs.loader.test.a( lookup) ord dup . s ap first in: 3 unit)test 3 times 0 , 3 0 (count)me( get)global 3 unit)test 0 (IN: vocabs.loader.test.a v)l)t)a)hello( Pstring)readerG (resource:coreQvocabsQloaderQtestQaQa.factor( parse)stream 3 0 errorGG errorGG errorGG no) ord)error: 3 must)fail) ith = (count)me( set)global 0 3 0 0

(vocabs.loader.test.b( forget)vocab 3 ith)compilation)unit 3 unit)test 0 f 3 0 (vocabs.loader.test.b( vocab)files empty: 3 unit)test 0 3 0 0

(vocabs.loader.test.b( vocab)files 0 forget)source 3 each 3 ith)compilation)unit 3 unit)test 0 (vocabs.loader.test.b( require 3 must)fail 0 1 3 0 (count)me( get)global 3 unit)test 0 3 0 0 (bob( (vocabs.loader.test.b( create 0 3 define 3 ith)compilation)unit 3 unit)test 0 3 0 (vocabs.loader.test.b( refresh 3 unit)test 0 , 3 0 (count)me( get)global 3 unit)test 0 f 3 0 (fred( (vocabs.loader.test.b( lookup) ord undefined) ord: 3 unit)test 0 3 0 0 (vocabs.loader.test.b( vocab)files 0 forget)source 3 each 3 ith)compilation)unit 3 unit)test 0 3 0 (vocabs.loader.test.b( changed)vocab 3 unit)test 0 3 0 (vocabs.loader.test.b( refresh 3 unit)test 0 - 3 0 (count)me( get)global 3 unit)test 0 + (resource:coreQkernelQkernel.factor( 1 . 3 0 (kernel( Pvocab)linkG here 3 unit)test 0 + (resource:coreQkernelQkernel.factor( 1 . 3 0 (kernel( lookup)vocab here 3 unit)test 0 3 0 0

(vocabs.loader.test.c( forget)vocab (vocabs.loader.test.d( forget)vocab 3 ith)compilation)unit 3 unit)test 0 2done2 3 0 0 (vocabs.loader.test.d( require 3 0 :1 3 recover (vocabs.loader.test.d( lookup)vocab source)loaded:GG 3 unit)test : forget)Funk 5 )) 6 0 + (,( (a( (b( (d( (e( (f( . 0 (vocabs.loader.test.( prepend forget)vocab 3 each 3 ith)compilation)unit ! forget)Funk

0 + . 3 0 (IN: xabbabbFa( eval5 )) 6 (xabbabbFa( vocab)files 3 unit)test 0 (xabbabbFa( forget)vocab 3 forget)Funk 0 3 0 0 (vocabs.loader.test.e( forget)vocab 3 = (vocabs.loader.test.g( set)global 0 3 (vocabs.loader.test.f( forget)vocab (vocabs.loader.test.g( forget)vocab ith)compilation)unit ith)compilation)unit 3 unit)test ith)compilation)unit

0 3 0 (vocabs.loader.test.g( require 3 unit)test 0 1 3 0 (vocabs.loader.test.g( get)global 3 unit)test 0 3 (vocabs.loader.test.h( forget)vocab (vocabs.loader.test.i( forget)vocab ith)compilation)unit

0 3 0 (vocabs.loader.test.h( require 3 unit)test 0 3

(vocabs.loader.test.F( forget)vocab (vocabs.loader.test.k( forget)vocab ith)compilation)unit

0 3 0 0 (vocabs.loader.test.F( require 3 0 drop :1 3 recover 3 unit)test 0 0 0 0 0 3 0 0 0 0 3 f 3 t 0 3 0 3 (vocabs.loader.test.m( require 3 unit)test 0 (vocabs.loader.test.n( lookup)vocab 3 unit)test (vocabs.loader.test.o( require 3 unit)test 0 (vocabs.loader.test.n( lookup)vocab Gboolean 3 unit)test

(mno( 0 (vocabs.loader.test.( s ap suffix forget)vocab 3 each ith)compilation)unit 3 f 3 t 0 3 0 3 (vocabs.loader.test.o( require 3 unit)test 0 (vocabs.loader.test.n( lookup)vocab 3 unit)test (vocabs.loader.test.m( require 3 unit)test 0 (vocabs.loader.test.n( lookup)vocab Gboolean 3 unit)test

0 f 3 0 (vocabs.loader.test.p( lookup)vocab 3 unit)test 0 3 0 (vocabs.loader.test.p.private( require 3 unit)test 0 + (foo( . 3 0 (vocabs.loader.test.p( ords 0 nameGG 3 map 3 unit)test 0 (mnop( 0 (vocabs.loader.test.( s ap suffix forget)vocab 3 each 3 ith)compilation)unit USING: vocabs vocabs.loader.private help.markup help.syntax ords strings io ! IN: vocabs.loader "#$I%&': (add)vocab)roots( (Jorking ith code outside of the @actor source tree(

(Nou can ork ith code outside of the @actor source tree by adding additional directories to the list of vocabulary roots.( *nl ($here are three ays of doing this.( *nl ($he first ay is to use an environment variable. @actor looks at the ( + *snippet (@"%$B#[#BB$S( . ( environment variable for a list of ( + *snippet (:( . ()separated paths 5on Unix6 or a list of ( + *snippet (!( . ()separated paths 5on Jindo s6.( *nl ($he second ay is to create a configuration file. Nou can list additional vocabulary roots in a file that @actor reads at startup:( + *subsections (.factor)roots( . (@inally< you can add vocabulary roots by calling a ord from your ( + *snippet (.factor)rc( . ( file 5see ( + *link (.factor)rc( . (6:( + *subsections add)vocab)root . ! "#$I%&': (vocabs.roots( (Vocabulary roots( ($he vocabulary loader searches for vocabularies in one of the root directories:( + *subsections vocab)roots . ($he default set of roots includes the follo ing directories in the @actor source directory:( + *list + + *snippet (core( . ( ) essential system vocabularies such as ( + *vocab)link (parser( . ( and ( + *vocab)link (sequences( . (. $he vocabularies in this root constitute the boot image! see ( + *link (bootstrap.image( . (.( . + + *snippet (basis( . ( ) useful libraries and tools< such as ( + *vocab)link (compiler( . (< ( + *vocab)link (ui( . (< ( + *vocab)link (calendar( . (< and so on.( . + + *snippet (extra( . ( ) additional contributed libraries.( . + + *snippet ( ork( . ( ) a root for vocabularies hich are not intended to be contributed back to @actor.( . . (Nou can store your o n vocabularies in the ( + *snippet ( ork( . ( directory.( + *subsections (add)vocab)roots( . ! "#$I%&': (vocabs.icons( (Vocabulary icons( ("n icon file representing the vocabulary can be provided for use by ( + *link (tools.deploy( . (. If any of the follo ing files exist inside the vocabulary directory< they ill be used as icons hen the application is deployed.( + *list + + *snippet (icon.ico( . ( on Jindo s( . + + *snippet (icon.icns( . ( on IacBS M( . + + *snippet (icon.png( . ( on &inux and 4ESC( . . ! "#$I%&': (vocabs.loader( (Vocabulary loader( ($he ( + *link ;BS$;BN': US': . ( and ( + *link ;BS$;BN': USING: . ( ords load vocabularies using the vocabulary loader. $he vocabulary loader is implemented in the ( + *vocab)link (vocabs.loader( . ( vocabulary.( *nl ($he vocabulary loader searches for vocabularies in a set of directories kno n as vocabulary roots.( + *subsections (vocabs.roots( . (Vocabulary names map directly to source files inside these roots. " vocabulary named ( + *snippet (foo.bar( . ( is defined in ( + *snippet (fooQbarQbar.factor( . (! that is< a source file named ( + *snippet (bar.factor( . ( ithin a ( + *snippet (bar( . ( directory nested inside a ( + *snippet (foo( . ( directory of a vocabulary root. "ny level of nesting< separated by dots< is permitted.( *nl ($he vocabulary directory ) ( + *snippet (bar( . ( in our example ) contains a

source file:( + *list + + *snippet (fooQbarQbar.factor( . ( ) the source file must define ords in the ( + *snippet (foo.bar( . ( vocabulary ith an ( + *snippet (IN: foo.bar( . ( form( . . ($ o other @actor source files< storing documentation and tests< respectively< may optionally be placed alongside the source file:( + *list + + *snippet (fooQbarQbar)docs.factor( . ( ) documentation< see ( + *link ( riting)help( . . + + *snippet (fooQbarQbar)tests.factor( . ( ) unit tests< see ( + *link (tools.test( . . . (Bptional text files may contain metadata.( + *subsections (vocabs.metadata( (vocabs.icons( . (Vocabularies can also be loaded at run time< ithout altering the vocabulary search path. $his is done by calling a ord hich loads a vocabulary if it is not in the image< doing nothing if it is:( + *subsections require . ($he above ord ill only ever load a vocabulary once in a given session. Sometimes< t o vocabularies require special code to interact. $he follo ing ord is used to load one vocabulary hen another is present:( + *subsections require) hen . ($here is another ord hich unconditionally loads vocabulary from disk< regardless of hether or not is has already been loaded:( + *subsections reload . (@or interactive development in the listener< calling ( + *link reload . ( directly is usually not necessary< since a better facility exists for ( + *link (vocabs.refresh( . (.( *nl ("pplication vocabularies can define a main entry point< giving the user a convenient ay to run the application:( + *subsections ;BS$;BN': I"IN: run runnable)vocab . + *see)also (vocabularies( (parser( (source)files( . ! "EBU$: (vocabs.loader( ?'&;: load)vocab + *values + (name( (a string( . + (vocab( (a hashtable or ( + *link f . . . + *description ("ttempts to load a vocabulary from disk< or looks up the vocabulary in the dictionary< and then outputs that vocabulary obFect.( . ! ?'&;: vocab)main + *values + (vocab)spec( (a vocabulary specifier( . + (main( ord . . + *description (Butputs the main entry point for a vocabulary. $he entry point can be executed ith ( + *link run . ( and set ith ( + *link ;BS$;BN': I"IN: . (.( . ! ?'&;: vocab)roots + *var)description (" sequence of pathname strings to search for vocabularies.( . ! ?'&;: add)vocab)root + *values + (root( (a pathname string( . . + *description ("dds a directory pathname to the list of vocabulary roots.( . + *see)also (.factor)roots( . !

?'&;: find)vocab)root + *values + (vocab( (a vocabulary specifier( . + (pathQf( (a pathname string( . . + *description (Searches for a vocabulary in the vocabulary roots.( . ! ?'&;: no)vocab + *values + (name( (a vocabulary name( . . + *description ($hro s a ( + *link no)vocab . (.( . + *error)description ($hro n hen a ( + *link ;BS$;BN': US': . ( or ( + *link ;BS$;BN': USING: . ( form refers to a non)existent vocabulary.( . ! ?'&;: load)help: + *var)description (If set to a true value< documentation ill be automatically loaded hen vocabularies are loaded. $his variable is usually on< except hen @actor has been bootstrapped ithout the help system.( . ! ?'&;: load)source + *values + (vocab( (a vocabulary specifier( . . + *description (&oads a vocabulary7s source code.( . ! ?'&;: load)docs + *values + (vocab( (a vocabulary specifier( . . + *description (If ( + *link load)help: . ( is on< loads a vocabulary7s documentation.( . ! ?'&;: reload + *values + (name( (a vocabulary name( . . + *description (#eloads the source code and documentation for a vocabulary.( . + *errors ($hro s a ( + *link no)vocab . ( error if the vocabulary does not exist on disk.( . ! ?'&;: require) hen + *values + (if( (a sequence of vocabulary specifiers( . + (then( (a vocabulary specifier( . . + *description (&oads the ( + *snippet (then( . ( vocabulary if it is not loaded and all of the ( + *snippet (if( . ( vocabulary is. If some of the ( + *snippet (if( . ( vocabularies are not loaded no < but they are later< then the ( + *snippet (then( . ( vocabulary ill be loaded along ith the final one.( . + *notes ($his is used to express a Foint dependency of vocabularies. If vocabularies ( + *snippet (a( . ( and ( + *snippet (b( . ( use code in vocabulary ( + *snippet (c( . ( to interact< then the follo ing line< hich can be placed in ( + *snippet (a( . ( or ( + *snippet (b( . (< expresses the dependency.( + *code (+ >(a>( >(b>( . >(c>( require) hen( . . ! ?'&;: run + *values + (vocab( (a vocabulary specifier( . . + *description (#uns a vocabulary7s main entry point. $he main entry point is set ith the ( + *link ;BS$;BN': I"IN: . ( parsing ord.( . ! ?'&;: vocab)source)path + *values + (vocab( (a vocabulary specifier( . + (pathQf( (a pathname string or ( + *link f . . . + *description (Butputs a pathname here source code for ( + *snippet (vocab( . ( might be found. Butputs ( + *link f . ( if the vocabulary does not have a directory on disk.( . ! ?'&;: vocab)docs)path + *values + (vocab( (a vocabulary specifier( . + (pathQf( (a pathname string or ( + *link f . . . + *description (Butputs a pathname here the documentation for ( + *snippet (vocab( . ( might be found. Butputs ( + *link f . ( if the vocabulary does not

have a directory on disk.( . ! IN: vocabs.loader.test.p : foo 5 )) 6 ! IN: vocabs.loader.test.l US': kernel (Bops( thro IN: vocabs.loader.test.i US': vocabs.loader.test.h IN: vocabs.loader.test.c G'N'#I%: foo I: foo IN: vocabs.loader.test.d : foo 5 )) 6 iterate)next !US': vocabs.loader IN: vocabs.loader.test.m + (vocabs.loader.test.o( (vocabs.loader.test.m( . (vocabs.loader.test.n( require) hen IN: vocabs.loader.test.n IN: vocabs.loader.test.o USING: namespaces ! IN: vocabs.loader.test.b PP global 0 (count)me( inc 3 ith)variables GG

: fred bob !IN: vocabs.loader.test.g USING: vocabs.loader.test.f namespaces ! 0 (vocabs.loader.test.g( inc 3 IN: vocabs.laoder.test.f US': vocabs (vocabs.loader.test.g( require 1 , IN: vocabs.loader.test.k US': vocabs.loader.test.F USING: namespaces parser ! IN: vocabs.loader.test.a PP global 0 (count)me( inc 3 : v)l)t)a)hello 5 )) a 6 / ! : byebye 5 )) a 6 v)l)t)a)hello ! 0 this is an error US': vocabs.loader.test.i IN: vocabs.loader.test.F (vocabs.loader.test.k( require K %opyright 5%6 ,==R< ,=1= 'duardo %ava8os< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs continuations definitions init io io.files io.pathnames kernel make namespaces parser sequences sets splitting strings vocabs ords ! IN: vocabs.loader SNIEB&: vocab)roots SNIEB&: add)vocab)root)hook 0 ith)variables GG ith)global

V+ (resource:core( (resource:basis( (resource:extra( (resource: ork( . clone vocab)roots set)global 0 drop 3 add)vocab)root)hook set)global 3 (vocabs.loader( add)startup)hook : add)vocab)root 5 root )) 6 trim)tail)separators 0 vocab)roots get adFoin 3 0 add)vocab)root)hook get)global call5 root )) 6 3 bi ! SNIEB&: root)cache root)cache 0 ?+ . clone 3 initiali8e '##B#: not)found)in)roots path ! P;#IV"$' : find)root)for 5 path )) pathQf 6 vocab)roots get 0 prepend)path exists: 3 ith find nip !

I: string vocab)path 5 string )) pathQf 6 dup find)root)for 0 prepend)path 3 0 not)found)in)roots 3 if4 ! ;#IV"$'G : vocab)dir 5 vocab )) dir 6 vocab)name ?+ + %?"#: . %?"#: Q . . substitute ! : append)vocab)dir 5 vocab strQf )) path 6 0 vocab)name (.( split 3 dip 0 0 dup last 3 dip append suffix 3 hen4 (Q( Foin ! : find)vocab)root 5 vocab )) pathQf 6 vocab)name root)cache get 0 dup (.private( tail: 0 drop f 3 0 (.factor( append)vocab)dir find)root)for 3 if 3 cache ! : vocab)append)path 5 vocab path )) ne path 6 s ap find)vocab)root dup 0 prepend)path 3 0 ,drop f 3 if ! : vocab)source)path 5 vocab )) pathQf 6 dup (.factor( append)vocab)dir vocab)append)path ! : vocab)docs)path 5 vocab )) pathQf 6 dup ()docs.factor( append)vocab)dir vocab)append)path ! SNIEB&: load)help: K Cefined by vocabs.metadata SNIEB&: check)vocab)hook check)vocab)hook 0 0 drop 3 3 initiali8e P;#IV"$'

SNIEB&: require) hen)vocabs require) hen)vocabs 0 ?S+ . clone 3 initiali8e SNIEB&: require) hen)table require) hen)table 0 V+ . clone 3 initiali8e : load)conditional)requires 5 vocab )) 6 vocab)name require) hen)vocabs get in: 0 require) hen)table get 0 0 0 lookup)vocab dup 0 source)loaded:GG 2done2 H 3 0 require 3 curry hen 3 assoc)each 3 hen ! : load)source 5 vocab )) 6 dup check)vocab)hook get call5 vocab )) 6 0 2parsing2 GGsource)loaded: dup vocab)source)path 0 parse)file 3 0 0 3 3 if4 0 2parsing2 GGsource)loaded: 3 dip 0 W 3 0 call5 )) 6 3 if)bootstrapping 2done2 GGsource)loaded: load)conditional)requires 3 0 3 0 f GGsource)loaded: 3 cleanup ! : load)docs 5 vocab )) 6 load)help: get 0 0 2parsing2 GGdocs)loaded: dup vocab)docs)path 0 :run)file 3 2done2 GGdocs)loaded: 3 0 3 0 f GGdocs)loaded: 3 cleanup 3 hen drop ! ;#IV"$'G : require) hen 5 if then )) 6 over 0 lookup)vocab 3 all: 0 require drop 3 0 0 drop require) hen)vocabs get adFoin)all 3 0 ,array require) hen)table get push 3 ,bi 3 if ! : reload 5 name )) 6 dup lookup)vocab 0 0 load)source 3 0 load)docs 3 bi 3 0 require 3 :if ! : run 5 vocab )) 6 dup load)vocab vocab)main 0 execute5 )) 6 3 0 ($he ( rite vocab)name rite ( vocabulary does not define an entry point.( print ($o define one< refer to >> I"IN: help( print 3 :if ! SNIEB&: blacklist P;#IV"$'

hen 3 all: 3 dip

hen4

: add)to)blacklist 5 error vocab )) 6 vocab)name blacklist get dup 0 set)at 3 0 -drop 3 if ! G'N'#I%: 5require6 5 name )) 6 I: vocab 5require6 0 dup source)loaded:GG 2parsing2 eq: 0 drop 3 0 dup source)loaded:GG 0 dup load)source 3 unless dup docs)loaded:GG 0 dup load)docs 3 unless drop 3 if 3 0 0 s ap add)to)blacklist 3 keep rethro 3 recover ! I: vocab)link 5require6 vocab)name 5require6 ! I: string 5require6 create)vocab 5require6 ! ;#IV"$'G 0 dup vocab)name blacklist get at4 0 rethro 3 0 drop dup find)vocab)root 0 5require6 3 0 dup lookup)vocab 0 drop 3 0 no)vocab 3 if 3 if 3 if 3 require)hook set)global I: vocab)spec here vocab)source)path dup 0 1 ,array 3 hen !

K put here to avoid circularity bet een vocabs.loader and source)files.errors + (source)files.errors( (debugger( . (source)files.errors.debugger( require) hen K %opyright 5%6 ,==R< ,==U 'duardo %ava8os< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs definitions kernel namespaces sequences sorting splitting strings ! IN: vocabs SNIEB&: dictionary $U;&': vocab P identity)tuple name ords main help source)loaded: docs)loaded: ! K sources)loaded: slot is one of these three SNIEB&: 2parsing2 SNIEB&: 2running2 SNIEB&: 2done2 : PvocabG 5 name )) vocab 6 > vocab ne s ap GGname ?+ . clone GG ords ! '##B#: bad)vocab)name name !

: check)vocab)name 5 name )) name 6 dup string: 0 bad)vocab)name 3 unless dup 0 (:Q>> ( member: 3 any: 0 bad)vocab)name 3 $U;&': vocab)link name ! %: Pvocab)linkG vocab)link UNIBN: vocab)spec vocab vocab)link ! G'N'#I%: vocab)name 5 vocab)spec )) name 6 I: vocab vocab)name nameGG ! I: vocab)link vocab)name nameGG ! I: obFect vocab)name check)vocab)name ! : vocab)name4 5 vocab)spec )) name 6 vocab)name (.private( :tail drop ! : private)vocab: 5 vocab )) : 6 vocab)name (.private( tail: ! G'N'#I%: lookup)vocab 5 vocab)spec )) vocab 6 I: vocab lookup)vocab !

hen !

I: obFect lookup)vocab 5 name )) vocab 6 vocab)name dictionary get at ! G'N'#I%: vocab) ords 5 vocab)spec )) I: vocab vocab) ords ordsGG ! ords 6

I: obFect vocab) ords lookup)vocab vocab) ords ! I: f vocab) ords ! G'N'#I%: vocab)help 5 vocab)spec )) help 6 I: vocab vocab)help helpGG ! I: obFect vocab)help lookup)vocab vocab)help ! I: f vocab)help ! G'N'#I%: vocab)main 5 vocab)spec )) main 6 I: vocab vocab)main mainGG ! I: obFect vocab)main lookup)vocab vocab)main ! I: f vocab)main ! SNIEB&: vocab)observers G'N'#I%: vocab)changed 5 vocab obF )) 6 : add)vocab)observer 5 obF )) 6 vocab)observers get push ! : remove)vocab)observer 5 obF )) 6

vocab)observers get remove)eqK drop ! : notify)vocab)observers 5 vocab )) 6 vocab)observers get 0 vocab)changed 3 ith each !

: create)vocab 5 name )) vocab 6 check)vocab)name dictionary get 0 PvocabG dup notify)vocab)observers 3 cache ! '##B#: no)vocab name ! : vocabs 5 )) seq 6 dictionary get keys natural)sort ! : ords 5 vocab )) seq 6 vocab) ords values ! ords 3 map concat !

: all) ords 5 )) seq 6 dictionary get values 0 :

ords)named 5 str )) seq 6 dictionary get values 0 vocab) ords at 3 ith map sift !

: child)vocab: 5 prefix name )) : 6 ,dup H pick empty: or 0 ,drop t 3 0 s ap %?"#: . suffix head: 3 if ! : child)vocabs 5 vocab )) seq 6 vocab)name vocabs 0 child)vocab: 3 G'N'#I%: Gvocab)link 5 name )) vocab 6 I: vocab)spec Gvocab)link ! I: obFect Gvocab)link dup lookup)vocab 0 3 0 Pvocab)linkG 3 :if ! : forget)vocab 5 vocab )) 6 0 ords forget)all 3 0 vocab)name dictionary get delete)at 3 0 notify)vocab)observers 3 tri ! I: vocab)spec forget4 forget)vocab ! SNIEB&: require)hook ;#'CI%"$': runnable)vocab P vocab vocab)main Gboolean ! INS$"N%': vocab)spec definition)mixin : call)require)hook 5 name )) 6 require)hook get call5 name )) 6 ! G'N'#I%: require 5 obFect )) 6 I: vocab require nameGG require ! I: vocab)link require nameGG require ! K Jhen calling (foo.private( require< load (foo( instead< but only hen K (foo.private( does not exist. $he reason for this is that stage1 bootstrap ith filter !

K starts out ith some .private vocabs that contain primitives< and K loading the public vocabs ould cause circularity issues. I: string require 5 vocab )) 6 dup (.private( :tail 0 over lookup)vocab 0 ,drop 3 0 nip call)require)hook 3 if 3 0 nip call)require)hook 3 if ! : load)vocab 5 name )) vocab 6 0 require 3 0 lookup)vocab 3 bi ! IN: vocabs.parser.tests USING: vocabs.parser tools.test eval kernel accessors definitions compiler.units ords vocabs ! 0 (@#BI: kernel HG doesnotexist !( eval5 )) 6 3 0 errorGG $+ no) ord)in)vocab + ord (doesnotexist( . + vocab (kernel( . . H 3 must)fail) ith 0 (#'N"I': doesnotexist kernel HG ne name( eval5 )) 6 3 0 errorGG $+ no) ord)in)vocab + ord (doesnotexist( . + vocab (kernel( . . H 3 must)fail) ith : aaa 5 )) 6 ! 0 0 3 0 (aaa( (vocabs.parser.tests( (uutt( add)renamed) ord 3 unit)test 0 3 0 (vocabs.parser.tests( dup add)qualified 3 unit)test 0 aaa 3 0 (uutt( search 3 unit)test 0 aaa 3 0 (vocabs.parser.tests:aaa( search 3 unit)test 0 3 0 0 (bbb( (vocabs.parser.tests( create drop 3 unit)test ith)compilation)unit 3

0 (bbb( 3 0 (vocabs.parser.tests:bbb( search nameGG 3 unit)test 0 3 0 0 > aaa forget 3 ith)compilation)unit 3 unit)test

0 3 0 0 (bbb( (vocabs.parser.tests( lookup) ord forget 3 ith)compilation)unit 3 unit)test 0 f 3 0 (uutt( search 3 unit)test 0 f 3 0 (vocabs.parser.tests:aaa( search 3 unit)test 0 3 0 (vocabs.parser.tests.foo( set)current)vocab 3 unit)test 0 3 0 0 (bbb( current)vocab create drop 3 0 t 3 0 (bbb( search Gboolean 3 unit)test 0 3 0 0 (vocabs.parser.tests.foo( forget)vocab 3 unit)test 0 0 (bbb( current)vocab create drop 3 no)current)vocab)error: 3 must)fail) ith ith)compilation)unit 3 ith)compilation)unit 3 unit)test

ith)compilation)unit 3 0 errorGG

0 begin)private 3 0 errorGG no)current)vocab)error: 3 must)fail) ith 0 end)private 3 0 errorGG no)current)vocab)error: 3 must)fail) ith 0 f 3 0 (bbb( search Gboolean 3 unit)test 3 ith)manifest USING: help.markup help.syntax parser strings IN: vocabs.parser ords assocs vocabs !

"#$I%&': ( ord)search)errors( (Jord lookup errors( (If the parser cannot not find a ord in the current vocabulary search path< it attempts to look for the ord in all loaded vocabularies.( *nl (If ( + *link auto)use: . ( mode is off< a restartable error is thro n ith a restart for each vocabulary in question< together ith a restart hich defers the ord in the current vocabulary< as if ( + *link ;BS$;BN': C'@'#: . ( as used.( *nl (If ( + *link auto)use: . ( mode is on and only one vocabulary has a ord ith this name< the vocabulary is added to the search path and parsing continues.( *nl (If any restarts ere invoked< or if ( + *link auto)use: . ( is on< the parser ill print the correct ( + *link ;BS$;BN': USING: . ( after parsing completes. $his form can be copy and pasted back into the source file.( + *subsections auto)use: . ! "#$I%&': ( ord)search)syntax( (Syntax to control ord lookup( (;arsing ords hich make all ords in a vocabulary available:( + *subsections ;BS$;BN': US': ;BS$;BN': USING: ;BS$;BN': DU"&I@I'C: ;BS$;BN': DU"&I@I'C)JI$?: . (;arsing ords hich make a subset of all ords in a vocabulary available:( + *subsections ;BS$;BN': @#BI: ;BS$;BN': 'M%&UC': ;BS$;BN': #'N"I': . (#emoving vocabularies from the search path:( + *subsections ;BS$;BN': UNUS': . (In the listener< the ( + *vocab)link (scratchpad( . ( is the default vocabulary for ne ord definitions. In source files< there is no default vocabulary. Cefining ords before declaring a vocabulary ith ( + *link ;BS$;BN': IN: . ( results in an error.( + *subsections ;BS$;BN': IN: . ! "#$I%&': ( ord)search)semantics( (#esolution of ambiguous ord names( ($here is a distinction bet een parsing ords hich perform ]open^ imports versus ]closed^ imports. "n open import introduces all ords from a vocabulary as identifiers< except possibly a finite set of exclusions. $he ( + *link ;BS$;BN': US': . (< ( + *link ;BS$;BN': USING: . ( and ( + *link ;BS$;BN': 'M%&UC': . ( ords perform open imports. " closed import only adds a fixed set of identifiers. $he ( + *link ;BS$;BN': @#BI: . (< ( + *link ;BS$;BN': #'N"I': . (< ( + *link ;BS$;BN': DU"&I@I'C: . ( and ( + *link ;BS$;BN': DU"&I@I'C)JI$?: . ( ords perform closed imports. Note that the latter t o are considered as closed imports< due to the fact that all identifiers they introduce are unambiguously qualified ith a prefix. $he ( + *link ;BS$;BN': IN: . ( parsing ord also performs a closed import of the ne ly)created vocabulary.( *nl

(Jhen the parser encounters a reference to a ord< it first searches the closed imports< in order. %losed imports are searched from the most recent to least recent. If the ord could not be found this ay< it searches open imports. Unlike closed imports< ith open imports< the order does not matter )) instead< if more than one vocabulary defines a ord ith this name< an error is thro n.( + *subsections ambiguous)use)error . ($o resolve the error< add a closed import< using ( + *link ;BS$;BN': @#BI: . (< ( + *link ;BS$;BN': DU"&I@I'C: . ( or ( + *link ;BS$;BN': DU"&I@I'C)JI$?: . (. $he closed import ill then take precedence over the open imports< and the ambiguity ill be resolved.( *nl ($he rationale for this behavior is as follo s. Bpen imports are named such because they are open to future extension! if a future version of a vocabulary that you use adds ne ords< those ne ords ill no be in scope in your source file< too. $o avoid problems< any references to the ne ord have to be resolved since the parser cannot safely determine hich vocabulary as meant. $his problem can be avoided entirely by using only closed imports< but this leads to additional verbosity.( *nl (In practice< a small set of guidelines helps avoid name clashes:( + *list (Yeep vocabularies small( + (?ide internal ords using ( + *link ;BS$;BN': P;#IV"$' . . + (Iake good use of ( + *link ;BS$;BN': @#BI: . (< ( + *link ;BS$;BN': DU"&I@I'C: . ( or ( + *link ;BS$;BN': DU"&I@I'C)JI$?: . . . ! "#$I%&': ( ord)search)private( (;rivate ords( (Jords hich only serve as implementation detail should be defined in a private code block. Jords in a private code blocks get defined in a vocabulary hose name is the name of the current vocabulary suffixed ith ( + *snippet (.private( . (. ;rivacy is not enforced by the system! private ords can be called from other vocabularies< and from the listener. ?o ever< this should be avoided here possible.( + *subsections ;BS$;BN': P;#IV"$' ;BS$;BN': ;#IV"$'G . ! "#$I%&': ( ord)search( (;arse)time ord lookup( (Jhen the parser reads a ord name< it resolves the ord at parse)time< looking up the ( + *link ord . ( instance in the right vocabulary and adding it to the parse tree.( *nl (Initially< only ords from the ( + *vocab)link (syntax( . ( vocabulary are available in source files. Since most files ill use ords in other vocabularies< they ill need to make those ords available using a set of parsing ords.( + *subsections ( ord)search)syntax( ( ord)search)private( ( ord)search)semantics( ( ord)search)errors( . + *see)also ( ords( . ! "#$I%&': ( ord)search)parsing( (#eflection support for vocabulary search path( ($he parsing ords described in ( + *link ( ord)search)syntax( . ( are implemented using the belo ords< hich you can also call from your o n parsing ords.( *nl ($he current state used for ord search is stored in a ( + *emphasis

(manifest( . (:( + *subsections manifest . (Jords for orking ith the current manifest:( + *subsections use)vocab unuse)vocab add)qualified add) ords)from add) ords)excluding . (Jords used to implement ( + *link ;BS$;BN': IN: . (:( + *subsections current)vocab set)current)vocab . (Jords used to implement ( + *link ( ord)search)private( . (:( + *subsections begin)private end)private . ! "EBU$: ( ord)search( ?'&;: manifest + *var)description ($he current manifest. Bnly set at parse time.( . + *class)description ('ncapsulates the current vocabulary< as ell as the vocabulary search path.( . ! ?'&;: PmanifestG + *values + (manifest( manifest . . + *description (%reates a ne manifest.( . ! ?'&;: set)current)vocab + *values + (name( string . . + *description (Sets the current vocabulary here ne ords ill be defined< creating the vocabulary first if it does not exist.( . + *notes ($his ord is used to implement ( + *link ;BS$;BN': IN: . (.( . ! ?'&;: no)current)vocab + *error)description ($hro n hen a ne ord is defined in a source file that does not have an ( + *link ;BS$;BN': IN: . ( form.( . ! ?'&;: current)vocab + *values + (vocab( vocab . . + *description (#eturns the current vocabulary< here ne ords ill be defined.( . + *errors ($hro s an error if the current vocabulary has not been set.( . ! ?'&;: begin)private + *description (Eegins a block of private ord definitions. ;rivate ord definitions are placed in the current vocabulary name< suffixed ith ( + *snippet (.private( . (.( . + *notes ($his ord is used to implement ( + *link ;BS$;BN': P;#IV"$' . (.( . ! ?'&;: end)private + *description ('nds a block of private ord definitions.( . + *notes ($his ord is used to implement ( + *link ;BS$;BN': ;#IV"$'G . (.( . ! ?'&;: use)vocab + *values + (vocab( (a vocabulary specifier( . . + *description ("dds a vocabulary to the current manifest.( . + *notes ($his ord is used to implement ( + *link ;BS$;BN': US': . (.( . !

?'&;: unuse)vocab + *values + (vocab( (a vocabulary specifier( . . + *description (#emoves a vocabulary from the current manifest.( . + *notes ($his ord is used to implement ( + *link ;BS$;BN': UNUS': . (.( . ! ?'&;: add)qualified + *values + (vocab( (a vocabulary specifier( . + (prefix( string . . + *description ("dds the vocabulary7s ords< prefixed ith the given string< to the current manifest.( . + *notes (If adding the vocabulary introduces ambiguity< the vocabulary ill take precedence hen resolving any ambiguous names. See the example in ( + *link ;BS$;BN': DU"&I@I'C: . ( for further explanation.( . ! ?'&;: add) ords)from + *values + (vocab( (a names( . . + *description ("dds ( the current manifest.( + *notes ($his ord is vocabulary specifier( . + ( ords( (a sequence of ord

+ *snippet ( ords( . ( from ( + *snippet (vocab( . ( to . used to implement ( + *link ;BS$;BN': @#BI: . (.( . !

?'&;: add) ords)excluding + *values + (vocab( (a vocabulary specifier( . + ( ords( (a sequence of ord names( . . + *description ("dds all ords except for ( + *snippet ( ords( . ( from ( + *snippet (vocab( . ( to the manifest.( . + *notes ($his ord is used to implement ( + *link ;BS$;BN': 'M%&UC': . (.( . ! ?'&;: add)renamed) ord + *values + ( ord( string . string . . + *description (Imports ( + but renamed to ( + *snippet + *notes ($his ord is used + (vocab( (a vocabulary specifier( . + (ne )name( *snippet ( ord( . ( from ( + *snippet (vocab( . (< (ne )name( . (.( . to implement ( + *link ;BS$;BN': #'N"I': . (.( . !

?'&;: use) ords + *values + (assoc( assoc . . + *description ("dds an assoc mapping ord names to ords to the current manifest.( . + *notes ($his ord is used by ( + *link (locals( . ( to implement lexically)scoped names.( . ! ?'&;: unuse) ords + *values + (assoc( assoc . . + *description (#emoves an assoc mapping ord names to ords from the current manifest.( . + *notes ($his ord is used by ( + *link (locals( . ( to implement lexically)scoped names.( . ! ?'&;: ambiguous)use)error + *error)description ($hro n hen a ord name referenced in source file is available in more than one vocabulary in the manifest. Such cases must be explicitly disambiguated using ( + *link ;BS$;BN': @#BI: . (< ( + *link ;BS$;BN': 'M%&UC': . (< ( + *link ;BS$;BN': DU"&I@I'C: . (< or ( + *link ;BS$;BN': DU"&I@I'C)JI$?: . (.( . ! ?'&;: search)manifest + *values + (name( string . + (manifest( manifest . + ( ordQf( + *maybe ord . . . + *description (Searches for a ord by name in the given manifest. If no such ord could be found< outputs ( + *link f . (.( . !

?'&;: search + *values + (name( string . + ( ordQf( + *maybe ord . . . + *description (Searches for a ord by name in the current manifest. If no such ord could be found< outputs ( + *link f . (.( . *parsing)note ! K %opyright 5%6 ,==R< ,=1= Caniel 'hrenberg< Eruno Ceferrari< K Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs combinators compiler.units continuations hash)sets hashtables kernel math namespaces parser.notes sequences sets sorting splitting vectors vocabs ords ! IN: vocabs.parser '##B#: no) ord)error name ! : ord)restarts 5 possibilities )) restarts 6 natural)sort 0 0 vocabularyGG (Use the ( ( vocabulary( surround 3 keep 3 + . mapGassoc ! ord)restarts) ith)defer 5 name possibilities )) restarts 6 ord)restarts s ap (Cefer ord in current vocabulary( s ap ,array suffix !

: Pno) ord)errorG 5 name possibilities )) error restarts 6 0 drop > no) ord)error boa 3 0 ord)restarts) ith)defer 3 ,bi ! $U;&': manifest current)vocab + search)vocab)names hash)set . + search)vocabs vector . + qualified)vocabs vector . + auto)used vector . ! : PmanifestG 5 )) manifest 6 manifest ne ?S+ . clone GGsearch)vocab)names V+ . clone GGsearch)vocabs V+ . clone GGqualified)vocabs V+ . clone GGauto)used ! I: manifest clone call)next)method 0 clone 3 change)search)vocab)names 0 clone 3 change)search)vocabs 0 clone 3 change)qualified)vocabs 0 clone 3 change)auto)used ! $U;&': extra) ords ords ! ordsGG 3 bi9 eq: 3 0 ,drop f 3 if !

I: extra) ords equal: over extra) ords: 0 0

%: Pextra) ordsG extra) ords '##B#: no) ord)in)vocab P;#IV"$' : 5add)qualified6 5 qualified )) 6 manifest get qualified)vocabsGG push ! ord vocab !

: 5from6 5 vocab ords )) vocab ,dup s ap load)vocab !

ords

ords7 vocab 6

: extract) ords 5 seq vocab )) assoc 6 0 ordsGG extract)keys dup 3 0 nameGG 3 bi 0 s ap 0 ,drop 3 0 no) ord)in)vocab 3 if 3 curry assoc)each ! : excluding) ords 5 seq vocab )) assoc 6 0 nip ordsGG 3 0 extract) ords 3 ,bi assoc)diff ! : qualified) ords 5 prefix vocab )) assoc 6 ordsGG s ap 0 s ap 0 s ap (:( glue 3 dip 3 curry assoc)map ! : 5lookup6 5 name assoc )) ordQf 6 at4 0 dup for ard)reference: 0 drop f 3 hen 3 hen !

: 5use) ords6 5 assoc )) extra) ords seq 6 Pextra) ordsG manifest get qualified)vocabsGG ! ;#IV"$'G : set)current)vocab 5 name )) 6 create)vocab 0 manifest get current)vocabPP 3 0 5add)qualified6 3 bi ! : ith)current)vocab 5 name quot )) 6 manifest get clone manifest 0 0 set)current)vocab 3 dip call 3 ith)variable ! inline

$U;&': no)current)vocab)error ! : no)current)vocab 5 )) vocab 6 > no)current)vocab)error boa + + (Cefine ords in scratchpad vocabulary( (scratchpad( . . thro )restarts dup set)current)vocab ! : current)vocab 5 )) vocab 6 manifest get current)vocabGG 0 no)current)vocab 3 unless4 ! : begin)private 5 )) 6 current)vocab nameGG (.private( :tail 0 drop 3 0 (.private( append set)current)vocab 3 if ! : end)private 5 )) 6 current)vocab nameGG (.private( :tail 0 set)current)vocab 3 0 drop 3 if ! : using)vocab: 5 vocab )) : 6 vocab)name manifest get search)vocab)namesGG in: ! : use)vocab 5 vocab )) 6 dup using)vocab: 0 vocab)name ("lready using __( (77 vocabulary( surround note. 3 0 manifest get 0 0 load)vocab 3 dip search)vocabsGG push 3 0 0 vocab)name 3 dip search)vocab)namesGG adFoin 3 ,bi 3 if ! : auto)use)vocab 5 vocab )) 6

0 use)vocab 3 0 manifest get auto)usedGG push 3 bi ! : auto)used: 5 )) : 6 manifest get auto)usedGG length = G ! : unuse)vocab 5 vocab )) 6 dup using)vocab: 0 manifest get 0 0 load)vocab 3 dip search)vocabsGG remove)eqK drop 3 0 0 vocab)name 3 dip search)vocab)namesGG delete 3 ,bi 3 0 drop 3 if ! $U;&': qualified vocab prefix ords !

: PqualifiedG 5 vocab prefix )) qualified 6 5from6 qualified) ords qualified boa ! : add)qualified 5 vocab prefix )) 6 PqualifiedG 5add)qualified6 ! $U;&': from vocab names ords !

: PfromG 5 vocab ords )) from 6 5from6 extract) ords from boa ! : add) ords)from 5 vocab ords )) 6 PfromG 5add)qualified6 ! $U;&': exclude vocab names ords !

: PexcludeG 5 vocab ords )) from 6 5from6 excluding) ords exclude boa ! : add) ords)excluding 5 vocab ords )) 6 PexcludeG 5add)qualified6 ! $U;&': rename ord vocab ords !

: PrenameG 5 ord vocab ne )name )) rename 6 0 ,dup load)vocab ordsGG dupd at 0 3 0 s ap no) ord)in)vocab 3 :if 3 dip associate rename boa ! : add)renamed) ord 5 ord vocab ne )name )) 6 PrenameG 5add)qualified6 ! : use) ords 5 assoc )) 6 5use) ords6 push ! : unuse) ords 5 assoc )) 6 5use) ords6 removeK drop ! $U;&': ambiguous)use)error ords !

: Pambiguous)use)errorG 5 ords )) error restarts 6 0 > ambiguous)use)error boa 3 0 ord)restarts 3 bi ! P;#IV"$' : 5vocab)search6 5 name assocs )) 0 ordsGG 5lookup6 3 ith map sift dup length ! : vocab)search 5 name manifest )) search)vocabsGG ords n 6

ordQf 6

5vocab)search6 + + = 0 drop f 3 . + 1 0 first 3 . 0 drop Pambiguous)use)errorG thro )restarts dup 0 vocabularyGG 3 0 nameGG 1array 3 bi add) ords)from 3 . case ! : qualified)search 5 name manifest )) ordQf 6 qualified)vocabsGG 5vocab)search6 = H 0 drop f 3 0 last 3 if ! ;#IV"$'G : search)manifest 5 name manifest )) ordQf 6 ,dup qualified)search dup 0 ,nip 3 0 drop vocab)search 3 if ! : search 5 name )) ordQf 6 manifest get search)manifest ! P;#IV"$' G'N'#I%: update 5 search)path)elt )) valid: 6 : trim)forgotten 5 qualified)vocab )) valid: 6 0 0 nip (forgotten( ord)prop not 3 assoc)filter 3 change) ords ordsGG assoc)empty: not ! I: I: I: I: from update trim)forgotten ! rename update trim)forgotten ! extra) ords update trim)forgotten ! exclude update trim)forgotten !

I: qualified update dup vocabGG lookup)vocab 0 dup 0 prefixGG 3 0 vocabGG load)vocab 3 bi qualified) ords GG ords 3 0 drop f 3 if ! I: vocab update dup nameGG lookup)vocab eq: ! : update)manifest 5 manifest )) 6 0 dup 0 nameGG lookup)vocab 3 hen 3 change)current)vocab 0 members 0 lookup)vocab 3 filter dup fast)set 3 change)search)vocab)names s ap 0 lookup)vocab 3 V+ . map)as GGsearch)vocabs qualified)vocabsGG 0 update 3 filterK drop ! I: manifest definitions)changed nip update)manifest ! ;#IV"$'G : ith)manifest 5 quot )) 6 PmanifestG manifest 0 0 call 3 0 0 manifest get add)definition)observer call 3 0 manifest get remove)definition)observer 3 0 3 cleanup 3 if)bootstrapping 3 ith)variable ! inline

K %opyright 5%6 ,==-< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: arrays assocs hashtables kernel kernel.private math sequences vectors ! S&B$: boxes S&B$: value @#BI: accessors HG boxesGG valueGG valuePP ! IN: namespaces P;#IV"$' $U;&': global)hashtable + boxes hashtable read)only . ! $U;&': global)box value ! : 5box)at6 5 key globals )) box 6 boxesGG ,dup at 0 ,nip 3 0 0 f global)box boa 3 ,dip 0 set)at 3 ,curry keep 3 if4 ! foldable : box)at 5 key globals )) box 6 5box)at6 + global)box . declare ! inline I: global)hashtable at4 boxesGG at4 0 + global)box . declare valueGG dup 3 0 drop f f 3 if ! inline I: global)hashtable set)at box)at valuePP ! inline I: global)hashtable delete)at box)at f s ap valuePP ! inline : namestack4 5 )) namestack 6 %BN$'M$)BEX)N"I'S$"%Y context)obFect + vector . declare ! inline : Gn 5 namespace )) 6 namestack4 push ! : ndrop 5 )) 6 namestack4 pop4 ! ;#IV"$'G : global 5 )) g 6 BEX)G&BE"& special)obFect + global)hashtable . declare ! foldable : namespace 5 )) namespace 6 namestack4 last ! inline : namestack 5 )) namestack 6 namestack4 clone ! : set)namestack 5 namestack )) 6 Gvector %BN$'M$)BEX)N"I'S$"%Y set)context)obFect ! : init)namespaces 5 )) 6 global 1array set)namestack ! : get 5 variable )) value 6 namestack4 assoc)stack ! inline : set 5 value variable )) 6 namespace set)at ! : on 5 variable )) 6 t s ap set ! inline : off 5 variable )) 6 f s ap set ! inline : is)global 5 variable )) : 6 global boxesGG key: ! inline : get)global 5 variable )) value 6 global box)at valueGG ! inline : set)global 5 value variable )) 6 global set)at ! inline : change 5 variable quot )) 6 0 0 get 3 keep 3 dip dip set ! inline : change)global 5 variable quot )) 6 0 0 get)global 3 keep 3 dip dip set)global ! inline : toggle 5 variable )) 6 0 not 3 change ! inline : 29 5 n variable )) 6 0 = or 2 3 change ! inline : inc 5 variable )) 6 1 s ap 29 ! inline : dec 5 variable )) 6 )1 s ap 29 ! inline

: ith)variables 5 ns quot )) 6 s ap Gn call ndrop ! inline : counter 5 variable )) n 6 0 = or 1 2 dup 3 change)global ! inline : make)assoc 5 quot exemplar )) hash 6 ,= s ap ne )assoc 0 s ap ith)variables 3 keep ! inline : ith)scope 5 quot )) 6 A PhashtableG s ap ith)variables ! inline : ith)variable 5 value key quot )) 6 0 associate 3 dip ith)variables ! inline : ith)global 5 quot )) 6 0 global 3 dip ith)variables ! inline : initiali8e 5 variable quot )) 6 0 unless4 3 curry change)global ! inline USING: assocs compiler.tree.debugger kernel namespaces tools.test ords ! IN: namespaces.tests ?+ . clone (test)namespace( set : test)namespace 5 )) : 6 ?+ . clone dup 0 namespace H 3 0 t 3 0 test)namespace 3 unit)test 1= (some)global( set 0 f 3 0 ?+ . clone 0 f (some)global( set (some)global( get 3 unit)test SNIEB&: test)initiali8e f test)initiali8e set)global test)initiali8e 0 1 3 initiali8e test)initiali8e 0 , 3 initiali8e 0 1 3 0 test)initiali8e get)global 3 unit)test f test)initiali8e set)global test)initiali8e 0 A 3 initiali8e 0 A 3 0 test)initiali8e get)global 3 unit)test SNIEB&: 0 f 3 0 0 t 3 0 0 f 3 0 toggle)test toggle)test get 3 unit)test toggle)test 0 toggle 3 0 get 3 bi 3 unit)test toggle)test 0 toggle 3 0 get 3 bi 3 unit)test ith)variables !

ith)variables 3

0 t 3 0 toggle)test 0 on 3 0 get 3 bi 3 unit)test 0 f 3 0 toggle)test 0 off 3 0 get 3 bi 3 unit)test 0 t 3 0 0 test)initiali8e get)global 3 + at4 set)at . inlined: 3 unit)test 0 t 3 0 0 test)initiali8e set)global 3 + at4 set)at . inlined: 3 unit)test USING: help.markup help.syntax kernel kernel.private sequences ords namespaces.private quotations vectors math.parser math ords.symbol assocs ! IN: namespaces "#$I%&': (namespaces)combinators( (Namespace combinators( + *subsections make)assoc ith)scope ith)variable ith)variables . ! "#$I%&': (namespaces)change( (%hanging variable values(

+ *subsections on off inc dec change change)global toggle . ! "#$I%&': (namespaces)global( (Global variables( + *subsections namespace global get)global set)global initiali8e ith)global . ! "#$I%&': (namespaces.private( (Namespace implementation details( ($he namestack holds namespaces.( + *subsections namestack set)namestack namespace . (" pair of ords push and pop namespaces on the namestack.( + *subsections Gn ndrop . ! "#$I%&': (namespaces( (Cynamic variables( ($he ( + *vocab)link (namespaces( . ( vocabulary implements dynamically)scoped variables.( *nl (" dynamic variable is an entry in an assoc of bindings< here the assoc is implicit rather than passed on the stack. $hese assocs are termed ( + *emphasis (namespaces( . (. Nesting of scopes is implemented ith a search order on namespaces< defined by a ( + *emphasis (namestack( . (. Since namespaces are Fust assocs< any obFect can be used as a variable. Ey convention< variables are keyed by ( + *link ( ords.symbol( . (.( *nl ($he ( + *link get . ( and ( + *link set . ( ords read and rite variable values. $he ( + *link get . ( ord searches the chain of nested namespaces< hile ( + *link set . ( al ays sets variable values in the current namespace only. Namespaces are dynamically scoped! hen a quotation is called from a nested scope< any ords called by the quotation also execute in that scope.( + *subsections get set . (Various utility ords provide common variable access patterns:( + *subsections (namespaces)change( (namespaces)combinators( . (Implementation details your code probably does not care about:( + *subsections (namespaces.private( . (Cynamic variables complement ( + *link (locals( . (.( !

"EBU$: (namespaces( ?'&;: get + *values + (variable( (a variable< by convention a symbol( . + (value( (the value< or ( + *link f . . . + *description (Searches the name stack for a namespace containing the variable< and outputs the associated value. If no such namespace is found< outputs ( + *link f . (.( . ! ?'&;: set + *values + (value( (the ne value( . + (variable( (a variable< by convention a symbol( . . + *description ("ssigns a value to the variable in the namespace at the top of the name stack.( . + *side)effects (variable( . ! ?'&;: off + *values + (variable( (a variable< by convention a symbol( . . + *description ("ssigns a value of ( + *link f . ( to the variable.( . + *side)effects (variable( . ! ?'&;: on + *values + (variable( (a variable< by convention a symbol( . . + *description ("ssigns a value of ( + *link t . ( to the variable.( . + *side)effects (variable( . ! ?'&;: change + *values + (variable( (a variable< by convention a symbol( . + (quot( + *quotation (5 old )) ne 6( . . . + *description ("pplies the quotation to the old value of the variable< and assigns the resulting value to the variable.( . + *side)effects (variable( . ! ?'&;: change)global + *values + (variable( (a variable< by convention a symbol( . + (quot( + *quotation (5 old )) ne 6( . . . + *description ("pplies the quotation to the old value of the global variable< and assigns the resulting value to the global variable.( . + *side)effects (variable( . ! ?'&;: toggle + *values + (variable( (a variable< by convention a symbol( . . + *description (%hanges the boolean value of a variable to its opposite.( . ! ?'&;: ith)global + *values + (quot( quotation . . + *description (#uns the quotation in the global namespace.( . ! ?'&;: 29 + *values + (n( (a number( . + (variable( (a variable< by convention a symbol( . . + *description ("dds ( + *snippet (n( . ( to the value of the variable. " variable value of ( + *link f . ( is interpreted as being 8ero.( . + *side)effects (variable( . + *examples + *example (USING: namespaces prettyprint !( (IN: scratchpad( (SNIEB&: foo>n1 foo 29>n1= foo 29>nfoo get .( (11( . . !

?'&;: inc + *values + (variable( (a variable< by convention a symbol( . . + *description (Increments the value of the variable by 1. " variable value of ( + *link f . ( is interpreted as being 8ero.( . + *side)effects (variable( . ! ?'&;: dec + *values + (variable( (a variable< by convention a symbol( . . + *description (Cecrements the value of the variable by 1. " variable value of ( + *link f . ( is interpreted as being 8ero.( . + *side)effects (variable( . ! ?'&;: counter + *values + (variable( (a variable< by convention a symbol( . + (n( integer . . + *description (Increments the value of the variable by 1< and returns its ne value.( . + *notes ($his ord is useful for generating 5some hat6 unique identifiers. @or example< the ( + *link gensym . ( ord uses it.( . + *side)effects (variable( . ! ?'&;: ith)scope + *values + (quot( quotation . . + *description (%alls the quotation in a ne namespace. "ny variables set by the quotation are discarded hen it returns.( . + *examples + *example (USING: math namespaces prettyprint !( (IN: scratchpad( (SNIEB&: x( (= x set( (0 x 0 A 2 3 change x get . 3 ith)scope x get .( (A>n=( . . ! ?'&;: ith)variable + *values + (value( obFect . + (key( (a variable< by convention a symbol( . + (quot( quotation . . + *description (%alls the quotation in a ne namespace here ( + *snippet (key( . ( is set to ( + *snippet (value( . (.( . + *examples ($he follo ing t o phrases are equivalent:( + *code (0 - x set foo 3 ith)scope( . + *code (- x 0 foo 3 ith)variable( . . ! ?'&;: make)assoc + *values + (quot( quotation . + (exemplar( assoc . + (hash( (a ne assoc( . . + *description (%alls the quotation in a ne namespace of the same type as ( + *snippet (exemplar( . (< and outputs this namespace hen the quotation returns. Useful for quickly building assocs.( . ! ?'&;: ith)variables + *values + (ns( assoc . + (quot( quotation . . + *description (%alls the quotation in the dynamic scope of ( + *snippet (ns( . (. Jhen variables are looked up by the quotation< ( + *snippet (ns( . ( is checked first< and setting variables in the quotation stores them in ( + *snippet (ns( . (.( . ! ?'&;: namespace + *values + (namespace( assoc . . + *description (Butputs the current namespace. %alls to ( + *link set . ( modify this namespace.( . ! ?'&;: global + *values + (g( assoc . . + *description (Butputs the global namespace. $he global namespace is al ays checked last hen looking up variable values.( . !

?'&;: get)global + *values + (variable( (a variable< by convention a symbol( . + (value( (the value( . . + *description (Butputs the value of a variable in the global namespace.( . ! ?'&;: set)global + *values + (value( (the ne value( . + (variable( (a variable< by convention a symbol( . . + *description ("ssigns a value to the variable in the global namespace.( . + *side)effects (variable( . ! ?'&;: namestack4 + *values + (namestack( (a vector of assocs( . . + *description (Butputs the current name stack.( . ! ?'&;: namestack + *values + (namestack( (a vector of assocs( . . + *description (Butputs a copy of the current name stack.( . ! ?'&;: set)namestack + *values + (namestack( (a vector of assocs( . . + *description (#eplaces the name stack ith a copy of the given vector.( . ! ?'&;: Gn + *values + (namespace( assoc . . + *description (;ushes a namespace on the name stack.( . ! ?'&;: ndrop + *description (;ops a namespace from the name stack.( . ! ?'&;: init)namespaces + *description (#esets the name stack to its initial state< holding a single copy of the global namespace.( . *lo )level)note ! ?'&;: initiali8e + *values + (variable( symbol . + (quot( quotation . . + *description (If ( + *snippet (variable( . ( does not have a value in the global namespace< calls ( + *snippet (quot( . ( and assigns the result to ( + *snippet (variable( . ( in the global namespace.( . ! K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs definitions hashtables kernel kernel.private math math.order namespaces quotations sequences slots.private strings vocabs ! @#BI: assocs HG change)at ! IN: ords EUI&$IN: ord + hashcode fixnum initial: = . name vocabulary + def quotation initial: 0 3 . props pic)def pic)tail)def + sub)primitive read)only . ! K Need a dummy ord here because EUI&$IN: ord is not a real ord K and parse)datum looks for things that are actually ords instead of K also looking for classes : ord 5 )) 4 6 (dummy ord( thro ! SNIEB&: last) ord)symbol : last) ord 5 )) ord 6 > last) ord)symbol get)global !

: set)last) ord 5 I: I: I: I: I: :

ord )) 6 > last) ord)symbol set)global !

ord execute 5execute6 ! ord :execute execute5 )) value 6 ! inline ord PHG 0 0 nameGG 3 0 vocabularyGG 3 bi ,array 3 compare ! ord definer drop > : > ! ! ord definition defGG ! ord)prop 5 ord name )) value 6 s ap propsGG at ! ord name )) 6 s ap propsGG delete)at !

: remove) ord)prop 5

: set) ord)prop 5 ord value name )) 6 over 0 pick propsGG :set)at GGprops drop 3 0 nip remove) ord)prop 3 if ! : change) ord)prop 5 ..a ord prop quot: 5 ..a value )) ..b ne value 6 )) ..b 6 0 s ap propsGG 3 dip change)at ! inline : reset)props 5 P;#IV"$' : caller 5 callstack )) ;#IV"$'G $U;&': undefined) ord ord ! : undefined 5 )) 4 6 callstack caller > undefined) ord boa thro : undefined)def 5 )) quot 6 ZK 7f7 inhibits tail call optimi8ation in non)optimi8ing ZK compiler< ensuring that e can pull out the caller ord ZK above. 0 undefined f 3 ! ;#'CI%"$': deferred P ord defGG undefined)def H ! I: deferred definer drop > C'@'#: f ! I: deferred definition drop f ! ;#'CI%"$': primitive P ord (primitive( ord)prop ! I: primitive definer drop > ;#III$IV': f ! I: primitive definition drop f ! : lookup) ord 5 name vocab )) ord 6 vocab) ords at ! ! ord 6 callstackGarray PreversedG third ! ord seq )) 6 0 remove) ord)prop 3 ith each !

: target) ord 5 ord )) target 6 0 nameGG 3 0 vocabularyGG 3 bi lookup) ord ! SNIEB&: bootstrapping: : if)bootstrapping 5 true false )) 6 0 bootstrapping: get 3 ,dip if ! inline : bootstrap) ord 5 ord )) target 6

0 target) ord 3 0 3 if)bootstrapping ! G'N'#I%: crossref: 5 I: ord crossref: dup (forgotten( ord )) : 6 ord)prop 0 drop f 3 0 vocabularyGG Gboolean 3 if ! ord )) seq 6

G'N'#I%: sub ords 5 I:

ord sub ords drop f ! ord )) ordQf 6

G'N'#I%: parent) ord 5 I:

ord parent) ord drop f !

: define 5 ord def )) 6 over changed)definition 0 3 like GGdef drop ! : changed)effect 5 ord )) 6 0 changed)effects get add)to)unit 3 0 dup primitive: 0 drop 3 0 changed)definition 3 if 3 bi ! : set)stack)effect 5 effect ord )) 6 ,dup (declared)effect( ord)prop H 0 ,drop 3 0 0 nip changed)effect 3 0 nip sub ords 0 changed)effect 3 each 3 0 s ap (declared)effect( set) ord)prop 3 ,tri 3 if ! : define)declared 5 ord def effect )) 6 0 nip s ap set)stack)effect 3 0 drop define 3 -bi ! : make)deprecated 5 ord )) 6 t (deprecated( set) ord)prop ! : inline: 5 obF )) : 6 dup ord: 0 (inline( ord)prop 3 0 drop f 3 if ! inline ord)prop 3 0 drop f 3 if ! inline

: recursive: 5 obF )) : 6 dup ord: 0 (recursive(

: inline)recursive: 5 obF )) : 6 dup ord: 0 dup (inline( ord)prop 0 (recursive( ord)prop 3 0 drop f 3 if 3 0 drop f 3 if ! inline '##B#: cannot)be)inline G'N'#I%: make)inline 5 I: ord ! ord )) 6

ord make)inline dup inline: 0 drop 3 0 0 t (inline( set) ord)prop 3 0 changed)effect 3 bi 3 if !

: define)inline 5 ord def effect )) 6 0 define)declared 3 0 ,drop make)inline 3 -bi !

: make)recursive 5 ord )) 6 t (recursive( set) ord)prop ! G'N'#I%: flushable: 5 I: ord )) : 6

ord flushable: 0 (flushable( ord)prop 3 0 parent) ord dup 0 flushable: 3

hen 3 bi or !

: make)flushable 5 ord )) 6 t (flushable( set) ord)prop ! G'N'#I%: foldable: 5 I: ord )) : 6

ord foldable: 0 (foldable( ord)prop 3 0 parent) ord dup 0 foldable: 3

hen 3 bi or !

: make)foldable 5 ord )) 6 dup make)flushable t (foldable( set) ord)prop ! G'N'#I%: reset) ord 5 I: ord )) 6

ord reset) ord dup flushable: 0 dup changed)conditionally 3 hen + (unannotated)def( (parsing( (inline( (recursive( (foldable( (flushable( (reading( ( riting( (reader( ( riter( (delimiter( (deprecated( . reset)props !

: reset)generic 5 ord )) 6 0 sub ords forget)all 3 0 reset) ord 3 0 f GGpic)def f GGpic)tail)def + (methods( (combination( (default)method( (engines( (decision)tree( . reset)props 3 tri ! : P ordG 5 name vocab )) ord 6 ,dup = hash)combine hash)combine Gfixnum 5 ord6 dup ne ) ord ! : Puninterned) ordG 5 name )) ord 6 f > Puninterned) ordG counter Gfixnum 5 ord6 ne ) ords get 0 dup ne ) ord 3 hen ! : gensym 5 )) ord 6 (5 gensym 6( Puninterned) ordG ! : define)temp 5 quot effect )) ord 6 0 gensym dup 3 ,dip define)declared ! : reveal 5 ord )) 6 dup 0 nameGG 3 0 vocabularyGG 3 bi dup vocab) ords 0 3 0 no)vocab 3 :if

set)at ! '##B#: bad)create name vocab ! : check)create 5 name vocab )) name vocab 6 ,dup 0 string: 3 0 0 string: 3 0 vocab: 3 bi or 3 bi4 and 0 bad)create 3 unless ! : create 5 name vocab )) ord 6 check)create ,dup lookup) ord dup 0 ,nip 3 0 drop vocab)name P ordG dup reveal dup changed)definition 3 if ! : constructor) ord 5 name vocab )) ord 6 0 (P( (G( surround 3 dip create ! ;#'CI%"$': parsing) ord P ord (parsing( ord)prop !

I: parsing) ord definer drop > SNN$"M: > ! ! : define)syntax 5 ord quot )) 6 0 drop 3 0 define 3 ,bi t (parsing( set) ord)prop ! : delimiter: 5 obF )) : 6 dup ord: 0 (delimiter( : deprecated: 5 obF )) : 6 dup ord: 0 (deprecated( ord)prop 3 0 drop f 3 if ! ord)prop 3 0 drop f 3 if !

K Cefinition protocol I: ord here (loc( ord)prop ! I: I: ord set) here s ap (loc( set) ord)prop ! ord forget4 dup (forgotten( ord)prop 0 drop 3 0 0 sub ords forget)all 3 0 0 nameGG 3 0 vocabularyGG vocab) ords 3 bi delete)at 3 0 t (forgotten( set) ord)prop 3 tri 3 if ! ord hashcode4 nip 1 slot + fixnum . declare ! inline foldable ord literali8e P rapperG ! ords compiler.units !

I: I:

INS$"N%': ord definition)mixin USING: help.syntax help.markup ords.symbol IN: ords.symbol

?'&;: symbol + *description ($he class of symbols created by ( + *link ;BS$;BN': SNIEB&: . (.( . ! ?'&;: define)symbol + *values + ( ord( ord . . + *description (Cefines the

ord to push itself on the stack

hen executed. $his

is the run time equivalent of ( + *link ;BS$;BN': SNIEB&: . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects ( ord( . ! "#$I%&': ( ords.symbol( (Symbols( (" symbol pushes itself on the stack hen executed. Ey convention< symbols are used as variable names 5( + *link (namespaces( . (6.( + *subsections symbol symbol: . (Cefining symbols at parse time:( + *subsections ;BS$;BN': SNIEB&: ;BS$;BN': SNIEB&S: . (Cefining symbols at run time:( + *subsections define)symbol . (Symbols are Fust compound definitions in disguise. $he follo ing t o lines are equivalent:( + *code (SNIEB&: foo( (: foo 5 )) value 6 >> foo !( . ! "EBU$: ( ords.symbol( K %opyright 5%6 ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors definitions kernel sequences ords ! IN: ords.symbol ;#'CI%"$': symbol P ord 0 defGG 3 0 0 3 curry 3 bi sequenceH ! I: symbol definer drop > SNIEB&: f ! I: symbol definition drop f ! : define)symbol 5 ord )) 6 dup 0 3 curry 5 )) value 6 define)inline ! USING: arrays generic assocs kernel math namespaces sequences tools.test ords definitions parser quotations vocabs continuations classes.tuple compiler.units io.streams.string accessors eval ords.symbol grouping ! IN: ords.tests 0 / 3 0 0 (poo( ( ords.tests( create 0 , , 2 3 5 )) n 6 define)declared 3 ith)compilation)unit (poo( ( ords.tests( lookup) ord execute 3 unit)test 0 t 3 0 t vocabs 0 C'@'#: plist)test 0 t 3 0 > plist)test t (sample)property( set) ord)prop > plist)test (sample)property( ord)prop 3 unit)test ords 0 ord: and 3 each 3 each 3 unit)test

0 f 3 0 > plist)test f (sample)property( set) ord)prop > plist)test (sample)property( ord)prop 3 unit)test 0 3 0 0 (create)test( (scratchpad( create + 1 , . (testing( set) ord)prop 3 ith)compilation)unit 3 unit)test 0 + 1 , . 3 0 (create)test( (scratchpad( lookup) ord (testing( 3 unit)test 0 ord)prop

0 t 3 0 > array: (array:( (arrays( lookup) ord H 3 unit)test ith)compilation)unit 3

0 3 0 0 (test)scope( (scratchpad( create drop 3 unit)test 3 ith)scope 0 (test)scope( 3 0 (test)scope( (scratchpad( lookup) ord nameGG 3 unit)test

0 t 3 0 vocabs array: 3 unit)test 0 t 3 0 vocabs 0 ords 0 ord: 3 all: 3 all: 3 unit)test 0 f 3 0 gensym gensym H 3 unit)test SNIEB&: a)symbol 0 t 3 0 > a)symbol symbol: 3 unit)test K See if redefining a generic as a colon def clears some K ord props. G'N'#I%: testing 5 a )) b 6 (IN: ords.tests : testing 5 )) 6 !( eval5 )) 6 0 f 3 0 > testing generic: 3 unit)test : forgotten 5 )) 6 ! : another)forgotten 5 )) 6 ! @B#G'$: forgotten @B#G'$: another)forgotten : another)forgotten 5 )) 6 ! K Iake sure that undefined ords thro proper errors C'@'#: deferred 0 deferred 3 0 $+ undefined) ord f deferred . H 3 must)fail) ith 0 (IN: ords.tests C'@'#: not)compiled PP not)compiled GG( eval5 )) 6 3 0 errorGG 0 undefined) ord: 3 0 ordGG nameGG (not)compiled( H 3 bi and 3 must)fail) ith 0 3 0 (IN: ords.tests @B#G'$: not)compiled( eval5 )) 6 3 unit)test

0 3 0 0 (no)loc( ( ords.tests( create drop 3 ith)compilation)unit 3 unit)test 0 f 3 0 (no)loc( ( ords.tests( lookup) ord here 3 unit)test 0 3 0 (IN: ords.tests : no)loc), 5 )) 6 !( eval5 )) 6 3 unit)test 0 f 3 0 (no)loc),( ( ords.tests( lookup) ord here 3 unit)test

0 3 0 (IN: ords.tests : test)last 5 )) 6 !( eval5 )) 6 3 unit)test 0 (test)last( 3 0 last) ord nameGG 3 unit)test (undef)test( ( ords.tests( lookup) ord 0 0 forget 3 ith)compilation)unit 3 hen4 0 (IN: ords.tests : undef)test 5 )) 6 ! PP undef)test GG( eval5 )) 6 3 0 errorGG undefined) ord: 3 must)fail) ith 0 3 0 (IN: ords.tests G'N'#I%: symbol)generic 5 )) 6( eval5 )) 6 3 unit)test 0 3 0 (IN: ords.tests SNIEB&: symbol)generic( eval5 )) 6 3 unit)test 0 t 3 0 (symbol)generic( ( ords.tests( lookup) ord symbol: 3 unit)test 0 f 3 0 (symbol)generic( ( ords.tests( lookup) ord generic: 3 unit)test 0 3 0 (IN: ords.tests G'N'#I%: symbol)generic 5 a )) b 6( Pstring)readerG (symbol)generic)test( parse)stream drop 3 unit)test 0 3 0 (IN: ords.tests $U;&': symbol)generic !( Pstring)readerG (symbol)generic)test( parse)stream drop 3 unit)test 0 t 3 0 (symbol)generic( ( ords.tests( lookup) ord symbol: 3 unit)test 0 f 3 0 (symbol)generic( ( ords.tests( lookup) ord generic: 3 unit)test K #egressions 0 3 0 (IN: ords.tests : decl)forget)test 5 )) 6 unit)test 0 t 3 0 (decl)forget)test( ( ords.tests( lookup) unit)test 0 3 0 (IN: ords.tests : decl)forget)test 5 )) 6 0 f 3 0 (decl)forget)test( ( ords.tests( lookup) unit)test 0 3 0 (IN: ords.tests : decl)forget)test 5 )) 6 unit)test 0 t 3 0 (decl)forget)test( ( ords.tests( lookup) unit)test 0 3 0 (IN: ords.tests : decl)forget)test 5 )) 6 0 f 3 0 (decl)forget)test( ( ords.tests( lookup) unit)test ! foldable( eval5 )) 6 3 ord (foldable( ord)prop 3

!( eval5 )) 6 3 unit)test ord (foldable( ord)prop 3 ! flushable( eval5 )) 6 3 ord (flushable( ord)prop 3

!( eval5 )) 6 3 unit)test ord (flushable( ord)prop 3

0 + . 3 0 all) ords 0 0 (effect)dependencies( ord)prop 3 0 (definition)dependencies( ord)prop 3 0 (conditional)dependencies( ord)prop 3 tri -append 0 (forgotten( ord)prop 3 filter 3 map harvest 3 unit)test

0 (hi( ord)code 3 must)fail USING: definitions help.markup help.syntax kernel parser kernel.private vocabs classes quotations strings effects compiler.units ! IN: ords "#$I%&': (interned) ords( (&ooking up and creating ords( (" ord is said to be ( + *emphasis (interned( . ( if it is a member of the vocabulary named by its vocabulary slot. Bther ise< the ord is ( + *emphasis (uninterned( . (.( *nl (Jords hose names are kno n at parse time )) that is< most ords making up your program )) can be referenced in source code by stating their name. ?o ever< the parser itself< and sometimes code you rite< ill need to create look up ords dynamically.( *nl (;arsing ords add definitions to the current vocabulary. Jhen a source file is being parsed< the current vocabulary is initially set to ( + *vocab)link (scratchpad( . (. $he current vocabulary may be changed ith the ( + *link ;BS$;BN': IN: . ( parsing ord 5see ( + *link ( ord)search( . (6.( + *subsections create create)in lookup) ord . ! "#$I%&': (uninterned) ords( (Uninterned ords( (" ord that is not a member of any vocabulary is said to be ( + *emphasis (uninterned( . (.( *nl ($here are several ays of creating an uninterned ord:( + *subsections P ordG Puninterned) ordG gensym define)temp . ! "#$I%&': (colon)definition( (%olon definitions( ("ll ords have associated definition ( + *link (quotations( . (. " ord7s definition quotation is called hen the ord is executed. " ( + *emphasis (colon definition( . ( is a ord here this quotation is supplied directly by the user. $his is the simplest and most common type of ord definition.( *nl (Cefining ords at parse time:( + *subsections ;BS$;BN': : ;BS$;BN': ! . (Cefining ords at run time:( + *subsections define define)declared define)inline . (Jord definitions must declare their stack effect. See ( + *link (effects( . (.( *nl ("ll other types of ord definitions< such as ( + *link ( ords.symbol( . ( and ( + *link (generic( . (< are Fust special cases of the above.( ! "#$I%&': (primitives( (;rimitives( (;rimitives are ords defined in the @actor VI. $hey provide the essential

lo )level services to the rest of the system.( + *subsections primitive primitive: . ! "#$I%&': (deferred( (Ceferred ords and mutual recursion( (Jords cannot be referenced before they are defined! that is< source files must order definitions in a strictly bottom)up fashion. $his is done to simplify the implementation< facilitate better parse time checking and remove some odd corner cases! it also encourages better coding style.( *nl (Sometimes this restriction gets in the ay< for example hen defining mutually)recursive ords! one ay to get around this limitation is to make a for ard definition.( + *subsections ;BS$;BN': C'@'#: . ($he class of deferred ord definitions:( + *subsections deferred deferred: . (Ceferred ords thro an error hen called:( + *subsections undefined . (Ceferred ords are Fust compound definitions in disguise. $he follo ing t o lines are equivalent:( + *code (C'@'#: foo( (: foo 5 )) 4 6 undefined !( . ! "#$I%&': (declarations( (%ompiler declarations( (%ompiler declarations are parsing ords that set a ord property in the most recently defined ord. $hey appear after the final ( + *link ;BS$;BN': ! . ( of a ord definition:( + *code (: cubed 5 x )) y 6 dup dup 4 4 ! foldable( . (%ompiler declarations assert that the ord follo s a certain contract< enabling certain optimi8ations that are not valid in general.( + *subsections ;BS$;BN': inline ;BS$;BN': foldable ;BS$;BN': flushable ;BS$;BN': recursive . (It is entirely up to the programmer to ensure that the ord satisfies the contract of a declaration. @urthermore< if a generic ord is declared ( + *link ;BS$;BN': foldable . ( or ( + *link ;BS$;BN': flushable . (< all methods must satisfy the contract. Unspecified behavior may result if a ord does not follo the contract of one of its declarations.( + *see)also (effects( . ! "#$I%&': ( ord)props( (Jord properties( ('ach ord has a hashtable of properties.( + *subsections ord)prop set) ord)prop . ($he stack effect of the above t o ords is designed so that it is most convenient hen ( + *snippet (name( . ( is a literal pushed on the stack right before executing this ord.( *nl ($he follo ing are some of the properties used by the library:( + *table

+ (;roperty( (Cocumentation( . + + *snippet (>(parsing>(( . + *link (parsing) ords( . . + + + *snippet (>(inline>(( . (< ( + *snippet (>(foldable>(( . (< ( + *snippet (flushable( . . + *link (declarations( . . + + *snippet (>(loc>(( . + (&ocation information ) ( + *link here . . .

+ + + *snippet (>(methods>(( . (< ( + *snippet (>(combination>(( . . + (Set on generic ords ) ( + *link (generic( . . . + + + *snippet (>(reading>(( . (< ( + *snippet (>( riting>(( . . + (Set on slot accessor ords ) ( + *link (slots( . . . + + *snippet (>(declared)effect>(( . + *link (effects( . . + + + *snippet (>(help>(( . (< ( + *snippet (>(help)loc>(( . (< ( + *snippet (>(help)parent>(( . . + (Jhere ord help is stored ) ( + *link ( riting)help( . . . + + *snippet (>(speciali8er>(( . + *link (hints( . . + + *snippet (>(predicating>(( . ( Set on class predicates< stores the corresponding class ord( . . (;roperties hich are defined for classes only:( + *table + (;roperty( (Cocumentation( . + + *snippet (>(class>(( . + (" boolean indicating hether this ord is a class ) ( + *link (classes( . . . + + *snippet (>(coercer>(( . + (" quotation for converting the top of the stack to an instance of this class( . . + + *snippet (>(constructor>(( . + *link (tuple)constructors( . . + + *snippet (>(type>(( . + *link (builtin)classes( . . + + + *snippet (>(superclass>(( . (< ( + *snippet (>(predicate)definition>(( . . + *link (predicates( . . + + *snippet (>(members>(( . + *link (unions( . . + + *snippet (>(slots>(( . + *link (slots( . . + + *snippet (>(predicate>(( . + (" quotation that tests if the top of the stack is an instance of this class ) ( + *link (class)predicates( . . . . ! "#$I%&': ( ord.private( (Jord implementation details( ($he ( + *snippet (def( . ( slot of a ord holds a ( + *link quotation . ( instance that is called hen the ord is executed.( *nl (" primitive to get the memory range storing the machine code for a ord:( + *subsections ord)code . ! "#$I%&': ( ords.introspection( (Jord introspection( (Jord introspection facilities and implementation details are found in the ( + *vocab)link ( ords( . ( vocabulary.( *nl (Jord obFects contain several slots:( + *table

+ + *snippet (name( . (a ord name( . + + *snippet (vocabulary( . (a ord vocabulary name( . + + *snippet (def( . (a definition quotation( . + + *snippet (props( . (an assoc of ord properties< including documentation and other meta)data( . . (Jords are instances of a class.( + *subsections ord ord: . (Jords implement the definition protocol! see ( + *link (definitions( . (.( + *subsections (interned) ords( (uninterned) ords( ( ord)props( ( ord.private( . ! "#$I%&': ( ords( (Jords( (Jords are the @actor equivalent of functions or procedures in other languages. Jords are essentially named ( + *link (quotations( . (.( *nl ($here are t o ays of creating ord definitions:( + *list (using parsing ords at parse time.( (using defining ords at run time.( . ($he latter is a more dynamic feature that can be used to implement code generation and such< and in fact parse time defining ords are implemented in terms of run time defining ords.( *nl ($ypes of ords:( + *subsections (colon)definition( ( ords.symbol( ( ords.alias( ( ords.constant( (primitives( . ("dvanced topics:( + *subsections (deferred( (declarations( ( ords.introspection( . + *see)also (vocabularies( (vocabs.loader( (definitions( (see( . ! "EBU$: ( ords( ?'&;: deferred + *class)description ($he class of deferred C'@'#: . (.( . ! + deferred ;BS$;BN': C'@'#: . related) ords ?'&;: undefined + *error)description ($his error is thro n in t o cases< and the debugger7s summary message reflects the cause:( + *list + (" ord as executed before being compiled. @or example< this can happen if a macro is defined in the same compilation unit here it as used. See ords created by ( + *link ;BS$;BN':

( + *link (compilation)units( . ( for a discussion.( . + (" ord defined ith ( + *link ;BS$;BN': C'@'#: . ( as executed. Since this syntax is usually used for mutually)recursive ord definitions< executing a deferred ord usually indicates a programmer mistake.( . . . ! ?'&;: primitive + *description ($he class of primitive ords.( . !

?'&;: ord)prop + *values + ( ord( ord . + (name( (a property name( . + (value( (a property value( . . + *description (#etrieves a ord property. Jord property names are conventionally strings.( . ! ?'&;: set) ord)prop + *values + ( ord( ord . + (value( (a property value( . + (name( (a property name( . . + *description (Stores a ord property. Jord property names are conventionally strings.( . + *side)effects ( ord( . ! ?'&;: remove) ord)prop + *values + ( ord( ord . + (name( (a property name( . . + *description (#emoves a ord property< so future lookups ill output ( + *link f . ( until it is set again. Jord property names are conventionally strings.( . + *side)effects ( ord( . ! ?'&;: ord)code + *values + ( ord( ord . + (start( (the ord7s start address( . + (end( (the ord7s end address( . . + *description (Butputs the memory range containing the ord7s machine code.( . ! ?'&;: define + *values + ( ord( ord . + (def( quotation . . + *description (Cefines the ord to call a quotation hen executed. $his is the run time equivalent of ( + *link ;BS$;BN': : . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects ( ord( . ! ?'&;: reset)props + *values + ( ord( ord . + (seq( (a sequence of ord property names( . . + *description (#emoves all listed ord properties from the ord.( . + *side)effects ( ord( . ! ?'&;: reset) ord + *values + ( ord( ord . . + *description (#eset ord declarations.( . *lo )level)note + *side)effects ( ord( . ! ?'&;: reset)generic + *values + ( ord( ord . . + *description (#eset ord declarations and generic *lo )level)note + *side)effects ( ord( . !

ord properties.( .

?'&;: P ordG + *values + (name( string . + (vocab( string . + ( ord(

ord . .

+ *description ("llocates a ord ith the specified name and vocabulary. User code should call ( + *link Puninterned) ordG . ( to create uninterned ords and ( + *link create . ( to create interned ords< instead of calling this constructor directly.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . ! ?'&;: Puninterned) ordG + *values + (name( string . + ( ord( ord . . + *description (%reates an uninterned ord ith the specified name< that is not equal to any other ord in the system.( . + *notes (Unlike ( + *link create . (< this ord does not have to be called from inside ( + *link ith)compilation)unit . (.( . ! ?'&;: gensym + *values + ( ord( ord . . + *description (%reates an uninterned ord that is not equal to any other ord in the system.( . + *examples + *example (USING: prettyprint ords !( (gensym .( (5 gensym 6( . . + *notes (Unlike ( + *link create . (< this ord does not have to be called from inside ( + *link ith)compilation)unit . (.( . ! ?'&;: bootstrapping: + *var)description (Set by the library hile bootstrap is in progress. Some parsing ords need to behave differently during bootstrap.( . ! ?'&;: last) ord + *values + ( ord( ord . . + *description (Butputs the most recently defined ord.( . + *class)description ($he class of ords. Bne notable subclass is ( + *link class . (< the class of class ords.( . ! + last) ord set)last) ord save)location . related) ords ?'&;: set)last) ord + *values + ( ord( ord . . + *description (Sets the recently defined

ord.( . !

?'&;: lookup) ord + *values + (name( string . + (vocab( string . + ( ord( + *maybe ord . . . + *description (&ooks up a ord in the dictionary. If the vocabulary or the is not defined< outputs ( + *link f . (.( . !

ord

?'&;: reveal + *values + ( ord( ord . . + *description ("dds a ne ly)created ord to the dictionary. Usually this ord does not need to be called directly< and is only called as part of ( + *link create . (.( . ! ?'&;: check)create + *values + (name( string . + (vocab( string . . + *description ($hro s a ( + *link check)create . ( error if ( + *snippet (name( . ( or ( + *snippet (vocab( . ( is not a string.( . + *error)description ($hro n if ( + *link create . ( is called ith invalid parameters.( . ! ?'&;: create + *values + (name( string . + (vocab( string . + ( ord( ord . .

+ *description (%reates a ne ord. If the vocabulary already contains a ord ith the requested name< outputs the existing ord. $he vocabulary must exist already! if it does not< you must call ( + *link create)vocab . ( first.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (. ;arsing ords should call ( + *link create)in . ( instead of this ord.( . ! ?'&;: constructor) ord + *values + (name( string . + (vocab( string . + ( ord( ord . . + *description (%reates a ne ord< surrounding ( + *snippet (name( . ( in angle brackets.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *examples + *example (USING: compiler.units prettyprint ords !( (0 >(salmon>( >(scratchpad>( constructor) ord 3 ith)compilation)unit .( (PsalmonG( . . ! + ;BS$;BN': @B#G'$: forget forget4 forget)vocab . related) ords ?'&;: target) ord + *values + ( ord( ord . + (target( ord . . + *description (&ooks up a ord ith the same name and vocabulary as the given ord. Used during bootstrap to transfer host ords to the target dictionary.( . ! ?'&;: bootstrap) ord + *values + ( ord( ord . + (target( ord . . + *description (&ooks up a ord ith the same name and vocabulary as the given ord< performing a transformation to handle parsing ords in the target dictionary. Used during bootstrap to transfer host ords to the target dictionary.( . ! ?'&;: parsing) ord: + *values + (obFect( obFect . + (:( (a boolean( . . + *description ($ests if an obFect is a parsing ord declared by ( + *link ;BS$;BN': SNN$"M: . (.( . + *notes (Butputs ( + *link f . ( if the obFect is not a ord.( . ! ?'&;: define)declared + *values + ( ord( ord . + (def( quotation . + (effect( effect . . + *description (Cefines a ord and declares its stack effect.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects ( ord( . ! ?'&;: define)temp + *values + (quot( quotation . + (effect( effect . + + *description (%reates an uninterned ord that ill ( hen executed.( . + *notes ($he follo ing phrases are equivalent:( + *code (0 , , 2 . 3 call( . + *code (0 , , 2 . 3 5 )) 6 define)temp execute( ($his ord must be called from inside ( + *link . ! ( ord( ord . . call ( + *snippet (quot( .

. ith)compilation)unit . (.(

?'&;: delimiter: + *values + (obF( obFect . + (:( (a boolean( . . + *description ($ests if an obFect is a delimiter ord declared by ( + *link ;BS$;BN': delimiter . (.( . + *notes (Butputs ( + *link f . ( if the obFect is not a ord.( . ! ?'&;: deprecated: + *values + (obF( obFect . + (:( (a boolean( . .

+ *description ($ests if an obFect is ( + *link ;BS$;BN': deprecated . (.( . + *notes (Butputs ( + *link f . ( if the obFect is not a ord.( . ! ?'&;: make)deprecated + *values + ( ord( ord . . + *description (Ceclares a ord as ( + *link ;BS$;BN': deprecated . (.( . + *side)effects ( ord( . ! ?'&;: make)flushable + *values + ( ord( ord . . + *description (Ceclares a ord as ( + *link ;BS$;BN': flushable . (.( . + *side)effects ( ord( . ! ?'&;: make)foldable + *values + ( ord( ord . . + *description (Ceclares a ord as ( + *link ;BS$;BN': foldable . (.( . + *side)effects ( ord( . ! ?'&;: make)inline + *values + ( ord( ord . . + *description (Ceclares a ord as ( + *link ;BS$;BN': inline . (.( . + *side)effects ( ord( . ! ?'&;: define)inline + *values + ( ord( ord . + (def( quotation . + (effect( effect . . + *description (Cefines a ord and makes it ( + *link ;BS$;BN': inline . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects ( ord( . ! K %opyright 5%6 ,==S< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: definitions kernel quotations ords ! IN: ords.constant ;#'CI%"$': constant P ord (constant( ord)prop Gboolean !

: define)constant 5 ord value )) 6 0 (constant( set) ord)prop 3 0 0 3 curry 5 )) value 6 define)inline 3 ,bi ! I: constant reset) ord 0 call)next)method 3 0 f (constant( set) ord)prop 3 bi ! I: constant definer drop > %BNS$"N$: f ! I: constant definition (constant( ord)prop literali8e 1quotation ! USING: help.markup help.syntax ords.constant ! IN: ords.constant "#$I%&': ( ords.constant( (%onstants( ($here is a syntax for defining ords hich push literals on the stack.( *nl (Cefine a ne ord that pushes a literal on the stack:( + *subsections ;BS$;BN': %BNS$"N$: . (Cefine an constant at run)time:( + *subsections define)constant . ! "EBU$: ( ords.constant( IN: ords.constant.tests USING: tools.test math ords.constant ! %BNS$"N$: a 2

0 2 3 0 a 3 unit)test 0 t 3 0 > a constant: 3 unit)test %BNS$"N$: b > 2 0 > 2 3 0 b 3 unit)test %BNS$"N$: c + 1 , - . 0 + 1 , - . 3 0 c 3 unit)test SNIEB&: foo 0 f 3 0 > foo constant: 3 unit)testUSING: math eval lexer tools.test effects sequences ! IN: ords.alias.tests "&I"S: foo 2 0 3 0 (IN: ords.alias.tests %BNS$"N$: foo A( eval5 )) 6 3 unit)test 0 5 )) value 6 3 0 > foo stack)effect 3 unit)test "&I"S: IN)?+ ?+ + ?+ + 1 , . . . 0 (IN: ords.alias.tests IN)?+ + 1 , . .( eval5 )) x 6 3 unit)test K %opyright 5%6 ,==S Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors definitions effects kernel quotations sequences ords ! IN: ords.alias ;#'CI%"$': alias P ord (alias( ord)prop !

: define)alias 5 ne old )) 6 0 0 1quotation 3 0 stack)effect 3 bi define)inline 3 0 drop t (alias( set) ord)prop 3 0 parsing) ord: 0 t (parsing( set) ord)prop 3 0 drop 3 if 3 ,tri ! I: alias reset) ord 0 call)next)method 3 0 f (alias( set) ord)prop 3 bi ! I: alias definer drop > "&I"S: f ! USING: help.markup help.syntax ords.alias ! IN: ords.alias "#$I%&': ( ords.alias( (Jord aliasing( ($here is a syntax for defining ne names for existing ords. $his useful for % library bindings< for example in the Jin-, ";I< here ords need to be renamed for symmetry.( *nl (Cefine a ne ord that aliases another ord:( + *subsections ;BS$;BN': "&I"S: . (Cefine an alias at run)time:( + *subsections define)alias . ! "EBU$: ( ords.alias( K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: alien alien.strings arrays byte)arrays generic hashtables hashtables.private io io.encodings.ascii kernel math

math.private math.order namespaces make parser sequences strings vectors ords quotations assocs layouts classes classes.private classes.builtin classes.singleton classes.tuple classes.tuple.private kernel.private vocabs vocabs.loader source)files definitions slots classes.union classes.intersection classes.predicate compiler.units bootstrap.image.private io.files accessors combinators ! IN: bootstrap.primitives (%reating primitives and basic runtime structures...( print flush ?+ . clone sub)primitives set (vocab:bootstrapQsyntax.factor( parse)file architecture get + + ( indo s)xSL.-,( (xSLQ-,Q indo s( . + ( indo s)xSL.L/( (xSLQL/Q indo s( . + (unix)xSL.-,( (xSLQ-,Qunix( . + (unix)xSL.L/( (xSLQL/Qunix( . + (linux)ppc.-,( (ppcQ-,Qlinux( . + (linux)ppc.L/( (ppcQL/Qlinux( . . :at 0 (Ead architecture: ( prepend thro 3 unless (vocab:cpuQ( (Qbootstrap.factor( surround parse)file (vocab:bootstrapQlayoutsQlayouts.factor( parse)file K No e have 5 syntax)quot arch)quot layouts)quot 6 on the stack

K Ering up a bare cross)compiling vocabulary. (syntax( lookup)vocab vocab) ords bootstrap)syntax set ?+ ?+ ?+ ?+ ?+ . . . . . clone clone clone clone clone dictionary set root)cache set source)files set update)map set implementors)map set

init)caches bootstrapping: on call5 )) 6 call5 )) 6 K Vocabulary for slot accessors (accessors( create)vocab drop K "fter e execute bootstrapQlayouts num)types get f ParrayG builtins set 0 call5 )) 6 K %reate some empty vocabs K classes ill go + (alien( (alien.accessors( (alien.libraries( (alien.private( here the belo primitives and

(arrays( (byte)arrays( (classes.private( (classes.tuple( (classes.tuple.private( (classes.predicate( (compiler.units( (continuations.private( (generic.single( (generic.single.private( (gro able( (hashtables( (hashtables.private( (io( (io.files( (io.files.private( (io.streams.c( (locals.backend( (kernel( (kernel.private( (math( (math.parser.private( (math.private( (memory( (memory.private( (quotations( (quotations.private( (sbufs( (sbufs.private( (scratchpad( (sequences( (sequences.private( (slots.private( (strings( (strings.private( (system( (system.private( (threads.private( (tools.dispatch.private( (tools.memory.private( (tools.profiler.sampling.private( ( ords( ( ords.private( (vectors( (vectors.private( (vm( . 0 create)vocab drop 3 each K Euiltin classes : lookup)type)number 5 ord )) n 6 0 target) ord 3 ith)global type)number ! : register)builtin 5 class )) 6 0 dup lookup)type)number (type( set) ord)prop 3 0 dup (type( ord)prop builtins get set)nth 3 0 f f f builtin)class define)class 3 tri ! : prepare)slots 5 slots )) slots7 6 0 0 dup pair: 0 first, create 3 hen 3 map 3 map !

: define)builtin)slots 5 class slots )) 6

prepare)slots make)slots 1 finali8e)slots 0 (slots( set) ord)prop 3 0 define)accessors 3 ,bi ! : define)builtin)predicate 5 class )) 6 dup classGtype 0 eq: 3 curry 0 tag 3 prepend define)predicate ! : define)builtin 5 symbol slotspec )) 6 0 0 define)builtin)predicate 3 keep 3 dip define)builtin)slots ! (fixnum( (math( create register)builtin (bignum( (math( create register)builtin (tuple( (kernel( create register)builtin (float( (math( create register)builtin (f( (syntax( lookup) ord register)builtin (array( (arrays( create register)builtin ( rapper( (kernel( create register)builtin (callstack( (kernel( create register)builtin (string( (strings( create register)builtin (quotation( (quotations( create register)builtin (dll( (alien( create register)builtin (alien( (alien( create register)builtin ( ord( ( ords( create register)builtin (byte)array( (byte)arrays( create register)builtin K Je need this before defining c)ptr belo (f( (syntax( lookup) ord + . define)builtin (f( (syntax( create 0 not 3 (predicate( set) ord)prop (f:( (syntax( vocab) ords delete)at (t( (syntax( lookup) ord define)singleton)class K Some unions (c)ptr( (alien( create 0 (alien( (alien( lookup) ord < (f( (syntax( lookup) ord < (byte)array( (byte)arrays( lookup) ord < 3 + . make define)union)class K " predicate class used for declarations (array)capacity( (sequences.private( create (fixnum( (math( lookup) ord 0 0 dup = fixnumGH 3 W bootstrap)max)array)capacity Pfake)bignumG 0 fixnumPH 3 curry < 0 0 drop f 3 if 3 W 3 0 3 make define)predicate)class (array)capacity( (sequences.private( lookup) ord 0 Gfixnum 3 bootstrap)max)array)capacity Pfake)bignumG 0 fixnum)bitand 3 curry append (coercer( set) ord)prop K %atch)all class for providing a default method. (obFect( (kernel( create 0 f f + . intersection)class define)class 3 0 0 drop t 3 (predicate( set) ord)prop 3 bi (obFect:( (kernel( vocab) ords delete)at

K 'mpty class ith no instances (null( (kernel( create 0 f + . f union)class define)class 3 0 0 drop f 3 (predicate( set) ord)prop 3 bi (null:( (kernel( vocab) ords delete)at (fixnum( (math( create + . define)builtin (fixnum( (math( create (integerGfixnum)strict( (math( create 1quotation (coercer( set) ord)prop (bignum( (math( create + . define)builtin (bignum( (math( create (Gbignum( (math( create 1quotation (coercer( set) ord)prop (float( (math( create + . define)builtin (float( (math( create (Gfloat( (math( create 1quotation (coercer( set) ord)prop (array( (arrays( create + + (length( + (array)capacity( (sequences.private( . read)only . . define)builtin ( rapper( (kernel( create + + ( rapped( read)only . . define)builtin (string( (strings( create + + (length( + (array)capacity( (sequences.private( . read)only . (aux( . define)builtin (quotation( (quotations( create + + (array( + (array( (arrays( . read)only . (cached)effect( (cache)counter( . define)builtin (dll( (alien( create + + (path( + (byte)array( (byte)arrays( . read)only . . define)builtin (alien( (alien( create + + (underlying( + (c)ptr( (alien( . read)only . (expired( . define)builtin ( ord( ( ords( create + + (hashcode( + (fixnum( (math( . . (name( (vocabulary( + (def( + (quotation( (quotations( . initial: 0 3 . (props( (pic)def( (pic)tail)def( + (sub)primitive( read)only . . define)builtin (byte)array( (byte)arrays( create + + (length( + (array)capacity( (sequences.private( . read)only . . define)builtin

(callstack( (kernel( create + . define)builtin (tuple( (kernel( create 0 + . define)builtin 3 0 define)tuple)layout 3 bi K %reate special tombstone values (tombstone( (hashtables.private( create tuple + (state( . define)tuple)class (55empty66( (hashtables.private( create (tombstone( (hashtables.private( lookup) ord f ,array Gtuple 1quotation 5 )) value 6 define)inline (55tombstone66( (hashtables.private( create (tombstone( (hashtables.private( lookup) ord t ,array Gtuple 1quotation 5 )) value 6 define)inline K Some tuple classes (curry( (kernel( create tuple + + (obF( read)only . + (quot( read)only . . prepare)slots define)tuple)class (curry( (kernel( lookup) ord + 0 f (inline( set) ord)prop 3 0 make)flushable 3 0 3 0 0 callable instance)check)quot W tuple)layout < > Ptuple)boaG < 3 0 3 make 3 . cleave 5 obF quot )) curry 6 define)declared (compose( (kernel( create tuple + + (first( read)only . + (second( read)only . . prepare)slots define)tuple)class (compose( (kernel( lookup) ord + 0 f (inline( set) ord)prop 3 0 make)flushable 3 0 3 0 0 callable instance)check)quot 0 dip 3 curry W callable instance)check)quot W tuple)layout < > Ptuple)boaG < 3 0 3 make

3 . cleave 5 quot1 quot, )) compose 6 define)declared K Sub)primitive ords : make)sub)primitive 5 ord vocab effect )) 6 0 create dup t (primitive( set) ord)prop dup 1quotation 3 dip define)declared ! + + (mega)cache)lookup( (generic.single.private( 5 methods index cache )) 6 . + (inline)cache)miss( (generic.single.private( 5 generic methods index cache )) 6 . + (inline)cache)miss)tail( (generic.single.private( 5 generic methods index cache )) 6 . + (drop( (kernel( 5 x )) 6 . + (,drop( (kernel( 5 x y )) 6 . + (-drop( (kernel( 5 x y 8 )) 6 . + (/drop( (kernel( 5 x y 8 )) 6 . + (dup( (kernel( 5 x )) x x 6 . + (,dup( (kernel( 5 x y )) x y x y 6 . + (-dup( (kernel( 5 x y 8 )) x y 8 x y 8 6 . + (/dup( (kernel( 5 x y 8 )) x y 8 x y 8 6 . + (rot( (kernel( 5 x y 8 )) y 8 x 6 . + ()rot( (kernel( 5 x y 8 )) 8 x y 6 . + (dupd( (kernel( 5 x y )) x x y 6 . + (s apd( (kernel( 5 x y 8 )) y x 8 6 . + (nip( (kernel( 5 x y )) y 6 . + (,nip( (kernel( 5 x y 8 )) 8 6 . + (over( (kernel( 5 x y )) x y x 6 . + (pick( (kernel( 5 x y 8 )) x y 8 x 6 . + (s ap( (kernel( 5 x y )) y x 6 . + (eq:( (kernel( 5 obF1 obF, )) : 6 . + (tag( (kernel.private( 5 obFect )) n 6 . + (5execute6( (kernel.private( 5 ord )) 6 . + (5call6( (kernel.private( 5 quot )) 6 . + (fpu)state( (kernel.private( 5 )) 6 . + (set)fpu)state( (kernel.private( 5 )) 6 . + (signal)handler( (kernel.private( 5 )) 6 . + (leaf)signal)handler( (kernel.private( 5 )) 6 . + (ffi)signal)handler( (kernel.private( 5 )) 6 . + (ffi)leaf)signal)handler( (kernel.private( 5 )) 6 . + (un ind)native)frames( (kernel.private( 5 )) 6 . + (set)callstack( (kernel.private( 5 callstack )) 4 6 . + (la8y)Fit)compile( (kernel.private( 5 )) 6 . + (c)to)factor( (kernel.private( 5 )) 6 . + (slot( (slots.private( 5 obF m )) value 6 . + (get)local( (locals.backend( 5 n )) obF 6 . + (load)local( (locals.backend( 5 obF )) 6 . + (drop)locals( (locals.backend( 5 n )) 6 . + (both)fixnums:( (math.private( 5 x y )) : 6 . + (fixnum2fast( (math.private( 5 x y )) 8 6 . + (fixnum)fast( (math.private( 5 x y )) 8 6 . + (fixnum4fast( (math.private( 5 x y )) 8 6 . + (fixnum)bitand( (math.private( 5 x y )) 8 6 . + (fixnum)bitor( (math.private( 5 x y )) 8 6 . + (fixnum)bitxor( (math.private( 5 x y )) 8 6 . + (fixnum)bitnot( (math.private( 5 x )) y 6 . + (fixnum)mod( (math.private( 5 x y )) 8 6 .

+ (fixnum)shift)fast( (math.private( 5 x y )) 8 6 . + (fixnumQi)fast( (math.private( 5 x y )) 8 6 . + (fixnumQmod)fast( (math.private( 5 x y )) 8 6 . + (fixnum2( (math.private( 5 x y )) 8 6 . + (fixnum)( (math.private( 5 x y )) 8 6 . + (fixnum4( (math.private( 5 x y )) 8 6 . + (fixnumP( (math.private( 5 x y )) : 6 . + (fixnumPH( (math.private( 5 x y )) 8 6 . + (fixnumG( (math.private( 5 x y )) : 6 . + (fixnumGH( (math.private( 5 x y )) : 6 . + (string)nth)fast( (strings.private( 5 n string )) ch 6 . + (5set)context6( (threads.private( 5 obF context )) obF7 6 . + (5set)context)and)delete6( (threads.private( 5 obF context )) 4 6 . + (5start)context6( (threads.private( 5 obF quot )) obF7 6 . + (5start)context)and)delete6( (threads.private( 5 obF quot )) 4 6 . . 0 first- make)sub)primitive 3 each K ;rimitive ords : make)primitive 5 ord vocab function effect )) 6 0 0 create dup reset) ord dup t (primitive( set) ord)prop 3 dip ascii stringGalien 0 do)primitive 3 curry 3 dip define)declared ! + + (PcallbackG( (alien( (primitive[callback( 5 return)re ind ord )) alien 6 . + (Pdisplaced)alienG( (alien( (primitive[displaced[alien( 5 displacement c)ptr )) alien 6 . + (alien)address( (alien( (primitive[alien[address( 5 c)ptr )) addr 6 . + (alien)cell( (alien.accessors( (primitive[alien[cell( 5 c)ptr n )) value 6 . + (alien)double( (alien.accessors( (primitive[alien[double( 5 c)ptr n )) value 6 . + (alien)float( (alien.accessors( (primitive[alien[float( 5 c)ptr n )) value 6 . + (alien)signed)1( (alien.accessors( (primitive[alien[signed[1( 5 c)ptr n )) value 6 . + (alien)signed),( (alien.accessors( (primitive[alien[signed[,( 5 c)ptr n )) value 6 . + (alien)signed)/( (alien.accessors( (primitive[alien[signed[/( 5 c)ptr n )) value 6 . + (alien)signed)S( (alien.accessors( (primitive[alien[signed[S( 5 c)ptr n )) value 6 . + (alien)signed)cell( (alien.accessors( (primitive[alien[signed[cell( 5 c)ptr n )) value 6 . + (alien)unsigned)1( (alien.accessors( (primitive[alien[unsigned[1( 5 c)ptr n )) value 6 . + (alien)unsigned),( (alien.accessors( (primitive[alien[unsigned[,( 5 c)ptr n )) value 6 . + (alien)unsigned)/( (alien.accessors( (primitive[alien[unsigned[/( 5 c)ptr n )) value 6 . + (alien)unsigned)S( (alien.accessors( (primitive[alien[unsigned[S( 5 c)ptr n )) value 6 . + (alien)unsigned)cell( (alien.accessors( (primitive[alien[unsigned[cell( 5 c)ptr n )) value 6 . + (set)alien)cell( (alien.accessors( (primitive[set[alien[cell( 5 value c)ptr n )) 6 .

+ (set)alien)double( (alien.accessors( (primitive[set[alien[double( 5 value c)ptr n )) 6 . + (set)alien)float( (alien.accessors( (primitive[set[alien[float( 5 value c)ptr n )) 6 . + (set)alien)signed)1( (alien.accessors( (primitive[set[alien[signed[1( 5 value c)ptr n )) 6 . + (set)alien)signed),( (alien.accessors( (primitive[set[alien[signed[,( 5 value c)ptr n )) 6 . + (set)alien)signed)/( (alien.accessors( (primitive[set[alien[signed[/( 5 value c)ptr n )) 6 . + (set)alien)signed)S( (alien.accessors( (primitive[set[alien[signed[S( 5 value c)ptr n )) 6 . + (set)alien)signed)cell( (alien.accessors( (primitive[set[alien[signed[cell( 5 value c)ptr n )) 6 . + (set)alien)unsigned)1( (alien.accessors( (primitive[set[alien[unsigned[1( 5 value c)ptr n )) 6 . + (set)alien)unsigned),( (alien.accessors( (primitive[set[alien[unsigned[,( 5 value c)ptr n )) 6 . + (set)alien)unsigned)/( (alien.accessors( (primitive[set[alien[unsigned[/( 5 value c)ptr n )) 6 . + (set)alien)unsigned)S( (alien.accessors( (primitive[set[alien[unsigned[S( 5 value c)ptr n )) 6 . + (set)alien)unsigned)cell( (alien.accessors( (primitive[set[alien[unsigned[cell( 5 value c)ptr n )) 6 . + (5dlopen6( (alien.libraries( (primitive[dlopen( 5 path )) dll 6 . + (5dlsym6( (alien.libraries( (primitive[dlsym( 5 name dll )) alien 6 . + (5dlsym)ra 6( (alien.libraries( (primitive[dlsym[ra ( 5 name dll )) alien 6 . + (dlclose( (alien.libraries( (primitive[dlclose( 5 dll )) 6 . + (dll)valid:( (alien.libraries( (primitive[dll[validp( 5 dll )) : 6 . + (current)callback( (alien.private( (primitive[current[callback( 5 )) n 6 . + (ParrayG( (arrays( (primitive[array( 5 n elt )) array 6 . + (resi8e)array( (arrays( (primitive[resi8e[array( 5 n array )) ne )array 6 . + (5byte)array6( (byte)arrays( (primitive[uninitiali8ed[byte[array( 5 n )) byte)array 6 . + (Pbyte)arrayG( (byte)arrays( (primitive[byte[array( 5 n )) byte)array 6 . + (resi8e)byte)array( (byte)arrays( (primitive[resi8e[byte[array( 5 n byte)array )) ne )byte)array 6 . + (Ptuple)boaG( (classes.tuple.private( (primitive[tuple[boa( 5 slots... layout )) tuple 6 . + (PtupleG( (classes.tuple.private( (primitive[tuple( 5 layout )) tuple 6 . + (modify)code)heap( (compiler.units( (primitive[modify[code[heap( 5 alist update)existing: reset)pics: )) 6 . + (lookup)method( (generic.single.private( (primitive[lookup[method( 5 obFect methods )) method 6 . + (mega)cache)miss( (generic.single.private( (primitive[mega[cache[miss( 5 methods index cache )) method 6 . + (5exists:6( (io.files.private( (primitive[existsp( 5 path )) : 6 . + (5fopen6( (io.streams.c( (primitive[fopen( 5 path mode )) alien 6 . + (fclose( (io.streams.c( (primitive[fclose( 5 alien )) 6 . + (fflush( (io.streams.c( (primitive[fflush( 5 alien )) 6 . + (fgetc( (io.streams.c( (primitive[fgetc( 5 alien )) byteQf 6 . + (fputc( (io.streams.c( (primitive[fputc( 5 byte alien )) 6 . + (fread)unsafe( (io.streams.c( (primitive[fread( 5 n buf alien )) count 6 . + (fseek( (io.streams.c( (primitive[fseek( 5 alien offset hence )) 6 . + (ftell( (io.streams.c( (primitive[ftell( 5 alien )) n 6 . + (f rite( (io.streams.c( (primitive[f rite( 5 data length alien )) 6 . + (5clone6( (kernel( (primitive[clone( 5 obF )) ne obF 6 . + (P rapperG( (kernel( (primitive[ rapper( 5 obF )) rapper 6 . + (callstack( (kernel( (primitive[callstack( 5 )) callstack 6 . + (callstackGarray( (kernel( (primitive[callstack[to[array( 5 callstack ))

array 6 . + (datastack( (kernel( (primitive[datastack( 5 )) array 6 . + (die( (kernel( (primitive[die( 5 )) 6 . + (retainstack( (kernel( (primitive[retainstack( 5 )) array 6 . + (5identity)hashcode6( (kernel.private( (primitive[identity[hashcode( 5 obF )) code 6 . + (become( (kernel.private( (primitive[become( 5 old ne )) 6 . + (callstack)bounds( (kernel.private( (primitive[callstack[bounds( 5 )) start end 6 . + (check)datastack( (kernel.private( (primitive[check[datastack( 5 array inZ outZ )) : 6 . + (compute)identity)hashcode( (kernel.private( (primitive[compute[identity[hashcode( 5 obF )) 6 . + (context)obFect( (kernel.private( (primitive[context[obFect( 5 n )) obF 6 . + (innermost)frame)executing( (kernel.private( (primitive[innermost[stack[frame[executing( 5 callstack )) obF 6 . + (innermost)frame)scan( (kernel.private( (primitive[innermost[stack[frame[scan( 5 callstack )) n 6 . + (set)context)obFect( (kernel.private( (primitive[set[context[obFect( 5 obF n )) 6 . + (set)datastack( (kernel.private( (primitive[set[datastack( 5 array )) 6 . + (set)innermost)frame)quot( (kernel.private( (primitive[set[innermost[stack[frame[quot( 5 n callstack )) 6 . + (set)retainstack( (kernel.private( (primitive[set[retainstack( 5 array )) 6 . + (set)special)obFect( (kernel.private( (primitive[set[special[obFect( 5 obF n )) 6 . + (special)obFect( (kernel.private( (primitive[special[obFect( 5 n )) obF 6 . + (strip)stack)traces( (kernel.private( (primitive[strip[stack[traces( 5 )) 6 . + (unimplemented( (kernel.private( (primitive[unimplemented( 5 )) 4 6 . + (load)locals( (locals.backend( (primitive[load[locals( 5 ... n )) 6 . + (bitsGdouble( (math( (primitive[bits[double( 5 n )) x 6 . + (bitsGfloat( (math( (primitive[bits[float( 5 n )) x 6 . + (doubleGbits( (math( (primitive[double[bits( 5 x )) n 6 . + (floatGbits( (math( (primitive[float[bits( 5 x )) n 6 . + (5format)float6( (math.parser.private( (primitive[format[float( 5 n format )) byte)array 6 . + (bignum4( (math.private( (primitive[bignum[multiply( 5 x y )) 8 6 . + (bignum2( (math.private( (primitive[bignum[add( 5 x y )) 8 6 . + (bignum)( (math.private( (primitive[bignum[subtract( 5 x y )) 8 6 . + (bignum)bit:( (math.private( (primitive[bignum[bitp( 5 n x )) : 6 . + (bignum)bitand( (math.private( (primitive[bignum[and( 5 x y )) 8 6 . + (bignum)bitnot( (math.private( (primitive[bignum[not( 5 x )) y 6 . + (bignum)bitor( (math.private( (primitive[bignum[or( 5 x y )) 8 6 . + (bignum)bitxor( (math.private( (primitive[bignum[xor( 5 x y )) 8 6 . + (bignum)log,( (math.private( (primitive[bignum[log,( 5 x )) n 6 . + (bignum)mod( (math.private( (primitive[bignum[mod( 5 x y )) 8 6 . + (bignum)gcd( (math.private( (primitive[bignum[gcd( 5 x y )) 8 6 . + (bignum)shift( (math.private( (primitive[bignum[shift( 5 x y )) 8 6 . + (bignumQi( (math.private( (primitive[bignum[divint( 5 x y )) 8 6 . + (bignumQmod( (math.private( (primitive[bignum[divmod( 5 x y )) 8 6 . + (bignumP( (math.private( (primitive[bignum[less( 5 x y )) : 6 . + (bignumPH( (math.private( (primitive[bignum[lesseq( 5 x y )) : 6 . + (bignumH( (math.private( (primitive[bignum[eq( 5 x y )) : 6 . + (bignumG( (math.private( (primitive[bignum[greater( 5 x y )) : 6 . + (bignumGH( (math.private( (primitive[bignum[greatereq( 5 x y )) : 6 . + (bignumGfixnum( (math.private( (primitive[bignum[to[fixnum( 5 x )) y 6 . + (fixnum)shift( (math.private( (primitive[fixnum[shift( 5 x y )) 8 6 . + (fixnumQi( (math.private( (primitive[fixnum[divint( 5 x y )) 8 6 .

+ (fixnumQmod( (math.private( (primitive[fixnum[divmod( 5 x y )) 8 6 . + (fixnumGbignum( (math.private( (primitive[fixnum[to[bignum( 5 x )) y 6 . + (fixnumGfloat( (math.private( (primitive[fixnum[to[float( 5 x )) y 6 . + (float4( (math.private( (primitive[float[multiply( 5 x y )) 8 6 . + (float2( (math.private( (primitive[float[add( 5 x y )) 8 6 . + (float)( (math.private( (primitive[float[subtract( 5 x y )) 8 6 . + (float)uP( (math.private( (primitive[float[less( 5 x y )) : 6 . + (float)uPH( (math.private( (primitive[float[lesseq( 5 x y )) : 6 . + (float)uG( (math.private( (primitive[float[greater( 5 x y )) : 6 . + (float)uGH( (math.private( (primitive[float[greatereq( 5 x y )) : 6 . + (floatQf( (math.private( (primitive[float[divfloat( 5 x y )) 8 6 . + (floatP( (math.private( (primitive[float[less( 5 x y )) : 6 . + (floatPH( (math.private( (primitive[float[lesseq( 5 x y )) : 6 . + (floatH( (math.private( (primitive[float[eq( 5 x y )) : 6 . + (floatG( (math.private( (primitive[float[greater( 5 x y )) : 6 . + (floatGH( (math.private( (primitive[float[greatereq( 5 x y )) : 6 . + (floatGbignum( (math.private( (primitive[float[to[bignum( 5 x )) y 6 . + (floatGfixnum( (math.private( (primitive[float[to[fixnum( 5 x )) y 6 . + (all)instances( (memory( (primitive[all[instances( 5 )) array 6 . + (5code)blocks6( (tools.memory.private( (primitive[code[blocks( 5 )) array 6 . + (5code)room6( (tools.memory.private( (primitive[code[room( 5 )) code)room 6 . + (compact)gc( (memory( (primitive[compact[gc( 5 )) 6 . + (5data)room6( (tools.memory.private( (primitive[data[room( 5 )) data)room 6 . + (disable)gc)events( (tools.memory.private( (primitive[disable[gc[events( 5 )) events 6 . + (enable)gc)events( (tools.memory.private( (primitive[enable[gc[events( 5 )) 6 . + (gc( (memory( (primitive[full[gc( 5 )) 6 . + (minor)gc( (memory( (primitive[minor[gc( 5 )) 6 . + (si8e( (memory( (primitive[si8e( 5 obF )) n 6 . + (5save)image6( (memory.private( (primitive[save[image( 5 path1 path, )) 6 . + (5save)image)and)exit6( (memory.private( (primitive[save[image[and[exit( 5 path1 path, )) 6 . + (Fit)compile( (quotations( (primitive[Fit[compile( 5 quot )) 6 . + (quot)compiled:( (quotations( (primitive[quot[compiled[p( 5 quot )) : 6 . + (quotation)code( (quotations( (primitive[quotation[code( 5 quot )) start end 6 . + (arrayGquotation( (quotations.private( (primitive[array[to[quotation( 5 array )) quot 6 . + (set)slot( (slots.private( (primitive[set[slot( 5 value obF n )) 6 . + (PstringG( (strings( (primitive[string( 5 n ch )) string 6 . + (resi8e)string( (strings( (primitive[resi8e[string( 5 n str )) ne str 6 . + (set)string)nth)fast( (strings.private( (primitive[set[string[nth[fast( 5 ch n string )) 6 . + (5exit6( (system( (primitive[exit( 5 n )) 4 6 . + (nano)count( (system( (primitive[nano[count( 5 )) ns 6 . + (5sleep6( (threads.private( (primitive[sleep( 5 nanos )) 6 . + (callstack)for( (threads.private( (primitive[callstack[for( 5 context )) array 6 . + (context)obFect)for( (threads.private( (primitive[context[obFect[for( 5 n context )) obF 6 . + (datastack)for( (threads.private( (primitive[datastack[for( 5 context )) array 6 . + (retainstack)for( (threads.private( (primitive[retainstack[for( 5 context )) array 6 . + (dispatch)stats( (tools.dispatch.private( (primitive[dispatch[stats( 5 )) stats 6 . + (reset)dispatch)stats( (tools.dispatch.private(

(primitive[reset[dispatch[stats( 5 )) 6 . + (optimi8ed:( ( ords( (primitive[optimi8ed[p( 5 ord )) : 6 . + ( ord)code( ( ords( (primitive[ ord[code( 5 ord )) start end 6 . + (5 ord6( ( ords.private( (primitive[ ord( 5 name vocab hashcode )) ord 6 . + (profiling( (tools.profiler.sampling.private( (primitive[sampling[profiler( 5 : )) 6 . + (5get)samples6( (tools.profiler.sampling.private( (primitive[get[samples( 5 )) samplesQf 6 . + (5clear)samples6( (tools.profiler.sampling.private( (primitive[clear[samples( 5 )) 6 . . 0 first/ make)primitive 3 each K Eump build number (build( (kernel( create build 1 2 0 3 curry 5 )) n 6 define)declared 3 ith)compilation)unit K %opyright 5%6 ,==R< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: alien arrays byte)arrays kernel layouts math namespaces quotations strings ords ! 1L data)alignment set =b1111 tag)mask set / tag)bits set 1/ num)types set -, mega)cache)si8e set ?+ + fixnum = . + ;BS$;BN': f 1 . + array , . + float - . + quotation / . + bignum A . + alien L . + tuple R . + rapper S . + byte)array U . + callstack 1= . + string 11 . + ord 1, . + dll 1- . . type)numbers set , header)bits set K %opyright 5%6 ,==/< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: arrays assocs continuations debugger destructors generic hash)sets hashtables init io io.files kernel kernel.private make math memory namespaces parser parser.notes prettyprint sequences splitting system vectors vocabs vocabs.loader ords ! DU"&I@I'C: bootstrap.image.private DU"&I@I'C: hashtables DU"&I@I'C: hash)sets IN: bootstrap.stage1 (Eootstrap stage 1...( print flush

(vocab:bootstrapQprimitives.factor( run)file load)help: off + (resource:core( . vocab)roots set K %reate a boot quotation for the target by collecting all top)level K forms into a quotation< surrounded by some boilerplate. 0 0 K #ehash hashtables first< since bootstrap.image creates K them using the host image7s hashing algorithms. 0 hashtable: 3 instances 0 hashtables:rehash 3 each 0 hash)set: 3 instances 0 hash)sets:rehash 3 each boot 3 W (math.integers( require (math.floats( require (memory( require (io.streams.c( require (vocabs.loader( require (syntax( require (bootstrap.layouts( require 0 f parser)quiet: set)global init)resource)path (resource:basisQbootstrapQstage,.factor( dup exists: 0 run)file 3 0 (%annot find ( rite rite (.( print (;lease move ( rite image rite ( into the same directory as the @actor sources<( print (and try again.( print 1 5exit6 3 if 3 W 3 0 3 make bootstrap.image.private:bootstrap)startup)quot set K %opyright 5%6 ,==R< ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: ords ords.symbol sequences vocabs kernel compiler.units ! IN: bootstrap.syntax 0 (syntax( create)vocab drop + (K( (>(( (ZK( (5( (:( (!( (P;#IV"$'( (E+(

(EV+( (%:( (%?"#:( (C'@'#:( ('##B#:( (@B#G'$:( (G'N'#I%Z( (G'N'#I%:( (?BBY:( (?+( (?S+( (IN:( (INS$"N%':( (I:( (I"IN:( (I"$?:( (IIMIN:( (N"N:( (;>(( (;BS$;BN':( (;#'CI%"$':( (;#III$IV':( (;#IV"$'G( (SEU@>(( (SING&'$BN:( (SING&'$BNS:( (EUI&$IN:( (SNIEB&:( (SNIEB&S:( (%BNS$"N$:( ($U;&':( (final( (S&B$:( ($+( (UNIBN:( (IN$'#S'%$IBN:( (US':( (UNUS':( (USING:( (DU"&I@I'C:( (DU"&I@I'C)JI$?:( (@#BI:( ('M%&UC':( (#'N"I':( ("&I"S:( (SNN$"M:( (V+( (J+( (0( (>>( (I>>( (3( (delimiter( (deprecated( (f( (flushable( (foldable( (inline( (recursive( (t( (+( (.(

(%S+( (PP( (GG( (call)next)method( (not+( (maybe+( (union+( (intersection+( (initial:( (read)only( (call5( (execute5( (PPPPPP( (HHHHHH( (GGGGGG( (PPPPPPP( (HHHHHHH( (GGGGGGG( . 0 (syntax( create drop 3 each (t( (syntax( lookup) ord define)symbol 3 ith)compilation)unit K %opyright 5%6 ,==-< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors alien.accessors byte)arrays kernel kernel.private math math.private sequences sequences.private slots.private ! IN: strings EUI&$IN: string + length array)capacity read)only initial: = . aux ! P;#IV"$' : string)hashcode 5 str )) n 6 - slot ! inline : set)string)hashcode 5 n str )) 6 - set)slot ! inline : reset)string)hashcode 5 str )) 6 f s ap set)string)hashcode ! inline : rehash)string 5 str )) 6 1 over sequence)hashcode s ap set)string)hashcode ! inline : 5aux6 5 n string )) byte)array m 6 auxGG + byte)array . declare s ap 1 fixnum)shift)fast ! inline : small)char: 5 ch )) : 6 dup = fixnumGH 0 =xRf fixnumPH 3 0 drop f 3 if ! inline : string)nth 5 n string )) ch 6 ,dup string)nth)fast dup small)char: 0 ,nip 3 0 0 5aux6 alien)unsigned), R fixnum)shift)fast 3 dip fixnum)bitxor 3 if ! inline : ensure)aux 5 string )) string 6 dup auxGG 0 dup length , 4 5byte)array6 GGaux 3 unless ! inline : set)string)nth)slo 5 ch n string )) 6 0 0 =xS= fixnum)bitor 3 ,dip set)string)nth)fast 3 0

ensure)aux 0 )R fixnum)shift)fast 1 fixnum)bitxor 3 ,dip 5aux6 set)alien)unsigned), 3 -bi ! : set)string)nth 5 ch n string )) 6 pick small)char: 0 set)string)nth)fast 3 0 set)string)nth)slo ;#IV"$'G I: string equal: over string: 0 ,dup 0 hashcode 3 bi9 eq: 0 sequenceH 3 0 ,drop f 3 if 3 0 ,drop f 3 if ! I: string hashcode4 nip dup string)hashcode 0 3 0 dup rehash)string string)hashcode 3 :if ! I: string length lengthGG ! inline I: string nth)unsafe 0 integerGfixnum 3 dip string)nth ! inline I: string set)nth)unsafe dup reset)string)hashcode 0 integerGfixnum 3 0 integerGfixnum 3 0 3 tri4 set)string)nth ! inline I: string clone 5clone6 0 clone 3 change)aux ! inline I: string resi8e resi8e)string ! inline : 1string 5 ch )) str 6 1 s ap PstringG ! inline : Gstring 5 seq )) str 6 (( clone)like ! inline I: string ne )sequence drop = PstringG ! inline INS$"N%': string sequence USING: continuations kernel math math.order namespaces make strings strings.private sbufs tools.test sequences vectors arrays memory prettyprint io.streams.null ! IN: strings.tests 0 %?"#: b 3 0 1 Gbignum (abc( nth 3 unit)test 0 3 0 1= 0 0 )1====== PsbufG 3 ignore)errors 3 times 3 unit)test 0 (abc( 3 0 0 (a( (b( (c( 3 0 0 W 3 each 3 (( make 3 unit)test 0 (abc( 3 0 (ab( (c( append 3 unit)test 0 (abc( 3 0 (a( (b( (c( -append 3 unit)test 0 - 3 0 (a( (hola( start 3 unit)test 0 f 3 0 (x( (hola( start 3 unit)test

3 if ! inline

0 0 0 0 0 0

= = = 1 f f

3 3 3 3 3 3

0 0 0 0 0 0

(( (a( start 3 unit)test (( (( start 3 unit)test (hola( (hola( start 3 unit)test (ol( (hola( start 3 unit)test (amigo( (hola( start 3 unit)test (holaa( (hola( start 3 unit)test

0 (Eeginning( 3 0 (Eeginning and end( U head 3 unit)test 0 f 3 0 %?"#: I (team( member: 3 unit)test 0 t 3 0 (ea( (team( subseq: 3 unit)test 0 f 3 0 (actore( (@actor( subseq: 3 unit)test 0 (end( 3 0 (Eeginning and end( 1/ tail 3 unit)test 0 0 0 0 t 3 0 t 3 0 (abc( (8( 3 (abc( (abd( before: 3 unit)test (8( (abd( after: 3 unit)test 3 0 (abc( (abd( min 3 unit)test 0 (8( (abd( max 3 unit)test

0 = 1= (hello( subseq 3 must)fail 0 (#eplacing2spaces2 ith2plus( 3 0 (#eplacing spaces ith plus( 0 dup %?"#: >s H 0 drop %?"#: 2 3 3 unit)test

hen 3 map

0 (=A( 3 0 (A( , %?"#: = pad)head 3 unit)test 0 (LLL( 3 0 (LLL( , %?"#: = pad)head 3 unit)test 0 1 (( nth 3 must)fail 0 )L (hello( nth 3 must)fail 0 t 3 0 (hello orld( dup Gvector Gstring H 3 unit)test

0 (ab( 3 0 , (abc( resi8e)string 3 unit)test 0 (abc>=>=>=( 3 0 L (abc( resi8e)string 3 unit)test 0 (>u==1,-/b( 3 0 , (>u==1,-/bc( resi8e)string 3 unit)test 0 (>u==1,-/bc>=>=>=( 3 0 L (>u==1,-/bc( resi8e)string 3 unit)test K #andom tester found this 0 , )R resi8e)string 3 0 + (kernel)error( - 11 )R . H 3 must)fail) ith K Iake sure ,/)bit strings (hello orld( (s( set ork

0 3 0 =x1,-/ 1 (s( get set)nth 3 unit)test 0 =x1,-/ 3 0 1 (s( get nth 3 unit)test 0 3 0 =x/-,1 - (s( get set)nth 3 unit)test 0 =x/-,1 3 0 - (s( get nth 3 unit)test 0 3 0 =xLA/-,1 A (s( get set)nth 3 unit)test 0 =xLA/-,1 3 0 A (s( get nth 3 unit)test 0 + %?"#: h =x1,-/

%?"#: l =x/-,1 %?"#: o =xLA/-,1 %?"#: %?"#: o %?"#: r %?"#: l %?"#: d 3 0 . (s( get Garray 3 unit)test K Iake sure string initiali8ation orks 0 =x1,-/AL 3 0 1== =x1,-/AL PstringG first 3 unit)test K Iake sure e clear aux vector hen storing octets 0 (>u1,-/ALhi( 3 0 (ih>u1,-/AL( clone reverseK 3 unit)test K Iake sure aux vector is not shared 0 (>udeadbe( 3 0 (>udeadbe( clone %?"#: >u1,-/AL over clone set)first 3 unit)test K #egressions 0 3 0 0 / 0 1== 0 (obdurak( clone 3 replicate gc dup 0 1,-/ = rot set)string)nth 3 each 1=== 0 1=== f ParrayG drop 3 times . 3 times 3 ith)null) riter 3 unit)test 0 t 3 0 1==== 0 drop -== 1== %?"#: >u1,-/AL 0 PstringG clone resi8e)string first 3 keep H 3 all)integers: 3 unit)test (M( (s( set 0 3 0 =x1==<==== = (s( get set)nth 3 unit)test 0 = 3 0 = (s( get nth 3 unit)test 0 3 0 )1 = (s( get set)nth 3 unit)test 0 =xRfffff 3 0 = (s( get nth 3 unit)test USING: arrays byte)arrays help.markup help.syntax kernel kernel.private strings.private sequences vectors sbufs math help.vocabs ! IN: strings

"#$I%&': (strings( (Strings( ($he ( + *vocab)link (strings( . ( vocabulary implements a data type for storing text. Strings are represented as fixed)si8e mutable sequences of Unicode code points. %ode points are represented as integers in the range 0=<,<=UR<1A,3.( *nl (Strings implement the ( + *link (sequence)protocol( . (< and basic string manipulation can be performed ith ( + *link (sequences( . ( from the ( + *vocab)link (sequences( . ( vocabulary. Iore text processing functionality can be found in vocabularies carrying the ( + *link $+ vocab)tag + name (text( . . . ( tag.( *nl (Strings form a class:( + *subsections string string: . (%reating ne strings:( + *subsections Gstring PstringG . (%reating a string from a single character:( + *subsections 1string . (#esi8ing strings:( + *subsections resi8e)string . + *see)also (syntax)strings( (sbufs( (unicode( (io.encodings( . ! "EBU$: (strings( ?'&;: string + *description ($he class of fixed)length character strings. See ( + *link (syntax)strings( . ( for syntax and ( + *link (strings( . ( for general information.( . ! ?'&;: string)nth + *values + (n( fixnum . + (string( string . + (ch( (the character at the ( + *snippet (n( . (th index( . . + *description (Unsafe string accessor< used to define ( + *link nth . ( on strings.( . + * arning ($his ord is in the ( + *vocab)link (strings.private( . ( vocabulary because it does not perform type or bounds checking. User code should call ( + *link nth . ( instead.( . ! ?'&;: set)string)nth + *values + (ch( (a character( . + (n( fixnum . + (string( string . . + *description (Unsafe string mutator< used to define ( + *link set)nth . ( on strings.( . + * arning ($his ord is in the ( + *vocab)link (strings.private( . ( vocabulary because it does not perform type or bounds checking. User code should call ( + *link set)nth . ( instead.( . ! ?'&;: PstringG + *values + (n( (a positive integer specifying string length( . + (ch( (an initial character( . + (string( string . . + *description (%reates a ne string ith the given length and all characters initially set to ( + *snippet (ch( . (.( . ! ?'&;: 1string + *values + (ch( (a character(. + (str( string . . + *description (Butputs a string of one character.( . ! ?'&;: Gstring

+ *values + (seq( (a sequence of characters( . + (str( string . . + *description (Butputs a freshly)allocated string ith the same elements as a given sequence< by interpreting the sequence elements as Unicode code points.( . + *notes ($his operation is only appropriate if the underlying sequence holds Unicode code points< hich is rare unless it is a ( + *link slice . ( of another string. $o convert a sequence of bytes to a string< use the ords documented in ( + *link (io.encodings.string( . (.( . + *errors ($hro s an error if the sequence contains elements other than integers.( . ! ?'&;: resi8e)string + *values + (n( (a non)negative integer( . + (str( string . + (ne str( string . . + *description (#esi8es the string to have a length of ( + *snippet (n( . ( elements. Jhen making the string shorter< this ord may either create a ne string or modify the existing string in place. Jhen making the string longer< this ord al ays allocates a ne string< filling remaining space ith 8eroes.( . + *side)effects (str( . ! USING: accessors eval strings.parser strings.parser.private tools.test ! IN: strings.parser.tests 0 (?ello>n>r orld( 3 0 (?ello>>n>>r orld( unescape)string 3 unit)test 0 (?ello>n>r orld( 3 0 (?ello>n>r orld( 3 unit)test 0 (?ello>n>r orld( 3 0 (((?ello>n>r orld((( 3 unit)test 0 (?ello>n>r orld>n( 3 0 (?ello>n>r orld ( 3 unit)test 0 (?ello>n>r orld( (hi( 3 0 (?ello>n>r orld( (hi( 3 unit)test 0 (?ello>n>r orld( (hi( 3 0 (((?ello>n>r orld((( (((hi((( 3 unit)test 0 (?ello>n>r orld>n( (hi( 3 0 (((?ello>n>r orld ((( (((hi((( 3 unit)test 0 (?ello>n>r orld>(( (hi( 3 0 (((?ello>n>r orld>(((( (((hi((( 3 unit)test 0 3 0 (>(>(>(?ello>n>r orld>>>n>(>(>(( eval5 )) obF 6 errorGG escaped)char)expected: 3 must)fail) ith 0 3 0 ( >( abc >( ( (>(>(>( >( abc >( >(>(>(( eval5 )) string 6 3 unit)test 0 3 0 (>(abc>(( (>(>(>(>(abc>(>(>(>(( eval5 )) string 6 3 unit)test 0 (>(>>( 3 0 (>(>>( 3 unit)test 0 (>e( 3 0 (>u====1b( 3 unit)test 0 (>e( 3 0 (>x1b( 3 unit)test USING: help.markup help.syntax strings lexer ! IN: strings.parser ?'&;: bad)escape + *error)description (Indicates the parser encountered an invalid escape code

follo ing a backslash 5( + *snippet (>>( . (6 in a string literal. See ( + *link (escape( . ( for a list of valid escape codes.( . ! ?'&;: escape + *values + (escape( (a single)character escape( . + (ch( (a character( . . + *description (%onverts from a single)character escape code and the corresponding character.( . + *examples + *example (USING: kernel prettyprint strings.parser !( (%?"#: n escape %?"#: >>n H .( (t( . . ! ?'&;: parse)string + *values + (str( (a ne ( + *link string . . . + *description (;arses the line until a quote 5>(6< interpreting escape codes along the ay.( . + *errors ($hro s an error if the string contains an invalid escape sequence.( . *parsing)note ! K %opyright 5%6 ,==S< ,==U Slava ;estov< Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs combinators kernel lexer make math math.parser namespaces sequences splitting strings ! IN: strings.parser '##B#: bad)escape char ! : escape 5 escape )) ch 6 ?+ + %?"#: a %?"#: >a . + %?"#: e %?"#: >e . + %?"#: n %?"#: >n . + %?"#: r %?"#: >r . + %?"#: t %?"#: >t . + %?"#: s %?"#: >s . + %?"#: >s %?"#: >s . + %?"#: = %?"#: >= . + %?"#: >> %?"#: >> . + %?"#: >( %?"#: >( . . :at 0 bad)escape 3 unless ! SNIEB&: nameGchar)hook nameGchar)hook 0 0 (Unicode support not available( thro 3 initiali8e : hex)escape 5 str )) ch str7 6 , cut)slice 0 hexG 3 dip ! : unicode)escape 5 str )) ch str7 6 (+( :head)slice 0 %?"#: . over index cut)slice 0 Gstring nameGchar)hook get call5 name )) char 6 3 dip rest)slice 3 0 L cut)slice 0 hexG 3 dip 3 if ! : next)escape 5 str )) ch str7 6 dup first + + %?"#: u 0 1 tail)slice unicode)escape 3 . + %?"#: x 0 1 tail)slice hex)escape 3 . 0 drop unclip)slice escape s ap 3 . case ! 3

: 5unescape)string6 5 str )) 6 %?"#: >> over index dup 0 cut)slice 0 W 3 dip rest)slice next)escape 0 < 3 dip 5unescape)string6 3 0 drop W 3 if ! : unescape)string 5 str )) str7 6 0 5unescape)string6 3 (( make ! : 5parse)string6 5 str )) m 6 dup 0 (>(>>( member: 3 find dup 0 0 cut)slice 0 W 3 dip rest)slice 3 dip %?"#: ( H 0 fromGG 3 0 next)escape 0 < 3 dip 5parse)string6 3 if 3 0 (Unterminated string( thro 3 if ! : parse)string 5 )) str 6 lexer get 0 0 s ap tail)slice 5parse)string6 3 (( make s ap 3 change)lexer)column ! P;#IV"$' : lexer)subseq 5 i )) before 6 0 0 lexer get 0 columnGG 3 0 line)textGG 3 bi 3 dip s ap subseq 3 0 lexer get columnPP 3 bi ! : rest)of)line 5 lexer )) seq 6 0 line)textGG 3 0 columnGG 3 bi tail)slice ! : current)char 5 lexer )) chQf 6 0 columnGG 3 0 line)textGG 3 bi :nth ! : advance)char 5 lexer )) 6 0 1 2 3 change)column drop ! '##B#: escaped)char)expected ! : next)char 5 lexer )) ch 6 dup still)parsing)line: 0 0 current)char 3 0 advance)char 3 bi 3 0 escaped)char)expected 3 if ! : lexer)head: 5 string )) : 6 0 lexer get rest)of)line 3 dip head: !

: advance)lexer 5 n )) 6 0 lexer get 3 dip 0 2 3 curry change)column drop ! inline : find)next)token 5 ch )) i elt 6 %?"#: > ,array 0 lexer get 0 columnGG 3 0 line)textGG 3 bi 3 dip 0 member: 3 curry find)from ! : next)lineW 5 lexer )) 6 0 rest)of)line W 3 0 next)line (>n( W 3 bi ! : take)double)quotes 5 )) string 6 lexer get dup current)char %?"#: ( H 0 0 3 0 columnGG 3 0 line)textGG 3 tri 0 %?"#: ( H not 3 find)from drop 0 s ap columnGG ) %?"#: ( PrepetitionG 3 0 rest)of)line 3 if4 3 0 drop f 3 if dup length advance)lexer ! : end)string)parse 5 delimiter )) 6 length - H 0 take)double)quotes - tail W 3 0 lexer get advance)char 3 if ! C'@'#: 5parse)multiline)string6 : parse)found)token 5 string i token )) 6 0 lexer)subseq W 3 dip %?"#: > H 0 lexer get 0 next)char < 3 0 next)char < 3 bi 5parse)multiline)string6 3 0 dup lexer)head: 0 end)string)parse 3 0 lexer get next)char < 5parse)multiline)string6 3 if 3 if ! '##B#: trailing)characters string ! : 5parse)multiline)string6 5 string )) 6 lexer get still)parsing: 0 dup first find)next)token 0 parse)found)token 3 0 drop lexer get next)lineW 5parse)multiline)string6 3 if4 3 0 thro )unexpected)eof 3 if ! ;#IV"$'G

: parse)multiline)string 5 )) string 6 lexer get rest)of)line (>(>(( head: 0 lexer get 0 , 2 3 change)column drop (>(>(>(( 3 0 (>(( 3 if 0 5parse)multiline)string6 3 (( make unescape)string ! USING: arrays byte)arrays kernel math math.order math.parser namespaces sequences kernel.private sequences.private strings sbufs tools.test vectors assocs generic vocabs.loader generic.single math.vectors math.functions ! IN: sequences.tests 0 (empty( 3 0 + . 0 (empty( 3 0 (not empty( 3 if)empty 3 unit)test 0 + 1 . (not empty( 3 0 + 1 . 0 (empty( 3 0 (not empty( 3 if)empty 3 unit)test 0 0 0 0 0 0 0 0 0 0 V+ 1 , - / . 3 0 1 A dup iota PsliceG Gvector 3 unit)test - 3 0 1 / dup iota PsliceG length 3 unit)test , 3 0 1 - + 1 , - / . PsliceG length 3 unit)test V+ , - . 3 0 1 - + 1 , - / . PsliceG Gvector 3 unit)test V+ / A . 3 0 + 1 , - / A . , tail)slice4 Gvector 3 unit)test V+ - / . 3 0 , / 1 1= dup iota PsliceG subseq Gvector 3 unit)test V+ - / . 3 0 = , , / 1 1= dup iota PsliceG PsliceG subseq Gvector 3 unit)test = 1= (hello( PsliceG 3 must)fail )1= - (hello( PsliceG 3 must)fail , 1 (hello( PsliceG 3 must)fail

0 (cba( 3 0 (abcdef( - head)slice reverse 3 unit)test 0 A=/= 3 0 0 1 , - / A L R 3 1 0 4 3 reduce 3 unit)test 0 A=/= + 1 1 , L ,/ 1,= R,= . 3 0 + 1 , - / A L R . 1 0 4 3 accumulate 3 unit)test 0 L/ E+ 1 , / 1L . 3 0 E+ , , / / . 1 0 4 3 accumulate 3 unit)test 0 A=/= + 1 1 , L ,/ 1,= R,= . 3 0 + 1 , - / A L R . 1 0 4 3 accumulateK 3 unit)test 0 t 3 0 + 1 , - / A L R . dup 1 0 4 3 accumulateK nip eq: 3 unit)test 0 0 0 0 0 f = 1 , f f 1 ( f 3 0 0 3 0 0 orld( 3 0 0 3 0 0 3 1 3 1 1 0 3 0 , , 3 0 0 find 3 unit)test 3 find 3 unit)test (hello( ( orld( 3 0 ( orld( H 3 find 3 unit)test 3 0 , G 3 find 3 unit)test 3 0 1= G 3 find 3 unit)test

0 1 %?"#: e 3 0 (hello orld( (aeiou( 0 member: 3 curry find 3 unit)test 0 / %?"#: o 3 0 - (hello orld( (aeiou( 0 member: 3 curry find)from 3 unit)test 0 0 0 0 f f f 3 0 f 3 0 %?"#: %?"#: (abcd( 0 1= G nip 3 find)index 3 unit)test (abcd( 0 drop %?"#: e H 3 find)index 3 unit)test d 3 0 (abcdefg( 0 - H nip 3 find)index 3 unit)test d 3 0 (abcdefg( 0 drop %?"#: d H 3 find)index 3 unit)test

0 = %?"#: a 3 0 = (abcdef( 0 drop %?"#: a GH 3 find)index)from 3 unit)test 0 1 %?"#: b 3 0 = (abcdef( 0 drop %?"#: a G 3 find)index)from 3 unit)test

0 , %?"#: c 3 0 1 (abcdef( 0 drop %?"#: b G 3 find)index)from 3 unit)test 0 0 0 0 f f t t 3 3 3 3 0 0 0 0 1 , 0 0 0 0 3 member: 1 , 3 member: 1 , 3 member: 1 , 3 member: 3 3 3 3 unit)test unit)test unit)test unit)test

0 t 3 0 0 (hello( ( orld( 3 0 second 3 keep member)eq: 3 unit)test 0 / 3 0 %?"#: x (tuv xy8( Gvector index 3 unit)test 0 f 3 0 %?"#: x A (tuv xy8( Gvector index)from 3 unit)test 0 f 3 0 %?"#: a = (tuv xy8( Gvector index)from 3 unit)test 0 f 3 0 0 (?ello( + . =.RA 3 0 string: 3 all: 3 unit)test 0 t 3 0 0 3 0 3 all: 3 unit)test 0 t 3 0 0 (hi( t =.A 3 0 3 all: 3 unit)test 0 0 1 , - 3 3 0 0 1 / , A - L 3 0 / P 3 filter 3 unit)test 0 + / , L . 3 0 + 1 / , A - L . 0 , mod = H 3 filter 3 unit)test 0 0 - 3 3 0 0 1 , - 3 , 0 s ap P 3 curry filter 3 unit)test 0 V+ 1 , - . 3 0 V+ 1 / , A - L . clone 0 / P 3 filterK 3 unit)test 0 V+ / , L . 3 0 V+ 1 / , A - L . clone 0 , mod = H 3 filterK 3 unit)test 0 V+ - . 3 0 V+ 1 , - . clone , 0 s ap P 3 curry filterK 3 unit)test 0 (hello orld ho are you( 3 0 + (hello( ( orld( (ho ( (are( (you( . ( ( Foin 3 unit)test 0 (hello orld ho are you( 3 0 + (hello( ( orld( (ho ( (are( (you( . ( ( (( Foin)as 3 unit)test 0 (( 3 0 + . (( Foin 3 unit)test 0 (( 3 0 + . (( (( Foin)as 3 unit)test 0 + . 3 0 + . flip 3 unit)test 0 + (b( (e( . 3 0 1 + + (a( (b( (c( . + (d( (e( (f( . . flip nth 3 unit)test 0 + + 1 / . + , A . + - L . . 3 0 + + 1 , - . + / A L . . flip 3 unit)test 0 0 , - / 3 3 0 0 1 , - 3 1 0 2 3 curry map 3 unit)test 0 1 3 0 = 0 1 , 3 nth 3 unit)test 0 , 3 0 1 0 1 , 3 nth 3 unit)test 0 0 0 0 0 0 0 0 0 0 3 1 , 1 1 3 3 , - / 3 , - / 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 3 1 3 1 1 3 0 , , 0 0 , 3 append 3 append 3 append 3 0 / 3 append 3 + / . append 3 3 3 3 3 unit)test unit)test unit)test unit)test unit)test

0 (a( )1 append 3 must)fail 0 )1 (a( append 3 must)fail + t . 0 E+ = . + 1 . append byte)array: 3 unit)test

+ t . 0 E+ = . + 1 . prepend byte)array: 3 unit)test 0 0 3 3 0 1 0 3 remove 3 unit)test 0 0 3 3 0 1 0 1 3 remove 3 unit)test 0 0 - 1 1 3 3 0 , 0 - , 1 , 1 3 remove 3 unit)test 0 0 3 3 0 0 3 reverse 3 unit)test 0 0 1 3 3 0 0 1 3 reverse 3 unit)test 0 0 - , 1 3 3 0 0 1 , - 3 reverse 3 unit)test 0 0 0 0 0 f 0 0 0 0 3 3 1 3 0 3 , 3 3 f 0 0 3 = 0 3 0 0 head 3 unit)test 1 3 = head 3 unit)test 3 0 0 1 , - / 3 - head 3 unit)test 1 , - 3 - tail 3 unit)test 0 1 , - 3 , tail 3 unit)test

0 (blah( 3 0 (blahxx( , head4 3 unit)test 0 (xx( 3 0 (blahxx( , tail4 3 unit)test 0 t 3 0 (xxfoo( , head)slice (xxbar( , head)slice H 3 unit)test 0 t 3 0 (xxfoo( , head)slice (xxbar( , head)slice 0 hashcode 3 same: 3 unit)test 0 t 3 0 (xxfoo( , head)slice SEU@( barxx( , tail)slice4 H 3 unit)test 0 t 3 0 (xxfoo( , head)slice SEU@( barxx( , tail)slice4 0 hashcode 3 same: 3 unit)test 0 0 0 0 t t t f 3 3 3 3 0 0 0 0 0 0 + 0 1 1 1 3 , , , 0 1 3 3 . , 0 + 0 1 1 1 3 , - 3 sequenceH 3 unit)test , - . sequenceH 3 unit)test , - 3 sequenceH 3 unit)test sequenceH 3 unit)test

0 + 1 - , / . 3 0 + 1 , - / . clone 1 , pick exchange 3 unit)test 0 + (( (a( (aa( (aaa( . 3 0 / 0 %?"#: a PstringG 3 + . map)integers 3 unit)test 0 0 0 0 0 V+ V+ V+ V+ V+ . 3 . 3 . 3 (x( (y( 0 (f( 0 (f( 0 (f( . 3 0 (x( . V+ . clone removeK 3 unit)test V+ (f( . clone removeK 3 unit)test V+ (f( (f( . clone removeK 3 unit)test (f( V+ (f( (x( (f( . clone removeK 3 unit)test 3 0 (f( V+ (y( (f( (x( (f( . clone removeK 3 unit)test

0 V+ = 1 / A . 3 0 L iota Gvector , / pick delete)slice 3 unit)test 0 L Gvector , S pick delete)slice 3 must)fail 0 V+ . 3 0 L iota Gvector = L pick delete)slice 3 unit)test 0 + 1 , (a( (b( A L R . 3 0 + (a( (b( . , / + 1 , - / A L R . replace)slice 3 unit)test 0 + 1 , (a( (b( L R . 3 0 + (a( (b( . , A + 1 , - / A L R . replace)slice 3 unit)test 0 + 1 , (a( (b( / A L R . 3 0 + (a( (b( . , - + 1 , - / A L R .

replace)slice 3 unit)test 0 + 1 , - / A L R (a( (b( . 3 0 + (a( (b( . R R + 1 , - / A L R . replace)slice 3 unit)test 0 + (a( - . 3 0 + (a( . = , + 1 , - . replace)slice 3 unit)test 0 + 1 / U . 3 0 + 1 , - . clone 0 sq 3 mapK 3 unit)test 0 A 3 0 1 Gbignum + 1 A R . nth)unsafe 3 unit)test 0 A 3 0 1 Gbignum + 1 A R . nth)unsafe 3 unit)test 0 A 3 0 1 Gbignum (>u=====1>u=====A>u=====R( nth)unsafe 3 unit)test 0 SEU@( before`after( 3 0 (`( L 11 SEU@( before and after( replace)slice 3 unit)test 0 - (a( 3 0 + (a( (b( (c( (a( (d( . 0 (a( H 3 find)last 3 unit)test 0 f f 3 0 1== + 1 , - . 0 1 H 3 find)from 3 unit)test 0 f f 3 0 1== + 1 , - . 0 1 H 3 find)last)from 3 unit)test 0 f f 3 0 )1 + 1 , - . 0 1 H 3 find)from 3 unit)test 0 = 3 0 + (a( (b( (c( . + ("( (E( (%( . mismatch 3 unit)test 0 1 3 0 + (a( (b( (c( . + (a( (E( (%( . mismatch 3 unit)test 0 f 3 0 + (a( (b( (c( . + (a( (b( (c( . mismatch 3 unit)test 0 V+ . V+ . 3 0 + (a( (b( . + (a( (b( . drop)prefix 0 Gvector 3 bi9 3 unit)test 0 V+ (%( . V+ (c( . 3 0 + (a( (b( (%( . + (a( (b( (c( . drop)prefix 0 Gvector 3 bi9 3 unit)test 0 )1 1 (abc( PsliceG 3 must)fail 0 V+ (a( (b( . V+ . 3 0 + (M( (a( (b( . + (M( . drop)prefix 0 Gvector 3 bi9 3 unit)test 0 =.A + 1 , - . nth 3 0 no)method: 3 must)fail) ith 0 =.A (asdfasdf( nth 3 0 no)method: 3 must)fail) ith K ;athological case 0 (ihbye( 3 0 (hi( PreversedG (bye( append 3 unit)test 0 t 3 0 (hi( PreversedG SEU@( hi( PreversedG H 3 unit)test 0 t 3 0 (hi( PreversedG SEU@( hi( PreversedG H 3 unit)test 0 t 3 0 (hi( PreversedG SEU@( hi( PreversedG 0 hashcode 3 same: 3 unit)test 0 )1= (hi( (bye( copy 3 must)fail 0 1= (hi( (bye( copy 3 must)fail 0 V+ 1 , - A L . 3 0 - V+ 1 , - / A L . clone remove)nthK 3 unit)test

K erg7s random tester found this one 0 SEU@( 1,-/1,-/( 3 0 U PsbufG dup (1,-/( s ap push)all dup dup s ap push)all 3 unit)test 0 f 3 0 f V+ . like f V+ . like eq: 3 unit)test 0 V+ f f f . 3 0 - V+ . ne )sequence 3 unit)test 0 SEU@( >=>=>=( 3 0 - SEU@( ( ne )sequence 3 unit)test 0 0 0 0 0 0 = 3 0 f length 3 unit)test f first 3 must)fail - 3 0 - 1= iota nth 3 unit)test - 3 0 - 1= iota nth)unsafe 3 unit)test )- 1= iota nth 3 must)fail 11 1= iota nth 3 must)fail

0 f 3 0 f :first 3 unit)test 0 f 3 0 + . :first 3 unit)test 0 = 3 0 1= iota :first 3 unit)test 0 f 3 0 f :last 3 unit)test 0 f 3 0 + . :last 3 unit)test 0 U 3 0 1= iota :last 3 unit)test 0 0 0 0 0 0 0 0 0 )1Q=. = remove)nthK 3 must)fail (( 3 0 (( 0 %?"#: >s H 3 trim 3 unit)test (( 3 0 (( 0 %?"#: >s H 3 trim)head 3 unit)test (( 3 0 (( 0 %?"#: >s H 3 trim)tail 3 unit)test (( 3 0 ( ( 0 %?"#: >s H 3 trim)head 3 unit)test (( 3 0 ( ( 0 %?"#: >s H 3 trim)tail 3 unit)test (asdf( 3 0 ( asdf ( 0 %?"#: >s H 3 trim 3 unit)test (asdf ( 3 0 ( asdf ( 0 %?"#: >s H 3 trim)head 3 unit)test ( asdf( 3 0 ( asdf ( 0 %?"#: >s H 3 trim)tail 3 unit)test

0 -,S-A= 3 0 1== iota 0 sq 3 map)sum 3 unit)test 0 A= 3 0 1== iota 0 even: 3 count 3 unit)test 0 A= 3 0 1== iota 0 odd: 3 count 3 unit)test 0 0 0 0 + + + + (b( (a( (d( (d( (d( (b( (c( (a( . 3 (c( (b( (b( 0 + (d( (a( (c( 1 . . . 3 3 3 . 0 0 0 + + + + (a( = 1 - , - = (b( , 1 = 1 , (c( . + . + . + (d( (a( (a( (a( . nths 3 unit)test (b( (c( (d( . nths 3 unit)test (b( (c( (d( . nths 3 unit)test (b( (c( (d( . nths 3 unit)test

0 (dac( 3 0 + - = , . (abcd( nths 3 unit)test $U;&': bogus)hashcode ! I: bogus)hashcode hashcode4 ,drop = Gbignum ! 0 = 3 0 + $+ bogus)hashcode . . hashcode 3 unit)test 0 + , / L . + 1 - A R . 3 0 + 1 , - / A L R . 0 even: 3 partition 3 unit)test 0 + 1 - R . 3 0 , + 1 - A R . remove)nth 3 unit)test 0 + 1 - (M( A R . 3 0 (M( , + 1 - A R . insert)nth 3 unit)test 0 V+ = , . 3 0 (a( + (a( (b( (a( . indices 3 unit)test

0 (a<b( 3 0 (a( (b( (<( glue 3 unit)test 0 (5abc6( 3 0 (abc( (5( (6( surround 3 unit)test 0 (?'&&B( 3 0 (?'&&B( + )1 )1 )1 )1 )1 . + , , , , , , . 0 4 , 2 2 3 -map 3 unit)test + - 1 . 0 0 -array 3 -map 3 must)infer)as + - = . 0 0 -drop 3 -each 3 must)infer)as 0 V+ = - . 3 0 ("( + ("( (E( (%( ("( (C( . indices 3 unit)test 0 0 0 0 (asdf( iota 3 must)fail )1 iota 3 must)fail $+ iota)tuple + n 1= . . 3 0 1= iota 3 unit)test = 3 0 1= iota first 3 unit)test

0 (hi( - 3 0 + 1 , - / A L R S . 0 ?+ + - (hi( . . at 3 map)find 3 unit)test 0 f f 3 0 + 1 , - / A L R S . 0 ?+ + 11 (hi( . . at 3 map)find 3 unit)test US': make 0 + (a( 1 (b( 1 (c( . 3 0 1 + (a( (b( (c( . 0 0 dup < 3 0 < 3 interleave drop 3 + . make 3 unit)test 0 t 3 0 = array)capacity: 3 unit)test 0 f 3 0 )1 array)capacity: 3 unit)test 0 0 0 0 0 0 0 0 2lt2 2lt2 2lt2 2gt2 2gt2 2gt2 2eq2 2eq2 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 + + + + + + + + = = = 1 = = . 1 = = = 1 1 = + , = = = 1 1 = . . + . + . + . + . + = . PHG . + 1 = = = = + 3 1 1 1 . PHG 3 1 1 . PHG 3 = = = . PHG = = . PHG 3 = = . PHG 3 = = = . PHG unit)test , - . PHG 3 unit)test unit)test 3 unit)test unit)test unit)test 3 unit)test unit)test

0 + + + 1 (a( . + 1 (b( . . + + , (a( . + , (b( . . . 3 0 + 1 , . + (a( (b( . cartesian)product 3 unit)test 0 + . 0 stringGdigits sum 3 0 2 3 map)reduce 3 must)infer 0 + . 0 3 0 2 3 map)reduce 3 must)fail 0 / 3 0 + 1 1 . 0 1 2 3 0 2 3 map)reduce 3 unit)test 0 + . + . 0 0 stringGdigits product 3 bi9 2 3 0 2 3 ,map)reduce 3 must)infer 0 + . + . 0 2 3 0 2 3 ,map)reduce 3 must)fail 0 ,/ 3 0 + 1 , . + - / . 0 2 3 0 4 3 ,map)reduce 3 unit)test 0 0 + + 0 0 + / 3 0 A iota 0 3 supremum)by 3 unit)test = 3 0 A iota 0 3 infimum)by 3 unit)test (bar( . 0 + (bar( (ba8( (qux( . 0 length 3 supremum)by 3 unit)test (bar( . 0 + (bar( (ba8( (qux( . 0 length 3 infimum)by 3 unit)test + (foo( . 3 0 + + (foo( . + (bar( . . 0 first 3 supremum)by 3 unit)test + (bar( . 3 0 + + (foo( . + (bar( . . 0 first 3 infimum)by 3 unit)test ), 1 . 0 ), + 1 , - . 0 over T 3 supremum)by 3 unit)test

+ ), - . 0 ), + 1 , - . 0 over T 3 infimum)by 3 unit)test 0 + = = ,AA . 3 0 + + = = = . + UA ,AA UA . + ,1A UA UA . + UA 1-A ,AA . + 1-A UA 1-A . + 1-A ,AA ,AA . + = = ,AA . + = UA UA . + = ,AA ,1A . + 1-A = UA . + ,AA = 1RA . . 0 + = = ,AA . distance 3 infimum)by 3 unit)test K %opyright 5%6 ,==A< ,=11 Slava ;estov< Caniel 'hrenberg. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors kernel kernel.private math math.order math.private slots.private ! IN: sequences IIMIN: sequence G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: length 5 seq )) n 6 flushable set)length 5 n seq )) 6 nth 5 n seq )) elt 6 flushable set)nth 5 elt n seq )) 6 ne )sequence 5 len seq )) ne seq 6 flushable ne )resi8able 5 len seq )) ne seq 6 flushable like 5 seq exemplar )) ne seq 6 flushable clone)like 5 seq exemplar )) ne seq 6 flushable

: ne )like 5 len exemplar quot )) seq 6 over 0 0 ne )sequence 3 dip call 3 dip like ! inline I: sequence like drop ! inline G'N'#I%: lengthen 5 n seq )) 6 G'N'#I%: shorten 5 n seq )) 6 I: sequence lengthen ,dup length G 0 set)length 3 0 ,drop 3 if ! inline I: sequence shorten ,dup length P 0 set)length 3 0 ,drop 3 if ! inline : empty: 5 seq )) : 6 length = H ! inline : if)empty 5 ..a seq quot1: 5 ..a )) ..b 6 quot,: 5 ..a seq )) ..b 6 )) ..b 6 0 dup empty: 3 0 0 drop 3 prepose 3 0 3 tri4 if ! inline : hen)empty 5 seq quot )) 6 0 3 if)empty ! inline

: unless)empty 5 seq quot )) 6 0 3 s ap if)empty ! inline : delete)all 5 seq )) 6 = s ap set)length ! : : : : first 5 seq )) first 6 second 5 seq )) second third 5 seq )) third 6 fourth 5 seq )) fourth = 6 , 6 s 1 s ap nth ! s ap nth ap nth ! s ap nth inline ! inline inline ! inline

: set)first 5 first seq )) 6 = s ap set)nth ! inline

: set)second 5 second seq )) 6 1 s ap set)nth ! inline : set)third 5 third seq )) 6 , s ap set)nth ! inline : set)fourth 5 fourth seq )) 6 - s ap set)nth ! inline : push 5 elt seq )) 6 0 length 3 0 set)nth 3 bi ! '##B#: bounds)error index seq ! G'N'#I%Z bounds)check: 1 5 n seq )) : 6 I: integer bounds)check: 5 n seq )) : 6 dupd length P 0 = GH 3 0 drop f 3 if ! inline : bounds)check 5 n seq )) n seq 6 ,dup bounds)check: 0 bounds)error 3 unless ! inline IIMIN: immutable)sequence '##B#: immutable element index sequence ! I: immutable)sequence set)nth immutable ! INS$"N%': immutable)sequence sequence P;#IV"$' : array)nth 5 n array )) elt 6 s ap , fixnum2fast slot ! inline : set)array)nth 5 elt n array )) 6 s ap , fixnum2fast set)slot ! inline : dispatch 5 n array )) 6 array)nth call ! G'N'#I%: resi8e 5 n seq )) ne seq 6 flushable K Unsafe sequence protocol for inner loops G'N'#I%: nth)unsafe 5 n seq )) elt 6 flushable G'N'#I%: set)nth)unsafe 5 elt n seq )) 6 I: sequence nth bounds)check nth)unsafe ! inline I: sequence set)nth bounds)check set)nth)unsafe ! inline I: sequence nth)unsafe nth ! inline I: sequence set)nth)unsafe set)nth ! inline : change)nth)unsafe 5 i seq quot )) 6 0 0 nth)unsafe 3 dip call 3 -keep drop set)nth)unsafe ! inline ;#IV"$'G K $he f obFect supports the sequence protocol trivially I: f length drop = ! inline I: f nth)unsafe nip ! inline I: f like drop 0 f 3 hen)empty ! inline INS$"N%': f immutable)sequence K Integer sequences $U;&': iota)tuple + n integer read)only . ! '##B#: non)negative)integer)expected n !

: iota 5 n )) iota 6 dup = P 0 non)negative)integer)expected 3 > iota)tuple boa ! inline I: iota)tuple length nGG ! inline I: iota)tuple nth)unsafe drop ! inline INS$"N%': iota)tuple immutable)sequence P;#IV"$' : : : : first)unsafe 5 seq )) first 6 second)unsafe 5 seq )) second third)unsafe 5 seq )) third 6 fourth)unsafe 5 seq )) fourth = 6 , 6 s 1 s -

hen

ap nth)unsafe ! s ap nth)unsafe ap nth)unsafe ! s ap nth)unsafe

inline ! inline inline ! inline

: first,)unsafe 5 seq )) first second 6 0 first)unsafe 3 0 second)unsafe 3 bi ! inline : first-)unsafe 5 seq )) first second third 6 0 first,)unsafe 3 0 third)unsafe 3 bi ! inline : first/)unsafe 5 seq )) first second third fourth 6 0 first-)unsafe 3 0 fourth)unsafe 3 bi ! inline : exchange)unsafe 5 m n seq )) 6 0 0 nth)unsafe 3 curry bi9 3 0 0 set)nth)unsafe 3 curry bi9 3 -bi ! inline : 5head6 5 seq n )) from to seq 6 0 = 3 ,dip s ap ! inline : 5tail6 5 seq n )) from to seq 6 s ap 0 length 3 keep ! inline : from)end 5 seq n )) seq n7 6 0 dup length 3 dip ) ! inline : 51sequence6 5 obF seq )) seq 6 0 = s ap set)nth)unsafe 3 keep ! inline : 5,sequence6 5 obF1 obF, seq )) seq 6 0 1 s ap set)nth)unsafe 3 keep 51sequence6 ! inline : 5-sequence6 5 obF1 obF, obF- seq )) seq 6 0 , s ap set)nth)unsafe 3 keep 5,sequence6 ! inline : 5/sequence6 5 obF1 obF, obF- obF/ seq )) seq 6 0 - s ap set)nth)unsafe 3 keep 5-sequence6 ! inline ;#IV"$'G : 1sequence 5 obF exemplar )) seq 6 1 s ap 0 51sequence6 3 ne )like ! inline : ,sequence 5 obF1 obF, exemplar )) seq 6 , s ap 0 5,sequence6 3 ne )like ! inline : -sequence 5 obF1 obF, obF- exemplar )) seq 6 - s ap 0 5-sequence6 3 ne )like ! inline : /sequence 5 obF1 obF, obF- obF/ exemplar )) seq 6 / s ap 0 5/sequence6 3 ne )like ! inline

: first, 5 seq )) first second 6 1 s ap bounds)check nip first,)unsafe ! inline : first- 5 seq )) first second third 6 , s ap bounds)check nip first-)unsafe ! inline : first/ 5 seq )) first second third fourth 6 - s ap bounds)check nip first/)unsafe ! inline : :nth 5 n seq )) eltQf 6 ,dup bounds)check: 0 nth)unsafe 3 0 ,drop f 3 if ! inline : :set)nth 5 elt n seq )) 6 ,dup bounds)check: 0 set)nth)unsafe 3 0 -drop 3 if ! inline : :first 5 seq )) eltQf 6 = s ap :nth ! inline : :second 5 seq )) eltQf 6 1 s ap :nth ! inline : :last 5 seq )) eltQf 6 0 length 1 ) 3 keep over = P 0 ,drop f 3 0 nth)unsafe 3 if ! inline IIMIN: virtual)sequence G'N'#I%: virtual)exemplar 5 seq )) seq7 6 G'N'#I%: virtual9 5 n seq )) n7 seq7 6 I: I: I: I: I: I: virtual)sequence virtual)sequence virtual)sequence virtual)sequence virtual)sequence virtual)sequence nth virtual9 nth ! inline set)nth virtual9 set)nth ! inline nth)unsafe virtual9 nth)unsafe ! inline set)nth)unsafe virtual9 set)nth)unsafe ! inline like virtual)exemplar like ! inline ne )sequence virtual)exemplar ne )sequence ! inline

INS$"N%': virtual)sequence sequence K " reversal of an underlying sequence. $U;&': reversed + seq read)only . ! %: PreversedG reversed I: reversed virtual)exemplar seqGG ! inline I: reversed virtual9 seqGG 0 length s ap ) 1 ) 3 keep ! inline I: reversed length seqGG length ! inline INS$"N%': reversed virtual)sequence K " slice of another sequence. $U;&': slice + from read)only . + to read)only . + seq read)only . ! : collapse)slice 5 m n slice )) m7 n7 seq 6 0 fromGG 3 0 seqGG 3 bi 0 0 2 3 curry bi9 3 dip ! inline '##B#: slice)error from to seq reason ! : check)slice)error 5 from to seq : string )) from to seq 6 0 slice)error 3 curry hen ! inline : check)slice 5 from to seq )) from to seq 6 -dup 0 ,drop = P (start P =( check)slice)error 3

0 0 drop 3 ,dip length G (end G sequence( check)slice)error 3 0 drop G (start G end( check)slice)error 3 -tri ! inline P;#IV"$' : Pslice)unsafeG 5 from to seq )) slice 6 dup slice: 0 collapse)slice 3 hen slice boa ! inline ;#IV"$'G : PsliceG 5 from to seq )) slice 6 check)slice Pslice)unsafeG ! inline I: slice virtual)exemplar seqGG ! inline I: slice virtual9 0 fromGG 2 3 0 seqGG 3 bi ! inline I: slice length 0 toGG 3 0 fromGG 3 bi ) ! inline : short 5 seq n )) seq n7 6 over length min ! inline : head)slice 5 seq n )) slice 6 5head6 PsliceG ! inline : tail)slice 5 seq n )) slice 6 5tail6 PsliceG ! inline : rest)slice 5 seq )) slice 6 1 tail)slice ! inline : head)slice4 5 seq n )) slice 6 from)end head)slice ! inline : tail)slice4 5 seq n )) slice 6 from)end tail)slice ! inline : but)last)slice 5 seq )) slice 6 1 head)slice4 ! inline INS$"N%': slice virtual)sequence K Bne element repeated many times $U;&': repetition + len read)only . + elt read)only . ! %: PrepetitionG repetition I: repetition length lenGG ! inline I: repetition nth)unsafe nip eltGG ! inline INS$"N%': repetition immutable)sequence P;#IV"$' '##B#: integer)length)expected obF ! : check)length 5 n )) n 6 dup integer: 0 integer)length)expected 3 unless ! inline $U;&': copy)state + src)i read)only . + src read)only . + dst)i read)only . + dst read)only . ! %: PcopyG copy)state : 55copy66 5 n copy )) 6

0 0 src)iGG 2 3 0 srcGG 3 bi nth)unsafe 3 0 0 dst)iGG 2 3 0 dstGG 3 bi set)nth)unsafe 3 ,bi ! inline : 5copy6 5 n copy )) dst 6 over = PH 0 nip dstGG 3 0 0 1 ) 3 dip 0 55copy66 3 0 5copy6 3 ,bi 3 if ! inline recursive : subseqGcopy 5 from to seq )) n copy 6 0 over ) check)length s ap 3 dip -dup nip ne )sequence = s ap PcopyG ! inline : bounds)check)head 5 n seq )) n seq 6 over = P 0 bounds)error 3 hen ! inline : check)copy 5 src n dst )) src n dst 6 -dup bounds)check)head 0 s ap length 2 3 dip lengthen ! inline : copy)unsafe 5 src i dst )) 6 ZK $he check)length call forces partial dispatch 0 0 length check)length = 3 keep 3 ,dip PcopyG 5copy6 drop ! inline ;#IV"$'G : subseq 5 from to seq )) subseq 6 0 check)slice subseqGcopy 5copy6 3 keep like ! : head 5 seq n )) headseq 6 5head6 subseq ! : tail 5 seq n )) tailseq 6 5tail6 subseq ! : rest 5 seq )) tailseq 6 1 tail ! : head4 5 seq n )) headseq 6 from)end head ! : tail4 5 seq n )) tailseq 6 from)end tail ! : but)last 5 seq )) headseq 6 1 head4 ! : copy 5 src i dst )) 6 check)copy copy)unsafe ! inline I: sequence clone)like 0 dup length 3 dip ne )sequence 0 = s ap copy)unsafe 3 keep ! inline I: immutable)sequence clone)like like ! inline : push)all 5 src dst )) 6 0 length 3 0 copy 3 bi ! inline P;#IV"$' : 5append6 5 seq1 seq, accum )) accum 6 0 0 over length 3 dip copy)unsafe 3 0 = s ap copy)unsafe 3 0 3 tri ! inline ;#IV"$'G : append)as 5 seq1 seq, exemplar )) ne seq 6 0 ,dup 0 length 3 bi9 2 3 dip 0 5append6 3 ne )like ! inline

: -append)as 5 seq1 seq, seq- exemplar )) ne seq 6 0 -dup 0 length 3 tri9 2 2 3 dip 0 0 0 ,over 0 length 3 bi9 2 3 dip copy)unsafe 3 0 5append6 3 bi 3 ne )like ! inline : append 5 seq1 seq, )) ne seq 6 over append)as ! : prepend)as 5 seq1 seq, exemplar )) ne seq 6 s apd append)as ! inline : prepend 5 seq1 seq, )) ne seq 6 over prepend)as ! : -append 5 seq1 seq, seq- )) ne seq 6 pick -append)as ! : surround 5 seq1 seq, seq- )) ne seq 6 s apd -append ! inline : glue 5 seq1 seq, seq- )) ne seq 6 s ap -append ! inline : change)nth 5 ..a i seq quot: 5 ..a elt )) ..b ne elt 6 )) ..b 6 0 0 nth 3 dip call 3 -keep drop set)nth)unsafe ! inline : min)length 5 seq1 seq, )) n 6 0 length 3 bi9 min ! inline : max)length 5 seq1 seq, )) n 6 0 length 3 bi9 max ! inline P;#IV"$' : 55each66 5 seq )) n quot 6 0 length 3 keep 0 nth)unsafe 3 curry ! inline : 5each6 5 seq quot )) n quot7 6 0 55each66 3 dip compose ! inline : 5each)index6 5 seq quot )) n quot7 6 0 55each66 0 keep 3 curry 3 dip compose ! inline : 5collect6 5 quot into )) quot7 6 0 0 keep 3 dip set)nth)unsafe 3 ,curry ! inline : collect 5 n quot into )) 6 5collect6 each)integer ! inline : map)into 5 seq quot into )) 6 0 5each6 3 dip collect ! inline : ,nth)unsafe 5 n seq1 seq, )) elt1 elt, 6 0 nth)unsafe 3 bi)curry9 bi ! inline : 55,each66 5 seq1 seq, )) n quot 6 0 min)length 3 ,keep 0 ,nth)unsafe 3 ,curry ! inline : 5,each6 5 seq1 seq, quot )) n quot7 6 0 55,each66 3 dip compose ! inline : -nth)unsafe 5 n seq1 seq, seq- )) elt1 elt, elt- 6 0 nth)unsafe 3 tri)curry9 tri ! inline : 5-each6 5 seq1 seq, seq- quot )) n quot7 6 0 0 0 length 3 tri9 min min 3 0 0 -nth)unsafe 3 -curry 3 -bi

3 dip compose ! inline : finish)find 5 i seq )) i elt 6 over 0 dupd nth)unsafe 3 0 drop f 3 if ! inline : 5find6 5 seq quot quot7 )) i elt 6 pick 0 0 5each6 3 dip call 3 dip finish)find ! inline : 5find)from6 5 n seq quot quot7 )) i elt 6 0 ,dup bounds)check: 3 ,dip 0 5find6 3 ,curry 0 ,drop f f 3 if ! inline : 5find)index6 5 seq quot quot7 )) i elt 6 pick 0 0 5each)index6 3 dip call 3 dip finish)find ! inline : 5find)index)from6 5 n seq quot quot7 )) i elt 6 0 ,dup bounds)check: 3 ,dip 0 5find)index6 3 ,curry 0 ,drop f f 3 if ! inline : 5accumulate6 5 seq identity quot )) identity seq quot 6 s apd 0 curry keep 3 curry ! inline ;#IV"$'G : each 5 ... seq quot: 5 ... x )) ... 6 )) ... 6 5each6 each)integer ! inline : reduce 5 ... seq identity quot: 5 ... prev elt )) ... next 6 )) ... result 6 s apd each ! inline : map)integers 5 ... len quot: 5 ... i )) ... elt 6 exemplar )) ... ne seq 6 0 over 3 dip 0 0 collect 3 keep 3 ne )like ! inline : map)as 5 ... seq quot: 5 ... elt )) ... ne elt 6 exemplar )) ... ne seq 6 0 5each6 3 dip map)integers ! inline : map 5 ... seq quot: 5 ... elt )) ... ne elt 6 )) ... ne seq 6 over map)as ! inline : replicate)as 5 ... len quot: 5 ... )) ... ne elt 6 exemplar )) ... ne seq 6 0 0 drop 3 prepose 3 dip map)integers ! inline : replicate 5 ... len quot: 5 ... )) ... ne elt 6 )) ... ne seq 6 + . replicate)as ! inline : mapK 5 ... seq quot: 5 ... elt )) ... ne elt 6 )) ... seq 6 over 0 map)into 3 keep ! inline : accumulate)as 5 ... seq identity quot: 5 ... prev elt )) ... next 6 exemplar )) ... final ne seq 6 0 5accumulate6 3 dip map)as ! inline : accumulate 5 ... seq identity quot: 5 ... prev elt )) ... next 6 )) ... final ne seq 6 pick accumulate)as ! inline : accumulateK 5 ... seq identity quot: 5 ... prev elt )) ... next 6 )) ... final seq 6

5accumulate6 mapK ! inline : ,each 5 ... seq1 seq, quot: 5 ... elt1 elt, )) ... 6 )) ... 6 5,each6 each)integer ! inline : ,reduce 5 ... seq1 seq, identity quot: 5 ... prev elt1 elt, )) ... next 6 )) ... result 6 0 )rot 3 dip ,each ! inline : ,map)as 5 ... seq1 seq, quot: 5 ... elt1 elt, )) ... ne elt 6 exemplar )) ... ne seq 6 0 5,each6 3 dip map)integers ! inline : ,map 5 ... seq1 seq, quot: 5 ... elt1 elt, )) ... ne elt 6 )) ... ne seq 6 pick ,map)as ! inline : ,all: 5 ... seq1 seq, quot: 5 ... elt1 elt, )) ... : 6 )) ... : 6 5,each6 all)integers: ! inline : -each 5 ... seq1 seq, seq- quot: 5 ... elt1 elt, elt- )) ... 6 )) ... 6 5-each6 each)integer ! inline : -map)as 5 ... seq1 seq, seq- quot: 5 ... elt1 elt, elt- )) ... ne elt 6 exemplar )) ... ne seq 6 0 5-each6 3 dip map)integers ! inline : -map 5 ... seq1 seq, seq- quot: 5 ... elt1 elt, elt- )) ... ne elt 6 )) ... ne seq 6 0 pick 3 dip s ap -map)as ! inline : find)from 5 ... n seq quot: 5 ... elt )) ... : 6 )) ... i elt 6 0 5find)integer6 3 5find)from6 ! inline : find 5 ... seq quot: 5 ... elt )) ... : 6 )) ... i elt 6 0 find)integer 3 5find6 ! inline : find)last)from 5 ... n seq quot: 5 ... elt )) ... : 6 )) ... i elt 6 0 nip find)last)integer 3 5find)from6 ! inline : find)last 5 ... seq quot: 5 ... elt )) ... : 6 )) ... i elt 6 0 0 1 ) 3 dip find)last)integer 3 5find6 ! inline : find)index)from 5 ... n seq quot: 5 ... elt i )) ... : 6 )) ... i elt 6 0 5find)integer6 3 5find)index)from6 ! inline : find)index 5 ... seq quot: 5 ... elt i )) ... : 6 )) ... i elt 6 0 find)integer 3 5find)index6 ! inline : all: 5 ... seq quot: 5 ... elt )) ... : 6 )) ... : 6 5each6 all)integers: ! inline : push)if 5 ..a elt quot: 5 ..a elt )) ..b : 6 accum )) ..b 6 0 keep 3 dip rot 0 push 3 0 ,drop 3 if ! inline : selector)for 5 quot exemplar )) selector accum 6 0 length 3 keep ne )resi8able 0 0 push)if 3 ,curry 3 keep ! inline : selector 5 quot )) selector accum 6 V+ . selector)for ! inline : filter)as 5 ... seq quot: 5 ... elt )) ... : 6 exemplar )) ... subseq 6 dup 0 selector)for 0 each 3 dip 3 curry dip like ! inline

: filter 5 ... seq quot: 5 ... elt )) ... : 6 )) ... subseq 6 over filter)as ! inline : push)either 5 ..a elt quot: 5 ..a elt )) ..b : 6 accum1 accum, )) ..b 6 0 keep s ap 3 ,dip : push ! inline : ,selector 5 quot )) selector accum1 accum, 6 V+ . clone V+ . clone 0 0 push)either 3 -curry 3 ,keep ! inline : partition 5 ... seq quot: 5 ... elt )) ... : 6 )) ... trueseq falseseq 6 over 0 ,selector 0 each 3 ,dip 3 dip 0 like 3 curry bi9 ! inline : collector)for 5 quot exemplar )) quot7 vec 6 0 length 3 keep ne )resi8able 0 0 push 3 curry compose 3 keep ! inline : collector 5 quot )) quot7 vec 6 V+ . collector)for ! inline : produce)as 5 ..a pred: 5 ..a )) ..b : 6 quot: 5 ..b )) ..a obF 6 exemplar )) ..b seq 6 dup 0 collector)for 0 hile 3 dip 3 curry dip like ! inline : produce 5 ..a pred: 5 ..a )) ..b : 6 quot: 5 ..b )) ..a obF 6 )) ..b seq 6 + . produce)as ! inline : follo 5 ... obF quot: 5 ... prev )) ... resultQf 6 )) ... seq 6 0 dup 3 s ap 0 keep 3 curry produce nip ! inline : each)index 5 ... seq quot: 5 ... elt index )) ... 6 )) ... 6 5each)index6 each)integer ! inline : interleave 5 ... seq bet een quot: 5 ... elt )) ... 6 )) ... 6 pick empty: 0 -drop 3 0 0 0 drop first)unsafe 3 dip call 3 0 0 rest)slice 3 ,dip 0 bi4 3 ,curry each 3 -bi 3 if ! inline : map)index 5 ... seq quot: 5 ... elt index )) ... ne elt 6 )) ... ne seq 6 0 dup length iota 3 dip ,map ! inline : reduce)index 5 ... seq identity quot: 5 ... prev elt index )) ... next 6 )) ... result 6 s apd each)index ! inline : index 5 obF seq )) n 6 0 H 3 ith find drop ! : index)from 5 obF i seq )) n 6 rot 0 H 3 curry find)from drop ! : last)index 5 obF seq )) n 6 0 H 3 ith find)last drop ! : last)index)from 5 obF i seq )) n 6 rot 0 H 3 curry find)last)from drop ! P;#IV"$' : 5indices6 5 elt i obF accum )) 6 0 s ap 0 H 3 dip 3 dip 0 push 3 ,curry hen ! inline

;#IV"$'G : indices 5 obF seq )) indices 6 s ap V+ . clone 0 0 5indices6 3 ,curry each)index 3 keep ! P;#IV"$' : nths)unsafe 5 indices seq )) seq7 6 0 0 nth)unsafe 3 curry 3 keep map)as ! ;#IV"$'G : nths 5 indices seq )) seq7 6 0 0 nth 3 curry 3 keep map)as ! : any: 5 ... seq quot: 5 ... elt )) ... : 6 )) ... : 6 find drop Gboolean ! inline : member: 5 elt seq )) : 6 0 H 3 ith any: ! : member)eq: 5 elt seq )) : 6 0 eq: 3 ith any: ! : remove 5 elt seq )) ne seq 6 0 H not 3 ith filter ! : remove)eq 5 elt seq )) ne seq 6 0 eq: not 3 ith filter ! : sift 5 seq )) ne seq 6 0 3 filter ! : harvest 5 seq )) ne seq 6 0 empty: not 3 filter ! P;#IV"$' : mismatch)unsafe 5 n seq1 seq, )) i 6 0 ,nth)unsafe H not 3 ,curry find)integer ! inline ;#IV"$'G : mismatch 5 seq1 seq, )) i 6 0 min)length 3 ,keep mismatch)unsafe ! inline I: sequence PHG 0 mismatch 3 ,keep pick 0 ,nth)unsafe PHG 3 0 0 length 3 compare nip 3 if ! : sequenceH 5 seq1 seq, )) : 6 ,dup 0 length 3 bi9 dupd H 0 )rot mismatch)unsafe not 3 0 -drop f 3 if ! inline '##B#: assert)sequence got expected ! : assert)sequenceH 5 a b )) 6 ,dup sequenceH 0 ,drop 3 0 assert)sequence 3 if ! P;#IV"$'

: sequence)hashcode)step 5 oldhash ne part )) ne hash 6 integerGfixnum s ap 0 0 ), fixnum)shift)fast 3 0 A fixnum)shift)fast 3 bi fixnum2fast fixnum2fast 3 keep fixnum)bitxor ! inline ;#IV"$'G : sequence)hashcode 5 n seq )) x 6 0 = 3 ,dip 0 hashcode4 sequence)hashcode)step 3 ith each ! inline

I: reversed equal: over reversed: 0 sequenceH 3 0 ,drop f 3 if ! I: slice equal: over slice: 0 sequenceH 3 0 ,drop f 3 if ! : move 5 to from seq )) 6 ,over H 0 -drop 3 0 0 nth s ap 3 0 set)nth 3 bi 3 if ! inline P;#IV"$' : move)unsafe 5 to from seq )) 6 ,over H 0 -drop 3 0 0 nth)unsafe s ap 3 0 set)nth)unsafe 3 bi 3 if ! inline : 5filterK6 5 ... quot: 5 ... elt )) ... : 6 store scan seq )) ... 6 ,dup length P 0 0 move)unsafe 3 -keep 0 nth)unsafe pick call 0 1 2 3 hen 3 ,keep 0 1 2 3 dip 5filterK6 3 0 nip set)length drop 3 if ! inline recursive ;#IV"$'G : filterK 5 ... seq quot: 5 ... elt )) ... : 6 )) ... seq 6 s ap 0 0 = = 3 dip 5filterK6 3 keep ! inline : removeK 5 elt seq )) seq 6 0 H not 3 ith filterK ! : remove)eqK 5 elt seq )) seq 6 0 eq: not 3 ith filterK ! : prefix 5 seq elt )) ne seq 6 over 0 over length 1 2 3 dip 0 51sequence6 0 1 s ap copy)unsafe 3 keep 3 ne )like ! : suffix 5 seq elt )) ne seq 6 over 0 over length 1 2 3 dip 0 0 0 over length 3 dip set)nth)unsafe 3 keep 0 = s ap copy)unsafe 3 keep 3 ne )like ! : suffixK 5 seq elt )) seq 6 over push ! inline : appendK 5 seq1 seq, )) seq1 6 over push)all ! inline : last 5 seq )) elt 6 0 length 1 ) 3 keep

over = P 0 bounds)error 3 0 nth)unsafe 3 if ! inline P;#IV"$' : last)unsafe 5 seq )) elt 6 0 length 1 ) 3 0 nth)unsafe 3 bi ! inline ;#IV"$'G : set)last 5 elt seq )) 6 0 length 1 ) 3 keep over = P 0 bounds)error 3 0 set)nth)unsafe 3 if ! inline : pop4 5 seq )) 6 0 length 1 ) 3 0 shorten 3 bi ! P;#IV"$' : move)back ard 5 shift from to seq )) 6 ,over H 0 /drop 3 0 0 0 ,over 2 pick 3 dip move)unsafe 0 1 2 3 dip 3 keep move)back ard 3 if ! : move)for ard 5 shift from to seq )) 6 ,over H 0 /drop 3 0 0 0 pick 0 dup dup 3 dip 2 s ap 3 dip move)unsafe 1 ) 3 keep move)for ard 3 if ! : 5open)slice6 5 shift from to seq : )) 6 0 0 0 1 ) 3 bi9 3 dip move)for ard 3 0 0 over ) 3 ,dip move)back ard 3 if ! : open)slice 5 shift from seq )) 6 pick = H 0 -drop 3 0 pick over length 2 over 0 pick = G 0 0 length 3 keep 3 dip 5open)slice6 3 ,dip set)length 3 if ! ;#IV"$'G : delete)slice 5 from to seq )) 6 check)slice 0 over 0 ) 3 dip 3 dip open)slice ! : remove)nthK 5 n seq )) seq 6 0 0 dup 1 2 3 dip delete)slice 3 keep ! : snip 5 from to seq )) head tail 6 0 s ap head 3 0 s ap tail 3 bi)curry bi4 ! inline : snip)slice 5 from to seq )) head tail 6 0 s ap head)slice 3 0 s ap tail)slice 3 bi)curry bi4 ! inline

: replace)slice 5 ne from to seq )) seq7 6 snip)slice surround ! : remove)nth 5 n seq )) seq7 6 0 0 dup 1 2 3 dip snip)slice 3 keep append)as ! : pop 0 0 0 5 seq )) elt length 1 ) 3 0 nth)unsafe bounds)error 6 keep over = GH 3 0 shorten 3 ,bi 3 3 if !

: exchange 5 m n seq )) 6 0 nip bounds)check ,drop 3 0 bounds)check -drop 3 0 exchange)unsafe 3 -tri ! : midpoint9 5 seq )) n 6 length ,Q ! inline : reverseK 5 seq )) seq 6 0 0 midpoint9 3 0 length 3 0 3 tri 0 0 over ) 1 ) 3 dip exchange)unsafe 3 ,curry each)integer 3 keep ! : reverse 5 seq )) ne seq 6 0 dup 0 length 3 keep ne )sequence 0 = s ap copy)unsafe 3 keep reverseK 3 keep like ! : sum)lengths 5 seq )) n 6 = 0 length 2 3 reduce ! : concat)as 5 seq exemplar )) ne seq 6 s ap 0 + . 3 0 0 sum)lengths over ne )resi8able 3 keep 0 appendK 3 each 3 if)empty s ap like ! : concat 5 seq )) ne seq 6 0 + . 3 0 dup first concat)as 3 if)empty ! P;#IV"$' : Foined)length 5 seq glue )) n 6 0 0 sum)lengths 3 0 length 1 0)3 3 bi 3 dip length 4 2 ! ;#IV"$'G : Foin)as 5 seq glue exemplar )) ne seq 6 over empty: 0 nip concat)as 3 0 0 ,dup Foined)length over ne )resi8able 0 0 0 push)all 3 ,curry 3 0 nip 0 push)all 3 curry 3 ,bi interleave 3 keep 3 dip like 3 if !

: Foin 5 seq glue )) ne seq 6 dup Foin)as ! inline : padding 0 0 0 3 dip 5 ... seq n elt quot: 5 ... seq1 seq, )) ... ne seq 6 )) ... ne seq 6 over length 0)3 dup = H 0 drop 3 3 dip PrepetitionG 3 curry compose if ! inline

: pad)head 5 seq n elt )) padded 6 0 s ap dup append)as 3 padding ! : pad)tail 5 seq n elt )) padded 6 0 append 3 padding ! : : : : shorter: 5 seq1 seq, )) : 6 0 length 3 bi9 P ! longer: 5 seq1 seq, )) : 6 0 length 3 bi9 G ! shorter 5 seq1 seq, )) seq 6 0 0 length 3 bi9 PH 3 ,keep : ! inline longer 5 seq1 seq, )) seq 6 0 0 length 3 bi9 GH 3 ,keep : ! inline

: head: 5 seq begin )) : 6 ,dup shorter: 0 ,drop f 3 0 0 nip 3 0 length head)slice 3 ,bi sequenceH 3 if ! : tail: 5 seq end )) : 6 ,dup shorter: 0 ,drop f 3 0 0 nip 3 0 length tail)slice4 3 ,bi sequenceH 3 if ! : cut)slice 5 seq n )) before)slice after)slice 6 0 head)slice 3 0 tail)slice 3 ,bi ! inline : insert)nth 5 elt n seq )) seq7 6 s ap cut)slice 0 s ap suffix 3 dip append ! : halves 5 seq )) first)slice second)slice 6 dup midpoint9 cut)slice ! inline P;#IV"$' : nth,)unsafe 5 n seq )) a b 6 0 nth)unsafe 3 0 0 1 2 3 dip nth)unsafe 3 ,bi ! inline : nth-)unsafe 5 n seq )) a b c 6 0 nth,)unsafe 3 0 0 , 2 3 dip nth)unsafe 3 ,bi ! inline : 5binary)reduce6 5 ... seq start quot: 5 ... elt1 elt, )) ... ne elt 6 from length )) ... value 6 ZK Je can7t use case here since combinators depends on ZK sequences dup / P 0 integerGfixnum + 0 ,drop nip 3 0 ,nip s ap nth)unsafe 3 0 )rot 0 drop s ap nth,)unsafe 3 dip call 3 0 )rot 0 drop s ap nth-)unsafe 3 dip bi9 3

. dispatch 3 0 0 ,Q 3 0 over ) 3 bi 0 ,dup 2 3 dip 0 5binary)reduce6 3 0 ,curry 3 curry ,bi9 pick 0 -bi 3 dip call 3 if ! inline recursive ;#IV"$'G : binary)reduce 5 ... seq start quot: 5 ... elt1 elt, )) ... ne elt 6 )) ... value 6 pick length = max = s ap 5binary)reduce6 ! inline : cut 5 seq n )) before after 6 0 head 3 0 tail 3 ,bi ! : cut4 5 seq n )) before after 6 0 head4 3 0 tail4 3 ,bi ! P;#IV"$' : 5start6 5 subseq seq n length )) subseq seq : 6 0 0 -dup 3 dip 0 2 s ap nth)unsafe 3 keep rot nth)unsafe H 3 all)integers: nip ! inline ;#IV"$'G : start4 5 subseq seq n )) i 6 pick length 0 pick length s ap ) 1 2 3 keep 0 5start6 3 curry 5find)integer6 ,nip ! : start 5 subseq seq )) i 6 = start4 ! inline : subseq: 5 subseq seq )) : 6 start Gboolean ! : drop)prefix 5 seq1 seq, )) slice1 slice, 6 ,dup mismatch 0 ,dup min)length 3 unless4 0 tail)slice 3 curry bi9 ! : unclip 5 seq )) rest first 6 0 rest 3 0 first)unsafe 3 bi ! : unclip)last 5 seq )) butlast last 6 0 but)last 3 0 last)unsafe 3 bi ! : unclip)slice 5 seq )) rest)slice first 6 0 rest)slice 3 0 first)unsafe 3 bi ! inline : map)reduce 5 ..a seq map)quot: 5 ..a elt )) ..b intermediate 6 reduce)quot: 5 ..b prev intermediate )) ..a next 6 )) ..a result 6 0 0 dup first 3 dip 0 call 3 keep 3 dip compose s apd 0 1 3 ,dip 5each6 5each)integer6 ! inline : ,map)reduce 5 ..a seq1 seq, map)quot: 5 ..a elt1 elt, )) ..b intermediate 6 reduce)quot: 5 ..b prev intermediate )) ..a next 6 )) ..a result 6 0 0 ,dup 0 first 3 bi9 3 dip 0 call 3 keep 3 dip compose 0 )rot 3 dip 0 1 3 -dip 5,each6 5each)integer6 ! inline P;#IV"$' : 5map)find6 5 seq quot find)quot )) result elt 6

0 0 f 3 ,dip 0 0 nip 3 dip call dup 3 curry 3 dip call 0 0 drop f 3 unless 3 dip ! inline ;#IV"$'G : map)find 5 ... seq quot: 5 ... elt )) ... resultQf 6 )) ... result elt 6 0 find 3 5map)find6 ! inline : map)find)last 5 ... seq quot: 5 ... elt )) ... resultQf 6 )) ... result elt 6 0 find)last 3 5map)find6 ! inline : unclip)last)slice 5 seq )) butlast)slice last 6 0 but)last)slice 3 0 last)unsafe 3 bi ! inline P;#IV"$' : 5trim)head6 5 seq quot )) seq n 6 over 0 0 not 3 compose find drop 3 dip 0 length or 3 keep s ap ! inline : 5trim)tail6 5 seq quot )) seq n 6 over 0 0 not 3 compose find)last drop :12 3 dip s ap ! inline ;#IV"$'G : trim)head)slice 5 ... seq quot: 5 ... elt )) ... : 6 )) ... slice 6 5trim)head6 tail)slice ! inline : trim)head 5 ... seq quot: 5 ... elt )) ... : 6 )) ... ne seq 6 5trim)head6 tail ! inline : trim)tail)slice 5 ... seq quot: 5 ... elt )) ... : 6 )) ... slice 6 5trim)tail6 head)slice ! inline : trim)tail 5 ... seq quot: 5 ... elt )) ... : 6 )) ... ne seq 6 5trim)tail6 head ! inline : trim)slice 5 ... seq quot: 5 ... elt )) ... : 6 )) ... slice 6 0 trim)head)slice 3 0 trim)tail)slice 3 bi ! inline : trim 5 ... seq quot: 5 ... elt )) ... : 6 )) ... ne seq 6 0 trim)slice 3 0 drop 3 ,bi like ! inline G'N'#I%: sum 5 seq )) n 6 I: obFect sum = 0 2 3 binary)reduce ! inline : product 5 seq )) n 6 1 0 4 3 binary)reduce ! : infimum 5 seq )) n 6 0 3 0 min 3 map)reduce ! : supremum 5 seq )) n 6 0 3 0 max 3 map)reduce ! : map)sum 5 ... seq quot: 5 ... elt )) ... n 6 )) ... n 6 0 = 3 ,dip 0 dip 2 3 curry 0 s ap 3 prepose each ! inline : count 5 ... seq quot: 5 ... elt )) ... : 6 )) ... n 6 0 1 = : 3 compose map)sum ! inline : cartesian)each 5 ... seq1 seq, quot: 5 ... elt1 elt, )) ... 6 )) ... 6 0 ith each 3 ,curry each ! inline

: cartesian)map 5 ... seq1 seq, quot: 5 ... elt1 elt, )) ... ne elt 6 )) ... ne seq 6 0 ith map 3 ,curry map ! inline : cartesian)product 5 seq1 seq, )) ne seq 6 0 + . ,sequence 3 cartesian)map ! : each)from 5 ... seq quot: 5 ... x )) ... 6 i )) ... 6 )rot 5each6 5each)integer6 ! inline P;#IV"$' : select)by 5 ... seq quot: 5 ... elt )) ... x 6 compare: 5 obF1 obF, )) : 6 )) ... elt 6 0 0 keep s ap 3 curry 0 0 first 3 dip call 3 ,keep 0 curry ,dip pick over 3 curry 3 0 0 0 ,drop 3 0 0 ,drop 3 ,dip 3 if 3 compose 3 bi4 compose 1 each)from drop ! inline ;#IV"$'G : supremum)by 5 ... seq quot: 5 ... elt )) ... x 6 )) ... elt 6 0 after: 3 select)by ! inline : infimum)by 5 ... seq quot: 5 ... elt )) ... x 6 )) ... elt 6 0 before: 3 select)by ! inline : shortest 5 seqs )) elt 6 0 length 3 infimum)by ! : longest 5 seqs )) elt 6 0 length 3 supremum)by ! K Je hand)optimi8e flip to such a degree because type hints K cannot express that an array is an array of arrays yet< and K this ord happens to be performance)critical since the compiler K itself uses it. Bptimi8ing it like this reduced compile time. P;#IV"$' : generic)flip 5 matrix )) ne 0 0 first)unsafe length 0 length min 3 5each6 3 keep 0 0 nth)unsafe 3 ith + . US': arrays : array)length 5 array )) len 6 + array . declare lengthGG ! inline : array)flip 5 matrix )) ne matrix 6 + array . declare 0 0 first)unsafe array)length 1 3 keep 0 array)length min 3 5each6 5each)integer6 iota 3 keep 0 0 + array . declare array)nth 3 ith + . map)as 3 curry + . map)as ! ;#IV"$'G : flip 5 matrix )) ne matrix 6 matrix 6 1 3 keep 5each)integer6 iota map)as 3 curry + . map)as ! inline

dup empty: 0 dup array: 0 dup 0 array: 3 all: 0 array)flip 3 0 generic)flip 3 if 3 0 generic)flip 3 if 3 unless ! USING: arrays help.markup help.syntax math sequences.private vectors strings kernel math.order layouts quotations generic.single ! IN: sequences ?'&;: sequence + *class)description (" mixin class hose instances are sequences. %ustom implementations of the sequence protocol should be declared as instances of this mixin for all sequence functionality to ork correctly:( + *code (INS$"N%': my)sequence sequence( . . ! ?'&;: length + *values + (seq( sequence . + (n( (a non)negative integer( . . + *contract (Butputs the length of the sequence. "ll sequences support this operation.( . ! ?'&;: set)length + *values + (n( (a non)negative integer( . + (seq( (a resi8able sequence( . . + *contract (#esi8es a sequence. $he initial contents of the ne area is undefined.( . + *errors ($hro s a ( + *link no)method . ( error if the sequence is not resi8able< and a ( + *link bounds)error . ( if the ne length is negative.( . + *side)effects (seq( . ! ?'&;: lengthen + *values + (n( (a non)negative integer( . + (seq( (a resi8able sequence( . . + *contract ('nsures the sequence has a length of at least ( + *snippet (n( . ( elements. $his ord differs from ( + *link set)length . ( in t o respects:( + *list + ($his ord does not shrink the sequence if ( + *snippet (n( . ( is less than its length.( . + ($he ord doubles the underlying storage of ( + *snippet (seq( . (< hereas ( + *link set)length . ( is permitted to set it to equal ( + *snippet (n( . (. $his ensures that repeated calls to this ord ith constant increments of ( + *snippet (n( . ( do not result in a quadratic amount of copying< so that for example ( + *link push)all . ( can run efficiently hen used in a loop.( . . . ! ?'&;: nth + *values + (n( (a non)negative integer( . + (seq( sequence . + (elt( (the element at the ( + *snippet (n( . (th index( . . + *contract (Butputs the ( + *snippet (n( . (th element of the sequence. 'lements are numbered from 8ero< so the last element has an index one less than the length of the sequence. "ll sequences support this operation.( . + *errors ($hro s a ( + *link bounds)error . ( if the index is negative< or greater than or equal to the length of the sequence.( . ! ?'&;: set)nth + *values + (elt( sequence( . . + *contract (Sets beyond the end of the sequence.( . + *errors ($hro s obFect . + (n( (a non)negative integer( . + (seq( (a mutable the ( + *snippet (n( . (th element of the sequence. Storing a resi8able sequence such as a vector or string buffer gro s an error if the index is negative< or if the sequence is not

resi8able and the index is greater than or equal to the length of the sequence.( *nl ($hro s an error if the sequence cannot hold elements of the given type.( . + *side)effects (seq( . ! ?'&;: nths + *values + (indices( sequence . + (seq( sequence . + (seq7( sequence . . + *description (Butputs a sequence of elements from the input sequence indexed by the indices.( . + *examples + *example (USING: prettyprint sequences !( (+ = , . + >(a>( >(b>( >(c>( . nths .( (+ >(a>( >(c>( .( . . ! ?'&;: immutable + *values + (seq( sequence . . + *description ($hro s an ( + *link immutable . ( error.( . + *error)description ($hro n if an attempt is made to modify an immutable sequence.( . ! ?'&;: ne )sequence + *values + (len( (a non)negative integer( . + (seq( sequence . + (ne seq( (a mutable sequence( . . + *contract (Butputs a mutable sequence of length ( + *snippet (len( . ( hich can hold the elements of ( + *snippet (seq( . (. $he initial contents of the sequence are undefined.( . ! ?'&;: ne )resi8able + *values + (len( (a non)negative integer( . + (seq( sequence . + (ne seq( (a resi8able mutable sequence( . . + *contract (Butputs a resi8able mutable sequence ith an initial capacity of ( + *snippet (len( . ( elements and 8ero length< hich can hold the elements of ( + *snippet (seq( . (.( . + *examples + *example (USING: prettyprint sequences !( (-== V+ . ne )resi8able .( (V+ .( . + *example (USING: prettyprint sequences !( (-== SEU@>( >( ne )resi8able .( (SEU@>( >(( . . ! ?'&;: like + *values + (seq( sequence . + (exemplar( sequence . + (ne seq( (a ne sequence( . . + *contract (Butputs a sequence ith the same elements as ( + *snippet (seq( . (< but ( + *emphasis (like( . ( the template sequence< in the sense that it either has the same class as the template sequence< or if the template sequence is a virtual sequence< the same class as the template sequence7s underlying sequence.( *nl ($he default implementation does nothing.( . + *notes (Unlike ( + *link clone)like . (< the output sequence might share storage ith the input sequence.( . ! ?'&;: empty: + *values + (seq( sequence . + (:( (a boolean( . . + *description ($ests if the sequence has 8ero length.( . ! ?'&;: if)empty

+ *values + (seq( sequence . + (quot1( quotation . + (quot,( quotation . . + *description (Iakes an implicit check if the sequence is empty. "n empty sequence is dropped and ( + *snippet (quot1( . ( is called. Bther ise< if the sequence has any elements< ( + *snippet (quot,( . ( is called on it.( . + *examples + *example (USING: kernel prettyprint sequences !( (+ 1 , - . 0 >(empty sequence>( 3 0 sum 3 if)empty .( (L( . . ! ?'&;: hen)empty + *values + (seq( sequence . + (quot( (the first quotation of an ( + *link if)empty . . . + *description (Iakes an implicit check if the sequence is empty. "n empty sequence is dropped and the ( + *snippet (quot( . ( is called.( . + *examples ($his ord is equivalent to ( + *link if)empty . ( ith an empty second quotation:( + *example (USING: sequences prettyprint !( (+ . 0 + / A L . 3 0 3 if)empty .( (+ / A L .( . + *example (USING: sequences prettyprint !( (+ . 0 + / A L . 3 hen)empty .( (+ / A L .( . . ! ?'&;: unless)empty + *values + (seq( sequence . + (quot( (the second quotation of an ( + *link if)empty . . . + *description (Iakes an implicit check if the sequence is empty. "n empty sequence is dropped. Bther ise< the ( + *snippet (quot( . ( is called on the sequence.( . + *examples ($his ord is equivalent to ( + *link if)empty . ( ith an empty first quotation:( + *example (USING: sequences prettyprint !( (+ / A L . 0 3 0 sum 3 if)empty .( (1A( . + *example (USING: sequences prettyprint !( (+ / A L . 0 sum 3 unless)empty .( (1A( . . ! ?'&;: delete)all + *values + (seq( (a resi8able sequence( . . + *description (#esi8es the sequence to 8ero length< removing all elements. Not all sequences are resi8able.( . + *errors ($hro s a ( + *link bounds)error . ( if the ne length is negative< or if the sequence is not resi8able.( . + *side)effects (seq( . ! ?'&;: resi8e

+ *values + (n( (a non)negative integer( . + (seq( sequence . + (ne seq( (a ne sequence( . . + *description (%reates a ne sequence of the same type as ( + *snippet (seq( . ( ith ( + *snippet (n( . ( elements< and copies the contents of ( + *snippet (seq( . ( into the ne sequence. If ( + *snippet (n( . ( exceeds the length of ( + *snippet (seq( . (< the remaining elements are filled ith a default value! ( + *link f . ( for arrays and = for strings.( . + *notes ($his generic ord is only implemented for strings and arrays.( . ! ?'&;: first + *values + (seq( sequence . + (first( (the first element of the sequence( . . + *description (Butputs the first element of the sequence.( . + *errors ($hro s an error if the sequence is empty.( . ! ?'&;: second + *values + (seq( sequence . + (second( (the second element of the sequence( . . + *description (Butputs the second element of the sequence.( . + *errors ($hro s an error if the sequence contains less than t o elements.( . ! ?'&;: third + *values + (seq( sequence . + (third( (the third element of the sequence( . . + *description (Butputs the third element of the sequence.( . + *errors ($hro s an error if the sequence contains less than three elements.( . ! ?'&;: fourth + *values + (seq( sequence . + (fourth( (the fourth element of the sequence( . . + *description (Butputs the fourth element of the sequence.( . + *errors ($hro s an error if the sequence contains less than four elements.( . ! ?'&;: push + *values + (elt( obFect . + (seq( (a resi8able mutable sequence( . . + *description ("dds an element at the end of the sequence. $he sequence length is adFusted accordingly.( . + *errors ($hro s an error if ( + *snippet (seq( . ( is not resi8able< or if the type of ( + *snippet (elt( . ( is not permitted in ( + *snippet (seq( . (.( . + *side)effects (seq( . ! ?'&;: bounds)check: + *values + (n( (an integer( . + (seq( sequence . + (:( (a boolean( . . + *description ($ests if the index is ithin the bounds of the sequence.( . ! ?'&;: bounds)error + *values + (n( (a positive integer( . + (seq( sequence . . + *description ($hro s a ( + *link bounds)error . (.( . + *error)description ($hro n by ( + *link nth . (< ( + *link set)nth . ( and ( + *link set)length . ( if the given index lies beyond the bounds of the sequence.( . ! ?'&;: bounds)check + *values + (n( (a positive integer( . + (seq( sequence . . + *description ($hro s an error if ( + *snippet (n( . ( is negative or if it is greater than or equal to the length of ( + *snippet (seq( . (. Bther ise the t o inputs remain on the stack.( . ! ?'&;: :nth + *values + (n( (an integer( . + (seq( sequence . + (eltQf( (an obFect or ( + *link f . . . + *description (" forgiving version of ( + *link nth . (. If the index is out of bounds< or if the sequence is ( + *link f . (< simply outputs ( + *link f . (.( . !

?'&;: :set)nth + *values + (elt( obFect . + (n( (an integer( . + (seq( sequence . . + *description (" forgiving version of ( + *link set)nth . (. If the index is out of bounds< does nothing.( . ! ?'&;: :first + *values + (seq( sequence . + (eltQf( (an obFect or ( + *link f . . . + *description (" forgiving version of ( + *link first . (. If the sequence is empty< or if the sequence is ( + *link f . (< simply outputs ( + *link f . (.( . + *examples (Bn an empty sequence:( + *example (USING: sequences prettyprint !( (+ . :first .( (f( . (Jorks like first on sequences ith elements:( + *example (USING: sequences prettyprint !( (+ 1 , - . :first .( (1( . . ! ?'&;: :second + *values + (seq( sequence . + (eltQf( (an obFect or ( + *link f . . . + *description (" forgiving version of ( + *link second . (. If the sequence has less than t o elements< or if the sequence is ( + *link f . (< simply outputs ( + *link f . (.( . ! ?'&;: :last + *values + (seq( sequence . + (eltQf( (an obFect or ( + *link f . . . + *description (" forgiving version of ( + *link last . (. If the sequence is empty< or if the sequence is ( + *link f . (< simply outputs ( + *link f . (.( . ! ?'&;: nth)unsafe + *values + (n( (an integer( . + (seq( sequence . + (elt( obFect . . + *contract (Unsafe variant of ( + *link nth . ( that does not perform bounds checks.( . ! ?'&;: set)nth)unsafe + *values + (elt( obFect . + (n( (an integer( . + (seq( sequence . . + *contract (Unsafe variant of ( + *link set)nth . ( that does not perform bounds checks.( . ! ?'&;: exchange)unsafe + *values + (m( (a non)negative integer( . + (n( (a non)negative integer( . + (seq( (a mutable sequence( . . + *description (Unsafe variant of ( + *link exchange . ( that does not perform bounds checks.( . ! ?'&;: first)unsafe + *values + (seq( sequence . + (first( (the first element( . . + *contract (Unsafe variant of ( + *link first . ( that does not perform bounds checks.( . ! ?'&;: first,)unsafe + *values + (seq( sequence . + (first( (the first element( . + (second( (the second element( . . + *contract (Unsafe variant of ( + *link first, . ( that does not perform bounds checks.( . !

?'&;: first-)unsafe + *values + (seq( sequence . + (first( (the first element( . + (second( (the second element( . + (third( (the third element( . . + *contract (Unsafe variant of ( + *link first- . ( that does not perform bounds checks.( . ! ?'&;: first/)unsafe + *values + (seq( sequence . + (first( (the first element( . + (second( (the second element( . + (third( (the third element( . + (fourth( (the fourth element( . . + *contract (Unsafe variant of ( + *link first/ . ( that does not perform bounds checks.( . ! ?'&;: 1sequence + *values + (obF( obFect . + (exemplar( sequence . + (seq( sequence . . + *description (%reates a one)element sequence of the same type as ( + *snippet (exemplar( . (.( . ! ?'&;: ,sequence + *values + (obF1( obFect . + (obF,( obFect . + (exemplar( sequence . + (seq( sequence . . + *description (%reates a t o)element sequence of the same type as ( + *snippet (exemplar( . (.( . ! ?'&;: -sequence + *values + (obF1( obFect . + (obF,( obFect . + (obF-( obFect . + (exemplar( sequence . + (seq( sequence . . + *description (%reates a three)element sequence of the same type as ( + *snippet (exemplar( . (.( . ! ?'&;: /sequence + *values + (obF1( obFect . + (obF,( obFect . + (obF-( obFect . + (obF/( obFect . + (exemplar( sequence . + (seq( sequence . . + *description (%reates a four)element sequence of the same type as ( + *snippet (exemplar( . (.( . ! ?'&;: first, + *values + (seq( sequence . + (first( (the first element( . + (second( (the second element( . . + *description (;ushes the first t o elements of a sequence.( . + *errors ($hro s an error if the sequence has less than t o elements.( . ! ?'&;: first+ *values + (seq( sequence . + (first( (the first element( . + (second( (the second element( . + (third( (the third element( . . + *description (;ushes the first three elements of a sequence.( . + *errors ($hro s an error if the sequence has less than three elements.( . ! ?'&;: first/ + *values + (seq( sequence . + (first( (the first element( . + (second( (the second element( . + (third( (the third element( . + (fourth( (the fourth element( . . + *description (;ushes the first four elements of a sequence.( . + *errors ($hro s an error if the sequence has less than four elements.( . ! ?'&;: array)capacity + *values + (array( (an array( . + (n( (a non)negative fixnum( . . + *class)description (" predicate class hose instances are valid array si8es for the current architecture. $he minimum value is 8ero and the maximum value is ( + *link max)array)capacity . (.( . + *description (&o )level array length accessor.( .

+ * arning ($his ord is in the ( + *vocab)link (sequences.private( . ( vocabulary because it is unsafe. It does not check types< so improper use can corrupt memory.( . ! ?'&;: array)nth + *values + (n( (a non)negative fixnum( . + (array( (an array( . + (elt( obFect . . + *description (&o )level array element accessor.( . + * arning ($his ord is in the ( + *vocab)link (sequences.private( . ( vocabulary because it is unsafe. It does not check types or array bounds< and improper use can corrupt memory. User code must use ( + *link nth . ( instead.( . ! ?'&;: set)array)nth + *values + (elt( obFect . + (n( (a non)negative fixnum( . + (array( (an array( . . + *description (&o )level array element mutator.( . + * arning ($his ord is in the ( + *vocab)link (sequences.private( . ( vocabulary because it is unsafe. It does not check types or array bounds< and improper use can corrupt memory. User code must use ( + *link set)nth . ( instead.( . ! ?'&;: collect + *values + (n( (a non)negative integer( . + (quot( + *quotation (5 ... n )) ... value 6( . . + (into( (a sequence of length at least ( + *snippet (n( . . . + *description (" primitive mapping operation that applies a quotation to all integers from = up to but not including ( + *snippet (n( . (< and collects the results in a ne array. User code should use ( + *link map . ( instead.( . ! ?'&;: each + *values + (seq( sequence . + (quot( + *quotation (5 ... x )) ... 6( . . . + *description ("pplies the quotation to each element of the sequence in order.( . ! ?'&;: reduce + *values + (seq( sequence . + (identity( obFect . + (quot( + *quotation (5 ... prev elt )) ... next 6( . . + (result( (the final result( . . + *description (%ombines successive elements of the sequence using a binary operation< and outputs the final result. Bn the first iteration< the t o inputs to the quotation are ( + *snippet (identity( . (< and the first element of the sequence. Bn successive iterations< the first input is the result of the previous iteration< and the second input is the corresponding element of the sequence.( . + *examples + *example (USING: math prettyprint sequences !( (+ 1 A - . = 0 2 3 reduce .( (U( . . ! ?'&;: reduce)index + *values + (seq( sequence . + (identity( obFect . + (quot( + *quotation (5 ... prev elt index )) ... next 6( . . + (result( obFect . . + *description (%ombines successive elements of the sequence and their indices binary operations< and outputs the final result. Bn the first iteration< the three inputs to the quotation are ( + *snippet (identity( . (< the first element of the sequence< and its index< =. Bn successive iterations< the first input is the result of the previous iteration< the second input is the corresponding element of the sequence< and the third is its index.( . + *examples + *example (USING: sequences prettyprint math !( (+ 1= A= U= . = 0 2 2 3 reduce)index .( (1A-( . . !

?'&;: accumulate)as + *values + (seq( sequence . + (identity( obFect . + (quot( + *quotation (5 ... prev elt )) ... next 6( . . + (exemplar( sequence . + (final( (the final result( . + (ne seq( (a ne sequence( . . + *description (%ombines successive elements of the sequence using a binary operation< and outputs a sequence of the same type as ( + *snippet (exemplar( . ( containing intermediate results< together ith the final result.( *nl ($he first element of the ne sequence is ( + *snippet (identity( . (. $hen< on the first iteration< the t o inputs to the quotation are ( + *snippet (identity( . (< and the first element of the old sequence. Bn successive iterations< the first input is the result of the previous iteration< and the second input is the corresponding element of the old sequence.( *nl (Jhen given the empty sequence< outputs an empty sequence together ith the ( + *snippet (identity( . (.( . ! ?'&;: accumulate + *values + (seq( sequence . + (identity( obFect . + (quot( + *quotation (5 ... prev elt )) ... next 6( . . + (final( (the final result( . + (ne seq( (a ne array( . . + *description (%ombines successive elements of the sequence using a binary operation< and outputs a sequence of intermediate results< together ith the final result.( *nl ($he first element of the ne sequence is ( + *snippet (identity( . (. $hen< on the first iteration< the t o inputs to the quotation are ( + *snippet (identity( . (< and the first element of the old sequence. Bn successive iterations< the first input is the result of the previous iteration< and the second input is the corresponding element of the old sequence.( *nl (Jhen given the empty sequence< outputs an empty sequence together ith the ( + *snippet (identity( . (.( . + *examples + *example (USING: math prettyprint sequences !( (+ , , , , , . = 0 2 3 accumulate . .( (+ = , / L S .>n1=( . . ! ?'&;: accumulateK + *values + (seq( sequence . + (identity( obFect . + (quot( + *quotation (5 ... prev elt )) ... next 6( . . + (final( (the final result( . . + *description (%ombines successive elements of the sequence using a binary operation< and outputs the original sequence of intermediate results< together ith the final result.( *nl ($he first element of the ne sequence is ( + *snippet (identity( . (. $hen< on the first iteration< the t o inputs to the quotation are ( + *snippet (identity( . (< and the first element of the old sequence. Bn successive iterations< the first input is the result of the previous iteration< and the second input is the corresponding element of the old sequence.( *nl (Jhen given the empty sequence< outputs an empty sequence together ith the ( + *snippet (identity( . (.( . + *examples + *example (USING: math prettyprint sequences !( (+ , , , , , . = 0 2 3 accumulateK . .( (+ = , / L S .>n1=( . . ! ?'&;: map + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... ne elt 6( . . + (ne seq( (a ne sequence( . .

+ *description ("pplies the quotation to each element of the sequence in order. $he ne elements are collected into a sequence of the same class as the input sequence.( . ! ?'&;: map)as + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... ne elt 6( . . + (exemplar( sequence . + (ne seq( (a ne sequence( . . + *description ("pplies the quotation to each element of the sequence in order. $he ne elements are collected into a sequence of the same class as ( + *snippet (exemplar( . (.( . + *examples ($he follo ing example converts a string into an array of one)element strings:( + *example (USING: prettyprint strings sequences !( (>(?ello>( 0 1string 3 + . map)as .( (+ >(?>( >(e>( >(l>( >(l>( >(o>( .( . (Note that ( + *link map . ( could not be used here< because it ould create another string to hold results< and one)element strings cannot themselves be elements of strings.( . ! ?'&;: each)index + *values + (seq( sequence . + (quot( + *quotation (5 ... elt index )) ... 6( . . . + *description (%alls the quotation ith the element of the sequence and its index on the stack< ith the index on the top of the stack.( . + *examples + *example (USING: arrays sequences prettyprint !( (+ 1= ,= -= . 0 ,array . 3 each)index( (+ 1= = .>n+ ,= 1 .>n+ -= , .( . . ! ?'&;: map)index + *values + (seq( sequence . + (quot( + *quotation (5 ... elt index + (ne seq( sequence . . + *description (%alls the quotation ith the element of the index on the stack< ith the index on the top of the stack. of the quotation and outputs them in a sequence of the same sequence.( . + *examples + *example (USING: arrays sequences prettyprint (+ 1= ,= -= . 0 ,array 3 map)index .( (+ + 1= = . + ,= 1 . + -= , . .( . . !

)) ... ne elt 6( . . sequence and its %ollects the outputs type as the input !(

?'&;: change)nth + *values + (i( (a non)negative integer( . + (seq( (a mutable sequence( . + (quot( + *quotation (5 ..a elt )) ..b ne elt 6( . . . + *description ("pplies the quotation to the ( + *snippet (i( . (th element of the sequence< storing the result back into the sequence.( . + *errors ($hro s an error if the sequence is immutable< if the index is out of bounds< or the sequence cannot hold elements of the type output by ( + *snippet (quot( . (.( . + *side)effects (seq( . ! ?'&;: mapK + *values + (seq( (a mutable sequence( . + (quot( + *quotation (5 ... elt )) ... ne elt 6( . . . + *description ("pplies the quotation to each element yielding a ne element< storing the ne elements back in the original sequence. #eturns the original sequence.( . + *errors ($hro s an error if the sequence is immutable< or the sequence cannot hold elements of the type output by ( + *snippet (quot( . (.( . + *side)effects (seq( . !

?'&;: min)length + *values + (seq1( sequence . + (seq,( sequence . + (n( (a non)negative integer( . . + *description (Butputs the minimum of the lengths of the t o sequences.( . ! ?'&;: max)length + *values + (seq1( sequence . + (seq,( sequence . + (n( (a non)negative integer( . . + *description (Butputs the maximum of the lengths of the t o sequences.( . ! ?'&;: ,each + *values + (seq1( sequence . + (seq,( sequence . + (quot( + *quotation (5 ... elt1 elt, )) ... 6( . . . + *description ("pplies the quotation to pairs of elements from ( + *snippet (seq1( . ( and ( + *snippet (seq,( . (.( . ! ?'&;: -each + *values + (seq1( sequence . + (seq,( sequence . + (seq-( sequence . + (quot( + *quotation (5 ... elt1 elt, elt- )) ... 6( . . . + *description ("pplies the quotation to triples of elements from ( + *snippet (seq1( . (< ( + *snippet (seq,( . ( and ( + *snippet (seq-( . (.( . ! ?'&;: ,reduce + *values + (seq1( sequence . + (seq,( sequence . + (identity( obFect . + (quot( + *quotation (5 ... prev elt1 elt, )) ... next 6( . . + (result( (the final result( . . + *description (%ombines successive pairs of elements from the t o sequences using a ternary operation. $he first input value at each iteration except the first one is the result of the previous iteration. $he first input value at the first iteration is ( + *snippet (identity( . (.( . ! ?'&;: ,map + *values + (seq1( sequence . + (seq,( sequence . + (quot( + *quotation (5 ... elt1 elt, )) ... ne elt 6( . . + (ne seq( (a ne sequence( . . + *description ("pplies the quotation to each pair of elements in turn< yielding ne elements hich are collected into a ne sequence having the same class as ( + *snippet (seq1( . (.( . ! ?'&;: -map + *values + (seq1( sequence . + (seq,( sequence . + (seq-( sequence . + (quot( + *quotation (5 ... elt1 elt, elt- )) ... ne elt 6( . . + (ne seq( (a ne sequence( . . + *description ("pplies the quotation to each triple of elements in turn< yielding ne elements hich are collected into a ne sequence having the same class as ( + *snippet (seq1( . (.( . ! ?'&;: ,map)as + *values + (seq1( sequence . + (seq,( sequence . + (quot( + *quotation (5 ... elt1 elt, )) ... ne elt 6( . . + (exemplar( sequence . + (ne seq( (a ne sequence( . . + *description ("pplies the quotation to each pair of elements in turn< yielding ne elements hich are collected into a ne sequence having the same class as ( + *snippet (exemplar( . (.( . ! ?'&;: -map)as + *values + (seq1( sequence *quotation (5 ... elt1 elt, + (ne seq( (a ne sequence( + *description ("pplies the . + (seq,( sequence . + (seq-( sequence . + (quot( + elt- )) ... ne elt 6( . . + (exemplar( sequence . . . quotation to each triple of elements in turn<

yielding ne elements hich are collected into a ne class as ( + *snippet (exemplar( . (.( . !

sequence having the same

?'&;: ,all: + *values + (seq1( sequence . + (seq,( sequence . + (quot( + *quotation (5 ... elt1 elt, )) ... : 6( . . + (:( (a boolean( . . + *description ($ests the predicate pair ise against elements of ( + *snippet (seq1( . ( and ( + *snippet (seq,( . (.( . ! ?'&;: find + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (i( (the index of the first match< or ( + *link f . . + (elt( (the first matching element< or ( + *link f . . . + *description (" simpler variant of ( + *link find)from . ( here the starting index is =.( . ! ?'&;: find)from + *values + (n( (a starting index( . + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (i( (the index of the first match< or ( + *link f . . + (elt( (the first matching element< or ( + *link f . . . + *description ("pplies the quotation to each element of the sequence in turn< until it outputs a true value or the end of the sequence is reached. If the quotation yields a true value for some sequence element< the ord outputs the element index and the element itself. Bther ise< the ord outputs an index of ( + *link f . ( and ( + *link f . ( as the element.( . ! ?'&;: find)last + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (i( (the index of the first match< or f( . + (elt( (the first matching element< or ( + *link f . . . + *description (" simpler variant of ( + *link find)last)from . ( here the starting index is one less than the length of the sequence.( . ! ?'&;: find)last)from + *values + (n( (a starting index( . + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (i( (the index of the first match< or f( . + (elt( (the first matching element< or ( + *link f . . . + *description ("pplies the quotation to each element of the sequence in reverse order< until it outputs a true value or the start of the sequence is reached. If the quotation yields a true value for some sequence element< the ord outputs the element index and the element itself. Bther ise< the ord outputs an index of ( + *link f . ( and ( + *link f . ( as the element.( . ! ?'&;: find)index + *values + (seq( sequence . + (quot( + *quotation (5 ... elt i )) ... : + (i( (the index of the first match< or ( + + (elt( (the first matching element< or ( + + *description (" varient of ( + *link find . ( here an element and its index.( . ! ?'&;: find)index)from + *values + (n( (a starting index( . + (seq( sequence . + (quot( + *quotation (5 ... elt i )) ... : + (i( (the index of the first match< or ( + + (elt( (the first matching element< or ( + + *description (" varient of ( + *link find)from . ( both an element and its index.( . !

6( . . *link f . . *link f . . . the quotation takes both

6( . . *link f . . *link f . . . here the quotation takes

?'&;: map)find + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... resultQf 6( . . + (result( (the first non)false result of the quotation( . + (elt( (the first matching element< or ( + *link f . . . + *description ("pplies the quotation to each element of the sequence< until the quotation outputs a true value. If the quotation ever yields a result hich is not ( + *link f . (< then the value is output< along ith the element of the sequence hich yielded this.( . ! ?'&;: any: + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (:( (a boolean( . . + *description ($ests if the sequence contains an element satisfying the predicate< by applying the predicate to each element in turn until a true value is found. If the sequence is empty or if the end of the sequence is reached< outputs ( + *link f . (.( . ! ?'&;: all: + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (:( (a boolean( . . + *description ($ests if all elements in the sequence satisfy the predicate by checking each element in turn. Given an empty sequence< vacuously outputs ( + *link t . (.( . ! ?'&;: push)if + *values + (elt( obFect . + (quot( + *quotation (5 ..a elt )) ..b : 6( . . + (accum( (a resi8able mutable sequence( . . + *description ("dds the element at the end of the sequence if the quotation yields a true value.( . + *notes ($his ord is a factor of ( + *link filter . (.( . ! ?'&;: filter + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (subseq( (a ne sequence( . . + *description ("pplies the quotation to each element in turn< and outputs a ne sequence containing the elements of the original sequence for hich the quotation output a true value.( . ! ?'&;: filter)as + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (exemplar( sequence . + (subseq( (a ne sequence( . . + *description ("pplies the quotation to each element in turn< and outputs a ne sequence of the same type as ( + *snippet (exemplar( . ( containing the elements of the original sequence for hich the quotation output a true value.( . ! ?'&;: filterK + *values + (seq( (a resi8able mutable sequence( . + (quot( + *quotation (5 ... elt )) ... : 6( . . . + *description ("pplies the quotation to each element in turn< and removes elements for hich the quotation outputs a false value.( . + *side)effects (seq( . ! ?'&;: interleave + *values + (seq( sequence . + (bet een( (a quotation( . + (quot( + *quotation (5 ... elt )) ... 6( . . . + *description ("pplies ( + *snippet (quot( . ( to each element in turn< also invoking ( + *snippet (bet een( . ( in)bet een each pair of elements.( . + *examples + *example (USING: io sequences !( (+ >(a>( >(b>( >(c>( . 0 >(M>( rite 3 0 rite 3 interleave( (aMbMc( . . ! ?'&;: index

+ *values + (obF( obFect . + (seq( sequence . + (n( (an index( . . + *description (Butputs the index of the first element in the sequence equal to ( + *snippet (obF( . (. If no element is found< outputs ( + *link f . (.( . ! ?'&;: index)from + *values + (obF( obFect . + (i( (a start index( . + (seq( sequence . + (n( (an index( . . + *description (Butputs the index of the first element in the sequence equal to ( + *snippet (obF( . (< starting the search from the ( + *snippet (i( . (th element. If no element is found< outputs ( + *link f . (.( . ! ?'&;: last)index + *values + (obF( obFect . + (seq( sequence . + (n( (an index( . . + *description (Butputs the index of the last element in the sequence equal to ( + *snippet (obF( . (! the sequence is traversed back to front. If no element is found< outputs ( + *link f . (.( . ! ?'&;: last)index)from + *values + (obF( obFect . + (i( (a start index( . + (seq( sequence . + (n( (an index( . . + *description (Butputs the index of the last element in the sequence equal to ( + *snippet (obF( . (< traversing the sequence back ards starting from the ( + *snippet (i( . (th element and finishing at the first. If no element is found< outputs ( + *link f . (.( . ! ?'&;: member: + *values + (elt( obFect . + (seq( sequence . + (:( (a boolean( . . + *description ($ests if the sequence contains an element equal to the obFect.( . + *notes ($his ord uses equality comparison 5( + *link H . (6.( . ! ?'&;: member)eq: + *values + (elt( obFect . + (seq( sequence . + (:( (a boolean( . . + *description ($ests if the sequence contains the obFect.( . + *notes ($his ord uses identity comparison 5( + *link eq: . (6.( . ! ?'&;: remove + *values + (elt( obFect . + (seq( sequence . + (ne seq( (a ne sequence( . . + *description (Butputs a ne sequence containing all elements of the input sequence except for given element.( . + *notes ($his ord uses equality comparison 5( + *link H . (6.( . ! ?'&;: remove)eq + *values + (elt( obFect . + (seq( sequence . + (ne seq( (a ne sequence( . . + *description (Butputs a ne sequence containing all elements of the input sequence except those equal to the given element.( . + *notes ($his ord uses identity comparison 5( + *link eq: . (6.( . ! ?'&;: remove)nth + *values + (n( integer . + (seq( sequence . + (seq7( sequence . . + *description (%reates a ne sequence ithout the element at index ( + *snippet (n( . (.( . + *examples (Notice that the original sequence is left intact:( + *example (USING: sequences prettyprint kernel !( (+ 1 , - . 1 over remove)nth . .( (+ 1 - .>n+ 1 , - .( . . ! ?'&;: move + *values + (to( (an index in ( + *snippet (seq( . . + (from( (an index in (

+ *snippet (seq( . . + (seq( (a mutable sequence( . . + *description (Sets the element ith index ( + *snippet (m( . ( to the element ith index ( + *snippet (n( . (.( . + *side)effects (seq( . ! ?'&;: removeK + *values + (elt( obFect . + (seq( (a resi8able mutable sequence( . . + *description (#emoves all elements equal to ( + *snippet (elt( . ( from ( + *snippet (seq( . ( and returns ( + *snippet (seq( . (.( . + *notes ($his ord uses equality comparison 5( + *link H . (6.( . + *side)effects (seq( . ! ?'&;: remove)eqK + *values + (elt( obFect . + (seq( (a resi8able mutable sequence( . . + *description (Butputs a ne sequence containing all elements of the input sequence except the given element.( . + *notes ($his ord uses identity comparison 5( + *link eq: . (6.( . + *side)effects (seq( . ! ?'&;: remove)nthK + *values + (n( (a non)negative integer( . + (seq( (a resi8able mutable sequence( . . + *description (#emoves the ( + *snippet (n( . (th element from the sequence< shifting all other elements do n and reducing its length by one.( . + *side)effects (seq( . ! ?'&;: delete)slice + *values + (from( (a non)negative integer( . + (to( (a non)negative integer( . + (seq( (a resi8able mutable sequence( . . + *description (#emoves a range of elements beginning at index ( + *snippet (from( . ( and ending before index ( + *snippet (to( . (.( . + *side)effects (seq( . ! ?'&;: replace)slice + *values + (ne ( sequence . + (from( (a non)negative integer( . + (to( (a non)negative integer( . + (seq( sequence . + (seq7( sequence . . + *description (#eplaces a range of elements beginning at index ( + *snippet (from( . ( and ending before index ( + *snippet (to( . ( ith a ne sequence.( . + *errors ($hro s an error if ( + *snippet (ne ( . ( contains elements hose types are not permissible in ( + *snippet (seq( . (.( . ! + push prefix suffix . related) ords ?'&;: suffix + *values + (seq( sequence . + (elt( obFect . + (ne seq( sequence . . + *description (Butputs a ne sequence obtained by adding ( + *snippet (elt( . ( at the end of ( + *snippet (seq( . (.( . + *errors ($hro s an error if the type of ( + *snippet (elt( . ( is not permitted in sequences of the same class as ( + *snippet (seq1( . (.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , - . / suffix .( (+ 1 , / .( . . ! ?'&;: suffixK + *values + (seq( sequence . + (elt( obFect . . + *description (Iodifiers a sequence in)place by adding ( + *snippet (elt( . ( to the end of ( + *snippet (seq( . (. Butputs ( + *snippet (seq( . (.( . + *errors ($hro s an error if the type of ( + *snippet (elt( . ( is not permitted in sequences of the same class as ( + *snippet (seq( . (.( . + *examples + *example (USING: prettyprint sequences !( (V+ 1 , - . / suffixK .( (V+ 1 ,

- / .( . . ! ?'&;: appendK + *values + (seq1( sequence . + (seq,( sequence . . + *description (Iodifiers ( + *snippet (seq1( . ( in)place by adding the elements from ( + *snippet (seq,( . ( to the end and outputs ( + *snippet (seq1( . (.( . + *examples + *example (USING: prettyprint sequences !( (V+ 1 , - . + / A L . appendK .( (V+ 1 , - / A L .( . . ! ?'&;: prefix + *values + (seq( sequence . + (elt( obFect . + (ne seq( sequence . . + *description (Butputs a ne sequence obtained by adding ( + *snippet (elt( . ( at the beginning of ( + *snippet (seq( . (.( . + *errors ($hro s an error if the type of ( + *snippet (elt( . ( is not permitted in sequences of the same class as ( + *snippet (seq1( . (.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , - . = prefix .( (+ = 1 , - .( . . ! ?'&;: sum)lengths + *values + (seq( (a sequence of sequences( . + (n( integer . . + *description (Butputs the sum of the lengths of all sequences in ( + *snippet (seq( . (.( . ! ?'&;: concat + *values + (seq( sequence . + (ne seq( sequence . . + *description (%oncatenates a sequence of sequences together into one sequence. If ( + *snippet (seq( . ( is empty< outputs ( + *snippet (+ .( . (< other ise the resulting sequence is of the same class as the first element of ( + *snippet (seq( . (.( . + *errors ($hro s an error if one of the sequences in ( + *snippet (seq( . ( contains elements not permitted in sequences of the same class as the first element of ( + *snippet (seq( . (.( . ! ?'&;: concat)as + *values + (seq( sequence . + (exemplar( sequence . + (ne seq( sequence . . + *description (%oncatenates a sequence of sequences together into one sequence ith the same type as ( + *snippet (exemplar( . (.( . + *errors ($hro s an error if one of the sequences in ( + *snippet (seq( . ( contains elements not permitted in sequences of the same class as ( + *snippet (exemplar( . (.( . ! ?'&;: Foin + *values + (seq( sequence . + (glue( sequence . + (ne seq( sequence . . + *description (%oncatenates a sequence of sequences together into one sequence< placing a copy of ( + *snippet (glue( . ( bet een each pair of sequences. $he resulting sequence is of the same class as ( + *snippet (glue( . (.( . + *notes (If the ( + *snippet (glue( . ( sequence is empty< this ord calls ( + *link concat)as . (.( . + *errors ($hro s an error if one of the sequences in ( + *snippet (seq( . ( contains elements not permitted in sequences of the same class as ( + *snippet (glue( . (.( . ! ?'&;: Foin)as + *values + (seq( sequence . + (glue( sequence . + (exemplar( sequence . + (ne seq( sequence . . + *description (%oncatenates a sequence of sequences together into one sequence<

placing a copy of ( + *snippet (glue( . ( bet een each pair of sequences. $he resulting sequence is of the same class as ( + *snippet (glue( . (.( . + *notes (If the ( + *snippet (glue( . ( sequence is empty< this ord calls ( + *link concat)as . (.( . + *errors ($hro s an error if one of the sequences in ( + *snippet (seq( . ( contains elements not permitted in sequences of the same class as ( + *snippet (exemplar( . (.( . ! + Foin Foin)as concat concat)as . related) ords ?'&;: last + *values + (seq( sequence . + (elt( obFect . . + *description (Butputs the last element of a sequence.( . + *errors ($hro s an error if the sequence is empty.( . ! + pop pop4 . related) ords ?'&;: pop4 + *values + (seq( (a resi8able mutable sequence( . . + *description (#emoves the last element and shortens the sequence.( . + *side)effects (seq( . + *errors ($hro s an error if the sequence is empty.( . ! ?'&;: pop + *values + (seq( (a resi8able mutable sequence( . + (elt( obFect . . + *description (Butputs the last element after removing it and shortening the sequence.( . + *side)effects (seq( . + *errors ($hro s an error if the sequence is empty.( . ! ?'&;: mismatch + *values + (seq1( sequence . + (seq,( sequence . + (i( (an index( . . + *description (%ompares pairs of elements up to the minimum of the sequences7 lengths< outputting the first index here the t o sequences have non)equal elements< or ( + *link f . ( if all tested elements ere equal.( . ! ?'&;: flip + *values + (matrix( (a sequence of equal)length sequences( . + (ne matrix( (a sequence of equal)length sequences( . . + *description ($ransposes the matrix! that is< ro s become columns and columns become ro s.( . + *examples + *example (USING: prettyprint sequences !( (+ + 1 , - . + / A L . . flip .( (+ + 1 / . + , A . + - L . .( . . ! ?'&;: exchange + *values + (m( (a non)negative integer( . + (n( (a non)negative integer( . + (seq( (a mutable sequence( . . + *description ('xchanges the ( + *snippet (m( . (th and ( + *snippet (n( . (th elements of ( + *snippet (seq( . (.( . ! ?'&;: reverseK + *values + (seq( (a mutable sequence( . . + *description (#everses a sequence in)place and outputs that sequence.( . + *side)effects (seq( . ! ?'&;: padding + *values + (seq( sequence . + (n( (a non)negative integer( . + (elt( obFect . + (quot( + *quotation (5 ... seq1 seq, )) ... ne seq 6( . . + (ne seq( (a ne sequence( . . + *description (Butputs a ne string sequence of ( + *snippet (elt( . ( repeated< that hen appended to ( + *snippet (seq( . (< yields a sequence of length ( + *snippet (n( . (. If the length of ( + *snippet (seq( . ( is greater

than ( + *snippet (n( . (< this

ord outputs an empty sequence.( . !

?'&;: pad)head + *values + (seq( sequence . + (n( (a non)negative integer( . + (elt( obFect . + (padded( (a ne sequence( . . + *description (Butputs a ne sequence consisting of ( + *snippet (seq( . ( padded on the left ith enough repetitions of ( + *snippet (elt( . ( to have the result be of length ( + *snippet (n( . (.( . + *examples + *example (USING: io sequences !( (+ >(ab>( >(quux>( . 0 A %?"#: ) pad)head print 3 each( ()))ab>n)quux( . . ! ?'&;: pad)tail + *values + (seq( sequence . + (n( (a non)negative integer( . + (elt( obFect . + (padded( (a ne sequence( . . + *description (Butputs a ne sequence consisting of ( + *snippet (seq( . ( padded on the right ith enough repetitions of ( + *snippet (elt( . ( to have the result be of length ( + *snippet (n( . (.( . + *examples + *example (USING: io sequences !( (+ >(ab>( >(quux>( . 0 A %?"#: ) pad)tail print 3 each( (ab)))>nquux)( . . ! ?'&;: sequenceH + *values + (seq1( sequence . + (seq,( sequence . + (:( (a boolean( . . + *description ($ests if the t o sequences have the same length and elements. $his is eaker than ( + *link H . (< since it does not ensure that the sequences are instances of the same class.( . ! ?'&;: reversed + *class)description (" virtual sequence hich presents a reversed vie underlying sequence. Ne instances can be created by calling ( + *link PreversedG . (.( . ! of an

?'&;: reverse + *values + (seq( sequence . + (ne seq( (a ne sequence( . . + *description (Butputs a ne sequence having the same elements as ( + *snippet (seq( . ( but in reverse order.( . ! + reverse PreversedG reverseK . related) ords ?'&;: PreversedG + *values + (seq( sequence . + (reversed( (a ne sequence( . . + *description (%reates an instance of the ( + *link reversed . ( class.( . + *see)also (virtual)sequences( . ! ?'&;: slice)error + *values + (str( (a reason( . . + *description ($hro s a ( + *link slice)error . (.( . + *error)description ($hro n by ( + *link PsliceG . ( if one of the follo ing invalid conditions holds:( + *list ($he start index is negative( ($he end index is greater than the length of the sequence( ($he start index is greater than the end index( . . ! ?'&;: slice + *class)description (" virtual sequence hich presents a subrange of the elements of an underlying sequence. Ne instances can be created by calling ( + *link PsliceG . (. %onvenience ords are also provided for creating slices here one endpoint is the start or end of the sequence! see ( + *link (sequences)slices( . ( for a list.( *nl

(Slices are mutable if the underlying sequence is mutable< and mutating a slice changes the underlying sequence. ?o ever< slices cannot be resi8ed after creation.( . ! ?'&;: check)slice + *values + (from( (a non)negative integer( . + (to( + (seq( sequence . . + *description ('nsures that ( + *snippet (m( . ( is + *snippet (m( . (< and that both indices are ithin (seq( . (.( . + *errors ($hro s a ( + *link slice)error . ( if the . ! (a non)negative integer( . less than or equal to ( bounds for ( + *snippet preconditions are not met.(

?'&;: collapse)slice + *values + (m( (a non)negative integer( . + (n( (a non)negative integer( . + (slice( slice . + (m7( (a non)negative integer( . + (n7( (a non)negative integer( . + (seq( sequence . . + *description (;repares to take the slice of a slice by adFusting the start and end indices accordingly< and replacing the slice ith its underlying sequence.( . ! ?'&;: PsliceG + *values + (from( (a non)negative integer( . + (to( (a non)negative integer( . + (seq( sequence . + (slice( slice . . + *description (Butputs a ne virtual sequence sharing storage ith the subrange of elements in ( + *snippet (seq( . ( ith indices starting from and including ( + *snippet (m( . (< and up to but not including ( + *snippet (n( . (.( . + *errors ($hro s an error if ( + *snippet (m( . ( or ( + *snippet (n( . ( is out of bounds.( . + *notes ($aking the slice of a slice outputs a slice of the underlying sequence< instead of a slice of a slice. $his means that you cannot assume that the ( + *snippet (from( . ( and ( + *snippet (to( . ( slots of the resulting slice ill be equal to the values you passed to ( + *link PsliceG . (.( . ! + PsliceG subseq . related) ords ?'&;: repetition + *class)description (" virtual sequence consisting of ( + *snippet (elt( . ( repeated ( + *snippet (len( . ( times. #epetitions are created by calling ( + *link PrepetitionG . (.( . ! ?'&;: PrepetitionG + *values + (len( (a non)negative integer( . + (elt( obFect . + (repetition( repetition . . + *description (%reates a ne ( + *link repetition . (.( . + *examples + *example (USING: arrays prettyprint sequences !( (1= >(M>( PrepetitionG Garray .( (+ >(M>( >(M>( >(M>( >(M>( >(M>( >(M>( >(M>( >(M>( >(M>( >(M>( .( . + *example (USING: prettyprint sequences !( (1= >(M>( PrepetitionG concat .( (>(MMMMMMMMMM>(( . . ! ?'&;: copy + *values + (src( sequence . + (i( (an index in ( + *snippet (dst( . . + (dst( (a mutable sequence( . . + *description (%opies all elements of ( + *snippet (src( . ( to ( + *snippet (dst( . (< ith destination indices starting from ( + *snippet (i( . (. Gro s ( + *snippet (dst( . ( first if necessary.( . + *side)effects (dst( . + *errors ("n error is thro n if ( + *snippet (dst( . ( is not resi8able< and not large enough to hold the copied elements.( . !

?'&;: push)all + *values + (src( sequence . + (dst( (a resi8able mutable sequence( . . + *description ("ppends ( + *snippet (src( . ( to the end of ( + *snippet (dst( . (.( . + *side)effects (dst( . + *errors ($hro s an error if ( + *snippet (src( . ( contains elements not permitted in ( + *snippet (dst( . (.( . ! ?'&;: append + *values + (seq1( sequence . + (seq,( sequence . + (ne seq( sequence . + *description (Butputs a ne sequence of the same type as ( + *snippet ( consisting of the elements of ( + *snippet (seq1( . ( follo ed by ( + (seq,( . (.( . + *errors ($hro s an error if ( + *snippet (seq,( . ( contains elements permitted in sequences of the same class as ( + *snippet (seq1( . (.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , . E+ - / . append .( (+ 1 , - / .( . + *example (USING: prettyprint sequences strings !( (>(go>( >(ing>( append .( (>(going>(( . . ! . (seq1( . *snippet not

?'&;: append)as + *values + (seq1( sequence . + (seq,( sequence . + (exemplar( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence of the same type as ( + *snippet (exemplar( . ( consisting of the elements of ( + *snippet (seq1( . ( follo ed by ( + *snippet (seq,( . (.( . + *errors ($hro s an error if ( + *snippet (seq1( . ( or ( + *snippet (seq,( . ( contain elements not permitted in sequences of the same class as ( + *snippet (exemplar( . (.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , . E+ - / . E+ . append)as .( (E+ 1 , - / .( . + *example (USING: prettyprint sequences strings !( (>(go>( >(ing>( SEU@>( >( append)as .( (SEU@>( going>(( . . ! + append append)as . related) ords ?'&;: prepend + *values + (seq1( sequence . + (seq,( sequence . + (ne seq( sequence . + *description (Butputs a ne sequence of the same type as ( + *snippet ( consisting of the elements of ( + *snippet (seq,( . ( follo ed by ( + (seq1( . (.( . + *errors ($hro s an error if ( + *snippet (seq,( . ( contains elements permitted in sequences of the same class as ( + *snippet (seq1( . (.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , . E+ - / . prepend .( (+ - / 1 , .( . + *example (USING: prettyprint sequences strings !( (>(go>( >(car>( prepend .( (>(cargo>(( . (seq1( . *snippet not

. . ! ?'&;: prepend)as + *values + (seq1( sequence . + (seq,( sequence . + (exemplar( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence of the same type as ( + *snippet (exemplar( . ( consisting of the elements of ( + *snippet (seq,( . ( follo ed by ( + *snippet (seq1( . (.( . + *errors ($hro s an error if ( + *snippet (seq1( . ( or ( + *snippet (seq,( . ( contain elements not permitted in sequences of the same class as ( + *snippet (exemplar( . (.( . + *examples + *example (USING: prettyprint sequences !( (+ - / . E+ 1 , . E+ . prepend)as .( (E+ 1 , - / .( . + *example (USING: prettyprint sequences strings !( (>(ing>( >(go>( SEU@>( >( prepend)as .( (SEU@>( going>(( . . ! + prepend prepend)as . related) ords ?'&;: -append + *values + (seq1( sequence . + (seq,( sequence . + (seq-( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence consisting of the elements of ( + *snippet (seq1( . (< ( + *snippet (seq,( . ( and ( + *snippet (seq-( . ( in turn.( . + *errors ($hro s an error if ( + *snippet (seq,( . ( or ( + *snippet (seq-( . ( contain elements not permitted in sequences of the same class as ( + *snippet (seq1( . (.( . + *examples + *example (USING: prettyprint sequences !( (>(a>( >(b>( >(c>( -append .( (>(abc>(( . . ! ?'&;: -append)as + *values + (seq1( sequence . + (seq,( sequence . + (seq-( sequence . + (exemplar( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence consisting of the elements of ( + *snippet (seq1( . (< ( + *snippet (seq,( . ( and ( + *snippet (seq-( . ( in turn of the same type as ( + *snippet (exemplar( . (.( . + *errors ($hro s an error if ( + *snippet (seq1( . (< ( + *snippet (seq,( . (< or ( + *snippet (seq-( . ( contain elements not permitted in sequences of the same class as ( + *snippet (exemplar( . (.( . + *examples + *example (USING: prettyprint sequences !( (>(a>( >(b>( >(c>( SEU@>( >( -append)as .( (SEU@>( abc>(( . . ! + -append -append)as . related) ords ?'&;: surround + *values + (seq1( sequence . + (seq,( sequence . + (seq-( sequence . + (ne seq( sequence . .

+ *description (Butputs a ne sequence ith ( + *snippet (seq1( . ( inserted bet een ( + *snippet (seq,( . ( and ( + *snippet (seq-( . (.( . + *examples + *example (USING: sequences prettyprint !( (>(sssssh>( >(5>( >(6>( surround .( (>(5sssssh6>(( . . ! ?'&;: glue + *values + (seq1( sequence . + (seq,( sequence . + (seq-( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence ith ( + *snippet (seq-( . ( inserted bet een ( + *snippet (seq1( . ( and ( + *snippet (seq,( . (.( . + *examples + *example (USING: sequences prettyprint !( (>(a>( >(b>( >(<>( glue .( (>(a<b>(( . . ! ?'&;: subseq + *values + (from( (a non)negative integer( . + (to( (a non)negative integer( . + (seq( sequence . + (subseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of all elements starting from and including ( + *snippet (from( . (< and up to but not including ( + *snippet (to( . (.( . + *errors ($hro s an error if ( + *snippet (from( . ( or ( + *snippet (to( . ( is out of bounds.( . ! ?'&;: clone)like + *values + (seq( sequence . + (exemplar( sequence . + (ne seq( (a ne sequence( . . + *description (Butputs a ne ly)allocated sequence ith the same elements as ( + *snippet (seq( . ( but of the same type as ( + *snippet (exemplar( . (.( . + *notes (Unlike ( + *link like . (< this ord al ays creates a ne sequence hich never shares storage ith the original.( . ! ?'&;: head)slice + *values + (seq( sequence . + (n( (a non)negative integer( . + (slice( (a slice( . . + *description (Butputs a virtual sequence sharing storage ith the first ( + *snippet (n( . ( elements of the input sequence.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: tail)slice + *values + (seq( sequence . + (n( (a non)negative integer( . + (slice( (a slice( . . + *description (Butputs a virtual sequence sharing storage ith all elements from the ( + *snippet (n( . (th index until the end of the input sequence.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: but)last)slice + *values + (seq( sequence . + (slice( (a slice( . . + *description (Butputs a virtual sequence sharing storage element of the input sequence.( . + *errors ($hro s an error on an empty sequence.( . ! ?'&;: rest)slice + *values + (seq( sequence . + (slice( (a slice( . . + *description (Butputs a virtual sequence sharing storage from the 1st index until the end of the input sequence.( .

ith all but the last

ith all elements

+ *notes ('quivalent to ( + *snippet (1 tail( . . + *errors ($hro s an error on an empty sequence.( . ! ?'&;: head)slice4 + *values + (seq( sequence . + (n( (a non)negative integer( . + (slice( (a slice( . . + *description (Butputs a virtual sequence sharing storage ith all elements of ( + *snippet (seq( . ( until the ( + *snippet (n( . (th element from the end. In other ords< it outputs a sequence of the first ( + *snippet (l)n( . ( elements of the input sequence< here ( + *snippet (l( . ( is its length.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: tail)slice4 + *values + (seq( sequence . + (n( (a non)negative integer( . + (slice( (a slice( . . + *description (Butputs a virtual sequence sharing storage ith the last ( + *snippet (n( . ( elements of the input sequence.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: head + *values + (seq( sequence . + (n( (a non)negative integer( . + (headseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of the first ( + *snippet (n( . ( elements of the input sequence.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: tail + *values + (seq( sequence . + (n( (a non)negative integer( . + (tailseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of the input sequence ith the first n items removed.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: but)last + *values + (seq( sequence . + (headseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of the input sequence last item removed.( . + *errors ($hro s an error on an empty sequence.( . ! ?'&;: rest + *values + (seq( sequence . + (tailseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of the input sequence first item removed.( . + *errors ($hro s an error on an empty sequence.( . !

ith the

ith the

?'&;: head4 + *values + (seq( sequence . + (n( (a non)negative integer( . + (headseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of all elements of ( + *snippet (seq( . ( until the ( + *snippet (n( . (th element from the end. In other ords< it outputs a sequence of the first ( + *snippet (l)n( . ( elements of the input sequence< here ( + *snippet (l( . ( is its length.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: tail4 + *values + (seq( sequence . + (n( (a non)negative integer( . + (tailseq( (a ne sequence( . . + *description (Butputs a ne sequence consisting of the last ( + *snippet (n( . ( elements of the input sequence.( . + *errors ($hro s an error if the index is out of bounds.( . ! ?'&;: shorter:

+ *values + (seq1( sequence . + (seq,( sequence . + (:( (a boolean( . . + *description ($ests if the length of ( + *snippet (seq1( . ( is smaller than the length of ( + *snippet (seq,( . (.( . ! ?'&;: head: + *values + (seq( sequence . + (begin( sequence . + (:( (a boolean( . . + *description ($ests if ( + *snippet (seq( . ( starts ith ( + *snippet (begin( . (. If ( + *snippet (begin( . ( is longer than ( + *snippet (seq( . (< this ord outputs ( + *link f . (.( . ! ?'&;: tail: + *values + (seq( sequence . + (end( sequence . + (:( (a boolean( . . + *description ($ests if ( + *snippet (seq( . ( ends ith ( + *snippet (end( . (. If ( + *snippet (end( . ( is longer than ( + *snippet (seq( . (< this ord outputs ( + *link f . (.( . ! + remove remove)nth remove)eq remove)eqK removeK remove)nthK . related) ords ?'&;: cut)slice + *values + (seq( sequence . + (n( (a non)negative integer( . + (before)slice( sequence . + (after)slice( (a slice( . . + *description (Butputs a pair of sequences< here ( + *snippet (before( . ( consists of the first ( + *snippet (n( . ( elements of ( + *snippet (seq( . ( and has the same type< hile ( + *snippet (after( . ( is a slice of the remaining elements.( . + *notes (Unlike ( + *link cut . (< the run time of this ord is proportional to the length of ( + *snippet (before( . (< not ( + *snippet (after( . (< so it is suitable for use in an iterative algorithm hich cuts successive pieces off a sequence.( . ! ?'&;: cut + *values + (seq( sequence . + (n( (a non)negative integer( . + (before( sequence . + (after( sequence . . + *description (Butputs a pair of sequences< here ( + *snippet (before( . ( consists of the first ( + *snippet (n( . ( elements of ( + *snippet (seq( . (< hile ( + *snippet (after( . ( holds the remaining elements. Eoth output sequences have the same type as ( + *snippet (seq( . (.( . + *notes (Since this ord copies the entire tail of the sequence< it should not be used in a loop. If this is important< consider using ( + *link cut)slice . ( instead< since it returns a slice for the tail instead of copying.( . ! ?'&;: cut4 + *values + (seq( sequence . + (n( (a non)negative integer( . + (before( sequence . + (after( sequence . . + *description (Butputs a pair of sequences< here ( + *snippet (after( . ( consists of the last ( + *snippet (n( . ( elements of ( + *snippet (seq( . (< hile ( + *snippet (before( . ( holds the remaining elements. Eoth output sequences have the same type as ( + *snippet (seq( . (.( . ! ?'&;: start4 + *values + (subseq( sequence . + (seq( sequence . + (n( (a start index( . + (i( (a start index( . . + *description (Butputs the start index of the first contiguous subsequence equal to ( + *snippet (subseq( . (< starting the search from the ( + *snippet (n( . (th element. If no matching subsequence is found< outputs ( + *link f . (.( . ! ?'&;: start + *values + (subseq( sequence . + (seq( sequence . + (i( (a start index( . . + *description (Butputs the start index of the first contiguous subsequence equal to ( + *snippet (subseq( . (< or ( + *link f . ( if no matching subsequence is found.( . !

?'&;: subseq: + *values + (subseq( sequence . + (seq( sequence . + (:( (a boolean( . . + *description ($ests if ( + *snippet (seq( . ( contains the elements of ( + *snippet (subseq( . ( as a contiguous subsequence.( . ! ?'&;: drop)prefix + *values + (seq1( sequence . + (seq,( sequence . + (slice1( (a slice( . + (slice,( (a slice( . . + *description (Butputs a pair of virtual sequences ith the common prefix of ( + *snippet (seq1( . ( and ( + *snippet (seq,( . ( removed.( . ! ?'&;: unclip + *values + (seq( sequence . + (rest( sequence . + (first( obFect . . + *description (Butputs a tail sequence and the first element of ( + *snippet (seq( . (! the tail sequence consists of all elements of ( + *snippet (seq( . ( but the first.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , - . unclip suffix .( (+ , - 1 .( . . ! ?'&;: unclip)slice + *values + (seq( sequence . + (rest)slice( slice . + + *description (Butputs a tail sequence and the first (seq( . (! the tail sequence consists of all elements but the first. Unlike ( + *link unclip . (< this ord the input sequence< and runs in constant time.( . + *examples + *example (USING: math.order prettyprint R . unclip)slice 0 min 3 reduce .( ()1=( . . ! (first( obFect . . element of ( + *snippet of ( + *snippet (seq( . ( does not make a copy of sequences !( (+ - )1 )1= A

?'&;: unclip)last + *values + (seq( sequence . + (butlast( sequence . + (last( obFect . . + *description (Butputs a head sequence and the last element of ( + *snippet (seq( . (! the head sequence consists of all elements of ( + *snippet (seq( . ( but the last.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , - . unclip)last prefix .( (+ - 1 , .( . . ! ?'&;: unclip)last)slice + *values + (seq( sequence . + (butlast)slice( slice . + (last( obFect . . + *description (Butputs a head sequence and the last element of ( + *snippet (seq( . (! the head sequence consists of all elements of ( + *snippet (seq( . ( but the last Unlike ( + *link unclip)last . (< this ord does not make a copy of the input sequence< and runs in constant time.( . ! ?'&;: sum + *values + (seq( (a sequence of numbers( . + (n( (a number( . . + *description (Butputs the sum of all elements of ( + *snippet (seq( . (. Butputs 8ero given an empty sequence.( . ! ?'&;: product + *values + (seq( (a sequence of numbers( . + (n( (a number( . . + *description (Butputs the product of all elements of ( + *snippet (seq( . (. Butputs one given an empty sequence.( . ! ?'&;: infimum + *values + (seq( (a sequence of real numbers( . + (n( (a number( . . + *description (Butputs the least element of ( + *snippet (seq( . (.( . + *errors ($hro s an error if the sequence is empty.( . !

?'&;: supremum + *values + (seq( (a sequence of real numbers( . + (n( (a number( . . + *description (Butputs the greatest element of ( + *snippet (seq( . (.( . + *errors ($hro s an error if the sequence is empty.( . ! + min max supremum infimum . related) ords ?'&;: produce + *values + (pred( + *quotation (5 ..a )) ..b : 6( . . + (quot( + *quotation (5 ..b )) ..a obF 6( . . + (seq( (a sequence( . . + *description (%alls ( + *snippet (pred( . ( repeatedly. If the predicate yields ( + *link f . (< stops< other ise< calls ( + *snippet (quot( . ( to yield a value. Values are accumulated and returned in a sequence at the end.( . + *examples ($he follo ing example divides a number by t o until e reach 8ero< and accumulates intermediate results:( + *example (USING: kernel math prettyprint sequences !( (1--R 0 dup = G 3 0 ,Q dup 3 produce nip .( (+ LLS --/ 1LR S- /1 ,= 1= A , 1 = .( . ($he follo ing example collects random numbers as long as they are greater than 1:( + *unchecked)example (USING: kernel prettyprint random sequences !( (0 1= random dup 1 G 3 0 3 produce nip .( (+ S , , U .( . . ! ?'&;: produce)as + *values + (pred( + *quotation (5 ..a )) ..b : 6( . . + (quot( + *quotation (5 ..b )) ..a obF 6( . . + (exemplar( sequence . + (seq( (a sequence( . . + *description (%alls ( + *snippet (pred( . ( repeatedly. If the predicate yields ( + *link f . (< stops< other ise< calls ( + *snippet (quot( . ( to yield a value. Values are accumulated and returned in a sequence of type ( + *snippet (exemplar( . ( at the end.( . + *examples (See ( + *link produce . ( for examples.( . ! ?'&;: map)sum + *values + (seq( sequence . + (quot( quotation . + (n( number . . + *description (&ike ( + *snippet (map sum( . (< but ithout creating an intermediate sequence.( . + *examples + *example (USING: math math.ranges sequences prettyprint !( (1== 01<b3 0 sq 3 map)sum .( (--S-A=( . . ! ?'&;: count + *values + (seq( sequence . + (quot( quotation . + (n( integer . . + *description ('fficiently returns the number of elements that the predicate quotation matches.( . + *examples + *example (USING: math math.ranges sequences prettyprint !( (1== 01<b3 0 even: 3 count .( (A=( . . ! ?'&;: selector + *values + (quot( + *quotation (5 ... elt )) ... : 6( . . + (selector( + *quotation (5 ... elt )) ... 6( . . + (accum( vector . .

+ *description (%reates a ne vector to accumulate the values hich return true for a predicate. #eturns a ne quotation hich accepts an obFect to be tested and stored in the collector if the test yields true. $he collector is left on the stack for convenience.( . + *examples + *example (K @ind all the even numbers:( (USING: prettyprint sequences math kernel !( (1= iota 0 even: 3 selector 0 each 3 dip .( (V+ = , / L S .( . . + *notes (Used to implement the ( + *link filter . ( ord. %ompare this ord ith ( + *link collector . (< hich is an unfiltering version.( . ! ?'&;: trim)head + *values + (seq( sequence . + (quot( quotation . + (ne seq( sequence . . + *description (#emoves elements starting from the left side of a sequence if they match a predicate. Bnce an element does not match< the test stops and the rest of the sequence is left on the stack as a ne sequence.( . + *examples + *example (USING: prettyprint math sequences !( (+ = = 1 , - = = . 0 8ero: 3 trim)head .( (+ 1 , - = = .( . . ! ?'&;: trim)head)slice + *values + (seq( sequence . + (quot( quotation . + (slice( slice . . + *description (#emoves elements starting from the left side of a sequence if they match a predicate. Bnce an element does not match< the test stops and the rest of the sequence is left on the stack as a slice.( . + *examples + *example (USING: prettyprint math sequences !( (+ = = 1 , - = = . 0 8ero: 3 trim)head)slice .( ($+ slice + from , . + to R . + seq + = = 1 , - = = . . .( . . ! ?'&;: trim)tail + *values + (seq( sequence . + (quot( quotation . + (ne seq( sequence . . + *description (#emoves elements starting from the right side of a sequence if they match a predicate. Bnce an element does not match< the test stops and the rest of the sequence is left on the stack as a ne sequence.( . + *examples + *example (USING: prettyprint math sequences !( (+ = = 1 , - = = . 0 8ero: 3 trim)tail .( (+ = = 1 , - .( . . ! ?'&;: trim)tail)slice + *values + (seq( sequence . + (quot( quotation . + (slice( slice . . + *description (#emoves elements starting from the right side of a sequence if they match a predicate. Bnce an element does not match< the test stops and the

rest of the sequence is left on the stack as a slice.( . + *examples + *example (USING: prettyprint math sequences !( (+ = = 1 , - = = . 0 8ero: 3 trim)tail)slice .( ($+ slice + from = . + to A . + seq + = = 1 , - = = . . .( . . ! ?'&;: trim + *values + (seq( sequence . + (quot( quotation . + (ne seq( sequence . . + *description (#emoves elements starting from the left and right sides of a sequence if they match a predicate. Bnce an element does not match< the test stops and the rest of the sequence is left on the stack as a ne sequence.( . + *examples + *example (USING: prettyprint math sequences !( (+ = = 1 , - = = . 0 8ero: 3 trim .( (+ 1 , - .( . . ! ?'&;: trim)slice + *values + (seq( sequence . + (quot( quotation . + (slice( slice . . + *description (#emoves elements starting from the left and right sides of a sequence if they match a predicate. Bnce an element does not match< the test stops and the rest of the sequence is left on the stack as a slice.( . + *examples + *example (USING: prettyprint math sequences !( (+ = = 1 , - = = . 0 8ero: 3 trim)slice .( ($+ slice + from , . + to A . + seq + = = 1 , - = = . . .( . . ! + trim trim)slice trim)head trim)head)slice trim)tail trim)tail)slice . related) ords ?'&;: sift + *values + (seq( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence ith all instance of ( + *link f . ( removed.( . + *examples + *example (USING: prettyprint sequences !( (+ >(a>( - + . f . sift .( (+ >(a>( - + . .( . . ! ?'&;: harvest + *values + (seq( sequence . + (ne seq( sequence . . + *description (Butputs a ne sequence ith all empty sequences removed.( . + *examples + *example (USING: prettyprint sequences !( (+ + . + , - . + A . + . . harvest .( (+ + , - . + A . .( .

. ! + filter filterK sift harvest . related) ords ?'&;: set)first + *values + (first( obFect . + (seq( sequence . . + *description (Sets the first element of a sequence.( . + *examples + *example (USING: prettyprint kernel sequences !( (+ 1 , - / . A over set)first .( (+ A , - / .( . . ! ?'&;: set)second + *values + (second( obFect . + (seq( sequence . . + *description (Sets the second element of a sequence.( . + *examples + *example (USING: prettyprint kernel sequences !( (+ 1 , - / . A over set)second .( (+ 1 A - / .( . . ! ?'&;: set)third + *values + (third( obFect . + (seq( sequence . . + *description (Sets the third element of a sequence.( . + *examples + *example (USING: prettyprint kernel sequences !( (+ 1 , - / . A over set)third .( (+ 1 , A / .( . . ! ?'&;: set)fourth + *values + (fourth( obFect . + (seq( sequence . . + *description (Sets the fourth element of a sequence.( . + *examples + *example (USING: prettyprint kernel sequences !( (+ 1 , - / . A over set)fourth .( (+ 1 , - A .( . . ! + set)first set)second set)third set)fourth . related) ords ?'&;: replicate + *values + (len( integer . + (quot( + *quotation (5 ... )) ... ne elt 6( . . + (ne seq( sequence . . + *description (%alls the quotation ( + *snippet (len( . ( times< collecting results into a ne array.( . + *examples + *unchecked)example (USING: kernel prettyprint random sequences !( (A 0 1== random 3 replicate .( (+ A, 1= /A S1 -= .( . . !

?'&;: replicate)as + *values + (len( integer . + (quot( + *quotation (5 ... )) ... ne elt 6( . . + (exemplar( sequence . + (ne seq( sequence . . + *description (%alls the quotation ( + *snippet (len( . ( times< collecting results into a ne sequence of the same type as the exemplar sequence.( . + *examples + *unchecked)example (USING: prettyprint kernel sequences !( (A 0 1== random 3 E+ . replicate)as .( (E+ // S , -- 1S .( . . ! + replicate replicate)as . related) ords ?'&;: partition + *values + (seq( sequence . + (quot( quotation . + (trueseq( sequence . + (falseseq( sequence . . + *description (%alls a predicate quotation on each element of the input sequence. If the test yields true< the element is added to ( + *snippet (trueseq( . (! if false< it7s added to ( + *snippet (falseseq( . (.( . + *examples + *example (USING: prettyprint kernel math sequences !( (+ 1 , - / A . 0 even: 3 partition 0 . 3 bi9( (+ , / .>n+ 1 - A .( . . ! ?'&;: virtual)exemplar + *values + (seq( sequence . + (seq7( sequence . . + *description (;art of the virtual sequence protocol< this ord is used to return an exemplar of the underlying storage. $his is used in ords like ( + *link ne )sequence . (.( . ! ?'&;: virtual9 + *values + (n( integer . + (seq( sequence . + (n7( integer . + (seq7( sequence . . + *description (;art of the sequence protocol< this ord translates the input index ( + *snippet (n( . ( into an index and the underlying storage this index points into.( . ! ?'&;: ,map)reduce + *values + (seq1( sequence . + (seq,( sequence . + (map)quot( + *quotation (5 ..a elt1 elt, )) ..b intermediate 6( . . + (reduce)quot( + *quotation (5 ..b prev intermediate )) ..a next 6( . . + (result( obFect . . + *description (%alls ( + *snippet (map)quot( . ( on each pair of elements from ( + *snippet (seq1( . ( and ( + *snippet (seq,( . ( and combines the results using ( + *snippet (reduce)quot( . ( in the same manner as ( + *link reduce . (< except that there is no identity element< and the sequence must have a length of at least 1.( . + *errors ($hro s an error if the sequence is empty.( . + *examples + *example (USING: sequences prettyprint math !( (+ 1= -= A= . + ,== /== L== . 0 2 3 0 2 3 ,map)reduce .( (1,U=(

. . ! ?'&;: ,selector + *values + (quot( quotation . + (selector( quotation . + (accum1( vector . + (accum,( vector . . + *description (%reates t o ne vectors to accumulate values based on a predicate. $he first vector accumulates values for hich the predicate yields true! the second for false.( . ! ?'&;: collector + *values + (quot( quotation . + (quot7( quotation . + (vec( vector . . + *description (%reates a ne quotation that pushes its result to a vector and outputs that vector on the stack.( . + *examples + *example (USING: sequences prettyprint kernel math !( (+ 1 , . 0 -= 2 3 collector 0 each 3 dip .( (V+ -1 -, .( . . ! ?'&;: binary)reduce + *values + (seq( sequence . + (start( integer . + (quot( + *quotation (5 ... elt1 elt, )) ... ne elt 6( . . + (value( obFect . . + *description (&ike ( + *link reduce . (< but splits the sequence in half recursively until each sequence is small enough< and calls the quotation on these smaller sequences. If the quotation computes values that depend on the si8e of their input< such as bignum arithmetic< then this algorithm can be more efficient than using ( + *link reduce . (.( . + *examples (%omputing factorial:( + *example (USING: prettyprint sequences math !( (/= iota rest)slice 1 0 4 3 binary)reduce .( (,=-URSS,=S11UR//--ASL/=,S1R-UU=,SUR-ALS========( . . ! ?'&;: follo + *values + (obF( obFect . + (quot( + *quotation (5 ... prev )) ... resultQf 6( . . + (seq( sequence . . + *description (Butputs a sequence containing the input obFect and all of the obFects generated by successively feeding the result of the quotation called on the input obFect to the quotation recursively. BbFects yielded by the quotation are added to the output sequence until the quotation yields ( + *link f . (< at hich point the recursion terminates.( . + *examples (Get random numbers until 8ero is reached:( + *unchecked)example (USING: random sequences prettyprint math !( (1== 0 random 0 f 3 hen)8ero 3 follo .( (+ 1== SL -/ -, ,/ 11 R , .( . . ! ?'&;: halves + *values + (seq( sequence . + (first)slice( slice . + (second)slice( slice . . + *description (Splits a sequence into t o slices at the midpoint. If the sequence has an odd number of elements< the extra element is returned in the second slice.( . + *examples + *example (USING: arrays sequences prettyprint kernel !( (+ 1 , - / A . halves 0 Garray . 3 bi9(

(+ 1 , .>n+ - / A .( . . ! ?'&;: indices + *values + (obF( obFect . + (seq( sequence . + (indices( sequence . . + *description (%ompares the input obFect to every element in the sequence and returns a vector containing the index of every position here the element as found.( . + *examples + *example (USING: sequences prettyprint !( (, + , / , L , S , 1= . indices .( (V+ = , / L .( . . ! ?'&;: insert)nth + *values + (elt( obFect . + (n( integer . + (seq( sequence . + (seq7( sequence . . + *description (%reates a ne sequence here the ( + *snippet (n( . (th index is set to the input obFect.( . + *examples + *example (USING: prettyprint sequences !( (/= - + 1= ,= -= A= . insert)nth .( (+ 1= ,= -= /= A= .( . . ! ?'&;: map)reduce + *values + (seq( sequence . + (map)quot( + *quotation (5 ..a elt )) ..b intermediate 6( . . + (reduce)quot( + *quotation (5 ..b prev intermediate )) ..a next 6( . . + (result( obFect . . + *description (%alls ( + *snippet (map)quot( . ( on each element and combines the results using ( + *snippet (reduce)quot( . ( in the same manner as ( + *link reduce . (< except that there is no identity element< and the sequence must have a length of at least 1.( . + *errors ($hro s an error if the sequence is empty.( . + *examples + *example (USING: sequences prettyprint math !( (+ 1 - A . 0 sq 3 0 2 3 map)reduce .( (-A( . . ! ?'&;: ne )like + *values + (len( integer . + (exemplar( (an exemplar sequence( . + (quot( quotation . + (seq( sequence . . + *description (%reates a ne sequence of length ( + *snippet (len( . ( and calls the quotation ith this sequence on the stack. $he output of the quotation and the original exemplar are then passed to ( + *link like . ( so that the output sequence is the exemplar7s type.( . ! ?'&;: push)either + *values + (elt( obFect . + (quot( quotation . + (accum1( vector . + (accum,( vector . . + *description (;ushes the input obFect onto one of the accumulators! the first if the quotation yields true< the second if false.( . ! ?'&;: sequence)hashcode + *values + (n( integer . + (seq( sequence . + (x( integer . .

+ *description (Iterates over a sequence< computes a hashcode ith ( + *link hashcode4 . ( for each element< and combines them using ( + *link sequence)hashcode)step . (.( . ! ?'&;: sequence)hashcode)step + *values + (oldhash( integer . + (ne part( integer . + (ne hash( integer . . + *description ("n implementation ord that computes a running hashcode of a sequence using some bit)t iddling. $he resulting hashcode is al ays a fixnum.( . ! ?'&;: short + *values + (seq( sequence . + (n( integer . + (n7( integer . . + *description (#eturns the input sequence and its length or ( + *snippet (n( . (< hichever is less.( . + *examples + *example (USING: sequences kernel prettyprint !( (>(abcd>( - short 0 . 3 bi9( (>(abcd>(>n-( . . ! ?'&;: shorten + *values + (n( integer . + (seq( sequence . . + *description (Shortens a ( + *link (gro able( . ( sequence to be ( + *snippet (n( . ( elements long.( . + *examples + *example (USING: sequences prettyprint kernel !( (V+ 1 , - / A . - over shorten .( (V+ 1 , - .( . . ! ?'&;: iota + *values + (n( integer . + (iota( iota . . + *description (%reates an immutable virtual sequence containing the integers from = to ( + *snippet (n)1( . (.( . + *examples + *example (USING: math sequences prettyprint !( (- iota 0 sq 3 map .( (+ = 1 / .( . . ! ?'&;: assert)sequenceH + *values + (a( sequence . + (b( sequence . . + *description ($hro s an error if all the elements of t o sequences< taken pair ise< are not equal.( . + *notes ($he sequences need not be of the same type.( . + *examples + *code (USING: prettyprint sequences !( (+ 1 , - . V+ 1 , - . assert)sequenceH( . . ! ?'&;: cartesian)each + *values + (seq1( sequence . + (seq,( sequence . + (quot( + *quotation (5 ... elt1 elt, )) ... 6( . . . + *description ("pplies the quotation to every possible pairing of elements from

the t o sequences.( . ! ?'&;: cartesian)map + *values + (seq1( sequence . + (seq,( sequence . + (quot( + *quotation (5 ... elt1 elt, )) ... ne elt 6( . . + (ne seq( (a ne sequence of sequences( . . + *description ("pplies the quotation to every possible pairing of elements from the t o sequences< collecting results into a ne sequence of sequences.( . ! ?'&;: cartesian)product + *values + (seq1( sequence . + (seq,( sequence . + (ne seq( (a ne sequence of sequences of pairs( . . + *description (Butputs a sequence of all possible pairings of elements from the t o sequences.( . + *examples + *example (USING: prettyprint sequences !( (+ 1 , . + - / . cartesian)product .( (+ + + 1 - . + 1 / . . + + , - . + , / . . .( . . ! "#$I%&': (sequences)unsafe( (Unsafe sequence operations( ($he ( + *link nth)unsafe . ( and ( + *link set)nth)unsafe . ( sequence protocol bypasses bounds checks for increased performance.( *nl ($hese ords assume the sequence index given is ithin bounds! if it is not< memory corruption can occur. Great care must be exercised hen using these ords. @irst< make sure the code in question is actually a bottleneck! next< try improving the algorithm first. If all else fails< then the unsafe sequence ords can be used.( *nl ($here is a very important invariant these ord must preserve: if at some point in time< the length of a sequence as ( + *snippet (n( . (< then any future lookups of elements ith indices belo ( + *snippet (n( . ( must not crash the VI< even if the sequence length is no less than ( + *snippet (n( . (. @or example< vectors preserve this invariant by never shrinking the underlying storage< only gro ing it as necessary.( *nl ($he Fustification for this is that the VI should not crash if a resi8able sequence is resi8ed during the execution of an iteration combinator.( *nl (Indeed< iteration combinators are the primary use)case for these ords! if the iteration index is already guarded by a loop test hich ensures it is ithin bounds< then additional bounds checks are redundant. @or example< see the implementation of ( + *link each . (.( ! "#$I%&': (sequence)protocol( (Sequence protocol( ("ll sequences must be instances of a mixin class:( + *subsections sequence sequence: . ("ll sequences must kno their length:( + *subsections length . ("t least one of the follo ing t o generic ords must have a method for accessing elements! the ( + *link sequence . ( mixin has default definitions hich are mutually recursive:( + *subsections nth nth)unsafe . (Note that sequences are al ays indexed starting from 8ero.( *nl ("t least one of the follo ing t o generic ords must have a method for storing elements! the ( + *link sequence . ( mixin has default definitions hich are mutually recursive:( + *subsections set)nth set)nth)unsafe . (If your sequence is immutable< then you must implement either ( + *link set)nth

. ( or ( + *link set)nth)unsafe . ( to simply call ( + *link immutable . ( to signal an error.( *nl ($he follo ing t o generic ords are optional< as not all sequences are resi8able:( + *subsections set)length lengthen . ("n optional generic ord for creating sequences of the same class as a given sequence:( + *subsections like . (Bptional generic ords for optimi8ation purposes:( + *subsections ne )sequence ne )resi8able . + *see)also (sequences)unsafe( . ! "#$I%&': (virtual)sequences)protocol( (Virtual sequence protocol( (Virtual sequences must kno their length:( + *subsections length . ("n exemplar of the underlying storage:( + *subsections virtual)exemplar . ($he index and the underlying storage here the value is located:( + *subsections virtual9 . ! "#$I%&': (virtual)sequences( (Virtual sequences( (" virtual sequence is an implementation of the ( + *link (sequence)protocol( . ( hich does not store its o n elements< and instead computes them< either from scratch or by retrieving them from another sequence.( *nl (Implementations include the follo ing:( + *subsections reversed slice . (Virtual sequences can be implemented ith the ( + *link (virtual)sequences)protocol( . (< by translating an index in the virtual sequence into an index in another sequence.( + *see)also (sequences)integers( . ! "#$I%&': (sequences)integers( (%ounted loops( (" virtual sequence is defined for iterating over integers from 8ero.( + *subsection iota . (@or example< calling ( + *link iota . ( on the integer - produces a sequence containing the elements =< 1< and ,. $his is very useful for performing counted loops using ords such as ( + *link each . (:( + *example (USING: sequences prettyprint ! - iota 0 . 3 each( (=>n1>n,( . (" common idiom is to iterate over a sequence< hile also maintaining a loop counter. $his can be done using ( + *link each)index . (< ( + *link map)index . ( and ( + *link reduce)index . (.( *nl (%ombinators that produce ne sequences< such as ( + *link map . (< ill output an array if the input is an instance of ( + *link iota . (.( *nl (Iore elaborate counted loops can be performed ith ( + *link (math.ranges( . (.( ! "#$I%&': (sequences)if( (%ontrol flo ith sequences( ($o reduce the boilerplate of checking if a sequence is empty< several combinators are provided.( *nl (%hecking if a sequence is empty:( + *subsections if)empty hen)empty unless)empty . ! "#$I%&': (sequences)access( ("ccessing sequence elements( ('lement access by index< ithout raising exceptions:( + *subsections :nth . (%oncise ay of extracting one of the first four elements:( + *subsections first second third fourth :first :second .

('xtracting the last element:( + *subsections last :last . (Unpacking sequences:( + *subsections first, first- first/ . + *see)also nth . ! "#$I%&': (sequences)add)remove( ("dding and removing sequence elements( ("dding elements:( + *subsections prefix suffix insert)nth . (#emoving elements:( + *subsections remove remove)eq remove)nth . ! "#$I%&': (sequences)reshape( (#eshaping sequences( (" ( + *emphasis (repetition( . ( is a virtual sequence consisting of a single element repeated multiple times:( + *subsections repetition PrepetitionG . (#eversing a sequence:( + *subsections reverse . (" ( + *emphasis (reversal( . ( presents a reversed vie of an underlying sequence:( + *subsections reversed PreversedG . ($ransposing a matrix:( + *subsections flip . ! "#$I%&': (sequences)appending( ("ppending sequences( (Easic append operations:( + *subsections append append)as prepend -append -append)as surround glue . (%ollapse a sequence unto itself:( + *subsections concat Foin . (" pair of ords useful for aligning strings:( + *subsections pad)head pad)tail . ! "#$I%&': (sequences)slices( (Subsequences and slices( ($here are t o ays to extract a subrange of elements from a sequence. $he first approach creates a ne sequence of the same type as the input< hich does not share storage ith the underlying sequence. $his takes time proportional to the number of elements being extracted. $he second approach creates a ( + *emphasis (slice( . (< hich is a virtual sequence 5see ( + *link (virtual)sequences( . (6 sharing storage ith the original sequence. Slices are constructed in constant time.( *nl (Some general guidelines for choosing bet een the t o approaches:( + *list (If you are using mutable state< the choice has to be made one ay or another because of semantics! mutating a slice ill change the underlying sequence.( + (Using a slice can improve algorithmic complexity. @or example< if each iteration of a loop decomposes a sequence using ( + *link first . ( and ( + *link rest . (< then the loop ill run in quadratic time< relative to the length of the sequence. Using ( + *link rest)slice . ( changes the loop to run in linear time< since ( + *link rest)slice . ( does not copy any elements. $aking a slice of a slice ill ]collapse^ the slice so to avoid the double indirection< so it is safe to use slices in recursive code.( . ("ccessing elements from a concrete sequence 5such as a string or an array6 is often faster than accessing elements from a slice< because slice access entails

additional indirection. ?o ever< in some cases< if the slice is immediately consumed by an iteration combinator< the compiler can eliminate the slice allocation and indirect altogether.( (If the slice outlives the original sequence< the original sequence ill still remain in memory< since the slice ill reference it. $his can increase memory consumption unnecessarily.( . + *heading (Subsequence operations( . ('xtracting a subsequence:( + *subsections subseq head tail head4 tail4 . (#emoving the first or last element:( + *subsections rest but)last . ($aking a sequence apart into a head and a tail:( + *subsections unclip unclip)last cut cut4 . + *heading (Slice operations( . ($he slice data type:( + *subsections slice slice: . ('xtracting a slice:( + *subsections PsliceG head)slice tail)slice head)slice4 tail)slice4 . (#emoving the first or last element:( + *subsections rest)slice but)last)slice . ($aking a sequence apart into a head and a tail:( + *subsections unclip)slice unclip)last)slice cut)slice . (#eplacing slices ith ne elements:( + *subsections replace)slice . ! "#$I%&': (sequences)combinators( (Sequence combinators( (Iteration:( + *subsections each each)index reduce interleave replicate replicate)as . (Iapping:( + *subsections map map)as map)index map)reduce accumulate accumulate)as accumulateK

. (@iltering:( + *subsections filter filter)as partition . ($esting if a sequence contains elements satisfying a predicate:( + *subsections any: all: . + *heading (#elated "rticles( . + *subsections (sequence),combinators( (sequence)-combinators( . ! "#$I%&': (sequence),combinators( (;air) ise sequence combinators( ($here is a set of combinators hich traverse t o sequences pair ise. If one sequence is shorter than the other< then only the prefix having the length of the minimum of the t o is examined.( + *subsections ,each ,reduce ,map ,map)as ,map)reduce ,all: . ! "#$I%&': (sequence)-combinators( ($riple) ise sequence combinators( ($here is a set of combinators hich traverse three sequences triple) ise. If one sequence is shorter than the others< then only the prefix having the length of the minimum of the three is examined.( + *subsections -each -map -map)as . ! "#$I%&': (sequences)tests( ($esting sequences( ($esting for an empty sequence:( + *subsections empty: . ($esting indices:( + *subsections bounds)check: . ($esting if a sequence contains an obFect:( + *subsections member: member)eq: . ($esting if a sequence contains a subsequence:( + *subsections head: tail: subseq: . ! "#$I%&': (sequences)search( (Searching sequences( (@inding the index of an element:( + *subsections index index)from last)index last)index)from . (@inding the start of a subsequence:( + *subsections start start4 . (@inding the index of an element satisfying a predicate:( + *subsections find

produce produce)as

. !

find)from find)last find)last)from map)find

"#$I%&': (sequences)trimming( ($rimming sequences( ($rimming ords:( + *subsections trim trim)head trim)tail . (;otentially more efficient trim:( + *subsections trim)slice trim)head)slice trim)tail)slice . ! "#$I%&': (sequences)destructive)discussion( (Jhen to use destructive operations( (%onstructive 5non)destructive6 operations should be preferred here possible because code ithout side)effects is usually more reusable and easier to reason about. $here are t o main reasons to use destructive operations:( + *list (@or the side)effect. Some code is simpler to express ith destructive operations! constructive operations return ne obFects< and sometimes __threading77 the obFects through the program manually complicates stack shuffling.( + ("s an optimi8ation. Some code ritten to use constructive operations suffers from orse performance. "n example is a loop hich adds an element to a sequence on each iteration. 'ither ( + *link suffix . ( or ( + *link suffixK . ( could be used! ho ever< the former copies the entire sequence each time< hich ould cause the loop to run in quadratic time.( . . ($he second reason is much eaker than the first one. In particular< many combinators 5see ( + *link map . (< ( + *link produce . ( and ( + *link (namespaces)make( . (6 as ell as more advanced data structures 5such as ( + *vocab)link (persistent.vectors( . (6 alleviate the need for explicit use of side effects.( ! "#$I%&': (sequences)destructive( (Cestructive sequence operations( (Iany operations have destructive variants that side effect an input sequence< instead of creating a ne sequence:( + *table + (%onstructive( (Cestructive( . + + *link suffix . + *link suffixK . . + + *link remove . + *link removeK . . + + *link remove)eq . + *link remove)eqK . . + + *link remove)nth . + *link remove)nthK . . + + *link reverse . + *link reverseK . . + + *link append . + *link appendK . . + + *link map . + *link mapK . . + + *link filter . + *link filterK . . . (%hanging elements:( + *subsections mapK change)nth . (Celeting elements:( + *subsections removeK remove)eqK remove)nthK delete)slice delete)all filterK . ("dding elements:( + *subsections suffixK appendK

. (Bther destructive ords:( + *subsections reverseK move exchange copy . + *heading (#elated "rticles( . + *subsections (sequences)destructive)discussion( (sequences)stacks( . + *see)also set)nth push push)all pop pop4 . ! "#$I%&': (sequences)stacks( ($reating sequences as stacks( ($he classical stack operations< modifying a sequence in place:( + *subsections push push)all pop pop4 . + *see)also empty: . ! "#$I%&': (sequences)comparing( (%omparing sequences( ('lement equality testing:( + *subsections sequenceH mismatch drop)prefix assert)sequenceH . ($he ( + *link PHG . ( generic ord performs lexicographic comparison applied to sequences.( !

hen

"#$I%&': (sequences)f( ($he f obFect as a sequence( ($he ( + *link f . ( obFect supports the sequence protocol in a trivial ay. It responds ith a length of 8ero and thro s an out of bounds error hen an attempt is made to access elements.( ! "#$I%&': (sequences)combinator)implementation( (Implementing sequence combinators( (%reating a ne sequence unconditionally:( + *subsections collector collector)for . (%reating a ne sequence conditionally:( + *subsections selector selector)for ,selector . ! "#$I%&': (sequences)cartesian( (%artesian product operations( ($he cartesian product of t o sequences is a sequence of all pairs here the first element of each pair is from the first sequence< and the second element of each pair is from the second sequence. $he number of elements in the cartesian product is the product of the lengths of the t o sequences.( *nl (%ombinators hich pair every element of the first sequence ith every element of the second:( + *subsections cartesian)each cartesian)map .

(%omputing the cartesian product of t o sequences:( + *subsections cartesian)product . ! "#$I%&': (sequences( (Sequence operations( (" ( + *emphasis (sequence( . ( is a finite< linearly)ordered collection of elements. Jords for orking ith sequences are in the ( + *vocab)link (sequences( . ( vocabulary.( *nl (Sequences implement a protocol:( + *subsections (sequence)protocol( (sequences)f( . (Sequence utility ords can operate on any obFect hose class implements the sequence protocol. Iost implementations are backed by storage. Some implementations obtain their elements from an underlying sequence< or compute them on the fly. $hese are kno n as ( + *link (virtual)sequences( . (.( + *subsections (sequences)access( (sequences)combinators( (sequences)add)remove( (sequences)appending( (sequences)slices( (sequences)reshape( (sequences)tests( (sequences)search( (sequences)comparing( (sequences)split( (grouping( (sequences)destructive( (sequences)stacks( (sequences)sorting( (binary)search( (sets( (sequences)trimming( (sequences)cartesian( (sequences.deep( . (Using sequences for looping:( + *subsections (sequences)integers( (math.ranges( . (Using sequences for control flo :( + *subsections (sequences)if( . (@or inner loops:( + *subsections (sequences)unsafe( . (Implementing sequence combinators:( + *subsections (sequences)combinator)implementation( . ! "EBU$: (sequences( K %opyright 5%6 ,==A< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: arrays kernel math sequences strings sbufs ! IN: splitting P;#IV"$' : :chomp 5 seq begin tester chopper )) ne seq : 6 0 0 ,dup 3 dip call 3 dip

0 0 length 3 dip call t 3 curry 0 drop f 3 if ! inline ;#IV"$'G : :head 5 seq begin )) ne seq : 6 0 head: 3 0 tail 3 :chomp ! : :head)slice 5 seq begin )) ne seq : 6 0 head: 3 0 tail)slice 3 :chomp ! : :tail 5 seq end )) ne seq : 6 0 tail: 3 0 head4 3 :chomp ! : :tail)slice 5 seq end )) ne seq : 6 0 tail: 3 0 head)slice4 3 :chomp ! P;#IV"$' : 5split16 5 seq subseq snip)quot )) before after 6 0 s ap 0 0 drop length 3 0 start dup 3 ,bi 0 0 nip 3 0 2 3 ,bi t 3 0 ,drop f f f 3 if 3 keep s ap 3 dip 0 ,nip f 3 if ! inline ;#IV"$'G : split1 5 seq subseq )) before after 6 0 snip 3 5split16 ! : split1)slice 5 seq subseq )) before)slice after)slice 6 0 snip)slice 3 5split16 ! : split)subseq 5 seq subseq )) seqs 6 dup empty: 0 drop 1array 3 0 0 dup 3 s ap 0 split1)slice s ap 3 curry produce nip 3 if ! : replace 5 seq old ne )) ne )seq 6 pick 0 0 split)subseq 3 dip 3 dip Foin)as ! P;#IV"$' : 5split1) hen6 5 ... seq quot: 5 ... elt )) ... : 6 snip)quot )) ... before)slice after)slice 6 0 dupd find drop 3 dip 0 s ap 0 dup 1 2 3 dip 3 prepose 0 f 3 if4 ! inline ;#IV"$'G : split1) hen 5 ... seq quot: 5 ... elt )) ... : 6 )) ... before after 6 0 snip 3 5split1) hen6 ! inline : split1) hen)slice 5 ... seq quot: 5 ... elt )) ... : 6 )) ... before)slice after)slice 6 0 snip)slice 3 5split1) hen6 ! inline

: split1)last 5 seq subseq )) before after 6 0 PreversedG 3 bi9 split1 0 reverse 3 bi9 dup 0 s ap 3 hen ! : split1)last)slice 5 seq subseq )) before)slice after)slice 6 0 PreversedG 3 bi9 split1)slice 0 PreversedG 3 bi9 0 f 3 0 s ap 3 if)empty ! P;#IV"$' : 5split6 5 n seq quot: 5 ... elt )) ... : 6 slice)quot )) pieces 6 pick 0 s ap curry 0 keep 1 2 s ap 3 curry 0 0 find)from drop dup 3 ,curry 0 keep )rot 3 curry 3 dip produce nip 3 ,keep s ap 0 0 length s apd 3 keep 3 dip ,curry call suffix ! inline ;#IV"$'G : split) hen 5 ... seq quot: 5 ... elt )) ... : 6 )) ... pieces 6 0 = 3 ,dip 0 subseq 3 5split6 ! inline : split) hen)slice 5 ... seq quot: 5 ... elt )) ... : 6 )) ... pieces 6 0 = 3 ,dip 0 PsliceG 3 5split6 ! inline : split 5 seq separators )) pieces 6 0 member: 3 curry split) hen ! inline : split)slice 5 seq separators )) pieces 6 0 member: 3 curry split) hen)slice ! inline G'N'#I%: string)lines 5 str )) seq 6 I: string string)lines dup 0 (>r>n( member: 3 any: 0 (>n( split 0 but)last)slice 0 dup :last %?"#: >r H 0 but)last 3 hen 0 %?"#: >r H 3 split) hen 3 mapK drop 3 0 0 length 1 ) 3 keep 0 0 %?"#: >r H 3 split) hen 3 change)nth 3 0 concat 3 tri 3 0 1array 3 if ! I: sbuf string)lines (( like string)lines ! USING: help.markup help.syntax sequences strings ! IN: splitting "#$I%&': (sequences)split( (Splitting sequences( (Splitting sequences at occurrences of subsequences:( + *subsections :head :head)slice

:tail :tail)slice split1 split1)slice split1) hen split1) hen)slice split1)last split1)last)slice split split) hen split) hen)slice . (Splitting a string into lines:( + *subsections string)lines . (#eplacing subsequences ith another subsequence:( + *subsections replace . ! "EBU$: (sequences)split( ?'&;: split1 + *values + (seq( (a sequence( . + (subseq( (a sequence( . + (before( (a ne sequence( . + (after( (a ne sequence( . . + *description (Splits ( + *snippet (seq( . ( at the first occurrence of ( + *snippet (subseq( . (< and outputs the pieces before and after the split. If ( + *snippet (subseq( . ( does not occur in ( + *snippet (seq( . (< then ( + *snippet (before( . ( is Fust ( + *snippet (seq( . ( and ( + *snippet (after( . ( is ( + *link f . (.( . ! ?'&;: split1)slice + *values + (seq( (a sequence( . + (subseq( (a sequence( . + (before)slice( slice . + (after)slice( slice . . + *description (Splits ( + *snippet (seq( . ( at the first occurrence of ( + *snippet (subseq( . (< and outputs the pieces before and after the split as slices. If ( + *snippet (subseq( . ( does not occur in ( + *snippet (seq( . (< then ( + *snippet (before( . ( is Fust ( + *snippet (seq( . ( and ( + *snippet (after( . ( is ( + *link f . (.( . ! ?'&;: split1) hen + *values + (seq( (a sequence( . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (before( (a ne sequence( . + (after( (a ne sequence( . . + *description (Splits ( + *snippet (seq( . ( at the first occurrence of an element for hich ( + *snippet (quot( . ( gives a true output and outputs the pieces before and after the split.( . ! ?'&;: split1) hen)slice + *values + (seq( (a sequence( . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (before)slice( slice . + (after)slice( slice . . + *description (Splits ( + *snippet (seq( . ( at the first occurrence of an element for hich ( + *snippet (quot( . ( gives a true output and outputs the pieces before and after the split as slices. If ( + *snippet (subseq( . ( does not occur in ( + *snippet (seq( . (< then ( + *snippet (before( . ( is Fust ( + *snippet (seq( . ( and ( + *snippet (after( . ( is ( + *link f . (.( . ! ?'&;: split1)last + *values + (seq( (a sequence( . + (subseq( (a sequence( . + (before( (a ne sequence( . + (after( (a ne sequence( . . + *description (Splits ( + *snippet (seq( . ( at the last occurrence of ( + *snippet (subseq( . (< and outputs the pieces before and after the split. If ( + *snippet (subseq( . ( does not occur in ( + *snippet (seq( . (< then ( + *snippet (before( . ( is Fust ( + *snippet (seq( . ( and ( + *snippet (after( . ( is ( + *link f . (.( . !

?'&;: split1)last)slice + *values + (seq( (a sequence( . + (subseq( (a sequence( . + (before)slice( slice . + (after)slice( slice . . + *description (Splits ( + *snippet (seq( . ( at the last occurrence of ( + *snippet (subseq( . (< and outputs the pieces before and after the split as slices. If ( + *snippet (subseq( . ( does not occur in ( + *snippet (seq( . (< then ( + *snippet (before( . ( is Fust ( + *snippet (seq( . ( and ( + *snippet (after( . ( is ( + *link f . (.( . ! + split1 split1)slice split1)last split1)last)slice . related) ords ?'&;: split) hen + *values + (seq( (a sequence( . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (pieces( (a ne array( . . + *description (Splits ( + *snippet (seq( . ( at each occurrence of an element for hich ( + *snippet (quot( . ( gives a true output and outputs an array of pieces. $he pieces do not include the elements along hich the sequence as split.( . + *examples + *example (USING: ascii kernel prettyprint splitting !( (>(hello< orld)ho .are:you>( 0 letter: not 3 split) hen .( (+ >(hello>( >( orld>( >(ho >( >(are>( >(you>( .( . . ! ?'&;: split) hen)slice + *values + (seq( (a sequence( . + (quot( + *quotation (5 ... elt )) ... : 6( . . + (pieces( (a ne array( . . + *description (Splits ( + *snippet (seq( . ( at each occurrence of an element for hich ( + *snippet (quot( . ( gives a true output and outputs an array of pieces as slices. $he pieces do not include the elements along hich the sequence as split.( . ! ?'&;: split + *values + (seq( (a sequence( . + (separators( (a sequence( . + (pieces( (a ne array( . . + *description (Splits ( + *snippet (seq( . ( at each occurrence of an element of ( + *snippet (separators( . ( and outputs an array of pieces. $he pieces do not include the elements along hich the sequence as split.( . + *examples + *example (USING: prettyprint splitting !( (>(hello orld)ho are you:>( >( )>( split .( (+ >(hello>( >( orld>( >(ho >( >(are>( >(you:>( .( . . ! ?'&;: :head + *values + (seq( (a sequence( . + (begin( (a sequence( . + (ne seq( (a ne sequence( . + (:( (a boolean( . . + *description ($ests if ( + *snippet (seq( . ( starts ith ( + *snippet (begin( . (. If there is a match< outputs the subrange of ( + *snippet (seq( . ( excluding ( + *snippet (begin( . (< and ( + *link t . (. If there is no match< outputs ( + *snippet (seq( . ( and ( + *link f . (.( . ! ?'&;: :head)slice + *values + (seq( (a sequence( . + (begin( (a sequence( . + (ne seq( slice . + (:( (a boolean( . . + *description (&ike ( + *link :head . (< except the resulting sequence is a ( + *link slice . (.( . ! ?'&;: :tail + *values + (seq( (a sequence( . + (end( (a sequence( . + (ne seq( (a ne sequence( . + (:( (a boolean( . . + *description ($ests if ( + *snippet (seq( . ( ends ith ( + *snippet (end( . (. If there is a match< outputs the subrange of ( + *snippet (seq( . ( excluding ( + *snippet (end( . (< and ( + *link t . (. If there is no match< outputs ( + *snippet (seq( . ( and ( + *link f . (.( . ! ?'&;: :tail)slice

+ *values + (seq( (a sequence( . + (end( (a sequence( . + (ne seq( slice . + (:( (a boolean( . . + *description (&ike ( + *link :tail . (< except the resulting sequence is a ( + *link slice . (.( . ! ?'&;: string)lines + *values + (str( string . + (seq( (a sequence of strings( . . + *description (Splits a string along line breaks.( . + *examples + *example (USING: prettyprint splitting !( (>(?ello>>r>>n orld>>n>( string)lines .( (+ >(?ello>( >( orld>( >(>( .( . . ! ?'&;: replace + *values + (seq( sequence . + (old( sequence . + (ne ( sequence . + (ne )seq( sequence . . + *description (#eplaces every occurrence of ( + *snippet (old( . ( ith ( + *snippet (ne ( . ( in the ( + *snippet (seq( . (.( . + *examples + *example (USING: io splitting !( (>(cool example is cool>( >(cool>( >(silly>( replace print( (silly example is silly( . . ! USING: splitting tools.test kernel sequences arrays strings ascii math ! IN: splitting.tests 0 0 0 0 0 0 0 0 (hello( ( (hello( ( (goodbye( (( (( 3 0 orld .( 3 0 (hello orld .( ( ( split1 3 unit)test orld)2.( 3 0 (hello)2 orld)2.( ()2( split1 3 unit)test f 3 0 (goodbye( ( ( split1 3 unit)test (great( (great( split1 3 unit)test

(hello orld( (.( 3 0 (hello orld .( ( ( split1)last 3 unit)test (hello)2 orld( (.( 3 0 (hello)2 orld)2.( ()2( split1)last 3 unit)test (goodbye( f 3 0 (goodbye( ( ( split1)last 3 unit)test (( (( 3 0 (great( (great( split1)last 3 unit)test

0 (hello orld( (.( 3 0 (hello orld .( ( ( split1)last)slice 0 Gstring 3 bi9 3 unit)test 0 (hello)2 orld( (.( 3 0 (hello)2 orld)2.( ()2( split1)last)slice 0 Gstring 3 bi9 3 unit)test 0 (goodbye( f 3 0 (goodbye( ( ( split1)last)slice 0 Gstring 3 dip 3 unit)test 0 (( f 3 0 (great( (great( split1)last)slice 0 Gstring 3 dip 3 unit)test 0 (and end( t 3 0 (Eeginning and end( (Eeginning ( :head 3 unit)test 0 (Eeginning and end( f 3 0 (Eeginning and end( (Eeginning x( :head 3 unit)test 0 (Eeginning and end( f 3 0 (Eeginning and end( (eginning ( :head 3 unit)test 0 (Eeginning( t 3 0 (Eeginning and end( ( and end( :tail 3 unit)test 0 (Eeginning and end( f 3 0 (Eeginning and end( (Eeginning x( :tail 3 unit)test 0 (Eeginning and end( f 3 0 (Eeginning and end( (eginning ( :tail 3 unit)test 0 + ($his( (is( (a( (split( (sentence( . 3 0 ($his is a split sentence( ( ( split 3 unit)test 0 + (BneJord( . 3 0 (BneJord( ( ( split 3 unit)test 0 + (a( (b( (c( (d( (e( (f( . 3 0 (aMbNcMdNeMf( (MN( split 3 unit)test

0 + (( (( . 3 0 ( ( ( ( split 3 unit)test 0 + (hey( . 3 0 (hey( ( ( split 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (?ello orld( t 3 0 (?ello orld>n( (>n( :tail 3 unit)test (?ello orld( f 3 0 (?ello orld( (>n( :tail 3 unit)test (( t 3 0 (>n( (>n( :tail 3 unit)test (( f 3 0 (( (>n( :tail 3 unit)test + + + + + + + + + + + + + + + + + + + + + + (( . 3 0 (( string)lines 3 unit)test (( (( . 3 0 (>n( string)lines 3 unit)test (( (( . 3 0 (>r( string)lines 3 unit)test (( (( . 3 0 (>r>n( string)lines 3 unit)test (hello( . 3 0 (hello( string)lines 3 unit)test (hello( (( . 3 0 (hello>n( string)lines 3 unit)test (hello( (( . 3 0 (hello>r( string)lines 3 unit)test (hello( (( . 3 0 (hello>r>n( string)lines 3 unit)test (hello( (hi( . 3 0 (hello>nhi( string)lines 3 unit)test (hello( (hi( . 3 0 (hello>rhi( string)lines 3 unit)test (hello( (hi( . 3 0 (hello>r>nhi( string)lines 3 unit)test (( . 3 0 SEU@( ( string)lines 3 unit)test (( (( . 3 0 SEU@( >n( string)lines 3 unit)test (( (( . 3 0 SEU@( >r( string)lines 3 unit)test (( (( . 3 0 SEU@( >r>n( string)lines 3 unit)test (hello( . 3 0 SEU@( hello( string)lines 3 unit)test (hello( (( . 3 0 SEU@( hello>n( string)lines 3 unit)test (hello( (( . 3 0 SEU@( hello>r( string)lines 3 unit)test (hello( (( . 3 0 SEU@( hello>r>n( string)lines 3 unit)test (hello( (hi( . 3 0 SEU@( hello>nhi( string)lines 3 unit)test (hello( (hi( . 3 0 SEU@( hello>rhi( string)lines 3 unit)test (hello( (hi( . 3 0 SEU@( hello>r>nhi( string)lines 3 unit)test

0 + (hey( ( orld( ( hat7s( (happening( . 3 0 (hey" orldE hat7s%happening( 0 &'$$'#: 3 split) hen 3 unit)test + + + , . + - . + A 1 . + R . . . 0 1 + , 1 - , A 1 - R . 0 dupd H dup 0 0 1 2 3 dip 3 hen 3 split) hen nip 3 unit)test 0 + (hey( ( orld( ( hat7s( (happening( . 3 0 (hey" orldE hat7s%happening( 0 &'$$'#: 3 split) hen)slice 0 Gstring 3 map 3 unit)test 0 (( f 3 0 (( 0 blank: 3 split1) hen 3 unit)test 0 (( ("E%( 3 0 ( "E%( 0 blank: 3 split1) hen 3 unit)test 0 (a( ( bc( 3 0 (a bc( 0 blank: 3 split1) hen 3 unit)test 0 (( f 3 0 (( 0 blank: 3 split1) hen)slice 3 unit)test 0 (( ("E%( 3 0 ( "E%( 0 blank: 3 split1) hen)slice 0 Gstring 3 bi9 3 unit)test 0 (a( ( bc( 3 0 (a bc( 0 blank: 3 split1) hen)slice 0 Gstring 3 bi9 3 unit)test + (abarbbarc( . 0 (afoobfooc( (foo( (bar( replace 3 unit)test + (abc( . 0 (afoobfooc( (foo( (( replace 3 unit)test

+ (afoobfooc( . 0 (afoobfooc( (( (bar( replace 3 unit)test + (afoobfooc( . 0 (afoobfooc( (( (( replace 3 unit)test + (( . 0 (( (( (( replace 3 unit)test K %opyright 5%6 ,==S< ,=1= Slava ;estov< Xoe Groff. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays combinators continuations io kernel math math.parser namespaces sequences source)files.errors strings vectors ! IN: lexer $U;&': lexer + text array . + line fixnum . + line)text maybe+ string . . + line)length fixnum . + column fixnum . + parsing) ords vector . ! $U;&': lexer)parsing) ord ord line line)text column !

: next)line 5 lexer )) 6 dup 0 lineGG 3 0 textGG 3 bi :nth 0 GGline)text 3 0 length GGline)length 3 bi 0 1 2 3 change)line = GGcolumn drop ! : push)parsing) ord 5 ord )) 6 lexer)parsing) ord ne s ap GG ord lexer get 0 0 lineGG GGline 0 line)textGG GGline)text 0 columnGG GGcolumn 3 0 parsing) ordsGG push 3 bi

3 3 3 tri !

: pop)parsing) ord 5 )) 6 lexer get parsing) ordsGG pop4 ! : ne )lexer 5 text class )) lexer 6 ne = GGline s ap GGtext V+ . clone GGparsing) ords dup next)line ! inline : PlexerG 5 text )) lexer 6 lexer ne )lexer ! '##B#: unexpected ant got ! hen 3 keep ! inline

: forbid)tab 5 c )) c 6 0 %?"#: >t eq: 0 (0space3( (0tab3( unexpected 3

: skip 5 i seq : )) n 6 over length 0 0 s ap forbid)tab %?"#: >s eq: xor 3 curry find)from drop 3 dip or !

: change)lexer)column 5 lexer quot )) 6 0 0 columnGG 3 0 line)textGG 3 bi 3 prepose keep columnPP ! inline G'N'#I%: skip)blank 5 lexer )) 6 I: lexer skip)blank 5 lexer )) 6 0 t skip 3 change)lexer)column ! G'N'#I%: skip) ord 5 lexer )) 6 P;#IV"$' : quote: 5 column text )) : 6 nth %?"#: ( eq: ! inline : shebang: 5 column text )) : 6 s ap 8ero: 0 (ZK( head: 3 0 drop f 3 if ! inline ;#IV"$'G I: lexer skip) ord 5 lexer )) 6 0 + + 0 ,dup quote: 3 0 drop 1 2 3 . + 0 ,dup shebang: 3 0 drop , 2 3 . 0 f skip 3 . cond 3 change)lexer)column ! : still)parsing: 5 lexer )) : 6 0 lineGG 3 0 textGG length 3 bi PH ! : still)parsing)line: 5 lexer )) : 6 0 columnGG 3 0 line)lengthGG 3 bi P ! : 5parse)token6 5 lexer )) str 6 + 0 columnGG 3 0 skip) ord 3 0 columnGG 3 0 line)textGG 3 . cleave subseq ! : parse)token 5 lexer )) strQf 6 dup still)parsing: 0 dup skip)blank dup still)parsing)line: 0 5parse)token6 3 0 dup next)line parse)token 3 if 3 0 drop f 3 if ! : 5scan)token6 5 )) strQf 6 lexer get parse)token ! ;#'CI%"$': unexpected)eof P unexpected gotGG not ! : thro )unexpected)eof 5 ord )) 4 6 f unexpected !

: scan)token 5 )) str 6 5scan)token6 0 (token( thro )unexpected)eof 3 unless4 ! : expect 5 token )) 6

scan)token ,dup H 0 ,drop 3 0 unexpected 3 if ! : each)token 5 ... end quot: 5 ... token )) ... 6 )) ... 6 0 scan)token 3 ,dip ,over H 0 -drop 3 0 0 nip call 3 0 each)token 3 ,bi 3 if ! inline recursive : map)tokens 5 ... end quot: 5 ... token )) ... elt 6 )) ... seq 6 collector 0 each)token 3 dip + . like ! inline : parse)tokens 5 end )) seq 6 0 3 map)tokens ! $U;&': lexer)error line column line)text parsing) ords error ! I: lexer)error error)file errorGG error)file ! I: lexer)error error)line 0 errorGG error)line 3 0 lineGG 3 bi or ! : Plexer)errorG 5 msg )) error 6 > lexer)error ne lexer get 0 0 lineGG GGline 3 0 columnGG GGcolumn 3 bi 3 0 0 line)textGG GGline)text 3 0 parsing) ordsGG clone GGparsing) ords 3 bi 3 bi s ap GGerror ! : simple)lexer)dump 5 error )) 6 0 lineGG numberGstring (: ( append 3 0 line)textGG dup string: 0 drop (( 3 unless 3 0 columnGG = or 3 tri pick length 2 %?"#: >s PstringG 0 rite 3 0 print 3 0 rite (T( print 3 tri4 ! : 5parsing) ord)lexer)dump6 5 error parsing) ord )) 6 0 lineGG numberGstring over lineGG numberGstring length %?"#: >s pad)head (: ( append rite 3 0 line)textGG dup string: 0 drop (( 3 unless print 3 bi simple)lexer)dump ! : parsing) ord)lexer)dump 5 error parsing) ord )) 6 ,dup 0 lineGG 3 same: 0 drop simple)lexer)dump 3 0 5parsing) ord)lexer)dump6 3 if ! : lexer)dump 5 error )) 6 dup parsing) ordsGG 0 simple)lexer)dump 3 0 last parsing) ord)lexer)dump 3 if)empty ! : ith)lexer 5 lexer quot )) ne quot 6 0 lexer set 3 dip 0 Plexer)errorG rethro 3 recover ! inline IN: lexer USING: help.markup help.syntax kernel math sequences strings ords quotations ! ?'&;: lexer

+ *var)description (Stores the current ( + *link lexer . ( instance.( . + *class)description ("n obFect for tokeni8ing parser input. It has the follo ing slots:( + *list + + *snippet (text( . ( ) the lines being parsed! an array of strings( . + + *snippet (line( . ( ) the line number being parsed! unlike most indices this is 1)based for friendlier error reporting and integration ith text editors( . + + *snippet (column( . ( ) the current column position< 8ero)based( . . (%ustom lexing can be implemented by delegating a tuple to an instance of this class and implementing the ( + *link skip) ord . ( and ( + *link skip)blank . ( generic ords.( . ! ?'&;: PlexerG + *values + (text( (a sequence of strings( . + (lexer( lexer . . + *description (%reates a ne lexer for tokeni8ing the given sequence of lines.( . ! ?'&;: next)line + *values + (lexer( lexer . . + *description ("dvances the lexer to the next input line< discarding the remainder of the current line.( . ! ?'&;: lexer)error + *error)description ($hro n hen the lexer encounters invalid input. " lexer error raps an underlying error together ith line and column numbers.( . ! ?'&;: Plexer)errorG + *values + (msg( (an error( . + (error( lexer)error . . + *description (%reates a ne ( + *link lexer)error . (< filling in the location information from the current ( + *link lexer . (.( . ! ?'&;: skip + *values + (i( (a starting index( . + (seq( sequence . + (:( (a boolean( . + (n( integer . . + *description (Skips to the first space character 5if ( + *snippet (boolean( . ( is ( + *link f . (6 or the first non)space character 5other ise6. $abulations used as separators instead of spaces ill be flagged as an error.( . ! ?'&;: change)lexer)column + *values + (lexer( lexer . + (quot( + *quotation (5 col line )) ne col 6( . . . + *description ("pplies a quotation to the current column and line text to produce a ne column< and moves the lexer position.( . ! ?'&;: skip)blank + *values + (lexer( lexer . . + *contract (Skips hitespace characters.( . + *notes (%ustom lexers can implement this generic

ord.( . !

?'&;: skip) ord + *values + (lexer( lexer . . + *contract (Skips until the end of the current token.( *nl ($he default implementation treats a single ( + *snippet (>(( . ( as a ord by itself! other ise it searches for ard until a hitespace character or the end of the line.( . + *notes (%ustom lexers can implement this generic ord.( . ! ?'&;: still)parsing)line:

+ *values + (lexer( lexer . + (:( (a boolean( . . + *description (Butputs ( + *link f . ( if the end of the current line has been reached< ( + *link t . ( other ise.( . ! ?'&;: parse)token + *values + (lexer( lexer . + (strQf( + *maybe string . . . + *description (#eads the next token from the lexer. $okens are delimited by hitespace< ith the exception that ( + *snippet (>(( . ( is treated like a single token even hen not follo ed by hitespace.( . ! ?'&;: 5scan)token6 + *values + (strQf( + *maybe string . . . + *description (#eads the next token from the lexer. $okens are delimited by hitespace< ith the exception that ( + *snippet (>(( . ( is treated like a single token even hen not follo ed by hitespace. $his ord outputs ( + *link f . ( on end of input. $o thro an error on end of input< use ( + *link scan)token . ( instead.( . *parsing)note ! ?'&;: scan)token + *values + (str( string . . + *description (#eads the next token from the lexer. $okens are delimited by hitespace< ith the exception that ( + *snippet (>(( . ( is treated like a single token even hen not follo ed by hitespace. $his ord thro s ( + *link unexpected)eof . ( on end of input. $o output ( + *link f . ( on end of input< use ( + *link 5scan)token6 . ( instead.( . *parsing)note ! ?'&;: still)parsing: + *values + (lexer( lexer . + (:( (a boolean( . . + *description (Butputs ( + *link f . ( if end of input has been reached< ( + *link t . ( other ise.( . ! ?'&;: each)token + *values + (end( string . + (quot( + *quotation (5 ... token )) ... 6( . . . + *description (#eads a sequence of tokens until the first occurrence of ( + *snippet (end( . (. ( + *snippet (quot( . ( is called on each token as it is read.( . + *examples ($his ord is used to implement ( + *link ;BS$;BN': USING: . (.( . *parsing)note ! ?'&;: map)tokens + *values + (end( string . + (quot( + *quotation (5 ... token )) ... elt 6( . . + (seq( (a ne sequence of ( + *snippet (obFect( . (s( . . + *description (#eads a sequence of tokens until the first occurrence of ( + *snippet (end( . (. ( + *snippet (quot( . ( is called on each token as it is read< and the results are collected into a ne output sequence.( . *parsing)note ! ?'&;: parse)tokens + *values + (end( string . + (seq( (a ne sequence of strings( . . + *description (#eads a sequence of tokens until the first occurrence of ( + *snippet (end( . (. $he tokens remain as strings and are not processed in any ay. $his ord is equivalent to ( + *link map)tokens . ( ith an empty quotation.( . *parsing)note ! ?'&;: unexpected + *values + ( ant( + *maybe ord . . + (got( ord . . + *description ($hro s an ( + *link unexpected . ( error.( . + *error)description ($hro n by the parser if an unmatched closing delimiter is encountered.( .

+ *examples (;arsing the follo ing snippet + *code (0 1 , - .( . . !

ill thro

this error:(

?'&;: unexpected)eof + *values + ( ord( (a ( + *link ord . . . + *description ($hro s an ( + *link unexpected . ( error indicating the parser as looking for an occurrence of ( + *snippet ( ord( . ( but encountered end of file.( . ! ?'&;: ith)lexer + *values + (lexer( lexer . + (quot( quotation . + (ne quot( quotation . . + *description (%alls the quotation ith the ( + *link lexer . ( variable set to the given lexer. $he quotation can make use of ords such as ( + *link scan)token . (. "ny errors thro n by the quotation are rapped in ( + *link lexer)error . ( instances.( . ! "#$I%&': (parser)lexer( ($he lexer( (" variable that encapsulate internal parser state:( + *subsections lexer . (%reating a default lexer:( + *subsections PlexerG . (" ord to test of the end of input has been reached:( + *subsections still)parsing: . (" ord to advance the lexer to the next line:( + *subsections next)line . ($ o generic ords to override the lexer7s token boundary detection:( + *subsections skip)blank skip) ord . (Utility combinator:( + *subsections ith)lexer . ! USING: help.markup help.syntax kernel kernel.private continuations.private vectors arrays namespaces assocs ords quotations lexer sequences math ! IN: continuations "#$I%&': (errors)restartable( (#estartable errors( (Support for restartable errors is built on top of the basic error handling facility. $he follo ing ords signals recoverable errors:( + *subsections thro )restarts rethro )restarts . (" utility ord using the above:( + *subsections thro )continue . ($he list of restarts from the most recently)thro n error is stored in a global variable:( + *subsections restarts . ($o invoke restarts< use ( + *link (debugger( . (.( ! "#$I%&': (errors)post)mortem( (;ost)mortem error inspection( ($he most recently thro n error< together ith the continuation at that point< are stored in a pair of global variables:( + *subsections error error)continuation .

(Ceveloper tools for inspecting these values are found in ( + *link (debugger( . (.( ! "#$I%&': (errors)anti)examples( (%ommon error handling pitfalls( (Jhen used correctly< exception handling can lead to more robust code ith less duplication of error handling logic. ?o ever< there are some pitfalls to keep in mind.( + *heading ("nti)pattern Z1: Ignoring errors( . ($he ( + *link ignore)errors . ( ord should almost never be used. Ignoring errors does not make code more robust and in fact makes it much harder to debug if an intermittent error does sho up hen the code is run under previously unforseen circumstances. Never ignore unexpected errors! al ays report them to the user.( + *heading ("nti)pattern Z,: %atching errors too early( . (" less severe form of the previous anti)pattern is code that makes overly 8ealous use of ( + *link recover . (. It is almost al ays a mistake to catch an error< log a message< and keep going. $he only exception is net ork servers and other long)running processes that must remain running even if individual tasks fail. In these cases< place the ( + *link recover . ( as high up in the call stack as possible.( *nl (In most other cases< ( + *link cleanup . ( should be used instead to handle an error and rethro it automatically.( + *heading ("nti)pattern Z-: Cropping and rethro ing( . (Co not use ( + *link recover . ( to handle an error by dropping it and thro ing a ne error. Ey losing the original error message< you signal to the user that something failed ithout leaving any indication of hat actually ent rong. 'ither rap the error in a ne error containing additional information< or rethro the original error. " more subtle form of this is using ( + *link thro . ( instead of ( + *link rethro . (. $he ( + *link thro . ( ord should only be used hen thro ing ne errors< and never hen rethro ing errors that have been caught.( + *heading ("nti)pattern Z/: &ogging and rethro ing( . (If you are going to rethro an error< do not log a message. If you do so< the user ill see t o log messages for the same error< hich ill clutter logs ithout adding any useful information.( ! "#$I%&': (errors( ('xception handling( (Support for handling exceptional situations such as bad user input< implementation bugs< and inputQoutput errors is provided by a set of ords built using continuations.( *nl ($ o ords raise an error in the innermost error handler for the current dynamic extent:( + *subsections thro rethro . (Jords for establishing an error handler:( + *subsections cleanup recover ignore)errors . (Syntax sugar for defining errors:( + *subsections ;BS$;BN': '##B#: . (Unhandled errors are reported in the listener and can be debugged using various tools. See ( + *link (debugger( . (.( + *subsections (errors)restartable( (debugger( (errors)post)mortem(

(errors)anti)examples( . (Jhen @actor encounters a critical error< it calls the follo ing + *subsections die . !

ord:(

"#$I%&': (continuations.private( (%ontinuation implementation details( (" continuation is simply a tuple holding the contents of the five stacks:( + *subsections continuation GcontinuationP . ($he five stacks can be read and ritten:( + *subsections datastack set)datastack retainstack set)retainstack callstack set)callstack namestack set)namestack catchstack set)catchstack . ! "#$I%&': (continuations( (%ontinuations( ("t any point in the execution of a program< the ( + *emphasis (current continuation( . ( represents the future of the computation.( *nl (Jords for orking ith continuations are found in the ( + *vocab)link (continuations( . ( vocabulary! implementation details are in ( + *vocab)link (continuations.private( . (.( *nl (%ontinuations can be reified ith the follo ing t o ords:( + *subsections callcc= callcc1 . ("nother t o ords resume continuations:( + *subsections continue continue) ith . (%ontinuations as control)flo :( + *subsections attempt)all ith)return . (%ontinuations serve as the building block for a number of higher)level abstractions< such as ( + *link (errors( . ( and ( + *link (threads( . (.( + *subsections (continuations.private( . ! "EBU$: (continuations( ?'&;: catchstack4 + *values + (catchstack( (a vector of continuations( . . + *description (Butputs the current catchstack.( . ! ?'&;: catchstack + *values + (catchstack( (a vector of continuations( . . + *description (Butputs a copy of the current catchstack.( . !

?'&;: set)catchstack + *values + (catchstack( (a vector of continuations( . . + *description (#eplaces the catchstack ith a copy of the given vector.( . ! ?'&;: continuation + *values + (continuation( continuation . . + *description (#eifies the current continuation from the point immediately after hich the caller returns.( . ! ?'&;: GcontinuationP + *values + (continuation( continuation . + (data( vector . + (call( vector . + (retain( vector . + (name( vector . + (catch( vector . . + *description ($akes a continuation apart into its constituents.( . ! ?'&;: ifcc + *values + (capture( + *quotation (5 continuation )) 6( . . + (restore( quotation . . + *description (#eifies a continuation from the point immediately after hich this ord returns< and passes it to ( + *snippet (capture( . (. Jhen the continuation is restored< execution resumes and ( + *snippet (restore( . ( is called.( . ! + callcc= continue callcc1 continue) ith ifcc . related) ords ?'&;: callcc= + *values + (quot( + *quotation (5 continuation )) 6( . . . + *description ("pplies the quotation to the current continuation< hich is reified from the point immediately after hich the caller returns. $he ( + *link continue . ( ord resumes the continuation.( . ! ?'&;: callcc1 + *values + (quot( + *quotation (5 continuation )) 6( . . + (obF( (an obFect provided hen resuming the continuation( . . + *description ("pplies the quotation to the current continuation< hich is reified from the point immediately after hich the caller returns. $he ( + *link continue) ith . ( ord resumes the continuation< passing a value back to the original execution context.( . ! ?'&;: continue + *values + (continuation( continuation . . + *description (#esumes a continuation reified by ( + *link callcc= . (.( . ! ?'&;: continue) ith + *values + (obF( (an obFect to pass to the continuation7s execution context( . + (continuation( continuation . . + *description (#esumes a continuation reified by ( + *link callcc1 . (. $he obFect ill be placed on the data stack hen the continuation resumes.( . ! ?'&;: error + *description (Global variable holding most recently thro n error.( . + *notes (Bnly updated by ( + *link thro . (< not ( + *link rethro . (.( . ! ?'&;: error)continuation + *description (Global variable holding current continuation of most recently thro n error.( . + *notes (Bnly updated by ( + *link thro . (< not ( + *link rethro . (.( . ! ?'&;: restarts + *var)description (Global variable holding the set of possible restarts for the most recently thro n error.( . + *notes (Bnly updated by ( + *link thro . (< not ( + *link rethro . (.( . !

?'&;: thro + *values + (error( obFect . . + *description (Saves the current continuation in the ( + *link error)continuation . ( global variable and thro s an error. 'xecution does not continue at the point after the ( + *link thro . ( call. #ather< the innermost catch block is invoked< and execution continues at that point.( . ! + cleanup recover . related) ords ?'&;: cleanup + *values + (try( + *quotation (5 ..a )) ..a 6( . . + (cleanup)al ays( + *quotation (5 ..a )) ..b 6( . . + (cleanup)error( + *quotation (5 ..b )) ..b 6( . . . + *description (%alls the ( + *snippet (try( . ( quotation. If no error is thro n< calls ( + *snippet (cleanup)al ays( . ( ithout restoring the data stack. If an error is thro n< restores the data stack< calls ( + *snippet (cleanup)al ays( . ( follo ed by ( + *snippet (cleanup)error( . (< and rethro s the error.( . ! ?'&;: recover + *values + (try( + *quotation (5 ..a )) ..b 6( . . + (recovery( + *quotation (5 ..a error )) ..b 6( . . . + *description (%alls the ( + *snippet (try( . ( quotation. If an exception is thro n in the dynamic extent of the ( + *snippet (try( . ( quotation< restores the data stack and calls the ( + *snippet (recovery( . ( quotation to handle the error.( . ! ?'&;: ignore)errors + *values + (quot( quotation . . + *description (%alls the quotation. If an exception is thro n in the dynamic extent of the quotation< restores the data stack and returns.( . ! ?'&;: rethro + *values + (error( obFect . . + *description ($hro s an error ithout saving the current continuation in the ( + *link error)continuation . ( global variable. $his is done so that inspecting the error stacks sheds light on the original cause of the exception< rather than the point here it as rethro n.( . + *notes ($his ord is intended to be used in conFunction ith ( + *link recover . ( to implement error handlers hich perform an action and pass the error to the next outermost error handler.( . + *examples ($he ( + *link ith)lexer . ( ord catches errors< annotates them ith the current line and column number< and rethro s them:( + *see ith)lexer . . ! ?'&;: thro )restarts + *values + (error( obFect . + (restarts( (a sequence of ( + *snippet (+ string obFect .( . ( pairs( . + (restart( obFect . . + *description ($hro s a restartable error using ( + *link thro . (. $he ( + *snippet (restarts( . ( parameter is a sequence of pairs here the first element in each pair is a human)readable description and the second is an arbitrary obFect. If the error reaches the top)level error handler< the user ill be presented ith the list of possible restarts< and upon invoking one< execution ill continue after the call to ( + *link thro )restarts . ( ith the obFect associated to the chosen restart on the stack.( . + *examples ($ry invoking one of the t o restarts hich are offered after the belo code thro s an error:(

. !

+ *code (: restart)test 5 )) 6( ( >(BopsK>( + + >(Bne>( 1 . + >($ o>( , . . thro )restarts( ( >(Nou restarted: >( rite . !( (restart)test( .

?'&;: rethro )restarts + *values + (error( obFect . + (restarts( (a sequence of ( + *snippet (+ string obFect .( . ( pairs( . + (restart( obFect . . + *description ($hro s a restartable error using ( + *link rethro . (. Bther ise< this ord is identical to ( + *link thro )restarts . (.( . ! + thro rethro thro )restarts rethro )restarts thro )continue . related) ords

?'&;: thro )continue + *values + (error( obFect . . + *description ($hro s a resumable error. If the user elects to continue execution< this ord returns normally.( . ! ?'&;: compute)restarts + *values + (error( obFect . + (seq( (a sequence( . . + *description (Butputs a sequence of triples< here each triple consists of a human)readable string< an obFect< and a continuation. #esuming a continuation ith the corresponding obFect restarts execution immediately after the corresponding call to ( + *link condition . (.( *nl ($his ord recursively travels up the delegation chain to collate restarts from nested and rapped conditions.( . ! ?'&;: save)error + *values + (error( (an error( . . + *description (%alled by the error handler to set the ( + *link error . ( and ( + *link restarts . ( global variables after an error as thro n.( . *lo )level)note ! ?'&;: ith)datastack + *values + (stack( sequence . + (quot( quotation . + (ne )stack( sequence . . + *description ('xecutes the quotation ith the given data stack contents< and outputs the ne data stack after the ord returns. $he input sequence is not modified! a ne sequence is produced. Coes not affect the data stack in surrounding code< other than consuming the t o inputs and pushing the output.( . + *examples + *example (USING: continuations math prettyprint !( (+ - R . 0 2 3 ith)datastack .( (+ 1= .( . . ! ?'&;: attempt)all + *values + (seq( sequence . + (quot( quotation . + (obF( obFect . . + *description ("pplies the quotation to elements in a sequence and returns the value from the first quotation that does not thro an error. If all quotations thro an error< returns the last error thro n.( . + *examples ($he first t o numbers thro < the last one doesn7t:( + *example (USING: prettyprint continuations kernel math !( (+ 1 - L . 0 dup odd: 0 >(Bdd>( thro 3 hen 3 attempt)all .( (L( . ("ll quotations thro < the last exception is rethro n:( + *example

. !

(USING: prettyprint continuations kernel math !( (0 + 1 - A . 0 dup odd: 0 thro 3 hen 3 attempt)all 3 0 3 recover .( (A( .

?'&;: return + *description (#eturns early from a quotation by reifying the continuation captured by ( + *link ith)return . ( ! execution is resumed starting immediately after ( + *link ith)return . (.( . ! ?'&;: ith)return + *values + (quot( quotation . . + *description (%aptures a continuation that can be reified by calling the ( + *link return . ( ord. If so< it ill resume execution immediately after the ( + *link ith)return . ( ord. If ( + *link return . ( is not called< then execution proceeds as if this ord ere simply ( + *link call . (.( . + *examples (Bnly >(?i>( ill print:( + *example (USING: prettyprint continuations io !( (0 >(?i>( print return >(Eye>( print 3 ith)return( (?i( . . ! + return ith)return . related) ords

?'&;: restart + *values + (restart( restart . . + *description (Invokes a restart.( . + *class)description ($he class of restarts.( . ! K %opyright 5%6 ,==-< ,=11 Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs combinators combinators.private kernel kernel.private make namespaces sequences vectors ! IN: continuations : ith)datastack 5 stack quot )) ne )stack 6 0 0 0 datastack 3 dip s ap 0 + . like set)datastack 3 dip 3 dip s ap 0 call datastack 3 dip s ap 0 set)datastack 3 dip 3 5 stack quot )) ne )stack 6 call)effect)unsafe ! original)error error error)continuation error)thread restarts

SNIEB&: SNIEB&: SNIEB&: SNIEB&: SNIEB&: P;#IV"$'

: catchstack4 5 )) catchstack 6 %BN$'M$)BEX)%"$%?S$"%Y context)obFect + vector . declare ! inline K Je have to defeat some optimi8ations to make continuations : dummy)1 5 )) obF 6 f ! : dummy), 5 obF )) obF 6 ! : catchstack 5 )) catchstack 6 catchstack4 clone ! inline ork

: 5set)catchstack6 5 catchstack )) 6 %BN$'M$)BEX)%"$%?S$"%Y set)context)obFect ! inline : set)catchstack 5 catchstack )) 6 Gvector 5set)catchstack6 ! inline : init)catchstack 5 )) 6 V+ . clone 5set)catchstack6 ! ;#IV"$'G $U;&': continuation data call retain name catch ! %: PcontinuationG continuation : current)continuation 5 )) continuation 6 datastack callstack retainstack namestack catchstack PcontinuationG ! P;#IV"$' '##B#: not)a)continuation obF ! : GcontinuationP 5 continuation )) data call retain name catch 6 dup continuation: 0 not)a)continuation 3 unless + 0 dataGG 3 0 callGG 3 0 retainGG 3 0 nameGG 3 0 catchGG 3 . cleave ! inline ;#IV"$'G : ifcc 5 capture restore )) 6 0 dummy)1 current)continuation 3 ,dip 0 dummy), 3 prepose :if ! inline : callcc= 5 quot )) 6 0 drop 3 ifcc ! inline : callcc1 5 quot )) obF 6 0 3 ifcc ! inline P;#IV"$' : 5continue6 5 continuation )) 4 6 0 GcontinuationP set)catchstack set)namestack set)retainstack 0 set)datastack 3 dip set)callstack 3 5 continuation )) 4 6 call)effect)unsafe ! ;#IV"$'G : continue) ith 5 obF continuation )) 4 6 0 s ap BEX)%"&&%%)1 set)special)obFect GcontinuationP set)catchstack set)namestack set)retainstack 0 set)datastack drop BEX)%"&&%%)1 special)obFect f BEX)%"&&%%)1 set)special)obFect

f 3 dip set)callstack 3 5 obF continuation )) 4 6 call)effect)unsafe ! : continue 5 continuation )) 4 6 f s ap continue) ith ! SNIEB&: return)continuation : ith)return 5 quot )) 6 0 0 return)continuation set 3 prepose callcc= 3 ith)scope ! inline

: return 5 )) 4 6 return)continuation get continue ! G'N'#I%: compute)restarts 5 error )) seq 6 P;#IV"$' : save)error 5 error )) 6 0 error set)global 3 0 compute)restarts restarts set)global 3 bi ! ;#IV"$'G G'N'#I%: error)in)thread 5 error thread )) 4 6 SNIEB&: thread)error)hook K 5 error thread )) 6 thread)error)hook 0 0 die 3 3 initiali8e I: obFect error)in)thread 5 error thread )) 4 6 thread)error)hook get)global call5 error thread )) 4 6 ! : in)callback: 5 )) : 6 %BN$'M$)BEX)IN)%"&&E"%Y); context)obFect ! SNIEB&: callback)error)hook K 5 error )) 4 6 callback)error)hook 0 0 die 3 3 initiali8e : rethro 5 error )) 4 6 dup save)error catchstack4 0 in)callback: 0 callback)error)hook get)global call5 error )) 4 6 3 0 BEX)%U##'N$)$?#'"C special)obFect error)in)thread 3 if 3 0 pop continue) ith 3 if)empty ! : recover 5 ..a try: 5 ..a )) ..b 6 recovery: 5 ..a error )) ..b 6 )) ..b 6 0 0 0 catchstack4 push 3 dip call catchstack4 pop4 3 curry 3 dip ifcc ! inline : ignore)errors 5 quot )) 6 0 drop 3 recover ! inline

: cleanup 5 try cleanup)al ays cleanup)error )) 6 0 compose 0 dip rethro 3 curry recover 3 0 drop 3 ,bi call ! inline '##B#: attempt)all)error ! : attempt)all 5 ... seq quot: 5 ... elt )) ... obF 6 )) ... obF 6 over empty: 0 attempt)all)error 3 0 0 0 0 < f 3 compose 0 < drop t 3 recover 3 curry all: 3 + . make last s ap 0 rethro 3 hen 3 if ! inline $U;&': condition error restarts continuation ! %: PconditionG condition : thro )restarts 5 error restarts )) restart 6 0 PconditionG thro 3 callcc1 ,nip ! : rethro )restarts 5 error restarts )) restart 6 0 PconditionG rethro 3 callcc1 ,nip ! : thro )continue 5 error )) 6 + + (%ontinue( t . . thro )restarts drop ! $U;&': restart name obF continuation ! %: PrestartG restart : continue)restart 5 restart )) 4 6 0 obFGG 3 0 continuationGG 3 bi continue) ith ! I: obFect compute)restarts drop + . ! I: condition compute)restarts 0 errorGG compute)restarts 3 0 0 restartsGG 3 0 continuationGG 0 PrestartG 3 curry 3 bi + . assocGmap 3 bi append ! P;#IV"$' : init)error)handler 5 )) 6 init)catchstack K VI calls on error 0 K LA H self BEX)%U##'N$)$?#'"C special)obFect error)thread set)global current)continuation error)continuation set)global 0 original)error set)global 3 0 rethro 3 bi 3 '##B#)?"NC&'#)DUB$ set)special)obFect K VI adds this to kernel errors< so that user)space K can identify them (kernel)error( BEX)'##B# set)special)obFect ! ;#IV"$'G USING: kernel math namespaces io tools.test sequences vectors continuations debugger parser memory arrays ords

kernel.private accessors eval ! IN: continuations.tests : 5callcc1)test6 5 n obF )) n7 obF 6 0 1 ) dup 3 dip :push over = H 0 (test)cc( get continue) ith 3 5callcc1)test6 !

hen

: callcc1)test 5 x )) list 6 0 (test)cc( set V+ . clone 5callcc1)test6 3 callcc1 nip ! : callcc)namespace)test 5 )) : 6 0 (test)cc( set A (x( set 0 L (x( set (test)cc( get continue 3 ith)scope 3 callcc= (x( get A H ! 0 t 3 0 1= callcc1)test 1= iota reverse Gvector H 3 unit)test 0 t 3 0 callcc)namespace)test 3 unit)test 0 A thro 3 0 A H 3 must)fail) ith

0 t 3 0 0 (?ello( thro 3 ignore)errors error get)global (?ello( H 3 unit)test (KKK $he follo ing error is part of the test( print 0 3 0 0 L 0 1, 0 (, car( 3 3 3 print)error 3 unit)test (KKK $he follo ing error is part of the test( print 0 3 0 0 0 (, car( 3 eval 3 try 3 unit)test 0 f thro 3 must)fail

K Jeird ;o er;% bug. 0 3 0 0 (/( thro 3 ignore)errors gc gc 3 unit)test K K K K K K See ho ell callstack overflo 0 clear drop 3 must)fail : callstack)overflo 0 callstack)overflo is handled f !

callstack)overflo 3 must)fail

: don7t)compile)me 5 )) 6 ! : foo 5 )) 6 callstack (c( set don7t)compile)me ! : bar 5 )) a b 6 1 foo , ! PP + don7t)compile)me foo bar . 0 t (no)compile( set) ord)prop 3 each GG

0 1 , 3 0 bar 3 unit)test 0 t 3 0 > bar defGG (c( get innermost)frame)executing H 3 unit)test 0 1 3 0 (c( get innermost)frame)scan 3 unit)test SNIEB&: al ays)counter SNIEB&: error)counter 0 = al ays)counter set = error)counter set 0 3 0 al ays)counter inc 3 0 error)counter inc 3 cleanup 0 1 3 0 al ays)counter get 3 unit)test 0 = 3 0 error)counter get 3 unit)test 0 0 (a( thro 3 0 al ays)counter inc 3 0 error)counter inc 3 cleanup 3 0 (a( H 3 must)fail) ith 0 , 3 0 al ays)counter get 3 unit)test 0 1 3 0 error)counter get 3 unit)test 0 0 3 0 al ays)counter inc (a( thro 0 error)counter inc 3 cleanup 3 0 (a( H 3 must)fail) ith

0 - 3 0 al ays)counter get 3 unit)test 0 1 3 0 error)counter get 3 unit)test ith)scope ith)return 3 unit)test

0 3 0 0 return 3

0 + . 0 3 attempt)all 3 0 attempt)all)error: 3 must)fail) ith 0 + / . 3 0 + , , . 0 2 3 ith)datastack 3 unit)test ords

0 ith)datastack 3 must)infer USING: compiler definitions compiler.units tools.test arrays sequences kernel accessors namespaces fry eval quotations math ! IN: compiler.units.tests 0 0 0 3 define)temp 3 0 0 0 3 define)temp 3 ith)compilation)unit 3 must)infer ith)nested)compilation)unit 3 must)infer

K Non)optimi8ing compiler bugs 0 1 1 3 0 ("( Puninterned) ordG 0 0 0 1 3 dip 3 ,array 1array t t modify)code)heap 3 keep 1 s ap execute 3 unit)test 0 ("( (E( 3 0 disable)optimi8er

gensym (a( set gensym (b( set 0 (a( get 0 ("( 3 define (b( get (a( get 70 [ execute 3 define 3 ith)compilation)unit (b( get execute 0 (a( get 0 (E( 3 define 3 ith)compilation)unit (b( get execute enable)optimi8er 3 unit)test K %heck that e notify observers SING&'$BN: observer observer add)definition)observer SNIEB&: counter = counter set)global I: observer definitions)changed ,drop 0 counter inc 3 ith)global ! 0 gensym 0 3 5 )) 6 define)declared 3 0 1 3 0 counter get)global 3 unit)test observer remove)definition)observer K Notify observers ith nested compilation units observer add)definition)observer = counter set)global C'@'#: nesting)test 0 3 0 (IN: compiler.units.tests PP : nesting)test 5 )) 6 ! GG( eval5 )) 6 3 unit)test observer remove)definition)observer K Iake sure that non)optimi8ed calls to a generic K hasn7t been compiled yet ork properly G'N'#I%: uncompiled)generic)test 5 a )) b 6 I: integer uncompiled)generic)test 1 2 ! PP 0 uncompiled)generic)test 3 0 Fit)compile 3 0 suffixK 3 bi GG (q( set 0 / 3 0 - (q( get call 3 unit)test 0 3 0 0 > uncompiled)generic)test forget 3 ith)compilation)unit 3 unit)test USING: help.markup help.syntax ords math source)files parser quotations definitions stack)checker.errors ! IN: compiler.units "#$I%&': (compilation)units)internals( (%ompilation units internals( ord hich ith)compilation)unit

($hese ords do not need to be called directly< and only serve to support the implementation.( *nl (%ompiling a set of ords:( + *subsections compile . (Jords called to associate a definition ith a compilation unit and a source file location:( + *subsections remember)definition remember)class . (@or ard reference checking 5see ( + *link (definition)checking( . (6:( + *subsections for ard)reference: . (" hook to be called at the end of the compilation unit. If the optimi8ing compiler is loaded< this compiles ne ords ith the ( + *link (compiler( . (:( + *subsections recompile . (&o )level compiler interface exported by the @actor VI:( + *subsections modify)code)heap . ! "#$I%&': (compilation)units( (%ompilation units( (" ( + *emphasis (compilation unit( . ( scopes a group of related definitions. $hey are compiled and entered into the system in one atomic operation.( *nl (Jhen a source file is being parsed< all definitions are part of a single compilation unit< unless the ( + *link ;BS$;BN': PP . ( parsing ord is used to create nested compilation units.( *nl (Jords defined in a compilation unit may not be called until the compilation unit is finished. $he parser detects this case for parsing ords and thro s a ( + *link staging)violation . (. Similarly< an attempt to use a macro from a ord defined in the same compilation unit ill thro a ( + *link transform)expansion)error . (. %alling any other ord from ithin its o n compilation unit thro s an ( + *link undefined . ( error.( *nl ($his means that parsing ords and macros generally cannot be used in the same source file as they are defined. $here are t o means of getting around this:( + *list + ($he simplest ay is to split off the parsing ords and macros into sub)vocabularies! perhaps suffixed by ( + *snippet (.syntax( . ( and ( + *snippet (.macros( . (.( . + ("lternatively< nested compilation units can be created using ( + *link (syntax)immediate( . (.( . . (;arsing ords hich create ne definitions at parse time ill implicitly add them to the compilation unit of the current source file.( *nl (%ode hich creates ne definitions at run time ill need to explicitly create a compilation unit ith a combinator. $here is an additional combinator used by the parser to implement ( + *link (syntax)immediate( . (.( + *subsections ith)compilation)unit ith)nested)compilation)unit . ("dditional topics:( + *subsections (compilation)units)internals( . ! "EBU$: (compilation)units( ?'&;: redefine)error + *values + (definition( (a definition specifier( . . + *description ($hro s a ( + *link redefine)error . (.( . + *error)description (Indicates that a single source file contains t o definitions for the same artifact< one of hich shado s the other. $his is an error since it indicates a likely mistake< such as t o ords accidentally named the same by the developer! the error is restartable.( . !

?'&;: remember)definition + *values + (definition( (a definition specifier( . + (loc( (a ( + *snippet (+ path lineZ .( . ( pair( . . + *description (Saves the location of a definition and associates this definition ith the current source file.( . ! ?'&;: old)definitions + *var)description (Stores a pair of sets here the members form the set of definitions hich ere defined by ( + *link file . ( the most recent time it loaded.( . !

as

?'&;: ne )definitions + *var)description (Stores a pair of sets here the members form the set of definitions hich ere defined so far by the current parsing of ( + *link file . (.( . ! ?'&;: ith)compilation)unit + *values + (quot( quotation . . + *description (%alls a quotation in a ne compilation unit. $he quotation can define ne ords and classes< as ell as forget ords. Jhen the quotation returns< any changed ords are recompiled< and changes are applied atomically.( . + *notes (%alls to ( + *link ith)compilation)unit . ( may be nested.( *nl ($he parser raps every source file in a compilation unit< so parsing ords may define ne ords ithout having to perform extra ork! to define ne ords at any other time< you must rap your defining code ith this combinator.( *nl (Since compilation is relatively expensive< you should try to batch up as many definitions into one compilation unit as possible.( . ! ?'&;: ith)nested)compilation)unit + *values + (quot( quotation . . + *description (%alls a quotation in a ne compilation unit. $he only difference bet een this ord and ( + *link ith)compilation)unit . ( is that variables used by the parser to associate definitions ith source files are not rebound.( . + *notes ($his ord is used by ( + *link (syntax)immediate( . ( to ensure that definitions in nested blocks are correctly recorded. User code should not depend on parser internals in such a ay that calling this combinator is required.( . ! ?'&;: recompile + *values + ( ords( (a sequence of ords( . + (alist( (an association list mapping ords to compiled definitions( . . + *contract (Internal ord hich compiles ords. %alled at the end of ( + *link ith)compilation)unit . (.( . ! ?'&;: no)compilation)unit + *values + ( ord( ord . . + *description ($hro s a ( + *link no)compilation)unit . ( error.( . + *error)description ($hro n hen an attempt is made to define a ord outside of a ( + *link ith)compilation)unit . ( combinator.( . ! ?'&;: modify)code)heap + *values + (alist( (an association list ith ords as keys( . + (update)existing:( (a boolean( . + (reset)pics:( (a boolean( . . + *description (&o est)level primitive for defining ords. "ssociates code blocks in the code heap.( *nl ($he alist maps ords to the follo ing:( + *list + (a quotation ) in this case< the quotation is compiled ith the

ords

ith

non)optimi8ing compiler and the ord ill call the quotation hen executed.( . + (a A)element array ( + *snippet (+ parameters literals relocation labels code .( . ( ) in this case< a code heap block is allocated ith the given data and the ord ill call the code block hen executed. $his is used by the optimi8ing compiler.( . . (If any of the redefined ords may already be referenced by other ords in the code heap< from outside of the compilation unit< then a scan of the code heap must be performed to update all ord call sites. ;assing ( + *link t . ( as the ( + *snippet (update)existing:( . ( parameter enables this code path.( *nl (If classes< methods or generic ords ere redefined< then inline cache call sites need to be updated as ell. ;assing ( + *link t . ( as the ( + *snippet (reset)pics:( . ( parameter enables this code path.( . + *notes ($his ord is called at the end of ( + *link ith)compilation)unit . (.( . ! ?'&;: compile + *values + ( ords( (a sequence of ords( . . + *description (%ompiles a set of ords.( . ! K %opyright 5%6 ,==S< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes classes.private classes.tuple classes.tuple.private continuations definitions generic init kernel kernel.private math namespaces sequences sets source)files.errors vocabs ords ! @#BI: namespaces HG set ! @#BI: sets HG members ! IN: compiler.units SNIEB&: old)definitions SNIEB&: ne )definitions $U;&': redefine)error def ! : thro )redefine)error 5 definition )) 6 > redefine)error boa thro )continue ! P;#IV"$' : add)once 5 key set )) 6 dupd :adFoin 0 drop 3 0 thro )redefine)error 3 if ! : 5remember)definition6 5 definition loc set )) 6 0 over set) here 3 dip add)once ! ;#IV"$'G : remember)definition 5 definition loc )) 6 ne )definitions get first 5remember)definition6 ! : fake)definition 5 definition )) 6 old)definitions get 0 delete 3 ith each ! : remember)class 5 class loc )) 6 0 dup ne )definitions get first in: 0 dup thro )redefine)error 3 ne )definitions get second 5remember)definition6 ! : for ard)reference: 5 ord )) : 6 dup old)definitions get 0 in: 3 ne )definitions get 0 in: 3 ith any: 0 ith any: not hen 3 dip

3 0 drop f 3 if ! SNIEB&: compiler)impl ?BBY: update)call)sites compiler)impl 5 class generic )) : changed)call)sites 5 class generic )) 6 update)call)sites 0 changed)definition 3 each ! I: generic update)generic 5 class generic )) 6 0 changed)call)sites 3 0 remake)generic drop 3 0 changed)conditionally drop 3 ,tri ! I: sequence update)methods 5 class seq )) 6 implementors 0 update)generic 3 ith each ! ?BBY: recompile compiler)impl 5 ords )) alist 6 ords 6 ords )) 6 ords 6

?BBY: to)recompile compiler)impl 5 ))

?BBY: process)forgotten) ords compiler)impl 5 : compile 5 ords )) 6 recompile t f modify)code)heap ! K Non)optimi8ing compiler I: f update)call)sites ,drop + . ! I: f to)recompile changed)definitions get members 0 I: f recompile 0 dup defGG 3 + . mapGassoc ! I: f process)forgotten) ords drop ! :

ord: 3 filter !

ithout)optimi8er 5 quot )) 6 0 f compiler)impl 3 dip ith)variable ! inline

: PdefinitionsG 5 )) pair 6 + ?S+ . ?S+ . . 0 clone 3 map ! SNIEB&: definition)observers G'N'#I%: definitions)changed 5 set obF )) 6 0 V+ . clone definition)observers set)global 3 (compiler.units( add)startup)hook K $his goes here because vocabs cannot depend on init 0 V+ . clone vocab)observers set)global 3 (vocabs( add)startup)hook : add)definition)observer 5 obF )) 6 definition)observers get push ! : remove)definition)observer 5 obF )) 6 definition)observers get remove)eqK drop ! : notify)definition)observers 5 set )) 6

definition)observers get 0 definitions)changed 3 ith each ! K K K : Incremented each time stack effects potentially changed< used by compiler.tree.propagation.call)effect for call5 and execute5 inline caching effect)counter 5 )) n 6 #'C'@INI$IBN)%BUN$'# special)obFect ! inline

G'N'#I%: al ays)bump)effect)counter: 5 defspec )) : 6 I: obFect al ays)bump)effect)counter: drop f ! P;#IV"$' : changed)vocabs 5 set )) vocabs 6 members 0 ord: 3 filter 0 vocabularyGG dup 0 lookup)vocab 3 : updated)definitions 5 )) set 6 ?S+ . clone forgotten)definitions get unionK ne )definitions get first unionK ne )definitions get second unionK changed)definitions get unionK maybe)changed get unionK dup changed)vocabs over adFoin)all ! : process)forgotten)definitions 5 )) 6 forgotten)definitions get members 0 0 ord: 3 filter process)forgotten) ords 3 0 0 delete)definition)errors 3 each 3 bi ! : bump)effect)counter: 5 )) : 6 changed)effects get members maybe)changed get members changed)definitions get members 0 al ays)bump)effect)counter: 3 filter -array combine ne ) ords get 0 in: not 3 curry any: ! : bump)effect)counter 5 )) 6 bump)effect)counter: 0 #'C'@INI$IBN)%BUN$'# special)obFect = or 1 2 #'C'@INI$IBN)%BUN$'# set)special)obFect 3 hen ! : notify)observers 5 )) 6 updated)definitions dup null: 0 drop 3 0 notify)definition)observers notify)error)observers 3 if ! : update)existing: 5 defs )) : 6 ne ) ords get 0 in: not 3 curry any: ! : reset)pics: 5 )) : 6 outdated)generics get null: not ! : finish)compilation)unit 5 )) 6 0 3 0 remake)generics to)recompile 0 recompile update)tuples process)forgotten)definitions

hen 3 map !

3 keep update)existing: reset)pics: modify)code)heap bump)effect)counter notify)observers 3 if)bootstrapping ! $U;&': nesting)observer ne ) ords ! I: nesting)observer definitions)changed 0 members 3 dip ne ) ordsGG 0 delete 3 curry each ! : add)nesting)observer 5 )) 6 ne ) ords get nesting)observer boa 0 nesting)observer set 3 0 add)definition)observer 3 bi ! : remove)nesting)observer 5 )) 6 nesting)observer get remove)definition)observer ! ;#IV"$'G : ith)nested)compilation)unit 5 quot )) 6 0 ?S+ . clone changed)definitions set ?S+ . clone maybe)changed set ?S+ . clone changed)effects set ?S+ . clone outdated)generics set ?+ . clone outdated)tuples set ?S+ . clone ne ) ords set add)nesting)observer 0 remove)nesting)observer finish)compilation)unit 3 0 3 cleanup 3 ith)scope ! inline

ith)compilation)unit 5 quot )) 6 0 PdefinitionsG ne )definitions set PdefinitionsG old)definitions set ?S+ . clone forgotten)definitions set ith)nested)compilation)unit 3 ith)scope ! inline K %opyright 5%6 ,==R< ,=1= Coug %oleman< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs continuations init kernel make namespaces sequences sets ! @#BI: namespaces HG set ! IN: destructors SNIEB&: disposables '##B#: already)unregistered disposable ! SNIEB&: debug)leaks: P;#IV"$' S&B$: continuation : register)disposable 5 obF )) 6 debug)leaks: get)global 0 current)continuation GGcontinuation 3 disposables get adFoin ! hen

: unregister)disposable 5 obF )) 6 disposables get ,dup in: 0 delete 3 0 drop already)unregistered 3 if ! ;#IV"$'G $U;&': disposable P identity)tuple + disposed boolean . continuation ! : ne )disposable 5 class )) disposable 6 ne dup register)disposable ! inline G'N'#I%: dispose4 5 disposable )) 6 '##B#: already)disposed disposable ! : check)disposed 5 disposable )) 6 dup disposedGG 0 already)disposed 3 0 drop 3 if ! inline G'N'#I%: dispose 5 disposable )) 6 : unless)disposed 5 disposable quot )) 6 0 dup disposedGG 0 drop 3 3 dip if ! inline I: obFect dispose 0 t GGdisposed dispose4 3 unless)disposed ! I: disposable dispose 0 0 unregister)disposable 3 0 call)next)method 3 bi 3 unless)disposed ! : dispose< 5 obF )) 6 0 dispose 3 curry 0 < 3 recover ! inline : dispose)each 5 seq )) 6 0 0 dispose< 3 each 3 + . make 0 last rethro 3 unless)empty ! : ith)disposal 5 obFect quot )) 6 over 0 dispose 3 curry 0 3 cleanup ! inline

P;#IV"$' SNIEB&: al ays)destructors SNIEB&: error)destructors : do)al ays)destructors 5 )) 6 al ays)destructors get PreversedG dispose)each ! : do)error)destructors 5 )) 6 error)destructors get PreversedG dispose)each ! ;#IV"$'G : `dispose 5 disposable )) disposable 6 dup al ays)destructors get push ! inline : adispose 5 disposable )) disposable 6 dup error)destructors get push ! inline

ith)destructors 5 quot )) 6 0 V+ . clone al ays)destructors set V+ . clone error)destructors set 0 do)al ays)destructors 3 0 do)error)destructors 3 cleanup 3 ith)scope ! inline

0 ?S+ . clone disposables set)global V+ . clone al ays)destructors set)global V+ . clone error)destructors set)global 3 (destructors( add)startup)hook 0 do)al ays)destructors do)error)destructors 3 (destructors( add)shutdo n)hook USING: help.markup help.syntax libc kernel continuations io sequences classes ! IN: destructors ?'&;: debug)leaks: + *var)description (Jhen this variable is on< ( + *link ne )disposable . ( stores the current continuation in the ( + *link disposable . (7s ( + *slot (continuation( . ( slot.( . + *see)also (tools.destructors( . ! ?'&;: disposable + *class)description (;arent class for disposable resources. $his class has three slots:( + *list + + *slot (disposed( . ( ) boolean. Set to true by ( + *link dispose . (. "ssert that it is false ith ( + *link check)disposed . (.( . + + *slot (id( . ( ) unique identifier. Set by ( + *link ne )disposable . (.( . + + *slot (continuation( . ( ) current continuation at construction time< for debugging. Set by ( + *link ne )disposable . ( if ( + *link debug)leaks: . ( is on.( . . (Ne instances must be constructed ith ( + *link ne )disposable . ( and subclasses must implement ( + *link dispose4 . (.( . ! ?'&;: ne )disposable + *values + (class( class . + (disposable( disposable . . + *description (%onstructs a ne instance of a subclass of ( + *link disposable . (. $his sets the ( + *slot (id( . ( slot< registers the ne obFect ith the global ( + *link disposables . ( set< and if ( + *link debug)leaks: . ( is on< stores the current continuation in the ( + *slot (continuation( . ( slot.( . ! ?'&;: dispose + *values + (disposable( (a disposable obFect( . . + *contract (#eleases operating system resources associated ith a disposable obFect. Cisposable obFects include streams< memory mapped files< and so on.( *nl (No further operations can be performed on a disposable obFect after this call.( *nl (Cisposing an obFect hich has already been disposed should have no effect< and in particular it should not fail ith an error. $o help implement this pattern<

inherit from the ( + *link disposable . ( class and implement the ( + *link dispose4 . ( method instead.( . + *notes (Nou must dispose of disposable obFects after you are finished orking ith them< to avoid leaking operating system resources. " convenient ay to automate this is by using the ( + *link ith)disposal . ( ord.( *nl ($he default implementation assumes the obFect has a ( + *snippet (disposed( . ( slot. If the slot is set to ( + *link f . (< it calls ( + *link dispose4 . ( and sets the slot to ( + *link t . (.( . ! ?'&;: dispose4 + *values + (disposable( (a disposable obFect( . . + *contract (#eleases operating system resources associated ith a disposable obFect. Cisposable obFects include streams< memory mapped files< and so on.( . + *notes ($his ord should not be called directly. It can be implemented on obFects ith a ( + *slot (disposed( . ( slot to ensure that the obFect is only disposed once.( . ! ?'&;: ith)disposal + *values + (obFect( (a disposable obFect( . + (quot( + *quotation (5 obFect )) 6( . . . + *description (%alls the quotation< disposing the obFect ith ( + *link dispose . ( after the quotation returns or if it thro s an error.( . ! ?'&;: ith)destructors + *values + (quot( (a quotation( . . + *description (%alls a quotation ithin a ne dynamic scope. $his quotation may register destructors using ( + *link `dispose . ( or ( + *link adispose . (. $he former registers a destructor that ill al ays run hether or not the quotation thre an error< and the latter registers a destructor that only runs if the quotation thro s an error. Cestructors are run in reverse order from the order in hich they ere registered.( . + *notes (Cestructors generali8e ( + *link ith)disposal . (. $he follo ing t o lines are equivalent< except that the second line establishes a ne dynamic scope:( + *code (0 M 3 ith)disposal( (0 `dispose M 3 ith)destructors( . . + *examples + *code (0 1= malloc `free 3 ith)destructors( . . ! ?'&;: `dispose + *values + (disposable( (a disposable obFect( . . + *description (Iarks the obFect for unconditional disposal at the end of the current ( + *link ith)destructors . ( scope.( . ! ?'&;: adispose + *values + (disposable( (a disposable obFect( . . + *description (Iarks the obFect for disposal in the event of an error at the end of the current ( + *link ith)destructors . ( scope.( . ! ?'&;: dispose)each + *values + (seq( sequence . . + *description ("ttempts to dispose of each element of a sequence and collects all of the errors into a sequence. If any errors are thro n during disposal< the last error is rethro n after all obFects have been disposed.( . !

?'&;: disposables + *var)description (Global variable holding all disposable obFects hich have not been disposed of yet. $he ( + *link ne )disposable . ( ord adds obFects here< and the ( + *link dispose . ( method on disposables removes them. $he ( + *link (tools.destructors( . ( vocabulary provides some ords for orking ith this data.( . + *see)also (tools.destructors( . ! "#$I%&': (destructors)anti)patterns( (#esource disposal anti)patterns( (Jords hich create obFects corresponding to external resources should al ays be used ith ( + *link ith)disposal . (. $he follo ing code is rong:( + *code (Pexternal)resourceG ... do stuff ... dispose( . ($he reason being that if ( + *snippet (do stuff( . ( thro s an error< the resource ill not be disposed of. $he most important case here this can occur is ith IQB streams< and the correct solution is to al ays use ( + *link ith)input)stream . ( and ( + *link ith)output)stream . (! see ( + *link (stdio( . ( for details.( ! "#$I%&': (destructors)using( (Using destructors( (Cisposing of an obFect:( + *subsections dispose . (Utility ord for scoped disposal:( + *subsections ith)disposal . (Utility ord for disposing multiple obFects:( + *subsections dispose)each . (Utility ords for more complex disposal patterns:( + *subsections ith)destructors `dispose adispose . ! "#$I%&': (destructors)extending( (Jriting ne destructors( (Superclass for disposable obFects:( + *subsections disposable . (;arametri8ed constructor for disposable obFects:( + *subsections ne )disposable . (Generic disposal ord:( + *subsections dispose4 . (Global set of disposable obFects:( + *subsections disposables . ! "#$I%&': (destructors( (Ceterministic resource disposal( (Bperating system resources such as streams< memory mapped files< and so on are not managed by @actor7s garbage collector and must be released hen you are done ith them. @ailing to release a resource can lead to reduced performance and instability.( + *subsections (destructors)using( (destructors)extending( (destructors)anti)patterns( . + *see)also (tools.destructors( . ! "EBU$: (destructors( USING: destructors kernel tools.test continuations accessors namespaces sequences destructors.private ! IN: destructors.tests

$U;&': dispose)error ! I: dispose)error dispose - thro $U;&': dispose)dummy disposed: ! I: dispose)dummy dispose t GGdisposed: drop ! $+ dispose)error . (a( set $+ dispose)dummy . (b( set 0 f 3 0 (b( get disposed:GG 3 unit)test 0 + (a( (b( . 0 get 3 map dispose)each 3 0 - H 3 must)fail) ith 0 t 3 0 (b( get disposed:GG 3 unit)test $U;&': dummy)obF destroyed: ! : Pdummy)obFG 5 )) obF 6 dummy)obF ne $U;&': dummy)destructor obF ! %: Pdummy)destructorG dummy)destructor I: dummy)destructor dispose 5 obF )) 6 obFGG t GGdestroyed: drop ! : destroy)al ays 5 obF )) 6 Pdummy)destructorG `dispose drop ! : destroy)later 5 obF )) 6 Pdummy)destructorG adispose drop ! 0 t 3 0 0 ! !

Pdummy)obFG dup destroy)al ays 3 ith)destructors destroyed:GG 3 unit)test 0 f 3 0 0

Pdummy)obFG dup destroy)later 3 ith)destructors destroyed:GG 3 unit)test 0 t 3 0 Pdummy)obFG 0 0 dup destroy)al ays (foo( thro 3 ith)destructors 3 ignore)errors destroyed:GG 3 unit)test 0 t 3 0 Pdummy)obFG 0 0 dup destroy)later (foo( thro 3 ith)destructors 3 ignore)errors destroyed:GG

3 unit)test $U;&': silly)disposable P disposable ! I: silly)disposable dispose4 drop ! silly)disposable ne )disposable (s( set (s( get dispose 0 (s( get unregister)disposable 3 0 disposableGG silly)disposable: 3 must)fail) ith K %opyright 5%6 ,=1= Caniel 'hrenberg K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: assocs hashtables kernel math sequences vectors ! @#BI: assocs HG change)at ! IN: sets K Set protocol IIMIN: set G'N'#I%: adFoin 5 elt set )) 6 G'N'#I%: :adFoin 5 elt set )) : 6 G'N'#I%: in: 5 elt set )) : 6 G'N'#I%: delete 5 elt set )) 6 G'N'#I%: set)like 5 set exemplar )) set7 6 G'N'#I%: fast)set 5 set )) set7 6 G'N'#I%: members 5 set )) seq 6 G'N'#I%: union 5 set1 set, )) set 6 G'N'#I%: intersect 5 set1 set, )) set 6 G'N'#I%: intersects: 5 set1 set, )) : 6 G'N'#I%: diff 5 set1 set, )) set 6 G'N'#I%: subset: 5 set1 set, )) : 6 G'N'#I%: setH 5 set1 set, )) : 6 G'N'#I%: duplicates 5 set )) seq 6 G'N'#I%: all)unique: 5 set )) : 6 G'N'#I%: null: 5 set )) : 6 G'N'#I%: cardinality 5 set )) n 6 G'N'#I%: clear)set 5 set )) 6 I: f members drop f ! I: f cardinality drop = ! I: f delete ,drop ! I: f clear)set drop ! inline K Cefaults for some methods. K Bverride them for efficiency I: set :adFoin ,dup in: 0 ,drop f 3 0 adFoin t 3 if ! I: set null: members null: ! inline I: set cardinality members length ! I: set clear)set 0 members 3 keep 0 delete 3 curry each ! I: set set)like drop ! inline P;#IV"$' : :members 5 set )) seq 6

dup sequence: 0 members 3 unless ! inline : 5union6 5 set1 set, )) seq 6 0 :members 3 bi9 append ! inline ;#IV"$'G I: set union 0 5union6 3 keep set)like ! P;#IV"$' : tester 5 set )) quot 6 fast)set 0 in: 3 curry ! inline : sequenceQtester 5 set1 set, )) set17 quot 6 0 members 3 0 tester 3 bi4 ! inline : smallQlarge 5 set1 set, )) set17 set,7 6 ,dup 0 cardinality 3 bi9 G 0 s ap 3 hen ! inline : 5intersect6 5 set1 set, )) seq 6 smallQlarge sequenceQtester filter ! inline : 5diff6 5 set1 set, )) seq 6 sequenceQtester 0 not 3 compose filter ! inline ;#IV"$'G I: set intersect 0 5intersect6 3 keep set)like ! I: set diff 0 5diff6 3 keep set)like ! I: set intersects: smallQlarge sequenceQtester any: ! P;#IV"$' : 5subset:6 5 set1 set, )) : 6 sequenceQtester all: ! inline ;#IV"$'G I: set subset: ,dup 0 cardinality 3 bi9 G 0 ,drop f 3 0 5subset:6 3 if ! I: set setH ,dup 0 cardinality 3 bi9 eq: 0 5subset:6 3 0 ,drop f 3 if ! I: set fast)set ! I: set duplicates drop f ! I: set all)unique: drop t ! P;#IV"$' : 5pruned6 5 elt set accum )) 6 ,over :adFoin 0 nip push 3 0 -drop 3 if ! inline : pruned 5 seq )) ne seq 6 0 f fast)set 3 0 length PvectorG 3 bi 0 0 5pruned6 3 ,curry each 3 keep !

;#IV"$'G K Sequences are sets INS$"N%': sequence set I: sequence in: member: ! inline I: sequence adFoin 0 delete 3 0 push 3 ,bi ! I: sequence delete removeK drop ! inline I: sequence set)like 0 members 3 dip like ! I: sequence members 0 pruned 3 keep like ! I: sequence null: empty: ! inline I: sequence cardinality fast)set cardinality ! I: sequence clear)set delete)all ! inline : combine 5 sets )) setQf 6 0 f 3 0 0 0 :members 3 map concat 3 0 first 3 bi set)like 3 if)empty ! : intersection 5 sets )) setQf 6 0 f 3 0 0 3 0 intersect 3 map)reduce 3 if)empty ! : gather 5 ... seq quot: 5 ... elt )) ... elt7 6 )) ... ne seq 6 map concat members ! inline : adFoin)at 5 value key assoc )) 6 0 0 f fast)set 3 unless4 0 adFoin 3 keep 3 change)at ! : : ithin 5 seq set )) subseq 6 tester filter ! ithout 5 seq set )) subseq 6 tester 0 not 3 compose filter !

: adFoin)all 5 seq set )) 6 0 adFoin 3 curry each ! : unionK 5 set1 set, )) set1 6 :members over adFoin)all ! : diffK 5 set1 set, )) set1 6 dupd sequenceQtester 0 dup 3 prepose pick 0 delete 3 curry 0 0 drop 3 if 3 curry compose each ! : intersectK 5 set1 set, )) set1 6 dupd sequenceQtester 0 dup 3 prepose 0 not 3 compose pick

0 delete 3 curry 0 0 drop 3 if 3 curry compose each ! K $emporarily for compatibility : unique 5 seq )) assoc 6 0 dup 3 ?+ . mapGassoc ! : conFoin 5 elt assoc )) 6 dupd set)at ! : conFoin)at 5 value key assoc )) 6 0 dupd :set)at 3 change)at ! USING: assocs hashtables help.markup help.syntax kernel quotations sequences vectors ! IN: sets "#$I%&': (sets( (Sets( (" set is an unordered list of elements. Jords for orking ( + *vocab)link (sets( . ( vocabulary.( *nl ("ll sets are instances of a mixin class:( + *subsections set set: . + *subsections (set)operations( (set)implementations( . ! "EBU$: (sets( "#$I%&': (set)operations( (Bperations on sets( ($o test if an obFect is a member of a set:( + *subsections in: . ("ll sets can be represented as a sequence< ithout duplicates< of their members:( + *subsections members . ($o get the number of elements in a set:( + *subsections cardinality . (Sets can have members added or removed destructively:( + *subsections adFoin delete clear)set unionK diffK intersectK . ($o test if a set is the empty set:( + *subsections null: . (Easic mathematical operations< hich any type of set may override for efficiency:( + *subsections diff intersect union . (Iathematical predicates on sets< hich may be overridden for efficiency:( + *subsections intersects: subset: setH . ("n optional generic ord for creating sets of the same class as a given set:( + *subsections set)like . ("n optional generic ord for creating a set ith a fast lookup operation< if the set itself has a slo lookup operation:( ith sets are in the

+ *subsections fast)set . (@or set types that allo duplicates< like sequence sets< some additional test for duplication:( + *subsections all)unique: duplicates . (Utilities for sets and sequences:( + *subsections ithin ithout . !

ords

"#$I%&': (set)implementations( (Set implementations( ($here are several implementations of sets in the @actor library. Iore can be added if they implement the ords of the set protocol< the basic set operations.( + *subsections (sequence)sets( (hash)sets( (bit)sets( . ! "#$I%&': (sequence)sets( (Sequences as sets( ("ny sequence can be used as a set. $he members of this set are the elements of the sequence. %alling the ord ( + *link members . ( on a sequence returns a copy of the sequence ith only one listing of each member. Cestructive operations ( + *link adFoin . ( and ( + *link delete . ( only ork properly on gro able sequences like ( + *link vector . (s.( *nl (%are must be taken in riting efficient code using sequence sets. $esting for membership ith ( + *link in: . (< as ell as the destructive set operations< take time proportional to the si8e of the sequence. "nother representation< like ( + *link (hash)sets( . (< ould take constant time for membership tests. Eut binary operations like ( + *link union . ( are asymptotically optimal< taking time proportional to the sum of the si8e of the inputs.( *nl ("s one particular example< ( + *link ;BS$;BN': f . ( is a representation of the empty set< since it is an empty sequence.( ! ?'&;: set + *class)description ($he class of all sets. %ustom implementations of the set protocol should be declared as instances of this mixin for all set implementation to ork correctly.( . ! ?'&;: adFoin + *values + (elt( obFect . + (set( set . . + *description (Cestructively adds ( + *snippet (elt( . ( to ( + *snippet (set( . (. @or sequences< this guarantees that this element is not duplicated< and that it is at the end of the sequence.( *nl ('ach mutable set type is expected to implement a method on this generic ord.( . + *examples + *example (USING: prettyprint sets kernel !( (V+ >(beans>( >(salsa>( >(cheese>( . clone( (>(nachos>( over adFoin( (>(salsa>( over adFoin( (.( (V+ >(beans>( >(cheese>( >(nachos>( >(salsa>( .( . . + *side)effects (set( . !

?'&;: :adFoin + *values + (elt( obFect . + (set( set . + (:( (a boolean( . . + *description (" version of ( + *link adFoin . ( hich returns hether the element as added to the set.( . + *notes ($his is slightly less efficient than ( + *link adFoin . ( due to the initial membership test.( . ! ?'&;: delete + *values + (elt( obFect . + (set( set . . + *description (Cestructively removes ( + *snippet (elt( . ( from ( + *snippet (set( . (. If the element is not present< this does nothing.( *nl ('ach mutable set type is expected to implement a method on this generic ord.( . + *side)effects (set( . ! ?'&;: clear)set + *values + (set( set . . + *contract (#emoves all entries from the set.( . + *side)effects (set( . ! ?'&;: members + *values + (set( set . + (seq( sequence . . + *description (%reates a sequence ith a single copy of each member of the set.( *nl ('ach set type is expected to implement a method on this generic ord.( . ! ?'&;: in: + *values + (elt( obFect . + (set( set . + (:( (a boolean( . . + *description ($ests hether the element is a member of the set.( *nl ('ach set type is expected to implement a method on this generic ord as part of the set protocol.( . ! ?'&;: adFoin)at + *values + (value( obFect . + (key( obFect . + (assoc( assoc . . + *description ("dds ( + *snippet (value( . ( to the set stored at ( + *snippet (key( . ( of ( + *snippet (assoc( . (.( . + *side)effects (assoc( . ! ?'&;: duplicates + *values + (set( set . + (seq( sequence . . + *description (Butputs a sequence consisting of elements hich occur more than once in ( + *snippet (set( . (.( . + *examples + *example (USING: sets prettyprint !( (+ 1 , - 1 , 1 . duplicates .( (+ 1 , 1 .( . . ! ?'&;: all)unique: + *values + (set( set . + (:( (a boolean( . . + *description ($ests hether a set contains any repeated elements.( . + *example (USING: sets prettyprint !( (+ = 1 1 , - A . all)unique: .( (f( . ! ?'&;: diff + *values + (set1( set . + (set,( set . + (set( set . . + *description (Butputs a set consisting of elements present in ( + *snippet (set1( . ( but not ( + *snippet (set,( . (< comparing elements for equality.( *nl ($his ord has a default definition hich orks for all sets< but set implementations may override the default for efficiency.(

. + *examples + *example (USING: sets prettyprint !( (+ 1 , - . + , - / . diff .( (+ 1 .( . . ! ?'&;: intersect + *values + (set1( set . + (set,( set . + (set( set . . + *description (Butputs a set consisting of elements present in both ( + *snippet (set1( . ( and ( + *snippet (set,( . (.( ($his ord has a default definition hich orks for all sets< but set implementations may override the default for efficiency.( . + *examples + *example (USING: sets prettyprint !( (+ 1 , - . + , - / . intersect .( (+ , - .( . . ! ?'&;: intersection + *values + (sets( sequence . + (setQf( (a ( + *link set . ( or ( + *link f . . . + *description (Butputs the intersection of all the sets of the sequence ( + *snippet (sets( . (< or ( + *link f . ( if ( + *snippet (sets( . ( is empty.( . ! ?'&;: union + *values + (set1( set . + (set,( set . + (set( set . . + *description (Butputs a set consisting of elements present in either ( + *snippet (set1( . ( or ( + *snippet (set,( . ( hich does not contain duplicate values.( *nl ($his ord has a default definition hich orks for all sets< but set implementations may override the default for efficiency.( . + *examples + *example (USING: sets prettyprint !( (+ 1 , - . + , - / . union .( (+ 1 , - / .( . . ! + diff intersect union . related) ords ?'&;: unionK + *values + (set1( set . + (set,( set . . + *description ("dds all members from ( + *snippet (set,( . ( to ( + *snippet (set1( . (.( . + *side)effects (set1( . ! ?'&;: diffK + *values + (set1( set . + (set,( set . . + *description (#emoves all members from ( + *snippet (set1( . ( contained in ( + *snippet (set,( . (.( . + *side)effects (set1( . ! ?'&;: intersectK + *values + (set1( set . + (set,( set . . + *description (#emoves all members from ( + *snippet (set1( . ( not contained in ( + *snippet (set,( . (.( . + *side)effects (set1( . ! ?'&;: intersects: + *values + (set1( set . + (set,( set . + (:( (a boolean( . . + *description ($ests if ( + *snippet (set1( . ( and ( + *snippet (set,( . ( have any elements in common.( . + *notes (If one of the sets is empty< the result is al ays ( + *link f . (.( . ! ?'&;: subset:

+ *values + (set1( set . + (set,( set . + (:( (a boolean( . . + *description ($ests if every element of ( + *snippet (set1( . ( is contained in ( + *snippet (set,( . (.( . + *notes (If ( + *snippet (set1( . ( is empty< the result is al ays ( + *link t . (.( . ! ?'&;: setH + *values + (set1( set . + (set,( set . + (:( (a boolean( . . + *description ($ests if both sets contain the same elements< disregrading order and duplicates.( . ! ?'&;: gather + *values + (seq( sequence . + (quot( quotation . + (ne seq( sequence . . + *description (Iaps a quotation onto a sequence< concatenates the results of the mapping< and removes duplicates.( . ! ?'&;: set)like + *values + (set( set . + (exemplar( set . + (set7( set . . + *description (If the conversion is defined for the exemplar< converts the set into a set of the exemplar7s class. $his is not guaranteed to create a ne set< for example if the input set and exemplar are of the same class.( *nl (Set implementations may optionally implement a method on this generic ord. $he default implementation returns its input set.( . + *examples + *example (USING: sets prettyprint !( (+ 1 , - . ?S+ . set)like .( (?S+ 1 , - .( . . ! ?'&;: ithin + *values + (seq( sequence . + (set( set . + (subseq( sequence . . + *description (#eturns the subsequence of the given sequence consisting of members of the set. $his may contain duplicates< if the sequence has duplicates.( . ! ?'&;: ithout + *values + (seq( sequence . + (set( set . + (subseq( sequence . . + *description (#eturns the subsequence of the given sequence consisting of things that are not members of the set. $his may contain duplicates< if the sequence has duplicates.( . ! ?'&;: null: + *values + (set( set . + (:( (a boolean( . . + *description ($ests hether the given set is empty. $his outputs ( + *snippet (t( . ( hen given a null set of any type.( . ! ?'&;: cardinality + *values + (set( set . + (n( (a non)negative integer( . . + *description (#eturns the number of elements in the set. "ll sets support this operation.( . ! ?'&;: combine + *values + (sets( (a sequence of sets( . + (setQf( (a ( + *link set . ( or ( + *link f . . . + *description (Butputs the union of a sequence of sets< or ( + *link f . ( if the sequence is empty.( . ! K %opyright 5%6 ,=1= Caniel 'hrenberg< Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: sets tools.test kernel prettyprint hash)sets sorting math sequences bit)sets bit)arrays ! IN: sets.tests

0 V+ 1 , - . 3 0 - V+ 1 , . clone 0 adFoin 3 keep 3 unit)test 0 V+ 1 , . 3 0 , V+ 1 , . clone 0 adFoin 3 keep 3 unit)test 0 t 3 0 / + , / A . in: 3 unit)test 0 f 3 0 1 + , / A . in: 3 unit)test 0 f 3 0 f A Pbit)setG in: 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 V+ 1 , . 3 0 - V+ V+ , . 3 0 1 V+ 1 = 3 0 A Pbit)setG = 3 0 A Pbit)setG = 3 0 A Pbit)setG = 3 0 A Pbit)setG ?S+ 1 . 3 0 ?S+ 1 + + + + t t 1 1 1 3 3 , , , , 0 0 1 / + 1 , . clone 0 delete 3 keep 3 unit)test , . clone 0 delete 3 keep 3 unit)test = over delete cardinality 3 unit)test f over delete cardinality 3 unit)test - over adFoin - over delete cardinality 3 unit)test 1= over delete cardinality 3 unit)test , . , over delete 3 unit)test 1 , , - - - - - . dup set)like natural)sort 3 unit)test , - . + . set)like natural)sort 3 unit)test , - - . + . set)like 3 unit)test , , 1 . + . set)like 3 unit)test Pbit)setG set)like / Pbit)setG H 3 unit)test . set)like ?S+ 1 , - . H 3 unit)test

. 3 0 + 1 1 . 3 0 ?S+ 1 . 3 0 + 1 , . 3 0 + - Pbit)setG 1 1 , - . ?S+

0 ?S+ 1 , - . 3 0 + 1 , - . fast)set 3 unit)test 0 $+ bit)set + table :+ f . . . 3 0 1 Pbit)setG fast)set 3 unit)test 0 + 1 . 3 0 + 1 . members 3 unit)test 0 + . 3 0 + . + . union 3 unit)test 0 + 1 , - / . 3 0 + 1 , - . + , - / . union 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + + + + + t f f f f + + + + + . , , , , 3 3 3 3 3 . 1 1 1 1 3 0 0 0 0 0 3 . . . . 0 . . / . + + + + + 0 3 3 3 3 + 3 3 . 3 1 / . 1 . + 0 0 0 0 . 0 0 3 0 , , + . + . + + + + + + + 0 + . . 1 + . + 1 1 1 1 . 1 1 + 1 intersect , - . + , , - . + , 1 , - / . , , - . + 3 + , unit)test / . intersect 3 unit)test / A . intersect 3 unit)test , - / . intersect 3 unit)test - - / . intersect 3 unit)test

+ 1 - . intersects: 3 unit)test + 1 - . intersects: 3 unit)test . intersects: 3 unit)test . intersects: 3 unit)test intersects: 3 unit)test . , , , 1 diff 3 unit)test - . + , - / . diff 3 unit)test - . + , - / A . diff 3 unit)test - / . + , - / . diff 3 unit)test , - . + , - / / . diff 3 unit)test

0 $+ bit)set + table :+ f f f . . . 3 0 - Pbit)setG = over adFoin dup diff 3 unit)test 0 0 0 0 0 0 f t t t t f 3 3 3 3 3 3 0 0 0 0 0 0 + + + + + + 1 1 1 . . 1 , , , + + . . 1 . + / . + 1 , . subset: 3 unit)test / . + 1 , . s ap subset: 3 unit)test + 1 , . subset: 3 unit)test , . subset: 3 unit)test subset: 3 unit)test . subset: 3 unit)test

0 t 3 0 + 1 , - . + , 1 - . setH 3 unit)test 0 f 3 0 + , - . + 1 , - . setH 3 unit)test

0 f 3 0 + 1 , - . + , - . setH 3 unit)test 0 + , 1 , 1 . 3 0 + 1 , - , 1 , 1 . duplicates 3 unit)test 0 f 3 0 ?S+ 1 , - 1 , 1 . duplicates 3 unit)test 0 f 3 0 + = 1 1 , - A . all)unique: 3 unit)test 0 t 3 0 + = 1 , - / A . all)unique: 3 unit)test 0 t 3 0 ?S+ = 1 , - / A . all)unique: 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 t f t f t f = = 1 1 1 = = , 1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f null: 3 unit)test + / . null: 3 unit)test ?S+ . null: 3 unit)test ?S+ - . null: 3 unit)test , Pbit)setG null: 3 unit)test - Pbit)setG = over adFoin null: 3 unit)test f cardinality 3 unit)test + . cardinality 3 unit)test + 1 . cardinality 3 unit)test + 1 1 . cardinality 3 unit)test ?S+ 1 . cardinality 3 unit)test ?S+ 1 , - . cardinality 3 unit)test = Pbit)setG cardinality 3 unit)test A Pbit)setG cardinality 3 unit)test A Pbit)setG = over adFoin 1 over adFoin cardinality 3 unit)test A Pbit)setG 1 over adFoin cardinality 3 unit)test

0 + . 3 0 + . + . ithin 3 unit)test 0 + , - . 3 0 + 1 , - . + , - / . ithin 3 unit)test 0 + , , - . 3 0 + 1 , , - . + , - - / . ithin 3 unit)test 0 + . 3 0 + . + . ithout 3 unit)test 0 + 1 . 3 0 + 1 , - . + , - / . ithout 3 unit)test 0 + 1 1 . 3 0 + 1 1 , - - . + , - / / . ithout 3 unit)test 0 + 1 , - . 3 0 + + 1 . + , . + 1 - . . combine 3 unit)test 0 f 3 0 + . combine 3 unit)test 0 + 1 / U 1L ,A -L . 3 0 + + 1 , - . + / A L . . 0 0 sq 3 map 3 gather 3 unit)test 0 ?+ + - ?S+ 1 , . . . 3 0 ?+ . clone 1 - pick adFoin)at , - pick adFoin)at 3 unit)test 0 ?+ + - ?+ + 1 1 . + , , . . . . 3 0 ?+ . clone 1 - pick conFoin)at , - pick conFoin)at 3 unit)test $U;&': null)set ! INS$"N%': null)set set I: null)set members drop f ! 0 = 3 0 $+ null)set . cardinality 3 unit)test 0 f 3 0 $+ null)set . members 3 unit)test 0 t 3 0 $+ null)set . $+ null)set . set)like $+ null)set . H 3 unit)test 0 0 0 0 0 t t t t f 3 3 3 3 3 0 0 0 0 0 $+ null)set . set: 3 unit)test ?S+ . set: 3 unit)test + . set: 3 unit)test A Pbit)setG set: 3 unit)test ?+ . set: 3 unit)test

0 ?S+ . 3 0 ?S+ . 0 clear)set 3 keep 3 unit)test

0 ?S+ . 3 0 ?S+ 1 , - . 0 clear)set 3 keep 3 unit)test 0 0 0 0 ?S+ ?S+ ?S+ ?S+ . 1 1 1 3 . . , 0 3 3 ?S+ . 0 ?S+ 0 ?S+ . 3 0 ?S+ . unionK 3 unit)test 1 . ?S+ . unionK 3 unit)test . ?S+ 1 . unionK 3 unit)test ?S+ 1 . ?S+ 1 , - . unionK 3 unit)test

0 f 3 0 + . intersection 3 unit)test 0 ?S+ . 3 0 + ?S+ . . intersection 3 unit)test 0 ?S+ 1 . 3 0 + ?S+ 1 , - . ?S+ 1 . . intersection 3 unit)test 0 0 0 0 0 0 0 0 ?S+ ?S+ ?S+ ?S+ ?S+ ?S+ ?S+ ?S+ . 1 1 1 . , . . 3 . . , 3 3 3 0 3 3 0 . 0 0 ?S+ . 0 ?S+ 0 ?S+ . 3 0 ?S+ 3 0 ?S+ ?S+ ?S+ 1 , 1 . ?S+ . diffK - . ?S+ ?S+ , 1 , - . 3 unit)test , - . diffK 3 unit)test / . diffK 3 unit)test ?S+ / . diffK 3 unit)test

. ?S+ . ?S+ 1 , 1 . ?S+ 1 , - .

intersectK 3 unit)test - . ?S+ , - . intersectK 3 unit)test , - / . intersectK 3 unit)test ?S+ / . intersectK 3 unit)test

USING: make sequences tools.test ! IN: make + ("E%C( . 0 0 ("E%C( 0 < 3 each 3 (( make 3 unit)test + ?+ + (key( (value( . . . 0 0 (value( (key( << 3 ?+ . make 3 unit)test + + + 1 , . . . 0 0 , 1 << 3 + . make 3 unit)test K %opyright 5%6 ,==-< ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: assocs kernel sequences namespaces ! IN: make SNIEB&: building P;#IV"$' : make)sequence 5 quot exemplar )) seq 6 0 -, s ap ne )resi8able 0 building 0 call 3 ith)variable 3 keep 3 keep like ! inline : make)assoc 5 quot exemplar )) assoc 6 A s ap ne )assoc 0 building 0 call 3 ith)variable 3 keep ! inline ;#IV"$'G : make 5 quot exemplar )) seq 6 dup sequence: 0 make)sequence 3 0 make)assoc 3 if ! inline : < 5 elt )) 6 building get push ! : W 5 seq )) 6 building get push)all ! : << 5 value key )) 6 building get set)at !

: WW 5 assoc )) 6 building get s ap assoc)unionK drop ! : <2 5 n key )) 6 building get at2 ! IN: make USING: assocs help.markup help.syntax kernel math.parser quotations sequences ! "#$I%&': (make)philosophy( (Iake philosophy( + *heading (Jhen to use make( . (Iake is useful for complex sequence construction hich is hard to express ith sequence combinators and various combinations of utility ords.( *nl (@or example< this example uses ( + *link make . ( and reads better than a version using utility ords:( + *code (0 0 leftGG < 3 0 >(2>( W centerGG W >()>( W 3 0 right < 3 tri 3 + . make( . (compare the above to( + *code (0 centerGG >(2>( >()>( surround 3 0 leftGG prefix 3 0 right suffix 3 tri( . ($he first one has a similar shape to the eventual output array. $he second one has an arbitrary structure and uses three different utilities. @urthermore< the second version also constructs t o redundant intermediate sequences< and for longer sequences< this extra copying ill out eigh any overhead ( + *link make . ( has due to its use of a dynamic variable to store the sequence being built.( *nl (Bn the other hand< using ( + *link make . ( instead of a single call to ( + *link surround . ( is overkill. $he belo headings summari8e the most important cases here other idioms are more appropriate than ( + *link make . (.( + *heading (Iake versus combinators( . (Sometimes< usages of ( + *link make . ( are better expressed ith ( + *link (sequences)combinators( . (. @or example< instead of calling a combinator ith a quotation hich executes ( + *link < . ( exactly once on each iteration< often a combinator encapsulating that specific idiom exists and can be used.( *nl (@or example<( + *code (0 0 /, 4 < 3 each 3 + . make( . (is equivalent to( + *code (0 /, 4 3 map( . (and( + *code (0 0 reverse W 3 each 3 >(>( make( . (is equivalent to( + *code (0 reverse 3 map concat( . + *heading (Utilities for simple make patterns( . (Sometimes< an existing ord already implements a specific ( + *link make . ( usage. @or example< ( + *link prefix . ( is equivalent to the follo ing< ith the added caveat that the belo example al ays outputs an array:( + *code (0 < W 3 + . make( . ($he existing utility ords can in some cases express intent better than a bunch of ( + *link < . ( and ( + *link W . (.( + *heading (%onstructing quotations( . (Simple quotation construction can often be accomplished using ( + *link (fry( . ( and ( + *link (compositional)combinators( . (.( *nl (@or example<( + *code (0 , < < >> 2 < 3 0 3 make( . (is better expressed as( + *code (70 , [ 2 3( . ! "#$I%&': (namespaces)make( (Iaking sequences ith variables( ($he ( + *vocab)link (make( . ( vocabulary implements a facility for constructing ( + *link sequence . (s and ( + *link assoc . (s by holding a

collector obFect in a variable. Storing the collector obFect rather than the stack may allo code to be ritten ith less manipulation.( *nl (BbFect construction is rapped in a combinator:( + *subsections make . (Inside the quotation passed to ( + *link make . (< several values:( + *subsections < W Z . (Jhen making an ( + *link assoc . (< you can use these ords pairs:( + *subsections << WW . ($he collector obFect can be accessed directly from inside a (:( + *subsections building . + *example (USING: make math.parser !( (0 >(&anguage Z>( W %?"#: >>s < A Z 3 >(>( make print( (&anguage Z A( . + *subsections (make)philosophy( . ! "EBU$: (namespaces)make(

in a variable stack

ords accumulate

to add keyQvalue

( + *link make .

?'&;: building + *var)description ($emporary mutable gro able sequence 5or assoc6 holding elements accumulated so far by ( + *link make . (.( . ! ?'&;: make + *values + (quot( quotation . + (exemplar( sequence . + (seq( (a ne sequence( . . + *description (%alls the quotation in a ne dynamic scope ith the ( + *link building . ( variable bound to a ne resi8able mutable sequence. $he quotation and any ords it calls can execute the ( + *link < . ( and ( + *link W . ( ords to accumulate elements into a sequence 5or ( + *link << . ( and ( + *link WW . ( into an assoc6. Jhen the quotation returns< all accumulated elements are collected into an obFect ith the same type as ( + *snippet (exemplar( . (.( . + *examples + *example (USING: make prettyprint !( (0 1 < , < - < 3 + . make .( (+ 1 , .( . + *example (USING: make prettyprint !( (0 , 1 << / - << 3 ?+ . make .( (?+ + 1 , . + - / . .( . . ! ?'&;: < + *values + (elt( obFect . . + *description ("dds an element to the end of the sequence being constructed by ( + *link make . (.( . ! ?'&;: W + *values + (seq( sequence . . + *description ("ppends a sequence to the end of the sequence being constructed by ( + *link make . (.( . ! ?'&;: <<

+ *values + (value( obFect . + (key( obFect . . + *description (Stores the keyQvalue pair into the assoc being constructed by ( + *link make . (.( . ! ?'&;: WW + *values + (assoc( assoc . . + *description ("dds all entries from ( + *snippet (assoc( . ( to the assoc being constructed by ( + *link make . (.( . ! K %opyright 5%6 ,==A< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs gro able.private kernel math math.order sequences sequences.private vectors ! IN: sorting K Bptimi8ed merge)sort: K K 16 only allocates , temporary arrays K ,6 first phase 5interchanging pairs x0i3< x0i213 K x0i3 G x0i2136 is handled specially P;#IV"$' $U;&': merge)state + seq array . + accum vector . + accum1 vector . + accum, vector . + from1 array)capacity + to1 array)capacity + from, array)capacity + to, array)capacity here

. . . . !

: l)elt 5 merge )) elt 6 0 from1GG 3 0 seqGG 3 bi nth)unsafe ! inline : r)elt 5 merge )) elt 6 0 from,GG 3 0 seqGG 3 bi nth)unsafe ! inline : l)done: 5 merge )) : 6 0 from1GG 3 0 to1GG 3 bi eq: ! inline : r)done: 5 merge )) : 6 0 from,GG 3 0 to,GG 3 bi eq: ! inline : dump)l 5 merge )) 6 0 0 from1GG 3 0 to1GG 3 0 seqGG 3 tri 3 0 accumGG 3 bi push)all)unsafe ! inline : dump)r 5 merge )) 6 0 0 from,GG 3 0 to,GG 3 0 seqGG 3 tri 3 0 accumGG 3 bi push)all)unsafe ! inline : l)next 5 merge )) 6 0 0 l)elt 3 0 0 1 2 3 change)from1 drop 3 bi 3 0 accumGG 3 bi push)unsafe ! inline : r)next 5 merge )) 6 0 0 r)elt 3 0 0 1 2 3 change)from, drop 3 bi 3 0 accumGG 3 bi push)unsafe ! inline : decide 5 merge quot: 5 elt1 elt, )) PHG 6 )) : 6 0 0 l)elt 3 0 r)elt 3 bi 3 dip call 2gt2 eq: ! inline : 5merge6 5 merge quot: 5 elt1 elt, )) PHG 6 )) 6 over r)done: 0 drop dump)l 3 0

over l)done: 0 drop dump)r 3 0 ,dup decide 0 over r)next 3 0 over l)next 3 if 5merge6 3 if 3 if ! inline recursive : flip)accum 5 merge )) 6 dup 0 accumGG 3 0 accum1GG 3 bi eq: 0 dup accum1GG underlyingGG GGseq dup accum,GG GGaccum 3 0 dup accum1GG GGaccum dup accum,GG underlyingGG GGseq 3 if dup accumGG = GGlength ,drop ! inline : PmergeG 5 seq )) merge 6 > merge)state ne over Gvector GGaccum1 s ap length PvectorG GGaccum, dup accum1GG underlyingGG GGseq dup accum,GG GGaccum ! inline : compute)midpoint 5 merge )) merge 6 dup 0 from1GG 3 0 to,GG 3 bi 2 ,Q GGto1 ! inline : merging 5 from to merge )) 6 s ap GGto, s ap GGfrom1 compute)midpoint dup 0 to1GG 3 0 seqGG length 3 bi min GGto1 dup 0 to,GG 3 0 seqGG length 3 bi min GGto, dup to1GG GGfrom, drop ! inline : nth)chunk 5 n si8e )) from to 6 0 4 dup 3 keep 2 ! inline : chunks 5 length si8e )) n 6 0 align 3 keep Qi ! inline : each)chunk 5 length si8e quot )) 6 0 0 chunks 3 keep 3 dip 0 nth)chunk 3 prepose curry each)integer ! inline : merge 5 from to merge quot )) 6 0 0 merging 3 keep 3 dip 5merge6 ! inline : sort)pass 5 merge si8e quot )) 6 0 over flip)accum over 0 seqGG length 3 ,dip 3 dip 0 merge 3 ,curry each)chunk ! inline : sort)loop 5 merge quot )) 6 0 , over seqGG length 0 over G 3 curry 3 dip 0 0 1 shift ,dup 3 dip sort)pass 3 curry hile ,drop ! inline : each)pair 5 seq quot )) 6 0 0 length 1 2 ,Q 3 keep 3 dip

0 0 1 shift dup 1 2 3 dip 3 prepose curry each)integer ! inline : 5sort)pairs6 5 i1 i, seq quot accum )) 6 0 ,dup length H 3 ,dip rot 0 0 drop nip nth)unsafe 3 dip push)unsafe 3 0 0 0 0 nth)unsafe 3 curry bi9 ,dup 3 dip call 2gt2 eq: 0 s ap 3 hen 3 dip 0 push)unsafe 3 curry bi9 3 if ! inline : sort)pairs 5 merge quot )) 6 0 0 seqGG 3 0 accumGG 3 bi 3 dip s ap 0 5sort)pairs6 3 ,curry each)pair ! inline ;#IV"$'G : sort 5 seq quot: 5 obF1 obF, )) PHG 6 )) sortedseq 6 0 PmergeG 3 dip 0 sort)pairs 3 0 sort)loop 3 0 drop accumGG underlyingGG 3 ,tri ! inline : natural)sort 5 seq )) sortedseq 6 0 PHG 3 sort ! : sort) ith 5 seq quot: 5 elt )) key 6 )) sortedseq 6 0 compare 3 curry sort ! inline : inv)sort) ith 5 seq quot: 5 elt )) key 6 )) sortedseq 6 0 compare invert)comparison 3 curry sort ! inline P;#IV"$' : check)bounds 5 alist n )) alist 6 0 s ap ,dup bounds)check: 0 ,drop 3 0 bounds)error 3 if 3 curry dupd each ! ;#IV"$'G G'N'#I%: sort)keys 5 obF )) sortedseq 6 I: obFect sort)keys Galist sort)keys ! I: sequence sort)keys = check)bounds 0 first)unsafe 3 sort) ith ! G'N'#I%: sort)values 5 obF )) sortedseq 6 I: obFect sort)values Galist sort)values ! I: sequence sort)values 1 check)bounds 0 second)unsafe 3 sort) ith ! : sort)pair 5 a b )) c d 6 ,dup after: 0 s ap 3 hen ! USING: sorting sequences kernel math math.order random tools.test vectors sets vocabs grouping ! IN: sorting.tests 0 + . 3 0 + . natural)sort 3 unit)test 0 + ,R======= ,R======1 . 3 0 $+ slice f ,R======= ,R======, $+ iota)tuple f ,R======, . . natural)sort 3

unit)test 0 t 3 0 1== 0 drop 1== 0 ,= random 0 1=== random 3 replicate 3 replicate dup natural)sort 0 setH 3 0 nip 0 beforeH: 3 monotonic: 3 ,bi and 3 all)integers: 3 unit)test 0 3 0 + 1 , . 0 ,drop 1 3 sort drop 3 unit)test K Is it a stable sort: 0 t 3 0 + + 1 (a( . + 1 (b( . + 1 (c( . . dup sort)keys H 3 unit)test 0 + + 1 (a( . + 1 (b( . + 1 (c( . + 1 (e( . + , (d( . . 3 0 + + 1 (a( . + 1 (b( . + 1 (c( . + , (d( . + 1 (e( . . sort)keys 3 unit)test 0 3 0 all) ords natural)sort drop 3 unit)test USING: help.markup help.syntax kernel ords math sequences math.order ! IN: sorting "#$I%&': (sequences)sorting( (Sorting sequences( ($he ( + *vocab)link (sorting( . ( vocabulary implements the merge)sort algorithm. It runs in ( + *snippet (B5n log n6( . ( time< and is a ( + *emphasis (stable( . ( sort< meaning that the order of equal elements is preserved.( *nl ($he algorithm only allocates t o additional arrays< both the si8e of the input sequence< and uses iteration rather than recursion< and thus is suitable for sorting large sequences.( *nl (Sorting combinators all take comparator quotations ith stack effect ( + *snippet (5 elt1 elt, )) PHG 6( . (< here the output value is one of the three ( + *link (order)specifiers( . (.( *nl (Sorting a sequence ith a custom comparator:( + *subsections sort . (Sorting a sequence ith common comparators:( + *subsections sort) ith inv)sort) ith natural)sort sort)keys sort)values . ! "EBU$: (sequences)sorting( ?'&;: sort + *values + (seq( (a sequence( . + (quot( + *quotation (5 obF1 obF, )) PHG 6( . . + (sortedseq( (a ne sorted sequence( . . + *description (Sorts the elements of ( + *snippet (seq( . ( into a ne using a stable sort.( . + *notes ($he algorithm used is the merge sort.( . !

array

?'&;: sort) ith + *values + (seq( (a sequence( . + (quot( + *quotation (5 elt )) key 6( . . + (sortedseq( (a ne sorted sequence( . . + *description (Sorts the elements of ( + *snippet (seq( . ( by applying ( + *link compare . ( ith ( + *snippet (quot( . ( to each pair of elements in the

sequence.( . ! ?'&;: inv)sort) ith + *values + (seq( (a sequence( . + (quot( + *quotation (5 elt )) key 6( . . + (sortedseq( (a ne sorted sequence( . . + *description (Sorts the elements of ( + *snippet (seq( . ( by applying ( + *link compare . ( ith ( + *snippet (quot( . ( to each pair of elements in the sequence and inverting the results.( . ! ?'&;: sort)keys + *values + (obF( (an obFect( . + (sortedseq( (a ne sorted sequence( . . + *description (Sorts the elements of ( + *snippet (obF( . ( 5converting to an alist first if not a sequence6< comparing first elements of pairs using the ( + *link PHG . ( ord.( . ! ?'&;: sort)values + *values + (obF( (an obFect( . + (sortedseq( (a ne sorted sequence( . . + *description (Sorts the elements of ( + *snippet (obF( . ( 5converting to an alist first if not a sequence6< comparing second elements of pairs using the ( + *link PHG . ( ord.( . ! ?'&;: natural)sort + *values + (seq( (a sequence of real numbers( . + (sortedseq( (a ne sorted sequence( . . + *description (Sorts a sequence of obFects in natural order using the ( + *link PHG . ( ord.( . ! ?'&;: sort)pair + *values + (a( obFect . + (b( obFect . + (c( obFect . + (d( obFect . . + *description (If ( + *snippet (a( . ( is greater than ( + *snippet (b( . (< exchanges ( + *snippet (a( . ( ith ( + *snippet (b( . (.( . ! ?'&;: midpoint9 + *values + (seq( (a sequence( . + (n( integer . . + *description (Butputs the index of the midpoint of ( + *snippet (seq( . (.( . ! + PHG compare natural)sort sort) ith inv)sort) ith sort)keys sort)values . related) ords USING: generic help.markup help.syntax kernel math memory namespaces sequences kernel.private classes classes.builtin sequences.private ! IN: layouts ?'&;: tag)bits + *var)description (Number of least significant bits reserved for a type tag in a tagged pointer.( . + *see)also tag . ! ?'&;: tag)mask + *var)description ($aking the bit ise and of a tagged pointer leaves the tag.( . ! ith this mask

?'&;: num)types + *var)description (Number of distinct built)in types. $his is one more than the maximum value from the ( + *link tag . ( primitive.( . ! ?'&;: type)number + *values + (class( class . + (n( (an integer or ( + *link f . . . + *description (Butputs the built)in type number instances of ( + *link class . (. Jill output ( + *link f . ( if this is not a built)in class.( . + *see)also builtin)class . !

?'&;: tag)fixnum + *values + (n( integer . + (tagged( integer . . + *description (Butputs a tagged fixnum.( . ! ?'&;: fixnum)bits + *values + (n( (number of bits in a fixnum( . . ! ?'&;: first)bignum + *values + (n( (smallest positive integer not representable by a fixnum( . . ! ?'&;: most)positive)fixnum + *values + (n( (largest positive integer representable by a fixnum( . . ! ?'&;: most)negative)fixnum + *values + (n( (smallest negative integer representable by a fixnum( . . ! ?'&;: bootstrap)first)bignum + *values + (n( (smallest positive integer not representable by a fixnum( . . + *description (Butputs the value for the target architecture hen bootstrapping.( . ! ?'&;: bootstrap)most)positive)fixnum + *values + (n( (largest positive integer representable by a fixnum( . . + *description (Butputs the value for the target architecture hen bootstrapping.( . ! ?'&;: bootstrap)most)negative)fixnum + *values + (n( (smallest negative integer representable by a fixnum( . . + *description (Butputs the value for the target architecture hen bootstrapping.( . ! ?'&;: cell + *values + (n( (a positive integer( . . + *description (Butputs the pointer si8e in bytes of the current %;U architecture.( . ! ?'&;: cells + *values + (m( integer . + (n( integer . . + *description (%omputes the number of bytes used by ( + *snippet (m( . ( %;U operand)si8ed cells.( . ! ?'&;: cell)bits + *values + (n( integer . . + *description (Butputs the number of bits in one %;U operand)si8ed cell.( . ! ?'&;: bootstrap)cell + *values + (n( (a positive integer( . . + *description (Butputs the pointer si8e in bytes for the target image 5if bootstrapping6 or the current %;U architecture 5other ise6.( . ! ?'&;: bootstrap)cells + *values + (m( integer . + (n( integer . . + *description (%omputes the number of bytes used by ( + *snippet (m( . ( cells in the target image 5if bootstrapping6 or the current %;U architecture 5other ise6.( . ! ?'&;: bootstrap)cell)bits + *values + (n( integer . . + *description (Butputs the number of bits in one cell in the target image 5if bootstrapping6 or the current %;U architecture 5other ise6.( . !

"#$I%&': (layouts)types( ($ype numbers( (%orresponding to every built)in class is a built)in type number. "n obFect can be asked for its built)in type number:( + *subsections tag . (Euilt)in type numbers can be converted to classes< and vice versa:( + *subsections typeGclass type)number num)types . + *see)also (builtin)classes( . ! "#$I%&': (layouts)tags( ($agged pointers( ('very pointer stored on the stack or in the heap has a ( + *emphasis (tag( . (< hich is a small integer identifying the type of the pointer. If the tag is not equal to one of the t o special tags< the remaining bits contain the memory address of a heap)allocated obFect. $he t o special tags are the ( + *link fixnum . ( tag and the ( + *link f . ( tag.( *nl (Jords for orking ith tagged pointers:( + *subsections tag)bits tag)mask . ($he @actor VI does not actually expose any ords for orking ith tagged pointers directly. $he above ords operate on integers! they are used in the bootstrap image generator and the optimi8ing compiler.( ! "#$I%&': (layouts)limits( (Si8es and limits( (;rocessor cell si8e:( + *subsections cell cells cell)bits . (#ange of integers representable by ( + *link fixnum . (s:( + *subsections most)negative)fixnum most)positive)fixnum . (Iaximum array si8e:( + *subsections max)array)capacity . ! "#$I%&': (layouts)bootstrap( (Eootstrap support( (;rocessor cell si8e for the target architecture:( + *subsections bootstrap)cell bootstrap)cells bootstrap)cell)bits . (#ange of integers representable by ( + *link fixnum . (s of the target architecture:( + *subsections bootstrap)most)negative)fixnum bootstrap)most)positive)fixnum . (Iaximum array si8e for the target architecture:( + *subsections bootstrap)max)array)capacity . ! "#$I%&': (layouts( (VI memory layouts( ($he ords documented in this section do not ever need to be called by user code. $hey are documented for the benefit of those ishing to explore the

internals of @actor7s implementation.( + *subsections (layouts)types( (layouts)tags( (layouts)limits( (layouts)bootstrap( . ! "EBU$: (layouts( K %opyright 5%6 ,==R< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: assocs kernel kernel.private math math.order namespaces ! IN: layouts SNIEB&: data)alignment SNIEB&: tag)mask SNIEB&: tag)bits SNIEB&: num)types SNIEB&: type)numbers SNIEB&: mega)cache)si8e SNIEB&: header)bits : type)number 5 class )) n 6 type)numbers get at ! : tag)fixnum 5 n )) tagged 6 tag)bits get shift ! : tag)header 5 n )) tagged 6 header)bits get shift ! : untag)fixnum 5 n )) tagged 6 tag)bits get neg shift ! : hashcode)shift 5 )) n 6 tag)bits get header)bits get 2 ! K Je do this in its o n compilation unit so that they can be K folded belo PP : cell 5 )) n 6 BEX)%'&&)SIO' special)obFect ! foldable : 5fixnum)bits6 5 m )) n 6 tag)bits get ) ! foldable : 5first)bignum6 5 m )) n 6 5fixnum)bits6 1 ) ,T ! foldable GG : cells 5 m )) n 6 cell 4 ! inline : cell)bits 5 )) n 6 S cells ! inline : bootstrap)cell 5 )) n 6 > cell get cell or ! inline : bootstrap)cells 5 m )) n 6 bootstrap)cell 4 ! inline : bootstrap)cell)bits 5 )) n 6 S bootstrap)cells ! inline

: first)bignum 5 )) n 6 cell)bits 5first)bignum6 ! inline : fixnum)bits 5 )) n 6 cell)bits 5fixnum)bits6 ! inline : most)positive)fixnum 5 )) n 6 first)bignum 1 ) Gfixnum ! inline : most)negative)fixnum 5 )) n 6 first)bignum neg Gfixnum ! inline : 5max)array)capacity6 5 b )) n 6 L ) ,T 1 ) ! inline : max)array)capacity 5 )) n 6 cell)bits 5max)array)capacity6 ! inline : bootstrap)first)bignum 5 )) n 6 bootstrap)cell)bits 5first)bignum6 ! : bootstrap)most)positive)fixnum 5 )) n 6 bootstrap)first)bignum 1 ) ! : bootstrap)most)negative)fixnum 5 )) n 6 bootstrap)first)bignum neg ! : bootstrap)max)array)capacity 5 )) n 6 bootstrap)cell)bits 5max)array)capacity6 ! I: bignum Ginteger dup most)negative)fixnum most)positive)fixnum bet een: 0 Gfixnum 3 hen ! I: real Ginteger dup most)negative)fixnum most)positive)fixnum bet een: 0 Gfixnum 3 0 Gbignum 3 if ! inline UNIBN: immediate fixnum ;BS$;BN': f ! USING: layouts math tools.test ! IN: system.tests 0 t 3 0 cell integer: 3 unit)test 0 t 3 0 bootstrap)cell integer: 3 unit)test K Smoke test 0 t 3 0 max)array)capacity cell)bits ,T P 3 unit)test 0 t 3 0 most)negative)fixnum fixnum: 3 unit)test 0 t 3 0 most)positive)fixnum fixnum: 3 unit)test USING: strings arrays byte)arrays help.markup help.syntax kernel vectors ! IN: sbufs "#$I%&': (sbufs( (String buffers( ($he ( + *vocab)link (sbufs( . ( vocabulary implements resi8able mutable sequence of characters. $he literal syntax is covered in ( + *link (syntax)sbufs( . (.( *nl (String buffers implement the ( + *link (sequence)protocol( . ( and thus all ( + *link (sequences( . ( can be used ith them. String buffers can be used to

construct ne strings by accumulating substrings and characters< ho ever usually they are only used indirectly< since the sequence construction ords are more convenient to use in most cases 5see ( + *link (namespaces)make( . (6.( *nl (String buffers form a class of obFects:( + *subsections sbuf sbuf: . (Jords for creating string buffers:( + *subsections Gsbuf PsbufG . (If you don7t care about initial capacity< a more elegant ay to create a ne string buffer is to rite:( + *code (SEU@>( >( clone( . ! "EBU$: (sbufs( ?'&;: sbuf + *description ($he class of resi8able character strings. See ( + *link (syntax)sbufs( . ( for syntax and ( + *link (sbufs( . ( for general information.( . ! ?'&;: PsbufG + *values + (n( (a positive integer specifying initial capacity( . + (sbuf( sbuf . . + *description (%reates a ne string buffer that can hold ( + *snippet (n( . ( characters before resi8ing.( . ! ?'&;: Gsbuf + *values + (seq( (a sequence of non)negative integers( . + (sbuf( sbuf . . + *description (Butputs a freshly)allocated string buffer ith the same elements as a given sequence.( . + *errors ($hro s an error if the sequence contains elements other than real numbers.( . ! USING: classes kernel math namespaces sbufs sequences sequences.private strings tools.test ! IN: sbufs.tests 0 A 3 0 (?ello( Gsbuf length 3 unit)test 0 (?ello( 3 0 1== PsbufG (buf( set (?ello( (buf( get push)all (buf( get clone (buf)clone( set (Jorld( (buf)clone( get push)all (buf( get Gstring 3 unit)test 0 %?"#: h 3 0 = SEU@( hello orld( nth 3 unit)test 0 %?"#: ? 3 0 %?"#: ? = SEU@( hello orld( 0 set)nth 3 keep first 3 unit)test 0 SEU@( x( 3 0 1 PsbufG %?"#: x Gbignum over push 3 unit)test 0 fixnum 3 0 1 Gbignum SEU@( ( ne )sequence length class)of 3 unit)test 0 fixnum 3 0 1 Gbignum iota 0 3 SEU@( ( map)as length class)of 3 unit)test

0 1.A SEU@( ( ne )sequence 3 must)fail 0 %?"#: " =.A =.A SEU@( a( set)nth)unsafe 3 must)fail K %opyright 5%6 ,==/< ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors gro able kernel math sequences sequences.private strings strings.private ! IN: sbufs $U;&': sbuf + underlying string . + length array)capacity . ! : PsbufG 5 n )) sbuf 6 = PstringG = sbuf boa ! inline I: sbuf set)nth)unsafe 0 integerGfixnum 3 0 integerGfixnum 3 0 underlyingGG 3 tri4 set)string)nth ! inline I: sbuf ne )sequence drop 0 = PstringG 3 0 integerGfixnum 3 bi sbuf boa ! inline : Gsbuf 5 seq )) sbuf 6 SEU@( ( clone)like ! inline I: sbuf contract ,drop ! inline I: sbuf like drop dup sbuf: 0 dup string: 0 dup length sbuf boa 3 0 Gsbuf 3 if 3 unless ! inline I: sbuf equal: over sbuf: 0 sequenceH 3 0 ,drop f 3 if ! I: string ne )resi8able drop PsbufG ! inline I: sbuf ne )resi8able drop PsbufG ! inline I: string like ZK If e have a string< e7re done. ZK If e have an sbuf< and it7s at full capacity< e7re done. ZK Bther ise< call resi8e)string< hich is a relatively ZK fast primitive. drop dup string: 0 dup sbuf: 0 0 length 3 0 underlyingGG 3 bi ,dup length eq: 0 nip dup reset)string)hashcode 3 0 resi8e)string 3 if 3 0 Gstring 3 if 3 unless ! inline INS$"N%': sbuf gro able K %opyright 5%6 ,==/< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel.private slots.private math.private ! IN: kernel EUI&$IN: callstack ! EUI&$IN: tuple ! EUI&$IN: rapper + rapped read)only . ! C'@'#: dip

C'@'#: ,dip C'@'#: -dip K Stack stuff : ,over 5 x y 8 )) x y 8 x y 6 pick pick ! inline : clear 5 )) 6 + . set)datastack ! K %ombinators G'N'#I%: call 5 callable )) 6 G'N'#I%: execute 5 G'N'#I%: :execute 5 I: obFect :execute ! C'@'#: if : : 5 : true false )) trueQfalse 6 ZK 7if7 and 7:7 can be defined in terms of each other ZK because the XI$ special)cases an 7if7 preceeded by ZK t o literal quotations. rot 0 drop 3 0 nip 3 if ! inline : if 5 ..a : true: 5 ..a )) ..b 6 false: 5 ..a )) ..b 6 )) ..b 6 : call ! K Single branch : unless 5 ..a : false: 5 ..a )) ..a 6 )) ..a 6 s ap 0 drop 3 0 call 3 if ! inline : hen 5 ..a : true: 5 ..a )) ..a 6 )) ..a 6 s ap 0 call 3 0 drop 3 if ! inline ord )) 6 ord )) value 6

K "naphoric : if4 5 ..a : true: 5 ..a : )) ..b 6 false: 5 ..a )) ..b 6 )) ..b 6 pick 0 drop call 3 0 ,nip call 3 if ! inline : hen4 5 ..a : true: 5 ..a : )) ..a 6 )) ..a 6 over 0 call 3 0 ,drop 3 if ! inline

: unless4 5 ..a : false: 5 ..a )) ..a x 6 )) ..a x 6 over 0 drop 3 0 nip call 3 if ! inline K Cefault : :if 5 ..a default cond true: 5 ..a cond )) ..b 6 false: 5 ..a default )) ..b 6 )) ..b 6 pick 0 drop 0 drop 3 ,dip call 3 0 ,nip call 3 if ! inline K Cippers. K Not declared inline because the compiler special)cases them : dip 5 x quot )) x 6 s ap 0 call 3 dip ! : ,dip 5 x y quot )) x y 6 s ap 0 dip 3 dip ! : -dip 5 x y 8 quot )) x y 8 6 s ap 0 ,dip 3 dip ! : /dip 5 x y 8 quot )) x y 8 6 s ap 0 -dip 3 dip ! inline

K Yeepers : keep 5 ..a x quot: 5 ..a x )) ..b 6 )) ..b x 6

over 0 call 3 dip ! inline : ,keep 5 ..a x y quot: 5 ..a x y )) ..b 6 )) ..b x y 6 0 ,dup 3 dip ,dip ! inline : -keep 5 ..a x y 8 quot: 5 ..a x y 8 )) ..b 6 )) ..b x y 8 6 0 -dup 3 dip -dip ! inline : /keep 5 ..a x y 8 quot: 5 ..a 0 /dup 3 dip /dip ! inline K %leavers : bi 5 x p q )) 6 0 keep 3 dip call ! inline : tri 5 x p q r )) 6 0 0 keep 3 dip keep 3 dip call ! inline K Couble cleavers : ,bi 5 x y p q )) 6 0 ,keep 3 dip call ! inline : ,tri 5 x y p q r )) 6 0 0 ,keep 3 dip ,keep 3 dip call ! inline K $riple cleavers : -bi 5 x y 8 p q )) 6 0 -keep 3 dip call ! inline : -tri 5 x y 8 p q r )) 6 0 0 -keep 3 dip -keep 3 dip call ! inline K Spreaders : bi4 5 x y p q )) 6 0 dip 3 dip call ! inline : tri4 5 x y 8 p q r )) 6 0 0 ,dip 3 dip dip 3 dip call ! inline K Couble spreaders : ,bi4 5 x y 8 p q )) 6 0 ,dip 3 dip call ! inline : ,tri4 5 u v x y 8 p q r )) 6 0 /dip 3 ,dip ,bi4 ! inline K "ppliers : bi9 5 x y quot )) 6 dup bi4 ! inline : tri9 5 x y 8 quot )) 6 dup dup tri4 ! inline K Couble appliers : ,bi9 5 x y 8 quot )) 6 dup ,bi4 ! inline : ,tri9 5 u v x y 8 quot )) 6 dup dup ,tri4 ! inline K Duotation building : ,curry 5 obF1 obF, quot )) curry 6 x y 8 )) ..b 6 )) ..b x y 8 6

curry curry ! inline : -curry 5 obF1 obF, obF- quot )) curry 6 curry curry curry ! inline : ith 5 param obF quot )) obF curry 6 s apd 0 s apd call 3 ,curry ! inline

: prepose 5 quot1 quot, )) compose 6 s ap compose ! inline K %urried cleavers P;#IV"$' : 0curry3 5 quot )) quot7 6 0 curry 3 curry ! inline ;#IV"$'G : bi)curry 5 x p q )) p7 q7 6 0 0curry3 3 bi9 bi ! inline : tri)curry 5 x p q r )) p7 q7 r7 6 0 0curry3 3 tri9 tri ! inline : bi)curry4 5 x y p q )) p7 q7 6 0 0curry3 3 bi9 bi4 ! inline : tri)curry4 5 x y 8 p q r )) p7 q7 r7 6 0 0curry3 3 tri9 tri4 ! inline : bi)curry9 5 x y q )) p7 q7 6 0curry3 bi9 ! inline : tri)curry9 5 x y 8 q )) p7 q7 r7 6 0curry3 tri9 ! inline K Eooleans UNIBN: boolean ;BS$;BN': t ;BS$;BN': f ! : Gboolean 5 obF )) : 6 0 t 3 0 f 3 if ! inline : not 5 obF )) : 6 0 f 3 0 t 3 if ! inline : and 5 obF1 obF, )) : 6 over : ! inline : or 5 obF1 obF, )) : 6 dupd : ! inline : xor 5 obF1 obF, )) : 6 0 f s ap : 3 hen4 ! inline

: both: 5 x y quot )) : 6 bi9 and ! inline : either: 5 x y quot )) : 6 bi9 or ! inline : most 5 x y quot )) 8 6 ,keep : ! inline K &oops : loop 5 ... pred: 5 ... )) ... : 6 )) ... 6 0 call 3 keep 0 loop 3 curry hen ! inline recursive : do 5 pred body )) pred body 6 dup ,dip ! inline : hile 5 ..a pred: 5 ..a )) ..b : 6 body: 5 ..b )) ..a 6 )) ..b 6 s ap do compose 0 loop 3 curry hen ! inline

: until 5 ..a pred: 5 ..a )) ..b : 6 body: 5 ..b )) ..a 6 )) ..b 6 0 0 not 3 compose 3 dip hile ! inline

K BbFect protocol G'N'#I%: hashcode4 5 depth obF )) code 6 I: obFect hashcode4 ,drop = ! inline I: f hashcode4 ,drop -1--R ! inline : hashcode 5 obF )) code 6 - s ap hashcode4 ! inline : identity)hashcode 5 obF )) code 6 dup tag = eq: 0 dup tag 1 eq: 0 drop = 3 0 dup 5identity)hashcode6 dup = eq: 0 drop dup compute)identity)hashcode 5identity)hashcode6 3 0 nip 3 if 3 if 3 unless ! inline G'N'#I%: equal: 5 obF1 obF, )) : 6 I: obFect equal: ,drop f ! inline $U;&': identity)tuple ! I: identity)tuple equal: ,drop f ! inline I: identity)tuple hashcode4 nip identity)hashcode ! inline : H 5 obF1 obF, )) : 6 ,dup eq: 0 ,drop t 3 0 ,dup both)fixnums: 0 ,drop f 3 0 equal: 3 if 3 if ! inline : same: 5 x y quot )) : 6 bi9 H ! inline G'N'#I%: clone 5 obF )) cloned 6 I: obFect clone ! inline I: callstack clone 5clone6 ! inline K $uple construction G'N'#I%: ne 5 class )) tuple 6 G'N'#I%: boa 5 slots... class )) tuple 6 K 'rror handling )) defined early so that other files can K thro errors before continuations are loaded G'N'#I%: thro 5 error )) 4 6 '##B#: assert got expect ! : assertH 5 a b )) 6 ,dup H 0 ,drop 3 0 assert 3 if ! P;#IV"$' : declare 5 spec )) 6 drop ! : do)primitive 5 number )) 6 (Improper primitive call( thro K Special obFect count and identifiers must be kept in sync ! ith:

K K

vmQobFects.hpp basisQbootstrapQimageQimage.factor

%BNS$"N$: special)obFect)count S= %BNS$"N$: BEX)J"&Y'#)?BBY %BNS$"N$: BEX)%"&&%%)1 / %BNS$"N$: '##B#)?"NC&'#)DUB$ A %BNS$"N$: BEX)'##B# L %BNS$"N$: BEX)%'&&)SIO' R %BNS$"N$: BEX)%;U S %BNS$"N$: BEX)BS U %BNS$"N$: BEX)"#GS 1= %BNS$"N$: BEX)S$CIN 11 %BNS$"N$: BEX)S$CBU$ 1, %BNS$"N$: BEX)II"G' 1%BNS$"N$: BEX)'M'%U$"E&' 1/ %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: BEX)'IE'CC'C 1A BEX)'V"&)%"&&E"%Y 1L BEX)NI'&C)%"&&E"%Y 1R BEX)S&'';)%"&&E"%Y 1S

%BNS$"N$: BEX)S$"#$U;)DUB$ ,= %BNS$"N$: BEX)G&BE"& ,1 %BNS$"N$: BEX)S?U$CBJN)DUB$ ,, %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: XI$);#B&BG ,XI$);#III$IV')JB#C ,/ XI$);#III$IV' ,A XI$)JB#C)XUI; ,L XI$)JB#C)%"&& ,R XI$)I@)JB#C ,S XI$)I@ ,U XI$)S"@';BIN$ -= XI$)';I&BG -1 XI$)#'$U#N -, XI$);#B@I&ING -XI$);US?)III'CI"$' -/ XI$)CI;)JB#C -A XI$)CI; -L XI$),CI;)JB#C -R XI$),CI; -S XI$)-CI;)JB#C -U XI$)-CI; /= XI$)'M'%U$' /1 XI$)C'%&"#')JB#C /, %)$B)@"%$B#)JB#C /&"ON)XI$)%BI;I&')JB#C // UNJINC)N"$IV')@#"I'S)JB#C /A G'$)@;U)S$"$')JB#C /L S'$)@;U)S$"$')JB#C /R SIGN"&)?"NC&'#)JB#C /S &'"@)SIGN"&)?"NC&'#)JB#C /U @@I)SIGN"&)?"NC&'#)JB#C A= @@I)&'"@)SIGN"&)?"NC&'#)JB#C A1

%BNS$"N$: #'C'@INI$IBN)%BUN$'# A, %BNS$"N$: %"&&E"%Y)S$UE A%BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: ;I%)&B"C A/ ;I%)$"G AA ;I%)$U;&' AL ;I%)%?'%Y)$"G AR ;I%)%?'%Y)$U;&' AS ;I%)?I$ AU ;I%)IISS)JB#C L= ;I%)IISS)$"I&)JB#C L1

%BNS$"N$: I'G")&BBYU; L, %BNS$"N$: I'G")&BBYU;)JB#C L%BNS$"N$: I'G")IISS)JB#C L/ %BNS$"N$: BEX)UNC'@IN'C LA %BNS$"N$: BEX)S$C'## LL %BNS$"N$: BEX)S$"G', LR %BNS$"N$: BEX)%U##'N$)$?#'"C LS %BNS$"N$: BEX)$?#'"CS LU %BNS$"N$: BEX)#UN)DU'U' R= %BNS$"N$: BEX)S&'';)DU'U' R1 %BNS$"N$: BEX)VI)%BI;I&'# R, %BNS$"N$: BEX)J"I$ING)%"&&E"%YS R%BNS$"N$: BEX)SIGN"&);I;' R/ K %ontext obFect count and identifiers must be kept in sync K vmQcontexts.hpp %BNS$"N$: context)obFect)count 1= %BNS$"N$: %BNS$"N$: %BNS$"N$: %BNS$"N$: %BN$'M$)BEX)N"I'S$"%Y = %BN$'M$)BEX)%"$%?S$"%Y 1 %BN$'M$)BEX)%BN$'M$ , %BN$'M$)BEX)IN)%"&&E"%Y); ith:

;#IV"$'G USING: generic help.markup help.syntax math memory namespaces sequences kernel.private layouts classes vectors combinators quotations strings ords assocs arrays math.order ! IN: kernel ?'&;: eq: + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *description ($ests if t o references point at the same obFect.( . ! ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: drop ,drop -drop /drop dup *shuffle *shuffle *shuffle *shuffle *shuffle ! ! ! ! !

?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;: ?'&;:

,dup -dup /dup nip ,nip over ,over pick s ap rot )rot dupd s apd

*shuffle *shuffle *shuffle *shuffle *shuffle *shuffle *shuffle *shuffle *shuffle

! ! ! ! ! ! ! ! ! ! ! ! !

*complex)shuffle *complex)shuffle *complex)shuffle *complex)shuffle

?'&;: datastack + *values + (array( array . . + *description (Butputs an array containing a copy of the data stack contents right before the call to this ord< ith the top of the stack at the end of the array.( . ! ?'&;: set)datastack + *values + (array( array . . + *description (#eplaces the data stack contents ith a copy of an array. $he end of the array becomes the top of the stack.( . ! ?'&;: retainstack + *values + (array( array . . + *description (Butputs an array containing a copy of the retain stack contents right before the call to this ord< ith the top of the stack at the end of the array.( . ! ?'&;: set)retainstack + *values + (array( array . . + *description (#eplaces the retain stack contents ith a copy of an array. $he end of the array becomes the top of the stack.( . ! ?'&;: callstack + *values + (callstack( callstack . . + *description (Butputs a copy of the call stack contents< ith the top of the stack at the end of the vector. $he stack frame of the caller ord is ( + *emphasis (not( . ( included.( . ! ?'&;: set)callstack + *values + (callstack( callstack . . + *description (#eplaces the call stack contents. %ontrol flo is transferred immediately to the innermost frame of the ne call stack.( . ! ?'&;: clear + *description (%lears the data stack.( . ! ?'&;: build + *values + (n( integer . . + *description ($he current build number. @actor increments this number a ne boot image is created.( . !

henever

?'&;: hashcode4 + *values + (depth( integer . + (obF( obFect . + (code( fixnum . . + *contract (Butputs the hashcode of an obFect. $he hashcode operation must satisfy the follo ing properties:( + *list + (If t o obFects are equal under ( + *link H . (< they must have equal

hashcodes.( . + (If the hashcode of an obFect depends on the values of its slots< the hashcode of the slots must be computed recursively by calling ( + *link hashcode4 . ( ith a ( + *snippet (level( . ( parameter decremented by one. $his avoids excessive ork hile still computing ell)distributed hashcodes. $he ( + *link recursive)hashcode . ( combinator can help ith implementing this logic<( . + ($he hashcode should be a ( + *link fixnum . (< ho ever returning a ( + *link bignum . ( ill not cause any problems other than potential performance degradation.( . + ($he hashcode is only permitted to change bet een t o invocations if the obFect or one of its slot values as mutated.( . . (If mutable obFects are used as hashtable keys< they must not be mutated in such a ay that their hashcode changes. Coing so ill violate bucket sorting invariants and result in undefined behavior. See ( + *link (hashtables.keys( . ( for details.( . ! ?'&;: hashcode + *values + (obF( obFect . + (code( fixnum . . + *description (%omputes the hashcode of an obFect ith a default hashing depth. See ( + *link hashcode4 . ( for the hashcode contract.( . ! ?'&;: identity)hashcode + *values + (obF( obFect . + (code( fixnum . . + *description (Butputs the identity hashcode of an obFect. $he identity hashcode is not guaranteed to be unique< ho ever it ill not change during the obFect7s lifetime.( . ! + hashcode hashcode4 identity)hashcode . related) ords ?'&;: H + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *description ($ests if t o obFects are equal. If ( + *snippet (obF1( . ( and ( + *snippet (obF,( . ( point to the same obFect< outputs ( + *link t . (. Bther ise< calls the ( + *link equal: . ( generic ord.( . + *examples + *example (USING: kernel prettyprint !( (A A H .( (t( . + *example (USING: kernel prettyprint !( (A ==A H .( (t( . + *example (USING: kernel prettyprint !( (A A.= H .( (f( . + *example (USING: arrays kernel prettyprint !( (+ >(a>( >(b>( . >(a>( >(b>( ,array H .( (t( . + *example (USING: arrays kernel prettyprint !( (+ >(a>( >(b>( . 0 >(a>( >(b>( 3 H .( (f( . . ! ?'&;: equal: + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *contract ($ests if t o obFects are equal.( *nl (User code should call ( + *link H . ( instead! that ord first tests the case here the obFects are ( + *link eq: . (< and so by extension< methods defined on ( + *link equal: . ( assume they are never called on ( + *link eq: . ( obFects.( *nl (Iethod definitions should ensure that this is an equality relation< modulo the assumption that the t o obFects are not ( + *link eq: . (. $hat is< for any three non)( + *link eq: . ( obFects ( + *snippet (a( . (< ( + *snippet (b( . ( and ( + *snippet (c( . (< e must have:(

+ *list + + *snippet (a H b( . ( implies ( + *snippet (b H a( . . + + *snippet (a H b( . ( and ( + *snippet (b H c( . ( implies ( + *snippet (a H c( . . . (If a class defines a custom equality comparison test< it should also define a compatible method for the ( + *link hashcode4 . ( generic ord.( . + *examples ("n example demonstrating hy this ord should only be used to define methods on< and never called directly:( + *example (USING: kernel prettyprint !( (A A equal: .( (f( . (Using ( + *link H . ( gives the expected behavior:( + *example (USING: kernel prettyprint !( (A A H .( (t( . . ! ?'&;: identity)tuple + *class)description (" class defining an ( + *link equal: . ( method hich al ays returns f.( . + *examples ($o define a tuple class such that t o instances are only equal if they are both the same instance< inherit from the ( + *link identity)tuple . ( class. $his class defines a method on ( + *link equal: . ( hich al ays returns ( + *link f . (. Since ( + *link H . ( handles the case here the t o obFects are ( + *link eq: . (< this method ill never be called ith t o ( + *link eq: . ( obFects< so such a definition is valid:( + *code ($U;&': foo P identity)tuple !( . (Ey calling ( + *link H . ( on instances of ( + *snippet (foo( . ( e get the results e expect:( + *unchecked)example ($+ foo . dup H .( (t( . + *unchecked)example ($+ foo . dup clone H .( (f( . . ! ?'&;: clone + *values + (obF( obFect . + (cloned( (a ne obFect( . . + *contract (Butputs a ne obFect equal to the given obFect. $his is not guaranteed to actually copy the obFect! it does nothing ith immutable obFects< and does not copy ords either. ?o ever< sequences and tuples can be cloned to obtain a shallo copy of the original.( . ! ?'&;: : + *values + (:( (a generali8ed boolean( . + (true( obFect . + (false( obFect . + (trueQfalse( (one t o input obFects( . . + *description (%hooses bet een t o values depending on the boolean value of ( + *snippet (cond( . (.( . ! ?'&;: boolean + *class)description (" union of the ( + *link ;BS$;BN': t . ( and ( + *link ;BS$;BN': f . ( classes.( . ! ?'&;: Gboolean + *values + (obF( (a generali8ed boolean( . + (:( (a boolean( . . + *description (%onvert a generali8ed boolean into a boolean. $hat is< ( + *link f . ( retains its value< hereas anything else becomes ( + *link t . (.( . ! ?'&;: not + *values + (obF( (a generali8ed boolean( . + (:( (a boolean( . . + *description (@or ( + *link f . ( outputs ( + *link t . ( and for anything else outputs ( + *link f . (.( . + *notes ($his ord implements boolean not< so applying it to integers ill not yield useful results 5all integers have a true value6. Eit ise not is the ( + *link bitnot . ( ord.( . !

?'&;: and + *values + (obF1( (a generali8ed boolean( . + (obF,( (a generali8ed boolean( . + (:( (a generali8ed boolean( . . + *description (If both inputs are true< outputs ( + *snippet (obF,( . (. other ise outputs ( + *link f . (.( . + *notes ($his ord implements boolean and< so applying it to integers ill not yield useful results 5all integers have a true value6. Eit ise and is the ( + *link bitand . ( ord.( . + *examples (Usually only the boolean value of the result is used< ho ever you can also explicitly rely on the behavior that if both inputs are true< the second is output:( + *example (USING: kernel prettyprint !( (t f and .( (f( . + *example (USING: kernel prettyprint !( (t R and .( (R( . + *example (USING: kernel prettyprint !( (>(hi>( 1,.= and .( (1,.=( . . ! ?'&;: or + *values + (obF1( (a generali8ed boolean( . + (obF,( (a generali8ed boolean( . + (:( (a generali8ed boolean( . . + *description (If both inputs are false< outputs ( + *link f . (. other ise outputs the first of ( + *snippet (obF1( . ( and ( + *snippet (obF,( . ( hich is true.( . + *notes ($his ord implements boolean inclusive or< so applying it to integers ill not yield useful results 5all integers have a true value6. Eit ise inclusive or is the ( + *link bitor . ( ord.( . + *examples (Usually only the boolean value of the result is used< ho ever you can also explicitly rely on the behavior that the result ill be the first true input:( + *example (USING: kernel prettyprint !( (t f or .( (t( . + *example (USING: kernel prettyprint !( (>(hi>( 1,.= or .( (>(hi>(( . . ! ?'&;: xor + *values + (obF1( (a generali8ed boolean( . + (obF,( (a generali8ed boolean( . + (:( (a generali8ed boolean( . . + *description (If exactly one input is false< outputs the other input. Bther ise outputs ( + *link f . (.( . + *notes ($his ord implements boolean exclusive or< so applying it to integers ill not yield useful results 5all integers have a true value6. Eit ise exclusive or is the ( + *link bitxor . ( ord.( . ! ?'&;: both: + *values + (x( obFect . + (y( obFect . + (quot( + *quotation (5 ... obF )) ... : 6( . . + (:( (a boolean( . . + *description ($ests if the quotation yields a true value hen applied to both ( + *snippet (x( . ( and ( + *snippet (y( . (.( . + *examples + *example (USING: kernel math prettyprint !( (- A 0 odd: 3 both: .( (t( . + *example (USING: kernel math prettyprint !( (1, R 0 even: 3 both: .( (f( . . ! ?'&;: either: + *values + (x( obFect . + (y( obFect . + (quot( + *quotation (5 ... obF )) ... : 6( . . + (:( (a boolean( . . + *description ($ests if the quotation yields a true value hen applied to either ( + *snippet (x( . ( or ( + *snippet (y( . (.( . + *examples + *example (USING: kernel math prettyprint !( (- L 0 odd: 3 either: .( (t( . + *example (USING: kernel math prettyprint !( (A R 0 even: 3 either: .( (f( .

. ! ?'&;: same: + *values + (x( obFect . + (y( obFect . + (quot( + *quotation (5 ... obF )) ... obF7 6( . . + (:( (a boolean( . . + *description ("pplies the quotation to both ( + *snippet (x( . ( and ( + *snippet (y( . (< and then checks if the results are equal.( . + *examples + *example (USING: kernel math prettyprint !( (/ A 0 ,Q 3 same: .( (t( . + *example (USING: kernel math prettyprint !( (- R 0 sq 3 same: .( (f( . . ! ?'&;: execute + *values + ( ord( ord . . + *description ('xecutes a ord. Jords hich ( + *link execute . ( an input parameter must be declared ( + *link ;BS$;BN': inline . ( so that a caller hich passes in a literal ord can have a static stack effect.( . + *examples + *example (USING: kernel io ords !( (IN: scratchpad( (: t ice 5 ord )) 6 dup execute execute ! inline>n: hello 5 )) 6 >(?ello>( print !>n>> hello t ice( (?ello>n?ello( . . ! + execute ;BS$;BN': execute5 . related) ords ?'&;: 5execute6 + *values + ( ord( ord . . + *description ('xecutes a ord ithout checking if it is a ord first.( . + * arning ($his ord is in the ( + *vocab)link (kernel.private( . ( vocabulary because it is unsafe. %alling ith a parameter that is not a ord ill crash @actor. Use ( + *link execute . ( instead.( . ! ?'&;: call + *values + (callable( callable . . + *description (%alls a quotation. Jords hich ( + *link call . ( an input parameter must be declared ( + *link ;BS$;BN': inline . ( so that a caller passes in a literal quotation can have a static stack effect.( . + *examples ($he follo ing t o lines are equivalent:( + *code (, 0 , 2 - 4 3 call( (, , 2 - 4( . . ! + call ;BS$;BN': call5 . related) ords ?'&;: keep + *values + (x( obFect . + (quot( + *quotation (5 ..a x )) ..b 6( . . . + *description (%all a quotation ith a value on the stack< restoring the value hen the quotation returns.( . + *examples + *example (USING: arrays kernel prettyprint !( (, >(greetings>( 0 ParrayG 3 keep ,array .( (+ + >(greetings>( >(greetings>( . >(greetings>( .( . . ! ?'&;: ,keep + *values + (x( obFect . + (y( obFect . + (quot( + *quotation (5 ..a x y )) ..b 6( . . . + *description (%all a quotation ith t o values on the stack< restoring the values hen the quotation returns.( . ! ?'&;: -keep + *values + (x( obFect . + (y( obFect . + (8( obFect . + (quot( + *quotation (5 ..a x y 8 )) ..b 6( . . .

hich

+ *description (%all a quotation ith three values on the stack< restoring the values hen the quotation returns.( . ! ?'&;: bi + *values + (x( obFect . + (p( + *quotation (5 ..a x )) ..b 6( . . + (q( + *quotation (5 ..c x )) ..d 6( . . . + *description ("pplies ( + *snippet (p( . ( to ( + *snippet (x( . (< then applies ( + *snippet (q( . ( to ( + *snippet (x( . (.( . + *examples (If ( + *snippet (0 p 3( . ( and ( + *snippet (0 q 3( . ( have stack effect ( + *snippet (5 x )) 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 bi( (dup p q( . (If ( + *snippet (0 p 3( . ( and ( + *snippet (0 q 3( . ( have stack effect ( + *snippet (5 x )) y 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 bi( (dup p s ap q( . (In general< the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 bi( (0 p 3 keep q( . . ! ?'&;: ,bi + *values + (x( obFect . + (y( obFect . + (p( + *quotation (5 x y )) ... 6( . . + (q( + *quotation (5 x y )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to the t o input values< then applies ( + *snippet (q( . ( to the t o input values.( . + *examples (If ( + *snippet (0 p 3( . ( and ( + *snippet (0 q 3( . ( have stack effect ( + *snippet (5 x y )) 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 ,bi( (,dup p q( . (If ( + *snippet (0 p 3( . ( and ( + *snippet (0 q 3( . ( have stack effect ( + *snippet (5 x y )) 8 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 ,bi( (,dup p )rot q( . (In general< the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 ,bi( (0 p 3 ,keep q( . . ! ?'&;: -bi + *values + (x( obFect . + (y( obFect . + (8( obFect . + (p( + *quotation (5 x y 8 )) ... 6( . . + (q( + *quotation (5 x y 8 )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to the three input values< then applies ( + *snippet (q( . ( to the three input values.( . + *examples (If ( + *snippet (0 p 3( . ( and ( + *snippet (0 q 3( . ( have stack effect ( + *snippet (5 x y 8 )) 6( . (< then the follo ing t o lines are equivalent:(

+ *code (0 p 3 0 q 3 (-dup p q( . (In general< the + *code (0 p 3 0 q 3 (0 p 3 -keep . . !

-bi( follo ing t o lines are equivalent:( -bi( q(

?'&;: tri + *values + (x( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 x )) ... 6( . . + (r( + *quotation (5 x )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to ( + *snippet (x( . (< then applies ( + *snippet (q( . ( to ( + *snippet (x( . (< and finally applies ( + *snippet (r( . ( to ( + *snippet (x( . (.( . + *examples (If ( + *snippet (0 p 3( . (< ( + *snippet (0 q 3( . ( and ( + *snippet (0 r 3( . ( have stack effect ( + *snippet (5 x )) 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 tri( (dup p dup q r( . (If ( + *snippet (0 p 3( . (< ( + *snippet (0 q 3( . ( and ( + *snippet (0 r 3( . ( have stack effect ( + *snippet (5 x )) y 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 tri( (dup p over q rot r( . (In general< the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 tri( (0 p 3 keep 0 q 3 keep r( . . ! ?'&;: ,tri + *values + (x( obFect . + (y( obFect . + (p( + *quotation (5 x y )) ... 6( . . + (q( + *quotation (5 x y )) ... 6( . . + (r( + *quotation (5 x y )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to the t o input values< then applies ( + *snippet (q( . ( to the t o input values< and finally applies ( + *snippet (r( . ( to the t o input values.( . + *examples (If ( + *snippet (0 p 3( . (< ( + *snippet (0 q 3( . ( and ( + *snippet (0 r 3( . ( have stack effect ( + *snippet (5 x y )) 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 ,tri( (,dup p ,dup q r( . (In general< the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 ,tri( (0 p 3 ,keep 0 q 3 ,keep r( . . ! ?'&;: -tri

+ *values + (x( obFect . + (y( obFect . + (8( obFect . + (p( + *quotation (5 x y 8 )) ... 6( . . + (q( + *quotation (5 x y 8 )) ... 6( . . + (r( + *quotation (5 x y 8 )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to the three input values< then applies ( + *snippet (q( . ( to the three input values< and finally applies ( + *snippet (r( . ( to the three input values.( . + *examples (If ( + *snippet (0 p 3( . (< ( + *snippet (0 q 3( . ( and ( + *snippet (0 r 3( . ( have stack effect ( + *snippet (5 x y 8 )) 6( . (< then the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 -tri( (-dup p -dup q r( . (In general< the follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 -tri( (0 p 3 -keep 0 q 3 -keep r( . . ! ?'&;: bi4 + *values + (x( obFect . + (y( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 y )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to ( + *snippet (x( . (< then applies ( + *snippet (q( . ( to ( + *snippet (y( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 bi4( (0 p 3 dip q( . . ! ?'&;: ,bi4 + *values + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 y 8 )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to ( + *snippet ( ( . ( and ( + *snippet (x( . (< then applies ( + *snippet (q( . ( to ( + *snippet (y( . ( and ( + *snippet (8( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 ,bi4( (0 p 3 ,dip q( . . ! ?'&;: ,tri4 + *values + (u( obFect . + (v( obFect . + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (p( + *quotation (5 u v )) ... 6( . . + (q( + *quotation (5 x )) ... 6( . . + (r( + *quotation (5 y 8 )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to ( + *snippet (u( . ( and ( + *snippet (v( . (< then applies ( + *snippet (q( . ( to ( + *snippet ( ( . ( and ( + *snippet (x( . (< and finally applies ( + *snippet (r( . ( to ( + *snippet (y( . ( and ( + *snippet (8( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 ,tri4( (0 0 p 3 ,dip q 3 ,dip r(

. . ! ?'&;: tri4 + *values + (x( obFect . + (y( obFect . + (8( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 y )) ... 6( . . + (r( + *quotation (5 8 )) ... 6( . . . + *description ("pplies ( + *snippet (p( . ( to ( + *snippet (x( . (< then applies ( + *snippet (q( . ( to ( + *snippet (y( . (< and finally applies ( + *snippet (r( . ( to ( + *snippet (8( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 tri4( (0 0 p 3 dip q 3 dip r( . . ! ?'&;: bi9 + *values + (x( obFect . + (y( obFect . + (quot( + *quotation (5 obF )) ... 6( . . . + *description ("pplies the quotation to ( + *snippet (x( . (< then to ( + *snippet (y( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 bi9( (0 p 3 dip p( . ($he follo ing t o lines are also equivalent:( + *code (0 p 3 bi9( (0 p 3 0 p 3 bi4( . . ! ?'&;: ,bi9 + *values + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (quot( + *quotation (5 obF1 obF, )) ... 6( . . . + *description ("pplies the quotation to ( + *snippet ( ( . ( and ( + *snippet (x( . (< then to ( + *snippet (y( . ( and ( + *snippet (8( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 ,bi9( (0 p 3 ,dip p( . ($he follo ing t o lines are also equivalent:( + *code (0 p 3 ,bi9( (0 p 3 0 p 3 ,bi4( . . ! ?'&;: tri9 + *values + (x( obFect . + (y( obFect . + (8( obFect . + (quot( + *quotation (5 obF )) ... 6( . . . + *description ("pplies the quotation to ( + *snippet (x( . (< then to ( + *snippet (y( . (< and finally to ( + *snippet (8( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code

. !

. ($he follo ing t o lines are also equivalent:( + *code (0 p 3 tri9( (0 p 3 0 p 3 0 p 3 tri4( .

(0 p 3 tri9( (0 0 p 3 dip p 3 dip p(

?'&;: ,tri9 + *values + (u( obFect . + (v( obFect . + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (quot( + *quotation (5 obF1 obF, )) ... 6( . . . + *description ("pplies the quotation to ( + *snippet (u( . ( and ( + *snippet (v( . (< then to ( + *snippet ( ( . ( and ( + *snippet (x( . (< and then to ( + *snippet (y( . ( and ( + *snippet (8( . (.( . + *examples ($he follo ing t o lines are equivalent:( + *code (0 p 3 ,tri9( (0 0 p 3 ,dip p 3 ,dip p( . ($he follo ing t o lines are also equivalent:( + *code (0 p 3 ,tri9( (0 p 3 0 p 3 0 p 3 ,tri4( . . ! ?'&;: bi)curry + *values + (x( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 x )) ... 6( . . + (p7( + *snippet (0 x p 3( . . + (q7( + *snippet (0 x q 3( . . . + *description (;artially applies ( + *snippet (p( . ( and ( + *snippet (q( . ( to ( + *snippet (x( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 bi)curry 0 call 3 bi9( (0 p 3 0 q 3 bi( . (?igher)arity variants of ( + *link bi . ( can be built from ( + *link bi)curry . (:( + *code (0 p 3 0 q 3 bi)curry bi HH 0 p 3 0 q 3 ,bi( (0 p 3 0 q 3 bi)curry bi)curry bi HH 0 p 3 0 q 3 -bi( . ($he combination ( + *snippet (bi)curry bi4( . ( cannot be expressed ith the non)currying dataflo combinators alone! it is equivalent to a stack shuffle preceding ( + *link ,bi4 . (:( + *code (0 p 3 0 q 3 bi)curry bi4( (0 s ap 3 keep 0 p 3 0 q 3 ,bi4( . ($o put it another ay< ( + *snippet (bi)curry bi4( . ( handles the case here you have three values ( + *snippet (a b c( . ( on the stack< and you ish to apply ( + *snippet (p( . ( to ( + *snippet (a c( . ( and ( + *snippet (q( . ( to ( + *snippet (b c( . (.( . ! ?'&;: tri)curry + *values

+ + + + + + +

(x( obFect . (p( + *quotation (5 x )) ... 6( . . (q( + *quotation (5 x )) ... 6( . . (r( + *quotation (5 x )) ... 6( . . (p7( + *snippet (0 x p 3( . . (q7( + *snippet (0 x q 3( . . (r7( + *snippet (0 x r 3( . .

. + *description (;artially applies ( + *snippet (p( . (< ( + *snippet (q( . ( and ( + *snippet (r( . ( to ( + *snippet (x( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 tri)curry 0 call 3 tri9( (0 p 3 0 q 3 0 r 3 tri( . (?igher)arity variants of ( + *link tri . ( can be built from ( + *link tri)curry . (:( + *code (0 p 3 0 q 3 0 r 3 tri)curry tri HH 0 p 3 0 q 3 0 r 3 ,tri( (0 p 3 0 q 3 0 r 3 tri)curry tri)curry bi HH 0 p 3 0 q 3 0 r 3 -tri( . ($he combination ( + *snippet (tri)curry tri4( . ( cannot be expressed ith the non)currying dataflo combinators alone! it handles the case here you have four values ( + *snippet (a b c d( . ( on the stack< and you ish to apply ( + *snippet (p( . ( to ( + *snippet (a d( . (< ( + *snippet (q( . ( to ( + *snippet (b d( . ( and ( + *snippet (r( . ( to ( + *snippet (c d( . (.( . ! ?'&;: bi)curry4 + *values + (x( obFect . + (y( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 y )) ... 6( . . + (p7( + *snippet (0 x p 3( . . + (q7( + *snippet (0 y q 3( . . . + *description (;artially applies ( + *snippet (p( . ( to ( + *snippet (x( . (< and ( + *snippet (q( . ( to ( + *snippet (y( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 bi)curry4 0 call 3 bi9( (0 p 3 0 q 3 bi4( . ($he combination ( + *snippet (bi)curry4 bi( . ( is equivalent to a stack shuffle preceding ( + *link ,bi4 . (:( + *code (0 p 3 0 q 3 bi)curry4 bi( (0 over 3 dip 0 p 3 0 q 3 ,bi4( . (In other ords< ( + *snippet (bi)curry4 bi( . ( handles the case here you have the three values ( + *snippet (a b c( . ( on the stack< and you ish to apply ( + *snippet (p( . ( to ( + *snippet (a b( . ( and ( + *snippet (q( . ( to ( + *snippet (a c( . (.( *nl ($he combination ( + *snippet (bi)curry4 bi4( . ( is equivalent to a stack shuffle preceding ( + *link ,bi4 . (:( + *code (0 p 3 0 q 3 bi)curry4 bi4( (0 s ap 3 dip 0 p 3 0 q 3 ,bi4( . (In other ords< ( + *snippet (bi)curry4 bi4( . ( handles the case here you have the four values ( + *snippet (a b c d( . ( on the stack< and you ish to apply ( + *snippet (p( . ( to ( + *snippet (a c( . ( and ( + *snippet (q( . ( to ( + *snippet (b d( . (.(

. ! ?'&;: tri)curry4 + *values + (x( obFect . + (y( obFect . + (8( obFect . + (p( + *quotation (5 x )) ... 6( . . + (q( + *quotation (5 y )) ... 6( . . + (r( + *quotation (5 8 )) ... 6( . . + (p7( + *snippet (0 x p 3( . . + (q7( + *snippet (0 y q 3( . . + (r7( + *snippet (0 8 r 3( . . . + *description (;artially applies ( + *snippet (p( . ( to ( + *snippet (x( . (< ( + *snippet (q( . ( to ( + *snippet (y( . ( and ( + *snippet (r( . ( to ( + *snippet (8( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (0 p 3 0 q 3 0 r 3 tri)curry4 0 call 3 tri9( (0 p 3 0 q 3 0 r 3 tri4( . ($he combination ( + *snippet (tri)curry4 tri( . ( is equivalent to a stack shuffle preceding ( + *link ,tri4 . (:( + *code (0 p 3 0 q 3 0 r 3 tri)curry4 tri( (0 0 over 3 dip over 3 dip 0 p 3 0 q 3 0 r 3 ,tri4( . . ! ?'&;: bi)curry9 + *values + (x( obFect . + (y( obFect . + (q( + *quotation (5 obF )) ... 6( . . + (p7( + *snippet (0 x q 3( . . + (q7( + *snippet (0 y q 3( . . . + *description (;artially applies ( + *snippet (q( . ( to ( + *snippet (x( . ( and ( + *snippet (y( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (0 q 3 bi)curry9( (0 q 3 0 q 3 bi)curry4( . . ! ?'&;: tri)curry9 + *values + (x( obFect . + (y( obFect . + (8( obFect . + (q( + *quotation (5 obF )) ... 6( . . + (p7( + *snippet (0 x q 3( . . + (q7( + *snippet (0 y q 3( . . + (r7( + *snippet (0 8 q 3( . . . + *description (;artially applies ( + *snippet (q( . ( to ( + *snippet (x( . (< ( + *snippet (y( . ( and ( + *snippet (8( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (0 q 3 tri)curry9( (0 q 3 0 q 3 0 q 3 tri)curry4( .

. ! ?'&;: if + *values + (:( (a generali8ed boolean( . + (true( quotation . + (false( quotation . . + *description (If ( + *snippet (cond( . ( is ( + *link f . (< calls the ( + *snippet (false( . ( quotation. Bther ise calls the ( + *snippet (true( . ( quotation.( *nl ($he ( + *snippet (cond( . ( value is removed from the stack before either quotation is called.( . + *examples + *example (USING: io kernel math !( (1= - P 0 >(Iath is broken>( print 3 0 >(Iath is good>( print 3 if( (Iath is good( . . + *notes + *snippet (if( . ( is executed as a primitive hen preceded by t o literal quotations. $he belo definition is not executed unless one of its arguments is a non)literal quotation< such as a quotation constructed ith ( + *link curry . ( or ( + *link compose . (< or for ( + *link (fry( . ( or quotations including ( + *link (locals( . (.( . ! ?'&;: hen + *values + (:( (a generali8ed boolean( . + (true( quotation . . + *description (If ( + *snippet (cond( . ( is not ( + *link f . (< calls the ( + *snippet (true( . ( quotation.( *nl ($he ( + *snippet (cond( . ( value is removed from the stack before the quotation is called.( . + *examples + *example (USING: kernel math prettyprint !( ()A dup = P 0 - 2 3 hen .( (),( . . ! ?'&;: unless + *values + (:( (a generali8ed boolean( . + (false( quotation . . + *description (If ( + *snippet (cond( . ( is ( + *link f . (< calls the ( + *snippet (false( . ( quotation.( *nl ($he ( + *snippet (cond( . ( value is removed from the stack before the quotation is called.( . + *examples + *example (USING: kernel math prettyprint sequences !( (IN: scratchpad( (( (%BNS$"N$: american)cities +( ( >(San @rancisco>(( ( >(&os "ngeles>(( ( >(Ne Nork>(( (.( (( (: add)tax 5 price city )) price7 6( ( american)cities member: 0 1.1 4 3 unless !( (( (1,- >(Btta a>( add)tax .( (1-A.-(

. . ! ?'&;: if4 + *values + (:( (a generali8ed boolean( . + (true( + *quotation (5 ..a : )) ..b 6( . . + (false( + *quotation (5 ..a )) ..b 6( . . . + *description ("lternative conditional form that preserves the ( + *snippet (cond( . ( value if it is true.( *nl (If the condition is true< it is retained on the stack before the ( + *snippet (true( . ( quotation is called. Bther ise< the condition is removed from the stack and the ( + *snippet (false( . ( quotation is called.( *nl ($he follo ing t o lines are equivalent:( + *code (M 0 N 3 0 O 3 if4( (M dup 0 N 3 0 drop O 3 if( . . + *examples (Notice ho in this example< the same value is tested by the conditional< and then used in the true branch! the false branch does not need to drop the value because of ho ( + *link if4 . ( orks:( + *example (USING: assocs io kernel math.parser !( (IN: scratchpad( (( (: curry)price 5 meat )) price 6 + + >(Eeef>( 1= . + >(%hicken>( 1, . + >(&amb>( 1- . . at ! : order)curry 5 meat )) 6 curry)price 0 >(Nour order ill be >( rite numberGstring rite >( dollars.>( rite 3 0 >(Invalid order.>( print 3 if4 !( (( (>(Ceer>( order)curry( (Invalid order.( . . ! ?'&;: hen4 + *values + (:( (a generali8ed boolean( . + (true( + *quotation (5 ..a : )) ..a 6( . . . + *description (Variant of ( + *link if4 . ( ith no false quotation.( *nl ($he follo ing t o lines are equivalent:( + *code (M 0 N 3 hen4( (M dup 0 N 3 0 drop 3 if( . . ! ?'&;: unless4 + *values + (:( (a generali8ed boolean( . + (false( + *quotation (5 ..a )) ..a x 6( . . + (x( obFect . . + *description (Variant of ( + *link if4 . ( ith no true quotation.( . + *notes ($he follo ing t o lines are equivalent:( + *code (M 0 N 3 unless4( (M dup 0 3 0 drop N 3 if( . . ! ?'&;: :if + *values + (default( obFect . + (cond( (a generali8ed boolean( . + (true( + *quotation (5 ..a cond )) ..b 6( . . + (false( + *quotation (5 ..a default )) ..b 6( . . .

+ *description ( quotation is Bther ise< the the stack.( . + *notes ($he follo ing + *code (0 M 3 ($he follo ing + *code (0 3 0

(If the condition is ( + *link f . (< the ( + *snippet (false( . called ith the ( + *snippet (default( . ( value on the stack. ( + *snippet (true( . ( quotation is called ith the condition on t 0 t 3 o lines are equivalent:( N 3 :if( (dup 0 nip M 3 0 drop N 3 if( . o lines are equivalent:( :if( (s ap or( . . !

?'&;: die + *description (Starts the front)end processor 5@';6< hich is a lo )level debugger hich can inspect memory addresses and the like. $he @'; is also entered hen a critical error occurs.( . + *notes ($he term @'; originates from the &isp machines of old. "ccording to the Xargon @ile<( *nl + *strong (fepped out( . ( Qfept o tQ ( + *emphasis (adF.( . ( $he Symbolics -L== &IS; Iachine has a @ront)'nd ;rocessor called a _@';7 5compare sense , of box6. Jhen the main processor gets edged< the @'; takes control of the keyboard and screen. Such a machine is said to have _fepped out7 or _dropped into the fep7.( *nl + *url (http:QQ .Fargon.netQFargonfileQfQfeppedout.html( . . ! ?'&;: 5clone6 + *values + (obF( obFect . + (ne obF( (a shallo copy( . . + *description (Butputs a byte)by)byte copy of the given obFect. User code should call ( + *link clone . ( instead.( . ! ?'&;: declare + *values + (spec( (an array of class ords( . . + *description (Ceclares that the elements at the top of the stack are instances of the classes in ( + *snippet (spec( . (.( . + * arning ($he compiler blindly trusts declarations< and false declarations can lead to crashes< memory corruption and other undesirable behavior.( . + *examples ($he optimi8er cannot do anything ith the belo code:( + *code (, 2 1= 4( . (?o ever< if e declare that the top of the stack is a ( + *link float . (< then type checks and generic dispatch are eliminated< and the compiler can use unsafe intrinsics:( + *code (+ float . declare , 2 1= 4( . . ! ?'&;: tag + *values + (obFect( obFect . + (n( (a tag number( . . + *description (Butputs an obFect7s tag number< bet een 8ero and one less than ( + *link num)types . (. $his is implementation detail and user code should call ( + *link class . ( instead.( . ! ?'&;: special)obFect + *values + (n( (a non)negative integer( . + (obF( obFect . . + *description (#eads an obFect from the @actor VI7s special obFect table. User code never has to read the special obFect table directly! instead< use one of the callers of this ord.( . ! ?'&;: set)special)obFect + *values + (obF( obFect . + (n( (a non)negative integer( . . + *description (Jrites an obFect to the @actor VI7s special obFect table. User

code never has to rite to the special obFect table directly! instead< use one of the callers of this ord.( . ! ?'&;: obFect + *class)description ($he class of all obFects. If a generic ord defines a method speciali8ing on this class< the method is used as a fallback< if no other applicable method is found. @or instance:( + *code (G'N'#I%: enclose 5 number )) array 6( (I: number enclose 1array !( (I: obFect enclose !( . . ! ?'&;: null + *class)description ($he canonical empty class ith no instances.( . + *notes (Unlike ( + *snippet (null( . ( in Xava or ( + *snippet (NU&&( . ( in %22< this is not a value signifying empty< or nothing. Use ( + *link f . ( for this purpose.( . ! ?'&;: most + *values + (x( obFect . + (y( obFect . + (quot( + *quotation (5 x y )) : 6( . . + (8( (either ( + *snippet (x( . ( or ( + *snippet (y( . . . + *description (If the quotation yields a true value hen applied to ( + *snippet (x( . ( and ( + *snippet (y( . (< outputs ( + *snippet (x( . (< other ise outputs ( + *snippet (y( . (.( . ! ?'&;: curry + *values + (obF( obFect . + (quot( callable . + (curry( curry . . + *description (;artial application. Butputs a ( + *link callable . ( hich first pushes ( + *snippet (obF( . ( and then calls ( + *snippet (quot( . (.( . + *class)description ($he class of obFects created by ( + *link curry . (. $hese obFects print identically to quotations and implement the sequence protocol< ho ever they only use t o cells of storage! a reference to the obFect and a reference to the underlying quotation.( . + *notes ('ven if ( + *snippet (obF( . ( is a ord< it ill be pushed as a literal.( *nl ($his operation is efficient and does not copy the quotation.( . + *examples + *example (USING: kernel prettyprint !( (A 0 . 3 curry .( (0 A . 3( . + *example (USING: kernel prettyprint see !( (>> H 0 see 3 curry .( (0 >> H see 3( . + *example (USING: kernel math prettyprint sequences !( (+ 1 , - . , 0 ) 3 curry map .( (+ )1 = 1 .( . . ! ?'&;: ,curry + *values + (obF1( obFect . + (obF,( obFect . + (quot( callable . + (curry( curry . . + *description (Butputs a ( + *link callable . ( hich pushes ( + *snippet (obF1( . ( and ( + *snippet (obF,( . ( and then calls ( + *snippet (quot( . (.( . + *notes ($his operation is efficient and does not copy the quotation.( . + *examples + *example (USING: kernel math prettyprint !( (A / 0 2 3 ,curry .( (0 A / 2 3( . . ! ?'&;: -curry

+ *values + (obF1( obFect . + (obF,( obFect . + (obF-( obFect . + (quot( callable . + (curry( curry . . + *description (Butputs a ( + *link callable . ( hich pushes ( + *snippet (obF1( . (< ( + *snippet (obF,( . ( and ( + *snippet (obF-( . (< and then calls ( + *snippet (quot( . (.( . + *notes ($his operation is efficient and does not copy the quotation.( . ! ?'&;: ith + *values + (param( obFect . + (obF( obFect . + (quot( + *quotation (5 param elt )) ... 6( . . + (curry( curry . . + *description (;artial application on the left. $he follo ing t o lines are equivalent:( + *code (s ap 0 s ap " 3 curry E( . + *code (0 " 3 ith E( . . + *notes ($his operation is efficient and does not copy the quotation.( . + *examples + *example (USING: kernel math prettyprint sequences !( (1 + 1 , - . 0 Q 3 ith map .( (+ 1 1Q, 1Q- .( . + *example (USING: kernel math prettyprint sequences !( (1=== 1== A iota 0 sq 2 2 3 ith ith map .( (+ 11== 11=1 11=/ 11=U 111L .( . . ! ?'&;: compose + *values + (quot1( callable . + (quot,( callable . + (compose( compose . . + *description (Duotation composition. Butputs a ( + *link callable . ( hich calls ( + *snippet (quot1( . ( follo ed by ( + *snippet (quot,( . (.( . + *notes ($he follo ing t o lines are equivalent:( + *code (compose call( (append call( . (?o ever< ( + *link compose . ( runs in constant time< and the optimi8ing compiler is able to compile code hich calls composed quotations.( . ! ?'&;: prepose + *values + (quot1( callable . + (quot,( callable . + (compose( compose . . + *description (Duotation composition. Butputs a ( + *link callable . ( hich calls ( + *snippet (quot,( . ( follo ed by ( + *snippet (quot1( . (.( . + *notes (See ( + *link compose . ( for details.( . ! + compose prepose . related) ords ?'&;: dip + *values + (x( obFect . + (quot( quotation . . + *description (#emoves ( + *snippet (x( . ( from the datastack< calls ( + *snippet (quot( . (< and restores ( + *snippet (x( . ( to the top of the datastack hen ( + *snippet (quot( . ( is finished.( . + *examples + *example (USING: arrays kernel math prettyprint !( (1= ,= -= 0 Q 3 dip ,array .( (+ 1Q, -= .( . . + *notes + *snippet (dip( . ( is executed as a primitive hen preceded by a literal quotation. $he belo definition is not executed unless its argument is a non)literal quotation< such as a quotation constructed ith ( + *link curry . ( or ( + *link compose . (< or for ( + *link (fry( . ( or quotations including ( + *link (locals( . (.( . !

?'&;: ,dip + *values + (x( obFect . + (y( obFect . + (quot( quotation . . + *description (#emoves ( + *snippet (x( . ( and ( + *snippet (y( . ( from the datastack< calls ( + *snippet (quot( . (< and restores the removed obFects to the top of the datastack hen ( + *snippet (quot( . ( is finished.( . + *notes ($he follo ing are equivalent:( + *code (0 0 foo bar 3 dip 3 dip( . + *code (0 foo bar 3 ,dip( . . ! ?'&;: -dip + *values + (x( obFect . + (y( obFect . + (8( obFect . + (quot( quotation . . + *description (#emoves ( + *snippet (x( . (< ( + *snippet (y( . (< and ( + *snippet (8( . ( from the datastack< calls ( + *snippet (quot( . (< and restores the removed obFects to the top of the datastack hen ( + *snippet (quot( . ( is finished.( . + *notes ($he follo ing are equivalent:( + *code (0 0 0 foo bar 3 dip 3 dip 3 dip( . + *code (0 foo bar 3 -dip( . . ! ?'&;: /dip + *values + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (quot( quotation . . + *description (#emoves ( + *snippet ( ( . (< ( + *snippet (x( . (< ( + *snippet (y( . (< and ( + *snippet (8( . ( from the datastack< calls ( + *snippet (quot( . (< and restores the removed obFects to the top of the datastack hen ( + *snippet (quot( . ( is finished.( . + *notes ($he follo ing are equivalent:( + *code (0 0 0 0 foo bar 3 dip 3 dip 3 dip 3 dip( . + *code (0 foo bar 3 /dip( . . ! ?'&;: hile + *values + (pred( + *quotation (5 ..a )) ..b : 6( . . + (body( + *quotation (5 ..b )) ..a 6( . . . + *description (%alls ( + *snippet (body( . ( until ( + *snippet (pred( . ( returns ( + *link f . (.( . ! ?'&;: until + *values + (pred( + *quotation (5 ..a )) ..b : 6( . . + (body( + *quotation (5 ..b )) ..a 6( . . . + *description (%alls ( + *snippet (body( . ( until ( + *snippet (pred( . ( returns ( + *link t . (.( . ! ?'&;: do + *values + (pred( + *quotation (5 ..a )) ..b : 6( . . + (body( + *quotation (5 ..b )) ..a 6( . . . + *description ('xecutes one iteration of a ( + *link hile . ( or ( + *link until . ( loop.( . ! ?'&;: loop + *values + (pred( quotation . . + *description (%alls the quotation repeatedly until it outputs ( + *link f . (.( . + *examples (&oop until e hit a 8ero:( + *unchecked)example (USING: kernel random math io ! ( ( 0 >(hi>( rite bl 1= random 8ero: not 3 loop( (hi hi hi( . (" fun loop:( + *example (USING: kernel prettyprint math ! (

. !

(- 0 dup . R 2 11 mod dup - H not 3 loop drop( (->n1=>nL>n,>nU>nA>n1>nS>n/>n=>nR( .

"#$I%&': (looping)combinators( (&ooping combinators( (In most cases< loops should be ritten using high)level combinators 5such as ( + *link (sequences)combinators( . (6 or tail recursion. ?o ever< sometimes< the best ay to express intent is ith a loop.( + *subsections hile until . ($o execute one iteration of a loop< use the follo ing ord:( + *subsections do . ($his ord is intended as a modifier. $he normal ( + *link hile . ( loop never executes the body if the predicate returns false on the first iteration. $o ensure the body executes at least once< use ( + *link do . (:( + *code (0 ; 3 0 D 3 do hile( . (" simpler looping combinator hich executes a single quotation until it returns ( + *link f . (:( + *subsections loop . ! ?'&;: assert + *values + (got( (the obtained value( . + (expect( (the expected value( . . + *description ($hro s an ( + *link assert . ( error.( . + *error)description ($hro n hen a unit test or other assertion fails.( . ! ?'&;: assertH + *values + (a( obFect . + (b( obFect . . + *description ($hro s an ( + *link assert . ( error if ( + *snippet (a( . ( does not equal ( + *snippet (b( . (.( . ! ?'&;: become + *values + (old( array . + (ne ( array . . + *description (#eplaces all references to obFects in ( + *snippet (old( . ( ith the corresponding obFect in ( + *snippet (ne ( . (. $his ord is used to implement tuple reshaping. See ( + *link (tuple)redefinition( . (.( . ! "#$I%&': (shuffle) ords)complex( (%omplex shuffle ords( ($hese shuffle ords tend to make code difficult to read and to reason about. %ode that uses them should almost al ays be re ritten using ( + *link (locals( . ( or ( + *link (dataflo )combinators( . (.( *nl (Cuplicating stack elements deep in the stack:( + *subsections dupd . (;ermuting stack elements deep in the stack:( + *subsections s apd rot )rot . ! "#$I%&': (shuffle) ords( (Shuffle ords( (Shuffle ords rearrange items at the top of the data stack as indicated by their stack effects. $hey provide simple data flo control bet een ords. Iore complex data flo control is available ith the ( + *link (dataflo )combinators( . ( and ith ( + *link (locals( . (.( *nl

(#emoving stack elements:( + *subsections drop ,drop -drop nip ,nip . (Cuplicating stack elements:( + *subsections dup ,dup -dup over ,over pick . (;ermuting stack elements:( + *subsections s ap . ($here are additional< more complex stack shuffling recommended.( + *subsections (shuffle) ords)complex( . !

ords

hose use is not

"#$I%&': (equality( ('quality( ($here are t o distinct notions of ]sameness^ hen it comes to obFects.( *nl (Nou can test if t o references point to the same obFect 5( + *emphasis (identity comparison( . (6. $his is rarely used! it is mostly useful ith large< mutable obFects here the obFect identity matters but the value is transient:( + *subsections eq: . (Nou can test if t o obFects are equal in a domain)specific sense< usually by being instances of the same class< and having equal slot values 5( + *emphasis (value comparison( . (6:( + *subsections H . (" third form of equality is provided by ( + *link numberH . (. It compares numeric value hile disregarding types.( *nl (%ustom value comparison methods for use ith ( + *link H . ( can be defined on a generic ord:( + *subsections equal: . (Utility class:( + *subsections identity)tuple . ("n obFect can be cloned! the clone has distinct identity but equal value:( + *subsections clone . ! "#$I%&': (assertions( ("ssertions( (Some ords to make assertions easier to enforce:( + *subsections assert assertH . ! USING: arrays byte)arrays kernel kernel.private math memory namespaces sequences tools.test math.private quotations continuations prettyprint io.streams.string debugger assocs sequences.private accessors locals.backend grouping ords system alien alien.accessors ! IN: kernel.tests

0 = 3 0 f si8e 3 unit)test 0 t 3 0 0 > H > H 3 all)equal: 3 unit)test K Con7t leak extra roots if error is thro n 0 3 0 1=== 0 0 - thro 3 ignore)errors 3 times 3 unit)test 0 3 0 1=== 0 0 )1 f ParrayG 3 ignore)errors 3 times 3 unit)test K Iake sure e report the correct error on stack underflo 0 clear drop 3 0 + (kernel)error( 1= f f . H 3 must)fail) ith 0 3 0 :c 3 unit)test 0 - 0 + . set)retainstack 3 dip 3 0 + (kernel)error( 1, f f . H 3 must)fail) ith 0 3 0 :c 3 unit)test : overflo )d 5 )) 6 - overflo )d ! : 5overflo )d)alt6 5 )) n 6 - ! : overflo )d)alt 5 )) 6 5overflo )d)alt6 overflo )d)alt ! : overflo )r 5 )) 6 - load)local overflo )r ! PP + overflo )d 5overflo )d)alt6 overflo )d)alt overflo )r . 0 t (no)compile( set) ord)prop 3 each GG 0 overflo )d 3 0 + (kernel)error( 11 f f . H 3 must)fail) ith 0 3 0 :c 3 unit)test 0 overflo )d)alt 3 0 + (kernel)error( 11 f f . H 3 must)fail) ith 0 3 0 0 :c 3 ith)string) riter drop 3 unit)test

0 overflo )r 3 0 + (kernel)error( 1- f f . H 3 must)fail) ith 0 3 0 :c 3 unit)test : overflo )c 5 )) 6 overflo )c overflo )c ! K $he VI cannot recover from callstack overflo on Jindo s< K because no facility exists to run memory protection K fault handlers on an alternate callstack. os indo s: 0 0 overflo )c 3 0 + (kernel)error( 1A f f . H 3 must)fail) ith 3 unless 0 )R Pbyte)arrayG 3 must)fail 0 0 0 0 0 0 0 0 f f / L f 1 , 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 t f / f 1 1 f f L L , f , and 3 unit)test and 3 unit)test and 3 unit)test or 3 unit)test or 3 unit)test xor 3 unit)test xor 3 unit)test xor 3 unit)test

0 f 3 0 f f xor 3 unit)test 0 dip 3 must)fail 0 3 0 :c 3 unit)test 0 1 0 call 3 dip 3 must)fail 0 3 0 :c 3 unit)test 0 1 , 0 call 3 dip 3 must)fail 0 3 0 :c 3 unit)test 0 A 3 0 1 0 , , 2 3 dip 2 3 unit)test 0 0 3 keep 3 must)fail 0 L 3 0 , 0 sq 3 keep 2 3 unit)test 0 0 3 ,keep 3 must)fail 0 1 0 3 ,keep 3 must)fail 0 - 1 , 3 0 1 , 0 ,drop - 3 ,keep 3 unit)test 0 = 3 0 f 0 sq 3 0 = 3 if4 3 unit)test 0 / 3 0 , 0 sq 3 0 = 3 if4 3 unit)test 0 = 3 0 f 0 = 3 unless4 3 unit)test 0 t 3 0 t 0 (?ello( 3 unless4 3 unit)test 0 (,>n( 3 0 0 1 , 0 . 3 0 sq . 3 :if 3 0 (U>n( 3 0 0 - f 0 . 3 0 sq . 3 :if 3 0 f 3 0 f 5clone6 3 unit)test 0 )1,- 3 0 )1,- 5clone6 3 unit)test 0 L , 3 0 1 , 0 A 2 3 dip 3 unit)test 0 3 0 callstack set)callstack 3 unit)test 0 -drop datastack 3 must)fail 0 3 0 :c 3 unit)test K Coesn7t compile! important : foo 5 a )) b 6 ! PP > foo t (no)compile( set) ord)prop GG 0 drop foo 3 must)fail 0 3 0 :c 3 unit)test K #egression : 5loop6 5 a b c d )) 6 0 pick 3 dip s ap 0 pick 3 dip s ap P 0 0 1 2 3 -dip 5loop6 3 0 /drop 3 if ! inline recursive : loop 5 obF )) 6 ?+ . values s ap 0 dup length s ap 3 dip 0 = 3 -dip 5loop6 ! 0 loop 3 must)fail K Ciscovered on Jindo s : total)failure)1 5 )) a 6 (( 0 3 map unimplemented ! 0 total)failure)1 3 must)fail ith)string) riter 3 unit)test ith)string) riter 3 unit)test

0 1 1 , , - - 3 0 1 , - 0 dup 3 tri9 3 unit)test 0 1 / U 3 0 1 , - 0 sq 3 tri9 3 unit)test 0 0 sq 3 tri9 3 must)infer 0 / 3 0 1 + 0 1 3 0 , 3 . dispatch sq 3 unit)test K $est traceback accuracy : last)frame 5 )) pair 6 error)continuation get callGG callstackGarray L head4 - tail4 ! 0 3 0 + 0 1 , 0 - thro 3 call / 3 0 1 , 0 - thro 3 call / 3 - .

0 0 1 , 0 - thro last)frame 3 unit)test 0 3 0 + 0 1 , 0 - thro

3 call / 3 call 3 ignore)errors

3 dip / 3 0 1 , 0 - thro

3 dip / 3 - .

0 0 1 , 0 - thro last)frame 3 unit)test 0 3 0 + 0 1 , - thro

3 dip / 3 call 3 ignore)errors

0 3 call / 3 0 1 , - thro

0 3 call / 3 - .

0 0 1 , - thro last)frame 3 unit)test 0 3 0 + 0 1 , - thro

0 3 call / 3 call 3 ignore)errors

0 3 dip / 3 0 1 , - thro

0 3 dip / 3 - .

0 0 1 , - thro last)frame 3 unit)test 0 3 0 + 0 1 , - thro

0 3 dip / 3 call 3 ignore)errors

0 3 0 3 if / 3 0 1 , - thro

0 3 0 3 if / 3 - .

0 0 1 , - thro last)frame 3 unit)test

0 3 0 3 if / 3 call 3 ignore)errors

0 1= , - / A 3 0 1 , - / A 0 1= 4 3 /dip 3 unit)test 0 - )1 AQL 3 0 1 , - / A L 0 2 3 0 ) 3 0 Q 3 ,tri4 3 unit)test 0 + 1 , . + - / . + A L . 3 0 1 , - / A L 0 ,array 3 ,tri9 3 unit)test 0 t 3 0 + . identity)hashcode fixnum: 3 unit)test 0 1,- 3 0 1,- identity)hashcode 3 unit)test 0 t 3 0 f identity)hashcode fixnum: 3 unit)test K Iake sure memory protection faults ork 0 f = alien)unsigned)1 3 0 vm)error: 3 must)fail) ith 0 1 PalienG = alien)unsigned)1 3 0 vm)error: 3 must)fail) ith + 1 , - 1 , - . 0 1 , - -dup 3 unit)test + 1 , - / 1 , - / . 0 1 , - / /dup 3 unit)test

K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays byte)arrays byte)vectors classes.algebra.private classes.builtin classes.intersection classes.maybe classes.mixin classes.parser classes.predicate classes.singleton classes.tuple classes.tuple.parser classes.union combinators compiler.units definitions effects.parser generic generic.hook generic.math generic.parser generic.standard hash)sets hashtables io.pathnames kernel lexer math namespaces parser quotations sbufs sequences slots source)files splitting strings strings.parser vectors vocabs.parser ords ords.alias ords.constant ords.symbol ! IN: bootstrap.syntax K K K K K K K $hese ords are defined as a top)level form< instead of ith defining parsing ords< because during stage1 bootstrap< the (syntax( vocabulary is copied from the host. Jhen stage1 bootstrap completes< the host7s syntax vocabulary is deleted from the target< then this top)level form creates the target7s (syntax( vocabulary as one of the first things done in stage,.

: define)delimiter 5 name )) 6 (syntax( lookup) ord t (delimiter( set) ord)prop ! : define)core)syntax 5 name quot )) 6 0 dup (syntax( lookup) ord 0 3 0 no) ord)error 3 :if 3 dip define)syntax ! 0 + (3( (.( (!( (GG( . 0 define)delimiter 3 each (;#III$IV':( 0 (;rimitive definition is not supported( thro 3 define)core)syntax (%S+( 0 (%all stack literals are not supported( thro 3 define)core)syntax (K( 0 lexer get next)line 3 define)core)syntax (ZK( 0 ;BS$;BN': K 3 define)core)syntax (IN:( 0 scan)token set)current)vocab 3 define)core)syntax (P;#IV"$'( 0 begin)private 3 define)core)syntax (;#IV"$'G( 0 end)private 3 define)core)syntax (US':( 0 scan)token use)vocab 3 define)core)syntax (UNUS':( 0 scan)token unuse)vocab 3 define)core)syntax (USING:( 0 (!( 0 use)vocab 3 each)token 3 define)core)syntax (DU"&I@I'C:( 0 scan)token dup add)qualified 3 define)core)syntax (DU"&I@I'C)JI$?:( 0 scan)token scan)token add)qualified 3 define)core)syntax (@#BI:( 0 scan)token (HG( expect (!( parse)tokens add) ords)from

3 define)core)syntax ('M%&UC':( 0 scan)token (HG( expect (!( parse)tokens add) ords)excluding 3 define)core)syntax (#'N"I':( 0 scan)token scan)token (HG( expect scan)token add)renamed) ord 3 define)core)syntax (N"N:( 0 1L scan)base Pfp)nanG suffixK 3 define)core)syntax (f( 0 f suffixK 3 define)core)syntax (%?"#:( 0 scan)token + + 0 dup length 1 H 3 0 first 3 . + 0 (>>( :head 3 0 next)escape Gstring (( assertH 3 . 0 nameGchar)hook get call5 name )) char 6 3 . cond suffixK 3 define)core)syntax (>(( 0 parse)multiline)string suffixK 3 define)core)syntax (SEU@>(( 0 lexer get skip)blank parse)string Gsbuf suffixK 3 define)core)syntax (;>(( 0 lexer get skip)blank parse)string PpathnameG suffixK 3 define)core)syntax (0( 0 parse)quotation suffixK 3 define)core)syntax (+( 0 > . 0 Garray 3 parse)literal 3 define)core)syntax (V+( 0 > . 0 Gvector 3 parse)literal 3 define)core)syntax (E+( 0 > . 0 Gbyte)array 3 parse)literal 3 define)core)syntax (EV+( 0 > . 0 Gbyte)vector 3 parse)literal 3 define)core)syntax (?+( 0 > . 0 parse)hashtable 3 parse)literal 3 define)core)syntax ($+( 0 parse)tuple)literal suffixK 3 define)core)syntax (J+( 0 > . 0 first P rapperG 3 parse)literal 3 define)core)syntax (?S+( 0 > . 0 Ghash)set 3 parse)literal 3 define)core)syntax (;BS$;BN':( 0 scan) ord suffixK 3 define)core)syntax (>>( 0 scan) ord P rapperG suffixK 3 define)core)syntax (I>>( 0 scan) ord scan) ord lookup)method P rapperG suffixK 3 define)core)syntax (inline( 0 last) ord make)inline 3 define)core)syntax (recursive( 0 last) ord make)recursive 3 define)core)syntax (foldable( 0 last) ord make)foldable 3 define)core)syntax (flushable( 0 last) ord make)flushable 3 define)core)syntax (delimiter( 0 last) ord t (delimiter( set) ord)prop 3 define)core)syntax (deprecated( 0 last) ord make)deprecated 3 define)core)syntax (SNN$"M:( 0 scan)ne ) ord parse)definition define)syntax 3 define)core)syntax (EUI&$IN:( 0 scan) ord)name current)vocab lookup) ord 5parse)tuple)definition6 ,drop check)builtin 3 define)core)syntax

(SNIEB&:( 0 scan)ne ) ord define)symbol 3 define)core)syntax (SNIEB&S:( 0 (!( 0 create)in 0 reset)generic 3 0 define)symbol 3 bi 3 each)token 3 define)core)syntax (SING&'$BNS:( 0 (!( 0 create)class)in define)singleton)class 3 each)token 3 define)core)syntax (C'@'#:( 0 scan)token current)vocab create 0 fake)definition 3 0 set)last) ord 3 0 undefined)def define 3 tri 3 define)core)syntax ("&I"S:( 0 scan)ne ) ord scan) ord define)alias 3 define)core)syntax (%BNS$"N$:( 0 scan)ne ) ord scan)obFect define)constant 3 define)core)syntax (:( 0 5:6 define)declared 3 define)core)syntax (G'N'#I%:( 0 0 simple)combination 3 5G'N'#I%:6 3 define)core)syntax (G'N'#I%Z( 0 0 scan)number Pstandard)combinationG 3 5G'N'#I%:6 3 define)core)syntax (I"$?:( 0 0 math)combination 3 5G'N'#I%:6 3 define)core)syntax (?BBY:( 0 0 scan) ord Phook)combinationG 3 5G'N'#I%:6 3 define)core)syntax (I:( 0 5I:6 define 3 define)core)syntax (UNIBN:( 0 scan)ne )class parse)definition define)union)class 3 define)core)syntax (IN$'#S'%$IBN:( 0 scan)ne )class parse)definition define)intersection)class 3 define)core)syntax (IIMIN:( 0 scan)ne )class define)mixin)class 3 define)core)syntax

(INS$"N%':( 0 location 0 scan) ord scan) ord ,dup add)mixin)instance Pmixin)instanceG 3 dip remember)definition 3 define)core)syntax (;#'CI%"$':( 0 scan)ne )class (P( expect scan)class parse)definition define)predicate)class 3 define)core)syntax (SING&'$BN:( 0 scan)ne )class define)singleton)class 3 define)core)syntax ($U;&':( 0 parse)tuple)definition define)tuple)class 3 define)core)syntax (final( 0 last) ord make)final 3 define)core)syntax (S&B$:( 0 scan)token define)protocol)slot 3 define)core)syntax (%:( 0 scan)ne ) ord scan) ord define)boa) ord 3 define)core)syntax ('##B#:( 0 parse)tuple)definition pick save)location define)error)class 3 define)core)syntax (@B#G'$:( 0 scan)obFect forget 3 define)core)syntax (5( 0 (6( parse)effect suffixK 3 define)core)syntax (I"IN:( 0 scan) ord 0 current)vocab mainPP 3 0 file get 0 mainPP 3 0 drop 3 if4 3 bi 3 define)core)syntax (PP( 0 0

> GG parse)until Gquotation 3 ith)nested)compilation)unit call5 )) 6 3 define)core)syntax (call)next)method( 0 current)method get 0

3 0

literali8e suffixK > 5call)next)method6 suffixK

not)in)a)method)error 3 if4 3 define)core)syntax (maybe+( 0 > . 0 Panonymous)unionG PmaybeG 3 parse)literal 3 define)core)syntax (not+( 0 > . 0 Panonymous)unionG Panonymous)complementG 3 parse)literal 3 define)core)syntax (intersection+( 0 > . 0 Panonymous)intersectionG 3 parse)literal 3 define)core)syntax (union+( 0 > . 0 Panonymous)unionG 3 parse)literal 3 define)core)syntax (initial:( (syntax( lookup) ord define)symbol (read)only( (syntax( lookup) ord define)symbol (call5( 0 > call)effect parse)call5 3 define)core)syntax (execute5( 0 > execute)effect parse)call5 3 define)core)syntax (PPPPPPP( 0 version)control)merge)conflict 3 define)core)syntax (HHHHHHH( 0 version)control)merge)conflict 3 define)core)syntax (GGGGGGG( 0 version)control)merge)conflict 3 define)core)syntax (PPPPPP( 0 version)control)merge)conflict 3 define)core)syntax (HHHHHH( 0 version)control)merge)conflict 3 define)core)syntax (GGGGGG( 0 version)control)merge)conflict 3 define)core)syntax 3 ith)compilation)unit USING: generic help.syntax help.markup kernel math parser ords effects classes classes.tuple generic.math generic.single arrays io.pathnames vocabs.loader io sequences assocs ords.symbol ords.alias ords.constant combinators vocabs.parser command)line ! IN: syntax "#$I%&': (parser)algorithm( (;arser algorithm( ("t the most abstract level< @actor syntax consists of hitespace)separated tokens. $he parser tokeni8es the input on hitespace boundaries. $he parser is case)sensitive and hitespace bet een tokens is significant< so the follo ing three expressions tokeni8e differently:( + *code (,M2>n, M 2>n, x 2( . ("s the parser reads tokens it makes a distinction bet een numbers< ordinary ords< and parsing ords. $okens are appended to the parse tree< the top level of hich is a quotation returned by the original parser invocation. Nested levels of the parse tree are created by parsing ords.( *nl ($he parser iterates through the input text< checking each character in turn. ?ere is the parser algorithm in more detail )) some of the concepts therein ill be defined shortly:( + *list + (If the current character is a double)quote 5>(6< the ( + *link ;BS$;BN': ( . ( parsing ord is executed< causing a string to be read.( .

+ (Bther ise< the next token is taken from the input. $he parser searches for a ord named by the token in the currently used set of vocabularies. If the ord is found< one of the follo ing t o actions is taken:( + *list (If the ord is an ordinary ord< it is appended to the parse tree.( (If the ord is a parsing ord< it is executed.( . . (Bther ise if the token does not represent a kno n ord< the parser attempts to parse it as a number. If the token is a number< the number obFect is added to the parse tree. Bther ise< an error is raised and parsing halts.( . (;arsing ords play a key role in parsing! hile ordinary ords and numbers are simply added to the parse tree< parsing ords execute in the context of the parser< and can do their o n parsing and create nested data structures in the parse tree. ;arsing ords are also able to define ne ords.( *nl (Jhile parsing ords supporting arbitrary syntax can be defined< the default set is found in the ( + *vocab)link (syntax( . ( vocabulary and provides the basis for all further syntactic interaction ith @actor.( ! "#$I%&': (syntax)comments( (%omments( + *subsections ;BS$;BN': K ;BS$;BN': ZK . ! "#$I%&': (syntax)immediate( (;arse time evaluation( (%ode can be evaluated at parse time. $his is a rarely)used feature! one use)case is ( + *link (loading)libs( . (< here you ant to execute some code before the ords in a source file are compiled.( + *subsections ;BS$;BN': PP ;BS$;BN': GG . ! "#$I%&': (syntax)integers( (Integer syntax( ($he printed representation of an integer consists of a sequence of digits< optionally prefixed by a sign.( + *code (1,-/AL( ()1=( (,/-,U=,==S1RLL/====( . (Integers are entered in base 1= unless prefixed ith a base)changing prefix. ( + *snippet (=x( . ( begins a hexadecimal literal< ( + *snippet (=o( . ( an octal literal< and ( + *snippet (=b( . ( a binary literal. " sign< if any< goes before the base prefix.( + *example (US': prettyprint( (1= .( (=b1= .( ()=o1= .( (=x1= .( (1=>n,>n)S>n1L( . (Iore information on integers can be found in ( + *link (integers( . (.( ! "#$I%&': (syntax)ratios( (#atio syntax( ($he printed representation of a ratio is a pair of integers separated by a slash 5( + *snippet (Q( . (6. " ratio can also be ritten as a proper fraction

by follo ing an integer part ith ( + *snippet (2( . ( or ( + *snippet ()( . ( 5matching the sign of the integer6 and a ratio. No intermediate hitespace is permitted ithin a ratio literal. ?ere are some examples:( + *code (RAQ--( (1Q1=( ()AQ)L( (121Q-( ()1=)1QR( . (Iore information on ratios can be found in ( + *link (rationals( . (.( ! "#$I%&': (syntax)floats( (@loat syntax( (@loating point literals are specified hen a literal number contains a decimal point or exponent. 'xponents are marked by an ( + *snippet (e( . ( or ( + *snippet ('( . (:( + *code (1=.A( ()-.1/AL( (Re1-( (1.=e)A( (1.='2A( . (&iteral numbers ithout a decimal point or an exponent al ays parse as integers:( + *example (1 float: .( (f( . + *example (1. float: .( (t( . + *example (1e= float: .( (t( . (&iteral floating point approximations of ratios can also be input by placing a decimal point in the denominator:( + *example (1Q,. .( (=.A( . + *example (1Q-. .( (=.----------------( . ($he special float values have their o n syntax:( + *table + (;ositive infinity( + *snippet (1Q=.( . . + (Negative infinity( + *snippet ()1Q=.( . . + (Not)a)number( + *snippet (=Q=.( . . . (" Not)a)number literal ith an arbitrary payload can also be input:( + *subsections ;BS$;BN': N"N: . (?exadecimal float literals are also supported. $hese consist of a hexadecimal literal ith a decimal point and an optional base)t o exponent expressed as a decimal number after ( + *snippet (p( . ( or ( + *snippet (;( . (:( + *example (S.= =x1.=p- H .( (t( .

+ *example ()1=,/.= )=x1.=;1= H .( (t( . + *example (1=.1,A =x1.//p- H .( (t( . ($he normali8ed hex form ( + *snippet (b=x1.IIIIIIIIIIIIIpb''''( . ( allo s any floating)point number to be specified precisely. $he values of IIIIIIIIIIIII and '''' map directly to the mantissa and exponent fields of the binary I''' RA/ representation.( *nl (Iore information on floats can be found in ( + *link (floats( . (.( ! "#$I%&': (syntax)complex)numbers( (%omplex number syntax( (" complex number is given by t o components< a ]real^ part and ]imaginary^ part. $he components must either be integers< ratios or floats.( + *code (%+ 1Q, 1Q- . K the complex number 1Q,21Q-i( (%+ = 1 . K the imaginary unit( . + *subsections ;BS$;BN': %+ . (Iore information on complex numbers can be found in ( + *link (complex)numbers( . (.( ! "#$I%&': (syntax)numbers( (Number syntax( (If a vocabulary lookup of a token fails< the parser attempts to parse it as a number.( + *subsections (syntax)integers( (syntax)ratios( (syntax)floats( (syntax)complex)numbers( . ! "#$I%&': (syntax) ords( (Jord syntax( (" ord occurring inside a quotation is executed hen the quotation is called. Sometimes a ord needs to be pushed on the data stack instead. $he canonical use case for this is passing the ord to the ( + *link execute . ( combinator< or alternatively< reflectively accessing ord properties 5( + *link ( ord)props( . (6.( + *subsections ;BS$;BN': > ;BS$;BN': ;BS$;BN': . ($he implementation of the ( + *link ;BS$;BN': > . ( ord is discussed in detail in ( + *link (reading)ahead( . (. Jords are documented in ( + *link ( ords( . (.( ! "#$I%&': (escape( (%haracter escape codes( + *table + ('scape code( (Ieaning( . + + *snippet (>>>>( . + *snippet (>>( . . + + *snippet (>>s( . (a space( . + + *snippet (>>t( . (a tab( . + + *snippet (>>n( . (a ne line( . + + *snippet (>>r( . (a carriage return( . + + *snippet (>>=( . (a null byte 5"S%II =6( . + + *snippet (>>e( . (escape 5"S%II ,R6( . + + *snippet (>>>(( . + *snippet (>(( . . + + *snippet (>>u( + *emphasis (xxxxxx( . . + ($he Unicode code point

ith

hexadecimal number ( + *snippet + *emphasis (xxxxxx( . . . . + + *snippet (>>u+( + *emphasis (name( . (.( . + ($he Unicode code point named ( + *snippet + *emphasis (name( . . . . . ! "#$I%&': (syntax)strings( (%haracter and string syntax( (@actor has no distinct character type. Integers representing Unicode code points can be read by specifying a literal character< or an escaped representation thereof.( + *subsections ;BS$;BN': %?"#: ;BS$;BN': ( (escape( . (Strings are documented in ( + *link (strings( . (.( ! "#$I%&': (syntax)sbufs( (String buffer syntax( + *subsections ;BS$;BN': SEU@( . (String buffers are documented in ( + *link (sbufs( . (.( ! "#$I%&': (syntax)arrays( ("rray syntax( + *subsections ;BS$;BN': + ;BS$;BN': . . ("rrays are documented in ( + *link (arrays( . (.( ! "#$I%&': (syntax)vectors( (Vector syntax( + *subsections ;BS$;BN': V+ . (Vectors are documented in ( + *link (vectors( . (.( ! "#$I%&': (syntax)hashtables( (?ashtable syntax( + *subsections ;BS$;BN': ?+ . (?ashtables are documented in ( + *link (hashtables( . (.( ! "#$I%&': (syntax)hash)sets( (?ash set syntax( + *subsections ;BS$;BN': ?S+ . (?ashtables are documented in ( + *link (hash)sets( . (.( ! "#$I%&': (syntax)tuples( ($uple syntax( + *subsections ;BS$;BN': $+ . ($uples are documented in ( + *link (tuples( . (.( ! "#$I%&': (syntax)quots( (Duotation syntax( + *subsections ;BS$;BN': 0 ;BS$;BN': 3 . (Duotations are documented in ( + *link (quotations( . (.( ! "#$I%&': (syntax)byte)arrays( (Eyte array syntax( + *subsections ;BS$;BN': E+ . (Eyte arrays are documented in ( + *link (byte)arrays( . (.( ! "#$I%&': (syntax)pathnames( (;athname syntax( + *subsections ;BS$;BN': ;( . (;athnames are documented in ( + *link (io.pathnames( . (.( ! "#$I%&': (syntax)effects( (Stack effect syntax( (Note that this is ( + *emphasis (not( . ( syntax to declare stack effects of ords. $his pushes an ( + *link effect . ( instance on the stack for reflection< for use ith ords such as ( + *link define)declared . (< ( + *link

call)effect . ( and ( + *link execute)effect . (.( + *subsections ;BS$;BN': 5 . + *see)also (effects( (inference( (tools.inference( . ! "#$I%&': (syntax)literals( (&iterals( (Iany different types of obFects can be constructed at parse time via literal syntax. Numbers are a special case since support for reading them is built)in to the parser. "ll other literals are constructed via parsing ords.( *nl (If a quotation contains a literal obFect< the same literal obFect instance is used each time the quotation executes! that is< literals are ]live^.( *nl (Using mutable obFect literals in ord definitions requires care< since if those obFects are mutated< the actual ord definition ill be changed< hich is in most cases not hat you ould expect. &iterals should be ( + *link clone . (d before being passed to a ord hich may potentially mutate them.( + *subsections (syntax)numbers( (syntax) ords( (syntax)quots( (syntax)arrays( (syntax)strings( (syntax)byte)arrays( (syntax)vectors( (syntax)sbufs( (syntax)hashtables( (syntax)hash)sets( (syntax)tuples( (syntax)pathnames( (syntax)effects( . ! "#$I%&': (syntax( (Syntax( (@actor has t o main forms of syntax: ( + *emphasis (definition( . ( syntax and ( + *emphasis (literal( . ( syntax. %ode is data< so the syntax for code is a special case of obFect literal syntax. $his section documents literal syntax. Cefinition syntax is covered in ( + *link ( ords( . (. 'xtending the parser is the main topic of ( + *link (parser( . (.( + *subsections (parser)algorithm( ( ord)search( (top)level)forms( (syntax)comments( (syntax)literals( (syntax)immediate( . ! "EBU$: (syntax( ?'&;: delimiter + *syntax (: foo ... ! delimiter( . + *description (Ceclares the most recently defined ord as a delimiter. Celimiters are ords hich are only ever valid as the end of a nested block to be read by ( + *link parse)until . (. "n unpaired occurrence of a delimiter is a parse error.( . ! ?'&;: deprecated + *syntax (: foo ... ! deprecated( . + *description (Ceclares the most recently defined + *vocab)link (tools.deprecation( . ( vocabulary is ords ill be noted by the ( + *link (tools.errors( + *notes (%ode that uses deprecated ords continues

ord as deprecated. If the ( loaded< usages of deprecated . ( system.( . to function normally! the

errors are purely informational. ?o ever< code that uses deprecated ords should be updated< for the deprecated ords are intended to be removed soon.( . ! ?'&;: SNN$"M: + *syntax (SNN$"M: foo ... !( . + *description (Cefines a parsing ord.( . + *examples (In the belo example< the ( + *snippet ( orld( . ( ord is never called< ho ever its body references a parsing ord hich executes immediately:( + *example (US': io( (IN: scratchpad( (PP SNN$"M: ?'&&B >(?ello parserK>( print ! GG>n: orld 5 )) 6 ?'&&B !( (?ello parserK( . . ! ?'&;: inline + *syntax (: foo ... ! inline( . + *description (Ceclares the most recently defined ord as an inline ord. $he optimi8ing compiler copies definitions of inline ords hen compiling calls to them.( *nl (%ombinators must be inlined in order to compile ith the optimi8ing compiler ) see ( + *link (inference)combinators( . (. @or any other ord< inlining is merely an optimi8ation. Note that inlined ords that can be compiled stand)alone are also< themselves< compiled by the optimi8ing compiler.( *nl ($he non)optimi8ing quotation compiler ignores inlining declarations.( . ! ?'&;: recursive + *syntax (: foo ... ! recursive( . + *description (Ceclares the most recently defined ord as a recursive ord.( . + *notes ($his declaration is only required for ( + *link ;BS$;BN': inline . ( ords hich call themselves. See ( + *link (inference)recursive)combinators( . (.( . ! ?'&;: foldable + *syntax (: foo ... ! foldable( . + *description (Ceclares that the most recently defined ord may be evaluated at compile)time if all inputs are literal. @oldable ords must satisfy a very strong contract:( + *list (foldable ords must not have any observable side effects<( (foldable ords must halt ) for example< a ord computing a series until it coverges should not be foldable< since compilation ill not halt in the event the series does not converge.( (both inputs and outputs of foldable ords must be immutable.( . ($he last restriction ensures that ords such as ( + *link clone . ( do not satisfy the foldable ord contract. Indeed< ( + *link clone . ( ill output a mutable obFect if its input is mutable< and so it is undesirable to evaluate it at compile)time< since doing so ould give incorrect semantics for code that clones mutable obFects and proceeds to mutate them.( . + *notes (@olding optimi8ations are not applied if the call site of a ord is in the same source file as the ord. $his is a side)effect of the compilation unit system! see ( + *link (compilation)units( . (.( . + *examples (Iost operations on numbers are foldable. @or example< ( + *snippet (, , 2( . ( compiles to a literal /< since ( + *link 2 . ( is declared foldable.( . ! ?'&;: flushable + *syntax (: foo ... ! flushable( .

+ *description (Ceclares that the most recently defined ord has no side effects< and thus calls to this ord may be pruned by the compiler if the outputs are not used.( *nl (Note that many ords are flushable but not foldable< for example ( + *link clone . ( and ( + *link ParrayG . (.( . ! ?'&;: t + *syntax (t( . + *values + (t( (the canonical truth value( . . + *class)description ($he canonical truth value< itself.( . !

hich is an instance of

?'&;: f + *syntax (f( . + *values + (f( (the singleton false value( . . + *description ($he ( + *link f . ( parsing ord adds the ( + *link f . ( obFect to the parse tree< and is also the class hose sole instance is the ( + *link f . ( obFect. $he ( + *link f . ( obFect is the singleton false value< the only obFect that is not true. $he ( + *link f . ( obFect is not equal to the ( + *link f . ( class ord< hich can be pushed on the stack using ord rapper syntax:( + *code (f K the singleton f obFect denoting falsity>n>> f K the f class ord( . . ! ?'&;: 0 + *syntax (0 elements... 3( . + *description (Iarks the beginning of a literal quotation.( . + *examples + *code (0 1 , - 3( . . ! + ;BS$;BN': 0 ;BS$;BN': 3 . related) ords ?'&;: 3 + *syntax (3( . + *description (Iarks the end of a literal quotation.( *nl (;arsing ords can use this ord as a generic end delimiter.( . ! ?'&;: . + *syntax (.( . + *description (Iarks the end of an array< vector< hashtable< complex number< tuple< or rapper.( *nl (;arsing ords can use this ord as a generic end delimiter.( . ! + ;BS$;BN': + ;BS$;BN': V+ ;BS$;BN': ?+ ;BS$;BN': ?S+ ;BS$;BN': %+ ;BS$;BN': $+ ;BS$;BN': J+ ;BS$;BN': . . related) ords ?'&;: + + *syntax (+ elements... .( . + *values + (elements( (a list of obFects( . . + *description (Iarks the beginning of a literal array. &iteral arrays are terminated by ( + *link ;BS$;BN': . . (.( . + *examples + *code (+ 1 , - .( . . ! ?'&;: V+ + *syntax (V+ elements... .( . + *values + (elements( (a list of obFects( . . + *description (Iarks the beginning of a literal vector. &iteral vectors are terminated by ( + *link ;BS$;BN': . . (.( . + *examples + *code (V+ 1 , - .( . . !

?'&;: E+ + *syntax (E+ elements... .( . + *values + (elements( (a list of integers( . . + *description (Iarks the beginning of a literal byte array. &iteral byte arrays are terminated by ( + *link ;BS$;BN': . . (.( . + *examples + *code (E+ 1 , - .( . . ! ?'&;: ?+ + *syntax (?+ + key value .... .( . + *values + (key( (an obFect( . + (value( (an obFect( . . + *description (Iarks the beginning of a literal hashtable< given as a list of t o)element arrays holding keyQvalue pairs. &iteral hashtables are terminated by ( + *link ;BS$;BN': . . (.( . + *examples + *code (?+ + >(tuna>( >(fish>( . + >(Falapeno>( >(vegetable>( . .( . . ! ?'&;: ?S+ + *syntax (?S+ members ... .( . + *values + (members( (a list of obFects( . . + *description (Iarks the beginning of a literal hash set< given as a list of its members. &iteral hashtables are terminated by ( + *link ;BS$;BN': . . (.( . + *examples + *code (?S+ - >(foo>( .( . . ! ?'&;: %+ + *syntax (%+ real)part imaginary)part .( . + *values + (real)part( (a real number( . + (imaginary)part( (a real number( . . + *description (;arses a complex number given in rectangular form as a pair of real numbers. &iteral complex numbers are terminated by ( + *link ;BS$;BN': . . (.( . ! ?'&;: $+ + *syntax ($+ class .( ($+ class f slot)values... .( ($+ class + slot)name slot)value . ... .( . + *values + (class( (a tuple class ord( . + (slots( (slot values( . . + *description (Iarks the beginning of a literal tuple.( *nl ($hree literal syntax forms are recogni8ed:( + *list + (empty tuple form: if no slot values are specified< then the literal tuple ill have all slots set to their initial values 5see ( + *link (slot)initial)values( . (6.( . + (EB")form: if the first element of ( + *snippet (slots( . ( is ( + *snippet (f( . (< then the remaining elements are slot values corresponding to slots in the order in hich they are defined in the ( + *link ;BS$;BN': $U;&': . ( form.( . + (assoc)form: other ise< ( + *snippet (slots( . ( is interpreted as a sequence of ( + *snippet (+ slot)name value .( . ( pairs. $he ( + *snippet (slot)name( . ( should not be quoted.( . . (EB" form is more concise< hereas assoc form is more readable for larger tuples ith many slots< or if only a fe slots are to be specified.( *nl (Jith EB" form< specifying an insufficient number of values is given after the class ord< the remaining slots of the tuple are set to their initial values 5see ( + *link (slot)initial)values( . (6. If too many values are given< an error ill be raised.( . + *examples ("n empty tuple! since vectors have their o n literal syntax< the above is equivalent to ( + *snippet (V+ .( . (( + *code ($+ vector .( . (" EB")form tuple:(

+ *code (US': colors( ($+ rgba f 1.= =.= =.A .( . ("n assoc)form tuple equal to the above:( + *code (US': colors( ($+ rgba + red 1.= . + green =.= . + blue =.A . .( . . ! ?'&;: J+ + *syntax (J+ obFect .( . + *values + (obFect( (an obFect( . . + *description (Iarks the beginning of a literal terminated by ( + *link ;BS$;BN': . . (.( . !

rapper. &iteral

rappers are

?'&;: ;BS$;BN': + *syntax (;BS$;BN': ord( . + *values + ( ord( (a ord( . . + *description (#eads the next ord from the input string and appends the ord to the parse tree< even if it is a parsing ord.( . + *examples (@or an ordinary ord ( + *snippet (foo( . (< ( + *snippet (foo( . ( and ( + *snippet (;BS$;BN': foo( . ( are equivalent! ho ever< if ( + *snippet (foo( . ( is a parsing ord< the former ill execute it at parse time< hile the latter ill execute it at runtime.( . + *notes ($his ord is used inside parsing ords to delegate further action to another parsing ord< and to refer to parsing ords literally from literal arrays and such.( . ! ?'&;: : + *syntax (: ord 5 stack )) effect 6 definition... !( . + *values + ( ord( (a ne ord to define( . + (definition( (a ord definition( . . + *description (Cefines a ord ith the given stack effect in the current vocabulary.( . + *examples + *code (: ask)name 5 )) name 6>n >(Jhat is your name: >( rite readln !>n: greet 5 name )) 6>n >(Greetings< >( rite print !>n: friend 5 )) 6>n ask)name greet !( . . ! + ;BS$;BN': : ;BS$;BN': ! define . related) ords ?'&;: ! + *syntax (!( . + *description (Iarks the end of a definition.( *nl (;arsing ords can use this ord as a generic end delimiter.( . ! ?'&;: SNIEB&: + *syntax (SNIEB&: ord( . + *values + ( ord( (a ne ord to define( . . + *description (Cefines a ne symbol ord in the current vocabulary. Symbols push themselves on the stack hen executed< and are used to identify variables 5see ( + *link (namespaces( . (6 as ell as for storing crufties in ord properties 5see ( + *link ( ord)props( . (6.( . + *examples + *example (US': prettyprint( (IN: scratchpad( (SNIEB&: foo>nfoo .( (foo( . . ! + define)symbol ;BS$;BN': SNIEB&: ;BS$;BN': SNIEB&S: . related) ords ?'&;: SNIEB&S:

+ *syntax (SNIEB&S: ords... !( . + *values + ( ords( (a sequence of ne ords to define( . . + *description (%reates a ne symbol for every token until the ( + *snippet (!( . (.( . + *examples + *example (USING: prettyprint !( (IN: scratchpad( (SNIEB&S: foo bar ba8 !>nfoo . bar . ba8 .( (foo>nbar>nba8( . . ! ?'&;: SING&'$BN: + *syntax (SING&'$BN: class( . + *values + (class( (a ne singleton to define( . . + *description (Cefines a ne singleton class. $he class ord itself is the sole instance of the singleton class.( . + *examples + *example (USING: classes.singleton kernel io !( (IN: singleton)demo( (US': prettyprint SING&'$BN: foo>nG'N'#I%: bar 5 obF )) 6>nI: foo bar drop >(a fooK>( print !>nfoo bar( (a fooK( . . ! ?'&;: SING&'$BNS: + *syntax (SING&'$BNS: ords... !( . + *values + ( ords( (a sequence of ne ords to define( . . + *description (%reates a ne singleton for every token until the ( + *snippet (!( . (.( . ! ?'&;: "&I"S: + *syntax ("&I"S: ne ) ord existing) ord( . + *values + (ne ) ord( ord . + (existing) ord( ord . . + *description (%reates a ne inlined ord that calls the existing + *examples + *example (USING: prettyprint sequences !( (IN: alias.test( ("&I"S: sequence)nth nth( (= + 1= ,= -= . sequence)nth .( (1=( . . ! + define)alias ;BS$;BN': "&I"S: . related) ords ?'&;: %BNS$"N$: + *syntax (%BNS$"N$: ord value( . + *values + ( ord( ord . + (value( obFect . . + *description (%reates a ord hich pushes a value on the stack.( . + *examples + *code (%BNS$"N$: magic 1( (%BNS$"N$: science =xff=f( . . ! + define)constant ;BS$;BN': %BNS$"N$: . related) ords ?'&;: > + *syntax (>> ord( . + *values + ( ord( (a ord( . . + *description (#eads the next ord from the input and appends a rapper holding the ord to the parse tree. Jhen the evaluator encounters a rapper< it pushes the rapped ord literally on the data stack.( . + *examples ($he follo ing t o lines are equivalent:( + *code (= >> PvectorG execute>n= PvectorG( . (If ( + *snippet (foo( . ( is a symbol< the follo ing t o lines are equivalent:( + *code (foo( (>> foo( . . ! ?'&;: C'@'#:

ord.( .

+ *syntax (C'@'#: ord( . + *values + ( ord( (a ne ord to define( . . + *description (%reate a ord in the current vocabulary that simply raises an error hen executed. Usually< the ord ill be replaced ith a real definition later.( . + *notes (Cue to the ay the parser orks< ords cannot be referenced before they are defined! that is< source files must order definitions in a strictly bottom)up fashion. Iutually)recursive pairs of ords can be implemented by ( + *emphasis (deferring( . ( one of the ords in the pair allo ing the second ord in the pair to parse< then by defining the first ord.( . + *examples + *code (C'@'#: foe>n: fie ... foe ... !>n: foe ... fie ... !( . . ! ?'&;: @B#G'$: + *syntax (@B#G'$: ord( . + *values + ( ord( (a ord( . . + *description (#emoves the ord from its vocabulary< or does nothing if no such ord exists. 'xisting definitions that reference forgotten ords ill continue to ork< but ne occurrences of the ord ill not parse.( . ! ?'&;: US': + *syntax (US': vocabulary( . + *values + (vocabulary( (a vocabulary name( . . + *description ("dds a ne vocabulary to the search path< loading it first if necessary.( . + *notes (If adding the vocabulary introduces ambiguity< referencing the ambiguous names ill thro a ( + *link ambiguous)use)error . (.( . + *errors ($hro s an error if the vocabulary does not exist or could not be loaded.( . ! ?'&;: UNUS': + *syntax (UNUS': vocabulary( . + *values + (vocabulary( (a vocabulary name( . . + *description (#emoves a vocabulary from the search path.( . + *errors ($hro s an error if the vocabulary does not exist.( . ! ?'&;: USING: + *syntax (USING: vocabularies... !( . + *values + (vocabularies( (a list of vocabulary names( . . + *description ("dds a list of vocabularies to the search path.( . + *notes (If adding the vocabularies introduces ambiguity< referencing the ambiguous names ill thro a ( + *link ambiguous)use)error . (.( . + *errors ($hro s an error if one of the vocabularies does not exist.( . ! ?'&;: DU"&I@I'C: + *syntax (DU"&I@I'C: vocab( . + *description ("dds the vocabulary7s ords< prefixed ith the vocabulary name< to the search path.( . + *notes (If adding the vocabulary introduces ambiguity< the vocabulary ill take precedence hen resolving any ambiguous names. $his is a rare case! for example< suppose a vocabulary ( + *snippet (fish( . ( defines a ord named ( + *snippet (go:fishing( . (< and a vocabulary named ( + *snippet (go( . ( defines a ord named ( + *snippet (fishing( . (. $hen< the follo ing ill call the latter ord:( + *code (US': fish( (DU"&I@I'C: go( (go:fishing( . . + *examples + *example (USING: prettyprint !( (DU"&I@I'C: math(

(1 , math:2 .( (-( . . ! ?'&;: DU"&I@I'C)JI$?: + *syntax (DU"&I@I'C)JI$?: vocab ord)prefix( . + *description (&ike ( + *link ;BS$;BN': DU"&I@I'C: . ( but uses ( + *snippet ( ord)prefix( . ( as prefix.( . + *examples + *example (USING: prettyprint !( (DU"&I@I'C)JI$?: math m( (1 , m:2 .( (-( . . ! ?'&;: @#BI: + *syntax (@#BI: vocab HG ords ... !( . + *description ("dds ( + *snippet ( ords( . ( from ( + *snippet (vocab( . ( to the search path.( . + *notes (If adding the ords introduces ambiguity< the ords ill take precedence hen resolving any ambiguous names.( . + *examples (Eoth the ( + *vocab)link (vocabs.parser( . ( and ( + *vocab)link (binary)search( . ( vocabularies define a ord named ( + *snippet (search( . (. $he follo ing ill thro an ( + *link ambiguous)use)error . (:( + *code (USING: vocabs.parser binary)search !( (... search ...( . (Eecause ( + *link ;BS$;BN': @#BI: . ( takes precedence over a ( + *link ;BS$;BN': USING: . (< the ambiguity can be resolved explicitly. Suppose you anted the ( + *vocab)link (binary)search( . ( vocabulary7s ( + *snippet (search( . ( ord:( + *code (USING: vocabs.parser binary)search !( (@#BI: binary)search HG search !( (... search ...( . . ! ?'&;: 'M%&UC': + *syntax ('M%&UC': vocab + *description ("dds all + *snippet (vocab( . ( to + *examples + *code ('M%&UC': math.parser hexG( . . ! HG ords ... !( . ords except for ( + *snippet ( ords( . ( from ( the search path.( . HG binG hexG !( (K imports everything but binG and

?'&;: #'N"I': + *syntax (#'N"I': ord vocab HG ne )name( . + *description (Imports ( + *snippet ( ord( . ( from ( + *snippet (vocab( . (< but renamed to ( + *snippet (ne )name( . (.( . + *notes (If adding the ords introduces ambiguity< the ords ill take precedence hen resolving any ambiguous names.( . + *examples + *example (USING: prettyprint !( (#'N"I': 2 math HG )( (, - ) .( (A( . . ! ?'&;: IN: + *syntax (IN: vocabulary( . + *values + (vocabulary( (a ne vocabulary name( . . + *description (Sets the current vocabulary here ne ords ill be defined< creating the vocabulary first if it does not exist. "fter the vocabulary has been created< it can be listed in ( + *link ;BS$;BN': US': . ( and ( + *link ;BS$;BN': USING: . ( declarations.( . !

?'&;: %?"#: + *syntax (%?"#: token( . + *values + (token( (a literal character< escape code< or Unicode code point name( . . + *description ("dds a Unicode code point to the parse tree.( . + *examples + *code (%?"#: x( (%?"#: >>u====-,( (%?"#: >>u+exclamation)mark.( (%?"#: exclamation)mark( (%?"#: ugaritic)letter)samka( . . ! ?'&;: ( + *syntax (>(string...>(( (>(>(>(string...>(>(>(( . + *values + (string( (literal and escaped characters( . . + *description (#eads from the input string until the next occurrence of ( + *snippet (>(( . ( or ( + *snippet (>(>(>(( . (< and appends the resulting string to the parse tree. String literals can span multiple lines. Various special characters can be read by inserting ( + *link (escape( . (. @or triple quoted strings< the double)quote character does not require escaping.( . + *examples (" string ith an escaped ne line in it:( + *example (US': io( (>(?ello>>n orld>( print( (?ello>n orld( . (" string ith an actual ne line in it:( + *example (US': io( (>(?ello>n orld>( print( (?ello>n orld( . (" string ith a named Unicode code point:( + *example (US': io( (>(>>u+greek)capital)letter)sigma.>( print( (>u+greek)capital)letter)sigma.( . (" triple)quoted string:( + *example (US': io >(>(>($each a man to >(fish>(...>nand fish ill go extinct>(>(>( print( ((($each a man to >(fish>(... and fish ill go extinct((( . . ! ?'&;: SEU@( + *syntax (SEU@>( string... >(( . + *values + (string( (literal and escaped characters( . . + *description (#eads from the input string until the next occurrence of ( + *link ;BS$;BN': ( . (< converts the string to a string buffer< and appends it to the parse tree.( . + *examples + *example (USING: io strings !( (SEU@>( ?ello orld>( Gstring print( (?ello orld( . . ! ?'&;: ;( + *syntax (;>( pathname>(( . + *values + (pathname( (a pathname string( . . + *description (#eads from the input string until the next occurrence of ( + *link ;BS$;BN': ( . (< creates a ne ( + *link pathname . (< and appends it to the parse tree. ;athnames presented in the UI are clickable< hich opens them in a text editor configured ith ( + *link (editor( . (.( . + *examples + *example (USING: accessors io io.files !( (;>( foo.txt>( stringGG print( (foo.txt( . . ! ?'&;: 5 + *syntax (5 inputs )) outputs 6( . + *values + (inputs( (a list of tokens( . + (outputs( (a list of tokens( . . + *description (&iteral stack effect syntax. "lso used by syntax ords 5such as ( + *link ;BS$;BN': : . (6< typically declaring the stack effect of the ord

definition hich follo s.( . + *notes (Useful for meta)programming ith ( + *link define)declared . (.( . + *examples + *example (USING: compiler.units kernel math prettyprint random ords !( (IN: scratchpad( (( (SNIEB&: my)dynamic) ord( (( (0( ( my)dynamic) ord , + 0 2 3 0 4 3 . random curry( ( 5 x )) y 6 define)declared( (3 ith)compilation)unit( (( (, my)dynamic) ord .( (/( . . + *see)also (effects( . ! ?'&;: K + *syntax (K comment...( . + *values + (comment( (characters( . . + *description (Ciscards all input until the end of the line.( . ! + ;BS$;BN': K ;BS$;BN': ZK . related) ords ?'&;: ZK + *syntax (ZKcomment...( . + *values + (comment( (characters( . . + *description (Ciscards all input until the end of the line.( . + *notes ($o allo Unix)style >(shebang>( scripts to ork as expected< ( + *snippet (ZK( . ( is parsed as a separate token regardless of follo ing hitespace if it appears at the beginning of a line.( + *example (ZKQusrQbinQenvQfactor( (USING: io !( (>(?ello orld>( print( (?ello orld( . . ! ?'&;: N"N: + *syntax (N"N: payload( . + *values + (payload( (L/)bit hexadecimal integer( . . + *description ("dds a floating point Not)a)Number literal to the parse tree.( . + *examples + *example (US': prettyprint( (N"N: S====deadbeef .( (N"N: S====deadbeef( . . ! ?'&;: G'N'#I%: + *syntax (G'N'#I%: ord 5 stack )) effect 6( . + *values + ( ord( (a ne ord to define( . . + *description (Cefines a ne generic ord in the current vocabulary. Initially< it contains no methods< and thus ill thro a ( + *link no)method . ( error hen called.( . ! ?'&;: G'N'#I%Z

+ *syntax (G'N'#I%Z ord n 5 stack )) effect 6( . + *values + ( ord( (a ne ord to define( . + (n( (the stack position to dispatch on( . . + *description (Cefines a ne generic ord hich dispatches on the ( + *snippet (n( . (th most element from the top of the stack in the current vocabulary. Initially< it contains no methods< and thus ill thro a ( + *link no)method . ( error hen called.( . + *notes ($he follo ing t o definitions are equivalent:( + *code (G'N'#I%: foo 5 obF )) 6( . + *code (G'N'#I%Z foo = 5 obF )) 6( . . ! ?'&;: I"$?: + *syntax (I"$?: ord( . + *values + ( ord( (a ne ord to define( . . + *description (Cefines a ne generic ord hich uses the ( + *link math)combination . ( method combination.( . ! ?'&;: ?BBY: + *syntax (?BBY: ord variable 5 stack )) effect 6( . + *values + ( ord( (a ne ord to define( . + (variable( ord . . + *description (Cefines a ne hook ord in the current vocabulary. ?ook ords are generic ords hich dispatch on the value of a variable< so methods are defined ith ( + *link ;BS$;BN': I: . (. ?ook ords differ from other generic ords in that the dispatch value is removed from the stack before the chosen method is called.( . + *examples + *example (USING: io namespaces !( (IN: scratchpad( (SNIEB&: transport( ($U;&': land)transport !( ($U;&': air)transport !( (?BBY: deliver transport 5 destination )) 6( (I: land)transport deliver >(&and delivery to >( rite print !( (I: air)transport deliver >("ir delivery to >( rite print !( ($+ air)transport . transport set( (>(Ne Nork %ity>( deliver( ("ir delivery to Ne Nork %ity( . . + *notes (?ook ords are really Fust generic ords ith a custom method combination 5see ( + *link (method)combination( . (6.( . ! ?'&;: I: + *syntax (I: class generic definition... !( . + *values + (class( (a class ord( . + (generic( (a generic ord( . + (definition( (a method definition( . . + *description (Cefines a method< that is< a behavior for the generic speciali8ed on instances of the class.( . !

ord

?'&;: UNIBN: + *syntax (UNIBN: class members... !( . + *values + (class( (a ne class ord to define( . + (members( (a list of class ords separated by hitespace( . . + *description (Cefines a union class. "n obFect is an instance of a union class if it is an instance of one of its members.( . ! ?'&;: IN$'#S'%$IBN:

+ *syntax (IN$'#S'%$IBN: class participants... !( . + *values + (class( (a ne class ord to define( . + (participants( (a list of class ords separated by hitespace( . . + *description (Cefines an intersection class. "n obFect is an instance of an intersection class if it is an instance of all of its participants.( . ! ?'&;: IIMIN: + *syntax (IIMIN: class( . + *values + (class( (a ne class ord to define( . . + *description (Cefines a mixin class. " mixin is similar to a union class< except it has no members initially< and ne members can be added ith the ( + *link ;BS$;BN': INS$"N%': . ( ord.( . + *examples ($he ( + *link sequence . ( and ( + *link assoc . ( mixin classes.( . ! ?'&;: INS$"N%': + *syntax (INS$"N%': instance mixin( . + *values + (instance( (a class ord( . + (mixin( (a mixin class ord( . . + *description (Iakes ( + *snippet (instance( . ( an instance of ( + *snippet (mixin( . (.( . ! ?'&;: ;#'CI%"$': + *syntax (;#'CI%"$': class P superclass predicate... !( . + *values + (class( (a ne class ord to define( . + (superclass( (an existing class ord( . + (predicate( (membership test ith stack effect ( + *snippet (5 superclass )) : 6( . . . + *description (Cefines a predicate class deriving from ( + *snippet (superclass( . (.( *nl ("n obFect is an instance of a predicate class if t o conditions hold:( + *list (it is an instance of the predicate7s superclass<( (it satisfies the predicate( . ('ach predicate must be defined as a subclass of some other class. $his ensures that predicates inheriting from disFoint classes do not need to be exhaustively tested during method dispatch.( . + *examples + *code (USING: math !( (;#'CI%"$': positive P integer = G !( . . ! ?'&;: $U;&': + *syntax ($U;&': class slots... !( ($U;&': class P superclass slots ... !( . + *values + (class( (a ne tuple class to define( . + (slots( (a list of slot specifiers( . . + *description (Cefines a ne tuple class.( *nl ($he superclass is optional! if left unspecified< it defaults to ( + *link tuple . (.( *nl (Slot specifiers take one of the follo ing three forms:( + *list + + *snippet (name( . ( ) a slot hich can hold any obFect< ith no attributes( . + + *snippet (+ name attributes... .( . ( ) a slot hich can hold any obFect< ith optional attributes( . + + *snippet (+ name class attributes... .( . ( ) a slot speciali8ed to a specific class< ith optional attributes( . . (Slot attributes are lists of slot attribute specifiers follo ed by values! a slot attribute specifier is one of ( + *link initial: . ( or ( + *link read)only

. (. See ( + *link (tuple)declarations( . ( for details.( . + *examples (" simple tuple class:( + *code ($U;&': color red green blue !( . (Ceclaring slots to be integer)valued:( + *code ($U;&': color( (+ red integer .( (+ green integer .( (+ blue integer . !( . ("n example mixing short and long slot specifiers:( + *code ($U;&': person( (+ age integer initial: = .( (+ department string initial: >(Iarketing>( .( (manager !( . . ! ?'&;: final + *syntax ($U;&': ... ! final( . + *description (Ceclares the most recently defined ord as a final tuple class hich cannot be subclassed. "ttempting to subclass a final class raises a ( + *link bad)superclass . ( error.( . ! ?'&;: initial: + *syntax ($U;&': ... + slot initial: value . ... !( . + *values + (slot( (a slot name( . + (value( (any literal( . . + *description (Specifies an initial value for a tuple slot.( . ! ?'&;: read)only + *syntax ($U;&': ... + slot read)only . ... !( . + *values + (slot( (a slot name( . . + *description (Cefines a tuple slot to be read)only. If a tuple has read)only slots< instances of the tuple should only be created by calling ( + *link boa . (< instead of ( + *link ne . (. Using ( + *link boa . ( is the only ay to set the value of a read)only slot.( . ! + initial: read)only . related) ords ?'&;: S&B$: + *syntax (S&B$: name( . + *values + (name( (a slot name( . . + *description (Cefines a protocol slot! that is< defines the accessor ords for a slot named ( + *snippet (slot( . ( ithout associating it ith any specific tuple.( . ! ?'&;: '##B#: + *syntax ('##B#: class slots... !( . + *values + (class( (a ne tuple class to define( . + (slots( (a list of slot names( . . + *description (Cefines a ne tuple class hose class ord thro s a ne instance of the error.( . + *notes ($he follo ing t o snippets are equivalent:( + *code ('##B#: invalid)values x y !( (( ($U;&': invalid)values x y !( (: invalid)values 5 x y )) 4 6( ( >> invalid)values boa thro !( . . ! ?'&;: %: + *syntax (%: constructor class( . + *values + (constructor( (a ne ord to define( . + (class( tuple)class . . + *description (Cefine a constructor ord for a tuple class hich simply performs EB" 5by order of arguments6 construction using ( + *link boa . (.( .

+ *examples (Suppose the follo ing tuple has been defined:( + *code ($U;&': color red green blue !( . ($he follo ing t o lines are equivalent:( + *code (%: PcolorG color( (: PcolorG 5 red green blue )) color 6 color boa !( . (In both cases< a ord ( + *snippet (PcolorG( . ( is defined< hich reads three values from the stack and creates a ( + *snippet (color( . ( instance having these values in the ( + *snippet (red( . (< ( + *snippet (green( . ( and ( + *snippet (blue( . ( slots< respectively.( . ! ?'&;: I"IN: + *syntax (I"IN: ord( . + *values + ( ord( ord . . + *description (Cefines the main entry point for the current vocabulary and source file. $his ord ill be executed hen this vocabulary is passed to ( + *link run . ( or the source file is passed to ( + *link run)script . (.( . ! ?'&;: P;#IV"$' + *syntax (P;#IV"$' ... ;#IV"$'G( . + *description (Eegins a block of private ord definitions. ;rivate ord definitions are placed in the current vocabulary name< suffixed ith ( + *snippet (.private( . (.( . + *notes ($he follo ing is an example of usage:( + *code (IN: factorial( (( (P;#IV"$'( (( (: 5fac6 5 accum n )) nK 6( ( dup 1 PH 0 drop 3 0 0 4 3 keep 1 ) 5fac6 3 if !( (( (;#IV"$'G( (( (: fac 5 n )) nK 6 1 s ap 5fac6 !( . ($he above is equivalent to:( + *code (IN: factorial.private( (( (: 5fac6 5 accum n )) nK 6( ( dup 1 PH 0 drop 3 0 0 4 3 keep 1 ) 5fac6 3 if !( (( (IN: factorial( (( (: fac 5 n )) nK 6 1 s ap 5fac6 !( . . ! ?'&;: ;#IV"$'G + *syntax (P;#IV"$' ... ;#IV"$'G( . + *description ('nds a block of private

ord definitions.( . !

+ ;BS$;BN': P;#IV"$' ;BS$;BN': ;#IV"$'G . related) ords ?'&;: PP + *syntax (PP ... GG( . + *description ('valuates some code at parse time.( .

+ *notes (%alling ords defined in the same source file at parse time is prohibited! see compilation unit as here it as defined! see ( + *link (compilation)units( . (.( . ! ?'&;: GG + *syntax (GG( . + *description (Iarks the end of a parse time code block.( . ! ?'&;: call)next)method + *syntax (call)next)method( . + *description (%alls the next applicable method. Bnly valid inside a method definition. $he values at the top of the stack are passed on to the next method< and they must be compatible ith that method7s class speciali8er.( . + *notes ($his ord looks like an ordinary ord but it is a parsing ord. It cannot be factored out of a method definition< since the code expansion references the current method obFect directly.( . + *errors ($hro s a ( + *link no)next)method . ( error if this is the least specific method< and thro s an ( + *link inconsistent)next)method . ( error if the values at the top of the stack are not compatible ith the current method7s speciali8er.( . ! + ;BS$;BN': call)next)method 5call)next)method6 next)method . related) ords + ;BS$;BN': PP ;BS$;BN': GG . related) ords ?'&;: call5 + *syntax (call5 stack )) effect 6( . + *description (%alls the quotation on the top of the stack< asserting that it has the given stack effect. $he quotation does not need to be kno n at compile time.( . + *examples + *code ($U;&': action name quot !( (: perform)action 5 action )) 6( ( 0 nameGG print 3 0 quotGG call5 )) 6 3 bi !( . . ! ?'&;: execute5 + *syntax (execute5 stack )) effect 6( . + *description (%alls the ord on the top of the stack< asserting that it has the given stack effect. $he ord does not need to be kno n at compile time.( . + *examples + *code (IN: scratchpad( (( (: eat 5 )) 6 ! : sleep 5 )) 6 ! : hack 5 )) 6 !( (+ eat sleep hack . 0 execute5 )) 6 3 each( . . ! + ;BS$;BN': call5 ;BS$;BN': execute5 . related) ords K %opyright 5%6 ,==L< ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays kernel kernel.private math sequences sequences.private slots.private ! IN: quotations EUI&$IN: quotation + array array read)only initial: + . .

cached)effect cache)counter ! P;#IV"$' : uncurry 5 curry )) obF quot 6 + curry . declare dup , slot s ap - slot ! inline : uncompose 5 compose )) quot quot, 6 + compose . declare dup , slot s ap - slot ! inline ;#IV"$'G I: quotation call 5call6 ! I: curry call uncurry call ! I: compose call uncompose 0 call 3 dip call ! I: rapper equal: over rapper: 0 0 rappedGG 3 same: 3 0 ,drop f 3 if !

UNIBN: callable quotation curry compose ! I: callable equal: over callable: 0 sequenceH 3 0 ,drop f 3 if ! I: quotation length arrayGG length ! I: quotation nth)unsafe arrayGG nth)unsafe ! : Gquotation 5 seq )) quot 6 Garray arrayGquotation ! inline I: callable like drop dup quotation: 0 Gquotation 3 unless ! INS$"N%': quotation immutable)sequence : 1quotation 5 obF )) quot 6 1array Gquotation ! G'N'#I%: literali8e 5 obF )) I: obFect literali8e ! I: rapper literali8e P rapperG ! rapped 6

I: curry length quotGG length 1 2 ! I: curry nth over = H 0 nip obFGG literali8e 3 0 0 1 ) 3 dip quotGG nth 3 if ! INS$"N%': curry immutable)sequence I: compose length 0 firstGG length 3 0 secondGG length 3 bi 2 ! I: compose virtual)exemplar firstGG ! I: compose virtual9

,dup firstGG length P 0 firstGG 3 0 0 firstGG length ) 3 0 secondGG 3 bi 3 if ! INS$"N%': compose virtual)sequence USING: arrays help.markup help.syntax strings sbufs vectors kernel combinators ! IN: quotations "#$I%&': (quotations( (Duotations( (" quotation is an anonymous function 5a value denoting a snippet of code6 hich can be used as a value and called using the ( + *link (call( . (.( *nl (Duotation literals appearing in source code are delimited by square brackets< for example ( + *snippet (0 , 2 3( . (! see ( + *link (syntax)quots( . ( for details on their syntax.( *nl (Duotations form a class of obFects:( + *subsections quotation quotation: . (" more general class is provided for methods to dispatch on that includes quotations< ( + *link curry . (< and ( + *link compose . ( obFects:( + *subsections callable . (Duotations evaluate sequentially from beginning to end. &iterals are pushed on the stack and ords are executed. Cetails can be found in ( + *link (evaluator( . (. Jords can be placed in rappers to suppress execution:( + *subsections ( rappers( . (Duotations implement the ( + *link (sequence)protocol( . (< and existing sequences can be converted into quotations:( + *subsections Gquotation 1quotation . ("lthough quotations can be treated as sequences< the compiler ill be unable to reason about quotations manipulated as sequences at runtime. ( + *link (compositional)combinators( . ( are provided for runtime partial application and composition of quotations.( ! "#$I%&': ( rappers( (Jrappers( (Jrappers evaluate to the obFect being rapped hen encountered in code. $hey are used to suppress the execution of ( + *link ( ords( . ( so that they can be used as values.( + *subsections rapper literali8e . (Jrapper literal syntax is documented in ( + *link (syntax) ords( . (.( + *example (IN: scratchpad( (C'@'#: my) ord( (>> my) ord nameGG .( (>(my) ord>(( . + *see)also (combinators( . ! "EBU$: (quotations(

?'&;: callable + *class)description ($he class hose instances can be passed to ( + *link call . (. $his includes quotations and composed quotations built up ith ( + *link curry . ( or ( + *link compose . (.( . ! ?'&;: quotation + *description ($he class of quotations. See ( + *link (syntax)quots( . ( for syntax and ( + *link (quotations( . ( for general information.( . ! ?'&;: Gquotation + *values + (seq( (a sequence( . + (quot( quotation . . + *description (Butputs a freshly)allocated quotation ith the same elements as a given sequence.( . ! ?'&;: 1quotation + *values + (obF( obFect . + (quot( quotation . . + *description (%onstructs a quotation holding one element.( . + *notes ($he follo ing t o phrases are equivalent:( + *code (>> reverse execute( . + *code (>> reverse 1quotation call( . . ! ?'&;: rapper + *description ($he class of rappers. Jrappers are created by calling ( + *link literali8e . (. See ( + *link (syntax) ords( . ( for syntax.( . ! ?'&;: P rapperG + *values + (obF( obFect . + ( rapper( rapper . . + *description (%reates an obFect hich pushes ( + *snippet (obF( . ( on the stack hen evaluated. User code should call ( + *link literali8e . ( instead< since it avoids rapping self)evaluating obFects 5 hich is redundant6.( . ! ?'&;: literali8e + *values + (obF( obFect . + ( rapped( obFect . . + *description (Butputs an obFect hich evaluates to ( + *snippet (obF( . ( hen placed in a quotation. If ( + *snippet (obF( . ( is not self)evaluating 5for example< it is a ord6< then it ill be rapped.( . + *examples + *example (USING: prettyprint quotations !( (A literali8e .( (A( . + *example (USING: math prettyprint quotations sequences !( (0 2 3 0 literali8e 3 map .( (0 >> 2 3( . . ! + literali8e curry P rapperG ;BS$;BN': > ;BS$;BN': J+ . related) ords USING: math kernel quotations tools.test sequences ! IN: quotations.tests 0 0 - 3 3 0 - 0 3 curry 3 unit)test 0 0 > 2 3 3 0 > 2 0 3 curry 3 unit)test 0 0 > 2 H 3 3 0 > 2 0 H 3 curry 3 unit)test 0 0 1 2 , 2 - 2 3 3 0 + 1 , - . 0 0 2 3 curry 3 map concat 3 unit)test 0 0 1 , - / 3 3 0 0 1 , 3 0 - / 3 append 3 unit)test 0 0 1 , - 3 3 0 0 1 , 3 - suffix 3 unit)test 0 0 - 1 , 3 3 0 0 1 , 3 - prefix 3 unit)test 0 0 (hi( 3 3 0 (hi( 1quotation 3 unit)test

0 1 > 2 curry 3 must)fail K %opyright 5%6 ,==U< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes classes.algebra combinators combinators.private definitions effects generic hashtables kernel layouts make math namespaces quotations sequences ords ! @#BI: assocs HG change)at ! IN: generic.single '##B#: no)method obFect generic ! '##B#: inconsistent)next)method class generic ! $U;&': single)combination ! ;#'CI%"$': single)generic P generic (combination( ord)prop single)combination: ! I: single)generic make)inline cannot)be)inline ! G'N'#I%: dispatchZ 5 ord )) n 6 ord)prop dispatchZ !

I: generic dispatchZ (combination( SNIEB&: SNIEB&: SNIEB&: SNIEB&: : assumed default generic) ord combination

ith)combination 5 combination quot )) 6 0 combination 3 dip ith)variable ! inline

?BBY: picker combination 5 )) quot 6 I: single)combination next)method)quot4 5 class generic combination )) quot 6 0 ,dup next)method dup 0 0 pick predicate)def W 1quotation < 0 inconsistent)next)method 3 ,curry < > if < 3 0 3 make picker prepend 3 0 -drop f 3 if 3 ith)combination ! : method)for)obFect 5 obF ord )) method 6 0 0 method)classes 0 instance: 3 ith filter smallest)class 3 keep :lookup)method 3 0 (default)method( ord)prop 3 bi or ! I: single)combination make)default)method 0 0 picker 3 dip 0 no)method 3 curry append 3 K K K Euild an engine K K K : find)default 5 methods )) default 6 ZK Side)effects methods. ith)combination !

0 obFect bootstrap) ord 3 dip delete)at4 0 drop generic) ord get (default)method( 3 unless ! K 1. @latten methods $U;&': predicate)engine class methods ! %: Ppredicate)engineG predicate)engine

ord)prop

: push)method 5 method class atomic assoc )) 6 dupd 0 0 3 0 ?+ . clone Ppredicate)engineG 3 :if 0 methodsGG set)at 3 keep 3 change)at ! : flatten)method 5 method class assoc )) 6 over flatten)class keys 0 s ap push)method 3 ith ith ith each ! : flatten)methods 5 assoc )) assoc7 6 ?+ . clone 0 0 s apd flatten)method 3 curry assoc)each 3 keep ! K ,. %onvert methods : split)methods 5 assoc class )) first second 6 0 0 nip classPH not 3 curry assoc)filter 3 0 0 nip classPH 3 curry assoc)filter 3 ,bi ! : convert)methods 5 assoc class ord )) assoc7 6 over 0 split)methods 3 ,dip pick assoc)empty: 0 -drop 3 0 0 execute 3 dip pick set)at 3 if ! inline K ,.1 %onvert tuple methods $U;&': echelon)dispatch)engine n methods ! %: Pechelon)dispatch)engineG echelon)dispatch)engine $U;&': tuple)dispatch)engine echelons ! : push)echelon 5 class method assoc )) 6 0 s ap dup (layout( ord)prop third 3 dip 0 :set)at 3 change)at ! : echelon)sort 5 assoc )) assoc7 6 ZK %onvert an assoc mapping classes to methods into an ZK assoc mapping echelons to assocs. $he first echelon ZK is al ays there ?+ + = f . . clone 0 0 push)echelon 3 curry assoc)each 3 keep ! : copy)superclass)methods 5 engine superclass assoc )) 6 at4 0 0 methodsGG 3 bi9 assoc)unionK drop 3 0 ,drop 3 if ! : copy)superclasses)methods 5 class engine assoc )) 6 0 superclasses 3 ,dip 0 s apd copy)superclass)methods 3 ,curry each ! : convert)tuple)inheritance 5 assoc )) assoc7 6 ZK " method on a superclass " might have a higher precedence ZK than a method on a subclass E< if the methods are ZK defined on incomparable classes that happen to contain ZK " and E< respectively. %opy "7s methods into E7s set so ZK that they can be sorted and selected properly. dup dup 0 copy)superclasses)methods 3 curry assoc)each !

: Ptuple)dispatch)engineG 5 methods )) engine 6 convert)tuple)inheritance echelon)sort 0 dupd Pechelon)dispatch)engineG 3 assoc)map > tuple)dispatch)engine boa ! : convert)tuple)methods 5 assoc )) assoc7 6 tuple bootstrap) ord > Ptuple)dispatch)engineG convert)methods ! K - $ag methods $U;&': tag)dispatch)engine methods ! %: Ptag)dispatch)engineG tag)dispatch)engine : PengineG 5 assoc )) engine 6 flatten)methods convert)tuple)methods Ptag)dispatch)engineG ! K K K %ompile engine K K K G'N'#I%: compile)engine 5 engine )) obF 6 : compile)engines 5 assoc )) assoc7 6 0 compile)engine 3 assoc)map ! : compile)engines4 5 assoc )) assoc7 6 0 over assumed 0 compile)engine 3 ith)variable 3 assoc)map ! : direct)dispatch)table 5 assoc n )) table 6 default get ParrayG PenumG s ap assoc)unionK seqGG ! : tag)number 5 class )) n 6 (type( ord)prop !

I: tag)dispatch)engine compile)engine methodsGG compile)engines4 0 0 tag)number 3 dip 3 assoc)map num)types get direct)dispatch)table ! : build)fast)hash 5 methods )) buckets 6 Galist V+ . clone 0 hashcode 1array 3 distribute)buckets 0 compile)engines4 Galist concat 3 map ! I: echelon)dispatch)engine compile)engine dup nGG = H 0 methodsGG dup assoc)si8e + + = 0 drop default get 3 . + 1 0 Galist first second compile)engine 3 . . case 3 0 methodsGG compile)engines4 build)fast)hash 3 if ! I: tuple)dispatch)engine compile)engine tuple assumed 0 echelonsGG compile)engines dup keys supremum 1 2 f ParrayG PenumG s ap assoc)unionK seqGG 3 ith)variable ! ;#'CI%"$': predicate)engine) ord P ord (o ner)generic( ord)prop !

SNIEB&: predicate)engines : sort)methods 5 assoc )) assoc7 6 Galist 0 keys sort)classes 3 keep extract)keys ! : quote)methods 5 assoc )) assoc7 6 0 1quotation > drop prefix 3 assoc)map ! : find)predicate)engine 5 classes )) ord 6 predicate)engines get 0 at 3 curry map)find drop ! : next)predicate)engine 5 engine )) classGG superclasses find)predicate)engine default get or ! ord 6

: methods) ith)default 5 engine )) assoc 6 0 methodsGG clone 3 0 next)predicate)engine 3 bi obFect bootstrap) ord pick set)at ! : keep)going: 5 assoc )) : 6 assumed get s ap second first classPH ! '##B#: unreachable ! : prune)redundant)predicates 5 assoc )) default assoc7 6 + + 0 dup empty: 3 0 drop 0 unreachable 3 + . 3 . + 0 dup length 1 H 3 0 first second + . 3 . + 0 dup keep)going: 3 0 rest)slice prune)redundant)predicates 3 . 0 0 first second 3 0 rest)slice 3 bi 3 . cond ! : class)predicates 5 assoc )) assoc 6 0 0 predicate)def 0 dup 3 prepend 3 dip 3 assoc)map ! : Ppredicate)engine) ordG 5 )) ord 6 generic) ord get nameGG (Qpredicate)engine( append f P ordG dup generic) ord get (o ner)generic( set) ord)prop ! I: predicate)engine) ord stack)effect (o ner)generic( : define)predicate)engine 5 alist )) ord 6 0 Ppredicate)engine) ordG 3 dip 0 define 3 0 drop generic) ord get (engines( ,tri ! ord)prop stack)effect !

ord)prop push 3 0 drop 3

: compile)predicate)engine 5 engine )) ord 6 methods) ith)default sort)methods quote)methods prune)redundant)predicates class)predicates 0 last 3 0 alistGquot picker prepend define)predicate)engine 3 if)empty ! I: predicate)engine compile)engine 0 compile)predicate)engine 3 0 classGG 3 bi 0 drop 3 0 predicate)engines get set)at 3 ,bi ! I: ord compile)engine !

I: f compile)engine !

: build)decision)tree 5 generic )) methods 6 0 (engines( ord)prop forget)all 3 0 V+ . clone (engines( set) ord)prop 3 0 (methods( ord)prop clone 0 find)default default set 3 0 PengineG compile)engine 3 bi 3 tri ! ?BBY: inline)cache)quots combination 5 pic)tail)quotQf 6 ord methods )) pic)quotQf

I: single)combination inline)cache)quots ,drop f f ! : define)inline)cache)quot 5 ord methods )) 6 0 drop 3 0 inline)cache)quots 3 ,bi 0 GGpic)def 3 0 GGpic)tail)def 3 bi4 drop ! ?BBY: mega)cache)quot combination 5 methods )) quotQf 6 I: single)combination perform)combination 0 ?+ . clone predicate)engines set dup generic) ord set dup build)decision)tree 0 (decision)tree( set) ord)prop 3 0 mega)cache)quot define 3 0 define)inline)cache)quot 3 ,tri 3 ith)combination ! USING: generic help.markup help.syntax sequences math math.parser effects ! IN: generic.single ?'&;: no)method + *values + (obFect( (an obFect( . + (generic( (a generic ord( . . + *description ($hro s a ( + *link no)method . ( error.( . + *error)description ($hro n by the ( + *snippet (generic( . ( ord to indicate it does not have a method for the class of ( + *snippet (obFect( . (.( . ! ?'&;: inconsistent)next)method + *error)description ($hro n by ( + *link ;BS$;BN': call)next)method . ( if the values on the stack are not compatible ith the current method.( . + *examples ($he follo ing code thro s this error:( + *code (G'N'#I%: error)test 5 obFect )) 6( (( (I: string error)test print !( (( (I: integer error)test numberGstring call)next)method !( (( (1,- error)test( . ($his results in the method on ( + *link integer . ( being called< hich then passes a string to ( + *link ;BS$;BN': call)next)method . (. ?o ever< this fails because the string is not compatible ith the current method.( *nl ($his usually indicates programmer error! if the intention above as to call the string method on the result of ( + *link numberGstring . (< the code should

be re ritten as follo s:( + *code (I: integer error)test numberGstring error)test !( . . !USING: generic generic.single generic.standard help.markup help.syntax sequences math math.parser effects ! IN: generic.hook ?'&;: hook)combination + *class)description (;erforms hook method combination . See ( + *link ;BS$;BN': ?BBY: . (.( . ! + standard)combination hook)combination . related) ordsUSING: arrays generic generic.single gro able kernel math namespaces sequences strings tools.test vectors ords ! IN: generic.hook.tests SNIEB&: my)var ?BBY: my)hook my)var 5 )) x 6 I: integer my)hook (an integer( ! I: string my)hook (a string( ! 0 (an integer( 3 0 - my)var set my)hook 3 unit)test 0 (a string( 3 0 my)hook my)var set my)hook 3 unit)test 0 1.= my)var set my)hook 3 0 $+ no)method f 1.= my)hook . H 3 must)fail) ith ?BBY: call)next)hooker my)var 5 )) x 6 I: sequence call)next)hooker (sequence( ! I: array call)next)hooker call)next)method (array ( prepend ! I: vector call)next)hooker call)next)method (vector ( prepend ! I: gro able call)next)hooker call)next)method (gro able ( prepend ! 0 (vector gro able sequence( 3 0 V+ . my)var 0 call)next)hooker 3 3 unit)test ith)variable

0 t 3 0 + . > nth effective)method nip I> sequence nth eq: 3 unit)test 0 t 3 0 > 2 > nth effective)method nip dup > nth (default)method( 3 unit)test K %opyright 5%6 ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors definitions generic generic.single kernel kernel.private namespaces quotations sequences ords ! DU"&I@I'C)JI$?: generic.single.private gsp IN: generic.hook $U;&': hook)combination P single)combination var ! %: Phook)combinationG hook)combination ;#'CI%"$': hook)generic P generic (combination( ord)prop hook)combination: ! ord)prop eq: and

I: hook)combination picker combination get varGG 0 get 3 curry ! I: hook)combination dispatchZ drop = ! I: hook)combination mega)cache)quot 1quotation picker 0 gsp:lookup)method 5execute6 3 surround ! I: hook)generic definer drop > ?BBY: f ! I: hook)generic effective)method 0 (combination( ord)prop varGG get 3 keep method)for)obFect ! USING: generic.parser tools.test ! IN: generic.parser.tests 0 0 0 0 t t f f 3 3 3 3 0 0 0 0 5 5 5 5 )) 6 5 a )) b a b )) a )) b )) 6 method)effectH 3 unit)test 6 5 x )) y 6 method)effectH 3 unit)test c 6 5 x )) y 6 method)effectH 3 unit)test 6 5 x y )) 8 6 method)effectH 3 unit)test

0 t 3 0 5 )) 4 6 5 )) 6 method)effectH 3 unit)test 0 f 3 0 5 )) 4 6 5 x )) y 6 method)effectH 3 unit)test 0 t 3 0 5 x )) 4 6 5 x )) y 6 method)effectH 3 unit)test 0 t 3 0 5 x )) 4 6 5 x )) y 8 6 method)effectH 3 unit)test K %opyright 5%6 ,==S< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays combinators effects.parser generic kernel namespaces parser quotations sequences ords ! IN: generic.parser '##B#: not)in)a)method)error ! : scan)ne )generic 5 )) ord 6 scan)ne dup reset) ord !

: 5G'N'#I%:6 5 quot )) 6 0 scan)ne )generic 3 dip call scan)effect define)generic ! inline : create)method)in 5 class generic )) method 6 create)method dup set)last) ord dup save)location ! : define)inline)method 5 class generic quot )) 6 0 create)method)in 3 dip 0 define 3 0 drop make)inline 3 ,bi ! : scan)ne )method 5 )) method 6 scan)class bootstrap) ord scan) ord create)method)in ! SNIEB&: current)method : ith)method)definition 5 method quot )) 6 over current)method set call current)method off ! inline ord)prop !

: generic)effect 5 ord )) effect 6 (method)generic( ord)prop (declared)effect(

: method)effectH 5 method)effect generic)effect )) : 6 0 0 inGG length 3 same: 3 0 over terminated:GG 0 ,drop t 3 0 0 outGG length 3 same: 3 if 3 ,bi and !

'##B#: bad)method)effect ! : check)method)effect 5 effect )) 6 last) ord generic)effect method)effectH 0 bad)method)effect 3 unless ! : :execute)parsing 5 ordQnumber )) seq 6 dup parsing) ord: 0 V+ . clone s ap execute)parsing 3 0 1array 3 if ! : parse)method)definition 5 )) quot 6 scan)datum + + > 5 0 (6( parse)effect check)method)effect parse)definition 3 . + > ! 0 0 3 3 . 0 :execute)parsing > ! parse)until append Gquotation 3 . case ! ;#IV"$'G : 5I:6 5 )) method def 6 0 scan)ne )method 0 parse)method)definition 3 ith)method)definition 3 ith)definition ! USING: help.markup help.syntax ords classes classes.algebra definitions kernel alien sequences math quotations generic.single generic.standard generic.hook generic.math combinators prettyprint effects ! IN: generic "#$I%&': (method)order( (Iethod precedence( (%onceptually< method dispatch is implemented by testing the obFect against the predicate ord for every class< in linear order 5( + *link (class)lineari8ation( . (6.( *nl (?ere is an example:( + *code (G'N'#I%: explain 5 obFect )) 6( (I: obFect explain drop >(an obFect>( print !( (I: generic explain drop >(a generic ord>( print !( (I: class explain drop >(a class ord>( print !( . ($he linear order is the follo ing< from least)specific to most)specific:( + *code (+ obFect generic class .( . (Neither ( + *link class . ( nor ( + *link generic . ( are subclasses of each other< and their intersection is non)empty. %alling ( + *snippet (explain( . ( ith a ord on the stack that is both a class and a generic ord ill print ( + *snippet (a class ord( . ( because ( + *link class . ( is more specific than ( + *link generic . ( in the class lineari8ation order. 5Bne example of a ord hich is both a class and a generic ord is the class of classes< ( + *link class . (< hich is also a ord to get the class of an obFect.6( *nl ($he ( + *link order . ( ord can be useful to clarify method dispatch order:( + *subsections order . ! "#$I%&': (generic)introspection( (Generic ord introspection( (In most cases< generic ords and methods are defined at parse time ith ( + *link ;BS$;BN': G'N'#I%: . ( 5or some other parsing ord6 and ( + *link ;BS$;BN': I: . (.( *nl (Sometimes< generic ords need to be inspected or defined at run time! ords for performing these tasks are found in the ( + *vocab)link (generic( . ( vocabulary.(

*nl ($he set of generic ords is a class hich implements the ( + *link (definition)protocol( . (:( + *subsections generic generic: . (Ne generic ords can be defined:( + *subsections define)generic define)simple)generic . (Iethods can be added to existing generic ords:( + *subsections create)method . (Iethod definitions can be looked up:( + *subsections lookup)method :lookup)method . (@inding the most specific method for an obFect:( + *subsections effective)method . (" generic ord contains methods! the list of methods speciali8ing on a class can also be obtained:( + *subsections implementors . (&o )level ord hich rebuilds the generic ord after methods are added or removed< or the method combination is changed:( + *subsections make)generic . (&o )level method constructor:( + *subsections PmethodG . (Iethods may be pushed on the stack ith a literal syntax:( + *subsections ;BS$;BN': I> . + *see)also (see( . ! "#$I%&': (method)combination( (%ustom method combination( ("bstractly< a generic ord can be thought of as a big chain of type conditional tests applied to the top of the stack< ith methods as the bodies of each test. $he ( + *emphasis (method combination( . ( is this control flo glue bet een the set of methods< and several aspects of it can be customi8ed:( + *list ( hich stack item5s6 the generic ord dispatches upon<( ( hich methods out of the set of applicable methods are called( . (" table of built)in method combination defining ords< and the method combinations themselves:( + *table + + *link ;BS$;BN': G'N'#I%: . + *link standard)combination . . + + *link ;BS$;BN': G'N'#I%Z . + *link standard)combination . . + + *link ;BS$;BN': ?BBY: . + *link hook)combination . . + + *link ;BS$;BN': I"$?: . + *link math)combination . . . (Ceveloping a custom method combination requires that a parsing ord calling ( + *link define)generic . ( be defined! additionally< it is a good idea to implement the ( + *link (definition)protocol( . ( on the class of ords having this method combination< to properly support developer tools.( *nl ($he combination quotation passed to ( + *link define)generic . ( has stack effect ( + *snippet (5 ord )) quot 6( . (. It7s Fob is to call various introspection ords< including at least obtaining the set of methods defined on the generic ord< then combining these methods in some ay to produce a quotation.( + *see)also (generic)introspection( . ! "#$I%&': (call)next)method( (%alling less)specific methods( (If a generic ord is called ith an obFect and multiple methods speciali8e on classes that this obFect is an instance of< usually the most specific method is

called 5( + *link (method)order( . (6.( *nl (&ess)specific methods can be called directly:( + *subsections ;BS$;BN': call)next)method . (" lo er)level ord hich the above expands into:( + *subsections 5call)next)method6 . ($o look up the next applicable method reflectively:( + *subsections next)method . ('rrors thro n by improper calls to ( + *link ;BS$;BN': call)next)method . (:( + *subsections inconsistent)next)method no)next)method . ! "#$I%&': (generic( (Generic ords and methods( (" ( + *emphasis (generic ord( . ( is composed of 8ero or more ( + *emphasis (methods( . ( together ith a ( + *emphasis (method combination( . (. " method ( + *emphasis (speciali8es( . ( on a class! hen a generic ord is executed< the method combination chooses the most appropriate method and calls its definition.( *nl (" generic ord behaves roughly like a long series of class predicate conditionals in a ( + *link cond . ( form< ho ever methods can be defined in independent source files< reducing coupling and increasing extensibility. $he method combination determines hich obFect the generic ord ill ( + *emphasis (dispatch( . ( on! this could be the top of the stack< or some other value.( *nl (Generic ords hich dispatch on the obFect at the top of the stack:( + *subsections ;BS$;BN': G'N'#I%: . (" method combination hich dispatches on a specified stack position:( + *subsections ;BS$;BN': G'N'#I%Z . (" method combination hich dispatches on the value of a variable at the time the generic ord is called:( + *subsections ;BS$;BN': ?BBY: . (" method combination hich dispatches on a pair of stack values< hich must be numbers< and upgrades both to the same type of number:( + *subsections ;BS$;BN': I"$?: . (Iethod definition:( + *subsections ;BS$;BN': I: . (Generic ords must declare their stack effect in order to compile. See ( + *link (effects( . (.( + *subsections (method)order( (call)next)method( (method)combination( (generic)introspection( . (Generic ords speciali8e behavior based on the class of an obFect! sometimes behavior needs to be speciali8ed on the obFect7s ( + *emphasis (structure( . (! this is kno n as ( + *emphasis (pattern matching( . ( and is implemented in the ( + *vocab)link (match( . ( vocabulary.( ! "EBU$: (generic( ?'&;: generic + *class)description ($he class of generic (generic( . (.( . ! ords< documented in ( + *link

+ generic define)generic define)simple)generic ;BS$;BN': G'N'#I%: ;BS$;BN': G'N'#I%Z ;BS$;BN': I"$?: ;BS$;BN': ?BBY: . related) ords ?'&;: make)generic

+ *values + ( ord( generic . . + *description (#egenerates the definition of a generic method combination to the set of defined methods.( . *lo )level)note !

ord by applying the

?'&;: define)generic + *values + ( ord( ord . + (combination( (a method combination( . + (effect( effect . . + *description (Cefines a generic ord. " method combination is an obFect hich responds to the ( + *link perform)combination . ( generic ord.( . + *contract ($he method combination quotation is called each time the generic ord has to be updated 5for example< hen a method is added6< and thus must be side)effect free.( . ! ?'&;: I> + *syntax (I>> class generic( . + *class)description (;ushes a method on the stack.( . + *examples + *code (I>> fixnum 2 see( . + *code (USING: ui.gadgets.editors ui.render !( (I>> editor dra )gadget4 edit( . . ! ?'&;: lookup)method + *values + (class( class . + (generic( generic . + (method( method . . + *description (&ooks up a method definition.( . + *class)description ($he class of method bodies< hich are ords ith special ord properties set.( . + *errors ($hro s an error if the method does not exist.( . ! ?'&;: :lookup)method + *values + (class( class . + (generic( generic . + (methodQf( + *maybe method . . . + *description (&ooks up a method definition.( . + *class)description ($he class of method bodies< hich are ords ith special ord properties set.( . ! + lookup)method :lookup)method create)method ;BS$;BN': I: . related) ords ?'&;: PmethodG + *values + (class( class . + (generic( generic . + (method( (a ne definition( . . + *description (%reates a ne method.( . ! method

?'&;: order + *values + (generic( generic . + (seq( (a sequence of classes( . . + *description (Butputs a sequence of classes for hich methods have been defined on this generic ord. $he sequence is sorted in method dispatch order.( . ! ?'&;: check)method + *values + (class( class . + (generic( generic . . + *description ("sserts that ( + *snippet (class( . ( is a class ord and ( + *snippet (generic( . ( is a generic ord< thro ing a ( + *link check)method . ( error if the assertion fails.( . + *error)description ($hro n if ( + *link ;BS$;BN': I: . ( or ( + *link create)method . ( is given an invalid class or generic ord.( . ! ?'&;: ith)methods + *values + (class( class . + (generic( generic . + (quot( + *quotation (5 methods )) 6( . . . + *description ("pplies a quotation to the generic ord7s methods hashtable< and regenerates the generic ord7s definition hen the quotation returns.( . *lo )level)note !

?'&;: create)method + *values + (class( class . + (generic( generic . + (method( method . . + *description (%reates a method or returns an existing one. $his is the runtime equivalent of ( + *link ;BS$;BN': I: . (.( . + *notes ($o define a method< pass the output value to ( + *link define . (.( . ! + sort)classes order . related) ords ?'&;: 5call)next)method6 + *values + (method( method . . + *description (&o )level ord implementing ( + *link ;BS$;BN': call)next)method . (.( . + *notes ($he ( + *link ;BS$;BN': call)next)method . ( ord parses into this ord. $he follo ing are equivalent:( + *code (I: class generic call)next)method !( (I: class generic I>> class generic 5call)next)method6 !( . . ! ?'&;: no)next)method + *error)description ($hro n by ( + *link ;BS$;BN': call)next)method . ( if the current method is already the least specific method.( . + *examples ($he follo ing code thro s this error:( + *code (G'N'#I%: error)test 5 obFect )) 6( (( (I: number error)test - 2 call)next)method !( (( (I: integer error)test recip call)next)method !( (( (1,- error)test( . ($his results in the method on ( + *link integer . ( being called< hich then calls the method on ( + *link number . (. $he latter then calls ( + *link ;BS$;BN': call)next)method . (< ho ever there is no method less specific than the method on ( + *link number . ( and so an error is thro n.( . ! K %opyright 5%6 ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays combinators definitions generic generic.single generic.single.private kernel layouts make math namespaces quotations sequences ords ! IN: generic.standard '##B#: bad)dispatch)position Z ! $U;&': standard)combination P single)combination Z ! : Pstandard)combinationG 5 Z )) standard)combination 6 dup = P 0 bad)dispatch)position 3 hen standard)combination boa ! ;#'CI%"$': standard)generic P generic (combination( ord)prop standard)combination: ! ;#'CI%"$': simple)generic P standard)generic (combination( ord)prop ZGG = H !

%BNS$"N$: simple)combination $+ standard)combination f = . : define)simple)generic 5 ord effect )) 6 0 simple)combination 3 dip define)generic ! : 5picker6 5 n )) quot 6 + + = 0 0 dup 3 3 . + 1 0 0 over 3 3 . + , 0 0 pick 3 3 . 0 1 ) 5picker6 0 dip s ap 3 curry 3 . case ! I: standard)combination picker combination get ZGG 5picker6 ! I: standard)combination dispatchZ ZGG ! I: standard)generic effective)method 0 datastack 3 dip 0 (combination( method)for)obFect ! ord)prop ZGG s ap PreversedG nth 3 keep

: inline)cache)quot 5 ord methods miss) ord )) quot 6 0 0 literali8e < 3 0 < 3 0 combination get ZGG < + . < < 3 tri4 3 0 3 make ! I: standard)combination inline)cache)quots ZK Cirect calls to the generic ord 5not tail calls or indirect calls6 ZK ill Fump to the inline cache entry point instead of the megamorphic ZK dispatch entry point. 0 > inline)cache)miss inline)cache)quot 3 0 > inline)cache)miss)tail inline)cache)quot 3 ,bi ! : make)empty)cache 5 )) array 6 mega)cache)si8e get f ParrayG ! I: standard)combination mega)cache)quot combination get ZGG make)empty)cache > mega)cache)lookup 0 3 /sequence ! I: standard)generic definer drop > G'N'#I%Z f ! I: simple)generic definer drop > G'N'#I%: f ! USING: generic generic.single help.markup help.syntax sequences math math.parser effects ! IN: generic.standard ?'&;: standard)combination + *class)description (;erforms standard method combination.( *nl (Generic ords using the standard method combination dispatch on of the obFect at the given stack position< here = is the top of the the obFect underneath< and , is the next one under that. " ( + *link ( error is thro n if no suitable method is defined on the class.( . + *examples (" generic ord for append strings and characters to a sequence< on the obFect underneath the top of the stack:( + *code (G'N'#I%Z build)string 1 5 elt str )) 6( (I: string build)string s ap push)all !( (I: integer build)string push !(

the class stack< 1 is no)method .

dispatching

. . ! ?'&;: define)simple)generic + *values + ( ord( (a ord( . + (effect( effect . . + *description (Cefines a generic ord ith the ( + *link standard)combination . ( method combination and a dispatch position of =.( . !USING: accessors arrays assocs bit)arrays bit)vectors byte)arrays classes.tuple classes.union compiler.crossref compiler.units definitions eval generic generic.single generic.standard io.streams.string kernel make math math.constants math.functions namespaces parser quotations sequences speciali8ed)vectors strings tools.test ords ! DU"&I@I'C)JI$?: alien.c)types c @#BI: namespaces HG set ! S;'%I"&IO'C)V'%$B#: c:double IN: generic.standard.tests G'N'#I%: class)of 5 x )) y 6 I: fixnum class)of drop (fixnum( ! I: ord class)of drop ( ord( ! 0 (fixnum( 3 0 A class)of 3 unit)test 0 ( ord( 3 0 > class)of class)of 3 unit)test 0 -./ class)of 3 must)fail G'N'#I%: foobar 5 x )) y 6 I: obFect foobar drop (?ello orld( ! I: fixnum foobar drop (Goodbye cruel orld( ! 0 (?ello orld( 3 0 / foobar foobar 3 unit)test 0 (Goodbye cruel orld( 3 0 / foobar 3 unit)test G'N'#I%: lo)tag)test 5 obF )) obF7 6 I: I: I: I: 0 0 0 0 integer lo)tag)test - 2 ! float lo)tag)test / ) ! rational lo)tag)test , ) ! complex lo)tag)test sq !

S 3 0 A Gbignum lo)tag)test 3 unit)test =.= 3 0 /.= lo)tag)test 3 unit)test )1Q, 3 0 121Q, lo)tag)test 3 unit)test )1L 3 0 %+ = / . lo)tag)test 3 unit)test

G'N'#I%: hi)tag)test 5 obF )) obF7 6 I: I: I: I: string hi)tag)test (< in bed( append ! integer hi)tag)test - 2 ! array hi)tag)test 0 hi)tag)test 3 map ! sequence hi)tag)test reverse !

0 E+ - , 1 . 3 0 E+ 1 , - . hi)tag)test 3 unit)test 0 + L U 1, . 3 0 + - L U . hi)tag)test 3 unit)test 0 (i like monkeys< in bed( 3 0 (i like monkeys( hi)tag)test 3 unit)test UNIBN: funnies quotation float complex ! G'N'#I%: funny 5 x )) y 6

I: funnies funny drop , ! I: obFect funny drop = ! G'N'#I%: union)containment 5 x )) y 6 I: integer union)containment drop 1 ! I: number union)containment drop , ! 0 1 3 0 1 union)containment 3 unit)test 0 , 3 0 1.= union)containment 3 unit)test 0 , 3 0 0 + . 3 funny 3 unit)test 0 = 3 0 + . funny 3 unit)test $U;&': shape ! $U;&': abstract)rectangle P shape idth height !

$U;&': rectangle P abstract)rectangle ! %: PrectangleG rectangle $U;&': parallelogram P abstract)rectangle ske %: PparallelogramG parallelogram $U;&': circle P shape radius ! %: PcircleG circle G'N'#I%: area 5 shape )) n 6 I: abstract)rectangle area 0 idthGG 3 0 heightGG 3 bi 4 ! !

I: circle area radiusGG sq pi 4 ! 0 1, 3 0 / - PrectangleG area 3 unit)test 0 1, 3 0 / - , PparallelogramG area 3 unit)test 0 t 3 0 , PcircleG area / pi 4 H 3 unit)test G'N'#I%: perimeter 5 shape )) n 6 : rectangle)perimeter 5 l )) n 6 2 , 4 !

I: rectangle perimeter 0 idthGG 3 0 heightGG 3 bi rectangle)perimeter ! : hypotenuse 5 a b )) c 6 0 sq 3 bi9 2 sqrt ! I: parallelogram perimeter 0 idthGG 3 0 0 heightGG 3 0 ske GG 3 bi hypotenuse 3 bi rectangle)perimeter ! I: circle perimeter , 4 pi 4 ! 0 1/ 3 0 / - PrectangleG perimeter 3 unit)test 0 -=.= 3 0 1= / - PparallelogramG perimeter 3 unit)test ;#'CI%"$': very)funny P funnies number: ! G'N'#I%: gooey 5 x )) y 6

I: very)funny gooey sq ! 0 =.,A 3 0 =.A gooey 3 unit)test G'N'#I%: empty)method)test 5 x )) y 6 I: obFect empty)method)test ! $U;&': for)arguments)sake ! %: Pfor)arguments)sakeG for)arguments)sake I: for)arguments)sake empty)method)test drop (?i( ! $U;&': another)one ! %: Panother)oneG another)one 0 (?i( 3 0 Pfor)arguments)sakeG empty)method)test empty)method)test 3 unit)test 0 $+ another)one f . 3 0 Panother)oneG empty)method)test 3 unit)test G'N'#I%: big)mix)test 5 obF )) obF7 6 I: obFect big)mix)test drop (obFect( ! I: tuple big)mix)test drop (tuple( ! I: integer big)mix)test drop (integer( ! I: float big)mix)test drop (float( ! I: complex big)mix)test drop (complex( ! I: string big)mix)test drop (string( ! I: array big)mix)test drop (array( ! I: sequence big)mix)test drop (sequence( ! I: rectangle big)mix)test drop (rectangle( ! I: parallelogram big)mix)test drop (parallelogram( ! I: circle big)mix)test drop (circle( ! 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (integer( 3 0 - big)mix)test 3 unit)test (float( 3 0 A.= big)mix)test 3 unit)test (complex( 3 0 )1 sqrt big)mix)test 3 unit)test (sequence( 3 0 E+ 1 , - . big)mix)test 3 unit)test (sequence( 3 0 :+ t f t . big)mix)test 3 unit)test (sequence( 3 0 SEU@( hello orld( big)mix)test 3 unit)test (sequence( 3 0 V+ (a( (b( . big)mix)test 3 unit)test (sequence( 3 0 EV+ 1 , . big)mix)test 3 unit)test (sequence( 3 0 :V+ t t f f . big)mix)test 3 unit)test (string( 3 0 (hello( big)mix)test 3 unit)test (rectangle( 3 0 1 , PrectangleG big)mix)test 3 unit)test (parallelogram( 3 0 1= / - PparallelogramG big)mix)test 3 unit)test (circle( 3 0 1== PcircleG big)mix)test 3 unit)test (tuple( 3 0 ?+ . big)mix)test 3 unit)test (obFect( 3 0 > 2 big)mix)test 3 unit)test

G'N'#I%: small)lo)tag 5 obF )) obF 6 I: fixnum small)lo)tag drop (fixnum( ! I: string small)lo)tag drop (string( !

I: array small)lo)tag drop (array( ! I: double)array small)lo)tag drop (double)array( ! I: byte)array small)lo)tag drop (byte)array( ! 0 (fixnum( 3 0 - small)lo)tag 3 unit)test 0 (double)array( 3 0 double)array+ 1.= . small)lo)tag 3 unit)test K $esting recovery from bad method definitions (IN: generic.standard.tests G'N'#I%: unhappy 5 x )) x 6( eval5 )) 6 0 (IN: generic.standard.tests I: dictionary unhappy !( eval5 )) 6 3 must)fail 0 3 0 (IN: generic.standard.tests G'N'#I%: unhappy 5 x )) x 6( eval5 )) 6 3 unit)test G'N'#I%Z complex)combination 1 5 a b )) c 6 I: string complex)combination drop ! I: obFect complex)combination nip ! 0 (hi( 3 0 (hi( - complex)combination 3 unit)test 0 (hi( 3 0 - (hi( complex)combination 3 unit)test K #egression $U;&': first)one ! $U;&': second)one ! UNIBN: both first)one union)class ! G'N'#I%: ii 5 x )) y 6 I: both ii drop - ! I: second)one ii drop / ! I: tuple)class ii drop A ! I: integer ii drop L ! 0 - 3 0 $+ first)one . ii 3 unit)test

G'N'#I%: tag)and)f 5 x )) x x 6 I: fixnum tag)and)f 1 ! I: bignum tag)and)f , ! I: float tag)and)f - ! I: f tag)and)f / ! 0 f / 3 0 f tag)and)f 3 unit)test 0 -./ - 3 0 -./ tag)and)f 3 unit)test K Issues ith forget G'N'#I%: generic)forget)test 5 a )) b 6 I: f generic)forget)test ! 0 3 0 > f > generic)forget)test lookup)method (m( set 3 unit)test 0 3 0 0 (m( get forget 3 ith)compilation)unit 3 unit)test

0 3 0 (IN: generic.standard.tests I: f generic)forget)test !( eval5 )) 6 3 unit)test 0 3 0 0 (m( get forget 3 ith)compilation)unit 3 unit)test

0 f 3 0 f generic)forget)test 3 unit)test K erg7s regression 0 3 0 (((IN: generic.standard.tests G'N'#I%: Feah 5 a )) b 6 $U;&': boii ! I: boii Feah ! G'N'#I%: Feah4 5 a )) b 6 I: boii Feah4 Feah !((( eval5 )) 6 (((IN: generic.standard.tests @B#G'$: boii((( eval5 )) 6 (((IN: generic.standard.tests $U;&': boii ! I: boii Feah !((( eval5 )) 6 3 unit)test K $esting next)method $U;&': person ! $U;&': intern P person ! $U;&': employee P person ! $U;&': tape)monkey P employee ! $U;&': manager P employee ! $U;&': Funior)manager P manager ! $U;&': middle)manager P manager ! $U;&': senior)manager P manager ! $U;&': executive P senior)manager ! $U;&': ceo P executive ! G'N'#I%: salary 5 person )) n 6 I: intern salary ZK Intentional mistake. call)next)method ! I: employee salary drop ,/=== ! I: manager salary call)next)method 1,=== 2 ! I: middle)manager salary call)next)method A=== 2 ! I: senior)manager salary call)next)method 1A=== 2 ! I: executive salary call)next)method , 4 !

I: ceo salary ZK Intentional error. drop A call)next)method - 4 ! 0 salary 3 must)infer 0 ,/=== 3 0 employee boa salary 3 unit)test 0 ,/=== 3 0 tape)monkey boa salary 3 unit)test 0 -L=== 3 0 Funior)manager boa salary 3 unit)test 0 /1=== 3 0 middle)manager boa salary 3 unit)test 0 A1=== 3 0 senior)manager boa salary 3 unit)test 0 1=,=== 3 0 executive boa salary 3 unit)test 0 ceo boa salary 3 0 $+ inconsistent)next)method f ceo salary . H 3 must)fail) ith 0 intern boa salary 3 0 no)next)method: 3 must)fail) ith K Jeird shit $U;&': a ! $U;&': b ! $U;&': c ! UNIBN: x a b ! UNIBN: y a c ! UNIBN: 8 x y ! G'N'#I%: funky4 5 obF )) 6 I: 8 funky4 (8( < drop ! I: x funky4 (x( < call)next)method ! I: y funky4 (y( < call)next)method ! I: a funky4 (a( < call)next)method ! I: b funky4 (b( < call)next)method ! I: c funky4 (c( < call)next)method ! : funky 5 obF )) seq 6 0 funky4 3 + . make ! 0 + (b( (x( (8( . 3 0 $+ b . funky 3 unit)test 0 + (c( (y( (8( . 3 0 $+ c . funky 3 unit)test 0 t 3 0 $+ a . funky + + (a( (x( (8( . + (a( (y( (8( . . member: 3 unit)test K %hanging method combination should not fail 0 3 0 (IN: generic.standard.tests G'N'#I%: xy8 5 a )) b 6( eval5 )) 6 3 unit)test

0 3 0 (IN: generic.standard.tests I"$?: xy8 5 a b )) c 6( eval5 )) 6 3 unit)test 0 f 3 0 (xy8( (generic.standard.tests( lookup) ord pic)defGG 3 unit)test 0 f 3 0 (xy8( (generic.standard.tests( lookup) ord (decision)tree( ord)prop 3 unit)test K %orner case 0 (IN: generic.standard.tests G'N'#I%Z broken)genericZ )1 5 a )) b 6( eval5 )) 6 3 0 errorGG bad)dispatch)position: 3 must)fail) ith K Generic ords cannot be inlined 0 3 0 (IN: generic.standard.tests G'N'#I%: foo 5 )) x 6( eval5 )) 6 3 unit)test 0 (IN: generic.standard.tests G'N'#I%: foo 5 )) x 6 inline( eval5 )) 6 3 must)fail K Ioving a method from one vocab to another didn7t al ays G'N'#I%: move)method)generic 5 a )) b 6 ork

0 3 0 (IN: generic.standard.tests.a US': strings US': generic.standard.tests I: string move)method)generic !( Pstring)readerG (move)method)test)1( parse)stream drop 3 unit)test 0 3 0 (IN: generic.standard.tests.b US': strings US': generic.standard.tests I: string move)method)generic !( Pstring)readerG (move)method)test),( parse)stream drop 3 unit)test 0 3 0 (IN: generic.standard.tests.a( Pstring)readerG (move)method)test)1( parse)stream drop 3 unit)test 0 + string . 3 0 > move)method)generic order 3 unit)test K @B#G'$: on method rappers G'N'#I%: forget)test 5 a )) b 6 I: integer forget)test - 2 ! 0 3 0 (IN: generic.standard.tests US': math @B#G'$: I>> integer forget)test( eval5 )) 6 3 unit)test 0 + . 3 0 > 2 effect)dependencies)of keys 0 method: 3 filter 0 (method)generic( ord)prop > forget)test eq: 3 filter 3 unit)test 0 1= forget)test 3 0 no)method: 3 must)fail) ith K Ceclarations on methods G'N'#I%: flushable)generic 5 a )) b 6 flushable I: integer flushable)generic ! 0 t 3 0 > flushable)generic flushable: 3 unit)test 0 t 3 0 I> integer flushable)generic flushable: 3 unit)test G'N'#I%: non)flushable)generic 5 a )) b 6 I: integer non)flushable)generic ! flushable 0 f 3 0 > non)flushable)generic flushable: 3 unit)test 0 t 3 0 I> integer non)flushable)generic flushable: 3 unit)test K method)for)obFect< method)for)class< effective)method

G'N'#I%: foo8ul 5 a )) b 6 I: reversed foo8ul ! I: integer foo8ul ! I: slice foo8ul ! 0 3 0 reversed > foo8ul method)for)class I> reversed foo8ul assertH 3 unit)test 0 3 0 + 1 , - . PreversedG > foo8ul method)for)obFect I> reversed foo8ul assertH 3 unit)test 0 3 0 + 1 , - . PreversedG > foo8ul effective)method I> reversed foo8ul assertH drop 3 unit)test 0 3 0 fixnum > foo8ul method)for)class I> integer foo8ul assertH 3 unit)test 0 3 0 1- > foo8ul method)for)obFect I> integer foo8ul assertH 3 unit)test 0 3 0 1- > foo8ul effective)method I> integer foo8ul assertH drop 3 unit)test K 'nsure dynamic and static dispatch match in ambiguous cases UNIBN: amb)union)1a integer float ! UNIBN: amb)union)1b float string ! G'N'#I%: amb)generic)1 5 a )) b 6 I: amb)union)1a amb)generic)1 drop (a( ! I: amb)union)1b amb)generic)1 drop (b( ! 0 3 0 A.= amb)generic)1 A.= > amb)generic)1 effective)method execute5 a )) b 6 assertH 3 unit)test 0 3 0 A.= amb)generic)1 A.= float > amb)generic)1 method)for)class execute5 a )) b 6 assertH 3 unit)test UNIBN: amb)union),a float string ! UNIBN: amb)union),b integer float ! G'N'#I%: amb)generic), 5 a )) b 6 I: amb)union),a amb)generic), drop (a( ! I: amb)union),b amb)generic), drop (b( ! 0 3 0 A.= amb)generic)1 A.= > amb)generic)1 effective)method execute5 a )) b 6 assertH 3 unit)test 0 3 0 A.= amb)generic)1 A.= float > amb)generic)1 method)for)class execute5 a )) b 6 assertH 3 unit)test $U;&': amb)tuple)a x ! $U;&': amb)tuple)b P amb)tuple)a ! ;#'CI%"$': amb)tuple)c P amb)tuple)a xGG - H ! G'N'#I%: amb)generic)- 5 a )) b 6 I: amb)tuple)b amb)generic)- drop (b( ! I: amb)tuple)c amb)generic)- drop (c( ! 0 3 0

$+ amb)tuple)b f - . amb)generic)$+ amb)tuple)b f - . > amb)generic)- effective)method execute5 a )) b 6 assertH 3 unit)test $U;&': amb)tuple)d ! UNIBN: amb)union)/ amb)tuple)a amb)tuple)d ! G'N'#I%: amb)generic)/ 5 a )) b 6 I: amb)tuple)b amb)generic)/ drop (b( ! I: amb)union)/ amb)generic)/ drop (/( ! 0 3 0 $+ amb)tuple)b f - . amb)generic)/ $+ amb)tuple)b f - . > amb)generic)/ effective)method execute5 a )) b 6 assertH 3 unit)test 0 3 0 $+ amb)tuple)b f - . amb)generic)/ $+ amb)tuple)b f - . amb)tuple)b > amb)generic)/ method)for)class execute5 a )) b 6 assertH 3 unit)test IIMIN: amb)mixin)A INS$"N%': amb)tuple)a amb)mixin)A INS$"N%': amb)tuple)d amb)mixin)A G'N'#I%: amb)generic)A 5 a )) b 6 I: amb)tuple)b amb)generic)A drop (b( ! I: amb)mixin)A amb)generic)A drop (A( ! 0 3 0 $+ amb)tuple)b f - . amb)generic)A $+ amb)tuple)b f - . > amb)generic)A effective)method execute5 a )) b 6 assertH 3 unit)test 0 3 0 $+ amb)tuple)b f - . amb)generic)A $+ amb)tuple)b f - . amb)tuple)b > amb)generic)A method)for)class execute5 a )) b 6 assertH 3 unit)test UNIBN: amb)union)L amb)tuple)b amb)tuple)d ! G'N'#I%: amb)generic)L 5 a )) b 6 I: amb)tuple)a amb)generic)L drop (a( ! I: amb)union)L amb)generic)L drop (L( ! 0 3 0 $+ amb)tuple)b f - . amb)generic)L $+ amb)tuple)b f - . > amb)generic)L effective)method execute5 a )) b 6 assertH 3 unit)test 0 3 0 $+ amb)tuple)b f - . amb)generic)L $+ amb)tuple)b f - . amb)tuple)b > amb)generic)L method)for)class execute5 a

)) b 6 assertH 3 unit)test IIMIN: amb)mixin)R INS$"N%': amb)tuple)b amb)mixin)R INS$"N%': amb)tuple)d amb)mixin)R G'N'#I%: amb)generic)R 5 a )) b 6 I: amb)tuple)a amb)generic)R drop (a( ! I: amb)mixin)R amb)generic)R drop (R( ! 0 3 0 $+ amb)tuple)b f - . amb)generic)R $+ amb)tuple)b f - . > amb)generic)R effective)method execute5 a )) b 6 assertH 3 unit)test 0 3 0 $+ amb)tuple)b f - . amb)generic)R $+ amb)tuple)b f - . amb)tuple)b > amb)generic)R method)for)class execute5 a )) b 6 assertH 3 unit)test K Same thing as above but ith predicate classes ;#'CI%"$': amb)predicate)a P integer 1= mod even: ! ;#'CI%"$': amb)predicate)b P amb)predicate)a 1= mod / H ! UNIBN: amb)union)S amb)predicate)b string ! G'N'#I%: amb)generic)S 5 a )) b 6 I: amb)union)S amb)generic)S drop (S( ! I: amb)predicate)a amb)generic)S drop (a( ! 0 3 0 / amb)generic)S / > amb)generic)S effective)method execute5 a )) b 6 assertH 3 unit)test K %opyright 5%6 ,==A< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: arrays assocs classes classes.algebra combinators definitions generic kernel kernel.private math math.order math.private namespaces quotations sequences ords ! IN: generic.math ;#'CI%"$': math)class P class dup null bootstrap) ord eq: 0 drop f 3 0 number bootstrap) ord classPH 3 if ! P;#IV"$' : bootstrap) ords 5 classes )) classes7 6 0 bootstrap) ord 3 map ! : math)precedence 5 class )) pair 6 0 + fixnum integer rational real number obFect . bootstrap) ords s ap 0 s ap classPH 3 curry find drop )1 or

3 0 + fixnum bignum ratio float complex obFect . bootstrap) ords s ap 0 classPH 3 curry find drop )1 or 3 bi ,array ! : 5math)upgrade6 5 max class )) quot 6 dupd H 0 drop 0 3 3 0 (coercer( ord)prop 0 3 or 3 if ! ;#IV"$'G : math)class)max 5 class1 class, )) class 6 0 0 math)precedence 3 bi9 after: 3 most ! : math)upgrade 5 class1 class, )) quot 6 0 math)class)max 3 ,keep 0 5math)upgrade6 dup empty: 0 0 dip 3 curry 0 3 like 3 unless 3 0 5math)upgrade6 3 bi)curry4 bi append ! '##B#: no)math)method left right generic ! : default)math)method 5 generic )) quot 6 0 no)math)method 3 curry 0 3 like ! P;#IV"$' : 5math)method6 5 generic class )) quot 6 over :lookup)method 0 1quotation 3 0 default)math)method 3 :if ! ;#IV"$'G : obFect)method 5 generic )) quot 6 obFect bootstrap) ord 5math)method6 ! : math)method 5 ord class1 class, )) quot 6 ,dup and 0 0 ,array 0 declare 3 curry nip 3 0 math)upgrade nip 3 0 math)class)max over nearest)class 5math)method6 3 -tri -append 3 0 ,drop obFect)method 3 if ! P;#IV"$' SNIEB&: generic) ord : make)math)method)table 5 classes quot: 5 ... class )) ... quot 6 )) alist 6 0 bootstrap) ords 3 dip 0 0 drop 3 0 call 3 ,bi 3 curry + . mapGassoc ! inline : math)alistGquot 5 alist )) quot 6 0 generic) ord get obFect)method 3 dip alistGquot ! : tag)dispatch)entry 5 tag picker )) quot 6 0 (type( ord)prop 1quotation 0 tag 3 0 eq: 3 surround 3 dip prepend !

: tag)dispatch 5 picker alist )) alist7 6 s ap 0 0 tag)dispatch)entry 3 curry dip 3 curry assoc)map math)alistGquot ! : tuple)dispatch)entry 5 class picker )) quot 6 0 1quotation 0 + tuple . declare class)of 3 0 eq: 3 surround 3 dip prepend ! : tuple)dispatch 5 picker alist )) alist7 6 s ap 0 0 tuple)dispatch)entry 3 curry dip 3 curry assoc)map math)alistGquot ! : math)dispatch)step 5 picker quot: 5 ... class )) ... quot 6 )) quot 6 0 0 + bignum float fixnum . 3 dip make)math)method)table 3 0 0 + ratio complex . 3 dip make)math)method)table tuple)dispatch 3 ,bi tuple s ap ,array prefix tag)dispatch ! inline ;#IV"$'G SING&'$BN: math)combination I: math)combination make)default)method drop default)math)method ! I: math)combination perform)combination drop dup generic) ord 0 dup 0 fixnum bootstrap) ord dup math)method 3 0 0 over 3 0 dup math)class: 0 0 dup 3 0 math)method 3 ith ith math)dispatch)step 3 0 drop obFect)method 3 if 3 ith math)dispatch)step 3 bi 0 if 3 ,curry 0 ,dup both)fixnums: 3 prepend define 3 ith)variable ! ;#'CI%"$': math)generic P generic (combination( ord)prop math)combination: ! I: math)generic definer drop > I"$?: f ! USING: kernel generic help.markup help.syntax math classes sequences quotations generic.math.private ! IN: generic.math ?'&;: math)upgrade + *values + (class1( class . + (class,( class . + (quot( + *quotation (5 n n )) n n 6( . . . + *description (Butputs a quotation for upgrading numberical types. It takes t o numbers on the stack< an instance of ( + *snippet (class1( . (< and an instance of ( + *snippet (class,( . (< and converts the one ith the lo er priority to the higher priority type.( . + *examples + *example (USING: generic.math math kernel prettyprint !( (fixnum bignum math)upgrade .( (0 0 Gbignum 3 dip 3( . . ! ?'&;: no)math)method + *values + (left( (an obFect( . + (right( (an obFect( . + (generic( generic . . + *description ($hro s a ( + *link no)math)method . ( error.( . + *error)description ($hro n by generic ords using the ( + *link math)combination . ( method combination if there is no suitable method defined

for the t o inputs.( . ! ?'&;: math)method + *values + ( ord( generic . + (class1( class . + (class,( class . + (quot( quotation . . + *description (Generates a definition for ( + *snippet ( ord( . ( hen the t o inputs are instances of ( + *snippet (class1( . ( and ( + *snippet (class,( . (< respectively.( . + *examples + *example (USING: generic.math math prettyprint !( (>> 2 fixnum float math)method .( (0 + fixnum float . declare 0 Gfloat 3 dip I>> float 2 3( . . ! ?'&;: math)class + *class)description ($he class of subtypes of ( + *link number . ( not ( + *link null . (.( . ! hich are

?'&;: math)combination + *values + ( ord( generic . + (quot( quotation . . + *description (Generates a double)dispatching ord definition. Bnly methods defined on numerical classes and ( + *link obFect . ( take effect in the math combination. Iethods defined on numerical classes are guaranteed to have their t o inputs upgraded to the highest priority type of the t o.( *nl ($he math method combination is used for binary operators such as ( + *link 2 . ( and ( + *link 4 . (.( *nl (" method can only be added to a generic ord using the math combination if the method speciali8es on one of the belo classes< or a union defined over one or more of the belo classes:( + *code (fixnum( (bignum( (ratio( (float( (complex( (obFect( . ($he math combination performs numerical upgrading as described in ( + *link (number)protocol( . (.( . ! ?'&;: math)generic + *class)description ($he class of generic math)combination . (.( . ! ords using ( + *link

USING: generic.math math tools.test kernel ! IN: generic.math.tests K 0 0 0 0 0 0 0 0 0 0 0 0 $est math)combination 0 0 Gfloat 3 dip 3 3 0 > real > float math)upgrade 3 unit)test 0 Gfloat 3 3 0 > float > real math)upgrade 3 unit)test 0 0 Gbignum 3 dip 3 3 0 > fixnum > bignum math)upgrade 3 unit)test 0 Gfloat 3 3 0 > float > integer math)upgrade 3 unit)test number 3 0 number float math)class)max 3 unit)test number 3 0 float number math)class)max 3 unit)test float 3 0 real float math)class)max 3 unit)test float 3 0 float real math)class)max 3 unit)test fixnum 3 0 fixnum null math)class)max 3 unit)test fixnum 3 0 null fixnum math)class)max 3 unit)test bignum 3 0 fixnum bignum math)class)max 3 unit)test bignum 3 0 bignum fixnum math)class)max 3 unit)test

0 number 3 0 fixnum number math)class)max 3 unit)test 0 number 3 0 number fixnum math)class)max 3 unit)test 0 t 3 0 > 2 math)generic: 3 unit)test K %opyright 5%6 ,==L< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes classes.algebra classes.algebra.private classes.maybe classes.private combinators definitions kernel make namespaces sequences sets ords ! @#BI: sets HG members ! IN: generic K Iethod combination protocol G'N'#I%: perform)combination 5 ord combination )) 6

G'N'#I%: make)default)method 5 generic combination )) method 6 ;#'CI%"$': generic P ord (combination( ord)prop Gboolean ! I: generic definition drop f ! : make)generic 5 ord )) 6 0 + (unannotated)def( . reset)props 3 0 dup (combination( ord)prop perform)combination 3 bi ! ;#'CI%"$': method P ord (method)generic( ord)prop Gboolean ! '##B#: method)lookup)failed class generic ! : :lookup)method 5 class generic )) methodQf 6 (methods( ord)prop at ! : lookup)method 5 class generic )) method 6 ,dup :lookup)method 0 ,nip 3 0 method)lookup)failed 3 if4 ! P;#IV"$' : interesting)class: 5 class1 class, )) : 6 + K %ase 1: no intersection. Ciscard and keep going + 0 ,dup classes)intersect: not 3 0 ,drop t 3 . K %ase ,: class1 contained in class,. "dd to K interesting set and keep going. + 0 ,dup classPH 3 0 nip < t 3 . K %ase -: class1 and class, are incomparable. Give up 0 ,drop f 3 . cond ! : interesting)classes 5 class classes )) interestingQf 6 0 0 interesting)class: 3 ith all: 3 + . make and ! ;#IV"$'G : method)classes 5 generic )) classes 6 (methods( ord)prop keys ! : order 5 generic )) seq 6 method)classes sort)classes !

: nearest)class 5 class generic )) classQf 6 method)classes interesting)classes smallest)class ! : method)for)class 5 class generic )) methodQf 6 0 nip 3 0 nearest)class 3 ,bi dup 0 s ap :lookup)method 3 0 ,drop f 3 if ! G'N'#I%: effective)method 5 generic )) method 6 > effective)method t (no)compile( set) ord)prop : next)method)class 5 class generic )) classQf 6 method)classes 0 classP 3 ith filter smallest)class ! : next)method 5 class generic )) methodQf 6 0 next)method)class 3 keep :lookup)method ! G'N'#I%: next)method)quot4 5 class generic combination )) quot 6 : next)method)quot 5 method )) quot 6 next)method)quot)cache get 0 0 (method)class( ord)prop 3 0 (method)generic( ord)prop dup (combination( ord)prop 3 bi next)method)quot4 3 cache ! '##B#: no)next)method method ! : 5call)next)method6 5 method )) 6 dup next)method)quot 0 call 3 0 no)next)method 3 :if ! '##B#: check)method)error class generic ! : check)method 5 classoid generic )) class generic 6 ,dup 0 classoid: 3 0 generic: 3 bi4 and 0 check)method)error 3 unless ! inline : remake)generic 5 generic )) 6 outdated)generics get add)to)unit ! : remake)generics 5 )) 6 outdated)generics get members 0 generic: 3 filter 0 make)generic 3 each ! G'N'#I%: update)generic 5 class generic )) 6 : ith)methods 5 class generic quot )) 6 0 (methods( ord)prop 3 prepose 0 update)generic 3 ,bi ! inline

: method) ord)name 5 class generic )) string 6 0 class)name 3 0 nameGG 3 bi4 (HG( glue ! I: method parent) ord (method)generic( ord)prop ! I: method crossref: (forgotten( ord)prop not ! : method) ord)props 5 class generic )) assoc 6

0 (method)generic( << (method)class( << 3 ?+ . make ! : PmethodG 5 class generic )) method 6 check)method 0 method) ord)name f P ordG 3 0 method) ord)props 3 ,bi GGprops ! G'N'#I%: implementor)classes 5 obF )) class 6 I: maybe implementor)classes classGG 1array ! I: class implementor)classes 1array ! I: anonymous)union implementor)classes membersGG ! I: anonymous)intersection implementor)classes participantsGG ! : ith)implementors 5 class generic quot )) 6 0 s ap implementor)classes 0 implementors)map get at 3 map 3 dip call ! inline : reveal)method 5 method classes generic )) 6 0 0 0 adFoin 3 ith each 3 ith)implementors 3 0 0 set)at 3 ith)methods 3 ,bi ! : create)method 5 class generic )) method 6 ,dup :lookup)method dup 0 ,nip dup reset)generic 3 0 drop 0 PmethodG dup 3 ,keep reveal)method reset)caches 3 if ! ;#'CI%"$': default)method P ord (default( ord)prop !

: Pdefault)methodG 5 generic combination )) method 6 0 drop obFect bootstrap) ord s ap PmethodG 3 0 make)default)method 3 ,bi 0 define 3 0 drop t (default( set) ord)prop 3 0 drop 3 ,tri ! : define)default)method 5 generic combination )) 6 dupd Pdefault)methodG (default)method( set) ord)prop ! K Cefinition protocol I: method definer drop > I: > ! ! I: method forget4 dup (forgotten( ord)prop 0 drop 3 0 0 dup default)method: 0 drop 3 0 0 0 (method)class( ord)prop 3 0 (method)generic( ord)prop 3 bi ,dup :lookup)method 3 keep eq: 0 0 0 delete)at 3 ith)methods 3 0 0 0 delete 3 ith each 3 ith)implementors 3

,bi reset)caches 3 0 ,drop 3 if 3 if 3 0 call)next)method 3 bi 3 if ! : define)generic 5 ord combination effect )) 6 0 nip s ap set)stack)effect 3 0 drop ,dup 0 (combination( ord)prop 3 dip H 0 ,drop 3 0 + 0 drop reset)generic 3 0 (combination( set) ord)prop 3 0 drop ?+ . clone (methods( set) ord)prop 3 0 define)default)method 3 . ,cleave 3 if 3 0 ,drop remake)generic 3 -tri ! I: generic sub ords 0 0 (default)method( ord)prop < 3 0 (methods( ord)prop values W 3 0 (engines( ord)prop W 3 tri 3 + . make ! I: class forget)methods 0 implementors 3 0 0 s ap :lookup)method 3 curry 3 bi map forget)all ! USING: accessors io io.streams.string kernel math parser sbufs sequences tools.test ords namespaces strings ! IN: io.tests + f . 0 (vocab:ioQtestQno)trailing)eol.factor( run)file (foo( (io.tests( lookup) ord 3 unit)test K Iake sure e use correct to[c[string form + . 0 (>=( rite 3 unit)test K $est default input stream protocol methods $U;&': up)to)1-)reader + i fixnum initial: = . ! INS$"N%': up)to)1-)reader input)stream I: up)to)1-)reader stream)element)type drop 2byte2 ! inline I: up)to)1-)reader stream)read1 0 dup 1 2 3 change)i drop dup 1- GH 0 drop f 3 hen ! inline + E+ = 1 , . . 0 - up)to)1-)reader ne + E+ = 1 , . . 0 - up)to)1-)reader ne stream)read 3 unit)test stream)read)partial 3 unit)test hen riting

+ E+ = 1 , - / A L R S U 1= 11 1, . f . 0 up)to)1-)reader ne 0 ,= s ap stream)read 3 0 ,= s ap stream)read 3 bi 3 unit)test

+ $+ slice f = S E+ = 1 , - / A L R . . t $+ slice f = A E+ S U 1= 11 1, ,=A ,=L ,=R . . t $+ slice f = = E+ S U 1= 11 1, ,=A ,=L ,=R . . f

. 0

up)to)1-)reader ne 0 E+ ,== ,=1 ,=, ,=- ,=/ ,=A ,=L ,=R . s ap stream)read)into 3 0 E+ ,== ,=1 ,=, ,=- ,=/ ,=A ,=L ,=R . s ap stream)read)into 3 0 E+ ,== ,=1 ,=, ,=- ,=/ ,=A ,=L ,=R . s ap stream)read)into 3 tri 3 unit)test + E+ = 1 , - / A L R S . U E+ 1= 11 1, . f f f

. 0

up)to)1-)reader ne 0 (>t( s ap stream)read)until 3 0 (>t( s ap stream)read)until 3 0 (>t( s ap stream)read)until 3 tri 3 unit)test + E+ = 1 , - / A L R S U . E+ 11 1, . f . 0 up)to)1-)reader ne 0 stream)readln 3 0 stream)readln 3 0 stream)readln 3 tri 3 unit)test K $est default output stream protocol methods $U;&': dumb) riter vector ! INS$"N%': dumb) riter output)stream : Pdumb) riterG 5 )) x 6 EV+ . clone dumb) riter boa ! inline I: dumb) riter stream)element)type drop 2byte2 ! inline I: dumb) riter stream) rite1 vectorGG push ! inline + EV+ 11 ,, -- . . 0 Pdumb) riterG 0 E+ 11 ,, -- . s ap stream) rite 3 0 vectorGG 3 bi 3 unit)test + EV+ 11 ,, -- 1= . . 0 Pdumb) riterG 0 E+ 11 ,, -- . s ap stream) rite 3 0 stream)nl 3 0 vectorGG 3 tri 3 unit)test + SEU@( asdf( . 0 (asdf( Pstring)readerG / PsbufG 0 stream)copy 3 keep 3 unit)test 0 (asdf( 3 0 0 0 (asdf( error)stream get stream) rite 3 3 ith)string) riter 3 unit)test 0 (asdf( 3 0

ith)errorGoutput

Pstring) riterG 0 0 0 (asdf( output)stream get stream) rite 3 3 ith)error)stream 3 keep Gstring 3 unit)test IN: io.tests US': math : foo 5 )) x 6 , , 2 ! @B#G'$: fooUSING: io.binary tools.test classes math ! IN: io.binary.tests 0 =x=-=,=1== 3 0 E+ = 1 , - . leG 3 unit)test 0 =x===1=,=- 3 0 E+ = 1 , - . beG 3 unit)test 0 =x--,,11 3 0 E+ =x11 =x,, =x-- . leG 3 unit)test 0 =xRa,cRU-b,ff=SAA/ 3 0 E+ =xA/ =xSA =xf= =x,f =x-b =xRU =x,c =xRa . leG 3 unit)test 0 =xUSSa,AUc-/--f,-R 3 0 E+ =x-R =xf, =x-- =x-/ =xUc =x,A =xSa =xUS . leG 3 unit)test 0 0 0 0 E+ E+ E+ E+ = = / =xd, . 3 0 1,-/ / Gbe 3 = = = = = = / =xd, . 3 0 1,-/ =xd, / = = . 3 0 1,-/ / Gle 3 =xd, / = = = = = = . 3 0 1,-/ unit)test S Gbe 3 unit)test unit)test S Gle 3 unit)test

ith)outputGerror

0 1,-/ 3 0 1,-/ / Gbe beG 3 unit)test 0 1,-/ 3 0 1,-/ / Gle leG 3 unit)test 0 fixnum 3 0 E+ = = = = = = = = = = . beG class)of 3 unit)test 0 =xALRS==== =x1,-/==== 3 0 =x1,-/====ALRS==== dG Q 3 unit)test 0 =xALRS =x1,-/ 3 0 =x1,-/ALRS GhQh 3 unit)test 0 =x-/ =x1, 3 0 =x1,-/ hGbQb 3 unit)test K %opyright 5%6 ,==-< ,==R Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel math sequences ! IN: io.binary : leG 5 seq )) x 6 dup length iota = 0 S 4 shift 2 3 ,reduce ! : beG 5 seq )) x 6 = 0 0 S shift 3 dip 2 3 reduce ! : mask)byte 5 x )) y 6 =xff bitand ! inline : nth)byte 5 x n )) b 6 )S 4 shift mask)byte ! inline P;#IV"$' : map)bytes 5 x seq )) byte)array 6 0 nth)byte 3 ith E+ . map)as ! inline ;#IV"$'G : Gle 5 x n )) byte)array 6 iota map)bytes !

: Gbe 5 x n )) byte)array 6 iota PreversedG map)bytes ! : dG Q 5 d )) 1 , 6 0 =xffffffff bitand 3 0 )-, shift =xffffffff bitand 3 bi ! : GhQh 5 )) h1 h, 6 0 =xffff bitand 3 0 )1L shift =xffff bitand 3 bi !

: hGbQb 5 h )) b1 b, 6 0 mask)byte 3 0 )S shift mask)byte 3 bi ! : signed)leG 5 bytes )) x 6 0 leG 3 0 length S 4 1 ) ,T 1 ) 3 bi ,dup G 0 bitnot bitor 3 0 drop 3 if ! : signed)beG 5 bytes )) x 6 PreversedG signed)leG ! USING: help.markup help.syntax io math byte)arrays ! IN: io.binary "#$I%&': (stream)binary( (Jorking ith binary data( (Stream ords on binary streams only read and rite byte arrays. ;acked binary integers can be read and ritten by converting to and from sequences of bytes. @loating point numbers can be read and ritten by converting them into a their bit ise integer representation 5( + *link (floats( . (6.( *nl ($here are t o ays to order the bytes making up an integer! ( + *emphasis (little endian( . ( byte order outputs the least significant byte first< and the most significant byte last< hereas ( + *emphasis (big endian( . ( is the other ay around.( *nl (%onsider the hexadecimal integer ( + *snippet (=xcafebabe( . (. &ittle endian byte order yields the follo ing sequence of bytes:( + *table + (Eyte:( (1( (,( (-( (/( . + (Value:( + *snippet (be( . + *snippet (ba( . + *snippet (fe( . + *snippet (ca( . . . (%ompare this ith big endian byte order:( + *table + (Eyte:( (1( (,( (-( (/( . + (Value:( + *snippet (ca( . + *snippet (fe( . + *snippet (ba( . + *snippet (be( . . . ($ o ords convert a sequence of bytes into an integer:( + *subsections beG leG . ($ o ords convert an integer into a sequence of bytes:( + *subsections Gbe Gle . (Jords for taking larger integers apart into smaller integers:( + *subsections dG Q GhQh hGbQb . ! "EBU$: (stream)binary(

?'&;: beG + *values + (seq( (a sequence of bytes( . + (x( (a non)negative integer( . . + *description (%onverts a sequence of bytes in big endian order into an unsigned integer.( . ! ?'&;: leG + *values + (seq( (a sequence of bytes( . + (x( (a non)negative integer( . . + *description (%onverts a sequence of bytes in little endian order into an unsigned integer.( . ! ?'&;: nth)byte + *values + (x( integer . + (n( (a non)negative integer( . + (b( (a byte( . . + *description (Butputs the ( + *snippet (n( . (th least significant byte of the sign)extended ,7s complement representation of ( + *snippet (x( . (.( . ! ?'&;: Gle + *values + (x( integer . + byte)array . . + *description (%onverts an + *snippet (n( . ( bytes in integer is not in the range ?'&;: Gbe + *values + (x( integer . + byte)array . . + *description (%onverts an + *snippet (n( . ( bytes in integer is not in the range (n( (a non)negative integer( . + (byte)array( integer ( + *snippet (x( . ( into a string of ( little endian order. $runcation ill occur if the ( + *snippet (0),T5Sn6<,T5Sn66( . (.( . ! (n( (a non)negative integer( . + (byte)array( integer ( + *snippet (x( . ( into a string of ( big endian order. $runcation ill occur if the ( + *snippet (0),T5Sn6<,T5Sn66( . (.( . !

?'&;: mask)byte + *values + (x( integer . + (y( (a non)negative integer( . . + *description (Iasks off the least significant S bits of an integer.( . ! ?'&;: dG Q + *values + (d( (a L/)bit integer( . + ( 1( (a -,)bit integer( . + ( ,( (a -,)bit integer( . . + *description (Butputs t o integers< the least follo ed by the most significant -, bits of the input.( . ! ?'&;: GhQh + *values + ( ( (a -,)bit integer( . + (h1( (a 1L)bit integer( . + (h,( (a 1L)bit integer( . . + *description (Butputs t o integers< the least follo ed by the most significant 1L bits of the input.( . ! ?'&;: hGbQb + *values + (h( (a 1L)bit integer( . + (b1( (an S)bit integer( . + (b,( (an S)bit integer( . . + *description (Butputs t o integers< the least follo ed by the most significant S bits of the input.( . ! USING: io.pathnames io.files.temp io.directories continuations math io.files.private kernel namespaces sequences system tools.test io.backend io.pathnames.private ! IN: io.pathnames.tests 0 0 0 0 (pass d( 3 0 (QetcQpass d( file)name 3 unit)test (a k( 3 0 (QusrQlibexecQa kQ( file)name 3 unit)test (a k( 3 0 (QusrQlibexecQa kQQQ( file)name 3 unit)test (( 3 0 (( file)name 3 unit)test

0 (freetypeL.dll( 3 0 (resource:freetypeL.dll( file)name 3 unit)test 0 (freetypeL.dll( 3 0 (resource:QfreetypeL.dll( file)name 3 unit)test 0 0 0 0 0 0 (QusrQlib( 3 0 (Qusr( (lib( append)path 3 unit)test (QusrQlib( 3 0 (QusrQ( (lib( append)path 3 unit)test (QusrQlib( 3 0 (Qusr( (.Qlib( append)path 3 unit)test (QusrQlibQ( 3 0 (Qusr( (.QlibQ( append)path 3 unit)test (Qlib( 3 0 (Qusr( (..Qlib( append)path 3 unit)test (QlibQ( 3 0 (Qusr( (..QlibQ( append)path 3 unit)test

0 (( 3 0 (( (.( append)path 3 unit)test 0 (( (..( append)path 3 must)fail 0 0 0 0 (Q( 3 0 (Q( (.Q.( append)path 3 unit)test (Q( 3 0 (Q( (.Q.Q( append)path 3 unit)test (QaQbQlib( 3 0 (QaQbQcQdQeQfQ( (..Q..Q..Q..Qlib( append)path 3 unit)test (QaQbQlibQ( 3 0 (QaQbQcQdQeQfQ( (..Q..Q..Q..QlibQ( append)path 3 unit)test

0 (( (..QlibQ( append)path 3 must)fail 0 (lib( 3 0 (( (lib( append)path 3 unit)test 0 (lib( 3 0 (( (.Qlib( append)path 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (fooQbarQ.( parent)directory 3 must)fail (fooQbarQ.Q( parent)directory 3 must)fail (fooQbarQba8Q..( parent)directory 3 must)fail (fooQbarQba8Q..Q( parent)directory 3 must)fail (.( parent)directory 3 must)fail (.Q( parent)directory 3 must)fail (..( parent)directory 3 must)fail (..Q( parent)directory 3 must)fail (..Q..Q( parent)directory 3 must)fail (fooQ..( parent)directory 3 must)fail (fooQ..Q( parent)directory 3 must)fail (( parent)directory 3 must)fail (.( 3 0 (boot.xSL.L/.image( parent)directory 3 unit)test (barQfoo( 3 0 (barQba8Qfoo( (barQfoo( 3 0 (barQfoo( 3 0 (barQba8( (..QQQfoo( append)path 3 unit)test 3 0 (barQba8( (.QQQfoo( append)path 3 unit)test (barQba8( (.Q..QQfoo( append)path 3 unit)test (barQba8( (.Q..Q.Q.Q.Q.Q.Q.QQQQfoo( append)path 3 unit)test

0 t 3 0 (resource:core( absolute)path: 3 unit)test 0 f 3 0 (( absolute)path: 3 unit)test 0 (touch)t ice)test( temp)file delete)file 3 ignore)errors 0 3 0 , 0 (touch)t ice)test( temp)file touch)file 3 times 3 unit)test K aum7s bug 0 (.( current)directory set (..( (resource)path( set 0 (..QcoreQbootstrapQstage,.factor( 3 0 (resource:coreQbootstrapQstage,.factor( absolute)path 3 unit)test 3 ith)scope 0 t 3 0 c d (misc( resource)path 0 3 ith)directory c d H 3 unit)test

K #egression test for bug in file)extension 0 f 3 0 (Qfunny.directoryQfile) ith)no)extension( file)extension 3 unit)test 0 (( 3 0 (Qfunny.directoryQfile) ith)no)extension.( file)extension 3 unit)test

K $esting c special pathname 0 t 3 0 os indo s: (c>>( (cQ( : absolute)path home H 3 unit)test 0 t 3 0 (cQ( home 0 normali8e)path 3 same: 3 unit)test 0 t 3 0 (c( absolute)path home H 3 unit)test 0 t 3 0 (c( home 0 normali8e)path 3 same: 3 unit)test 0 t 3 0 (c( home 0 (foo( append)path 3 bi9 0 normali8e)path 3 same: 3 unit)test 0 t 3 0 os indo s: (c>>cQ( (cQcQ( : (c( (c( append)path 0 path)components 3 same: 3 unit)test K %opyright 5%6 ,==/< ,==U Slava ;estov< Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors combinators io.backend kernel math math.order namespaces sequences splitting strings system ! IN: io.pathnames SNIEB&: current)directory : path)separator: 5 ch )) : 6 os : path)separator 5 )) string 6 os indo s: (Q>>( (Q( : member: ! indo s: (>>( (Q( : !

: trim)tail)separators 5 string )) string7 6 0 path)separator: 3 trim)tail ! : trim)head)separators 5 string )) string7 6 0 path)separator: 3 trim)head ! : last)path)separator 5 path )) n : 6 0 length 1 ) 3 keep 0 path)separator: 3 find)last)from ! ?BBY: root)directory: io)backend 5 path )) : 6 I: obFect root)directory: 5 path )) : 6 0 f 3 0 0 path)separator: 3 all: 3 if)empty ! '##B#: no)parent)directory path ! : parent)directory 5 path )) parent 6 dup root)directory: 0 trim)tail)separators dup last)path)separator 0 1 2 cut 3 0 drop (.( s ap 3 if + (( (.( (..( . member: 0 no)parent)directory 3 hen 3 unless ! P;#IV"$' : head)path)separator: 5 path1 : )) :7 6 0 0 t 3 0 first path)separator: 3 if)empty 3 0 drop f 3 if !

: head.: 5 path )) : 6 (.( :head head)path)separator: ! : head..: 5 path )) : 6 (..( :head head)path)separator: ! : append)path)empty 5 path1 path, )) path7 6 + + 0 dup head.: 3 0 rest trim)head)separators append)path)empty 3 . + 0 dup head..: 3 0 drop no)parent)directory 3 . 0 nip 3 . cond ! : indo s)absolute)path: 5 path )) path : 6 + + 0 dup (>>>>:>>( head: 3 0 t 3 . + 0 dup length , P 3 0 f 3 . + 0 dup second %?"#: : H 3 0 t 3 . 0 f 3 . cond !

: special)path: 5 path )) rest : 6 + + 0 (resource:( :head 3 0 t 3 . + 0 (vocab:( :head 3 0 t 3 . 0 f 3 . cond ! ;#IV"$'G : absolute)path: 5 path )) : 6 + + 0 dup empty: 3 0 f 3 . + 0 dup special)path: nip 3 0 t 3 . + 0 os indo s: 3 0 indo s)absolute)path: 3 . + 0 dup first path)separator: 3 0 t 3 . 0 f 3 . cond nip ! : append)relative)path 5 path1 path, )) path 6 0 trim)tail)separators 3 0 trim)head)separators 3 bi4 (Q( glue ! : append)path 5 path1 path, )) path 6 + + 0 over empty: 3 0 append)path)empty 3 . + 0 dup empty: 3 0 drop 3 . + 0 over trim)tail)separators (.( H 3 0 nip 3 . + 0 dup absolute)path: 3 0 nip 3 . + 0 dup head.: 3 0 rest trim)head)separators append)path 3 . + 0 dup head..: 3 0 , tail trim)head)separators 0 parent)directory 3 dip append)path 3 . + 0 over absolute)path: over first path)separator: and 3 0 0 , head 3 dip append 3 . 0 append)relative)path 3 . cond ! : prepend)path 5 path1 path, )) path 6

s ap append)path ! inline : file)name 5 path )) string 6 dup root)directory: 0 trim)tail)separators dup last)path)separator 0 1 2 tail 3 0 drop special)path: 0 file)name 3 hen 3 if 3 unless ! : file)stem 5 path )) stem 6 file)name (.( split1)last drop ! : file)extension 5 path )) extension 6 file)name (.( split1)last nip ! : path)components 5 path )) seq 6 normali8e)path path)separator split harvest ! ?BBY: resolve)symlinks os 5 path )) path7 6 I: obFect resolve)symlinks normali8e)path ! : resource)path 5 path )) ne path 6 (resource)path( get prepend)path ! ?BBY: home io)backend 5 )) dir 6 I: obFect home (( resource)path ! G'N'#I%: vocab)path 5 path )) ne path 6 G'N'#I%: absolute)path 5 path )) path7 6 I: string absolute)path (resource:( :head 0 trim)head)separators resource)path absolute)path 3 0 (vocab:( :head 0 trim)head)separators vocab)path absolute)path 3 0 (c( :head 0 trim)head)separators home prepend)path absolute)path 3 0 current)directory get prepend)path 3 if 3 if 3 if ! I: obFect normali8e)path 5 path )) path7 6 absolute)path ! $U;&': pathname string ! %: PpathnameG pathname I: pathname absolute)path stringGG absolute)path ! I: pathname PHG 0 stringGG 3 compare !

USING: help.markup help.syntax io.backend io.files io.directories strings system sequences io.pathnames.private ! IN: io.pathnames ?'&;: path)separator: + *values + (ch( (a code point( . + (:( (a boolean( . . + *description ($ests if the code point is a platform)specific path separator.( . + *examples (Bn Unix:( + *example (USING: io.pathnames prettyprint !( (%?"#: Q path)separator: .( (t( . . ! ?'&;: parent)directory + *values + (path( (a pathname string( . + (parent( (a pathname string( . . + *description (Strips the last component off a pathname.( . + *examples + *example (USING: io io.pathnames !( (>(QetcQpass d>( parent)directory print( (QetcQ( . . ! ?'&;: file)name + *values + (path( (a pathname string( . + (string( string . . + *description (Butputs the last component of a pathname string.( . + *examples + *example (USING: io.pathnames prettyprint !( (>(QusrQbinQgcc>( file)name .( (>(gcc>(( . + *example (USING: io.pathnames prettyprint !( (>(QusrQlibexecQa kQ>( file)name .( (>(a k>(( . . ! ?'&;: file)extension + *values + (path( (a pathname string( . + (extension( string . . + *description (Butputs the extension of ( + *snippet (path( . (< or ( + *link f . ( if the filename has no extension.( . + *examples + *example (USING: io.pathnames prettyprint !( (>(QusrQbinQgcc>( file)extension .( (f( . + *example (USING: io.pathnames prettyprint !( (>(QhomeQcsiQgui.vbs>( file)extension .( (>(vbs>(( . . ! ?'&;: file)stem + *values + (path( (a pathname string( . + (stem( string . . + *description (Butputs the ( + *link file)name . ( of ( + *snippet (path( . ( ith the file extension removed< if any.( . + *examples + *example (USING: io.pathnames prettyprint !( (>(QusrQbinQgcc>( file)stem .( (>(gcc>(( . + *example (USING: io.pathnames prettyprint !( (>(QhomeQcsiQgui.vbs>( file)stem .( (>(gui>(( . . ! + file)name file)stem file)extension . related) ords ?'&;: path)components + *values + (path( (a pathnames string( . + (seq( sequence . . + *description (Splits a pathname on the ( + *link path)separator . ( into its its component strings.( . ! ?'&;: append)path + *values + (path1( (a pathname string( . + (path,( (a pathname string( . + (path( (a pathname string( . .

+ *description ("ppends ( + *snippet (path1( . ( and ( + *snippet (path,( . ( to form a pathname.( . + *examples + *unchecked)example (((USING: io.pathnames prettyprint ! (first( (second.txt( append)path .((( (>(firstQsecond.txt>(( . . ! ?'&;: prepend)path + *values + (path1( (a pathname string( . + (path,( (a pathname string( . + (path( (a pathname string( . . + *description ("ppends ( + *snippet (path,( . ( and ( + *snippet (path1( . ( to form a pathname.( . + *examples + *unchecked)example (((USING: io.pathnames prettyprint ! (second.txt( (first( prepend)path .((( (>(firstQsecond.txt>(( . . ! + append)path prepend)path . related) ords ?'&;: absolute)path: + *values + (path( (a pathname string( . + (:( (a boolean( . . + *description ($ests if a pathname is absolute. 'xamples of absolute pathnames are ( + *snippet (QfooQbar( . ( on Unix and ( + *snippet (c:>>foo>>bar( . ( on Jindo s.( . ! ?'&;: indo s)absolute)path: + *values + (path( (a pathname string( . + (:( (a boolean( . . + *description ($ests if a pathname is absolute on Jindo s. 'xamples of absolute pathnames on Jindo s are ( + *snippet (c:>>foo>>bar( . ( and ( + *snippet (>>>>:>>c:>>foo>>bar( . ( for absolute Unicode pathnames.( . ! ?'&;: root)directory: + *values + (path( (a pathname string( . + (:( (a boolean( . . + *description ($ests if a pathname is a root directory. 'xamples of root directory pathnames are ( + *snippet (Q( . ( on Unix and ( + *snippet (c:>>( . ( on Jindo s.( . ! + absolute)path: indo s)absolute)path: root)directory: . related) ords

?'&;: resource)path + *values + (path( (a pathname string( . + (ne path( (a pathname string( . . + *description (#esolve a path relative to the @actor source code location.( . ! ?'&;: pathname + *class)description (%lass of path name obFects. ;ath name obFects can be created by calling ( + *link PpathnameG . (.( . ! ?'&;: normali8e)path + *values + (path( (a pathname string( . + (path7( (a ne pathname string( . . + *description (;repends the ( + *link current)directory . ( to the pathname< resolves a ( + *snippet (resource:( . ( or ( + *snippet (vocab:( . ( prefix< if present 5see ( + *link (io.pathnames.special( . (6. "lso converts the path into a UN% path on Jindo s.( . + *notes (?igh)level ords< such as ( + *link Pfile)readerG . ( and ( + *link delete)file . ( call this ord for you. It only needs to be called directly hen passing pathnames to % functions or external processes. $his is because @actor does not use the operating system7s notion of a current directory< and instead maintains its o n dynamically)scoped ( + *link current)directory . (

variable.( . + *notes (Bn Jindo s N$ platforms< this ord prepends the Unicode path prefix.( . + *examples (@or example< if you create a file named ( + *snippet (data.txt( . ( in the current directory< and ish to pass it to a process< you must normali8e it:( + *code (>(1 , ->( >(data.txt>( ascii set)file)contents( (>(munge>( >(data.txt>( normali8e)path ,array run)process( . . ! ?'&;: absolute)path + *values + (path( (a pathname string( . + (path7( (a pathname string( . . + *description (;repends the ( + *link current)directory . ( to the pathname and resolves a ( + *snippet (resource:( . (< ( + *snippet (c( . ( or ( + *snippet (vocab:( . ( prefix< if present 5see ( + *link (io.pathnames.special( . (6.( . + *notes ($his ord is exactly the same as ( + *link normali8e)path . (< except on Jindo s N$ platforms< here it does not prepend the Unicode path prefix. Iost code should call ( + *link normali8e)path . ( instead.( . ! ?'&;: resolve)symlinks + *values + (path( (a pathname string( . + (path7( (a ne pathname string( . . + *description (Butputs a path here none of the path components are symlinks. $his ord is useful for determining the actual path on disk here a file is stored! the root of this absolute path is a mount point in the file)system.( . + *notes (Iost code should not need to call this ord except in very special circumstances. Bne use case is finding the actual file)system on hich a file is stored.( . ! ?'&;: PpathnameG + *values + (string( (a pathname string( . + (pathname( pathname . . + *description (%reates a ne ( + *link pathname . (.( . ! ?'&;: home + *values + (dir( string . . + *description (Butputs the user7s home directory.( . + *examples + *unchecked)example (USING: io.pathnames prettyprint !( (home .( (>(QhomeQfactor)user>(( . . ! "#$I%&': (io.pathnames.special( (Special pathnames( (If a pathname begins ith ( + *snippet (resource:( . (< it is resolved relative to the directory containing the current image 5see ( + *link image . (6.( *nl (If a pathname begins ith ( + *snippet (vocab:( . (< then it ill be searched for in all current vocabulary roots 5see ( + *link (add)vocab)roots( . (6.( *nl (If a pathname begins ith ( + *snippet (c( . (< it ill be searched for in the home directory. Subsequent tildes in the pathname ill be construed as literal tilde path or filenames and ill not be treated specially. $o access a filename named ( + *snippet (c( . (< you must construct a path to reference the filename< even if it7s ithin the current directory such as ( + *snippet (.Qc( . (.( ! "#$I%&': (io.pathnames.presentations( (;athname presentations( (;athname presentations are obFects that rap a pathname string. %licking a

pathname presentation in the UI brings up the file in one of the supported editors. See ( + *link (editor( . ( for more details.( + *subsections pathname PpathnameG . (&iteral pathname presentations:( + *subsections ;BS$;BN': ;( . (Iany ords that accept pathname strings can also ork on pathname presentations.( ! "#$I%&': (io.pathnames( (;athnames( (;athnames are strings that refer to a file on disk. ;athname semantics are platform)specific< and @actor makes no attempt to abstract a ay the differences. Note that on Jindo s< both for ard and back ard slashes are accepted as directory separators.( *nl (;athname introspection:( + *subsections parent)directory file)name file)stem file)extension path)components . ("ppending pathnames:( + *subsections prepend)path append)path . (Normali8ing pathnames:( + *subsections normali8e)path absolute)path resolve)symlinks . ("dditional topics:( + *subsections (io.pathnames.presentations( (io.pathnames.special( . ! "EBU$: (io.pathnames( K %opyright 5%6 ,==-< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: destructors kernel kernel.private math namespaces sequences sequences.private ! IN: io SNIEB&S: 2byte2 2character2 ! G'N'#I%: stream)element)type 5 stream )) type 6 G'N'#I%: stream)read1 5 stream )) elt 6 G'N'#I%: stream)read)unsafe 5 n buf stream )) count 6 G'N'#I%: stream)read)until 5 seps stream )) seq sepQf 6 G'N'#I%: stream)read)partial)unsafe 5 n buf stream )) count 6 G'N'#I%: stream)readln 5 stream )) strQf 6 G'N'#I%: stream)contents4 5 stream )) seq 6 : stream)contents 5 stream )) seq 6 0 stream)contents4 3 ith)disposal ! G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: stream) rite1 5 elt stream )) 6 stream) rite 5 data stream )) 6 stream)flush 5 stream )) 6 stream)nl 5 stream )) 6

'##B#: bad)seek)type type ! SING&'$BNS: seek)absolute seek)relative seek)end !

G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%:

stream)tell 5 stream )) n stream)seek 5 n seek)type stream)seekable: 5 stream stream)length 5 stream ))

6 stream )) 6 )) : 6 nQf 6

: stream)print 5 str stream )) 6 0 stream) rite 3 0 stream)nl 3 bi ! inline K Cefault streams IIMIN: input)stream IIMIN: output)stream SNIEB&: error)stream : : : : : : : readln 5 )) strQf 6 input)stream get stream)readln ! inline read1 5 )) elt 6 input)stream get stream)read1 ! inline read)until 5 seps )) seq sepQf 6 input)stream get stream)read)until ! inline tell)input 5 )) n 6 input)stream get stream)tell ! inline tell)output 5 )) n 6 output)stream get stream)tell ! inline seek)input 5 n seek)type )) 6 input)stream get stream)seek ! inline seek)output 5 n seek)type )) 6 output)stream get stream)seek ! inline

: rite1 5 elt )) 6 output)stream get stream) rite1 ! inline : rite 5 seq )) 6 output)stream get stream) rite ! inline : flush 5 )) 6 output)stream get stream)flush ! inline : nl 5 )) 6 output)stream get stream)nl ! inline : : : : : : : : : : : : ith)input)stream4 5 stream quot )) 6 input)stream s ap ith)variable ! inline ith)input)stream 5 stream quot )) 6 0 ith)input)stream4 3 curry ith)disposal ! inline ith)output)stream4 5 stream quot )) 6 output)stream s ap ith)variable ! inline ith)output)stream 5 stream quot )) 6 0 ith)output)stream4 3 curry ith)disposal ! inline ith)error)stream4 5 stream quot )) 6 error)stream s ap ith)variable ! inline ith)error)stream 5 stream quot )) 6 0 ith)error)stream4 3 curry ith)disposal ! inline ith)output2error)stream4 5 stream quot )) 6 0 dup 3 dip 0 ith)error)stream4 3 curry ith)output)stream4 ! inline ith)output2error)stream 5 stream quot )) 6 0 ith)output2error)stream4 3 curry ith)disposal ! inline ith)outputGerror 5 quot )) 6 error)stream get s ap ith)output)stream4 ! inline ith)errorGoutput 5 quot )) 6 output)stream get s ap ith)error)stream4 ! inline ith)streams4 5 input output quot )) 6 s apd 0 ith)output)stream4 3 curry ith)input)stream4 ! inline ith)streams 5 input output quot )) 6

ZK Je have to dispose of the output stream first< so that ZK if both streams point to the same @C< e get to flush the ZK buffer before closing the @C. s apd 0 ith)output)stream 3 curry ith)input)stream ! inline : : ith)input)output2error)streams4 5 input output2error quot )) 6 s apd 0 ith)output2error)stream4 3 curry ith)input)stream4 ! inline ith)input)output2error)streams 5 input output2error quot )) 6 s apd 0 ith)output2error)stream 3 curry ith)input)stream ! inline

: print 5 str )) 6 output)stream get stream)print ! inline : stream)bl 5 stream )) 6 ( ( s ap stream) rite ! inline : bl 5 )) 6 output)stream get stream)bl ! : each)morsel 5 ..a handler: 5 ..a data )) ..b 6 reader: 5 ..b )) ..a data 6 )) ..a 6 0 dup 3 compose s ap hile drop ! inline P;#IV"$' : stream)exemplar 5 stream )) exemplar 6 stream)element)type 2byte2 H E+ . (( : ! inline : stream)exemplar)gro able 5 stream )) exemplar 6 stream)element)type 2byte2 H EV+ . SEU@( ( : ! inline : 5ne )sequence)for)stream6 5 n stream )) seq 6 stream)exemplar ne )sequence ! inline : resi8e)if)necessary 5 anted)n got)n seq )) seq7 6 ,over H 0 0 ,drop 3 dip 3 0 resi8e nip 3 if ! inline : 5read)into)ne 6 5 n stream quot )) seqQf 6 0 dup 3 ,dip 0 ,dup 5ne )sequence)for)stream6 s ap 3 dip curry keep over = H 0 -drop f 3 0 resi8e)if)necessary 3 if ! inline : 5read)into6 5 buf stream quot )) buf)sliceQf 6 0 dup length over 3 ,dip call 0 5head6 Pslice)unsafeG 3 0 8ero: not 3 bi ! inline ;#IV"$'G : stream)read 5 n stream )) seqQf 6 0 stream)read)unsafe 3 5read)into)ne 6 ! inline : stream)read)partial 5 n stream )) seqQf 6 0 stream)read)partial)unsafe 3 5read)into)ne 6 ! inline '##B#: invalid)read)buffer buf stream ! : stream)read)into 5 buf stream )) buf)slice more: 6 0 stream)read)unsafe + fixnum . declare 3 5read)into6 ! inline : stream)read)partial)into 5 buf stream )) buf)slice more: 6 0 stream)read)partial)unsafe + fixnum . declare 3 5read)into6 ! inline : read 5 n )) seq 6 input)stream get stream)read ! inline

: read)partial 5 n )) seq 6 input)stream get stream)read)partial ! inline : read)into 5 buf )) buf)slice more: 6 input)stream get stream)read)into ! inline : read)partial)into 5 buf )) buf)slice more: 6 input)stream get stream)read)partial)into ! inline : each)stream)line 5 ... stream quot: 5 ... line )) ... 6 )) ... 6 s ap 0 stream)readln 3 curry each)morsel ! inline : each)line 5 ... quot: 5 ... line )) ... 6 )) ... 6 input)stream get s ap each)stream)line ! inline : stream)lines 5 stream )) seq 6 0 0 3 collector 0 each)stream)line 3 dip + . like 3 ith)disposal ! inline : lines 5 )) seq 6 input)stream get stream)lines ! inline %BNS$"N$: each)block)si8e LAA-L : each)stream)block)slice 5 ... stream quot: 5 ... block)slice )) ... 6 )) ... 6 0 drop 3 prepose s ap 0 each)block)si8e s ap 5ne )sequence)for)stream6 3 keep 0 stream)read)partial)into 3 ,curry each)morsel drop ! inline : each)stream)block 5 ... stream quot: 5 ... block )) ... 6 )) ... 6 s ap 0 each)block)si8e s ap stream)read)partial 3 curry each)morsel ! inline : each)block)slice 5 ... quot: 5 ... block )) ... 6 )) ... 6 input)stream get s ap each)stream)block)slice ! inline : each)block 5 ... quot: 5 ... block )) ... 6 )) ... 6 input)stream get s ap each)stream)block ! inline : 5stream)contents)by)length6 5 stream len )) seq 6 dup rot 0 5ne )sequence)for)stream6 3 0 0 stream)read)unsafe 3 curry keep resi8e 3 bi ! inline : 5stream)contents)by)block6 5 stream )) seq 6 0 0 3 collector 0 each)stream)block 3 dip + . like 3 0 stream)exemplar concat)as 3 bi ! inline : 5stream)contents)by)length)or)block6 5 stream )) seq 6 dup stream)length 0 5stream)contents)by)length6 3 0 5stream)contents)by)block6 3 if4 ! inline : 5stream)contents)by)element6 5 stream )) seq 6 0 0 0 stream)read1 dup 3 curry 0 3 3 0 stream)exemplar produce)as nip 3 bi 3 ith)disposal ! inline : contents 5 )) seq 6 input)stream get stream)contents ! inline : stream)copy4 5 in out )) 6

0 stream) rite 3 curry each)stream)block ! inline : stream)copy 5 in out )) 6 0 0 stream)copy4 3 ith)disposal 3 curry ith)disposal ! inline

K Cefault implementations of stream operations in terms of read1Q rite1 P;#IV"$' : read)loop 5 buf stream n i )) count 6 ,dup H 0 nip nip nip 3 0 pick stream)read1 0 over 0 pick set)nth)unsafe 3 ,curry -dip 1 2 read)loop 3 0 nip nip nip 3 if4 3 if ! inline recursive : finali8e)read)until 5 seq sepQf )) seqQf sepQf 6 ,dup 0 empty: 3 0 not 3 bi4 and 0 ,drop f f 3 hen ! inline : read)until)loop 5 seps stream )) seq sepQf 6 0 0 stream)read1 dup 0 rot member: not 3 0 nip f 3 if4 3 ,curry 0 3 3 0 stream)exemplar 3 bi produce)as s ap finali8e)read)until ! inline ;#IV"$'G I: I: I: I: input)stream stream)read)unsafe rot = read)loop ! inline input)stream stream)read)partial)unsafe stream)read)unsafe ! inline input)stream stream)read)until read)until)loop ! inline input)stream stream)readln (>n( s ap stream)read)until drop ! inline I: input)stream stream)contents4 5stream)contents)by)length)or)block6 ! inline I: input)stream stream)seekable: drop f ! inline I: input)stream stream)length drop f ! inline I: I: I: I: I: I: I: I: I: I: I: output)stream output)stream output)stream output)stream output)stream f f f f f f stream) rite 0 stream) rite1 3 curry each ! inline stream)flush drop ! inline stream)nl %?"#: >n s ap stream) rite1 ! inline stream)seekable: drop f ! inline stream)length drop f ! inline

stream)read1 drop f ! inline stream)read)unsafe -drop = ! inline stream)read)until ,drop f f ! inline stream)read)partial)unsafe -drop = ! inline stream)readln drop f ! inline stream)contents4 drop f ! inline

I: f stream) rite1 ,drop ! inline I: f stream) rite ,drop ! inline I: f stream)flush drop ! inline I: f stream)nl drop ! inline USING: help.markup help.syntax io strings arrays io.backend io.files.private quotations sequences ! IN: io.files "#$I%&': (io.files.examples( ('xamples of reading and riting files( (Sort the lines in a file and rite them back to the same file:( + *code (USING: io io.encodings.utfS io.files sequences sorting !( (>(lines.txt>( utfS 0 file)lines natural)sort 3 ,keep set)file)lines( . (#ead 1=,/ bytes from a file:( + *code

. !

(USING: io io.encodings.binary io.files !( (>(data.bin>( binary 0 1=,/ read 3 ith)file)reader(

"#$I%&': (io.files( (#eading and riting files( + *subsections (io.files.examples( . (@ile streams:( + *subsections Pfile)readerG Pfile) riterG Pfile)appenderG . (#eading and riting the entire contents of a file! this is only recommended for smaller files:( + *subsections file)contents set)file)contents file)lines set)file)lines . (Utility combinators:( + *subsections ith)file)reader ith)file) riter ith)file)appender . ! "EBU$: (io.files( ?'&;: Pfile)readerG + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (stream( (an input stream( . . + *description (Butputs an input stream for reading from the specified pathname using the given encoding.( . + *notes (Iost code should use ( + *link ith)file)reader . ( instead< to ensure the stream is properly disposed of after.( . + *errors ($hro s an error if the file is unreadable.( . ! ?'&;: Pfile) riterG + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (stream( (an output stream( . . + *description (Butputs an output stream for riting to the specified pathname using the given encoding. $he file7s length is truncated to 8ero.( . + *notes (Iost code should use ( + *link ith)file) riter . ( instead< to ensure the stream is properly disposed of after.( . + *errors ($hro s an error if the file cannot be opened for riting.( . ! ?'&;: Pfile)appenderG + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (stream( (an output stream( . . + *description (Butputs an output stream for riting to the specified pathname using the given encoding. $he stream begins riting at the end of the file.( . + *notes (Iost code should use ( + *link ith)file)appender . ( instead< to ensure the stream is properly disposed of after.( . + *errors ($hro s an error if the file cannot be opened for riting.( . ! ?'&;: ith)file)reader + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (quot( (a quotation( . . + *description (Bpens a file for reading and calls the quotation using ( + *link ith)input)stream . (.( . + *errors ($hro s an error if the file is unreadable.( . !

?'&;: ith)file) riter + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (quot( (a quotation( . . + *description (Bpens a file for riting using the given encoding and calls the quotation using ( + *link ith)output)stream . (.( . + *errors ($hro s an error if the file cannot be opened for riting.( . ! ?'&;: ith)file)appender + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (quot( (a quotation( . . + *description (Bpens a file for appending using the given encoding and calls the quotation using ( + *link ith)output)stream . (.( . + *errors ($hro s an error if the file cannot be opened for riting.( . ! ?'&;: set)file)lines + *values + (seq( (an array of strings( . + (path( (a pathname string( . + (encoding( (an encoding descriptor( . . + *description (Sets the contents of a file to the strings ith the given encoding.( . + *errors ($hro s an error if the file cannot be opened for riting.( . ! ?'&;: file)lines + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (seq( (an array of strings( . . + *description (Bpens the file at the given path using the given encoding< and returns a list of the lines in that file.( . + *errors ($hro s an error if the file cannot be opened for reading.( . ! ?'&;: set)file)contents + *values + (seq( sequence . + (path( (a pathname string( . + (encoding( (an encoding descriptor( . . + *description (Sets the contents of a file to a sequence ith the given encoding.( . + *errors ($hro s an error if the file cannot be opened for riting.( . ! ?'&;: file)contents + *values + (path( (a pathname string( . + (encoding( (an encoding descriptor( . + (seq( sequence . . + *description (Bpens the file at the given path using the given encoding< and the contents of that file as a sequence.( . + *errors ($hro s an error if the file cannot be opened for reading.( . ! + set)file)lines file)lines set)file)contents file)contents . related) ords ?'&;: exists: + *values + (path( (a pathname string( . + (:( (a boolean( . . + *description ($ests if the file named by ( + *snippet (path( . ( exists.( . ! USING: alien alien.c)types alien.data arrays classes.struct debugger.threads destructors generic.single io io.directories io.encodings.S)bit.latin1 io.encodings.ascii io.encodings.binary io.encodings.string io.files io.files.private io.files.temp io.files.unique kernel make math sequences speciali8ed)arrays system threads tools.test vocabs compiler.units ! @#BI: speciali8ed)arrays.private HG speciali8ed)array)vocab ! S;'%I"&IO'C)"##"N: int IN: io.files.tests 0 3 0 (append)test( temp)file dup exists: 0 delete)file 3 0 drop 3 if 3 unit)test

0 3 0 (append)test( temp)file ascii Pfile)appenderG dispose 3 unit)test 0 3 0 ($his is a line.>r$his is another line.>r( (vocab:ioQtestQmac)os)eol.txt( latin1 0 A== read 3 ith)file)reader 3 unit)test 0 3 0 ,AA

(vocab:ioQtestQbinary.txt( latin1 0 read1 3 ith)file)reader Gfixnum 3 unit)test 0 3 0 ($his( %?"#: >s (vocab:ioQtestQread)until)test.txt( ascii 0 ( ( read)until 3 ith)file)reader 3 unit)test 0 3 0 ($his( %?"#: >s

(vocab:ioQtestQread)until)test.txt( binary 0 ( ( read)until 0 ascii decode 3 dip 3 ith)file)reader 3 unit)test 0 3 0 (It seems Xobs has lost his grasp on reality again.>n( (separator)test.txt( temp)file latin1 set)file)contents 3 unit)test 0 + + (It seems ( %?"#: X . + (obs has lost h( %?"#: i . + (s grasp on reality again.>n( f .

. 3 0 0

(separator)test.txt( temp)file latin1 0 (X( read)until ,array < (i( read)until ,array < (M( read)until ,array < 3 ith)file)reader 3 + . make 3 unit)test 0 3 0 image binary 0 1= 0 LAA-L read drop 3 times 3 ith)file)reader 3 unit)test K Jriting speciali8ed arrays to binary streams should 0 3 0 (test.txt( temp)file binary 0 int)array+ 1 , - . rite ork

3 ith)file) riter 3 unit)test 0 int)array+ 1 , - . 3 0 (test.txt( temp)file binary 0 - / 4 read 3 ith)file)reader int cast)array 3 unit)test 0 3 0 EV+ = 1 , . (test.txt( temp)file binary set)file)contents 3 unit)test 0 t 3 0 (test.txt( temp)file binary file)contents E+ = 1 , . H 3 unit)test S$#U%$: pt + x uint . + y uint . ! S;'%I"&IO'C)"##"N: pt %BNS$"N$: pt)array)1 pt)array+ S+ pt f 1 1 . S+ pt f , , . S+ pt f - - . . 0 3 0 pt)array)1 (test.txt( temp)file binary set)file)contents 3 unit)test 0 t 3 0 (test.txt( temp)file binary file)contents pt)array)1 Gc)ptr sequenceH 3 unit)test K Slices should support Gc)ptr and byte)length 0 3 0 pt)array)1 rest)slice (test.txt( temp)file binary set)file)contents 3 unit)test 0 t 3 0 (test.txt( temp)file binary file)contents pt cast)array pt)array)1 rest)slice sequenceH 3 unit)test 0 3 0 0

pt speciali8ed)array)vocab forget)vocab 3 ith)compilation)unit 3 unit)test K Jriting strings to binary streams should fail 0 (test.txt( temp)file binary 0 (BIG@"I&( rite 3 ith)file) riter 3 must)fail K $est 'B@ behavior

0 1= 3 0 image binary 0 = read drop 1= read length 3 ith)file)reader 3 unit)test K Iake sure that riting to a closed stream from another thread doesn7t crash 0 3 0 (test)quux.txt( temp)file ascii 0 0 yield (?i( rite 3 ($est( spa n drop 3 ith)file) riter 3 unit)test 0 3 0 (test)quux.txt( temp)file delete)file 3 unit)test 0 3 0 (test)quux.txt( temp)file ascii 0 0 yield (?i( ith)file) riter 3 unit)test rite 3 ($est( spa n drop 3

0 3 0 (test)quux.txt( (quux)test.txt( 0 temp)file 3 bi9 move)file 3 unit)test 0 t 3 0 (quux)test.txt( temp)file exists: 3 unit)test 0 3 0 (quux)test.txt( temp)file delete)file 3 unit)test K @ile seeking tests 0 E+ - , - / A . 3 0 (seek)test1( unique)file binary 0 0 E+ 1 , - / A . rite tell)output A assertH = seek)absolute seek)output tell)output = assertH E+ - . rite tell)output 1 assertH 3 ith)file) riter 3 0 file)contents 3 ,bi 3 unit)test 0 E+ 1 , - / - . 3 0 (seek)test,( unique)file binary 0 0 E+ 1 , - / A . rite tell)output A assertH )1 seek)relative seek)output tell)output / assertH E+ - . rite tell)output A assertH 3 ith)file) riter 3 0 file)contents 3 ,bi 3 unit)test 0 E+ 1 , - / A = - . 3 0 (seek)test-( unique)file binary 0 0

3 3 0

E+ 1 , - / A . rite tell)output A assertH 1 seek)relative seek)output tell)output L assertH E+ - . rite tell)output R assertH ith)file) riter

file)contents 3 ,bi 3 unit)test 0 E+ - . 3 0 E+ 1 , - / A . (seek)test/( unique)file binary 0 set)file)contents 3 0 0 tell)input = assertH )- seek)end seek)input tell)input , assertH 1 read tell)input - assertH 3 ith)file)reader 3 ,bi 3 unit)test 0 E+ , . 3 0 E+ 1 , - / A . (seek)testA( unique)file binary 0 set)file)contents 3 0 0 tell)input = assertH - seek)absolute seek)input tell)input - assertH ), seek)relative seek)input tell)input 1 assertH 1 read tell)input , assertH 3 ith)file)reader 3 ,bi 3 unit)test 0 (seek)testL( unique)file binary 0 )1= seek)absolute seek)input 3 ith)file)reader 3 must)fail 0 3 0 (resource:license.txt( binary 0 // read drop tell)input // assertH )// seek)relative seek)input tell)input = assertH 3 ith)file)reader 3 unit)test 0 (non)string)error( unique)file ascii 0 + . rite

3 ith)file) riter 3 0 no)method: 3 must)fail) ith 0 (non)byte)array)error( unique)file binary 0 (( rite 3 ith)file) riter 3 0 no)method: 3 must)fail) ith K Jhat happens if e close a file t ice: 0 3 0 (closing)t ice( unique)file ascii Pfile) riterG 0 dispose 3 0 dispose 3 bi 3 unit)test K %opyright 5%6 ,==/< ,==U Slava ;estov< Caniel 'hrenberg. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: alien.strings init io io.backend io.encodings io.encodings.utfS io.files.private io.pathnames kernel kernel.private namespaces sequences splitting system ! IN: io.files IIMIN: file)reader IIMIN: file) riter I: file)reader stream)element)type drop 2byte2 ! inline I: file) riter stream)element)type drop 2byte2 ! inline ?BBY: 5file)reader6 io)backend 5 path )) stream 6 ?BBY: 5file) riter6 io)backend 5 path )) stream 6 ?BBY: 5file)appender6 io)backend 5 path )) stream 6 : Pfile)readerG 5 path encoding )) stream 6 0 normali8e)path 5file)reader6 + file)reader . declare 3 dip PdecoderG ! inline : Pfile) riterG 5 path encoding )) stream 6 0 normali8e)path 5file) riter6 + file) riter . declare 3 dip PencoderG ! inline : Pfile)appenderG 5 path encoding )) stream 6 0 normali8e)path 5file)appender6 + file) riter . declare 3 dip PencoderG ! inline : file)lines 5 path encoding )) seq 6 Pfile)readerG stream)lines ! : ith)file)reader 5 path encoding quot )) 6 0 Pfile)readerG 3 dip ith)input)stream ! inline

: file)contents 5 path encoding )) seq 6 Pfile)readerG stream)contents ! : ith)file) riter 5 path encoding quot )) 6 0 Pfile) riterG 3 dip ith)output)stream ! inline

: set)file)lines 5 seq path encoding )) 6 0 0 print 3 each 3 ith)file) riter ! : set)file)contents 5 seq path encoding )) 6 0 rite 3 ith)file) riter !

ith)file)appender 5 path encoding quot )) 6 0 Pfile)appenderG 3 dip ith)output)stream ! inline

: exists: 5 path )) : 6 normali8e)path native)stringGalien 5exists:6 ! K %urrent directory P;#IV"$' ?BBY: cd io)backend 5 path )) 6 ?BBY: c d io)backend 5 )) path 6 I: obFect c d 5 )) path 6 (.( ! ;#IV"$'G : init)resource)path 5 )) 6 BEX)"#GS special)obFect 0 utfS alienGstring ()resource)pathH( :head 0 drop f 3 unless 3 map)find drop 0 image parent)directory 3 unless4 (resource)path( set)global ! 0 c d current)directory set)global BEX)II"G' special)obFect alienGnative)string c d prepend)path > image set)global BEX)'M'%U$"E&' special)obFect alienGnative)string c d prepend)path > vm set)global init)resource)path 3 (io.files( add)startup)hook USING: io.encodings.utfS tools.test io.encodings.string strings arrays bootstrap.unicode kernel sequences ! IN: io.encodings.utfS.tests : decode)utfS) Qstream 5 array )) ne array 6 utfS decode Garray ! : encode)utfS) Qstream 5 array )) ne array 6 Gstring utfS encode Garray ! 0 + %?"#: replacement)character . 3 0 + =b1111=<1=1 =b1=<111111 =b1=<====== =b11111111 . decode)utfS) Qstream 3 unit)test 0 (x( 3 0 (x( decode)utfS) Qstream Gstring 3 unit)test 0 + =b11111====== . 3 0 + =b11=<11111 =b1=<====== . decode)utfS) Qstream Garray 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b1======= . decode)utfS) Qstream 3 unit)test 0 + =b1111======111111 . 3 0 + =b111=<1111 =b1=<====== =b1=<111111 . decode)utfS) Qstream Garray 3 unit)test 0 + =b1111=<1=1 =b1=<111111 =b1=<====== =b1=<111111 =b111=<1111 =b1=<====== =b1=<111111 =b11=<11111 =b1=<====== %?"#: x . 3 0 + =b1=1111111======111111 =b1111======111111 =b11111====== %?"#: x . encode)utfS) Qstream 3 unit)test 0 - 3 0 1 (( GutfS)index 3 unit)test

0 - 3 0 U (( utfS)indexG 3 unit)test 0 - 3 0 , (ldpis( GutfS)index 3 unit)test 0 V+ . 3 0 1===== iota 0 0 code)point)length 3 0 1string utfS encode length 3 bi H not 3 filter 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b11=<===== =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b11=<====1 =b1=<111111 . decode)utfS) Qstream 3 unit)test 0 + =xS= . 3 0 + =b11=<===1= =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b111=<==== =b1=<====== =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b111=<==== =b1=<=11111 =b1=<111111 . decode)utfS) Qstream 3 unit)test 0 + =xS== . 3 0 + =b111=<==== =b1=<1===== =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b1111=<=== =b1=<====== =b1=<====== =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b1111=<=== =b1=<==1111 =b1=<111111 =b1=<111111 . decode)utfS) Qstream 3 unit)test 0 + %?"#: replacement)character . 3 0 + =b1111=<1== =b1=<=1==== =b1=<====== =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + =x1==== . 3 0 + =b1111=<=== =b1=<=1==== =b1=<====== =b1=<====== . decode)utfS) Qstream 3 unit)test 0 + =x1=@@@@ . 3 0 + =b1111=<1== =b1=<==1111 =b1=<111111 =b1=<111111 . decode)utfS) Qstream 3 unit)test K %opyright 5%6 ,==L< ,==S Caniel 'hrenberg. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays math math.order kernel sequences sbufs vectors gro able io continuations namespaces io.encodings combinators strings ! IN: io.encodings.utfS K Cecoding U$@)S SING&'$BN: utfS P;#IV"$' : starts),: 5 char )) : 6 dup 0 )L shift =b1= numberH 3 hen ! inline

: append)nums 5 stream byte )) stream char 6 over stream)read1 dup starts),: 0 0 L shift 3 dip =b111111 bitand bitor 3 0 ,drop replacement)char 3 if ! inline : minimum)code)point 5 char minimum )) char 6 over G 0 drop replacement)char 3 hen ! inline : maximum)code)point 5 char maximum )) char 6 over P 0 drop replacement)char 3 hen ! inline : double 5 stream byte )) stream char 6 =b11111 bitand append)nums =xS= minimum)code)point ! inline : triple 5 stream byte )) stream char 6

=b1111 bitand append)nums append)nums =xS== minimum)code)point ! inline : quadruple 5 stream byte )) stream char 6 =b111 bitand append)nums append)nums append)nums =x1==== minimum)code)point =x1=@@@@ maximum)code)point ! inline : begin)utfS 5 stream byte )) stream char 6 dup 1,R G 0 + + 0 dup )A shift =b11= H 3 0 double 3 . + 0 dup )/ shift =b111= H 3 0 triple 3 . + 0 dup )- shift =b1111= H 3 0 quadruple 3 . 0 drop replacement)char 3 . cond 3 hen ! inline : decode)utfS 5 stream )) charQf 6 dup stream)read1 dup 0 begin)utfS 3 I: utfS decode)char drop decode)utfS ! inline I: utfS decode)until 5decode)until6 ! K 'ncoding U$@)S : encoded 5 stream char )) 6 =b111111 bitand =b1======= bitor s ap stream) rite1 ! inline : charGutfS 5 char stream )) 6 over 1,R PH 0 stream) rite1 3 0 s ap + + 0 dup )11 shift 8ero: 3 0 ,dup )L shift =b11====== bitor s ap stream) rite1 encoded 3 . + 0 dup )1L shift 8ero: 3 0 ,dup )1, shift =b111===== bitor s ap stream) rite1 ,dup )L shift encoded encoded 3 . 0 ,dup )1S shift =b1111==== bitor s ap stream) rite1 ,dup )1, shift encoded ,dup )L shift encoded encoded 3 . cond 3 if ! inline I: utfS encode)char drop charGutfS ! I: utfS encode)string drop over auxGG 0 0 charGutfS 3 curry each 3 0 0 Gbyte)array 3 dip stream) rite 3 if ! ;#IV"$'G hen nip ! inline

: code)point)length 0 1 3 0 log, + + 0 dup + 0 dup + 0 dup + 0 dup . cond nip 3 if)8ero !

5 n )) x 6 = L bet een: 3 0 1 3 . R 1= bet een: 3 0 , 3 . 11 1A bet een: 3 0 - 3 . 1L ,= bet een: 3 0 / 3 .

: code)point)offsets 5 string )) indices 6 = 0 code)point)length 2 3 accumulate s ap suffix ! : utfS)indexG 5 n string )) n7 6 code)point)offsets 0 PH 3 ith find drop ! : GutfS)index 5 n string )) n7 6 code)point)offsets nth ! USING: help.markup help.syntax ! IN: io.encodings.utfS ?'&;: utfS + *class)description ('ncoding descriptor for U$@)S encoding.( . ! "#$I%&': (io.encodings.utfS( (U$@)S encoding( (U$@)S is a variable) idth encoding. R)bit "S%II characters are encoded as single bytes< and other Unicode code points are encoded as , to / byte sequences.( + *subsections utfS . ! "EBU$: (io.encodings.utfS( USING: help.markup help.syntax io quotations math ! IN: io.encodings ?'&;: PencoderG + *values + (stream( (an output stream( . + (encoding( (an encoding descriptor( . + (ne stream( (an encoded output stream( . . + *description (Jraps the given stream in a ne stream using the given encoding for all output. $he encoding descriptor can either be a class or an instance of something conforming to the ( + *link (encodings)protocol( . (.( . *lo )level)note ! ?'&;: PdecoderG + *values + (stream( (an input stream( . + (encoding( (an encoding descriptor( . + (ne stream( (an encoded output stream( . . + *description (Jraps the given stream in a ne stream using the given encoding for all input. $he encoding descriptor can either be a class or an instance of something conforming to the ( + *link (encodings)protocol( . (.( . *lo )level)note ! ?'&;: decode)char + *values + (stream( (an underlying input stream( . + (encoding( ("n encoding descriptor tuple( . + (charQf( (a code point or ( + *link f . . . + *contract (#eads a single code point from the underlying stream< interpreting it by the encoding. #eturns ( + *link f . ( if the stream is reached.( . *lo )level)note ! ?'&;: encode)char

+ *values + (char( (a character( . + (stream( (an underlying output stream( . + (encoding( (an encoding descriptor( . . + *contract (Jrites the code point to the underlying stream in the given encoding.( . *lo )level)note ! + encode)char decode)char . related) ords ?'&;: decode)input + *values + (encoding( (an encoding descriptor( . . + *description (%hanges the encoding of the current input stream stored in the ( + *link input)stream . ( variable.( . ! ?'&;: encode)output + *values + (encoding( (an encoding descriptor( . . + *description (%hanges the encoding of the current output stream stored in the ( + *link output)stream . ( variable.( . ! ?'&;: re)decode + *values + (stream( (a stream( . + (encoding( (an encoding descriptor( . + (ne stream( (a ne stream( . . + *description (%reates a ne decoding stream ith the supplied encoding descriptor from an existing stream by calling the ( + *link PdecoderG . ( . ! ?'&;: re)encode + *values + (stream( (a stream( . + (encoding( (an encoding descriptor( . + (ne stream( (a ne stream( . . + *description (%reates a ne encoding stream ith the supplied encoding descriptor from an existing stream by calling the ( + *link PencoderG . ( . ! + re)decode re)encode . related) ords ?'&;: ith)decoded)input + *values + (encoding( (an encoding descriptor( . + (quot( quotation . . + *description (%reates a ne decoding stream ith the given encoding descriptor and calls the quotation ith this stream set to the ( + *link input)stream . ( variable. $he original decoder stream is restored after the quotation returns and the stream is kept open for future input operations.( . ! ?'&;: ith)encoded)output + *values + (encoding( (an encoding descriptor( . + (quot( quotation . . + *description (%reates a ne encoder ith the given encoding descriptor and calls the quotation using this encoder. $he original encoder obFect is restored after the quotation returns and the stream is kept open for future output operations.( . ! ?'&;: replacement)char

ord.(

ord.(

+ *values + (value( integer . . + *description (" code point that replaces input that could not be decoded. $he presence of this character in the decoded data usually signifies an error.( . ! "#$I%&': (encodings)descriptors( ('ncoding descriptors( ("n encoding descriptor is something hich can be used ith binary input or output streams to encode or decode bytes stored in a certain representation. It must conform to the ( + *link (encodings)protocol( . (. 'ncodings hich you can use are defined in the follo ing vocabularies:( + *subsections (io.encodings.binary( (io.encodings.utfS( . + *vocab)subsection (U$@)1L encoding( (io.encodings.utf1L( . + *vocab)subsection (U$@)-, encoding( (io.encodings.utf-,( . + *vocab)subsection (Strict encodings( (io.encodings.strict( . (&egacy encodings:( + *vocab)subsection (S)bit encodings( (io.encodings.S)bit( . + *vocab)subsection ("S%II encoding( (io.encodings.ascii( . + *see)also (encodings)introduction( . ! "#$I%&': (encodings)protocol( ('ncoding protocol( ($here are t o parts to implementing a ne encoding. @irst< methods for creating an encoded or decoded stream must be provided. $hese have defaults< ho ever< hich rap a stream in an encoder or decoder rapper ith the given encoding descriptor.( + *subsections PencoderG PdecoderG . (If an encoding might be contained in the code slot of an encoder or decoder tuple< then the follo ing methods must be implemented to read or rite one code point from a stream:( + *subsections decode)char encode)char . + *see)also (encodings)introduction( . ! "#$I%&': (encodings)constructors( (Ianually constructing an encoded stream( ($he follo ing ords can be used to construct encoded streams. Note that they are usually not used directly< but rather by the stream constructors themselves. Iost stream constructors take an encoding descriptor as a parameter and call these constructors internally.( + *subsections PencoderG PdecoderG . ! "#$I%&': (io.encodings( (IQB encodings( ($he ( + *vocab)link (io.encodings( . ( vocabulary provides utilities for encoding and decoding bytes that represent text. 'ncodings can be used in the follo ing situations:( + *list (Jith binary input streams< to convert bytes to characters( (Jith binary output streams< to convert characters to bytes( (Jith byte arrays< to convert bytes to characters( (Jith strings< to convert characters to bytes( . + *subsections

(encodings)descriptors( (encodings)constructors( (io.encodings.string( . (Ne types of encodings can be defined:( + *subsections (encodings)protocol( . (Setting encodings on the current streams:( + *subsections encode)output decode)input . (Setting encodings on streams:( + *subsections re)encode re)decode . (%ombinators to change the encoding:( + *subsections ith)encoded)output ith)decoded)input . + *see)also (encodings)introduction( . ! "EBU$: (io.encodings( K %opyright 5%6 ,==L< ,==U Caniel 'hrenberg. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays combinators io io.binary io.encodings kernel math math.private namespaces sbufs sequences sequences.private splitting strings.private vectors ! IN: io.encodings.utf1L SING&'$BN: utf1Lbe SING&'$BN: utf1Lle SING&'$BN: utf1L '##B#: missing)bom ! P;#IV"$' K U$@)1LE' decoding : append)nums 5 byte ch )) ch 6 over 0 S shift bitor 3 0 ,drop replacement)char 3 if ! : double)be 5 stream byte )) stream char 6 over stream)read1 s ap append)nums ! : quad)be 5 stream byte )) stream char 6 double)be over stream)read1 0 dup ), shift =b11=111 numberH 0 0 , shift 3 dip =b11 bitand bitor over stream)read1 s ap append)nums =x1==== 2 3 0 ,drop dup stream)read1 drop replacement)char 3 if 3 hen4 ! : ignore 5 stream )) stream char 6 dup stream)read1 drop replacement)char ! : begin)utf1Lbe 5 stream byte )) stream char 6 dup )- shift =b11=11 numberH 0

dup =b=====1== bitand 8ero: 0 =b11 bitand quad)be 3 0 drop ignore 3 if 3 0 double)be 3 if ! I: utf1Lbe decode)char drop dup stream)read1 dup 0 begin)utf1Lbe 3 K U$@)1L&' decoding : quad)le 5 stream ch )) stream char 6 over stream)read1 s ap 1= shift bitor over stream)read1 dup ), shift =b11=111 H 0 =b11 bitand append)nums =x1==== 2 3 0 ,drop replacement)char 3 if ! : double)le 5 stream byte1 byte, )) stream char 6 dup )- shift =b11=11 H 0 dup =b1== bitand = numberH 0 =b11 bitand S shift bitor quad)le 3 0 ,drop replacement)char 3 if 3 0 append)nums 3 if ! : begin)utf1Lle 5 stream byte )) stream char 6 over stream)read1 dup 0 double)le 3 0 ,drop replacement)char 3 if ! I: utf1Lle decode)char drop dup stream)read1 dup 0 begin)utf1Lle 3 K U$@)1L&'QE' encoding : encode)first 5 char )) byte1 byte, 6 )1= shift 0 )S shift =b11=11=== bitor 3 0 =x@@ bitand 3 bi ! inline : encode)second 5 char )) byte- byte/ 6 =b1111111111 bitand 0 )S shift =b11=111== bitor 3 0 =b11111111 bitand 3 bi ! inline : stream) rite, 5 char1 char, stream )) 6 0 E+ . ,sequence 3 dip stream) rite ! inline K 0 stream) rite1 3 curry bi9 ! inline : charGutf1Lbe 5 char stream )) 6 over =x@@@@ G 0 0 =x1==== ) 3 dip 0 0 encode)first 3 dip stream) rite, 3 0 0 encode)second 3 dip stream) rite, 3 ,bi 3 0 0 hGbQb s ap 3 dip stream) rite, 3 if ! inline I: utf1Lbe encode)char 5 char stream encoding )) 6 drop charGutf1Lbe ! : charGutf1Lle 5 char stream )) 6 over =x@@@@ G 0 0 =x1==== ) 3 dip 0 0 encode)first s ap 3 dip stream) rite, 3 0 0 encode)second s ap 3 dip stream) rite, 3 ,bi 3 0 0 hGbQb 3 dip stream) rite, 3 if ! inline I: utf1Lle encode)char 5 char stream encoding )) 6 drop charGutf1Lle ! hen nip ! hen nip !

: ascii)charGutf1L)byte)array 5 off n byte)array string )) 6 0 over 3 dip string)nth)fast )rot 0 , fixnum4fast rot fixnum2fast 3 dip set)nth)unsafe ! inline : ascii)stringGutf1L)byte)array 5 off string )) byte)array 6 0 length Gfixnum 0 iota 3 0 , fixnum4fast Pbyte)arrayG 3 bi 3 keep 0 0 ascii)charGutf1L)byte)array 3 ,curry ith each 3 ,keep drop ! inline : ascii)stringGutf1Lle 5 string stream )) 6 0 = s ap ascii)stringGutf1L)byte)array 3 dip stream) rite ! inline : ascii)stringGutf1Lbe 5 string stream )) 6 0 1 s ap ascii)stringGutf1L)byte)array 3 dip stream) rite ! inline I: utf1Lle encode)string drop over auxGG 0 0 charGutf1Lle 3 curry each 3 0 ascii)stringGutf1Lle 3 if ! I: utf1Lbe encode)string drop over auxGG 0 0 charGutf1Lbe 3 curry each 3 0 ascii)stringGutf1Lbe 3 if ! I: utf1Lle guess)encoded)length drop , 4 ! inline I: utf1Lle guess)decoded)length drop , Qi ! inline I: utf1Lbe guess)encoded)length drop , 4 ! inline I: utf1Lbe guess)decoded)length drop , Qi ! inline K U$@)1L %BNS$"N$: bom)le E+ =xff =xfe . %BNS$"N$: bom)be E+ =xfe =xff . : bomGleQbe 5 bom )) leQbe 6 dup bom)le sequenceH 0 drop utf1Lle 3 0 bom)be sequenceH 0 utf1Lbe 3 0 missing)bom 3 if 3 if ! I: utf1L PdecoderG 5 stream utf1L )) decoder 6 drop , over stream)read bomGleQbe PdecoderG ! I: utf1L PencoderG 5 stream utf1L )) encoder 6 drop bom)le over stream) rite utf1Lle PencoderG ! ;#IV"$'G K %opyright 5%6 ,==S Caniel 'hrenberg K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: help.markup help.syntax io.encodings strings ! IN: io.encodings.utf1L "#$I%&': (io.encodings.utf1L( (U$@)1L encoding( ($he U$@)1L encoding is a variable) idth encoding. Unicode code points are encoded as , or / byte sequences. $here are three encoding descriptor classes for orking ith U$@)1L< depending on endianness or the presence of a EBI:( + *subsections utf1L

. !

utf1Lle utf1Lbe

"EBU$: (io.encodings.utf1L( ?'&;: utf1Lle + *class)description ($he encoding descriptor for U$@)1L&'< that is< U$@)1L in little endian< ithout a byte order mark. Streams can be made hich read or rite th this encoding.( . + *see)also (encodings)introduction( . ! ?'&;: utf1Lbe + *class)description ($he encoding descriptor for U$@)1LE'< that is< U$@)1L in big endian< ithout a byte order mark. Streams can be made hich read or rite th this encoding.( . + *see)also (encodings)introduction( . ! ?'&;: utf1L + *class)description ($he encoding descriptor for U$@)1L< that is< U$@)1L ith a byte order mark. $his is the most useful for general input and output in U$@)1L. Streams can be made hich read or rite th this encoding.( . + *see)also (encodings)introduction( . ! + utf1L utf1Lle utf1Lbe . related) ords K %opyright 5%6 ,==S Caniel 'hrenberg. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel tools.test io.encodings.utf1L arrays sbufs io.streams.byte)array sequences io.encodings io strings io.encodings.string alien.c)types alien.strings accessors classes ! IN: io.encodings.utf1L.tests 0 + %?"#: x . 3 0 E+ = %?"#: x . utf1Lbe 0 + =x1C11' . 3 0 E+ =xCS =x-/ =xCC =x1' 0 + %?"#: replacement)character . 3 0 E+ Garray 3 unit)test 0 + %?"#: replacement)character . 3 0 E+ utf1Lbe decode Garray 3 unit)test decode Garray 3 unit)test . utf1Lbe decode Garray 3 unit)test =b11=11111 %?"#: q . utf1Lbe decode =b11=11=11 %?"#: x =b11=11=11 %?"#: x .

0 + = 1,= ,1L A, ,,1 -= . 3 0 + %?"#: x =x1d11e . Gstring utf1Lbe encode Garray 3 unit)test 0 + %?"#: x . 3 0 E+ %?"#: x = . utf1Lle decode Garray 3 unit)test 0 + 11U=R= . 3 0 E+ =x-/ =xCS =x1' =xCC . Gstring utf1Lle decode Garray 3 unit)test 0 + %?"#: replacement)character . 3 0 + = =b11=11111 . Gstring utf1Lle decode Garray 3 unit)test 0 + %?"#: replacement)character . 3 0 + = =b11=11=11 = = . Gstring utf1Lle decode Garray 3 unit)test 0 + 1,= = A, ,1L -= ,,1 . 3 0 + %?"#: x =x1d11e . Gstring utf1Lle encode Garray 3 unit)test 0 + %?"#: x . 3 0 E+ =xff =xfe %?"#: x = . utf1L decode Garray 3 unit)test 0 + %?"#: x . 3 0 E+ =xfe =xff = %?"#: x . utf1L decode Garray 3 unit)test 0 + =xff =xfe 1,= = A, ,1L -= ,,1 . 3 0 + %?"#: x =x1d11e . Gstring utf1L encode Garray 3 unit)test K test ascii encoding path 0 E+ %?"#: a = %?"#: b = %?"#: c = . 3 0 (abc( utf1Lle encode 3 unit)test

0 E+ = %?"#: a = %?"#: b = %?"#: c . 3 0 (abc( utf1Lbe encode 3 unit)test K %opyright 5%6 ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: io.encodings io.encodings.utf1L kernel alien.accessors ! IN: io.encodings.utf1Ln K Native)order U$@)1L SING&'$BN: utf1Ln : choose)utf1L)endian 5 )) descriptor 6 E+ 1 = = = . = alien)unsigned)/ 1 H utf1Lle utf1Lbe : ! foldable I: utf1Ln PdecoderG drop choose)utf1L)endian PdecoderG ! I: utf1Ln PencoderG drop choose)utf1L)endian PencoderG ! USING: help.markup help.syntax ! IN: io.encodings.utf1Ln ?'&;: utf1Ln + *class)description ($he encoding descriptor for U$@)1L ithout a byte order mark in native endian order. $his is useful mostly for @@I calls hich take input of strings of the type char[t4( . + *see)also (encodings)introduction( . ! USING: accessors alien.c)types alien.data kernel io.encodings.utf1L io.streams.byte)array tools.test ! IN: io.encodings.utf1Ln : correct)endian 5 obF )) : 6 codeGG little)endian: 0 utf1Lle H 3 0 utf1Lbe H 3 if ! 0 t 3 0 E+ . utf1Ln Pbyte)readerG correct)endian 3 unit)test 0 t 3 0 utf1Ln Pbyte) riterG correct)endian 3 unit)test K %opyright 5%6 ,==S< ,=1= Caniel 'hrenberg< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors combinators destructors io io.streams.plain kernel math namespaces sbufs sequences sequences.private splitting strings ! IN: io.encodings K $he encoding descriptor protocol G'N'#I%: guess)encoded)length 5 string)length encoding )) byte)length 6 G'N'#I%: guess)decoded)length 5 byte)length encoding )) string)length 6 I: obFect guess)decoded)length drop ! inline I: obFect guess)encoded)length drop ! inline G'N'#I%: decode)char 5 stream encoding )) charQf 6 G'N'#I%: decode)until 5 seps stream encoding )) stringQf sepQf 6 P;#IV"$' K K K : If the stop: branch is taken convert the sbuf to a string If sep is present< returns __string sep77 5string can be ((6 If sep is f< returns __string f77 or __f f77 read)until)loop 5 buf quot: 5 )) char stop: 6 )) stringQf sepQf 6 dup call 0 nip 0 (( like 3 dip 0 f like f 3 unless4 3 0 pick push read)until)loop 3 if ! inline recursive

;#IV"$'G : 5decode)until6 5 seps stream encoding )) stringQf sepQf 6 0 decode)char dup 3 ,curry s ap 0 dupd member: 3 curry 0 0 drop f t 3 if 3 curry compose 0 1== PsbufG 3 dip read)until)loop ! inline I: obFect decode)until 5decode)until6 ! G'N'#I%: encode)char 5 char stream encoding )) 6 G'N'#I%: encode)string 5 string stream encoding )) 6 I: obFect encode)string 0 encode)char 3 ,curry each ! inline G'N'#I%: PdecoderG 5 stream encoding )) ne stream 6 %BNS$"N$: replacement)char =xfffd $U;&': decoder + stream read)only . + code read)only . + cr boolean . ! INS$"N%': decoder input)stream '##B#: decode)error ! G'N'#I%: PencoderG 5 stream encoding )) ne stream 6 $U;&': encoder + stream read)only . + code read)only . ! INS$"N%': encoder output)stream '##B#: encode)error ! K Cecoding I: obFect PdecoderG f decoder boa ! inline P;#IV"$' : cr2 5 stream )) 6 t GGcr drop ! inline : cr) 5 stream )) 6 f GGcr drop ! inline : GdecoderP 5 decoder )) stream encoding 6 0 streamGG 3 0 codeGG 3 bi ! inline I: decoder stream)element)type drop 2character2 ! inline : 5read16 5 decoder )) ch 6 GdecoderP decode)char ! inline : fix)cr 5 decoder c )) c7 6 over crGG 0 over cr) dup %?"#: >n eq: 0 drop 5read16 3 0 nip 3 if 3 0 nip 3 if ! inline I: decoder stream)read1 5 decoder )) ch 6 dup 5read16 fix)cr ! inline : 5read)first6 5 n buf decoder )) buf stream encoding n c 6 0 rot 0 GdecoderP 3 dip ,over decode)char 3 0 s ap fix)cr 3 bi ! inline

: 5store)read6 5 buf stream encoding n c i )) buf stream encoding n 6 0 rot 0 set)nth)unsafe 3 keep 3 ,curry -dip ! inline : 5finish)read6 5 buf stream encoding n i )) i 6 ,nip ,nip ! inline : 5read)next6 5 stream encoding n i )) stream encoding n i c 6 0 ,dup decode)char 3 ,dip rot ! inline : 5read)rest6 5 buf stream encoding n i )) count 6 ,dup H 0 5finish)read6 3 0 5read)next6 0 s ap 0 5store)read6 3 0 1 2 3 bi 5read)rest6 3 0 5finish)read6 3 if4 3 if ! inline recursive I: decoder stream)read)unsafe pick = H 0 -drop = 3 0 5read)first6 0 = 5store)read6 1 5read)rest6 3 0 /drop = 3 if4 3 if ! inline I: decoder stream)contents4 5stream)contents)by)element6 ! inline : line)endsQeof 5 stream str )) str 6 f like s ap cr) ! inline : line)ends>r 5 stream str )) str 6 s ap cr2 ! inline : line)ends>n 5 stream str )) str 6 over crGG over empty: and 0 drop dup cr) stream)readln 3 0 s ap cr) 3 if ! inline : handle)readln 5 stream str ch )) str 6 + + f 0 line)endsQeof 3 . + %?"#: >r 0 line)ends>r 3 . + %?"#: >n 0 line)ends>n 3 . . case ! inline I: decoder stream)read)until GdecoderP decode)until ! I: decoder stream)readln (>r>n( over GdecoderP decode)until handle)readln ! I: decoder dispose streamGG dispose ! K 'ncoding I: obFect PencoderG encoder boa ! inline : GencoderP 5 encoder )) stream encoding 6 0 streamGG 3 0 codeGG 3 bi ! inline I: encoder stream)element)type drop 2character2 ! inline I: encoder stream) rite1 GencoderP encode)char ! inline

I: encoder stream) rite GencoderP encode)string ! inline I: encoder dispose streamGG dispose ! inline I: encoder stream)flush streamGG stream)flush ! inline INS$"N%': encoder plain) riter ;#IV"$'G G'N'#I%Z re)encode 1 5 stream encoding )) ne stream 6 I: obFect re)encode PencoderG ! I: encoder re)encode 0 streamGG 3 dip re)encode ! : encode)output 5 encoding )) 6 output)stream 0 s ap re)encode 3 change ! : ith)encoded)output 5 encoding quot )) 6 0 0 output)stream get 3 dip re)encode 3 dip ith)output)stream4 ! inline

G'N'#I%Z re)decode 1 5 stream encoding )) ne stream 6 I: obFect re)decode PdecoderG ! I: decoder re)decode 0 streamGG 3 dip re)decode ! : decode)input 5 encoding )) 6 input)stream 0 s ap re)decode 3 change ! : ith)decoded)input 5 encoding quot )) 6 0 0 input)stream get 3 dip re)decode 3 dip ith)input)stream4 ! inline USING: accessors io io.encodings io.encodings.ascii io.encodings.utfS io.files io.streams.byte)array io.streams.string kernel namespaces tools.test ! IN: io.encodings.tests 0 + . 3 0 (vocab:ioQtestQempty)file.txt( ascii file)lines 3 unit)test : lines)test 5 file encoding )) line1 line, 6 0 readln readln 3 ith)file)reader ! 0 3 0 ($his is a line.( ($his is another line.(

(vocab:ioQtestQ indo s)eol.txt( ascii lines)test 3 unit)test 0 3 0 ($his is a line.( ($his is another line.(

(vocab:ioQtestQmac)os)eol.txt( ascii lines)test 3 unit)test

0 3 0

($his is a line.( ($his is another line.(

(vocab:ioQtestQunix)eol.txt( ascii lines)test 3 unit)test 0 3 0 (1,-/(

(?ello orld>r>n1,-/( Pstring)readerG dup stream)readln drop / s ap stream)read 3 unit)test 0 3 0 (1,-/(

(?ello orld>r>n1,-/( Pstring)readerG dup stream)readln drop / s ap stream)read)partial 3 unit)test 0 3 0 %?"#: 1

(?ello orld>r>n1,-/( Pstring)readerG dup stream)readln drop stream)read1 3 unit)test 0 utfS ascii 3 0 (foo( utfS 0 input)stream get codeGG ascii decode)input input)stream get codeGG 3 ith)byte)reader 3 unit)test 0 utfS ascii 3 0 utfS 0 output)stream get codeGG ascii encode)output output)stream get codeGG 3 ith)byte) riter drop 3 unit)test K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors alien alien.strings byte)arrays destructors io io.backend io.encodings.utfS io.files kernel kernel.private make math sequences threads.private ! IN: io.streams.c $U;&': c)stream P disposable handle ! : ne )c)stream 5 handle class )) c)stream 6 ne )disposable s ap GGhandle ! inline I: c)stream dispose4 handleGG fclose !

$U;&': c) riter P c)stream ! INS$"N%': c) riter output)stream INS$"N%': c) riter file) riter : Pc) riterG 5 handle )) stream 6 c) riter ne )c)stream ! I: c) riter stream) rite1 dup check)disposed handleGG fputc ! I: c) riter stream) rite dup check)disposed 0 0 Gc)ptr 3 0 byte)length 3 bi 3 0 handleGG 3 bi4 f rite ! I: c) riter stream)flush dup check)disposed handleGG fflush ! $U;&': c)reader P c)stream ! INS$"N%': c)reader input)stream INS$"N%': c)reader file)reader : Pc)readerG 5 handle )) stream 6 c)reader ne )c)stream ! I: c)reader stream)read)unsafe dup check)disposed handleGG fread)unsafe ! I: c)reader stream)read1 dup check)disposed handleGG fgetc ! : read)until)loop 5 stream delim )) ch 6 over stream)read1 dup 0 dup pick member)eq: 0 ,nip 3 0 < read)until)loop 3 if 3 0 ,nip 3 if ! inline recursive I: c)reader stream)read)until dup check)disposed 0 s ap read)until)loop 3 E+ . make s ap over empty: over not and 0 ,drop f f 3 hen ! I: c)io)backend init)io ! : stdin)handle 5 )) alien 6 BEX)S$CIN special)obFect ! : stdout)handle 5 )) alien 6 BEX)S$CBU$ special)obFect ! : stderr)handle 5 )) alien 6 BEX)S$C'## special)obFect ! : init)c)stdio 5 )) 6 stdin)handle Pc)readerG stdout)handle Pc) riterG stderr)handle Pc) riterG set)stdio ! I: c)io)backend init)stdio init)c)stdio ! I: c)io)backend io)multiplex dup = H 0 drop 3 0 L= L= 4 1=== 4 1=== 4 or 5sleep6 3 if ! : fopen 5 path mode )) alien 6 0 utfS stringGalien 3 bi9 5fopen6 ! I: c)io)backend 5file)reader6 (rb( fopen Pc)readerG ! I: c)io)backend 5file) riter6 ( b( fopen Pc) riterG !

I: c)io)backend 5file)appender6 (ab( fopen Pc) riterG ! : sho 5 msg )) 6 ZK " ord hich directly calls primitives. It is used to ZK print stuff from contexts here the IQB system ould ZK other ise not ork 5tools.deploy.shaker< the IQB ZK multiplexer thread6. (>n( append Gbyte)array dup length stdout)handle f rite stdout)handle fflush ! USING: tools.test io.files io.files.temp io io.streams.c io.encodings.ascii strings destructors kernel speciali8ed)arrays alien.c)types math alien.data ! S;'%I"&IO'C)"##"N: int IN: io.streams.c.tests 0 (hello orld( 3 0 (hello orld( (test.txt( temp)file ascii set)file)contents (test.txt( temp)file (rb( fopen Pc)readerG stream)contents Gstring 3 unit)test K Jriting speciali8ed arrays to binary streams 0 3 0 (test.txt( temp)file ( b( fopen Pc) riterG 0 int)array+ 1 , - . rite 3 ith)output)stream 3 unit)test 0 int)array+ 1 , - . 3 0 (test.txt( temp)file (rb( fopen Pc)readerG 0 - / 4 read 3 ith)input)stream int cast)array 3 unit)test K Jriting strings to binary streams should fail 0 (test.txt( temp)file ( b( fopen Pc) riterG 0 (BIG@"I&( rite 3 ith)output)stream 3 must)fail USING: help.markup help.syntax io io.files threads strings byte)arrays io.streams.plain alien math ! IN: io.streams.c "#$I%&': (io.streams.c( ("NSI % streams( (% streams are found in the ( + *vocab)link (io.streams.c( . ( vocabulary! they are ( + *link (stream)protocol( . ( implementations hich read and rite % ( + *snippet (@I&'4( . ( handles.( + *subsections Pc)readerG Pc) riterG . (Underlying primitives used to implement the above:( + *subsections fopen f rite fflush fclose

fputc fgetc fread)unsafe . ($he three standard file handles:( + *subsections stdin)handle stdout)handle stderr)handle . ! "EBU$: (io.streams.c( ?'&;: Pc)readerG + *values + (handle( (a % @I&'4 handle( . + (stream( (a ne stream( . . + *description (%reates a stream hich reads data by calling % standard library functions.( . + *notes (Usually % streams are only used during bootstrap< and non)blocking BS)specific IQB routines are used during normal operation.( . ! ?'&;: Pc) riterG + *values + (handle( (a % @I&'4 handle( . + (stream( (a ne stream( . . + *description (%reates a stream hich rites data by calling % standard library functions.( . + *notes (Usually % streams are only used during bootstrap< and non)blocking BS)specific IQB routines are used during normal operation.( . ! ?'&;: fopen + *values + (path( (a pathname string( . + (mode( (an access mode specifier( . + (alien( (a % @I&'4 handle( . . + *description (Bpens a file named by ( + *snippet (path( . (. $he ( + *snippet (mode( . ( parameter should be something like ( + *snippet (>(r>(( . ( or ( + *snippet (>(r >(( . (! consult the ( + *snippet (fopen5-6( . ( manual page for details.( . + *errors ($hro s an error if the file could not be opened.( . + *notes (User code should call ( + *link Pfile)readerG . ( or ( + *link Pfile) riterG . ( to get a high level stream.( . ! ?'&;: f rite + *values + (data( c)ptr . + (length( integer . + (alien( (a % @I&'4 handle( . . + *description (Jrites some bytes to a % @I&'4 handle.( . + *errors ($hro s an error if the output operation failed.( . ! ?'&;: fflush + *values + (alien( (a % @I&'4 handle( . . + *description (@orces pending output on a % @I&'4 handle to complete.( . + *errors ($hro s an error if the output operation failed.( . ! ?'&;: fclose + *values + (alien( (a % @I&'4 handle( . . + *description (%loses a % @I&'4 handle.( . ! ?'&;: fgetc + *values + (alien( (a % @I&'4 handle( . + (byteQf( (an integer from = to ,AA or ( + *link f . . . + *description (#eads a single byte from a % @I&'4 handle< and outputs ( + *link f . ( on end of file.( . + *errors ($hro s an error if the input operation failed.( . ! ?'&;: fputc + *values + (byte( (an integer from = to ,AA( . + (alien( (a % @I&'4 handle( . . + *description (Jrites a single byte to a % @I&'4 handle.( .

+ *errors ($hro s an error if the output operation failed.( . ! ?'&;: fread)unsafe + *values + (n( (a positive integer( . + (buf( c)ptr . + (alien( (a % @I&'4 handle( . + (count( integer . . + *description (#eads ( + *snippet (n( . ( bytes from a % @I&'4 handle into the memory referenced by ( + *snippet (buf( . (< and outputs the number of characters read. Oero is output on end of file.( . + * arning ($his ord does not check hether ( + *snippet (buf( . ( is large enough to accommodate the requested number of bytes. Iemory corruption ill occur if this is not the case.( . + *errors ($hro s an error if the input operation failed.( . ! ?'&;: stdin)handle + *values + (alien( (a % @I&'4 handle( . . + *description (Butputs the console standard input file handle.( . ! ?'&;: stdout)handle + *values + (alien( (a % @I&'4 handle( . . + *description (Butputs the console standard output file handle.( . ! ?'&;: stderr)handle + *values + (alien( (a % @I&'4 handle( . . + *description (Butputs the console standard error file handle.( . ! K 5c6,=11 Xoe Groff bsd license USING: alien.data destructors io io.streams.memory kernel libc tools.test ! IN: io.streams.memory.tests + 1 , - . 0 E+ 1 , - . Pmemory)streamG 0 stream)read1 3 0 stream)read1 3 0 stream)read1 3 tri 3 unit)test + 1 , - . 0 0 E+ 1 , - . malloc)byte)array `free Pmemory)streamG 0 stream)read1 3 0 stream)read1 3 0 stream)read1 3 tri 3 ith)destructors 3 unit)test + E+ 1 , - . E+ / A L R S . . 0 E+ 1 , - / A L R S . Pmemory)streamG 0 - s ap stream)read 3 0 A s ap stream)read 3 bi 3 unit)test + E+ 1 , - . E+ / A L R S . . 0 0 E+ 1 , - / A L R S . malloc)byte)array `free Pmemory)streamG 0 - s ap stream)read 3 0 A s ap stream)read 3 bi 3 ith)destructors 3 unit)test K %opyright 5%6 ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors alien alien.accessors io kernel ! IN: io.streams.memory $U;&': memory)stream alien ! : Pmemory)streamG 5 alien )) stream 6 memory)stream boa !

INS$"N%': memory)stream input)stream I: memory)stream stream)element)type drop 2byte2 ! I: memory)stream stream)read1 0 1 over Pdisplaced)alienG 3 change)alien drop = alien)unsigned)1 ! inline : ith)memory)reader 5 alien quot )) 6 0 Pmemory)streamG 3 dip ith)input)stream4 ! inline K %opyright 5%6 ,==A< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel io ! IN: io.streams.plain IIMIN: plain) riter I: plain) riter stream)nl %?"#: >n s ap stream) rite1 ! USING: help.markup help.syntax io ! IN: io.streams.plain "EBU$: (io.streams.plain( ?'&;: plain) riter + *class)description ("n output stream mixin providing an implementation of the extended stream output protocol in a trivial ay.( . + *see)also (stream)protocol( . ! K %opyright 5%6 ,==S< ,==U Caniel 'hrenberg K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays byte)vectors destructors io io.encodings io.streams.sequence kernel namespaces sequences sequences.private ! IN: io.streams.byte)array INS$"N%': byte)vector output)stream I: byte)vector stream)element)type drop 2byte2 ! : Pbyte) riterG 5 encoding )) stream 6 A1, Pbyte)vectorG s ap PencoderG ! : ith)byte) riter 5 encoding quot )) byte)array 6 0 Pbyte) riterG 3 dip 0 output)stream get 3 compose dup encoder: 0 streamGG 3 hen Gbyte)array ! inline ith)output)stream4

$U;&': byte)reader + underlying byte)array read)only . + i array)capacity . ! INS$"N%': byte)reader input)stream I: byte)reader stream)element)type drop 2byte2 ! I: I: I: I: I: I: I: I: byte)reader byte)reader byte)reader byte)reader byte)reader byte)reader byte)reader byte)reader stream)read)unsafe sequence)read)unsafe ! stream)read1 sequence)read1 ! stream)read)until sequence)read)until ! dispose drop ! stream)tell iGG ! stream)seek 5stream)seek6 ! stream)seekable: drop t ! inline stream)length underlyingGG length ! inline

: Pbyte)readerG 5 byte)array encoding )) stream 6 0 E+ . like = byte)reader boa 3 dip PdecoderG !

ith)byte)reader 5 byte)array encoding quot )) 6 0 Pbyte)readerG 3 dip ith)input)stream4 ! inline USING: help.syntax help.markup io byte)arrays quotations ! IN: io.streams.byte)array "EBU$: (io.streams.byte)array( "#$I%&': (io.streams.byte)array( (Eyte)array streams( (Eyte array streams:( + *subsections Pbyte)readerG Pbyte) riterG . (Utility combinators:( + *subsections ith)byte)reader ith)byte) riter . ! ?'&;: Pbyte)readerG + *values + (byte)array( byte)array . + (encoding( (an encoding descriptor( . + (stream( (a ne byte reader( . . + *description (%reates an input stream reading from a byte array using an encoding.( . ! ?'&;: Pbyte) riterG + *values + (encoding( (an encoding descriptor( . + (stream( (a ne byte riter( . . + *description (%reates an output stream riting data to a byte array using an encoding.( . ! ?'&;: ith)byte)reader + *values + (byte)array( byte)array . + (encoding( (an encoding descriptor( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope ith ( + *link input)stream . ( rebound to an input stream for reading from a byte array using an encoding.( . ! ?'&;: ith)byte) riter + *values + (encoding( (an encoding descriptor( . + (quot( quotation . + (byte)array( byte)array . . + *description (%alls the quotation in a ne dynamic scope ith ( + *link output)stream . ( rebound to an output stream riting data to a byte array using an encoding.( . ! USING: tools.test io.streams.byte)array io.encodings.binary io.encodings.utfS io kernel arrays strings namespaces math speciali8ed)arrays alien.c)types alien.data io.encodings.ascii ! S;'%I"&IO'C)"##"N: int IN: io.streams.byte)array.tests 0 E+ . 3 0 E+ . binary 0 contents 3 K 0 0 0 0 0 Issue f 3 0 f 3 0 f 3 0 f 3 0 f f 3 ith)byte)reader 3 unit)test

ZR= github E+ . binary 0 = read 3 ith)byte)reader 3 unit)test E+ . binary 0 1 read 3 ith)byte)reader 3 unit)test E+ . ascii 0 = read 3 ith)byte)reader 3 unit)test E+ . ascii 0 readln 3 ith)byte)reader 3 unit)test 0 E+ . ascii 0 (a( read)until 3 ith)byte)reader 3 unit)test

0 f f 3 0 E+ . binary 0 + , . read)until 3 0 E+ 1 , 0 E+ 1 , ith)byte) 0 E+ 1 , . 3 0 / A L riter . 3 0

ith)byte)reader 3 unit)test

binary 0 E+ 1 , - . rite 3 ith)byte) riter 3 unit)test . 3 0 binary 0 E+ 1 , - . rite E+ / A L . rite 3 3 unit)test + 1 , - . binary 0 - read 3 ith)byte)reader 3 unit)test

0 E+ =b1111=1=1 =b1=111111 =b1======= =b1=111111 =b111=1111 =b1======= =b1=111111 =b11=11111 =b1======= %?"#: x . 3 0 + =b1=1111111======111111 =b1111======111111 =b11111====== %?"#: x . Gstring utfS 0 rite 3 ith)byte) riter 3 unit)test 0 + =b1111111======111111 . t 3 0 + =b1111===1 =b1=111111 =b1======= =b1=111111 . utfS Pbyte)readerG stream)contents dup Garray s ap string: 3 unit)test 0 E+ 1,1 1,= . = 3 0 E+ = 1,1 1,= = = = = = = . binary 0 1 read drop (>=( read)until 3 ith)byte)reader 3 unit)test 0 1 1 / 11 f 3 0 E+ 1 , - / A L R S U 1= 11 1, . binary 0 read1 = seek)absolute input)stream get stream)seek read1 , seek)relative input)stream get stream)seek read1 ), seek)end input)stream get stream)seek read1 = seek)end input)stream get stream)seek read1 3 ith)byte)reader 3 unit)test 0 = 3 0 E+ 1 , - / A L R S U 1= 11 1, . binary 0 tell)input 3 3 unit)test K Bverly aggressive compiler optimi8ations 0 E+ 1,- . 3 0 binary 0 1,- Gbignum rite1 3 ith)byte) riter 3 unit)test K Jriting speciali8ed arrays to byte riters 0 int)array+ 1 , - . 3 0 binary 0 int)array+ 1 , - . rite 3 ith)byte) riter int cast)array 3 unit)test K %opyright 5%6 ,==U Caniel 'hrenberg K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors combinators destructors gro able io io.private io.streams.plain kernel math math.order sequences sequences.private ! IN: io.streams.sequence K #eaders S&B$: underlying S&B$: i : Gsequence)streamP 5 stream )) i underlying 6 ith)byte)reader

0 iGG 3 0 underlyingGG 3 bi ! inline : sequence)read1 5 stream )) eltQf 6 dup Gsequence)streamP dupd :nth 0 1 2 s ap iPP 3 dip ! inline : 5sequence)read)length6 5 n buf stream )) buf count 6 0 underlyingGG length 3 0 iGG 3 bi ) rot min ! inline : Psequence)copyG 5 dst n i src )) n copy 6 0 = 3 -curry dip PcopyG ! inline : 5sequence)read)unsafe6 5 n buf stream )) count 6 0 5sequence)read)length6 3 0 0 dup pick 2 3 change)i underlyingGG 3 bi 0 Psequence)copyG 5copy6 drop 3 ,curry keep ! inline : sequence)read)unsafe 5 n buf stream )) count 6 dup Gsequence)streamP bounds)check: 0 5sequence)read)unsafe6 3 0 -drop = 3 if ! inline : find)separator 5 seps stream )) sepQf n 6 s ap 0 Gsequence)streamP 3 dip 0 member)eq: 3 curry 0 find)from s ap 3 curry ,keep pick 0 drop ) 3 0 length s ap ) nip 3 if ! inline : sequence)read)until 5 seps stream )) seq sepQf 6 0 find)separator 3 keep 0 0 5sequence)read)unsafe6 3 5read)into)ne 6 3 0 0 1 2 3 change)i drop 3 bi s ap ! inline K Jriters I: gro able dispose drop ! I: gro able stream) rite1 push ! I: gro able stream) rite push)all ! I: gro able stream)flush drop ! INS$"N%': gro able output)stream INS$"N%': gro able plain) riter K Seeking : 5stream)seek6 5 n seek)type stream )) 6 s ap + + seek)absolute 0 iPP 3 . + seek)relative 0 0 2 3 change)i drop 3 . + seek)end 0 0 underlyingGG length 2 3 0 iPP 3 bi 3 . 0 bad)seek)type 3 . case ! USING: help.markup help.syntax quotations hashtables kernel classes strings continuations destructors math byte)arrays alien speciali8ed)arrays sequences ! IN: io "#$I%&': (stream)types( (Einary and text streams( (" ord hich outputs the stream element type:( + *subsections stream)element)type . (Stream element types:( + *subsections 2byte2 2character2 . ($he stream element type is the data type read and ritten by ( + *link stream)read1 . ( and ( + *link stream) rite1 . (.( *nl (Einary streams have an element type of ( + *link 2byte2 . (. 'lements are

integers in the range ( + *snippet (0=<,AA3( . (< representing bytes. #eading a sequence of elements produces a ( + *link byte)array . (. "ny obFect implementing the ( + *link Gc)ptr . ( and ( + *link byte)length . ( generic ords can be ritten to a binary stream.( *nl (%haracter streams have an element type of ( + *link 2character2 . (. 'lements are non)negative integers< representing Unicode code points. Bnly instances of the ( + *link string . ( class can be read or ritten on a character stream.( *nl (Iost external streams are binary streams< and can be rapped in string streams once a suitable encoding has been provided! see ( + *link (io.encodings( . (.( ! ?'&;: 2byte2 + *description (" stream element type. See ( + *link stream)element)type . ( for explanation.( . ! ?'&;: 2character2 + *description (" stream element type. See ( + *link stream)element)type . ( for explanation.( . ! ?'&;: stream)element)type + *values + (stream( (a stream( . + (type( + *link 2byte2 . ( or ( + *link 2character2 . . . + *contract (Butputs one of ( + *link 2byte2 . ( or ( + *link 2character2 . (.( . ! ?'&;: stream)readln + *values + (stream( (an input stream( . + (strQf( (a string or ( + *link f . . . + *contract (#eads a line of input from the stream. Butputs ( + *link f . ( on stream exhaustion.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link readln . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)read1 + *values + (stream( (an input stream( . + (elt( (an element or ( + *link f . . . + *contract (#eads an element from the stream. Butputs ( + *link f . ( on stream exhaustion.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link read1 . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)read + *values + (n( (a non)negative integer( . + (stream( (an input stream( . + (seqQf( + *or byte)array string f . . . + *contract (#eads ( + *snippet (n( . ( elements from the stream. Butputs a truncated string or ( + *link f . ( on stream exhaustion.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link read . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)read)unsafe + *values + (n( (a non)negative integer( . + (buf( + *or c)ptr string . . + (stream( (an input stream( . + (count( integer . . + *contract (#eads up to ( + *snippet (n( . ( elements from the stream. $he data is stored directly into the buffer provided by ( + *snippet (buf( . (< hich must be a string 5in the case of a character stream6 or a byte array< speciali8ed array< or other pointer to memory 5in the case of a byte stream6. $here must be space in the buffer for at least ( + *snippet (n( . ( elements. #eturns the number of elements read from the stream< hich ill be equal to (

+ *snippet (n( . ( unless the end of the stream is reached. If the stream is exhausted< returns 8ero.( . + * arning ($his ord does not perform bounds checking on ( + *snippet (buf( . (. Iost code should use ( + *link stream)read . ( or ( + *link stream)read)into . ( instead.( . *io)error ! ?'&;: read)into + *values + (buf( + *or byte)array speciali8ed)array string . . + (buf)slice( slice . + (more:( boolean . . + *contract (#eads from the current ( + *link input)stream . ( into the sequence ( + *snippet (buf( . (< until either the length of ( + *snippet (buf( . ( is reached or the stream is exhausted. #eturns a ( + *link slice . ( over the part of ( + *snippet (buf( . ( that as ritten to< and a boolean value that ill be ( + *link f . ( if the stream as exhausted.( . *io)error ! ?'&;: stream)read)into + *values + (buf( + *or byte)array speciali8ed)array string . . + (stream( (an input stream( . + (buf)slice( slice . + (more:( boolean . . + *contract (#eads from the stream into the sequence ( + *snippet (buf( . (< until either the length of ( + *snippet (buf( . ( is reached or the stream is exhausted. #eturns a ( + *link slice . ( over the part of ( + *snippet (buf( . ( that as ritten to< and a boolean value that ill be ( + *link f . ( if the stream as exhausted.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link read)into . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)read)until + *values + (seps( string . + (stream( (an input stream( . + (seq( + *or byte)array string f . . + (sepQf( (a character or ( + *link f . . . + *contract (#eads elements from the stream< until the first occurrence of a separator character< or stream exhaustion. In the former case< the separator is pushed on the stack< and is not part of the output string. In the latter case< the entire stream contents are output< along ith ( + *link f . (.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link read)until . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)read)partial + *values + (n( (a non)negative integer( . + (stream( (an input stream( . + (seqQf( + *or byte)array string f . . . + *description (#eads at most ( + *snippet (n( . ( elements from a stream and returns up to that many characters ithout blocking. If no characters are available< blocks until some are and returns them.( . ! ?'&;: stream)read)partial)unsafe + *values + (n( (a non)negative integer( . + (buf( + *or c)ptr string . . + (stream( (an input stream( . + (count( integer . . + *contract (#eads up to ( + *snippet (n( . ( elements from the stream ithout blocking. If no data is available immediately on the stream< blocks until data is available. $he data is stored directly into the buffer provided by ( + *snippet (buf( . (< hich must be a string 5in the case of a character stream6< or a byte array< speciali8ed array< or other pointer to memory 5in the case of a byte stream6. $here must be space in the buffer for at least ( + *snippet (n( . ( elements. #eturns the number of elements read from the stream< or 8ero if the end of the stream as reached.( . + * arning ($his ord does not perform bounds checking on ( + *snippet (buf( . (. Iost code should use ( + *link stream)read)partial . ( or ( + *link stream)read)partial)into . ( instead.( .

*io)error ! ?'&;: read)partial)into + *values + (buf( + *or byte)array speciali8ed)array string . . + (buf)slice( slice . + (more:( boolean . . + *contract (#eads available data from the current ( + *link input)stream . ( into the sequence ( + *snippet (buf( . ( ithout blocking until all immediately available data is read or the length of ( + *snippet (buf( . ( is reached. If no data is immediately available< blocks until data is available. #eturns a ( + *link slice . ( over the part of ( + *snippet (buf( . ( that as ritten to< and a boolean that ill be ( + *link f . ( if the stream as exhausted.( . *io)error ! ?'&;: stream)read)partial)into + *values + (buf( + *or byte)array speciali8ed)array string . . + (stream( (an input stream( . + (buf)slice( slice . + (more:( boolean . . + *contract (#eads available data from the stream into the sequence ( + *snippet (buf( . ( ithout blocking until all immediately available data is read or the length of ( + *snippet (buf( . ( is reached. If no data is immediately available< blocks until data is available. #eturns a ( + *link slice . ( over the part of ( + *snippet (buf( . ( that as ritten to< and a boolean that ill be ( + *link f . ( if the stream as exhausted.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link read)partial)into . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream) rite1 + *values + (elt( (an element( . + (stream( (an output stream( . . + *contract (Jrites an element to the stream. If the stream does buffering< output may not be performed immediately! use ( + *link stream)flush . ( to force output.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link rite1 . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream) rite + *values + (data( (binary data or a string( . + (stream( (an output stream( . . + *contract (Jrites a piece of data to the stream. If the stream performs buffering< output may not be performed immediately! use ( + *link stream)flush . ( to force output.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link rite . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)flush + *values + (stream( (an output stream( . . + *contract (Jaits for any pending output to complete.( . + *notes (Jith many output streams< ritten output is buffered and not sent to the underlying resource until either the buffer is full< or this ord is called.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link flush . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)nl + *values + (stream( (an output stream( . . + *contract (Jrites a line terminator. If the stream does buffering< output may not be performed immediately! use ( + *link stream)flush . ( to force output.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link nl . (! see ( + *link (stdio( . (.( . *io)error !

?'&;: stream)print + *values + (str( string . + (stream( (an output stream( . . + *description (Jrites a ne line)terminated string.( . + *notes (Iost code only orks on one stream at a time and should instead use ( + *link print . (! see ( + *link (stdio( . (.( . *io)error ! ?'&;: stream)copy4 + *values + (in( (an input + *description (%opies the left open hen the copy is used instead to close them *io)error ! stream( . + (out( (an output stream( . . contents of one stream into another. $he streams are completed. $he ( + *link stream)copy . ( ord can be on completion< if desired.( .

?'&;: stream)copy + *values + (in( (an input stream( . + (out( (an output stream( . . + *description (%opies the contents of one stream into another< closing both streams hen done. $o copy ithout closing the streams< use ( + *link stream)copy4 . (.( . *io)error ! ?'&;: stream)tell + *values + (stream( (a stream( . + (n( integer . . + *description (#eturns the index of the stream pointer if the stream is seekable.( . + *notes (Stream seeking is not supported on streams that do not have a kno n length< e.g. $%;QI; streams.( . ! ?'&;: stream)seek + *values + (n( integer . + (seek)type( (a seek singleton( . + (stream( (a stream( . . + *description (Ioves the pointer associated ith a stream7s handle to an offset ( + *snippet (n( . ( bytes from the seek type so that further reading or riting happens at the ne location. @or output streams< the buffer is flushed before seeking. Seeking past the end of an output stream ill pad the difference ith 8eros once the stream is ritten to again.( *nl ($hree methods of seeking are supported:( + *list + *link seek)absolute . + *link seek)relative . + *link seek)end . . . + *notes (Stream seeking is not supported on streams that do not have a kno n length< e.g. $%;QI; streams.( . ! ?'&;: stream)seekable: + *values + (stream( (a stream( . + (:( boolean . . + *description (#eturns true if ( + *snippet (stream( . ( is a seekable stream.( . + *notes (Stream seeking is not supported on streams that do not have a kno n length< e.g. $%;QI; streams.( . ! ?'&;: stream)length + *values + (stream( (a stream( . + (nQf( (an integer or ( + *link f . . . + *description (#eturns the length of the data supplied by ( + *snippet (stream( . (< or ( + *link f . ( if the stream is not seekable or has unkno n length.( . + *notes (Stream seeking is not supported on streams that do not have a kno n length< e.g. $%;QI; streams.( . !

?'&;: seek)absolute + *values + (value( (a seek singleton( . . + *description (Seeks to an offset from the beginning of the stream.( . ! ?'&;: seek)end + *values + (value( (a seek singleton( . . + *description (Seeks to an offset from the end of the stream. If the offset puts the stream pointer past the end of the data on an output stream< riting to it ill pad the difference ith 8eros.( . ! ?'&;: seek)relative + *values + (value( (a seek singleton( . . + *description (Seeks to an offset from the current position of the stream pointer.( . ! + stream)seek stream)tell stream)seekable: stream)length . related) ords + seek)absolute seek)relative seek)end . related) ords ?'&;: seek)input + *values + (n( integer . + (seek)type( (a seek singleton( . . + *description (%alls ( + *link stream)seek . ( on the stream stored in ( + *link input)stream . (.( . ! ?'&;: seek)output + *values + (n( integer . + (seek)type( (a seek singleton( . . + *description (%alls ( + *link stream)seek . ( on the stream stored in ( + *link output)stream . (.( . ! ?'&;: input)stream + *var)description (?olds an input stream for various implicit stream operations. #ebound using ( + *link ith)input)stream . ( and ( + *link ith)input)stream4 . (.( . ! ?'&;: output)stream + *var)description (?olds an output stream for various implicit stream operations. #ebound using ( + *link ith)output)stream . ( and ( + *link ith)output)stream4 . (.( . ! ?'&;: error)stream + *var)description (?olds an error stream.( . ! ?'&;: readln + *values + (strQf( (a string or ( + *link f . . . + *description (#eads a line of input from ( + *link input)stream . (. Butputs ( + *link f . ( on stream exhaustion.( . *io)error ! ?'&;: read1

+ *values + (elt( (an element or ( + *link f . . . + *description (#eads an element from ( + *link input)stream . (. Butputs ( + *link f . ( on stream exhaustion.( . *io)error ! ?'&;: read + *values + (n( (a non)negative integer( . + (seq( + *or byte)array string f . . . + *description (#eads ( + *snippet (n( . ( elements from ( + *link input)stream . (. If there is no input available< outputs ( + *link f . (. If there are less than ( + *snippet (n( . ( elements available< outputs a sequence shorter than ( + *snippet (n( . ( in length.( . *io)error ! ?'&;: read)until + *values + (seps( string . + (seq( + *or byte)array string f . . + (sepQf( (a character or ( + *link f . . . + *contract (#eads elements from ( + *link input)stream . ( until the first occurrence of a separator< or stream exhaustion. In the former case< the separator character is pushed on the stack< and is not part of the output. In the latter case< the entire stream contents are output< along ith ( + *link f . (.( . *io)error ! ?'&;: read)partial + *values + (n( integer . + (seq( + *or byte)array string f . . . + *description (#eads at most ( + *snippet (n( . ( elements from ( + *link input)stream . ( and returns them in a sequence. $his ord should be used instead of ( + *link read . ( hen processing the entire element a chunk at a time< since on some stream implementations it may be slightly faster.( . ! ?'&;: rite1 + *values + (elt( (an element( . . + *contract (Jrites an element to ( + *link output)stream . (. If the stream does buffering< output may not be performed immediately! use ( + *link flush . ( to force output.( . *io)error ! ?'&;: rite + *values + (seq( + *or byte)array string f . . . + *description (Jrites a sequence of elements to ( + *link output)stream . (. If the stream does buffering< output may not be performed immediately! use ( + *link flush . ( to force output.( . *io)error ! ?'&;: flush + *description (Jaits for any pending output on ( + *link output)stream . ( to complete.( . *io)error ! ?'&;: nl + *description (Jrites a line terminator to ( + *link output)stream . (. If the stream does buffering< output may not be performed immediately! use ( + *link flush . ( to force output.( . *io)error ! ?'&;: print + *values + (str( string . . + *description (Jrites a ne line)terminated string to ( + *link output)stream . (.( . *io)error !

?'&;: ith)input)stream + *values + (stream( (an input stream( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope< ith ( + *link input)stream . ( rebound to ( + *snippet (stream( . (. $he stream is closed if the quotation returns or thro s an error.( . ! ?'&;: ith)output)stream + *values + (stream( (an output stream( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope< ith ( + *link output)stream . ( rebound to ( + *snippet (stream( . (. $he stream is closed if the quotation returns or thro s an error.( . ! ?'&;: ith)streams + *values + (input( (an input stream( . + (output( (an output stream( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope< ith ( + *link input)stream . ( rebound to ( + *snippet (input( . ( and ( + *link output)stream . ( rebound to ( + *snippet (output( . (. $he stream is closed if the quotation returns or thro s an error.( . ! ?'&;: ith)streams4 + *values + (input( (an input stream( . + (output( (an output stream( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope< ith ( + *link input)stream . ( rebound to ( + *snippet (input( . ( and ( + *link output)stream . ( rebound to ( + *snippet (output( . (.( . + *notes ($his ord does not close the stream. %ompare ith ( + *link ith)streams . (.( . ! + + ith)input)stream ith)output)stream ith)input)stream4 . related) ords ith)output)stream4 . related) ords

?'&;: ith)input)stream4 + *values + (stream( (an input stream( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope< ith ( + *link input)stream . ( rebound to ( + *snippet (stream( . (.( . + *notes ($his ord does not close the stream. %ompare ith ( + *link ith)input)stream . (.( . ! ?'&;: ith)output)stream4 + *values + (stream( (an output stream( . + (quot( quotation . . + *description (%alls the quotation in a ne dynamic scope< ith ( + *link output)stream . ( rebound to ( + *snippet (stream( . (.( . + *notes ($his ord does not close the stream. %ompare ith ( + *link ith)output)stream . (.( . ! ?'&;: bl + *description (Butputs a space character 5( + *snippet (>( >(( . (6 to ( + *link output)stream . (.( . *io)error ! ?'&;: stream)lines + *values + (stream( (an input stream( . + (seq( (a sequence of strings( . . + *description (#eads lines of text until the stream is exhausted< collecting them in a sequence of strings.( . ! ?'&;: lines + *values + (seq( (a sequence of strings( . . + *description (#eads lines of text until from the ( + *link input)stream . ( until it is exhausted< collecting them in a sequence of strings.( . !

?'&;: each)line + *values + (quot( + *quotation (5 ... line )) ... 6( . . . + *description (%alls the quotation ith successive lines of text< until the current ( + *link input)stream . ( is exhausted.( . ! ?'&;: each)block + *values + (quot( + *quotation (5 ... block )) ... 6( . . . + *description (%alls the quotation ith successive blocks of data< until the current ( + *link input)stream . ( is exhausted.( . ! ?'&;: stream)contents + *values + (stream( (an input stream( . + (seq( + *or string byte)array . . . + *description (#eads all elements in the given stream until the stream is exhausted. $he type of the sequence depends on the stream7s element type. $he stream is closed after completion.( . *io)error ! ?'&;: contents + *values + (seq( + *or string byte)array . . . + *description (#eads all elements in the ( + *link input)stream . ( until the stream is exhausted. $he type of the sequence depends on the stream7s element type.( . *io)error ! ?'&;: tell)input + *values + (n( integer . . + *description (#eturns the index of the stream stored in ( + *link input)stream . (.( . ! ?'&;: tell)output + *values + (n( integer . . + *description (#eturns the index of the stream stored in ( + *link output)stream . (.( . ! "#$I%&': (stream)protocol( (Stream protocol( ($he stream protocol consists of a large number of generic ords< many of hich are optional.( *nl (Stream protocol ords are rarely called directly< since code hich only orks ith one stream at a time should be ritten to use ( + *link (stdio( . ( instead< rapping IQB operations such as ( + *link read . ( and ( + *link rite . ( in ( + *link ith)input)stream . ( and ( + *link ith)output)stream . (.( *nl ("ll streams must implement the ( + *link dispose . ( ord in addition to the stream protocol.( + *subsections (stream)types( . ($hese ords are required for binary and string input streams:( + *subsections stream)read1 stream)read)unsafe stream)read)until stream)read)partial)unsafe . ($he ( + *link stream)read)unsafe . ( and ( + *link stream)read)partial)unsafe . ( ords should be implemented by streams but not used by client code. $he follo ing safe ords are provided for reading from input streams:( + *subsections

. ($his ord is only required for string input streams:( + *subsections stream)readln . ($hese ords are required for binary and string output streams:( + *subsections stream)flush stream) rite1 stream) rite . ($his ord is only required for string output streams:( + *subsections stream)nl . ($hese ords are for seekable streams:( + *subsections stream)seekable: stream)tell stream)seek tell)input tell)output stream)length . + *see)also (io.timeouts( . ! "#$I%&': (stdio)motivation( (Iotivation for default streams( (Iost IQB code only operates on one stream at a time. $he ( + *link input)stream . ( and ( + *link output)stream . ( variables are implicit parameters used by many IQB ords. Using this idiom improves code in three ays:( + *list + (%ode becomes simpler because there is no need to keep a stream around on the stack.( . + (%ode becomes more robust because ( + *link ith)input)stream . ( and ( + *link ith)output)stream . ( automatically close the streams if there is an error.( . + (%ode becomes more reusable because it can be ritten to not orry about hich stream is being used< and instead the caller can use ( + *link ith)input)stream . ( or ( + *link ith)output)stream . ( to specify the source or destination for IQB operations.( . . (@or example< here is a program hich reads the first line of a file< converts it to an integer< then reads that many characters< and splits them into groups of 1L:( + *code (USING: continuations kernel io io.files math.parser splitting !( (>(data.txt>( utfS Pfile)readerG( (dup stream)readln stringGnumber over stream)read 1L group( (s ap dispose( . ($his code has t o problems: it has some unnecessary stack shuffling< and if either ( + *link stream)readln . ( or ( + *link stream)read . ( thro s an IQB error< the stream is not closed because ( + *link dispose . ( is never reached. So e can add a call to ( + *link ith)disposal . ( to ensure the stream is al ays closed:( + *code (USING: continuations kernel io io.files math.parser splitting !( (>(data.txt>( utfS Pfile)readerG 0( ( dup stream)readln stringGnumber over stream)read( ( 1L group( (3 ith)disposal( .

stream)read stream)read)into stream)read)partial stream)read)partial)into

($his code is robust< ho ever it is more complex than it needs to be. $his is here the default stream ords come in! using them< the above can be re ritten as follo s:( + *code (USING: continuations kernel io io.files math.parser splitting !( (>(data.txt>( utfS Pfile)readerG 0( ( readln stringGnumber read 1L group( (3 ith)input)stream( . ("n even better implementation that takes advantage of a utility ord:( + *code (USING: continuations kernel io io.files math.parser splitting !( (>(data.txt>( utfS 0( ( readln stringGnumber read 1L group( (3 ith)file)reader( . ! "#$I%&': (stdio( (Cefault input and output streams( + *subsections (stdio)motivation( . ($he default input stream is stored in a dynamically)scoped variable:( + *subsections input)stream . (Unless rebound in a child namespace< this variable ill be set to a console stream for reading input from the user.( *nl (Jords reading from the default input stream:( + *subsections read1 read read)into read)until read)partial read)partial)into readln . (If the default input stream is a character stream 5( + *link stream)element)type . ( outputs ( + *link 2character2 . (6< lines of text can be read:( + *subsections readln . (Seeking on the default input stream:( + *subsections seek)input . (" pair of combinators for rebinding the ( + *link input)stream . ( variable:( + *subsections ith)input)stream ith)input)stream4 . ($he default output stream is stored in a dynamically)scoped variable:( + *subsections output)stream . (Unless rebound in a child namespace< this variable ill be set to a console stream for sho ing output to the user.( *nl (Jords riting to the default output stream:( + *subsections flush rite1 rite . (If the default output stream is a character stream 5( + *link stream)element)type . ( outputs ( + *link 2character2 . (6< lines of text can be ritten:( + *subsections print nl

bl . (Seeking on the default output stream:( + *subsections seek)output . (" pair of combinators for rebinding the ( + *link output)stream . ( variable:( + *subsections ith)output)stream ith)output)stream4 . (" pair of combinators for rebinding both default streams at once:( + *subsections ith)streams ith)streams4 . ! "#$I%&': (stream)utils( (Stream utilities( ($here are a fe useful stream)related ords hich are not generic< but merely built up from the stream protocol.( *nl (@irst< a simple composition of ( + *link stream) rite . ( and ( + *link stream)nl . (:( + *subsections stream)print . (;rocessing lines one by one:( + *subsections stream)lines lines each)line . (;rocessing blocks of data:( + *subsections stream)contents contents each)block . (%opying the contents of one stream to another:( + *subsections stream)copy4 . + *subsections stream)copy . ! "#$I%&': (stream)examples( (Stream example( ("sk the user for their age< and print it back:( + *code (USING: io math.parser !( (( (: ask)age 5 )) 6 >(?o old are you:>( print !( (( (: read)age 5 )) n 6 readln stringGnumber !( (( (: print)age 5 n )) 6( ( >(Nou are >( rite( ( numberGstring rite( ( >( years old.>( print !( (: example 5 )) 6 ask)age read)age print)age !( (( (example( . ! "#$I%&': (streams( (Streams( (Input and output centers on the concept of a ( + *emphasis (stream( . (< hich is a source or sink of ( + *emphasis (elements( . (.( + *subsections (stream)examples( . (" stream can either be passed around on the stack or bound to a dynamic variable and used as one of the t o implicit ( + *emphasis (default streams( .

(.( + *subsections (stream)protocol( (stdio( (stream)utils( . + *see)also (io.streams.string( (io.streams.plain( (io.streams.duplex( . ! "EBU$: (streams( USING: tools.test io.backend kernel ! IN: io.backend.tests 0 3 0 (a( normali8e)path drop 3 unit)test USING: help.markup help.syntax io io.backend strings byte)arrays ! ?'&;: io)multiplex + *values + (nanos( (a non)negative integer( . . + *contract (Jaits up to ( + *snippet (nanos( . ( nanoseconds for pending IQB requests to complete.( . ! ?'&;: init)io + *contract (Initiali8es the IQB system. %alled on startup.( . ! ?'&;: init)stdio + *contract (Initiali8es the global ( + *link input)stream . ( and ( + *link output)stream . (. %alled on startup.( . ! K %opyright 5%6 ,==R< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: assocs init io io.encodings io.encodings.utfS kernel namespaces system ! IN: io.backend SNIEB&: io)backend SING&'$BN: c)io)backend io)backend 0 c)io)backend 3 initiali8e ?BBY: init)io io)backend 5 )) 6 ?BBY: init)stdio io)backend 5 )) 6 : set)stdio 5 input output error )) 6 0 utfS PdecoderG input)stream set)global 3 0 utfS PencoderG output)stream set)global 3 0 utfS PencoderG error)stream set)global 3 tri4 ! ?BBY: io)multiplex io)backend 5 nanos )) 6 ?BBY: normali8e)directory io)backend 5 path )) path7 6 ?BBY: normali8e)path io)backend 5 path )) path7 6 I: obFect normali8e)directory normali8e)path ! : set)io)backend 5 io)backend )) 6 io)backend set)global init)io init)stdio (io.files( startup)hooks get at call5 )) 6 ! K Note that e have 7alien7 in our using list so that the alien K init hook runs before this one.

0 init)io embedded: 0 init)stdio 3 unless 3 (io.backend( add)startup)hook USING: arrays math parser tools.test kernel generic ords io.streams.string namespaces classes effects source)files assocs sequences strings io.files io.pathnames definitions continuations sorting classes.tuple compiler.units debugger vocabs vocabs.loader accessors eval combinators lexer vocabs.parser ords.symbol multiline source)files.errors tools.crossref grouping sets ! IN: parser.tests 0 1 0 , 0 - 3 / 3 A 3 0 (1>n0>n,>n0>n->n3>n/>n3>nA( eval5 )) a b c 6 3 unit)test 0 t t f f 3 0 (t t f f( eval5 )) : : : : 6 3 unit)test 0 (hello orld( 3 0 (>(hello orld>(( eval5 )) string 6 3 unit)test 0 (>n>r>t>>( 3 0 (>(>>n>>r>>t>>>>>(( eval5 )) string 6 3 unit)test 0 (hello orld( 3 0 (((ZKQusrQbinQenv factor (hello orld( ((( eval5 )) string 6 3 unit)test 0 (hello orld( 3 0 (IN: parser.tests : hello 5 )) str 6 >(hello orld>( !( eval5 )) 6 (US': parser.tests hello( eval5 )) string 6 3 unit)test 0 3 0 (K $his is a comment< people.( eval5 )) 6 3 unit)test K $est escapes 0 ( ( 3 0 (>(>>u====,=>(( eval5 )) string 6 3 unit)test 0 (7( 3 0 (>(>>u====,R>(( eval5 )) string 6 3 unit)test K $est 'B& comments in multiline strings. 0 (?ello( 3 0 (ZK $his calls until)eol.>n>(?ello>(( eval5 )) string 6 3 unit)test 0 ord 3 0 > f class)of 3 unit)test

K $est stack effect parsing : effect)parsing)test 5 a b )) c 6 2 !

0 t 3 0 (effect)parsing)test( (parser.tests( lookup) ord > effect)parsing)test eq: 3 unit)test 0 $+ effect f + (a( (b( . + (c( . f . 3 0 > effect)parsing)test (declared)effect( : ba8 5 a b )) 4 6 ,array thro 0 t 3 0 > ba8 (declared)effect( unit)test ! ord)prop 3 unit)test

ord)prop terminated:GG 3

0 3 0 (IN: parser.tests US': math : effect)parsing)test 5 a b )) d 6 ) !( eval5 )) 6 3 unit)test 0 t 3 0 (effect)parsing)test( (parser.tests( lookup) ord > effect)parsing)test eq: 3 unit)test 0 $+ effect f + (a( (b( . + (d( . f . 3 0 > effect)parsing)test (declared)effect( ord)prop 3 unit)test

0 (IN: parser.tests : missing)) 5 a b 6 !( eval5 )) 6 3 must)fail K @unny bug 0 , 3 0 (IN: parser.tests : >=. 5 )) x 6 , ! >=.( eval5 )) n 6 3 unit)test C'@'#: foo (IN: parser.tests USING: math prettyprint ! SNN$"M: foo , , 2 . !( eval5 )) 6 0 3 0 (US': parser.tests foo( eval5 )) 6 3 unit)test (IN: parser.tests USING: math prettyprint ! : foo 5 )) 6 , , 2 . !( eval5 )) 6 0 t 3 0 (US': parser.tests >> foo( eval5 )) ord 6 (foo( (parser.tests( lookup) ord eq: 3 unit)test K parse)tokens should do the right thing on 'B@ 0 (USING: kernel( eval5 )) 6 3 0 errorGG $+ unexpected + ant (token( . . H 3 must)fail) ith K $est smudging 0 1 3 0 (IN: parser.tests : smudge)me 5 )) 6 !( Pstring)readerG (foo( parse)stream drop (foo( source)file definitionsGG first cardinality 3 unit)test 0 t 3 0 (smudge)me( (parser.tests( lookup) ord Gboolean 3 unit)test 0 3 0 (IN: parser.tests : smudge)me)more 5 )) 6 !( Pstring)readerG (foo( parse)stream drop

3 unit)test 0 t 3 0 (smudge)me)more( (parser.tests( lookup) ord Gboolean 3 unit)test 0 f 3 0 (smudge)me( (parser.tests( lookup) ord Gboolean 3 unit)test 0 - 3 0 (IN: parser.tests USING: math strings ! G'N'#I%: smudge)me 5 a )) b 6 I: integer smudge)me ! I: string smudge)me !( Pstring)readerG (foo( parse)stream drop (foo( source)file definitionsGG first cardinality 3 unit)test 0 1 3 0 (IN: parser.tests USING: arrays ! I: array smudge)me !( Pstring)readerG (bar( parse)stream drop (bar( source)file definitionsGG first cardinality 3 unit)test 0 , 3 0 (IN: parser.tests USING: math strings ! G'N'#I%: smudge)me 5 a )) b 6 I: integer smudge)me !( Pstring)readerG (foo( parse)stream drop (foo( source)file definitionsGG first cardinality 3 unit)test 0 t 3 0 array (smudge)me( (parser.tests( lookup) ord order member)eq: 3 unit)test 0 t 3 0 integer (smudge)me( (parser.tests( lookup) ord order member)eq: 3 unit)test 0 f 3 0 string (smudge)me( (parser.tests( lookup) ord order member)eq: 3 unit)test 0 3 0 (IN: parser.tests US': math , , 2( Pstring)readerG (a( parse)stream drop 3 unit)test 0 t 3 0 (a( PpathnameG > 2 usage member: 3 unit)test 0 3 0 (IN: parser.tests US': math , , )( Pstring)readerG (a( parse)stream drop 3 unit)test 0 f 3 0 (a( PpathnameG > 2 usage member: 3 unit)test 0 3 0 (a( source)files get delete)at , 0

(IN: parser.tests C'@'#: x : y 5 )) 6 x ! : x 5 )) 6 y !( Pstring)readerG (a( parse)stream drop 3 times 3 unit)test (a( source)files get delete)at 0 (IN: parser.tests : x 5 )) 6 ! : y 5 )) 4 6 - thro Pstring)readerG (a( parse)stream 3 0 source)file)error: 3 must)fail) ith 0 t 3 0 (y( (parser.tests( lookup) ord Gboolean 3 unit)test 0 f 3 0 (IN: parser.tests : x 5 )) 6 !( Pstring)readerG (a( parse)stream drop (y( (parser.tests( lookup) ord 3 unit)test K $est ne for ard definition logic 0 3 0 (IN: axx : axx 5 )) 6 !( Pstring)readerG (axx( parse)stream drop 3 unit)test 0 3 0 (US': axx IN: bxx : bxx 5 )) 6 ! : cxx 5 )) 6 axx bxx !( Pstring)readerG (bxx( parse)stream drop 3 unit)test K So e move the bxx ord to axx... 0 3 0 (IN: axx : axx 5 )) 6 ! : bxx 5 )) 6 !( Pstring)readerG (axx( parse)stream drop 3 unit)test 0 t 3 0 (bxx( (axx( lookup) ord Gboolean 3 unit)test K "nd reload the file that uses it... 0 3 0 (US': axx IN: bxx 5 )) 6 : cxx 5 )) 6 axx bxx !( Pstring)readerG (bxx( parse)stream drop 3 unit)test K "nd hope not to get a for ard)errorK K $urning a generic into a non)generic could cause all K kinds of funnyness 0 3 0 (IN: ayy US': kernel G'N'#I%: ayy 5 a )) b 6 I: obFect ayy !( Pstring)readerG (ayy( parse)stream drop 3 unit)test 0 3 0 (IN: ayy US': kernel : ayy 5 )) 6 !( Pstring)readerG (ayy( parse)stream drop 3 unit)test ! this is an error(

0 3 0 (IN: a88 $U;&': my)class ! G'N'#I%: a)generic 5 a )) b 6( Pstring)readerG (a88( parse)stream drop 3 unit)test 0 3 0 (US': a88 I: my)class a)generic !( Pstring)readerG (a88),( parse)stream drop 3 unit)test 0 3 0 (IN: a88 G'N'#I%: a)generic 5 a )) b 6( Pstring)readerG (a88( parse)stream drop 3 unit)test 0 3 0 (US': a88 US': math I: integer a)generic !( Pstring)readerG (a88),( parse)stream drop 3 unit)test 0 3 0 (IN: parser.tests : Pbogus)errorG 5 )) 6 ! : bogus 5 )) error 6 Pbogus)errorG !( Pstring)readerG (bogus)error( parse)stream drop 3 unit)test 0 3 0 (IN: parser.tests $U;&': bogus)error ! %: Pbogus)errorG bogus)error : bogus 5 )) error 6 Pbogus)errorG !( Pstring)readerG (bogus)error( parse)stream drop 3 unit)test K ;roblems ith class predicates )vs) ordinary ords 0 3 0 (IN: parser.tests $U;&': killer !( Pstring)readerG (removing)the)predicate( parse)stream drop 3 unit)test 0 3 0 (IN: parser.tests G'N'#I%: killer: 5 a )) b 6( Pstring)readerG (removing)the)predicate( parse)stream drop 3 unit)test 0 t 3 0 (killer:( (parser.tests( lookup) ord Gboolean 3 unit)test 0 (IN: parser.tests $U;&': another)pred)test ! G'N'#I%: another)pred)test: 5 a )) b 6( Pstring)readerG (removing)the)predicate( parse)stream 3 0 errorGG errorGG errorGG redefine)error: 3 must)fail) ith 0 (IN: parser.tests $U;&': class)redef)test ! $U;&': class)redef)test !( Pstring)readerG (redefining)a)class)1( parse)stream 3 0 errorGG errorGG errorGG redefine)error: 3 must)fail) ith 0 3 0 (IN: parser.tests $U;&': class)redef)test ! SNIEB&: class)redef)test( Pstring)readerG (redefining)a)class),( parse)stream drop 3 unit)test

(IN: parser.tests $U;&': class)redef)test ! SNIEB&: class)redef)test : class)redef)test 5 )) 6 !( Pstring)readerG (redefining)a)class)-( parse)stream drop 3 0 errorGG errorGG errorGG redefine)error: 3 must)fail) ith 0 3 0 (IN: parser.tests $U;&': class)f d)test !( Pstring)readerG (redefining)a)class)-( parse)stream drop 3 unit)test 0 (IN: parser.tests >> class)f d)test( Pstring)readerG (redefining)a)class)-( parse)stream drop 3 0 errorGG errorGG errorGG no) ord)error: 3 must)fail) ith 0 3 0 (IN: parser.tests $U;&': class)f d)test ! SNIEB&: class)f d)test( Pstring)readerG (redefining)a)class)-( parse)stream drop 3 unit)test 0 (IN: parser.tests >> class)f d)test( Pstring)readerG (redefining)a)class)-( parse)stream drop 3 0 errorGG errorGG errorGG no) ord)error: 3 must)fail) ith 0 (IN: parser.tests : foo 5 )) 6 ! $U;&': foo !( Pstring)readerG (redefining)a)class)/( parse)stream drop 3 0 errorGG errorGG errorGG redefine)error: 3 must)fail) ith 0 3 0 (IN: parser.tests : foo 5 x y )) 8 6 1 , ! : bar 5 a )) b 6 !( eval5 )) 6 3 unit)test 0 (IN: parser.tests : foo 5 x y )) 86 1 , ! : bar 5 a )) b 6 !( eval5 )) 6 3 must)fail 0 3 0 (IN: parser.tests US': kernel ;#'CI%"$': foo P obFect !( eval5 )) 6 3 unit)test 0 t 3 0 (foo( (parser.tests( lookup) ord last) ord eq: 3 unit)test 0 3 0 0

(redefining)a)class)A( forget)source (redefining)a)class)L( forget)source (redefining)a)class)R( forget)source 3 ith)compilation)unit 3 unit)test , 0 0 3 0 (IN: parser.tests $U;&': foo ! G'N'#I%: foo 5 a )) b 6( Pstring)readerG (redefining)a)class)A( parse)stream drop 3 unit)test

0 3 0 (IN: parser.tests I: f foo !( Pstring)readerG (redefining)a)class)L( parse)stream drop 3 unit)test 0 f 3 0 f (foo( (parser.tests( lookup) ord execute 3 unit)test 0 3 0 (IN: parser.tests $U;&': foo ! G'N'#I%: foo 5 a )) b 6( Pstring)readerG (redefining)a)class)A( parse)stream drop 3 unit)test 0 f 3 0 f (foo( (parser.tests( lookup) ord execute 3 unit)test 0 3 0 (IN: parser.tests $U;&': foo ! G'N'#I%: foo 5 a )) b 6( Pstring)readerG (redefining)a)class)R( parse)stream drop 3 unit)test 0 f 3 0 f (foo( (parser.tests( lookup) ord execute 3 unit)test 0 3 0 (IN: parser.tests $U;&': foo !( Pstring)readerG (redefining)a)class)R( parse)stream drop 3 unit)test 0 t 3 0 (foo( (parser.tests( lookup) ord symbol: 3 unit)test 3 times 0 (vocab:parserQtestQassert)depth.factor( run)file 3 must)fail , 0 0 3 0 (IN: parser.tests C'@'#: d)f)s d)f)s SNIEB&: d)f)s d)f)s( Pstring)readerG (d)f)s)test( parse)stream drop 3 unit)test 0 3 0 (IN: parser.tests C'@'#: d)f)s d)f)s @B#G'$: d)f)s SNIEB&: d)f)s d)f)s( Pstring)readerG (d)f)s)test( parse)stream drop 3 unit)test 0 3 0 (IN: parser.tests C'@'#: d)f)s d)f)s SNIEB&: d)f)s d)f)s( Pstring)readerG (d)f)s)test( parse)stream drop 3 unit)test 3 times 0 3 0 0 (this)better)not)exist( forget)vocab 3 3 unit)test 0 (US': this)better)not)exist( eval5 )) 6 3 must)fail 0 (: foo !( eval5 )) 6 3 0 errorGG errorGG no)current)vocab)error: 3 must)fail) ith 0 U, 3 0 (%?"#: >>( eval5 )) n 6 3 unit)test 0 U, 3 0 (%?"#: >>>>( eval5 )) n 6 3 unit)test ith)compilation)unit

0 3 0 +

(IN: parser.tests( (USING: math arrays kernel !( (G'N'#I%: change)combination 5 obF a )) b 6( (I: integer change)combination ,drop 1 !( (I: array change)combination ,drop , !( . (>n( Foin Pstring)readerG (change)combination)test( parse)stream drop 3 unit)test 0 3 0 +

(IN: parser.tests( (USING: math arrays kernel !( (G'N'#I%Z change)combination 1 5 obF a )) b 6( (I: integer change)combination ,drop 1 !( (I: array change)combination ,drop , !( . (>n( Foin Pstring)readerG (change)combination)test( parse)stream drop 3 unit)test 0 , 3 0 (change)combination( (parser.tests( lookup) ord (methods( ord)prop assoc)si8e 3 unit)test 0 3 0 , 0 (IN: parser.tests C'@'#: t ice)fails @B#G'$: t ice)fails IIMIN: t ice)fails( Pstring)readerG (t ice)fails)test( parse)stream drop 3 times 3 unit)test 0 0 3 3 0 (IN: parser.tests : staging)problem)test)1 5 )) a 6 1 ! : staging)problem)test), 5 )) a 6 staging)problem)test)1 !( Pstring)readerG (staging)problem)test( parse)stream 3 unit)test 0 t 3 0 (staging)problem)test)1( (parser.tests( lookup) ord Gboolean 3 unit)test 0 t 3 0 (staging)problem)test),( (parser.tests( lookup) ord Gboolean 3 unit)test 0 0 3 3 0 (IN: parser.tests PP : staging)problem)test)1 5 )) a 6 1 ! GG : staging)problem)test), 5 )) a 6 staging)problem)test)1 !( Pstring)readerG (staging)problem)test( parse)stream 3 unit)test 0 t 3 0 (staging)problem)test)1( (parser.tests( lookup) ord Gboolean 3 unit)test 0 t 3 0 (staging)problem)test),( (parser.tests( lookup) ord Gboolean 3 unit)test 0 (C'@'#: blahy( eval5 )) 6 3 0 errorGG errorGG no)current)vocab)error: 3 must)fail) ith 0 3 0 (IN: parser.tests SNN$"M: blahy ! @B#G'$: blahy( eval5 )) 6 errorGG staging)violation: 3 must)fail) ith

K Eogus error message C'@'#: blahy 0 (IN: parser.tests US': kernel $U;&': blahy P tuple ! : blahy 5 )) 6 ! $U;&': blahy P tuple ! : blahy 5 )) 6 !( eval5 )) 6 3 0 errorGG errorGG defGG > blahy eq: 3 must)fail) ith 0 (%?"#: >>uUUUUUUUUUUUUU( eval5 )) n 6 3 must)fail SNIEB&S: a b c ! 0 a 3 0 a 3 unit)test 0 b 3 0 b 3 unit)test 0 c 3 0 c 3 unit)test C'@'#: blah 0 3 0 (IN: parser.tests G'N'#I%: blah 5 )) 6( eval5 )) 6 3 unit)test 0 3 0 (IN: parser.tests SNIEB&S: blah !( eval5 )) 6 3 unit)test 0 f 3 0 > blah generic: 3 unit)test 0 t 3 0 > blah symbol: 3 unit)test C'@'#: blah1 0 (IN: parser.tests SING&'$BNS: blah1 blah1 blah1 !( eval5 )) 6 3 0 errorGG errorGG defGG > blah1 eq: 3 must)fail) ith IN: : x : y IN: : x : y IN: : x qualified.tests.foo 5 )) a 6 1 ! 5 )) a 6 A ! qualified.tests.bar 5 )) a 6 , ! 5 )) a 6 / ! qualified.tests.ba8 5 )) a 6 - !

DU"&I@I'C: qualified.tests.foo DU"&I@I'C: qualified.tests.bar 0 1 , - 3 0 qualified.tests.foo:x qualified.tests.bar:x x 3 unit)test DU"&I@I'C)JI$?: qualified.tests.bar p 0 , 3 0 p:x 3 unit)test #'N"I': x qualified.tests.ba8 HG y 0 - 3 0 y 3 unit)test @#BI: qualified.tests.ba8 HG x ! 0 - 3 0 x 3 unit)test 0 - 3 0 y 3 unit)test 'M%&UC': qualified.tests.bar HG x ! 0 - 3 0 x 3 unit)test 0 / 3 0 y 3 unit)test K $ o similar bugs K #eplace : def ith something in PP GG Q4 0 0 3 3 0 (IN: parser.tests : as)once)a) ord)bug 5 )) 6 !( Pstring)readerG ( as)once)a) ord)test( parse)stream

3 unit)test 0 t 3 0 ( as)once)a) ord)bug( (parser.tests( lookup) ord Gboolean 3 unit)test 0 0 3 3 0 (IN: parser.tests US': ords PP >( as)once)a) ord)bug>( >(parser.tests>( create 0 3 5 )) 6 define)declared GG( Pstring)readerG ( as)once)a) ord)test( parse)stream 3 unit)test 0 t 3 0 ( as)once)a) ord)bug( (parser.tests( lookup) ord Gboolean 3 unit)test 4Q K #eplace : def ith C'@'#: 0 0 3 3 0 (IN: parser.tests : is)not)deferred 5 )) 6 !( Pstring)readerG (is)not)deferred( parse)stream 3 unit)test 0 t 3 0 (is)not)deferred( (parser.tests( lookup) ord Gboolean 3 unit)test 0 f 3 0 (is)not)deferred( (parser.tests( lookup) ord deferred: 3 unit)test 0 0 3 3 0 (IN: parser.tests C'@'#: is)not)deferred( Pstring)readerG (is)not)deferred( parse)stream 3 unit)test 0 t 3 0 (is)not)deferred( (parser.tests( lookup) ord Gboolean 3 unit)test 0 t 3 0 (is)not)deferred( (parser.tests( lookup) ord deferred: 3 unit)test K @or ard)reference resolution case iterated using list in the 0 0 3 3 0 (IN: parser.tests.for ard)ref)1 C'@'#: x C'@'#: y( Pstring)readerG (for ard)ref)1( parse)stream 3 unit)test 0 0 3 3 0 (IN: parser.tests.for ard)ref), C'@'#: x C'@'#: y( Pstring)readerG (for ard)ref),( parse)stream 3 unit)test 0 0 3 3 0 (IN: parser.tests.for ard)ref)- @#BI: parser.tests.for ard)ref)1 HG x y ! @#BI: parser.tests.for ard)ref), HG x y ! : 8 5 )) 6 x y !( Pstring)readerG (for ard)ref)-( parse)stream 3 unit)test 0 t 3 0 (8( (parser.tests.for ard)ref)-( lookup) ord defGG 0 vocabularyGG 3 map all)equal: 3 unit)test 0 0 3 3 0 (@#BI: parser.tests.for ard)ref)1 HG x y ! @#BI: parser.tests.for ard)ref), HG x y ! IN: parser.tests.for ard)ref)- : x 5 )) 6 ! : 8 5 )) 6 x y !( Pstring)readerG (for ard)ref)-( parse)stream 3 unit)test 0 f 3 0 (8( (parser.tests.for ard)ref)-( lookup) ord defGG 0 vocabularyGG 3 map all)equal: 3 unit)test rong direction

0 0 3 3 0 (IN: parser.tests.for ard)ref)- @#BI: parser.tests.for ard)ref)1 HG x y ! @#BI: parser.tests.for ard)ref), HG x y ! : 8 5 )) 6 x y !( Pstring)readerG (for ard)ref)-( parse)stream 3 unit)test 0 t 3 0 (8( (parser.tests.for ard)ref)-( lookup) ord defGG 0 vocabularyGG 3 map all)equal: 3 unit)test 0 0 dup 3 3 0 (US': kernel dup( Pstring)readerG (unuse)test( parse)stream 3 unit)test 0 (dup( Pstring)readerG (unuse)test( parse)stream 3 0 errorGG errorGG errorGG no) ord)error: 3 must)fail) ith 0 (US': kernel UNUS': kernel dup( Pstring)readerG (unuse)test( parse)stream 3 0 errorGG errorGG errorGG no) ord)error: 3 must)fail) ith 0 3 0 0 (vocabs.loader.test.l( forget)vocab 3 0 ith)compilation)unit 3 unit)test

0 (vocabs.loader.test.l( use)vocab 3 must)fail 0 f 3 0 (vocabs.loader.test.l( manifest get search)vocab)namesGG in: 3 unit)test 0 3 0 (vocabs.loader.test.l( unuse)vocab 3 unit)test 0 f 3 0 (vocabs.loader.test.l( manifest get search)vocab)namesGG in: 3 unit)test 3 ith)file)vocabs K $est cases for Z1S0 (SING&'$BN: --( Pstring)readerG (class identifier test( parse)stream 3 0 errorGG lexer)error: 3 must)fail) ith 0 (: // 5 )) 6 !( Pstring)readerG ( ord identifier test( parse)stream 3 0 errorGG lexer)error: 3 must)fail) ith 0 (G'N'#I%: -- 5 )) 6( Pstring)readerG (generic identifier test( parse)stream 3 0 errorGG lexer)error: 3 must)fail) ith 1 , USING: lexer namespaces parser.notes source)files tools.test ! IN: parser.notes.tests 0 3 0 f lexer set f file set (?ello orld( note. 3 unit)testK %opyright 5%6 ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors io kernel lexer math.parser namespaces source)files ! IN: parser.notes SNIEB&: parser)quiet: t parser)quiet: set)global : note. 5 str )) 6 parser)quiet: get 0 file get 0 pathGG rite (:( rite 3 hen4 lexer get 0 lineGG numberGstring rite (: (

rite 3

hen4

(Note:( print dup print 3 unless drop ! USING: help.markup help.syntax io parser.notes ! IN: parser.notes ?'&;: parser)quiet: + *var)description (" boolean controlling hether the parser ill print various notes. S itched on by default. If a source file is being run for its effect on ( + *link output)stream . (< this variable should remain s itched on< to prevent parser notes from polluting the output.( . ! USING: help.markup help.syntax kernel sequences ords math strings vectors quotations generic effects classes vocabs.loader definitions io vocabs source)files namespaces compiler.units assocs lexer ords.symbol ords.alias ords.constant vocabs.parser ! IN: parser "#$I%&': (reading)ahead( (#eading ahead( (;arsing ords can consume input from the input stream. Jords come in t o flavors: ords that thro upon finding end of file< and ords that return ( + *link f . ( upon the same.( *nl (;arsing ords that thro on end of file:( + *subsections scan)token scan) ord)name scan) ord scan)datum scan)number scan)obFect . (;arsing ords that return ( + *link f . ( on end of file:( + *subsections 5scan)token6 5scan)datum6 . (" simple example is the ( + *link ;BS$;BN': > . ( ord:( + *see ;BS$;BN': > . ! "#$I%&': (parsing) ord)nest( (Nested structure( (#ecall that the parser loop calls parsing ords ith an accumulator vector on the stack. $he parser loop can be invoked recursively ith a ne < empty accumulator! the result can then be added to the original accumulator. $his is ho parsing ords for obFect literals are implemented! obFect literals can nest arbitrarily deep.( *nl (" simple example is the parsing ord that reads a quotation:( + *see ;BS$;BN': 0 . ($his ord uses a utility ord hich recursively invokes the parser< reading obFects into a ne accumulator until an occurrence of ( + *link ;BS$;BN': 3 . (:( + *subsections parse)literal . ($here is another< lo er)level ord for reading nested structure< hich is also useful hen called directly:( + *subsections parse)until . (Jords such as ( + *link ;BS$;BN': 3 . ( use a declaration hich causes them to thro an error hen an unpaired occurrence is encountered:( + *subsections ;BS$;BN': delimiter . + *see)also ;BS$;BN': + ;BS$;BN': ?+ ;BS$;BN': V+ ;BS$;BN': J+ ;BS$;BN': $+ ;BS$;BN': . . ! "#$I%&': (defining) ords( (Cefining ords(

(Cefining ords add definitions to the dictionary ithout modifying the parse tree. $he simplest example is the ( + *link ;BS$;BN': SNIEB&: . ( ord.( + *see ;BS$;BN': SNIEB&: . ($he key factor in the definition of ( + *link ;BS$;BN': SNIEB&: . ( is ( + *link scan)ne . (< hich reads a token from the input and creates a ord ith that name. $his ord is then passed to ( + *link define)symbol . (.( + *subsections scan)ne scan)ne ) ord . (%olon definitions are defined in a more elaborate ay:( + *subsections ;BS$;BN': : . ($he ( + *link ;BS$;BN': : . ( ord first calls ( + *link scan)ne . (< and then reads input until reaching ( + *link ;BS$;BN': ! . ( using a utility ord:( + *subsections parse)definition . ($he ( + *link ;BS$;BN': ! . ( ord is Fust a delimiter! an unpaired occurrence thro s a parse error:( + *see ;BS$;BN': ! . ($here are additional parsing ords hose syntax is delimited by ( + *link ;BS$;BN': ! . (< and they are all implemented by calling ( + *link parse)definition . (.( ! "#$I%&': (parsing)tokens( (;arsing ra tokens( (So far e have seen ho to read individual tokens< or read a sequence of parsed obFects until a delimiter. It is also possible to read ra tokens from the input and perform custom processing.( *nl (Bne example is the ( + *link ;BS$;BN': USING: . ( parsing ord.( + *see ;BS$;BN': USING: . (It reads a list of vocabularies terminated by ( + *link ;BS$;BN': ! . (. ?o ever< the vocabulary names do not name ords< except by coincidence! so ( + *link parse)until . ( cannot be used here. Instead< a set of lo er)level combinators can be used:( + *subsections each)token map)tokens parse)tokens . ! "#$I%&': (parsing) ords( (;arsing ords( ($he @actor parser follo s a simple recursive)descent design. $he parser reads successive tokens from the input! if the token identifies a number or an ordinary ord< it is added to an accumulator vector. Bther ise if the token identifies a parsing ord< the parsing ord is executed immediately.( *nl (;arsing ords are defined using the defining ord:( + *subsections ;BS$;BN': SNN$"M: . (;arsing ords have uppercase names by convention. ?ere is the simplest possible parsing ord! it prints a greeting at parse time:( + *code (SNN$"M: ?'&&B >(?ello orld>( print !( . (;arsing ords must not pop or push items from the stack! ho ever< they are permitted to access the accumulator vector supplied by the parser at the top of the stack. $hat is< parsing ords must have stack effect ( + *snippet (5 accum )) accum 6( . (< here ( + *snippet (accum( . ( is the accumulator vector supplied by the parser.( *nl (;arsing ords can read input< add ord definitions to the dictionary< and do anything an ordinary ord can.( *nl (Eecause of the stack restriction< parsing ords cannot pass data to other ords by leaving values on the stack! instead< use ( + *link suffixK . ( to add the data to the parse tree so that it can be evaluated later.(

*nl (;arsing ords cannot be called from the same source file here they are defined< because ne definitions are only compiled at the end of the source file. "n attempt to use a parsing ord in its o n source file raises an error:( + *subsections staging)violation . ($ools for implementing parsing ords:( + *subsections (reading)ahead( (parsing) ord)nest( (defining) ords( (parsing)tokens( ( ord)search)parsing( . ! "#$I%&': (top)level)forms( ($op level forms( ("ny code outside of a definition is kno n as a ( + *emphasis (top)level form( . (! top)level forms are run after the entire source file has been parsed< regardless of their position in the file.( *nl ($op)level forms cannot access the parse)time manifest 5( + *link ( ord)search)parsing( . (6< nor do they run inside ( + *link ith)compilation)unit . (! as a result< meta)programming might require extra ork in a top)level form compared ith a parsing ord.( *nl ("lso< top)level forms run in a ne dynamic scope< so using ( + *link set . ( to store values is almost al ays rong< since the values ill be lost after the top)level form completes. $o save values computed by a top)level form< either use ( + *link set)global . ( or define a ne ord ith the value.( ! "#$I%&': (parser( ($he parser( ($he @actor parser reads textual representations of obFects and definitions< ith all syntax determined by ( + *link (parsing) ords( . (. $he parser is implemented in the ( + *vocab)link (parser( . ( vocabulary< ith standard syntax in the ( + *vocab)link (syntax( . ( vocabulary. See ( + *link (syntax( . ( for a description of standard syntax.( *nl ($he parser cross)references ( + *link (source)files( . ( and ( + *link (definitions( . (. $his functionality is used for improved error checking< as ell as tools such as ( + *link (tools.crossref( . ( and ( + *link (editor( . (.( *nl ($he parser can be invoked reflectively< to run strings and source files.( + *subsections (eval( run)file parse)file . (If @actor is run from the command line ith a script file supplied as an argument< the script is run using ( + *link run)file . (. See ( + *link (command)line( . (.( *nl (Jhile ( + *link run)file . ( can be used interactively in the listener to load user code into the session< this should only be done for quick one)off scripts< and real programs should instead rely on the automatic ( + *link (vocabs.loader( . (.( + *see)also (parsing) ords( (definitions( (definition)checking( . ! "EBU$: (parser( ?'&;: location + *values + (loc( (a ( + *snippet (+ path lineZ .( . ( pair( . . + *description (Butputs the current parser location. $his value can be passed to

( + *link set) here . ( or ( + *link remember)definition . (.( . ! ?'&;: save)location + *values + (definition( (a definition specifier( . . + *description (Saves the location of a definition and associates this definition ith the current source file.( . ! ?'&;: bad)number + *error)description (Indicates the parser encountered an invalid numeric literal.( . ! ?'&;: create)in + *values + (str( (a ord name( . + ( ord( (a ne ord( . . + *description (%reates a ord in the current vocabulary. Until re)defined< the ord thro s an error hen invoked.( . *parsing)note ! ?'&;: scan)ne + *values + ( ord( ord . . + *description (#eads the next token from the parser input< and creates a ith that name in the current vocabulary.( . + *errors ($hro s an error if the end of the file is reached.( . *parsing)note !

ord

?'&;: scan)ne ) ord + *values + ( ord( ord . . + *description (#eads the next token from the parser input< and creates a ord ith that name in the current vocabulary and resets the generic ord properties of that ord.( . + *errors ($hro s an error if the end of the file is reached.( . *parsing)note ! ?'&;: no) ord)error + *error)description ($hro n if the parser encounters a token hich does not name a ord in the current vocabulary search path. If any ords ith this name exist in vocabularies not part of the search path< a number of restarts ill offer to add those vocabularies to the search path and use the chosen ord.( . + *notes ("part from a missing ( + *link ;BS$;BN': US': . (< this error can also indicate an ordering issue. In @actor< ords must be defined before they can be called. Iutual recursion can be implemented via ( + *link ;BS$;BN': C'@'#: . (.( . ! ?'&;: no) ord + *values + (name( string . + (ne ord( ord . . + *description ($hro s a ( + *link no) ord)error . (.( . ! ?'&;: parse) ord + *values + (string( string . + ( ord( (a number( . . + *description (If ( + *snippet (string( . ( is a valid number literal< it is converted to a number< other ise the current vocabulary search path is searched for a ord named by the string.( . + *errors ($hro s an error if the token does not name a ord< and does not parse as a number.( . + *notes ($his ord is used to implement ( + *link scan) ord . (.( . ! ?'&;: parse)datum + *values + (string( string . + ( ordQnumber( (a ord or number( . . + *description (If ( + *snippet (string( . ( is a valid number literal< it is converted to a number< other ise the current vocabulary search path is searched for a ord named by the string.( . + *errors ($hro s an error if the token does not name a ord< and does not parse as a number.( .

+ *notes ($his ord is used to implement ( + *link 5scan)datum6 . ( and ( + *link scan)datum . (.( . ! ?'&;: scan) ord + *values + ( ord( (a ord( . . + *description (#eads the next token from parser input. If the token is a valid number literal< it is converted to a number< other ise the vocabulary search path is searched for a ord named by the token.( . + *errors ($hro s an error if the token does not name a ord or end of file is reached.( . *parsing)note ! + scan) ord parse) ord . related) ords ?'&;: scan) ord)name + *values + (string( string . . + *description (#eads the next token from parser input and makes sure it does not parse as a number.( . + *errors ($hro s an error if the scanned token is a number or upon finding end of file.( . *parsing)note ! ?'&;: 5scan)datum6 + *values + ( ordQnumberQf( (a ord< a number< or ( + *link f . . . + *description (#eads the next token from parser input. If the token is found in the vocabulary search path< returns the ord named by the token. If the token does not find a ord< it is next converted to a number. If this conversion fails< too< this ord returns ( + *link f . (.( . *parsing)note ! ?'&;: scan)datum + *values + ( ordQnumber( (a ord or a number( . . + *description (#eads the next token from parser input. If the token is found in the vocabulary search path< returns the ord named be the token. If the token is not found in the vocabulary search path< it is converted to a number. If this conversion fails< an error is thro n.( . + *errors ($hro s an error if the token is not a number or end of file is reached.( . *parsing)note ! ?'&;: scan)number + *values + (number( (a number( . . + *description (#eads the next token from parser input. If the token is a number literal< it is converted to a number. Bther ise< it thro s an error.( . + *errors ($hro s an error if the token is not a number or end of file is reached.( . *parsing)note ! ?'&;: parse)until)step + *values + (accum( vector . + (end( ord . + (:( (a boolean( . . + *description (;arses a token. If the token is a number or an ordinary ord< it is added to the accumulator. If it is a parsing ord< calls the parsing ord ith the accumulator on the stack. Butputs ( + *link f . ( if ( + *snippet (end( . ( is encountered< ( + *link t . ( other ise.( . *parsing)note ! ?'&;: 5parse)until6 + *values + (accum( vector . + (end( ord . . + *description (;arses obFects from parser input until ( + *snippet (end( . ( is encountered< adding them to the accumulator.( . *parsing)note !

?'&;: parse)until + *values + (end( ord . + (vec( (a ne vector( . . + *description (;arses obFects from parser input until ( + *snippet (end( . (. Butputs a ne vector ith the results.( . + *examples ($his ord is used to implement ( + *link ;BS$;BN': "#$I%&': . (.( . *parsing)note ! + parse)tokens each)token map)tokens 5parse)until6 parse)until . related) ords ?'&;: 5parse)lines6 + *values + (lexer( lexer . + + *description (;arses @actor search path is taken from the + *errors ($hro s a ( + *link (quot( (a ne ( + *link quotation . . . source code using a custom lexer. $he vocabulary current scope.( . lexer)error . ( if the input is malformed.( . !

?'&;: parse)lines + *values + (lines( (a sequence of strings( . + (quot( (a ne ( + *link quotation . . . + *description (;arses @actor source code hich has been tokeni8ed into lines. $he vocabulary search path is taken from the current scope.( . + *errors ($hro s a ( + *link lexer)error . ( if the input is malformed.( . ! ?'&;: parse)literal + *values + (accum( vector . + (end( ord . + (quot( + *quotation (5 seq )) obF 6( . . . + *description (;arses obFects from parser input until ( + *snippet (end( . (< applies the quotation to the resulting sequence< and adds the output value to the accumulator.( . + *examples ($his ord is used to implement ( + *link ;BS$;BN': 0 . (.( . *parsing)note ! ?'&;: parse)definition + *values + (quot( (a ne ( + *link quotation . . . + *description (;arses obFects from parser input until ( + *link ;BS$;BN': ! . ( and outputs a quotation ith the results.( . + *examples ($his ord is used to implement ( + *link ;BS$;BN': : . (.( . *parsing)note ! ?'&;: bootstrap)syntax + *var)description (Bnly set during bootstrap. Stores a copy of the ( + *link vocab) ords . ( of the host7s syntax vocabulary! this allo s the host7s parsing ords to be used during bootstrap source parsing< not the target7s.( . ! ?'&;: ith)file)vocabs + *values + (quot( quotation . . + *description (%alls the quotation in a scope ith an initial vocabulary search path consisting of Fust the ( + *snippet (syntax( . ( vocabulary.( . ! ?'&;: parse)fresh + *values + (lines( (a sequence of strings( . + (quot( quotation . . + *description (;arses @actor source code in a sequence of lines. $he initial vocabulary search path is used 5see ( + *link ith)file)vocabs . (6.( . + *errors ($hro s a parse error if the input is malformed.( . ! ?'&;: filter)moved + *values + (set1( set . + (set,( set . + (seq( (an sequence of definitions( . . + *description (#emoves all definitions from ( + *snippet (set,( . ( hich are in ( + *snippet (set1( . ( or are no longer present in the current ( + *link file . (.( . ! ?'&;: forget)smudged + *description (@orgets removed definitions.( . !

?'&;: finish)parsing + *values + (lines( (the lines of text Fust parsed( . + (quot( (the quotation Fust parsed( . . + *description (#ecords information to the current ( + *link file . (.( . + *notes ($his is one of the factors of ( + *link parse)stream . (.( . ! ?'&;: parse)stream + *values + (stream( (an input stream( . + (name( (a file name for error reporting and cross)referencing( . + (quot( quotation . . + *description (;arses @actor source code read from the stream. $he initial vocabulary search path is used.( . + *errors ($hro s an IQB error if there as an error reading from the stream. $hro s a parse error if the input is malformed.( . ! ?'&;: parse)file + *values + (file( (a pathname string( . + (quot( quotation . . + *description (;arses the @actor source code stored in a file. $he initial vocabulary search path is used.( . + *errors ($hro s an IQB error if there as an error reading from the file. $hro s a parse error if the input is malformed.( . ! ?'&;: run)file + *values + (file( (a pathname string( . . + *description (;arses the @actor source code stored in a file and runs it. $he initial vocabulary search path is used.( . + *errors ($hro s an error if loading the file fails< there input is malformed< or if a runtime error occurs hile calling the parsed quotation.( . ! ?'&;: :run)file + *values + (path( (a pathname string( . . + *description (If the file exists< runs it other ise does nothing.( . !

ith ( + *link run)file . (<

?'&;: staging)violation + *values + ( ord( ord . . + *description ($hro s a ( + *link staging)violation . ( error.( . + *error)description ($hro n by the parser if a parsing ord is used in the same compilation unit as here it as defined! see ( + *link (compilation)units( . (.( . + *notes (Bne possible orkaround is to use the ( + *link ;BS$;BN': PP . ( ord to execute code at parse time. ?o ever< executing ords defined in the same source file at parse time is still prohibited.( . ! ?'&;: auto)use: + *var)description (If set to a true value< the behavior of the parser hen encountering an unkno n ord name is changed. If only one loaded vocabulary has a ord ith this name< instead of thro ing an error< the parser adds the vocabulary to the search path and prints a parse note. Bff by default.( . + *notes ($his feature is intended to help during development. $o generate a ( + *link ;BS$;BN': USING: . ( form automatically< enable ( + *link auto)use: . (< load the source file< and copy and paste the ( + *link ;BS$;BN': USING: . ( form printed by the parser back into the file< then disable ( + *link auto)use: . (. See ( + *link ( ord)search)errors( . (.( . ! ?'&;: scan)obFect + *values + (obFect( obFect . . + *description (;arses a literal representation of an obFect.( . *parsing)note ! K %opyright 5%6 ,==A< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes combinators

compiler.units continuations definitions effects io io.encodings.utfS io.files kernel lexer math.parser namespaces parser.notes quotations sequences sets slots source)files vectors vocabs vocabs.parser ords ords.symbol ! @#BI: sets HG members ! IN: parser : location 5 )) loc 6 file get lexer get lineGG ,dup and 0 0 pathGG 3 dip ,array 3 0 ,drop f 3 if ! : save)location 5 definition )) 6 location remember)definition ! I: parsing) ord stack)effect drop 5 parsed )) parsed 6 ! : create)in 5 str )) ord 6 current)vocab create dup set)last) ord dup save)location ! SNIEB&: auto)use: : auto)use 5 )) 6 auto)use: on ! : no) ord)restarted 5 restart)value )) ord 6 dup ord: 0 dup vocabularyGG 0 auto)use)vocab 3 0 ("dded >(( (>( vocabulary to search path( surround note. 3 bi 3 0 create)in 3 if ! : ignore)for ards 5 seq )) seq7 6 0 for ard)reference: not 3 filter ! : private: 5 ord )) : 6 vocabularyGG (.private( tail: !

: ignore)privates 5 seq )) seq7 6 dup 0 private: 3 all: 0 0 private: not 3 filter 3 unless ! : no) ord 5 name )) ne ord 6 dup ords)named ignore)for ards dup ignore)privates dup length 1 H auto)use: get and 0 ,nip first no) ord)restarted 3 0 drop Pno) ord)errorG thro )restarts no) ord)restarted 3 if ! : parse) ord 5 string )) ord 6 dup search 0 3 0 no) ord 3 :if ! '##B#: number)expected ! : parse)number 5 string )) number 6 stringGnumber 0 number)expected 3 unless4 ! : parse)datum 5 string )) ordQnumber 6 dup search 0 3 0 dup stringGnumber 0 3 0 no) ord 3 :if 3 :if ! : 5scan)datum6 5 )) ordQnumberQf 6 5scan)token6 dup 0 parse)datum 3 : scan)datum 5 )) ordQnumber 6 hen !

5scan)datum6 0 >

ord thro )unexpected)eof 3 unless4 !

: scan) ord 5 )) ord 6 5scan)token6 parse) ord ! : scan)number 5 )) number 6 5scan)token6 parse)number ! : scan) ord)name 5 )) string 6 scan)token dup stringGnumber 0 (Jord names cannot be numbers( thro 3 hen ! : scan)ne 5 )) ord 6 scan) ord)name create)in ! : scan)ne ) ord 5 )) ord 6 scan)ne dup reset)generic ! '##B#: staging)violation ord !

: 5execute)parsing6 5 accum ord )) accum 6 dup push)parsing) ord execute5 accum )) accum 6 pop)parsing) ord ! inline : execute)parsing 5 accum ord )) accum 6 dup changed)definitions get in: 0 staging)violation 3 5execute)parsing6 ! : scan)obFect 5 )) obFect 6 scan)datum dup parsing) ord: 0 V+ . clone s ap execute)parsing first 3 hen ! : scan)class 5 )) class 6 scan)obFect > f or ! : parse)until)step 5 accum end )) accum : 6 5scan)datum6 + + 0 ,dup eq: 3 0 ,drop f 3 . + 0 dup not 3 0 drop thro )unexpected)eof t 3 . + 0 dup delimiter: 3 0 unexpected t 3 . + 0 dup parsing) ord: 3 0 nip execute)parsing t 3 . 0 pick push drop t 3 . cond ! : 5parse)until6 5 accum end )) accum 6 0 parse)until)step 3 keep s ap 0 5parse)until6 3 0 drop 3 if ! : parse)until 5 end )) vec 6 1== PvectorG s ap 5parse)until6 ! SNIEB&: quotation)parser ?BBY: parse)quotation quotation)parser 5 )) quot 6 I: f parse)quotation > 3 parse)until Gquotation ! : 5parse)lines6 5 lexer )) quot 6 hen

0 f parse)until Gquotation 3

ith)lexer !

: parse)lines 5 lines )) quot 6 Garray PlexerG 5parse)lines6 ! : parse)literal 5 accum end quot )) accum 6 0 parse)until 3 dip call suffixK ! inline : parse)definition 5 )) quot 6 > ! parse)until Gquotation ! '##B#: bad)number ! : scan)base 5 base )) n 6 scan)token s ap baseG 0 bad)number 3 unless4 ! SNIEB&: bootstrap)syntax : ith)file)vocabs 5 quot )) 6 0 (syntax( use)vocab bootstrap)syntax get 0 use) ords 3 call 3 ith)manifest ! inline

hen4

SNIEB&: print)use)hook print)use)hook 0 0 3 3 initiali8e : parse)fresh 5 lines )) quot 6 0 parse)lines auto)used: 0 print)use)hook get call5 )) 6 3 3 ith)file)vocabs ! : parsing)file 5 file )) 6 parser)quiet: get 0 drop 3 0 (&oading (

hen

rite print flush 3 if !

: filter)moved 5 set1 set, )) seq 6 s ap diff members 0 + + 0 dup here dup 0 first 3 hen file get pathGG H not 3 0 f 3 . + 0 dup reader)method: 3 0 f 3 . + 0 dup riter)method: 3 0 f 3 . 0 t 3 . cond nip 3 filter ! : removed)definitions 5 )) set1 set, 6 ne )definitions old)definitions 0 get first, union 3 bi9 ! : removed)classes 5 )) set1 set, 6 ne )definitions old)definitions 0 get second 3 bi9 ! : forget)removed)definitions 5 )) 6 removed)definitions filter)moved forget)all ! : reset)removed)classes 5 )) 6 removed)classes filter)moved 0 class: 3 filter 0 forget)class 3 each !

: fix)class) ords 5 )) 6 ZK If a class ord had a compound definition hich as ZK removed< it must go back to being a symbol. ne )definitions get first, filter)moved 0 0 reset)generic 3 0 define)symbol 3 bi 3 each ! : forget)smudged 5 )) 6 forget)removed)definitions reset)removed)classes fix)class) ords ! : finish)parsing 5 lines quot )) 6 file get 0 record)top)level)form 3 0 record)definitions 3 0 record)checksum 3 tri ! : parse)stream 5 stream name )) quot 6 0 0 stream)lines dup parse)fresh 0 nip 3 0 finish)parsing 3 ,bi forget)smudged 3 ith)source)file 3 ith)compilation)unit ! : parse)file)restarts 5 file )) restarts 6 (&oad ( ( again( surround t ,array 1array ! : parse)file 5 file )) quot 6 0 0 parsing)file 3 keep 0 utfS Pfile)readerG 3 keep parse)stream 3 0 over parse)file)restarts rethro )restarts drop parse)file 3 recover ! : run)file 5 file )) 6 parse)file call5 )) 6 ! : :run)file 5 path )) 6 dup exists: 0 run)file 3 0 drop 3 if ! '##B#: version)control)merge)conflict ! USING: accessors kernel kernel.private math memory prettyprint io sequences tools.test ords namespaces layouts classes classes.builtin arrays quotations system ! @#BI: tools.memory HG data)room code)room ! IN: memory.tests 0 save)image)and)exit 3 must)fail K $ests for 7instances7 0 0 3 instances 3 must)infer , 0 0 0 - thro 3 instances 3 must)fail 3 times K $ests for 7become7 0 3 0 + . + . become 3 unit)test

K Eug found on Jindo s build box< having too many ords in the K image breaks 7become7 0 3 0 1===== 0 f Puninterned) ordG 3 replicate + . + . become drop 3 unit)test K K K K K K : Eug: code heap collection had to be done hen data heap as full< not Fust hen code heap as full. If the code heap contained dead code blocks referring to large data heap obFects< those large obFects ould continue to live on even if the code blocks ere not reachable< as long as the code heap did not fill up. leak)step 5 )) 6 S===== f ParrayG 1quotation call5 )) obF 6 drop !

: leak)loop 5 )) 6 1== 0 leak)step 3 times ! 0 3 0 leak)loop 3 unit)test K Eug: allocation of large obFects directly into tenured space K can proceed past the high ater mark. K K Suppose the nursery and aging spaces are mostly comprised of K reachable obFects. Jhen doing a full G%< obFects from young K generations ere promoted 4before4 unreachable obFects in K tenured space are freed by the s eep phase. So if large obFect K allocation filled up the heap past the high ater mark< this K promotion might trigger heap gro th< even if most of those K large obFects are unreachable. SNIEB&: foo 0 3 0 gc data)room tenuredGG si8eGG 1= 0 / 0 1,= 1=,/ 4 f ParrayG 3 replicate foo set)global 1== 0 ,AL 1=,/ 4 f ParrayG drop 3 times 3 times data)room tenuredGG si8eGG assertH 3 unit)test K %opyright 5%6 ,==A< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: alien.strings io.backend kernel memory.private sequences system ! IN: memory : instances 5 quot )) seq 6 0 all)instances 3 dip filter ! inline : saving)path 5 path )) saving)path path 6 0 (.saving( append 3 keep 0 native)stringGalien 3 bi9 ! : save)image 5 path )) 6 normali8e)path saving)path 5save)image6 ! : save)image)and)exit 5 path )) 6 normali8e)path saving)path 5save)image)and)exit6 ! : save 5 )) 6 image save)image !

USING: help.markup help.syntax debugger sequences kernel quotations math ! IN: memory ?'&;: instances + *values + (quot( + *quotation (5 obF )) : 6( . . + (seq( (a fresh sequence( . . + *description (Butputs a sequence of all obFects in the heap hich satisfy the quotation.( . ! ?'&;: gc + *description (;erforms a full garbage collection.( . ! ?'&;: si8e + *values + (obF( (an obFect( . + (n( (a si8e in bytes( . . + *description (Butputs the si8e of the obFect in memory< in bytes. $agged immediate obFects such as fixnums and ( + *link f . ( ill yield a si8e of =.( . ! ?'&;: save)image + *values + (path( (a pathname string( . . + *description (Saves a snapshot of the heap to the given file< over riting the file if it already exists.( . ! ?'&;: save)image)and)exit + *values + (path( (a pathname string( . . + *description (Saves a snapshot of the heap to the given file< over riting the file if it already exists. $his ord compacts the code heap and immediately exits @actor< since the @actor VI cannot continue executing after compiled code blocks have been moved around.( . ! + save save)image save)image)and)exit . related) ords ?'&;: save + *description (Saves a snapshot of the heap to the current image file.( . ! "#$I%&': (images( (Images( (@actor has the ability to save the entire state of the system into an ( + *emphasis (image file( . (. $he image contains a complete dump of all data and code in the current @actor instance.( + *subsections save save)image save)image)and)exit . ($o start @actor ith a custom image< use the ( + *snippet ()iH( + *emphasis (image( . . ( command line s itch! see ( + *link (runtime)cli)args( . (.( *nl (Bne reason to save a custom image is if you find yourself loading the same libraries in every @actor session! some libraries take a little hile to compile< so saving an image ith those libraries loaded can save you a lot of time.( *nl (@or example< to save an image ith the eb frame ork loaded<( + *code (US': furnace( (save( . (Ne images can be created from scratch:( + *subsections (bootstrap.image( . ($he ( + *link (tools.deploy( . ( tool creates stripped)do n images containing Fust enough code to run a single application.( + *see)also (tools.memory( . ! "EBU$: (images(

K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays byte)vectors continuations.private init kernel kernel.private math namespaces sequences ! IN: alien EUI&$IN: alien + underlying c)ptr read)only initial: f . expired ! EUI&$IN: dll + path byte)array read)only initial: E+ . . ! ;#'CI%"$': pinned)alien P alien underlyingGG not ! UNIBN: pinned)c)ptr pinned)alien ;BS$;BN': f ! G'N'#I%: element)si8e 5 seq )) n 6 flushable I: byte)array element)si8e drop 1 ! inline I: byte)vector element)si8e drop 1 ! inline I: slice element)si8e seqGG element)si8e ! inline I: f element)si8e drop 1 ! inline G'N'#I%: byte)length 5 obF )) n 6 flushable I: obFect byte)length 0 length 3 0 element)si8e 3 bi 4 ! inline G'N'#I%: Gc)ptr 5 obF )) c)ptr 6 flushable I: c)ptr Gc)ptr ! inline I: slice Gc)ptr 0 0 fromGG 3 0 element)si8e 3 bi 4 3 0 seqGG Gc)ptr 3 bi Pdisplaced)alienG ! inline S&B$: underlying I: obFect Gc)ptr underlyingGG ! inline : binary)obFect 5 obF )) c)ptr n 6 0 Gc)ptr 3 0 byte)length 3 bi ! inline G'N'#I%: expired: 5 c)ptr )) : 6 flushable I: alien expired: expiredGG ! I: f expired: drop t ! : PalienG 5 address )) alien 6 f Pdisplaced)alienG + pinned)c)ptr . declare ! inline : Pbad)alienG 5 )) alien 6 )1 PalienG t GGexpired ! inline I: alien equal: over alien: 0 ,dup 0 expired: 3 either: 0 0 expired: 3 both: 3 0 0 alien)address 3 same: 3 if 3 0

,drop f 3 if ! I: pinned)alien hashcode4 nip dup expiredGG 0 drop 1,-/ 3 0 alien)address 3 if ! SING&'$BNS: stdcall thiscall fastcall cdecl ming UNIBN: abi stdcall thiscall fastcall cdecl ming : callee)cleanup: 5 abi )) : 6 + stdcall fastcall thiscall . member: ! '##B#: alien)callback)error ! : alien)callback 5 return parameters abi quot )) alien 6 alien)callback)error ! '##B#: alien)indirect)error ! : alien)indirect 5 args... funcptr return parameters abi )) return... 6 alien)indirect)error ! '##B#: alien)invoke)error library symbol ! : alien)invoke 5 args... return library function parameters )) return... 6 ,over alien)invoke)error ! '##B#: alien)assembly)error code ! : alien)assembly 5 args... return parameters abi quot )) return... 6 dup alien)assembly)error ! P;#IV"$' K %allbacks are registered in a global hashtable. Note that they K are also pinned in a special callback area< so clearing this K hashtable ill not reclaim callbacks. It should only be K cleared on startup. SNIEB&: callbacks 0 ?+ . clone callbacks set)global 3 (alien( add)startup)hook K Used by compiler.codegen to rap callback bodies : do)callback 5 callback)quot ait)quot: 5 callback )) 6 )) 6 t %BN$'M$)BEX)IN)%"&&E"%Y); set)context)obFect init)namespaces init)catchstack current)callback 0 ,drop call 3 0 s ap call5 callback )) 6 drop 3 -bi ! inline K " utility for defining global variables that are recompiled in K every session $U;&': expiry)check obFect alien ! : recompute)value: 5 check )) : 6 dup 0 alienGG expired: 3 0 drop t 3 if ! ;#IV"$'G : initiali8e)alien 5 symbol quot )) 6 s ap dup get)global dup recompute)value: ! !

0 drop 0 call dup -1--R PalienG expiry)check boa 3 dip set)global 3 0 ,nip obFectGG 3 if ! inline K %opyright 5%6 ,==S< ,=11 Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors alien arrays byte)arrays init io io.encodings io.encodings.utf1Ln io.encodings.utfS io.streams.byte)array io.streams.memory kernel kernel.private namespaces sequences strings system system.private ! IN: alien.strings G'N'#I%Z alienGstring 1 5 c)ptr encoding )) stringQf 6 I: c)ptr alienGstring 0 Pmemory)streamG 3 0 PdecoderG 3 bi4 (>=( s ap stream)read)until drop ! I: obFect alienGstring 0 underlyingGG 3 dip alienGstring ! I: f alienGstring drop ! '##B#: invalid)c)string string ! : check)string 5 string )) 6 = over member)eq: 0 invalid)c)string 3 0 drop 3 if ! G'N'#I%Z stringGalien 1 5 string encoding )) byte)array 6 I: c)ptr stringGalien drop ! I: string stringGalien over check)string Pbyte) riterG 0 stream) rite 3 0 = s ap stream) rite1 3 0 streamGG Gbyte)array 3 tri ! I: tuple stringGalien drop underlyingGG ! ?BBY: native)string)encoding os 5 )) encoding 6 foldable I: unix native)string)encoding utfS ! I: indo s native)string)encoding utf1Ln ! : alienGnative)string 5 alien )) string 6 native)string)encoding alienGstring ! inline : native)stringGalien 5 string )) alien 6 native)string)encoding stringGalien ! inline : dll)path 5 dll )) string 6 pathGG alienGnative)string ! G'N'#I%: stringGsymbol 5 strQseq )) alien 6 I: string stringGsymbol utfS stringGalien ! I: sequence stringGsymbol 0 utfS stringGalien 3 map ! : 5symbolGstring6 5 alien )) str 6

utfS alienGstring ! G'N'#I%: symbolGstring 5 symbol5s6 )) string5s6 6 I: byte)array symbolGstring 5symbolGstring6 ! I: array symbolGstring 0 5symbolGstring6 3 map ! 0 BEX)%;U special)obFect utfS alienGstring stringGcpu > cpu set)global BEX)BS special)obFect utfS alienGstring stringGos > os set)global BEX)VI)%BI;I&'# special)obFect utfS alienGstring > vm)compiler set)global 3 (alien.strings( add)startup)hook USING: alien.strings alien.c)types alien.data tools.test kernel libc io.encodings.utfS io.encodings.utf1L io.encodings.utf1Ln io.encodings.ascii alien io.encodings.string io.encodings.S)bit.latin1 ! IN: alien.strings.tests 0 (>u====ff( 3 0 (>u====ff( latin1 stringGalien latin1 alienGstring 3 unit)test 0 (hello orld( 3 0 (hello orld( latin1 stringGalien latin1 alienGstring 3 unit)test 0 (hello>u==abcd orld( 3 0 (hello>u==abcd orld( utf1Lle stringGalien utf1Lle alienGstring 3 unit)test 0 t 3 0 f expired: 3 unit)test 0 (hello orld( 3 0 (hello orld( ascii malloc)string dup ascii alienGstring s ap free 3 unit)test 0 (hello orld( 3 0 (hello orld( utf1Ln malloc)string dup utf1Ln alienGstring s ap free 3 unit)test 0 f 3 0 f utfS alienGstring 3 unit)test 0 (hello( 3 0 (hello( utf1L encode utf1L decode 3 unit)test 0 (hello( 3 0 (hello( utf1L stringGalien utf1L alienGstring 3 unit)test USING: help.markup help.syntax strings byte)arrays alien libc debugger io.encodings.string sequences ! IN: alien.strings ?'&;: stringGalien + *values + (string( string . + (encoding( (an encoding descriptor( . + (byte)array( byte)array . . + *description ('ncodes a string together ith a trailing null code point using the given encoding< and stores the resulting bytes in a freshly)allocated byte array.( . + *errors ($hro s an error if the string contains null characters< or characters not representable in the given encoding.( . ! ?'&;: alienGstring + *values + (c)ptr( c)ptr . + (encoding( (an encoding descriptor( . + (stringQf( (a string or ( + *link f . . . + *description (#eads a null)terminated % string from the specified address ith

the given encoding.( . ! ?'&;: stringGsymbol + *values + (strQseq( + *or string sequence . . + (alien( alien . . + *description (%onverts the string to a format hich is a valid symbol name for the @actor VI7s compiled code linker. Ey performing this conversion ahead of time< the image loader can run ithout allocating memory.( *nl (Bn all platforms< symbols are "S%II strings.( . ! "EBU$: (c)strings( USING: accessors alien alien.accessors alien.syntax byte)arrays arrays kernel kernel.private namespaces tools.test sequences libc math system prettyprint layouts alien.libraries sets ! @#BI: namespaces HG set ! IN: alien.tests 0 t 3 0 )1 PalienG alien)address = G 3 unit)test 0 0 0 0 0 t f f f f 3 3 3 3 3 0 0 0 0 0 = PalienG = PalienG H 3 unit)test = PalienG 1=,/ PalienG H 3 unit)test (hello( 1=,/ PalienG H 3 unit)test = PalienG 3 unit)test = f Pdisplaced)alienG 3 unit)test

K $esting the various bignum accessor 1= Pbyte)arrayG (dump( set 0 (dump( get alien)address 3 must)fail 0 1,- 3 0 1,- (dump( get = set)alien)signed)1 (dump( get = alien)signed)1 3 unit)test 0 1,-/A 3 0 1,-/A (dump( get = set)alien)signed), (dump( get = alien)signed), 3 unit)test 0 1,-/ALRS 3 0 1,-/ALRS (dump( get = set)alien)signed)/ (dump( get = alien)signed)/ 3 unit)test 0 1,-/ALRSU=1,-/ALR 3 0 1,-/ALRSU=1,-/ALR (dump( get = set)alien)signed)S (dump( get = alien)signed)S 3 unit)test 0 )1 3 0 )1 (dump( get = set)alien)signed)S (dump( get = alien)signed)S 3 unit)test cell S H 0 0 =x1,-/1,-/1,-/ 3 0 S Pbyte)arrayG =x1,-/1,-/1,-/ over = set)alien)signed)S = alien)signed)S 3 unit)test

0 =x1,-/1,-/1,-/ 3 0 S Pbyte)arrayG =x1,-/1,-/1,-/ over = set)alien)signed)cell = alien)signed)cell 3 unit)test hen

0 ("&I'N: 1,-/( 3 0 =x1,-/ PalienG unparse 3 unit)test 0 3 0 = E+ 1 , - . Pdisplaced)alienG drop 3 unit)test 0 = E+ 1 , - . Pdisplaced)alienG alien)address 3 must)fail 0 1 1 Pdisplaced)alienG 3 must)fail 0 f 3 0 1 E+ 1 , - . Pdisplaced)alienG pinned)c)ptr: 3 unit)test 0 f 3 0 , E+ 1 , - . Pdisplaced)alienG 1 s ap Pdisplaced)alienG pinned)c)ptr: 3 unit)test 0 t 3 0 = E+ 1 , - . Pdisplaced)alienG 1 s ap Pdisplaced)alienG underlyingGG byte)array: 3 unit)test 0 (5 displaced alien 6( 3 0 1 E+ 1 , - . Pdisplaced)alienG unparse 3 unit)test SNIEB&: initiali8e)test f initiali8e)test set)global 0 -1--R 3 0 initiali8e)test 0 -1--R 3 initiali8e)alien 3 unit)test 0 -1--R 3 0 initiali8e)test 0 LU 3 initiali8e)alien 3 unit)test 0 3 0 initiali8e)test get E"C)"&I'N GGalien drop 3 unit)test 0 RARA 3 0 initiali8e)test 0 RARA 3 initiali8e)alien 3 unit)test 0 + E"C)"&I'N . 3 0 + E"C)"&I'N E"C)"&I'N E"C)"&I'N . members 3 unit)test USING: alien.accessors alien.c)types alien.libraries alien.syntax arrays byte)arrays compiler cpu.xSL debugger definitions eval help.markup help.syntax io io.backend kernel libc math parser quotations sequences system ! IN: alien ?'&;: cdecl + *description ($his symbol is passed as the ( + *snippet (abi( . ( argument to ( + *link alien)indirect . (< ( + *link alien)callback . (< ( + *link alien)assembly . (< and ( + *link add)library . ( to indicate that the standard % calling convention should be used< here the caller cleans up the stack frame after calling the function. $his symbol only has meaning on -,)bit xSL platforms.( . ! ?'&;: stdcall + *description ($his symbol is passed as the ( + *snippet (abi( . ( argument to ( + *link alien)indirect . (< ( + *link alien)callback . (< ( + *link alien)assembly . (< and ( + *link add)library . ( to indicate that the Jindo s ";I calling convention should be used< here the called function cleans up its o n stack frame before returning to the caller. $his symbol only has meaning on -,)bit xSL platforms.( . ! ?'&;: fastcall + * arning (In the current implementation this "EI only orks for functions that

take only integer and pointer arguments.( . + *description ($his symbol is passed as the ( + *snippet (abi( . ( argument to ( + *link alien)indirect . (< ( + *link alien)callback . (< ( + *link alien)assembly . (< and ( + *link add)library . ( to indicate that the >(fast call>( calling convention should be used< here the first t o integer or pointer arguments are passed in registers and the function cleans up its o n stack frame before returning to the caller. $his symbol only has meaning on -,)bit xSL platforms.( . ! ?'&;: thiscall + *description ($his symbol is passed as the ( + *snippet (abi( . ( argument to ( + *link alien)indirect . (< ( + *link alien)callback . (< ( + *link alien)assembly . (< and ( + *link add)library . ( to indicate that Iicrosoft Visual %22 calling convention should be used< here the first argument 5 hich must be a >(this>( pointer6 is passed in a register and the function cleans up its o n stack frame before returning to the caller. $his symbol only has meaning on -,)bit xSL platforms.( . ! + cdecl stdcall fastcall thiscall . related) ords ?'&;: Gc)ptr + *values + (obF( obFect . + (c)ptr( c)ptr . . + *contract (Butputs a pointer to the binary data of this obFect.( . ! ?'&;: byte)length + *values + (obF( obFect . + (n( (a non)negative integer( . . + *contract (Butputs the number of bytes of binary data that ill be output by ( + *link Gc)ptr . (.( . ! ?'&;: element)si8e + *values + (seq( sequence . + (n( (a non)negative integer( . . + *contract (Butputs the number of bytes used for each element of the sequence.( . + *notes (If a sequence class implements ( + *link element)si8e . ( and ( + *link Gc)ptr . (< then instances of this sequence< as ell as slices of this sequence< can be used as binary obFects.( . ! + Gc)ptr element)si8e byte)length . related) ords ?'&;: alien + *class)description ($he class of alien pointers. See ( + *link (syntax)aliens( . ( for syntax and ( + *link (c)data( . ( for general information.( . ! ?'&;: dll + *class)description ($he class of native library handles. See ( + *link (syntax)aliens( . ( for syntax and ( + *link (dll.private( . ( for general information.( . ! ?'&;: dll)valid: + *values + (dll( dll . + (:( (a boolean( . . + *description (#eturns true if the library exists and is loaded.( . ! ?'&;: expired: + *values + (c)ptr( c)ptr . + (:( (a boolean( . . + *description ($ests if the alien is a relic from an earlier session. " byte array is never considered to have expired< hereas passing ( + *link f . ( al ays yields true.( . ! ?'&;: Pbad)alienG + *values + (alien( c)ptr . . + *description (%onstructs an invalid alien pointer that has expired.( . !

?'&;: Pdisplaced)alienG + *values + (displacement( (an integer( . + (c)ptr( c)ptr . + (alien( (a ne alien( . . + *description (%reates a ne alien address obFect< rapping a ra memory address. $he alien points to a location in memory hich is offset by ( + *snippet (displacement( . ( from the address of ( + *snippet (c)ptr( . (.( . + *notes (;assing a value of ( + *link f . ( for ( + *snippet (c)ptr( . ( creates an alien ith an absolute address! this is ho ( + *link PalienG . ( is implemented.( *nl (;assing a 8ero absolute address does not construct a ne alien obFect< but instead makes the ord output ( + *link f . (.( . ! + PalienG Pdisplaced)alienG alien)address . related) ords ?'&;: alien)address + *values + (c)ptr( c)ptr . + (addr( (a non)negative integer( . . + *description (Butputs the address of an alien.( . + *notes ($aking the address of a ( + *link byte)array . ( is explicitly prohibited since byte arrays can be moved by the garbage collector bet een the time the address is taken< and hen it is accessed. If you need to pass pointers to % functions hich ill persist across alien calls< you must allocate unmanaged memory instead. See ( + *link (malloc( . (.( . ! ?'&;: PalienG + *values + (address( (a non)negative integer( . + (alien( (a ne alien address( . . + *description (%reates an alien obFect< rapping a ra memory address.( . + *notes ("lien obFects are invalidated bet een image saves and loads.( . ! ?'&;: c)ptr + *class)description (%lass of obFects consisting of aliens< byte arrays and ( + *link f . (. $hese obFects all can be used as values of ( + *link pointer . ( % types.( . ! ?'&;: alien)invoke)error + *error)description ($hro n if the ord calling ( + *link alien)invoke . ( as not compiled ith the optimi8ing compiler. $his may be a result of one of several failure conditions:( + *list + ($his can happen hen experimenting ith ( + *link alien)invoke . ( in this listener. $o fix the problem< place the ( + *link alien)invoke . ( call in a ord! ord definitions are automatically compiled ith the optimi8ing compiler.( . + ($he return type or parameter list references an unkno n % type.( . + ($he symbol or library could not be found.( . + (Bne of the four inputs to ( + *link alien)invoke . ( is not a literal value. $o call functions hich are not kno n at compile)time< use ( + *link alien)indirect . (.( . . . ! ?'&;: alien)invoke + *values + (args...( (8ero or more obFects passed to the % function( . + (return( (a % return type( . + (library( (a logical library name( . + (function( (a % function name( . + (parameters( (a sequence of % parameter types( . + (return...( (the return value of the function< if not ( + *link void . . . + *description (%alls a % library function ith the given name. Input parameters are taken from the data stack< and the return value is pushed on the data stack after the function returns. " return type of ( + *link void . ( indicates that no value is to be expected.( .

+ *notes (% type names are documented in ( + *link (c)types)specs( . (.( . + *errors ($hro s an ( + *link alien)invoke)error . ( if the ord calling ( + *link alien)invoke . ( as not compiled ith the optimi8ing compiler.( . ! ?'&;: alien)indirect)error + *error)description ($hro n if the ord calling ( + *link alien)indirect . ( as not compiled ith the optimi8ing compiler. $his may be a result of one of t o failure conditions:( + *list + ($his can happen hen experimenting ith ( + *link alien)indirect . ( in this listener. $o fix the problem< place the ( + *link alien)indirect . ( call in a ord! ord definitions are automatically compiled ith the optimi8ing compiler.( . + (Bne of the three inputs to ( + *link alien)indirect . ( is not a literal value.( . . . ! ?'&;: alien)indirect + *values + (args...( (8ero or more obFects passed to the % function( . + (funcptr( (a % function pointer( . + (return( (a % return type( . + (parameters( (a sequence of % parameter types( . + (abi( (one of ( + *link cdecl . ( or ( + *link stdcall . . + (return...( (the return value of the function< if not ( + *link void . . . + *description (Invokes a % function pointer passed on the data stack. Input parameters are taken from the data stack follo ing the function pointer< and the return value is pushed on the data stack after the function returns. " return type of ( + *link void . ( indicates that no value is to be expected.( . + *notes (% type names are documented in ( + *link (c)types)specs( . (.( . + *errors ($hro s an ( + *link alien)indirect)error . ( if the ord calling ( + *link alien)indirect . ( is not compiled.( . ! ?'&;: alien)callback)error + *error)description ($hro n if the ord calling ( + *link alien)callback . ( as not compiled ith the optimi8ing compiler. $his may be a result of one of t o failure conditions:( + *list + ($his can happen hen experimenting ith ( + *link alien)callback . ( in this listener. $o fix the problem< place the ( + *link alien)callback . ( call in a ord! ord definitions are automatically compiled ith the optimi8ing compiler.( . + (Bne of the four inputs to ( + *link alien)callback . ( is not a literal value.( . . . ! ?'&;: alien)callback + *values + (return( (a % return type( . + (parameters( (a sequence of % parameter types( . + (abi( (one of ( + *link cdecl . ( or ( + *link stdcall . . + (quot( quotation . + (alien( alien . . + *description (Cefines a callback from % to @actor hich accepts the given set of parameters from the % caller< pushes them on the data stack< calls the quotation< and passes a return value back to the % caller. " return type of ( + *snippet (void( . ( indicates that no value is to be returned.( *nl (Jhen a compiled reference to this ord is called< it pushes the callback7s alien address on the data stack. $his address can be passed to any % function expecting a % function pointer ith the correct signature. $he callback is actually generated hen the ord calling ( + *link alien)callback . ( is

compiled.( *nl (%allback quotations run ith freshly)allocated stacks. $his means the data stack contains the values passed by the % function< and nothing else. It also means that if the callback thro s an error hich is not caught< the @actor runtime ill halt. See ( + *link (errors( . ( for error handling options.( . + *notes (% type names are documented in ( + *link (c)types)specs( . (.( . + *examples (" simple example< sho ing a % function hich returns the difference of t o given integers:( + *code (: difference)callback 5 )) alien 6( ( int + int int . cdecl 0 ) 3 alien)callback !( . . + *errors ($hro s an ( + *link alien)callback)error . ( if the ord calling ( + *link alien)callback . ( is not compiled.( . ! ?'&;: alien)assembly)error + *error)description ($hro n if the ord calling ( + *link alien)assembly . ( as not compiled ith the optimi8ing compiler. $his may be a result of one of t o failure conditions:( + *list + ($his can happen hen experimenting ith ( + *link alien)assembly . ( in this listener. $o fix the problem< place the ( + *link alien)assembly . ( call in a ord! ord definitions are automatically compiled ith the optimi8ing compiler.( . + (Bne of the four inputs to ( + *link alien)assembly . ( is not a literal value.( . . . ! ?'&;: alien)assembly + *values + (args...( (8ero or more obFects passed to the % function( . + (return( (a % return type( . + (parameters( (a sequence of % parameter types( . + (abi( (one of ( + *link cdecl . ( or ( + *link stdcall . . + (quot( quotation . + (return...( (the return value of the function< if not ( + *link void . . . + *description (Invokes arbitrary machine code< generated at compile)time by the quotation. Input parameters are taken from the data stack< and the return value is pushed on the data stack after the function returns. " return type of ( + *link void . ( indicates that no value is to be expected.( *nl ($he quotation passed to this ord must preserve the ( + *link ds)reg . ( and ( + *link rs)reg . ( registers. Note that this is not a ( + *snippet (call( . ( in the assembly sense< so there is no return address on the stack.( *nl (It7s important to mind the "EI. @or instance< on xSL.-,< parameters are passed on the stack in ( + *snippet ('S;( . (< hile on xSL.L/ arguments are passed in ( + *snippet (#CI( . (< ( + *snippet (#SI( . (< ( + *snippet (#CM( . (< and ( + *snippet (#%M( . (< and then on the stack. Bn Jindo s L/< integers and pointers are passed in ( + *snippet (#%M( . (< ( + *snippet (#CM( . (< ( + *snippet (#S( . (< and ( + *snippet (#U( . (.( *nl ($here are @actor ords for the input parameters< such as ( + *snippet (param)reg)=( . ( and ( + *snippet (param)reg)1( . (.( *nl (@or output parameters< use ( + *link return)reg . (.( *nl .

+ *notes (% type names are documented in ( + *link (c)types)specs( . (.( . + *errors ($hro s an ( + *link alien)assembly)error . ( if the ord calling ( + *link alien)assembly . ( is not compiled.( . ! + alien)invoke alien)indirect alien)assembly alien)callback . related) ords "#$I%&': (alien)expiry( ("lien expiry( (Jhen an image is loaded< any alien obFects hich persisted from the previous session are marked as having expired. $his is because the % pointers they contain are almost certainly no longer valid.( *nl (@or this reason< the ( + *link ;BS$;BN': "&I'N: . ( ord should not be used in source files< since loading the source file then saving the image ill result in the literal becoming expired. Use ( + *link PalienG . ( instead< and ensure the ord calling ( + *link PalienG . ( is not declared ( + *link ;BS$;BN': flushable . (.( + *subsections expired: . ! "#$I%&': (aliens( ("lien addresses( (Instances of the ( + *link alien . ( class represent pointers to % data outside the @actor heap:( + *subsections PalienG Pdisplaced)alienG alien)address . ("ny here that a ( + *link alien . ( instance is accepted< the ( + *link f . ( singleton may be passed in to denote a null pointer.( *nl (Usually alien obFects do not have to created and dereferenced directly! instead declaring % function parameters and return values as having a ( + *link pointer . ( type such as ( + *snippet (void4( . ( takes care of the details.( + *subsections (syntax)aliens( (alien)expiry( . (Jhen higher)level abstractions on7t do:( + *subsections (reading) riting)memory( . + *see)also (c)data( (c)types)specs( . ! "#$I%&': (reading) riting)memory( (#eading and riting memory directly( (Numerical values can be read from memory addresses and converted to @actor obFects using the various typed memory accessor ords:( + *subsections alien)signed)1 alien)unsigned)1 alien)signed), alien)unsigned), alien)signed)/ alien)unsigned)/ alien)signed)cell alien)unsigned)cell alien)signed)S alien)unsigned)S alien)float alien)double . (@actor numbers can also be converted to % values and stored to memory:( + *subsections set)alien)signed)1 set)alien)unsigned)1 set)alien)signed),

set)alien)unsigned), set)alien)signed)/ set)alien)unsigned)/ set)alien)signed)cell set)alien)unsigned)cell set)alien)signed)S set)alien)unsigned)S set)alien)float set)alien)double . ! "#$I%&': (alien)invoke( (%alling % from @actor( ($he easiest ay to call into a % library is to define bindings using a pair of parsing ords:( + *subsections ;BS$;BN': &IE#"#N: ;BS$;BN': @UN%$IBN: ;BS$;BN': @UN%$IBN)"&I"S: . ($he above parsing ords create ord definitions hich call a lo er)level ord! you can use it directly< too:( + *subsections alien)invoke . (Sometimes it is necessary to invoke a % function pointer< rather than a named % function:( + *subsections alien)indirect . ($here are some details concerning the conversion of @actor obFects to % values< and vice versa. See ( + *link (c)data( . (.( ! "#$I%&': (alien)callback( (%alling @actor from %( (%allbacks can be defined and passed to % code as function pointers! the % code can then invoke the callback and run @actor code:( + *subsections alien)callback ;BS$;BN': %"&&E"%Y: . ($here are some caveats concerning the conversion of @actor obFects to % values< and vice versa. See ( + *link (c)data( . (.( + *see)also (byte)arrays)gc( . ! "#$I%&': (alien)globals( ("ccessing % global variables( ($he ( + *vocab)link (alien.syntax( . ( vocabulary defines t o parsing ords for accessing the value of a global variable< and get the address of a global variable< respectively.( + *subsections ;BS$;BN': %)G&BE"&: ;BS$;BN': `: . ! "#$I%&': (alien)assembly( (%alling arbitrary assembly code( (It is possible to rite a ord hose body consists of arbitrary assembly code. $he assembly receives parameters and returns values as per the platform7s "EI! marshalling and unmarshalling @actor values is taken care of by the % library interface< as ith ( + *link alien)invoke . (.( *nl ("ssembler opcodes are defined in %;U)specific vocabularies:( + *list + *vocab)link (cpu.arm.assembler( . + *vocab)link (cpu.ppc.assembler( . + *vocab)link (cpu.xSL.assembler( . . ($he combinator for generating arbitrary assembly by calling a quotation at compile time:(

+ *subsection alien)assembly . ! "#$I%&': (dll.private( (C&& handles( (C&& handles are a built)in class of obFects hich represent loaded native libraries. C&& handles are instances of the ( + *link dll . ( class< and have a literal syntax used for debugging printouts! see ( + *link (syntax)aliens( . (.( *nl (Usually one never has to deal ith C&& handles directly! the % library interface creates them as required. ?o ever if direct access to these operating system facilities is required< the follo ing primitives can be used:( + *subsections dlopen dlsym dlclose dll)valid: . ! "#$I%&': (embedding)api( (@actor embedding ";I( ($he @actor embedding ";I is defined in ( + *snippet (vmQmaster.h( . (.( *nl ($he ( + *snippet (@[%?"#( . ( type is an alias for the character type used for path names by the operating system! ( + *snippet (char( . ( on Unix and ( + *snippet ( char[t( . ( on Jindo s.( *nl (Including this header file into a % compilation unit ill declare the follo ing functions:( + *table + + + *code (void init[factor[from[args5( ( @[%?"# 4image< int argc< @[%?"# 44argv< bool embedded( (6( . (Initiali8es @actor.( *nl (If ( + *snippet (image( . ( is ( + *snippet (NU&&( . (< @actor ill load an image file hose name is obtained by suffixing the executable name ith ( + *snippet (.image( . (.( *nl ($he ( + *snippet (argc( . ( and ( + *snippet (argv( . ( parameters are interpreted Fust like normal command line arguments hen running @actor stand)alone! see ( + *link (command)line( . (.( *nl ($he ( + *snippet (embedded( . ( flag ensures that this function returns as soon as @actor has been initiali8ed. Bther ise< @actor ill start up normally.( . . + + + *code (char 4factor[eval[string5char 4string6( . ('valuates a piece of code in the embedded @actor instance by passing the string to ( + *link evalGstring . ( and returning the result. $he result must be explicitly freed by a call to ( + *snippet (factor[eval[free( . (.( . . + + + *code (void factor[eval[free5char 4result6( . (@rees a string returned by ( + *snippet (factor[eval[string56( . (.( . . + + + *code (void factor[yield5void6( . (Gives all @actor threads a chance to run.( . . + + + *code (void factor[sleep5long us6( . (Gives all @actor threads a chance to run for ( + *snippet (us( . (

microseconds.( . . . ! "#$I%&': (embedding)restrictions( ('mbedding ";I restrictions( ($he @actor VI is not thread safe< and does not support multiple instances. $here must only be one @actor instance per process< and this instance must be consistently accessed from the same thread for its entire lifetime. Bnce initiali8ed< a @actor instance cannot be destroyed other than by exiting the process.( ! "#$I%&': (embedding)factor( (Jhat embedding looks like from @actor( (@actor code ill run inside an embedded instance in the same ay it ould run in a stand)alone instance.( *nl (Bne exception is that the global ( + *link input)stream . ( and ( + *link output)stream . ( streams are not bound by default< to avoid conflicting ith any IQB the host process might perform. $he ( + *link init)stdio . ( ords must be called explicitly to initiali8e terminal streams.( *nl ($here is a ord hich can detect hen @actor is embedded:( + *subsections embedded: . (No special support is provided for calling out from @actor into the o ner process. $he % library interface orks fine for this task ) see ( + *link (alien( . (.( ! "#$I%&': (embedding( ('mbedding @actor into % applications( ($he @actor ( + *snippet (Iakefile( . ( builds the @actor VI both as an executable and a library. $he library can be used by other applications. @ile names for the library on various operating systems:( + *table + (BS( (&ibrary name( (Shared:( . + (Jindo s M;QVista( + *snippet (factor.dll( . (Nes( . + (Iac BS M( + *snippet (libfactor.dylib( . (Nes( . + (Bther Unix( + *snippet (libfactor.a( . (No( . . ("n image file must be supplied! a minimal image can be built< ho ever the compiler must be included for the embedding ";I to ork 5see ( + *link (bootstrap)cli)args( . (6.( + *subsections (embedding)api( (embedding)factor( (embedding)restrictions( . ! "#$I%&': (alien( (% library interface( (@actor can directly call % functions in native libraries. It is also possible to compile callbacks hich run @actor code< and pass them to native libraries as function pointers.( *nl ($he % library interface is entirely self)contained! there is no % code hich one must rite in order to rap a library.( *nl (% library interface ords are found in the ( + *vocab)link (alien( . ( vocabulary and its subvocabularies.( + * arning (% does not perform runtime type checking< automatic memory management or array bounds checks. Incorrect usage of % library functions can lead to crashes< data corruption< and security exploits.( . + *subsections (loading)libs( (alien)invoke( (alien)callback(

. !

(c)data( (classes.struct( (alien)globals( (alien)assembly( (dll.private( (embedding(

"EBU$: (alien( K %opyright 5%6 ,==R< ,=1= Caniel 'hrenberg< Slava ;estov K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays kernel math sequences sequences.private vectors ! IN: assocs IIMIN: assoc G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: at4 5 key assoc )) valueQf : 6 value)at4 5 value assoc )) keyQf : 6 set)at 5 value key assoc )) 6 ne )assoc 5 capacity exemplar )) ne assoc 6 delete)at 5 key assoc )) 6 clear)assoc 5 assoc )) 6 assoc)si8e 5 assoc )) n 6 assoc)like 5 assoc exemplar )) ne assoc 6 assoc)clone)like 5 assoc exemplar )) ne assoc 6 Galist 5 assoc )) ne assoc 6 keys 5 assoc )) keys 6 values 5 assoc )) values 6

I: assoc assoc)like drop ! inline : :at 5 key assoc )) valueQkey : 6 ,dup at4 0 ,nip t 3 0 ,drop f 3 if ! inline : maybe)set)at 5 value key assoc )) changed: 6 -dup at4 0 H 0 -drop f 3 0 set)at t 3 if 3 0 ,drop set)at t 3 if ! P;#IV"$' : 5assoc)each6 5 assoc quot )) seq quot7 6 0 Galist 3 dip 0 first, 3 prepose ! inline : 5assoc)stack6 5 key i seq )) value 6 over = P 0 -drop f 3 0 -dup nth)unsafe at4 0 0 -drop 3 dip 3 0 drop 0 1 ) 3 dip 5assoc)stack6 3 if 3 if ! inline recursive : search)alist 5 key alist )) pairQf iQf 6 0 first H 3 ith find s ap ! inline : substituter 5 assoc )) quot 6 0 :at drop 3 curry ! inline : ith)assoc 5 assoc quot: 5 ..a value key assoc )) ..b 6 )) quot: 5 ..a key value )) ..b 6 6 curry 0 s ap 3 prepose ! inline ;#IV"$'G

: assoc)find 5 ... assoc quot: 5 ... key value )) ... : 6 )) ... key value : 6 5assoc)each6 find s ap 0 first,)unsafe t 3 0 drop f f f 3 if ! inline : key: 5 key assoc )) : 6 at4 nip ! inline : assoc)each 5 ... assoc quot: 5 ... key value )) ... 6 )) ... 6 5assoc)each6 each ! inline : assocGmap 5 ... assoc quot: 5 ... key value )) ... elt 6 exemplar )) ... seq 6 0 5assoc)each6 3 dip map)as ! inline : assoc)map)as 5 ... assoc quot: 5 ... key value )) ... ne key ne value 6 exemplar )) ... ne assoc 6 0 0 ,array 3 compose + . assocGmap 3 dip assoc)like ! inline : assoc)map 5 ... assoc quot: 5 ... key value )) ... ne key ne value 6 )) ... ne assoc 6 over assoc)map)as ! inline : assoc)filter)as 5 ... assoc quot: 5 ... key value )) ... : 6 exemplar )) ... subassoc 6 0 5assoc)each6 filter 3 dip assoc)like ! inline : assoc)filter 5 ... assoc quot: 5 ... key value )) ... : 6 )) ... subassoc 6 over assoc)filter)as ! inline : assoc)filterK 5 ... assoc quot: 5 ... key value )) ... : 6 )) ... assoc 6 0 over 0 0 0 drop 3 ,bi 3 dip 0 delete)at 3 ,curry unless 3 ,curry assoc)each 3 0 drop 3 ,bi ! inline : sift)keys 5 assoc )) assoc7 6 0 drop 3 assoc)filter ! inline : sift)values 5 assoc )) assoc7 6 0 nip 3 assoc)filter ! inline : assoc)partition 5 ... assoc quot: 5 ... key value )) ... : 6 )) ... true)assoc false)assoc 6 0 5assoc)each6 partition 3 0 drop 3 ,bi 0 assoc)like 3 curry bi9 ! inline : assoc)any: 5 ... assoc quot: 5 ... key value )) ... : 6 )) ... : 6 assoc)find ,nip ! inline : assoc)all: 5 ... assoc quot: 5 ... key value )) ... : 6 )) ... : 6 0 not 3 compose assoc)any: not ! inline : at 5 key assoc )) valueQf 6 at4 drop ! inline : :of 5 assoc key )) valueQkey : 6 s ap :at ! inline : of 5 assoc key )) valueQf 6 s ap at ! inline I: assoc assoc)clone)like 5 assoc exemplar )) ne assoc 6 0 dup assoc)si8e 3 dip ne )assoc 0 0 set)at 3 ith)assoc assoc)each 3 keep ! inline

I: assoc keys 0 drop 3 + . assocGmap ! I: assoc values 0 nip 3 + . assocGmap ! : delete)at4 5 key assoc )) old : 6 0 at4 3 ,keep delete)at ! : rename)at 5 ne key key assoc )) 6 0 delete)at4 3 keep 0 set)at 3 ith)assoc 0 ,drop 3 if ! : assoc)empty: 5 assoc )) : 6 assoc)si8e = H ! inline : assoc)stack 5 key seq )) value 6 0 length 1 ) 3 keep 5assoc)stack6 ! flushable : assoc)subset: 5 assoc1 assoc, )) : 6 0 at4 0 H 3 0 ,drop f 3 if 3 ith)assoc assoc)all: ! : assocH 5 assoc1 assoc, )) : 6 ,dup 0 assoc)si8e 3 bi9 eq: 0 assoc)subset: 3 0 ,drop f 3 if ! : assoc)hashcode 5 n assoc )) code 6 Galist hashcode4 ! : assoc)intersect 5 assoc1 assoc, )) intersection 6 s ap 0 nip key: 3 curry assoc)filter ! : assoc)unionK 5 assoc1 assoc, )) assoc1 6 over 0 set)at 3 ith)assoc assoc)each ! : assoc)union 5 assoc1 assoc, )) union 6 0 0 0 assoc)si8e 3 bi9 2 3 0 drop 3 ,bi ne )assoc 3 ,keep 0 assoc)unionK 3 bi9 ! : assoc)combine 5 seq )) union 6 ?+ . clone 0 assoc)unionK 3 reduce ! : assoc)refine 5 seq )) assoc 6 0 f 3 0 0 3 0 assoc)intersect 3 map)reduce 3 if)empty ! : assoc)differ 5 key )) quot 6 0 nip key: not 3 curry ! inline : assoc)diff 5 assoc1 assoc, )) diff 6 assoc)differ assoc)filter ! : assoc)diffK 5 assoc1 assoc, )) assoc1 6 assoc)differ assoc)filterK ! : substitute 5 seq assoc )) ne seq 6 substituter map ! : cache 5 ... key assoc quot: 5 ... key )) ... value 6 )) ... value 6 0 0 at4 3 ,keep 3 dip 0 0 nip call dup 3 0 drop 3 -bi set)at 3 -curry 0 drop 3 prepose unless ! inline : ,cache 5 ... key1 key, assoc quot: 5 ... key1 key, )) ... value 6 )) ... value 6

0 ,array 3 ,dip 0 first,)unsafe 3 prepose cache ! inline : change)at 5 ..a key assoc quot: 5 ..a value )) ..b ne value 6 )) ..b 6 0 0 at 3 dip call 3 0 drop 3 -bi set)at ! inline : at2 5 n key assoc )) 6 0 = or 2 3 change)at ! inline : inc)at 5 key assoc )) 6 0 1 3 ,dip at2 ! inline : mapGassoc 5 ... seq quot: 5 ... elt )) ... key value 6 exemplar )) ... assoc 6 dup sequence: 0 0 0 ,array 3 compose 3 dip map)as 3 0 0 over assoc)si8e 3 dip ne )assoc 0 0 s apd set)at 3 curry compose each 3 keep 3 if ! inline : extract)keys 5 seq assoc )) subassoc 6 0 0 dupd at 3 curry 3 keep mapGassoc ! I: assoc value)at4 s ap 0 H nip 3 curry assoc)find nip ! : value)at 5 value assoc )) keyQf 6 value)at4 drop ! : value: 5 value assoc )) : 6 value)at4 nip ! : push)at 5 value key assoc )) 6 0 :push 3 change)at ! : 8ip 5 keys values )) alist 6 0 ,array 3 + . ,map)as ! inline : un8ip 5 assoc )) keys values 6 dup assoc)empty: 0 drop + . + . 3 0 Galist flip first, 3 if ! I: sequence at4 search)alist 0 second t 3 0 f 3 if ! I: sequence set)at ,dup search)alist 0 ,nip set)second 3 0 drop 0 s ap ,array 3 dip push 3 if ! I: sequence ne )assoc drop PvectorG ! inline I: sequence clear)assoc delete)all ! inline I: sequence delete)at 0 nip 3 0 search)alist nip 3 ,bi 0 s ap remove)nthK drop 3 0 drop 3 if4 ! I: sequence assoc)si8e length ! inline I: sequence assoc)clone)like 0 Galist 3 dip clone)like ! inline I: sequence assoc)like 0 Galist 3 dip like ! inline I: sequence Galist ! inline K Bverride sequence HG assoc instance for f

I: f at4 ,drop f f ! inline I: f assoc)si8e drop = ! inline I: f clear)assoc drop ! inline I: f assoc)like drop dup assoc)empty: 0 drop f 3 INS$"N%': sequence assoc $U;&': enum + seq read)only . ! %: PenumG enum I: enum at4 seqGG ,dup bounds)check: 0 nth)unsafe t 3 0 ,drop f f 3 if ! inline I: enum set)at seqGG set)nth ! inline I: enum delete)at seqGG remove)nthK drop ! inline I: enum Galist 5 enum )) alist 6 seqGG 0 length iota 3 keep 8ip ! inline I: enum keys seqGG length iota Garray ! inline I: enum values seqGG Garray ! inline I: enum assoc)si8e seqGG length ! inline I: enum clear)assoc seqGG delete)all ! inline INS$"N%': enum assoc I: enum length seqGG length ! inline I: enum nth)unsafe dupd seqGG nth)unsafe ,array ! inline INS$"N%': enum immutable)sequence USING: kernel math namespaces make tools.test vectors sequences sequences.private hashtables io prettyprint assocs continuations speciali8ed)arrays alien.c)types ! S;'%I"&IO'C)"##"N: double IN: assocs.tests 0 0 0 0 0 0 0 t f t t f f t 3 3 3 3 3 3 3 0 0 0 0 0 0 0 ?+ ?+ ?+ ?+ ?+ ?+ ?+ . + . + + + + dup assoc)subset: 3 unit)test 1 - . . ?+ . assoc)subset: 3 unit)test ?+ + 1 - . . assoc)subset: 3 unit)test 1 - . . ?+ + 1 - . . assoc)subset: 3 unit)test 1 - . . ?+ + 1 (hey( . . assoc)subset: 3 unit)test 1 f . . ?+ . assoc)subset: 3 unit)test 1 f . . ?+ + 1 f . . assoc)subset: 3 unit)test hen ! inline

K $est some combinators 0 + / 1/ -, . 3 0 0 ?+ + 1 , . + - / .

+ A L . . 0 4 , 2 < 3 assoc)each 3 + . make 3 unit)test 0 0 0 0 0 t t f t f 3 3 3 3 3 0 0 0 0 0 ?+ ?+ ?+ ?+ ?+ . + + + + 0 1 1 1 1 ,drop 1 . . , . . 1 . + , . + f 0 0 , , 3 H H , , assoc)all: 3 unit)test 3 assoc)all: 3 unit)test 3 assoc)all: 3 unit)test . . 0 H 3 assoc)all: 3 unit)test . . 0 H 3 assoc)all: 3 unit)test

0 ?+ . 3 0 ?+ + t f . + f t . . 0 ,drop f 3 assoc)filter 3 unit)test 0 ?+ . 3 0 ?+ + t f . + f t . . clone dup 0 ,drop f 3 assoc)filterK drop 3 unit)test 0 ?+ . 3 0 ?+ + t f . + f t . . clone 0 ,drop f 3 assoc)filterK 3 unit)test 0 ?+ + - / . + / A . + L R . . 3 0 ?+ + 1 , . + , - . + - / . + / A . + L R . . 0 drop - GH 3 assoc)filter 3 unit)test 0 ?+ + - / . + / A . + L R . . 3 0 ?+ + 1 , . + , - . + - / . + / A . + L R . . clone 0 drop - GH 3 assoc)filterK 3 unit)test 0 ?+ + - / . + / A . + L R . . 3 0 ?+ + 1 , . + , - . + - / . + / A . + L R . . clone dup 0 drop - GH 3 assoc)filterK drop 3 unit)test 0 ,1 3 0 = ?+ + 1 , . + - / . + A L . . 0 2 2 3 assoc)each 3 unit)test ?+ . clone (cache)test( set 0 0 0 0 0 3 0 ?+ + (factor( (rocks( . + - / . . ?+ + (factor( (rocks( . + (dup( (sq( . + - / . . ?+ + (factor( (rocks( . + 1 , . + , - . + - / . . assoc)intersect 3 unit)test 0 3 0 ?+ + 1 , . + , - . + L A . . ?+ + , / . + L A . . ?+ + 1 , . + , - . . assoc)union 3 unit)test / A / A 3 3 3 3 0 0 0 0 1 , 1 , (cache)test( (cache)test( (cache)test( (cache)test( get get get get 0 0 0 0 2 2 2 2 3 3 3 3 cache cache cache cache 3 3 3 3 unit)test unit)test unit)test unit)test

0 3 0

?+ + 1 , . + , - . + L A . .

?+ + , / . + L A . . clone dup ?+ + 1 , . + , - . . assoc)unionK drop 3 unit)test 0 3 0 ?+ + 1 , . + , - . + L A . . ?+ + , / . + L A . . clone ?+ + 1 , . + , - . . assoc)unionK 3 unit)test 0 ?+ + 1 , . + , - . . t 3 0 f ?+ + 1 , . + , - . . 0 assoc)union 3 ,keep s ap assoc)union dupd H 3 unit)test 0 3 0 ?+ + 1 f . .

?+ + 1 f . . ?+ + 1 f . . assoc)intersect 3 unit)test 0 3 0 ?+ + - / . .

?+ + 1 , . + - / . . ?+ + 1 - . . assoc)diff 3 unit)test 0 3 0 ?+ + - / . .

?+ + 1 , . + - / . . clone dup ?+ + 1 - . . assoc)diffK drop 3 unit)test 0 3 0 ?+ + - / . .

?+ + 1 , . + - / . . clone ?+ + 1 - . . assoc)diffK 3 unit)test 0 ?+ + (hi( , . + - / . . 3 0 (hi( 1 ?+ + 1 , . + - / . . clone 0 rename)at 3 keep 3 unit)test 0 ?+ + 1 , . + - / . . 3 0 (hi( A ?+ + 1 , . + - / . . clone 0 rename)at 3 keep 3 unit)test 0 3 0 ?+ + 1.= 1.= . + ,.= ,.= . .

double)array+ 1.= ,.= . 0 dup 3 ?+ . mapGassoc 3 unit)test 0 + - . 3 0 0 ?+ . clone , 0

,dup 0 < f 3 cache drop 3 times ,drop 3 + . make 3 unit)test 0 ?+ . 3 0 + (bangers( (mash( . + (fries( (onion rings( .

+ (bangers( (fries( . ?+ + (fish( (chips( . + (bangers( (mash( . + (fries( (onion rings( . + (nachos( (cheese( . . extract)keys 3 unit)test 0 ?+ + (b( 0 , 3 . + (d( 0 / 3 . . ?+ + (a( 0 1 3 . + (c( 0 - 3 . . 3 0 ?+ + (a( 0 1 3 . + (b( 0 , 3 . + (c( 0 - 3 . + (d( 0 / 3 . . 0 nip first even: 3 assoc)partition 3 unit)test 0 1 f 3 0 1 ?+ . :at 3 unit)test 0 , t 3 0 1 ?+ + 1 , . . :at 3 unit)test 0 f 3 0 1 , ?+ + , 1 . . maybe)set)at 3 unit)test 0 t 3 0 1 - ?+ + , 1 . . clone maybe)set)at 3 unit)test 0 t 3 0 - , ?+ + , 1 . . clone maybe)set)at 3 unit)test 0 ?+ + 1 , . + , - . . 3 0 + ?+ + 1 - . . ?+ + , - . . ?+ + 1 , . . . assoc)combine 3 unit)test 0 ?+ + 1 R . . 3 0 + ?+ + 1 , . + , / . + A L . . ?+ + 1 - . + , A . . ?+ + 1 R . + A L . . . assoc)refine 3 unit)test 0 0 0 0 + . 0 + + 1 f . . + + 1 f . + f , . . sift)keys f 1 , f 3 3 3 3 0 0 0 0 (a( (a( (b( (c( + + + + . assoc)stack 3 unit)test ?+ + (a( 1 . . ?+ + (b( , . . . assoc)stack 3 unit)test ?+ + (a( 1 . . ?+ + (b( , . . . assoc)stack 3 unit)test ?+ + (a( 1 . . ?+ + (b( , . . . assoc)stack 3 unit)test

3 unit)test + . 0 + + f , . . + + 1 f . + f , . . sift)values 3 unit)testK %opyright 5%6 ,==R< ,==U Caniel 'hrenberg< Slava ;estov< and Coug %oleman K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: help.markup help.syntax kernel sequences sequences.private namespaces math quotations assocs.private sets ! IN: assocs "#$I%&': (alists( ("ssociation lists( ("n ( + *emphasis (association list( . (< abbreviated ( + *emphasis (alist( . (< is an association represented as a sequence here all elements are keyQvalue pairs. $he ( + *link sequence . ( mixin is an instance of the ( + *link assoc . ( mixin< hence all sequences support the ( + *link (assocs)protocol( . ( in this ay.( *nl (Jhile not an association list< note that ( + *link f . ( also implements the associative mapping protocol in a trivial ay! it is an immutable assoc ith no entries.( *nl ("n alist is slo er to search than a hashtable for a large set of associations. $he main advantage of an association list is that the elements are ordered! also sometimes it is more convenient to construct an association list ith sequence ords than to construct a hashtable ith association ords. Iuch of the time< hashtables are more appropriate. See ( + *link (hashtables( . (.( *nl ($here is no special syntax for literal alists since they are Fust sequences! in practice< literals look like so:( + *code (+( ( + key1 value1 .( ( + key, value, .( (.( . ($o make an assoc into an alist:( + *subsections Galist . ! "#$I%&': (enums( ('numerations( ("n enumeration provides a vie of a sequence as an assoc mapping integer indices to elements:( + *subsections enum PenumG . (Inverting a permutation using enumerations:( + *example (IN: scratchpad( (: invert 5 perm )) perm7 6( ( PenumG sort)values keys !( (+ , = / 1 - . invert .( (+ 1 - = / , .( . ! ?'&;: enum + *class)description ("n associative structure hich raps a sequence and maps integers to the corresponding elements of the sequence.( *nl ('numerations are mutable! note that deleting a key calls ( + *link remove)nthK . (< hich results in all subsequent elements being shifted do n.( . ! ?'&;: PenumG + *values + (seq( sequence . + (enum( enum . . + *description (%reates a ne enumeration.( . ! "#$I%&': (assocs)protocol( ("ssociative mapping protocol( ("ll associative mappings must be instances of a mixin class:(

+ *subsections assoc assoc: . ("ll associative mappings must implement methods on the follo ing generic ords:( + *subsections at4 assoc)si8e Galist . (Iutable assocs should implement the follo ing additional ords:( + *subsections set)at delete)at clear)assoc . ($he follo ing three ords are optional:( + *subsections value)at4 ne )assoc assoc)like . ("ssocs should also implement methods on the ( + *link clone . (< ( + *link equal: . ( and ( + *link hashcode4 . ( generic ords. $ o utility ords ill help ith the implementation of the last t o:( + *subsections assocH assoc)hashcode . (@inally< assoc classes should define a ord for converting other types of assocs! conventionally< such ords are named ( + *snippet (G( + *emphasis (class( . . ( here ( + *snippet + *emphasis (class( . . ( is the class name. Such a ord can be implemented using a utility:( + *subsections assoc)clone)like . ! "#$I%&': (assocs)lookup( (&ookup and querying of assocs( (Utility operations built up from the ( + *link (assocs)protocol( . (:( + *subsections key: at :at of :of assoc)empty: keys values assoc)stack . + *see)also at4 assoc)si8e . ! "#$I%&': (assocs)values( ($ransposed assoc operations( (Iost assoc ords take a key and find the corresponding value. $he follo ing ords take a value and find the corresponding key:( + *subsections value)at value)at4 value: . (Jith most assoc implementations< these ords runs in linear time< proportional to the number of entries in the assoc. @or fast value lookups< use ( + *vocab)link (biassocs( . (.( !

"#$I%&': (assocs)sets( (Set)theoretic operations on assocs( (It is often useful to use the keys of an associative mapping as a set< exploiting the constant or logarithmic lookup time of most implementations 5( + *link (alists( . ( being a notable exception6.( *nl (Set)theoretic operations:( + *subsections assoc)subset: assoc)intersect assoc)union assoc)diff substitute extract)keys . ("dding elements to sets:( + *subsections conFoin conFoin)at . (Cestructive operations:( + *subsections assoc)unionK assoc)diffK . + *see)also key: assoc)any: assoc)all: (sets( . ! "#$I%&': (assocs)mutation( (Storing keys and values in assocs( (Utility operations built up from the ( + *link (assocs)protocol( . (:( + *subsections delete)at4 rename)at change)at at2 inc)at . + *see)also set)at delete)at clear)assoc push)at . ! "#$I%&': (assocs)conversions( ("ssociative mapping conversions( (%onverting to other assocs:( + *subsections assoc)clone)like . (%ombining a sequence of assocs into a single assoc:( + *subsections assoc)combine . (%reating an assoc from keyQvalue sequences:( + *subsections 8ip . (%reating keyQvalue sequences from an assoc:( + *subsections un8ip . ! "#$I%&': (assocs)combinators( ("ssociative mapping combinators( ($he follo ing combinators can be used on any associative mapping.( *nl ($he ( + *link assoc)find . ( combinator is part of the ( + *link (assocs)protocol( . ( and must be implemented once for each class of assoc. "ll other combinators are implemented in terms of this combinator.( *nl ($he standard functional programming idioms:( + *subsections assoc)each assoc)find assoc)map assoc)filter

. (#emoving empty keys or values:( + *subsections sift)keys sift)values . (Iapping bet een assocs and sequences:( + *subsections mapGassoc assocGmap assoc)map)as . (Cestructive combinators:( + *subsections assoc)filterK cache ,cache . ! "#$I%&': (assocs( ("ssociative mapping operations( ("n ( + *emphasis (associative mapping( . (< abbreviated ( + *emphasis (assoc( . (< is a collection of keyQvalue pairs hich provides efficient lookup and storage indexed by key.( *nl (Jords used for orking ith assocs are in the ( + *vocab)link (assocs( . ( vocabulary.( *nl ("ssociative mappings implement a protocol:( + *subsections (assocs)protocol( . (" large set of utility ords ork on any obFect hose class implements the associative mapping protocol.( + *subsections (assocs)lookup( (assocs)values( (assocs)mutation( (assocs)combinators( (assocs)sets( (assocs)conversions( . ! "EBU$: (assocs( ?'&;: assoc + *class)description (" mixin class hose instances are associative mappings. %ustom implementations of the assoc protocol should be declared as instances of this mixin for all assoc functionality to ork correctly:( + *code (INS$"N%': avl)tree assoc( . . ! ?'&;: at4 + *values + (key( (an obFect to look up in the assoc( . + (assoc( assoc . + (valueQf( (the value associated to the key< or ( + *link f . ( if the key is not present in the assoc( . + (:( (a ( + *link boolean . ( indicating if the key as present( . . + *contract (&ooks up the value associated ith a key. $he boolean flag can decide bet een the case of a missing value< and a value of ( + *link f . (.( . ! ?'&;: set)at

assoc)filter)as assoc)partition assoc)any: assoc)all:

+ *values + (value( (a value( . + (key( (a key to add( . + (assoc( assoc . . + *contract (Stores the keyQvalue pair into the assoc.( . + *side)effects (assoc( . ! ?'&;: ne )assoc + *values + (capacity( (a non)negative integer( . + (exemplar( assoc . + (ne assoc( assoc . . + *contract (%reates a ne assoc from an ( + *snippet (exemplar( . ( hich can hold ( + *snippet (capacity( . ( entries before gro ing.( . ! ?'&;: assoc)find + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... : 6( . . + (key( (the successful key< or f( . + (value( (the successful value< or f( . + (:( boolean . . + *description ("pplies a predicate quotation to each entry in the assoc. #eturns the key and value that the quotation succeeds on< or ( + *link f . ( for both if the quotation fails. It also returns a boolean describing hether there as anything found! this can be used to distinguish bet een a key and a value equal to ( + *link f . (< or nothing being found.( . ! ?'&;: clear)assoc + *values + (assoc( assoc . . + *contract (#emoves all entries from the assoc.( . + *side)effects (assoc( . ! ?'&;: delete)at + *values + (key( (a key( . + (assoc( assoc . . + *contract (#emoves an entry from the assoc.( . + *side)effects (assoc( . ! ?'&;: assoc)si8e + *values + (assoc( assoc . + (n( (a non)negative integer( . . + *contract (Butputs the number of entries stored in the assoc.( . ! ?'&;: assoc)like + *values + (assoc( assoc . + (exemplar( assoc . + (ne assoc( (a ne assoc( . . + *contract (%reates a ne assoc having the same entries as ( + *snippet (assoc( . ( and the same type as ( + *snippet (exemplar( . (.( . ! ?'&;: assoc)empty: + *values + (assoc( assoc . + (:( boolean . . + *description ($ests if the assoc contains no entries.( . ! ?'&;: key: + *values + (key( obFect . + (assoc( assoc . + (:( boolean . . + *description ($ests if an assoc contains a key.( . ! + at at4 key: :at of :of . related) ords ?'&;: at + *values + (key( obFect . + (assoc( assoc . + (valueQf( (the value associated to the key< or ( + *link f . ( if the key is not present in the assoc( . . + *description (&ooks up the value associated ith a key. $his ord makes no distinction bet een a missing value and a value set to ( + *link f . (! if the difference is important< use ( + *link at4 . (.( . ! ?'&;: :at + *values + (key( obFect . + (assoc( assoc . + (valueQkey( (the value associated to the key< or the key if the key is not present in the assoc( . + (:( (a ( + *link boolean . ( indicating if the key as present( . . + *description (&ooks up the value associated ith a key. If the key as not present< an error can be thro n ithout extra stack shuffling. $his ord handles

assocs that store ( + *link f . (.( . ! ?'&;: of + *values + (assoc( assoc . + (key( obFect . + (valueQf( (the value associated to the key< or ( + *link f . ( if the key is not present in the assoc( . . + *description (&ooks up the value associated ith a key. $his ord makes no distinction bet een a missing value and a value set to ( + *link f . (! if the difference is important< use ( + *link :of . (.( . ! ?'&;: :of + *values + (assoc( assoc . + (key( obFect . + (valueQkey( (the value associated to the key< or the key if the key is not present in the assoc( . + (:( (a ( + *link boolean . ( indicating if the key as present( . . + *description (&ooks up the value associated ith a key. If the key as not present< an error can be thro n ithout extra stack shuffling. $his ord handles assocs that store ( + *link f . (.( . ! ?'&;: assoc)each + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... 6( . . . + *description ("pplies a quotation to each entry in the assoc.( . + *examples + *example (USING: assocs kernel math prettyprint !( (?+ + >(bananas>( A . + >(apples>( /, . + >(pears>( 1R . .( (= s ap 0 nip 2 3 assoc)each .( (L/( . . ! ?'&;: assoc)map + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... ne key ne value 6( . . + (ne assoc( (a ne assoc( . . + *description ("pplies the quotation to each entry in the input assoc and collects the results in a ne assoc of the same type as the input.( . + *examples + *unchecked)example (: discount 5 prices n )) ne prices 6( ( 0 ) 3 curry assoc)map !( (?+ + >(bananas>( A . + >(apples>( /, . + >(pears>( 1R . .( (, discount .( (?+ + >(bananas>( - . + >(apples>( /= . + >(pears>( 1A . .( . . ! + assoc)map assoc)map)as . related) ords ?'&;: assoc)filter + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... : 6( . . + (subassoc( (a ne assoc( . . + *description (Butputs an assoc of the same type as ( + *snippet (assoc( . ( consisting of all entries for hich the predicate quotation yields true.( . ! ?'&;: assoc)filter)as + *values + (assoc( assoc . + (quot( + *quotation . + (exemplar( assoc . + (subassoc( (a ne assoc( + *description (Butputs an assoc of the same type consisting of all entries for hich the predicate (5 ... key value )) ... : 6( . . . as ( + *snippet (exemplar( . ( quotation yields true.( . !

?'&;: assoc)filterK + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... : 6( . . .

+ *description (#emoves all entries for true.( . + *side)effects (assoc( . !

hich the predicate quotation yields

+ assoc)filter assoc)filter)as assoc)filterK . related) ords ?'&;: assoc)partition + *values + (assoc( assoc . + (quot( quotation . + (true)assoc( assoc . + (false)assoc( assoc . . + *description (%alls a predicate quotation on each key of the input assoc. If the test yields true< the keyQvalue pair is added to ( + *snippet (true)assoc( . (! if false< it7s added to ( + *snippet (false)assoc( . (.( . ! ?'&;: assoc)any: + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... : 6( . . + (:( boolean . . + *description ($ests if the assoc contains an entry satisfying a predicate by applying the quotation to each entry in turn. Iteration stops if an entry is found for hich the quotation outputs a true value.( . ! ?'&;: assoc)all: + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... : 6( . . + (:( boolean . . + *description ($ests if all entries in the assoc satisfy a predicate by applying the quotation to each entry in turn. a predicate quotation to entry in the assoc. Iteration stops if an entry is found for hich the quotation outputs ( + *link f . (. If the assoc is empty< al ays outputs ( + *link t . (.( . ! ?'&;: assoc)refine + *values + (seq( sequence . + (assoc( assoc . . + *description (Butputs the intersection of all the assocs of the assocs sequence ( + *snippet (seq( . (< or ( + *link f . ( if ( + *snippet (seq( . ( is empty.( . ! ?'&;: assoc)subset: + *values + (assoc1( assoc . + (assoc,( assoc . + (:( boolean . . + *description ($ests if ( + *snippet (assoc,( . ( contains all keyQvalue pairs of ( + *snippet (assoc1( . (.( . ! ?'&;: sift)keys + *values + (assoc( assoc . + (assoc7( (a ne assoc( . . + *description (Butputs an assoc removing keys that are ( + *link f . (.( . ! ?'&;: sift)values + *values + (assoc( assoc . + (assoc7( (a ne assoc( . . + *description (Butputs an assoc removing values that are ( + *link f . (.( . ! ?'&;: assocH + *values + (assoc1( assoc . + (assoc,( assoc . + (:( boolean . . + *description ($ests if t o assocs contain the same entries. Unlike ( + *link H . (< the t o assocs may be of different types.( . + *notes ("ssoc implementations should define a method for the ( + *link equal: . ( generic ord hich calls this ord after checking that both inputs have the same type.( . ! ?'&;: assoc)hashcode + *values + (n( (a non)negative integer( . + (assoc( assoc . + (code( integer . . + *description (%omputes a hashcode for an assoc< such that equal assocs have the same hashcode.( .

ill

+ *notes (%ustom assoc implementations should use this ord to implement a method for the ( + *link hashcode4 . ( generic ord.( . ! ?'&;: assoc)stack + *values + (key( (a key( . + (seq( (a sequence of assocs( . + (value( (a value or ( + *link f . . . + *description (Searches for the key in successive elements of the sequence< starting from the end. If an assoc containing the key is found< the associated value is output. If no assoc contains the key< outputs ( + *link f . (.( . + *notes ($his ord is used to implement abstractions such as nested scopes! if the sequence is a stack represented by a vector< then the most recently pushed assoc )) the innermost scope )) ill be searched first.( . ! ?'&;: value)at4 + *values + (value( obFect . + (assoc( assoc . + (keyQf( (the key associated to the value< or ( + *link f . . + (:( boolean . . + *description (&ooks up the key associated ith a value. $he boolean flag can decide bet een the case of a missing key< and a key of ( + *link f . (.( . ! ?'&;: value)at + *values + (value( obFect . + (assoc( assoc . + (keyQf( (the key associated to the value< or ( + *link f . . . + *description (&ooks up the key associated ith a value. No distinction is made bet een a missing key and a key set to ( + *link f . (.( . ! ?'&;: value: + *values + (value( obFect . + (assoc( assoc . + (:( boolean . . + *description ($ests if an assoc contains at least one key ith the given value.( . ! ?'&;: delete)at4 + *values + (key( (a key( . + (assoc( assoc . + (old( (the previous value or ( + *link f . . + (:( boolean . . + *description (#emoves an entry from the assoc and outputs the previous value together ith a boolean indicating hether it as present.( . + *side)effects (assoc( . ! ?'&;: rename)at + *values + (ne key( obFect . + (key( obFect . + (assoc( assoc . . + *description (#emoves the values associated to ( + *snippet (key( . ( and re)adds it as ( + *snippet (ne key( . (. Coes nothing if the assoc does not contain ( + *snippet (key( . (.( . ! ?'&;: keys + *values + (assoc( assoc . + (keys( (an array of keys( . . + *description (Butputs an array of all keys in the assoc.( . ! ?'&;: values + *values + (assoc( assoc . + (values( (an array of values( . . + *description (Butputs an array of all values in the assoc.( . ! + keys values . related) ords ?'&;: assoc)intersect + *values + (assoc1( assoc . + (assoc,( assoc . + (intersection( (a ne assoc( . . + *description (Butputs an assoc consisting of all entries from ( + *snippet (assoc,( . ( such that the key is also present in ( + *snippet (assoc1( . (.( . + *notes ($he values of the keys in ( + *snippet (assoc1( . ( are disregarded< so this ord is usually used for set)theoretic calculations here the assoc in question either has dummy sentinels as values< or the values equal the

keys.( . ! ?'&;: assoc)unionK + *values + (assoc1( assoc . + (assoc,( assoc . . + *description ("dds all entries from ( + *snippet (assoc,( . ( to ( + *snippet (assoc1( . (.( . + *side)effects (assoc1( . ! ?'&;: assoc)union + *values + (assoc1( assoc . + (assoc,( assoc . + (union( (a ne assoc( . . + *description (Butputs a assoc consisting of all entries from ( + *snippet (assoc1( . ( and ( + *snippet (assoc,( . (< ith entries from ( + *snippet (assoc,( . ( taking precedence in case the corresponding values are not equal.( . ! ?'&;: assoc)diff + *values + (assoc1( assoc . + (assoc,( assoc . + (diff( (a ne assoc( . . + *description (Butputs an assoc consisting of all entries from ( + *snippet (assoc1( . ( hose key is not contained in ( + *snippet (assoc,( . (.( . ! ?'&;: assoc)diffK + *values + (assoc1( assoc . + (assoc,( assoc . . + *description (#emoves all entries from ( + *snippet (assoc1( . ( contained in ( + *snippet (assoc,( . (.( . + *side)effects (assoc1( . ! ?'&;: substitute + *values + (seq( sequence . + (assoc( assoc + *description (%reates a ne sequence here hich appear as keys in ( + *snippet (assoc( corresponding values< and all other elements

hose key is

. + (ne seq( sequence . . elements of ( + *snippet (seq( . ( . ( are replaced by the are unchanged.( . !

?'&;: cache + *values + (key( (a key( . + (assoc( assoc . + (quot( + *quotation (5 ... key )) ... value 6( . . + (value( (a previously)retained or freshly)computed value( . . + *description (If the key is present in the assoc< outputs the associated value< other ise calls the quotation to produce a value and stores the keyQvalue pair into the assoc. #eturns a value either looked up or ne ly stored in the assoc.( . + *side)effects (assoc( . ! ?'&;: ,cache + *values + (key1( (a key( . + (key,( (a key( . + (assoc( assoc . + (quot( + *quotation (5 ... key1 key, )) ... value 6( . . + (value( (a previously)retained or freshly)computed value( . . + *description (If a single key composed of the input keys is present in the assoc< outputs the associated value< other ise calls the quotation to produce a value and stores the keysQvalue pair into the assoc. #eturns the value stored in the assoc. #eturns a value either looked up or ne ly stored in the assoc.( . + *side)effects (assoc( . ! ?'&;: mapGassoc + *values + (seq( sequence . + (quot( + *quotation (5 ... elt )) ... key value 6( . . + (exemplar( assoc . + (assoc( (a ne assoc( . . + *description ("pplies the quotation to each element of the sequence< and collects the keys and values into a ne assoc having the same type as ( + *snippet (exemplar( . (.( . ! ?'&;: assocGmap + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... elt 6(

. . + (exemplar( sequence . + (seq( (a ne sequence( . . + *description ("pplies the quotation to each entry of the assoc and collects the results into a ne sequence of the same type as the exemplar.( . ! ?'&;: change)at + *values + (key( obFect . + (assoc( assoc . + (quot( + *quotation (5 ..a value )) ..b ne value 6( . . . + *description ("pplies the quotation to the value associated ith ( + *snippet (key( . (< storing the ne value back in the assoc.( . + *side)effects (assoc( . ! + change)at change)nth change . related) ords ?'&;: at2 + *values + (n( number . + (key( obFect . + (assoc( assoc . . + *description ("dds ( + *snippet (n( . ( to the value associated ith ( + *snippet (key( . (! if there is no value< stores ( + *snippet (n( . (< thus behaving as if the value as =.( . + *side)effects (assoc( . ! ?'&;: inc)at + *values + (key( obFect . + (assoc( assoc . . + *description ("dds 1 to the value associated there is no value< stores 1.( . + *side)effects (assoc( . !

ith ( + *snippet (key( . (! if

?'&;: Galist + *values + (assoc( assoc . + (ne assoc( (an array of keyQvalue pairs( . . + *contract (%onverts an associative structure into an association list.( . ! ?'&;: assoc)clone)like + *values + (assoc( assoc . + (exemplar( assoc . + (ne assoc( assoc . . + *description (Butputs a ne ly)allocated assoc ith the same elements as ( + *snippet (assoc( . (.( . + *examples + *example (USING: prettyprint assocs hashtables !( (?+ + 1 , . + / . . + . assoc)clone)like .( (+ + 1 , . + - / . .( . . ! ?'&;: assoc)combine + *values + (seq( (a sequence of assocs( . + (union( assoc . . + *description ($akes the union of all of the ( + *snippet (assocs( . ( in ( + *snippet (seq( . (.( . + *examples + *example (USING: prettyprint assocs !( (+ ?+ + 1 , . . ?+ + / . . . assoc)combine .( (?+ + 1 , . + - / . .( . . ! ?'&;: assoc)map)as + *values + (assoc( assoc . + (quot( + *quotation (5 ... key value )) ... ne key ne value 6( . . + (exemplar( assoc . + (ne assoc( assoc . . + *description ("pplies the quotation to each entry in the input assoc and collects the results in a ne assoc of the same type as the exemplar.( . + *examples + *example (USING: prettyprint assocs hashtables math !( ( ?+ + 1 , . + - / . . 0 sq 3 + . assoc)map)as .( (+ + 1 / . + - 1L . .( . . ! ?'&;: extract)keys + *values + (seq( sequence . + (assoc( assoc . + (subassoc( assoc . .

+ *description (Butputs an ne ( + *snippet (assoc( . ( ith keyQvalue pairs hose keys match the elements in the input ( + *snippet (seq( . (.( . + *examples + *example (USING: prettyprint assocs !( (+ 1 - . + + 1 1= . + , ,= . + - -= . . extract)keys .( (+ + 1 1= . + - -= . .( . . ! ?'&;: push)at + *values + (value( obFect . + (key( obFect . + (assoc( assoc . . + *description (;ushes the ( + *snippet (value( . ( onto a ( + *snippet (vector( . ( stored at the ( + *snippet (key( . ( in the ( + *snippet (assoc( . (. If the ( + *snippet (key( . ( does not yet exist< creates a ne ( + *snippet (vector( . ( at that ( + *snippet (key( . ( and pushes the ( + *snippet (value( . (.( . + *examples + *example (USING: prettyprint assocs kernel !( (?+ + >(cats>( V+ >(Iittens>( . . . >(Ie >( >(cats>( pick push)at .( (?+ + >(cats>( V+ >(Iittens>( >(Ie >( . . .( . . ! ?'&;: search)alist + *values + (key( obFect . + (alist( (an array of keyQvalue pairs( . + (pairQf( (a keyQvalue pair( . + (iQf( integer . . + *description (Iterates over ( + *snippet (alist( . ( and stops hen the key is matched or the end of the ( + *snippet (alist( . ( has been reached. If there is no match< both outputs are ( + *link f . (.( . + *notes ($his ord is used to implement ( + *link at4 . ( and ( + *link set)at . ( on sequences< and should not be called directly.( . + *examples + *example (USING: prettyprint assocs.private kernel !( (- + + 1 , . + - / . . search)alist 0 . 3 bi9( (+ - / .>n1( . + *example (USING: prettyprint assocs.private kernel !( (L + + 1 , . + - / . . search)alist 0 . 3 bi9( (f>nf( . . ! ?'&;: un8ip + *values + (assoc( assoc . + (keys( sequence . + (values( sequence . . + *description (Butputs an array of keys and an array of values of the input ( + *snippet (assoc( . (.( . + *examples + *example (USING: prettyprint assocs kernel !( (+ + 1 / . + , A . + - L . . un8ip 0 . 3 bi9( (+ 1 , - .>n+ / A L .( . . ! ?'&;: 8ip + *values + (keys( sequence . + (values( sequence . + (alist( (an array of keyQvalue pairs( . . + *description (%ombines t o sequences pair ise into a single sequence of keyQvalue pairs.( . + *examples + *example (USING: prettyprint assocs !( (+ 1 , - . + / A L . 8ip .( (+ + 1 / . + , A . + - L . .(

. . ! + un8ip 8ip . related) ords USING: accessors arrays kernel kernel.private math namespaces sequences sequences.private strings tools.test vectors continuations random gro able classes ! IN: vectors.tests 0 3 0 1= 0 0 )1====== PvectorG 3 ignore)errors 3 times 3 unit)test 0 - 3 0 0 t f t 3 length 3 unit)test 0 - 3 0 V+ t f t . length 3 unit)test 0 )- V+ . nth 3 must)fail 0 - V+ . nth 3 must)fail 0 - A/.- nth 3 must)fail 0 (hey( 0 1 , 3 set)length 3 must)fail 0 (hey( V+ 1 , . set)length 3 must)fail 0 - 3 0 - = PvectorG 0 set)length 3 keep length 3 unit)test 0 (yo( 3 0 (yo( / 1 PvectorG 0 set)nth 3 keep / s ap nth 3 unit)test 0 0 0 0 1 V+ . nth 3 must)fail )1 V+ . set)length 3 must)fail V+ . 3 0 0 3 Gvector 3 unit)test V+ 1 , . 3 0 0 1 , 3 Gvector 3 unit)test

0 t 3 0 1== 0 1== random 3 V+ . replicate)as dup Garray Gvector H 3 unit)test 0 0 0 0 f f f f 3 3 3 3 0 0 0 0 V+ . V+ 1 , - . H 3 unit)test V+ 1 , . V+ 1 , - . H 3 unit)test 0 1 , 3 V+ 1 , - . H 3 unit)test V+ 1 , . 0 1 , - 3 H 3 unit)test

0 + 1 / U 1L . 3 0 0 1 , - / 3 Gvector 0 dup 4 3 map Garray 3 unit)test 0 0 0 0 t t t t 3 3 3 3 0 0 0 0 V+ V+ V+ V+ . 1 1 . hashcode V+ . hashcode H 3 unit)test , - . hashcode V+ 1 , - . hashcode H 3 unit)test V+ , . - . hashcode V+ 1 V+ , . - . hashcode H 3 unit)test hashcode V+ . hashcode H 3 unit)test

0 V+ 1 , - . V+ 1 , - / A L . 3 0 V+ 1 , - . dup V+ / A L . append 3 unit)test 0 V+ 1 , - / . 3 0 0 V+ 1 . 0 , 3 V+ - / . 3 concat 3 unit)test 0 V+ . 3 0 V+ . = tail 3 unit)test 0 V+ . 3 0 V+ 1 , . , tail 3 unit)test 0 V+ - / . 3 0 V+ 1 , - / . , tail 3 unit)test 0 V+ - . 3 0 V+ 1 , - . 1 tail4 3 unit)test

= PvectorG (funny)stack( set 0 0 0 0 0 0 0 0 0 3 0 V+ 1 A . (funny)stack( get push 3 unit)test 3 0 V+ , - . (funny)stack( get push 3 unit)test V+ , - . 3 0 (funny)stack( get pop 3 unit)test V+ 1 A . 3 0 (funny)stack( get last 3 unit)test V+ 1 A . 3 0 (funny)stack( get pop 3 unit)test (funny)stack( get pop 3 must)fail (funny)stack( get pop 3 must)fail 3 0 (funky( (funny)stack( get push 3 unit)test (funky( 3 0 (funny)stack( get pop 3 unit)test

0 t 3 0 V+ 1 , - / . dup underlyingGG length 0 clone underlyingGG length 3 dip H 3 unit)test 0 f 3 0 V+ 1 , - / . dup clone 0 underlyingGG 3 bi9 eq: 3 unit)test 0 = 3 0 0 1= PvectorG (x( set (x( get clone length 3 ith)scope 3 unit)test 0 f 3 0 A V+ . index 3 unit)test 0 / 3 0 A V+ 1 , - / A . index 3 unit)test 0 t 3 0 1== iota Garray dup Gvector PreversedG Garray 0 reverse 3 dip H 3 unit)test 0 fixnum 3 0 1 Gbignum V+ . ne )sequence length class)of 3 unit)test 0 fixnum 3 0 1 Gbignum iota 0 3 V+ . map)as length class)of 3 unit)test 0 V+ (lul8( . 3 0 (lul8( 1vector 3 unit)test USING: arrays byte)arrays help.markup help.syntax kernel sbufs strings quotations sequences.private vectors.private combinators ! IN: vectors "#$I%&': (vectors( (Vectors( ($he ( + *vocab)link (vectors( . ( vocabulary implements resi8able mutable sequence hich support the ( + *link (sequence)protocol( . (.( *nl ($he ( + *vocab)link (vectors( . ( vocabulary only includes ords for creating ne vectors. $o access and modify vector elements< use ( + *link (sequences( . ( in the ( + *vocab)link (sequences( . ( vocabulary.( *nl (Vector literal syntax is documented in ( + *link (syntax)vectors( . (.( *nl (Vectors are intended to be used ith ( + *link (sequences)destructive( . (. %ode that does not modify sequences in)place can use fixed)si8e arrays ithout loss of generality! see ( + *link (arrays( . (.( *nl (Vectors form a class of obFects:(

+ *subsections vector vector: . (%reating ne vectors:( + *subsections Gvector PvectorG . (%reating a vector from a single element:( + *subsections 1vector . (If you don7t care about initial capacity< an elegant is to rite:( + *code (V+ . clone( . ! "EBU$: (vectors(

ay to create a ne

vector

?'&;: vector + *description ($he class of resi8able vectors. See ( + *link (syntax)vectors( . ( for syntax and ( + *link (vectors( . ( for general information.( . ! ?'&;: PvectorG + *values + (n( (a positive integer specifying initial capacity( . + (vector( vector . . + *description (%reates a ne vector that can hold ( + *snippet (n( . ( elements before resi8ing.( . ! ?'&;: Gvector + *values + (seq( (a sequence( . + (vector( vector . . + *description (Butputs a freshly)allocated vector ith the same elements as a given sequence.( . ! ?'&;: 1vector + *values + (x( obFect . + (vector( vector . . + *description (%reate a ne vector ith one element.( . ! ?'&;: :push + *values + (elt( obFect . + (seqQf( (a resi8able mutable sequence< or ( + *link f . . + (seq( (a resi8able mutable sequence( . . + *description (If the given sequence is ( + *link f . (< creates and outputs a ne one)element vector holding ( + *snippet (elt( . (. Bther ise< pushes ( + *snippet (elt( . ( onto the given sequence.( . + *errors ($hro s an error if ( + *snippet (seq( . ( is not resi8able< or if the type of ( + *snippet (elt( . ( is not permitted in ( + *snippet (seq( . (.( . + *side)effects (seq( . ! K %opyright 5%6 ,==/< ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays gro able kernel math sequences sequences.private ! IN: vectors $U;&': vector + underlying array . + length array)capacity . ! : PvectorG 5 n )) vector 6 = ParrayG = vector boa ! inline : Gvector 5 seq )) vector 6 V+ . clone)like ! I: vector like drop dup vector: 0 dup array: 0 dup length vector boa 3 0 Gvector 3 if

3 unless ! inline I: vector ne )sequence drop 0 f ParrayG 3 0 integerGfixnum 3 bi vector boa ! inline I: vector equal: over vector: 0 sequenceH 3 0 ,drop f 3 if ! I: array like ZK If e have an array< e7re done. ZK If e have a vector< and it7s at full capacity< e7re done. ZK Bther ise< call resi8e)array< hich is a relatively ZK fast primitive. drop dup array: 0 dup vector: 0 0 length 3 0 underlyingGG 3 bi ,dup length eq: 0 nip 3 0 resi8e)array 3 if 3 0 Garray 3 if 3 unless ! inline I: sequence ne )resi8able drop PvectorG ! inline INS$"N%': vector gro able : 1vector 5 x )) vector 6 V+ . 1sequence ! : :push 5 elt seqQf )) seq 6 0 1 PvectorG 3 unless4 0 push 3 keep ! USING: tools.test generic kernel definitions sequences compiler.units ords ! IN: definitions.tests G'N'#I%: some)generic 5 a )) b 6 US': arrays I: array some)generic ! US': bit)arrays I: bit)array some)generic ! US': byte)arrays I: byte)array some)generic ! $U;&': some)class ! I: some)class some)generic ! 0 3 0 0 > some)generic > some)class ,array forget)all 3 ith)compilation)unit 3 unit)test USING: help.markup help.syntax ords math source)files parser quotations compiler.units ! IN: definitions

"#$I%&': (definition)protocol( (Cefinition protocol( (" common protocol is used to build generic tools for orking ith all definitions.( *nl (Cefinitions must kno hat source file they ere loaded from< and provide a ay to set this:( + *subsections here set) here . (Cefinitions can be removed:( + *subsections forget . (Cefinitions must implement a fe operations used for printing them in source form:( + *subsections definer definition . + *see)also (see( . ! "#$I%&': (definition)checking( (Cefinition sanity checking( (Jhen a source file is reloaded< the parser compares the previous list of definitions ith the current list! any definitions hich are no longer present in the file are removed by a call to ( + *link forget . (.( *nl ($he parser also catches for ard references hen reloading source files. $his is best illustrated ith an example. Suppose e load a source file ( + *snippet (a.factor( . (:( + *code (USING: io sequences !( (IN: a( (: hello 5 )) str 6 >(?ello>( !( (: orld 5 )) str 6 >( orld>( !( (: hello) orld 5 )) 6 hello >( >( orld -append print !( . ($he definitions for ( + *snippet (hello( . (< ( + *snippet ( orld( . (< and ( + *snippet (hello) orld( . ( are in the dictionary.( *nl (No < after some heavily editing and refactoring< the file looks like this:( + *code (USING: make !( (IN: a( (: hello 5 )) 6 >(?ello>( W !( (: hello) orld 5 )) str 6 0 hello >( >( W orld 3 >(>( make !( (: orld 5 )) 6 >( orld>( W !( . (Note that the developer has made a mistake< placing the definition of ( + *snippet ( orld( . ( ( + *emphasis (after( . ( its usage in ( + *snippet (hello) orld( . (.( *nl (If the parser did not have special checks for this case< then the modified source file ould still load< because hen the definition of ( + *snippet (hello) orld( . ( on line / is being parsed< the ( + *snippet ( orld( . ( ord is already present in the dictionary from an earlier run. $he developer ould then not discover this mistake until attempting to load the source file into a fresh image.( *nl (Since this is undesirable< the parser explicitly raises a ( + *link no) ord . ( error if a source file refers to a ord hich is in the dictionary< but defined after it is used.( *nl

($he parser also catches duplicate definitions. If an artifact is defined t ice in the same source file< the earlier definition ill never be accessible< and this is almost al ays a mistake< perhaps due to a bad choice of ord names< or a copy and paste error. $he parser raises an error in this case.( + *subsections redefine)error . ! "#$I%&': (definitions( (Cefinitions( (" ( + *emphasis (definition( . ( is an artifact read from a source file. Jords for orking ith definitions are found in the ( + *vocab)link (definitions( . ( vocabulary.( *nl (Cefinitions are defined using parsing ords. 'xamples of definitions together ith their defining parsing ords are ords 5( + *link ;BS$;BN': : . (6< methods 5( + *link ;BS$;BN': I: . (6< and vocabularies 5( + *link ;BS$;BN': IN: . (6.( *nl ("ll definitions share some common traits:( + *list ($here is a ord to list all definitions of a given type( ($here is a parsing ord for creating ne definitions( ($here is an ordinary ord hich is the runtime equivalent of the parsing ord< for introspection( (Instances of the definition may be introspected and modified ith the definition protocol( . (@or every source file loaded into the system< a list of definitions is maintained. ;athname obFects implement the definition protocol< acting over the definitions their source files contain. See ( + *link (source)files( . ( for details.( + *subsections (definition)protocol( (definition)checking( (compilation)units( . (" parsing ord to remove definitions:( + *subsections ;BS$;BN': @B#G'$: . + *see)also (see( (parser( (source)files( ( ords( (generic( (help)impl( . ! "EBU$: (definitions( ?'&;: here + *values + (defspec( (a definition specifier( . + (loc( (a ( + *snippet (+ path lineZ .( . ( pair( . . + *description (Butputs the location of a definition. If the location is not kno n< ill output ( + *link f . (.( . ! ?'&;: set) here + *values + (loc( (a ( + *snippet (+ path lineZ .( . ( pair( . + (defspec( (a definition specifier( . . + *description (Sets the definition7s location.( . + *notes ($his ord is used by the parser.( . ! ?'&;: forget + *values + (defspec( (a definition specifier( . . + *description (@orgets about a definition. @or example< if it is a ord< it ill be removed from its vocabulary.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . ! ?'&;: forget)all + *values + (definitions( (a sequence of definition specifiers( . . + *description (@orgets every definition in a sequence.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit .

(.( . ! K %opyright 5%6 ,==L< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs kernel namespaces sequences sets ! IN: definitions IIMIN: definition)mixin '##B#: no)compilation)unit definition ! : add)to)unit 5 key set )) 6 0 adFoin 3 0 no)compilation)unit 3 if4 ! SNIEB&: changed)definitions : changed)definition 5 defspec )) 6 changed)definitions get add)to)unit ! SNIEB&: maybe)changed : changed)conditionally 5 class )) 6 maybe)changed get add)to)unit ! SNIEB&: changed)effects SNIEB&: outdated)generics SNIEB&: ne ) ords : ne ) ord 5 ord )) 6 ne ) ords get add)to)unit ! : ne ) ord: 5 ord )) : 6 ne ) ords get in: ! G'N'#I%: I: obFect here 5 defspec )) loc 6 here drop f !

G'N'#I%: set) here 5 loc defspec )) 6 G'N'#I%: forget4 5 defspec )) 6 SNIEB&: forgotten)definitions : forgotten)definition 5 defspec )) 6 forgotten)definitions get add)to)unit ! : forget 5 defspec )) 6 0 forgotten)definition 3 0 forget4 3 bi ! I: f forget4 drop ! I: rapper forget4 rappedGG forget !

: forget)all 5 definitions )) 6 0 forget 3 each ! G'N'#I%: definer 5 defspec )) start end 6 G'N'#I%: definition 5 defspec )) seq 6 USING: help.markup help.syntax kernel sequences sequences.private ! IN: gro able

"#$I%&': (gro able( (#esi8able sequence implementation( (#esi8able sequences are implemented by having a rapper obFect hold a reference to an underlying sequence< together ith a fill pointer indicating ho many elements of the underlying sequence are occupied. Jhen the fill pointer exceeds the underlying sequence capacity< the underlying sequence gro s.( *nl ($here is a resi8able sequence mixin:( + *subsections gro able . ($his mixin implements the sequence protocol by assuming the obFect has t o specific slots:( + *list + + *snippet (length( . ( ) the fill pointer 5number of occupied elements in the underlying storage6( . + + *snippet (underlying( . ( ) the underlying storage( . . ($he underlying sequence must implement a generic ord:( + *subsections resi8e . + *link (vectors( . ( and ( + *link (sbufs( . ( are implemented using the resi8able sequence facility.( ! "EBU$: (gro able( ?'&;: capacity + *values + (seq( (a vector or string buffer( . + (n( (the capacity of the sequence( . . + *description (Butputs the number of elements the sequence can hold ithout gro ing.( . ! ?'&;: ne )si8e + *values + (old( (a positive integer( . + (ne ( (a positive integer( . . + *description (%omputes the ne si8e of a resi8able sequence.( . ! ?'&;: ensure + *values + (n( (a positive integer( . + (seq( gro able . . + *description ($his ord behaves as follo s< depending on the relation bet een ( + *snippet (n( . ( and the length of the sequence:( + *list + (If ( + *snippet (n( . ( is less than the length of the sequence< does nothing.( . + (If ( + *snippet (n( . ( exceeds the capacity of the underlying storage< the underlying storage is gro n.( . + (If ( + *snippet (n( . ( is greater than or equal to the length but less than the capacity of the underlying storage< the fill pointer is moved and nothing else is done.( . . (In the case that ne elements are added to the sequence 5last t o cases6< the ne elements are undefined.( . + *notes ($his ord is used in the implementation of the ( + *link set)nth . ( generic for sequences supporting the resi8able sequence protocol 5see ( + *link (gro able( . (6.( . ! USING: math sequences classes gro able tools.test kernel layouts ! IN: gro able.tests K erg found this one 0 fixnum 3 0 , Gbignum V+ . 0 set)length 3 keep length class)of 3 unit)test K overflo bugs

0 (hi( most)positive)fixnum , 4 , 2 V+ . clone set)nth 3 must)fail 0 most)positive)fixnum , 4 , 2 + 1 . clone nth 3 must)fail 0 most)positive)fixnum , 4 , 2 V+ . clone lengthen 3 must)fail 0 most)positive)fixnum , 4 , 2 V+ . clone set)length 3 must)fail 0 1= V+ . 0 set)length 3 keep =.A s ap set)length 3 must)fail K %opyright 5%6 ,==A< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors kernel math math.private sequences sequences.private ! IN: gro able IIMIN: gro able S&B$: length S&B$: underlying I: gro able length lengthGG ! inline I: gro able nth)unsafe underlyingGG nth)unsafe ! inline I: gro able set)nth)unsafe underlyingGG set)nth)unsafe ! inline P;#IV"$' : push)unsafe 5 elt seq )) 6 0 length integerGfixnum 3 keep 0 set)nth)unsafe 3 0 0 1 fixnum2fast 3 dip lengthPP 3 ,bi ! inline : push)all)unsafe 5 from to src dst )) 6 0 over ) s ap 3 ,dip 0 pick 3 dip 0 length integerGfixnum 3 keep 0 0 fixnum2fast 3 dip lengthPP 3 ,keep PcopyG 5copy6 drop ! inline ;#IV"$'G : capacity 5 seq )) n 6 underlyingGG length ! inline : expand 5 len seq )) 6 0 resi8e 3 change)underlying drop ! inline G'N'#I%: contract 5 len seq )) 6 I: gro able contract 5 len seq )) 6 0 length 3 keep 0 0 = 3 ,dip set)nth)unsafe 3 curry 5each)integer6 ! inline I: gro able set)length 5 n seq )) 6 bounds)check)head ,dup length P 0 ,dup contract 3 0 ,dup capacity G 0 ,dup expand 3 3 if

hen

lengthPP ! : ne )si8e 5 old )) ne 6 1 2 - 4 ! inline

: ensure 5 n seq )) n seq 6 bounds)check)head ,dup length GH 0 ,dup capacity GH 0 over ne )si8e over expand 3 0 integerGfixnum 3 dip over 1 fixnum2fast over lengthPP 3 0 0 integerGfixnum 3 dip 3 if ! inline I: gro able set)nth ensure set)nth)unsafe ! inline

hen

I: gro able clone 5clone6 0 clone 3 change)underlying ! inline I: gro able lengthen 5 n seq )) 6 ,dup length G 0 ,dup capacity G 0 over ne )si8e over expand 3 ,dup lengthPP 3 hen ,drop ! inline I: gro able shorten 5 n seq )) 6 bounds)check)head ,dup length P 0 ,dup contract ,dup lengthPP 3 hen ,drop ! inline I: gro able ne )resi8able ne )sequence = over set)length ! inline INS$"N%': gro able sequence K %opyright 5%6 ,==L Coug %oleman K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: checksums io.binary kernel math sequences sequences.private ! IN: checksums.crc-, %BNS$"N$: crc-,)polynomial =xedbSS-,= %BNS$"N$: crc-,)table V+ . ,AL iota 0 S 0 0 ,Q 3 0 even: 3 bi 0 crc-,)polynomial bitxor 3 unless 3 times 3 map = crc-,)table copy : 5crc-,6 5 crc ch )) crc 6 dupd bitxor mask)byte crc-,)table nth)unsafe s ap )S shift bitxor ! inline SING&'$BN: crc-, INS$"N%': crc-, checksum : init)crc-, 5 input checksum )) x y input 6 drop 0 =xffffffff dup 3 dip ! inline

hen

: finish)crc-, 5 x y )) bytes 6 bitxor / Gbe ! inline I: crc-, checksum)bytes init)crc-, 0 5crc-,6 3 each finish)crc-, ! inline I: crc-, checksum)lines init)crc-, 0 0 5crc-,6 3 each %?"#: >n 5crc-,6 3 each finish)crc-, ! inline USING: checksums checksums.crc-, kernel math tools.test namespaces ! 0 E+ = = = = . 3 0 (( crc-, checksum)bytes 3 unit)test 0 E+ =xcb =xf/ =x-U =x,L . 3 0 (1,-/ALRSU( crc-, checksum)bytes 3 unit)test USING: help.markup help.syntax math ! IN: checksums.crc-, ?'&;: crc-, + *class)description ($he %#%-, checksum algorithm.( . ! "#$I%&': (checksums.crc-,( (%#%-, checksum( ($he %#%-, checksum algorithm provides a quick but unreliable changes in data.( + *subsections crc-, . ! "EBU$: (checksums.crc-,( K %opyright 5c6 ,==S Slava ;estov K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays byte)vectors io io.backend io.files kernel math math.parser sequences ! IN: checksums IIMIN: checksum $U;&': checksum)state + bytes)read integer . + block)si8e integer . + bytes byte)vector . ! : ne )checksum)state 5 class )) checksum)state 6 ne EV+ . clone GGbytes ! inline I: checksum)state clone call)next)method 0 clone 3 change)bytes ! G'N'#I%: initiali8e)checksum)state 5 class )) checksum)state 6 G'N'#I%: checksum)block 5 bytes checksum )) 6 G'N'#I%: get)checksum 5 checksum )) value 6 : add)checksum)bytes 5 checksum)state over bytesGG 0 push)all 3 keep 0 dup length pick block)si8eGG GH 0 over block)si8eGG cut)slice 0 over 0 checksum)block 3 0 0 3 0 block)si8eGG 3 bi data )) checksum)state 6 3 Gbyte)array 3 dip 0 0 2 3 curry change)bytes)read drop 3 bi ay to detect

3 dip 3 hile Gbyte)vector 0 GGbytes 3 0 length 0 2 3 curry change)bytes)read 3 bi ! : add)checksum)stream 5 checksum)state stream )) checksum)state 6 0 0 0 s ap add)checksum)bytes drop 3 curry each)block 3 keep 3 ith)input)stream ! : add)checksum)file 5 checksum)state path )) checksum)state 6 normali8e)path 5file)reader6 add)checksum)stream ! G'N'#I%: checksum)bytes 5 bytes checksum )) value 6 G'N'#I%: checksum)stream 5 stream checksum )) value 6 G'N'#I%: checksum)lines 5 lines checksum )) value 6 I: checksum checksum)stream 0 stream)contents 3 dip checksum)bytes ! I: checksum checksum)lines 0 E+ %?"#: >n . Foin 3 dip checksum)bytes ! : checksum)file 5 path checksum )) value 6 ZK normali8e)path 5file)reader6 is equivalent to ZK binary Pfile)readerG. Je use the lo er)level form ZK so that e can move io.encodings.binary to basisQ. 0 normali8e)path 5file)reader6 3 dip checksum)stream ! : hex)string 5 seq )) str 6 0 Ghex , %?"#: = pad)head 3 + . map)as concat ! USING: help.markup help.syntax kernel math sequences quotations math.private byte)arrays strings ! IN: checksums ?'&;: checksum + *class)description ($he class of checksum algorithms.( . ! ?'&;: hex)string + *values + (seq( (a sequence( . + (str( (a string( . . + *description (%onverts a sequence of values from =),AA to a string of hex numbers from =)ff.( . + *examples + *example (USING: checksums io !( (E+ 1 , - / . hex)string print( (=1=,=-=/( . . + *notes (Numbers are 8ero)padded on the left.( . ! ?'&;: checksum)stream + *values + (stream( (an input stream( . + (checksum( (a checksum specifier( . + (value( byte)array . . + *contract (%omputes the checksum of all data read from the stream.( . + *side)effects (stream( . ! ?'&;: checksum)bytes + *values + (bytes( (a sequence of bytes( . + (checksum( (a checksum specifier( . + (value( byte)array . . + *contract (%omputes the checksum of all data in a sequence.( . + *examples + *example

(USING: checksums checksums.crc-, prettyprint !( (E+ 1 1= 1== . crc-, checksum)bytes .( (E+ RS 1RU ,A/ ,-S .( . ! .

?'&;: checksum)lines + *values + (lines( (a sequence of sequences of bytes( . + (checksum( (a checksum specifier( . + (value( byte)array . . + *contract (%omputes the checksum of all data in a sequence.( . + *examples + *example (USING: checksums checksums.crc-, prettyprint !( (((+ ($ake me out to the ball game( ($ake me out ith the cro d( . crc-, checksum)lines .((( (E+ 111 ,=A U ,R .( . . ! ?'&;: checksum)file + *values + (path( (a pathname specifier( . + (checksum( (a checksum specifier( . + (value( byte)array . . + *contract (%omputes the checksum of all data in a file.( . + *examples + *example (USING: checksums checksums.crc-, prettyprint !( ((((resource:license.txt( crc-, checksum)file .((( (E+ 1== 1-U 1UU U, .( . . ! "#$I%&': (checksums( (%hecksums( (" ( + *emphasis (checksum( . ( is a function mapping sequences of bytes to fixed)length strings. Jhile checksums are not one)to)one< a good checksum should have a lo probability of collision. "dditionally< some checksum algorithms are designed to be hard to reverse< in the sense that finding an input string hich hashes to a given checksum string requires a brute)force search.( *nl (%hecksums are instances of a class:( + *subsections checksum . (Bperations on checksums:( + *subsections checksum)bytes checksum)stream checksum)lines . (%hecksums should implement at least one of ( + *link checksum)bytes . ( and ( + *link checksum)stream . (. Implementing ( + *link checksum)lines . ( is optional.( *nl (Utilities:( + *subsections checksum)file hex)string . (%hecksum implementations:( + *subsections (checksums.crc-,( . + *vocab)subsection (ICA checksum( (checksums.mdA( . + *vocab)subsection (S?" checksums( (checksums.sha( . + *vocab)subsection ("dler)-, checksum( (checksums.adler)-,( .

+ *vocab)subsection (BpenSS& checksums( (checksums.openssl( . + *vocab)subsection (Internet checksum( (checksums.internet( . ! "EBU$: (checksums( K %opyright 5%6 ,==A< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors kernel math sequences sequences.private ! IN: arrays EUI&$IN: array + length array)capacity read)only initial: = . ! I: I: I: I: I: I: I: I: array clone 5clone6 ! inline array length lengthGG ! inline array nth)unsafe 0 integerGfixnum 3 dip array)nth ! inline array set)nth)unsafe 0 integerGfixnum 3 dip set)array)nth ! inline array resi8e resi8e)array ! inline array equal: over array: 0 sequenceH 3 0 ,drop f 3 if ! obFect ne )sequence drop = ParrayG ! inline f ne )sequence drop 0 f 3 0 = ParrayG 3 if)8ero ! inline

INS$"N%': array sequence : : : : : Garray 1array ,array -array /array 5 5 5 5 5 seq )) array 6 + x )) array 6 1 s x y )) array 6 + x y 8 )) array 6 x y 8 )) array . clone)like ! ap ParrayG ! inline . ,sequence ! inline + . -sequence ! inline 6 + . /sequence ! inline

;#'CI%"$': pair P array length , numberH ! USING: accessors arrays kernel sequences sequences.private gro able tools.test vectors layouts system math vectors.private ! IN: arrays.tests 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ), + (a( (b( (c( . nth 3 must)fail 1= + (a( (b( (c( . nth 3 must)fail (hi( ), + (a( (b( (c( . set)nth 3 must)fail (hi( 1= + (a( (b( (c( . set)nth 3 must)fail f 3 0 + (a( (b( (c( . dup clone eq: 3 unit)test (hi( 3 0 (hi( 1 + (a( (b( (c( . clone 0 set)nth 3 keep second 3 unit)test V+ (a( (b( (c( . 3 0 + (a( (b( (c( . Gvector 3 unit)test f 3 0 + (a( (b( (c( . dup Garray eq: 3 unit)test t 3 0 + (a( (b( (c( . dup + . like eq: 3 unit)test t 3 0 + (a( (b( (c( . dup dup length vector boa underlyingGG eq: 3 unit)test V+ (a( (b( (c( . 3 0 + (a( (b( (c( . V+ . like 3 unit)test + (a( (b( (c( . 3 0 + (a( . + (b( (c( . append 3 unit)test + (a( (b( (c( (d( (e( . 3 + (a( . + (b( (c( . + (d( (e( . -append 3 unit)test

0 )1 f ParrayG 3 must)fail 0 cell)bits cell log, ) ,T f ParrayG 3 must)fail USING: help.markup help.syntax kernel kernel.private prettyprint sequences.private sequences ! IN: arrays "#$I%&': (arrays)unsafe( (Unsafe array operations( ($hese t o ords are used internally by the @actor implementation. User code should never need to call them! instead use ( + *link nth . ( and ( + *link set)nth . (.( + *subsections array)nth set)array)nth . !

"#$I%&': (arrays( ("rrays( ($he ( + *vocab)link (arrays( . ( vocabulary implements fixed)si8e mutable sequences hich support the ( + *link (sequence)protocol( . (.( *nl ($he ( + *vocab)link (arrays( . ( vocabulary only includes ords for creating ne arrays. $o access and modify array elements< use ( + *link (sequences( . ( in the ( + *vocab)link (sequences( . ( vocabulary.( *nl ("rray literal syntax is documented in ( + *link (syntax)arrays( . (. #esi8able arrays also exist and are kno n as ( + *link (vectors( . (.( *nl ("rrays form a class of obFects:( + *subsections array array: . (%reating ne arrays:( + *subsections Garray ParrayG . (%reating an array from several elements on the stack:( + *subsections 1array ,array -array /array . (#esi8ing arrays:( + *subsections resi8e)array . ($he class of t o)element arrays:( + *subsections pair . ("rrays can be accessed ithout bounds checks in a pointer unsafe ay.( + *subsections (arrays)unsafe( . ! "EBU$: (arrays( ?'&;: array + *description ($he class of fixed)length arrays. See ( + *link (syntax)arrays( . ( for syntax and ( + *link (arrays( . ( for general information.( . ! ?'&;: ParrayG + *values + (n( (a non)negative integer( . + (elt( (an initial element( . + (array( (a ne array( . . + *description (%reates a ne array ith the given length and all elements initially set to ( + *snippet (elt( . (.( . ! ?'&;: Garray + *values + (seq( (a sequence( . + (array( array . . + *description (Butputs a freshly)allocated array ith the same elements as a given sequence.( . ! ?'&;: 1array + *values + (x( obFect . + (array( array . . + *description (%reate a ne array ith one element.( . ! + 1array ,array -array /array . related) ords ?'&;: ,array + *values + (x( obFect . + (y( obFect . + (array( array . .

+ *description (%reate a ne appearing first.( . !

array

ith t o elements<

ith ( + *snippet (x( . (

?'&;: -array + *values + (x( obFect . + (y( obFect . + (8( obFect . + (array( array . . + *description (%reate a ne array ith three elements< ith ( + *snippet (x( . ( appearing first.( . ! ?'&;: /array + *values + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (array( array . . + *description (%reate a ne array ith four elements< ith ( + *snippet ( ( . ( appearing first.( . ! ?'&;: resi8e)array + *values + (n( (a non)negative integer( . + (array( array . + (ne )array( array . . + *description (#esi8es the array to have a length of ( + *snippet (n( . ( elements. Jhen making the array shorter< this ord may either create a ne array or modify the existing array in place. Jhen making the array longer< this ord al ays allocates a ne array< filling remaining space ith ( + *link f . (.( . + *side)effects (array( . ! ?'&;: pair + *class)description ($he class of t o)element arrays< kno n as pairs.( . ! K %opyright 5%6 ,==/< ,=11 Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs classes classes.algebra classes.algebra.private classes.builtin classes.private combinators definitions kernel kernel.private math math.private quotations sequences ords ! @#BI: sets HG setH ! IN: classes.union ;#'CI%"$': union)class P class (metaclass( ord)prop union)class eq: ! P;#IV"$' G'N'#I%: union)of)builtins: 5 class )) : 6 I: builtin)class union)of)builtins: drop t ! I: union)class union)of)builtins: members 0 union)of)builtins: 3 all: ! I: class union)of)builtins: drop f ! : fast)union)mask 5 class )) n 6 0 = 3 dip flatten)class 0 drop classGtype ,T bitor 3 assoc)each ! : empty)union)predicate)quot 5 class )) quot 6 drop 0 drop f 3 ! : fast)union)predicate)quot 5 class )) quot 6 fast)union)mask 1quotation 0 tag 1 s ap fixnum)shift)fast 3 0 fixnum)bitand = eq: not 3 surround !

: slo )union)predicate)quot 5 class )) quot 6 members 0 predicate)def 3 map unclip s ap 0 0 dup 3 prepend 0 drop t 3 3 + . mapGassoc alistGquot ! : union)predicate)quot 5 class )) quot 6 + + 0 dup members empty: 3 0 empty)union)predicate)quot 3 . + 0 dup union)of)builtins: 3 0 fast)union)predicate)quot 3 . 0 slo )union)predicate)quot 3 . cond ! : define)union)predicate 5 class )) 6 dup union)predicate)quot define)predicate ! I: union)class update)class define)union)predicate ! : 5define)union)class6 5 class members )) 6 f s ap f union)class make)class)props 5define)class6 ! '##B#: cannot)reference)self class members ! G'N'#I%: classes)contained)by 5 obF )) members 6 I: union)class classes)contained)by 5 union )) members 6 (members( ord)prop 0 f 3 hen)empty ! I: obFect classes)contained)by (members( ord)prop 0 f 3 hen)empty ! : check)self)reference 5 class members )) class members 6 ,dup 0 dup dup 0 classes)contained)by 3 map concat sift append ,dup setH 0 ,drop f 3 0 nip 3 if 3 follo concat member)eq: 0 cannot)reference)self 3 hen ! ;#IV"$'G : define)union)class 5 class members )) 6 0 check)self)reference 5define)union)class6 3 0 drop changed)conditionally 3 0 drop update)classes 3 ,tri ! I: union)class rank)class drop R ! I: union)class instance: (members( ord)prop 0 instance: 3 ith any: !

I: anonymous)union instance: membersGG 0 instance: 3 ith any: ! I: anonymous)union class)name membersGG 0 class)name 3 map ( ( Foin ! I: union)class normali8e)class members Panonymous)unionG normali8e)class ! I: union)class 5flatten)class6 members Panonymous)unionG 5flatten)class6 ! USING: generic help.markup help.syntax kernel kernel.private namespaces sequences ords arrays help effects math

classes.private classes compiler.units ! IN: classes.union "#$I%&': (unions( (Union classes( ("n obFect is an instance of a union class if it is an instance of one of its members.( + *subsections ;BS$;BN': UNIBN: define)union)class . (Union classes can be introspected:( + *subsections members . ($he set of union classes is a class:( + *subsections union)class union)class: . (Unions are used to define behavior shared bet een a fixed set of classes< as ell as to conveniently define predicates.( + *see)also (mixins( (tuple)subclassing( . ! "EBU$: (unions( ?'&;: define)union)class + *values + (class( class . + (members( (a sequence of classes( . . + *description (Cefines a union class ith specified members. $his is the run time equivalent of ( + *link ;BS$;BN': UNIBN: . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects (class( . ! + union)class define)union)class ;BS$;BN': UNIBN: . related) ords ?'&;: union)class + *class)description ($he class of union classes.( . ! USING: accessors alien arrays definitions generic assocs hashtables io kernel math namespaces parser prettyprint sequences strings tools.test vectors ords quotations classes classes.private classes.union classes.mixin classes.predicate classes.algebra classes.union.private source)files compiler.units kernel.private sorting vocabs io.streams.string eval see math.private slots generic.single ! IN: classes.union.tests K C'@'#: bah K @B#G'$: bah UNIBN: bah fixnum alien ! 0 bah 3 0 > bah: (predicating(

ord)prop 3 unit)test

0 (USING: alien math !>nIN: classes.union.tests>nUNIBN: bah fixnum alien !>n( 3 0 0 > bah see 3 ith)string) riter 3 unit)test K $est redefinition of classes UNIBN: union)1 fixnum float ! G'N'#I%: generic)update)test 5 x )) y 6 I: union)1 generic)update)test drop (union)1( ! 0 f 3 0 bignum union)1 classPH 3 unit)test 0 t 3 0 union)1 number classPH 3 unit)test 0 (union)1( 3 0 1.= generic)update)test 3 unit)test

(IN: classes.union.tests US': math US': arrays UNIBN: union)1 rational array !( eval5 )) 6 0 t 3 0 bignum union)1 classPH 3 unit)test 0 f 3 0 union)1 number classPH 3 unit)test 0 (union)1( 3 0 + 1.= . generic)update)test 3 unit)test (IN: classes.union.tests US': math ;#'CI%"$': union)1 P integer even: !( eval5 )) 6 0 0 0 0 f 3 0 union)1 union)class: 3 unit)test t 3 0 union)1 predicate)class: 3 unit)test (union)1( 3 0 S generic)update)test 3 unit)test )R generic)update)test 3 must)fail

K 'mpty unions ere causing problems G'N'#I%: empty)union)test 5 obF )) obF 6 UNIBN: empty)union)1 ! I: empty)union)1 empty)union)test ! UNIBN: empty)union), ! I: empty)union), empty)union)test ! 0 0 drop f 3 3 0 > empty)union)1: defGG 3 unit)test K #edefining a class didn7t update containing unions UNIBN: redefine)bug)1 fixnum ! UNIBN: redefine)bug), redefine)bug)1 quotation ! 0 t 3 0 fixnum redefine)bug), classPH 3 unit)test 0 t 3 0 quotation redefine)bug), classPH 3 unit)test 0 3 0 (IN: classes.union.tests US': math UNIBN: redefine)bug)1 bignum !( eval5 )) 6 3 unit)test 0 t 3 0 bignum redefine)bug)1 classPH 3 unit)test 0 f 3 0 fixnum redefine)bug), classPH 3 unit)test 0 t 3 0 bignum redefine)bug), classPH 3 unit)test K $oo eager ith reset)class

0 3 0 (IN: classes.union.tests SING&'$BN: foo UNIBN: blah foo !( Pstring)readerG (union)reset)test( parse)stream drop 3 unit)test 0 t 3 0 (blah( (classes.union.tests( lookup) ord union)class: 3 unit)test 0 t 3 0 (foo:( (classes.union.tests( lookup) ord predicate: 3 unit)test 0 3 0 (IN: classes.union.tests US': math UNIBN: blah integer !( Pstring)readerG (union)reset)test( parse)stream drop 3 unit)test 0 t 3 0 (blah( (classes.union.tests( lookup) ord union)class: 3 unit)test 0 f 3 0 (foo:( (classes.union.tests( lookup) ord predicate: 3 unit)test G'N'#I%: test)generic 5 x )) y 6

$U;&': a)tuple ! UNIBN: a)union a)tuple ! I: a)union test)generic ! 0 f 3 0 > test)generic (methods( 0 3 0 0 > a)tuple forget)class 3 0 t 3 0 > test)generic (methods( K @ast union predicates 0 t 3 0 integer union)of)builtins: 3 unit)test 0 t 3 0 > integer: defGG > fixnum)bitand s ap member: 3 unit)test 0 3 0 (IN: classes.union.tests US': math UNIBN: fast)union)1 fixnum ! UNIBN: fast)union), fast)union)1 bignum !( eval5 )) 6 3 unit)test 0 t 3 0 (fast)union),:( (classes.union.tests( lookup) ord defGG > fixnum)bitand s ap member: 3 unit)test 0 3 0 (IN: classes.union.tests US': vectors UNIBN: fast)union)1 vector !( eval5 )) 6 3 unit)test 0 f 3 0 (fast)union),:( (classes.union.tests( lookup) ord defGG > fixnum)bitand s ap member: 3 unit)test K $est union+ $U;&': stuff + a union+ integer string . . ! 0 0 0 0 = 3 0 stuff ne aGG 3 unit)test - 3 0 stuff ne - GGa aGG 3 unit)test (asdf( 3 0 stuff ne (asdf( GGa aGG 3 unit)test stuff ne -./ GGa aGG 3 0 bad)slot)value: 3 must)fail) ith ord)prop assoc)empty: 3 unit)test ith)compilation)unit 3 unit)test ord)prop assoc)empty: 3 unit)test

$U;&': things + a union+ integer float . . ! 0 0 0 0 = 3 0 stuff ne aGG 3 unit)test - 3 0 stuff ne - GGa aGG 3 unit)test (asdf( 3 0 stuff ne (asdf( GGa aGG 3 unit)test stuff ne -./ GGa aGG 3 0 bad)slot)value: 3 must)fail) ith

;#'CI%"$': numba)ova)1= P union+ float integer . 1= G ! 0 0 0 0 0 f t t f f 3 3 3 3 3 0 0 0 0 0 1==Q- numba)ova)1=: 3 unit)test 1== numba)ova)1=: 3 unit)test 1==.= numba)ova)1=: 3 unit)test A numba)ova)1=: 3 unit)test A.RA numba)ova)1=: 3 unit)test

K Issue Z/,= lol 0 (IN: issue)/,= UNIBN: omg omg !( eval5 )) 6 3 0 errorGG cannot)reference)self: 3 must)fail) ith IN: issue)/,= UNIBN: a ! UNIBN: b a !

0 (IN: issue)/,= UNIBN: a b !( eval5 )) 6 3 0 errorGG cannot)reference)self: 3 must)fail) ith K %opyright 5%6 ,==A< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes classes.algebra classes.algebra.private classes.builtin classes.private combinators definitions effects generic kernel kernel.private make math math.private memory namespaces quotations sequences sequences.private slots slots.private strings ords ! IN: classes.tuple ;#'CI%"$': tuple)class P class (metaclass( ord)prop tuple)class eq: ! '##B#: not)a)tuple obFect ! : all)slots 5 class )) slots 6 superclasses 0 (slots( ord)prop 3 map concat ! '##B#: no)slot name tuple ! : offset)of)slot 5 name tuple )) n 6 ,dup class)of all)slots slot)named 0 ,nip offsetGG 3 0 no)slot 3 if4 ! : get)slot)named 5 name tuple )) value 6 0 nip 3 0 offset)of)slot 3 ,bi slot ! : set)slot)named 5 value name tuple )) 6 0 nip 3 0 offset)of)slot 3 ,bi set)slot ! : set)slots 5 assoc tuple )) 6 0 s apd set)slot)named 3 curry assoc)each ! inline : from)slots 5 assoc class )) tuple 6 ne 0 set)slots 3 keep ! inline ;#'CI%"$': immutable)tuple)class P tuple)class all)slots 0 read)onlyGG 3 all: ! P;#IV"$' : tuple)layout 5 class )) layout 6 (layout( ord)prop ! : layout)of 5 tuple )) layout 6 1 slot + array . declare ! inline I: tuple class)of layout)of , slot + ord . declare ! inline

: tuple)si8e 5 tuple )) si8e 6 layout)of - slot + fixnum . declare ! inline : layout)up)to)date: 5 obFect )) : 6 dup tuple: 0 0 layout)of 3 0 class)of tuple)layout 3 bi eq: 3 0 drop t 3 if ! : check)tuple 5 obFect )) tuple 6 dup tuple: 0 not)a)tuple 3 unless ! inline : prepare)tupleGarray 5 tuple )) n tuple layout 6

check)tuple 0 tuple)si8e iota 3 0 3 0 layout)of 3 tri ! : copy)tuple)slots 5 n tuple )) array 6 0 array)nth 3 curry map ! : check)slots 5 seq class )) seq class 6 0 3 0 ,dup all)slots 0 classGG ,dup instance: 0 ,drop 3 0 bad)slot)value 3 if 3 ,each 3 if)bootstrapping ! inline : initial)values 5 class )) slots 6 all)slots 0 initialGG 3 map ! : pad)slots 5 slots class )) slots7 class 6 0 initial)values over length tail append 3 keep ! inline ;#IV"$'G : tupleGarray 5 tuple )) array 6 prepare)tupleGarray 0 copy)tuple)slots 3 dip first prefix ! : tuple)slots 5 tuple )) seq 6 prepare)tupleGarray drop copy)tuple)slots ! G'N'#I%: slotsGtuple 5 seq class )) tuple 6 I: tuple)class slotsGtuple 5 seq class )) tuple 6 check)slots pad)slots tuple)layout PtupleG 0 0 tuple)si8e iota 3 0 0 set)array)nth 3 curry 3 bi ,each 3 keep ! : Gtuple 5 seq )) tuple 6 unclip slotsGtuple ! '##B#: bad)superclass class ! : tupleH 5 tuple1 tuple, )) : 6 ,dup 0 tuple: 3 both: 0 ,dup 0 layout)of 3 bi9 eq: 0 0 drop tuple)si8e 3 0 0 0 drop array)nth 3 0 nip array)nth 3 -bi H 3 ,curry 3 ,bi all)integers: 3 0 ,drop f 3 if 3 0 ,drop f 3 if ! inline G'N'#I%: final)class: 5 obFect )) : 6 I: tuple)class final)class: (final( ord)prop !

I: builtin)class final)class: tuple eq: not ! I: class final)class: drop t ! I: obFect final)class: drop f !

P;#IV"$' : tuple)predicate)quotQ1 5 class )) quot 6 ZK @ast path for tuples ith no superclass 0 3 curry 0 layout)of R slot 3 0 eq: 3 surround 1quotation 0 dup tuple: 3 0 0 drop f 3 if 3 surround ! : tuple)instance: 5 obFect class offset )) : 6 rot dup tuple: 0 layout)of ,dup 1 slot fixnumPH 0 s ap slot eq: 3 0 -drop f 3 if 3 0 -drop f 3 if ! inline : layout)class)offset 5 echelon )) n 6 , 4 A 2 ! : tuple)predicate)quot 5 class echelon )) quot 6 layout)class)offset 0 tuple)instance: 3 ,curry ! : echelon)of 5 class )) n 6 tuple)layout third ! : define)tuple)predicate 5 class )) 6 dup dup echelon)of + + 1 0 tuple)predicate)quotQ1 3 . 0 tuple)predicate)quot 3 . case define)predicate ! : class)si8e 5 class )) n 6 superclasses 0 (slots( ord)prop length 3 map)sum ! : boa)check)quot 5 class )) quot 6 all)slots 0 classGG instance)check)quot 3 map shallo )spreadGquot f like ! : define)boa)check 5 class )) 6 dup boa)check)quot (boa)check( set) ord)prop ! : tuple)prototype 5 class )) prototype 6 0 initial)values 3 keep over 0 3 any: 0 slotsGtuple 3 0 ,drop f 3 if ! : define)tuple)prototype 5 class )) 6 dup tuple)prototype (prototype( set) ord)prop ! : prepare)slots 5 slots superclass )) slots7 6 0 make)slots 3 0 class)si8e , 2 3 bi4 finali8e)slots ! : define)tuple)slots 5 class )) 6 dup (slots( ord)prop over superclass prepare)slots define)accessors ! : make)tuple)layout 5 class )) layout 6 0 + 0 < 3 0 0 superclass class)si8e 3 0 (slots( ord)prop length 3 bi 2 < 3 0 superclasses length 1 ) < 3 0 superclasses 0 0 < 3 0 hashcode < 3 bi 3 each 3 . cleave

3 + . make ! : define)tuple)layout 5 class )) 6 dup make)tuple)layout (layout( set) ord)prop ! : compute)slot)permutation 5 ne )slots old)slots )) triples 6 0 0 0 nameGG 3 map 3 bi9 0 index 3 curry map 3 0 drop 0 classGG 3 map 3 0 drop 0 initialGG 3 map 3 ,tri -array flip ! : update)slot 5 old)values n class initial )) value 6 pick 0 0 0 s ap nth dup 3 dip instance: 3 dip s ap 0 drop 3 0 nip 3 if 3 0 0 -drop 3 dip 3 if ! : apply)slot)permutation 5 old)values triples )) ne )values 6 0 first- update)slot 3 ith map ! SNIEB&: outdated)tuples : permute)slots 5 old)values layout )) ne )values 6 0 first all)slots 3 0 outdated)tuples get at 3 bi compute)slot)permutation apply)slot)permutation ! : update)tuple 5 tuple )) ne tuple 6 0 tuple)slots 3 0 layout)of 3 bi 0 permute)slots 3 0 first 3 bi slotsGtuple ! : outdated)tuple: 5 tuple assoc )) : 6 0 0 layout)of 3 dip key: 3 0 drop class)of (forgotten( ord)prop not 3 ,bi and ! : update)tuples 5 )) 6 outdated)tuples get dup assoc)empty: 0 drop 3 0 0 0 tuple: 3 instances 3 dip 0 outdated)tuple: 3 curry filter dup 0 update)tuple 3 map become 3 if ! : update)tuples)after 5 class )) 6 0 all)slots 3 0 tuple)layout 3 bi outdated)tuples get set)at ! I: tuple)class update)class + 0 define)boa)check 3 0 define)tuple)layout 3 0 define)tuple)slots 3 0 define)tuple)predicate 3 0 define)tuple)prototype 3 . cleave ! : define)ne )tuple)class 5 class superclass slots )) 6 + 0 drop f f tuple)class define)class 3 0 nip (slots( set) ord)prop 3 0 ,drop update)classes 3 0 ,drop f (defining)class( set) ord)prop 3

. -cleave ! : subclasses 5 class )) classes 6 class)usages 0 tuple)class: 3 filter ! : each)subclass 5 class quot )) 6 0 subclasses 3 dip each ! inline : redefine)tuple)class 5 class superclass slots )) 6 0 ,drop 0 0 update)tuples)after 3 0 changed)conditionally 3 bi 3 each)subclass 3 0 define)ne )tuple)class 3 -bi ! : tuple)class)unchanged: 5 class superclass slots )) : 6 0 0 superclass 3 0 bootstrap) ord 3 bi4 H 3 0 0 (slots( ord)prop 3 dip H 3 bi)curry4 bi and ! : check)superclass 5 superclass )) 6 dup final)class: 0 bad)superclass 3 hen dup class: 0 bad)superclass 3 unless drop ! G'N'#I%Z 5define)tuple)class6 , 5 class superclass slots )) 6 : thro er)effect 5 slots )) effect 6 0 nameGG 3 map + (4( . PeffectG ! : error)slots 5 slots )) slots7 6 0 dup string: 0 1array 3 hen read)only s ap remove read)only suffix 3 map ! : reset)final 5 class )) 6 dup final)class: 0 0 f (final( set) ord)prop 3 0 changed)conditionally 3 bi 3 0 drop 3 if ! ;#IV"$'G : define)tuple)class 5 class superclass slots )) 6 over check)superclass over prepare)slots 5define)tuple)class6 ! G'N'#I%: make)final 5 class )) 6 I: tuple)class make)final 0 dup class)usage :metaclass)changed 3 0 t (final( set) ord)prop 3 bi ! I: ord 5define)tuple)class6

define)ne )tuple)class ! I: tuple)class 5define)tuple)class6 pick reset)final -dup tuple)class)unchanged: 0 ,drop :define)symbol 3 0 redefine)tuple)class 3 if ! ;#'CI%"$': error)class P tuple)class (error)class( ord)prop ! I: error)class reset)class 0 call)next)method 3 0 (error)class( remove) ord)prop 3 bi ! : define)error)class 5 class superclass slots )) 6 error)slots + 0 define)tuple)class 3 0 ,drop reset)generic 3 0 ,drop t (error)class( set) ord)prop 3 0 ,drop 0 dup 0 boa thro 3 curry 3 0 all)slots thro er)effect 3 bi define)declared 3 . -cleave ! : boa)effect 5 class )) effect 6 0 all)slots 0 nameGG 3 map 3 0 nameGG 1array 3 bi PeffectG ! '##B#: not)a)tuple)class obF ! : check)tuple)class 5 class )) class 6 dup tuple)class: 0 not)a)tuple)class 3 unless ! inline : define)boa) ord 5 ord class )) 6 check)tuple)class 0 0 boa 3 curry 3 0 boa)effect 3 bi define)inline ! : forget)slot)accessors 5 class slots )) 6 0 nameGG 0 reader) ord :lookup)method forget 3 0 riter) ord :lookup)method forget 3 ,bi 3 ith each ! I: tuple)class reset)class 0 dup (slots( ord)prop forget)slot)accessors 3 0 0 call)next)method 3 0 + (layout( (slots( (boa)check( (prototype( (final( . reset)props 3 bi 3 bi ! I: tuple)class metaclass)changed K Bur superclass is no longer a tuple class< redefine K default superclass nip tuple over (slots( ord)prop define)tuple)class ! I: tuple)class rank)class drop 1 ! I: tuple)class instance: ith

dup echelon)of layout)class)offset tuple)instance: ! I: tuple)class 5flatten)class6 dup << ! I: tuple)class 5classes)intersect:6 + + 0 over builtin)class: 3 0 drop tuple eq: 3 . + 0 over tuple)class: 3 0 0 classPH 3 0 s ap classPH 3 ,bi or 3 . . cond ! I: tuple clone 5clone6 ! inline I: tuple equal: over tuple: 0 tupleH 3 0 ,drop f 3 if ! : tuple)hashcode 5 depth obF )) hash 6 0 0 drop 1=====- 3 dip 0 class)of hashcode 3 0 tuple)si8e 3 bi 0 dup fixnum2fast S,A,= fixnum2fast 3 0 iota 3 bi 3 ,keep 0 s apd array)nth hashcode4 Gfixnum rot fixnum)bitxor pick fixnum4fast 0 0 fixnum2fast 3 keep 3 dip s ap 3 ,curry each drop nip URA-1 fixnum2fast ! inline I: tuple hashcode4 0 tuple)hashcode 3 recursive)hashcode ! I: tuple)class ne dup (prototype( ord)prop 0 5clone6 3 0 tuple)layout PtupleG 3 :if ! hen4 3

I: tuple)class boa 0 (boa)check( ord)prop 0 call 3 0 tuple)layout 3 bi Ptuple)boaG !

I: tuple)class initial)value4 ne t ! USING: accessors classes.tuple.parser lexer ords classes sequences math kernel slots tools.test parser compiler.units arrays classes.tuple eval multiline ! IN: classes.tuple.parser.tests $U;&': test)1 ! 0 t 3 0 test)1 (slots( ord)prop empty: 3 unit)test

$U;&': test), P test)1 ! 0 t 3 0 test), (slots( ord)prop empty: 3 unit)test 0 test)1 3 0 test), superclass 3 unit)test $U;&': test)- a ! 0 + (a( . 3 0 test)- (slots( ord)prop 0 nameGG 3 map 3 unit)test ord)prop slot)named classGG 3 unit)test

0 obFect 3 0 (a( test)- (slots( $U;&': test)/ P test)- b ! 0 + (b( . 3 0 test)/ (slots( $U;&': test)A + a integer . ! 0 + + (a( integer . . 3

ord)prop 0 nameGG 3 map 3 unit)test

0 test)A (slots( ord)prop 0 0 nameGG 3 0 classGG 3 bi ,array 3 map 3 unit)test $U;&': test)L P test)A + b integer . ! 0 integer 3 0 (b( test)L (slots( ord)prop slot)named classGG 3 unit)test

0 + + (b( integer . . 3 0 test)L (slots( ord)prop 0 0 nameGG 3 0 classGG 3 bi ,array 3 map 3 unit)test $U;&': test)R + b integer initial: - . ! 0 - 3 0 (b( test)R (slots( ord)prop slot)named initialGG 3 unit)test

$U;&': test)S + b integer read)only . ! 0 t 3 0 (b( test)S (slots( C'@'#: foo 0 (IN: classes.tuple.parser.tests $U;&': foo P test)1 P !( eval5 )) 6 3 0 errorGG invalid)slot)name: 3 must)fail) ith 0 (IN: classes.tuple.parser.tests $U;&': foo :( eval5 )) 6 3 0 errorGG invalid)slot)name: 3 must)fail) ith 0 (IN: classes.tuple.parser.tests $U;&': foo( eval5 )) 6 3 0 errorGG unexpected)eof: 3 must)fail) ith , 0 0 (IN: classes.tuple.parser.tests US': alien $U;&': foo + slot dll . !( eval5 )) 6 3 0 errorGG bad)initial)value: 3 must)fail) ith 0 f 3 0 > foo tuple)class: 3 unit)test 3 times , 0 0 (IN: classes.tuple.parser.tests US': arrays $U;&': foo + slot array initial: A . !( eval5 )) 6 3 0 errorGG bad)initial)value: 3 must)fail) ith 0 f 3 0 > foo tuple)class: 3 unit)test 3 times 0 (IN: classes.tuple.parser.tests US': arrays $U;&': foo slot + slot array . !( eval5 )) 6 3 0 errorGG duplicate)slot)names: 3 must)fail) ith 0 f 3 0 > foo tuple)class: 3 unit)test ord)prop slot)named read)onlyGG 3 unit)test

0 3 0 0

+ test)1 test), test)- test)/ test)A test)L test)R test)S foo . 0 dup class: 0 forget)class 3 0 drop 3 if 3 each 3 ith)compilation)unit 3 unit)test $U;&': syntax)test bar ba8 ! 0 $+ syntax)test . 3 0 $+ syntax)test . 3 unit)test 0 $+ syntax)test f + , - . + / + A . . . 3 0 $+ syntax)test + bar + , - . . + ba8 + / + A . . . . 3 unit)test K %orner case $U;&': parsing)corner)case x ! 0 $+ parsing)corner)case f - . 3 0 + (US': classes.tuple.parser.tests( ($+ parsing)corner)case( ( f( ( -( (.( . (>n( Foin eval5 )) tuple 6 3 unit)test 0 $+ parsing)corner)case f - . 3 0 + (US': classes.tuple.parser.tests( ($+ parsing)corner)case( ( + x - .( (.( . (>n( Foin eval5 )) tuple 6 3 unit)test 0 $+ parsing)corner)case f - . 3 0 + (US': classes.tuple.parser.tests( ($+ parsing)corner)case +( ( x - .( (.( . (>n( Foin eval5 )) tuple 6 3 unit)test 0

(US': classes.tuple.parser.tests $+ parsing)corner)case( ( + x - .( . (>n( Foin eval5 )) tuple 6 3 0 errorGG unexpected)eof: 3 must)fail) ith 0 (US': classes.tuple.parser.tests $+ parsing)corner)case +( ( x - .( . (>n( Foin eval5 )) tuple 6 3 0 errorGG unexpected)eof: 3 must)fail) ith $U;&': bad)inheritance)tuple ! 0 (IN: classes.tuple.parser.tests $U;&': bad)inheritance)tuple P +

bad)inheritance)tuple !( eval5 )) 6 3 0 errorGG bad)inheritance: 3 must)fail) ith $U;&': bad)inheritance)tuple, ! $U;&': bad)inheritance)tuple- P bad)inheritance)tuple, ! 0 (IN: classes.tuple.parser.tests $U;&': bad)inheritance)tuple, P bad)inheritance)tuple- !( eval5 )) 6 3 0 errorGG bad)inheritance: 3 must)fail) ith K $his must not fail $U;&': tup ! UNIBN: u tup ! 0 3 0 (IN: classes.tuple.parser.tests $U;&': u P tup !( eval5 )) 6 3 unit)test 0 t 3 0 u ne tup: 3 unit)test IN: classes.tuple.parser USING: strings help.markup help.syntax ! ?'&;: invalid)slot)name + *values + (name( string . . + *description ($hro s an ( + *link invalid)slot)name . ( error.( . + *error)description ($hro n by ( + *link ;BS$;BN': $U;&': . ( and ( + *link ;BS$;BN': '##B#: . ( if a suspect token appears as a slot name.( . + *notes ($he suspect tokens are chosen so that the follo ing code raises this parse error< instead of silently greating a tuple ith garbage slots:( + *code ($U;&': my)mistaken)tuple slot)a slot)b( (( (: some) ord 5 a b c )) 6 ... !( . . ! K %opyright 5%6 ,==S< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes.parser classes.tuple combinators kernel lexer make parser parser.notes sequences sets slots ! IN: classes.tuple.parser : slot)names 5 slots )) seq 6 0 dup array: 0 first 3 hen 3 map ! : shado ed)slots 5 superclass slots )) shado ed 6 0 all)slots 0 nameGG 3 map 3 0 slot)names 3 bi4 intersect ! : check)slot)shado ing 5 class superclass slots )) 6 shado ed)slots 0 0 (Cefinition of slot __( W W (77 in class __( W nameGG W (77 shado s a superclass slot( W 3 (( make note. 3 ith each ! '##B#: duplicate)slot)names names ! : check)duplicate)slots 5 slots )) 6 slot)names duplicates 0 duplicate)slot)names 3 unless)empty !

'##B#: invalid)slot)name name ! : parse)long)slot)name 5 )) spec 6 0 scan)token < > . parse)until W 3 + . make ! : parse)slot)name)delim 5 end)delim stringQf )) : 6 K %heck for mistakes of this form: K K $U;&': blahblah foo bing K K : ... + + 0 dup + (:( (5( (P( (>(( (K( . member: 3 0 invalid)slot)name 3 . + 0 ,dup H 3 0 drop f 3 . 0 dup (+( H 0 drop parse)long)slot)name 3 hen < t 3 . cond nip ! : parse)tuple)slots)delim 5 end)delim )) 6 dup scan)token parse)slot)name)delim 0 parse)tuple)slots)delim 3 0 drop 3 if ! : parse)slot)name 5 stringQf )) : 6 (!( s ap parse)slot)name)delim ! : parse)tuple)slots 5 )) 6 (!( parse)tuple)slots)delim ! : 5parse)tuple)definition6 5 ord )) class superclass slots 6 scan)token + + (!( 0 tuple f 3 . + (P( 0 scan) ord 0 parse)tuple)slots 3 + . make 3 . 0 tuple s ap 0 parse)slot)name 0 parse)tuple)slots 3 hen 3 + . make 3 . case dup check)duplicate)slots -dup check)slot)shado ing ! : parse)tuple)definition 5 )) class superclass slots 6 scan)ne )class 5parse)tuple)definition6 ! '##B#: bad)literal)tuple ! '##B#: bad)slot)name class slot ! : check)slot)name 5 class slots name )) name 6 ,dup s ap slot)named 0 ,nip 3 0 nip bad)slot)name 3 if ! : parse)slot)value 5 class slots )) 6 scan)token check)slot)name scan)obFect ,array < scan)token + + (.( 0 3 . 0 bad)literal)tuple 3 . case ! : 5parse)slot)values6 5 class slots )) 6 ,dup parse)slot)value scan)token + + (+( 0 5parse)slot)values6 3 . + (.( 0 ,drop 3 . 0 ,nip bad)literal)tuple 3 . case !

: parse)slot)values 5 class slots )) values 6 0 5parse)slot)values6 3 + . make ! G'N'#I%Z boaGobFect 1 5 class slots )) tuple 6 I: tuple)class boaGobFect s ap prefix Gtuple ! : check)slot)exists 5 class initials slot)specQf indexQf name )) class initials slot)spec index 6 over 0 drop 3 0 nip nip nip bad)slot)name 3 if ! : slot)named)checked 5 class initials name slots )) class initials slot)spec 6 over 0 slot)named4 3 dip check)slot)exists drop ! : assocGobFect 5 class slots values )) tuple 6 0 0 0 initialGG 3 map PenumG 3 keep 3 dip s ap 0 0 slot)named)checked 3 curry dip 3 curry assoc)map assoc)unionK seqGG boaGobFect ! : parse)tuple)literal)slots 5 class slots )) tuple 6 scan)token + + (f( 0 drop > . parse)until boaGobFect 3 . + (+( 0 ,dup parse)slot)values assocGobFect 3 . + (.( 0 drop ne 3 . 0 bad)literal)tuple 3 . case ! : parse)tuple)literal 5 )) tuple 6 scan) ord dup all)slots parse)tuple)literal)slots ! USING: accessors arrays assocs calendar classes classes.algebra classes.private classes.tuple classes.tuple.private columns compiler.errors compiler.units continuations definitions effects eval generic generic.single generic.standard grouping io.streams.string kernel kernel.private math math.constants math.order namespaces parser parser.notes prettyprint quotations random see sequences sequences.private slots slots.private splitting strings summary threads tools.test vectors vocabs ords ords.symbol fry literals memory combinators.short)circuit ! IN: classes.tuple.tests $U;&': rect x y : PrectG 5 x y h ! h )) rect 6 rect boa !

: move 5 x rect )) rect 6 0 2 3 change)x ! 0 f 3 0 1= ,= -= /= PrectG dup clone A s ap move H 3 unit)test 0 t 3 0 1= ,= -= /= PrectG dup clone = s ap move H 3 unit)test K Iake sure e handle tuple class redefinition $U;&': redefinition)test ! %: Predefinition)testG redefinition)test Predefinition)testG (redefinition)test( set 0 t 3 0 (redefinition)test( get redefinition)test: 3 unit)test (IN: classes.tuple.tests $U;&': redefinition)test !( eval5 )) 6

0 t 3 0 (redefinition)test( get redefinition)test: 3 unit)test K Iake sure e handle changing shapesK $U;&': point x y ! 0 3 0 1== ,== point boa (p( set 3 unit)test K Use eval to sequence parsing explicitly 0 3 0 (IN: classes.tuple.tests $U;&': point x y 8 !( eval5 )) 6 3 unit)test 0 1== 3 0 (p( get xGG 3 unit)test 0 ,== 3 0 (p( get yGG 3 unit)test 0 f 3 0 (p( get (8GG( (accessors( lookup) ord execute 3 unit)test 0 3 0 (p( get -== (GG8( (accessors( lookup) ord execute drop 3 unit)test 0 - 3 0 (p( get tuple)si8e 3 unit)test 0 -== 3 0 (p( get (8GG( (accessors( lookup) ord execute 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': point 8 y !( eval5 )) 6 3 unit)test 0 , 3 0 (p( get tuple)si8e 3 unit)test 0 (p( get xGG 3 must)fail 0 ,== 3 0 (p( get yGG 3 unit)test 0 -== 3 0 (p( get (8GG( (accessors( lookup) ord execute 3 unit)test $U;&': slotty a b c ! 0 $+ slotty . 3 0 ?+ . slotty from)slots 3 unit)test 0 $+ slotty f 1 , f . 3 0 ?+ + (a( 1 . + (b( , . . slotty from)slots 3 unit)test 0 ?+ + (d( = . . slotty ne set)slots 3 must)fail $U;&': predicate)test ! %: Ppredicate)testG predicate)test : predicate)test 5 a )) : 6 drop f ! 0 t 3 0 Ppredicate)testG predicate)test: 3 unit)test ;#'CI%"$': silly)pred P tuple class)of > rect H ! G'N'#I%: area 5 obF )) n 6 I: silly)pred area dup GG s ap hGG 4 ! $U;&': circle radius ! I: circle area radiusGG sq pi 4 ! 0 ,== 3 0 $+ rect f = = 1= ,= . area 3 unit)test K ?ashcode breakage $U;&': empty ! %: PemptyG empty 0 t 3 0 PemptyG hashcode fixnum: 3 unit)test K %ompiler regression

0 t length 3 0 obFectGG t eq: 3 must)fail) ith 0 (Pconstructor)testG( 3 0 (IN: classes.tuple.test $U;&': constructor)test ! %: Pconstructor)testG constructor)test( eval5 )) 6 last) ord nameGG 3 unit)test $U;&': si8e)test a b c d ! 0 t 3 0 $+ si8e)test . tuple)si8e si8e)test tuple)layout second H 3 unit)test G'N'#I%: Pyo)mommaG 5 a )) b 6 $U;&': yo)momma ! 0 3 0 (IN: classes.tuple.tests %: Pyo)mommaG yo)momma( eval5 )) 6 3 unit)test 0 f 3 0 > Pyo)mommaG generic: 3 unit)test K $est forget 0 0 t 3 0 > yo)momma class: 3 unit)test 0 3 0 > yo)momma forget 3 unit)test 0 3 0 > Pyo)mommaG forget 3 unit)test 0 f 3 0 > yo)momma update)map get values member)eq: 3 unit)test 3 ith)compilation)unit $U;&': loc)recording ! 0 f 3 0 > loc)recording K 7forget7 here not 3 unit)test

asn7t robust enough

$U;&': forget)robustness ! G'N'#I%: forget)robustness)generic 5 a )) b 6 I: forget)robustness forget)robustness)generic ! I: integer forget)robustness)generic ! 0 0 3 0 > forget)robustness)generic forget 3 unit)test 0 3 0 > forget)robustness forget 3 unit)test 0 3 0 I> forget)robustness forget)robustness)generic forget 3 unit)test ith)compilation)unit

K rapido found this one G'N'#I%Z m1 = 5 s n )) n 6 G'N'#I%Z m, 1 5 s n )) v 6 $U;&': t1 ! I: t1 m1 drop ! I: t1 m, nip ! $U;&': t, ! I: t, m1 drop ! I: t, m, nip !

$U;&': t- ! I: t- m1 drop ! I: t- m, nip ! $U;&': t/ ! I: t/ m1 drop ! I: t/ m, nip ! %: Pt/G t/ 0 1 3 0 1 Pt/G m1 3 unit)test 0 1 3 0 Pt/G 1 m, 3 unit)test K another combination issue G'N'#I%: silly 5 obF )) obF obF 6 UNIBN: my)union slice repetition column array vector reversed ! I: my)union silly (x( ! I: array silly (y( ! I: column silly (fdsfds( ! I: repetition silly (888( ! I: reversed silly (88( ! I: slice silly (tt( ! I: string silly (t( ! I: vector silly (8( ! 0 (88( 3 0 1,- PreversedG silly nip 3 unit)test K $ypo SNIEB&: not)a)tuple)class K Iissing check 0 not)a)tuple)class boa 3 must)fail 0 not)a)tuple)class ne 3 must)fail $U;&': erg7s)reshape)problem a b c d ! %: Perg7s)reshape)problemG erg7s)reshape)problem K Inheritance $U;&': computer cpu ram ! %: PcomputerG computer 0 ($U;&': computer cpu ram !( 3 0 0 > computer see 3 ith)string) riter string)lines second 3 unit)test $U;&': laptop P computer battery ! %: PlaptopG laptop 0 t 3 0 laptop tuple)class: 3 unit)test

0 t 3 0 laptop tuple classPH 3 unit)test 0 t 3 0 laptop computer classPH 3 unit)test 0 t 3 0 laptop computer classes)intersect: 3 unit)test 0 0 0 0 3 t t t 0 3 3 3 (;entium( 1,S - hours PlaptopG (laptop( set 3 unit)test 0 (laptop( get laptop: 3 unit)test 0 (laptop( get computer: 3 unit)test 0 (laptop( get tuple: 3 unit)test

: test)laptop)slot)values 5 )) 6 0 laptop 3 0 (laptop( get class)of 3 unit)test 0 (;entium( 3 0 (laptop( get cpuGG 3 unit)test 0 1,S 3 0 (laptop( get ramGG 3 unit)test 0 t 3 0 (laptop( get batteryGG - hours H 3 unit)test ! test)laptop)slot)values 0 ($U;&': laptop P computer battery !( 3 0 0 > laptop see 3 ith)string) riter string)lines second 3 unit)test 0 + tuple computer laptop . 3 0 laptop superclasses 3 unit)test $U;&': server P computer rackmount ! %: PserverG server 0 0 0 0 0 0 0 0 t t t t 3 t t t 3 3 3 3 0 3 3 3 0 0 0 0 server server server server tuple)class: 3 unit)test tuple classPH 3 unit)test computer classPH 3 unit)test computer classes)intersect: 3 unit)test

(;o er;%( L/ (1U( PserverG (server( set 3 unit)test 0 (server( get server: 3 unit)test 0 (server( get computer: 3 unit)test 0 (server( get tuple: 3 unit)test

: test)server)slot)values 5 )) 6 0 server 3 0 (server( get class)of 3 unit)test 0 (;o er;%( 3 0 (server( get cpuGG 3 unit)test 0 L/ 3 0 (server( get ramGG 3 unit)test 0 (1U( 3 0 (server( get rackmountGG 3 unit)test ! test)server)slot)values 0 f 3 0 (server( get laptop: 3 unit)test 0 f 3 0 (laptop( get server: 3 unit)test 0 f 3 0 server laptop classPH 3 unit)test 0 f 3 0 laptop server classPH 3 unit)test 0 f 3 0 laptop server classes)intersect: 3 unit)test 0 f 3 0 1 , PcomputerG laptop: 3 unit)test 0 f 3 0 > 2 server: 3 unit)test 0 ($U;&': server P computer rackmount !( 3 0 0 > server see 3 ith)string) riter string)lines second 3 unit)test 0 (IN: classes.tuple.tests $U;&': invalid)superclass P 3 must)fail ord !( eval5 )) 6

K Cynamically changing inheritance hierarchy $U;&': electronic)device ! : computer:7 5 a )) b 6 computer: ! 0 t 3 0 laptop ne computer:7 3 unit)test

0 3 0 (IN: classes.tuple.tests $U;&': computer P electronic)device cpu ram ! %: PcomputerG computer %: PlaptopG laptop %: PserverG server( eval5 )) 6 3 unit)test 0 t 3 0 laptop ne computer:7 3 unit)test

0 f 3 0 electronic)device laptop classPH 3 unit)test 0 t 3 0 server electronic)device classPH 3 unit)test 0 t 3 0 laptop server class)or electronic)device classPH 3 unit)test 0 0 0 0 0 0 0 0 t t t f t t f t 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 (laptop( (laptop( (laptop( (laptop( (server( (server( (server( (server( get get get get get get get get electronic)device: 3 unit)test computer: 3 unit)test laptop: 3 unit)test server: 3 unit)test electronic)device: 3 unit)test computer: 3 unit)test laptop: 3 unit)test server: 3 unit)test

0 3 0 (IN: classes.tuple.tests $U;&': computer cpu ram ! %: PcomputerG computer %: PlaptopG laptop %: PserverG server( eval5 )) 6 3 unit)test 0 f 3 0 (laptop( get electronic)device: 3 unit)test 0 t 3 0 (laptop( get computer: 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': computer P electronic)device cpu ram disk ! %: PcomputerG computer %: PlaptopG laptop %: PserverG server( eval5 )) 6 3 unit)test test)laptop)slot)values test)server)slot)values 0 3 0 (IN: classes.tuple.tests $U;&': electronic)device voltage ! %: PcomputerG computer %: PlaptopG laptop %: PserverG server( eval5 )) 6 3 unit)test test)laptop)slot)values test)server)slot)values $U;&': make)me)some)accessors voltage grounded: ! 0 f 3 0 (laptop( get voltageGG 3 unit)test 0 f 3 0 (server( get voltageGG 3 unit)test 0 3 0 (laptop( get ,,= GGvoltage drop 3 unit)test 0 3 0 (server( get 11= GGvoltage drop 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': electronic)device voltage grounded: ! %: PcomputerG computer( eval5 )) 6 3 unit)test test)laptop)slot)values test)server)slot)values 0 ,,= 3 0 (laptop( get voltageGG 3 unit)test 0 11= 3 0 (server( get voltageGG 3 unit)test

0 3 0 (IN: classes.tuple.tests $U;&': electronic)device grounded: voltage ! %: PcomputerG computer %: PlaptopG laptop %: PserverG server( eval5 )) 6 3 unit)test test)laptop)slot)values test)server)slot)values 0 ,,= 3 0 (laptop( get voltageGG 3 unit)test 0 11= 3 0 (server( get voltageGG 3 unit)test K #eshaping superclass and subclass simultaneously 0 3 0 (IN: classes.tuple.tests $U;&': electronic)device voltage ! $U;&': computer P electronic)device cpu ram ! %: PcomputerG computer %: PlaptopG laptop %: PserverG server( eval5 )) 6 3 unit)test test)laptop)slot)values test)server)slot)values 0 ,,= 3 0 (laptop( get voltageGG 3 unit)test 0 11= 3 0 (server( get voltageGG 3 unit)test K #eshape crash $U;&': test1 a ! $U;&': test, P test1 b ! (a( (b( test, boa (test( set : test)aQb 5 )) 6 0 (a( 3 0 (test( get aGG 3 unit)test 0 (b( 3 0 (test( get bGG 3 unit)test ! test)aQb 0 3 0 (IN: classes.tuple.tests $U;&': test1 a x ! $U;&': test, P test1 b y !( eval5 )) 6 3 unit)test test)aQb 0 3 0 (IN: classes.tuple.tests $U;&': test1 a ! $U;&': test, P test1 b !( eval5 )) 6 3 unit)test test)aQb K $ ice in the same compilation unit 0 test1 tuple + (a( (x( (y( . define)tuple)class test1 tuple + (a( (y( . define)tuple)class 3 ith)compilation)unit test)aQb K Ioving slots up and do n $U;&': move)up)1 a b ! $U;&': move)up), P move)up)1 c ! $+ move)up), f (a( (b( (c( . (move)up( set : test)move)up 5 )) 6 0 (a( 3 0 (move)up( get aGG 3 unit)test 0 (b( 3 0 (move)up( get bGG 3 unit)test 0 (c( 3 0 (move)up( get cGG 3 unit)test !

test)move)up 0 3 0 (IN: classes.tuple.tests $U;&': move)up)1 a b c ! $U;&': move)up), P move)up)1 !( eval5 )) 6 3 unit)test test)move)up 0 3 0 (IN: classes.tuple.tests $U;&': move)up)1 a c ! $U;&': move)up), P move)up)1 b !( eval5 )) 6 3 unit)test test)move)up 0 3 0 (IN: classes.tuple.tests $U;&': move)up)1 c ! $U;&': move)up), P move)up)1 b a !( eval5 )) 6 3 unit)test test)move)up 0 3 0 (IN: classes.tuple.tests $U;&': move)up)1 ! $U;&': move)up), P move)up)1 a b c !( eval5 )) 6 3 unit)test K %onstructors must be recompiled $U;&': constructor)update)1 xxx ! hen changing superclass

$U;&': constructor)update), P constructor)update)1 yyy 888 ! : Pconstructor)update),G 5 a b c )) tuple 6 constructor)update), boa ! + - 1 . 0 Pconstructor)update),G 3 must)infer)as 0 3 0 (IN: classes.tuple.tests $U;&': constructor)update)1 xxx ttt eval5 )) 6 3 unit)test + - 1 . 0 Pconstructor)update),G 3 must)infer)as 0 1 , - / A Pconstructor)update),G 3 0 not)compiled: 3 must)fail) ith 0 3 0 0 > Pconstructor)update),G forget 3 K #edefinition problem $U;&': redefinition)problem ! UNIBN: redefinition)problem7 redefinition)problem integer ! 0 t 3 0 - redefinition)problem7: 3 unit)test $U;&': redefinition)problem), ! (IN: classes.tuple.tests $U;&': redefinition)problem P redefinition)problem), !( eval5 )) 6 0 t 3 0 - redefinition)problem7: 3 unit)test K ?ardcore unit tests > thread (slots( 0 3 0 0 3 ord)prop (slots( set ith)compilation)unit 3 unit)test !(

> thread tuple + (xxx( . (slots( get append define)tuple)class ith)compilation)unit

0 1--R sleep 3 ($est( spa n drop 0 > thread tuple (slots( get define)tuple)class 3 ith)compilation)unit 3 unit)test > vocab (slots( 0 3 0 0 3 ord)prop (slots( set

> vocab identity)tuple + (xxx( . (slots( get append define)tuple)class ith)compilation)unit

all) ords drop 0 > vocab identity)tuple (slots( get define)tuple)class 3 ith)compilation)unit 3 unit)test 0 (US': ords $+ ord .( eval5 )) 6 3 0 errorGG $+ no)method f ord ne . H 3 must)fail) ith K "ccessors not being forgotten... 0 0 3 3 0 (IN: classes.tuple.tests $U;&': forget)accessors)test x y 8 !( Pstring)readerG (forget)accessors)test( parse)stream 3 unit)test 0 t 3 0 (forget)accessors)test( (classes.tuple.tests( lookup) ord class: 3 unit)test : accessor)exists: 5 name )) : 6 0 (forget)accessors)test( (classes.tuple.tests( lookup) ord 3 dip (GG( append (accessors( lookup) ord :lookup)method Gboolean ! 0 t 3 0 (x( accessor)exists: 3 unit)test 0 t 3 0 (y( accessor)exists: 3 unit)test 0 t 3 0 (8( accessor)exists: 3 unit)test 0 0 3 3 0 (IN: classes.tuple.tests G'N'#I%: forget)accessors)test 5 a )) b 6( Pstring)readerG (forget)accessors)test( parse)stream 3 unit)test 0 f 3 0 (forget)accessors)test( (classes.tuple.tests( lookup) ord class: 3 unit)test 0 f 3 0 (x( accessor)exists: 3 unit)test 0 f 3 0 (y( accessor)exists: 3 unit)test 0 f 3 0 (8( accessor)exists: 3 unit)test $U;&': another)forget)accessors)test !

0 0 3 3 0 (IN: classes.tuple.tests G'N'#I%: another)forget)accessors)test 5 a )) b 6( Pstring)readerG (another)forget)accessors)test( parse)stream 3 unit)test 0 t 3 0 > another)forget)accessors)test class: 3 unit)test K Shado ing test 0 f 3 0 f parser)quiet: 0 0 (IN: classes.tuple.tests $U;&': shado )1 a b ! $U;&': shado ), P shado )1 a b !( eval5 )) 6 3 ith)string) riter empty: 3 ith)variable 3 unit)test K Iissing error check 0 (IN: classes.tuple.tests US': 6 3 must)fail ords $U;&': rong)superclass P ord !( eval5 ))

K Insufficient type checking 0 > vocab tupleGarray drop 3 must)fail K %heck type declarations $U;&': declared)types + n fixnum . + m string . ! 0 $+ declared)types f = (hi( . 3 0 + declared)types = (hi( . Gtuple 3 unit)test 0 + declared)types (hi( = . Gtuple 3 0 $+ bad)slot)value f (hi( fixnum . H 3 must)fail) ith K %heck fixnum coercer 0 =.= (hi( declared)types boa nGG 3 0 $+ no)method f =.= integerGfixnum)strict . H 3 must)fail) ith 0 declared)types ne H 3 must)fail) ith =.= GGn nGG 3 0 $+ no)method f =.= integerGfixnum)strict .

0 $+ declared)types f ----- (asdf( . 3 0 ----- Gbignum (asdf( declared)types boa 3 unit)test 0 /////////////////////////////////////////////////----- Gbignum (asdf( declared)types boa 3 0 $+ out)of)fixnum)range f /////////////////////////////////////////////////----- . H 3 must)fail) ith K %heck bignum coercer $U;&': bignum)coercer + n bignum initial: *0 = Gbignum 3 . ! 0 1- bignum 3 0 1-.A bignum)coercer boa nGG dup class)of 3 unit)test 0 1- bignum 3 0 bignum)coercer ne K %heck float coercer $U;&': float)coercer + n float . ! 1-.A GGn nGG dup class)of 3 unit)test

0 1-.= float 3 0 1- float)coercer boa nGG dup class)of 3 unit)test 0 1-.= float 3 0 float)coercer ne 1- GGn nGG dup class)of 3 unit)test

K %heck integer coercer $U;&': integer)coercer + n integer . ! 0 1-.A integer)coercer boa nGG dup class)of 3 0 $+ bad)slot)value f 1-.A integer . H 3 must)fail) ith 0 integer)coercer ne 1-.A GGn nGG dup class)of 3 0 $+ bad)slot)value f 1-.A integer . H 3 must)fail) ith : foo 5 a b )) c 6 declared)types boa ! > foo defGG must)infer 0 =.= (hi( foo 3 0 $+ no)method f =.= integerGfixnum)strict . H 3 must)fail) ith 0 (hi( =.= declared)types boa 3 0 $+ no)method f (hi( integerGfixnum)strict . H 3 must)fail) ith 0 = + . declared)types boa 3 0 $+ bad)slot)value f + . string . H 3 must)fail) ith 0 (hi( =.= foo 3 0 $+ no)method f (hi( integerGfixnum)strict . H 3 must)fail) ith 0 = + . foo 3 0 $+ bad)slot)value f + . string . H 3 must)fail) ith 0 $+ declared)types f = (( . 3 0 declared)types ne : blah 5 )) vec 6 vector ne 0 vector ne 3 must)infer ! 3 unit)test

0 V+ . 3 0 blah 3 unit)test K $est reshaping ith type declarations and slot attributes $U;&': reshape)test x ! $+ reshape)test f (hi( . (tuple( set 0 3 0 (IN: classes.tuple.tests $U;&': reshape)test + x read)only . !( eval5 )) 6 3 unit)test 0 f 3 0 > reshape)test > xPP :lookup)method 3 unit)test 0 (tuple( get A GGx 3 must)fail 0 (hi( 3 0 (tuple( get xGG 3 unit)test 0 3 0 (IN: classes.tuple.tests US': math $U;&': reshape)test + x integer read)only . !( eval5 )) 6 3 unit)test 0 = 3 0 (tuple( get xGG 3 unit)test

0 3 0 (IN: classes.tuple.tests US': math $U;&': reshape)test + x fixnum initial: / read)only . !( eval5 )) 6 3 unit)test 0 = 3 0 (tuple( get xGG 3 unit)test $U;&': boa)coercer)test + x array)capacity . ! 0 fixnum 3 0 = Gbignum boa)coercer)test boa xGG class)of 3 unit)test 0 $+ boa)coercer)test f = . 3 0 $+ boa)coercer)test . 3 unit)test K $est error classes '##B#: error)class)test a b c ! 0 (5 a b c )) 4 6( 3 0 > error)class)test stack)effect effectGstring 3 unit)test 0 f 3 0 > error)class)test (inline( ord)prop 3 unit)test 0 (IN: classes.tuple.tests '##B#: error)x ! : error)x - !( eval5 )) 6 3 0 errorGG errorGG redefine)error: 3 must)fail) ith C'@'#: error)y 0 3 0 0 > error)y dup class: 0 forget)class 3 0 drop 3 if 3 ith)compilation)unit 3 unit)test 0 3 0 (IN: classes.tuple.tests G'N'#I%: error)y 5 a )) b 6( eval5 )) 6 3 unit)test 0 f 3 0 > error)y tuple)class: 3 unit)test 0 f 3 0 > error)y error)class: 3 unit)test 0 t 3 0 > error)y generic: 3 unit)test 0 3 0 (IN: classes.tuple.tests '##B#: error)y !( eval5 )) 6 3 unit)test 0 t 3 0 > error)y tuple)class: 3 unit)test 0 t 3 0 > error)y error)class: 3 unit)test 0 f 3 0 > error)y generic: 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': forget)subclass)test ! $U;&': forget)subclass)test7 P forget)subclass)test !( Pstring)readerG (forget)subclass)test( parse)stream drop 3 unit)test 0 3 0 (forget)subclass)test7( (classes.tuple.tests( lookup) ord ne set 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': forget)subclass)test a !( Pstring)readerG (forget)subclass)test( parse)stream drop 3 unit)test 0 3 0 (IN: sequences $U;&': reversed + seq read)only . !( eval5 )) 6 3 unit)test (bad)obFect(

$U;&': bogus)hashcode)1 x ! $U;&': bogus)hashcode), x ! I: bogus)hashcode)1 hashcode4 ,drop = Gbignum ! 0 3 0 $+ bogus)hashcode), f $+ bogus)hashcode)1 . . hashcode drop 3 unit)test C'@'#: change)slot)test S&B$: kex 0 3 0 (IN: classes.tuple.tests USING: kernel accessors ! $U;&': change)slot)test ! S&B$: kex I: change)slot)test kexGG drop - !( Pstring)readerG (change)slot)test( parse)stream drop 3 unit)test 0 t 3 0 > change)slot)test > kexGG :lookup)method Gboolean 3 unit)test 0 3 0 (IN: classes.tuple.tests USING: kernel accessors ! $U;&': change)slot)test kex !( Pstring)readerG (change)slot)test( parse)stream drop 3 unit)test 0 t 3 0 > change)slot)test > kexGG :lookup)method Gboolean 3 unit)test 0 3 0 (IN: classes.tuple.tests USING: kernel accessors ! $U;&': change)slot)test ! S&B$: kex I: change)slot)test kexGG drop - !( Pstring)readerG (change)slot)test( parse)stream drop 3 unit)test 0 t 3 0 > change)slot)test > kexGG :lookup)method Gboolean 3 unit)test 0 f 3 0 > change)slot)test > kexGG :lookup)method (reading( ord)prop 3 unit)test C'@'#: redefine)tuple)t ice 0 3 0 (IN: classes.tuple.tests $U;&': redefine)tuple)t ice !( eval5 )) 6 3 unit)test 0 t 3 0 > redefine)tuple)t ice symbol: 3 unit)test 0 3 0 (IN: classes.tuple.tests C'@'#: redefine)tuple)t ice( eval5 )) 6 3 unit)test 0 t 3 0 > redefine)tuple)t ice deferred: 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': redefine)tuple)t ice !( eval5 )) 6 3 unit)test 0 t 3 0 > redefine)tuple)t ice symbol: 3 unit)test '##B#: base)error x y ! '##B#: derived)error P base)error 8 ! 0 5 x y 8 )) 4 6 3 0 > derived)error stack)effect 3 unit)test

K Iake sure that tuple reshaping updates code heap roots $U;&': code)heap)ref ! : code)heap)ref7 5 )) a 6 $+ code)heap)ref . ! K ;ush foo7s literal to tenured space 0 3 0 gc 3 unit)test K #eshapeK 0 3 0 (IN: classes.tuple.tests US': math $U;&': code)heap)ref + x integer initial: A . !( eval5 )) 6 3 unit)test K %ode heap reference 0 t 3 0 code)heap)ref7 code)heap)ref: 3 unit)test 0 A 3 0 code)heap)ref7 xGG 3 unit)test K Cata heap reference 0 t 3 0 > code)heap)ref7 defGG first code)heap)ref: 3 unit)test 0 A 3 0 > code)heap)ref7 defGG first xGG 3 unit)test K If the metaclass of a superclass changes into something other K than a tuple class< the tuple needs to have its superclass reset $U;&': metaclass)change ! $U;&': metaclass)change)subclass P metaclass)change ! 0 metaclass)change 3 0 metaclass)change)subclass superclass 3 unit)test 0 3 0 (IN: classes.tuple.tests IIMIN: metaclass)change( eval5 )) 6 3 unit)test 0 t 3 0 metaclass)change)subclass tuple)class: 3 unit)test 0 tuple 3 0 metaclass)change)subclass superclass 3 unit)test K #eshaping bug related to the above $U;&': a)g ! $U;&': g P a)g ! 0 3 0 g ne (g( set 3 unit)test

0 3 0 (IN: classes.tuple.tests IIMIN: a)g $U;&': g !( eval5 )) 6 3 unit)test 0 t 3 0 g ne layout)of (g( get layout)of eq: 3 unit)test

K Xoe Groff discovered this bug C'@'#: factor)crashes)anymore 0 3 0 (IN: classes.tuple.tests $U;&': unsafe)slot)access ! %BNS$"N$: unsafe)slot)access7 $+ unsafe)slot)access .( eval5 )) 6 3 unit)test 0 3 0 (IN: classes.tuple.tests US': accessors $U;&': unsafe)slot)access + x read)only initial: -1--R . ! : factor)crashes)anymore 5 )) x 6 unsafe)slot)access7 xGG !( eval5 )) 6 3 unit)test 0 -1--R 3 0 factor)crashes)anymore 3 unit)test $U;&': tuple)predicate)redefine)test !

0 3 0 (IN: classes.tuple.tests $U;&': tuple)predicate)redefine)test !( eval5 )) 6 3 unit)test 0 t 3 0 > tuple)predicate)redefine)test: predicate: 3 unit)test K @inal classes $U;&': final)superclass ! $U;&': final)subclass P final)superclass ! 0 final)superclass 3 0 final)subclass superclass 3 unit)test K Iaking the superclass final should change the superclass of the subclass 0 3 0 (IN: classes.tuple.tests $U;&': final)superclass ! final( eval5 )) 6 3 unit)test 0 tuple 3 0 final)subclass superclass 3 unit)test 0 f 3 0 > final)subclass final)class: 3 unit)test K Subclassing a final class should fail 0 (IN: classes.tuple.tests $U;&': final)subclass P final)superclass !( eval5 )) 6 3 0 errorGG bad)superclass: 3 must)fail) ith K Iaking a final class non)final should ork 0 3 0 (IN: classes.tuple.tests $U;&': final)superclass !( eval5 )) 6 3 unit)test 0 3 0 (IN: classes.tuple.tests $U;&': final)subclass P final)superclass ! final( eval5 )) 6 3 unit)test K %hanging a superclass should not change the final status of a subclass 0 3 0 (IN: classes.tuple.tests $U;&': final)superclass x !( eval5 )) 6 3 unit)test 0 t 3 0 > final)subclass final)class: 3 unit)test K $est reset)class on tuples K Should forget all accessors on rclasstest $U;&': rclasstest a b ! 0 3 0 0 > rclasstest reset)class 3 ith)compilation)unit 3 unit)test 0 f 3 0 > rclasstest > aGG :lookup)method 3 unit)test 0 f 3 0 > rclasstest > aPP :lookup)method 3 unit)test 0 f 3 0 > rclasstest > bGG :lookup)method 3 unit)test 0 f 3 0 > rclasstest > bPP :lookup)method 3 unit)test PP > rclasstest forget GG K initial: should type check $U;&': initial)class ! C'@'#: initial)slot 0 3 0 (IN: classes.tuple.tests $U;&': initial)slot + x initial)class . !( eval5 )) 6 3 unit)test 0 t 3 0 initial)slot ne xGG initial)class: 3 unit)test

0 (IN: classes.tuple.tests $U;&': initial)slot + x initial)class initial: f . !( eval5 )) 6 3 0 errorGG $+ bad)initial)value f (x( f initial)class . H 3 must)fail) ith

0 (IN: classes.tuple.tests $U;&': initial)slot + x initial)class initial: - . !( eval5 )) 6 3 0 errorGG $+ bad)initial)value f (x( - initial)class . H 3 must)fail) ith 0 (IN: classes.tuple.tests US': math $U;&': foo P foo !( eval5 )) 6 3 0 errorGG bad)superclass: 3 must)fail) ith 0 (IN: classes.tuple.tests US': math $U;&': foo P 2 !( eval5 )) 6 3 0 errorGG bad)superclass: 3 must)fail) ith K $est no)slot error and getQset)slot)named $U;&': no)slot)tuple= a b c ! %: Pno)slot)tuple=G no)slot)tuple= 0 1 , - Pno)slot)tuple=G (d( over get)slot)named 3 0 + 0 no)slot: 3 0 tupleGG no)slot)tuple=: 3 0 nameGG (d( H 3 . 1`` 3 must)fail) ith + 1 . 0 1 , - Pno)slot)tuple=G (a( s ap get)slot)named 3 unit)test + , . 0 1 , - Pno)slot)tuple=G (b( s ap get)slot)named 3 unit)test + - . 0 1 , - Pno)slot)tuple=G (c( s ap get)slot)named 3 unit)test + / . 0 1 , - Pno)slot)tuple=G / (a( pick set)slot)named (a( s ap get)slot)named 3 unit)test 0 1 , - Pno)slot)tuple=G / (d( pick set)slot)named 3 0 + 0 no)slot: 3 0 tupleGG no)slot)tuple=: 3 0 nameGG (d( H 3 . 1`` 3 must)fail) ith USING: generic help.markup help.syntax kernel classes.tuple.private classes slots quotations ords arrays generic.standard sequences definitions compiler.units gro able vectors sbufs assocs math strings ! IN: classes.tuple "#$I%&': (slot)read)only)declaration( (#ead)only slots( (Ey default< all slots are ritable. If a slot is explicitly declared ( + *link read)only . (< then no riter method is generated for the slot< and the only ay to set it to a value other than its initial value is to construct an instance of the tuple ith ( + *link boa . (< passing the initial value for the read)only slot on the stack! the common idiom of calling ( + *link ne . ( and then immediately filling in slot values ith setter ords ill not ork ith read)only slots.( !

"#$I%&': (slot)class)declaration( (Slot class declarations( (%lass declaration is optional< and the default value is ( + *link obFect . (< the class of all obFects. If a more specific class is declared< then the obFect system maintains an invariant that the value of the slot must al ays be an instance of the class< even during construction. $his invariant is enforced at a number of locations:( + *list + (Jriter ords 5( + *link (accessors( . (6 thro an error if the ne value does not satisfy the class predicate.( . + ($he ( + *link ne . ( ord fills in slots ith their initial values! the 5per)class6 initial values are required to satisfy the class predicate.( . + ($he ( + *link boa . ( ord ensures that the values on the stack satisfy the class predicate.( . + + *link (mirrors( . ( ensure that the value passed to ( + *link set)at . ( satisfies the class predicate.( . + ($he ( + *link slotsGtuple . ( and ( + *link Gtuple . ( ords ensure that the values in the sequence satisfy the correct class predicates.( . + + *link (tuple)redefinition( . ( fills in ne slots ith initial values and ensures that changes to existing declarations result in incompatible values being replaced ith the initial value of their respective slots.( . . + *subsections (slot)class)coercion( . ! "#$I%&': (slot)class)coercion( (%oercive slot declarations( (If the class of a slot is declared to be one of ( + *link fixnum . ( or ( + *link float . (< then rather than testing values ith the class predicate< riter ords coerce values to the relevant type ith ( + *link Gfixnum . ( or ( + *link Gfloat . (. $his may still result in error< but permits a ider range of values than a class predicate test. It also results in a possible loss of precision! for example< storing a large integer into a ( + *link fixnum . ( slot ill silently overflo and discard high bits< and storing a ratio into a ( + *link float . ( slot may lose precision if the ratio is one hich cannot be represented exactly ith floating)point.( *nl ($his feature is mostly intended as an optimi8ation for lo )level code designed to avoid integer overflo < or here floating point precision is sufficient. Iost code needs to ork transparently ith large integers< and thus should avoid the coercion behavior by using ( + *link integer . ( and ( + *link real . ( in place of ( + *link fixnum . ( and ( + *link float . (.( ! "#$I%&': (tuple)declarations( ($uple slot declarations( ($he slot specifier syntax of the ( + *link ;BS$;BN': $U;&': . ( parsing understands the follo ing slot attributes:( + *list (class declaration: values must satisfy the class predicate( + ( hether a slot is read only or not 5( + *link read)only . (6( . + (an initial value 5( + *link initial: . (6( . . + *subsections (slot)read)only)declaration( (slot)class)declaration( (slot)initial)values( . ! ord

"#$I%&': (parametri8ed)constructors( (;arameteri8ed constructors( (" ( + *emphasis (parametri8ed constructor( . ( is a ord hich directly or indirectly calls ( + *link ne . ( or ( + *link boa . (< but instead of passing a literal class symbol< it takes the class symbol as an input from the stack.( *nl (;arametri8ed constructors are useful in many situations< in particular ith subclassing. @or example< consider the follo ing code:( + *code

($U;&': vehicle max)speed occupants !( (( (: add)occupant 5 person vehicle )) 6 occupantsGG push !( (( ($U;&': car P vehicle engine !( (: PcarG 5 max)speed engine )) car 6( ( car ne ( ( V+ . clone GGoccupants( ( s ap GGengine( ( s ap GGmax)speed !( (( ($U;&': aeroplane P vehicle max)altitude !( (: PaeroplaneG 5 max)speed max)altitude )) aeroplane 6( ( aeroplane ne ( ( V+ . clone GGoccupants( ( s ap GGmax)altitude( ( s ap GGmax)speed !( . ($he t o constructors depend on the implementation of ( + *snippet (vehicle( . ( because they are responsible for initiali8ing the ( + *snippet (occupants( . ( slot to an empty vector. If this slot is changed to contain a hashtable instead< there ill be t o places instead of one. " better approach is to use a parametri8ed constructor for vehicles:( + *code ($U;&': vehicle max)speed occupants !( (( (: add)occupant 5 person vehicle )) 6 occupantsGG push !( (( (: ne )vehicle 5 class )) vehicle 6( ( ne ( ( V+ . clone GGoccupants !( (( ($U;&': car P vehicle engine !( (: PcarG 5 max)speed engine )) car 6( ( car ne )vehicle( ( s ap GGengine( ( s ap GGmax)speed !( (( ($U;&': aeroplane P vehicle max)altitude !( (: PaeroplaneG 5 max)speed max)altitude )) aeroplane 6( ( aeroplane ne )vehicle( ( s ap GGmax)altitude( ( s ap GGmax)speed !( . ($he naming convention for parametri8ed constructors is ( + *snippet (ne )( + *emphasis (class( . . (.( ! "#$I%&': (tuple)constructors( ($uple constructors( ($uples are created by calling one of t o constructor primitives:( + *subsections ne boa . (" shortcut for defining EB" constructors:( + *subsections ;BS$;BN': %: . (Ey convention< construction logic is encapsulated in a ord named after the tuple class surrounded in angle brackets! for example< the constructor ord for a ( + *snippet (point( . ( class might be named ( + *snippet (PpointG( . (.( *nl (%onstructors play a part in enforcing the invariant that slot values must al ays match slot declarations. $he ( + *link ne . ( ord fills in the tuple ith initial values< and ( + *link boa . ( ensures that the values on the stack

match the corresponding slot declarations. See ( + *link (tuple)declarations( . (.( *nl ("ll tuple construction should be done through constructor ords< and construction primitives should be encapsulated and never called outside of the vocabulary here the class is defined< because this encourages looser coupling. @or example< a constructor ord could be changed to use memoi8ation instead of al ays constructing a ne instance< or it could be changed to construct a different class< ithout breaking callers.( *nl ('xamples of constructors:( + *code ($U;&': color( (+ red integer .( (+ green integer .( (+ blue integer .( (+ alpha integer initial: 1 . !( (( (K $he follo ing t o are equivalent( (%: PrgbaG color( (: PrgbaG color boa !( (( (K Je can define constructors hich call other constructors( (: PrgbG 5 r g b )) color 6 1 PrgbaG !( (( (K $he follo ing t o are equivalent! note the initial value( (: PcolorG 5 )) color 6 color ne !( (: PcolorG 5 )) color 6 = = = 1 PrgbaG !( (K #un)time error( (>(not a number>( , - / color boa( . + *subsections (parametri8ed)constructors( . ! "#$I%&': (tuple)inheritance)example( ($uple subclassing example( (#ectangles< parallelograms and circles are all shapes. Je support t o operations on shapes:( + *list (%omputing the area( (%omputing the perimeter( . (#ectangles and parallelograms use the same algorithm for computing the area< hereas they use different algorithms for computing perimeter. "lso< rectangles and parallelograms both have ( + *snippet ( idth( . ( and ( + *snippet (height( . ( slots. Je can exploit this ith subclassing:( + *code (USING: accessors kernel math math.constants math.functions !( (G'N'#I%: area 5 shape )) n 6( (G'N'#I%: perimeter 5 shape )) n 6( (( ($U;&': shape !( (( ($U;&': circle P shape radius !( (I: circle area radiusGG sq pi 4 !( (I: circle perimeter radiusGG , 4 pi 4 !( (( ($U;&': quad P shape idth height !( (I: quad area 0 idthGG 3 0 heightGG 3 bi 4 !( (( ($U;&': rectangle P quad !( (I: rectangle perimeter 0 idthGG , 4 3 0 heightGG , 4 3 bi 2 !( (( (: hypot 5 a b )) c 6 0 sq 3 bi9 2 sqrt !(

. !

(( ($U;&': parallelogram P quad ske !( (I: parallelogram perimeter( ( 0 idthGG , 4 3 0 0 heightGG 3 0 ske GG 3 bi hypot , 4 3 bi 2 !(

"#$I%&': (tuple)inheritance)anti)example( (Jhen not to use tuple subclassing( ($uple subclassing should only be used for ( + *emphasis (is)a( . ( relationships! for example< a car ( + *emphasis (is a( . ( vehicle< and a circle ( + *emphasis (is a( . ( shape.( + *heading ("nti)pattern Z1: subclassing for has)a( . (Subclassing should not be used for ( + *emphasis (has)a( . ( relationships. @or example< if a shape ( + *emphasis (has a( . ( color< then ( + *snippet (shape( . ( should not subclass ( + *snippet (color( . (. Using tuple subclassing in inappropriate situations leads to code hich is more brittle and less flexible than it should be.( *nl (@or example< suppose that ( + *snippet (shape( . ( inherits from ( + *snippet (color( . (:( + *code ($U;&': color r g b !( ($U;&': shape P color ... !( . (No < the implementation of ( + *snippet (shape( . ( depends on a specific representation of colors as #GE colors. If a ne generic color protocol is devised hich also allo s ?SE and NUV colors to be used< the shape class ill not be able to take advantage of them ithout changes. " better approach is to store the color in a slot:( + *code ($U;&': rgb)color r g b !( ($U;&': hsv)color h s v !( (...( ($U;&': shape color ... !( . ($he ( + *vocab)link (delegate( . ( library provides a language abstraction for expressing has)a relationships.( + *heading ("nti)pattern Z,: subclassing for implementation sharing only( . ($uple subclassing purely for sharing implementations of methods is not a good idea either. If a class ( + *snippet ("( . ( is a subclass of a class ( + *snippet (E( . (< then instances of ( + *snippet ("( . ( should be usable any here that an instance of ( + *snippet (E( . ( is. If this property does not hold< then subclassing should not be used.( *nl ($here are t o alternatives hich are preferred to subclassing in this case. $he first is ( + *link (mixins( . (.( *nl ($he second is to use ad)hoc slot polymorphism. If t o classes define a slot ith the same name< then code hich uses ( + *link (accessors( . ( can operate on instances of both obFects< assuming the values stored in that slot implement a common protocol. $his allo s code to be shared ithout creating contrived relationships bet een classes.( + *heading ("nti)pattern Z-: subclassing to override a method definition( . (Jhile method overriding is a very po erful tool< improper use can cause tight coupling of code and lead to difficulty in testing and refactoring. Subclassing should not be used as a means of ]monkey patching^ methods to fix bugs and add features. Bnly subclass from classes hich ere designed to be inherited from< and hen riting classes of your o n hich are intended to be subclassed< clearly document hat subclasses may and may not do. $his includes construction policy! document hether subclasses should use ( + *link ne . (< ( + *link boa . (< or a custom parametri8ed constructor.( + *see)also (parametri8ed)constructors( . !

"#$I%&': (tuple)subclassing( ($uple subclassing( ($uple subclassing can be used to express natural relationships bet een classes at the language level. @or example< every car ( + *emphasis (is a( . ( vehicle< so if the ( + *snippet (car( . ( class subclasses the ( + *snippet (vehicle( . ( class< it can ( + *emphasis (inherit( . ( the slots and methods of ( + *snippet (vehicle( . (.( *nl ($o define one tuple class as a subclass of another< use the optional superclass parameter to ( + *link ;BS$;BN': $U;&': . (:( + *code ($U;&': subclass P superclass ... !( . + *subsections (tuple)inheritance)example( (tuple)inheritance)anti)example( . (Ceclaring a tuple class final prohibits other classes from subclassing it:( + *subsections ;BS$;BN': final . + *see)also (call)next)method( (parametri8ed)constructors( (unions( (mixins( . ! "#$I%&': (tuple)introspection( ($uple introspection( (In addition to the slot reader and riter ords hich ( + *link ;BS$;BN': $U;&': . ( defines for every tuple class< it is possible to construct and take apart entire tuples in a generic ay.( + *subsections Gtuple tupleGarray tuple)slots . ($uples can be compared for slot equality even if the tuple class overrides ( + *link equal: . (:( + *subsections tupleH . ($uple classes can also be defined at run time:( + *subsections define)tuple)class . + *see)also (slots( (mirrors( . ! "#$I%&': (tuple)examples( ($uple examples( ("n example:( + *code ($U;&': employee name position salary !( . ($his defines a class ord named ( + *snippet (employee( . (< a predicate ( + *snippet (employee:( . (< and the follo ing slot accessors:( + *table + (#eader( (Jriter( (Setter( (%hanger( . + + *snippet (nameGG( . + *snippet (namePP( . + *snippet (GGname( . + *snippet (change)name( . . + + *snippet (positionGG( . + *snippet (positionPP( . + *snippet (GGposition( . + *snippet (change)position( . . + + *snippet (salaryGG( . + *snippet (salaryPP( . + *snippet (GGsalary( . + *snippet (change)salary( . . . (Je can define a constructor hich makes an empty employee:( + *code (: PemployeeG 5 )) employee 6( ( employee ne !( . (Br e may ish the default constructor to al ays give employees a starting salary:( + *code (: PemployeeG 5 )) employee 6( ( employee ne ( ( /==== GGsalary !( .

(Je can define more refined constructors:( + *code (: PmanagerG 5 )) manager 6( ( PemployeeG >(proFect manager>( GGposition !( . ("n alternative strategy is to define the most general EB" constructor first:( + *code (: PemployeeG 5 name position )) employee 6( ( /==== employee boa !( . (No e can define more specific constructors:( + *code (: PmanagerG 5 name )) employee 6( ( >(manager>( PemployeeG !( . ("n example using reader ords:( + *code ($U;&': check to amount number !( (( (SNIEB&: checks( (( (: PcheckG 5 to amount )) check 6( ( checks counter check boa !( (( (: bi eekly)paycheck 5 employee )) check 6( ( 0 nameGG 3 0 salaryGG ,L Q 3 bi PcheckG !( . ("n example of using a changer:( + *code (: positions 5 )) seq 6( ( +( ( >(Funior programmer>(( ( >(senior programmer>(( ( >(proFect manager>(( ( >(department manager>(( ( >(executive>(( ( >(%$B>(( ( >(%'B>(( ( >(enterprise Xava orld dictator>(( ( . !( (( (: next)position 5 role )) ne role 6( ( positions 0 index 1 2 3 keep nth !( (( (: promote 5 employee )) employee 6( ( 0 1., 4 3 change)salary( ( 0 next)position 3 change)position !( . ("n example using subclassing can be found in ( + *link (tuple)inheritance)example( . (.( ! "#$I%&': (tuple)redefinition( ($uple redefinition( (In the follo ing< the ( + *emphasis (direct slots( . ( of a tuple class refers to the slot names specified in the ( + *link ;BS$;BN': $U;&': . ( form defining the tuple class< and the ( + *emphasis (effective slots( . ( refers to the concatenation of the direct slots together ith slots defined on superclasses.( *nl (Jhen the ( + *emphasis (effective slots( . ( of a tuple class change< all instances of the class< including subclasses< are updated.( *nl ($here are three ays in hich the list of effective slots may change:( + *list ("dding or removing direct slots of the class( ("dding or removing direct slots of a superclass of the class(

. (In all cases< the ne effective slots are compared ith the old effective slots< and each instance is updated as follo s:( + *list (If any slots ere removed< the values are removed from the instance and are lost forever.( (If any slots ere added< the instance gains these slots< all set to their initial values.( (If any slots are permuted< their values in instances do not change! only the layout of the instance changes in memory.( (If the slot declaration of an existing slot changes< existing values are checked to see if they are still an instance of the required class. "ny hich are not are replaced by the initial value of that slot.( (If the number or order of effective slots changes< any EB" constructors are recompiled.( . (Note that if a slot is moved from a class to its superclass 5or vice versa6 in the same compilation unit< the value of the slot is preserved in existing instances< because tuple instance update al ays runs at the end of a compilation unit. ?o ever< if it is removed in one compilation unit and added in another< the value in existing instances is lost.( ! "#$I%&': (protocol)slots( (;rotocol slots( (" ( + *emphasis (protocol slot( . ( is one hich is assumed to exist by the implementation of a class< ithout being defined on the class itself. $he burden is on subclasses 5or mixin instances6 to provide this slot.( *nl (;rotocol slots are defined using a parsing ord:( + *subsections ;BS$;BN': S&B$: . (;rotocol slots are used here the implementation of a superclass needs to assume that each subclass defines certain slots< ho ever the slots of each subclass are potentially declared ith different class speciali8ers< thus preventing the slots from being defined in the superclass.( *nl (@or example< the ( + *link gro able . ( mixin provides an implementation of the sequence protocol hich raps an underlying sequence< resi8ing it as necessary hen elements are added beyond the length of the sequence. It assumes that the concrete mixin instances define t o slots< ( + *snippet (length( . ( and ( + *snippet (underlying( . (. $hese slots are defined as protocol slots: ( + *snippet (S&B$: length( . ( and ( + *snippet (S&B$: underlying( . (. ( ("n alternate approach ould be to define ( + *link gro able . ( as a tuple class ith these t o slots< and have other classes subclass it as required. ?o ever< this rules out subclasses defining these slots ith custom type declarations.( *nl (@or example< compare the definitions of the ( + *link sbuf . ( class<( + *code ($U;&': sbuf( (+ underlying string .( (+ length array)capacity . !( (( (INS$"N%': sbuf gro able( . ( ith that of the ( + *link vector . ( class:( + *code ($U;&': vector( (+ underlying array .( (+ length array)capacity . !( (( (INS$"N%': vector gro able(

(%hanging the inheritance hierarchy by changing the superclass of a class( (Ceclarations changing on existing slots(

. ! "#$I%&': (tuples( ($uples( ($uples are user)defined classes composed of named slots. $hey are the central data type of @actor7s obFect system.( + *subsections (tuple)examples( . (" parsing ord defines tuple classes:( + *subsections ;BS$;BN': $U;&': . (@or each tuple class< several ords are defined< the class ord< a class predicate< and accessor ords for each slot.( *nl ($he class ord is used for defining methods on the tuple class! it has the same name as the tuple class. $he predicate is named ( + *snippet + *emphasis (name( . (:( . (. Initially< no specific ords are defined for constructing ne instances of the tuple. %onstructors must be defined explicitly< and tuple slots are accessed via automatically)generated accessor ords.( + *subsections (accessors( (tuple)constructors( (tuple)subclassing( (tuple)declarations( (protocol)slots( (tuple)introspection( . ($uple classes can be redefined! this updates existing instances:( + *subsections (tuple)redefinition( . ($uple literal syntax is documented in ( + *link (syntax)tuples( . (.( ! "EBU$: (tuples( ?'&;: tuple)class + *class)description ($he class of tuple class ords.( . + *examples + *example (USING: classes.tuple prettyprint !( (IN: scratchpad( ($U;&': name title first last !( (name tuple)class: .( (t( . . ! ?'&;: tupleH + *values + (tuple1( tuple . + (tuple,( tuple . + (:( (a boolean( . . + *description (%hecks if t o tuples have equal slot values. $his is the default behavior of ( + *link H . ( on tuples< unless the tuple class subclasses ( + *link identity)tuple . ( or implements a method on ( + *link equal: . (. In cases here equality has been redefined< this ord can be used to get the default semantics if needed.( . ! ?'&;: tuple + *class)description ($he class of tuples. $his class is further partitioned into disFoint subclasses! each tuple shape defined by ( + *link ;BS$;BN': $U;&': . ( is a ne class.( *nl ($uple classes have additional ord properties:( + *list + + *snippet (>(predicate>(( . ( ) a quotation hich tests if the top of the stack is an instance of this tuple class( . + + *snippet (>(slots>(( . ( ) a sequence of ( + *link slot)spec . ( instances( . + + *snippet (>(layout>(( . ( ) an array ith the tuple si8e and superclasses encoded in a format amneable to fast method dispatch( . . . ! ?'&;: define)tuple)predicate + *values + (class( tuple)class . . + *description (Cefines a predicate ord that tests if the top of the stack is an instance of ( + *snippet (class( . (. $his ill only ork if ( + *snippet

(class( . ( is a tuple class.( . *lo )level)note ! ?'&;: redefine)tuple)class + *values + (class( class . + (superclass( class . + (slots( (a sequence of strings( . . + *description (If the ne slot layout differs from the existing one< updates all existing instances of this tuple class< and forgets any slot accessor ords hich are no longer needed.( *nl (If the class is not a tuple class ord< this ord does nothing.( . *lo )level)note ! ?'&;: tuple)slots + *values + (tuple( tuple . + (seq( sequence . . + *description (;ushes a sequence of tuple slot values< not including the tuple class ord.( . ! + tuple)slots tupleGarray . related) ords ?'&;: define)tuple)slots + *values + (class( tuple)class . . + *description (Cefines slot accessor and mutator *lo )level)note !

ords for the tuple.( .

?'&;: check)tuple + *values + (class( class . . + *description ($hro s a ( + *link check)tuple . ( error if ( + *snippet ( ord( . ( is not a tuple class ord.( . + *error)description ($hro n if ( + *link ;BS$;BN': %: . ( is called ith a hich does not name a tuple class.( . !

ord

?'&;: define)tuple)class + *values + (class( ord . + (superclass( class . + (slots( (a sequence of strings( . . + *description (Cefines a tuple class inheriting from ( + *snippet (superclass( . ( ith slots named by ( + *snippet (slots( . (. $his is the run time equivalent of ( + *link ;BS$;BN': $U;&': . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects (class( . ! + tuple)class define)tuple)class ;BS$;BN': $U;&': . related) ords ?'&;: Gtuple + *values + (seq( sequence . + (tuple( tuple . . + *description (%reates a tuple ith slot values taken from a sequence. $he first element of the sequence must be a tuple class ord and the remainder the declared slots.( *nl (If the sequence has too fe elements< the remaining slots in the tuple are set to their initial values.( . + *errors ($hro s an error if one of the follo ing occurs:( + *list (the first element of the sequence is not a tuple class ord( (the values in the sequence do not satisfy the slot class predicates( (the sequence is too long( . . ! ?'&;: tupleGarray + *values + (tuple( tuple . + (array( array . .

+ *description (Butputs an array having the tuple7s slots as elements. $he first element is the tuple class ord and remainder are declared slots.( . ! ?'&;: PtupleG + *values + (layout( (a tuple layout array( . + (tuple( tuple . . + *description (&o )level tuple constructor. User code should never call this directly< and instead use ( + *link ne . (.( . ! ?'&;: Ptuple)boaG + *values + (slots...( (values( . + (layout( (a tuple layout array( . + (tuple( tuple . . + *description (&o )level tuple constructor. User code should never call this directly< and instead use ( + *link boa . (.( . ! ?'&;: ne + *values + (class( tuple)class . + (tuple( tuple . . + *description (%reates a ne instance of ( + *snippet (class( . ( ith all slots set to their initial values 5see ( + *link (tuple)declarations( . (6.( . + *examples + *example (USING: kernel prettyprint !( (IN: scratchpad( ($U;&': employee number name department !( (employee ne .( ($+ employee .( . . ! ?'&;: boa + *values + (slots...( (slot values( . + (class( tuple)class . + (tuple( tuple . . + *description (%reates a ne instance of ( + *snippet (class( . ( and fill in the slots from the stack< ith the top)most stack element being stored in the right)most slot.( . + *notes ($he name ( + *snippet (boa( . ( is shorthand for ]by order of arguments^< and ]EB" constructor^ is a pun on ]boa constrictor^.( . + *errors ($hro s an error if the slot values do not match class declarations on slots 5see ( + *link (tuple)declarations( . (6.( . ! ?'&;: bad)superclass + *error)description ($hro n if an attempt is made to subclass a class that is not a tuple class< or a tuple class declared ( + *link ;BS$;BN': final . (.( . ! ?'&;: offset)of)slot + *values + (name( string . + (tuple( tuple . + (n( integer . . + *description (#eturns the offset of a tuple slot accessed by ( + *snippet (name( . (.( . ! ?'&;: get)slot)named + *values + (name( string . + (tuple( tuple . + (value( obFect . . + *description (#eturns the ( + *snippet (value( . ( stored in a tuple slot accessed by ( + *snippet (name( . (.( . ! ?'&;: set)slot)named + *values + (value( obFect . + (name( string . + (tuple( tuple . . + *description (Stores the ( + *snippet (value( . ( into a tuple slot accessed by ( + *snippet (name( . (.( . ! ?'&;: set)slots + *values + (assoc( assoc . + (tuple( tuple . . + *description (@or each ( + *snippet (+ key value .( . ( pair in ( + *snippet (assoc( . (< sets the ( + *snippet (key( . ( slot in ( + *snippet (obF( . ( to (

+ *snippet (value( . (.( . ! ?'&;: from)slots + *values + (assoc( assoc . + (class( tuple)class . + (tuple( tuple . . + *description (%reates a ne instance of ( + *snippet (class( . ( ith slot values specified by ( + *snippet (assoc( . (.( . ! USING: generic help.markup help.syntax kernel kernel.private namespaces sequences ords arrays help effects math layouts classes.private classes compiler.units ! IN: classes.intersection "#$I%&': (intersections( (Intersection classes( ("n obFect is an instance of a intersection class if it is an instance of all of its participants.( + *subsections ;BS$;BN': IN$'#S'%$IBN: . + *subsections define)intersection)class . (Intersection classes can be introspected:( + *subsections participants . ($he set of intersection classes is a class:( + *subsections intersection)class intersection)class: . (Intersection classes are used to associate a method ith obFects hich are simultaneously instances of multiple different classes< as ell as to conveniently define predicates.( ! "EBU$: (intersections( ?'&;: define)intersection)class + *values + (class( class . + (participants( (a sequence of classes( . . + *description (Cefines a intersection class ith specified participants. $his is the run time equivalent of ( + *link ;BS$;BN': IN$'#S'%$IBN: . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects (class( . ! + intersection)class define)intersection)class ;BS$;BN': IN$'#S'%$IBN: . related) ords ?'&;: intersection)class + *class)description ($he class of intersection classes.( . ! K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs classes classes.algebra classes.algebra.private classes.builtin classes.private combinators kernel make sequences ords ! IN: classes.intersection ;#'CI%"$': intersection)class P class (metaclass( ord)prop intersection)class eq: ! P;#IV"$' : intersection)predicate)quot 5 members )) quot 6 0 0 drop t 3 3 0 unclip predicate)def s ap 0 predicate)def 0 dup 3 0 not 3 surround 0 drop f 3 3 + . mapGassoc alistGquot

3 if)empty ! : define)intersection)predicate 5 class )) 6 dup participants intersection)predicate)quot define)predicate ! I: intersection)class update)class define)intersection)predicate ! I: intersection)class rank)class drop A ! I: intersection)class instance: (participants( ord)prop 0 instance: 3 ith all: !

I: anonymous)intersection instance: participantsGG 0 instance: 3 ith all: ! I: intersection)class normali8e)class participants Panonymous)intersectionG normali8e)class ! I: intersection)class 5flatten)class6 participants Panonymous)intersectionG 5flatten)class6 ! K ?orribly inefficient and inaccurate : intersect)flattened)classes 5 seq1 seq, )) seq- 6 K Bnly keep those in seq1 that intersect something in seq,. 0 0 classes)intersect: 3 ith any: 3 curry filter ! I: anonymous)intersection 5flatten)class6 participantsGG 0 full)cover 3 0 0 flatten)class keys 3 0 intersect)flattened)classes 3 map)reduce 0 dup << 3 each 3 if)empty ! I: anonymous)intersection class)name participantsGG 0 class)name 3 map ( ( Foin ! ;#IV"$'G : define)intersection)class 5 class participants )) 6 0 0 f f 3 dip intersection)class define)class 3 0 drop update)classes 3 ,bi ! USING: kernel tools.test generic generic.standard classes math accessors classes.intersection slots math.order ! IN: classes.intersection.tests $U;&': a ! $U;&': a1 P a ! $U;&': a, P a ! $U;&': a- P a, ! IIMIN: b INS$"N%': a- b INS$"N%': a1 b IN$'#S'%$IBN: c a, b ! G'N'#I%: x 5 a )) b 6 I: c x drop c ! I: a x drop a ! 0 a 3 0 $+ a . x 3 unit)test 0 a 3 0 $+ a1 . x 3 unit)test 0 a 3 0 $+ a, . x 3 unit)test

0 t 3 0 $+ a- . c: 3 unit)test 0 t 3 0 $+ a- . > x effective)method I> c x eq: nip 3 unit)test 0 c 3 0 $+ a- . x 3 unit)test K Iore $U;&': $U;&': $U;&': complex case t1 ! t, P t1 ! $U;&': t- P t1 ! t/ P t, ! $U;&': tA P t, !

UNIBN: m t/ tA t- ! IN$'#S'%$IBN: i t, m ! G'N'#I%: g 5 a )) b 6 I: i g drop i ! I: t/ g drop t/ ! 0 t/ 3 0 $+ t/ . g 3 unit)test 0 i 3 0 $+ tA . g 3 unit)test ;#'CI%"$': odd)integer P integer odd: ! K 0 $U;&': omg + a intersection+ fixnum odd)integer . initial: , . !( eval5 )) 6 3 K 0 bad)initial)value: 3 must)fail) ith $U;&': omg + a intersection+ fixnum odd)integer . initial: 1 . ! 0 1 3 0 omg ne aGG 3 unit)test 0 - 3 0 omg ne - GGa aGG 3 unit)test 0 omg ne 1., GGa aGG 3 0 bad)slot)value: 3 must)fail) ith ;#'CI%"$': oddQfloat)bet een)1=),= P union+ odd)integer float . 1= ,= bet een: ! 0 t 3 0 1R oddQfloat)bet een)1=),=: 3 unit)test 0 t 3 0 1R./ oddQfloat)bet een)1=),=: 3 unit)test 0 f 3 0 1S oddQfloat)bet een)1=),=: 3 unit)test 0 f 3 0 A oddQfloat)bet een)1=),=: 3 unit)test 0 f 3 0 A.RA oddQfloat)bet een)1=),=: 3 unit)test USING: math tools.test classes.algebra ords kernel sequences assocs accessors eval definitions compiler.units generic strings classes generic.single ! IN: classes.predicate.tests ;#'CI%"$': negative P integer = P ! ;#'CI%"$': positive P integer = G ! 0 0 0 0 0 0 t t f f f f 3 3 3 3 3 3 0 0 0 0 0 0 negative integer classP 3 unit)test positive integer classP 3 unit)test integer negative classP 3 unit)test integer positive classP 3 unit)test negative negative classP 3 unit)test positive negative classP 3 unit)test

G'N'#I%: abs 5 n )) n 6 I: integer abs ! I: negative abs )1 4 ! I: positive abs ! 0 1= 3 0 )1= abs 3 unit)test 0 1= 3 0 1= abs 3 unit)test

0 = 3 0 = abs 3 unit)test K Eug report from Eruno Ceferrari $U;&': tuple)a slot ! $U;&': tuple)b P tuple)a ! ;#'CI%"$': tuple)c P tuple)b slotGG ! G'N'#I%: ptest 5 tuple )) x 6 I: tuple)a ptest drop tuple)a ! I: tuple)c ptest drop tuple)c ! 0 tuple)a 3 0 tuple)b ne 0 tuple)c 3 0 tuple)b ne ptest 3 unit)test t GGslot ptest 3 unit)test

;#'CI%"$': tuple)d P tuple)a slotGG ! G'N'#I%: ptest7 5 tuple )) x 6 I: tuple)a ptest7 drop tuple)a ! I: tuple)d ptest7 drop tuple)d ! 0 tuple)a 3 0 tuple)b ne 0 tuple)d 3 0 tuple)b ne ptest7 3 unit)test t GGslot ptest7 3 unit)test

;#'CI%"$': bad)inheritance)predicate P string ! 0 (IN: classes.predicate.tests ;#'CI%"$': bad)inheritance)predicate P bad)inheritance)predicate !( eval5 )) 6 3 0 errorGG bad)inheritance: 3 must)fail) ith ;#'CI%"$': bad)inheritance)predicate, P string ! ;#'CI%"$': bad)inheritance)predicate- P bad)inheritance)predicate, ! 0 (IN: classes.predicate.tests ;#'CI%"$': bad)inheritance)predicate, P bad)inheritance)predicate- !( eval5 )) 6 3 0 errorGG bad)inheritance: 3 must)fail) ith K $his must not fail ;#'CI%"$': tup P string ! UNIBN: u tup ! 0 3 0 (IN: classes.predicate.tests ;#'CI%"$': u P tup !( eval5 )) 6 3 unit)test K %hanging the metaclass of the predicate superclass should G'N'#I%: change)meta)test 5 a )) b 6 $U;&': change)meta)test)class length ! ;#'CI%"$': change)meta)test)predicate P change)meta)test)class lengthGG , G ! I: change)meta)test)predicate change)meta)test lengthGG ! 0 f 3 0 > change)meta)test (methods( ord)prop assoc)empty: 3 unit)test ork

0 $+ change)meta)test)class f = . change)meta)test 3 0 no)method: 3 must)fail) ith 0 R 3 0 $+ change)meta)test)class f R . change)meta)test 3 unit)test 0 3 0 (IN: classes.predicate.tests US': arrays UNIBN: change)meta)test)class array !( eval5 )) 6 3 unit)test K Should not have changed

0 change)meta)test)class 3 0 change)meta)test)predicate superclass 3 unit)test 0 + . change)meta)test 3 0 no)method: 3 must)fail) ith 0 / 3 0 + 1 , - / . change)meta)test 3 unit)test 0 3 0 0 > change)meta)test)class forget)class 3 unit)test ith)compilation)unit 3

0 f 3 0 change)meta)test)predicate class: 3 unit)test 0 t 3 0 > change)meta)test (methods( ord)prop assoc)empty: 3 unit)test USING: generic help.markup help.syntax kernel kernel.private namespaces sequences ords arrays layouts help effects math classes.private classes compiler.units ! IN: classes.predicate "#$I%&': (predicates( (;redicate classes( (;redicate classes allo fine)grained control over method dispatch.( + *subsections ;BS$;BN': ;#'CI%"$': define)predicate)class . ($he set of predicate classes is a class:( + *subsections predicate)class predicate)class: . ! "EBU$: (predicates( ?'&;: define)predicate)class + *values + (class( class . + (superclass( class . + (definition( + *quotation (5 superclass )) : 6( . . . + *description (Cefines a predicate class. $his is the run time equivalent of ( + *link ;BS$;BN': ;#'CI%"$': . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects (class( . ! + predicate)class define)predicate)class ;BS$;BN': ;#'CI%"$': . related) ords ?'&;: predicate)class + *class)description ($he class of predicate class ords< defined by ( + *link ;BS$;BN': ;#'CI%"$': . ( and documented in ( + *link (predicates( . (.( . ! K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: classes classes.algebra classes.algebra.private classes.private kernel make ords ! IN: classes.predicate ;#'CI%"$': predicate)class P class (metaclass( ord)prop predicate)class eq: ! P;#IV"$' G'N'#I%: predicate)quot 5 class )) quot 6 I: predicate)class predicate)quot 0 > dup < 0 superclass predicate)def W 3 0 (predicate)definition( ord)prop < 3 bi 0 drop f 3 < > if <

3 0 3 make ! ;#IV"$'G : define)predicate)class 5 class superclass definition )) 6 0 drop f f predicate)class define)class 3 0 nip (predicate)definition( set) ord)prop 3 0 ,drop 0 dup predicate)quot define)predicate 3 0 update)classes 3 bi 3 -tri ! I: predicate)class reset)class 0 call)next)method 3 0 + (predicate)definition( . reset)props 3 bi ! I: predicate)class rank)class drop , ! I: predicate)class instance: ,dup superclass instance: 0 (predicate)definition( ord)prop call5 obFect )) : 6 3 0 ,drop f 3 if ! I: predicate)class 5flatten)class6 superclass 5flatten)class6 ! I: predicate)class 5classes)intersect:6 superclass classes)intersect: ! K %opyright 5%6 ,=11 Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: classes.maybe eval generic.single kernel tools.test math classes accessors slots classes.algebra classes.algebra.private ! IN: classes.maybe.tests 0 t 3 0 - maybe+ integer . instance: 3 unit)test 0 t 3 0 f maybe+ integer . instance: 3 unit)test 0 f 3 0 -.= maybe+ integer . instance: 3 unit)test $U;&': maybe)integer)container + something maybe+ integer . . ! 0 f 3 0 maybe)integer)container ne somethingGG 3 unit)test 0 - 3 0 maybe)integer)container ne - GGsomething somethingGG 3 unit)test 0 maybe)integer)container ne -.= GGsomething 3 0 bad)slot)value: 3 must)fail) ith $U;&': self)pointer + next maybe+ self)pointer . . ! 0 $+ self)pointer + next $+ self)pointer . . . 3 0 self)pointer ne self)pointer ne GGnext 3 unit)test 0 t 3 0 f maybe+ ;BS$;BN': f . instance: 3 unit)test ;#'CI%"$': natural P maybe+ integer . = G ! 0 f 3 0 )1 natural: 3 unit)test 0 f 3 0 = natural: 3 unit)test 0 t 3 0 1 natural: 3 unit)test 0 t 3 0 f maybe+ maybe+ integer . . instance: 3 unit)test

0 t 3 0 - maybe+ maybe+ integer . . instance: 3 unit)test 0 f 3 0 -.=- maybe+ maybe+ integer . . instance: 3 unit)test IN$'#S'%$IBN: only)f maybe+ integer . ;BS$;BN': f ! 0 t 3 0 f only)f instance: 3 unit)test 0 f 3 0 t only)f instance: 3 unit)test 0 f 3 0 -= only)f instance: 3 unit)test UNIBN: :integer)float maybe+ integer . maybe+ float . ! 0 0 0 0 t t t f 3 3 3 3 0 0 0 0 -= :integer)float instance: 3 unit)test -=.= :integer)float instance: 3 unit)test f :integer)float instance: 3 unit)test t :integer)float instance: 3 unit)test

$U;&': foo ! G'N'#I%: lol 5 obF )) string 6 I: maybe+ foo . lol drop (lol( ! 0 (lol( 3 0 foo ne lol 3 unit)test 0 (lol( 3 0 f lol 3 unit)test 0 - lol 3 0 no)method: 3 must)fail) ith $U;&': foo, a ! G'N'#I%: lol, 5 obF )) string 6 I: maybe+ foo . lol, drop (lol,( ! I: f lol, drop (lol,,( ! 0 (lol,( 3 0 foo ne lol, 3 unit)test 0 (lol,,( 3 0 f lol, 3 unit)test 0 - lol, 3 0 no)method: 3 must)fail) ith 0 t 3 0 > 2 PmaybeG classoid: 3 unit)test 0 f 3 0 > 2 PmaybeG valid)classoid: 3 unit)test 0 (IN: classes)tests maybe+ 1 , - .( eval5 )) 6 3 0 errorGG not)classoids: 3 must)fail) ith K %opyright 5%6 ,=11 Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays classes classes.algebra classes.algebra.private classes.private classes.union.private kernel ords ! IN: classes.maybe K $he class slot has to be a union of a ord and a classoid K for $U;&': foo + a maybe+ foo . . ! and maybe+ union+ integer float . . K to ork. K In the first case< foo is not yet a tuple)class hen maybe+ is reached< K thus it7s not a classoid yet. union+ is a classoid< so the second case orks. K ords are not generally classoids< so classoid alone is insufficient. $U;&': maybe + class union+ ord classoid . initial: obFect read)only . ! %: PmaybeG maybe INS$"N%': maybe classoid I: maybe instance: over 0 classGG instance: 3 0 ,drop t 3 if ! : maybe)class)or 5 maybe )) classoid 6 classGG > f class)or !

I: maybe normali8e)class maybe)class)or ! I: maybe valid)classoid: classGG valid)classoid: ! I: maybe rank)class drop L ! I: maybe 5flatten)class6 maybe)class)or 5flatten)class6 ! I: maybe union)of)builtins: classGG union)of)builtins: ! I: maybe class)name classGG class)name ! I: maybe predicate)def classGG predicate)def 0 0 t 3 if4 3 curry ! I: maybe classes)contained)by classGG 1array ! USING: alien arrays generic assocs hashtables io io.streams.string kernel math namespaces parser prettyprint sequences strings tools.test vectors ords quotations classes classes.private classes.union classes.mixin classes.predicate classes.algebra definitions source)files compiler.units kernel.private sorting vocabs memory eval accessors sets ! IN: classes.tests 0 0 0 0 0 t t f t f 3 3 3 3 3 0 0 0 0 0 obFect instance: 3 unit)test fixnum instance: 3 unit)test float instance: 3 unit)test number instance: 3 unit)test null instance: 3 unit)test

K #egression G'N'#I%: method)forget)test 5 obF )) obF 6 $U;&': method)forget)class ! I: method)forget)class method)forget)test ! 0 f 3 0 > method)forget)test (methods( 0 3 0 0 > method)forget)class forget 3 0 t 3 0 > method)forget)test (methods( 0 + . + . 3 0 all) ords 0 class: 3 filter implementors)map get keys 0 natural)sort 3 bi9 0 diff 3 0 s ap diff 3 ,bi 3 unit)test K &ong)standing problem US': multiline K So the user has some code... 0 3 0 (((IN: classes.test.a G'N'#I%: g 5 a )) b 6 $U;&': x ! I: x g ! $U;&': 8 P x !((( Pstring)readerG ord)prop assoc)empty: 3 unit)test ith)compilation)unit 3 unit)test ord)prop assoc)empty: 3 unit)test

(class)intersect)no)method)a( parse)stream drop 3 unit)test K Note that q inlines I: x g ! 0 3 0 (((IN: classes.test.b US': classes.test.a US': kernel : q 5 )) b 6 8 ne g !((( Pstring)readerG (class)intersect)no)method)b( parse)stream drop 3 unit)test K No < the user removes the 8 class and adds a method< 0 3 0 (((IN: classes.test.a G'N'#I%: g 5 a )) b 6 $U;&': x ! I: x g ! $U;&': F ! I: F g !((( Pstring)readerG (class)intersect)no)method)a( parse)stream drop 3 unit)test K "nd changes the definition of q 0 3 0 (((IN: classes.test.b US': classes.test.a US': kernel : q 5 )) b 6 F ne g !((( Pstring)readerG (class)intersect)no)method)b( parse)stream drop 3 unit)test K Similar problem< but ith anonymous classes 0 3 0 (((IN: classes.test.c US': kernel G'N'#I%: g 5 a )) b 6 I: obFect g ! $U;&': 8 !((( Pstring)readerG (class)intersect)no)method)c( parse)stream drop 3 unit)test 0 3 0 (((IN: classes.test.d US': classes.test.c US': kernel : q 5 a )) b 6 dup 8: 0 g 3 unless !((( Pstring)readerG (class)intersect)no)method)d( parse)stream drop 3 unit)test K No < the user removes the 8 class and adds a method< 0 3 0 (((IN: classes.test.c US': kernel G'N'#I%: g 5 a )) b 6 I: obFect g ! $U;&': F ! I: F g !((( Pstring)readerG (class)intersect)no)method)c( parse)stream drop 3 unit)test K @orget the above crap

0 3 + (classes.test.a( (classes.test.b( (classes.test.c( (classes.test.d( . 0 forget)vocab 3 each ith)compilation)unit

$U;&': forgotten)predicate)test ! 0 3 0 0 > forgotten)predicate)test forget 3 ith)compilation)unit 3 unit)test 0 f 3 0 > forgotten)predicate)test: predicate: 3 unit)test G'N'#I%: generic)predicate: 5 a )) b 6 0 3 0 (IN: classes.tests $U;&': generic)predicate !( eval5 )) 6 3 unit)test 0 f 3 0 > generic)predicate: generic: 3 unit)test K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: classes classes.algebra.private classes.private kernel kernel.private make namespaces sequences ords ! IN: classes.builtin SNIEB&: builtins ;#'CI%"$': builtin)class P class (metaclass( ord)prop builtin)class eq: ! '##B#: not)a)builtin obFect ! : check)builtin 5 class )) 6 dup builtin)class: 0 drop 3 0 not)a)builtin 3 if ! : classGtype 5 class )) n 6 (type( ord)prop ! foldable

: typeGclass 5 n )) class 6 builtins get)global nth ! foldable : bootstrap)typeGclass 5 n )) class 6 builtins get nth ! I: obFect class)of tag typeGclass ! inline I: builtin)class rank)class drop = ! I: builtin)class instance: 0 tag 3 0 classGtype 3 bi4 eq: ! I: builtin)class 5flatten)class6 dup << ! I: builtin)class 5classes)intersect:6 eq: ! : full)cover 5 )) 6 builtins get 0 5flatten)class6 3 each ! I: anonymous)complement 5flatten)class6 drop full)cover ! USING: help.syntax help.markup classes layouts ! IN: classes.builtin "#$I%&': (builtin)classes( (Euilt)in classes( ('very obFect is an instance of exactly one canonical ( + *emphasis (built)in class( . ( hich defines its layout in memory and basic behavior.( *nl ($he set of built)in classes is a class:( + *subsections builtin)class builtin)class: .

(See ( + *link (class)index( . ( for a list of built)in classes.( ! ?'&;: builtin)class + *class)description ($he class of built)in classes.( . + *examples ($he class of arrays is a built)in class:( + *example (USING: arrays classes.builtin prettyprint !( (array builtin)class: .( (t( . (?o ever< an instance of the array class is not a built)in class! it is not even a class:( + *example (USING: classes.builtin prettyprint !( (+ 1 , - . builtin)class: .( (f( . . ! ?'&;: builtins + *var)description (Vector mapping type numbers to builtin class ords.( . !

?'&;: typeGclass + *values + (n( (a non)negative integer( . + (class( class . . + *description (Butputs a builtin class hose instances are precisely those having a given pointer tag.( . + *notes ($he parameter ( + *snippet (n( . ( must be bet een = and the return value of ( + *link num)types . (.( . ! USING: tools.test ords sequences kernel memory accessors ! IN: classes.builtin.tests 0 f 3 0 0 ord: 3 instances 0 0 nameGG (f:( H 3 0 vocabularyGG (syntax( H 3 bi and 3 any: 3 unit)test K %opyright 5%6 ,==S< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: classes compiler.units kernel parser vocabs.parser IN: classes.parser : save)class)location 5 class )) 6 location remember)class ! : create)class)in 5 string )) ord 6 current)vocab create dup t (defining)class( set) ord)prop dup set)last) ord dup save)class)location dup create)predicate) ord save)location ! : scan)ne )class 5 )) ord 6 scan) ord)name create)class)in ! K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs combinators definitions kernel make namespaces quotations sequences sets ords ords.symbol ! @#BI: namespaces HG set ! DU"&I@I'C: sets IN: classes '##B#: bad)inheritance class superclass ! ;#'CI%"$': class P ord (class( ord)prop !

ords !

;#'CI%"$': defining)class P

ord (defining)class(

ord)prop !

IIMIN: classoid INS$"N%': class classoid INS$"N%': defining)class classoid P;#IV"$' SNIEB&: SNIEB&: SNIEB&: SNIEB&: SNIEB&: SNIEB&: classPH)cache class)not)cache classes)intersect)cache class)and)cache class)or)cache next)method)quot)cache

: init)caches 5 )) 6 ?+ . clone classPH)cache set ?+ . clone class)not)cache set ?+ . clone classes)intersect)cache set ?+ . clone class)and)cache set ?+ . clone class)or)cache set ?+ . clone next)method)quot)cache set ! : reset)caches 5 )) 6 classPH)cache get clear)assoc class)not)cache get clear)assoc classes)intersect)cache get clear)assoc class)and)cache get clear)assoc class)or)cache get clear)assoc next)method)quot)cache get clear)assoc ! SNIEB&: update)map SNIEB&: implementors)map G'N'#I%: class)name 5 class )) string 6 I: class class)name nameGG ! G'N'#I%: rank)class 5 class )) n 6 G'N'#I%: reset)class 5 class )) 6 I: class reset)class + (defining)class( (class( (metaclass( (superclass( (members( (participants( (predicate( . reset)props ! I: ord reset)class drop !

;#IV"$'G : classes 5 )) seq 6 implementors)map get keys ! ;#'CI%"$': predicate P ord (predicating( ord)prop Gboolean !

: create)predicate) ord 5 ord )) predicate 6 0 nameGG (:( append 3 0 vocabularyGG 3 bi create dup predicate: 0 dup reset)generic 3 unless ! G'N'#I%: class)of 5 obFect )) class 6 G'N'#I%: instance: 5 obFect class )) : 6 flushable G'N'#I%: predicate)def 5 obF )) quot 6 I: ord predicate)def (predicate( ord)prop !

I: obFect predicate)def 0 instance: 3 curry ! : predicate) ord 5 ord )) predicate 6 predicate)def first ! I: predicate flushable: drop t ! I: predicate forget4 0 call)next)method 3 0 f (predicating( set) ord)prop 3 bi ! I: predicate reset) ord 0 call)next)method 3 0 f (predicating( set) ord)prop 3 bi ! : define)predicate 5 class quot )) 6 0 predicate) ord 3 dip 5 obFect )) : 6 define)declared ! : superclass 5 class )) super 6 ZK Butput f for non)classes to ork ith algebra code dup class: 0 (superclass( ord)prop 3 0 drop f 3 if ! : superclasses 5 class )) supers 6 0 superclass 3 follo reverseK ! : superclass)of: 5 class superclass )) : 6 superclasses member)eq: ! : subclass)of: 5 class superclass )) : 6 s ap superclass)of: ! : members 5 class )) seq 6 ZK Butput f for non)classes to ork ith algebra code dup class: 0 (members( ord)prop 3 0 drop f 3 if ! : participants 5 class )) seq 6 ZK Butput f for non)classes to ork ith algebra code dup class: 0 (participants( ord)prop 3 0 drop f 3 if ! G'N'#I%: implementors 5 classQclasses )) seq 6 K update)map : class)uses 5 class )) seq 6 0 0 members W 3 0 participants W 3 0 superclass 0 < 3 hen4 3 tri 3 + . make !

: class)usage 5 class )) seq 6 update)map get at sets:members ! P;#IV"$' : 5closure6 5 obF set quot: 5 elt )) seq 6 )) 6 ,over :adFoin 0 0 dip 3 keep 0 5closure6 3 ,curry each 3 0 -drop 3 if ! inline recursive : closure 5 obF quot )) set 6 ?S+ . clone 0 s ap 5closure6 3 keep ! inline ;#IV"$'G : class)usages 5 class )) seq 6 0 class)usage 3 closure sets:members ! I: class implementors implementors)map get at sets:members ! I: sequence implementors 0 implementors 3 gather ! P;#IV"$' : update)map2 5 class )) 6 dup class)uses update)map get 0 adFoin)at 3 curry ith each ! : update)map) 5 class )) 6 dup class)uses update)map get 0 at delete 3 curry ith each ! : implementors)map2 5 class )) 6 0 ?S+ . clone 3 dip implementors)map get set)at ! : implementors)map) 5 class )) 6 implementors)map get delete)at ! : make)class)props 5 superclass members participants metaclass )) assoc 6 0 + 0 dup 0 bootstrap) ord 3 hen (superclass( << 3 0 0 bootstrap) ord 3 map (members( << 3 0 0 bootstrap) ord 3 map (participants( << 3 0 (metaclass( << 3 . spread 3 ?+ . make ! G'N'#I%: metaclass)changed 5 use class )) 6 : :metaclass)changed 5 class usagesQf )) 6 dup 0 0 metaclass)changed 3 ith each 3 0 ,drop 3 if ! : check)metaclass 5 class metaclass )) usagesQf 6 over class: 0 over (metaclass( ord)prop eq: 0 drop f 3 0 class)usage 3 if 3 0 ,drop f 3 if ! : :define)symbol 5 ord )) 6 dup deferred: 0 define)symbol 3 0 drop 3 if !

: 5define)class6 5 ord props )) 6 reset)caches ,dup (metaclass( of check)metaclass + 0 ,drop update)map) 3 0 ,drop dup class: 0 reset)class 3 0 implementors)map2 3 if 3 0 ,drop :define)symbol 3 0 drop 0 assoc)union 3 curry change)props drop 3 0 ,drop dup create)predicate) ord 0 1quotation (predicate( set) ord)prop 3 0 s ap (predicating( set) ord)prop 3 ,bi 3 0 ,drop t (class( set) ord)prop 3 0 ,drop update)map2 3 0 nip :metaclass)changed 3 . -cleave ! G'N'#I%: update)class 5 class )) 6 I: class update)class drop ! G'N'#I%: update)methods 5 class seq )) 6 : update)classes 5 class )) 6 dup class)usages 0 nip 0 update)class 3 each 3 0 update)methods 3 ,bi ! : check)inheritance 5 subclass superclass )) 6 ,dup superclass)of: 0 bad)inheritance 3 0 ,drop 3 if ! : define)class 5 ord superclass members participants metaclass )) 6 0 ,dup check)inheritance 3 -dip make)class)props 0 5define)class6 3 0 drop changed)definition 3 ,bi ! : forget)predicate 5 class )) 6 dup predicate)def dup length 1 H 0 first 0 nip 3 0 (predicating( 0 forget 3 0 drop 3 if 3 0 ,drop 3 if !

ord)prop H 3 ,bi

G'N'#I%: forget)methods 5 class )) 6 ;#IV"$'G : forget)class 5 class )) 6 dup f check)metaclass + 0 drop forget)predicate 3 0 drop forget)methods 3 0 drop implementors)map) 3 0 drop update)map) 3 0 drop reset)class 3 0 ,drop reset)caches 3 0 :metaclass)changed 3 . ,cleave ! I: class metaclass)changed

s ap class: 0 drop 3 0 forget)class 3 if ! I: class forget4 5 class )) 6 0 call)next)method 3 0 forget)class 3 bi ! USING: help.markup help.syntax kernel kernel.private namespaces sequences ords arrays effects math classes.private classes.union classes.mixin classes.predicate quotations ! IN: classes "#$I%&': (class)predicates( (%lass predicate ords( (Jith a handful of exceptions< each class has a membership predicate ord< named ( + *snippet + *emphasis (class( . (:( . (. " quotation calling this predicate is stored in the ( + *snippet (>(predicate>(( . ( ord property.( *nl (Jhen it comes to predicates< the exceptional classes are:( + *table + (%lass( (;redicate( ('xplanation( . + + *link f . + *snippet (0 not 3( . + ($he conventional name for a ord hich outputs true hen given false is ( + *link not . (! ( + *snippet (f:( . ( ould be confusing.( . . + + *link obFect . + *snippet (0 drop t 3( . + ("ll obFects are instances of ( + *link obFect . . . + + *link null . + *snippet (0 drop f 3( . + (No obFect is an instance of ( + *link null . . . . ($he set of class predicate ords is a class:( + *subsections predicate predicate: . (" predicate ord holds a reference to the class it is predicating over in the ( + *snippet (>(predicating>(( . ( ord property.( *nl (Implementation of class reloading:( + *subsections reset)class forget)class forget)methods . ! "#$I%&': (classes( (%lasses( (%onceptually< a ( + *snippet (class( . ( is a set of obFects hose members can be identified ith a predicate< and on hich generic ords can speciali8e methods. %lasses are organi8ed into a general partial order< and an obFect may be an instance of more than one class.( *nl ("t the implementation level< a class is a ord ith certain ord properties set.( *nl (Jords for orking ith classes are found in the ( + *vocab)link (classes( . ( vocabulary.( *nl (%lasses themselves form a class:( + *subsections class: . (Nou can ask an obFect for its class:( + *subsections class)of . ($esting if an obFect is an instance of a class:( + *subsections instance: . (Nou can ask a class for its superclass:( + *subsections superclass superclasses subclass)of: . (%lass predicates can be used to test instances directly:( + *subsections (class)predicates( .

($here is a universal class hich all obFects are an instance of< and an empty class ith no instances:( + *subsections obFect null . (Bbtaining a list of all defined classes:( + *subsections classes . ($here are several sorts of classes:( + *subsections (builtin)classes( (unions( (intersections( (mixins( (predicates( (singletons( . + *link (tuples( . ( are documented in their o n section.( *nl (%lasses can be inspected and operated upon:( + *subsections (class)operations( (class)lineari8ation( . + *see)also (class)index( . ! "EBU$: (classes( ?'&;: class)of + *values + (obFect( obFect . + (class( class . . + *description (Butputs an obFect7s canonical class. Jhile an obFect may be an instance of more than one class< the canonical class is either its built)in class< or if the obFect is a tuple< its tuple class.( . + *class)description ($he class of all class ords.( . + *examples + *example (USING: classes prettyprint !( (1.= class)of .( (float( . + *example (USING: classes prettyprint !( (IN: scratchpad( ($U;&': point x y 8 !>n$+ point f 1 , - . class)of .( (point( . . ! ?'&;: classes + *values + (seq( (a sequence of class ords( . . + *description (@inds all class ords in the dictionary.( . ! ?'&;: update)map + *var)description ("ssoc mapping each class to a set of classes defined in terms of this class. $he ( + *link define)class . ( ord uses this information to update generic ords hen classes are redefined.( . ! ?'&;: predicate) ord + *values + ( ord( (a ord( . + (predicate( (a predicate ord( . . + *description (Suffixes the ord7s name ith >(:>( and creates a ord name in the same vocabulary as the ord itself.( . ! ?'&;: define)predicate + *values + (class( class . + (quot( quotation . . + *description (Cefines a predicate ord for a class.( . *lo )level)note ! ?'&;: superclass + *values + (class( class . + (super( class . . + *description (Butputs the superclass of a class. "ll instances of this class are also instances of the superclass.( . + *examples

ith that

. !

+ *example (USING: classes prettyprint !( (t superclass .( ( ord( .

?'&;: superclasses + *values + (class( class . + (supers( sequence . . + *description (Butputs a sequence of superclasses of a class along class itself.( . + *examples + *example (USING: classes prettyprint !( (t superclasses .( (+ ord t .( . . !

ith the

?'&;: subclass)of: + *values + (class( class . + (superclass( class . + (:( boolean . . + *description (Butputs a boolean value indicating hether ( + *snippet (class( . ( is at any level a subclass of ( + *snippet (superclass( . (.( . + *examples + *example (USING: classes classes.tuple prettyprint ords !( (tuple)class >> class subclass)of: .( (t( . . ! + superclass superclasses subclass)of: . related) ords ?'&;: members + *values + (class( class . + (seq( (a sequence of union members< or ( + *link f . . . + *description (If ( + *snippet (class( . ( is a union class< outputs a sequence of its member classes< other ise outputs ( + *link f . (.( . ! ?'&;: participants + *values + (class( class . + (seq( (a sequence of intersection participants< or ( + *link f . . . + *description (If ( + *snippet (class( . ( is an intersection class< outputs a sequence of its participant classes< other ise outputs ( + *link f . (.( . ! ?'&;: define)class + *values + ( ord( ord . + (superclass( class . + (members( (a sequence of class ords( . + (participants( (a sequence of class ords( . + (metaclass( class . . + *description (Sets a property indicating this ord is a class ord< thus making it an instance of ( + *link class . (< and registers it ith ( + *link update)map . (.( . *lo )level)note ! ?'&;: implementors + *values + (classQclasses( (a class or a sequence of classes( . + (seq( (a sequence of generic ords( . . + *description (@inds all generic ords in the dictionary implementing methods for the given set of classes.( . !

?'&;: instance: + *values + (obFect( obFect . + (class( class . + (:( (a boolean( . . + *description ($ests hether the input obFect is a member of the class.( . ! ?'&;: reset)class + *values + (class( class . . + *description (@orgets all of ords that the class defines< but not ords that are defined on the class. @or instance< on a tuple class< this ord should reset all of the tuple accessors but not things like ( + *link nth . ( that may be defined on the class else here.( . ! ?'&;: forget)class + *values + (class( class . . + *description (#emoves a class by forgetting all of the methods defined on that class and all of the methods generated hen that class as defined. "lso resets any caches that may contain that class.( . ! ?'&;: forget)methods + *values + (class( class . . + *description (@orgets all methods defined on a class. In contrast to ( + *link reset)class . (< this not only forgets accessors but also any methods at all on the class.( . ! K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors assocs classes classes.algebra classes.algebra.private classes.private classes.union classes.union.private combinators definitions kernel sequences ords ! IN: classes.mixin ;#'CI%"$': mixin)class P union)class (mixin( I: mixin)class normali8e)class ! I: mixin)class 5classes)intersect:6 members 0 classes)intersect: 3 ith any: ! I: mixin)class reset)class 0 call)next)method 3 0 + (mixin( . reset)props 3 bi ! I: mixin)class rank)class drop S ! '##B#: check)mixin)class)error class ! : check)mixin)class 5 mixin )) mixin 6 dup mixin)class: 0 check)mixin)class)error 3 unless ! P;#IV"$' : redefine)mixin)class 5 class members )) 6 0 5define)union)class6 3 0 drop changed)conditionally 3 0 drop t (mixin( set) ord)prop 3 ,tri ! : if)mixin)member: 5 class mixin true false )) 6 ord)prop !

0 check)mixin)class ,dup members member)eq: 3 ,dip if ! inline : change)mixin)class 5 class mixin quot )) 6 0 0 members s ap bootstrap) ord 3 dip call 3 0 drop 3 ,bi s ap redefine)mixin)class ! inline : 5add)mixin)instance6 5 class mixin )) 6 ZK %all update)methods before adding the member: ZK ) %all sites of generics speciali8ing on 7mixin7 ZK here the inferred type is 7class7 are updated< ZK ) %all sites here the inferred type is a subtype ZK of 7mixin7 disFoint from 7class7 are not updated dup class)usages + 0 nip update)methods 3 0 drop 0 suffix 3 change)mixin)class 3 0 drop 0 f 3 ,dip (instances( ord)prop set)at 3 0 ,nip 0 update)class 3 each 3 . -cleave ! : 5remove)mixin)instance6 5 class mixin )) 6 ZK %all update)methods after removing the member: ZK ) %all sites of generics speciali8ing on 7mixin7 ZK here the inferred type is 7class7 are updated< ZK ) %all sites here the inferred type is a subtype ZK of 7mixin7 disFoint from 7class7 are not updated dup class)usages + 0 drop 0 s ap remove 3 change)mixin)class 3 0 drop (instances( ord)prop delete)at 3 0 ,nip 0 update)class 3 each 3 0 nip update)methods 3 . -cleave ! ;#IV"$'G G'N'#I%Z add)mixin)instance 1 5 class mixin )) 6 I: class add)mixin)instance 0 ,drop 3 0 5add)mixin)instance6 3 if)mixin)member: ! : remove)mixin)instance 5 class mixin )) 6 0 5remove)mixin)instance6 3 0 ,drop 3 if)mixin)member: ! I: mixin)class metaclass)changed over class: 0 ,drop 3 0 remove)mixin)instance 3 if ! : define)mixin)class 5 class )) 6 dup mixin)class: 0 drop 3 0 0 + . redefine)mixin)class 3 0 ?+ . clone (instances( set) ord)prop 3 0 update)classes 3 tri 3 if ! K Cefinition protocol implementation ensures that removing an K INS$"N%': declaration from a source file updates the mixin. $U;&': mixin)instance class mixin ! %: Pmixin)instanceG mixin)instance P;#IV"$'

: Gmixin)instanceP 5 mixin)instance )) class mixin 6 0 classGG 3 0 mixinGG 3 bi ! inline ;#IV"$'G I: mixin)instance here Gmixin)instanceP (instances( ord)prop at ! ord)prop set)at !

I: mixin)instance set) here Gmixin)instanceP (instances( I: mixin)instance definer drop > INS$"N%': f ! I: mixin)instance definition drop f !

I: mixin)instance forget4 Gmixin)instanceP dup mixin)class: 0 remove)mixin)instance 3 0 ,drop 3 if ! USING: alien arrays definitions generic assocs hashtables io kernel math namespaces parser prettyprint sequences strings tools.test ords quotations classes classes.private classes.union classes.mixin classes.predicate classes.algebra vectors source)files compiler.units kernel.private sorting vocabs eval ! IN: classes.mixin.tests K $est mixins IIMIN: sequence)mixin INS$"N%': array sequence)mixin INS$"N%': vector sequence)mixin INS$"N%': slice sequence)mixin IIMIN: assoc)mixin INS$"N%': hashtable assoc)mixin G'N'#I%: collection)si8e 5 x )) y 6 I: sequence)mixin collection)si8e length ! I: assoc)mixin collection)si8e assoc)si8e ! 0 0 0 0 0 0 t t f t , 3 3 3 3 3 3 0 0 0 0 0 0 array sequence)mixin classPH 3 unit)test + 1 , - . sequence)mixin: 3 unit)test + 1 , - . collection)si8e 3 unit)test ?+ + 1 , . + , - . . sequence)mixin: 3 unit)test ?+ + 1 , . + , - . . assoc)mixin: 3 unit)test ?+ + 1 , . + , - . . collection)si8e 3 unit)test classes after the fact

K $est mixing in of ne C'@'#: mx1 @B#G'$: mx1 IIMIN: mx1 INS$"N%': integer mx1

0 t 3 0 integer mx1 classPH 3 unit)test 0 f 3 0 mx1 integer classPH 3 unit)test 0 f 3 0 mx1 number classPH 3 unit)test (IN: classes.mixin.tests US': arrays INS$"N%': array mx1( eval5 )) 6

0 t 3 0 array mx1 classPH 3 unit)test 0 f 3 0 mx1 number classPH 3 unit)test 0 > mx1 forget 3 ith)compilation)unit

US': io.streams.string , 0 0 (mixin)forget)test( forget)source 3 0 3 0 + ith)compilation)unit

(USING: sequences !( (IN: classes.mixin.tests( (IIMIN: mixin)forget)test( (INS$"N%': sequence mixin)forget)test( (G'N'#I%: mixin)forget)test)g 5 x )) y 6( (I: mixin)forget)test mixin)forget)test)g !( . (>n( Foin Pstring)readerG (mixin)forget)test( parse)stream drop 3 unit)test 0 + . 3 0 + . (mixin)forget)test)g( (classes.mixin.tests( lookup) ord execute 3 unit)test 0 ?+ . (mixin)forget)test)g( (classes.mixin.tests( lookup) ord execute 3 must)fail 0 3 0 + (USING: hashtables !( (IN: classes.mixin.tests( (IIMIN: mixin)forget)test( (INS$"N%': hashtable mixin)forget)test( (G'N'#I%: mixin)forget)test)g 5 x )) y 6( (I: mixin)forget)test mixin)forget)test)g !( . (>n( Foin Pstring)readerG (mixin)forget)test( parse)stream drop 3 unit)test 0 + . (mixin)forget)test)g( (classes.mixin.tests( lookup) ord execute 3 must)fail 0 ?+ . 3 0 ?+ . (mixin)forget)test)g( (classes.mixin.tests( lookup) ord execute 3 unit)test 3 times K Iethod flattening interfered IIMIN: flat)mx)1 $U;&': flat)mx)1)1 ! INS$"N%': $U;&': flat)mx)1), ! INS$"N%': $U;&': flat)mx)1)- ! INS$"N%': $U;&': flat)mx)1)/ ! INS$"N%': IIMIN: flat)mx), INS$"N%': $U;&': flat)mx),)1 ! INS$"N%': ith mixin update flat)mx)1)1 flat)mx)1 flat)mx)1), flat)mx)1 flat)mx)1)- flat)mx)1 flat)mx)1)/ flat)mx)1 flat)mx), flat)mx)1 flat)mx),)1 flat)mx),

0 t 3 0 $+ flat)mx),)1 . flat)mx)1: 3 unit)test K $oo eager ith reset)class

0 3 0 (IN: classes.mixin.tests IIMIN: blah SING&'$BN: boo INS$"N%': boo blah( Pstring)readerG (mixin)reset)test( parse)stream drop 3 unit)test 0 t 3 0 (blah( (classes.mixin.tests( lookup) ord mixin)class: 3 unit)test

0 3 0 (IN: classes.mixin.tests IIMIN: blah( Pstring)readerG (mixin)reset)test( parse)stream drop 3 unit)test 0 t 3 0 (blah( (classes.mixin.tests( lookup) ord mixin)class: 3 unit)test IIMIN: empty)mixin 0 f 3 0 (hi( empty)mixin: 3 unit)test IIMIN: move)instance)declaration)mixin 0 3 0 (IN: classes.mixin.tests.a US': strings US': classes.mixin.tests INS$"N%': string move)instance)declaration)mixin( Pstring)readerG (move)mixin)test)1( parse)stream drop 3 unit)test 0 3 0 (IN: classes.mixin.tests.b US': strings US': classes.mixin.tests INS$"N%': string move)instance)declaration)mixin( Pstring)readerG (move)mixin)test),( parse)stream drop 3 unit)test 0 3 0 (IN: classes.mixin.tests.a( Pstring)readerG (move)mixin)test)1( parse)stream drop 3 unit)test 0 + string . 3 0 move)instance)declaration)mixin members 3 unit)test IIMIN: silly)mixin SNIEB&: not)a)class 0 0 > not)a)class > silly)mixin add)mixin)instance 3 must)fail SNIEB&: not)a)mixin $U;&': a)class ! 0 0 > a)class > not)a)mixin add)mixin)instance 3 must)fail ith)compilation)unit 3 ith)compilation)unit 3

K %hanging a mixin member7s metaclass should not remove it from the mixin IIMIN: metaclass)change)mixin $U;&': metaclass)change ! INS$"N%': metaclass)change metaclass)change)mixin G'N'#I%: metaclass)change)generic 5 a )) b 6 I: metaclass)change)mixin metaclass)change)generic ! 0 $+ metaclass)change . 3 0 $+ metaclass)change . metaclass)change)generic 3 unit)test 0 3 0 (IN: classes.mixin.tests US': math UNIBN: metaclass)change integer !( eval5 )) 6 3 unit)test 0 = 3 0 = metaclass)change)generic 3 unit)test K @orgetting a mixin member class should remove it from the mixin 0 3 0 0 metaclass)change forget)class 3 ith)compilation)unit 3 unit)test 0 t 3 0 metaclass)change)mixin members empty: 3 unit)test USING: help.markup help.syntax help ords compiler.units classes sequences ! IN: classes.mixin

"#$I%&': (mixins( (Iixin classes( ("n obFect is an instance of a union class if it is an instance of one of its members. In this respect< mixin classes are identical to union classes. ?o ever< mixin classes have the additional property that they are ( + *emphasis (open( . (! ne classes can be added to the mixin after the original definition of the mixin.( + *subsections ;BS$;BN': IIMIN: ;BS$;BN': INS$"N%': define)mixin)class add)mixin)instance . ($he set of mixin classes is a class:( + *subsections mixin)class mixin)class: . (Iixins are used to defines suites of behavior hich are generally useful and can be applied to user)defined classes. @or example< the ( + *link immutable)sequence . ( mixin can be used ith user)defined sequences to make them immutable.( + *see)also (unions( (tuple)subclassing( . ! ?'&;: mixin)class + *class)description ($he class of mixin classes.( . ! ?'&;: define)mixin)class + *values + (class( ord . . + *description (Cefines a mixin class. $his is the run time equivalent of ( + *link ;BS$;BN': IIMIN: . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects (class( . ! ?'&;: add)mixin)instance + *values + (class( class . + (mixin( class . . + *description (Cefines a class to be an instance of a mixin class. $his is the run time equivalent of ( + *link ;BS$;BN': INS$"N%': . (.( . + *notes ($his ord must be called from inside ( + *link ith)compilation)unit . (.( . + *side)effects (class( . ! + mixin)class define)mixin)class add)mixin)instance ;BS$;BN': IIMIN: ;BS$;BN': INS$"N%': . related) ords "EBU$: (mixins( USING: help.markup help.syntax kernel classes classes.private checksums checksums.crc-, sequences math ! IN: classes.algebra "#$I%&': (class)operations( (%lass operations( (Set)theoretic operations on classes:( + *subsections classH classP classPH class)and class)or classes)intersect: flatten)class . ! ords

"#$I%&': (class)lineari8ation( (%lass lineari8ation( (%lasses have an intrinsic partial order! given t o classes " and E< e either have that " is a subset of E< E is a subset of "< " and E are equal as sets< or they are incomparable. $he last t o situations present difficulties for method dispatch:( + *list (If a generic ord defines a method on a mixin class " and another on class E< and E is the only instance of "< there is an ambiguity because " and E are equal as sets! any obFect that is an instance of one is an instance of both.( + (If a generic ord defines methods on t o union classes hich are incomparable but not disFoint< for example ( + *link sequence . ( and ( + *link number . (< there is an ambiguity because the generic ord may be called on an obFect that is an instance of both unions.( . . ($he first ambiguity is resolved ith a tie)breaker that compares metaclasses. $he intrinsic meta)class order< from most)specific to least)specific:( + *list (Euilt)in classes and tuple classes( (;redicate classes( (Union classes( (Iixin classes( . ($his means that in the above example< the generic ord ith methods on a mixin and its sole instance ill al ays call the method for the sole instance< since it is more specific than a mixin class.( *nl ($he second problem is resolved ith another tie)breaker. Jhen performing the topological sort of classes< if there are multiple candidates at any given step of the sort< lexicographical order on the class name is used.( *nl (Bperations:( + *subsections classP sort)classes smallest)class . (Ietaclass order:( + *subsections rank)class . ! ?'&;: flatten)class + *values + (class( class . + (assoc( (an assoc hose keys are classes( . . + *description (Butputs a set of builtin and tuple classes hose union is the smallest cover of ( + *snippet (class( . (.( . ! ?'&;: classPH + *values + (first( (a class( . + (second( (a class( . + (:( (a boolean( . . + *description ($ests if all instances of ( + *snippet (class1( . ( are also instances of ( + *snippet (class,( . (.( . + *notes (%lasses are partially ordered. $his means that if ( + *snippet (class1 PH class,( . ( and ( + *snippet (class, PH class1( . (< then ( + *snippet (class1 PH class,( . (. "lso< if ( + *snippet (class1 PH class,( . ( and ( + *snippet (class, PH class-( . (< then ( + *snippet (class1 PH class-( . (.( . ! ?'&;: sort)classes + *values + (seq( (a sequence of class( . + (ne seq( (a ne sequence of classes( . . + *description (Butputs a linear sort of a sequence of classes. &arger classes come before their subclasses.( . ! ?'&;: class)or + *values + (first( class . + (second( class . + (class( class . .

+ *description (Butputs the smallest anonymous class containing both ( + *snippet (class1( . ( and ( + *snippet (class,( . (.( . ! ?'&;: class)and + *values + (first( class . + (second( class . + (class( class . . + *description (Butputs the largest anonymous class contained in both ( + *snippet (class1( . ( and ( + *snippet (class,( . (.( . ! ?'&;: classes)intersect: + *values + (first( class . + (second( class . + (:( (a boolean( . . + *description ($ests if t o classes have a non)empty intersection. If the intersection is empty< no obFect can be an instance of both classes at once.( . ! ?'&;: smallest)class + *values + (classes( (a sequence of class ords( . + (classQf( + *maybe class . . . + *description (Butputs a minimum class from the given sequence.( . ! USING: alien arrays definitions generic assocs hashtables io kernel math namespaces parser prettyprint sequences strings tools.test ords quotations classes classes.algebra classes.private classes.union classes.mixin classes.predicate vectors source)files compiler.units gro able random stack)checker effects kernel.private sbufs math.order classes.tuple accessors generic.private ! IN: classes.algebra.tests $U;&': first)one ! $U;&': second)one ! UNIBN: both first)one union)class ! ;#'CI%"$': no)docs P ord (documentation( ord)prop not !

UNIBN: no)docs)union no)docs integer ! $U;&': a ! $U;&': b ! UNIBN: c a b ! $U;&': tuple)example ! $U;&': a1 ! $U;&': b1 ! $U;&': c1 ! UNIBN: x1 a1 b1 ! UNIBN: y1 a1 c1 ! UNIBN: 81 b1 c1 ! SING&'$BN: sa SING&'$BN: sb SING&'$BN: sc IN$'#S'%$IBN: empty)intersection ! IN$'#S'%$IBN: generic)class generic class ! UNIBN: union) ith)one)member a ! IIMIN: mixin) ith)one)member INS$"N%': union) ith)one)member mixin) ith)one)member

K 0 0 0 0 0 0

classPH t 3 0 > t 3 0 > f 3 0 > t 3 0 > f 3 0 > t 3 0 >

fixnum > integer classPH 3 unit)test fixnum > fixnum classPH 3 unit)test integer > fixnum classPH 3 unit)test integer > obFect classPH 3 unit)test integer > null classPH 3 unit)test null > obFect classPH 3 unit)test

0 t 3 0 > generic > ord classPH 3 unit)test 0 f 3 0 > ord > generic classPH 3 unit)test 0 f 3 0 > reversed > slice classPH 3 unit)test 0 f 3 0 > slice > reversed classPH 3 unit)test 0 t 3 0 no)docs no)docs)union classPH 3 unit)test 0 f 3 0 no)docs)union no)docs classPH 3 unit)test 0 t 3 0 > c > tuple classPH 3 unit)test 0 f 3 0 > tuple > c classPH 3 unit)test 0 t 3 0 > tuple)class > class classPH 3 unit)test 0 f 3 0 > class > tuple)class classPH 3 unit)test 0 0 0 0 0 t f f t f 3 3 3 3 3 0 0 0 0 0 > > > > > null > tuple)example classPH 3 unit)test obFect > tuple)example classPH 3 unit)test obFect > tuple)example classPH 3 unit)test tuple)example > tuple classPH 3 unit)test tuple > tuple)example classPH 3 unit)test

0 f 3 0 81 x1 y1 class)and classPH 3 unit)test 0 t 3 0 x1 y1 class)and a1 classPH 3 unit)test 0 f 3 0 b1 c1 class)or a1 b1 class)or a1 c1 class)and class)and classPH 3 unit)test 0 t 3 0 a1 b1 class)or a1 c1 class)or class)and a1 classPH 3 unit)test 0 f 3 0 gro able tuple sequence class)and classPH 3 unit)test 0 f 3 0 gro able assoc class)and tuple classPH 3 unit)test 0 t 3 0 obFect > f > f class)not class)or classPH 3 unit)test 0 t 3 0 fixnum class)not integer class)and bignum classH 3 unit)test 0 t 3 0 array number class)not classPH 3 unit)test 0 f 3 0 bignum number class)not classPH 3 unit)test 0 t 3 0 fixnum fixnum bignum class)or classPH 3 unit)test 0 f 3 0 fixnum class)not integer class)and array classPH 3 unit)test 0 f 3 0 fixnum class)not integer classPH 3 unit)test 0 f 3 0 number class)not array classPH 3 unit)test 0 f 3 0 fixnum class)not array classPH 3 unit)test 0 t 3 0 number class)not integer class)not classPH 3 unit)test

0 f 3 0 fixnum class)not integer classPH 3 unit)test 0 0 0 0 0 0 0 t t t f t t t 3 3 3 3 3 3 3 0 0 0 0 0 0 0 obFect empty)intersection classPH 3 unit)test empty)intersection obFect classPH 3 unit)test > f class)not empty)intersection classPH 3 unit)test empty)intersection > f class)not classPH 3 unit)test > number empty)intersection classPH 3 unit)test empty)intersection class)not null classPH 3 unit)test null empty)intersection class)not classPH 3 unit)test

0 t 3 0 > f class)not > f class)or empty)intersection classPH 3 unit)test 0 t 3 0 empty)intersection > f class)not > f class)or classPH 3 unit)test 0 t 3 0 obFect > f class)not > f class)or classPH 3 unit)test 0 t 3 0 fixnum class)not fixnum fixnum class)not class)or classPH 3 unit)test 0 t 3 0 generic)class generic classPH 3 unit)test 0 t 3 0 generic)class > class classPH 3 unit)test 0 t 3 0 a union) ith)one)member classPH 3 unit)test 0 f 3 0 union) ith)one)member class)not integer classPH 3 unit)test IIMIN: empty)mixin 0 f 3 0 empty)mixin class)not null classPH 3 unit)test 0 f 3 0 empty)mixin null classPH 3 unit)test 0 t 3 0 empty)mixin class)not obFect classPH 3 unit)test 0 t 3 0 empty)mixin obFect classPH 3 unit)test 0 t 3 0 empty)mixin class)not obFect classPH 3 unit)test 0 t 3 0 empty)mixin obFect classPH 3 unit)test 0 t 3 0 obFect empty)mixin class)not classPH 3 unit)test 0 t 3 0 array sequence vector class)not class)and classPH 3 unit)test 0 f 3 0 vector sequence vector class)not class)and classPH 3 unit)test K class)and : class)and4 5 cls1 cls, cls- )) : 6 0 class)and 3 dip classH ! 0 0 0 0 0 0 0 0 0 0 0 t t t t t t t t t t t 3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 obFect fixnum obFect fixnum fixnum integer obFect obFect fixnum fixnum integer fixnum obFect fixnum fixnum fixnum fixnum fixnum class)and4 class)and4 class)and4 class)and4 class)and4 class)and4 3 3 3 3 3 3 unit)test unit)test unit)test unit)test unit)test unit)test

vector fixnum number obFect obFect number slice reversed > f class)not > f

null class)and4 3 unit)test number class)and4 3 unit)test number class)and4 3 unit)test null class)and4 3 unit)test null class)and4 3 unit)test

0 t 3 0 vector array class)not vector class)and4 3 unit)test 0 obFect 3 0 obFect empty)mixin class)not class)and 3 unit)test

0 obFect 3 0 empty)mixin class)not obFect class)and 3 unit)test K class)or : class)or4 5 cls1 cls, cls- )) : 6 0 class)or 3 dip classH ! 0 t 3 0 > f class)not > f obFect class)or4 3 unit)test

0 obFect 3 0 obFect empty)mixin class)not class)or 3 unit)test 0 obFect 3 0 empty)mixin class)not obFect class)or 3 unit)test K class)not 0 vector 3 0 vector class)not class)not 3 unit)test K classes)intersect: 0 t 3 0 both tuple classes)intersect: 3 unit)test 0 t 3 0 tuple both classes)intersect: 3 unit)test 0 f 3 0 vector virtual)sequence classes)intersect: 3 unit)test 0 f 3 0 virtual)sequence vector classes)intersect: 3 unit)test 0 t 3 0 number vector class)or sequence classes)intersect: 3 unit)test 0 t 3 0 sequence number vector class)or classes)intersect: 3 unit)test 0 f 3 0 number vector class)and sequence classes)intersect: 3 unit)test 0 f 3 0 sequence number vector class)and classes)intersect: 3 unit)test 0 f 3 0 y1 81 class)and x1 classes)intersect: 3 unit)test 0 f 3 0 x1 y1 81 class)and classes)intersect: 3 unit)test 0 f 3 0 a1 c1 class)or b1 c1 class)or class)and a1 b1 class)or classes)intersect: 3 unit)test 0 f 3 0 a1 b1 class)or a1 c1 class)or b1 c1 class)or class)and classes)intersect: 3 unit)test 0 f 3 0 integer integer class)not classes)intersect: 3 unit)test 0 f 3 0 integer class)not integer classes)intersect: 3 unit)test 0 f 3 0 fixnum class)not number class)and array classes)intersect: 3 unit)test 0 f 3 0 array fixnum class)not number class)and classes)intersect: 3 unit)test 0 0 0 0 t t f f 3 3 3 3 0 0 0 0 > ord generic)class generic)class > ord number generic)class generic)class number classes)intersect: classes)intersect: classes)intersect: classes)intersect: 3 3 3 3 unit)test unit)test unit)test unit)test

0 f 3 0 sa sb classes)intersect: 3 unit)test 0 f 3 0 sb sa classes)intersect: 3 unit)test 0 t 3 0 a union) ith)one)member classes)intersect: 3 unit)test 0 f 3 0 fixnum union) ith)one)member classes)intersect: 3 unit)test 0 t 3 0 obFect union) ith)one)member classes)intersect: 3 unit)test 0 t 3 0 union) ith)one)member a classes)intersect: 3 unit)test 0 f 3 0 union) ith)one)member fixnum classes)intersect: 3 unit)test 0 t 3 0 union) ith)one)member obFect classes)intersect: 3 unit)test 0 t 3 0 a mixin) ith)one)member classes)intersect: 3 unit)test 0 f 3 0 fixnum mixin) ith)one)member classes)intersect: 3 unit)test 0 t 3 0 obFect mixin) ith)one)member classes)intersect: 3 unit)test 0 t 3 0 mixin) ith)one)member a classes)intersect: 3 unit)test 0 f 3 0 mixin) ith)one)member fixnum classes)intersect: 3 unit)test

0 t 3 0 mixin) ith)one)member obFect classes)intersect: 3 unit)test 0 f 3 0 null obFect classes)intersect: 3 unit)test 0 f 3 0 obFect null classes)intersect: 3 unit)test 0 t 3 0 null class)not obFect classH 3 unit)test 0 t 3 0 obFect class)not null classH 3 unit)test 0 f 3 0 obFect class)not obFect classH 3 unit)test 0 f 3 0 null class)not null classH 3 unit)test K smallest)class etc 0 real 3 0 + real sequence . smallest)class 3 unit)test 0 real 3 0 + sequence real . smallest)class 3 unit)test : min)class 5 class classes )) classQf 6 interesting)classes smallest)class ! 0 f 3 0 fixnum + . min)class 3 unit)test 0 string 3 0 > string 0 integer string array reversed sbuf slice vector quotation 3 sort)classes min)class 3 unit)test 0 fixnum 3 0 > fixnum 0 fixnum integer obFect 3 sort)classes min)class 3 unit)test 0 integer 3 0 > fixnum 0 integer float obFect 3 sort)classes min)class 3 unit)test 0 obFect 3 0 > ord 0 integer float obFect 3 sort)classes min)class 3 unit)test 0 reversed 3 0 > reversed 0 integer reversed slice 3 sort)classes min)class 3 unit)test 0 f 3 0 null + number fixnum null . min)class 3 unit)test K $est for hangs: : random)class 5 )) class 6 classes random ! : random)op 5 )) ord 6 + class)and class)or

class)not . random ! 1= 0 0 3 0 ,= 0 random)op 3 0 3 replicate)as 0 infer inGG length 0 random)class 3 times 3 keep call drop 3 unit)test 3 times : random)boolean 5 )) : 6 + t f . random ! : booleanGclass 5 : )) class 6 obFect null : ! : random)boolean)op 5 )) + and or not xor . random ! ord 6

: class)xor 5 cls1 cls, )) cls- 6 0 class)or 3 ,keep class)and class)not class)and ! : boolean)opGclass)op 5 ord )) + + and class)and . + or class)or . + not class)not . + xor class)xor . . at ! ord7 6

,= 0 0 t 3 0 ,= 0 random)boolean)op 3 0 3 replicate)as dup . 0 infer inGG length 0 random)boolean 3 replicate dup . 3 keep 0 0 0 3 each 3 dip call 3 ,keep 0 0 booleanGclass 3 each 3 dip 0 boolean)opGclass)op 3 map call obFect classH H 3 unit)test 3 times SING&'$BN: xxx UNIBN: yyy xxx ! 0 + yyy xxx . 3 0 + xxx yyy . sort)classes 3 unit)test 0 + yyy xxx . 3 0 + yyy xxx . sort)classes 3 unit)test 0 + number ratio integer . 3 0 + ratio number integer . sort)classes 3 unit)test 0 + sequence number ratio . 3 0 + ratio number sequence . sort)classes 3 unit)test $U;&': xa !

$U;&': $U;&': $U;&': $U;&': $U;&': $U;&': $U;&':

xb xc xd xe xf xg xh

! P P ! P P P

xa ! xb ! xb ! xb ! xb !

0 t 3 0 + xa xb xc xd xe xf xg xh . sort)classes dup sort)classes H 3 unit)test 0 ?+ + ord ord . . 3 0 generic)class flatten)class 3 unit)test 0 sa 3 0 sa + sa sb sc . min)class 3 unit)test 0 > 2 flatten)class 3 must)fail K %opyright 5%6 ,==/< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays assocs classes classes.private combinators kernel make math math.order namespaces sequences sorting vectors ords ! @#BI: classes HG members ! #'N"I': members sets HG set)members IN: classes.algebra C'@'#: sort)classes P;#IV"$' $U;&': anonymous)union + members read)only . ! INS$"N%': anonymous)union classoid '##B#: not)classoids sequence ! : check)classoids 5 members )) members 6 dup 0 classoid: 3 all: 0 0 classoid: not 3 filter not)classoids 3 unless ! '##B#: not)a)classoid obFect ! : check)classoid 5 obFect )) obFect 6 dup classoid: 0 not)a)classoid 3 unless ! : Panonymous)unionG 5 members )) classoid 6 check)classoids 0 null eq: not 3 filter set)members dup length 1 H 0 first 3 0 sort)classes f like anonymous)union boa 3 if ! I: anonymous)union rank)class drop L ! $U;&': anonymous)intersection + participants read)only . ! INS$"N%': anonymous)intersection classoid : Panonymous)intersectionG 5 participants )) classoid 6 check)classoids set)members dup length 1 H 0 first 3 0 sort)classes f like anonymous)intersection boa 3 if ! I: anonymous)intersection rank)class drop / !

$U;&': anonymous)complement + class read)only . ! INS$"N%': anonymous)complement classoid : Panonymous)complementG 5 obFect )) classoid 6 dup classoid: 0 1array not)classoids 3 unless anonymous)complement boa ! I: anonymous)complement rank)class drop - ! I: anonymous)complement instance: over 0 classGG instance: not 3 0 ,drop t 3 if ! I: anonymous)complement class)name classGG class)name ! C'@'#: 5classPH6 C'@'#: 5class)not6 G'N'#I%: 5classes)intersect:6 5 first second )) : 6 C'@'#: 5class)and6 C'@'#: 5class)or6 G'N'#I%: 5flatten)class6 5 class )) 6 G'N'#I%: normali8e)class 5 class )) class7 6 I: obFect normali8e)class ! : symmetric)class)op 5 first second cache quot )) result 6 0 ,dup 0 rank)class 3 bi9 G 0 s ap 3 hen 3 ,dip ,cache ! inline ;#IV"$'G G'N'#I%: valid)classoid: 5 obF )) : 6 I: ord valid)classoid: class: ! I: anonymous)union valid)classoid: membersGG 0 valid)classoid: 3 all: ! I: anonymous)intersection valid)classoid: participantsGG 0 valid)classoid: 3 all: ! I: anonymous)complement valid)classoid: classGG valid)classoid: ! I: obFect valid)classoid: drop f ! : only)classoid: 5 obF )) : 6 dup classoid: 0 class: not 3 0 drop f 3 if ! : classPH 5 first second )) : 6 classPH)cache get 0 5classPH6 3 ,cache ! : classP 5 first second )) : 6 + + 0 ,dup classPH not 3 0 ,drop f 3 . + 0 ,dup s ap classPH not 3 0 ,drop t 3 . 0 0 rank)class 3 bi9 P 3 . cond ! : classH 5 first second )) : 6 ,dup classPH 0 s ap classPH 3 0 ,drop f 3 if !

: class)not 5 class )) complement 6 class)not)cache get 0 5class)not6 3 cache ! : classes)intersect: 5 first second )) : 6 0 normali8e)class 3 bi9 classes)intersect)cache get 0 5classes)intersect:6 3 symmetric)class)op ! : class)and 5 first second )) class 6 class)and)cache get 0 5class)and6 3 symmetric)class)op ! : class)or 5 first second )) class 6 class)or)cache get 0 5class)or6 3 symmetric)class)op ! SNIEB&: 2incomparable2 : compare)classes 5 first second )) PHG 6 0 s ap classPH 3 0 classPH 3 ,bi 0 2eq2 2lt2 3 0 2gt2 2incomparable2 3 if : ! : evaluate)class)predicate 5 class1 class, )) : 6 + + 0 ,dup classPH 3 0 t 3 . + 0 ,dup classes)intersect: not 3 0 f 3 . 0 2incomparable2 3 . cond ,nip ! P;#IV"$' : superclassPH 5 first second )) : 6 s ap superclass dup 0 s ap classPH 3 0 ,drop f 3 if ! : left)anonymous)unionPH 5 first second )) : 6 0 membersGG 3 dip 0 classPH 3 curry all: ! : right)unionPH 5 first second )) : 6 members 0 classPH 3 ith any: ! : right)anonymous)unionPH 5 first second )) : 6 membersGG 0 classPH 3 ith any: ! : left)anonymous)intersectionPH 5 first second )) : 6 0 participantsGG 3 dip 0 classPH 3 curry any: ! ;#'CI%"$': nontrivial)anonymous)intersection P anonymous)intersection participantsGG empty: not ! : right)anonymous)intersectionPH 5 first second )) : 6 participantsGG 0 classPH 3 ith all: ! : anonymous)complementPH 5 first second )) : 6 0 classGG 3 bi9 s ap classPH ! : normali8e)complement 5 class )) class7 6 classGG normali8e)class + + 0 dup anonymous)union: 3 0 membersGG 0 class)not normali8e)class 3 map Panonymous)intersectionG 3 . + 0 dup anonymous)intersection: 3 0 participantsGG

3 . 0 drop obFect 3 . cond !

0 class)not normali8e)class 3 map Panonymous)unionG

: left)anonymous)complementPH 5 first second )) : 6 0 normali8e)complement 3 dip classPH ! ;#'CI%"$': nontrivial)anonymous)complement P anonymous)complement classGG + 0 anonymous)union: 3 0 anonymous)intersection: 3 0 members 3 0 participants 3 . cleave or or or ! ;#'CI%"$': empty)union P anonymous)union membersGG empty: ! ;#'CI%"$': empty)intersection P anonymous)intersection participantsGG empty: ! : 5classPH6 5 first second )) : 6 ,dup eq: 0 ,drop t 3 0 0 normali8e)class 3 bi9 ,dup superclassPH 0 ,drop t 3 0 + + 0 ,dup eq: 3 0 ,drop t 3 . + 0 dup empty)intersection: 3 0 ,drop t 3 . + 0 over empty)union: 3 0 ,drop t 3 . + 0 ,dup 0 anonymous)complement: 3 both: 3 0 anonymous)complementPH 3 . + 0 over anonymous)union: 3 0 left)anonymous)unionPH 3 . + 0 over nontrivial)anonymous)intersection: 3 0 left)anonymous)intersectionPH 3 . + 0 over nontrivial)anonymous)complement: 3 0 left)anonymous)complementPH 3 . + 0 dup members 3 0 right)unionPH 3 . + 0 dup anonymous)union: 3 0 right)anonymous)unionPH 3 . + 0 dup anonymous)intersection: 3 0 right)anonymous)intersectionPH 3 . + 0 dup anonymous)complement: 3 0 classGG classes)intersect: not 3 . 0 ,drop f 3 . cond 3 if 3 if ! I: anonymous)union 5classes)intersect:6 membersGG 0 classes)intersect: 3 ith any: ! I: anonymous)intersection 5classes)intersect:6 participantsGG 0 classes)intersect: 3 ith all: ! I: anonymous)complement 5classes)intersect:6 classGG classPH not ! : anonymous)union)and 5 first second )) class 6 membersGG 0 class)and 3 ith map Panonymous)unionG ! : anonymous)intersection)and 5 first second )) class 6 participantsGG s ap suffix Panonymous)intersectionG !

: 5class)and6 5 first second )) class 6 ,dup compare)classes + + 2lt2 0 drop 3 . + 2gt2 0 nip 3 . + 2eq2 0 nip 3 . + 2incomparable2 0 ,dup classes)intersect: 0 0 normali8e)class 3 bi9 + + 0 dup anonymous)union: 3 0 anonymous)union)and 3 . + 0 dup anonymous)intersection: 3 0 anonymous)intersection)and 3 . + 0 over anonymous)union: 3 0 s ap anonymous)union)and 3 . + 0 over anonymous)intersection: 3 0 s ap anonymous)intersection)and 3 . 0 ,array Panonymous)intersectionG 3 . cond 3 0 ,drop null 3 if 3 . . case ! : anonymous)union)or 5 first second )) class 6 membersGG s ap suffix Panonymous)unionG ! : 55class)or66 5 first second )) class 6 0 normali8e)class 3 bi9 + + 0 dup anonymous)union: 3 0 anonymous)union)or 3 . + 0 over anonymous)union: 3 0 s ap anonymous)union)or 3 . 0 ,array Panonymous)unionG 3 . cond ! : anonymous)complement)or 5 first second )) class 6 ,dup classGG s ap classPH 0 ,drop obFect 3 0 55class)or66 3 if ! : 5class)or6 5 first second )) class 6 ,dup compare)classes + + 2lt2 0 nip 3 . + 2gt2 0 drop 3 . + 2eq2 0 nip 3 . + 2incomparable2 0 + + 0 dup anonymous)complement: 3 0 anonymous)complement)or 3 . + 0 over anonymous)complement: 3 0 s ap anonymous)complement)or 3 . 0 55class)or66 3 . cond 3 . . case ! : 5class)not6 5 class )) complement 6 + + 0 dup anonymous)complement: 3 0 classGG 3 . + 0 dup obFect eq: 3 0 drop null 3 . + 0 dup null eq: 3 0 drop obFect 3 . 0 Panonymous)complementG 3 . cond ! I: anonymous)union 5flatten)class6 membersGG 0 5flatten)class6 3 each ! ;#IV"$'G '##B#: topological)sort)failed !

: largest)class 5 seq )) n elt 6 dup 0 0 classP 3 ith any: not 3 curry find)last 0 topological)sort)failed 3 unless4 ! : sort)classes 5 seq )) ne seq 6 0 class)name 3 sort) ith Gvector 0 dup empty: not 3 0 dup largest)class 0 s ap remove)nthK 3 dip 3 produce nip ! : smallest)class 5 classes )) classQf 6 0 f 3 0 natural)sort PreversedG 0 3 0 0 classPH 3 most 3 map)reduce 3 if)empty ! : flatten)class 5 class )) assoc 6 0 5flatten)class6 3 ?+ . make ! USING: help.markup help.syntax kernel IN: classes.singleton

ords !

"#$I%&': (singletons( (Singleton classes( (" singleton is a class ith only one instance and ith no state.( + *subsections ;BS$;BN': SING&'$BN: ;BS$;BN': SING&'$BNS: define)singleton)class . ($he set of all singleton classes is itself a class:( + *subsections singleton)class: singleton)class . ! ?'&;: define)singleton)class + *values + ( ord( (a ne ord( . . + *description (Cefines a singleton class. $his is the run)time equivalent of ( + *link ;BS$;BN': SING&'$BN: . (.( . ! + ;BS$;BN': SING&'$BN: define)singleton)class . related) ords ?'&;: singleton)class + *class)description ($he class of singleton classes.( . ! "EBU$: (singletons( K %opyright 5%6 ,==S< ,=1= Coug %oleman< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: classes classes.algebra.private classes.predicate classes.predicate.private kernel sequences ords ! IN: classes.singleton P;#IV"$' : singleton)predicate)quot 5 class )) quot 6 0 eq: 3 curry ! ;#IV"$'G ;#'CI%"$': singleton)class P predicate)class 0 (predicate)definition( ord)prop 3 0 singleton)predicate)quot 3

bi sequenceH ! : define)singleton)class 5 ord )) 6 > ord over singleton)predicate)quot define)predicate)class ! I: singleton)class instance: eq: ! I: singleton)class 5classes)intersect:6 over singleton)class: 0 eq: 3 0 call)next)method 3 if ! I: singleton)class predicate)quot singleton)predicate)quot ! USING: kernel classes.singleton tools.test prettyprint io.streams.string see ! IN: classes.singleton.tests 0 3 0 SING&'$BN: b88t 3 unit)test 0 t 3 0 b88t b88t: 3 unit)test 0 t 3 0 b88t b88t eq: 3 unit)test G'N'#I%: 8ammo 5 obF )) str 6 0 3 0 I: b88t 8ammo drop (yesK( ! 3 unit)test 0 (yesK( 3 0 b88t 8ammo 3 unit)test 0 3 0 SING&'$BN: omg 3 unit)test 0 t 3 0 omg singleton)class: 3 unit)test 0 (IN: classes.singleton.tests>nSING&'$BN: omg>n( 3 0 0 omg see 3 ith)string) riter 3 unit)test SING&'$BN: : ord)and)singleton

ord)and)singleton 5 )) x 6 - !

0 t 3 0 > ord)and)singleton ord)and)singleton: 3 unit)test 0 - 3 0 ord)and)singleton 3 unit)test K %opyright 5%6 ,==L< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays classes combinators kernel make math math.order math.parser sequences sequences.private strings ords ! IN: effects $U;&': effect + in array read)only . + out array read)only . + terminated: read)only . + in)var read)only . + out)var read)only . ! : :terminated 5 out )) out terminated: 6 dup + (4( . H 0 drop + . t 3 0 f 3 if ! : PeffectG 5 in out )) effect 6 :terminated f f effect boa ! : Pterminated)effectG 5 in out terminated: )) effect 6 f f effect boa ! inline : Pvariable)effectG 5 in)var in out)var out )) effect 6 s ap 0 rot 3 dip 0 :terminated 3 ,dip effect boa ! : effect)height 5 effect )) n 6 0 outGG length 3 0 inGG length 3 bi ) ! inline : variable)effect: 5 effect )) : 6 0 in)varGG 3 0 out)varGG 3 bi or !

: bivariable)effect: 5 effect )) : 6 0 in)varGG 3 0 out)varGG 3 bi H not ! : effectPH 5 effect1 effect, )) : 6 + + 0 over terminated:GG 3 0 t 3 . + 0 dup terminated:GG 3 0 f 3 . + 0 ,dup 0 bivariable)effect: 3 either: 3 0 f 3 . + 0 ,dup 0 variable)effect: 3 0 variable)effect: not 3 bi4 and 3 0 f 3 . + 0 ,dup 0 inGG length 3 bi9 G 3 0 f 3 . + 0 ,dup 0 effect)height 3 same: not 3 0 f 3 . 0 t 3 . cond ,nip ! inline : effectH 5 effect1 effect, )) : 6 0 0 inGG length 3 same: 3 0 0 outGG length 3 same: 3 0 0 terminated:GG 3 same: 3 ,tri and and ! G'N'#I%: effectGstring 5 obF )) str 6 I: string effectGstring ! I: obFect effectGstring drop (obFect( ! I: ord effectGstring nameGG ! I: integer effectGstring numberGstring ! I: pair effectGstring first,)unsafe 0 effectGstring 3 bi9 (: ( glue ! : stack)picture 5 seq )) string 6 0 0 effectGstring W %?"#: >s < 3 each 3 (( make ! : var)picture 5 var )) string 6 0 (..( ( ( surround 3 0 (( 3 if4 ! I: effect effectGstring 5 effect )) string 6 0 (5 ( W dup in)varGG var)picture W dup inGG stack)picture W ()) ( W dup out)varGG var)picture W dup outGG stack)picture W dup terminated:GG 0 (4 ( W 3 hen drop (6( W 3 (( make ! G'N'#I%: effectGtype 5 obF )) type 6 I: obFect effectGtype drop obFect ! I: ord effectGtype ! I: pair effectGtype second)unsafe effectGtype ! I: classoid effectGtype ! : effect)in)types 5 effect )) input)types 6 inGG 0 effectGtype 3 map ! : effect)out)types 5 effect )) input)types 6 outGG 0 effectGtype 3 map ! G'N'#I%: stack)effect 5 I: ord stack)effect 0 (declared)effect( ord )) effectQf 6 ord)prop 3

0 parent) ord dup 0 stack)effect 3

hen 3 bi or !

I: deferred stack)effect call)next)method 5 )) 4 6 or ! I: effect clone 0 inGG clone 3 0 outGG clone 3 bi PeffectG ! : stack)height 5 ord )) n 6 stack)effect effect)height ! inline : shuffle)mapping 5 effect )) mapping 6 0 outGG 3 0 inGG 3 bi 0 index 3 curry map ! : shuffle 5 stack shuffle )) ne stack 6 shuffle)mapping s ap nths ! : add)effect)input 5 effect )) effect7 6 0 inGG (obF( suffix 3 0 outGG 3 0 terminated:GG 3 tri Pterminated)effectG ! : compose)effects 5 effect1 effect, )) effect7 6 over terminated:GG 0 drop 3 0 0 0 0 inGG length 3 0 outGG length 3 bi 3 0 inGG length 3 bi4 s ap 0)3 2 3 0 0 outGG length 3 0 0 inGG length 3 0 outGG length 3 bi 3 bi4 0 0)3 3 dip 2 3 0 nip terminated:GG 3 ,tri 0 0 (x( ParrayG 3 bi9 3 dip Pterminated)effectG 3 if ! inline : curry)effect 5 effect )) effect7 6 0 inGG length 3 0 outGG length 3 0 terminated:GG 3 tri pick = H 0 0 1 2 3 dip 3 0 0 1 ) 3 ,dip 3 if 0 0 (x( ParrayG 3 bi9 3 dip Pterminated)effectG ! IN: effects.parser USING: strings effects help.markup help.syntax ! ?'&;: parse)effect + *values + (end( string . + (effect( (an instance of ( + *link effect . . . + *description (;arses a stack effect from the current input line.( . + *examples ($his ord is used by ( + *link ;BS$;BN': 5 . ( to parse stack effect declarations.( . *parsing)note ! K %opyright 5%6 ,==S< ,=1= Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: arrays combinators effects kernel lexer make namespaces parser sequences splitting ords ! IN: effects.parser C'@'#: parse)effect '##B#: '##B#: '##B#: '##B#: bad)effect ! invalid)ro )variable ! ro )variable)can7t)have)type ! stack)effect)omits)dashes !

SNIEB&: effect)var P;#IV"$'

: : : :

end)token: 5 end token )) token effect)opener: 5 token )) token effect)closer: 5 token )) token ro )variable: 5 token )) token7

: : : :

6 6 6 6

0 nip 3 0 H 3 ,bi ! inline dup + f (5( (55( ())( . member: ! inline dup + (6( (66( . member: ! inline (..( :head ! inline

: parse)effect)var 5 first: var name )) var 6 nip 0 (:( :tail 0 ro )variable)can7t)have)type 3 0 invalid)ro )variable 3 if ! : parse)effect)value 5 token )) value 6 (:( :tail 0 scan)obFect ,array 3 hen ! ;#IV"$'G

hen 3 curry

: parse)effect)token 5 first: var end )) var more: 6 scan)token + + 0 end)token: 3 0 drop nip f 3 . + 0 effect)opener: 3 0 bad)effect 3 . + 0 effect)closer: 3 0 stack)effect)omits)dashes 3 . + 0 ro )variable: 3 0 parse)effect)var t 3 . 0 0 drop 3 ,dip parse)effect)value < t 3 . cond ! : parse)effect)tokens 5 end )) var tokens 6 0 0 t f 3 dip 0 parse)effect)token 0 f 3 ,dip 3 curry 0 3 3 + . make ! : parse)effect 5 end )) effect 6 0 ())( parse)effect)tokens 3 dip parse)effect)tokens Pvariable)effectG ! : scan)effect 5 )) effect 6 (5( expect (6( parse)effect ! : parse)call5 5 accum ord )) accum 6 0 (6( parse)effect 3 dip ,array appendK ! SNIEB&: in)definition '##B#: can7t)nest)definitions ord ! hen !

hile nip

: check)in)definition 5 )) 6 in)definition get 0 last) ord can7t)nest)definitions 3 : ith)definition 5 quot )) 6 0 check)in)definition t in)definition 3 dip

ith)variable ! inline

: 5:6 5 )) ord def effect 6 0 scan)ne ) ord scan)effect parse)definition s ap 3 ith)definition ! USING: arrays classes help.markup help.syntax math strings combinators sequences ! IN: effects

ords kernel

"#$I%&': (effects( (Stack effect declarations( (Jord definition ords such as ( + *link ;BS$;BN': : . ( and ( + *link ;BS$;BN': G'N'#I%: . ( have a ( + *emphasis (stack effect declaration( . ( as part of their syntax. " stack effect declaration takes the follo ing form:(

+ *code (5 input1 input, ... )) output1 ... 6( . (Stack elements in a stack effect are ordered so that the top of the stack is on the right side. ?ere is an example:( + *synopsis 2 . (;arameters hich are quotations can be declared by suffixing the parameter name ith ( + *snippet (:( . ( and then riting a nested stack effect declaration. If the number of inputs or outputs depends on the stack effects of quotation parameters< ro variables can be declared:( + *subsection (effects)variables( . (Some examples of ro )polymorphic combinators:( + *synopsis hile . + *synopsis if4 . + *synopsis each . (@or ords that are not ( + *link ;BS$;BN': inline . (< only the number of inputs and outputs carries semantic meaning< and effect variables are ignored. ?o ever< nested quotation declarations are enforced for inline ords. Nested quotation declarations are optional for non)recursive inline combinators and only provide better error messages. ?o ever< quotation inputs to ( + *link ;BS$;BN': recursive . ( combinators must have an effect declared. See ( + *link (inference)recursive)combinators( . (.( *nl (In concatenative code< input and output names are for documentation purposes only and certain conventions have been established to make them more descriptive. @or code ritten ith ( + *link (locals( . (< stack values are bound to local variables named by the stack effect7s input parameters.( *nl (Inputs and outputs are typically named after some pun on their data type< or a description of the value7s purpose if the type is very general. $he follo ing are some examples of value names:( + *table + + + *snippet (:( . . (a boolean( . + + + *snippet (PHG( . . + (an ordering specifier! see ( + *link (order)specifiers( . . . + + + *snippet (elt( . . (an obFect hich is an element of a sequence( . + + + *snippet (m( . (< ( + *snippet (n( . . (an integer( . + + + *snippet (obF( . . (an obFect( . + + + *snippet (quot( . . (a quotation( . + + + *snippet (seq( . . (a sequence( . + + + *snippet (assoc( . . (an associative mapping( . + + + *snippet (str( . . (a string( . + + + *snippet (x( . (< ( + *snippet (y( . (< ( + *snippet (8( . . (a number( . + + *snippet (loc( . (a screen location specified as a t o)element array holding x and y co)ordinates( . + + *snippet (dim( . (a screen dimension specified as a t o)element array holding idth and height values( . + + *snippet (4( . ( hen this symbol appears by itself in the list of outputs< it means the ord unconditionally thro s an error( . . (@or reflection and metaprogramming< you can use ( + *link (syntax)effects( . ( to include literal stack effects in your code< or these constructor ords to construct stack effect obFects at runtime:( + *subsections PeffectG Pterminated)effectG Pvariable)effectG . + *see)also (inference( . ! ?'&;: PeffectG + *values + (in( (a sequence of strings or stringetype pairs( .

. + *description (%onstructs an ( + *link effect . ( obFect. 'ach element of ( + *snippet (in( . ( and ( + *snippet (out( . ( must be either a string< hich is equivalent to a ( + *snippet (name( . ( in literal stack effect syntax< or a ( + *link pair . ( here the first element is a string and the second is either a ( + *link class . ( or effect< hich is equivalent to ( + *snippet (name: class( . ( or ( + *snippet (name: 5 nested )) effect 6( . ( in the literal syntax. If the ( + *snippet (out( . ( array consists of a single string element ( + *snippet (>(4>(( . (< a terminating stack effect ill be constructed.( . + *notes ($his ord cannot construct effects ith ( + *link (effects)variables( . (. Use ( + *link Pvariable)effectG . ( to construct variable stack effects.( . + *examples + *example (((USING: effects prettyprint ! + (a( (b( . + (c( . PeffectG .((( (((5 a b )) c 6((( . + *example (((USING: arrays effects prettyprint ! + (a( + (b( array . . + (c( . PeffectG .((( (((5 a b: array )) c 6((( . + *example (((USING: effects prettyprint ! + (a( + (b( 5 x y )) 8 6 . . + (c( . PeffectG .((( (((5 a b: 5 x y )) 8 6 )) c 6((( . + *example (((USING: effects prettyprint ! + (a( + (b( 5 x y )) 8 6 . . + (4( . PeffectG .((( (((5 a b: 5 x y )) 8 6 )) 4 6((( . . ! ?'&;: Pterminated)effectG + *values + (in( (a sequence of strings or stringetype pairs( . + (out( (a sequence of strings or stringetype pairs( . + (terminated:( boolean . + (effect( effect . . + *description (%onstructs an ( + *link effect . ( obFect like ( + *link PeffectG . (. If ( + *snippet (terminated:( . ( is true< the value of ( + *snippet (out( . ( is ignored< and a terminating stack effect is constructed.( . + *notes ($his ord cannot construct effects ith ( + *link (effects)variables( . (. Use ( + *link Pvariable)effectG . ( to construct variable stack effects.( . + *examples + *example (((USING: effects prettyprint ! + (a( + (b( 5 x y )) 8 6 . . + (c( . f Pterminated)effectG .((( (((5 a b: 5 x y )) 8 6 )) c 6((( . + *example (((USING: effects prettyprint ! + (a( + (b( 5 x y )) 8 6 . . + . t Pterminated)effectG .((( (((5 a b: 5 x y )) 8 6 )) 4 6((( . . ! ?'&;: Pvariable)effectG + *values + (in)var( + *maybe string . . + (in( (a sequence of strings or stringetype pairs( . + (out)var( + *maybe string . . + (out( (a sequence of strings or stringetype pairs( . + (effect( effect . . + *description (%onstructs an ( + *link effect . ( obFect like ( + *link PeffectG . (. If ( + *snippet (in)var( . ( or ( + *snippet (out)var( . ( are not ( + *link f . (< they are used as the names of the ( + *link (effects)variables( . ( for the inputs and outputs of the effect obFect.( .

+ (out( (a sequence of strings or stringetype pairs( . + (effect( effect .

+ *examples + *example (((USING: effects prettyprint ! f + (a( (b( . f + (c( . Pvariable)effectG .((( (((5 a b )) c 6((( . + *example (((USING: effects prettyprint ! (x( + (a( (b( . (y( + (c( . Pvariable)effectG .((( (((5 ..x a b )) ..y c 6((( . + *example (((USING: arrays effects prettyprint ! (y( + (a( + (b( 5 ..x )) ..y 6 . . (x( + (c( . Pvariable)effectG .((( (((5 ..y a b: 5 ..x )) ..y 6 )) ..x c 6((( . + *example (((USING: effects prettyprint ! (.( + (a( (b( . f + (4( . Pvariable)effectG .((( (((5 ... a b )) 4 6((( . . ! + PeffectG Pterminated)effectG Pvariable)effectG . related) ords "#$I%&': (effects)variables( (Stack effect ro variables( ($he stack effect of many ( + *link ;BS$;BN': inline . ( combinators can have variable stack effects< depending on the effect of the quotation they call. @or example< the quotation parameter to ( + *link each . ( receives an element from the input sequence each time it is called< but it can also manipulate values on the stack belo the element as long as it leaves the same number of elements on the stack. 5$his is ho ( + *link reduce . ( is implemented in terms of ( + *snippet (each( . (.6 $he stack effect of an ( + *snippet (each( . ( expression thus depends on the stack effect of its input quotation:( + *example (((USING: io sequences stack)checker ! 0 0 rite 3 each 3 infer.((( (((5 x )) 6((( . + *example (((USING: sequences stack)checker ! 0 0 append 3 each 3 infer.((( (((5 x x )) x 6((( . ($his feature is referred to as ro polymorphism. #o )polymorphic combinators are declared by including ro variables in their stack effect< hich are indicated by names starting ith ( + *snippet (..( . (:( + *synopsis each . (Using the same variable name in both the inputs and outputs 5in the above case of ( + *snippet (each( . (< ( + *snippet (...( . (6 indicates that the number of additional inputs and outputs must be the same. Using different variable names indicates that they can be independent. In combinators ith multiple quotation inputs< the number of inputs or outputs represented by a particular ( + *snippet (..( . ( name must match among all of the quotations. @or example< the branches of ( + *link if4 . ( can take a different number of inputs from outputs< as long as they both have the same stack height. $he true branch receives the test value as an added input. $his is declared as follo s:( + *synopsis if4 . (Stack effect variables can only occur as the first input or first output of a stack effect! names starting in ( + *snippet (..( . ( cause a syntax error if they occur else here in the effect. @or ords that are not ( + *link ;BS$;BN': inline . (< effect variables are currently ignored by the stack checker.( ! "EBU$: (effects( ?'&;: effect + *class)description ("n obFect representing a stack effect. ?olds a sequence of inputs< a sequence of outputs and a flag indicating if an error is thro n unconditionally.( . ! ?'&;: effect)height + *values + (effect( effect . + (n( integer . . + *description (Butputs the number of obFects added to the data stack by the stack effect. $his ill be negative if the stack effect only removes obFects

from the stack.( . ! ?'&;: effectPH + *values + (effect1( effect . + (effect,( effect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (effect1( . ( is substitutable for ( + *snippet (effect,( . (. Jhat this means is that both stack effects change the stack height by the same amount< the first takes a smaller or equal number of inputs as the second< and either both or neither one terminate execution by thro ing an error.( . ! ?'&;: effectH + *values + (effect1( effect . + (effect,( effect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (effect1( . ( and ( + *snippet (effect,( . ( represent the same stack transformation< ithout looking parameter names.( . + *examples + *example (USING: effects prettyprint !( (5 a )) b 6 5 x )) y 6 effectH .( (t( . . ! ?'&;: effectGstring + *values + (obF( obFect . + (str( string . . + *description ($urns a stack effect obFect into a string mnemonic.( . + *examples + *example (USING: effects io !( (+ >(x>( . + >(y>( >(8>( . PeffectG effectGstring print( (5 x )) y 8 6( . . ! ?'&;: stack)effect + *values + ( ord( ord . + (effectQf( + *maybe effect . . . + *description (Butputs the stack effect of a ord! either a stack effect declared ith ( + *link ;BS$;BN': 5 . (< or an inferred stack effect 5see ( + *link (inference( . (6.( . ! USING: effects effects.parser eval kernel tools.test prettyprint accessors quotations sequences ! IN: effects.tests 0 t 3 0 + (a( . + (a( . PeffectG + (a( (b( . + (a( unit)test 0 f 3 0 + (a( . + . PeffectG + (a( (b( . + (a( (b( unit)test 0 t 3 0 + (a( (b( . + (a( (b( . PeffectG + (a( (b( effectPH 3 unit)test 0 f 3 0 + (a( (b( (c( . + (a( (b( (c( . PeffectG + PeffectG effectPH 3 unit)test 0 f 3 0 + (a( (b( . + (a( (b( (c( . PeffectG + (a( effectPH 3 unit)test 0 , 3 0 5 a b )) c 6 inGG length 3 unit)test 0 1 3 0 5 a b )) c 6 outGG length 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 t t f f f f 3 3 3 3 3 3 0 0 0 0 0 0 5 5 5 5 5 5 a b )) c 6 5 ... b )) 6 5 ... a b ... a b )) ... c ... b )) ... 6 5 a b )) c 6 5 ... a b )) c 6 5 ..x a b )) ... )) ... c 6 6 5 a b )) a b )) c 6 a b )) c 6 a b )) ..y (b( . PeffectG effectPH 3 . PeffectG effectPH 3 . + (a( (b( . PeffectG (a( (b( . + (a( (b( . (b( . + (a( (b( . PeffectG

c 6 effectPH 3 unit)test effectPH 3 unit)test c 6 effectPH 3 unit)test effectPH 3 unit)test effectPH 3 unit)test c 6 effectPH 3 unit)test

(5 (5 (5 (5 (5 (5

obFect )) obFect 6( 3 0 + f . + f . PeffectG unparse 3 unit)test a b )) c d 6( 3 0 + (a( (b( . + (c( (d( . PeffectG unparse 3 unit)test )) c d 6( 3 0 + . + (c( (d( . PeffectG unparse 3 unit)test a b )) 6( 3 0 + (a( (b( . + . PeffectG unparse 3 unit)test )) 6( 3 0 + . + . PeffectG unparse 3 unit)test a b )) c 6( 3 0 5 a b )) c 6 unparse 3 unit)test

0 + (x( (y( . 3 0 + (y( (x( . 5 a b )) b a 6 shuffle 3 unit)test 0 + (y( (x( (y( . 3 0 + (y( (x( . 5 a b )) a b a 6 shuffle 3 unit)test 0 + . 3 0 + (y( (x( . 5 a b )) 6 shuffle 3 unit)test 0 t 3 0 5 )) 6 5 )) 6 compose)effects 5 )) 6 effectH 3 unit)test 0 t 3 0 5 )) 4 6 5 )) 6 compose)effects 5 )) 4 6 effectH 3 unit)test 0 t 3 0 5 )) 6 5 )) 4 6 compose)effects 5 )) 4 6 effectH 3 unit)test 0 + obFect obFect . 3 0 5 a b )) 6 effect)in)types 3 unit)test 0 + obFect sequence . 3 0 5 a b: sequence )) 6 effect)in)types 3 unit)test 0 0 0 0 f 3 f 3 (a( 3 + (b( 0 5 0 5 0 5 (c( a b c )) d 6 in)varGG 3 unit)test )) d 6 in)varGG 3 unit)test ..a b c )) d 6 in)varGG 3 unit)test . 3 0 5 ..a b c )) d 6 inGG 3 unit)test

0 f 3 0 5 ..a b c )) e 6 out)varGG 3 unit)test 0 (d( 3 0 5 ..a b c )) ..d e 6 out)varGG 3 unit)test 0 + (e( . 3 0 5 ..a b c )) ..d e 6 outGG 3 unit)test 0 (5 a ..b c )) d 6( eval5 )) effect 6 3 0 errorGG invalid)ro )variable: 3 must)fail) ith 0 (5 ..a: integer b c )) d 6( eval5 )) effect 6 3 0 errorGG ro )variable)can7t)have)type: 3 must)fail) ith K test curry)effect 0 5 )) x 6 3 0 5 c )) d 6 curry)effect 3 unit)test 0 5 )) x x 6 3 0 5 )) d 6 curry)effect 3 unit)test 0 5 x )) 6 3 0 5 a b )) 6 curry)effect 3 unit)test K %opyright 5%6 ,==R< ,==U Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors alien.accessors kernel math sequences sequences.private ! IN: byte)arrays EUI&$IN: byte)array + length array)capacity read)only initial: = . ! I: byte)array I: byte)array I: byte)array I: byte)array : Gbyte)array I: byte)array clone 5clone6 ! inline length lengthGG ! inline nth)unsafe s ap integerGfixnum alien)unsigned)1 ! inline set)nth)unsafe s ap integerGfixnum set)alien)unsigned)1 ! inline 5 seq )) byte)array 6 E+ . clone)like ! inline ne )sequence drop 5byte)array6 ! inline

I: byte)array equal: over byte)array: 0 sequenceH 3 0 ,drop f 3 if ! I: byte)array resi8e resi8e)byte)array ! inline INS$"N%': byte)array sequence : 1byte)array 5 x )) byte)array 6 E+ . 1sequence ! inline : ,byte)array 5 x y )) byte)array 6 E+ . ,sequence ! inline : -byte)array 5 x y 8 )) byte)array 6 E+ . -sequence ! inline : /byte)array 5 x y 8 )) byte)array 6 E+ . /sequence ! inline

USING: byte)arrays kernel math sequences sequences.private tools.test ! IN: byte)arrays.tests 0 L E+ 1 , - . 3 0 L E+ 1 , - . resi8e)byte)array 0 length 3 0 - head 3 bi 3 unit)test 0 E+ 1 , . 3 0 , E+ 1 , - / A L R S U . resi8e)byte)array 3 unit)test 0 )1= E+ . resi8e)byte)array 3 must)fail 0 E+ 1,- . 3 0 1,- 1byte)array 3 unit)test 0 E+ 1,- . 3 0 1,- = E+ = . 0 set)nth 3 keep 3 unit)test 0 E+ 1,- . 3 0 1,- Gbignum = E+ = . 0 set)nth 3 keep 3 unit)test 0 1.A E+ 1 , - . nth)unsafe 3 must)fail 0 = 1.A E+ 1 , - . set)nth)unsafe 3 must)fail USING: kernel help.markup help.syntax ! IN: byte)arrays "#$I%&': (byte)arrays( (Eyte arrays( (Eyte arrays are fixed)si8e mutable sequences 5( + *link (sequence)protocol( . (6 hose elements are integers in the range =),AA< inclusive. 'ach element only uses one byte of storage< hence the name. $he literal syntax is covered in ( + *link (syntax)byte)arrays( . (.( *nl (Eyte array ords are in the ( + *vocab)link (byte)arrays( . ( vocabulary.( *nl (Eyte arrays play a special role in the % library interface! they can be used to pass binary data back and forth bet een @actor and %. See ( + *link (c)pointers( . (.( *nl (Eyte arrays form a class of obFects.( + *subsections byte)array byte)array: . ($here are several ays to construct byte arrays.( + *subsections Gbyte)array Pbyte)arrayG 1byte)array ,byte)array -byte)array /byte)array . (#esi8ing byte arrays:( + *subsections resi8e)byte)array . ! "EBU$: (byte)arrays( ?'&;: byte)array + *description ($he class of byte arrays. See ( + *link (syntax)byte)arrays( . ( for syntax and ( + *link (byte)arrays( . ( for general information.( . ! ?'&;: Pbyte)arrayG + *values + (n( (a non)negative integer( . + (byte)array( (a ne byte array( . . + *description (%reates a ne byte array holding ( + *snippet (n( . (

bytes.( . ! ?'&;: 5byte)array6 + *values + (n( (a non)negative integer( . + (byte)array( (a ne byte array( . . + *description (%reates a ne byte array ith unspecified contents of length ( + *snippet (n( . ( bytes.( . ! ?'&;: Gbyte)array + *values + (seq( (a sequence( . + (byte)array( byte)array . . + *description (Butputs a freshly)allocated byte array hose elements have the same signed byte values as a given sequence.( . + *errors ($hro s an error if the sequence contains elements other than integers.( . ! ?'&;: 1byte)array + *values + (x( obFect . + (byte)array( byte)array . . + *description (%reates a ne byte)array ?'&;: ,byte)array + *values + (x( obFect . + (y( obFect . + (byte)array( byte)array . . + *description (%reates a ne byte)array

ith one element.( . !

ith t o elements.( . !

?'&;: -byte)array + *values + (x( obFect . + (y( obFect . + (8( obFect . + (byte)array( byte)array . . + *description (%reates a ne byte)array ith three element.( . ! ?'&;: /byte)array + *values + ( ( obFect . + (x( obFect . + (y( obFect . + (8( obFect . + (byte)array( byte)array . . + *description (%reates a ne byte)array ith four elements.( . ! + 1byte)array ,byte)array -byte)array /byte)array . related) ords ?'&;: resi8e)byte)array + *values + (n( (a non)negative integer( . + (byte)array( byte)array . + (ne )byte)array( byte)array . . + *description (#esi8es the byte array to have a length of ( + *snippet (n( . ( elements. Jhen making the byte array shorter< this ord may either create a ne byte array or modify the existing byte array in place. Jhen making the byte array longer< this ord al ays allocates a ne byte array< filling remaining space ith 8eroes.( . + *side)effects (byte)array( . ! USING: help.markup help.syntax math sequences ! IN: hash)sets "#$I%&': (hash)sets( (?ash sets( ($he ( + *vocab)link (hash)sets( . ( vocabulary implements hashtable)like sets. ?ash sets form a class:( + *subsections hash)set . (%onstructing ne hash sets:( + *subsections Phash)setG Ghash)set . ($he syntax for hash sets is described in ( + *link (syntax)hash)sets( . (.( ! "EBU$: (hash)sets(

?'&;: hash)set + *class)description ($he class of hashtable)like sets. $hese implement the ( + *link (sets( . (.( . ! ?'&;: Phash)setG + *values + (capacity( number . + (hash)set( hash)set . . + *description (%reates a ne hash set capable of storing ( + *snippet (capacity( . ( elements before gro ing.( . ! ?'&;: Ghash)set + *values + (members( sequence . + (hash)set( hash)set . . + *description (%reates a ne hash set ith the given members.( . ! K %opyright 5%6 ,=1= Caniel 'hrenberg K %opyright 5%6 ,==A< ,=11 Xohn Eenediktsson< Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors arrays hash)sets hashtables.private kernel kernel.private math math.private sequences sequences.private sets sets.private slots.private vectors ! IN: hash)sets $U;&': hash)set + count array)capacity . + deleted array)capacity . + array array . ! P;#IV"$' : hash9 5 key array )) i 6 0 hashcode Gfixnum 3 dip rap ! inline

: probe 5 array i probeZ )) array i probeZ 6 1 fixnum2fast 0 fixnum2fast over rap 3 keep ! inline : no)key 5 key array )) array n : 6 nip f f ! inline : 5key96 5 key array i probeZ )) array n : 6 0 -dup s ap array)nth 3 dip over 55empty66 eq: 0 /drop no)key 3 0 0 H 3 dip s ap 0 drop rot drop t 3 0 probe 5key96 3 if 3 if ! inline recursive : key9 5 key hash )) array n : 6 arrayGG dup lengthGG = eq: 0 no)key 3 0 ,dup hash9 = 5key96 3 if ! inline : Phash)arrayG 5 n )) array 6 1 2 next)po er)of), , 4 55empty66 ParrayG ! inline : reset)hash 5 n hash )) 6 s ap Phash)arrayG GGarray init)hash ! inline : 5ne )key96 5 key array i probeZ F )) array i F empty: 6 0 ,dup s ap array)nth 3 ,dip pick tombstone: 0 rot 55empty66 eq: 0 nip 0 drop 3 -dip t 3 0 pick or 0 probe 3 dip 5ne )key96 3 if

3 0 0 0 pick 3 dip H 3 ,dip rot 0 nip 0 drop 3 -dip f 3 0 0 probe 3 dip 5ne )key96 3 if 3 if ! inline recursive : ne )key9 5 key hash )) array n : 6 0 arrayGG ,dup hash9 = f 5ne )key96 3 keep s ap 0 over 0 hash)deleted) 3 0 hash)count2 3 if s ap or t 3 0 ,drop f 3 if ! inline : set)nth)item 5 key seq n )) 6 , fixnum2fast set)slot ! inline : 5adFoin6 5 key hash )) : 6 dupd ne )key9 0 set)nth)item 3 dip ! inline : 5rehash6 5 seq hash )) 6 0 5adFoin6 drop 3 curry each ! inline : hash)large: 5 hash )) : 6 0 countGG - fixnum4fast 1 fixnum2fast 3 0 arrayGG lengthGG 1 fixnum)shift)fast 3 bi fixnumG ! inline : each)member 5 array quot: 5 elt )) 6 )) 6 0 if 3 curry 0 dup tombstone: 0 drop 3 3 prepose each ! inline : gro )hash 5 hash )) 6 + hash)set . declare 0 0 arrayGG 3 0 cardinality 1 2 3 0 reset)hash 3 tri 3 keep 0 5adFoin6 drop 3 curry each)member ! : :gro )hash 5 hash )) 6 dup hash)large: 0 gro )hash 3 0 drop 3 if ! inline ;#IV"$'G : Phash)setG 5 capacity )) hash)set 6 hash)set ne 0 reset)hash 3 keep ! inline I: hash)set in: key9 ,nip ! I: hash)set clear)set 0 init)hash 3 0 arrayGG 0 drop 55empty66 3 mapK drop 3 bi ! I: hash)set delete 0 nip 3 0 key9 3 ,bi 0 0 55tombstone66 3 ,dip set)nth)item hash)deleted2 3 0 -drop 3 if ! I: hash)set cardinality 0 countGG 3 0 deletedGG 3 bi ) ! inline : rehash 5 hash)set )) 6 0 members 3 0 clear)set 3 0 5rehash6 3 tri !

I: hash)set adFoin dup :gro )hash 5adFoin6 drop ! I: hash)set :adFoin dup :gro )hash 5adFoin6 ! I: hash)set members 0 arrayGG 3 0 cardinality PvectorG 3 bi 0 0 push)unsafe 3 curry each)member 3 keep + . like ! I: hash)set clone 5clone6 0 clone 3 change)array ! inline I: hash)set equal: over hash)set: 0 setH 3 0 ,drop f 3 if ! : Ghash)set 5 members )) hash)set 6 dup length Phash)setG 0 5rehash6 3 keep ! inline I: hash)set set)like drop dup hash)set: 0 :members Ghash)set 3 unless ! inline INS$"N%': hash)set set K Bverrides for performance P;#IV"$' : and)tombstones 5 quot: 5 elt )) : 6 )) quot: 5 elt )) : 6 6 0 if 3 curry 0 dup tombstone: 0 drop t 3 3 prepose ! inline : not)tombstones 5 quot: 5 elt )) : 6 )) quot: 5 elt )) : 6 6 0 if 3 curry 0 dup tombstone: 0 drop f 3 3 prepose ! inline : arrayQtester 5 hash)set1 hash)set, )) array quot 6 0 arrayGG 3 dip 0 in: 3 curry ! inline : filter)members 5 hash)set array quot: 5 elt )) : 6 )) accum 6 0 dup 3 prepose rot cardinality PvectorG 0 0 push)unsafe 3 curry 0 0 drop 3 if 3 curry compose each 3 keep ! inline ;#IV"$'G I: hash)set intersect over hash)set: 0 smallQlarge dupd arrayQtester not)tombstones filter)members Ghash)set 3 0 5intersect6 Ghash)set 3 if ! I: hash)set intersects: over hash)set: 0 smallQlarge arrayQtester not)tombstones any: 3 0 smallQlarge sequenceQtester any: 3 if ! I: hash)set union over hash)set: 0 smallQlarge 0 arrayGG 3 0 clone 3 bi4 0 0 adFoin 3 curry each)member 3 keep

3 0 5union6 Ghash)set 3 if ! I: hash)set diff over hash)set: 0 dupd arrayQtester 0 not 3 compose not)tombstones filter)members Ghash)set 3 0 5diff6 Ghash)set 3 if ! I: hash)set subset: over hash)set: 0 ,dup 0 cardinality 3 bi9 G 0 ,drop f 3 0 arrayQtester and)tombstones all: 3 if 3 0 call)next)method 3 if ! I: hash)set setH over hash)set: 0 ,dup 0 cardinality 3 bi9 eq: 0 arrayQtester and)tombstones all: 3 0 ,drop f 3 if 3 0 call)next)method 3 if ! K Cefault methods I: f fast)set drop = Phash)setG ! I: sequence fast)set Ghash)set ! I: sequence duplicates dup length Phash)setG 0 :adFoin not 3 curry filter ! I: sequence all)unique: dup length Phash)setG 0 :adFoin 3 curry all: ! K %opyright 5%6 ,=1= Caniel 'hrenberg K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: sets tools.test kernel sorting prettyprint hash)sets ! IN: hash)sets.tests 0 + 1 , - . 3 0 ?S+ 1 , - . members natural)sort 3 unit)test 0 (?S+ 1 , - / .( 3 0 ?S+ 1 , - / . unparse 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 t 3 f 3 ?S+ ?S+ ?S+ ?S+ ?S+ + 1 ?S+ ?S+ t 3 f 3 f 3 f 3 t 3 t 3 ?S+ t 3 t 3 0 0 1 1 1 1 1 , 1 , 0 0 0 0 0 0 1 0 0 1 , , , , , . ?S+ ?S+ - . . 3 - . . 3 . 3 3 0 / 3 1 1 1 1 , . 0 1 1 = 1 , . in: 3 unit)test = 1 , . in: 3 unit)test 3 0 - ?S+ 1 , . clone 0 adFoin 3 keep 3 unit)test 0 , ?S+ 1 , . clone 0 adFoin 3 keep 3 unit)test 3 0 / ?S+ 1 , - . clone 0 delete 3 keep 3 unit)test 0 - ?S+ 1 , - . clone 0 delete 3 keep 3 unit)test 0 ?S+ 1 , . fast)set 3 unit)test ?S+ 1 , . members natural)sort 3 unit)test . 3 0 ?S+ 0 ?S+ 1 , , - . ?S+ . ?S+ , . ?S+ , , - . ?S+ - . ?S+ , ?S+ , - / ?S+ 1 , , - . ?S+ , - . ?S+ 1 , / / , . . , , , - . ?S+ , - / . union 3 unit)test . ?S+ , - / . intersect 3 unit)test - / . intersects: 3 unit)test . intersects: 3 unit)test . subset: 3 unit)test - / . subset: 3 unit)test / . subset: 3 unit)test subset: 3 unit)test ?S+ , - / . diff 3 unit)test 1 - . setH 3 unit)test 1 - . H 3 unit)test

, - . ?S+ ?S+ ?S+ ?S+ ?S+ ?S+ . 3 ?S+ ?S+

0 f 3 0 ?S+ , - . ?S+ , 1 - . setH 3 unit)test 0 f 3 0 ?S+ 1 , - . ?S+ , - . setH 3 unit)test 0 ?S+ 1 , . ?S+ 1 , - . 3 0 ?S+ 1 , . clone dup clone 0 - s ap adFoin 3 keep 3 unit)test 0 t 3 0 ?S+ . null: 3 unit)test 0 f 3 0 ?S+ 1 . null: 3 unit)test + + . . 0 + 1 , - . duplicates 3 unit)test + f . 0 + 1 , - . Ghash)set duplicates 3 unit)test + + 1 . . 0 + 1 , 1 . duplicates 3 unit)test K %opyright 5%6 ,==S< ,=1= Slava ;estov< Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel kernel.private math ! IN: math.order SNIEB&: 2lt2 SNIEB&: 2eq2 SNIEB&: 2gt2 : invert)comparison 5 PHG )) GHP 6 ZK %an7t use case< index or nth here dup 2lt2 eq: 0 drop 2gt2 3 0 2eq2 eq: 2eq2 2lt2 : 3 if ! G'N'#I%: PHG 5 obF1 obF, )) PHG 6 : GHP 5 obF1 obF, )) GHP 6 PHG invert)comparison ! inline P;#IV"$' K Cefining a math generic for comparison forces a single math K promotion< and speeds up comparisons on numbers. : 5realPHG6 5 x y )) PHG 6 ,dup P 0 ,drop 2lt2 3 0 numberH 2eq2 2gt2 : 3 if ! inline I"$?: realPHG 5 x y )) PHG 6 I: fixnum realPHG + fixnum fixnum . declare 5realPHG6 ! inline I: bignum realPHG + bignum bignum . declare 5realPHG6 ! inline I: float realPHG + float float . declare 5realPHG6 ! inline I: real realPHG 5realPHG6 ! inline ;#IV"$'G I: real PHG realPHG ! inline G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: I: I: I: I: I: I: I: I: obFect obFect obFect obFect real real real real before: 5 obF1 obF, )) : 6 after: 5 obF1 obF, )) : 6 beforeH: 5 obF1 obF, )) : 6 afterH: 5 obF1 obF, )) : 6 before: 5 obF1 obF, )) : 6 PHG 2lt2 eq: ! inline after: 5 obF1 obF, )) : 6 PHG 2gt2 eq: ! inline beforeH: 5 obF1 obF, )) : 6 PHG 2gt2 eq: not ! inline afterH: 5 obF1 obF, )) : 6 PHG 2lt2 eq: not ! inline

before: 5 obF1 obF, )) : 6 P ! inline after: 5 obF1 obF, )) : 6 G ! inline beforeH: 5 obF1 obF, )) : 6 PH ! inline afterH: 5 obF1 obF, )) : 6 GH ! inline

G'N'#I%: min 5 obF1 obF, )) obF 6

G'N'#I%: max 5 obF1 obF, )) obF 6 I: obFect min 0 before: 3 most ! inline I: obFect max 0 after: 3 most ! inline : clamp 5 x min max )) y 6 0 max 3 dip min ! inline : bet een: 5 x y 8 )) : 6 pick afterH: 0 afterH: 3 0 ,drop f 3 if ! inline : 0)3 5 x y )) 8 6 ) = max ! inline : compare 5 obF1 obF, quot )) PHG 6 bi9 PHG ! inline USING: kernel math.order tools.test ! IN: math.order.tests 0 0 0 0 0 2lt2 2gt2 2lt2 2eq2 2gt2 3 3 3 3 3 0 0 0 0 0 (ab( (abc( PHG 3 unit)test (abc( (ab( PHG 3 unit)test - / PHG 3 unit)test / / PHG 3 unit)test / - PHG 3 unit)test

0 ,= 3 0 ,= = 1== clamp 3 unit)test 0 = 3 0 ),= = 1== clamp 3 unit)test 0 1== 3 0 1,= = 1== clamp 3 unit)test USING: help.markup help.syntax kernel math quotations math.private ords ords.symbol ! IN: math.order ?'&;: PHG + *values + (obF1( obFect . + (obF,( obFect . + (PHG( (an ordering specifier( . . + *contract (%ompares t o obFects using an intrinsic linear order< for example< the natural order for real numbers and lexicographic order for strings.( *nl ($he output value is one of the follo ing:( + *list + + *link 2lt2 . ( ) indicating that ( + *snippet (obF1( . ( precedes ( + *snippet (obF,( . . + + *link 2eq2 . ( ) indicating that ( + *snippet (obF1( . ( is equal to ( + *snippet (obF,( . . + + *link 2gt2 . ( ) indicating that ( + *snippet (obF1( . ( follo s ( + *snippet (obF,( . . . . ! ?'&;: GHP + *values + (obF1( obFect . + (obF,( obFect . + (GHP( (an ordering specifier( . . + *description (%ompares t o obFects using the ( + *link PHG . ( comparator and inverts the output.( . ! + PHG GHP . related) ords ?'&;: 2lt2 + *description (Butput by ( + *link PHG . ( less than the second obFect.( . ! ?'&;: 2eq2 + *description (Butput by ( + *link PHG . ( the second obFect.( . ! hen the first obFect is strictly

hen the first obFect is equal to

?'&;: 2gt2 + *description (Butput by ( + *link PHG . ( greater than the second obFect.( . !

hen the first obFect is strictly

?'&;: invert)comparison + *values + (PHG( (an ordering specifier( . + (GHP( (an ordering specifier( . . + *description (Invert the comparison symbol returned by ( + *link PHG . (.( . + *examples + *example (USING: math.order prettyprint !( (2lt2 invert)comparison .( (2gt2( . . ! ?'&;: compare + *values + (obF1( obFect . + (obF,( obFect . + (quot( + *quotation (5 obF )) ne obF 6( . . + (PHG( (an ordering specifier( . . + *description (%ompares the results of applying the quotation to both obFects via ( + *link PHG . (.( . + *examples + *example (USING: kernel math.order prettyprint sequences !( (>(hello>( >(hi>( 0 length 3 compare .( (2gt2( . . ! ?'&;: max + *values + (obF1( obFect . + (obF,( obFect . + (obF( obFect . . + *description (Butputs the greatest of t o ordered values.( . + *notes (If one value is a floating point positive 8ero and the other is a negative 8ero< the result is undefined.( . ! ?'&;: min + *values + (obF1( obFect . + (obF,( obFect . + (obF( obFect . . + *description (Butputs the smallest of t o ordered values.( . + *notes (If one value is a floating point positive 8ero and the other is a negative 8ero< the result is undefined.( . ! ?'&;: clamp + *values + (x( obFect . + (min( obFect . + (max( obFect . + (y( obFect . . + *description (Butputs ( + *snippet (x( . ( if contained in the interval ( + *snippet (0min<max3( . ( or else outputs one of the endpoints.( . ! ?'&;: bet een: + *values + (x( obFect . + (y( obFect . + (8( obFect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (x( . ( is in the interval ( + *snippet (0y<83( . (.( . + *notes ("s per the closed interval notation< the end)points are included in the interval.( . ! ?'&;: before: + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (obF1( . ( comes before ( + *snippet (obF,( . ( using an intrinsic total order.( . + *notes (Implemented using ( + *link PHG . (.( . ! ?'&;: after: + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (obF1( . ( comes after ( + *snippet (obF,( . ( using an intrinsic total order.( . + *notes (Implemented using ( + *link PHG . (.( . ! ?'&;: beforeH: + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (obF1( . ( comes before or equals ( + *snippet (obF,( . ( using an intrinsic total order.( . + *notes (Implemented using ( + *link PHG . (.( . !

?'&;: afterH: + *values + (obF1( obFect . + (obF,( obFect . + (:( (a boolean( . . + *description ($ests if ( + *snippet (obF1( . ( comes after or equals ( + *snippet (obF,( . ( using an intrinsic total order.( . + *notes (Implemented using ( + *link PHG . (.( . ! + before: after: beforeH: afterH: . related) ords ?'&;: 0)3 + *values + (x( real . + (y( real . + (8( real . . + *description (Subtracts ( + *snippet (y( . ( from ( + *snippet (x( . (. If the result is less than 8ero< outputs 8ero.( . ! "#$I%&': (order)specifiers( (Brdering specifiers( (Brdering ords such as ( + *link PHG . ( output one of the follo ing values< indicating that of t o obFects being compared< the first is less than the second< the t o are equal< or that the first is greater than the second:( + *subsections 2lt2 2eq2 2gt2 . ! "#$I%&': (math.order.example( (&inear order example( (" tuple class hich defines an ordering among instances by comparing the values of the ( + *snippet (id( . ( slot:( + *code ($U;&': sprite id name bitmap !( (I: sprite PHG 0 idGG 3 compare !( . ! "#$I%&': (math.order( (&inear order protocol( (Some classes define an intrinsic order amongst instances. $his includes numbers< sequences 5in particular< strings6< and ords.( + *subsections PHG GHP compare invert)comparison . ($he above ords output order specifiers.( + *subsections (order)specifiers( . (Utilities for comparing obFects:( + *subsections after: before: afterH: beforeH: . (Iinimum< maximum< clamping:( + *subsections min max clamp . (But of the above generic ords< it suffices to implement ( + *link PHG . ( alone. $he others may be provided as an optimi8ation.( + *subsections (math.order.example( . + *see)also (sequences)sorting( . ! "EBU$: (math.order(

K %opyright 5%6 ,==-< ,==U Slava ;estov< Xoe Groff. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel ! IN: math EUI&$IN: fixnum ! EUI&$IN: bignum ! EUI&$IN: float ! G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: Gfixnum 5 x )) n 6 foldable Gbignum 5 x )) n 6 foldable Ginteger 5 x )) n 6 foldable Gfloat 5 x )) y 6 foldable integerGfixnum 5 x )) y 6 foldable integerGfixnum)strict 5 x )) y 6 foldable

G'N'#I%: numerator 5 aQb )) a 6 G'N'#I%: denominator 5 aQb )) b 6 G'N'#I%: real)part 5 8 )) x 6 G'N'#I%: imaginary)part 5 8 )) y 6 I"$?: numberH 5 x y )) : 6 foldable I: obFect numberH ,drop f ! I"$?: I"$?: I"$?: I"$?: I"$?: I"$?: I"$?: I"$?: I"$?: P PH G GH 5 5 5 5 x x x x y y y y )) )) )) )) : : : : 6 6 6 6 foldable foldable foldable foldable )) : 6 foldable foldable foldable foldable foldable

unordered: 5 uP 5 x y )) uPH 5 x y )) uG 5 x y )) uGH 5 x y ))

x : : : :

y 6 6 6 6

I: obFect unordered: ,drop f ! I"$?: I"$?: I"$?: I"$?: I"$?: I"$?: I"$?: 2 ) 4 Q Qf Qi mod 5 5 5 5 5 5 5 x x x x x x x y y y y y y y )) )) )) )) )) )) )) 8 8 8 8 8 8 8 6 6 6 6 6 6 6 foldable foldable foldable foldable foldable foldable foldable 6 foldable

I"$?: Qmod 5 x y )) 8

I"$?: bitand 5 x y )) 8 6 foldable I"$?: bitor 5 x y )) 8 6 foldable I"$?: bitxor 5 x y )) 8 6 foldable G'N'#I%Z shift 1 5 x n )) y 6 foldable G'N'#I%: bitnot 5 x )) y 6 foldable G'N'#I%Z bit: 1 5 x n )) : 6 foldable G'N'#I%: abs 5 x )) y 6 foldable P;#IV"$' G'N'#I%: 5log,6 5 x )) n 6 foldable

;#IV"$'G '##B#: out)of)fixnum)range n ! '##B#: log,)expects)positive x ! : log, 5 x )) n 6 dup = PH 0 log,)expects)positive 3 0 5log,6 3 if ! inline : : : : : : : : : : 8ero: 5 x )) : 6 = numberH ! inline ,Q 5 x )) y 6 )1 shift ! inline sq 5 x )) y 6 dup 4 ! inline neg 5 x )) )x 6 )1 4 ! inline sgn 5 x )) n 6 dup = P 0 drop )1 3 0 = G 1 = : 3 if ! inline :12 5 x )) y 6 0 1 2 3 0 = 3 if4 ! inline rem 5 x y )) 8 6 abs 0 mod 3 0 2 3 0 mod 3 tri ! foldable ,T 5 n )) ,Tn 6 1 s ap shift ! inline even: 5 n )) : 6 1 bitand 8ero: ! inline odd: 5 n )) : 6 1 bitand 1 numberH ! inline

G'N'#I%: neg: 5 x )) )x 6 : if)8ero 5 ..a n quot1: 5 ..a )) ..b 6 quot,: 5 ..a n )) ..b 6 )) ..b 6 0 dup 8ero: 3 0 0 drop 3 prepose 3 0 3 tri4 if ! inline : hen)8ero 5 ..a n quot: 5 ..a )) ..b 6 )) ..b 6 0 3 if)8ero ! inline

: unless)8ero 5 ..a n quot: 5 ..a )) ..b 6 )) ..b 6 0 3 s ap if)8ero ! inline UNIBN: integer fixnum bignum ! $U;&': ratio + numerator integer read)only . + denominator integer read)only . ! UNIBN: rational integer ratio ! I: rational neg: = P ! inline UNIBN: real rational float ! $U;&': complex + real real read)only . + imaginary real read)only . ! UNIBN: number real complex ! G'N'#I%: recip 5 x )) y 6 I: number recip 1 s ap Q ! inline : fp)bit iseH 5 x y )) : 6 0 doubleGbits 3 same: ! inline G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: G'N'#I%: I: I: I: I: I: obFect obFect obFect obFect obFect fp)special: 5 x )) : 6 fp)nan: 5 x )) : 6 fp)qnan: 5 x )) : 6 fp)snan: 5 x )) : 6 fp)infinity: 5 x )) : 6 fp)nan)payload 5 x )) bits 6 fp)sign 5 x )) : 6 fp)special: drop f ! inline fp)nan: drop f ! inline fp)qnan: drop f ! inline fp)snan: drop f ! inline fp)infinity: drop f ! inline

: Pfp)nanG 5 payload )) nan 6 =xRff============= bitor bitsGdouble ! inline G'N'#I%: next)float 5 m )) n 6 G'N'#I%: prev)float 5 m )) n 6 : next)po er)of), 5 m )) n 6 dup , PH 0 drop , 3 0 1 ) log, 1 2 ,T 3 if ! inline : po er)of),: 5 n )) : 6 dup = PH 0 drop f 3 0 dup 1 ) bitand 8ero: 3 if ! foldable : align 5 m )) n 6 1 ) 0 2 3 keep bitnot bitand ! inline P;#IV"$' : iterate)prep 5 n quot )) i n quot 6 0 = 3 ,dip ! inline : if)iterate: 5 i n true false )) 6 0 ,over P 3 ,dip if ! inline : iterate)step 5 i n quot )) i n quot 6 ZK "pply quot to i< keep i and quot< hide n. 0 nip call 3 -keep ! inline : iterate)rot 5 : i n quot )) i n quot : 6 0 rot 3 dip s ap ! inline : iterate)next 5 i n quot )) i7 n quot 6 0 1 2 3 ,dip ! inline ;#IV"$'G : 5each)integer6 5 ... i n quot: 5 ... i )) ... 6 )) ... 6 0 iterate)step iterate)next 5each)integer6 3 0 -drop 3 if)iterate: ! inline recursive : 5find)integer6 5 ... i n quot: 5 ... i )) ... : 6 )) ... iQf 6 0 iterate)step iterate)rot 0 ,drop 3 0 iterate)next 5find)integer6 3 if 3 0 -drop f 3 if)iterate: ! inline recursive : 5all)integers:6 5 ... i n quot: 5 ... i )) ... : 6 )) ... : 6 0 iterate)step iterate)rot 0 iterate)next 5all)integers:6 3 0 -drop f 3 if 3 0 -drop t 3 if)iterate: ! inline recursive : each)integer 5 ... n quot: 5 ... i )) ... 6 )) ... 6 iterate)prep 5each)integer6 ! inline : times 5 ... n quot: 5 ... )) ... 6 )) ... 6 0 drop 3 prepose each)integer ! inline : find)integer 5 ... n quot: 5 ... i )) ... : 6 )) ... i 6 iterate)prep 5find)integer6 ! inline : all)integers: 5 ... n quot: 5 ... i )) ... : 6 )) ... : 6 iterate)prep 5all)integers:6 ! inline : find)last)integer 5 ... n quot: 5 ... i )) ... : 6 )) ... i 6

over = P 0 ,drop f 3 0 0 call 3 ,keep rot 0 drop 3 0 0 1 ) 3 dip find)last)integer 3 if 3 if ! inline recursive USING: help.markup help.syntax kernel sequences quotations math.private byte)arrays io.binary ! IN: math ?'&;: numberH + *values + (x( number . + (y( number . + (:( (a boolean( . . + *description ($ests if t o numbers have the same numeric value.( . + *notes ($his ord differs from ( + *link H . ( in that it disregards differences in type hen comparing numbers.( *nl ($his ord performs an unordered comparison on floating point numbers. See ( + *link (math.floats.compare( . ( for an explanation.( . + *examples + *example (USING: math prettyprint !( (-.= - numberH .( (t( . + *example (USING: kernel math prettyprint !( (-.= - H .( (f( . . ! ?'&;: P + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is less than ( + *snippet (y( . (.( . + *notes ($his ord performs an ordered comparison on floating point numbers. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: PH + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is less than or equal to ( + *snippet (y( . (.( . + *notes ($his ord performs an ordered comparison on floating point numbers. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: G + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is greater than ( + *snippet (y( . (.( . + *notes ($his ord performs an ordered comparison on floating point numbers. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: GH + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is greater than or equal to ( + *snippet (y( . (.( . + *notes ($his ord performs an ordered comparison on floating point numbers. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: unordered: + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is unordered ith respect to ( + *snippet (y( . (. $his can only occur if one or both values is a floating)point Not)a)Number value.( . ! ?'&;: uP + *values + (x( real . + (y( real . + (:( boolean . .

+ *description ($ests if ( + *snippet (x( . ( is less than ( + *snippet (y( . (.( . + *notes ($his ord performs an unordered comparison on floating point numbers. Bn rational numbers it is equivalent to ( + *link P . (. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: uPH + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is less than or equal to ( + *snippet (y( . (.( . + *notes ($his ord performs an unordered comparison on floating point numbers. Bn rational numbers it is equivalent to ( + *link PH . (. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: uG + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is greater than ( + *snippet (y( . (.( . + *notes ($his ord performs an unordered comparison on floating point numbers. Bn rational numbers it is equivalent to ( + *link G . (. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: uGH + *values + (x( real . + (y( real . + (:( boolean . . + *description ($ests if ( + *snippet (x( . ( is greater than or equal to ( + *snippet (y( . (.( . + *notes ($his ord performs an unordered comparison on floating point numbers. Bn rational numbers it is equivalent to ( + *link GH . (. See ( + *link (math.floats.compare( . ( for an explanation.( . ! ?'&;: 2 + *values + (x( number . + (y( number . + (8( number . . + *description ("dds t o numbers.( + *list ("ddition of fixnums may overflo and convert the result to a bignum.( ("ddition of bignums al ays yields a bignum.( ("ddition of floats al ays yields a float.( ("ddition of ratios and complex numbers proceeds using the relevant mathematical rules.( . . ! ?'&;: ) + *values + (x( number . + (y( number . + (8( number . . + *description (Subtracts ( + *snippet (y( . ( from ( + *snippet (x( . (.( + *list (Subtraction of fixnums may overflo and convert the result to a bignum.( (Subtraction of bignums al ays yields a bignum.( (Subtraction of floats al ays yields a float.( (Subtraction of ratios and complex numbers proceeds using the relevant mathematical rules.( . . ! ?'&;: 4 + *values + (x( number . + (y( number . + (8( number . . + *description (Iultiplies t o numbers.( + *list

(Iultiplication of fixnums may overflo bignum.(

and convert the result to a

(Iultiplication of bignums al ays yields a bignum.( (Iultiplication of floats al ays yields a float.( (Iultiplication of ratios and complex numbers proceeds using the relevant mathematical rules.( . . ! ?'&;: Q + *values + (x( number . + (y( number . + (8( number . . + *description (Civides ( + *snippet (x( . ( by ( + *snippet (y( . (< retaining as much precision as possible.( + *list (Civision of fixnums may yield a ratio< or overflo and yield a bignum.( (Civision of bignums may yield a ratio.( (Civision of floats al ays yields a float.( (Civision of ratios and complex numbers proceeds using the relevant mathematical rules.( . . + *see)also (division)by)8ero( . ! ?'&;: Qi + *values + (x( real . + (y( real . + (8( integer . . + *description (Civides ( + *snippet (x( . ( by ( + *snippet (y( . (< truncating the result to an integer.( . + *see)also (division)by)8ero( . ! ?'&;: Qf + *values + (x( real . + (y( real . + (8( float . . + *description (Civides ( + *snippet (x( . ( by ( + *snippet (y( . (< representing the result as a floating point number.( . + *see)also (division)by)8ero( . ! ?'&;: mod + *values + (x( rational . + (y( rational . + (8( rational . + *description (%omputes the remainder of dividing ( + *snippet (x( . ( . (< ith the remainder being negative if ( + *snippet (x( . + *list (Iodulus of fixnums al ays yields a fixnum.( (Iodulus of bignums al ays yields a bignum.( + (Iodulus of rationals al ays yields a rational. In remainder is computed using the formula ( + *snippet (x ) 5x . . + *see)also (division)by)8ero( rem . ! . by ( + *snippet (y( ( is negative.(

this case< the mod y6 4 y( . (.( .

?'&;: Qmod + *values + (x( real . + (y( real . + (8( integer . + ( ( real . . + *description (%omputes the quotient ( + *snippet (8( . ( and remainder ( + *snippet ( ( . ( of dividing ( + *snippet (x( . ( by ( + *snippet (y( . (< ith the remainder being negative if ( + *snippet (x( . ( is negative.( + *list ($he quotient of t o fixnums may overflo and yield a bignum! the

remainder is al ays a fixnum( ($he quotient and remainder of t o bignums is al ays a bignum.( . . + *examples + *example (USING: kernel math prettyprint !( (A - Qmod 0 . 3 bi9( (1>n,( . + *example (USING: kernel math prettyprint !( (AQ, 1Q- Qmod 0 . 3 bi9( (R>n1QL( . . + *see)also (division)by)8ero( . ! ?'&;: bitand + *values + (x( integer . + (y( integer . + (8( integer . . + *description (Butputs a ne integer here each bit is set if and only if the corresponding bit is set in both inputs.( . + *examples + *example (USING: math prettyprint !( (=b1=1 =b1= bitand .b( (=( . + *example (USING: math prettyprint !( (=b11= =b1= bitand .b( (1=( . . + *notes ($his ord implements bit ise and< so applying it to booleans ill thro an error. Eoolean and is the ( + *link and . ( ord.( . ! ?'&;: bitor + *values + (x( integer . + (y( integer . + (8( integer . . + *description (Butputs a ne integer here each bit is set if and only if the corresponding bit is set in at least one of the inputs.( . + *examples + *example (USING: math prettyprint !( (=b1=1 =b1= bitor .b( (111( . + *example (USING: math prettyprint !( (=b11= =b1= bitor .b( (11=( . . + *notes ($his ord implements bit ise inclusive or< so applying it to booleans ill thro an error. Eoolean inclusive or is the ( + *link and . ( ord.( . ! ?'&;: bitxor + *values + (x( integer . + (y( integer . + (8( integer . . + *description (Butputs a ne integer here each bit is set if and only if the corresponding bit is set in exactly one of the inputs.( . + *examples + *example (USING: math prettyprint !( (=b1=1 =b1= bitxor .b( (111( . + *example (USING: math prettyprint !( (=b11= =b1= bitxor .b( (1==( . . + *notes ($his ord implements bit ise exclusive or< so applying it to booleans ill thro an error. Eoolean exclusive or is the ( + *link xor . ( ord.( . ! ?'&;: shift + *values + (x( integer . + (n( integer . + (y( integer . . + *description (Shifts ( + *snippet (x( . ( to the left by ( + *snippet (n( . ( bits if ( + *snippet (n( . ( is positive< or ( + *snippet ()n( . ( bits to the right if ( + *snippet (n( . ( is negative. " left shift of a fixnum may overflo < yielding a bignum. " right shift may result in bits ]falling off^ the right hand side and being discarded.( . + *examples + *example (USING: math prettyprint !( (=b1=1 A shift .b( (1=1=====( . + *example (USING: math prettyprint !( (=b11111 ), shift .b( (111( . . ! ?'&;: bitnot + *values + (x( integer . + (y( integer . . + *description (%omputes the bit ise complement of the input! that is< each bit in the input number is flipped.( . + *notes ($his ord implements bit ise not< so applying it to booleans ill thro an error. Eoolean not is the ( + *link not . ( ord.( *nl (Cue to the t o7s complement representation of signed integers< the follo ing

t o lines are equivalent:( + *code (bitnot( (neg 1 )( . . ! ?'&;: bit: + *values + (x( integer . + (n( integer . + (:( (a boolean( . . + *description ($ests if the ( + *snippet (n( . (th bit of ( + *snippet (x( . ( is set.( . + *examples + *example (USING: math prettyprint !( (=b1=1 , bit: .( (t( . . ! ?'&;: log, + *values + (x( (a positive integer( . + (n( integer . . + *description (Butputs the largest integer ( + *snippet (n( . ( such that ( + *snippet (,Tn( . ( is less than or equal to ( + *snippet (x( . (.( . + *errors ($hro s an error if ( + *snippet (x( . ( is 8ero or negative.( . ! ?'&;: :12 + *values + (x( + *maybe number . . + (y( number . . + *description (If the input is not ( + *link f . (< adds one. Bther ise< outputs a ( + *snippet (=( . (.( . ! ?'&;: sq + *values + (x( number . + (y( number . . + *description (Iultiplies a number by itself.( . ! ?'&;: neg + *values + (x( number . + ()x( number . . + *description (%omputes a number7s additive inverse.( . ! ?'&;: recip + *values + (x( number . + (y( number . . + *description (%omputes a number7s multiplicative inverse.( . + *errors ($hro s an error if ( + *snippet (x( . ( is the integer =.( . ! ?'&;: rem + *values + (x( rational . + (y( rational . + (8( rational . . + *description (%omputes the remainder of dividing ( + *snippet (x( . ( by ( + *snippet (y( . (< ith the remainder al ays positive or 8ero.( + *list (Given fixnums< al ays yields a fixnum.( (Given bignums< al ays yields a bignum.( (Given rationals< al ays yields a rational.( . . + *see)also (division)by)8ero( mod . ! ?'&;: sgn + *values + (x( real . + (n( ()1< = or 1( . . + *description (Butputs one of the follo ing:( + *list + ()1 if ( + *snippet (x( . ( is negative( . + (= if ( + *snippet (x( . ( is equal to =( . + (1 if ( + *snippet (x( . ( is positive( . . . ! ?'&;: ,Q + *values + (x( integer . + (y( integer + *description (Shifts ( + *snippet (x( + *examples + *example (USING: math prettyprint + *example (USING: math prettyprint . . . ( to the right by one bit.( . !( (1/ ,Q .( (R( . !( (1R ,Q .( (S( .

+ *example (USING: math prettyprint !( ()1R ,Q .( ()U( . . + *notes ($his ord is not equivalent to ( + *snippet (, Q( . ( or ( + *snippet (, Qi( . (! the name is historic and originates from the @orth programming language.( . ! ?'&;: ,T + *values + (n( (a positive integer( . + (,Tn( (a positive integer( . . + *description (%omputes t o to the po er of ( + *snippet (n( . (. $his ord ill only give correct results if ( + *snippet (n( . ( is greater than 8ero! for the general case< use ( + *snippet (, s ap T( . (.( . ! ?'&;: 8ero: + *values + (x( number . + (:( (a boolean( . . + *description ($ests if the number is equal to 8ero.( . ! ?'&;: if)8ero + *values + (n( number . + (quot1( quotation . + (quot,( quotation . . + *description (Iakes an implicit check if the number is 8ero. " 8ero is dropped and ( + *snippet (quot1( . ( is called. Bther ise< if the number is not 8ero< ( + *snippet (quot,( . ( is called on it.( . + *example (USING: kernel math prettyprint sequences !( (- 0 >(8ero>( 3 0 sq 3 if)8ero .( (U( . ! ?'&;: hen)8ero + *values + (n( number . + (quot( (the first quotation of an ( + *link if)8ero . . . + *description (Iakes an implicit check if the number is 8ero. " 8ero is dropped and the ( + *snippet (quot( . ( is called.( . + *examples ($his ord is equivalent to ( + *link if)8ero . ( ith an empty second quotation:( + *example (USING: math prettyprint !( (= 0 / 3 0 3 if)8ero .( (/( . + *example (USING: math prettyprint !( (= 0 / 3 hen)8ero .( (/( . . ! ?'&;: unless)8ero + *values + (n( number . + (quot( (the second quotation of an ( + *link if)empty . . . + *description (Iakes an implicit check if the number is 8ero. " 8ero is dropped. Bther ise< the ( + *snippet (quot( . ( is called on the number.( . + *examples ($his ord is equivalent to ( + *link if)8ero . ( ith an empty first quotation:( + *example (USING: sequences math prettyprint !( (- 0 3 0 sq 3 if)8ero .( (U( . + *example (USING: sequences math prettyprint !( (- 0 sq 3 unless)8ero .(

. !

(U( .

?'&;: times + *values + (n( integer . + (quot( quotation . . + *description (%alls the quotation ( + *snippet (n( . ( times.( . + *notes (If you need to pass the current index to the quotation< use ( + *link each . (.( . + *examples + *example (USING: io math !( (- 0 >(?i>( print 3 times( (?i>n?i>n?i( . . ! ?'&;: fp)bit iseH + *values + (x( float . + (y( float . + (:( boolean . . + *description (%ompares t o floating point numbers for bit equality.( . + *notes (Unlike ( + *link H . ( or ( + *link numberH . (< this ord ill consider NaNs ith equal payloads to be equal< and positive 8ero and negative 8ero to be not equal.( . + *examples (Not)a)number equality:( + *example (USING: kernel math prettyprint !( (=.= =.= Q dup numberH .( (f( . + *example (USING: kernel math prettyprint !( (=.= =.= Q dup fp)bit iseH .( (t( . (Signed 8ero equality:( + *example (USING: math prettyprint !( ()=.= =.= fp)bit iseH .( (f( . + *example (USING: math prettyprint !( ()=.= =.= numberH .( (t( . . ! ?'&;: fp)special: + *values + (x( real . + (:( (a boolean( . . + *description ($ests if ( + *snippet (x( . ( is an I''' special value 5Not)a)Number or Infinity6. Jhile ( + *snippet (x( . ( can be any real number< this ord ill only ever yield true if ( + *snippet (x( . ( is a ( + *link float . (.( . ! ?'&;: fp)nan: + *values + (x( real . + (:( (a boolean( . . + *description ($ests if ( + *snippet (x( . ( is an I''' Not)a)Number value. Jhile ( + *snippet (x( . ( can be any real number< this ord ill only ever yield true if ( + *snippet (x( . ( is a ( + *link float . (.( . ! ?'&;: fp)qnan: + *values + (x( real . + (:( (a boolean( . .

+ *description ($ests if ( + *snippet (x( . ( is an I''' Duiet Not)a)Number value. Jhile ( + *snippet (x( . ( can be any real number< this ord ill only ever yield true if ( + *snippet (x( . ( is a ( + *link float . (.( . ! ?'&;: fp)snan: + *values + (x( real . + (:( (a boolean( . . + *description ($ests if ( + *snippet (x( . ( is an I''' Signaling Not)a)Number value. Jhile ( + *snippet (x( . ( can be any real number< this ord ill only ever yield true if ( + *snippet (x( . ( is a ( + *link float . (.( . ! ?'&;: fp)infinity: + *values + (x( real . + (:( (a boolean( . . + *description ($ests if ( + *snippet (x( . ( is an I''' Infinity value. Jhile ( + *snippet (x( . ( can be any real number< this ord ill only ever yield true if ( + *snippet (x( . ( is a ( + *link float . (.( . + *examples + *example (USING: math prettyprint !( (1Q=. fp)infinity: .( (t( . + *example (USING: io kernel math !( ()1Q=. 0 fp)infinity: 3 0 = P 3 bi and 0 >(negative infinity>( print 3 hen( (negative infinity( . . ! ?'&;: fp)sign + *values + (x( float . + (:( (a boolean( . . + *description (Butputs the sign bit of ( + *snippet (x( . (. @or ordered non)8ero values< this is equivalent to calling ( + *snippet (= P( . (. @or 8ero values< this outputs the 8ero7s sign bit.( . ! ?'&;: fp)nan)payload + *values + (x( real . + (bits( integer . . + *description (If ( + *snippet (x( . ( is an I''' Not)a)Number value< returns the payload encoded in the value. #eturns ( + *link f . ( if ( + *snippet (x( . ( is not a ( + *link float . (.( . ! ?'&;: Pfp)nanG + *values + (payload( integer . + (nan( float . . + *description (%onstructs an I''' Not)a)Number value ith a payload of ( + *snippet (payload( . (.( . + *notes (" ( + *snippet (payload( . ( of ( + *snippet (=( . ( ill construct an Infinity value.( . ! + fp)special: fp)nan: fp)qnan: fp)snan: fp)infinity: fp)nan)payload Pfp)nanG . related) ords ?'&;: next)float + *values + (m( float . + (n( float . . + *description (#eturns the least representable ( + *link float . ( value greater than ( + *snippet (m( . (< or in the case of ( + *snippet ()=.=( . (< returns ( + *snippet (2=.=( . (.( . ! ?'&;: prev)float + *values + (m( float . + (n( float . . + *description (#eturns the greatest representable ( + *link float . ( value less than ( + *snippet (m( . (< or in the case of ( + *snippet (2=.=( . (< returns ( + *snippet ()=.=( . (.( . ! + next)float prev)float . related) ords ?'&;: real)part + *values + (8( number . + (x( real . . + *description (Butputs the real part of a complex number. $his acts as the identity on real numbers.( . + *examples + *example (USING: math prettyprint !( (%+ 1 , . real)part .(

(1( . . ! ?'&;: imaginary)part + *values + (8( number . + (y( real . . + *description (Butputs the imaginary part of a complex number. $his outputs 8ero for real numbers.( . + *examples + *example (USING: math prettyprint !( (%+ 1 , . imaginary)part .( (,( . + *example (USING: math prettyprint !( (- imaginary)part .( (=( . . ! ?'&;: real + *class)description ($he class of real numbers< rationals and floats.( . ! ?'&;: number + *class)description ($he class of numbers.( . ! ?'&;: next)po er)of), + *values + (m( (a non)negative integer( . + (n( (an integer( . . + *description (Butputs the smallest po er of , greater than ( + *snippet (m( . (. $he output value is al ays at least ,.( . ! ?'&;: po er)of),: + *values + (n( integer . + (:( (a boolean( . . + *description ($ests if ( + *snippet (n( . ( is a po er of ,.( . ! ?'&;: each)integer + *values + (n( integer . + (quot( + *quotation (5 ... i )) ... 6( . . . + *description ("pplies the quotation to each integer from = up to ( + *snippet (n( . (< excluding ( + *snippet (n( . (.( . + *notes ($his ord is used to implement ( + *link each . (.( . ! ?'&;: all)integers: + *values + (n( integer . + (quot( + *quotation (5 ... i )) ... : 6( . . + (:( (a boolean( . . + *description ("pplies the quotation to each integer from = up to ( + *snippet (n( . (< excluding ( + *snippet (n( . (. Iteration stops hen the quotation outputs ( + *link f . ( or the end is reached. If the quotation yields a false value for some integer< this ord outputs ( + *link f . (. Bther ise< this ord outputs ( + *link t . (.( . + *notes ($his ord is used to implement ( + *link all: . (.( . ! ?'&;: find)integer + *values + (n( integer . + (quot( + *quotation (5 ... i )) ... : 6( . . + (i( (an integer or ( + *link f . . . + *description ("pplies the quotation to each integer from = up to ( + *snippet (n( . (< excluding ( + *snippet (n( . (. Iteration stops hen the quotation outputs a true value or the end is reached. If the quotation yields a true value for some integer< this ord outputs that integer. Bther ise< this ord outputs ( + *link f . (.( . + *notes ($his ord is used to implement ( + *link find . (.( . ! ?'&;: find)last)integer + *values + (n( integer . + (quot( + *quotation (5 ... i )) ... : 6( . . + (i( (an integer or ( + *link f . . . + *description ("pplies the quotation to each integer from ( + *snippet (n( . ( do n to =< inclusive. Iteration stops hen the quotation outputs a true value or = is reached. If the quotation yields a true value for some integer< the ord outputs that integer. Bther ise< the ord outputs ( + *link f . (.( . + *notes ($his ord is used to implement ( + *link find)last . (.( . ! hich is a disFoint union of

"#$I%&': (division)by)8ero( (Civision by 8ero( (Eehavior of division operations hen a denominator of 8ero is used depends on the data types in question< as ell as the platform being used.( *nl (@loating point division only thro s an error if the appropriate traps are enabled in the floating point environment. If traps are disabled< a Not)a)number value or an infinity is output< depending on hether the numerator is 8ero or non)8ero.( *nl (@loating point traps are disabled by default and the ( + *vocab)link (math.floats.env( . ( vocabulary provides ords to enable them. @loating point division is performed by ( + *link Q . (< ( + *link Qf . ( or ( + *link mod . ( if at least one of the t o inputs is a float. @loating point division is al ays performed by ( + *link Qf . (.( *nl ($he behavior of integer division is hard are specific. Bn xSL processors< ( + *link Qi . ( and ( + *link mod . ( raise an error if both inputs are integers and the denominator is 8ero. Bn ;o er;%< integer division by 8ero yields a result of 8ero.( *nl ($he ( + *link Q . ( ord< hen given integer arguments< implements a much more expensive division algorithm hich al ays yields an exact rational ans er< and this ord al ays tests for division by 8ero explicitly.( ! "#$I%&': (number)protocol( (Number protocol( (Iath operations obey certain numerical upgrade rules. If one of the inputs is a bignum and the other is a fixnum< the latter is first coerced to a bignum! if one of the inputs is a float< the other is coerced to a float.( *nl ($ o examples here you should note the types of the inputs and outputs:( + *example (US': classes( (- Gfixnum L Gbignum 4 class)of .( (bignum( . + *example (1Q, ,.= 2 .( (,.A( . ($he follo ing usual operations are supported by all numbers.( + *subsections 2 ) 4 Q . (Non)commutative operations take operands from the stack in the natural order! ( + *snippet (L , Q( . ( divides L by ,.( + *subsections (division)by)8ero( . (#eal numbers 5but not complex numbers6 can be ordered:( + *subsections P PH G GH . (Numbers can be compared for equality using ( + *link H . (< or a less precise test hich disregards types:( + *subsections numberH . + *see)also (math.floats.compare( . ! "#$I%&': (modular)arithmetic( (Iodular arithmetic( + *subsections mod rem Qmod Qi . + *see)also (integer)functions( . !

"#$I%&': (bit ise)arithmetic( (Eit ise arithmetic( ($here are t o ays of looking at an integer )) as an abstract mathematical entity< or as a string of bits. $he latter representation motivates ( + *emphasis (bit ise operations( . (.( + *subsections bitand bitor bitxor bitnot shift ,Q ,T bit: . ("dvanced topics:( + *subsections (math.bit ise( (math.bits( . + *see)also (booleans( . ! "#$I%&': (arithmetic( ("rithmetic( (@actor attempts to preserve natural mathematical semantics for numbers. Iultiplying t o large integers never results in overflo < and dividing t o integers yields an exact ratio. @loating point numbers are also supported< along ith complex numbers.( *nl (Iath ords are in the ( + *vocab)link (math( . ( vocabulary. Implementation details are in the ( + *vocab)link (math.private( . ( vocabulary.( + *subsections (number)protocol( (modular)arithmetic( (bit ise)arithmetic( . + *see)also (integers( (rationals( (floats( (complex)numbers( . ! "EBU$: (arithmetic( USING: kernel math namespaces make tools.test ! IN: math.tests 0 3 0 A 0 3 times 3 unit)test 0 3 0 = 0 3 times 3 unit)test 0 3 0 )1 0 3 times 3 unit)test 0 3 0 A 0 drop 3 each)integer 3 unit)test 0 0 = 1 , - / 3 3 0 0 A 0 < 3 each)integer 3 0 3 make 3 unit)test 0 0 3 3 0 0 )1 0 < 3 each)integer 3 0 3 make 3 unit)test 0 0 0 0 K K 0 0 0 f f t t 0 0 t f t 3 3 3 3 t f 3 3 3 0 0 0 0 3 3 0 0 0 1Q=. fp)nan: 3 unit)test )1Q=. fp)nan: 3 unit)test )=Q=. fp)nan: 3 unit)test 1 Pfp)nanG fp)nan: 3 unit)test 0 1 Pfp)nanG fp)snan: 3 unit)test 0 1 Pfp)nanG fp)qnan: 3 unit)test =xS===========1 Pfp)nanG fp)nan: 3 unit)test =xS===========1 Pfp)nanG fp)snan: 3 unit)test =xS===========1 Pfp)nanG fp)qnan: 3 unit)test

0 t 3 0 1Q=. fp)infinity: 3 unit)test 0 t 3 0 )1Q=. fp)infinity: 3 unit)test

0 f 3 0 )=Q=. fp)infinity: 3 unit)test 0 f 3 0 = Pfp)nanG fp)nan: 3 unit)test 0 t 3 0 = Pfp)nanG fp)infinity: 3 unit)test 0 t 3 0 =.= neg )=.= fp)bit iseH 3 unit)test 0 t 3 0 )=.= neg =.= fp)bit iseH 3 unit)test 0 =.= 3 0 )=.= next)float 3 unit)test 0 t 3 0 1.= dup next)float P 3 unit)test 0 t 3 0 )1.= dup next)float P 3 unit)test 0 )=.= 3 0 =.= prev)float 3 unit)test 0 t 3 0 1.= dup prev)float G 3 unit)test 0 t 3 0 )1.= dup prev)float G 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f f f f f f f f f f f f f f f f f f f f f f f f f f f t t f f f t t t 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 =Q=. =Q=. =Q=. 1.= =Q=. 1Q=. =Q=. )1Q=. H H H H H H H H P P P P 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test unit)test

0 =Q=. =Q=. 0 1.= =Q=. 0 )1Q=. =Q=. 0 1Q=. =Q=. 0 0 0 0 0 0 0 0 =Q=. =Q=. =Q=. 1.= =Q=. 1Q=. =Q=. )1Q=. =Q=. =Q=. =Q=. 1.= =Q=. 1Q=. =Q=. )1Q=.

PH PH PH PH G G G G

0 =Q=. =Q=. 0 1.= =Q=. 0 )1Q=. =Q=. 0 1Q=. =Q=. 0 =Q=. =Q=. 0 1.= =Q=. 0 )1Q=. =Q=. 0 1Q=. =Q=. 0 0 0 0 0 0 0 0 0 0 0

3 3 3 3 3 3 3 3

GH GH GH GH

= neg: 3 unit)test 1Q, neg: 3 unit)test 1 neg: 3 unit)test )1Q, neg: 3 unit)test )1 neg: 3 unit)test =.= neg: 3 unit)test 1.= neg: 3 unit)test 1Q=. neg: 3 unit)test )=.= neg: 3 unit)test )1.= neg: 3 unit)test )1Q=. neg: 3 unit)test

+ )=x-fffffff . 0 =x-ffffffe Gbignum bitnot 3 unit)test + )=x/======= . 0 =x-fffffff Gbignum bitnot 3 unit)test + )=x/======1 . 0 =x/======= Gbignum bitnot 3 unit)test

+ )=x-fffffffffffffff . 0 =x-ffffffffffffffe Gbignum bitnot 3 unit)test + )=x/=============== . 0 =x-fffffffffffffff Gbignum bitnot 3 unit)test + )=x/==============1 . 0 =x/=============== Gbignum bitnot 3 unit)test USING: kernel literals math math.parser sequences tools.test ! IN: math.parser.tests 0 f 3 0 f stringGnumber 3 unit)test 0 f 3 0 (!( stringGnumber 3 unit)test 0 f 3 0 (PG( stringGnumber 3 unit)test 0 f 3 0 (T( stringGnumber 3 unit)test 0 f 3 0 (RSU:!PHG:9( stringGnumber 3 unit)test 0 f 3 0 (1,-/Aabcdef( stringGnumber 3 unit)test 0 1, 3 0 (21,( stringGnumber 3 unit)test 0 )1, 3 0 ()1,( stringGnumber 3 unit)test 0 f 3 0 ()21,( stringGnumber 3 unit)test 0 f 3 0 (2)1,( stringGnumber 3 unit)test 0 f 3 0 ())1,( stringGnumber 3 unit)test 0 f 3 0 ()( stringGnumber 3 unit)test 0 f 3 0 (e( stringGnumber 3 unit)test 0 0 0 0 1Q, 3 0 (1Q,( stringGnumber 3 unit)test )1Q, 3 0 ()1Q,( stringGnumber 3 unit)test , 3 0 (/Q,( stringGnumber 3 unit)test f 3 0 (1Q),( stringGnumber 3 unit)test

0 0 0 0 0 0 0 0 0 0

f 3 0 (1Q,Q-( stringGnumber 3 unit)test 121Q, 3 0 (121Q,( stringGnumber 3 unit)test 121Q, 3 0 (2121Q,( stringGnumber 3 unit)test f 3 0 (1)1Q,( stringGnumber 3 unit)test )1)1Q, 3 0 ()1)1Q,( stringGnumber 3 unit)test f 3 0 ()121Q,( stringGnumber 3 unit)test f 3 0 (12,( stringGnumber 3 unit)test f 3 0 (12( stringGnumber 3 unit)test f 3 0 (1)( stringGnumber 3 unit)test f 3 0 (121Q,2,( stringGnumber 3 unit)test

0 1===== 3 0 (1==<===( stringGnumber 3 unit)test 0 1=====.= 3 0 (1==<===.=( stringGnumber 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 f f f f f f 3 3 3 3 3 3 0 0 0 0 0 0 (<( stringGnumber 3 unit)test ()<( stringGnumber 3 unit)test (1<( stringGnumber 3 unit)test ()1<( stringGnumber 3 unit)test (<,( stringGnumber 3 unit)test ()<,( stringGnumber 3 unit)test

,.= 3 0 (,.( stringGnumber 3 unit)test ,.= 3 0 (2,.( stringGnumber 3 unit)test =.,A 3 0 (.,A( stringGnumber 3 unit)test ),.= 3 0 (),.( stringGnumber 3 unit)test )=.,A 3 0 ().,A( stringGnumber 3 unit)test f 3 0 ().( stringGnumber 3 unit)test

0 ,AA 3 0 (ff( hexG 3 unit)test 0 1==.= 3 0 (1.=e,( stringGnumber 3 unit)test 0 1==.= 3 0 (1==.=( stringGnumber 3 unit)test 0 1==.= 3 0 (1==.( stringGnumber 3 unit)test 0 1==.= 3 0 (1e,( stringGnumber 3 unit)test 0 1==.= 3 0 (1e2,( stringGnumber 3 unit)test 0 =x1e, 3 0 (1e,( hexG 3 unit)test 0 0 0 0 =x1.UUUUUUUUUUUUap)=x1.-------------p= =x1.AAAAAAAAAAAAAp= =x1.aaaaaaaaaaaabp= 3 3 3 3 0 0 0 0 (=.,( stringGnumber 3 unit)test (1.,( stringGnumber 3 unit)test (1.---<---<---<---<---<---( stringGnumber 3 unit)test (1.LLL<LLL<LLL<LLL<LLL<LLL( stringGnumber 3 unit)test

0 (1==.=( 3 0 (1.=e,( stringGnumber numberGstring 3 unit)test 0 )1==.= 3 0 ()1.=e,( stringGnumber 3 unit)test 0 )1==.= 3 0 ()1==.=( stringGnumber 3 unit)test 0 )1==.= 3 0 ()1==.( stringGnumber 3 unit)test 0 ()1==.=( 3 0 ()1.=e,( stringGnumber numberGstring 3 unit)test 0 )1==.= 3 0 ()1.e,( stringGnumber 3 unit)test 0 (=.=1( 3 0 (1.=e),( stringGnumber numberGstring 3 unit)test

0 =.=1 3 0 (1.=e),( stringGnumber 3 unit)test 0 ()=.=1( 3 0 ()1.=e),( stringGnumber numberGstring 3 unit)test 0 )=.=1 3 0 ()1.=e),( stringGnumber 3 unit)test 0 ()=.=1( 3 0 ()1.e),( stringGnumber numberGstring 3 unit)test 0 )1.=e)1, 3 0 ()1.=e)1,( stringGnumber 3 unit)test 0 t 3 0 ()1.=e)1,( stringGnumber numberGstring + ()1.=e)1,( ()1.=e)=1,( . member: 3 unit)test 0 f 3 0 ()1e),e/( stringGnumber 3 unit)test 0 (-.1/( 3 0 (-.1/( stringGnumber numberGstring 3 unit)test 0 f 3 0 (.( stringGnumber 3 unit)test 0 f 3 0 (.e( stringGnumber 3 unit)test 0 (1=1.=( 3 0 (1.=1e,( stringGnumber numberGstring 3 unit)test 0 ()1=1.=( 3 0 ()1.=1e,( stringGnumber numberGstring 3 unit)test 0 (1.=1( 3 0 (1=1.=e),( stringGnumber numberGstring 3 unit)test 0 ()1.=1( 3 0 ()1=1.=e),( stringGnumber numberGstring 3 unit)test 0 f 3 0 (1e1Q,( stringGnumber 3 unit)test 0 f 3 0 (1e1.,( stringGnumber 3 unit)test 0 f 3 0 (eQ,( stringGnumber 3 unit)test

0 f 3 0 (1,( binG 3 unit)test 0 f 3 0 (fdsf( binG 3 unit)test 0 - 3 0 (11( binG 3 unit)test 0 f 3 0 (>=.( stringGnumber 3 unit)test 0 0 0 0 0 0 1 1 Gbase 3 must)fail 1 = Gbase 3 must)fail 1 )1 Gbase 3 must)fail ,21Q, )1 Gbase 3 0 invalid)radix: 3 must)fail) ith 1,-./AL S Gbase 3 0 invalid)radix: 3 must)fail) ith 1,-./AL , Gbase 3 0 invalid)radix: 3 must)fail) ith

0 (=Q=.( 3 0 =.= =.= Q numberGstring 3 unit)test 0 (1Q=.( 3 0 1.= =.= Q numberGstring 3 unit)test 0 ()1Q=.( 3 0 )1.= =.= Q numberGstring 3 unit)test 0 t 3 0 (=Q=.( stringGnumber fp)nan: 3 unit)test 0 1Q=. 3 0 (1Q=.( stringGnumber 3 unit)test 0 )1Q=. 3 0 ()1Q=.( stringGnumber 3 unit)test 0 )=.A 3 0 ()1Q,.( stringGnumber 3 unit)test 0 ()=.=( 3 0 )=.= numberGstring 3 unit)test 0 ()-Q/( 3 0 )-Q/ numberGstring 3 unit)test 0 ()1)1Q/( 3 0 )AQ/ numberGstring 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (1.=p=( 3 0 1.= Ghex 3 unit)test (1.Sp,( 3 0 L.= Ghex 3 unit)test (1.=Sp,( 3 0 /.1,A Ghex 3 unit)test (1.Sp),( 3 0 =.-RA Ghex 3 unit)test ()1.Sp,( 3 0 )L.= Ghex 3 unit)test (1.Sp1=( 3 0 1A-L.= Ghex 3 unit)test (=.=( 3 0 =.= Ghex 3 unit)test (1.=p)1=R/( 3 0 1 bitsGdouble Ghex 3 unit)test ()=.=( 3 0 )=.= Ghex 3 unit)test 1.= 3 0 (1.=p=( hexG 3 unit)test 1.A 3 0 (1.Sp=( hexG 3 unit)test 1.SRA 3 0 (1.ep=( hexG 3 unit)test 1.U=L,A 3 0 (1.eSp=( hexG 3 unit)test 1.=-1,A 3 0 (1.=Sp=( hexG 3 unit)test 1A.A 3 0 (f.Sp=( hexG 3 unit)test 1A.A-1,A 3 0 (f.SSp=( hexG 3 unit)test )1A.A 3 0 ()f.Sp=( hexG 3 unit)test 1A.A 3 0 (f.Sp=( hexG 3 unit)test )1A.A 3 0 ()f.Sp=( hexG 3 unit)test L,.= 3 0 (f.Sp,( hexG 3 unit)test -.SRA 3 0 (f.Sp),( hexG 3 unit)test *0 1 bitsGdouble 3 3 0 (1.=p)1=R/( hexG 3 unit)test =.= 3 0 (1.=p)1=RA( hexG 3 unit)test 1Q=. 3 0 (1.=p1=,/( hexG 3 unit)test )1Q=. 3 0 ()1.=p1=,/( hexG 3 unit)test

0 = 3 0 (=( stringGnumber 3 unit)test 0 = 3 0 (==( stringGnumber 3 unit)test 0 = 3 0 (=<===( stringGnumber 3 unit)test

0 0 0 0 0 0

=.= =.= =.= = 3 = 3 = 3

3 3 3 0 0 0

0 (=.( stringGnumber 3 unit)test 0 (=.=( stringGnumber 3 unit)test 0 (=x=.=p=( stringGnumber 3 unit)test (=x=( stringGnumber 3 unit)test (=o=( stringGnumber 3 unit)test (=b=( stringGnumber 3 unit)test

0 1= 3 0 (=1=( stringGnumber 3 unit)test 0 1L 3 0 (=x1=( stringGnumber 3 unit)test 0 S 3 0 (=o1=( stringGnumber 3 unit)test 0 , 3 0 (=b1=( stringGnumber 3 unit)test 0 )1= 3 0 ()=1=( stringGnumber 3 unit)test 0 )1L 3 0 ()=x1=( stringGnumber 3 unit)test 0 )S 3 0 ()=o1=( stringGnumber 3 unit)test 0 ), 3 0 ()=b1=( stringGnumber 3 unit)test 0 0 0 0 f f f f 3 3 3 3 0 0 0 0 (=1a( stringGnumber 3 unit)test (=x1g( stringGnumber 3 unit)test (=o1S( stringGnumber 3 unit)test (=b1,( stringGnumber 3 unit)test

0 11 3 0 (=x=b( stringGnumber 3 unit)test 0 f 3 0 (=x=o=( stringGnumber 3 unit)test 0 =xR@@@<"E%C 3 0 (=xR@@@<"E%C( stringGnumber 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1.= 3 0 (=x1.=p=( stringGnumber 3 unit)test L.= 3 0 (=x1.Sp,( stringGnumber 3 unit)test =.-RA 3 0 (=x1.Sp),( stringGnumber 3 unit)test )L.= 3 0 ()=x1.Sp,( stringGnumber 3 unit)test )=.-RA 3 0 ()=x1.Sp),( stringGnumber 3 unit)test f f f f f f f f f f f f 3 3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 (=x( stringGnumber 3 unit)test (=b( stringGnumber 3 unit)test (=o( stringGnumber 3 unit)test (=x<( stringGnumber 3 unit)test (=b<( stringGnumber 3 unit)test (=o<( stringGnumber 3 unit)test (=x<1( stringGnumber 3 unit)test (=b<1( stringGnumber 3 unit)test (=o<1( stringGnumber 3 unit)test (=x1<( stringGnumber 3 unit)test (=b1<( stringGnumber 3 unit)test (=o1<( stringGnumber 3 unit)test

K Z-R, K hex float requires exponent 0 f 3 0 (=x1.=( stringGnumber 3 unit)test K hex float rounds to even 0 =x1.====<====<====<=p= 3 unit)test 0 =x1.====<====<====<,p= 3 unit)test 0 =x1.====<====<====<=p= 3 0 =x1.====<====<====<,p= 3 on half 0 (=x1.====<====<====<=<Sp=( stringGnumber 3 0 (=x1.====<====<====<1<Sp=( stringGnumber 3 0 (=xS.====<====<====</p)-( stringGnumber 3 unit)test 0 (=xS.====<====<====<%p)-( stringGnumber 3 unit)test

0 )=x1.====<====<====<=p= 3 0 ()=x1.====<====<====<=<Sp=( stringGnumber 3 unit)test 0 )=x1.====<====<====<,p= 3 0 ()=x1.====<====<====<1<Sp=( stringGnumber 3 unit)test

0 )=x1.====<====<====<=p= 3 0 ()=xS.====<====<====</p)-( stringGnumber 3 unit)test 0 )=x1.====<====<====<,p= 3 0 ()=xS.====<====<====<%p)-( stringGnumber 3 unit)test K hex float rounds to nearest ith tiny epsilons 0 =x1.====<====<====<=p= 3 0 (=x1.====<====<====<=</p=( stringGnumber 3 unit)test 0 =x1.====<====<====<=p= 3 0 (=x1.====<====<====<=<R@p=( stringGnumber 3 unit)test 0 =x1.====<====<====<=p= 3 0 (=x1.====<====<====<=<R@@@<@@@@<@@@@<@@@@p=( stringGnumber 3 unit)test 0 =x1.====<====<====<1p= 3 0 (=x1.====<====<====<=<%p=( stringGnumber 3 unit)test 0 =x1.====<====<====<1p= 3 0 (=x1.====<====<====<=<S1p=( stringGnumber 3 unit)test 0 =x1.====<====<====<1p= 3 0 (=x1.====<====<====<=<S===<====<====<===1p=( stringGnumber 3 unit)test 0 =x1.====<====<====<1p= 3 0 (=x1.====<====<====<1</p=( stringGnumber 3 unit)test 0 =x1.====<====<====<1p= 3 0 (=x1.====<====<====<1<R@p=( stringGnumber 3 unit)test 0 =x1.====<====<====<1p= 3 0 (=x1.====<====<====<1<R@@@<@@@@<@@@@<@@@@p=( stringGnumber 3 unit)test 0 =x1.====<====<====<,p= 3 0 (=x1.====<====<====<1<%p=( stringGnumber 3 unit)test 0 =x1.====<====<====<,p= 3 0 (=x1.====<====<====<1<S1p=( stringGnumber 3 unit)test 0 =x1.====<====<====<,p= 3 0 (=x1.====<====<====<1<S===<====<====<===1p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<=p= 3 0 ()=x1.====<====<====<=</p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<=p= 3 0 ()=x1.====<====<====<=<R@p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<=p= 3 0 ()=x1.====<====<====<=<R@@@<@@@@<@@@@<@@@@p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<1p= 3 0 ()=x1.====<====<====<=<%p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<1p= 3 0 ()=x1.====<====<====<=<S1p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<1p= 3 0 ()=x1.====<====<====<=<S===<====<====<===1p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<1p= 3 0 ()=x1.====<====<====<1</p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<1p= 3 0 ()=x1.====<====<====<1<R@p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<1p= 3 0 ()=x1.====<====<====<1<R@@@<@@@@<@@@@<@@@@p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<,p= 3 0 ()=x1.====<====<====<1<%p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<,p= 3 0 ()=x1.====<====<====<1<S1p=( stringGnumber 3 unit)test 0 )=x1.====<====<====<,p= 3 0 ()=x1.====<====<====<1<S===<====<====<===1p=( stringGnumber 3 unit)test

K Z/AK hexG decG octG binG shouldn7t admit radix prefixes 0 0 0 0 0 0 0 0 0 0 0 0 =x=b 3 0 (=b( hexG 3 unit)test =x=b= 3 0 (=b=( hexG 3 unit)test f 3 0 (=o=( hexG 3 unit)test f 3 0 (=x=( hexG 3 unit)test f f f f f f f f 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 (=b( decG 3 unit)test (=b=( decG 3 unit)test (=o=( decG 3 unit)test (=x=( decG 3 unit)test (=b( octG 3 unit)test (=b=( octG 3 unit)test (=o=( octG 3 unit)test (=x=( octG 3 unit)test

0 f 3 0 (=b( binG 3 unit)test 0 f 3 0 (=b=( binG 3 unit)test 0 f 3 0 (=o=( binG 3 unit)test 0 f 3 0 (=x=( binG 3 unit)test USING: help.markup help.syntax math math.parser.private prettyprint namespaces make strings ! IN: math.parser "#$I%&': (number)strings( (%onverting bet een numbers and strings( ($hese ords only convert bet een real numbers and strings. %omplex numbers are constructed by the parser 5( + *link (parser( . (6 and printed by the prettyprinter 5( + *link (prettyprint( . (6.( *nl (Integers can be converted to and from arbitrary bases. @loating point numbers can only be converted to and from base 1= and 1L.( *nl (%onverting numbers to strings:( + *subsections numberGstring Gbin Goct Ghex Gbase . (%onverting strings to numbers:( + *subsections stringGnumber binG octG hexG baseG . (Nou can also input literal numbers in a different base 5( + *link (syntax)integers( . (6.( + *see)also (prettyprint)numbers( . ! "EBU$: (number)strings( ?'&;: digitsGinteger + *values + (seq( (a sequence of integers( . + (radix( (an integer bet een , and 1L( . + (nQf( + *maybe integer . . . + *description (%onverts a sequence of digits 5 ith most significant digit first6 into an integer.( . + *notes ($his is one of the factors of ( + *link stringGnumber . (.( . !

?'&;: Gdigit + *values + (n( (an integer bet een = and 1A( . + (ch( (a character( . . + *description (Butputs a character representation of a digit.( . + *notes ($his is one of the factors of ( + *link numberGstring . (.( . ! ?'&;: digitG + *values + (ch( (a character( . + (n( integer . . + *description (%onverts a character representation of a digit to an integer.( . + *notes ($his is one of the factors of ( + *link stringGnumber . (.( . ! ?'&;: baseG + *values + (str( string . + (radix( (an integer bet een , and 1L( . + (nQf( (a real number or ( + *link f . . . + *description (%reates a real number from a string representation ith the given radix. $he radix is ignored for floating point literals! they are al ays taken to be in base 1=.( *nl (Butputs ( + *link f . ( if the string does not represent a number.( . ! + Gbase baseG . related) ords ?'&;: stringGnumber + *values + (str( string . + (nQf( (a real number or ( + *link f . . . + *description (%reates a real number from a string representation of a number in base 1=.( *nl (Butputs ( + *link f . ( if the string does not represent a number.( . ! + stringGnumber numberGstring . related) ords ?'&;: binG + *values + (str( string . + (nQf( (a real number or ( + *link f . . . + *description (%reates a real number from a string representation of a number in base ,.( *nl (Butputs ( + *link f . ( if the string does not represent a number.( . ! + Gbin binG .b . related) ords ?'&;: octG + *values + (str( string . + (nQf( (a real number or ( + *link f . . . + *description (%reates a real number from a string representation of a number in base S.( *nl (Butputs ( + *link f . ( if the string does not represent a number.( . ! + Goct octG .o . related) ords ?'&;: hexG + *values + (str( string . + (nQf( (a real number or ( + *link f . . . + *description (%reates a real number from a string representation of a number in base 1L.( *nl (Butputs ( + *link f . ( if the string does not represent a number.( . ! + Ghex hexG .h . related) ords ?'&;: Gbase + *values + (n( real . + (radix( (an integer bet een , and 1L( . + (str( string . . + *description (%onverts a real number into a string representation using the

given radix. If the number is a float< the radix is ignored and the output is al ays in base 1=.( . ! ?'&;: Gbin + *values + (n( real . + (str( string . . + *description (Butputs a string representation of a number using base ,.( . ! ?'&;: Goct + *values + (n( real . + (str( string . . + *description (Butputs a string representation of a number using base S.( . ! ?'&;: Ghex + *values + (n( real . + (str( string . . + *description (Butputs a string representation of a number using base 1L.( . + *examples + *example (USING: math.parser prettyprint !( (-R-AU,SAAU Ghex .( (>(deadbeef>(( . + *example (USING: math.parser prettyprint !( ()1A.A Ghex .( (>()1.fp->(( . . ! ?'&;: floatGstring + *values + (n( real . + (str( string . . + *description (;rimitive for getting a string representation of a float.( . + *notes ($he ( + *link numberGstring . ( ord is more general.( . ! ?'&;: numberGstring + *values + (n( real . + (str( string . . + *description (%onverts a real number to a string.( . + *notes (;rinting complex numbers requires the more general prettyprinter facility 5see ( + *link (prettyprint( . (6.( . ! ?'&;: Z + *values + (n( real . . + *description ("ppends the string representation of a real number to the end of the sequence being constructed by ( + *link make . (.( . ! K %opyright 5%6 ,==U Xoe Groff< ,=1- Xohn Eenediktsson K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays combinators kernel kernel.private layouts make math math.private namespaces sbufs sequences sequences.private splitting strings ! IN: math.parser : digitG 5 ch )) n 6 + + 0 dup %?"#: U PH 3 0 %?"#: = ) dup = P 0 drop ,AA 3 + 0 dup %?"#: a P 3 0 %?"#: " 1= ) ) dup 1= P 0 drop ,AA 3 0 %?"#: a 1= ) ) dup 1= P 0 drop ,AA 3 . cond ! inline '##B#: invalid)radix radix ! P;#IV"$' $U;&': number)parse + str read)only .

hen 3 . hen 3 . hen 3

+ length fixnum read)only . + radix fixnum read)only . ! : Pnumber)parseG 5 str radix )) i number)parse n 6 0 = 3 ,dip 0 dup length 3 dip number)parse boa = ! inline : 5next)digit6 5 i number)parse n digit)quot end)quot )) nQf 6 0 ,over lengthGG P 3 ,dip 0 0 ,over strGG nth)unsafe Gfixnum 0 1 2 Gfixnum 3 -dip 3 prepose 3 dip if ! inline : require)next)digit 5 i number)parse n quot )) nQf 6 0 -drop f 3 5next)digit6 ! inline : next)digit 5 i number)parse n quot )) nQf 6 0 ,nip 3 5next)digit6 ! inline : add)digit 5 i number)parse n digit quot )) nQf 6 0 0 dup radixGG 3 0 4 3 0 2 3 tri4 3 dip next)digit ! inline : digit)in)radix 5 number)parse n char )) number)parse n digit : 6 digitG pick radixGG over G ! inline : :make)ratio 5 num denomQf )) ratioQf 6 0 Q 3 0 drop f 3 if4 ! inline $U;&': float)parse + radix fixnum read)only . + point read)only . + exponent read)only . ! : inc)point 5 float)parse )) float)parse7 6 0 radixGG 3 0 pointGG 1 2 3 0 exponentGG 3 tri float)parse boa ! inline : store)exponent 5 float)parse n expt )) float)parse7 n 6 s ap 0 0 drop radixGG 3 0 drop pointGG 3 0 nip 3 ,tri float)parse boa 3 dip ! inline : :store)exponent 5 float)parse n exptQf )) float)parse7 nQf 6 0 store)exponent 3 0 drop f 3 if4 ! inline : 55po 66 5 base x )) baseTx 6 iota 1 rot 0 nip 4 3 curry reduce ! inline : 5po 6 5 base x )) baseTx 6 dup = GH 0 55po 66 3 0 0 recip 3 0 neg 3 bi4 55po 66 3 if ! inline : add)mantissa)digit 5 float)parse i number)parse n digit quot )) float)parse7 nQf 6 0 0 inc)point 3 /dip 3 dip add)digit ! inline : make)float)dec)exponent 5 float)parse nQf )) floatQf 6 0 0 radixGG 3 0 pointGG 3 0 exponentGG 3 tri ) 5po 6 3 0 s ap Qf 3 bi4 ! inline : make)float)bin)exponent 5 float)parse nQf )) floatQf 6 0 drop 0 radixGG 3 0 pointGG 3 bi 5po 6 3 0 nip s ap Qf 3 0 drop ,.= s ap exponentGG 5po 6 4 3 ,tri ! inline

: :default)exponent 5 float)parse nQf )) float)parse7 nQf7 6 over exponentGG 0 over radixGG 1= H 0 0 0 radixGG 3 0 pointGG 3 bi = float)parse boa 3 dip 3 0 drop f 3 if 3 unless ! inline : :make)float 5 float)parse nQf )) floatQf 6 + float)parse obFect . declare :default)exponent + + 0 dup not 3 0 ,drop f 3 . + 0 over radixGG 1= H 3 0 make)float)dec)exponent 3 . 0 make)float)bin)exponent 3 . cond ! : :neg 5 nQf )) )nQf 6 0 neg 3 0 f 3 if4 ! inline : :add)ratio 5 m nQf )) m2nQf 6 dup ratio: 0 2 3 0 ,drop f 3 if ! inline : 9abort 5 i number)parse n x )) f 6 /drop f ! inline : 9split 5 i number)parse n )) n i number)parse n7 6 )rot = ! inline : 9split)exponent 5 i number)parse n )) n i number)parse7 n7 6 )rot 0 strGG 3 0 lengthGG 3 bi 1= number)parse boa = ! inline : Pfloat)parseG 5 i number)parse n )) float)parse i number)parse n 6 0 drop nip radixGG = f float)parse boa 3 -keep ! inline C'@'#: C'@'#: C'@'#: C'@'#: C'@'#: C'@'#: 9exponent)digit 9mantissa)digit 9denom)digit 9num)digit 9pos)digit 9neg)digit

: 9exponent)digit)or)punc 5 float)parse i number)parse n char )) float)parse nQf 6 + + %?"#: < 0 0 9exponent)digit 3 require)next)digit 3 . 0 9exponent)digit 3 . case ! inline : 9exponent)digit 5 float)parse i number)parse n char )) float)parse nQf 6 + float)parse fixnum number)parse integer fixnum . declare digit)in)radix 0 0 9exponent)digit)or)punc 3 add)digit 3 0 9abort 3 if ! : 9exponent)first)char 5 float)parse i number)parse n char )) float)parse nQf 6 + + %?"#: ) 0 0 9exponent)digit 3 require)next)digit :neg 3 . + %?"#: 2 0 0 9exponent)digit 3 require)next)digit 3 . 0 9exponent)digit 3 . case ! inline : )Gexponent 5 float)parse i number)parse n )) float)parse7 nQf 6 9split)exponent 0 9exponent)first)char 3 require)next)digit :

store)exponent ! inline : exponent)char: 5 number)parse n char )) number)parse n char : 6 -dup nip s ap radixGG + + 1= 0 0 %?"#: e %?"#: ' 3 dip 0 H 3 curry either: 3 . 0 drop 0 %?"#: p %?"#: ; 3 dip 0 H 3 curry either: 3 . case ! inline : or)exponent 5 i number)parse n char quot )) nQf 6 0 exponent)char: 0 drop Pfloat)parseG )Gexponent :make)float 3 3 dip if ! inline : or)mantissa)Gexponent 5 float)parse i number)parse n char quot )) float)parse nQf 6 0 exponent)char: 0 drop )Gexponent 3 3 dip if ! inline : 9mantissa)digit)or)punc 5 float)parse i number)parse n char )) float)parse nQf 6 + + %?"#: < 0 0 9mantissa)digit 3 require)next)digit 3 . 0 9mantissa)digit 3 . case ! inline : 9mantissa)digit 5 float)parse i number)parse n char )) float)parse nQf 6 + float)parse fixnum number)parse integer fixnum . declare 0 digit)in)radix 0 0 9mantissa)digit)or)punc 3 add)mantissa)digit 3 0 9abort 3 if 3 or)mantissa)Gexponent ! : )Gmantissa 5 i number)parse n )) nQf 6 Pfloat)parseG 0 9mantissa)digit 3 next)digit :make)float ! inline : )Grequired)mantissa 5 i number)parse n )) nQf 6 Pfloat)parseG 0 9mantissa)digit 3 require)next)digit :make)float ! inline : 9denom)digit)or)punc 5 i number)parse n char )) nQf 6 + + %?"#: < 0 0 9denom)digit 3 require)next)digit 3 . + %?"#: . 0 )Gmantissa 3 . 0 0 9denom)digit 3 or)exponent 3 . case ! inline : 9denom)digit 5 i number)parse n char )) nQf 6 + fixnum number)parse integer fixnum . declare digit)in)radix 0 0 9denom)digit)or)punc 3 add)digit 3 0 9abort 3 if ! : 9denom)first)digit 5 i number)parse n char )) nQf 6 + + %?"#: . 0 )Gmantissa 3 . 0 9denom)digit 3 . case ! inline : )Gdenominator 5 i number)parse n )) nQf 6 + fixnum number)parse integer . declare 9split 0 9denom)first)digit 3 require)next)digit :make)ratio ! : 9num)digit)or)punc 5 i number)parse n char )) nQf 6 + + %?"#: < 0 0 9num)digit 3 require)next)digit 3 . + %?"#: Q 0 )Gdenominator 3 .

0 9num)digit 3 . case ! inline : 9num)digit 5 i number)parse n char )) nQf 6 + fixnum number)parse integer fixnum . declare digit)in)radix 0 0 9num)digit)or)punc 3 add)digit 3 0 9abort 3 if ! : )Gnumerator 5 i number)parse n )) nQf 6 + fixnum number)parse integer . declare 9split 0 9num)digit 3 require)next)digit :add)ratio ! : 9pos)digit)or)punc 5 i number)parse n char )) nQf 6 + + %?"#: < 0 0 9pos)digit 3 require)next)digit 3 . + %?"#: 2 0 )Gnumerator 3 . + %?"#: Q 0 )Gdenominator 3 . + %?"#: . 0 )Gmantissa 3 . 0 0 9pos)digit 3 or)exponent 3 . case ! inline : 9pos)digit 5 i number)parse n char )) nQf 6 + fixnum number)parse integer fixnum . declare digit)in)radix 0 0 9pos)digit)or)punc 3 add)digit 3 0 9abort 3 if ! : 5)Gradix6 5 number)parse radix )) number)parse7 6 0 0 strGG 3 0 lengthGG 3 bi 3 dip number)parse boa ! inline : )Gradix 5 i number)parse n quot radix )) i number)parse n quot 6 0 5)Gradix6 3 curry ,dip ! inline : ith)radix)char 5 i number)parse n radix)quot nonradix)quot )) nQf 6 0 rot + + %?"#: b 0 drop , )Gradix require)next)digit 3 . + %?"#: o 0 drop S )Gradix require)next)digit 3 . + %?"#: x 0 drop 1L )Gradix require)next)digit 3 . + f 0 -drop ,drop = 3 . 0 0 drop 3 ,dip s ap call 3 . case 3 ,curry next)digit ! inline

: 9pos)first)digit 5 i number)parse n char )) nQf 6 + + %?"#: . 0 )Grequired)mantissa 3 . + %?"#: = 0 0 9pos)digit 3 0 9pos)digit)or)punc 3 0 9pos)digit 3 . case ! inline : 9neg)digit)or)punc 5 i number)parse n char )) nQf 6 + + %?"#: < 0 0 9neg)digit 3 require)next)digit 3 . + %?"#: ) 0 )Gnumerator 3 . + %?"#: Q 0 )Gdenominator 3 . + %?"#: . 0 )Gmantissa 3 . 0 0 9neg)digit 3 or)exponent 3 . case ! inline

ith)radix)char 3 .

: 9neg)digit 5 i number)parse n char )) nQf 6 + fixnum number)parse integer fixnum . declare digit)in)radix 0 0 9neg)digit)or)punc 3 add)digit 3 0 9abort 3 if ! : 9neg)first)digit 5 i number)parse n char )) nQf 6

+ + %?"#: . 0 )Grequired)mantissa 3 . + %?"#: = 0 0 9neg)digit 3 0 9neg)digit)or)punc 3 0 9neg)digit 3 . case ! inline ith)radix)char 3 .

: 9first)char 5 i number)parse n char )) nQf 6 + + %?"#: ) 0 0 9neg)first)digit 3 require)next)digit :neg 3 . + %?"#: 2 0 0 9pos)first)digit 3 require)next)digit 3 . 0 9pos)first)digit 3 . case ! inline : 9first)char)no)radix 5 i number)parse n char )) nQf 6 + + %?"#: ) 0 0 9neg)digit 3 require)next)digit :neg 3 . + %?"#: 2 0 0 9pos)digit 3 require)next)digit 3 . 0 9pos)digit 3 . case ! inline ;#IV"$'G : stringGnumber 5 str )) nQf 6 1= Pnumber)parseG 0 9first)char 3 require)next)digit ! : baseG 5 str radix )) nQf 6 Pnumber)parseG 0 9first)char)no)radix 3 require)next)digit ! : : : : binG octG decG hexG 5 5 5 5 str str str str )) )) )) )) nQf nQf nQf nQf 6 , baseG 6 S baseG 6 1= baseG 6 1L baseG ! ! ! ! inline inline inline inline

: stringGdigits 5 str )) digits 6 0 digitG 3 E+ . map)as ! inline P;#IV"$' : 5digitsGinteger6 5 valid: accum digit radix )) valid: accum 6 ,dup P 0 s apd 4 2 3 0 /drop f = 3 if ! inline : each)digit 5 seq radix quot )) nQf 6 0 t = 3 -dip curry each s ap 0 drop f 3 unless ! inline ;#IV"$'G : digitsGinteger 5 seq radix )) nQf 6 0 5digitsGinteger6 3 each)digit ! inline : Gdigit 5 n )) ch 6 dup 1= P 0 %?"#: = 2 3 0 1= ) %?"#: a 2 3 if ! inline P;#IV"$' %BNS$"N$: /S /S A= A= A, A, A/ A/ AL AL . $'NS E+ /S /S /S A= A= A= A, A, A, A/ A/ A/ AL AL AL /S A= A, A/ AL /S A= A, A/ AL /S A= A, A/ AL /S A= A, A/ AL /S A= A, A/ AL /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR /U A1 AAA AR

%BNS$"N$: /S /U /S /U /S /U /S /U /S /U .

BN'S E+ A= A1 A, A= A1 A, A= A1 A, A= A1 A, A= A1 A,

AAAAA-

A/ A/ A/ A/ A/

AA AA AA AA AA

AL AL AL AL AL

AR AR AR AR AR

/S /S /S /S /S

/U /U /U /U /U

A= A= A= A= A=

A1 A1 A1 A1 A1

A, A, A, A, A,

AAAAA-

A/ A/ A/ A/ A/

AA AA AA AA AA

AL AL AL AL AL

AR AR AR AR AR

: 5t o)digit6 5 num accum )) num7 accum 6 0 1== Qmod 0 $'NS nth)unsafe 3 0 BN'S nth)unsafe 3 bi 3 dip 0 push 3 keep 0 push 3 keep ! inline : 5one)digit6 5 num accum )) num7 accum 6 0 1= Qmod %?"#: = 2 3 dip 0 push 3 keep ! inline : 5bignumGdec6 5 num accum )) num7 accum 6 0 over most)positive)fixnum G 3 0 + bignum sbuf . declare 5t o)digit6 3 0 Gfixnum 3 dip ! inline

hile

: 5fixnumGdec6 5 num accum )) num7 accum 6 + fixnum sbuf . declare 0 over 1= GH 3 0 5t o)digit6 3 hile 0 over 8ero: 3 0 5one)digit6 3 until ! inline G'N'#I%: 5positiveGdec6 5 num )) str 6 I: bignum 5positiveGdec6 1, PsbufG 5bignumGdec6 5fixnumGdec6 (( like reverseK nip ! inline : 5count)digits6 5 digits n )) digits7 6 + + 0 dup 1= P 3 0 drop 3 . + 0 dup 1== P 3 0 drop 1 fixnum2fast 3 . + 0 dup 1<=== P 3 0 drop , fixnum2fast 3 . 0 dup 1<===<===<===<=== P 0 dup 1==<===<=== P 0 dup 1<===<=== P 0 dup 1=<=== P 0 drop 3 0 1==<=== GH A / : 3 if 3 0 1=<===<=== GH R L : 3 if 3 0 dup 1=<===<===<=== P 0 1<===<===<=== GH U S : 3 0 1==<===<===<=== GH 11 1= : 3 if 3 if fixnum2fast 3 0 0 1, fixnum2fast 3 0 1<===<===<===<=== Qi 3 bi4 5count)digits6 3 if 3 . cond ! inline recursive

I: fixnum 5positiveGdec6 1 over 5count)digits6 PsbufG 5fixnumGdec6 (( like reverseK nip ! inline : 5positiveGbase6 5 num radix )) str 6 dup 1 PH 0 invalid)radix 3 hen 0 dup = G 3 s ap 0 Qmod Gdigit 3 curry (( produce)as nip reverseK ! inline : positiveGbase 5 num radix )) str 6 dup 1= H 0 drop 5positiveGdec6 3 0 5positiveGbase6 3 if ! inline ;#IV"$'G G'N'#I%Z Gbase 1 5 n radix )) str 6 : numberGstring 5 n )) str 6 1= Gbase ! inline : Gbin 5 n )) str 6 , Gbase ! inline : Goct 5 n )) str 6 S Gbase ! inline : Ghex 5 n )) str 6 1L Gbase ! inline I: integer Gbase over = H 0 ,drop (=( 3 0 over = G 0 positiveGbase 3 0 0 neg 3 dip positiveGbase %?"#: ) prefix 3 if 3 if ! I: ratio Gbase 0 0 = P 3 0 abs 1 Qmod 3 bi 3 0 0 positiveGbase 3 curry 3 bi4 0 0 0 numerator 3 0 denominator 3 bi 3 dip bi9 (Q( glue 3 keep rot 0 drop 3 0 s ap call pick ()( (2( : rot -append 3 if)8ero s ap 0 %?"#: ) prefix 3 hen ! : fix)float 5 str )) ne str 6 + + 0 %?"#: e over member: 3 0 (e( split1 0 fix)float (e( 3 dip -append 3 . + 0 %?"#: . over member: 3 0 3 . 0 (.=( append 3 . cond ! P;#IV"$' : mantissa)expt)normali8e 5 mantissa expt )) mantissa7 expt7 6 0 dup log, A, s ap ) 0 shift A, ,T 1 ) bitand 3 0 1=,, 2 neg 3 bi 3 0 1=,- ) 3 if)8ero ! : mantissa)expt 5 float )) mantissa expt 6 0 A, ,T 1 ) bitand 3 0 )=.= doubleGbits bitnot bitand )A, shift 3 bi

mantissa)expt)normali8e ! : floatGhex)sign 5 bits )) str 6 )=.= doubleGbits bitand 8ero: (( ()( : ! : floatGhex)value 5 mantissa )) str 6 Ghex 1- %?"#: = pad)head 0 %?"#: = H 3 trim)tail 0 (=( 3 hen)empty (1.( prepend ! : floatGhex)expt 5 mantissa )) str 6 1= Gbase (p( prepend ! : floatGhex 5 n )) str 6 doubleGbits 0 floatGhex)sign 3 0 mantissa)expt 0 floatGhex)value 3 0 floatGhex)expt 3 bi4 3 bi -append ! : format)float 5 n format )) string 6 = suffix Gbyte)array 5format)float6 dup 0 = H 3 find drop head Gstring fix)float ! : floatGbase 5 n radix )) str 6 + + 1L 0 floatGhex 3 . + 1= 0 (W.1Lg( format)float 3 . 0 invalid)radix 3 . case ! inline ;#IV"$'G : floatGstring 5 n )) str 6 1= floatGbase ! inline I: float Gbase + + 0 over fp)nan: 3 0 + 0 over 1Q=. H 3 0 + 0 over )1Q=. H 3 0 + 0 over =.= fp)bit + 0 over )=.= fp)bit 0 floatGbase 3 . cond !

,drop (=Q=.( 3 . ,drop (1Q=.( 3 . ,drop ()1Q=.( 3 . iseH 3 0 ,drop (=.=( 3 . iseH 3 0 ,drop ()=.=( 3 .

: Z 5 n )) 6 numberGstring W ! inline USING: help.markup help.syntax math math.private ! IN: math.integers "#$I%&': (integers( (Integers( + *subsections integer . (Integers come in t o varieties )) fixnums and bignums. @ixnums fit in a machine ord and are faster to manipulate! if the result of a fixnum operation is too large to fit in a fixnum< the result is upgraded to a bignum. ?ere is an example here t o fixnums are multiplied yielding a bignum:( + *example (US': classes( (LR1=SSL/ class)of .( (fixnum( . + *example (US': classes( (1,S class)of .( (fixnum( . + *example (1-/,1RR,S 1,S 4 .( (1R1RUSLU1S/( . + *example (US': classes( (1 1,S shift class)of .( (bignum( . (Integers can be entered using a different base! see ( + *link (syntax)numbers( . (.( *nl

(Integers can be tested for< and real numbers can be converted to integers:( + *subsections fixnum: bignum: Gfixnum Ginteger Gbignum . + *see)also (prettyprint)numbers( (modular)arithmetic( (bit ise)arithmetic( (integer)functions( (syntax)integers( . ! "EBU$: (integers( ?'&;: fixnum + *class)description ($he class of fixnums< hich are fixed) idth integers small enough to fit in a machine cell. Eecause they are not heap)allocated< fixnums do not have obFect identity. 'quality of tagged pointer bit patterns is actually ( + *emphasis (value( . ( equality for fixnums.( . ! ?'&;: Gfixnum + *values + (x( real . + (n( fixnum . . + *description (%onverts a real number to a fixnum< precision and overflo .( . ! ?'&;: bignum + *class)description ($he class of bignums< arbitrary)precision integers.( . !

ith a possible loss of

hich are heap)allocated

?'&;: Gbignum + *values + (x( real . + (n( bignum . . + *description (%onverts a real number to a bignum< precision.( . ! ?'&;: Ginteger + *values + (x( real . + (n( integer . . + *description (%onverts a real number to an integer< precision.( . ! ?'&;: integer + *class)description ($he class of integers< fixnums and bignums.( . !

ith a possible loss of

ith a possible loss of

hich is a disFoint union of

?'&;: even: + *values + (n( integer . + (:( (a boolean( . . + *description ($ests if an integer is even.( . ! ?'&;: odd: + *values + (n( integer . + (:( (a boolean( . . + *description ($ests if an integer is odd.( . ! K Unsafe primitives ?'&;: fixnum2 + *values + (x( fixnum . + (y( fixnum . + (8( integer . . + *description (;rimitive version of ( + *link 2 . (. $he result may overflo to a bignum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 2 . ( instead.( . ! ?'&;: fixnum) + *values + (x( fixnum . + (y( fixnum . + (8( integer . . + *description (;rimitive version of ( + *link ) . (. $he result may overflo

to

a bignum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link ) . ( instead.( . ! ?'&;: fixnum4 + *values + (x( fixnum . + (y( fixnum . + (8( integer . . + *description (;rimitive version of ( + *link 4 . (. $he result may overflo to a bignum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 4 . ( instead.( . ! ?'&;: fixnumQi + *values + (x( fixnum . + (y( fixnum . + (8( integer . . + *description (;rimitive version of ( + *link Qi . (. $he result may overflo to a bignum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link Qi . ( instead.( . ! ?'&;: fixnum)mod + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link mod . (. $he result al ays fits in a fixnum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link mod . ( instead.( . ! ?'&;: fixnumQmod + *values + (x( fixnum . + (y( fixnum . + (8( integer . + ( ( fixnum . . + *description (;rimitive version of ( + *link Qmod . (. $he result may overflo to a bignum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link Qmod . ( instead.( . ! ?'&;: fixnumP + *values + (x( fixnum . + (y( fixnum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link P . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link P . ( instead.( . ! ?'&;: fixnumPH + *values + (x( fixnum . + (y( fixnum . + (8( integer . . + *description (;rimitive version of ( + *link PH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link PH . ( instead.( . ! ?'&;: fixnumG + *values + (x( fixnum . + (y( fixnum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link G . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link G . ( instead.( . ! ?'&;: fixnumGH + *values + (x( fixnum . + (y( fixnum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link GH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the

rong type can crash the runtime. User code should call the generic + *link GH . ( instead.( . !

ord (

?'&;: fixnum)bitand + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link bitand . (. $he result al ays fits in a fixnum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitand . ( instead.( . ! ?'&;: fixnum)bitor + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link bitor . (. $he result al ays fits in a fixnum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitor . ( instead.( . ! ?'&;: fixnum)bitxor + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link bitxor . (. $he result al ays fits in a fixnum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitxor . ( instead.( . ! ?'&;: fixnum)bitnot + *values + (x( fixnum . + (y( fixnum . . + *description (;rimitive version of ( + *link bitnot . (. $he result al ays fits in a fixnum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitnot . ( instead.( . ! ?'&;: fixnum)shift + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link shift . (. $he result may overflo to a bignum.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link shift . ( instead.( . ! ?'&;: fixnum)shift)fast + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link shift . (. Unlike ( + *link fixnum)shift . (< does not perform an overflo check< so the result may be incorrect.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link shift . ( instead.( . ! ?'&;: fixnum2fast + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link 2 . (. Unlike ( + *link fixnum2 . (< does not perform an overflo check< so the result may be incorrect.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 2 . ( instead.( . ! ?'&;: fixnum)fast + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . .

+ *description (;rimitive version of ( (< does not perform an overflo check< + * arning ($his ord does not perform rong type can crash the runtime. User + *link ) . ( instead.( . !

+ *link ) . (. Unlike ( + *link fixnum) . so the result may be incorrect.( . type checking< and passing obFects of the code should call the generic ord (

?'&;: fixnum4fast + *values + (x( fixnum . + (y( fixnum . + (8( fixnum . . + *description (;rimitive version of ( + *link 4 . (. Unlike ( + *link fixnum4 . (< does not perform an overflo check< so the result may be incorrect.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 4 . ( instead.( . ! ?'&;: bignum2 + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link 2 . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 2 . ( instead.( . ! ?'&;: bignum) + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link ) . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link ) . ( instead.( . ! ?'&;: bignum4 + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link 4 . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 4 . ( instead.( . ! ?'&;: bignumQi + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link Qi . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link Qi . ( instead.( . ! ?'&;: bignum)mod + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link mod . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link mod . ( instead.( . ! ?'&;: bignumQmod + *values + (x( bignum . + (y( bignum . + (8( bignum . + ( ( bignum . . + *description (;rimitive version of ( + *link Qmod . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link Qmod . ( instead.( . ! ?'&;: bignumP + *values + (x( bignum . + (y( bignum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link P . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link P . ( instead.( . !

?'&;: bignumPH + *values + (x( bignum . + (y( bignum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link PH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link PH . ( instead.( . ! ?'&;: bignumG + *values + (x( bignum . + (y( bignum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link G . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link G . ( instead.( . ! ?'&;: bignumGH + *values + (x( bignum . + (y( bignum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link GH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link GH . ( instead.( . ! ?'&;: bignumH + *values + (x( bignum . + (y( bignum . + (:( (a boolean( . . + *description (;rimitive version of ( + *link numberH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link numberH . ( instead.( . ! ?'&;: bignum)bitand + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link bitand . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitand . ( instead.( . ! ?'&;: bignum)bitor + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link bitor . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitor . ( instead.( . ! ?'&;: bignum)bitxor + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link bitxor . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitxor . ( instead.( . ! ?'&;: bignum)bitnot + *values + (x( bignum . + (y( bignum . . + *description (;rimitive version of ( + *link bitnot . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link bitnot . ( instead.( . ! ?'&;: bignum)shift + *values + (x( bignum . + (y( bignum . + (8( bignum . . + *description (;rimitive version of ( + *link shift . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord (

+ *link shift . ( instead.( . ! USING: kernel math math.functions math.order namespaces prettyprint math.private continuations tools.test sequences random prettyprint.config ! IN: math.integers.tests 1= number)base 0 0 ()S( 3 0 )S unparse 3 unit)test 3 ith)variable 0 0 0 0 t t t t 3 3 3 3 0 0 0 0 = fixnum: 3 unit)test -1/1A number: 3 unit)test -1/1A Gbignum number: 3 unit)test ,-/AL,1 fixnum: 3 unit)test

0 t 3 0 ,-/AL,1 dup Gbignum Gfixnum H 3 unit)test 0 0 0 0 0 0 0 0 0 0 0 0 t f f t t f f t 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 = = 1 = = = = = Gfixnum Gfixnum Gbignum Gbignum Gbignum Gfixnum Gfixnum Gfixnum = 1 = = Gbignum Gbignum Gbignum Gfixnum 3 3 3 3 H H H H 3 3 3 3 unit)test unit)test unit)test unit)test

bignum: bignum: bignum: fixnum:

unit)test unit)test unit)test unit)test

)1 3 0 1 neg 3 unit)test )1 3 0 1 Gbignum neg 3 unit)test 1-/,1RR,S 3 0 )1-/,1RR,S Gfixnum )1 4 3 unit)test 1-/,1RR,S 3 0 )1-/,1RR,S Gfixnum neg 3 unit)test

0 U - 3 0 U- 1= Qmod 3 unit)test 0 U - 3 0 U- Gbignum 1= Qmod 3 unit)test 0 A 3 0 , Gbignum - Gbignum 2 3 unit)test 0 )1=========1US1,S/-A, 3 0 )1=================== )=x1======== bitand 3 unit)test 0 UUUUUUUUURLSL-1R=AL 3 0 1=================== )=x1======== bitand 3 unit)test 0 /,U/ULR,UL 3 0 )1=================== =x1======== bitand 3 unit)test 0 = 3 0 1=================== =x1======== bitand 3 unit)test 0 )1 3 0 )1 Gbignum Gfixnum 3 unit)test 1= number)base 0 0 (SASUU-/AU,( 3 0 1-/,1RR,S dup 2 dup 2 dup 2 dup 2 dup 2 dup 2 unparse 3

3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

unit)test ith)variable R S S = R S S = t f t t f t f t t f t t f f t t t f f t 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ,AA ,AL ,AR 1 ,AA ,AL ,AR 1 log, log, log, log, 3 3 3 3 unit)test unit)test unit)test unit)test log, log, log, log, 3 3 3 3 3 3 3 3 3 unit)test unit)test unit)test unit)test

Gbignum Gbignum Gbignum Gbignum = 1 , /

=b11=1 =b11=1 =b11=1 =b11=1 =b11=1 =b11=1 =b11=1 =b11=1 =b11=1 =b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1 )=b11=1

bit: bit: bit: bit: bit:

unit)test unit)test unit)test unit)test unit)test = 1 , / 3 3 3 3 3 bit: bit: bit: bit: bit: 3 3 3 3 3 unit)test unit)test unit)test unit)test unit)test

Gbignum Gbignum Gbignum Gbignum Gbignum = 1 , / bit: bit: bit: bit: bit:

unit)test unit)test unit)test unit)test unit)test bit: bit: bit: bit: bit: 3 3 3 3 3 unit)test unit)test unit)test unit)test unit)test

Gbignum Gbignum Gbignum Gbignum Gbignum

= 1 , /

0 t 3 0 1=LRS11LRRU,1-1=RRU Gbignum AU bit: 3 unit)test 0 0 0 0 0 0 , 3 0 = next)po er)of), 3 , 3 0 1 next)po er)of), 3 , 3 0 , next)po er)of), 3 / 3 0 - next)po er)of), 3 1L 3 0 1- next)po er)of), 1L 3 0 1L next)po er)of), unit)test unit)test unit)test unit)test 3 unit)test 3 unit)test

0 1-/,1RR,S 3 0 )1-/,1RR,S Gfixnum )1 Qi 3 unit)test 0 1-/,1RR,S = 3 0 )1-/,1RR,S Gfixnum )1 Qmod 3 unit)test 0 = 3 0 )1 )1-/,1RR,S Gfixnum Qi 3 unit)test 0 //,=SS=UULSLUSA=URR 3 0 1-,L,L/,UU=L=UAA,U-1 - Qi 3 unit)test 0 = )1 3 0 )1 )1-/,1RR,S Gfixnum Qmod 3 unit)test 0 = )1 3 0 )1 )1-/,1RR,S Gbignum Qmod 3 unit)test 0 1/-AA 3 0 1AU1A1R1ASSR-1/L-A1S1RSA=SS======= -,RLU mod 3 unit)test 0 S A-=A=AR1UL,/-S,1,- 3 0 1-,L,L/,UU=L=UAA,U-1 1AU1A1R1ASSR-1/L-A1 Qmod 3 unit)test 0 S 3 0 1-,L,L/,UU=L=UAA,U-1 1AU1A1R1ASSR-1/L-A1 Qi 3 unit)test 0 A-=A=AR1UL,/-S,1,- 3 0 1-,L,L/,UU=L=UAA,U-1 1AU1A1R1ASSR-1/L-A1 mod 3 unit)test 0 )-A1-S,RU, 3 0 )/-U,,S/U - shift 3 unit)test 0 t 3 0 = 8ero: 3 unit)test

0 f 3 0 -= 8ero: 3 unit)test 0 t 3 0 = Gbignum 8ero: 3 unit)test 0 ,1/R/S-L-, 3 0 1-/,1RR,R Gfixnum 1L fixnum4 3 unit)test 0 ,-L=-U/U-1==11/L/-11=SL1,-S==SA-RRUR--A=L1L=R/-L-L-UU,AUAASLS/1/,S//AA,1A1=/1 3 0 1UARR-UA=LA=-U,=R-,L,AS==-A-==SR/,AS/=SR=U=S1=/==U,1S==S=SUUR,1S,LLA1RAARUL-,S11 R1U=L1U=U/RS=1A,S=US1SSSSRASLRAA/R///UASALRRA=,LUA,,LR1,-SS-,L,SS,=SLU1,=/ RUAL,S1A1//A=-SA==LA,-/U,11URLA1-RLA1=AUA,L,L,S=--=LU-R,RL=S--U-U=L=L-RAL/U-1 bignum)mod 3 unit)test K K 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Je don7t care if this fails or returns = 5its %;U)specific6 as long as it doesn7t crash 3 0 0 = = Qi drop 3 ignore)errors 3 unit)test 3 0 0 1================= = Qi drop 3 ignore)errors 3 unit)test ), 3 0 1 bitnot 3 unit)test ), 3 0 1 Gbignum bitnot 3 unit)test ), 3 0 1 Gbignum bitnot 3 unit)test = 3 0 1,- dup bitnot bitand 3 unit)test = 3 0 1,- Gbignum dup bitnot bitand 3 unit)test = 3 0 1,- dup bitnot Gbignum bitand 3 unit)test = 3 0 1,- dup bitnot bitand Gbignum 3 unit)test )1 3 0 1,- dup bitnot bitor 3 unit)test )1 3 0 1,- Gbignum dup bitnot bitor 3 unit)test )1 3 0 1,- dup bitnot Gbignum bitor 3 unit)test )1 3 0 1,- dup bitnot bitor Gbignum 3 unit)test )1 3 0 1,- dup bitnot bitxor 3 unit)test )1 3 0 1,- Gbignum dup bitnot bitxor 3 unit)test )1 3 0 1,- dup bitnot Gbignum bitxor 3 unit)test )1 3 0 1,- dup bitnot bitxor Gbignum 3 unit)test / 3 0 / R bitand 3 unit)test ,AL 3 0 LAA-L )S shift 3 unit)test ,AL 3 0 LAA-L Gbignum )S shift 3 unit)test ,AL 3 0 LAA-L )S Gbignum shift 3 unit)test ,AL 3 0 LAA-L Gbignum )S Gbignum shift 3 unit)test /,U/ULR,UL 3 0 1 1L shift 1L shift 3 unit)test /,U/ULR,UL 3 0 1 -, shift 3 unit)test 1,LRLA=L==,,S,,U/=1/ULR=-,=A-RL 3 0 1 1== shift 3 unit)test

0 t 3 0 1 ,L shift fixnum: 3 unit)test 0 t 3 0 t 0 ,R ,S ,U -= -1 -, AU L= L1 L, L- L/ 3 0 1 over shift s ap 1 Gbignum s ap shift H and 3 each 3 unit)test 0 t 3 0 t 0 ,R ,S ,U -= -1 -, AU L= L1 L, L- L/ 3 0 )1 over shift s ap )1 Gbignum s ap shift H and 3 each

3 unit)test 0 0 0 0 0 1, 1, 1= 1/ 11 3 3 3 3 3 0 0 0 0 0 11 1, 1= 111 / / , , 1 align align align align align 3 3 3 3 3 unit)test unit)test unit)test unit)test unit)test

0 t 3 0 ,AL po er)of),: 3 unit)test 0 f 3 0 1,- po er)of),: 3 unit)test 0 f 3 0 )1,S po er)of),: 3 unit)test 0 f 3 0 = po er)of),: 3 unit)test 0 t 3 0 1 po er)of),: 3 unit)test : ratioGfloat 5 a b )) f 6 0 Gbignum 3 bi9 Qf ! 0 0 0 0 0 0 0 0 A. 3 0 A 1 ratioGfloat 3 unit)test /. 3 0 / 1 ratioGfloat 3 unit)test ,. 3 0 , 1 ratioGfloat 3 unit)test .A 3 0 1 , ratioGfloat 3 unit)test .RA 3 0 - / ratioGfloat 3 unit)test 1. 3 0 ,=== ,T ,=== ,T 1 2 ratioGfloat 3 unit)test )1. 3 0 ,=== ,T neg ,=== ,T 1 2 ratioGfloat 3 unit)test =./ 3 0 L 1A ratioGfloat 3 unit)test

0 =x-feAA-A,,d,-=U-1 3 0 L1ULR=,==-U U,US/RU,=R- ratioGfloat doubleGbits 3 unit)test : random)integer 5 )) n 6 -, random)bits + t f . random 0 neg 3 hen + t f . random 0 Gbignum 3 hen ! 0 t 3 0 1==== 0 drop random)integer random)integer 0 Gfloat Q 3 0 Qf 3 ,bi =.1 c 3 all)integers: 3 unit)test K 'nsure that Qf is accurate for fixnums G ,TA- on L/)bit platforms 0 =x1.RASbec11/U,fUp)A/ 3 0 1 1,-/ALRSU=1,-/ALR Qf 3 unit)test 0 )=x1.RASbec11/U,fUp)A/ 3 0 1 )1,-/ALRSU=1,-/ALR Qf 3 unit)test K 0 0 0 0 'nsure that Qf rounds to nearest and not to 8ero =x1.=pAA 3 0 =xRf<ffff<ffff<ffff Gbignum 1 Qf 3 unit)test =x1.=pAA 3 0 )=xRf<ffff<ffff<ffff Gbignum )1 Qf 3 unit)test )=x1.=pAA 3 0 )=xRf<ffff<ffff<ffff Gbignum 1 Qf 3 unit)test )=x1.=pAA 3 0 =xRf<ffff<ffff<ffff Gbignum )1 Qf 3 unit)test

0 =x1.====<====<====<=pAL 3 0 =x1==<====<====<===R Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<=pAL 3 0 )=x1==<====<====<===R Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<=p1,= 3 0 =x1==<====<====<===R<@@@@<@@@@<@@@@<@@@@ Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<=p1,= 3 0 )=x1==<====<====<===R<@@@@<@@@@<@@@@<@@@@ Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<=pAL 3 0 =x1==<====<====<===S Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<=pAL 3 0 )=x1==<====<====<===S Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<1pAL 3 0 =x1==<====<====<===U Gbignum 1 Qf 3 unit)test

0 =x1.====<====<====<1pAL 3 0 )=x1==<====<====<===U Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<1p1,= 3 0 =x1==<====<====<===S<====<====<====<===1 Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<1p1,= 3 0 )=x1==<====<====<===S<====<====<====<===1 Gbignum )1 Qf 3 unit)test K 'nsure that Qf rounds to even on tie 0 =x1.====<====<====<1pAL 3 0 =x1==<====<====<==1R Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<1pAL 3 0 )=x1==<====<====<==1R Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<1p1,= 3 0 =x1==<====<====<==1R<@@@@<@@@@<@@@@<@@@@ Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<1p1,= 3 0 )=x1==<====<====<==1R<@@@@<@@@@<@@@@<@@@@ Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<,pAL 3 0 =x1==<====<====<==1S Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<,pAL 3 0 )=x1==<====<====<==1S Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<,pAL 3 0 =x1==<====<====<==1U Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<,pAL 3 0 )=x1==<====<====<==1U Gbignum )1 Qf 3 unit)test 0 =x1.====<====<====<,p1,= 3 0 =x1==<====<====<==1S<====<====<====<===1 Gbignum 1 Qf 3 unit)test 0 =x1.====<====<====<,p1,= 3 0 )=x1==<====<====<==1S<====<====<====<===1 Gbignum )1 Qf 3 unit)test 0 1R 3 0 1R Gbignum A max 3 unit)test 0 A 3 0 1R Gbignum A min 3 unit)test 0 1 3 0 1 ,=,/=,,A--=R-1=L1S-A,/UA-/LR1SU1R-=R=/UAALL/URL/1/,11S-ALU=1-AS=,R/-=--UALRUUA-/ LSU1UL=-S-R=1/-R1,//UA1SR=RRSL/-1LS11U11-SUS=SR-R-SARU-/RLSLR=1--UUU/=R-SA=UU,1A 1R/,/,RLALL-L1-L//LLU=RR/,=U-,1L-/1,-URLRLRS/R,R/A=LSAL,==R/S-/,/LU,LUSL1S1=--AA L/U1AUAAL-/=S1==ALA1,-ASRLUAA,---/1/L1A,-=A=,A-,1SL-,RA=SL/L==L,L--=RR=RR/1=U-/U /RS/ Qf doubleGbits 3 unit)test 0 1, 3 0 A=L==AL--,LS,RLA/ASS1,-S-LLRUR,U-,LRL,-SU1L,//1=-AA,UASU,,A--UA=LSARAS/SU1UUSS-L R,,UU==UAU,A-AU,S11,-RULRLU/LL=RU,=,URRS/R/A,1S/-/L//S-LU,1LRA--/UUSA1S/L,R/S=-R U-AL=LU1/1AU=-/111LR,LU-AA,--=/=SA-=UU/1U1UL1S1SL,LR1/=A=1SR=SAL1R-1R/LA/A,AS-SU 1,,SUSSU=SA,=,A1/1,S=SULU,-SS=S--A-LA-S=RL,AL--=/LAS1SRR1L1A=1ALAS,LU,LU-A,R--RLUL Qf doubleGbits 3 unit)test 0 1,- 3 0 1,,=,/=,,A--=R-1=L1S-A,/UA-/LR1SU1R-=R=/UAALL/URL/1/,11S-ALU=1-AS=,R/-=--UALRUUA-/ LSU1UL=-S-R=1/-R1,//UA1SR=RRSL/-1LS11U11-SUS=SR-R-SARU-/RLSLR=1--UUU/=R-SA=UU,1A 1R/,/,RLALL-L1-L//LLU=RR/,=U-,1L-/1,-URLRLRS/R,R/A=LSAL,==R/S-/,/LU,LUSL1S1=--AA L/U1AUAAL-/=S1==ALA1,-ASRLUAA,---/1/L1A,-=A=,A-,1SL-,RA=SL/L==L,L--=RR=RR/1=U-/U /RS/ Qf doubleGbits 3 unit)test 0 1,-/ 3 0 L1R 1=1,=11,LLA-LAA-=U1RL,/RLR--AU/ASLA-A,/RRS-,/SS,=R1=AU1RS/A=LRU=1-R1A1LURS-UURLR -//AUS=1U1SA=R1SAL,,/RAU-A-SU-,1AS/=AUAALU/U=/-LSLU,SULR-S/--A=LLUUUR=-LU,A/UL=R ASR1,1-S,S-1S=LS,,--/A-SR1=/LL=S1R=L1USS-S-U,-L-R,A-/,S1==-R/1R1,-/L-/U-=U=A1LRR S,/ARURRS1R=/=A=,S,AL1RU-S/RRL1LLR=R-=RL1A,A1,LL=U-1L-RA/-,-==-1-1LA-SA-SR=A/LR/ R-U, Qf doubleGbits 3 unit)test 0 1Q=. 3 0 ,=/S ,T 1 Qf 3 unit)test 0 )1Q=. 3 0 ,=/S ,T )1 Qf 3 unit)test 0 )1Q=. 3 0 ,=/S ,T neg 1 Qf 3 unit)test 0 1Q=. 3 0 ,=/S ,T neg )1 Qf 3 unit)test K %opyright 5%6 ,==/< ,=1= Slava ;estov. K %opyright 5%6 ,==S< Coug %oleman. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: combinators kernel kernel.private math math.order math.private ! IN: math.integers.private : fixnum)min 5 x y )) 8 6 0 fixnumP 3 most ! foldable : fixnum)max 5 x y )) 8 6 0 fixnumG 3 most ! foldable

I: integer numerator ! inline I: integer denominator drop 1 ! inline I: I: I: I: I: I: fixnum fixnum fixnum fixnum fixnum fixnum Gfixnum ! inline Gbignum fixnumGbignum ! inline Ginteger ! inline Gfloat fixnumGfloat ! inline integerGfixnum ! inline integerGfixnum)strict ! inline

I: fixnum hashcode4 nip ! inline I: fixnum equal: over bignum: 0 Gbignum bignumH 3 0 ,drop f 3 if ! inline I: fixnum numberH eq: ! inline I: I: I: I: I: I: I: I: fixnum fixnum fixnum fixnum fixnum fixnum fixnum fixnum P fixnumP ! PH fixnumPH G fixnumG ! GH fixnumGH inline ! inline inline ! inline inline ! inline inline ! inline

uP fixnumP ! uPH fixnumPH uG fixnumG ! uGH fixnumGH

I: fixnum min over fixnum: 0 fixnum)min 3 0 call)next)method 3 if ! inline I: fixnum max over fixnum: 0 fixnum)max 3 0 call)next)method 3 if ! inline I: I: I: I: fixnum fixnum fixnum fixnum 2 fixnum2 ! ) fixnum) ! 4 fixnum4 ! Qi fixnumQi inline inline inline ! inline

I: fixnum mod fixnum)mod ! inline I: fixnum Qmod fixnumQmod ! inline I: I: I: I: fixnum fixnum fixnum fixnum bitand fixnum)bitand bitor fixnum)bitor ! bitxor fixnum)bitxor shift integerGfixnum ! inline inline ! inline fixnum)shift ! inline

I: fixnum bitnot fixnum)bitnot ! inline : fixnum)bit: 5 n m )) b 6 neg shift 1 bitand 8ero: not ! inline I: fixnum bit: fixnum)bit: ! inline : fixnum)log, 5 x )) n 6 + fixnum . declare = s ap 0 dup 1 eq: 3 0 0 1 fixnum2fast 3 0 ,Q 3 bi4 3 until drop ! I: fixnum 5log,6 fixnum)log, + fixnum . declare ! inline I: bignum Gfixnum bignumGfixnum ! inline I: bignum Gbignum ! inline I: bignum integerGfixnum bignumGfixnum ! inline I: bignum integerGfixnum)strict

dup bignumGfixnum ,dup numberH 0 nip 3 0 drop out)of)fixnum)range 3 if ! inline I: bignum hashcode4 nip bignumGfixnum ! I: bignum equal: over bignum: 0 bignumH 3 0 s ap dup fixnum: 0 Gbignum bignumH 3 0 ,drop f 3 if 3 if ! inline I: bignum numberH bignumH ! inline I: I: I: I: I: I: I: I: I: I: I: I: I: bignum bignum bignum bignum bignum bignum bignum bignum bignum bignum bignum bignum bignum P bignumP ! PH bignumPH G bignumG ! GH bignumGH inline ! inline inline ! inline inline ! inline inline ! inline

uP bignumP ! uPH bignumPH uG bignumG ! uGH bignumGH

2 bignum2 ! inline ) bignum) ! inline 4 bignum4 ! inline Qi bignumQi ! inline mod bignum)mod ! inline

I: bignum Qmod bignumQmod ! inline I: I: I: I: bignum bignum bignum bignum bitand bignum)bitand bitor bignum)bitor ! bitxor bignum)bitxor shift integerGfixnum ! inline inline ! inline bignum)shift ! inline

I: bignum bitnot bignum)bitnot ! inline I: bignum bit: bignum)bit: ! inline I: bignum 5log,6 bignum)log, ! inline K %onverting ratios to floats. Eased on @&B"$)#"$IB from K sbclQsrcQcodeQfloat.lisp< hich has the follo ing license: K ($he soft are is in the public domain and is K provided ith absolutely no arranty.( K @irst step: pre)scaling : t os 5 x )) y 6 dup 1 ) bitxor log, ! inline : scale)denonimator 5 den )) scaled)den scale7 6 dup t os neg 0 shift 3 keep ! inline : 5epsilon:6 5 num shift )) : 6 dup neg: 0 neg ,T 1 ) bitand 8ero: not 3 0 ,drop f 3 if ! inline : pre)scale 5 num den )) epsilon: mantissa den7 scale 6 ,dup 0 log, 3 bi9 ) 0 neg A/ 2 0 5epsilon:6 3 0 shift 3 ,bi 3 0 0 scale)denonimator 3 dip 2 3 bi)curry bi4 ! inline K Second step: loop : 5,Q) ith)epsilon6 5 epsilon: num )) epsilon:7 num7 6 0 1 bitand 8ero: not or 3 0 ,Q 3 bi ! inline

: Qf)loop 5 epsilon: mantissa den scale )) epsilon:7 fraction)and)guard rem scale7 6 0 ,over Qi log, A- G 3 0 0 5,Q) ith)epsilon6 3 0 3 0 1 2 3 tri4 3 hile 0 Qmod 3 dip ! inline K $hird step: post)scaling : scale)float 5 mantissa scale )) float7 6 + + 0 dup 1=,/ G 3 0 ,drop 1Q=. 3 . + 0 dup )1=,- P 3 0 1=,1 2 shift bitsGdouble 3 . 0 0 A, ,T 1 ) bitand 3 dip 1=,, 2 A, shift bitor bitsGdouble 3 . cond ! inline : post)scale 5 mantissa scale )) n 6 0 ,Q 3 dip over log, A, G 0 0 ,Q 3 0 1 2 3 bi4 3 scale)float ! inline hen

: round)to)nearest 5 epsilon: fraction)and)guard rem )) fraction)and)guard7 6 over odd: 0 8ero: 0 dup , bitand 8ero: not rot or 0 1 2 3 hen 3 0 nip 1 2 3 if 3 0 drop nip 3 if ! inline K Iain ord : Qf)abs 5 m n )) f 6 over 8ero: 0 nip 8ero: =Q=. =.= : 3 0 0 drop 1Q=. 3 0 pre)scale Qf)loop 0 round)to)nearest 3 dip post)scale 3 if)8ero 3 if ! inline : bignumQf 5 m n )) f 6 0 0 abs 3 bi9 Qf)abs 3 0 0 = P 3 bi9 xor 3 ,bi 0 neg 3 hen ! inline

I: bignum Qf 5 m n )) f 6 + bignum bignum . declare bignumQf ! %BNS$"N$: bignumQf)threshold =x,=<====<====<==== : fixnumQf 5 m n )) mQn 6 0 Gfloat 3 bi9 floatQf ! inline I: fixnum Qf + fixnum fixnum . declare ,dup 0 abs bignumQf)threshold GH 3 either: 0 bignumQf 3 0 fixnumQf 3 if ! inline : bignumGfloat 5 bignum )) float 6 + bignum . declare 1 Gbignum bignumQf ! I: bignum Gfloat bignumGfloat ! inline K %opyright 5%6 ,==/< ,=1= Slava ;estov< Xoe Groff. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: kernel math math.private math.order ! IN: math.floats.private

: float)unordered: 5 x y )) : 6 0 fp)nan: 3 either: ! : float)min 5 x y )) 8 6 0 floatP 3 most ! foldable : float)max 5 x y )) 8 6 0 floatG 3 most ! foldable I: float Gfixnum floatGfixnum ! inline I: float Gbignum floatGbignum ! inline I: float Gfloat ! inline I: float hashcode4 nip floatGbits ! inline I: float equal: over float: 0 floatH 3 0 ,drop f 3 if ! inline I: float numberH floatH ! inline I: I: I: I: I: I: I: I: I: float float float float float float float float float P PH G GH floatP ! inline floatPH ! inline floatG ! inline floatGH ! inline

unordered: float)unordered: ! inline uP float)uP ! inline uPH float)uPH ! inline uG float)uG ! inline uGH float)uGH ! inline

I: float min over float: 0 float)min 3 0 call)next)method 3 if ! inline I: float max over float: 0 float)max 3 0 call)next)method 3 if ! inline I: I: I: I: I: I: float float float float float float 2 float2 ! inline ) float) ! inline 4 float4 ! inline Q floatQf ! inline Qf floatQf ! inline Qi floatQf Ginteger ! inline hen ! inline

I: real abs dup = P 0 neg 3

I: real Qmod ,dup mod 0 s ap 0 ) 3 0 Qi 3 bi4 3 keep ! inline I: float fp)special: doubleGbits )A, shift =xRff 0 bitand 3 keep H ! inline I: float fp)nan)payload doubleGbits A, ,T 1 ) bitand ! inline I: float fp)nan: dup floatH not ! I: float fp)qnan: dup fp)nan: 0 fp)nan)payload A1 ,T bitand 8ero: not 3 0 drop f 3 if ! inline I: float fp)snan: dup fp)nan: 0 fp)nan)payload A1 ,T bitand 8ero: 3 0 drop f 3 if ! inline I: float fp)infinity: dup fp)special: 0 fp)nan)payload 8ero: 3 0 drop f 3 if ! inline I: float next)float doubleGbits dup )=.= doubleGbits G 0 1 ) bitsGdouble 3 0 K negative non)8ero dup )=.= doubleGbits H 0 drop =.= 3 0 K negative 8ero 1 2 bitsGdouble K positive 3 if

3 if ! inline I: float prev)float doubleGbits dup )=.= doubleGbits GH 0 1 2 bitsGdouble 3 0 K negative dup =.= doubleGbits H 0 drop )=.= 3 0 K positive 8ero 1 ) bitsGdouble K positive non)8ero 3 if 3 if ! inline I: float fp)sign doubleGbits L- bit: ! inline I: float neg: fp)sign ! inline I: float abs doubleGbits L- ,T bitnot bitand bitsGdouble ! inline USING: help.markup help.syntax math math.private ! IN: math.floats ?'&;: float + *class)description ($he class of double)precision floating point numbers.( . ! ?'&;: Gfloat + *values + (x( real . + (y( float . . + *description (%onverts a real to a float. $his is the identity on floats< and performs a floating point division on rationals.( . ! ?'&;: bitsGdouble + *values + (n( (a L/)bit integer representing an I''' RA/ double)precision float( . + (x( float . . + *description (%reates a ( + *link float . ( obFect from a L/)bit binary representation. $his ord is usually used to reconstruct floats read from streams.( . ! + bitsGdouble bitsGfloat doubleGbits floatGbits . related) ords ?'&;: bitsGfloat + *values + (n( (a -,)bit integer representing an I''' RA/ single)precision float( . + (x( float . . + *description (%reates a ( + *link float . ( obFect from a -,)bit binary representation. $his ord is usually used to reconstruct floats read from streams.( . ! ?'&;: doubleGbits + *values + (x( float . + (n( (a L/)bit integer representing an I''' RA/ double)precision float( . . + *description (%reates a L/)bit binary representation of a ( + *link float . ( obFect. $his can be used in the process of riting a float to a stream.( . ! ?'&;: floatGbits + *values + (x( float . + (n( (a -,)bit integer representing an I''' RA/ single)precision float( . . + *description (%reates a -,)bit binary representation of a ( + *link float . ( obFect. $his can be used in the process of riting a float to a stream.( . ! K Unsafe primitives ?'&;: float2 + *values + (x( float . + (y( float . + (8( float . . + *description (;rimitive version of ( + *link 2 . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 2 . ( instead.( . !

?'&;: float) + *values + (x( float . + (y( float . + (8( float . . + *description (;rimitive version of ( + *link ) . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link ) . ( instead.( . ! ?'&;: float4 + *values + (x( float . + (y( float . + (8( float . . + *description (;rimitive version of ( + *link 4 . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link 4 . ( instead.( . ! ?'&;: floatQf + *values + (x( float . + (y( float . + (8( float . . + *description (;rimitive version of ( + *link Qf . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link Qf . ( instead.( . ! ?'&;: floatP + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link P . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link P . ( instead.( . ! ?'&;: floatPH + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link PH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link PH . ( instead.( . ! ?'&;: floatG + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link G . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link G . ( instead.( . ! ?'&;: floatGH + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link uGH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link uGH . ( instead.( . ! ?'&;: float)uP + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link uP . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link uP . ( instead.( . ! ?'&;: float)uPH + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link uPH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link uPH . ( instead.( . !

?'&;: float)uG + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link uG . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link uG . ( instead.( . ! ?'&;: float)uGH + *values + (x( float . + (y( float . + (:( (a boolean( . . + *description (;rimitive version of ( + *link uGH . (.( . + * arning ($his ord does not perform type checking< and passing obFects of the rong type can crash the runtime. User code should call the generic ord ( + *link uGH . ( instead.( . ! "#$I%&': (math.floats.compare( (@loating point comparison operations( (In mathematics< real numbers are linearly ordered! for any t o numbers ( + *snippet (a( . ( and ( + *snippet (b( . (< exactly one of the follo ing is true:( + *code (a P b( (a H b( (a G b( . (Jith floating point values< there is a fourth possibility! ( + *snippet (a( . ( and ( + *snippet (b( . ( may be ( + *emphasis (unordered( . (. $his happens if one or both values are Not)a)Number values.( *nl ("ll comparison operators< including ( + *link numberH . (< return ( + *link f . ( in the unordered case 5and in particular< this means that a NaN is not equal to itself6.( *nl ($he ( + *emphasis (ordered( . ( comparison operators set floating point exception flags if the result of the comparison is unordered. $he standard comparison operators 5( + *link P . (< ( + *link PH . (< ( + *link G . (< ( + *link GH . (6 perform ordered comparisons.( *nl ($he ( + *link numberH . ( operation performs an unordered comparison. $he follo ing set of operators also perform unordered comparisons:( + *subsections uP uPH uG uGH . (" ord to check if t o values are unordered ith respect to each other:( + *subsections unordered: . ($o test for floating point exceptions< use the ( + *vocab)link (math.floats.env( . ( vocabulary.( *nl (If neither input to a comparison operator is a floating point value< then ( + *link uP . (< ( + *link uPH . (< ( + *link uG . ( and ( + *link uGH . ( are equivalent to the ordered operators.( ! "#$I%&': (math.floats.bit ise( (Eit ise operations on floats( (@loating point numbers are represented internally in I''' RA/ double)precision format. $his internal representation can be accessed for advanced operations and inputQoutput purposes.( + *subsections floatGbits doubleGbits bitsGfloat

bitsGdouble . (%onstructing floating point NaNs:( + *subsections Pfp)nanG . (@loating point numbers are discrete:( + *subsections prev)float next)float . (Introspection on floating point numbers:( + *subsections fp)special: fp)nan: fp)qnan: fp)snan: fp)infinity: fp)nan)payload . (%omparing t o floating point numbers for bit ise equality:( + *subsections fp)bit iseH . + *see)also ;BS$;BN': N"N: . ! "#$I%&': (floats( (@loats( + *subsections float . (#ational numbers represent ( + *emphasis (exact( . ( quantities. Bn the other hand< a floating point number is an ( + *emphasis (approximate( . ( value. Jhile rationals can gro to any required precision< floating point numbers have limited precision< and manipulating them is usually faster than manipulating ratios or bignums.( *nl (Introducing a floating point number in a computation forces the result to be expressed in floating point.( + *example (AQ/ 1Q, 2 .( (12-Q/( . + *example (AQ/ =.A 2 .( (1.RA( . (@loating point literal syntax is documented in ( + *link (syntax)floats( . (.( *nl (Integers and rationals can be converted to floats:( + *subsections Gfloat . ($ o real numbers can be divided yielding a float result:( + *subsections Qf (math.floats.bit ise( (math.floats.compare( . ($he ( + *vocab)link (math.floats.env( . ( vocabulary provides functionality for controlling floating point exceptions< rounding modes< and denormal behavior.( ! "EBU$: (floats( USING: kernel math math.constants math.order tools.test sequences grouping ! IN: math.floats.tests 0 t 3 0 =.= float: 3 unit)test 0 t 3 0 -.1/1A number: 3 unit)test 0 f 3 0 1, float: 3 unit)test 0 f 3 0 1 1.= H 3 unit)test 0 t 3 0 1 1.= numberH 3 unit)test 0 f 3 0 1 Gbignum 1.= H 3 unit)test 0 t 3 0 1 Gbignum 1.= numberH 3 unit)test

0 f 3 0 1.= 1 H 3 unit)test 0 t 3 0 1.= 1 numberH 3 unit)test 0 f 3 0 1.= 1 Gbignum H 3 unit)test 0 t 3 0 1.= 1 Gbignum numberH 3 unit)test 0 0 0 0 f f f f 3 3 3 3 0 0 0 0 1 1.- H 3 unit)test 1 Gbignum 1.- H 3 unit)test 1.- 1 H 3 unit)test 1.- 1 Gbignum H 3 unit)test

0 t 3 0 1-/.- Gfixnum 1-/ H 3 unit)test 0 - 3 0 -.A Gbignum 3 unit)test 0 )- 3 0 )-.A Gbignum 3 unit)test 0 - 3 0 -.A Gfixnum 3 unit)test 0 )- 3 0 )-.A Gfixnum 3 unit)test 0 ,.1 3 0 ),.1 neg 3 unit)test 0 - 3 0 -.1/1A Gfixnum 3 unit)test 0 - 3 0 -.1/1A Gbignum 3 unit)test 0 t 3 0 pi - G 3 unit)test 0 f 3 0 e , PH 3 unit)test 0 t 3 0 1.= dup floatGbits bitsGfloat H 3 unit)test 0 t 3 0 pi doubleGbits bitsGdouble pi H 3 unit)test 0 t 3 0 e doubleGbits bitsGdouble e H 3 unit)test 0 =b11111111111=================================================== 3 0 1.A doubleGbits 3 unit)test 0 1.A 3 0 =b11111111111=================================================== bitsGdouble 3 unit)test 0 ,.= 3 0 1.= 1 2 3 unit)test 0 =.= 3 0 1.= 1 ) 3 unit)test 0 t 3 0 =.= 8ero: 3 unit)test 0 t 3 0 )=.= 8ero: 3 unit)test 0 = 3 0 1Q=. Gbignum 3 unit)test 0 t 3 0 L/ iota 0 ,T =.A 4 3 map 0 P 3 monotonic: 3 unit)test 0 A 3 0 1=.A 1.U Qi 3 unit)test 0 0 0 0 0 0 0 0 t t t t 3 3 3 3 0 0 0 0 = =.= =.= = 0 0 0 0 = =.= =.= = 1 = 1.= 1.= 1 = Qf Qf Q 0 Gbignum 3 bi9 Qf fp)nan: fp)nan: fp)nan: fp)nan: 3 3 3 3 unit)test unit)test unit)test unit)test

1Q=. 1Q=. 1Q=. 1Q=.

3 3 3 3

Qf 3 unit)test =.= Qf 3 unit)test =.= Q 3 unit)test 0 Gbignum 3 bi9 Qf 3 unit)test

0 )1Q=. 3 0 )1 = Qf 3 unit)test 0 )1Q=. 3 0 )1.= =.= Qf 3 unit)test

0 )1Q=. 3 0 )1.= =.= Q 3 unit)test 0 )1Q=. 3 0 )1 = 0 Gbignum 3 bi9 Qf 3 unit)test 0 0 0 0 0 0 0 0 t t t f t t f f 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 =Q=. =Q=. unordered: 3 unit)test 1.= =Q=. unordered: 3 unit)test =Q=. 1.= unordered: 3 unit)test 1.= 1.= unordered: 3 unit)test )=.= fp)sign 3 unit)test )1.= fp)sign 3 unit)test =.= fp)sign 3 unit)test 1.= fp)sign 3 unit)test

0 t 3 0 )=.= abs =.= fp)bit iseH 3 unit)test 0 1.A 3 0 )1.A abs 3 unit)test 0 1.A 3 0 1.A abs 3 unit)test 0 A.= 3 0 - A.= max 3 unit)test 0 - 3 0 - A.= min 3 unit)test + + + + + + + + + + + + -U =x1.UUUUUUUUUUUSap)/ . 0 /.= .1 Qmod 3 unit)test -S =x1.UUUUUUUUUUUS/p)/ . 0 -.U .1 Qmod 3 unit)test )-U =x1.UUUUUUUUUUUSap)/ . 0 /.= ).1 Qmod 3 unit)test )-S =x1.UUUUUUUUUUUS/p)/ . 0 -.U ).1 Qmod 3 unit)test -U )=x1.UUUUUUUUUUUSap)/ . 0 )/.= ).1 Qmod 3 unit)test -S )=x1.UUUUUUUUUUUS/p)/ . 0 )-.U ).1 Qmod 3 unit)test )-U )=x1.UUUUUUUUUUUSap)/ . 0 )/.= .1 Qmod 3 unit)test )-S )=x1.UUUUUUUUUUUS/p)/ . 0 )-.U .1 Qmod 3 unit)test =.A . 0 -.A =.RA mod 3 unit)test )=.A . 0 )-.A =.RA mod 3 unit)test )=.A . 0 )-.A )=.RA mod 3 unit)test =.A . 0 -.A )=.RA mod 3 unit)test

+ / =.A . 0 -.A =.RA Qmod 3 unit)test + )/ )=.A . 0 )-.A =.RA Qmod 3 unit)test + / )=.A . 0 )-.A )=.RA Qmod 3 unit)test + )/ =.A . 0 -.A )=.RA Qmod 3 unit)test USING: arrays byte)arrays help.markup help.syntax kernel combinators ! IN: byte)vectors "#$I%&': (byte)vectors( (Eyte vectors( ($he ( + *vocab)link (byte)vectors( . ( vocabulary implements resi8able mutable sequence of unsigned bytes. Eyte vectors implement the ( + *link (sequence)protocol( . ( and thus all ( + *link (sequences( . ( can be used ith them.( *nl (Eyte vectors form a class:( + *subsections byte)vector byte)vector: . (%reating byte vectors:( + *subsections Gbyte)vector Pbyte)vectorG . (&iteral syntax:( + *subsections ;BS$;BN': EV+ . (If you don7t care about initial capacity< a more elegant ay to create a ne byte vector is to rite:( + *code (EV+ . clone( . !

"EBU$: (byte)vectors( ?'&;: byte)vector + *description ($he class of resi8able byte vectors. See ( + *link (byte)vectors( . ( for information.( . ! ?'&;: Pbyte)vectorG + *values + (n( (a positive integer specifying initial capacity( . + (byte)vector( byte)vector . . + *description (%reates a ne byte vector that can hold ( + *snippet (n( . ( bytes before resi8ing.( . ! ?'&;: Gbyte)vector + *values + (seq( (a sequence( . + (byte)vector( byte)vector . . + *description (Butputs a freshly)allocated byte vector ith the same elements as a given sequence.( . + *errors ($hro s an error if the sequence contains elements other than integers.( . ! ?'&;: EV+ + *syntax (EV+ elements... .( . + *values + (elements( (a list of bytes( . . + *description (Iarks the beginning of a literal byte vector. &iteral byte vectors are terminated by ( + *link ;BS$;BN': . . (.( . + *examples + *code (EV+ 1 , - 1, .( . . ! K %opyright 5%6 ,==S Slava ;estov. K See http:QQfactorcode.orgQlicense.txt for ESC license. USING: accessors byte)arrays gro able kernel math sequences sequences.private ! IN: byte)vectors $U;&': byte)vector + underlying byte)array . + length array)capacity . ! : Pbyte)vectorG 5 n )) byte)vector 6 5byte)array6 = byte)vector boa ! inline : Gbyte)vector 5 seq )) byte)vector 6 Gbyte)array dup length byte)vector boa ! I: byte)vector like drop dup byte)vector: 0 dup byte)array: 0 dup length byte)vector boa 3 0 Gbyte)vector 3 if 3 unless ! inline I: byte)vector ne )sequence drop 0 5byte)array6 3 0 Gfixnum 3 bi byte)vector boa ! inline I: byte)vector equal: over byte)vector: 0 sequenceH 3 0 ,drop f 3 if ! I: byte)vector contract ,drop ! inline I: byte)array like ZK If e have an byte)array< e7re done. ZK If e have a byte)vector< and it7s at full capacity< ZK e7re done. Bther ise< call resi8e)byte)array< hich is a ZK relatively fast primitive. drop dup byte)array: 0

dup byte)vector: 0 0 length 3 0 underlyingGG 3 bi ,dup length eq: 0 nip 3 0 resi8e)byte)array 3 if 3 0 Gbyte)array 3 if 3 unless ! inline I: byte)array ne )resi8able drop Pbyte)vectorG ! inline I: byte)vector ne )resi8able drop Pbyte)vectorG ! inline INS$"N%': byte)vector gro able USING: tools.test byte)vectors vectors sequences kernel prettyprint math ! IN: byte)vectors.tests 0 = 3 0 1,- Pbyte)vectorG length 3 unit)test : do)it 5 seq )) seq 6 1,- 0 over push 3 each)integer ! 0 t 3 0 - Pbyte)vectorG do)it - PvectorG do)it sequenceH 3 unit)test 0 t 3 0 EV+ . byte)vector: 3 unit)test 0 (EV+ .( 3 0 EV+ . unparse 3 unit)test

You might also like