Skip to content

Commit 5ac1b2e

Browse files
committed
Implement REPL.
1 parent 7bbd110 commit 5ac1b2e

File tree

8 files changed

+253
-71
lines changed

8 files changed

+253
-71
lines changed

py/compile.c

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ typedef struct _compiler_t {
4444
qstr qstr___doc__;
4545
qstr qstr_assertion_error;
4646
qstr qstr_micropython;
47+
qstr qstr_byte_code;
4748
qstr qstr_native;
4849
qstr qstr_viper;
4950
qstr qstr_asm_thumb;
5051

52+
bool is_repl;
5153
pass_kind_t pass;
54+
bool had_error; // try to keep compiler clean from nlr
5255

5356
int next_label;
5457

@@ -196,7 +199,7 @@ static int comp_next_label(compiler_t *comp) {
196199
}
197200

198201
static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn, uint emit_options) {
199-
scope_t *scope = scope_new(kind, pn, rt_get_new_unique_code_id(), emit_options);
202+
scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options);
200203
scope->parent = comp->scope_cur;
201204
scope->next = NULL;
202205
if (comp->scope_head == NULL) {
@@ -855,7 +858,8 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, py_parse_
855858
}
856859

857860
qstr attr = PY_PARSE_NODE_LEAF_ARG(name_nodes[1]);
858-
if (0) {
861+
if (attr == comp->qstr_byte_code) {
862+
*emit_options = EMIT_OPT_BYTE_CODE;
859863
#if MICROPY_EMIT_NATIVE
860864
} else if (attr == comp->qstr_native) {
861865
*emit_options = EMIT_OPT_NATIVE_PYTHON;
@@ -1046,7 +1050,13 @@ void compile_continue_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
10461050
}
10471051

10481052
void compile_return_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
1053+
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1054+
printf("SyntaxError: 'return' outside function\n");
1055+
comp->had_error = true;
1056+
return;
1057+
}
10491058
if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) {
1059+
// no argument to 'return', so return None
10501060
EMIT(load_const_tok, PY_TOKEN_KW_NONE);
10511061
} else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
10521062
// special case when returning an if-expression; to match CPython optimisation
@@ -1566,11 +1576,21 @@ void compile_with_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
15661576

15671577
void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
15681578
if (PY_PARSE_NODE_IS_NULL(pns->nodes[1])) {
1569-
if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !PY_PARSE_NODE_IS_ID(pns->nodes[0])) {
1570-
// do nothing with a lonely constant
1579+
if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1580+
// for REPL, evaluate then print the expression
1581+
EMIT(load_id, qstr_from_str_static("__repl_print__"));
1582+
compile_node(comp, pns->nodes[0]);
1583+
EMIT(call_function, 1, 0, false, false);
1584+
EMIT(pop_top);
1585+
15711586
} else {
1572-
compile_node(comp, pns->nodes[0]); // just an expression
1573-
EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1587+
// for non-REPL, evaluate then discard the expression
1588+
if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !PY_PARSE_NODE_IS_ID(pns->nodes[0])) {
1589+
// do nothing with a lonely constant
1590+
} else {
1591+
compile_node(comp, pns->nodes[0]); // just an expression
1592+
EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1593+
}
15741594
}
15751595
} else {
15761596
py_parse_node_struct_t *pns1 = (py_parse_node_struct_t*)pns->nodes[1];
@@ -2287,6 +2307,7 @@ void compile_node(compiler_t *comp, py_parse_node_t pn) {
22872307
case PY_PARSE_NODE_TOKEN:
22882308
if (arg == PY_TOKEN_NEWLINE) {
22892309
// this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
2310+
// or when single_input lets through a NEWLINE (user enters a blank line)
22902311
// do nothing
22912312
} else {
22922313
EMIT(load_const_tok, arg);
@@ -2299,7 +2320,7 @@ void compile_node(compiler_t *comp, py_parse_node_t pn) {
22992320
compile_function_t f = compile_function[PY_PARSE_NODE_STRUCT_KIND(pns)];
23002321
if (f == NULL) {
23012322
printf("node %u cannot be compiled\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns));
2302-
parse_node_show(pn, 0);
2323+
py_parse_node_show(pn, 0);
23032324
assert(0);
23042325
} else {
23052326
f(comp, pns);
@@ -2481,14 +2502,17 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
24812502
scope->stack_size = 0;
24822503
}
24832504

2505+
#if MICROPY_EMIT_CPYTHON
24842506
if (comp->pass == PASS_3) {
2485-
//printf("----\n");
24862507
scope_print_info(scope);
24872508
}
2509+
#endif
24882510

24892511
// compile
24902512
if (scope->kind == SCOPE_MODULE) {
2491-
check_for_doc_string(comp, scope->pn);
2513+
if (!comp->is_repl) {
2514+
check_for_doc_string(comp, scope->pn);
2515+
}
24922516
compile_node(comp, scope->pn);
24932517
EMIT(load_const_tok, PY_TOKEN_KW_NONE);
24942518
EMIT(return_value);
@@ -2731,7 +2755,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
27312755
}
27322756
}
27332757

2734-
void py_compile(py_parse_node_t pn) {
2758+
bool py_compile(py_parse_node_t pn, bool is_repl) {
27352759
compiler_t *comp = m_new(compiler_t, 1);
27362760

27372761
comp->qstr___class__ = qstr_from_str_static("__class__");
@@ -2742,10 +2766,14 @@ void py_compile(py_parse_node_t pn) {
27422766
comp->qstr___doc__ = qstr_from_str_static("__doc__");
27432767
comp->qstr_assertion_error = qstr_from_str_static("AssertionError");
27442768
comp->qstr_micropython = qstr_from_str_static("micropython");
2769+
comp->qstr_byte_code = qstr_from_str_static("byte_code");
27452770
comp->qstr_native = qstr_from_str_static("native");
27462771
comp->qstr_viper = qstr_from_str_static("viper");
27472772
comp->qstr_asm_thumb = qstr_from_str_static("asm_thumb");
27482773

2774+
comp->is_repl = is_repl;
2775+
comp->had_error = false;
2776+
27492777
comp->break_label = 0;
27502778
comp->continue_label = 0;
27512779
comp->except_nest_level = 0;
@@ -2764,7 +2792,7 @@ void py_compile(py_parse_node_t pn) {
27642792
comp->emit_inline_asm = NULL;
27652793
comp->emit_inline_asm_method_table = NULL;
27662794
uint max_num_labels = 0;
2767-
for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
2795+
for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
27682796
if (false) {
27692797
#if MICROPY_EMIT_INLINE_THUMB
27702798
} else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
@@ -2781,7 +2809,7 @@ void py_compile(py_parse_node_t pn) {
27812809
}
27822810

27832811
// compute some things related to scope and identifiers
2784-
for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
2812+
for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
27852813
compile_scope_compute_things(comp, s);
27862814
}
27872815

@@ -2796,7 +2824,7 @@ void py_compile(py_parse_node_t pn) {
27962824
#if MICROPY_EMIT_INLINE_THUMB
27972825
emit_inline_asm_t *emit_inline_thumb = NULL;
27982826
#endif
2799-
for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
2827+
for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
28002828
if (false) {
28012829
// dummy
28022830

@@ -2857,4 +2885,6 @@ void py_compile(py_parse_node_t pn) {
28572885
}
28582886

28592887
m_free(comp);
2888+
2889+
return !comp->had_error;
28602890
}

py/compile.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
void py_compile(py_parse_node_t pn);
1+
bool py_compile(py_parse_node_t pn, bool is_repl);

py/parse.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ py_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) {
128128
return pn;
129129
}
130130

131-
void parse_node_show(py_parse_node_t pn, int indent) {
131+
void py_parse_node_show(py_parse_node_t pn, int indent) {
132132
for (int i = 0; i < indent; i++) {
133133
printf(" ");
134134
}
@@ -155,7 +155,7 @@ void parse_node_show(py_parse_node_t pn, int indent) {
155155
printf("rule(%u) (n=%d)\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns2), n);
156156
#endif
157157
for (int i = 0; i < n; i++) {
158-
parse_node_show(pns2->nodes[i], indent + 2);
158+
py_parse_node_show(pns2->nodes[i], indent + 2);
159159
}
160160
}
161161
}
@@ -164,7 +164,7 @@ void parse_node_show(py_parse_node_t pn, int indent) {
164164
static void result_stack_show(parser_t *parser) {
165165
printf("result stack, most recent first\n");
166166
for (int i = parser->result_stack_top - 1; i >= 0; i--) {
167-
parse_node_show(parser->result_stack[i], 0);
167+
py_parse_node_show(parser->result_stack[i], 0);
168168
}
169169
}
170170
*/
@@ -251,8 +251,7 @@ static void push_result_rule(parser_t *parser, rule_t *rule, int num_args) {
251251
push_result_node(parser, (py_parse_node_t)pn);
252252
}
253253

254-
py_parse_node_t py_parse(py_lexer_t *lex, int wanted_rule) {
255-
wanted_rule = RULE_file_input;
254+
py_parse_node_t py_parse(py_lexer_t *lex, py_parse_input_kind_t input_kind) {
256255
parser_t *parser = m_new(parser_t, 1);
257256
parser->rule_stack_alloc = 64;
258257
parser->rule_stack_top = 0;
@@ -261,7 +260,13 @@ py_parse_node_t py_parse(py_lexer_t *lex, int wanted_rule) {
261260
parser->result_stack = m_new(py_parse_node_t, 1000);
262261
parser->result_stack_top = 0;
263262

264-
push_rule(parser, rules[wanted_rule], 0);
263+
int top_level_rule;
264+
switch (input_kind) {
265+
case PY_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
266+
//case PY_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
267+
default: top_level_rule = RULE_file_input;
268+
}
269+
push_rule(parser, rules[top_level_rule], 0);
265270

266271
uint n, i;
267272
bool backtrack = false;

py/parse.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ typedef struct _py_parse_node_struct_t {
5454

5555
py_parse_node_t py_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
5656

57-
void parse_node_show(py_parse_node_t pn, int indent);
57+
void py_parse_node_show(py_parse_node_t pn, int indent);
5858

59-
py_parse_node_t py_parse(struct _py_lexer_t *lex, int wanted_rule);
59+
typedef enum {
60+
PY_PARSE_SINGLE_INPUT,
61+
PY_PARSE_FILE_INPUT,
62+
PY_PARSE_EVAL_INPUT,
63+
} py_parse_input_kind_t;
64+
65+
py_parse_node_t py_parse(struct _py_lexer_t *lex, py_parse_input_kind_t input_kind);

0 commit comments

Comments
 (0)