blob: f7b06d4f8343c8c0a74ee0ada07d154aa2ce55cc [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 }
Damienfa2162b2013-10-20 17:42:00 +010071
Damiena5185f42013-10-20 14:41:27 +010072 py_lexer_t *lex = py_lexer_new_from_str_len("<stdin>", line, strlen(line), false);
Damien5ac1b2e2013-10-18 19:58:12 +010073 py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT);
Damienfa2162b2013-10-20 17:42:00 +010074 py_lexer_free(lex);
75
Damien5ac1b2e2013-10-18 19:58:12 +010076 if (pn != PY_PARSE_NODE_NULL) {
77 //py_parse_node_show(pn, 0);
78 bool comp_ok = py_compile(pn, true);
79 if (comp_ok) {
80 py_obj_t module_fun = rt_make_function_from_id(1);
81 if (module_fun != py_const_none) {
82 nlr_buf_t nlr;
83 if (nlr_push(&nlr) == 0) {
84 rt_call_function_0(module_fun);
85 nlr_pop();
86 } else {
87 // uncaught exception
88 py_obj_print((py_obj_t)nlr.ret_val);
89 printf("\n");
90 }
91 }
92 }
93 }
94 }
95}
96
97void do_file(const char *file) {
Damiena5185f42013-10-20 14:41:27 +010098 py_lexer_t *lex = py_lexer_new_from_file(file);
Damien429d7192013-10-04 19:53:11 +010099 //const char *pysrc = "def f():\n x=x+1\n print(42)\n";
100 //py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false);
101 if (lex == NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +0100102 return;
Damien429d7192013-10-04 19:53:11 +0100103 }
104
105 if (0) {
Damien5ac1b2e2013-10-18 19:58:12 +0100106 // just tokenise
Damien429d7192013-10-04 19:53:11 +0100107 while (!py_lexer_is_kind(lex, PY_TOKEN_END)) {
108 py_token_show(py_lexer_cur(lex));
109 py_lexer_to_next(lex);
110 }
Damien5ac1b2e2013-10-18 19:58:12 +0100111 py_lexer_free(lex);
112
Damien429d7192013-10-04 19:53:11 +0100113 } else {
Damien5ac1b2e2013-10-18 19:58:12 +0100114 // compile
115
116 py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT);
Damienfa2162b2013-10-20 17:42:00 +0100117 py_lexer_free(lex);
118
Damien91d387d2013-10-09 15:09:52 +0100119 if (pn != PY_PARSE_NODE_NULL) {
120 //printf("----------------\n");
Damiena3977762013-10-09 23:10:10 +0100121 //parse_node_show(pn, 0);
Damien91d387d2013-10-09 15:09:52 +0100122 //printf("----------------\n");
Damien5ac1b2e2013-10-18 19:58:12 +0100123 bool comp_ok = py_compile(pn, false);
Damien91d387d2013-10-09 15:09:52 +0100124 //printf("----------------\n");
Damien429d7192013-10-04 19:53:11 +0100125
Damiena5185f42013-10-20 14:41:27 +0100126#if MICROPY_EMIT_CPYTHON
127 if (!comp_ok) {
128 printf("compile error\n");
129 }
130#else
Damien5ac1b2e2013-10-18 19:58:12 +0100131 if (1 && comp_ok) {
132 // execute it
133 py_obj_t module_fun = rt_make_function_from_id(1);
134 if (module_fun != py_const_none) {
135 nlr_buf_t nlr;
136 if (nlr_push(&nlr) == 0) {
137 py_obj_t ret = rt_call_function_0(module_fun);
138 printf("done! got: ");
139 py_obj_print(ret);
140 printf("\n");
141 nlr_pop();
142 } else {
143 // uncaught exception
144 printf("exception: ");
145 py_obj_print((py_obj_t)nlr.ret_val);
146 printf("\n");
147 }
148 }
Damience89a212013-10-15 22:25:17 +0100149 }
Damien5ac1b2e2013-10-18 19:58:12 +0100150#endif
Damien429d7192013-10-04 19:53:11 +0100151 }
152 }
Damien5ac1b2e2013-10-18 19:58:12 +0100153}
Damien429d7192013-10-04 19:53:11 +0100154
Damien5ac1b2e2013-10-18 19:58:12 +0100155int main(int argc, char **argv) {
156 qstr_init();
157 rt_init();
158
159 if (argc == 1) {
160 do_repl();
161 } else if (argc == 2) {
162 do_file(argv[1]);
163 } else {
164 printf("usage: py [<file>]\n");
165 return 1;
166 }
Damien429d7192013-10-04 19:53:11 +0100167 rt_deinit();
168
169 //printf("total bytes = %d\n", m_get_total_bytes_allocated());
170 return 0;
171}