Skip to content

pscm cc

logo

pscm cc 是 PikachuHy's Scheme 的 C++ 实现版本,代码规模约 14000+ 行(42 个源文件)。该版本参考 Guile 1.8,基于 setjmp/longjmp 实现了 continuation 支持,并完整实现了模块系统和文件加载功能。

WARNING

pscm 依然处于非常简陋的状态

设计目标

利用有限的 C++ 特性实现一个精简版本的 Guile 1.8,保留驱动 TeXmacs 所需的必要特性。

📋 详细功能列表和开发规划:请参考 pscm_cc 功能现状与开发规划

核心架构

类型系统

  • 统一类型:所有值都是 struct SCM(内部为 void*
  • 类型转换:通过 cast<Type>(scm) 转换为具体类型,通过 wrap(type) 包装为 SCM
  • 支持类型:19 种数据类型(NONE, NIL, LIST, NUM, FLOAT, RATIO, CHAR, STR, SYM, BOOL, PROC, FUNC, CONT, MACRO, HASH_TABLE, VECTOR, PORT, PROMISE, MODULE
  • 源位置跟踪:每个 AST 节点携带可选的源位置信息(文件名、行号、列号),用于错误报告

数据结构

  • 列表:使用 SCM_List 链表实现,支持 dotted pair
  • 环境:链表结构,通过 parent 指针实现词法作用域链
  • 哈希表:链式哈希表,支持 eq?eqv?equal? 三种比较方式
  • 向量:固定长度数组,支持随机访问

求值器

  • 尾递归优化:使用 goto 减少栈深度
  • 模块化设计:每个特殊形式独立文件,统一接口在 eval.h 声明
  • 支持的特殊形式define, lambda, if, cond, case, and, or, begin, let/let*/letrec, do, for-each, map, quote, quasiquote, apply, call/cc, call-with-values, dynamic-wind, delay, define-module, use-modules, export, define-public
  • 宏系统define-macro 支持定义宏,支持 dotted pair 参数列表;macroexpand-1macroexpand 用于调试宏展开

Continuation 实现

  • 机制:基于 setjmp/longjmp,通过栈复制保存和恢复执行上下文
  • 动态 wind:支持 dynamic-wind,在 continuation 跳转时执行 before/after thunk
  • 模块状态保存:continuation 会保存和恢复当前模块上下文,确保变量查找正确
  • 打印格式#<continuation@地址>

解析器

  • 实现:从零实现的递归下降解析器
  • 语法支持:完整的 Scheme 语法(数字、符号、字符串、布尔值、列表、引号、准引用、点对、注释)
  • 特殊处理:支持 1+1- 作为符号(避免被解析为数字和运算符)
  • 错误报告:包含文件名、行号、列号的清晰错误信息

C/C++ 函数注册

兼容 Guile 1.8 接口,支持三种注册方式:

  • 固定参数scm_define_function(name, req, opt, rst, func_ptr)
  • 泛型函数scm_define_generic_function(name, func_ptr, init_val)(如 +*
  • 可变参数scm_define_vararg_function(name, func_ptr)(如 listapply

内置函数

支持丰富的内置函数,包括:

  • 类型检查procedure?, boolean?, null?, pair?, char?, number?
  • 列表操作car, cdr, cons, list, append, set-car!, set-cdr!
  • 数字运算+, -, *, /, expt, abs, gcd, lcm 等(支持整数、浮点数、分数混合运算)
  • 字符串操作string-length, make-string, string-ref, string-set!, string=?, string<?, string<=?, substring, string-append, string->list, list->string, display, write
  • 字符操作char=?, char<?, char>?, char<=?, char>=?, char-upcase, char-downcase, char->integer, integer->char
  • 向量操作make-vector, vector-length, vector-ref, vector-set!, vector->list, list->vector
  • 哈希表:完整的哈希表操作集(创建、设置、获取、删除、遍历)
  • 端口操作open-input-file, open-output-file, open-input-string, open-output-string, read, read-char, peek-char, write-char, eof-object?, char-ready?, call-with-input-file, call-with-output-file
  • 系统操作exit
  • 延迟求值delay, force(Promise 支持)
  • 模块操作current-module, set-current-module, resolve-module, module-ref, module-bound?
  • 文件加载load, primitive-load(支持 %load-path 路径搜索)
  • 宏调试工具macroexpand-1, macroexpand(用于调试宏展开)
  • 其他gensym, not, eval, equal?, eq?, eqv?

代码组织

模块划分

  • 核心pscm.h(类型定义)、eval.h(求值接口)、eval.cc(主求值器)
  • 特殊形式do.cc, cond.cc, case.cc, map.cc, apply.cc, quasiquote.cc, macro.cc, let.cc, for_each.cc, values.cc, delay.cc, define.ccandoreval.cc 中实现)
  • 内置函数predicate.cc, number.cc, list.cc, string.cc, char.cc, eq.cc, alist.cc, hash_table.cc, vector.cc, port.cc, exit.cc
  • 模块系统module.cc(模块定义、查找、导入导出)、load.cc(文件加载)
  • 基础设施parse.cc(解析器)、print.cc(打印)、continuation.cc(continuation)、environment.cc(环境)、source_location.cc(源位置)、dynwind.cc(dynamic-wind)

错误处理

  • 统一使用 eval_error 函数
  • 错误信息包含完整源位置
  • 宏展开时自动传播源位置
  • 调用栈追踪:自动追踪表达式求值路径,错误时显示完整调用栈(最多 20 层)
  • 增强的错误报告:包含表达式类型、值、源位置和完整求值上下文

已知限制

  1. 内存管理:未实现垃圾回收(GC),所有分配的内存不会释放,存在内存泄漏风险
  2. 错误处理:多数情况下直接 exit(1),缺少优雅的错误恢复机制(已有调用栈追踪)
  3. 性能:环境查找使用线性搜索(O(n)),符号比较使用 memcmp
  4. 缺失功能:Guile API 兼容层(C API 接口)、垃圾回收机制等

下一步计划

高优先级

  • 实现垃圾回收机制
  • Guile API 兼容层(C API 接口)

中优先级

  • 错误处理机制(异常捕获,当前已有调用栈追踪)
  • 模块系统完善(公共接口、延迟绑定等高级特性)

已实现功能

模块系统 ✅

  • 模块定义define-module 支持模块命名和选项
  • 模块使用use-modules 支持从其他模块导入符号
  • 模块导出exportdefine-public 支持符号导出
  • 模块查找:支持从模块的 obarrayuses 列表和根模块中查找变量
  • 模块解析resolve-module 支持从文件系统加载模块(通过 %load-path
  • 模块查询module-refmodule-bound? 等查询函数

文件加载 ✅

  • 文件加载loadprimitive-load 支持加载 Scheme 文件
  • 路径搜索:支持 %load-path 变量,可配置模块搜索路径
  • 模块集成:加载文件时自动处理 define-module,支持模块文件自动加载

This website is released under the MIT License.