Merge commit 'factor/master'
commit
5a05aaa869
|
@ -15,7 +15,7 @@ HELP: fry
|
|||
} ;
|
||||
|
||||
HELP: '[
|
||||
{ $syntax "code... ]" }
|
||||
{ $syntax "'[ code... ]" }
|
||||
{ $description "Literal fried quotation. Expands into code which takes values from the stack and substitutes them in place of the fry specifiers " { $link _ } " and " { $link @ } "." }
|
||||
{ $examples "See " { $link "fry.examples" } "." } ;
|
||||
|
||||
|
@ -49,6 +49,8 @@ $nl
|
|||
"{ 8 13 14 27 } [ even? ] 5 [ dup ] swap [ ? ] curry 3compose map"
|
||||
"{ 8 13 14 27 } [ even? dup 5 ? ] map"
|
||||
}
|
||||
"The following is a no-op:"
|
||||
{ $code "'[ @ ]" }
|
||||
"Here are some built-in combinators rewritten in terms of fried quotations:"
|
||||
{ $table
|
||||
{ { $link literalize } { $snippet ": literalize '[ _ ] ;" } }
|
||||
|
@ -74,18 +76,21 @@ ARTICLE: "fry.limitations" "Fried quotation limitations"
|
|||
"As with " { $vocab-link "locals" } ", fried quotations cannot contain " { $link >r } " and " { $link r> } ". This is not a real limitation in practice, since " { $link dip } " can be used instead." ;
|
||||
|
||||
ARTICLE: "fry" "Fried quotations"
|
||||
"A " { $emphasis "fried quotation" } " differs from a literal quotation in that when it is evaluated, instead of just pushing itself on the stack, it consumes zero or more stack values and inserts them into the quotation."
|
||||
"The " { $vocab-link "fry" } " vocabulary implements " { $emphasis "fried quotation" } ". Conceptually, fried quotations are quotations with ``holes'' (more formally, " { $emphasis "fry specifiers" } "), and the holes are filled in when the fried quotation is pushed on the stack."
|
||||
$nl
|
||||
"Fried quotations are denoted with a special parsing word:"
|
||||
"Fried quotations are started by a special parsing word:"
|
||||
{ $subsection POSTPONE: '[ }
|
||||
"Fried quotations contain zero or more " { $emphasis "fry specifiers" } ":"
|
||||
"There are two types of fry specifiers; the first can hold a value, and the second ``splices'' a quotation, as if it were inserted without surrounding brackets:"
|
||||
{ $subsection _ }
|
||||
{ $subsection @ }
|
||||
"When a fried quotation is being evaluated, values are consumed from the stack and spliced into the quotation from right to left."
|
||||
"The holes are filled in with the top of stack going in the rightmost hole, the second item on the stack going in the second hole from the right, and so on."
|
||||
{ $subsection "fry.examples" }
|
||||
{ $subsection "fry.philosophy" }
|
||||
{ $subsection "fry.limitations" }
|
||||
"Quotations can also be fried without using a parsing word:"
|
||||
{ $subsection fry } ;
|
||||
"Fry is implemented as a parsing word which reads a quotation and scans for occurrences of " { $link _ } " and " { $link @ } "; these words are not actually executed, and doing so raises an error (this can happen if they're accidentally used outside of a fry)."
|
||||
$nl
|
||||
"Fried quotations can also be constructed without using a parsing word; this is useful when meta-programming:"
|
||||
{ $subsection fry }
|
||||
"Fried quotations are an abstraction on top of the " { $link "compositional-combinators" } "; their use is encouraged over the combinators, because often the fry form is shorter and clearer than the combinator form." ;
|
||||
|
||||
ABOUT: "fry"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
USING: help.markup help.syntax io kernel math namespaces parser
|
||||
prettyprint sequences vocabs.loader namespaces stack-checker ;
|
||||
prettyprint sequences vocabs.loader namespaces stack-checker
|
||||
help ;
|
||||
IN: help.cookbook
|
||||
|
||||
ARTICLE: "cookbook-syntax" "Basic syntax cookbook"
|
||||
|
@ -324,6 +325,19 @@ ARTICLE: "cookbook-pitfalls" "Pitfalls to avoid"
|
|||
{ "If " { $link run-file } " throws a stack depth assertion, it means that the top-level form in the file left behind values on the stack. The stack depth is compared before and after loading a source file, since this type of situation is almost always an error. If you have a legitimate need to load a source file which returns data in some manner, define a word in the source file which produces this data on the stack and call the word after loading the file." }
|
||||
} ;
|
||||
|
||||
ARTICLE: "cookbook-next" "Next steps"
|
||||
"Once you have read through " { $link "first-program" } " and " { $link "cookbook" } ", the best way to keep learning Factor is to start looking at some simple example programs. Here are a few particularly nice vocabularies which should keep you busy for a little while:"
|
||||
{ $list
|
||||
{ $vocab-link "base64" }
|
||||
{ $vocab-link "roman" }
|
||||
{ $vocab-link "rot13" }
|
||||
{ $vocab-link "smtp" }
|
||||
{ $vocab-link "time-server" }
|
||||
{ $vocab-link "tools.hexdump" }
|
||||
{ $vocab-link "webapps.counter" }
|
||||
}
|
||||
"If you see code in there that you do not understand, use " { $link see } " and " { $link help } " to explore." ;
|
||||
|
||||
ARTICLE: "cookbook" "Factor cookbook"
|
||||
"The Factor cookbook is a high-level overview of the most important concepts required to program in Factor."
|
||||
{ $subsection "cookbook-syntax" }
|
||||
|
@ -336,6 +350,7 @@ ARTICLE: "cookbook" "Factor cookbook"
|
|||
{ $subsection "cookbook-scripts" }
|
||||
{ $subsection "cookbook-compiler" }
|
||||
{ $subsection "cookbook-philosophy" }
|
||||
{ $subsection "cookbook-pitfalls" } ;
|
||||
{ $subsection "cookbook-pitfalls" }
|
||||
{ $subsection "cookbook-next" } ;
|
||||
|
||||
ABOUT: "cookbook"
|
||||
|
|
|
@ -65,6 +65,11 @@ $nl
|
|||
{ "word" { "the basic unit of code, analogous to a function or procedure in other programming languages. See " { $link "words" } } }
|
||||
} ;
|
||||
|
||||
ARTICLE: "tail-call-opt" "Tail-call optimization"
|
||||
"If the last action performed is the execution of a word, the current quotation is not saved on the call stack; this is known as " { $emphasis "tail-call optimization" } " and the Factor implementation guarantees that it will be performed."
|
||||
$nl
|
||||
"Tail-call optimization allows iterative algorithms to be implemented in an efficient manner using recursion, without the need for any kind of primitive looping construct in the language. However, in practice, most iteration is performed via combinators such as " { $link while } ", " { $link each } ", " { $link map } ", " { $link assoc-each } ", and so on. The definitions of these combinators do bottom-out in recursive words, however." ;
|
||||
|
||||
ARTICLE: "evaluator" "Evaluation semantics"
|
||||
{ $link "quotations" } " are evaluated sequentially from beginning to end. When the end is reached, the quotation returns to its caller. As each object in the quotation is evaluated in turn, an action is taken based on its type:"
|
||||
{ $list
|
||||
|
@ -72,7 +77,7 @@ ARTICLE: "evaluator" "Evaluation semantics"
|
|||
{ "a " { $link wrapper } " - the wrapped object is pushed on the data stack. Wrappers are used to push word objects directly on the stack when they would otherwise execute. See the " { $link POSTPONE: \ } " parsing word." }
|
||||
{ "All other types of objects are pushed on the data stack." }
|
||||
}
|
||||
"If the last action performed is the execution of a word, the current quotation is not saved on the call stack; this is known as " { $snippet "tail-recursion" } " and allows iterative algorithms to execute without incurring unbounded call stack usage."
|
||||
{ $subsection "tail-call-opt" }
|
||||
{ $see-also "compiler" } ;
|
||||
|
||||
ARTICLE: "objects" "Objects"
|
||||
|
|
|
@ -310,8 +310,9 @@ ARTICLE: "math-bitfields" "Constructing bit fields"
|
|||
"Some applications, such as binary communication protocols and assemblers, need to construct integers from elaborate bit field specifications. Hand-coding this using " { $link shift } " and " { $link bitor } " results in repetitive code. A higher-level facility exists to factor out this repetition:"
|
||||
{ $subsection bitfield } ;
|
||||
|
||||
ARTICLE: "math.bitwise" "Bitwise arithmetic"
|
||||
"The " { $vocab-link "math.bitwise" } " vocabulary can implements bitwise arithmetic words that are useful for efficiency, low-level programming, and interfacing with C libraries." $nl
|
||||
ARTICLE: "math.bitwise" "Additional bitwise arithmetic"
|
||||
"The " { $vocab-link "math.bitwise" } " vocabulary provides bitwise arithmetic words extending " { $link "bitwise-arithmetic" } ". They are useful for efficiency, low-level programming, and interfacing with C libraries."
|
||||
$nl
|
||||
"Setting and clearing bits:"
|
||||
{ $subsection set-bit }
|
||||
{ $subsection clear-bit }
|
||||
|
|
|
@ -217,14 +217,24 @@ M: vector pprint* pprint-object ;
|
|||
M: byte-vector pprint* pprint-object ;
|
||||
M: hashtable pprint* pprint-object ;
|
||||
|
||||
GENERIC: valid-callable? ( obj -- ? )
|
||||
|
||||
M: object valid-callable? drop f ;
|
||||
|
||||
M: quotation valid-callable? drop t ;
|
||||
|
||||
M: curry valid-callable? quot>> valid-callable? ;
|
||||
|
||||
M: compose valid-callable?
|
||||
[ first>> ] [ second>> ] bi [ valid-callable? ] both? ;
|
||||
|
||||
M: curry pprint*
|
||||
dup quot>> callable? [ pprint-object ] [
|
||||
dup valid-callable? [ pprint-object ] [
|
||||
"( invalid curry )" swap present-text
|
||||
] if ;
|
||||
|
||||
M: compose pprint*
|
||||
dup [ first>> callable? ] [ second>> callable? ] bi and
|
||||
[ pprint-object ] [
|
||||
dup valid-callable? [ pprint-object ] [
|
||||
"( invalid compose )" swap present-text
|
||||
] if ;
|
||||
|
||||
|
|
|
@ -365,3 +365,8 @@ M: started-out-hustlin' ended-up-ballin' ; inline
|
|||
[ "USING: prettyprint.tests ;\nM: started-out-hustlin' ended-up-ballin' ; inline\n" ] [
|
||||
[ { started-out-hustlin' ended-up-ballin' } see ] with-string-writer
|
||||
] unit-test
|
||||
|
||||
[ "( invalid curry )" ] [ 1 2 curry unparse ] unit-test
|
||||
[ "( invalid curry )" ] [ 1 2 3 curry curry unparse ] unit-test
|
||||
[ "( invalid compose )" ] [ 1 2 compose unparse ] unit-test
|
||||
[ "( invalid compose )" ] [ [ 1 ] 2 3 curry compose unparse ] unit-test
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
USING: accessors tools.test ui.gadgets ui.gadgets.labels ;
|
||||
IN: ui.gadgets.labels.tests
|
||||
|
||||
[ { 119 14 } ] [
|
||||
<gadget> { 100 14 } >>dim
|
||||
<gadget> { 14 14 } >>dim
|
||||
label-on-right { 5 5 } >>gap
|
||||
pref-dim
|
||||
] unit-test
|
|
@ -129,10 +129,12 @@ M: scroller focusable-child*
|
|||
M: scroller model-changed
|
||||
nip f >>follows drop ;
|
||||
|
||||
TUPLE: limited-scroller < scroller fixed-dim ;
|
||||
TUPLE: limited-scroller < scroller
|
||||
{ min-dim initial: { 0 0 } }
|
||||
{ max-dim initial: { 1/0. 1/0. } } ;
|
||||
|
||||
: <limited-scroller> ( gadget dim -- scroller )
|
||||
>r limited-scroller new-scroller r> >>fixed-dim ;
|
||||
: <limited-scroller> ( gadget -- scroller )
|
||||
limited-scroller new-scroller ;
|
||||
|
||||
M: limited-scroller pref-dim*
|
||||
fixed-dim>> ;
|
||||
[ call-next-method ] [ min-dim>> vmax ] [ max-dim>> vmin ] tri ;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
! Copyright (C) 2006, 2008 Slava Pestov.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: accessors io kernel math namespaces
|
||||
sequences words math.vectors ui.gadgets ui.gadgets.packs
|
||||
math.geometry.rect fry ;
|
||||
USING: accessors io kernel namespaces fry
|
||||
math math.vectors math.geometry.rect math.order
|
||||
sequences words ui.gadgets ui.gadgets.packs ;
|
||||
|
||||
IN: ui.gadgets.tracks
|
||||
|
||||
|
@ -35,13 +35,16 @@ TUPLE: track < pack sizes ;
|
|||
|
||||
M: track layout* ( track -- ) dup track-layout pack-layout ;
|
||||
|
||||
: track-pref-dims-1 ( track -- dim ) children>> pref-dims max-dim ;
|
||||
: track-pref-dims-1 ( track -- dim )
|
||||
children>> pref-dims max-dim ;
|
||||
|
||||
: track-pref-dims-2 ( track -- dim )
|
||||
[ children>> pref-dims ] [ normalized-sizes ] bi
|
||||
[ [ v/n ] when* ] 2map
|
||||
max-dim
|
||||
[ >fixnum ] map ;
|
||||
[
|
||||
[ children>> pref-dims ] [ normalized-sizes ] bi
|
||||
[ [ v/n ] when* ] 2map max-dim [ >fixnum ] map
|
||||
]
|
||||
[ [ gap>> ] [ children>> length 1 [-] ] bi v*n ] bi
|
||||
v+ ;
|
||||
|
||||
M: track pref-dim* ( gadget -- dim )
|
||||
[ track-pref-dims-1 ]
|
||||
|
|
|
@ -96,9 +96,12 @@ TUPLE: deploy-gadget < pack vocab settings ;
|
|||
: com-close ( gadget -- )
|
||||
close-window ;
|
||||
|
||||
deploy-gadget "misc" "Miscellaneous commands" {
|
||||
{ T{ key-down f f "ESC" } com-close }
|
||||
} define-command-map
|
||||
|
||||
deploy-gadget "toolbar" f {
|
||||
{ f com-close }
|
||||
{ f com-help }
|
||||
{ T{ key-down f f "F1" } com-help }
|
||||
{ f com-revert }
|
||||
{ f com-save }
|
||||
{ T{ key-down f f "RET" } com-deploy }
|
||||
|
|
|
@ -25,7 +25,9 @@ TUPLE: listener-gadget < track input output stack ;
|
|||
: listener-input, ( listener -- listener )
|
||||
dup <listener-input> >>input
|
||||
dup input>>
|
||||
{ 0 100 } <limited-scroller>
|
||||
<limited-scroller>
|
||||
{ 0 100 } >>min-dim
|
||||
{ 1/0. 100 } >>max-dim
|
||||
"Input" <labelled-gadget>
|
||||
f track-add ;
|
||||
|
||||
|
|
|
@ -43,7 +43,10 @@ M: traceback-gadget pref-dim* drop { 550 600 } ;
|
|||
<pane-control> ;
|
||||
|
||||
: <variables-gadget> ( model -- gadget )
|
||||
<namestack-display> { 400 400 } <limited-scroller> ;
|
||||
<namestack-display>
|
||||
<limited-scroller>
|
||||
{ 400 400 } >>min-dim
|
||||
{ 400 400 } >>max-dim ;
|
||||
|
||||
: variables ( traceback -- )
|
||||
model>> <variables-gadget>
|
||||
|
|
|
@ -47,12 +47,15 @@ M: gadget tool-scroller drop f ;
|
|||
: get-tool ( class -- gadget )
|
||||
get-workspace find-tool nip ;
|
||||
|
||||
: <help-pane> ( topic -- pane )
|
||||
<pane> [ [ help ] with-pane ] keep ;
|
||||
|
||||
: help-window ( topic -- )
|
||||
[
|
||||
<pane> [ [ help ] with-pane ] keep
|
||||
{ 550 700 } <limited-scroller>
|
||||
] keep
|
||||
article-title open-window ;
|
||||
<help-pane> <limited-scroller>
|
||||
{ 550 700 } >>max-dim
|
||||
] [ article-title ] bi
|
||||
open-window ;
|
||||
|
||||
: hide-popup ( workspace -- )
|
||||
dup popup>> track-remove
|
||||
|
|
|
@ -2,7 +2,7 @@ USING: help.markup help.syntax ;
|
|||
IN: values
|
||||
|
||||
ARTICLE: "values" "Global values"
|
||||
"Usually, dynamically scoped variables are sufficient for holding data which is not literal. But occasionally, for global information that's calculated just once, it's useful to use the word mechanism instead, and set the word to the appropriate value just once. Values abstract over this concept. To create a new word as a value, use the following syntax:"
|
||||
"Usually, dynamically scoped variables are sufficient for holding data which is not literal. But occasionally, for global information that's calculated just once, it's useful to use the word mechanism instead, and set the word to the appropriate value just once. The " { $vocab-link "values" } " vocabulary implements " { $emphasis "values" } ", which abstract over this concept. To create a new word as a value, use the following syntax:"
|
||||
{ $subsection POSTPONE: VALUE: }
|
||||
"To get the value, just call the word. The following words manipulate values:"
|
||||
{ $subsection get-value }
|
||||
|
@ -10,6 +10,8 @@ ARTICLE: "values" "Global values"
|
|||
{ $subsection POSTPONE: to: }
|
||||
{ $subsection change-value } ;
|
||||
|
||||
ABOUT: "values"
|
||||
|
||||
HELP: VALUE:
|
||||
{ $syntax "VALUE: word" }
|
||||
{ $values { "word" "a word to be created" } }
|
||||
|
|
|
@ -348,6 +348,7 @@ ARTICLE: "bitwise-arithmetic" "Bitwise arithmetic"
|
|||
{ $subsection 2/ }
|
||||
{ $subsection 2^ }
|
||||
{ $subsection bit? }
|
||||
"The " { $vocab-link "math.bitwise" } " vocabulary implements additional bitwise integer operations."
|
||||
{ $see-also "conditionals" } ;
|
||||
|
||||
ARTICLE: "arithmetic" "Arithmetic"
|
||||
|
|
|
@ -428,7 +428,7 @@ must-fail-with
|
|||
"USE: this-better-not-exist" eval
|
||||
] must-fail
|
||||
|
||||
[ ": foo ;" eval ] [ error>> no-current-vocab? ] must-fail-with
|
||||
[ ": foo ;" eval ] [ error>> error>> no-current-vocab? ] must-fail-with
|
||||
|
||||
[ 92 ] [ "CHAR: \\" eval ] unit-test
|
||||
[ 92 ] [ "CHAR: \\\\" eval ] unit-test
|
||||
|
@ -483,7 +483,7 @@ must-fail-with
|
|||
|
||||
[ t ] [ "staging-problem-test-2" "parser.tests" lookup >boolean ] unit-test
|
||||
|
||||
[ "DEFER: blah" eval ] [ error>> no-current-vocab? ] must-fail-with
|
||||
[ "DEFER: blah" eval ] [ error>> error>> no-current-vocab? ] must-fail-with
|
||||
|
||||
[
|
||||
"IN: parser.tests : blah ; parsing FORGET: blah" eval
|
||||
|
|
Loading…
Reference in New Issue