X-Git-Url: http://git.hcoop.net/jackhill/mal.git/blobdiff_plain/afc3a8d5843e877a150ea20566704d7bb8e92fa0..6e7390b73b8930bded62a9b430abb771f4fe68dd:/crystal/types.cr diff --git a/crystal/types.cr b/crystal/types.cr index 59da8ea3..af61cb7f 100644 --- a/crystal/types.cr +++ b/crystal/types.cr @@ -1,7 +1,13 @@ +require "./printer" + module Mal class Symbol - property :val - def initialize(@val) + property :str + def initialize(@str) + end + + def ==(other : Symbol) + @str == other.str end end @@ -14,8 +20,95 @@ module Mal class HashMap < Hash(String, Type) end - alias Type = Nil | Bool | Int32 | String | Symbol | List | Vector | HashMap + 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 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.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 = Type::Func +end - class ParseException < Exception +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 +