跳到正文豫言豫言教程与指南

豫言语言语法规范

本文描述当前编译器源码采用的核心语法。

文件

豫言源文件通常使用 .yuyan 或 。豫 后缀。一个文件是一组声明,声明之间用中文句号 。 分隔。大多数声明自身以 也 收束,因此常见结尾是 也。

空白和换行主要用于排版。表达式需要明确分组时使用全角圆括号 (...)。

词法

标识符使用书名号式引号:

「数」
「表达式」
「进行类型检查」

函数名、类型名、构造器名、模块名和绑定名都按这个规则书写。数字字面量目前也使用同一对引号,由编译器在名称解析前识别。

字符串使用 『』:

『你好』
『可以包含中文标点。』

注释使用 「:...:」,可以单独成行,也可以夹在类型或表达式附近:

「:这里是注释:」

整数和小数字面量写在 「」 中,可以使用汉字数字或阿拉伯数字,并用 点 或 . 分隔小数部分:

「零」
「一」
「一二三」
「三点一四」
「123」
「3.14」

这些内容在词法阶段与普通标识符形式相同,随后才会转换成数字节点;裸写的 一 或 3.14 不能作为数字表达式。

导入

模块路径由 之 串联,每一段是一个标识符:第一段是包名,其后是子包名或包内的模块路径。

寻「豫章」之书。
观「豫章」之书。
寻观「豫章」之「算术」之「抽签」之书。

寻 导入模块,并以路径末段命名一个静态的命名空间;观 把已导入模块的名字纳入未限定名称查找,所以示例中的第二行接在第一行的 寻 之后;寻观 同时导入并打开。

路径只写包名(如示例的前两行)时,按该库包描述里「类型」的「默认导入」展开:它是一个模块列表,寻观「豫章」之书。 依次打开列表里的各个模块,并把 豫章 绑成对应这些模块的命名空间;寻「豫章」之书。 只绑命名空间,「豫章」之「加」 在这些模块里逐个查找。标准库的默认导入列出常用的前置模块(内建类型、列表、字符串、整数运算、打印等),其他标准库模块写出完整路径导入,如示例的第三行。字段的写法见豫构包系统“默认导入”。

声明

类型声明:

「翻倍」乃化「数」为「数」者也。

定义声明:

「翻倍」者得「其数」而
 「其数」加「其数」
也。

普通定义可以先用 乃 声明类型,再紧接一个使用 者 的同名定义。类型定义使用 即,默认可以在类型检查时展开,不需要额外标记:

「别名」即「数」也。

构造器声明使用 立:

「选项」立化「类」为「类」者也。
 「可无」立凡「甲」而「选项」于「甲」者也。
 「可有」立凡「甲」而化「甲」为「选项」于「甲」者也。

测试(。测试。豫)与脚本(。脚本。豫)的顶层可以直接放表达式,按次序执行;普通源文件的顶层只放编译期能确定的定义,可执行程序从入口函数「入口」开始运行:

「书」于『完成』。

类型

显式函数类型:

化「数」为「文」

带名的类型参数:

凡「甲」而化「甲」为「甲」。

当前编译器只允许这种参数的定义域为 「类」;不支持依赖于普通运行时值的函数类型。

隐式函数类型:

凡「甲」而「甲」
凡「甲」而化「甲」为「甲」

类型函数也用 于 应用:

「或可有」于「数」

对子或元组类型使用 合,列类型通过类型构造器 「列」 表示:

「文」合「数」
「列」于「表达式」

类型标注表达式使用 也,类型写在左侧、被标注的表达式写在右侧:

(「数」也「值」)

表达式

标识符表达式就是一个带引号的名字:

「翻倍」

显式函数调用使用 于,多参数调用连续书写:

「翻倍」于「一二」
「加」于「一」于「二」

隐式参数调用使用 以:

「听」以「数」于「引用」。

显式函数使用 会...而...:

得「其数」而「其数」加「其数」。

带参数类型的函数使用 遇...者...而...:

得「其数」属「数」而「其数」加「其数」。

隐式函数使用 受...而...:

设「甲」而得「物」而「物」。

局部绑定使用 虑...者...而...:

令「结果」为「一」加「二」而
「述数」于「结果」。

表达式级递归绑定使用 复令...属...即...而...。属 后写递归值的类型,即 后写递归值定义,最后的 而 后写使用该递归值的表达式:

复令「求零」属化「数」为「数」
 即得「其数」而
  若「其数」等于「零」则「零」否则(「求零」于(「其数」减「一」))而
「求零」于「三」。

复令 适合在表达式内部构造局部递归函数或递归值。绑定名在定义体和后续表达式中都可见。编译器会先把它降为显式递归单元,再进行闭包转换,因此递归函数可以安全捕获自身。

顶层定义在其类型声明之后可以直接引用自身,不需要旧的 循...以... 形式。例如标准库中的列长度函数可以写成:

「计」乃凡「甲」而化(「列」于「甲」)为「数」者也。
「计」者设「甲」而得「列值」而
 鉴「列值」而
  或有「罄」则「零」
  或有「缀」于「头」于「尾」则「一」加(「计」以「甲」于「尾」)
也。

条件表达式:

若「条件」则「真值」否则「假值」

顺序执行使用 ;:

(「写匣」于「引用」于「值」而后「本读匣」于「引用」)

模块或结构投影使用 之,左侧是 寻 建立的命名空间(如上文导入的 抽签),右侧是其中的名称:

「抽签」之「抽数」

对子或元组投影使用 中:

「对子」中「零」
「三元组」中「二」

数据构造

对子值使用 与:

「名字」与「类型」

列值使用标准库构造器 「罄」 和 「缀」:

「罄」
「缀」于「头」于「尾」
「缀」于「甲」于(「缀」于「乙」于(「缀」于「丙」于「罄」))

当前编译器不支持在括号中内联声明结构;模块结构由源文件以及导入和打开操作组成。

模式匹配

模式匹配使用 鉴...而...。第一个分支用 有,后续分支用 或有:

鉴「可」而
    或有(「可有」于「物」)则「物」
    或有「可无」则「默认」也

空参构造器或绑定名直接写在 有、或有 后面,不额外加一层括号:

或有「可无」则「默认」

带参数构造器模式用普通应用形式:

或有(「可有」于「物」)则「物」

列模式使用同样的构造器匹配空列或头尾:

或有「罄」则「零」
或有「缀」于「头」于「尾」则「加」于「一」于(「计」于「尾」)

对子模式使用 与:

或有(「左」与「右」)则「左」

宿主与内建能力

宿主函数在 。接口。豫 中声明为带类型导入,源码按普通函数调用语法传递参数。编译器内建原语在 。内建。豫 中声明,由编译器按原语签名检查并生成实现。

完整示例

寻观「豫章」之书。

「取默认」乃凡「甲」而化(「或可有」于「甲」)又化「甲」为「甲」者也。
「取默认」者设「甲」而得「可」又得「默认」而
 鉴「可」而
  或有(「可有」于「物」)则「物」
  或有「可无」则「默认」
也。

「翻倍」乃化「数」为「数」者也。
「翻倍」者得「其数」而
 「其数」加「其数」
也。