]> gitweb.factorcode.org Git - factor.git/blob - core/slots/slots-docs.factor
Fixing everything for mandatory stack effects
[factor.git] / core / slots / slots-docs.factor
1 USING: help.markup help.syntax generic kernel.private parser
2 words kernel quotations namespaces sequences words arrays
3 effects generic.standard classes.tuple classes.builtin
4 slots.private classes strings math ;
5 IN: slots
6
7 ARTICLE: "accessors" "Slot accessors"
8 "For each tuple slot, methods are defined on two accessor words in the " { $vocab-link "accessors" } " vocabulary:"
9 { $list
10     { "The " { $emphasis "reader" } " is named " { $snippet { $emphasis "slot" } ">>" } " and pushes the value of a slot on the stack." }
11     { "The " { $emphasis "writer" } " is named " { $snippet "(>>" { $emphasis "slot" } ")" } " and stores a value into a slot. It has stack effect " { $snippet "( value object -- )" } "." }
12 }
13 "In addition, two utility words are defined for each distinct slot name used in the system:"
14 { $list
15     { "The " { $emphasis "setter" } " is named " { $snippet ">>" { $emphasis "slot" } } " and stores a value into a slot. It has stack effect " { $snippet "( object value -- object )" } "." }
16     { "The " { $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 "( object quot -- object )" } "." }
17 }
18 "Since the reader and writer are generic, words can be written which do not depend on the specific class of tuple passed in, but instead work on any tuple that defines slots with certain names."
19 $nl
20 "In most cases, using the setter is preferred over the writer because the stack effect is better suited to the common case where the tuple is needed again, and where the new slot value was just computed and so is at the top of the stack. For example, consider the case where you want to create a tuple and fill in the slots with literals. The following version uses setters:"
21 { $code
22     "<email>"
23     "    \"Happy birthday\" >>subject"
24     "    { \"bob@bigcorp.com\" } >>to"
25     "    \"alice@bigcorp.com\" >>from"
26     "send-email"
27 }
28 "The following uses writers, and requires some stack shuffling:"
29 { $code
30     "<email>"
31     "    \"Happy birthday\" over (>>subject)"
32     "    { \"bob@bigcorp.com\" } over (>>to)"
33     "    \"alice@bigcorp.com\" over (>>from)"
34     "send-email"
35 }
36 "Even if some of the slot values come from the stack underneath the tuple being constructed, setters win:"
37 { $code
38     "<email>"
39     "    swap >>subject"
40     "    swap >>to"
41     "    \"alice@bigcorp.com\" >>from"
42     "send-email"
43 }
44 "This is because " { $link swap } " is easier to understand than " { $link tuck } ":"
45 { $code
46     "<email>"
47     "    tuck (>>subject)"
48     "    tuck (>>to)"
49     "    \"alice@bigcorp.com\" over (>>from)"
50     "send-email"
51 }
52 "The changer word abstracts a common pattern where a slot value is read then stored again; so the following is not idiomatic code:"
53 { $code
54     "find-manager"
55     "    salary>> 0.75 * >>salary"
56 }
57 "The following version is preferred:"
58 { $code
59     "find-manager"
60     "    [ 0.75 * ] change-salary"
61 }
62 { $see-also "slots" "mirrors" } ;
63
64 ARTICLE: "slots" "Slots"
65 "A " { $emphasis "slot" } " is a component of an object which can store a value."
66 $nl
67 { $link "tuples" } " are composed entirely of slots, and instances of " { $link "builtin-classes" } " consist of slots together with intrinsic data."
68 "The " { $vocab-link "slots" } " vocabulary contains words for introspecting the slots of an object."
69 $nl
70 "The " { $snippet "\"slots\"" } " word property of built-in and tuple classes holds an array of " { $emphasis "slot specifiers" } " describing the slot layout of each instance."
71 { $subsection slot-spec }
72 "The four words associated with a slot can be looked up in the " { $vocab-link "accessors" } " vocabulary:"
73 { $subsection reader-word }
74 { $subsection writer-word }
75 { $subsection setter-word }
76 { $subsection changer-word }
77 "Looking up a slot by name:"
78 { $subsection slot-named }
79 "Defining slots dynamically:"
80 { $subsection define-reader }
81 { $subsection define-writer }
82 { $subsection define-setter }
83 { $subsection define-changer }
84 { $subsection define-slot-methods }
85 { $subsection define-accessors }
86 { $see-also "accessors" "mirrors" } ;
87
88 ABOUT: "slots"
89
90 HELP: slot-spec
91 { $class-description "A slot specification. The " { $snippet "\"slots\"" } " word property of " { $link builtin-class } " and " { $link tuple-class } " instances holds sequences of slot specifications."
92 $nl
93 "The slots of a slot specification are:"
94 { $list
95     { { $link slot-spec-type } " - a " { $link class } " declaring the set of possible values for the slot." }
96     { { $link slot-spec-name } " - a " { $link string } " identifying the slot." }
97     { { $link slot-spec-offset } " - an " { $link integer } " offset specifying where the slot value is stored inside instances of the relevant class. This is an implementation detail." }
98     { { $link slot-spec-reader } " - a " { $link word } " for reading the value of this slot." }
99     { { $link slot-spec-writer } " - a " { $link word } " for writing the value of this slot." }
100 } } ;
101
102 HELP: define-typecheck
103 { $values { "class" class } { "generic" "a generic word" } { "quot" quotation } }
104 { $description
105     "Defines a generic word with the " { $link standard-combination } " using dispatch position 0, and having one method on " { $snippet "class" } "."
106     $nl
107     "This creates a definition analogous to the following code:"
108     { $code
109         "GENERIC: generic"
110         "M: class generic quot ;"
111     }
112     "It checks if the top of the stack is an instance of " { $snippet "class" } ", and if so, executes the quotation. Delegation is respected."
113 }
114 { $notes "This word is used internally to wrap low-level code that does not do type-checking in safe user-visible words. For example, see how " { $link word-name } " is implemented." } ;
115
116 HELP: define-slot-word
117 { $values { "class" class } { "slot" "a positive integer" } { "word" word } { "quot" quotation } }
118 { $description "Defines " { $snippet "word" } " to be a simple type-checking generic word that receives the slot number on the stack as a fixnum." }
119 $low-level-note ;
120
121 HELP: define-reader
122 { $values { "class" class } { "name" string } { "slot" integer } }
123 { $description "Defines a reader word to read a slot from instances of " { $snippet "class" } "." }
124 $low-level-note ;
125
126 HELP: define-writer
127 { $values { "class" class } { "name" string } { "slot" integer } }
128 { $description "Defines a generic word " { $snippet "writer" } " to write a new value to a slot in instances of " { $snippet "class" } "." }
129 $low-level-note ;
130
131 HELP: define-slot-methods
132 { $values { "class" class } { "name" string } { "slot" integer } }
133 { $description "Defines a reader, writer, setter and changer for a slot in instances of " { $snippet "class" } "." }
134 $low-level-note ;
135
136 HELP: define-accessors
137 { $values { "class" class } { "specs" "a sequence of " { $link slot-spec } " instances" } }
138 { $description "Defines slot methods." }
139 $low-level-note ;
140
141 HELP: slot ( obj m -- value )
142 { $values { "obj" object } { "m" "a non-negative fixnum" } { "value" object } }
143 { $description "Reads the object stored at the " { $snippet "n" } "th slot of " { $snippet "obj" } "." }
144 { $warning "This word is in the " { $vocab-link "slots.private" } " vocabulary because it does not perform type or bounds checks, and slot numbers are implementation detail." } ;
145
146 HELP: set-slot ( value obj n -- )
147 { $values { "value" object } { "obj" object } { "n" "a non-negative fixnum" } }
148 { $description "Writes " { $snippet "value" } " to the " { $snippet "n" } "th slot of " { $snippet "obj" } "." }
149 { $warning "This word is in the " { $vocab-link "slots.private" } " vocabulary because it does not perform type or bounds checks, and slot numbers are implementation detail." } ;
150
151 HELP: slot-named
152 { $values { "name" string } { "specs" "a sequence of " { $link slot-spec } " instances" } { "spec/f" "a " { $link slot-spec } " or " { $link f } } }
153 { $description "Outputs the " { $link slot-spec } " with the given name." } ;