microPython的源码解析之 compile.c

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 
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

openwin_top

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值