MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计.
#include <stdbool.h> // 包含布尔类型的定义
#include <stdint.h> // 包含整数类型的定义
#include <stdio.h> // 包含输入输出函数的定义
#include <string.h> // 包含字符串操作函数的定义
#include <assert.h> // 包含断言宏的定义
// 包含MicroPython特有的头文件
#include "py/scope.h"
#include "py/emit.h"
#include "py/compile.h"
#include "py/runtime.h"
#include "py/asmbase.h"
#include "py/nativeglue.h"
#include "py/persistentcode.h"
#include "py/smallint.h"
#if MICROPY_ENABLE_COMPILER
// 定义编译规则,每个规则都有一个编译函数
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
PN_const_object, // 用于表示常量的通用Python对象的特殊节点
// 定义没有编译函数的规则
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) PN_##rule,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
} pn_kind_t;
// 判断一个mp_parse_node_struct_t是否对应于列表推导或生成器
#define MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns) \
(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2 && \
MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for))
#define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE
#if NEED_METHOD_TABLE
// 为了进行发射函数的查找,我们需要一个方法表
#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST))
#define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL))
#else
// 如果我们只启用了字节码发射器,那么我们可以直接调用函数
#define EMIT(fun) (mp_emit_bc_##fun(comp->emit))
#define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))
#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST))
#define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL))
#endif
#if MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
// 定义本地发射器的宏
#define NATIVE_EMITTER(f) emit_native_table[mp_dynamic_compiler.native_arch]->emit_##f
#define NATIVE_EMITTER_TABLE (emit_native_table[mp_dynamic_compiler.native_arch])
// 定义本地发射器表
static const emit_method_table_t *emit_native_table[] = {
NULL,
&emit_native_x86_method_table,
&emit_native_x64_method_table,
&emit_native_arm_method_table,
&emit_native_thumb_method_table,
&emit_native_thumb_method_table,
&emit_native_thumb_method_table,
&emit_native_thumb_method_table,
&emit_native_thumb_method_table,
&emit_native_thumb_method_table,
&emit_native_xtensa_method_table,
&emit_native_xtensawin_method_table,
};
#elif MICROPY_EMIT_NATIVE
// 定义访问外部本地发射器的宏
#if MICROPY_EMIT_X64
#define NATIVE_EMITTER(f) emit_native_x64_##f
#elif MICROPY_EMIT_X86
#define NATIVE_EMITTER(f) emit_native_x86_##f
#elif MICROPY_EMIT_THUMB
#define NATIVE_EMITTER(f) emit_native_thumb_##f
#elif MICROPY_EMIT_ARM
#define NATIVE_EMITTER(f) emit_native_arm_##f
#elif MICROPY_EMIT_XTENSA
#define NATIVE_EMITTER(f) emit_native_xtensa_##f
#elif MICROPY_EMIT_XTENSAWIN
#define NATIVE_EMITTER(f) emit_native_xtensawin_##f
#else
#error "未知的本地发射器"
#endif
#define NATIVE_EMITTER_TABLE (&NATIVE_EMITTER(method_table))
#endif
#if MICROPY_EMIT_INLINE_ASM && MICROPY_DYNAMIC_COMPILER
// 定义内联汇编发射器的宏
#define ASM_EMITTER(f) emit_asm_table[mp_dynamic_compiler.native_arch]->asm_##f
#define ASM_EMITTER_TABLE emit_asm_table[mp_dynamic_compiler.native_arch]
// 定义内联汇编发射器表
static const emit_inline_asm_method_table_t *emit_asm_table[] = {
NULL,
NULL,
NULL,
&emit_inline_thumb_method_table,
&emit_inline_thumb_method_table,
&emit_inline_thumb_method_table,
&emit_inline_thumb_method_table,
&emit_inline_thumb_method_table,
&emit_inline_thumb_method_table,
&emit_inline_thumb_method_table,
&emit_inline_xtensa_method_table,
NULL,
};
#elif MICROPY_EMIT_INLINE_ASM
// 定义内联汇编的宏
#if MICROPY_EMIT_INLINE_THUMB
#define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb
#define ASM_EMITTER(f) emit_inline_thumb_##f
#elif MICROPY_EMIT_INLINE_XTENSA
#define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa
#define ASM_EMITTER(f) emit_inline_xtensa_##f
#else
#error "未知的汇编发射器"
#endif
#define ASM_EMITTER_TABLE &ASM_EMITTER(method_table)
#endif
// 定义内联汇编的函数
#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
// 编译器结构体,包含编译过程中的所有状态信息
typedef struct _compiler_t {
uint8_t is_repl; // 是否为交互式解释器模式
uint8_t pass; // 编译的阶段
uint8_t have_star; // 是否有星号参数
// 避免使用非局部返回(NLR)
mp_obj_t compile_error; // 编译错误时设置为异常对象
size_t compile_error_line; // 错误行号的最佳猜测
uint next_label; // 下一个标签号
uint16_t num_dict_params; // 字典类型参数的数量
uint16_t num_default_params; // 默认参数的数量
uint16_t break_label; // 用于跳出循环的标签号
uint16_t continue_label; // 用于继续循环的标签号
uint16_t cur_except_level; // 当前异常处理的层级
uint16_t break_continue_except_level; // 用于跳出/继续的异常处理层级
scope_t *scope_head; // 作用域链的头部
scope_t *scope_cur; // 当前作用域
emit_t *emit; // 当前发射器
#if NEED_METHOD_TABLE
const emit_method_table_t *emit_method_table; // 当前发射方法表
#endif
#if MICROPY_EMIT_INLINE_ASM
emit_inline_asm_t *emit_inline_asm; // 用于内联汇编的当前发射器
const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // 用于内联汇编的当前发射方法表
#endif
mp_emit_common_t emit_common; // 通用发射器信息
} compiler_t;
#if MICROPY_COMP_ALLOW_TOP_LEVEL_AWAIT
bool mp_compile_allow_top_level_await = false;
#endif
// mp_emit_common_t辅助函数
// 这些函数定义在这里,以便可以内联,减少代码大小。
// 初始化通用发射器信息
static void mp_emit_common_init(mp_emit_common_t *emit, qstr source_file) {
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
mp_map_init(&emit->qstr_map, 1);
// 将源文件作为qstr表的第一个条目
mp_map_elem_t *elem = mp_map_lookup(&emit->qstr_map, MP_OBJ_NEW_QSTR(source_file), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
elem->value = MP_OBJ_NEW_SMALL_INT(0);
#endif
mp_obj_list_init(&emit->const_obj_list, 0);
}
// 开始编译的一个新的阶段
static void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass) {
emit->pass = pass;
if (pass == MP_PASS_CODE_SIZE) {
if (emit->ct_cur_child == 0) {
emit->children = NULL;
} else {
emit->children = m_new0(mp_raw_code_t *, emit->ct_cur_child);
}
}emit->ct_cur_child = 0;
}
// 填充模块上下文信息
static void mp_emit_common_populate_module_context(mp_emit_common_t *emit, qstr source_file, mp_module_context_t *context) {
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
size_t qstr_map_used = emit->qstr_map.used;
mp_module_context_alloc_tables(context, qstr_map_used, emit->const_obj_list.len);
for (size_t i = 0; i < emit->qstr_map.alloc; ++i) {
if (mp_map_slot_is_filled(&emit->qstr_map, i)) {
size_t idx = MP_OBJ_SMALL_INT_VALUE(emit->qstr_map.table[i].value);
qstr qst = MP_OBJ_QSTR_VALUE(emit->qstr_map.table[i].key);
context->constants.qstr_table[idx] = qst;
}
}
#else
mp_module_context_alloc_tables(context, 0, emit->const_obj_list.len);
context->constants.source_file = source_file;
#endif
for (size_t i = 0; i < emit->const_obj_list.len; ++i) {
context->constants.obj_table[i] = emit->const_obj_list.items[i];
}
}
// 编译过程中的错误处理函数
static void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) {
// 如果错误的行号未知,则尝试从pn中更新
if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) {
comp->compile_error_line = ((mp_parse_node_struct_t *)pn)->source_line;
}
}
// 编译语法错误
static void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, mp_rom_error_text_t msg) {
// 只有在没有其他错误的情况下才记录错误
if (comp->compile_error == MP_OBJ_NULL) {
comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
compile_error_set_line(comp, pn);
}
}
// 编译函数定义、列表推导和生成器的辅助函数
static void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
static void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);
static void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map);
static void compile_node(compiler_t *comp, mp_parse_node_t pn);
// 获取下一个标签号
static uint comp_next_label(compiler_t *comp) {
return comp->next_label++;
}
#if MICROPY_EMIT_NATIVE
// 为本地代码预留标签
static void reserve_labels_for_native(compiler_t *comp, int n) {
if (comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
comp->next_label += n;
}
}
#else
#define reserve_labels_for_native(comp, n)
#endif
// 增加异常处理层级
static void compile_increase_except_level(compiler_t *comp, uint label, int kind) {
EMIT_ARG(setup_block, label, kind);
comp->cur_except_level += 1;
if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
comp->scope_cur->exc_stack_size = comp->cur_except_level;
}
}
// 减少异常处理层级
static void compile_decrease_except_level(compiler_t *comp) {
assert(comp->cur_except_level > 0);
comp->cur_except_level -= 1;
EMIT(end_finally);
reserve_labels_for_native(comp, 1);
}
// 创建并链接新的作用域
static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
scope_t *scope = scope_new(kind, pn, emit_options);
scope->parent = comp->scope_cur;
scope->next = NULL;
if (comp->scope_head == NULL) {
comp->scope_head = scope;
} else {
scope_t *s = comp->scope_head;
while (s->next != NULL) {
s = s->next;
}
s->next = scope;
}
return scope;
}
// 应用列表函数的辅助函数
typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);
// 对单个节点或列表应用函数
static void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, apply_list_fun_t f) {
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
for (int i = 0; i < num_nodes; i++) {
f(comp, pns->nodes[i]);
}
} else if (!MP_PARSE_NODE_IS_NULL(pn)) {
f(comp, pn);
}
}
// 编译所有节点的通用函数
static void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
for (int i = 0; i < num_nodes; i++) {
compile_node(comp, pns->nodes[i]);
if (comp->compile_error != MP_OBJ_NULL) {
// 如果发生错误,添加错误行信息
compile_error_set_line(comp, pns->nodes[i]);
return;
}
}
}
// 编译加载标识符
static void compile_load_id(compiler_t *comp, qstr qst) {
if (comp->pass == MP_PASS_SCOPE) {
// 在作用域阶段,获取加载标识符的ID
mp_emit_common_get_id_for_load(comp->scope_cur, qst);
} else {
// 在其他阶段,根据发射方法表加载标识符
#if NEED_METHOD_TABLE
mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);
#else
mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);
#endif
}
}
// 编译存储标识符
static void compile_store_id(compiler_t *comp, qstr qst) {
if (comp->pass == MP_PASS_SCOPE) {
// 在作用域阶段,获取存储标识符的ID
mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
} else {
// 在其他阶段,根据发射方法表存储标识符
#if NEED_METHOD_TABLE
mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);
#else
mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);
#endif
}
}
// 编译删除标识符
static void compile_delete_id(compiler_t *comp, qstr qst) {
if (comp->pass == MP_PASS_SCOPE) {
// 在作用域阶段,获取删除标识符的ID
mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
} else {
// 在其他阶段,根据发射方法表删除标识符
#if NEED_METHOD_TABLE
mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);
#else
mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);
#endif
}
}
// 编译通用元组表达式
static void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
// 一个简单的元组表达式
size_t num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
for (size_t i = 0; i < num_nodes; i++) {
compile_node(comp, pns->nodes[i]);
}
EMIT_ARG(build, num_nodes, MP_EMIT_BUILD_TUPLE);
}
// 编译条件跳转
static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
// 如果条件为假且不跳转,或者条件为真且跳转
if (mp_parse_node_is_const_false(pn)) {
if (jump_if == false) {
EMIT_ARG(jump, label);
}
return;
} else if (mp_parse_node_is_const_true(pn)) {
if (jump_if == true) {
EMIT_ARG(jump, label);
}
return;
} else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
// 如果节点是结构体,根据其种类进行不同的处理
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
// 或逻辑
if (jump_if == false) {
// 如果不跳转,处理每个子节点
and_or_logic1:;
uint label2 = comp_next_label(comp);
for (int i = 0; i < n - 1; i++) {
c_if_cond(comp, pns->nodes[i], !jump_if, label2);
}
c_if_cond(comp, pns->nodes[n - 1], jump_if, label);
EMIT_ARG(label_assign, label2);
} else {
// 如果跳转,处理每个子节点
and_or_logic2:
for (int i = 0; i < n; i++) {
c_if_cond(comp, pns->nodes[i], jump_if, label);
}
}
return;
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
// 与逻辑
if (jump_if == false) {
goto and_or_logic2;
} else {
goto and_or_logic1;
}
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
// 非逻辑
c_if_cond(comp, pns->nodes[0], !jump_if, label);
return;
}
}
// 如果没有特殊处理,回退到默认的节点编译和跳转
compile_node(comp, pn);
EMIT_ARG(pop_jump_if, jump_if, label);
}
// 编译赋值
typedef enum {
ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
static void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
// 编译原子表达式的赋值
static void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
// 如果不是增强存储赋值,则编译左侧表达式
if (assign_kind != ASSIGN_AUG_STORE) {
compile_node(comp, pns->nodes[0]);
}
// 检查右侧表达式是否为结构体
if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {
// 如果是尾随操作,编译每个尾随操作
int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
if (assign_kind != ASSIGN_AUG_STORE) {
for (int i = 0; i < n - 1; i++) {
compile_node(comp, pns1->nodes[i]);
}
}
assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
pns1 = (mp_parse_node_struct_t *)pns1->nodes[n - 1];
}
if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
// 如果是索引操作,根据赋值类型执行相应操作
if (assign_kind == ASSIGN_AUG_STORE) {
EMIT(rot_three);
EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE);
} else {
compile_node(comp, pns1->nodes[0]);
if (assign_kind == ASSIGN_AUG_LOAD) {
EMIT(dup_top_two);
EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD);
} else {
EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE);
}
}
return;
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
// 如果是属性访问,根据赋值类型执行相应操作
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
if (assign_kind == ASSIGN_AUG_LOAD) {
EMIT(dup_top);
EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_LOAD);
} else {
if (assign_kind == ASSIGN_AUG_STORE) {
EMIT(rot_two);
}
EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_STORE);
}
return;
}
}
// 编译语法错误,无法对表达式赋值
compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("无法对表达式赋值"));
}
// 编译元组赋值
static void c_assign_tuple(compiler_t *comp, uint num_tail, mp_parse_node_t *nodes_tail) {
// 查找星号表达式
uint have_star_index = -1;
for (uint i = 0; i < num_tail; i++) {
if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
if (have_star_index == (uint)-1) {
// 如果星号表达式是第一个,则进行解包
EMIT_ARG(unpack_ex, i, num_tail - i - 1);
have_star_index = i;
} else {
// 如果有多个星号表达式,则报错
compile_syntax_error(comp, nodes_tail[i], MP_ERROR_TEXT("赋值中不能有多个*"));
return;
}
}
}
if (have_star_index == (uint)-1) {
// 如果没有星号表达式,则进行序列解包
EMIT_ARG(unpack_sequence, num_tail);
}
for (uint i = 0; i < num_tail; i++) {
if (i == have_star_index) {
// 如果是星号表达式,则进行存储赋值
c_assign(comp, ((mp_parse_node_struct_t *)nodes_tail[i])->nodes[0], ASSIGN_STORE);
} else {
// 否则进行存储赋值
c_assign(comp, nodes_tail[i], ASSIGN_STORE);
}
}
}
// 编译赋值操作,将栈顶赋值给pn
static void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
assert(!MP_PARSE_NODE_IS_NULL(pn));
if (MP_PARSE_NODE_IS_LEAF(pn)) {
// 如果是叶子节点,检查是否为标识符
if (MP_PARSE_NODE_IS_ID(pn)) {
qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
// 根据赋值类型执行相应操作
switch (assign_kind) {
case ASSIGN_STORE:
case ASSIGN_AUG_STORE:
compile_store_id(comp, arg);
break;
case ASSIGN_AUG_LOAD:
default:
compile_load_id(comp, arg);
break;
}
} else {
// 如果不是标识符,则报错
goto cannot_assign;
}
} else {
// 如果是结构体节点,根据其种类进行不同的处理
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
case PN_atom_expr_normal:
// 如果是索引或属性访问,编译原子表达式赋值
c_assign_atom_expr(comp, pns, assign_kind);
break;
case PN_testlist_star_expr:
case PN_exprlist:
// 如果是元组,进行元组赋值
if (assign_kind != ASSIGN_STORE) {
goto cannot_assign;
}
c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
break;
case PN_atom_paren:
// 如果是括号中的表达式,进行元组赋值
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// 如果是空元组,则报错
goto cannot_assign;
} else {
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
if (assign_kind != ASSIGN_STORE) {
goto cannot_assign;
}
pns = (mp_parse_node_struct_t *)pns->nodes[0];
goto testlist_comp;
}
break;
case PN_atom_bracket:
// 如果是方括号中的表达式,进行元组赋值
if (assign_kind != ASSIGN_STORE) {
goto cannot_assign;
}
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// 如果是空列表,则允许赋值
c_assign_tuple(comp, 0, NULL);
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pns = (mp_parse_node_struct_t *)pns->nodes[0];
goto testlist_comp;
} else {
// 如果是包含单个元素的方括号,则进行元组赋值
c_assign_tuple(comp, 1, pns->nodes);
}
break;
default:
goto cannot_assign;
}
return;
testlist_comp:
// 如果是序列,进行元组赋值
if (MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns)) {
goto cannot_assign;
}
c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
return;
}
return;
cannot_assign:
// 如果无法赋值,则报错
compile_syntax_error(comp, pn, MP_ERROR_TEXT("无法对表达式赋值"));
}
// 编译lambda表达式和推导式以及生成器的辅助函数
// 如果n_pos_defaults > 0,则栈上有具有位置默认值的元组
// 如果n_kw_defaults > 0,则栈上有具有关键字默认值的字典
// 如果两者都存在,则元组在字典之上(即第一个弹出操作获取元组)
static void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
assert(n_pos_defaults >= 0);
assert(n_kw_defaults >= 0);
// 设置标志
if (n_kw_defaults > 0) {
this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;
}
this_scope->num_def_pos_args = n_pos_defaults;
#if MICROPY_EMIT_NATIVE
// 创建函数/闭包时,将引用当前的全局变量
comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS | MP_SCOPE_FLAG_HASCONSTS;
#endif
// 制作闭包变量,如果有的话
// 确保它们按照外部作用域中定义的顺序进行闭包(主要是为了与CPython一致)
int nfree = 0;
if (comp->scope_cur->kind != SCOPE_MODULE) {
for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
id_info_t *id = &comp->scope_cur->id_info[i];
if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
for (int j = 0; j < this_scope->id_info_len; j++) {
id_info_t *id2 = &this_scope->id_info[j];
if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
// 在MicroPython中,我们使用LOAD_FAST加载闭包
EMIT_LOAD_FAST(id->qst, id->local_num);
nfree += 1;
}
}
}
}
}
// 制作函数/闭包
if (nfree == 0) {
EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
} else {
EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
}
}
// 编译函数定义和lambda表达式的参数
static void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
// 为了提高下面代码的效率,我们先提取解析节点的种类
int pn_kind;
if (MP_PARSE_NODE_IS_ID(pn)) {
pn_kind = -1;
} else {
assert(MP_PARSE_NODE_IS_STRUCT(pn));
pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn);
}
if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {
comp->have_star = true;
/* 不需要区分裸星号和命名星号
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// 裸星号
} else {
// 命名星号
}
*/
} else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) {
// 命名双星号
// TODO 我们需要对这个做什么吗?
} else {
mp_parse_node_t pn_id;
mp_parse_node_t pn_equal;
if (pn_kind == -1) {
// 这个参数只是一个标识符
pn_id = pn;
pn_equal = MP_PARSE_NODE_NULL;
} else if (pn_kind == PN_typedargslist_name) {
// 这个参数有冒号和/或等号指定符
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
pn_id = pns->nodes[0];
// pn_colon = pns->nodes[1]; // 未使用
pn_equal = pns->nodes[2];
} else {
assert(pn_kind == PN_varargslist_name); // 应该是
// 这个参数有等号指定符
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
pn_id = pns->nodes[0];
pn_equal = pns->nodes[1];
}
if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
// 这个参数没有默认值
// 检查非默认参数是否在默认参数之后给出(允许解析器,但语法上无效)
if (!comp->have_star && comp->num_default_params != 0) {
compile_syntax_error(comp, pn, MP_ERROR_TEXT("非默认参数在默认参数之后"));
return;
}
} else {
// 这个参数有一个默认值
// 在CPython中,None(和True,False?)作为默认参数是使用LOAD_NAME加载的;不理解为什么
if (comp->have_star) {
comp->num_dict_params += 1;
// 在MicroPython中,我们使用字节码将默认字典参数放入字典中
if (comp->num_dict_params == 1) {
// 在MicroPython中,我们使用字节码将默认位置参数放入元组中
// 我们需要在开始构建默认关键字的映射之前做这个
if (comp->num_default_params > 0) {
EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
} else {
EMIT(load_null); // 表示空默认位置参数的哨兵
}
// 第一个默认字典参数,所以制作映射
EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
}
// 编译值然后键,然后将其存储到字典中
compile_node(comp, pn_equal);
EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
EMIT(store_map);
} else {
comp->num_default_params += 1;
compile_node(comp, pn_equal);
}
}
}
}
// 编译函数定义和lambda表达式
static void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {
// 当我们调用compile_funcdef_lambdef_param时,它可以编译任意表达式作为默认参数,这可能包含一个lambda。Lambda将在这里以嵌套的方式调用,所以我们必须保存和恢复相关状态。
bool orig_have_star = comp->have_star;
uint16_t orig_num_dict_params = comp->num_dict_params;
uint16_t orig_num_default_params = comp->num_default_params;
// 编译默认参数
comp->have_star = false;
comp->num_dict_params = 0;
comp->num_default_params = 0;
apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);
if (comp->compile_error != MP_OBJ_NULL) {
return;
}
// 在MicroPython中,我们使用字节码将默认位置参数放入元组中
// 默认关键字参数可能已经制作了元组;如果没有,现在就做
if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
EMIT(load_null); // 表示空默认关键字参数的哨兵
}
// 制作函数
close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
// 恢复状态
comp->have_star = orig_have_star;
comp->num_dict_params = orig_num_dict_params;
comp->num_default_params = orig_num_default_params;
}
// 编译函数定义辅助函数,返回函数名称并将其放在栈上
static qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
if (comp->pass == MP_PASS_SCOPE) {
// 为这个函数创建一个新作用域
scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
// 存储函数作用域,以便编译函数在每个阶段都可以使用它
pns->nodes[4] = (mp_parse_node_t)s;
}
// 获取这个函数的作用域
scope_t *fscope = (scope_t *)pns->nodes[4];
// 编译函数定义
compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);
// 返回它的名称("def f(...):"中的'f')
return fscope->simple_name;
}
// 编译类定义辅助函数,返回类名称并将其放在栈上
static qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
if (comp->pass == MP_PASS_SCOPE) {
// 为这个类创建一个新作用域
scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
// 存储类作用域,以便编译函数在每个阶段都可以使用它
pns->nodes[3] = (mp_parse_node_t)s;
}
EMIT(load_build_class);
// 获取这个类的作用域
scope_t *cscope = (scope_t *)pns->nodes[3];
// 编译类
close_over_variables_etc(comp, cscope, 0, 0);
// 获取它的名称
EMIT_ARG(load_const_str, cscope->simple_name);
// nodes[1]包含父类,如果有的话
// 空括号(例如class C():)会作为空的PN_classdef_2到达这里,需要特殊处理
mp_parse_node_t parents = pns->nodes[1];
if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
parents = MP_PARSE_NODE_NULL;
}
compile_trailer_paren_helper(comp, parents, false, 2);
// 返回它的名称("class C(...):"中的'C')
return cscope->simple_name;
}
// 检查是否为内置装饰器(即使内置装饰器有错误),返回true
static bool compile_built_in_decorator(compiler_t *comp, size_t name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
return false;
}
if (name_len != 2) {
compile_syntax_error(comp, name_nodes[0], MP_ERROR_TEXT("无效的micropython装饰器"));
return true;
}
qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
if (attr