MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
#include <assert.h>
#include "py/emit.h"
#include "py/nativeglue.h"
#if MICROPY_ENABLE_COMPILER
// 如果启用了字节码编译器
#if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
// 函数:mp_emit_common_use_qstr,用于在编译时查找或添加字符串常量
qstr_short_t mp_emit_common_use_qstr(mp_emit_common_t *emit, qstr qst) {
// 在字符串映射中查找或添加字符串常量
mp_map_elem_t *elem = mp_map_lookup(&emit->qstr_map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
// 如果该值未被设置,则为其分配一个新的小整数索引
if (elem->value == MP_OBJ_NULL) {
elem->value = MP_OBJ_NEW_SMALL_INT(emit->qstr_map.used - 1);
}
// 返回字符串常量的索引
return MP_OBJ_SMALL_INT_VALUE(elem->value);
}
#endif
// 函数:strictly_equal,用于比较两个对象是否类型和值完全相同
static bool strictly_equal(mp_obj_t a, mp_obj_t b) {
// 如果两个对象的地址相同,则它们相等
if (a == b) {
return true;
}
#if MICROPY_EMIT_NATIVE
// 如果对象是函数表,则它们不相等
if (a == MP_OBJ_FROM_PTR(&mp_fun_table) || b == MP_OBJ_FROM_PTR(&mp_fun_table)) {
return false;
}
#endif
// 获取两个对象的类型
const mp_obj_type_t *a_type = mp_obj_get_type(a);
const mp_obj_type_t *b_type = mp_obj_get_type(b);
// 如果类型不同,则对象不相等
if (a_type != b_type) {
return false;
}
// 如果类型是元组
if (a_type == &mp_type_tuple) {
// 获取元组对象
mp_obj_tuple_t *a_tuple = MP_OBJ_TO_PTR(a);
mp_obj_tuple_t *b_tuple = MP_OBJ_TO_PTR(b);
// 如果元组长度不同,则不相等
if (a_tuple->len != b_tuple->len) {
return false;
}
// 比较元组中的每个元素
for (size_t i = 0; i < a_tuple->len; ++i) {
if (!strictly_equal(a_tuple->items[i], b_tuple->items[i])) {
return false;
}
}
// 所有元素都相等,元组相等
return true;
} else {
// 使用标准的对象比较函数进行比较
return mp_obj_equal(a, b);
}
}
// 函数:mp_emit_common_use_const_obj,用于查找或添加常量对象
size_t mp_emit_common_use_const_obj(mp_emit_common_t *emit, mp_obj_t const_obj) {
// 遍历常量对象列表
for (size_t i = 0; i < emit->const_obj_list.len; ++i) {
// 如果找到相同的对象,则返回其索引
if (strictly_equal(emit->const_obj_list.items[i], const_obj)) {
return i;
}
}
// 将常量对象添加到列表末尾
mp_obj_list_append(MP_OBJ_FROM_PTR(&emit->const_obj_list), const_obj);
// 返回新添加对象的索引
return emit->const_obj_list.len - 1;
}
// 函数:mp_emit_common_get_id_for_modification,用于获取或添加修改标识符信息
id_info_t *mp_emit_common_get_id_for_modification(scope_t *scope, qstr qst) {
// 在作用域中查找或添加标识符
id_info_t *id = scope_find_or_add_id(scope, qst, ID_INFO_KIND_GLOBAL_IMPLICIT);
// 如果标识符是隐式全局的
if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
// 如果作用域是函数类似的,则将其绑定为局部变量
if (SCOPE_IS_FUNC_LIKE(scope->kind)) {
id->kind = ID_INFO_KIND_LOCAL;
} else {
// 标记为已赋值,防止其被闭包捕获
id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT_ASSIGNED;
}
}
// 返回标识符信息
return id;
}
// 函数:mp_emit_common_id_op,用于根据标识符信息生成相应的代码
void mp_emit_common_id_op(emit_t *emit, const mp_emit_method_table_id_ops_t *emit_method_table, scope_t *scope, qstr qst) {
// 确保所有标识符都在当前作用域中定义
// 在作用域中查找标识符
id_info_t *id = scope_find(scope, qst);
assert(id != NULL);
// 根据标识符的类型调用相应的代码生成函数
if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT || id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT_ASSIGNED) {
// 生成全局变量的代码
emit_method_table->global(emit, qst, MP_EMIT_IDOP_GLOBAL_NAME);
} else if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {