microPython的源码解析之 bc.c

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

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

#include <stdbool.h>
#include <string.h>
#include <assert.h>

#include "py/bc0.h"
#include "py/bc.h"
#include "py/objfun.h"

#if MICROPY_DEBUG_VERBOSE // 打印调试信息
#define DEBUG_PRINT (1)
#else // 不打印调试信息
#define DEBUG_PRINT (0)
#define DEBUG_printf(...) (void)0
#endif

void mp_encode_uint(void *env, mp_encode_uint_allocator_t allocator, mp_uint_t val) {
   
    // 我们将每个7位存储在一个单独的字节中,这就是需要的字节数
    byte buf[MP_ENCODE_UINT_MAX_BYTES];
    byte *p = buf + sizeof(buf);
    // 我们以小端序编码,但以大端序存储,以帮助解码
    do {
   
        *--p = val & 0x7f;
        val >>= 7;
    } while (val != 0);
    byte *c = allocator(env, buf + sizeof(buf) - p);
    if (c != NULL) {
   
        while (p != buf + sizeof(buf) - 1) {
   
            *c++ = *p++ | 0x80;
        }
        *c = *p;
    }
}

mp_uint_t mp_decode_uint(const byte **ptr) {
   
    mp_uint_t unum = 0;
    byte val;
    const byte *p = *ptr;
    do {
   
        val = *p++;
        unum = (unum << 7) | (val & 0x7f);
    } while ((val & 0x80) != 0);
    *ptr = p;
    return unum;
}

// 这个函数用于帮助减少调用者栈的使用,对于调用者不需要增加ptr参数的情况。如果ptr是一个局部变量
// 并且调用者使用mp_decode_uint(&ptr)而不是这个函数,那么编译器必须为ptr分配一个栈槽,
// 并且因为这个指针可能存储在全局并在函数中稍后重用,所以这个槽不能被其他东西重用。
mp_uint_t mp_decode_uint_value(const byte *ptr) {
   
    return mp_decode_uint(&ptr);
}

// 这个函数用于帮助减少调用者栈的使用,对于调用者不需要实际值,只想跳过它的情况。
const byte *mp_decode_uint_skip(const byte *ptr) {
   
    while ((*ptr++) & 0x80) {
   
    }
    return ptr;
}

static NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {
   
    #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
    // 通用消息,也用于其他参数问题
    (void)f;
    (void)expected;
    (void)given;
    mp_arg_error_terse_mismatch();
    #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL
    (void)f;
    mp_raise_msg_varg(&mp_type_TypeError,
        MP_ERROR_TEXT("函数需要 %d 个位置参数,但给出了 %d 个"), expected, given);
    #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
    mp_raise_msg_varg(&mp_type_TypeError,
        MP_ERROR_TEXT("%q() 需要 %d 个位置参数,但给出了 %d 个"),
        mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given);
    #endif
}

#if DEBUG_PRINT
static void dump_args(const mp_obj_t *a, size_t sz) {
   
    DEBUG_printf("%p: ", a);
    for (size_t i = 0; i < sz; i++) {
   
        DEBUG_printf("%p ", a[i]);
    }
    DEBUG_printf("\n");
}
#else
#define dump_args(...) (void)0
#endif

// 进入时,code_state 应该在某处分配(栈/堆),并且包含以下有效条目:
//    - code_state->fun_bc 应包含函数对象的指针
//    - code_state->ip 应包含指向序言开头的指针
//    - code_state->sp 应该是:&code_state->state[0] - 1
//    - code_state->n_state 应该是本地状态中对象的数量
static void mp_setup_code_state_helper(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) {
   
    // 这个函数相当复杂。它的主要目的是在速度和RAM使用方面高效地处理常见情况,即只有位置参数。

    // 获取我们想要设置的函数对象(可以是字节码或本地代码)
    mp_obj_fun_bc_t *self = code_state->fun_bc;

    // 获取缓存的 n_state(而不是再次解码它)
    size_t n_state = code_state->n_state;

    // 解码序言
    size_t n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args, n_kwonly_args, n_def_pos_args;
    MP_BC_PRELUDE_SIG_DECODE_INTO(code_state->ip, n_state_unused, n_exc_stack_unused, scope_flags, n_pos_args
  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

openwin_top

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

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

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

打赏作者

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

抵扣说明:

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

余额充值