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
9 changes: 9 additions & 0 deletions demo/demo-main.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(import (scheme process-context))

(define (main)
(display "Hello from demo-main.scm!")
(newline)
(display "Arguments: ")
(display (command-line))
(newline)
) ;define
9 changes: 9 additions & 0 deletions demo/demo/hello.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
(define-library (demo hello)
(export main)
(import (scheme base))
(begin
(define (main)
(display "Hello from (demo hello)!")
(newline))
)
)
10 changes: 10 additions & 0 deletions demo/demo/lib.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(define-library (demo lib)
(export main)
(import (scheme base)
(scheme write))
(begin
(define (main)
(display "Hello from (demo lib)!")
(newline))
)
)
6 changes: 6 additions & 0 deletions demo/liii/demo-main.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(import (scheme base))

(define (main)
(display "Hello from demo/liii/demo-main.scm!")
(newline)
) ;define
59 changes: 59 additions & 0 deletions devel/200_40.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# [200_40] 新增 gf run 子命令

## 任务相关的代码文件
- src/goldfish.hpp
- devel/200_40.md
- demo/demo-main.scm
- demo/liii/demo-main.scm
- demo/demo/hello.scm

## 如何测试
```bash
# 构建
xmake b goldfish

# 测试运行文件
bin/gf run demo/demo-main.scm

# 测试运行带路径的文件
bin/gf run demo/liii/demo-main.scm

# 测试运行模块(模块需要在 load path 中)
bin/gf run liii.demo-main

# 测试不存在的文件
bin/gf run nonexistent.scm

# 测试没有 main 函数的文件
bin/gf run liii.base
```

## 2026-03-21 实现 gf run 子命令

### What
新增 `gf run` 子命令,支持以下用法:

1. `gf run x/y/z.scm` - 运行指定文件中的 main 函数
2. `gf run x.y` - 导入模块 (x y) 后运行 main 函数
3. `gf run z.scm` - 按文件处理(如果文件不存在则报错)

### 实现逻辑
- 解析 run 子命令后的参数
- 判断目标类型:
- 包含 `/` 或以 `.scm` 结尾:按文件路径处理,检查文件是否存在
- 其他:按模块名处理(如 `liii.string` -> `(liii string)`)
- 导入或加载后,调用 main 函数

### How
在 goldfish.hpp 中添加:
1. 帮助信息中添加 run 子命令说明
2. 添加 run 子命令处理逻辑:
- 获取目标参数
- 判断类型并处理(文件或模块)
- 检查 main 函数是否存在
- 运行 main 函数

### Demo 文件
- `demo/demo-main.scm` - 普通文件形式的 demo
- `demo/liii/demo-main.scm` - 带路径的文件 demo
- `demo/demo/hello.scm` - 模块形式的 demo((demo hello))
83 changes: 83 additions & 0 deletions src/goldfish.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3369,6 +3369,11 @@ display_help () {
cout << " Options:" << endl;
cout << " --only PATTERN Run tests matching PATTERN" << endl;
cout << " (e.g. json, sicp, list-test.scm)" << endl;
cout << " run TARGET Run main function from TARGET" << endl;
cout << " TARGET can be:" << endl;
cout << " FILE.scm Load file and run main" << endl;
cout << " x/y/z.scm Load file and run main" << endl;
cout << " module.name Import (module name) and run main" << endl;
#ifdef GOLDFISH_WITH_REPL
cout << " repl Enter interactive REPL mode" << endl;
#endif
Expand Down Expand Up @@ -4524,6 +4529,84 @@ repl_for_community_edition (s7_scheme* sc, int argc, char** argv) {
return 0;
}

// 处理 run 子命令
if (command == "run") {
// 获取 TARGET 参数
string target;
for (int i= command_index + 1; i < argc; ++i) {
string arg= argv[i];
if (arg == "--mode" || arg == "-m") {
i++; // skip mode value
continue;
}
if (arg.rfind ("--mode=", 0) == 0 || arg.rfind ("-m=", 0) == 0) {
continue;
}
target= arg;
break;
}
if (target.empty ()) {
std::cerr << "Error: 'run' requires TARGET argument.\n" << std::endl;
s7_close_output_port (sc, s7_current_error_port (sc));
s7_set_current_error_port (sc, old_port);
if (gc_loc != -1) s7_gc_unprotect_at (sc, gc_loc);
exit (1);
}

// 判断类型并处理
if (target.find ('/') != string::npos || target.rfind (".scm") == target.length () - 4) {
// 包含 / 或以 .scm 结尾,按文件路径处理
// 检查文件是否存在
std::error_code ec;
if (!fs::exists (target, ec) || !fs::is_regular_file (target, ec)) {
s7_close_output_port (sc, s7_current_error_port (sc));
s7_set_current_error_port (sc, old_port);
if (gc_loc != -1) s7_gc_unprotect_at (sc, gc_loc);
std::cerr << "Error: File not found: " << target << std::endl;
return 1;
}
goldfish_eval_file (sc, target, true);
}
else {
// 按模块名处理,例如: liii.string -> (liii string)
string import_expr= "(import (" + target + "))";
// 将 . 替换为空格
for (size_t i= 0; i < import_expr.length (); ++i) {
if (import_expr[i] == '.') import_expr[i]= ' ';
}
s7_eval_c_string (sc, import_expr.c_str ());
}

errmsg= s7_get_output_string (sc, s7_current_error_port (sc));
if ((errmsg) && (*errmsg)) {
cout << errmsg;
s7_close_output_port (sc, s7_current_error_port (sc));
s7_set_current_error_port (sc, old_port);
if (gc_loc != -1) s7_gc_unprotect_at (sc, gc_loc);
return 1;
}

// 检查并调用 main 函数
s7_pointer main_func= s7_name_to_value (sc, "main");
if ((!main_func) || (!s7_is_procedure (main_func))) {
s7_close_output_port (sc, s7_current_error_port (sc));
s7_set_current_error_port (sc, old_port);
if (gc_loc != -1) s7_gc_unprotect_at (sc, gc_loc);
std::cerr << "Error: No main function found in target: " << target << std::endl;
return 1;
}

// 调用 main 函数
s7_call (sc, main_func, s7_nil (sc));

errmsg= s7_get_output_string (sc, s7_current_error_port (sc));
if ((errmsg) && (*errmsg)) cout << errmsg;
s7_close_output_port (sc, s7_current_error_port (sc));
s7_set_current_error_port (sc, old_port);
if (gc_loc != -1) s7_gc_unprotect_at (sc, gc_loc);
return 0;
}

// 处理直接执行文件(以 .scm 结尾或存在的文件)
// 检查是否是文件
std::error_code ec;
Expand Down
Loading