microPython的源码解析之 parse.c

本文深入解析MicroPython的parse.c源码,帮助读者理解MicroPython核心逻辑,特别是解析器的工作原理,涉及内存管理、常量折叠等关键功能。通过一系列文章,逐步剖析MicroPython的实现,适合嵌入式硬件和Python开发者学习。
摘要由CSDN通过智能技术生成

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


microPython Python最小内核源码解析
NI-motion运动控制c语言示例代码解析
python编程示例系列 python编程示例系列二
python的Web神器Streamlit


#include <stdbool.h> // 包含布尔类型定义
#include <stdint.h> // 包含整数类型定义
#include <stdio.h> // 包含标准输入输出定义
#include <unistd.h> // 包含 ssize_t 类型定义,用于跨平台的文件描述符操作
#include <assert.h> // 包含断言宏
#include <string.h> // 包含字符串操作函数

// 包含 MicroPython 相关的头文件
#include "py/lexer.h"
#include "py/parse.h"
#include "py/parsenum.h"
#include "py/runtime.h"
#include "py/objint.h"
#include "py/objstr.h"
#include "py/builtin.h"

// 预处理器指令,用于条件编译
#if MICROPY_ENABLE_COMPILER

// 定义规则动作的掩码,用于解析器内部表示规则的行为
#define RULE_ACT_ARG_MASK       (0x0f)
#define RULE_ACT_KIND_MASK      (0x30)
#define RULE_ACT_ALLOW_IDENT    (0x40)
#define RULE_ACT_ADD_BLANK      (0x80)
#define RULE_ACT_OR             (0x10)
#define RULE_ACT_AND            (0x20)
#define RULE_ACT_LIST           (0x30)

// 定义规则参数的掩码,用于解析器内部表示规则的参数
#define RULE_ARG_KIND_MASK      (0xf000)
#define RULE_ARG_ARG_MASK       (0x0fff)
#define RULE_ARG_TOK            (0x1000)
#define RULE_ARG_RULE           (0x2000)
#define RULE_ARG_OPT_RULE       (0x3000)

// 关闭格式化,避免代码在复制过程中被编辑器格式化
// *FORMAT-OFF*

// 枚举所有规则,包括有编译函数的规则和无编译函数的规则
enum {
   
// 定义有编译函数的规则
#define DEF_RULE(rule, comp, kind, ...) RULE_##rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC

    // 特殊节点,用于表示一个常量,通用的 Python 对象
    RULE_const_object,

// 定义无编译函数的规则
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) RULE_##rule,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};

// 定义一个数组,对应每个规则的动作
static const uint8_t rule_act_table[] = {
   
#define or(n)                   (RULE_ACT_OR | n)
#define and(n)                  (RULE_ACT_AND | n)
#define and_ident(n)            (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT)
#define and_blank(n)            (RULE_ACT_AND | n | RULE_ACT_ADD_BLANK)
#define one_or_more             (RULE_ACT_LIST | 2)
#define list                    (RULE_ACT_LIST | 1)
#define list_with_end           (RULE_ACT_LIST | 3)

#define DEF_RULE(rule, comp, kind, ...) kind,
#define DEF_RULE_NC(rule, kind, ...) kind,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC

    0, // RULE_const_object

#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) kind,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC

#undef or
#undef and
#undef and_ident
#undef and_blank
#undef one_or_more
#undef list
#undef list_with_end
};

// 定义规则参数数据的数组,合并存储
static const uint16_t rule_arg_combined_table[] = {
   
#define tok(t)                  (RULE_ARG_TOK | MP_TOKEN_##t)
#define rule(r)                 (RULE_ARG_RULE | RULE_##r)
#define opt_rule(r)             (RULE_ARG_OPT_RULE | RULE_##r)

#define DEF_RULE(rule, comp, kind, ...) __VA_ARGS__,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC

#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...)  __VA_ARGS__,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC

#undef tok
#undef rule
#undef opt_rule
};

// 定义宏,用于创建 N 个标识符的列表,N 是宏的参数数量
#define RULE_EXPAND(x) x
#define RULE_PADDING(rule, ...) RULE_PADDING2(rule, __VA_ARGS__, RULE_PADDING_IDS(rule))
#define RULE_PADDING2(rule, ...) RULE_EXPAND(RULE_PADDING3(rule, __VA_ARGS__))
#define RULE_PADDING3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) __VA_ARGS__
#define RULE_PADDING_IDS(r) PAD13_##r, PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r,

// 使用枚举创建规则参数在 rule_arg_combined_table 中占用空间的常量
enum {
   
#define DEF_RULE(rule, comp, kind, ...) RULE_PADDING(rule, __VA_ARGS__)
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
#define_DEF_RULE(rule, comp, kind, ...)
#define_DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};

// 定义宏,用于计算规则参数在 rule_arg_combined_table 中的起始位置
#define RULE_ARG_OFFSET(rule, ...) RULE_ARG_OFFSET2(rule, __VA_ARGS__, RULE_ARG_OFFSET_IDS(rule))
#define RULE_ARG_OFFSET2(rule, ...) RULE_EXPAND(RULE_ARG_OFFSET3(rule, __VA_ARGS__))
#define RULE_ARG_OFFSET3(rule, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) _14
#define RULE_ARG_OFFSET_IDS(r) PAD13_##r, PAD12_##r, PAD11_##r, PAD10_##r, PAD9_##r, PAD8_##r, PAD7_##r, PAD6_##r, PAD5_##r, PAD4_##r, PAD3_##r, PAD2_##r, PAD1_##r, PAD0_##r,

// 使用上述枚举值创建每个规则参数数据的偏移表,索引 rule_arg_combined_table
// 偏移量需要 9 位存储,但这里只存储低 8 位。第 9 位在 get_rule_arg 函数中计算
static const uint8_t rule_arg_offset_table[] = {
   
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
    0, // RULE_const_object
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};

// 定义一个常量,用于确定 rule_arg_offset_table 中值的第 9 位
static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 =
#define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) >= 0x100 ? RULE_##rule :
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
#define_DEF_RULE(rule, comp, kind, ...)
#define_DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
0;

#if MICROPY_DEBUG_PARSE_RULE_NAME
// 定义一个数组,对应每个规则的名称
static const char *const rule_name_table[] = {
   
#define DEF_RULE(rule, comp, kind, ...) #rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
    "", // RULE_const_object
#define_DEF_RULE(rule, comp, kind, ...)
#define_DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};
#endif

// 定义解析器栈的结构体
typedef struct _rule_stack_t {
   
    size_t src_line : (8 * sizeof(size_t) - 8); // 源代码行号,使用位字段存储
    size_t rule_id : 8; // 规则标识符,使用位字段存储
    size_t arg_i; // 参数索引,指示 "列表" 中的元素数量
} rule_stack_t;

// 定义解析器块的结构体
typedef struct _mp_parse_chunk_t {
   
   size_t alloc;
    union {
   
        size_t used;
        struct _mp_parse_chunk_t *next;
    } union_;
    byte data[];
} mp_parse_chunk_t;

// 定义解析器的结构体
typedef struct _parser_t {
   
    size_t rule_stack_alloc;
    size_t rule_stack_top;
    rule_stack_t *rule_stack;

    size_t result_stack_alloc;
    size_t result_stack_top;
    mp_parse_node_t *result_stack;

    mp_lexer_t *lexer;

    mp_parse_tree_t tree;
    mp_parse_chunk_t *cur_chunk;

    #if MICROPY_COMP_CONST
    mp_map_t consts;
    #endif
} parser_t;

// 定义函数原型
static void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args);

// 定义获取规则参数的函数
static const uint16_t *get_rule_arg(uint8_t r_id) {
   
    size_t off = rule_arg_offset_table[r_id];
    if (r_id >= FIRST_RULE_WITH_OFFSET_ABOVE_255) {
   
        off |= 0x100;
    }
    return &rule_arg_combined_table[off];
}

// 定义解析器的内存分配函数
static void *parser_alloc(parser_t *parser, size_t num_bytes) {
   
    // 使用自定义的内存分配器,将解析节点顺序存储在大块内存中

    mp_parse_chunk_t *chunk = parser->cur_chunk;

    if (chunk != NULL && chunk->union_.used + num_bytes > chunk->alloc) {
   
        // 如果当前块没有足够的空间,则尝试扩展
        mp_parse_chunk_t *new_data = (mp_parse_chunk_t *)m_renew_maybe(byte, chunk,
            sizeof(mp_parse_chunk_t) + chunk->alloc,
            sizeof(mp_parse_chunk_t) + chunk->alloc + num_bytes, false);
        if (new_data == NULL) {
   
            // 无法扩展现有内存;将其缩小以适应之前的使用情况
            (void)m_renew_maybe(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc,
                sizeof(mp_parse_chunk_t) + chunk->union_.used, false);
            chunk->alloc = chunk->union_.used;
            chunk->union_.next = parser->tree.chunk;
            parser->tree.chunk = chunk;
            chunk = NULL;
        } else {
   
            // 扩展现有内存成功
            chunk->alloc += num_bytes;
        }
    }

    if (chunk == NULL) {
   
        // 没有之前的块,分配一个新块
        size_t alloc = MICROPY_ALLOC_PARSE_CHUNK_INIT;
        if (alloc < num_bytes) {
   
            alloc = num_bytes;
        }
        chunk = (mp_parse_chunk_t *)m_new(byte, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

openwin_top

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

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

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

打赏作者

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

抵扣说明:

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

余额充值