Build a new program language called "z" like python and base on python.
v1_base 实现了基础的四则运算、基础类型、变量、print 基础: 实现了整数和浮点数两种数字类型。 能力: 支持加+、减-、乘*、除/四则运算,并能通过括号( )控制优先级。 状态管理: 实现了变量赋值=和读取,让语言拥有了最基础的“记忆”能力。 交互: 内置了一个print函数,作为语言与外部世界沟通的第一个窗口。 核心成就: 我们成功搭建了从 Lexer -> Parser -> Interpreter 的完整语言处理流水线。
增加if语句,增加比较运算符和布尔逻辑,比较运算符==和!=用关键字isE和notE来替代。 决策能力: 引入了if/else语句,这是语言的第一次认知飞跃,使其从一个线性执行的脚本,变成了一个可以做出决策的程序。 独特的语法: 我们共同设计了z语言独有的比较关键字isE (等于) 和 notE (不等于),彻底消除了=与==的混淆。 比较能力: 增加了全套的有序比较运算符 (>, <, >=, <=)。
字符串、注释和类型安全 新数据类型: 引入了字符串 ("..."),极大地扩展了语言的表达范围,使其能处理非数字信息。 字符串操作: 实现了字符串的拼接 (+) 和重复 (*),赋予了基本的文本处理能力。 人性化: 引入了注释 (#) 功能,这标志着我们开始关注代码作为“人类交流媒介”的属性。
布尔类型、逻辑运算符、代码部分重构、加入起始和结束位置方便定位错误 新数据类型: 引入了真正的布尔值 (True, False),使语言的类型系统更加清晰和严谨。 逻辑推理: 实现了核心逻辑运算符and, or, not,使语言能够进行复杂的逻辑组合与推理。 专业特性: 实现了and和or的短路求值,这是一个专业语言必备的高效、安全特性。
while、代码块
function、闭包
list
for
break、contine
break、contine和解释器中的运行时错误处理重构 利用宿主语言的“异常处理” 性能差: 异常处理在大多数语言中都是一个“重型”操作,不应该用于常规的控制流。 依赖特性: 如果我们想用C语言重写我们的解释器,这个方法就完全行不通了。 逻辑模糊: 它将一种语言(“z”语言)的控制流,与另一种语言(Python)的错误处理机制混在了一起,逻辑上不够纯粹。
因此,创建我们自己的“信使” (RuntimeResult)
RuntimeResult对象就像一份详尽的“任务执行状态报告”。这份报告包含了所有上层调用者需要知道的一切信息:
self.value:- 职责: 存放本次任务的“产出物”,也就是成功计算出的那个
Value对象(Number,StringValue等)。 - 对应: 正常情况下,函数应该返回什么。
- 职责: 存放本次任务的“产出物”,也就是成功计算出的那个
self.error:- 职责: 存放任务执行过程中发生的“事故报告”,也就是一个
RTError对象。 - 对应: 如果计算出错了(如除以零),这里就不为空。
- 职责: 存放任务执行过程中发生的“事故报告”,也就是一个
self.should_return/should_break/should_continue:- 职责: 这三个布尔标志位,是信使携带的“紧急指令旗帜”。
- 对应:
return,break,continue关键字。当解释器visit到一个ReturnNode时,它不会返回一个普通的RuntimeResult,而是会调用.success_return()来创建一个举着“返回”旗帜的信使。register方法的设计逻辑:一个“信息汇总站”
register方法的设计,是为了解决一个核心问题:当我在一个复杂的表达式(如a + b)中,如何处理子表达式(a和b)可能产生的错误或信号?
register就像一个严格的“安检员”或“信息汇总员”。它的逻辑是:
“我被派去执行一个子任务(比如
self.visit(node.left_node, ...))。这个子任务会派回它自己的信使(res)。我的职责是:
- 检查信使的旗帜: 我要检查这个信使是否举着任何“错误”或“紧急指令”的旗帜。
- “污染”我自己的报告: 如果我发现任何旗帜,我必须立刻在我自己的状态报告(
self)中,也举起同样的旗帜。- 提取纯粹的产出: 如果一切正常,我就从信使的包裹里,取出那个纯粹的“产出物”(
res.value),然后返回它,供我的上级(比如加法操作)使用。”
register的return语句是关键:return res.value。它确保了在正常的执行路径中,代码可以写得很自然:
left = res.register(self.visit(node.left_node, context))
如果visit成功,left就会被赋值为那个纯粹的Number对象,而不是整个RuntimeResult。
但是,如果visit失败了,res.register在将错误“注册”到res上之后,if res.error: return res这条检查就会被触发,从而立即中断当前函数的执行,并将这个带有错误信息的、被“污染”的res对象,原封不动地传递给更上层的调用者。
v11 调用栈 构建完整的函数调用栈
v12 同时可用==和isE表示值相等
v13 自定义类