Browse Source

语言虚拟机完成

myuan 2 years ago
parent
commit
c12a5c6e13

+ 24 - 6
3. 简单的数值语言及其虚拟机/code-examples.ve

@@ -1,12 +1,30 @@
 # 这是示例代码
 # 注释的长度受限, /笑
 
-# output(output(1 + 2 * 3 / 4)) # 首先输出`1+2*3/4`为2.5, 之后再输出`2.5`作为输出的长度为3
+output(output(1 + 2 * 3 / 4))     # 首先输出`1+2*3/4`为2.5, 之后再输出`2.5`作为输出的长度为3
 
+f(0) = 0             # 定义函数
+f(x) = x + f(x - 1)  # 函数可以同名, 之后会自动重载决议
+f(x, y) = x + y      # 多个参数也没问题
 
-f(0) = 0
-f(x) = x + f(x - 1)
-f(x, y) = x + y
+output(f(10))        # f(10) = 10 + f(9) = 10 + 9 + f(8) = ... = 10+9+8+7+...+1+0 = 55
+output(f(1, 2))      # f(1, 2) = 1 + 2 = 3
 
-output(f(10))
-output(f(1, 2))
+
+fib(1) = 1                        # 经典斐波那契数列定义
+fib(2) = 1                        # 经典斐波那契数列定义
+fib(x) = fib(x - 1) + fib(x - 2)  # 经典斐波那契数列定义
+output(fib(20))                   # 不用查表了, 这个值是正确的
+
+exp(x, 0) = 1                   # 递归求幂
+exp(x, y) = exp(x, y - 1) * x   # 递归求幂
+square(x) = exp(x, 2)           # 嵌套函数调用, 定义平方函数
+
+output(exp(2, square(2)))       # 2^(2^2)
+
+
+sqrt(x) = sqrt(x, x / 2, 1, 10) # 奇妙的递归求平方根方法, 精度超高, 收敛超快
+sqrt(x, s, y, 0) = s
+sqrt(x, s, y, n) = sqrt(x, (s + y) / 2, x / ((s + y) / 2), n - 1)
+
+output(sqrt(2), square(sqrt(2)))

BIN
3. 简单的数值语言及其虚拟机/exe.exe


BIN
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.e


BIN
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.代码/代码.e


+ 299 - 2
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.代码/代码/即时解释虚拟机.static.e.txt

@@ -1,8 +1,11 @@
 .版本 2
+.支持库 spec
+.支持库 eAPI
 
 .程序集 即时解释虚拟机
 .程序集变量 词, 词, , "0"
 .程序集变量 函数列表, 抽象语法树节点, , "0"
+.程序集变量 上一运算结果, 双精度小数型
 
 .子程序 解释代码入口
     .参数 代码, 文本型
@@ -14,12 +17,306 @@
     .计次循环首 (取数组成员数 (行), i)
         词法分析 (行 [i], 词)
         根 = 语法分析 (词)
-        输出语法分析结果 (根, )
+        ' 输出语法分析结果 (根, )
+        解释代码 (根)
+    .计次循环尾 ()
+    
+
+.子程序 交互运行
+    .局部变量 根, 抽象语法树节点
+    .局部变量 解释返回, 文本型
+
+    .判断循环首 (真)
+        标准输出 (, “ve > ”)
+        词法分析 (标准输入 (), 词)
+        根 = 语法分析 (词)
+        .如果真 (解释代码 (根) = “表达式求值”)
+            标准输出 (, 到文本 (上一运算结果) + #换行符)
+        .如果真结束
+        
+    .判断循环尾 ()
+
+.子程序 解释代码, 文本型
+    .参数 节点, 抽象语法树节点
+    .局部变量 节点语类, 整数型
+    .局部变量 节点词类, 整数型
+    .局部变量 节点参量, 整数型
+    .局部变量 节点名, 文本型
+
+    节点语类 = 节点.获取语类 ()
+    节点词类 = 节点.获取词类 ()
+    节点参量 = 节点.获取参数数量 ()
+    节点名 = 节点.获取函数名 ()
+    
+    .如果真 (节点语类 = #语类_根)
+        .如果 (节点参量 = 1)
+            返回 (解释代码 (节点.获取参数节点 (1)))
+        .否则
+            .如果真 (节点参量 > 1)
+                调试输出 (“警告 根节点有超过一个子节点”)
+            .如果真结束
+            
+        .如果结束
+        
+    .如果真结束
+    
+    .如果真 (节点.包含语类 (#语类_nop))
+        调试输出 (“警告 nop 泄露到了运行时”)
+    .如果真结束
+    
+    .如果真 (节点词类 = #词类_注释)
+        返回 (“注释”)
+    .如果真结束
+    
+    .如果真 (节点语类 = #语类_定义)
+        ' 现在所有的定义都是函数定义
+        添加函数 (节点)
+        返回 (“定义”)
+    .如果真结束
+    
+    .如果真 (节点.包含语类 (#语类_函数调用))
+        ' 这里的函数调用包含 f(x) 式的, 也包含 1+1 式的
+        上一运算结果 = 表达式求值 (节点, , )
+        返回 (“表达式求值”)
+    .如果真结束
+    返回 (“无匹配”)
+    
+
+.子程序 表达式求值, 双精度小数型
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 节点名, 文本型
+    .局部变量 i, 整数型
+    .局部变量 待输出文本组, 文本型, , "0"
+    .局部变量 待输出文本, 文本型
+    .局部变量 节点词类, 整数型
+
+    节点名 = 节点.获取函数名 ()
+    节点词类 = 节点.获取词类 ()
+    ' 调试输出 (“准备表达式求值”, 节点.生成展示文本 (), 可用上层参数名, 可用上层参数值)
+    .如果真 (节点名 = “output”)
+        清除数组 (待输出文本组)
+        .计次循环首 (节点.获取参数数量 (), i)
+            加入成员 (待输出文本组, 格式化文本 (“%s”, 到文本 (表达式求值 (节点.获取参数节点 (i)))))
+        .计次循环尾 ()
+        待输出文本 = 连接字符串 (待输出文本组, “, ”) + #换行符
+        标准输出 (, 待输出文本)
+        返回 (取文本长度 (待输出文本) - 2) ' #换行符长度为2
+    .如果真结束
+    .如果真 (节点名 = “dir”)
+        标准输出 (, “当前函数如下: ” + #换行符)
+        .计次循环首 (取数组成员数 (函数列表), i)
+            标准输出 (, 到文本 (i) + #换行符)
+            输出语法分析结果 (函数列表 [i], )
+        .计次循环尾 ()
+        返回 (取数组成员数 (函数列表))
+    .如果真结束
+    .如果真 (节点词类 = #词类_数字)
+        返回 (到数值 (节点名))
+    .如果真结束
+    .如果真 (节点词类 = #词类_算符)
+        返回 (处理算符 (节点, 可用上层参数名, 可用上层参数值))
+    .如果真结束
+    .如果真 (节点词类 = #词类_括号)
+        返回 (表达式求值 (节点.获取参数节点 (1), 可用上层参数名, 可用上层参数值))
+    .如果真结束
+    .如果真 (节点.获取参数数量 () = 0 且 节点词类 = #词类_标识符)
+        返回 (处理标识符 (节点, 可用上层参数名, 可用上层参数值))
+    .如果真结束
+    
+    ' 到这个地步 只有 f(x) 式的函数调用了
+    返回 (处理函数调用 (节点, 可用上层参数名, 可用上层参数值))
+    
+
+.子程序 处理标识符, 双精度小数型, , 如果要处理标识符值, 应当从当前函数参数值中找匹配的标识符
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 i, 整数型
+    .局部变量 节点名, 文本型
+
+    节点名 = 节点.获取函数名 ()
+    ' 调试输出 (可用上层参数名, 可用上层参数值)
+    .计次循环首 (取数组成员数 (可用上层参数名), i)
+        .如果真 (节点名 = 可用上层参数名 [i])
+            返回 (可用上层参数值 [i])
+        .如果真结束
+        
+    .计次循环尾 ()
+    
+    标准输出 (, “[错误] 找不到标识符: ” + 节点名 + #换行符)
+    标准输入 ()
+    结束 ()
+    返回 (0)
+
+.子程序 处理函数调用, 双精度小数型, , 只处理 f(x) 式的
+    .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 节点名, 文本型
+    .局部变量 节点词类, 整数型
+    .局部变量 参数数量, 整数型
+    .局部变量 i, 整数型
+    .局部变量 函数原型, 抽象语法树节点
+    .局部变量 同参量函数, 抽象语法树节点, , "0"
+    .局部变量 同参量函数_匹配度, 整数型, , "0"
+    .局部变量 当前最大匹配度, 整数型
+    .局部变量 当前最大匹配度索引, 整数型
+
+    .局部变量 同名函数数, 整数型
+    .局部变量 参数求值结果, 双精度小数型, , "0"
+    .局部变量 参数值完全匹配数量, 整数型
+    .局部变量 函数参数索引, 整数型
+    .局部变量 待匹配参数节点, 抽象语法树节点
+    .局部变量 当前待匹配值, 双精度小数型
+    .局部变量 当前匹配度, 整数型
+
+    .局部变量 可用本层参数名, 文本型, 数组, "0"
+    .局部变量 可用本层参数值, 双精度小数型, 数组, "0"
+    .局部变量 待调用函数, 抽象语法树节点
+    .局部变量 当前结果, 双精度小数型
+
+    节点名 = 节点.获取函数名 ()
+    节点词类 = 节点.获取词类 ()
+    参数数量 = 节点.获取参数数量 ()
+    清除数组 (参数求值结果)
+    
+    .计次循环首 (参数数量, i)
+        当前结果 = 表达式求值 (节点.获取参数节点 (i), 可用上层参数名, 可用上层参数值)
+        加入成员 (参数求值结果, 当前结果)
+        ' 调试输出 (“参数求值结果”, 节点.获取参数节点 (i).获取函数名 (), 当前结果)
+    .计次循环尾 ()
+    
+    ' 找同名函数
+    清除数组 (同参量函数)
+    清除数组 (同参量函数_匹配度)
+    
+    清除数组 (可用本层参数名)
+    清除数组 (可用本层参数值)
+    
+    .计次循环首 (取数组成员数 (函数列表), i)
+        函数原型 = 函数列表 [i].获取参数节点 (1)
+        .如果真 (函数原型.获取函数名 () = 节点名)
+            同名函数数 = 同名函数数 + 1
+            .如果真 (函数原型.获取参数数量 () = 参数数量)
+                加入成员 (同参量函数, 函数列表 [i])
+                参数值完全匹配数量 = 0
+                .计次循环首 (参数数量, 函数参数索引)
+                    待匹配参数节点 = 函数原型.获取参数节点 (函数参数索引)
+                    ' 词类是标识符的是未知数  不论如何不会增加最佳匹配量, 之外的, 可以求值然后对比值
+                    ' 如果求值结果不同, 一定不能加入匹配, 直接打散到最小上
+                    .如果真 (待匹配参数节点.获取词类 () ≠ #词类_标识符)
+                        当前待匹配值 = 表达式求值 (待匹配参数节点)
+                        .如果 (当前待匹配值 = 参数求值结果 [函数参数索引])
+                            参数值完全匹配数量 = 参数值完全匹配数量 + 1
+                        .否则
+                            参数值完全匹配数量 = -9999
+                            跳出循环 ()
+                        .如果结束
+                        
+                    .如果真结束
+                    
+                .计次循环尾 ()
+                加入成员 (同参量函数_匹配度, 参数值完全匹配数量)
+            .如果真结束
+            
+        .如果真结束
+        
+    .计次循环尾 ()
+    ' 给出合适的报错
+    .如果真 (同名函数数 = 0)
+        标准输出 (, “[错误] 找不到函数 ” + 节点名 + “. 相关上下文如下: ” + #换行符 + #换行符)
+        输出语法分析结果 (节点, )
+        标准输入 ()
+        结束 ()
+    .如果真结束
+    
+    .如果真 (取数组成员数 (同参量函数) = 0)
+        标准输出 (, “[错误] 找不到可重载函数, 同名函数有: ” + #换行符)
+        .计次循环首 (取数组成员数 (同参量函数), i)
+            标准输出 (, 到文本 (i) + “:” + #换行符)
+            输出语法分析结果 (同参量函数 [i], )
+        .计次循环尾 ()
+        标准输入 ()
+        结束 ()
+    .如果真结束
+    
+    ' 找到最佳匹配度的那个函数
+    当前最大匹配度 = -99999
+    当前最大匹配度索引 = 0
+    .计次循环首 (取数组成员数 (同参量函数), i)
+        当前匹配度 = 同参量函数_匹配度 [i]
+        .如果真 (当前匹配度 > 当前最大匹配度)
+            当前最大匹配度索引 = i
+            当前最大匹配度 = 当前匹配度
+        .如果真结束
         
     .计次循环尾 ()
+    
+    ' 把标识符参数拿出来并给值
+    函数原型 = 同参量函数 [当前最大匹配度索引].获取参数节点 (1)
+    待调用函数 = 同参量函数 [当前最大匹配度索引].获取参数节点 (2)
+    ' 输出语法分析结果 (同参量函数 [当前最大匹配度索引], )
+    ' 输出语法分析结果 (函数原型, )
+    
+    .计次循环首 (参数数量, 函数参数索引)
+        
+        待匹配参数节点 = 函数原型.获取参数节点 (函数参数索引)
+        ' 输出语法分析结果 (待匹配参数节点, )
+        .如果真 (待匹配参数节点.获取词类 () = #词类_标识符)
+            加入成员 (可用本层参数名, 函数原型.获取参数节点 (函数参数索引).获取函数名 ())
+            加入成员 (可用本层参数值, 参数求值结果 [函数参数索引])
+            ' 调试输出 (“可用本层参数”, 函数原型.获取参数节点 (函数参数索引).获取函数名 (), 参数求值结果 [函数参数索引])
+        .如果真结束
+        
+    .计次循环尾 ()
+    
+    
+    ' 调试输出 (“调用一个函数”, 节点.生成展示文本 ())
+    
+    返回 (表达式求值 (待调用函数, 可用本层参数名, 可用本层参数值))
 
-.子程序 解释代码
+.子程序 处理算符, 双精度小数型
     .参数 节点, 抽象语法树节点
+    .参数 可用上层参数名, 文本型, 可空 数组
+    .参数 可用上层参数值, 双精度小数型, 可空 数组
+    .局部变量 节点名, 文本型
+    .局部变量 l, 双精度小数型
+    .局部变量 r, 双精度小数型
 
+    节点名 = 节点.获取函数名 ()
+    ' 调试输出 (可用上层参数名, 可用上层参数值)
     
+    l = 表达式求值 (节点.获取参数节点 (1), 可用上层参数名, 可用上层参数值)
+    r = 表达式求值 (节点.获取参数节点 (2), 可用上层参数名, 可用上层参数值)
+    
+    .判断开始 (节点名 = “+”)
+        返回 (l + r)
+    .判断 (节点名 = “-”)
+        返回 (l - r)
+    .判断 (节点名 = “*”)
+        返回 (l × r)
+    .判断 (节点名 = “/”)
+        返回 (l ÷ r)
+    .默认
+        调试输出 (“警告 遇到奇怪的算符”, 节点名)
+    .判断结束
+    返回 (0)
+
+.子程序 添加函数
+    .参数 节点, 抽象语法树节点
+
+    调试输出 (“新增一个函数”, 节点.获取参数节点 (1).获取函数名 ())
+    加入成员 (函数列表, 节点)
+    
+
+.子程序 取最小, 双精度小数型
+    .参数 a, 双精度小数型
+    .参数 b, 双精度小数型
+
+    .如果真 (a > b)
+        返回 (b)
+    .如果真结束
+    返回 (a)
 

+ 8 - 0
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.代码/代码/抽象语法树节点.class.e.txt

@@ -171,6 +171,14 @@
     .局部变量 字节数组, 通用型, 数组, "0"
 
     返回 (取字节集数据 (指针到字节集 (当前节点指针 + #语法树节点_语类, 4), #整数型, ))
+    
+
+.子程序 包含语类, 逻辑型, 公开
+    .参数 类, 整数型
+    .局部变量 当前语类, 整数型
+
+    当前语类 = 获取语类 ()
+    返回 (位与 (当前语类, 类) ≠ 0)
 
 .子程序 设置词类, , 公开
     .参数 类, 整数型

+ 13 - 3
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.代码/代码/程序集1.static.e.txt

@@ -7,6 +7,7 @@
     代码 = UTF8到文本 (读入文件 (“code-examples.ve”))
     解释代码入口 (代码)
     
+    交互运行 ()
     
     .判断循环首 (真)
         标准输出 (, “> ”)
@@ -37,7 +38,8 @@
         文件名 = t [2]
         代码 = UTF8到文本 (读入文件 (文件名))
         解释代码入口 (代码)
-        
+    .判断 (t [1] = “交互运行”)
+        交互运行 ()
     .默认
         标准输出 (, “未知命令” + #换行符)
     .判断结束
@@ -45,12 +47,20 @@
 
 .子程序 连接字符串, 文本型
     .参数 字符串组, 文本型, 数组
+    .参数 连接词, 文本型
     .局部变量 res, 文本型, 数组
     .局部变量 i, 整数型, 数组
+    .局部变量 组长度, 整数型
 
     res = “”
-    .计次循环首 (取文本长度 (字符串组), i)
+    组长度 = 取数组成员数 (字符串组)
+    
+    .计次循环首 (组长度, i)
         res = res + 字符串组 [i]
+        .如果真 (i < 组长度)
+            res = res + 连接词
+        .如果真结束
+        
     .计次循环尾 ()
-    
+    返回 (res)
 

+ 1 - 0
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.代码/代码/语法分析程序集.static.e.txt

@@ -279,6 +279,7 @@
         右括号 = 当前节点.生成自词节点 (下个词 ())
         词游标自增 ()
         当前节点.初始化内存 (“括号”, 父节点.获取当前节点指针 ())
+        当前节点.设置词类 (#词类_括号)
         当前节点.添加参数节点 (中表达式)
         返回 (当前节点)
         

+ 5 - 0
3. 简单的数值语言及其虚拟机/简单的数值语言及其虚拟机.代码/自定义类型.e.txt

@@ -4,3 +4,8 @@
     .成员 内容, 文本型, 数组
     .成员 类型, 整数型, 数组
 
+.数据类型 函数返回, 公开
+    .成员 函数名, 文本型
+    .成员 有效, 逻辑型
+    .成员 返回值, 双精度小数型
+