Changeset 11144 for lang/c

Show
Ignore:
Timestamp:
05/05/08 07:28:23 (7 months ago)
Author:
mokehehe
Message:

マクロ追加
関数をScheme寄りに

Location:
lang/c/misc/mlisp
Files:
10 modified

Legend:

Unmodified
Added
Removed
  • lang/c/misc/mlisp/compiler/compiler.cpp

    r11110 r11144  
    88#include "op.h" 
    99#include "inner.h" 
     10 
     11extern SExp evaluate(SExp code); 
     12 
     13 
     14static SExp s_macros; 
    1015 
    1116 
     
    7580                } 
    7681        } else { 
    77                 return compile_pair_loop(cdr(args), compile(car(args), e, list(2, intern("argument"), c)), e, next); 
     82                return compile_pair_loop(cdr(args), compile(car(args), e, list(2, ARGUMENT, c)), e, next); 
    7883        } 
    7984} 
     
    127132} 
    128133 
     134 
     135 
     136/// �}�N���� 
     137static void compile_defmacro(SExp name, SExp vars, SExp body) { 
     138        SExp mac = cons(name, cons(intern("lambda"), cons(vars, body))); 
     139        s_macros = cons(mac, s_macros); 
     140} 
     141 
     142SExp is_macro(SExp name) { 
     143        return assoc(name, s_macros); 
     144} 
     145 
     146/// �}�N���Ăяo���R�[�h�쐬 
     147static SExp quotize(SExp s) { 
     148        return list(2, intern("quote"), s); 
     149} 
     150static SExp gen_macro_call(SExp m, SExp x) { 
     151        return cons(cdr(m), mapcar(quotize, cdr(x))); 
     152} 
     153 
     154/// �}�N����i�W�J 
     155SExp macroexpand_1(SExp m, SExp x) { 
     156        SExp code = gen_macro_call(m, x); 
     157        return evaluate(code); 
     158} 
     159 
     160/// �}�N���K�p 
     161static SExp compile_macro_apply(SExp m, SExp x, SExp e, SExp next) { 
     162        SExp trans = macroexpand_1(m, x); 
     163        return compile(trans, e, next); 
     164} 
     165 
     166 
     167 
     168/// �o�b�N�N�H�[�g�̕ϊ� 
     169 
     170static SExp transform_quasiquote_loop(SExp x) { 
     171        if (!consp(x))                                                                          return list(2, intern("quote"), list(1, x)); 
     172        else if (eq(car(x), intern("unquote")))                         return list(2, intern("list"), cadr(x)); 
     173        else if (eq(car(x), intern("unquote-splicing")))        return cadr(x); 
     174        else                                                                                            return list(2, intern("list"), cons(intern("append"), mapcar(transform_quasiquote_loop, x))); 
     175} 
     176 
     177static SExp transform_quasiquote(SExp x) { 
     178        SExp res = transform_quasiquote_loop(x); 
     179        SExp hd = car(res); 
     180        if              (eq(hd, intern("list")))        return cadr(res); 
     181        else if (eq(hd, intern("quote")))       return list(2, intern("quote"), car(cadr(res))); 
     182        else    { assert(!"unexpected"); return nil; } 
     183} 
     184 
     185/// ����void init_compile(void) { 
     186        s_macros = nil; 
     187} 
     188 
    129189/// �P�‚̎�����p�C�� 
    130190SExp compile(SExp x, SExp e, SExp next) { 
     
    136196                return list(3, REFER, access, next); 
    137197        } else if (consp(x)) { 
    138                 SExp op = car(x); 
    139                 if (eq(op, intern("quote"))) { 
    140                         SExp obj = cadr(x); 
    141                         return list(3, CONSTANT, obj, next); 
    142                 } else if (eq(op, intern("lambda"))) { 
    143                         SExp vars = cadr(x); 
    144                         SExp body = cddr(x); 
    145                         return list(3, CLOSE, compile_block(body, extend(e, vars), cons(RETURN, nil)), next); 
    146                 } else if (eq(op, intern("if"))) { 
    147                         SExp test = cadr(x); 
    148                         SExp then = caddr(x); 
    149                         SExp thenc = compile(then, e, next); 
    150                         SExp els, elsec; 
    151                         SExp ddd = cdddr(x); 
    152                         if (!nilp(ddd))         els = cadddr(x); 
    153                         else                            els = nil; 
    154                         elsec = compile(els, e, next); 
    155                         return compile(test, e, list(3, TEST, thenc, elsec)); 
    156                 } else if (eq(op, intern("set!"))) { 
    157                         SExp var = cadr(x); 
    158                         SExp xx = caddr(x); 
    159                         return compile_set(ASSIGN, var, xx, e, next, false); 
    160                 } else if (eq(op, intern("define"))) { 
    161                         SExp var = cadr(x); 
    162                         SExp body = cddr(x); 
    163                         return compile_define(var, body, e, next); 
    164                 } else if (eq(op, intern("call/cc"))) { 
    165                         SExp xx = cadr(x); 
    166                         SExp c = list(2, CONTI, list(2, ARGUMENT, compile(xx, e, cons(APPLY, nil)))); 
    167                         if (tailp(next)) 
    168                                 return c; 
    169                         else 
    170                                 return list(3, FRAME, c, next); 
     198                SExp m = is_macro(car(x)); 
     199                if (!nilp(m)) { 
     200                        return compile_macro_apply(m, x, e, next); 
    171201                } else { 
    172                         return compile_pair_loop(cdr(x), compile(car(x), e, cons(APPLY, nil)), e, next); 
     202                        SExp op = car(x); 
     203                        if (eq(op, intern("quote"))) { 
     204                                SExp obj = cadr(x); 
     205                                return list(3, CONSTANT, obj, next); 
     206                        } else if (eq(op, intern("quasiquote"))) { 
     207                                SExp obj = cadr(x); 
     208                                SExp trans = transform_quasiquote(obj); 
     209                                return compile(trans, e, next); 
     210                        } else if (eq(op, intern("unquote"))) { 
     211                                compile_error(ERR_UNEXPECTED); 
     212                                return nil; 
     213                        } else if (eq(op, intern("unquote-splicing"))) { 
     214                                compile_error(ERR_UNEXPECTED); 
     215                                return nil; 
     216                        } else if (eq(op, intern("lambda"))) { 
     217                                SExp vars = cadr(x); 
     218                                SExp body = cddr(x); 
     219                                return list(3, CLOSE, compile_block(body, extend(e, vars), cons(RETURN, nil)), next); 
     220                        } else if (eq(op, intern("if"))) { 
     221                                SExp test = cadr(x); 
     222                                SExp then = caddr(x); 
     223                                SExp thenc = compile(then, e, next); 
     224                                SExp els, elsec; 
     225                                SExp ddd = cdddr(x); 
     226                                if (!nilp(ddd))         els = cadddr(x); 
     227                                else                            els = nil; 
     228                                elsec = compile(els, e, next); 
     229                                return compile(test, e, list(3, TEST, thenc, elsec)); 
     230                        } else if (eq(op, intern("set!"))) { 
     231                                SExp var = cadr(x); 
     232                                SExp xx = caddr(x); 
     233                                return compile_set(ASSIGN, var, xx, e, next, false); 
     234                        } else if (eq(op, intern("define"))) { 
     235                                SExp var = cadr(x); 
     236                                SExp body = cddr(x); 
     237                                return compile_define(var, body, e, next); 
     238                        } else if (eq(op, intern("call/cc"))) { 
     239                                SExp xx = cadr(x); 
     240                                SExp c = list(2, CONTI, list(2, ARGUMENT, compile(xx, e, cons(APPLY, nil)))); 
     241                                if (tailp(next)) 
     242                                        return c; 
     243                                else 
     244                                        return list(3, FRAME, c, next); 
     245                        } else if (eq(op, intern("defmacro"))) { 
     246                                SExp name = cadr(x); 
     247                                SExp vars = caddr(x); 
     248                                SExp body = cdddr(x); 
     249                                compile_defmacro(name, vars, body); 
     250                                return next; 
     251                        } else { 
     252                                return compile_pair_loop(cdr(x), compile(car(x), e, cons(APPLY, nil)), e, next); 
     253                        } 
    173254                } 
    174255        } else { 
  • lang/c/misc/mlisp/compiler/compiler.h

    r11061 r11144  
    1111#endif 
    1212 
     13void init_compile(void); 
    1314SExp compile(SExp x, SExp e, SExp next); 
    1415SExp compile_block(SExp sexps, SExp e, SExp next); 
     16 
     17SExp is_macro(SExp name); 
     18SExp macroexpand_1(SExp m, SExp x); 
    1519 
    1620#ifdef __cplusplus 
  • lang/c/misc/mlisp/sexp/inner.h

    r11059 r11144  
    2525        ERR_TYPE_REQUIRED, 
    2626        ERR_UNDEFINED_SYMBOL, 
     27        ERR_UNEXPECTED, 
    2728}; 
    2829 
  • lang/c/misc/mlisp/sexp/sexp.cpp

    r11059 r11144  
    2222        "type required: %s", 
    2323        "undefined symbol", 
     24        "unexpected", 
    2425}; 
    2526 
  • lang/c/misc/mlisp/sexp/sprint.cpp

    r11057 r11144  
    11#include "inner.h" 
     2#include "sutil.h" 
    23 
    34static void print_rec(SExp s); 
     
    3031                { 
    3132                        SExp a = car(s); 
    32                         if (eq(a, intern("quote"))) { 
     33                        if (eq(a, intern("quote")) && singlep(cdr(s))) { 
    3334                                printf("'"); 
    3435                                print_rec(car(cdr(s))); 
  • lang/c/misc/mlisp/sexp/sutil.cpp

    r11057 r11144  
    6262} 
    6363 
     64SExp mapcar(SExp (*fn)(SExp), SExp ls) { 
     65        SExp acc = nil; 
     66        for (; !nilp(ls); ls = cdr(ls)) { 
     67                acc = cons(fn(car(ls)), acc); 
     68        } 
     69        return nreverse(acc); 
     70} 
     71 
     72SExp assoc(SExp sym, SExp alist) { 
     73        for (; consp(alist); alist = cdr(alist)) { 
     74                SExp elem = car(alist); 
     75                if (eq(sym, car(elem))) return elem; 
     76        } 
     77        return nil; 
     78} 
     79 
     80 
    6481 
    6582int singlep(SExp ls) { 
  • lang/c/misc/mlisp/sexp/sutil.h

    r11058 r11144  
    2929SExp nreverse(SExp s); 
    3030 
     31/// ���X�g�̊e�v�f�Ɋ֐���p�i���X�g�͂P�Œ�� 
     32SExp mapcar(SExp (*fn)(SExp), SExp ls); 
     33 
     34/// alist ((key . value) ...) ������ 
     35SExp assoc(SExp sym, SExp alist); 
     36 
     37 
    3138/// ���X�g�ŗv�f���ЂƂ‚����H 
    3239int singlep(SExp ls); 
  • lang/c/misc/mlisp/test/main.cpp

    r11059 r11144  
    3131 
    3232 
    33 SExp comp_env, run_env; 
     33SExp g_comp_env, g_run_env; 
    3434 
    3535int load(const char* fn); 
     
    4141 
    4242SExp run(SExp c) { 
    43         return vm(nil, c, run_env, nil, nil); 
     43        return vm(nil, c, g_run_env, nil, nil); 
    4444} 
    4545 
    4646SExp evaluate(SExp code) { 
    4747        SExp halt_code = cons(HALT, nil); 
    48         SExp c = compile(code, comp_env, halt_code); 
     48        SExp c = compile(code, g_comp_env, halt_code); 
    4949        return run(c); 
    5050} 
     
    8686        SExp d = cadr(arg); 
    8787        return eq(a, d) ? t : nil; 
     88} 
     89 
     90static SExp builtin_rplaca(SExp arg) { 
     91        SExp a = car(arg); 
     92        SExp d = cadr(arg); 
     93        rplaca(a, d); 
     94        return nil; 
     95} 
     96 
     97static SExp builtin_rplacd(SExp arg) { 
     98        SExp a = car(arg); 
     99        SExp d = cadr(arg); 
     100        rplacd(a, d); 
     101        return nil; 
    88102} 
    89103 
     
    210224        SExp code = car(arg); 
    211225        SExp halt_code = cons(HALT, nil); 
    212         return compile(code, comp_env, halt_code); 
    213 } 
     226        return compile(code, g_comp_env, halt_code); 
     227} 
     228 
     229static SExp builtin_macroexpand_1(SExp arg) { 
     230        SExp code = car(arg); 
     231        if (consp(code)) { 
     232                SExp m = is_macro(car(code)); 
     233                if (!nilp(m))   return macroexpand_1(m, code); 
     234                else                    return code; 
     235        } else { 
     236                return code; 
     237        } 
     238} 
     239 
     240 
     241 
     242static SExp builtin_list(SExp arg) { 
     243        // @todo: �j�󂵂Ă������m���߂�     return arg; 
     244} 
     245 
     246static SExp cat(SExp a, SExp b) { 
     247        if (!consp(a))  return b; 
     248        else                    return cons(car(a), cat(cdr(a), b)); 
     249} 
     250 
     251static SExp builtin_append(SExp arg) { 
     252        if (!consp(arg))                        return arg; 
     253        else if (nilp(cdr(arg)))        return car(arg); 
     254        else                                            return cat(car(arg), builtin_append(cdr(arg))); 
     255} 
     256 
     257static SExp builtin_reverse(SExp arg) { 
     258        return reverse(car(arg)); 
     259} 
     260 
     261static SExp builtin_nreverse(SExp arg) { 
     262        return nreverse(car(arg)); 
     263} 
     264 
     265static SExp builtin_global_symbols(SExp arg) { 
     266        return car(g_comp_env); 
     267} 
     268 
     269 
    214270 
    215271static void add_proctbl(SExp* pcenv, SExp* prenv) { 
     
    227283                {       "car",          builtin_car,            FALSE,  1,      1,      }, 
    228284                {       "cdr",          builtin_cdr,            FALSE,  1,      1,      }, 
    229                 {       "consp",        builtin_consp,          FALSE,  1,      1,      }, 
    230                 {       "eq",           builtin_eq,                     FALSE,  2,      2,      }, 
     285                {       "pair?",        builtin_consp,          FALSE,  1,      1,      }, 
     286                {       "eq?",          builtin_eq,                     FALSE,  2,      2,      }, 
     287                {       "set-car!",     builtin_rplaca,         FALSE,  2,      2,      }, 
     288                {       "set-cdr!",     builtin_rplacd,         FALSE,  2,      2,      }, 
    231289                {       "+",            builtin_plus,           FALSE,  0,      -1,     }, 
    232290                {       "-",            builtin_difference,     FALSE,  1, -1,  }, 
     
    241299                {       "eval",         builtin_eval,           FALSE,  1,      1,      }, 
    242300 
     301                {       "list",         builtin_list,           FALSE,  0,      -1,     }, 
     302                {       "append",       builtin_append,         FALSE,  0,      -1,     }, 
     303                {       "reverse",      builtin_reverse,        FALSE,  0,      -1,     }, 
     304                {       "nreverse",     builtin_nreverse,       FALSE,  0,      -1,     }, 
     305 
    243306                {       "load",         builtin_load,           FALSE,  1,      1,      }, 
    244307                {       "compile",      builtin_compile,        FALSE,  1,      1,      }, 
     308                {       "macroexpand-1",        builtin_macroexpand_1,  FALSE,  1,      1,      }, 
     309 
     310                {       "global-symbols",       builtin_global_symbols, FALSE,  1,      1,      }, 
    245311        }; 
    246312        for (int i=0; i<sizeof(tbl)/sizeof(*tbl); ++i) { 
     
    282348        add_consttbl(&cenv, &renv); 
    283349 
    284         comp_env = cons(cenv, nil); 
    285         run_env = cons(renv, nil); 
     350        g_comp_env = cons(cenv, nil); 
     351        g_run_env = cons(renv, nil); 
    286352} 
    287353 
     
    290356        FILE* fp = fopen(fn, "r"); 
    291357        SExp code = nil; 
    292         if (fp != NULL) { 
     358        if (fp == NULL) { 
    293359//              runtime_error(); 
    294360        } else { 
     
    300366                } 
    301367                SExp halt_code = cons(HALT, nil); 
    302                 code = compile_block(nreverse(acc), comp_env, halt_code); 
     368                code = compile_block(nreverse(acc), g_comp_env, halt_code); 
    303369 
    304370                fclose(fp); 
     
    347413 
    348414        mlisp_new(&vtbl); 
     415        init_compile(); 
    349416        init_env(); 
    350417        if (argc >= 2) { 
  • lang/c/misc/mlisp/vm/op.h

    r11110 r11144  
    66 
    77#if 1 
    8 #define HALT            intern("halt") 
    9 #define REFER           intern("refer") 
    10 #define CONSTANT        intern("constant") 
    11 #define CLOSE           intern("close") 
    12 #define TEST            intern("test") 
    13 #define ASSIGN          intern("assign") 
    14 #define DEFINE          intern("define") 
    15 #define CONTI           intern("conti") 
    16 #define NUATE           intern("nuate") 
    17 #define FRAME           intern("frame") 
    18 #define ARGUMENT        intern("argument") 
    19 #define APPLY           intern("apply") 
    20 #define RETURN          intern("return") 
     8#define HALT            intern("HALT") 
     9#define REFER           intern("REFER") 
     10#define CONSTANT        intern("CONSTANT") 
     11#define CLOSE           intern("CLOSE") 
     12#define TEST            intern("TEST") 
     13#define ASSIGN          intern("ASSIGN") 
     14#define DEFINE          intern("DEFINE") 
     15#define CONTI           intern("CONTI") 
     16#define NUATE           intern("NUATE") 
     17#define FRAME           intern("FRAME") 
     18#define ARGUMENT        intern("ARGUMENT") 
     19#define APPLY           intern("APPLY") 
     20#define RETURN          intern("RETURN") 
    2121 
    2222#else 
  • lang/c/misc/mlisp/vm/vm.cpp

    r11061 r11144  
    1515 
    1616static void runtime_error(const char* msg) { 
    17         assert(!msg); 
     17        printf("%s\n", msg); 
     18        error(ERR_UNEXPECTED); 
    1819} 
    1920 
     
    3536        for (int elt = s2int(cdr(access)); ; --elt) { 
    3637                if (nilp(r)) { 
    37                         SExp le = car(e); 
    38                         if (!nilp(le)) { 
    39                                 extend_run_env(car(e), elt + 1); 
     38                        if (!b_extend) { 
     39                                runtime_error("illegal access"); 
     40                                return nil; 
    4041                        } else { 
    41                                 rplaca(e, replicate(elt + 1, nil)); 
     42                                SExp le = car(e); 
     43                                if (!nilp(le)) { 
     44                                        extend_run_env(car(e), elt + 1); 
     45                                } else { 
     46                                        rplaca(e, replicate(elt + 1, nil)); 
     47                                } 
     48 
     49                                r = car(e);     elt = s2int(cdr(access)); 
    4250                        } 
    43  
    44                         r = car(e);     elt = s2int(cdr(access)); 
    4551                } 
    4652                if (elt == 0)   return r;