summaryrefslogtreecommitdiff
path: root/py/compile.c
diff options
context:
space:
mode:
authorDamien <damien.p.george@gmail.com>2013-10-18 19:58:12 +0100
committerDamien <damien.p.george@gmail.com>2013-10-18 19:58:12 +0100
commit5ac1b2efbd5dfb2a62fe984dc9dc8a7127fb5e82 (patch)
treea00fad2e39bc0d3604dc91cbd21910c6800d3e14 /py/compile.c
parent7bbd1106915b481816fe5baa72ce7c6068c7386a (diff)
Implement REPL.
Diffstat (limited to 'py/compile.c')
-rw-r--r--py/compile.c56
1 files changed, 43 insertions, 13 deletions
diff --git a/py/compile.c b/py/compile.c
index 0967c855c..d622242b6 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -44,11 +44,14 @@ typedef struct _compiler_t {
qstr qstr___doc__;
qstr qstr_assertion_error;
qstr qstr_micropython;
+ qstr qstr_byte_code;
qstr qstr_native;
qstr qstr_viper;
qstr qstr_asm_thumb;
+ bool is_repl;
pass_kind_t pass;
+ bool had_error; // try to keep compiler clean from nlr
int next_label;
@@ -196,7 +199,7 @@ static int comp_next_label(compiler_t *comp) {
}
static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn, uint emit_options) {
- scope_t *scope = scope_new(kind, pn, rt_get_new_unique_code_id(), emit_options);
+ scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options);
scope->parent = comp->scope_cur;
scope->next = NULL;
if (comp->scope_head == NULL) {
@@ -855,7 +858,8 @@ static bool compile_built_in_decorator(compiler_t *comp, int name_len, py_parse_
}
qstr attr = PY_PARSE_NODE_LEAF_ARG(name_nodes[1]);
- if (0) {
+ if (attr == comp->qstr_byte_code) {
+ *emit_options = EMIT_OPT_BYTE_CODE;
#if MICROPY_EMIT_NATIVE
} else if (attr == comp->qstr_native) {
*emit_options = EMIT_OPT_NATIVE_PYTHON;
@@ -1046,7 +1050,13 @@ void compile_continue_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
}
void compile_return_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
+ if (comp->scope_cur->kind != SCOPE_FUNCTION) {
+ printf("SyntaxError: 'return' outside function\n");
+ comp->had_error = true;
+ return;
+ }
if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) {
+ // no argument to 'return', so return None
EMIT(load_const_tok, PY_TOKEN_KW_NONE);
} else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
// 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) {
void compile_expr_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
if (PY_PARSE_NODE_IS_NULL(pns->nodes[1])) {
- if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !PY_PARSE_NODE_IS_ID(pns->nodes[0])) {
- // do nothing with a lonely constant
+ if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
+ // for REPL, evaluate then print the expression
+ EMIT(load_id, qstr_from_str_static("__repl_print__"));
+ compile_node(comp, pns->nodes[0]);
+ EMIT(call_function, 1, 0, false, false);
+ EMIT(pop_top);
+
} else {
- compile_node(comp, pns->nodes[0]); // just an expression
- EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
+ // for non-REPL, evaluate then discard the expression
+ if (PY_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !PY_PARSE_NODE_IS_ID(pns->nodes[0])) {
+ // do nothing with a lonely constant
+ } else {
+ compile_node(comp, pns->nodes[0]); // just an expression
+ EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
+ }
}
} else {
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) {
case PY_PARSE_NODE_TOKEN:
if (arg == PY_TOKEN_NEWLINE) {
// this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
+ // or when single_input lets through a NEWLINE (user enters a blank line)
// do nothing
} else {
EMIT(load_const_tok, arg);
@@ -2299,7 +2320,7 @@ void compile_node(compiler_t *comp, py_parse_node_t pn) {
compile_function_t f = compile_function[PY_PARSE_NODE_STRUCT_KIND(pns)];
if (f == NULL) {
printf("node %u cannot be compiled\n", (uint)PY_PARSE_NODE_STRUCT_KIND(pns));
- parse_node_show(pn, 0);
+ py_parse_node_show(pn, 0);
assert(0);
} else {
f(comp, pns);
@@ -2481,14 +2502,17 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
scope->stack_size = 0;
}
+#if MICROPY_EMIT_CPYTHON
if (comp->pass == PASS_3) {
- //printf("----\n");
scope_print_info(scope);
}
+#endif
// compile
if (scope->kind == SCOPE_MODULE) {
- check_for_doc_string(comp, scope->pn);
+ if (!comp->is_repl) {
+ check_for_doc_string(comp, scope->pn);
+ }
compile_node(comp, scope->pn);
EMIT(load_const_tok, PY_TOKEN_KW_NONE);
EMIT(return_value);
@@ -2731,7 +2755,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
}
}
-void py_compile(py_parse_node_t pn) {
+bool py_compile(py_parse_node_t pn, bool is_repl) {
compiler_t *comp = m_new(compiler_t, 1);
comp->qstr___class__ = qstr_from_str_static("__class__");
@@ -2742,10 +2766,14 @@ void py_compile(py_parse_node_t pn) {
comp->qstr___doc__ = qstr_from_str_static("__doc__");
comp->qstr_assertion_error = qstr_from_str_static("AssertionError");
comp->qstr_micropython = qstr_from_str_static("micropython");
+ comp->qstr_byte_code = qstr_from_str_static("byte_code");
comp->qstr_native = qstr_from_str_static("native");
comp->qstr_viper = qstr_from_str_static("viper");
comp->qstr_asm_thumb = qstr_from_str_static("asm_thumb");
+ comp->is_repl = is_repl;
+ comp->had_error = false;
+
comp->break_label = 0;
comp->continue_label = 0;
comp->except_nest_level = 0;
@@ -2764,7 +2792,7 @@ void py_compile(py_parse_node_t pn) {
comp->emit_inline_asm = NULL;
comp->emit_inline_asm_method_table = NULL;
uint max_num_labels = 0;
- for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
+ for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
if (false) {
#if MICROPY_EMIT_INLINE_THUMB
} else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
@@ -2781,7 +2809,7 @@ void py_compile(py_parse_node_t pn) {
}
// compute some things related to scope and identifiers
- for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
+ for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
compile_scope_compute_things(comp, s);
}
@@ -2796,7 +2824,7 @@ void py_compile(py_parse_node_t pn) {
#if MICROPY_EMIT_INLINE_THUMB
emit_inline_asm_t *emit_inline_thumb = NULL;
#endif
- for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
+ for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
if (false) {
// dummy
@@ -2857,4 +2885,6 @@ void py_compile(py_parse_node_t pn) {
}
m_free(comp);
+
+ return !comp->had_error;
}