豫言 / 技术规范

本篇描述 4cdeca1 的实现。版本与适用边界见基线说明。

文件后缀

豫言用文件后缀区分文件的种类。源文件一律以全角句号加“豫”字结尾(。豫),模块名与种类段之间也用全角句号,如 字节串。豫、宿主。接口。豫、逐元。底层。测试。豫。后缀决定四件事:文件里能写什么、无体声明由谁提供、按哪种模式编译,以及导入时能找到哪些模块。本篇按当前仓库列出全部后缀,每种附一个仓库里的例子:缀一是源文件,缀二是导入时的查找次序,缀三是文档、测试数据、构建产物等其他文件。各子语言共同遵守的设计原则及其配合方式见子语言设计。

各条以“缀”编号。

缀一:源文件

导入路径只写模块名,种类段由编译器按缀二补上。例如 寻观「豫章」之「形制」之「帛书」之书。 找到的文件是 库/豫章/形制/帛书。豫。

高级源文件

高级源文件有垃圾回收,编成 WasmGC 模块。

后缀 含义 例子
名。豫 普通源文件,一个文件是一个模块;顶层只有定义,值只能是数据(见执行与编译行一) 库/豫章/形制/帛书。豫
名。脚本。豫 脚本:顶层就是程序体,按次序执行;可以单独构建运行,也可以用 豫构 运行 直接运行(提案 00003);不能被导入;有同名期望输出(。期望 或 。成功)的由全树测试按编译执行与单元装载两种方式各跑一遍 应用/度量/列段/基准。脚本。豫
名。会话。豫 会话:编程智能体捉刀的一场会话(提案 00036)。行首(前面只许空白)是 | 的行是篇里块的内容,读源码时先整行清空、换行留下,其余就是一篇脚本,照脚本编译运行;| 行里写什么都不必转义。这个写法只在会话文件里有效。不能被导入,不算包里的模块;格式化与格式检查跳过它 会话。会话。豫
名。测试。豫 单元测试:顶层就是程序体,可以单独构建运行;构建库时跳过,全树测试自动发现并运行;只有测试与脚本能导入测试 应用/豫构/包系统。测试。豫
名。接口。豫 宿主接口:只写类型与 乃 签名,由宿主或构建时绑定的适配提供实现;每个声明编成带类型的 Wasm 导入,导入模块名是所在包的短名 库/豫章/东道。接口。豫,导入模块“标准库”
名。应用接口。豫 应用接口:由应用或库实现,入口或任一链进的普通模块定义了同名顶层函数时编成导出 豫寓榫卯/网页服务/网页理。应用接口。豫
名。内建。豫 内建声明:编译器提供的语言原语,签名按编译器的原语表核对 库/豫章/本原/本术。内建。豫

着色文件

着色文件用豫言标准语法写 GPU 着色程序,详见着色语言。

后缀 含义 例子
名。着色器。豫 着色源:类型检查后译成 WGSL、MSL 与 PTX;高级代码导入它,得到构建时生成的模块 库/算阵/公用。着色器。豫
名。着色器。接口。豫 着色内建声明:着色目标提供的运算与内建函数 库/点染/点染本。着色器。接口。豫
名。着色生成。豫 虚拟路径:高级代码导入着色源时得到的生成模块,由翻译器在构建时生成,只存在于编译过程中 导入 公用。着色器。豫 得到 公用。着色生成。豫

设计语言

设计语言(提案 00018)的作品用构造写法写在设计源文件里,由引擎库「设计」求值、渲染。

后缀 含义 例子
名。设计。豫 设计源:顶层就是程序体,可以调用函数(编译期常量折叠由运行顶层求得),定义作品「作品」;任何源文件都能按模块名导入它,导入后顶层在载入时求值 库/匠心/样例/你好。设计。豫
名。设计 设计二进制:树码的种类「设计」(外框同树码,设计头写能力、预算、时长、画幅与段表,后接结构段),由 豫构 设计 编译 源。设计。豫 --输出 名。设计 编成,播放器加载时验证;豫构 设计 还原 写回源码 你好。设计(编自 你好。设计。豫)

底层文件

文件名带“。底层”的是底层文件:无垃圾回收,编成整数 Wasm,用于执行器、驱动、张量内核等系统代码。语言子集与后端见 应用/豫言编译器/文档/底层模式.汉语.md。

后缀 含义 例子
名。底层。豫 底层源文件 豫言操作系统/裸机/客体二号/入口。底层。豫
名。底层。测试。豫 底层单元测试,全树测试照常发现并运行 库/底层库/中枢算阵/测试/逐元。底层。测试。豫
名。底层接口。豫 底层接口:每个无体声明编成一个 Wasm 导入,导入模块名是文件名去掉后缀 豫言操作系统/裸机/原生样例/你好/林纳。底层接口。豫,导入模块“林纳”
名。底层内建。豫 底层内建声明:底层库的原语表,调用就地编成 Wasm 指令 库/底层库/本术。底层内建。豫

包描述

后缀 含义 例子
名。包。豫 包描述:名称、所有者、版本、简介、说明、类型、依赖等字段,由豫构读取;当作模块导入时报错 库/豫章/豫章。包。豫

数据文件

数据文件(数据子语言,提案 00028)存静态数据。

后缀 含义 例子
名。数据。豫 数据文件:顶层只放导入、签名与 「名」者 值 也。;值是字面量(字符串、整数、小数、阳、阴、元)、「列」【…】 与构造写法 「头」【「字段」者 值 也,…】,构造写法的头与单写的名字是值构造器(立)。高级文件导入它,得到带类型的顶层数据;它只供导入,当程序入口时报错;豫构构建与检查库时,数据文件随导入方编译 应用/豫言编译器/校场/语法/数据文件/正确。数据。豫,社区包仓库根的 工具链钉。数据。豫
  • 类型检查分两步:检查之前查写法,值里的函数、运算与其他调用,以及 即、立 定义都报错,报错写明原因;检查之后查构造写法的头与单写的名字是值构造器。字段名、字段类型与必填项由构造写法降级按头的签名检查(标签函数类型签七),写错字段名时报“构造「头」没有属性「名」”。
  • 「列」【…】 直接用内建的列构造,数据文件不必导入标准库;签名里写「列」「文」等类型名时导入标准库。
  • 单独检查一个数据文件:豫构 类型检查 <包> <模块段…>,如 豫构 类型检查 软件目录 测试 样例。
  • 运行时下载或读入的数据文件由库「数据文件」只做词法与语法分析地读写;工具与 CI 之间交换的清单、软件目录(如包仓库的 /豫/社区/软件/豫言-兼容六十四。数据。豫)与工具链钉都写成数据文件。
  • 「典」【…】 只供库「数据文件」在运行时读取;编译与导入时「典」的类型留待后续版本,数据文件里写「典」时报错。

约定的文件名

  • 入口。豫:可执行包常用的入口模块名,包描述的「类型」里写 「入口」者『入口』也;它定义入口函数「入口」(类型 化「有」而「有」),包描述可以用「入口函数」另指一个名字。底层可执行包的入口文件是 入口。底层。豫。

兼容输入另接受以 .yuyan 结尾的源文件路径。

缀二:模块查找

导入路径的末段是模块名。编译器按导入方的种类给模块名依次补上下列后缀,取第一个存在的文件:

导入方 依次查找
高级文件 名。豫、名。接口。豫、名。应用接口。豫、名。内建。豫、名。着色器。豫、名。设计。豫、名。数据。豫
着色文件 名。着色器。豫、名。着色器。接口。豫
底层文件 名。底层。豫、名。底层接口。豫、名。底层内建。豫
  • 导入路径只写包名(或止于子包)时,先按库包描述里「类型」的「默认导入」展开成若干条目,每个条目再按导入方的种类补上表中的后缀(见豫构包系统“默认导入”)。
  • 各项都不存在时报“包内模块不存在”。高级文件要导入的模块只有底层文件时,报错附上“这是底层模块,高级代码不能导入”;底层文件找不到模块时,报错列出它可以导入的三种后缀。
  • 包入口与 豫构 文件 指定的文件可以是高级文件,也可以是底层文件,查找次序是表中高级与底层两行相接。数据文件可以作类型检查的入口;构建程序时它当入口报错。
  • 测试与脚本按全名导入(末段写 名。测试、名。脚本):测试只能被测试与脚本导入,普通模块导入测试时报“普通模块不能导入测试”;脚本不能被导入,导入时报“脚本不能被导入”。
  • 程序的编译模式看入口文件:入口是底层文件时,整个程序走底层管线;其余程序走高级管线,编成 WasmGC。

例如 豫言操作系统/裸机/原生样例/你好/入口。底层。豫 是底层文件,它的两条导入:

寻观「磐石」之书。
寻「原生你好」之「林纳」之书。

第一条按底层库的默认导入展开成 基、仓廪、格、址算 四个底层模块(如 库/底层库/基。底层。豫),第二条取同包的 林纳。底层接口。豫。

缀三:其他文件

文件名除半角点外全是汉字时,后缀一律用全角句号分隔;英文后缀(.md、.html、.wasm 等)用半角点。半角点接汉字后缀的是旧名,仓里已全部改用全角句号(汇编树码已改为 。树码,工具链也认旧名 .树码);CI 的 formatting check 对 Git 受控文件里名字除半角点外全是汉字的发警告,本地用 ./格式检查。林檎。豫行 --文件名 列出。

文档

后缀 含义 例子
名.汉语.md、名.文言.md 一篇文档的现代汉语稿与文言稿,成对存放、同步修改;包描述的「说明」登记包说明这一对 库/豫章/包说明.汉语.md、库/豫章/包说明.文言.md

测试数据

后缀 含义 例子
名。输入 固定测试输入:喂给被测程序的按键文字,可含控制字符 豫言操作系统/裸机/壳/测试/中断。输入
名其编号。豫 配 名。成功 或 名。失败 黄金样例:同组源文件按编号命名,“其”后把编号逐位写成汉字数字(名其一。豫、名其二。豫……名其一零。豫);顶层就是程序体;标记文件写明期望。。成功 要求构建、运行成功,标记文件非空时标准输出须与它相同;。失败 要求构建或运行失败,标记文件非空时输出须包含它的文字 库/豫章/测试/内建/一元积其一。豫 配 一元积。成功
名。期望 期望输出:命令壳测试、原生一致性探针等按它核对程序输出 豫言操作系统/裸机/壳/测试/基本。期望
名。测试页.html 浏览器测试页,在浏览器里打开运行 豫言操作系统/宿主/浏览器/中断。测试页.html
名。测试.mjs、名。测试.cjs、名.test.mjs、名.test.cjs、名.e2e.mjs 宿主代码(JS)的测试,全树测试用 node --test 运行 豫言操作系统/宿主/云工/公网取。测试.mjs
名。包。豫.txt 包描述模板:验收用的包描述,豫构发行的自动模式把它复制成真正的 。包。豫 后使用;包的发现只收 。包。豫 库/群书/藏时部/芥子/验收/箧卷/目录文件验收。包。豫.txt

构建产物与缓存

后缀 含义 例子
名。林檎。豫行、名。林纳。豫行 宿主上的本机原生程序(macOS 为 Mach-O,Linux 为 ELF),系统名取 --目标系统 的写法:豫构 构建 <包> --输出 名。林檎。豫行;没写 --输出 时豫构按本机系统补这个后缀。Windows 凭扩展名认可执行文件,本机程序是 名.exe(改成 名。轩窗。豫行 留待后续版本)。仓库据此忽略 格式化。林檎。豫行
名。豫行 豫行文件:豫言操作系统的可执行文件(加 --目标系统 豫言 编出),宿主上用豫行启动器运行;仓库据此忽略 豫构兼。豫行
名、名.wasm、名。林檎。豫行 仓库目标与 CI 产出的工具链(豫构。林檎。豫行、编译器。林檎。豫行、执行器 执行器。树码、网页后端的 编译器.wasm、豫构.wasm 等)与 Windows 上的 .wasm 工具,都放在仓库根目录;仓库根目录按白名单受控,这些产物一律忽略 豫构.wasm、编译器。林檎。豫行
名。树码 编译器各阶段的中间产物,存放在构建缓存里 .豫构缓存/豫构语言服务/<包描述基名>。语言服务。树码
名。树码 汇编树码:编译器的输出路径以 。树码 结尾时写出的豫汇模块(提案 00001 议十),豫言系统的 ARM64 工具映像直接从它生成;底层模式的模块写成底层豫汇(执行器 执行器。树码,原生产物与豫行文件直接从它生成) 豫构。树码、执行器。树码
单元序号.单元 装载单元:编译器加 --目标 单元 --执行器 执行器 时为每个模块写出的单元文件(模块元数据、预编机器码、重定位与符号,见《豫行格式》“装载单元”;提案 00003),与同名的 .wasm 放在同一输出目录 单元3.单元
名。清单。豫行 清单豫行:一个程序的各装载单元按装入次序打包成的单文件(豫构 构建 <包> --清单 --输出 名。清单。豫行 写出,见《豫行格式》“清单豫行”;提案 00038),由 豫构 运行 装入运行;壳的「行」遇到这个后缀时交给会话的豫构运行 开发。清单。豫行
号.上下文 包上下文:豫构写给编译器的包索引(制表符分隔的文本,第五版),按内容存放在当前目录的 .豫构缓存/豫构上下文 里,编译器以 --package-context 读入 .豫构缓存/豫构上下文/557988.上下文
号.上下文。境检 境检(包上下文二进制索引):存放目录里的上下文头一次启用时写在它旁边,记着上下文原文、仓库根前缀与各包的目录、身份、缓存号,编译任务按它查所属包与缓存号,不必解析整份上下文 .豫构缓存/豫构上下文/557988.上下文。境检

豫言系统造盘

后缀 含义 例子
名。预置 预置目录(也可以是指向目录的链接):造盘时整棵放进盘里,其中的 名。豫 编成 Wasm 豫言操作系统/裸机/壳/测试/示例。预置