aboutsummaryrefslogtreecommitdiff
path: root/main.c
blob: 1911873eef036351682fd4772ee9f0a7407211af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include "interp.h"
#include "parser.h"
#include "sexp.h"

int main(int argc, char **argv) {
    int mainret = 0;
    Interp interp;
    Interp_init(&interp);
    if (argc > 2) {
        fprintf(stderr, "Usage: bamboo-lisp [file.lisp]\n");
        return -1;
    }
    if (argc == 2) {
        const char *filename = argv[1];
        SExpRef ret = Interp_load_file(&interp, filename);
        if (Interp_ref(&interp, ret)->type == kErrSignal) {
            fprintf(stderr, "Error: %s", Interp_ref(&interp, ret)->str);
            const char *stacktrace = lisp_stacktrace_to_string(&interp, interp.stacktrace);
            fprintf(stderr, "%s", stacktrace);
            free((void*)stacktrace);
            interp.stacktrace = interp.nil;
            mainret = -1; goto end;
        }
        if (Interp_ref(&interp, ret)->type == kExceptionSignal) {
            const char *exception_str = lisp_to_string(&interp, Interp_ref(&interp, ret)->ret);
            fprintf(stderr, "Uncatched exception: %s\n", exception_str);
            free((void*)exception_str);
            const char *stacktrace = lisp_stacktrace_to_string(&interp, interp.stacktrace);
            fprintf(stderr, "%s", stacktrace);
            free((void*)stacktrace);
            interp.stacktrace = interp.nil;
            mainret = -1; goto end;
        }
    }
#ifdef WITHREADLINE
    Parser_set_readline(interp.parser);
#else
    Parser_set_file(interp.parser, stdin);
#endif
    SExpRef sexp, res;
    ParseResult parse_result;
    while (1) {
#ifndef WITHREADLINE
        printf(">>> ");
        fflush(stdout);
#endif
        parse_result = parse_sexp(interp.parser);
        if (parse_result.errmsg != NULL) {
            if (Parser_peek(interp.parser) == EOF) goto end;
            fprintf(stderr, "Parsing error: %s", parse_result.errmsg);
#ifdef WITHREADLINE
            free((void*)interp.parser->string);
            Parser_set_readline(interp.parser);
#endif
            continue;
        }

        res = lisp_eval(&interp, parse_result.val, false);
        if (Interp_ref(&interp, res)->type == kErrSignal) {
            fprintf(stderr, "Eval error: %s", Interp_ref(&interp, res)->str);
            continue;
        }
        if (Interp_ref(&interp, res)->type == kBreakSignal
                || Interp_ref(&interp, res)->type == kContinueSignal
                || Interp_ref(&interp, res)->type == kReturnSignal) {
            fprintf(stderr, "Eval error: unexpected control flow signal.\n");
            continue;
        }
        lisp_print(&interp, res, stdout);
    }
end:
    Interp_free(&interp);
    return mainret;
}