Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 176 additions & 0 deletions devel/200_58.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# [200_58] 缺失函数提示增强

## 如何测试

### 1. 函数存在,但对应库没有导入
```bash
./bin/gf eval '(path-join "a" "b")'
```

预期会输出类似:

```text
unbound-variable

;unbound variable path-join in (path-join "a" "b")
(path-join "a" "b")

Hint: function `path-join` exists in library `(liii path)`.
Please import that library first: `(import (liii path))`.
```

### 2. 函数在多个库中都有实现
```bash
./bin/gf eval '(remove 1)'
```

预期会输出类似:

```text
Hint: function `remove` exists in multiple visible libraries:
(liii list)
(liii os)
(srfi srfi-1)
Try one of these commands to decide which library to use:
gf doc liii/list "remove"
gf doc liii/os "remove"
gf doc srfi/srfi-1 "remove"
```

### 3. 函数不存在
```bash
./bin/gf eval '(foo 1)'
```

预期会输出类似:

```text
Hint: try `gf doc "foo"` .
`gf doc` may show similarly named functions when there is no exact match.
If it finds nothing similar, try searching the codebase with `git grep "foo"`, implement that function yourself, or stop using it.
```

这里的提示说明了两种情况:

- `gf doc "foo"` 可能会返回与 `foo` 命名相近的函数
- 如果连命名相近的函数也找不到,就建议使用 `git grep` 等工具继续查找,或者自行实现该函数,或者放弃使用

### 4. REPL 中也应当出现同样的提示
```bash
printf '(path-join "a" "b")\n,q\n' | ./bin/gf repl
```

预期会输出类似:

```text
;unbound variable path-join in (path-join "a" "b")
(path-join "a" "b")

Hint: function `path-join` exists in library `(liii path)`.
Please import that library first: `(import (liii path))`.
```

### 5. 嵌套表达式中的缺失函数也应当提示
```bash
./bin/gf eval '((display (path-read-text "/tmp/demo")) 0)'
```

预期会输出类似:

```text
;unbound variable path-read-text ...
...
Hint: function `path-read-text` exists in library `(liii path)`.
Please import that library first: `(import (liii path))`.
```

这一步的意义是确认提示逻辑不只适用于最外层直接调用 `(foo ...)`,也能处理更大的表达式内部出现的未绑定函数。



### 6. 相关测试
```bash
xmake build goldfish
./bin/gf test doc-hint-test.scm
./bin/gf test function-libraries-test.scm
./bin/gf test tests/liii/goldsource/source-command-test.scm
./bin/gf test tests/goldfish/scheme/
```

## 说明

本次改动的目标,是让 Goldfish 在执行一段代码时,如果碰到“函数名未绑定”,能够更准确地区分下面几种情况:

- 函数其实存在,只是还没有导入对应的库
- 函数在多个库里都存在,用户需要先判断自己想用哪个库
- 当前可见的 `*load-path*` 中根本找不到这个函数

为此,本次新增了一条独立于 `gf doc` 实现的函数查找逻辑。运行时不会去依赖 `golddoc` 或 `tests/function-library-index.json`,而是直接扫描当前 `*load-path*` 下的 Scheme 库源码文件,读取 `define-library` 和 `export` 信息,判断某个函数名被哪些库导出。

这条逻辑对外暴露为:

```scheme
(g_function-libraries "string-split")
```

返回值是一个列表,例如:

```scheme
((liii string))
```

如果一个函数在多个库中导出,则会返回多个库名;如果没有找到,则返回空列表。

在报错提示层面,本次统一了多条执行链的行为:

- `gf eval`
- `gf repl`
- `gf load`
- `gf test`
- `gf doc`
- `gf source`

现在这些路径在处理 Scheme 报错时,都会先尝试识别 `unbound variable ...` 是否对应“缺失函数调用”,然后追加更合适的 hint。

具体行为如下:

### 1. 只在一个库中找到

提示用户该函数存在于哪个库,并直接给出建议的 `import` 语句。

### 2. 在多个库中找到

提示该函数存在于多个可见库中,并给出多条:

```bash
gf doc 库 函数
```

形式的命令,让用户逐个查看文档和用例,自己判断该选哪个库。

### 3. 完全找不到

提示用户先调用:

```bash
gf doc 目标函数
```

并明确说明:

- `gf doc` 有可能返回命名相近的函数
- 如果没有任何命名相近的函数,就建议使用 `git grep` 等工具搜索代码库,或者自己实现该函数,或者放弃使用

## 额外修复

在这次整理过程中,还顺手修复了 `gf source` 的一个问题。

`tools/goldsource/liii/goldsource-cli.scm` 内部直接调用了 `path-read-text`,但之前没有导入 `(liii path)`,导致:

```bash
./bin/gf source liii/path
```

会错误地报出 `path-read-text` 未绑定。现在已经补上该导入,`gf source` 会正常输出目标库的源码。

## 2026/04/03 缺失函数提示增强,并补齐 REPL 与 source 场景
Loading
Loading