实现一个中文编程语言:从经典结构开始
theme: cyanosis
highlight: a11y-dark
任意计算一: 解释器词令
未经审视的人生不值得过
__苏格拉底 在审判后 放弃流亡,选择饮下毒酒。
我们说:
审视过往,使用中文方块字去计算。
__记实现一个mini版tree-walk解释器内核的快乐过程。
0 写在前面
真理好言值得重复。 优秀的人生和经验值借鉴。
从前以为,他人越过或达到的高峰,我再去就没有了意义。
他人得出了真理,我也没有必要去验证。
因为一个失去了原创性的产品,就像装了马粪的圣杯,一个失去贞操的有洁癖的人。(抱歉这个比喻可能不恰当,但是一时半会想不出其他,网络流行语:文化有待提高)。
实际上,优秀的真理发现 和 独特的产品发明,值得大众学习和借鉴,并且对于普通人具有无穷尽的启发性,比如运势八卦(格局低了)。
但是这里我不打算继续谈论古老的运势结构,也许在将来可能继续。
我想在这里谈论一些结构,一些基于现代科学文明的启示,我们现在知道蒸汽机,电灯,自行车的结构,更复杂的如汽车是多种结构的组合,直升机,大型运输机更加进一步发展了这个逻辑。
在谈论计算机时,这里不谈论量子计算机这样前卫潮流的高大上概念,也不去回顾沿用至今的冯.诺伊曼的经典电子计算组织结构。
我们希望回顾的是,计算机是如何"思考和计算"的,或者说,人们如何让计算机具备了“思考”的能力。
鄙人认为,让一堆铁疙瘩加了油可以在物理世界开始运行跑起来,和让一个铁疙瘩通电后可以计算和思考一样,是真理好言,值得我们去重复和借鉴。
本系列将尝试在3个大的章节内,企图实现可用、快速的语言所需的最基本要素的介绍。
简介: 什么样的产出值得拥有
今天很多编程的方式让人有些头疼,好像越来越无聊,因为没有机会做新鲜事。进行这样的工作的人们的兴奋来自于有趣结果,而不是通过创造新事物得到的那种兴奋。
语言是一个巨大的话题,有成堆的概念和术语可以讨论。它在理论需要一定程度的精神上的严谨,我们可能从未有过这种精神。但是我们不打算在这里讨论太多概念。
我们已经习惯于工程方面的事情诸如DDD,MVC,MTV…,但是这里实现解释器使用了一些在其他类型的应用程序中不常见的架构方式。
鉴于所有这些,我们将让我们必须编写的代码尽可能简单明了。
所以在不到一千行干净的代码中,我们将为 Otao 构建一个完整的解释器,
它属于一种“高级”语言的一部分,使用者不必知道内部的实现细节,不必了解阴暗的角落,不过我们将要路过那里。
1 经典结构: 执行计算
在进入其中每一个黑暗和杂乱的角落之前,如果我们立即开始为解释器编写代码,而看不到我们最终会得到什么似乎很残忍. 我们先查看它的结构。
这里有一个示例,我们使用寄存器模拟函数的调用,以执行计算和输出结果。
我们需要模拟 逻辑与或,加减乘除,以及输出结果,我们约定
为了方便理解,我们规定如下词素:
中文 英文 运算符
刷 print PRINTI /PRINTF
与(按位) LAND &&
或(按位) LOR ||
加 PLUS +
减 MINUS -
乘 TIMES *
除 DIVIDE /
拜托,用刷 来表示打印 print 实在难懂,太低级,太幼稚,很不科学,客人们不喜欢… 等一下,我们只是为了与“古老的” 活字印刷术关联起来。
我们不希望退回到 。 - | 丿 仄 , 这里不用刷漆,刷墙,只是把结果 "刷"到 控制台,或者文本中,似乎没有那么过分。
我们将使用这些来完成最常见的二元运算,也就是运算符两侧的子表达式是操作数。因为有两个,所以它们被称为二元运算符。
为了保持时髦,考虑到我们中有多少人整天都在使用OOP语言。如您所见,我们也制造OOP的代码用以执行。
结果非常有趣。没有你担心的那么难,可以说很简单,引人入胜。
首先在你本机保存如下
将要使机器计算的内容 testxzh.bl
刷 149 加 151;
刷 49 乘 511 减 22 乘 100;
刷 149 除 51;
刷 222222222 乘 555555555;
刷 2 与 2;
刷 3 或 4;
类似的英文的如下: 保存如下内容为 testxen.bl
print 49 + 51 + 100;
print 49 + 51 - 101;
print 12345679 * 99999;
print 3 && 2;
print 3 || 4;
下载执行程序:
二进制版本
https://github.com/hahamx/otao/tree/main/builds/zhbitao
win版本
https://github.com/hahamx/otao/tree/main/builds/enbitao || zhbitao
执行中文代码:
.\zhbitao.exe .\testxzh.bl
得到输出:
read code from file:.\testxzh.bl
刷 49 加 51;
刷 149 加 151;
刷 49 乘 511 减 22 乘 100;
刷 149 除 51;
刷 222222222 乘 555555555;
刷 2 与 2;
刷 3 或 4;
Debug Result:
100
300
22839
2
123456789876543210
2
7
我们将深入一些观察这一切是如何进行的。
2 摄入扫描: 积跬步以至千里,从哪儿开始让计算机开始“思考”
从最初的 图灵的(turing)想法,输入,运算,输出。 无限的输入,无限的运算,无限的输出。
扫描对我们来说也是一个很好的起点,因为代码并不难,一个指令,几个表达式,
在我们实际扫描一些代码之前,我们需要勾勒出解释器Otao 的基本形状。一切都开始于一个类。
import (
"fmt"
"os"
"path/filepath"
"reflect"
)
/*
@param cpath: 可选代码路径,如果没有指定,将加载默认 的代码路径
/按行 读取 代码文件,并存储在链表中
/表示最多读 并存入chan 1000行
*/
func ReadCodeToString(cpath ...string) string {
if cpath != nil {
code_path = cpath[0]
}
fileBytes, err := os.ReadFile(code_path)
if err != nil {
return ""
}
return string(fileBytes)
}
3 结语:
选择发布在华为博客这个平台,是希望借平台这个巨人看的更远。 谢谢。
- 点赞
- 收藏
- 关注作者
评论(0)