2015年6月23日火曜日

開発環境

Schemeの処理系(解釈系、評価器、レジスタ計算機を翻訳した命令列中心のより、もう少しC言語の特性を使った書き方をしたもの(label, gotoではなく、関数を呼び出すとか))を少しずつ書き進めてめていくことに。

Land of Lisp で必要になった, 準クォート(quasiquote、バッククォートともいうのかも)、unquote 等を実装。

参考書籍等

kscheme

コード(BBEdit, Emacs)

quasiquote.c

#include "quasiquote.h"
#include "list_operations.h"

void quasiquote_print(FILE *stream, data_s in) {
  fprintf(stream, "#<syntax quasiquote>");
}

const data_s quasiquote_data = {.type = QUASIQUOTE};

data_s quasiquote_sym;

#include "empty.h"
#include "symbol.h"
static data_s quasiquote2expr(data_s in) {
  data_s out;
  data_s quote_sym = data_s_new(SYMBOL, "quote");
  data_s quasiquote_sym = data_s_new(SYMBOL, "quasiquote");
  data_s unquote_sym = data_s_new(SYMBOL, "unquote");
  data_s cons_sym = data_s_new(SYMBOL, "cons");
  data_s t = cadr(in);
  if (t.type == EMPTY)
    out = list(2, quote_sym, empty_data);
  else if (t.type != PAIR)
    out = list(2, quote_sym, t);
  else {
    out = list(2, quote_sym, empty_data);
    data_s reversed = reverse(t);
    while (reversed.type != EMPTY) {
      data_s elem = car(reversed);
      if (elem.type == PAIR) {
        data_s t = car(elem);
        if (t.type == SYMBOL && symbol_is_eq(t, unquote_sym)) {
          out = list(3, cons_sym, cadr(elem), out);
        } else {
          out = list(3, cons_sym,
                     quasiquote2expr(list(2, quasiquote_sym, elem)), out);
        }
      } else {
        out = list(3, cons_sym, list(2, quote_sym, elem), out);
      }
      reversed = cdr(reversed);
    }
  }
  return out;
}

#include "evaluator.h" // eval_flag
void ev_quasiquote() {
  expr = quasiquote2expr(expr);
  eval_flag = 1;
}

入出力結果(Terminal(kscm), REPL(Read, Eval, Print, Loop))

$ kscheme 
kscm> `()
()
kscm> `(1)
(1)
kscm> `(1 2)
(1 2)
kscm> `(1 (+ 2 3))
(1 (+ 2 3))
kscm> `(1 ,(+ 2 3))
(1 5)
kscm> `(1 (+ 2 3) 4)
(1 (+ 2 3) 4)
kscm> `(1 ,(+ 2 3) 4)
(1 5 4)
kscm> `((1) 2)
((1) 2)
kscm> `((+ 1 2) 3)
((+ 1 2) 3)
kscm> `(,(+ 1 2) 3)
(3 3)
kscm> `(1 2 (3 ,(+ 4 5)))
(1 2 (3 9))
kscm> `(1 2 (3 ,(+ 4 5) 6))
(1 2 (3 9 6))
kscm> `(1 2 (,(+ 4 5) 6))
(1 2 (9 6))
kscm> `(`(1 2))
((quasiquote (1 2)))
kscm> $

0 コメント:

コメントを投稿