defstruct.doc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. DEFSTRUCT - "Structure" definition facility.
  2. --------------------------------------------
  3. Defstruct is similar to the Spice (Common) Lisp/Lisp machine/Maclisp flavor
  4. of struct definitions, and is expected to be subsumed by the Mode package.
  5. It is implemented in PSL as a function which builds access macros and fns
  6. for "typed" vectors, including constructor and alterant macros, a type
  7. predicate for the structure type, and individual selector/assignment fns
  8. for the elements. Defstruct understands a keyword-option oriented
  9. structure specification.
  10. First a few miscellaneous functions on types, before we get into the depths
  11. of defining Defstructs:
  12. DefstructP( NAME:id ): extra-boolean expr
  13. ---- -- ------------- ----
  14. is a predicate that returns non-NIL (the Defstruct definition) if NAME
  15. is a structured type which has been defined using Defstruct, or NIL if
  16. it is not.
  17. DefstructType( S:struct ): id expr
  18. - ------ -- ----
  19. returns the type name field of an instance of a structured type, or
  20. NIL if S cannot be a defstruct type.
  21. SubTypeP( NAME1:id, NAME2:id ): boolean expr
  22. ----- -- ----- -- ------- ----
  23. returns true if NAME1 is a structured type which has been !:Include'd in
  24. the definition of structured type NAME2, possibly through intermediate
  25. structure definitions. (In other words, the selectors of NAME1 can be
  26. applied to NAME2.)
  27. Now the function which defines the beasties, in all its gory glory:
  28. Defstruct( name-and-options:{id,list}, [slot-descs:{id,list}] ): id fexpr
  29. ---------------- -- ---- ---------- -- ---- -- -----
  30. Defines a record-structure data type. A general call to defstruct
  31. looks like this: (in Rlisp syntax)
  32. defstruct( struct-name( option-1, option-2, ... ),
  33. slot-description-1,
  34. slot-description-2,
  35. ...
  36. ); % (The name of the defined structure is returned.)
  37. where slot-descriptions are:
  38. slot-name( default-init, slot-option-1, slot-option-2, ... )
  39. Struct-name and slot-name are id's. If there are no options following
  40. a name in a spec, it can be a bare id with no option argument list.
  41. The default-init form is optional and may be omitted. The default-init
  42. form is evaluated EACH TIME a structure is to be constructed and the
  43. value is used as the initial value of the slot. Options are either a
  44. keyword id, or the keyword followed by its argument list. Options are
  45. described below.
  46. A call to a Constructor macro has the form:
  47. MakeThing( slot-name-1( value-expr-1 ),
  48. slot-name-2( value-expr-2 ),
  49. ... );
  50. where the slot-name:value lists override the default-init values
  51. which were part of the structure definition. Note that the
  52. slot-names look like unary functions of the value, so the parens can
  53. be left off. A call to MakeThing with no arguments of course takes
  54. all of the default values. The order of evaluation of the
  55. default-init forms and the list of assigned values is undefined, so
  56. code should not depend upon the ordering.
  57. Implementors Note: Common/LispMachine Lisps define it this
  58. way, but Is this necessary? It wouldn't be too tough to
  59. make the order be the same as the struct defn, or the
  60. argument order in the constructor call. Maybe they think
  61. such things should not be advertized and thus constrained
  62. in the future. Or perhaps the theory is that constucts
  63. such as this can be compiled more efficiently if the
  64. ordering is flexible?? Also, should the overridden
  65. default-init forms be evaluated or not? I think not.
  66. The Alterant macro calls have a similar form:
  67. AlterThing( thing,
  68. slot-name-1 value-expr-1,
  69. slot-name-2 value-expr-2,
  70. ... );
  71. where the first argument evaluates to the struct to be altered. (The
  72. optional parens were left off here.) This is just a
  73. multiple-assignment form, which eventually goes through the slot
  74. depositors. Remember that the slot-names are used, not the depositor
  75. names. (See !:Prefix, below.) The altered structure instance
  76. is returned as the value of an Alterant macro.
  77. Implementators note: Common/LispMachine Lisp defines this
  78. such that all of the slots are altered in parallel AFTER
  79. the new value forms are evaluated, but still with the order
  80. of evaluation of the forms undefined. This seemed to lose
  81. more than it gained, but arguments for its worth will be
  82. entertained.
  83. Options:
  84. Structure options appear as an argument list to the struct-name. Many
  85. of the options themselves take argument lists, which are sometimes
  86. optional. Option id's all start with a colon (!:), on the theory that
  87. this distinguishes them from other things.
  88. By default, the names of the constructor, alterant and predicate
  89. macros are MakeName, AlterName and NameP, where "Name" is the
  90. struct-name. The !:Constructor, !:Alterant, and !:Predicate options
  91. can be used to override the default names. Their argument is the
  92. name to use, and a name of NIL causes the respective macro not to be
  93. defined at all.
  94. The !:Creator option causes a different form of constructor to be
  95. defined, in addition to the regular "Make" constructor (which can be
  96. suppressed.) As in the !:Constructor option above, an argument
  97. supplies the name fo the macro, but the default name in this case is
  98. CreateName. A call to a Creator macro has the form:
  99. CreateThing( slot-value-1, slot-value-2, ... );
  100. where ALL of the slot-values of the structure MUST BE PRESENT, in the
  101. order they appear in the structure definition. No checking is done,
  102. other than assuring that the number of values is the same as the
  103. number of slots. For obvous reasons, constructors of this form ARE
  104. NOT RECOMMENDED for structures with many fields, or which may be
  105. expanded or modified.
  106. Slot selector macros may appear on either the LHS or the RHS of an
  107. assignment. They are by default named the same as the slot-names,
  108. but can be given a common prefix by the !:Prefix option. If
  109. !:Prefix does not have an argument, the structure name is the
  110. prefix. If there is an argument, it should be a string or an id
  111. whose printname is the prefix.
  112. The !:Include option allows building a new structure definition as an
  113. extension of an old one. The required argument is the name of a
  114. previously defined structure type. The access functions for the
  115. slots of the source type will also work on instances of the new type.
  116. This can be used to build hierarchies of types, where the source
  117. types contain generic information in common to the more specific
  118. subtypes which !:Include them.
  119. The !:IncludeInit option takes an argument list of
  120. "slot-name(default-init)" pairs, like slot-descriptors without
  121. slot-options, and files them away to modify the default-init values for
  122. fields inherited as part of the !:Include'd structure type.
  123. Slot Options:
  124. Slot-options include the !:Type option, which has an argument
  125. declaring the type of the slot as a type id or list of permissible
  126. type id's. This is not enforced now, but anticipates the Mode system
  127. structures.
  128. The !:UserGet and !:UserPut slot-options allow overriding the simple
  129. vector reference and assignment semantics of the generated selector
  130. macros with user-defined functions. The !:UserGet fn name is a
  131. combination of the slot-name and a !:Prefix if applicable. The
  132. !:UserPut fn name is the same, with "Put" prefixed. One application
  133. of this capability is building depositors which handle the
  134. incremental maintenance of parallel datastructures as a side effect,
  135. such as automatically maintaining display file representations of
  136. objects which are resident in a remote display processor in parallel
  137. with modifications to the Lisp structures which describe the objects.
  138. The Make and Create macros bypass the depositors, while Alter uses them.
  139. A simple example: (Input lines have a "> " prompt at the beginning.)
  140. > % (Do definitions twice to see what functions were defined.)
  141. > macro procedure TWICE u; list( 'PROGN, second u, second u );
  142. TWICE
  143. > % A definition of Complex, structure with Real and Imaginary parts.
  144. > % Redefine to see what functions were defined. Give 0 Init values.
  145. > TWICE
  146. > Defstruct( Complex( !:Creator(Complex) ), R(0), I(0) );
  147. *** Function `MAKECOMPLEX' has been redefined
  148. *** Function `ALTERCOMPLEX' has been redefined
  149. *** Function `COMPLEXP' has been redefined
  150. *** Function `COMPLEX' has been redefined
  151. *** Function `R' has been redefined
  152. *** Function `PUTR' has been redefined
  153. *** Function `I' has been redefined
  154. *** Function `PUTI' has been redefined
  155. *** Defstruct `COMPLEX' has been redefined
  156. COMPLEX
  157. > C0 := MakeComplex(); % Constructor with default inits.
  158. [COMPLEX 0 0]
  159. > ComplexP C0; % Predicate.
  160. T
  161. > C1:=MakeComplex( R 1, I 2 ); % Constructor with named values.
  162. [COMPLEX 1 2]
  163. > R(C1); I(C1); % Named selectors.
  164. 1
  165. 2
  166. > C2:=Complex(3,4) % Creator with positional values.
  167. [COMPLEX 3 4]
  168. > AlterComplex( C1, R(2), I(3) ); % Alterant with named values.
  169. [COMPLEX 2 3]
  170. > C1;
  171. [COMPLEX 2 3]
  172. > R(C1):=5; I(C1):=6; % Named depositors.
  173. 5
  174. 6
  175. > C1;
  176. [COMPLEX 5 6]
  177. > % Show use of Include Option. (Again, redef to show fns defined.)
  178. > TWICE
  179. > Defstruct( MoreComplex( !:Include(Complex) ), Z(99) );
  180. *** Function `MAKEMORECOMPLEX' has been redefined
  181. *** Function `ALTERMORECOMPLEX' has been redefined
  182. *** Function `MORECOMPLEXP' has been redefined
  183. *** Function `Z' has been redefined
  184. *** Function `PUTZ' has been redefined
  185. *** Defstruct `MORECOMPLEX' has been redefined
  186. MORECOMPLEX
  187. > M0 := MakeMoreComplex();
  188. [MORECOMPLEX 0 0 99]
  189. > M1 := MakeMoreComplex( R 1, I 2, Z 3 );
  190. [MORECOMPLEX 1 2 3]
  191. > R C1;
  192. 5
  193. > R M1;
  194. 1
  195. > % A more complicated example: The structures which are used in the
  196. > % Defstruct facility to represent defstructs. (The EX prefix has
  197. > % been added to the names to protect the innocent...)
  198. > TWICE % Redef to show fns generated.
  199. > Defstruct(
  200. > EXDefstructDescriptor( !:Prefix(EXDsDesc), !:Creator ),
  201. > DsSize( !:Type int ), % (Upper Bound of vector.)
  202. > Prefix( !:Type string ),
  203. > SlotAlist( !:Type alist ), % (Cdrs are SlotDescriptors.)
  204. > ConsName( !:Type fnId ),
  205. > AltrName( !:Type fnId ),
  206. > PredName( !:Type fnId ),
  207. > CreateName( !:Type fnId ),
  208. > Include( !:Type typeid ),
  209. > InclInit( !:Type alist )
  210. > );
  211. *** Function `MAKEEXDEFSTRUCTDESCRIPTOR' has been redefined
  212. *** Function `ALTEREXDEFSTRUCTDESCRIPTOR' has been redefined
  213. *** Function `EXDEFSTRUCTDESCRIPTORP' has been redefined
  214. *** Function `CREATEEXDEFSTRUCTDESCRIPTOR' has been redefined
  215. *** Function `EXDSDESCDSSIZE' has been redefined
  216. *** Function `PUTEXDSDESCDSSIZE' has been redefined
  217. *** Function `EXDSDESCPREFIX' has been redefined
  218. *** Function `PUTEXDSDESCPREFIX' has been redefined
  219. *** Function `EXDSDESCSLOTALIST' has been redefined
  220. *** Function `PUTEXDSDESCSLOTALIST' has been redefined
  221. *** Function `EXDSDESCCONSNAME' has been redefined
  222. *** Function `PUTEXDSDESCCONSNAME' has been redefined
  223. *** Function `EXDSDESCALTRNAME' has been redefined
  224. *** Function `PUTEXDSDESCALTRNAME' has been redefined
  225. *** Function `EXDSDESCPREDNAME' has been redefined
  226. *** Function `PUTEXDSDESCPREDNAME' has been redefined
  227. *** Function `EXDSDESCCREATENAME' has been redefined
  228. *** Function `PUTEXDSDESCCREATENAME' has been redefined
  229. *** Function `EXDSDESCINCLUDE' has been redefined
  230. *** Function `PUTEXDSDESCINCLUDE' has been redefined
  231. *** Function `EXDSDESCINCLINIT' has been redefined
  232. *** Function `PUTEXDSDESCINCLINIT' has been redefined
  233. *** Defstruct `EXDEFSTRUCTDESCRIPTOR' has been redefined
  234. EXDEFSTRUCTDESCRIPTOR
  235. > TWICE % Redef to show fns generated.
  236. > Defstruct(
  237. > EXSlotDescriptor( !:Prefix(EXSlotDesc), !:Creator ),
  238. > SlotNum( !:Type int ),
  239. > InitForm( !:Type form ),
  240. > SlotFn( !:Type fnId ), % Selector/Depositor id.
  241. > SlotType( !:Type type ), % Hm...
  242. > UserGet( !:Type boolean ),
  243. > UserPut( !:Type boolean )
  244. > );
  245. *** Function `MAKEEXSLOTDESCRIPTOR' has been redefined
  246. *** Function `ALTEREXSLOTDESCRIPTOR' has been redefined
  247. *** Function `EXSLOTDESCRIPTORP' has been redefined
  248. *** Function `CREATEEXSLOTDESCRIPTOR' has been redefined
  249. *** Function `EXSLOTDESCSLOTNUM' has been redefined
  250. *** Function `PUTEXSLOTDESCSLOTNUM' has been redefined
  251. *** Function `EXSLOTDESCINITFORM' has been redefined
  252. *** Function `PUTEXSLOTDESCINITFORM' has been redefined
  253. *** Function `EXSLOTDESCSLOTFN' has been redefined
  254. *** Function `PUTEXSLOTDESCSLOTFN' has been redefined
  255. *** Function `EXSLOTDESCSLOTTYPE' has been redefined
  256. *** Function `PUTEXSLOTDESCSLOTTYPE' has been redefined
  257. *** Function `EXSLOTDESCUSERGET' has been redefined
  258. *** Function `PUTEXSLOTDESCUSERGET' has been redefined
  259. *** Function `EXSLOTDESCUSERPUT' has been redefined
  260. *** Function `PUTEXSLOTDESCUSERPUT' has been redefined
  261. *** Defstruct `EXSLOTDESCRIPTOR' has been redefined
  262. EXSLOTDESCRIPTOR
  263. > END;
  264. NIL