diff --git a/TODO.md b/TODO.md index 1282eb38..dc3e0a93 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ # articles -[docs] 反应网编程 -- 完成 `mul` 的讲解 [docs] 反应网编程 -- 完成 `List` 的讲解 [docs] 反应网编程 -- 完成 `DiffList` 的讲解 diff --git "a/docs/articles/\345\217\215\345\272\224\347\275\221\347\274\226\347\250\213.md" "b/docs/articles/\345\217\215\345\272\224\347\275\221\347\274\226\347\250\213.md" index 9310351e..5b63ce0f 100644 --- "a/docs/articles/\345\217\215\345\272\224\347\275\221\347\274\226\347\250\213.md" +++ "b/docs/articles/\345\217\215\345\272\224\347\275\221\347\274\226\347\250\213.md" @@ -711,8 +711,116 @@ three two max # 10 -TODO `mul`, `nat_erase`, `nat_dup` -- 零返回值和多返回值。 +我们已经分析了代表加法的节点 `(add)`, +下面我们来分析代表乘法的节点 `(mul)`。 + +我们将会发现,为了定义 `(mul)` 与 `(zero)` 和 `(add1)` 之间的反应规则, +我们又要引入两个新的辅助节点: + +- `(nat_erase)` 删除一个自然数。 +- `(nat_dup)` 复制一个自然数。 + +这两个节点与之前的所有节点都不一样, +之前的所有节点都有一个输出节点, +然而: + +- `(nat_erase)` 有零个输出节点。 +- `(nat_dup)` 有两个输出节点。 + +这其实是我们使用栈来构造网的主要原因。 + +使用栈的好处之一是, +可以自然地处理零个返回值和多个返回值的节点, +而不必为它们设计新的特殊的语法。 + +决定使用栈来构造网之后,就进而决定使用纯粹的后缀表达式作为语法。 +这样的零一个好处是,词之间复合具有结合性, +因此当我们想要把一个词的定义中的一部分切分出来,定义成新的词时, +不用考虑那么多语法上相互影响的地方。 + +下面我们就不用 ASCII 画图了, +点开去演算场的连接, +就可以看到自动渲染出来的图。 + +在下面的代码中,我们用了一个新的语法关键词 `import` 来从其他模块中引入定义。 + +- 一个文件对应一个模块。 +- 用 `.i` 作为文件名后缀。 +- 可以使用完整的 URL `https//...` 来指定文件, + 也可以使用相对路径 `./...` 来指定文件。 + +我们还用了一种新的词 `$local` 来将栈顶的值保存到名为 `local` 的局部变量中。 + +- 用 `$local` 保存一个值之后,可以通过调用 `local` 来取出这个值。 +- 取出之后,`$local` 就空了,就又可以用于保存新的值了。 + + +[去 `Nat` 与 `(mul)` 的演算场](https://inet.run/playground/aW1wb3J0CiAgTmF0LCB6ZXJvLCBhZGQxLCBhZGQsCiAgb25lLCB0d28sIHRocmVlLApmcm9tICJodHRwczovL2Nkbi5pbmV0LnJ1bi90ZXN0cy9kYXRhdHlwZS9OYXQuaSIKCm5vZGUgbmF0X2VyYXNlCiAgTmF0IDp0YXJnZXQhCiAgLS0tLS0tLS0KZW5kCgpydWxlIHplcm8gbmF0X2VyYXNlIGVuZAoKcnVsZSBhZGQxIG5hdF9lcmFzZQogIChhZGQxKS1wcmV2IG5hdF9lcmFzZQplbmQKCm5vZGUgbmF0X2R1cAogIE5hdCA6dGFyZ2V0IQogIC0tLS0tLS0tCiAgTmF0IDpzZWNvbmQKICBOYXQgOmZpcnN0CmVuZAoKcnVsZSB6ZXJvIG5hdF9kdXAKICB6ZXJvIGZpcnN0LShuYXRfZHVwKQogIHplcm8gc2Vjb25kLShuYXRfZHVwKQplbmQKCnJ1bGUgYWRkMSBuYXRfZHVwCiAgKGFkZDEpLXByZXYgbmF0X2R1cCAkZmlyc3QgJHNlY29uZAogIGZpcnN0IGFkZDEgZmlyc3QtKG5hdF9kdXApCiAgc2Vjb25kIGFkZDEgc2Vjb25kLShuYXRfZHVwKQplbmQKCm5vZGUgbXVsCiAgTmF0IDp0YXJnZXQhCiAgTmF0IDptdWxlbmQKICAtLS0tLS0tLQogIE5hdCA6cmV0dXJuCmVuZAoKcnVsZSB6ZXJvIG11bAogIChtdWwpLW11bGVuZCBuYXRfZXJhc2UKICB6ZXJvIHJldHVybi0obXVsKQplbmQKCnJ1bGUgYWRkMSBtdWwKICAobXVsKS1tdWxlbmQgbmF0X2R1cCAkZmlyc3QgJHNlY29uZAogIChhZGQxKS1wcmV2IGZpcnN0IG11bCBzZWNvbmQgYWRkCiAgcmV0dXJuLShtdWwpCmVuZAoKdHdvIG5hdF9kdXAgJGZpcnN0ICRzZWNvbmQKCnR3byB0d28gbXVsCgp0aHJlZSB0aHJlZSBtdWw) + +``` +import + Nat, zero, add1, add, + one, two, three, +from "https://cdn.inet.run/tests/datatype/Nat.i" + +node nat_erase + Nat :target! + -------- +end + +rule zero nat_erase end + +rule add1 nat_erase + (add1)-prev nat_erase +end + +node nat_dup + Nat :target! + -------- + Nat :second + Nat :first +end + +rule zero nat_dup + zero first-(nat_dup) + zero second-(nat_dup) +end + +rule add1 nat_dup + (add1)-prev nat_dup $first $second + first add1 first-(nat_dup) + second add1 second-(nat_dup) +end + +node mul + Nat :target! + Nat :mulend + -------- + Nat :return +end + +rule zero mul + (mul)-mulend nat_erase + zero return-(mul) +end + +rule add1 mul + (mul)-mulend nat_dup $first $second + (add1)-prev first mul second add + return-(mul) +end + +two nat_dup $first $second + +two two mul + +three three mul +``` + +# 11 TODO `List` -- `append` 如何与 `add` 类似。 +# 12 + TODO `DiffList` -- 对表达式与图的反思 -- 简单的图也是双线连接的表达式。 diff --git a/tests/datatype/Nat.i b/tests/datatype/Nat.i index ac6defb4..e6930bf3 100644 --- a/tests/datatype/Nat.i +++ b/tests/datatype/Nat.i @@ -50,7 +50,10 @@ node nat_erase end rule zero nat_erase end -rule add1 nat_erase (add1)-prev nat_erase end + +rule add1 nat_erase + (add1)-prev nat_erase +end node nat_dup Nat :target!