X-Git-Url: http://git.hcoop.net/jackhill/mal.git/blobdiff_plain/2c76c2ff166c9943aa45e84ffa894fb785ae954b..6e7390b73b8930bded62a9b430abb771f4fe68dd:/crystal/types.cr diff --git a/crystal/types.cr b/crystal/types.cr index 4ecc7428..af61cb7f 100644 --- a/crystal/types.cr +++ b/crystal/types.cr @@ -1,8 +1,14 @@ +require "./printer" + module Mal class Symbol property :str def initialize(@str) end + + def ==(other : Symbol) + @str == other.str + end end class List < Array(Type) @@ -14,20 +20,95 @@ module Mal class HashMap < Hash(String, Type) end + class Atom + property :val + def initialize(@val) + end + + def ==(rhs : Atom) + @val == rhs.val + end + end + + class Closure + property :ast, :params, :env, :fn + def initialize(@ast, @params, @env, @fn) + end + end + class Type - alias ValueType = Nil | Bool | Int32 | String | Symbol | List | Vector | HashMap | ((Array(Type) -> Type)) + alias Func = (Array(Type) -> Type) + alias ValueType = Nil | Bool | Int32 | String | Symbol | List | Vector | HashMap | Func | Closure | Atom + + is_macro :: Bool + meta :: Type + + property :is_macro, :meta def initialize(@val : ValueType) + @is_macro = false + @meta = nil end def initialize(other : Type) - @val = other.val + @val = other.unwrap + @is_macro = other.is_macro + @meta = other.meta end def unwrap @val end + + def macro? + @is_macro + end + + def to_s + pr_str(self) + end + + def dup + Type.new(@val).tap do |t| + t.is_macro = @is_macro + t.meta = @meta + end + end + + def ==(other : Type) + @val == other.unwrap + end + + macro rel_op(*ops) + {% for op in ops %} + def {{op.id}}(other : Mal::Type) + l, r = @val, other.unwrap + {% for t in [Int32, String] %} + if l.is_a?({{t}}) && r.is_a?({{t}}) + return (l) {{op.id}} (r) + end + {% end %} + if l.is_a?(Symbol) && r.is_a?(Symbol) + return l.str {{op.id}} r.str + end + false + end + {% end %} + end + + rel_op :<, :>, :<=, :>= end - alias Func = Array(Type) -> Type + alias Func = Type::Func +end + +macro gen_type(t, *args) + Mal::Type.new {{t.id}}.new({{*args}}) end + +class Array + def to_mal(t = Mal::List) + each_with_object(t.new){|e, l| l << e} + end +end +