Option in compile.c to emit compatible or not with CPython.
This commit is contained in:
parent
c025ebb2dc
commit
3a205179ea
148
py/compile.c
148
py/compile.c
@ -15,7 +15,6 @@
|
|||||||
#include "emit.h"
|
#include "emit.h"
|
||||||
|
|
||||||
// TODO need to mangle __attr names
|
// TODO need to mangle __attr names
|
||||||
// TODO add #define to enable/disable CPython compatibility
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PN_none = 0,
|
PN_none = 0,
|
||||||
@ -250,7 +249,8 @@ void compile_generic_all_nodes(compiler_t *comp, py_parse_node_struct_t *pns) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool c_tuple_is_const(py_parse_node_t pn) {
|
#if defined(MICROPY_EMIT_ENABLE_CPYTHON)
|
||||||
|
static bool cpython_c_tuple_is_const(py_parse_node_t pn) {
|
||||||
if (!PY_PARSE_NODE_IS_LEAF(pn)) {
|
if (!PY_PARSE_NODE_IS_LEAF(pn)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -260,7 +260,7 @@ bool c_tuple_is_const(py_parse_node_t pn) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void c_tuple_emit_const(compiler_t *comp, py_parse_node_t pn) {
|
static void cpython_c_tuple_emit_const(compiler_t *comp, py_parse_node_t pn) {
|
||||||
assert(PY_PARSE_NODE_IS_LEAF(pn));
|
assert(PY_PARSE_NODE_IS_LEAF(pn));
|
||||||
int arg = PY_PARSE_NODE_LEAF_ARG(pn);
|
int arg = PY_PARSE_NODE_LEAF_ARG(pn);
|
||||||
switch (PY_PARSE_NODE_LEAF_KIND(pn)) {
|
switch (PY_PARSE_NODE_LEAF_KIND(pn)) {
|
||||||
@ -282,8 +282,7 @@ void c_tuple_emit_const(compiler_t *comp, py_parse_node_t pn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// funnelling all tuple creations through this function and all this constant stuff is purely to agree with CPython
|
static void cpython_c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_list) {
|
||||||
void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_list) {
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if (pns_list != NULL) {
|
if (pns_list != NULL) {
|
||||||
n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
|
n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
|
||||||
@ -292,12 +291,12 @@ void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_l
|
|||||||
bool is_const = true;
|
bool is_const = true;
|
||||||
if (!PY_PARSE_NODE_IS_NULL(pn)) {
|
if (!PY_PARSE_NODE_IS_NULL(pn)) {
|
||||||
total += 1;
|
total += 1;
|
||||||
if (!c_tuple_is_const(pn)) {
|
if (!cpython_c_tuple_is_const(pn)) {
|
||||||
is_const = false;
|
is_const = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (!c_tuple_is_const(pns_list->nodes[i])) {
|
if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
|
||||||
is_const = false;
|
is_const = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -307,14 +306,14 @@ void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_l
|
|||||||
EMIT(load_const_verbatim_start);
|
EMIT(load_const_verbatim_start);
|
||||||
EMIT(load_const_verbatim_str, "(");
|
EMIT(load_const_verbatim_str, "(");
|
||||||
if (!PY_PARSE_NODE_IS_NULL(pn)) {
|
if (!PY_PARSE_NODE_IS_NULL(pn)) {
|
||||||
c_tuple_emit_const(comp, pn);
|
cpython_c_tuple_emit_const(comp, pn);
|
||||||
need_comma = true;
|
need_comma = true;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (need_comma) {
|
if (need_comma) {
|
||||||
EMIT(load_const_verbatim_str, ", ");
|
EMIT(load_const_verbatim_str, ", ");
|
||||||
}
|
}
|
||||||
c_tuple_emit_const(comp, pns_list->nodes[i]);
|
cpython_c_tuple_emit_const(comp, pns_list->nodes[i]);
|
||||||
need_comma = true;
|
need_comma = true;
|
||||||
}
|
}
|
||||||
if (total == 1) {
|
if (total == 1) {
|
||||||
@ -333,30 +332,46 @@ void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_l
|
|||||||
EMIT(build_tuple, total);
|
EMIT(build_tuple, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
|
||||||
|
void c_tuple(compiler_t *comp, py_parse_node_t pn, py_parse_node_struct_t *pns_list) {
|
||||||
|
#if defined(MICROPY_EMIT_ENABLE_CPYTHON)
|
||||||
|
cpython_c_tuple(comp, pn, pns_list);
|
||||||
|
#else
|
||||||
|
int total = 0;
|
||||||
|
if (!PY_PARSE_NODE_IS_NULL(pn)) {
|
||||||
|
compile_node(comp, pn);
|
||||||
|
total += 1;
|
||||||
|
}
|
||||||
|
if (pns_list != NULL) {
|
||||||
|
int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
compile_node(comp, pns_list->nodes[i]);
|
||||||
|
}
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
EMIT(build_tuple, total);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void compile_generic_tuple(compiler_t *comp, py_parse_node_struct_t *pns) {
|
void compile_generic_tuple(compiler_t *comp, py_parse_node_struct_t *pns) {
|
||||||
// a simple tuple expression
|
// a simple tuple expression
|
||||||
/*
|
|
||||||
int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
compile_node(comp, pns->nodes[i]);
|
|
||||||
}
|
|
||||||
EMIT(build_tuple, n);
|
|
||||||
*/
|
|
||||||
c_tuple(comp, PY_PARSE_NODE_NULL, pns);
|
c_tuple(comp, PY_PARSE_NODE_NULL, pns);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool node_is_const_false(py_parse_node_t pn) {
|
static bool node_is_const_false(py_parse_node_t pn) {
|
||||||
return PY_PARSE_NODE_IS_TOKEN_KIND(pn, PY_TOKEN_KW_FALSE);
|
return PY_PARSE_NODE_IS_TOKEN_KIND(pn, PY_TOKEN_KW_FALSE);
|
||||||
// untested: || (PY_PARSE_NODE_IS_SMALL_INT(pn) && PY_PARSE_NODE_LEAF_ARG(pn) == 1);
|
// untested: || (PY_PARSE_NODE_IS_SMALL_INT(pn) && PY_PARSE_NODE_LEAF_ARG(pn) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool node_is_const_true(py_parse_node_t pn) {
|
static bool node_is_const_true(py_parse_node_t pn) {
|
||||||
return PY_PARSE_NODE_IS_TOKEN_KIND(pn, PY_TOKEN_KW_TRUE) || (PY_PARSE_NODE_IS_SMALL_INT(pn) && PY_PARSE_NODE_LEAF_ARG(pn) == 1);
|
return PY_PARSE_NODE_IS_TOKEN_KIND(pn, PY_TOKEN_KW_TRUE) || (PY_PARSE_NODE_IS_SMALL_INT(pn) && PY_PARSE_NODE_LEAF_ARG(pn) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// having c_if_cond_2 and the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
|
#if defined(MICROPY_EMIT_ENABLE_CPYTHON)
|
||||||
void c_if_cond_2(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label, bool is_nested) {
|
// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
|
||||||
|
static void cpython_c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label, bool is_nested) {
|
||||||
if (node_is_const_false(pn)) {
|
if (node_is_const_false(pn)) {
|
||||||
if (jump_if == false) {
|
if (jump_if == false) {
|
||||||
EMIT(jump, label);
|
EMIT(jump, label);
|
||||||
@ -374,32 +389,32 @@ void c_if_cond_2(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label,
|
|||||||
if (jump_if == false) {
|
if (jump_if == false) {
|
||||||
int label2 = comp_next_label(comp);
|
int label2 = comp_next_label(comp);
|
||||||
for (int i = 0; i < n - 1; i++) {
|
for (int i = 0; i < n - 1; i++) {
|
||||||
c_if_cond_2(comp, pns->nodes[i], true, label2, true);
|
cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
|
||||||
}
|
}
|
||||||
c_if_cond_2(comp, pns->nodes[n - 1], false, label, true);
|
cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
|
||||||
EMIT(label_assign, label2);
|
EMIT(label_assign, label2);
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
c_if_cond_2(comp, pns->nodes[i], true, label, true);
|
cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
|
} else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
|
||||||
if (jump_if == false) {
|
if (jump_if == false) {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
c_if_cond_2(comp, pns->nodes[i], false, label, true);
|
cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int label2 = comp_next_label(comp);
|
int label2 = comp_next_label(comp);
|
||||||
for (int i = 0; i < n - 1; i++) {
|
for (int i = 0; i < n - 1; i++) {
|
||||||
c_if_cond_2(comp, pns->nodes[i], false, label2, true);
|
cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
|
||||||
}
|
}
|
||||||
c_if_cond_2(comp, pns->nodes[n - 1], true, label, true);
|
cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
|
||||||
EMIT(label_assign, label2);
|
EMIT(label_assign, label2);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (!is_nested && PY_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
|
} else if (!is_nested && PY_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
|
||||||
c_if_cond_2(comp, pns->nodes[0], !jump_if, label, true);
|
cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,9 +427,67 @@ void c_if_cond_2(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label,
|
|||||||
EMIT(pop_jump_if_true, label);
|
EMIT(pop_jump_if_true, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label) {
|
static void c_if_cond(compiler_t *comp, py_parse_node_t pn, bool jump_if, int label) {
|
||||||
c_if_cond_2(comp, pn, jump_if, label, false);
|
#if defined(MICROPY_EMIT_ENABLE_CPYTHON)
|
||||||
|
cpython_c_if_cond(comp, pn, jump_if, label, false);
|
||||||
|
#else
|
||||||
|
if (node_is_const_false(pn)) {
|
||||||
|
if (jump_if == false) {
|
||||||
|
EMIT(jump, label);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (node_is_const_true(pn)) {
|
||||||
|
if (jump_if == true) {
|
||||||
|
EMIT(jump, label);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (PY_PARSE_NODE_IS_STRUCT(pn)) {
|
||||||
|
py_parse_node_struct_t *pns = (py_parse_node_struct_t*)pn;
|
||||||
|
int n = PY_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||||
|
if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
|
||||||
|
if (jump_if == false) {
|
||||||
|
int label2 = comp_next_label(comp);
|
||||||
|
for (int i = 0; i < n - 1; i++) {
|
||||||
|
c_if_cond(comp, pns->nodes[i], true, label2);
|
||||||
|
}
|
||||||
|
c_if_cond(comp, pns->nodes[n - 1], false, label);
|
||||||
|
EMIT(label_assign, label2);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
c_if_cond(comp, pns->nodes[i], true, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
|
||||||
|
if (jump_if == false) {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
c_if_cond(comp, pns->nodes[i], false, label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int label2 = comp_next_label(comp);
|
||||||
|
for (int i = 0; i < n - 1; i++) {
|
||||||
|
c_if_cond(comp, pns->nodes[i], false, label2);
|
||||||
|
}
|
||||||
|
c_if_cond(comp, pns->nodes[n - 1], true, label);
|
||||||
|
EMIT(label_assign, label2);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (PY_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
|
||||||
|
c_if_cond(comp, pns->nodes[0], !jump_if, label);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing special, fall back to default compiling for node and jump
|
||||||
|
compile_node(comp, pn);
|
||||||
|
if (jump_if == false) {
|
||||||
|
EMIT(pop_jump_if_false, label);
|
||||||
|
} else {
|
||||||
|
EMIT(pop_jump_if_true, label);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
|
typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
|
||||||
@ -1859,9 +1932,6 @@ void compile_comprehension(compiler_t *comp, py_parse_node_struct_t *pns, scope_
|
|||||||
void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) {
|
void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) {
|
||||||
if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
if (PY_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||||
// an empty tuple
|
// an empty tuple
|
||||||
/*
|
|
||||||
EMIT(build_tuple, 0);
|
|
||||||
*/
|
|
||||||
c_tuple(comp, PY_PARSE_NODE_NULL, NULL);
|
c_tuple(comp, PY_PARSE_NODE_NULL, NULL);
|
||||||
} else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
|
} else if (PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
|
||||||
pns = (py_parse_node_struct_t*)pns->nodes[0];
|
pns = (py_parse_node_struct_t*)pns->nodes[0];
|
||||||
@ -1871,18 +1941,9 @@ void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) {
|
|||||||
if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
|
if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
|
||||||
// tuple of one item, with trailing comma
|
// tuple of one item, with trailing comma
|
||||||
assert(PY_PARSE_NODE_IS_NULL(pns2->nodes[0]));
|
assert(PY_PARSE_NODE_IS_NULL(pns2->nodes[0]));
|
||||||
/*
|
|
||||||
compile_node(comp, pns->nodes[0]);
|
|
||||||
EMIT(build_tuple, 1);
|
|
||||||
*/
|
|
||||||
c_tuple(comp, pns->nodes[0], NULL);
|
c_tuple(comp, pns->nodes[0], NULL);
|
||||||
} else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
|
} else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
|
||||||
// tuple of many items
|
// tuple of many items
|
||||||
/*
|
|
||||||
compile_node(comp, pns->nodes[0]);
|
|
||||||
compile_generic_all_nodes(comp, pns2);
|
|
||||||
EMIT(build_tuple, 1 + PY_PARSE_NODE_STRUCT_NUM_NODES(pns2));
|
|
||||||
*/
|
|
||||||
c_tuple(comp, pns->nodes[0], pns2);
|
c_tuple(comp, pns->nodes[0], pns2);
|
||||||
} else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
|
} else if (PY_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
|
||||||
// generator expression
|
// generator expression
|
||||||
@ -1894,11 +1955,6 @@ void compile_atom_paren(compiler_t *comp, py_parse_node_struct_t *pns) {
|
|||||||
} else {
|
} else {
|
||||||
// tuple with 2 items
|
// tuple with 2 items
|
||||||
tuple_with_2_items:
|
tuple_with_2_items:
|
||||||
/*
|
|
||||||
compile_node(comp, pns->nodes[0]);
|
|
||||||
compile_node(comp, pns->nodes[1]);
|
|
||||||
EMIT(build_tuple, 2);
|
|
||||||
*/
|
|
||||||
c_tuple(comp, PY_PARSE_NODE_NULL, pns);
|
c_tuple(comp, PY_PARSE_NODE_NULL, pns);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user