blob: 018e1a9704f12b5561c741e0e21f14ddf6b4d652 [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"
Damien429d7192013-10-04 19:53:11 +01009#include "parse.h"
10#include "compile.h"
11#include "runtime.h"
12
Damien5ac1b2e2013-10-18 19:58:12 +010013#include <readline/readline.h>
Damien429d7192013-10-04 19:53:11 +010014
Damien5ac1b2e2013-10-18 19:58:12 +010015bool str_startswith_word(const char *str, const char *head) {
16 int i;
17 for (i = 0; str[i] && head[i]; i++) {
18 if (str[i] != head[i]) {
19 return false;
20 }
Damien429d7192013-10-04 19:53:11 +010021 }
Damien5ac1b2e2013-10-18 19:58:12 +010022 return head[i] == '\0' && (str[i] == '\0' || !g_unichar_isalpha(str[i]));
23}
24
25bool is_compound_stmt(const char *line) {
26 // TODO also "compound" if unmatched open bracket
27 return
28 str_startswith_word(line, "if")
29 || str_startswith_word(line, "while")
30 || str_startswith_word(line, "for")
31 || str_startswith_word(line, "true")
32 || str_startswith_word(line, "with")
33 || str_startswith_word(line, "def")
34 || str_startswith_word(line, "class")
35 || str_startswith_word(line, "@");
36}
37
38char *str_join(const char *s1, int sep_char, const char *s2) {
39 int l1 = strlen(s1);
40 int l2 = strlen(s2);
41 char *s = m_new(char, l1 + l2 + 2);
42 memcpy(s, s1, l1);
43 if (sep_char != 0) {
44 s[l1] = sep_char;
45 l1 += 1;
46 }
47 memcpy(s + l1, s2, l2);
48 return s;
49}
50
51void do_repl() {
52 for (;;) {
53 char *line = readline(">>> ");
54 if (line == NULL) {
55 // EOF
56 return;
57 }
58 if (is_compound_stmt(line)) {
59 for (;;) {
60 char *line2 = readline("... ");
61 if (line2 == NULL || strlen(line2) == 0) {
62 break;
63 }
64 char *line3 = str_join(line, '\n', line2);
65 m_free(line);
66 m_free(line2);
67 line = line3;
68 }
69 }
70 py_lexer_t *lex = py_lexer_from_str_len("<stdin>", line, strlen(line), false);
71 py_parse_node_t pn = py_parse(lex, PY_PARSE_SINGLE_INPUT);
72 if (pn != PY_PARSE_NODE_NULL) {
73 //py_parse_node_show(pn, 0);
74 bool comp_ok = py_compile(pn, true);
75 if (comp_ok) {
76 py_obj_t module_fun = rt_make_function_from_id(1);
77 if (module_fun != py_const_none) {
78 nlr_buf_t nlr;
79 if (nlr_push(&nlr) == 0) {
80 rt_call_function_0(module_fun);
81 nlr_pop();
82 } else {
83 // uncaught exception
84 py_obj_print((py_obj_t)nlr.ret_val);
85 printf("\n");
86 }
87 }
88 }
89 }
90 }
91}
92
93void do_file(const char *file) {
94 py_lexer_t *lex = py_lexer_from_file(file);
Damien429d7192013-10-04 19:53:11 +010095 //const char *pysrc = "def f():\n x=x+1\n print(42)\n";
96 //py_lexer_t *lex = py_lexer_from_str_len("<>", pysrc, strlen(pysrc), false);
97 if (lex == NULL) {
Damien5ac1b2e2013-10-18 19:58:12 +010098 return;
Damien429d7192013-10-04 19:53:11 +010099 }
100
101 if (0) {
Damien5ac1b2e2013-10-18 19:58:12 +0100102 // just tokenise
Damien429d7192013-10-04 19:53:11 +0100103 while (!py_lexer_is_kind(lex, PY_TOKEN_END)) {
104 py_token_show(py_lexer_cur(lex));
105 py_lexer_to_next(lex);
106 }
Damien5ac1b2e2013-10-18 19:58:12 +0100107 py_lexer_free(lex);
108
Damien429d7192013-10-04 19:53:11 +0100109 } else {
Damien5ac1b2e2013-10-18 19:58:12 +0100110 // compile
111
112 py_parse_node_t pn = py_parse(lex, PY_PARSE_FILE_INPUT);
Damien91d387d2013-10-09 15:09:52 +0100113 if (pn != PY_PARSE_NODE_NULL) {
114 //printf("----------------\n");
Damiena3977762013-10-09 23:10:10 +0100115 //parse_node_show(pn, 0);
Damien91d387d2013-10-09 15:09:52 +0100116 //printf("----------------\n");
Damien5ac1b2e2013-10-18 19:58:12 +0100117 bool comp_ok = py_compile(pn, false);
Damien91d387d2013-10-09 15:09:52 +0100118 //printf("----------------\n");
Damien429d7192013-10-04 19:53:11 +0100119
Damien5ac1b2e2013-10-18 19:58:12 +0100120 py_lexer_free(lex);
Damien429d7192013-10-04 19:53:11 +0100121
Damien3ef4abb2013-10-12 16:53:13 +0100122#if !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +0100123 if (1 && comp_ok) {
124 // execute it
125 py_obj_t module_fun = rt_make_function_from_id(1);
126 if (module_fun != py_const_none) {
127 nlr_buf_t nlr;
128 if (nlr_push(&nlr) == 0) {
129 py_obj_t ret = rt_call_function_0(module_fun);
130 printf("done! got: ");
131 py_obj_print(ret);
132 printf("\n");
133 nlr_pop();
134 } else {
135 // uncaught exception
136 printf("exception: ");
137 py_obj_print((py_obj_t)nlr.ret_val);
138 printf("\n");
139 }
140 }
Damience89a212013-10-15 22:25:17 +0100141 }
Damien5ac1b2e2013-10-18 19:58:12 +0100142#endif
Damien429d7192013-10-04 19:53:11 +0100143 }
144 }
Damien5ac1b2e2013-10-18 19:58:12 +0100145}
Damien429d7192013-10-04 19:53:11 +0100146
Damien5ac1b2e2013-10-18 19:58:12 +0100147int main(int argc, char **argv) {
148 qstr_init();
149 rt_init();
150
151 if (argc == 1) {
152 do_repl();
153 } else if (argc == 2) {
154 do_file(argv[1]);
155 } else {
156 printf("usage: py [<file>]\n");
157 return 1;
158 }
Damien429d7192013-10-04 19:53:11 +0100159 rt_deinit();
160
161 //printf("total bytes = %d\n", m_get_total_bytes_allocated());
162 return 0;
163}