microPython的源码解析之 objint.c

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"
  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

openwin_top

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

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

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

打赏作者

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

抵扣说明:

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

余额充值