blob: e3999db68bbcac6c0505171a52252c4c9c3a72e1 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <stdint.h>
2#include <stdio.h>
3#include <string.h>
4
Damience89a212013-10-15 22:25:17 +01005#include "nlr.h"
Damien429d7192013-10-04 19:53:11 +01006#include "misc.h"
Damienc025ebb2013-10-12 14:30:21 +01007#include "mpyconfig.h"
Damien429d7192013-10-04 19:53:11 +01008#include "lexer.h"
Damiena5185f42013-10-20 14:41:27 +01009#include "lexerunix.h"
Damien429d7192013-10-04 19:53:11 +010010#include "parse.h"
11#include "compile.h"
12#include "runtime.h"
13
Damien5ac1b2e2013-10-18 19:58:12 +010014#include <readline/readline.h>
Damien429d7192013-10-04 19:53:11 +010015
Damien5ac1b2e2013-10-18 19:58:12 +010016bool str_startswith_word(const char *str, const char *head) {
17 int i;
18 for (i = 0; str[i] && head[i]; i++) {
19 if (str[i] != head[i]) {
20 return false;
21 }
Damien429d7192013-10-04 19:53:11 +010022 }
Damien5ac1b2e2013-10-18 19:58:12 +010023 return head[i] == '\0' && (str[i] == '\0' || !g_unichar_isalpha(str[i]));
24}
25
26bool is_compound_stmt(const char *line) {
27 // TODO also "compound" if unmatched open bracket
28 return
29 str_startswith_word(line, "if")
30 || str_startswith_word(line, "while")
31 || str_startswith_word(line, "for")
32 || str_startswith_word(line, "true")
33 || str_startswith_word(line, "with")
34 || str_startswith_word(line, "def")
35 || str_startswith_word(line, "class")
36 || str_startswith_word(line, "@");
37}
38
39char *str_join(const char *s1, int sep_char, const char *s2) {
40 int l1 = strlen(s1);
41 int l2 = strlen(s2);
42 char *s = m_new(char, l1 + l2 + 2);
43 memcpy(s, s1, l1);
44 if (sep_char != 0) {
45 s[l1] = sep_char;
46 l1 += 1;
47 }
48 memcpy(s + l1, s2, l2);
49 return s;
50}
51
52void do_repl() {
53 for (;;) {
54 char *line = readline(">>> ");
55 if (line == NULL) {
56 // EOF
57 return;
58 }
59 if (is_compound_stmt(line)) {
60 for (;;) {
61 char *line2 = readline("... ");
62 if (line2 == NULL || strlen(line2) == 0) {
63 break;
64 }
65 char *line3 = str_join(line, '\n', line2);
66 m_free(line);
67 m_free(line2);
68 line = line3;
69 }
70 }
Damiena5185f42013-10-20 14:41:27 +010071 py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", line, strlen(line), false);
Damien5ac1b2e2013-10-18 19:58:12 +010072 py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT);
73 if (pn != PY_PARSE_NODE_NULL) {
74 //py_parse_node_show(pn, 0);
75 bool comp_ok = py_compile(pn, true);
76 if (comp_ok) {
77 py_obj_t module_fun = rt_make_function_from_id(1);
78 if (module_fun != py_const_none) {
79 nlr_buf_t nlr;
80 if (nlr_push(&nlr) == 0) {
81 rt_call_function_0(module_fun);
82 nlr_pop();
83 } else {
84 // uncaught exception
85 py_obj_print((py_obj_t)nlr.ret_val);
86 printf("\n");
87 }
88 }
89 }
90 }
91 }
92}
93
94void do_file(const char *file) {
Damiena5185f42013-10-20 14:41:27 +010095 py_lexer_t *lex = py_lexer_new_from_file(file);
Damien429d7192013-10-04 19:53:11 +010096 //const char *pysrc = "def f():\n x=x+1\n print(42)\n";
97 //py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false);
98 if (lex == NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +010099 return;
Damien429d7192013-10-04 19:53:11 +0100100 }
101
102 if (0) {
Damien5ac1b2e2013-10-18 19:58:12 +0100103 // just tokenise
Damien429d7192013-10-04 19:53:11 +0100104 while (!py_lexer_is_kind(lex, PY_TOKEN_END)) {
105 py_token_show(py_lexer_cur(lex));
106 py_lexer_to_next(lex);
107 }
Damien5ac1b2e2013-10-18 19:58:12 +0100108 py_lexer_free(lex);
109
Damien429d7192013-10-04 19:53:11 +0100110 } else {
Damien5ac1b2e2013-10-18 19:58:12 +0100111 // compile
112
113 py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT);
Damien91d387d2013-10-09 15:09:52 +0100114 if (pn != PY_PARSE_NODE_NULL) {
115 //printf("----------------\n");
Damiena3977762013-10-09 23:10:10 +0100116 //parse_node_show(pn, 0);
Damien91d387d2013-10-09 15:09:52 +0100117 //printf("----------------\n");
Damien5ac1b2e2013-10-18 19:58:12 +0100118 bool comp_ok = py_compile(pn, false);
Damien91d387d2013-10-09 15:09:52 +0100119 //printf("----------------\n");
Damien429d7192013-10-04 19:53:11 +0100120
Damien5ac1b2e2013-10-18 19:58:12 +0100121 py_lexer_free(lex);
Damien429d7192013-10-04 19:53:11 +0100122
Damiena5185f42013-10-20 14:41:27 +0100123#if MICROPY_EMIT_CPYTHON
124 if (!comp_ok) {
125 printf("compile error\n");
126 }
127#else
Damien5ac1b2e2013-10-18 19:58:12 +0100128 if (1 && comp_ok) {
129 // execute it
130 py_obj_t module_fun = rt_make_function_from_id(1);
131 if (module_fun != py_const_none) {
132 nlr_buf_t nlr;
133 if (nlr_push(&nlr) == 0) {
134 py_obj_t ret = rt_call_function_0(module_fun);
135 printf("done! got: ");
136 py_obj_print(ret);
137 printf("\n");
138 nlr_pop();
139 } else {
140 // uncaught exception
141 printf("exception: ");
142 py_obj_print((py_obj_t)nlr.ret_val);
143 printf("\n");
144 }
145 }
Damience89a212013-10-15 22:25:17 +0100146 }
Damien5ac1b2e2013-10-18 19:58:12 +0100147#endif
Damien429d7192013-10-04 19:53:11 +0100148 }
149 }
Damien5ac1b2e2013-10-18 19:58:12 +0100150}
Damien429d7192013-10-04 19:53:11 +0100151
Damien5ac1b2e2013-10-18 19:58:12 +0100152int main(int argc, char **argv) {
153 qstr_init();
154 rt_init();
155
156 if (argc == 1) {
157 do_repl();
158 } else if (argc == 2) {
159 do_file(argv[1]);
160 } else {
161 printf("usage: py [<file>]\n");
162 return 1;
163 }
Damien429d7192013-10-04 19:53:11 +0100164 rt_deinit();
165
166 //printf("total bytes = %d\n", m_get_total_bytes_allocated());
167 return 0;
168}