main.c 6.01 KB
Newer Older
1
2
3
4
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
Markus Siemens's avatar
Markus Siemens committed
5

6
7
8
9
10
11
12
13
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "qstr.h"
#include "lexer.h"
#include "lexerunix.h"
#include "parse.h"
#include "obj.h"
14
#include "parsehelper.h"
15
16
17
18
#include "compile.h"
#include "runtime0.h"
#include "runtime.h"
#include "repl.h"
19
#include "build/py/py-version.h"
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#if MICROPY_USE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif

extern const mp_obj_fun_native_t mp_builtin_open_obj;
void file_init();

static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
    if (lex == NULL) {
        return;
    }

    if (0) {
        // just tokenise
        while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) {
            mp_token_show(mp_lexer_cur(lex));
            mp_lexer_to_next(lex);
        }
        mp_lexer_free(lex);
        return;
    }

44
45
    mp_parse_error_kind_t parse_error_kind;
    mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind);
46
47
48

    if (pn == MP_PARSE_NODE_NULL) {
        // parse error
49
        mp_parse_show_exception(lex, parse_error_kind);
50
51
52
53
54
55
56
57
58
59
60
61
62
        mp_lexer_free(lex);
        return;
    }

    qstr source_name = mp_lexer_source_name(lex);
    mp_lexer_free(lex);

    /*
    printf("----------------\n");
    mp_parse_node_print(pn, 0);
    printf("----------------\n");
    */

63
    mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, is_repl);
64
65
66
67
68
69
70
71
72

    if (module_fun == mp_const_none) {
        // compile error
        return;
    }

    // execute it
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
Damien George's avatar
Damien George committed
73
        mp_call_function_0(module_fun);
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
        nlr_pop();
    } else {
        // uncaught exception
        mp_obj_print_exception((mp_obj_t)nlr.ret_val);
    }
}

static char *str_join(const char *s1, int sep_char, const char *s2) {
    int l1 = strlen(s1);
    int l2 = strlen(s2);
    char *s = m_new(char, l1 + l2 + 2);
    memcpy(s, s1, l1);
    if (sep_char != 0) {
        s[l1] = sep_char;
        l1 += 1;
    }
    memcpy(s + l1, s2, l2);
    s[l1 + l2] = 0;
    return s;
}

static char *prompt(char *p) {
#if MICROPY_USE_READLINE
    char *line = readline(p);
    if (line) {
        add_history(line);
    }
#else
    static char buf[256];
    fputs(p, stdout);
    char *s = fgets(buf, sizeof(buf), stdin);
    if (!s) {
        return NULL;
    }
    int l = strlen(buf);
    if (buf[l - 1] == '\n') {
        buf[l - 1] = 0;
    } else {
        l++;
    }
    char *line = malloc(l);
    memcpy(line, buf, l);
#endif
    return line;
}

static void do_repl(void) {
121
122
    printf("Micro Python build " MICROPY_GIT_HASH " on " MICROPY_BUILD_DATE "; Windows version\n");

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    for (;;) {
        char *line = prompt(">>> ");
        if (line == NULL) {
            // EOF
            return;
        }
        if (mp_repl_is_compound_stmt(line)) {
            for (;;) {
                char *line2 = prompt("... ");
                if (line2 == NULL || strlen(line2) == 0) {
                    break;
                }
                char *line3 = str_join(line, '\n', line2);
                free(line);
                free(line2);
                line = line3;
            }
        }

        mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false);
        execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, true);
        free(line);
    }
}

static void do_file(const char *file) {
    // hack: set dir for import based on where this file is
    {
        const char * s = strrchr(file, '\\');
        if (s != NULL) {
            int len = s - file;
            char *dir = m_new(char, len + 1);
            memcpy(dir, file, len);
            dir[len] = '\0';
            mp_import_set_directory(dir);
        }
    }

    mp_lexer_t *lex = mp_lexer_new_from_file(file);
    execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false);
}

static void do_str(const char *str) {
    mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, str, strlen(str), false);
    execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false);
}

int usage(void) {
    printf("usage: py [-c <command>] [<filename>]\n");
    return 1;
}

mp_obj_t mem_info(void) {
    printf("mem: total=%d, current=%d, peak=%d\n", m_get_total_bytes_allocated(), m_get_current_bytes_allocated(), m_get_peak_bytes_allocated());
    return mp_const_none;
}

mp_obj_t qstr_info(void) {
    uint n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
    qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
    printf("qstr pool: n_pool=%u, n_qstr=%u, n_str_data_bytes=%u, n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
    return mp_const_none;
}

int main(int argc, char **argv) {
    qstr_init();
Damien George's avatar
Damien George committed
189
    mp_init();
190
191
192

    mp_obj_t m_sys = mp_obj_new_module(MP_QSTR_sys);
    mp_obj_t py_argv = mp_obj_new_list(0, NULL);
Damien George's avatar
Damien George committed
193
    mp_store_attr(m_sys, MP_QSTR_argv, py_argv);
194

Damien George's avatar
Damien George committed
195
196
    mp_store_name(qstr_from_str("mem_info"), mp_make_function_n(0, mem_info));
    mp_store_name(qstr_from_str("qstr_info"), mp_make_function_n(0, qstr_info));
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222

    file_init();

    /*
    printf("bytes:\n");
    printf("    total %d\n", m_get_total_bytes_allocated());
    printf("    cur   %d\n", m_get_current_bytes_allocated());
    printf("    peak  %d\n", m_get_peak_bytes_allocated());
    */

    if (argc == 1) {
        do_repl();
    } else {
        for (int a = 1; a < argc; a++) {
            if (argv[a][0] == '-') {
                if (strcmp(argv[a], "-c") == 0) {
                    if (a + 1 >= argc) {
                        return usage();
                    }
                    do_str(argv[a + 1]);
                    a += 1;
                } else {
                    return usage();
                }
            } else {
                for (int i = a; i < argc; i++) {
223
                    mp_obj_list_append(py_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
224
225
226
227
228
229
230
                }
                do_file(argv[a]);
                break;
            }
        }
    }

Damien George's avatar
Damien George committed
231
    mp_deinit();
232
233
234
235

    //printf("total bytes = %d\n", m_get_total_bytes_allocated());
    return 0;
}