MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
这段代码定义了MicroPython的内置模块builtins
,其中包括了许多常用的内置函数和类型。这些函数和类型是Python编程语言的核心部分,提供了基本的操作和功能,如数学运算、迭代器操作、类型转换等。代码中包含了大量的注释,详细解释了每个函数的用途和工作原理,有助于理解MicroPython的内部实现。
#include <stdio.h>
#include <assert.h>
// 导入MicroPython的小型整数和对象类型等头文件
#include "py/smallint.h"
#include "py/objint.h"
#include "py/objstr.h"
#include "py/objtype.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/stream.h"
// 如果启用了浮点数支持,则导入数学库
#if MICROPY_PY_BUILTINS_FLOAT
#include <math.h>
#endif
// 如果启用了I/O支持,声明一个标准输出对象
#if MICROPY_PY_IO
extern struct _mp_dummy_t mp_sys_stdout_obj; // 类型不重要,只需要指针
#endif
// 定义构建类的函数
static mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) {
assert(2 <= n_args); // 确保至少有两个参数
// 设置新类的__locals__对象
mp_obj_dict_t *old_locals = mp_locals_get(); // 获取当前的本地变量字典
mp_obj_t class_locals = mp_obj_new_dict(0); // 创建一个新的空字典对象
mp_locals_set(MP_OBJ_TO_PTR(class_locals)); // 设置为当前的本地变量
// 调用类代码
mp_obj_t cell = mp_call_function_0(args[0]); // 调用类体中的函数
// 恢复旧的__locals__对象
mp_locals_set(old_locals);
// 从基类对象中获取类类型(元对象)
mp_obj_t meta;
if (n_args == 2) {
// 没有显式基类,使用'type'
meta = MP_OBJ_FROM_PTR(&mp_type_type);
} else {
// 使用第一个基类的类型
meta = MP_OBJ_FROM_PTR(mp_obj_get_type(args[2]));
}
// TODO 为多个基类做适当的元类解析
// 使用元对象创建新类
mp_obj_t meta_args[3];
meta_args[0] = args[1]; // 类名
meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // 基类的元组
meta_args[2] = class_locals; // 成员字典
mp_obj_t new_class = mp_call_function_n_kw(meta, 3, 0, meta_args);
// 如果需要,存储到cell中
if (cell != mp_const_none) {
mp_obj_cell_set(cell, new_class);
}
return new_class;
}
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__);
// 定义绝对值函数
static mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
return mp_unary_op(MP_UNARY_OP_ABS, o_in); // 调用一元操作函数,这里是绝对值操作
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);
// 定义all函数,检查迭代器中的所有元素是否都为True
static mp_obj_t mp_builtin_all(mp_obj_t o_in) {
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(o_in, &iter_buf); // 获取迭代器
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
// 遍历迭代器
if (!mp_obj_is_true(item)) {
// 如果有元素不为True
return mp_const_false; // 返回False
}
}
return mp_const_true; // 所有元素都为True,返回True
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all);
// 定义any函数,检查迭代器中是否有任意元素为True
static mp_obj_t mp_builtin_any(mp_obj_t o_in) {
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(o_in, &iter_buf); // 获取迭代器
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
// 遍历迭代器
if (mp_obj_is_true(item)) {
// 如果有元素为True
return mp_const_true; // 返回True
}
}
return mp_const_false; // 没有元素为True,返回False
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);
// 定义bin函数,返回一个整数的二进制字符串表示
static mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
mp_obj_t args[] = {
MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL); // 调用字符串格式化函数
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);
// 定义callable函数,检查对象是否可调用
static mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
if (mp_obj_is_callable(o_in)) {
// 如果对象是可调用的
return mp_const_true; // 返回True
} else {
return mp_const_false; // 否则返回False
}
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);
// 定义chr函数,返回ASCII码对应的字符
static mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
#if MICROPY_PY_BUILTINS_STR_UNICODE
mp_uint_t c = mp_obj_get_int(o_in); // 获取整数
if (c >= 0x110000) {
// 如果字符码超出Unicode范围
mp_raise_ValueError(MP_ERROR_TEXT("chr() arg not in range(0x110000)")); // 抛出值错误
}
VSTR_FIXED(buf, 4); // 创建一个固定大小的字符串缓冲区
vstr_add_char(&buf, c); // 将字符添加到缓冲区
return mp_obj_new_str_via_qstr(buf.buf, buf.len); // 创建并返回新的字符串对象
#else
mp_int_t ord = mp_obj_get_int(o_in); // 获取整数
if (0 <= ord && ord <= 0xff) {
// 如果字符码在ASCII范围内
uint8_t str[1] = {
ord}; // 创建一个字节的字符串
return mp_obj_new_str_via_qstr((char *)str, 1); // 创建并返回新的字符串对象
} else {
mp_raise_ValueError(MP_ERROR_TEXT("chr() arg not in range(256)")); // 抛出值错误
}
#endif
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);
// 定义dir函数,返回对象的属性列表
static mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) {
mp_obj_t dir = mp_obj_new_list(0, NULL); // 创建一个新的空列表
if (n_args == 0) {
// 如果没有参数,返回本地命名空间中的属性列表
mp_obj_dict_t *dict = mp_locals_get(); // 获取本地变量字典
for (size_t i = 0; i < dict->map.alloc; i++) {
// 遍历字典
if (mp_map_slot_is_filled(&dict->map, i)) {
// 如果槽已填充
mp_obj_list_append(dir, dict->map.table[i].key); // 将键添加到列表中
}
}
} else {
// 否则,返回对象的属性列表
// 通过探测所有可能的qstrs与mp_load_method_maybe实现
size_t nqstr = QSTR_TOTAL();
for (size_t i = MP_QSTR_ + 1; i < nqstr; ++i) {
mp_obj_t dest[2];
mp_load_method_protected(args[0], i, dest, false); // 尝试加载方法
if (dest[0] != MP_OBJ_NULL) {
// 如果方法存在
#if MICROPY_PY_ALL_SPECIAL_METHODS
// 支持__dir__特殊方法:查看是否可以调度此特殊方法
// 这依赖于MP_QSTR__dir__在MP_QSTR_之后首先出现
if (i == MP_QSTR___dir__ && dest[1] != MP_OBJ_NULL) {
return mp_call_method_n_kw(0, 0, dest); // 调用方法
}
#endif
mp_obj_list_append(dir, MP_OBJ_NEW_QSTR(i)); // 将qstr添加到列表中
}
}
}
return dir; // 返回属性列表
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir);
// 定义divmod函数,返回两个数的商和余数
static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in,mp_obj_t o2_in) {
return mp_binary_op(MP_BINARY_OP_DIVMOD, o1_in, o2_in); // 调用二元操作函数,这里是取模操作
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod);
// 定义hash函数,返回对象的哈希值
static mp_obj_t mp_builtin_hash(mp_obj_t o_in) {
// 结果保证是一个(小的)整数
return mp_unary_op(MP_UNARY_OP_HASH, o_in); // 调用一元操作函数,这里是哈希操作
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash);
// 定义hex函数,返回一个整数的十六进制字符串表示
static mp_obj_t mp_builtin_hex(mp_obj_t o_in) {
#if MICROPY_PY_BUILTINS_STR_OP_MODULO
return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_x), o_in); // 使用字符串格式化操作
#else
mp_obj_t args[] = {
MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_x_brace_close_), o_in };
return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL); // 调用字符串格式化函数
#endif
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex);
// 如果启用了输入支持,定义input函数
#if MICROPY_PY_BUILTINS_INPUT
#include "py/mphal.h"
#include "shared/readline/readline.h"
// 如果端口定义了mp_hal_readline,将使用自定义函数
#ifndef mp_hal_readline
#define mp_hal_readline readline
#endif
static mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
mp_obj_print(args[0], PRINT_STR); // 打印提示信息
}
vstr_t line;
vstr_init(&line, 16); // 初始化字符串缓冲区
int ret = mp_hal_readline(&line, ""); // 读取一行输入
if (ret == CHAR_CTRL_C) {
// 如果用户输入了Ctrl+C
mp_raise_type(&mp_type_KeyboardInterrupt); // 抛出