A fork of Crisp for HARP
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
1.9 KiB

  1. require "./printer"
  2. module Mal
  3. class Symbol
  4. property :str
  5. def initialize(@str)
  6. end
  7. def ==(other : Symbol)
  8. @str == other.str
  9. end
  10. end
  11. class List < Array(Type)
  12. end
  13. class Vector < Array(Type)
  14. end
  15. class HashMap < Hash(String, Type)
  16. end
  17. class Atom
  18. property :val
  19. def initialize(@val)
  20. end
  21. def ==(rhs : Atom)
  22. @val == rhs.val
  23. end
  24. end
  25. class Closure
  26. property :ast, :params, :env, :fn
  27. def initialize(@ast, @params, @env, @fn)
  28. end
  29. end
  30. class Type
  31. alias Func = (Array(Type) -> Type)
  32. alias ValueType = Nil | Bool | Int32 | String | Symbol | List | Vector | HashMap | Func | Closure | Atom
  33. is_macro :: Bool
  34. meta :: Type
  35. property :is_macro, :meta
  36. def initialize(@val : ValueType)
  37. @is_macro = false
  38. @meta = nil
  39. end
  40. def initialize(other : Type)
  41. @val = other.unwrap
  42. @is_macro = other.is_macro
  43. @meta = other.meta
  44. end
  45. def unwrap
  46. @val
  47. end
  48. def macro?
  49. @is_macro
  50. end
  51. def to_s
  52. pr_str(self)
  53. end
  54. def dup
  55. Type.new(@val).tap do |t|
  56. t.is_macro = @is_macro
  57. t.meta = @meta
  58. end
  59. end
  60. def ==(other : Type)
  61. @val == other.unwrap
  62. end
  63. macro rel_op(*ops)
  64. {% for op in ops %}
  65. def {{op.id}}(other : Mal::Type)
  66. l, r = @val, other.unwrap
  67. {% for t in [Int32, String] %}
  68. if l.is_a?({{t}}) && r.is_a?({{t}})
  69. return (l) {{op.id}} (r)
  70. end
  71. {% end %}
  72. if l.is_a?(Symbol) && r.is_a?(Symbol)
  73. return l.str {{op.id}} r.str
  74. end
  75. false
  76. end
  77. {% end %}
  78. end
  79. rel_op :<, :>, :<=, :>=
  80. end
  81. alias Func = Type::Func
  82. end
  83. macro gen_type(t, *args)
  84. Mal::Type.new {{t.id}}.new({{*args}})
  85. end
  86. class Array
  87. def to_mal(t = Mal::List)
  88. each_with_object(t.new){|e, l| l << e}
  89. end
  90. end