Merge pull request #238 from prt2121/pt/haskell-7.10.1
[jackhill/mal.git] / ruby / core.rb
index 268ebad..0b68c4a 100644 (file)
@@ -1,9 +1,26 @@
+require "readline"
+require_relative "reader"
+require_relative "printer"
+
 $core_ns = {
     :"=" =>       lambda {|a,b| a == b},
+    :throw =>     lambda {|a| raise MalException.new(a), "Mal Exception"},
+    :nil? =>      lambda {|a| a == nil},
+    :true? =>     lambda {|a| a == true},
+    :false? =>    lambda {|a| a == false},
+    :string? =>   lambda {|a| (a.is_a? String) && "\u029e" != a[0]},
+    :symbol =>    lambda {|a| a.to_sym},
+    :symbol? =>   lambda {|a| a.is_a? Symbol},
+    :keyword =>   lambda {|a| "\u029e"+a},
+    :keyword? =>  lambda {|a| (a.is_a? String) && "\u029e" == a[0]},
+
     :"pr-str" =>  lambda {|*a| a.map {|e| _pr_str(e, true)}.join(" ")},
-    :"str" =>     lambda {|*a| a.map {|e| _pr_str(e, false)}.join("")},
-    :"prn" =>     lambda {|*a| puts(a.map {|e| _pr_str(e, true)}.join(" "))},
-    :"println" => lambda {|*a| puts(a.map {|e| _pr_str(e, false)}.join(" "))},
+    :str =>       lambda {|*a| a.map {|e| _pr_str(e, false)}.join("")},
+    :prn =>       lambda {|*a| puts(a.map {|e| _pr_str(e, true)}.join(" "))},
+    :println =>   lambda {|*a| puts(a.map {|e| _pr_str(e, false)}.join(" "))},
+    :readline =>  lambda {|a| Readline.readline(a,true)},
+    :"read-string" => lambda {|a| read_str(a)},
+    :slurp =>     lambda {|a| File.read(a)},
     :< =>         lambda {|a,b| a < b},
     :<= =>        lambda {|a,b| a <= b},
     :> =>         lambda {|a,b| a > b},
@@ -12,9 +29,41 @@ $core_ns = {
     :- =>         lambda {|a,b| a - b},
     :* =>         lambda {|a,b| a * b},
     :/ =>         lambda {|a,b| a / b},
+    :"time-ms" => lambda {|| (Time.now.to_f * 1000).to_i},
+
     :list =>      lambda {|*a| List.new a},
     :list? =>     lambda {|*a| a[0].is_a? List},
+    :vector =>    lambda {|*a| Vector.new a},
+    :vector? =>   lambda {|*a| a[0].is_a? Vector},
+    :"hash-map" =>lambda {|*a| Hash[a.each_slice(2).to_a]},
+    :map? =>      lambda {|a| a.is_a? Hash},
+    :assoc =>     lambda {|*a| a[0].merge(Hash[a.drop(1).each_slice(2).to_a])},
+    :dissoc =>    lambda {|*a| h = a[0].clone; a.drop(1).each{|k| h.delete k}; h},
+    :get =>       lambda {|a,b| return nil if a == nil; a[b]},
+    :contains? => lambda {|a,b| a.key? b},
+    :keys =>      lambda {|a| List.new a.keys},
+    :vals =>      lambda {|a| List.new a.values},
+
+    :sequential? => lambda {|a| sequential?(a)},
+    :cons =>      lambda {|a,b| List.new(b.clone.insert(0,a))},
+    :concat =>    lambda {|*a| List.new(a && a.reduce(:+) || [])},
+    :nth =>       lambda {|a,b| raise "nth: index out of range" if b >= a.size; a[b]},
+    :first =>     lambda {|a| a.nil? ? nil : a[0]},
+    :rest =>      lambda {|a| List.new(a.nil? || a.size == 0 ? [] : a.drop(1))},
     :empty? =>    lambda {|a| a.size == 0},
-    :count =>     lambda {|a| a.size},
+    :count =>     lambda {|a| return 0 if a == nil; a.size},
+    :apply =>     lambda {|*a| a[0][*a[1..-2].concat(a[-1])]},
+    :map =>       lambda {|a,b| List.new(b.map {|e| a[e]})},
+
+    :conj =>      lambda {|*a| a[0].clone.conj(a.drop(1))},
+    :seq =>       lambda {|a| a.nil? ? nil : a.size == 0 ? nil : a.seq},
+
+    :"with-meta" => lambda {|a,b| x = a.clone; x.meta = b; x},
+    :meta =>      lambda {|a| a.meta},
+    :atom =>      lambda {|a| Atom.new(a)},
+    :atom? =>     lambda {|a| a.is_a? Atom},
+    :deref =>     lambda {|a| a.val},
+    :reset! =>    lambda {|a,b| a.val = b},
+    :swap! =>     lambda {|*a| a[0].val = a[1][*[a[0].val].concat(a.drop(2))]},
 }