;; this is miku primitive operators.
;; don't change this file.
;; normally, you should make another library files.

(require_runtime_library "enumerator")

(def 'defmacro
     (macro (name alist (rest body))
            `(def ,(list 'quote name) (macro ,alist ,@body))))

;; (defmacro setq (var val)
;;   `(set ,(list 'quote var) ,val))
(defmacro setq ((rest args))
  (set 'result '(set))
  (each_slice args 2 #((pair)
                       (append result (list (list 'quote (car pair)) (nth pair 1)))))
  result)

(defmacro defun (name alist (rest body))
  `(def ,(list 'quote name) #(,alist ,@body)))

(defun to_hash (ary)
  (setq result (new Hash))
  (each ary #((pair) (store result (car pair) (cdr pair))))
  result)

(defmacro and (body (rest other))
  (if (empty? other)
      body
  `(if ,body (and ,@other))))

(defmacro or (body (rest other))
  `(if ,body
       true
     ,(if other
          `(or ,@other))))

(defmacro let (bind (rest body))
  (#((mapped)
	 `(#(,(map mapped #((node) (car node)))
		 ,@body) ,@(map mapped #((node) (cdr node)))))
   (map bind #((node)
			   (if (listp node)
				   (cons (car node) (nth node 1))
				   (cons node nil))))))

(defmacro let* (bind (rest body))
  (if (cdr bind)
      `(let (,(car bind))
         (let* ,(cdr bind) ,@body))
    `(let (,(car bind))
       ,@body)))

(defmacro progn ((rest body))
  `(#(() ,@body)))

(defmacro cond (condition (rest follow))
  `(if ,(car condition) (progn ,@(cdr condition)) ,(if (not (empty? follow)) (cons 'cond follow))))
