root/lang/c/misc/mlisp/src/mlisp.cpp @ 2383

Revision 2383, 17.9 kB (checked in by mokehehe, 5 years ago)

README修正

Line 
1//=============================================================================
2///     minimal lisp
3/**
4        ���e�����F
5                ����                            ���������͂Ȃ�
6                ������`"                ��͒P�Ȃ����{��
7
8        �r���̓��\��     SExp
9                ���ʂP�r�b�g���P         �����i������1bit�A������30bit�j
10                ����YPE_BITS ��
11                        tCell                           �Z��
12                        tSymb                           �V���{��
13                        tOther                          ���̑��it, nil, �j
14                        tFunc                           �֐��i�����_ or �}�N���j
15
16        �Z���F
17                �Z���̏ꍇ�ASExp �̏��r�b�g�ŃZ���o�b�t�@��
18                �C���f�N�X�������
19
20        �֐��F
21                �֐����ʂ̓Z���Ɠ������Z������C���f�N�X�ɂȂ�Ă��āA
22                ���̃Z����car �Ɋ֐��̏��i�����_���}�N�����A
23                C�̑g�ݍ��݊֐����Z�����j�����������œ��
24                cdr �ɂ́AC�̑g�ݍ��݊֐��̏ꍇ�g�ݍ��݊֐��f�[�^�̃C���f�N�X���A
25                �Z���̏ꍇ�֐��̈��֐��{�̂����
26*/
27//=============================================================================
28
29#include "mlisp.h"
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <ctype.h>
35#include <assert.h>
36
37#ifndef FALSE
38#define FALSE           (0)
39#define TRUE            (1)
40#endif
41
42#ifndef min
43#define min(a, b)                       ((a)<(b) ? (a) : (b))
44#endif
45#ifndef max
46#define max(a, b)                       ((a)>(b) ? (a) : (b))
47#endif
48
49/// define
50#define SEXP_BITS                       (sizeof(SExp) * 8)
51#define VAL_BITS                        (SEXP_BITS - TYPE_BITS)
52
53/// macros
54#define SEXP_VAL(a)                     ((a) >> TYPE_BITS)
55#define SEXP_UVAL(a)            ((unsigned int)(a) >> TYPE_BITS)
56
57/// constant value
58#define cFail                           MAKE_SEXP(tOther, -1)
59#define cDot                            MAKE_SEXP(tOther, -2)
60#define cUndef                          MAKE_SEXP(tOther, -3)
61
62// function type
63#define FuncTypeMask            (1<<0)
64#define FuncTypeMacro           (0<<0)                  // macro
65#define FuncTypeLambda          (1<<0)                  // lambda
66
67// function category
68#define FuncCategoryMask        (1<<1)
69#define FuncCategoryBuiltin     (0<<1)                  // builtin function (C)
70#define FuncCategoryCell        (1<<1)                  // user defined (cell)
71
72
73/// cons cell
74typedef struct {
75        SExp car;
76        SExp cdr;
77} Cell;
78
79/// builtin-function data
80typedef struct {
81        MLBuiltinFunc cfunc;
82} BuiltinFuncData;
83
84/// symbol
85typedef struct {
86        char str[32];
87        SExp sexp;
88} Symbol;
89
90
91//=============================================================================
92
93const char ERR_ILLEGAL_CHAR[] = "illegal char";
94const char ERR_STRING_NOT_TERMINATE[] = "sting not terminate";
95const char ERR_NO_CLOSE_PAREN[] = "no close paren";
96const char ERR_DOT_FIRST[] = "dot first";
97const char ERR_EMPTY_AFTER_DOT[] = "empty after dot";
98const char ERR_ILLEGAL_DOT_LIST[] = "illegal dot list";
99
100const char ERR_NOT_SYMBOL[] = "not symbol";
101const char ERR_CANT_CALL_FUNCTION[] = "cant' call function";
102const char ERR_UNDEFINED_SYMBOL[] = "undefined symbol";
103const char ERR_NOT_LAMBDA[] = "not lambda";
104
105
106//=============================================================================
107
108#define MAX_CELL                (1024)
109#define MAX_SYMBOL              (1024)
110#define MAX_STACK               (128)
111#define MAX_BUILTIN             (64)
112
113/// �R���e�L�X�g�̎��
114struct MLContext {
115        MLContext();
116        ~MLContext();
117
118        void set_flag(ML_FLAG flag, int atom);                  ///< �������O�ݒ�
119        void dump();                                                                    ///< ���o��
120
121        SExp read(FILE* fp);
122        SExp eval(SExp a);
123        void print(FILE* fp, SExp a, bool b_cell);
124        SExp apply(SExp ca, SExp cd, bool b_eval);
125
126        SExp cons(SExp a, SExp d);                                              ///< cons
127        SExp car(SExp a);                                                               ///< car
128        SExp cdr(SExp a);                                                               ///< cdr
129        void rplaca(SExp cs, SExp a);                                   ///< car �v�f�̒u��
130        void rplacd(SExp cs, SExp d);                                   ///< cdr �v�f�̒u��
131
132        void setq(SExp symb, SExp arg_body);
133
134        const char* get_symbol_string(SExp symb);
135
136        SExp resist_builtin(const char* word, MLBuiltinFunc cfunc, bool b_macro);
137        SExp create_lambda(SExp arg_body);
138        void defmacro(SExp symb, SExp arg_body);
139
140        void syntax_error(const char* msg);
141        void runtime_error(SExp a, const char* msg);
142
143private:
144        SExp read_string(FILE* fp);
145        SExp read_list(FILE* fp);
146        SExp read_rec(FILE* fp);
147        void print_rec(FILE* fp, SExp a);
148        void print_cell(FILE* fp, SExp a);
149
150        Cell* get_cell_ptr(SExp a);
151
152        SExp alloc_symbol();
153        Symbol* get_symbol_ptr(SExp a);
154        SExp find_symbol(const char* str, const char* end);
155        SExp make_symbol(const char* str, const char* end);
156
157        SExp eval_cell(SExp a);                                                 ///< �Z���������car �̊֐��Ɏc�������ČĂяo���j
158        SExp eval_list(SExp a);                                                 ///< list �̊e�v�f������Ă�����X�g�ɂ��ĕԂ�
159        void bind_arg1(SExp symb, SExp val);
160        void bind_arg(SExp arg, SExp param);                    ///< �֐��Ăяo�����́A���o�C���h
161        void unbind_arg(SExp arg);                                              ///< �o�C���h�����ϐ����
162        void push_sexp(SExp s);                                                 ///< �r����^�b�N�ɑޔ�SExp pop_sexp();                                                            ///< ���A
163
164private:
165        int flags[numofMLF];
166
167        Cell g_cell_buf[MAX_CELL];
168        int g_cell_free_p;
169
170        Symbol g_symbol_buf[MAX_SYMBOL];
171        int g_symbol_free_p;
172
173        SExp g_stack[MAX_STACK];
174        int g_stack_p;
175
176        BuiltinFuncData builtin_func_buf[MAX_BUILTIN];
177        int g_builtin_p;
178};
179
180
181//=============================================================================
182// helper functions
183
184SExp ml_int2sexp(int x)
185{
186        return (x << 1) | 1;
187}
188
189int ml_sexp2int(SExp a)
190{
191        assert(SEXP_IS_INT(a));
192        return a >> 1;
193}
194
195/// �\��
196static SExp reserved(const char* p, size_t n)
197{
198        struct {
199                const char* str;
200                SExp sexp;
201        } static tbl[] = {
202                {       "\x03nil",      cNil,   },
203                {       "\x01t",        cT,             },
204                {       "\x01.",        cDot,   },
205
206//              {       "quote",        cUndef, },
207        };
208        const int N = sizeof(tbl)/sizeof(*tbl);
209        for (int i=0; i<N; ++i) {
210                const char* s = tbl[i].str;
211                char l = *s++;
212                if (n == l && strncmp(p, s, n) == 0) {
213                        return tbl[i].sexp;
214                }
215        }
216        return cFail;
217}
218
219/// �󔒓ǂݔ��
220static int skip_space(FILE* fp)
221{
222        for (;;) {
223                int c = fgetc(fp);
224                if (c != ' ' && c != '\t') {
225                        return c;
226                }
227        }
228}
229
230/// ��œǂݔ��
231static void skip_line_comment(FILE* fp)
232{
233        for (;;) {
234                int c = fgetc(fp);
235                if (c == EOF || c == '\n')      break;
236        }
237}
238
239
240//=============================================================================
241
242MLContext::MLContext()
243{
244        memset(flags, 0x00, sizeof(flags));
245
246        g_cell_free_p = 0;
247        g_symbol_free_p = 0;
248        g_stack_p = 0;
249        g_builtin_p = 0;
250}
251
252MLContext::~MLContext()
253{
254}
255
256void MLContext::set_flag(ML_FLAG flag, int atom)
257{
258        flags[flag] = atom;
259}
260
261void MLContext::dump()
262{
263        printf("#cell:%d\n", g_cell_free_p);
264        printf("#symbol:%d\n", g_symbol_free_p);
265        for (int i=0; i<g_symbol_free_p; ++i) {
266                printf("%s,", g_symbol_buf[i].str);
267        }
268        printf("\n");
269}
270
271void MLContext::syntax_error(const char* msg)
272{
273        FILE* fp = stderr;
274        fprintf(fp, "syntax error:%s\n", msg != NULL ? msg : "??");
275}
276
277void MLContext::runtime_error(SExp a, const char* msg)
278{
279        FILE* fp = stderr;
280        fprintf(fp, "runtime error:%s", msg != NULL ? msg : "??");
281        if (a != cNil) {
282                fprintf(fp, " :");
283                print(fp, a, false);
284        } else {
285                fprintf(fp, "\n");
286        }
287}
288
289SExp MLContext::cons(SExp a, SExp d)
290{
291        assert(g_cell_free_p < MAX_CELL);
292        int idx = g_cell_free_p++;
293
294        Cell* p = &g_cell_buf[idx];
295        p->car = a;
296        p->cdr = d;
297
298        return MAKE_SEXP(tCell, idx);
299}
300
301Cell* MLContext::get_cell_ptr(SExp a)
302{
303        assert(SEXP_TYPE(a) == tCell || SEXP_TYPE(a) == tFunc);
304        return &g_cell_buf[SEXP_UVAL(a)];
305}
306
307SExp MLContext::car(SExp a)
308{
309        Cell* p = get_cell_ptr(a);
310        return p->car;
311}
312
313SExp MLContext::cdr(SExp a)
314{
315        Cell* p = get_cell_ptr(a);
316        return p->cdr;
317}
318
319void MLContext::rplaca(SExp cs, SExp a)
320{
321        Cell* p = get_cell_ptr(cs);
322        p->car = a;
323}
324
325void MLContext::rplacd(SExp cs, SExp d)
326{
327        Cell* p = get_cell_ptr(cs);
328        p->cdr = d;
329}
330
331void MLContext::setq(SExp symb, SExp a)
332{
333        if (SEXP_TYPE(symb) != tSymb) {
334                runtime_error(symb, ERR_NOT_SYMBOL);
335        } else {
336                Symbol* p = get_symbol_ptr(symb);
337                p->sexp = a;
338        }
339}
340
341const char* MLContext::get_symbol_string(SExp symb)
342{
343        const char* str = NULL;
344        if (SEXP_TYPE(symb) == tSymb) {
345                str = get_symbol_ptr(symb)->str;
346        }
347        return str;
348}
349
350SExp MLContext::alloc_symbol()
351{
352        assert(g_symbol_free_p < MAX_SYMBOL);
353        int idx = g_symbol_free_p++;
354        return MAKE_SEXP(tSymb, idx);
355}
356
357Symbol* MLContext::get_symbol_ptr(SExp a)
358{
359        assert(SEXP_TYPE(a) == tSymb);
360        return &g_symbol_buf[SEXP_UVAL(a)];
361}
362
363SExp MLContext::find_symbol(const char* str, const char* end)
364{
365        int len;
366        if (end == NULL) {
367                len = strlen(str);
368        } else {
369                len = end - str;
370        }
371
372        // @todo�F�������Ă��ƌ��Ȃ��ɂ���  for (int i=0; i<g_symbol_free_p; ++i) {
373                Symbol* p = &g_symbol_buf[i];
374                int l = strlen(p->str);
375                if (l == len && strncmp(str, p->str, l) == 0) {
376                        return MAKE_SEXP(tSymb, i);
377                }
378        }
379        return cFail;
380}
381
382SExp MLContext::make_symbol(const char* str, const char* end)
383{
384        SExp a;
385        a = find_symbol(str, end);
386        if (a == cFail) {
387                a = alloc_symbol();
388                Symbol* p = get_symbol_ptr(a);
389                p->sexp = cUndef;
390                if (end == NULL) {
391                        strncpy(p->str, str, sizeof(p->str)-1);
392                } else {
393                        const int MAX = sizeof(p->str)-1;
394                        int len = end - str;
395                        len = min(len, MAX);
396                        strncpy(p->str, str, len);
397                        p->str[len] = '\0';
398                }
399        }
400        return a;
401}
402
403SExp MLContext::resist_builtin(const char* word, MLBuiltinFunc cfunc, bool b_macro)
404{
405        assert(g_builtin_p < MAX_BUILTIN);
406        int idx = g_builtin_p++;
407        BuiltinFuncData* p = &builtin_func_buf[idx];
408        p->cfunc = cfunc;
409
410        int info;
411        if (b_macro)    info = FuncTypeMacro;
412        else                    info = FuncTypeLambda;
413        info |= FuncCategoryBuiltin;
414        SExp cell = cons(ml_int2sexp(info), ml_int2sexp(idx));
415        SExp fn = MAKE_SEXP(tFunc, SEXP_UVAL(cell));
416
417        SExp symb = make_symbol(word, NULL);
418        setq(symb, fn);
419        return symb;
420}
421
422SExp MLContext::create_lambda(SExp arg_body)
423{
424        int info = FuncTypeLambda | FuncCategoryCell;
425        SExp fn = cons(ml_int2sexp(info), arg_body);
426        return MAKE_SEXP(tFunc, SEXP_UVAL(fn));
427}
428
429void MLContext::defmacro(SExp symb, SExp arg_body)
430{
431        int info = FuncTypeMacro | FuncCategoryCell;
432        SExp fn = cons(ml_int2sexp(info), arg_body);
433        setq(symb, MAKE_SEXP(tFunc, SEXP_UVAL(fn)));
434}
435
436SExp MLContext::read_string(FILE* fp)
437{
438        char str[256];
439        int c;
440        char* q = str;
441        for (; c = fgetc(fp), c != '"'; ) {
442                if (c == EOF) {
443                        syntax_error(ERR_STRING_NOT_TERMINATE);
444                        break;
445                }
446                if (c == '\\') {
447                        c = fgetc(fp);
448                        switch (c) {
449                        default:        break;
450                        case 't':       c = '\t';       break;
451                        case 'n':       c = '\n';       break;
452                        case '0':       c = '\0';       break;
453                        }
454                }
455                *q++ = c;
456        }
457        assert(q - str < sizeof(str));
458        *q = '\0';
459
460        SExp a = make_symbol(str, q);
461        return cons(find_symbol("quote", NULL), cons(a, cNil));
462}
463
464SExp MLContext::read_list(FILE* fp)
465{
466        SExp a;
467        SExp top = cNil, tail = cNil;
468        for (;;) {
469                a = read_rec(fp);
470                if (a == cFail || a == cEOF)    return top;
471                if (a == cNL)   continue;
472                if (a == cDot)  break;
473
474                SExp cd = cons(a, cNil);
475                if (top == cNil) {
476                        top = cd;
477                } else {
478                        rplacd(tail, cd);
479                }
480                tail = cd;
481        }
482
483        // dot appear
484        do {
485                a = read_rec(fp);
486        } while (a == cNL);
487        if (a == cFail || a == cEOF) {
488                // ERR: (x .)
489                syntax_error(ERR_EMPTY_AFTER_DOT);
490        } else {
491                bool err = false;
492                if (top == cNil) {
493                        // ERR: (. x)
494                        syntax_error(ERR_DOT_FIRST);
495                        err = true;
496                } else {
497                        rplacd(tail, a);
498                }
499
500                bool err2 = false;
501                for (; a=read_rec(fp), a != cFail && a != cEOF; ) {
502                        if (a != cNL)   err2 = true;
503                }
504                if (err2 && !err) {
505                        // ERR: (x . y z)
506                        syntax_error(ERR_ILLEGAL_DOT_LIST);
507                }
508        }
509
510        return top;
511}
512
513SExp MLContext::read_rec(FILE* fp)
514{
515        int c;
516
517        for (;;) {
518                c = skip_space(fp);
519                if (c == EOF)   return cEOF;
520                if (c == '\n')  return cNL;
521
522                if (c == ';') {
523                        skip_line_comment(fp);
524                        continue;
525                }
526                break;
527        }
528
529        if (c == '(') {
530                SExp a = read_list(fp);
531
532                // close paren
533                int c = fgetc(fp);
534                if (c != ')') {
535                        ungetc(c, fp);
536                        syntax_error(ERR_NO_CLOSE_PAREN);
537                }
538
539                return a;
540        }
541        if (c == '\'') {
542                SExp a = read_rec(fp);
543                return cons(make_symbol("quote", NULL), cons(a, cNil));
544        }
545        if (c == '"') {
546                return read_string(fp);
547        }
548
549        {
550                char symb[256];
551                char* q = symb;
552                // search delimiter
553                int bDigit = TRUE;
554                for (; c != EOF && strchr(" \t\n()'@,", c) == NULL; *q++ = c, c = fgetc(fp)) {
555                        if (!isdigit(c))        bDigit = FALSE;
556                }
557                assert(q - symb < sizeof(symb));
558                ungetc(c, fp);
559                *q = '\0';
560                if (q == symb) {
561                        return cFail;
562                } else if (bDigit) {
563                        int x = atoi(symb);
564                        return ml_int2sexp(x);
565                } else {
566                        SExp a = reserved(symb, q-symb);
567                        if (a == cFail) {
568                                a = make_symbol(symb, q);
569                        }
570                        return a;
571                }
572        }
573}
574
575SExp MLContext::read(FILE* fp)
576{
577        SExp s = read_rec(fp);
578        if (s == cFail) {
579                int c = fgetc(fp);
580                syntax_error(ERR_ILLEGAL_CHAR);
581        }
582        return s;
583}
584
585SExp MLContext::eval(SExp a)
586{
587        if (SEXP_IS_INT(a)) {
588                return a;
589        }
590
591        switch (SEXP_TYPE(a)) {
592        default:        assert(false);  return cNil;
593        case tCell:
594                {
595                        SExp ca = car(a);
596                        SExp cd = cdr(a);
597                        return apply(ca, cd, true);
598                }
599                break;
600        case tOther:
601        case tFunc:
602                return a;
603        case tSymb:
604                {
605                        Symbol* p = get_symbol_ptr(a);
606                        SExp s = p->sexp;
607                        if (s == cUndef) {
608                                runtime_error(a, ERR_UNDEFINED_SYMBOL);
609                                return cNil;
610                        }
611                        return s;
612                }
613                break;
614        }
615}
616
617SExp MLContext::apply(SExp ca, SExp cd, bool b_eval)
618{
619        SExp fn = eval(ca);
620
621        if (SEXP_TYPE(fn) != tFunc) {
622                runtime_error(ca, ERR_CANT_CALL_FUNCTION);
623                return cNil;
624        }
625
626
627        // apply
628
629        SExp param = cd;
630
631        int info = ml_sexp2int(car(fn));
632        int type = info & FuncTypeMask;
633        int category = info & FuncCategoryMask;
634
635        if (type == FuncTypeLambda && b_eval) {
636                param = eval_list(param);
637        }
638
639        switch (category) {
640        default:        assert(false);  return cNil;
641        case FuncCategoryBuiltin:
642                {
643                        int idx = ml_sexp2int(cdr(fn));
644                        BuiltinFuncData* p = &builtin_func_buf[idx];
645                        return p->cfunc(this, param);
646                }
647                break;
648        case FuncCategoryCell:
649                {
650                        SExp cd = cdr(fn);
651                        SExp arg = car(cd);
652                        SExp body = car(cdr(cd));
653
654                        if (flags[MLF_PRINT_FUNC_ARG]) {
655                                print(stdout, param, false);
656                        }
657                        bind_arg(arg, param);
658
659                        if (type == FuncTypeMacro) {
660                                SExp replace = eval(body);
661                                if (flags[MLF_PRINT_MACRO_REPLACE]) {
662                                        print(stdout, replace, false);
663                                }
664                                body = replace;
665                        }
666
667                        SExp res = eval(body);
668
669                        unbind_arg(arg);
670
671                        return res;
672                }
673                break;
674        }
675}
676
677SExp MLContext::eval_list(SExp a)
678{
679        SExp top = cNil, tail = cNil;
680        SExp p;
681        for (p=a; SEXP_CONSP(p); p=cdr(p)) {
682                SExp ca = car(p);
683                SExp cd = cons(eval(ca), cNil);
684                if (top == cNil) {
685                        top = cd;
686                } else {
687                        rplacd(tail, cd);
688                }
689                tail = cd;
690        }
691        if (p != cNil) {
692                rplacd(tail, eval(p));
693        }
694        return top;
695}
696
697void MLContext::push_sexp(SExp s)
698{
699        assert(g_stack_p < MAX_STACK);
700        g_stack[g_stack_p++] = s;
701}
702
703SExp MLContext::pop_sexp()
704{
705        assert(g_stack_p > 0);
706        return g_stack[--g_stack_p];
707}
708
709void MLContext::bind_arg1(SExp symb, SExp val)
710{
711        Symbol* p = get_symbol_ptr(symb);
712        push_sexp(p->sexp);
713
714        p->sexp = val;
715
716        if (flags[MLF_PRINT_FUNC_ARG]) {
717                printf("bind ");
718                print_rec(stdout, symb);
719                printf(":");
720                print(stdout, val, false);
721        }
722}
723
724void MLContext::bind_arg(SExp arg, SExp param)
725{
726        for (; SEXP_CONSP(arg); arg = cdr(arg)) {
727                SExp symb = car(arg);
728                if (symb == cNil)       continue;
729
730                SExp nxt = cNil;
731                SExp val = param;
732                if (SEXP_CONSP(param)) {
733                        val = car(param);
734                        nxt = cdr(param);
735                }
736                bind_arg1(symb, val);
737
738                param = nxt;
739        }
740
741        if (arg != cNil) {
742                bind_arg1(arg, param);
743        }
744}
745
746void MLContext::unbind_arg(SExp arg)
747{
748        SExp a;
749        if (SEXP_TYPE(arg) == tCell) {
750                unbind_arg(cdr(arg));
751                a = car(arg);
752        } else {
753                a = arg;
754        }
755
756        if (SEXP_TYPE(a) == tSymb) {
757                Symbol* p = get_symbol_ptr(a);
758                p->sexp = pop_sexp();
759        }
760}
761
762void MLContext::print_rec(FILE* fp, SExp a)
763{
764        if (SEXP_IS_INT(a)) {
765                fprintf(fp, "%d", ml_sexp2int(a));
766                return;
767        }
768
769        switch (SEXP_TYPE(a)) {
770        default:        assert(false);  break;
771        case tOther:
772                switch (a) {
773                default:        /*assert(false);*/      break;
774                case cNil:      fprintf(fp, "nil");     break;
775                case cT:        fprintf(fp, "t");       break;
776                }
777                break;
778        case tSymb:
779                {
780                        Symbol* p = get_symbol_ptr(a);
781                        fprintf(fp, "%s", p->str);
782                }
783                break;
784        case tCell:
785                fprintf(fp, "(");
786                print_cell(fp, a);
787                fprintf(fp, ")");
788                break;
789        case tFunc:
790                fprintf(fp, "#<lambda>");
791                break;
792        }
793}
794
795void MLContext::print_cell(FILE* fp, SExp a)
796{
797        for (int idx=0; a != cNil; ++idx) {
798                if (idx != 0)   fprintf(fp, " ");
799
800                SExp ca;
801                if (SEXP_TYPE(a) != tCell) {
802                        fprintf(fp, ". ");
803                        ca = a;
804                        a = cNil;
805                } else {
806                        Cell* p = get_cell_ptr(a);
807                        ca = p->car;
808                        a = p->cdr;
809                }
810                print_rec(fp, ca);
811        }
812}
813
814void MLContext::print(FILE* fp, SExp a, bool b_cell)
815{
816        if (!b_cell) {
817                print_rec(fp, a);
818        } else {
819                print_cell(fp, a);
820        }
821        printf("\n");
822}
823
824
825//=============================================================================
826
827MLContext* ml_new(void)                                                                                         { return new MLContext; }
828void ml_delete(MLContext* ml)                                                                           { delete ml; }
829
830void ml_set_flag(MLContext* ml, ML_FLAG flag, int atom)                         { return ml->set_flag(flag, atom); }
831
832void ml_dump(MLContext* ml)                                                                                     { ml->dump(); }
833
834
835SExp ml_read(MLContext* ml, FILE* fp)                                                           { return ml->read(fp); }
836SExp ml_eval(MLContext* ml, SExp a)                                                                     { return ml->eval(a); }
837void ml_print(MLContext* ml, FILE* fp, SExp a, int b_cell)                      { ml->print(fp, a, b_cell != FALSE); }
838SExp ml_apply(MLContext* ml, SExp ca, SExp cd)                                          { return ml->apply(ca, cd, false); }
839
840SExp ml_resist_builtin(MLContext* ml, const char* word, MLBuiltinFunc cfunc, int b_macro)               { return ml->resist_builtin(word, cfunc, b_macro != FALSE); }
841SExp ml_create_lambda(MLContext* ml, SExp arg_body)     { return ml->create_lambda(arg_body); }
842void ml_defmacro(MLContext* ml, SExp symb, SExp arg_body)                       { ml->defmacro(symb, arg_body); }
843
844void ml_runtime_error(MLContext* ml, SExp a, const char* msg)           { ml->runtime_error(a, msg); }
845
846
847SExp ml_cons(MLContext* ml, SExp a, SExp d)                                                     { return ml->cons(a, d); }
848SExp ml_car(MLContext* ml, SExp a)                                                                      { return ml->car(a); }
849SExp ml_cdr(MLContext* ml, SExp a)                                                                      { return ml->cdr(a); }
850void ml_rplacd(MLContext* ml, SExp a, SExp d)                                           { ml->rplacd(a, d); }
851
852void ml_setq(MLContext* ml, SExp symb, SExp arg_body)                           { ml->setq(symb, arg_body); }
853
854const char* ml_get_symbol_string(MLContext* ml, SExp symb)                      { return ml->get_symbol_string(symb); }
855
Note: See TracBrowser for help on using the browser.