lisp on yarv製作日誌14

rubyのハッシュを簡単に使えるようにしてみました。

(make_hash h (("a" 10) ("b" 20) ("c" 30)))

(get_hash h "a")

#=> 10

ちなみにマクロで書きました。

(macro (make_hash a hash_list)
  `(begin
     (rasm ,a.to_s)
     (rasm " = {")
     ,@(map (lambda (val)
	      `(begin
		 (macro_val_print ,(car val))
		 (rasm " => ")
		 (macro_val_print ,(cadr val))
		 (rasm ", "))) hash_list)
     (rasm "}")))

(macro (gethash a key)
  `(begin
     (macro_val_print ,a)
     (rasm "[")
     (macro_val_print ,key)
     (rasm "]"))

macro_val_printはコンパイルしたときに、改行を行わないようにする命令です。
例えば、(gethash h "a")でmacro_val_printを使わなかった場合、
h
["a"]
のように、コンパイルされてしまいます。

このマクロ使えばruby以外の言語の生成もできそうな気がしたので試してみました。

(macro (def_c k name args  *body)
  `(begin
     (macro_val_print ,k)
     (rasm " ")
     (macro_val_print ,name)
     (rasm "(")
     (macro_val_print ,(caar args))
     (rasm " ")
     (macro_val_print ,(cadar args))
     ,@(map (lambda (a)
	      `(begin
		 (rasm ",")
		 (macro_val_print ,(car a))
		 (rasm " ")
		 (macro_val_print ,(cadr a))))(cdr args))
     (rasm ")\n")
     (rasm "{\n")
     ,@(a2l body)
     (rasm "}")))

(def_c int add ((int a) (int b))
  (return (+ a b)))

;コンパイル結果
int add(int a, int b)
{
return(a+b)
}

これは、なかなか楽しいですね。もう少し汎用的に使えるようなのを作るのも、
面白そうです。