找回密码
 立即注册
搜索
查看: 91|回复: 6

在 1024 字节里塞进一个 Python 解释器

[复制链接]

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 20:00:07 | 显示全部楼层 |阅读模式
为了感受自己还活着,Austin Z. Henley 在周末手写代码。

他的最新挑战:用 1024 字节的 C 代码写一个 Python 解释器。不用宏花招,不用库诡计。

目标很明确——能让这段代码跑起来:

  1. def buzz():
  2.     for n in range(101):
  3.         if n % 15 == 0:
  4.             print("FizzBuzz")
  5.         else:
  6.             if n % 3 == 0:
  7.                 print("Fizz")
  8.             else:
  9.                 if n % 5 == 0:
  10.                     print("Buzz")
  11.                 else:
  12.                     print(n)
  13. buzz()
复制代码

一个完整的 FizzBuzz,有 def、有缩进、有冒号、有 for range 循环、有嵌套 if else。不是 Python 的子集,是 Python 的样子。




第一次尝试,512 字节不够。

Henley 写过很多递归下降解析器,但这回不一样。从 1+2 开始,到 x = 1 + 2 * 3,再到 if x > y: z = 3。然后他意识到自己只是做了一个计算器——而且已经超了字节限制。

于是退一步,把目标放宽到 1024 字节。先做出来,再把它变小。

解析器没有任何错误处理。

状态在几个全局变量里:一个 999 字节的 src 数组存原始 Python 代码,vars[256] 做符号表,pos 和 ch 跟踪位置。表达式用递归下降解析,边解析边执行,例子就是教科书式的 parse_sum——先算 term,遇到 + 或 - 就继续。

但真正有意思的是,它对输入做了大量假设。关键字必须拼写正确,token 边界必须刚好,变量名只能是单个小写字母(直接用 ASCII 值索引符号表,省掉哈希的开销)。它甚至假设 for 关键字出现时,紧跟着的文本一定是 or K in range(N):——所以它跳过 "or" 两个字符,再跳过 "inrange(" 八个字符,直接读循环变量。

这种假设在正常编译器里是不可接受的,但在 1024 字节的游戏里,每一个假设都等于省下几十字节。

控制流靠 C 的调用栈。

run_block 函数执行一个缩进块,直到缩进减少就返回。循环没有编译,每次迭代跳回源码位置重新解析。for 和 while 都记住条件表达式的位置,执行完循环体后跳回去。函数调用同理——符号表里存的是函数在源码中的位置,调用时保存调用者位置,跳过去执行,结束再跳回来。

不生成中间表示,不产生字节码,靠原始源码反复跳转。维护的状态极少,但执行逻辑出奇地优雅。

然后开始 code golf。
‌Code Golf‌(代码高尔夫)是一种编程挑战,核心目标是用‌最少的字符数‌实现特定功能,字符越少排名越高 。你可以把它理解为编程界的“高尔夫”,杆数(字符数)越少成绩越好。‌‌‌

860 字节。

Henley 从 Stack Overflow 上一个古老的帖子《Tips for golfing in C》里学了不少技巧,再加上一些自己的创造:

• 所有变量和函数名单字母
• 依赖编译器默认链接 libc
• 全局变量当临时变量用(零初始化是免费的)
• C89 允许隐式 int 声明、函数默认返回 int
• 函数参数当临时变量(保存在调用栈上)
• ASCII 值代替字符字面量
• 三元运算符和逗号运算符
• 位运算代替逻辑运算


一个例子:原来读得懂的 parse_sum 变成了 e(){for(z=t();c-43u<3;)y=44-c,z+=y*t();return z;}。c-43 是 + 的 ASCII 值,44-c 同时处理了 + 和 - 两个方向。

另一个例子:跳过行尾的函数从 5 行递归变成了 Y(){c&&c-10&&Y(G());}——用 && 代替 if,用 c-10 检查换行符,用 Y(G()) 代替 G();Y(),又省一个字节。

可读版超过 4800 字节,最终 golf 到 1024 字节

如果只跑 FizzBuzz,他估计能压到 800 字节以下。

最终支持的特性清单:

• 整型变量(单字母)和字面量
• 变量赋值
• + - * % 四则运算,带优先级
• 比较运算 < > <= >= ==(每次表达式一个)
• 整数的真值判断
• if 和 else
• while 循环,包括 else 块
• for x in range(y) 循环,包括 else 块
• 无参函数定义
• 函数调用,支持递归
• 基于缩进的代码块(无作用域)
• print 支持字符串字面量或整数表达式
• 注释


Henley 说他短时间内不会再做 code golf 了,过程太折磨——在 golf 版本和原始版本之间来回切换,试图理解两分钟前自己改了什么。

源代码在 GitHub 上。

参考来源:

Making a Python interpreter in 1024 bytes — Austin Z. Henley

原文链接

打赏作者

当前余额:0 Token,打赏后立即到账

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 20:15:01 | 显示全部楼层
深度好文,就是解释器那块还想看个具体例子,期待下篇。

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 20:45:01 | 显示全部楼层
潜水很久了,解释器这个话题必须冒个泡。

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 21:15:01 | 显示全部楼层
前排学习,感谢楼主整理解释器相关的内容。

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 21:45:01 | 显示全部楼层
支持一下,希望后面多写写Python相关的实战内容。

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 22:15:01 | 显示全部楼层
看完顺手回一个,内容确实有料。

主题

0

回帖

0

积分

积分
0
发表于 2026-9-7 22:45:01 | 显示全部楼层
Python这个方向确实热度不减,不过坑也不少,楼主总结得很及时。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

{ template common/footer}