trait.scm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. (module trait (trait?
  2. define-trait
  3. define-trait-impl
  4. with-type
  5. with-type-of
  6. ;; functions below are supposed to be used only in
  7. ;; code generated by macros
  8. __create_trait
  9. __trait-get-func
  10. __trait-reg-func
  11. __trait-select-func
  12. __trait-select-func-of
  13. __trait-reg-func-to-cls)
  14. (import scheme
  15. (chicken base)
  16. (chicken syntax)
  17. srfi-69)
  18. (define-syntax define-macro
  19. (er-macro-transformer
  20. (lambda (exp r c)
  21. (let ((def (cadr exp))
  22. (body (cddr exp)))
  23. `(define-syntax ,(car def)
  24. (er-macro-transformer
  25. (lambda (e2 r2 c2)
  26. (define (transform-func ,@(cdr def))
  27. ,@body)
  28. (apply transform-func (cdr e2)))))))))
  29. ;; body
  30. (define-record trait name func-names func-table)
  31. (define func-to-class-table (make-hash-table))
  32. (define (__trait-reg-func-to-cls func cls)
  33. (hash-table-set! func-to-class-table func cls))
  34. (define (__trait-select-func pred func name)
  35. (define cls (hash-table-ref func-to-class-table func))
  36. (define func-list (hash-table-ref (trait-func-table cls)
  37. name))
  38. (define (find-in lst)
  39. (if (null? lst)
  40. '()
  41. (if (or (eq? pred (caar lst))
  42. (null? (caar lst)))
  43. (cdar lst)
  44. (find-in (cdr lst)))))
  45. (find-in func-list))
  46. (define (__create_trait name func-names default-funcs)
  47. (let ((table (make-hash-table)))
  48. (define cls (make-trait name func-names table))
  49. (define (init-table func-names)
  50. (if (null? func-names)
  51. '()
  52. (let ()
  53. (hash-table-set! (trait-func-table cls)
  54. (car func-names)
  55. '())
  56. (init-table (cdr func-names)))))
  57. (init-table func-names)
  58. cls))
  59. (define (__trait-get-func cls func-sym obj)
  60. (define func-list (hash-table-ref (trait-func-table cls)
  61. func-sym))
  62. (define (find-in lst)
  63. (if (null? lst)
  64. '()
  65. (if (or (null? (caar lst))
  66. ((caar lst) obj))
  67. (cdar lst)
  68. (find-in (cdr lst)))))
  69. (find-in func-list))
  70. (define (__trait-select-func-of obj func name)
  71. (define cls (hash-table-ref func-to-class-table func))
  72. (__trait-get-func cls name obj))
  73. (define (__trait-reg-func cls func-sym pred func)
  74. (define func-table (trait-func-table cls))
  75. (hash-table-set! func-table
  76. func-sym
  77. (cons (cons pred func)
  78. (hash-table-ref func-table func-sym))))
  79. (define-macro (define-trait name . body)
  80. (let ()
  81. (define (func-def-tr entry)
  82. (define args (gensym))
  83. `(begin
  84. (define (,(car entry) . ,args)
  85. (apply (__trait-get-func ,name
  86. (quote ,(car entry))
  87. (car ,args))
  88. ,args))
  89. (__trait-reg-func-to-cls ,(car entry) ,name)))
  90. (define (default-func-register-tr entry)
  91. `(__trait-reg-func ,name
  92. (quote ,(car entry))
  93. '()
  94. ,(if (null? (cdr entry))
  95. '(quote ())
  96. (cadr entry))))
  97. (define (define-trait-tr name . body)
  98. `(begin
  99. (define ,name
  100. (__create_trait (quote ,name)
  101. (quote ,(map car body))
  102. (quote ,(map (lambda (x)
  103. (if (null? (cdr x))
  104. '()
  105. (cadr x)))
  106. body))))
  107. ,@(map func-def-tr body)
  108. ,@(map default-func-register-tr body)))
  109. (define form (apply define-trait-tr (cons name body)))
  110. ;; (display form) (newline)
  111. form))
  112. (define-macro (define-trait-impl name . body)
  113. (let ()
  114. (define (define-trait-impl-tr name . body)
  115. (define cls (car name))
  116. (define pred (cadr name))
  117. (define (reg-func-tr entry)
  118. `(__trait-reg-func ,cls
  119. (quote ,(car entry))
  120. ,pred
  121. ,(cadr entry)))
  122. `(begin
  123. ,@(map reg-func-tr body)))
  124. (define form (apply define-trait-impl-tr (cons name body)))
  125. ;; (display form) (newline)
  126. form))
  127. (define-macro (with-type pred func)
  128. `(__trait-select-func ,pred ,func (quote ,func)))
  129. (define-macro (with-type-of obj func)
  130. `(__trait-select-func-of ,obj ,func (quote ,func))))