MicroPython 是一种适用于微控制器和其他受限环境的 Python 编程语言的实现。它旨在提供与 Python 3 语言的紧密兼容,同时考虑到内存和计算资源的限制。MicroPython 库是这门语言的核心组成部分,提供了一系列的模块和函数,使得开发者能够在硬件上执行各种任务。
下面将通过系列文章,逐一解读microPython,以便让读者了解掌握microPython的整个核心逻辑.,以便读者可以透过这个Python的最小内核,掌握Python解析器的核心实现逻辑,学习世界上最优秀的源码设计之一.
microPython Python最小内核源码解析
这段代码是MicroPython的整数对象实现的一部分,它包含了创建、打印、转换和操作整数对象的相关函数和数据结构。代码中包含了对不同整数实现的支持,包括小整数和长整数,以及对浮点数转换为整数的处理。此外,还提供了从字节序列创建整数和将整数转换为字节序列的功能。代码中的注释详细解释了每个函数的作用和实现细节。
#include <stdlib.h>
#include <assert.h>
#include <string.h>
// 导入MicroPython特定的头文件
#include "py/parsenum.h"
#include "py/smallint.h"
#include "py/objint.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/binary.h"
// 如果启用了浮点数支持
#if MICROPY_PY_BUILTINS_FLOAT
#include <math.h>
#endif
// 这个构造函数用于创建新的整数对象,与长整型的实现无关
static mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
(void)type_in; // 忽略传入的类型信息
mp_arg_check_num(n_args, n_kw, 0, 2, false); // 检查参数数量和关键字参数的数量
// 根据传入的参数数量进行不同的处理
switch (n_args) {
case 0: // 无参数,返回0
return MP_OBJ_NEW_SMALL_INT(0);
case 1: {
// 一个参数
mp_buffer_info_t bufinfo;
mp_obj_t o = mp_unary_op(MP_UNARY_OP_INT_MAYBE, args[0]); // 尝试将参数转换为整数
if (o != MP_OBJ_NULL) {
return o;
} else if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
// 如果参数是文本表示,解析它
return mp_parse_num_integer(bufinfo.buf, bufinfo.len, 0, NULL);
#if MICROPY_PY_BUILTINS_FLOAT
} else if (mp_obj_is_float(args[0])) {
// 如果参数是浮点数
return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
#endif
} else {
mp_raise_TypeError_int_conversion(args[0]); // 抛出类型错误
}
}
case 2: // 两个参数,默认为字符串解析
default: {
// 解析字符串形式的整数
size_t l;
const char *s = mp_obj_str_get_data(args[0], &l);
return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
}
}
}
// 如果启用了浮点数支持
#if MICROPY_PY_BUILTINS_FLOAT
// 枚举定义浮点数转换为整数的类别
typedef enum {
MP_FP_CLASS_FIT_SMALLINT, // 适合小整数
MP_FP_CLASS_FIT_LONGINT, // 适合长整数
MP_FP_CLASS_OVERFLOW // 溢出
} mp_fp_as_int_class_t;
// 根据浮点数值判断其转换为整数的类别
static mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
// 联合体用于读取浮点数的二进制表示
union {
mp_float_t f;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
uint32_t i;
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
uint32_t i[2];
#endif
} u = {
val};
uint32_t e;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
e = u.i;
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
e = u.i[MP_ENDIANNESS_LITTLE];
#endif
#define MP_FLOAT_SIGN_SHIFT_I32 ((MP_FLOAT_FRAC_BITS + MP_FLOAT_EXP_BITS) % 32)
#define MP_FLOAT_EXP_SHIFT_I32 (MP_FLOAT_FRAC_BITS % 32)
// 处理符号位
if (e & (1U << MP_FLOAT_SIGN_SHIFT_I32)) {
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
e |= u.i[MP_ENDIANNESS_BIG] != 0;
#endif
if ((e & ~(1U << MP_FLOAT_SIGN_SHIFT_I32)) == 0) {
// 处理-0的情况
e = 0;
} else {
e += ((1U << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
}
} else {
e &= ~((1U << MP_FLOAT_EXP_SHIFT_I32) - 1);
}
// 计算指数部分
// 8 * sizeof(uintptr_t) 计算小整数的位数
if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) {
return MP_FP_CLASS_FIT_SMALLINT;
}
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
if (e <= (((sizeof(long long) * MP_BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) {
return MP_FP_CLASS_FIT_LONGINT;
}
#endif
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
return MP_FP_CLASS_FIT_LONGINT;
#else
return MP_FP_CLASS_OVERFLOW;
#endif
}
#undef MP_FLOAT_SIGN_SHIFT_I32
#undef MP_FLOAT_EXP_SHIFT_I32
// 从浮点数创建一个新的整数对象
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
mp_float_union_t u = {
val};
// 如果浮点数的指数部分全为1,说明是无穷大或NaN
if (u.p.exp == ((1 << MP_FLOAT_EXP_BITS) - 1)) {
if (u.p.frc == 0) {
// 无穷大
mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("can't convert inf to int"