type.scm 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. (module (arguile base type)
  2. #:export (base-type coerce ->))
  3. (use (arguile base mac)
  4. (arguile base fn)
  5. (arguile base ctrl)
  6. (arguile base err)
  7. (arguile base module)
  8. (arguile base type lst)
  9. (arguile base type str)
  10. (arguile base type num)
  11. (arguile base type fn)
  12. (arguile base type sym)
  13. (arguile base type syn)
  14. (arguile base type chr)
  15. (arguile base type kwrd)
  16. (arguile base type strm))
  17. ;;; TODO: add simple heirarchy
  18. (def base-type (x)
  19. (cond
  20. ;; TODO: nest related types
  21. ;((pair? x) 'pair)
  22. ((lst? x) 'lst)
  23. ((str? x) 'str)
  24. ((int? x) 'int)
  25. ((num? x) 'num)
  26. ((fn? x) 'fn)
  27. ((sym? x) 'sym)
  28. ((syn? x) 'syn)
  29. ((hash-table? x) 'hash-tbl)
  30. ((chr? x) 'chr)
  31. ((vector? x) 'vector)
  32. ((kwrd? x) 'kwrd)
  33. ;; TODO: is null? useful as a type?
  34. ((null? x) 'sym)
  35. (else (error "Type: unknown type" x))))
  36. (def coerce (x to-type . args)
  37. (let x-type (base-type x)
  38. (if (eqv? to-type x-type) x
  39. (w/ (fail (fn args (error "Can't coerce" args '-> to-type))
  40. conversions (hash-ref coercions to-type fail)
  41. converter (hash-ref conversions x-type fail))
  42. (apply converter (cons x args))))))
  43. ;;; Deprecated: use base type constructors, or data converter
  44. (mac -> ((_ type obj . args) #'(coerce obj 'type . args)))
  45. (def coercions
  46. (ret coercions (make-hash-table)
  47. (for-each
  48. (fn (e)
  49. (w/ (target-type (car e)
  50. conversions (make-hash-table))
  51. (hash-set! coercions target-type conversions)
  52. (for-each
  53. (fn (x) (hash-set! conversions (car x) (cadr x)))
  54. (cdr e))))
  55. `((dat (syn ,syn->dat)
  56. (lst ,syn->dat))
  57. ;; So clearly this is a bit hacky
  58. (syn (lst ,(fn (dat ctx) (dat->syn ctx dat)))
  59. (num ,(fn (dat ctx) (dat->syn ctx dat)))
  60. (str ,(fn (dat ctx) (dat->syn ctx dat)))
  61. (sym ,(fn (dat ctx) (dat->syn ctx dat)))
  62. (kwrd ,(fn (dat ctx) (dat->syn ctx dat))))
  63. (str (int ,num->str)
  64. (num ,num->str)
  65. (chr ,string)
  66. (sym ,(fn (x) (if (eqv? x (symbol)) "" (sym->str x)))))
  67. (sym (str ,str->sym)
  68. (chr ,(fn (c) (str->sym (string c))))
  69. (num ,(\\ (comp str->sym num->str) _)))
  70. (int (chr ,(fn (c . args) (chr->int c)))
  71. (num ,(fn (x . args) (iround x)))
  72. (str ,(fn (x . args)
  73. (aif (str->num x) (iround it)
  74. (err "Can't coerce" x '-> 'int)))))
  75. (num (str ,(fn (x . args)
  76. (or (str->num x)
  77. (err "Can't coerce " x '-> 'num))))
  78. (int ,(fn (x) x)))
  79. (chr (int ,int->chr)
  80. (num ,(fn (x) (int->chr
  81. (iround x)))))))
  82. coercions))
  83. (def iround (compose inexact->exact round))
  84. (mac export-type-ctrs
  85. ((_ t1 ...)
  86. #`(do #,@(map (fn (t)
  87. #`(defp #,t (obj . args)
  88. (apply coerce obj '#,t args)))
  89. #'(t1 ...)))))
  90. ;;; Exporting type constructors
  91. (export-type-ctrs str num int sym syn dat chr)
  92. (re-export-modules
  93. (arguile base type lst)
  94. (arguile base type str)
  95. (arguile base type num)
  96. (arguile base type fn)
  97. (arguile base type sym)
  98. (arguile base type syn)
  99. (arguile base type chr)
  100. (arguile base type kwrd)
  101. (arguile base type strm))