Skip to content

Commit 82e8512

Browse files
committed
[lang0] test about equivalent between recursive functions
1 parent 10b259c commit 82e8512

File tree

6 files changed

+34
-20
lines changed

6 files changed

+34
-20
lines changed

TODO.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
> 支持直接递归函数与相互递归函数,不能判断等价的地方就不判断。
44
5-
[lang0] test about equivalent between recursive functions
5+
[lang0] 学习 prolog 处理递归 term unification without occor check 的方式,
6+
实现更好的 definitional equivalence。
67

78
[lang0] 用中文重新整理 lambda encoding 相关的知识,形成一本书。
89
[lang0] 用中文重新整理 lambda encoding 和 self type 相关的知识。

docs/lang0/examples/factorial.scm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@
1111

1212
factorial
1313

14+
(assert-equal factorial factorial)
15+
16+
(assert-equal
17+
factorial
18+
(lambda (x) (factorial x))
19+
(lambda (y) (factorial y)))
20+
21+
(assert-equal
22+
(lambda (x) (factorial x))
23+
factorial)
24+
1425
(assert-equal (factorial zero) one)
1526
(assert-equal (factorial one) one)
1627
(assert-equal (factorial two) two)

docs/lang0/examples/nat-even-odd.scm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
(if (zero? n) false
1212
(even? (sub1 n))))
1313

14+
(assert-equal even? even?)
15+
(assert-equal odd? odd?)
16+
1417
(assert-equal
1518
(even? zero)
1619
(even? two)

src/lang0/actions/doAp.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export function doAp(target: Value, arg: Value): Value {
1515
}
1616

1717
case "FnRecursive": {
18+
arg = Values.lazyActiveDeep(arg)
19+
1820
if (arg["@kind"] === "NotYet") {
1921
return Values.NotYet(Neutrals.ApRecursive(target, arg.neutral))
2022
}

src/lang0/equivalent/equivalent.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ export function equivalent(
1010
left: Value,
1111
right: Value,
1212
): boolean {
13-
left = prepare(left)
14-
right = prepare(right)
13+
left = Values.lazyActiveDeep(left)
14+
right = Values.lazyActiveDeep(right)
15+
16+
if (right["@kind"] === "FnRecursive" && left["@kind"] === "FnRecursive") {
17+
return left.name === right.name && left.mod === right.mod
18+
}
1519

1620
switch (left["@kind"]) {
1721
case "NotYet": {
@@ -21,32 +25,17 @@ export function equivalent(
2125
)
2226
}
2327

24-
case "Fn": {
28+
case "Fn":
29+
case "FnRecursive": {
2530
const freshName = freshen(ctx.usedNames, left.name)
2631
ctx = ctx.useName(freshName)
2732
const v = Neutrals.Var(freshName)
2833
const arg = Values.NotYet(v)
2934
return equivalent(ctx, Actions.doAp(left, arg), Actions.doAp(right, arg))
3035
}
3136

32-
case "FnRecursive": {
33-
return (
34-
right["@kind"] === "FnRecursive" &&
35-
left.name === right.name &&
36-
left.mod === right.mod
37-
)
38-
}
39-
4037
case "Lazy": {
4138
return equivalent(ctx, Values.lazyActive(left), right)
4239
}
4340
}
4441
}
45-
46-
function prepare(value: Value): Value {
47-
if (value["@kind"] === "Lazy") {
48-
return prepare(Values.lazyActive(value))
49-
}
50-
51-
return value
52-
}

src/lang0/value/lazyActive.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,11 @@ export function lazyActive(lazy: Values.Lazy): Value {
1111
lazy.cache = value
1212
return value
1313
}
14+
15+
export function lazyActiveDeep(value: Value): Value {
16+
if (value["@kind"] === "Lazy") {
17+
return lazyActiveDeep(lazyActive(value))
18+
}
19+
20+
return value
21+
}

0 commit comments

Comments
 (0)