Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

QuickCoffee 是一台以 Rust 编写、受 CoffeeScript 启发的字节码脚本引擎。它保留紧凑、可读的表达式语法,却不兼容 JavaScript:没有原型链、`this`、`eval` 或嵌入 JavaScript。

当前实现遵循 [RFCs/0000-project-scope.md](RFCs/0000-project-scope.md) 至 [RFCs/0087-reproducible-locked-builds.md](RFCs/0087-reproducible-locked-builds.md)。
当前实现遵循 [RFCs/0000-project-scope.md](RFCs/0000-project-scope.md) 至 [RFCs/0091-descending-ranges.md](RFCs/0091-descending-ranges.md)。

```coffee
square = (x) -> x * x
Expand Down
2 changes: 1 addition & 1 deletion RFCs/0014-range-literals.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- 状态:已采纳
- 依赖:RFC 0001、RFC 0002

`[start..end]` 生成包含 `end` 的整数数组;`[start...end]` 生成不包含 `end` 的整数数组。两端都是先求值的表达式,且必须为有限整数。若起点不小于终点,结果是空数组;包含式的 `i64` 最大终点会报告运行时错误,避免溢出。单个区间至多生成 1,000,000 项超限为运行时错误,以免在 fuel 检查前以一次分配耗尽宿主内存。
`[start..end]` 生成包含 `end` 的整数数组;`[start...end]` 生成不包含 `end` 的整数数组。两端都是先求值的表达式,且必须为有限整数。方向、降序和边界保护由 RFC 0091 定义;单个区间至多生成 1,000,000 项超限为运行时错误,以免在 fuel 检查前以一次分配耗尽宿主内存。

编译器直接发出 `MakeRange(inclusive)` 指令,而不是编译成可被用户同名绑定覆盖的 `range(start, end)` 调用。VM 以现有的数组值表示结果;因此可直接索引或供 `for` 使用。`...` 在此上下文表示排除上界,在函数参数末位才表示 rest/splat;其含义由解析上下文决定。

Expand Down
28 changes: 28 additions & 0 deletions RFCs/0090-string-map-pattern-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# RFC 0090:映射解构的字面字符串键

- 状态:已采纳
- 依赖:RFC 0012、RFC 0023、RFC 0075

## 动机

QuickCoffee 的映射字面量允许任意字符串键,但映射解构过去只接受标识符键。这样无法
解构外部数据常见的 `first-name`、`content-type` 等键,也使“映射键是字符串”与“映射
解构键必须是标识符”产生不必要的不对称。

## 契约

映射模式的键可以是标识符或已解码的非插值字符串字面量:

```coffee
{"first-name": first} = {"first-name": "Ada"}
```

字符串键按字面值查找,不执行插值、名称读取或其他表达式;动态 computed key 仍不支持。
重命名、默认值、递归模式、末尾 map rest 和原子匹配规则保持 RFC 0012、0023、0075 不变。
非法缺键、类型错误和模式失败仍不会留下部分绑定。

## 验收

`tests/rfc_core.rs` 覆盖连字符字符串键、单引号键、缺键错误和成功绑定;双语语法索引必须
区分字面字符串键与未支持的 computed key。现有验证器与 VM 指令无需新增,`make check` 仍
执行完整回归与五份文学手册。
28 changes: 28 additions & 0 deletions RFCs/0091-descending-ranges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# RFC 0091:降序整数区间

- 状态:已采纳
- 依赖:RFC 0014、RFC 0029、RFC 0042

## 动机

CoffeeScript 风格整数区间不应因终点小于起点而静默变成空数组。升序和降序都常用于倒序
遍历;当前 `MakeRange`/`range` 实现只生成升序,导致 `[4..2]` 与 `range(4, 2)` 丢失用户
明确表达的元素。

## 契约

区间方向由起点与终点决定:

- `[2..4]` 为 `[2, 3, 4]`,`[2...4]` 为 `[2, 3]`;
- `[4..2]` 为 `[4, 3, 2]`,`[4...2]` 为 `[4, 3]`;
- 标准库 `range(a, b)` 使用同样的方向规则,并继续排除终点。

边界必须是有限整数;区间长度超过既有 `MAX_RANGE_ITEMS` 仍报运行时错误。生成过程使用
整数方向和受保护计数,不依赖 `i64` 终点加一/减一,因此 `i64` 边界不会溢出。数组 `for`
与 `by` 继续按生成后数组位置迭代,映射循环和字符串 `by` 规则不变。

## 验收

`tests/rfc_core.rs` 覆盖升降序、开闭终点、标准库 `range` 和现有非整数/超长边界错误;五份
文学手册与中英文语法索引说明降序示例。`make check`、`make docs` 和性能语义护栏必须继续
通过。
1 change: 1 addition & 0 deletions docs/manual.classical-zh.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<p>return expression 惟函中可用,反其值而终此函;徒 return 得 nil,且清环行 finally。</p>
<p>函参可层叠数组映射之式;常值与余参仍惟名可书。</p>
<p>整数之区间,`[1..3]` 及其终,`[1...3]` 则不及。</p>
<p>区间亦可逆行,`[3..1]` 得 `[3, 2, 1]`,`[3...1]` 得 `[3, 2]`。</p>
<p>数组之截,a[start..end] 及终,a[start...end] 不及终;端须界内有限整数,负自末计,受者 nil 则安截不求端。</p>
<p>空值回退,书 left ? right;惟 nil 发之,false 与零不易。</p>
<p>后缀 value? 惟验非 nil;nil? 为 false,false? 与 0? 皆 true,未名之误弗隐。</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/manual.classical-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ QuickCoffee 者,Rust 所为字节码机也,非 JavaScript 之运行时。其

同一收集之法,亦可后置作 `value * 2 for value in items`,或括之为 `[value * 2 for value in items]`。方括惟为推导之界,不更生一层数组;`by`、`when`、映射、诸式、`break`、`continue` 皆循前式。

整数之区间,`[1..3]` 及其终,得 `[1, 2, 3]`;`[1...3]` 则不及,得 `[1, 2]`。其界必为有限整数。
整数之区间,`[1..3]` 及其终,得 `[1, 2, 3]`;`[1...3]` 则不及,得 `[1, 2]`;逆行亦然,`[3..1]` 得 `[3, 2, 1]`。其界必为有限整数。

后缀 `value?`,惟验其非 nil:`nil?` 为 false,而 `false?` 与 `0?` 皆 true;未名之误弗隐,亦非 `left ? right` 之回退。

Expand Down
1 change: 1 addition & 0 deletions docs/manual.devanagari-sa.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<p>return expression केवलं वर्तमान-कार्यं समाप्तं करोति; केवलः return nil फलति, loop शुद्धीकरोति, finally च चलयति।</p>
<p>parameter strict array/map-pattern गृह्णाति; default तथा rest केवलं name भवतः।</p>
<p>पूर्णाङ्क-range `[1..3]` अन्तं गृह्णाति; `[1...3]` अन्तं न गृह्णाति।</p>
<p>Range अधोमुखोऽपि भवति: `[3..1]` `[3, 2, 1]` ददाति, `[3...1]` `[3, 2]` ददाति।</p>
<p>array-slice a[start..end] अन्तं गृह्णाति, a[start...end] अन्तं न गृह्णाति; सीमा finite integer array-अन्तर्गतौ, negative अन्तात्, nil-safe slice nil-receiver मध्ये सीमौ न मूल्यते।</p>
<p>nil-विशेष-fallback left ? right इति; false तथा zero न परिवर्तेते।</p>
<p>postfix value? non-nil एव परीक्षते: nil? false, false? तथा 0? true; unbound-name-error न गोप्यते।</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/manual.devanagari.sa.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ nil-सुरक्षित suffix CoffeeScript-रीत्या `record?.nam

स एव collector CoffeeScript-postfix-comprehension अपि स्वीकरोति: `value * 2 for value in items`, अथवा `[value * 2 for value in items]`। brackets केवलं comprehension-सीमा, अतिरिक्त nested-array न; `by`, `when`, map, pattern, `break`, `continue` prefix-रूपस्य नियमैः चलन्ति।

पूर्णाङ्क-range `[1..3]` अन्तं गृह्णाति, अतः `[1, 2, 3]` भवति; `[1...3]` अन्तं न गृह्णाति, अतः `[1, 2]` भवति। सीमा finite integer भवेत्।
पूर्णाङ्क-range `[1..3]` अन्तं गृह्णाति, अतः `[1, 2, 3]` भवति; `[1...3]` अन्तं न गृह्णाति, अतः `[1, 2]` भवति; अधोमुख-range `[3..1]` `[3, 2, 1]` भवति। सीमा finite integer भवेत्।

postfix `value?` केवलं non-nil परीक्षते: `nil?` false, `false?` तथा `0?` true; unbound-name-error न गोपयति, `left ? right` fallback अपि न।

Expand Down
1 change: 1 addition & 0 deletions docs/manual.en.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<p>switch/when selects one strict-equality branch without fallthrough.</p>
<p>try/catch/finally handles QuickCoffee runtime errors without JavaScript Error objects.</p>
<p>Integer ranges use [1..3] for an inclusive end and [1...3] for an exclusive end.</p>
<p>Ranges may descend too: [3..1] yields [3, 2, 1], while [3...1] yields [3, 2].</p>
<p>Triple-quoted heredocs preserve newlines: &quot;&quot;&quot;...&quot;&quot;&quot; interpolates and '''...''' remains literal.</p>
<p>Array slices use a[start..end] for an inclusive end and a[start...end] for an exclusive end; bounds are finite in-range integers, negatives count from the end, and a nil-safe slice skips bounds on nil.</p>
<p>Nil-specific fallback is written as left ? right; false and zero are kept unchanged.</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/manual.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Arrays (including `range` results) can be iterated with `for item in items then

The same collector has CoffeeScript's postfix comprehension form: `value * 2 for value in items`, or `[value * 2 for value in items]`. The brackets delimit the comprehension and do not create an extra nested array; `by`, `when`, map iteration, patterns, `break`, and `continue` retain their prefix-form semantics.

Integer range literals are arrays built directly by the bytecode VM: `[1..3]` includes its end (`[1, 2, 3]`), while `[1...3]` excludes it (`[1, 2]`). Their bounds must be finite integers.
Integer range literals are arrays built directly by the bytecode VM: `[1..3]` includes its end (`[1, 2, 3]`), while `[1...3]` excludes it (`[1, 2]`); descending forms work too, so `[3..1]` is `[3, 2, 1]`. Their bounds must be finite integers.

Array slices use `items[start..end]` for an inclusive end and `items[start...end]` for an exclusive end: `[0..4][1..3]` is `[1, 2, 3]`. Bounds evaluate once from left to right and must be finite in-range integers; negative bounds count from the end, so `-1` is the last item. Slices are arrays only and never clip implicitly. `items?[start..end]` returns `nil` without evaluating bounds when its receiver is `nil`.

Expand Down
1 change: 1 addition & 0 deletions docs/manual.latin.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
<p>return expressio functionem praesentem finit; nudum return nil dat, iterata purgat, et finally circumstantia peragit.</p>
<p>Parametri patterna stricta seriei/map habere possunt; default et rest nomina manent.</p>
<p>Spatium integrorum `[1..3]` finem includit; `[1...3]` finem excludit.</p>
<p>Spatia descendere quoque possunt: `[3..1]` `[3, 2, 1]` reddit, `[3...1]` `[3, 2]` reddit.</p>
<p>Sectio seriei a[start..end] finem includit, a[start...end] excludit; termini integri finiti intra limites sunt, negativi ab extremo numerantur, et sectio nil-tuta terminos nil recipiente omittit.</p>
<p>Recessus nil-specialis left ? right scribitur; false et zero servantur.</p>
<p>Suffixum value? non-nil tantum probat: nil? false est, false? et 0? true sunt, nomen non ligatum errorem manet.</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/manual.latin.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Ordo scribitur `for item in items then expressio`; ligamen pattern strictum esse

Eadem collectio formam postfixam CoffeeScript habet: `value * 2 for value in items`, vel `[value * 2 for value in items]`. Bracteae solum terminum comprehensionis indicant nec seriem interiorem addunt; `by`, `when`, maps, patterna, `break`, et `continue` regulas formae praefixae servant.

Spatium integrorum `[1..3]` finem includit atque `[1, 2, 3]` facit; `[1...3]` finem excludit atque `[1, 2]` facit. Fines integri finiti esse debent.
Spatium integrorum `[1..3]` finem includit atque `[1, 2, 3]` facit; `[1...3]` finem excludit atque `[1, 2]` facit; descendens `[3..1]` `[3, 2, 1]` facit. Fines integri finiti esse debent.

Suffixum `value?` tantum non-nil probat: `nil?` false est, `false?` et `0?` true sunt; errorem nominis non ligati non celat neque recessus `left ? right` est.

Expand Down
1 change: 1 addition & 0 deletions docs/manual.zh-CN.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<p>return expression 只在函数内结束当前调用;裸 return 得 nil,并清理循环且执行沿途 finally。</p>
<p>形参可使用严格嵌套数组/映射模式,默认值和 rest 仍只用于名称。</p>
<p>整数区间 `[1..3]` 包含上界,`[1...3]` 不包含上界。</p>
<p>区间也可降序:`[3..1]` 得到 `[3, 2, 1]`,`[3...1]` 得到 `[3, 2]`。</p>
<p>三引号 heredoc 保留换行:&quot;&quot;&quot;...&quot;&quot;&quot; 插值,'''...''' 为字面量。</p>
<p>数组切片 a[start..end] 包含末端,a[start...end] 不包含末端;端点须为界内有限整数,负数自末计,nil 安全切片在接收者 nil 时不求端点。</p>
<p>空值回退写作 left ? right,仅 nil 触发,false 与 0 保留。</p>
Expand Down
2 changes: 1 addition & 1 deletion docs/manual.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ nil 安全后缀采用 CoffeeScript 风格写法:`record?.name`、`values?[ind

同一收集器也支持 CoffeeScript 风格后置推导:`value * 2 for value in items`,或写作 `[value * 2 for value in items]`。方括号只是推导界标,不产生额外嵌套数组;`by`、`when`、映射、模式、`break`、`continue` 仍遵循前置形式。

整数区间字面量由 VM 的专用字节码直接构造:`[1..3]` 包含上界,结果为 `[1, 2, 3]`;`[1...3]` 不包含上界,结果为 `[1, 2]`。边界必须是有限整数。
整数区间字面量由 VM 的专用字节码直接构造:`[1..3]` 包含上界,结果为 `[1, 2, 3]`;`[1...3]` 不包含上界,结果为 `[1, 2]`;降序同样支持,`[3..1]` 为 `[3, 2, 1]`。边界必须是有限整数。

数组切片写作 `items[start..end]`(含末端)或 `items[start...end]`(不含末端),例如 `[0..4][1..3]` 为 `[1, 2, 3]`。端点从左到右各求值一次,必须是界内有限整数;负数从末尾计,`-1` 是最后一项。切片只用于数组且不隐式截断。nil 安全形式 `items?[start..end]` 在接收者为 `nil` 时不求端点而产生 `nil`。

Expand Down
Loading