microPython的源码解析之 modbuiltins.c

MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.

microPython 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); // 抛出
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

openwin_top

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

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

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

打赏作者

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

抵扣说明:

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

余额充值