struct.lisp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. (import core/prelude ())
  2. (import data/function (cut))
  3. (import compiler (flag?))
  4. (import data/format (format))
  5. (import control/setq (defsetq))
  6. (defun gen-def (name ll body &extra) :hidden
  7. (case name
  8. [(hide ?x) `(defun ,x ,ll :hidden ,@extra ,@body)]
  9. [?x `(defun ,x ,ll ,@extra ,@body)]))
  10. (defun map-name (f field) :hidden
  11. (case field
  12. [(hide ?x) (list 'hide (f x))]
  13. [?x (f x)]))
  14. (defun field-name (x) :hidden
  15. (case x
  16. [(immutable ?name . _) name]
  17. [(mutable ?name . _) name]
  18. [?name name]))
  19. (defun symb-name (x) :hidden
  20. (case x
  21. [(hide ?x) x]
  22. [?x x]))
  23. (defun maybe-check (field tp value) :hidden
  24. (if (flag? :strict :strict-structs)
  25. `(when (/= (type ,value) ,(symbol->string tp))
  26. (format 1 "{}: value '{}' is not of type {}"
  27. ',(symb-name field) ,value ',tp))
  28. `nil))
  29. (defun gen-setq-definiton (name type check) :hidden
  30. (let* [(struct (gensym 'struct))
  31. (value (gensym 'val))
  32. (fun (gensym 'fun))
  33. (val (gensym 'val))
  34. (use (lambda (x)
  35. `(,'unquote (,'quote ,x))))
  36. (embed (lambda (x)
  37. `(,'unquote ,x)))
  38. (inner ``(let [(,,(use val) ,,(embed struct))]
  39. (.<! ,,(use val) ,,(symbol->string name)
  40. (,,(embed fun) (.> ,,(use val) ,,(symbol->string name))))
  41. ,,(use val)))]
  42. (case name
  43. [(hide ?x) 'nil]
  44. [?name
  45. `(defsetq (,(sym.. type '- name) ,(sym.. '? struct))
  46. (lambda (,fun)
  47. ,inner))])))
  48. (defun field->def (nm field) :hidden
  49. (let* [(self (gensym nm))
  50. (val (gensym (symb-name (field-name field))))]
  51. (case field
  52. [(immutable ?name (optional (string? @ ?docs)))
  53. (list
  54. (gen-def (map-name (cut sym.. nm '- <>) name)
  55. `(,self)
  56. `(,(maybe-check (map-name (cut sym.. nm '- <>) name) nm self)
  57. (.> ,self ,(symbol->string (symb-name name))))
  58. (or docs `nil)))]
  59. [(immutable ?name ?accessor (optional (string? @ ?docs)))
  60. (list
  61. (gen-def accessor
  62. `(,self)
  63. `(,(maybe-check accessor nm self)
  64. (.> ,self ,(symbol->string (symb-name name))))
  65. (or docs `nil)))]
  66. [(symbol? @ ?name)
  67. (field->def nm (list 'immutable name))]
  68. [(mutable ?name (optional (string? @ ?docs)))
  69. (snoc
  70. (field->def nm (list 'immutable name))
  71. (gen-def (map-name (cut sym.. 'set- nm '- <> '!) name)
  72. (list self val)
  73. `(,(maybe-check (map-name (cut sym.. 'set- nm '- <> '!) name)
  74. nm self)
  75. (.<! ,self ,(symbol->string (symb-name name)) ,val))
  76. (or docs `nil))
  77. (gen-setq-definiton name nm
  78. (maybe-check (map-name (cut sym.. 'set- nm '- <> '!) name) nm self)))]
  79. [(mutable ?name ?getter ?setter (optional (string? @ ?docs)))
  80. (snoc
  81. (field->def nm (list 'immutable name getter))
  82. (gen-def setter
  83. (list self val)
  84. `(,(maybe-check setter nm self)
  85. (.<! ,self ,(symbol->string (symb-name name)) ,val))
  86. (or docs `nil))
  87. (gen-setq-definiton setter nm
  88. (maybe-check (map-name (cut sym.. 'set- nm '- <> '!) name) nm self)))])))
  89. (defun make-constructor (docs type-name fields symbol spec) :hidden
  90. (let* [(lambda-list (map (lambda (x) (symb-name (field-name x))) fields))
  91. (kv-pairs (map (function
  92. [((immutable (symb-name -> ?name) . _))
  93. (list (symbol->string name) name)]
  94. [((mutable (symb-name -> ?name) . _))
  95. (list (symbol->string name) name)]
  96. [((symb-name -> ?name))
  97. (list (symbol->string name) name)])
  98. fields))
  99. (name (symb-name symbol))
  100. (hide (and (list? symbol) (eq? (car symbol) 'hide)))]
  101. `(define ,name ,@(if hide '(:hidden) '())
  102. ,@(if (nil? docs) '() (list docs))
  103. (let* [(,(car spec)
  104. (lambda ,lambda-list
  105. { :tag ,(symbol->string type-name)
  106. ,@(flatten kv-pairs) }))]
  107. ,(cadr spec)))))
  108. (defun assoc-cdr (list k or-val) :hidden
  109. (case list
  110. [() or-val]
  111. [(((?x . ?y) . _)
  112. :when (eq? x k))
  113. y]
  114. [(_ . ?x) (assoc-cdr x k or-val)]))
  115. (defun make-meta-decl (type-name constructor-name predicate-name clauses meta-clause fields-clause) :hidden
  116. (let* [(name-sym (symb-name (car meta-clause)))
  117. (hide (if (list? (car meta-clause)) (eql? (caar meta-clause) 'hide) false))
  118. (docs (or (cadr meta-clause) nil))
  119. (fields-clause-sym (gensym))
  120. (destructure (let* [(self (gensym 'self))]
  121. `(lambda (,'_ ,self)
  122. (list ,@(map (lambda (x)
  123. `(.> ,self
  124. ,(symbol->string (symb-name (field-name x)))))
  125. fields-clause)))))]
  126. `(define ,name-sym ,@(if hide '(:hidden) '()) ,@(if docs (list docs) '())
  127. (let* [(,fields-clause-sym ',fields-clause)]
  128. (setmetatable
  129. { :test ,predicate-name }
  130. { :__call ,destructure })))))
  131. (defmacro defstruct (name &clauses)
  132. "Define a struct called NAME.
  133. NAME can be either a symbol or a list of three elements, whose
  134. elements name, respectively, the type (returned from `type` and
  135. used in `defmethod`, for instance), the constructor's name, and
  136. the predicate's name. In case NAME is a symbol, the constructor
  137. and predicate names are automatically derived from that symbol.
  138. Consider:
  139. ```cl :no-test
  140. (defstruct thing ...)
  141. (defstruct (other-thing make-something-else is-something-else?) ...)
  142. ```
  143. The first struct declaration generates a constructor called
  144. `make-thing` and a predicate called `thing?`, but the second
  145. declaration generates a constructor called `make-something-else`
  146. and a predicate `is-something-else?`.
  147. The CLAUSES argument to [[defstruct]] controls the contents of the
  148. generated structure.
  149. The `(fields field ...)` clause defines the fields of the structure
  150. type. Each `field` must be of one of the following forms:
  151. - `field-name`
  152. - `(immutable field-name [getter-name])`
  153. - `(mutable field-name [getter-name setter-name])`
  154. Where a field in square brackets is optional. If no name is
  155. specified for the getter, it will have the name `struct-field`,
  156. while the setter will have the name `set-struct-field!`.
  157. The `(constructor tag fun)` clause will use `fun` as the constructor
  158. for the structure type. `tag` will be a symbol in `fun`'s scope that
  159. builds the structure according to the fields clause."
  160. (let* [((name constr pred)
  161. (case name
  162. [(?n ?c ?p) (values-list n c p)]
  163. [?n (values-list n (sym.. 'make- n) (sym.. n '?))]))
  164. ((docs clauses)
  165. (if (string? (car clauses))
  166. (values-list (car clauses) (cdr clauses))
  167. (values-list nil clauses)))
  168. (meta (assoc-cdr clauses 'meta (list (sym.. '$ name))))
  169. (fields (assoc-cdr clauses 'fields '()))
  170. (constructor (assoc-cdr clauses 'constructor '(new new)))]
  171. (let* [(work '())]
  172. (push! work (make-constructor docs name fields
  173. constr constructor))
  174. (push! work (let* [(self (gensym name))]
  175. (gen-def pred (list self)
  176. `((and (table? ,self)
  177. (= (.> ,self :tag) ,(symbol->string name)))))))
  178. (map (lambda (x)
  179. (map (cut push! work <>) (field->def name x)))
  180. fields)
  181. (push! work (make-meta-decl name (symb-name constr) (symb-name pred) ; names
  182. clauses ; clauses
  183. meta fields)) ; clauses we use
  184. (splice work))))