nondescript:一款简单的嵌入式编程语言

Lobsters Hottest 工具

摘要

Nondescript 是一种全新的单文件、可嵌入 C 项目的脚本语言,采用 AppleScript 风格语法,支持列表推导、可扩展语法等特性。

<p><a href="https://lobste.rs/s/ivj2o8/nondescript_simple_embedded">评论</a></p>
查看原文 导出为 Word 导出为 PDF
查看缓存全文

缓存时间: 2026/04/22 21:06

deadpixi/nondescript 源码:https://github.com/deadpixi/nondescript

Nondescript

一款可嵌入 C 应用的极简脚本语言。Nondescript 的定位与 Lua 类似:体积小巧、单文件实现,可零依赖地编译进任何 C 项目。

特性

  • 单文件实现 —— 一个 .c 和一个 .h,仅依赖 C 标准库
  • 兼容 C11(实为 C99 + _Alignof
  • AppleScript 风格语法 —— 受自然语言启发,大小写不敏感
  • 可扩展语法 —— 用自定义关键字模式注册宿主命令
  • Chunk 访问器 —— word 1 of myStringitem 3 of myList 等,可在运行时注册自己的 chunk 类型
  • given 代码块 —— 向函数传入一段代码
  • 列表推导 —— set nonSpaces to every character of myString where it != ' '
  • 可插拔分配器 —— 内置池分配器与限额分配器

编译

Nondescript 设计为直接编译进你的工程:

#include "nondescript.h"
cc -o myapp myapp.c nondescript.c -lm

快速上手

#include <stdio.h>
#include "nondescript.h"

int main(int argc, char **argv) {
    if (argc < 2) {
        fprintf(stderr, "usage: nds <script.nds>\n");
        return 1;
    }
    NDSConfig config = {0};
    NDSContext *ctx = NDSContext_new(&config);
    NDSStatus status = NDSContext_evaluateFile(ctx, argv[1]);
    if (status != NDSStatus_OK)
        fprintf(stderr, "%s\n", NDSContext_getError(ctx));
    NDSContext_free(ctx);
    return status == NDSStatus_OK ? 0 : 1;
}
-- 函数
function greet(name)
    println("hello, ", name, "!")
end function
greet("world")

-- Chunk 与 set 表达式
set firstItem to item 1 of ["foo", "bar", "baz"]
println("firstItem:", firstItem)

-- 列表推导
set nonSpaces to every character of "foo bar baz" where it != ' '
println("nonSpaces:", nonSpaces)

-- 代码块
function map(input)
    my result is []
    for each item i in input do
        append given(i) to result
    end for
    return result
end function

set plus2 to map([1, 2, 3]) given (i)
    return i + 2
end given
println("plus2:", plus2)

-- 块作用域。Set 会设置最近一层的绑定。
-- 使用 "my" 显式声明内部绑定。所有结构都会引入新作用域。
function functionScope()
    my outer is "outer"
    if true then
        my outer
        set outer to "inner now!"
        println("inside if block:", outer)
    end if
    println("outside if block:", outer)
end function
functionScope()

-- 错误处理按函数划分
function errorFunction()
    my NaN is 1 / 0
    on error myError
        println("errored:", myError)
    end function
errorFunction()

-- 错误会向上冒泡
function innerError()
    raise nothing message "foo"
end function

function outerError()
    innerError()
    on error myError
        println("got error with message", message of myError)
    end function
outerError()

示例

examples/ 目录:

  • calc —— 在脚本里定义函数,通过 NDSContext_callFunction 从 C 调用
  • turtle —— 注册自然语言宿主命令(move forward 100turn right 90),运行脚本并输出 SVG

编译示例:

cd examples
c11 -o turtle turtle.c ../nondescript.c
./turtle

许可证

Apache 2.0

TODO

  • 字节/字符的分裂很奇怪……应该拆成独立类型。
  • 大量小修小补。NDSValue/NDSObject 的拆分也很丑……

相似文章

Show HN: Nibble

Hacker News Top

Nibble 是一种类 C 的系统编程语言,用 3000 行 C 代码实现,无需外部依赖或堆分配即可生成 LLVM IR。它支持 defer、递归、多种类型、结构体、指针,并包含图形演示。

Nanopass Framework: 简洁编译器构建语言

Hacker News Top

Nanopass Framework 是一种嵌入在 Scheme 中的领域特定语言,用于通过小的遍历和中间表示来创建编译器,减少样板代码并提高可维护性。