2个版本

0.1.1 2023年9月20日
0.1.0 2023年9月20日

#288编程语言


用于 seraphine-cli

MIT 许可证

170KB
4.5K SLoC

seraphine

seraphine是一种动态的、强类型和解释型的编程语言。

目前,seraphine是我探索将可读源代码转换为可执行代码过程的学习和实验项目。这就是为什么它的语言核心没有使用外部依赖实现。由于解释器非常原始,seraphine目前非常慢。在我的机器上,与等效的Python实现相比,sudoku示例慢了约2.5倍,与等效的Rust实现相比慢了约200倍。

了解语言的最佳方式是看一个示例

// This function returns a new counter object. Since the last expression is
// returned automatically, we can simply use double curly braces.
fn new_counter(initial_count) {{
    count: initial_count,
    previous_counts: [],
    increment() {
        // `this` receiver to access object
        this.previous_counts.push(this.count)
        this.count = this.count + 1
    },
    for_each_count(func) {
        // Boolean coercion
        if (func) {
            // For loops to iterate over lists
            for (c in this.previous_counts) {
                func(c)
            }
        }
    },
    get_initial_count() {
        if (this.previous_counts.length == 0) {
            return this.count
        } else {
            return this.previous_counts[0]
        }
    },
}}

counter = new_counter(42)
println("Counter at", counter.count)
while (counter.count < 45) {
    counter.increment()
}
println("Counter at", counter.count)

// Anonymous functions (closures are possible)
counter.for_each_count(fn (count) {
    println("Counter was", count)
})

println("Initial count was", counter.get_initial_count())

更多示例可以在示例目录中找到。

特性

  • 算术和逻辑运算
  • 带有 else ifelse 的if语句
  • while和for循环
    • breakcontinue
  • 内置和用户定义的函数
    • 函数自动返回最后一个表达式
  • 类型
    • null
    • 数字
    • 布尔
    • 字符串
    • 函数
    • 列表
    • 对象
    • 迭代器
  • 对值进行索引和成员访问
  • this 对象方法接收者
  • 从stdin读取并写入stdout和stderr
  • 使用 // 的注释
  • 对换行字符进行宽松解析,允许将代码拆分为多行
  • 用户友好的错误消息,包括堆栈跟踪
    • 注意:堆栈跟踪目前在REPL中不可用
  • REPL(读取-评估-打印循环)

执行模型

有两种可能的执行Seraphine代码的方式。这没有实际用途。这只是语言发展的方式——由于这是一个学习项目,我想保留两种方法。

第一种方法是较老的一种:直接由 评估器 评估抽象语法树(AST)。

第二种方法使用 AST 生成简单的指令形式的字节码。然后,虚拟机(VM) 执行这些指令。字节码也可以被序列化。

目前,序列化的字节码还包含编译它的代码。该代码仅用于在运行时错误发生时生成用户友好的错误信息。

REPL

可以使用 REPL 与语言进行交互式探索并评估代码。要启动 REPL,将 repl 作为 CLI 的第一个参数传递(例如:seraphine repl)。REPL 目前使用评估器执行代码。

REPL 使用原始终端并提供以下功能:

  • 在当前行移动光标
  • 历史记录
  • 清屏
  • 评估不适合一行代码的代码(例如,具有非平凡主体的 if 语句)

构建和运行

由于 Seraphine 是用 Rust 实现的,因此您首先需要 安装 Rust 工具链

要在调试模式下运行 REPL,可以使用以下命令:cargo run -- repl。您也可以选择使用 cargo run -- eval my_file.sr 评估文件。为了获得更好的性能,您应该在 cargo run 之后放置 --release 标志。为了仅构建可执行文件,请使用 cargo build --release。可执行文件将放在目录 target/release 中。

测试

所有 Seraphine 功能都由测试覆盖。使用 cargo test --workspace 运行测试套件。

工作空间结构

  • seraphine-core 包含核心功能(令牌化器、解析器、评估器、字节码生成和序列化、VM)
  • seraphine-cli 包含 CLI 和 REPL 功能的可执行文件

无运行时依赖