@mirascript/help 0.1.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/index.d.ts +79 -0
  2. package/dist/index.js +78 -0
  3. package/package.json +21 -0
  4. package/scripts/build.js +165 -0
  5. package/src/keyword/and.md +26 -0
  6. package/src/keyword/break.md +32 -0
  7. package/src/keyword/case.md +16 -0
  8. package/src/keyword/const.md +10 -0
  9. package/src/keyword/continue.md +14 -0
  10. package/src/keyword/effect.md +6 -0
  11. package/src/keyword/else.md +32 -0
  12. package/src/keyword/false.md +5 -0
  13. package/src/keyword/finally.md +6 -0
  14. package/src/keyword/fn.md +35 -0
  15. package/src/keyword/for.md +43 -0
  16. package/src/keyword/global.md +16 -0
  17. package/src/keyword/handle.md +6 -0
  18. package/src/keyword/if.md +40 -0
  19. package/src/keyword/in.md +44 -0
  20. package/src/keyword/inf.md +10 -0
  21. package/src/keyword/is.md +11 -0
  22. package/src/keyword/let.md +11 -0
  23. package/src/keyword/loop.md +13 -0
  24. package/src/keyword/match.md +18 -0
  25. package/src/keyword/mod.md +6 -0
  26. package/src/keyword/mut.md +25 -0
  27. package/src/keyword/nan.md +10 -0
  28. package/src/keyword/nil.md +11 -0
  29. package/src/keyword/not.md +26 -0
  30. package/src/keyword/op.md +6 -0
  31. package/src/keyword/or.md +26 -0
  32. package/src/keyword/perform.md +6 -0
  33. package/src/keyword/pub.md +6 -0
  34. package/src/keyword/resume.md +6 -0
  35. package/src/keyword/return.md +12 -0
  36. package/src/keyword/true.md +5 -0
  37. package/src/keyword/try.md +6 -0
  38. package/src/keyword/type.md +10 -0
  39. package/src/keyword/underscore.md +16 -0
  40. package/src/keyword/use.md +6 -0
  41. package/src/keyword/where.md +6 -0
  42. package/src/keyword/while.md +12 -0
  43. package/src/operator/arrow.md +6 -0
  44. package/src/operator/assign.md +23 -0
  45. package/src/operator/asterisk.md +9 -0
  46. package/src/operator/asterisk_assign.md +11 -0
  47. package/src/operator/brace.md +26 -0
  48. package/src/operator/bracket.md +32 -0
  49. package/src/operator/caret.md +10 -0
  50. package/src/operator/caret_assign.md +11 -0
  51. package/src/operator/colon.md +29 -0
  52. package/src/operator/colon_colon.md +10 -0
  53. package/src/operator/comma.md +13 -0
  54. package/src/operator/dot.md +15 -0
  55. package/src/operator/equal.md +43 -0
  56. package/src/operator/exclamation.md +23 -0
  57. package/src/operator/greater.md +10 -0
  58. package/src/operator/greater_equal.md +9 -0
  59. package/src/operator/half_open_range.md +12 -0
  60. package/src/operator/less.md +9 -0
  61. package/src/operator/less_equal.md +9 -0
  62. package/src/operator/logical_and.md +9 -0
  63. package/src/operator/logical_and_assign.md +11 -0
  64. package/src/operator/logical_or.md +9 -0
  65. package/src/operator/logical_or_assign.md +11 -0
  66. package/src/operator/minus.md +10 -0
  67. package/src/operator/minus_assign.md +11 -0
  68. package/src/operator/not_equal.md +10 -0
  69. package/src/operator/null_coalescing.md +10 -0
  70. package/src/operator/null_coalescing_assign.md +14 -0
  71. package/src/operator/paren.md +39 -0
  72. package/src/operator/percent.md +9 -0
  73. package/src/operator/percent_assign.md +11 -0
  74. package/src/operator/plus.md +10 -0
  75. package/src/operator/plus_assign.md +11 -0
  76. package/src/operator/question.md +9 -0
  77. package/src/operator/question_colon.md +12 -0
  78. package/src/operator/semicolon.md +13 -0
  79. package/src/operator/slash.md +9 -0
  80. package/src/operator/slash_assign.md +11 -0
  81. package/src/operator/spread_range.md +31 -0
  82. package/src/operator/tilde_equal.md +24 -0
  83. package/src/operator/tilde_not_equal.md +10 -0
@@ -0,0 +1,79 @@
1
+ /* Generated by scripts/build.js. Do not edit manually. */
2
+
3
+ export declare const KEYWORDS: {
4
+ readonly "and": string;
5
+ readonly "break": string;
6
+ readonly "case": string;
7
+ readonly "const": string;
8
+ readonly "continue": string;
9
+ readonly "else": string;
10
+ readonly "false": string;
11
+ readonly "fn": string;
12
+ readonly "for": string;
13
+ readonly "global": string;
14
+ readonly "if": string;
15
+ readonly "in": string;
16
+ readonly "inf": string;
17
+ readonly "is": string;
18
+ readonly "let": string;
19
+ readonly "loop": string;
20
+ readonly "match": string;
21
+ readonly "mut": string;
22
+ readonly "nan": string;
23
+ readonly "nil": string;
24
+ readonly "not": string;
25
+ readonly "or": string;
26
+ readonly "return": string;
27
+ readonly "true": string;
28
+ readonly "type": string;
29
+ readonly "_": string;
30
+ readonly "while": string;
31
+ };
32
+ export declare const OPERATORS: {
33
+ readonly "=": string;
34
+ readonly "*": string;
35
+ readonly "*=": string;
36
+ readonly "{": string;
37
+ readonly "}": string;
38
+ readonly "[": string;
39
+ readonly "]": string;
40
+ readonly "^": string;
41
+ readonly "^=": string;
42
+ readonly ":": string;
43
+ readonly "::": string;
44
+ readonly ",": string;
45
+ readonly ".": string;
46
+ readonly "==": string;
47
+ readonly "!": string;
48
+ readonly ">": string;
49
+ readonly ">=": string;
50
+ readonly "..<": string;
51
+ readonly "<": string;
52
+ readonly "<=": string;
53
+ readonly "&&": string;
54
+ readonly "&&=": string;
55
+ readonly "||": string;
56
+ readonly "||=": string;
57
+ readonly "-": string;
58
+ readonly "-=": string;
59
+ readonly "!=": string;
60
+ readonly "??": string;
61
+ readonly "??=": string;
62
+ readonly "(": string;
63
+ readonly ")": string;
64
+ readonly "%": string;
65
+ readonly "%=": string;
66
+ readonly "+": string;
67
+ readonly "+=": string;
68
+ readonly "?": string;
69
+ readonly "?:": string;
70
+ readonly ";": string;
71
+ readonly "/": string;
72
+ readonly "/=": string;
73
+ readonly "..": string;
74
+ readonly "=~": string;
75
+ readonly "!~": string;
76
+ };
77
+
78
+ export type Keyword = keyof typeof KEYWORDS;
79
+ export type Operator = keyof typeof OPERATORS;
package/dist/index.js ADDED
@@ -0,0 +1,78 @@
1
+ /* Generated by scripts/build.js. Do not edit manually. */
2
+
3
+ export const KEYWORDS = Object.freeze({
4
+ __proto__: null,
5
+ "and": "`and` 用于在模式匹配中组合多个模式,也可以作为 `&&` 运算符的替代写法。\n\n---\n\n逻辑与模式:\n\n```mira\nfn is_month(month) {\n month is >= 1 and <= 12\n}\n```\n\n---\n\n逻辑与运算符:\n\n```mira\nfn is_adult(age) {\n // 等同于 age >= 18 && age <= 65\n age >= 18 and age <= 65\n}\n```\n",
6
+ "break": "`break` 用于提前退出 `for` / `while` / `loop`。\n\n---\n\n基本用法\n\n```mira\nlet mut i = 0;\nloop {\n i += 1;\n break;\n}\n```\n\n---\n\n从循环中返回一个值\n\n```mira\nlet mut i = 0;\nlet result = loop {\n i += 1;\n if i == 10 {\n break i * 2;\n }\n};\n// result 的值是 20\n```\n",
7
+ "case": "`case` 是 `match` 表达式中的分支。\n\n```mira\nfn age_group(age) {\n match age {\n case 0..12 { \"child\"}\n case 13..19 { \"teenager\" }\n case 20..64 { \"adult\" }\n case _ { \"senior\" }\n }\n}\n```\n",
8
+ "const": "`const` 用于声明常量。常量名必须以 `@` 开头。\n\n```mira\nconst @PI = 3.14159;\n// @PI = 0; // 错误:常量不可重新赋值\n```\n",
9
+ "continue": "`continue` 用于跳过本次循环剩余部分,进入下一次循环。\n\n```mira\nlet mut sum = 0;\nfor i in 1..5 {\n if i % 2 == 0 { continue; }\n sum += i;\n}\n// sum == 1 + 3 + 5\n```\n",
10
+ "else": "`else` 用于 `if` 表达式,也可用作 `while` 和 `for` 循环的可选分支。\n\n---\n\n作为 `if` 表达式的分支\n\n```mira\nlet x = if false { 1 } else { 2 }; // 2\n```\n\n---\n\n作为循环的可选分支\n\n```mira\nlet mut i = 0;\nlet result = while i < 5 {\n i += 1;\n if i == 6 {\n // 使用 break 语句提前退出循环,并返回一个值\n break i * 2;\n }\n} else {\n // 当循环正常结束时执行\n 100\n};\n// result 的值是 100\n```\n",
11
+ "false": "`false` 是布尔字面量,表示逻辑假。\n",
12
+ "fn": "使用 `fn` 关键字定义一个函数或函数表达式。\n\n---\n\n定义一个简单的函数:\n\n```mira\nfn add(a, b) {\n return a + b;\n}\n```\n\n---\n\n定义一个变量,并使用函数表达式初始化:\n\n```mira\nlet multiply = fn(x, y) {\n return x * y;\n};\n```\n\n---\n\n当函数只有一个参数时,可以省略括号,并用 `it` 引用该参数。\n\n```mira\nfn square {\n return it * it;\n}\n```\n",
13
+ "for": "`for` 用于遍历可迭代对象。\n\n---\n\n遍历一个范围:\n\n```mira\nlet mut sum = 0;\nfor i in 1..3 { // 或者 1..<4\n sum += i;\n}\n// sum == 6\n```\n\n---\n\n遍历一个数组:\n\n```mira\nlet arr = [10, 20, 30];\nlet mut sum = 0;\nfor value in arr {\n sum += value;\n}\n// sum == 60\n```\n\n---\n\n遍历一个记录:\n\n```mira\nlet record = (a: 1, b: 2, c: 3);\nlet mut sum = 0;\nfor key in record {\n sum += record[key];\n}\n// sum == 6\n```\n",
14
+ "global": "`global` 表示全局对象(全局命名空间)。通常用于读取全局变量或判断某个全局键是否存在。\n\n```mira\n// 访问全局变量\nglobal.some_name;\n\n// 动态访问全局变量\nglobal['some_name'];\n\n// 判断键是否存在\n'some_name' in global;\n```\n",
15
+ "if": "`if` 用于 `if` 表达式或 `match` 表达式的守卫条件。\n\n---\n\n`if` 表达式根据条件选择分支。条件必须是 `boolean`。\n\n```mira\nlet x = if 1 > 0 { \"pos\" } else { \"neg\" };\n```\n\n---\n\n使用 `else if` 添加多个条件分支:\n\n```mira\nlet x = if 1 > 2 {\n \"greater\"\n} else if 1 == 2 {\n \"equal\"\n} else {\n \"less\"\n};\n```\n\n---\n\n在 `match` 表达式中使用 `if` 作为守卫条件:\n\n```mira\nlet num = 10;\nlet result = match num {\n case n if n % 2 == 0 { \"even\" }\n case n { \"odd\" }\n};\n// result 的值是 \"even\"\n```\n",
16
+ "in": "`in` 用于“包含/存在”判断,以及 `for` 循环。\n\n---\n\n对于 `array` 类型,`in` 用于判断某个元素是否在数组中存在:\n\n```mira\nfn is_spring(month) {\n month in [3, 4, 5]\n}\n```\n\n---\n\n对于 `record` / `module` / `extern` 类型,`in` 用于判断某个键是否在容器中存在:\n\n```mira\nlet record = (a: 1, b: 2, c: 3);\nlet a_exists = 'a' in record; // true\n```\n\n---\n\n也可与 `global` 关键字结合使用,判断全局变量是否存在:\n\n```mira\nif 'my_global' in global {\n my_global += 1;\n}\n```\n\n---\n\n同时,`for` 循环也使用 `in`:\n\n```mira\nfor i in 1..3 {\n // i: 1, 2, 3\n}\n```\n",
17
+ "inf": "`inf` 是正无穷大的 `number` 常量。\n\n```mira\ninf > 1e100; // true\n-inf < 0; // true\n```\n",
18
+ "is": "`is` 用于模式匹配:`value is pattern`,结果为 `boolean`。\n\n```mira\n1 is 1; // true\n1 is > 0; // true\n(a: 1) is (a: x); // true(并绑定 x)\n```\n",
19
+ "let": "`let` 用于声明局部变量。\n\n```mira\nlet x = 1;\nlet y = x + 2;\nlet mut z = y * 3;\n```\n",
20
+ "loop": "`loop` 创建一个无限循环,通常配合 `break` 退出。\n\n```mira\nlet mut i = 0;\nloop {\n i += 1;\n if i >= 3 { break; }\n}\n```\n",
21
+ "match": "`match` 表达式对一个值进行分支匹配,由多个 `case` 组成。\n\n```mira\nfn classify {\n match it {\n case (0, 0) { \"Origin\" }\n case (x, 0) if x > 0 { \"Positive X-Axis (x=$x)\" }\n case (x, 0) if x < 0 { \"Negative X-Axis (x=$x)\" }\n case (0, y) { \"Y-Axis (y=$y)\" }\n case (x, y) { \"Somewhere else (x=$x, y=$y)\" }\n case _ { \"Not a point\" }\n }\n}\n```\n",
22
+ "mut": "`mut` 用于声明可变变量。\n\n---\n\n使用 `let` 语句时声明一个可变变量:\n\n```mira\nlet mut x = 1;\nx += 2;\n// x == 3\n```\n\n---\n\n在模式匹配中声明一个可变绑定:\n\n```mira\nlet (mut a, b) = (1, 2);\na += 10;\n// b += 10; // 这行代码会报错,因为 b 是不可变的\n```\n",
23
+ "nan": "`nan` 是一个特殊的 `number` 值(Not a Number)。它与任何值都不相等(包括它自己)。\n\n```mira\nnan == nan; // false\nnan =~ nan; // false\n```\n",
24
+ "nil": "`nil` 表示“空值”。当访问不存在的字段、对 `nil` 进行空安全链式调用等场景时,结果也会是 `nil`。\n\n```mira\nlet x = nil;\nlet y = x ?? 0; // 0\nlet z = x.anything; // nil(空安全访问)\n```\n",
25
+ "not": "`not` 用于在模式匹配中取反一个模式,也可以作为 `!` 运算符的替代写法。\n\n---\n\n逻辑非模式:\n\n```mira\nfn is_not_weekend(day) {\n day is not 6 and not 7\n}\n```\n\n---\n\n逻辑非运算符:\n\n```mira\nfn is_minor(age) {\n // 等同于 !(age >= 18)\n not (age >= 18)\n}\n```\n",
26
+ "or": "`or` 用于在模式匹配中组合多个模式,也可以作为 `||` 运算符的替代写法。\n\n---\n\n逻辑或模式:\n\n```mira\nfn is_weekend(day) {\n day is 6 or 7\n}\n```\n\n---\n\n逻辑或运算符:\n\n```mira\nfn is_superuser(role) {\n // 等同于 role == \"admin\" || role == \"superuser\"\n role == \"admin\" or role == \"superuser\"\n}\n```\n",
27
+ "return": "`return` 用于从函数中返回值。\n\n```mira\nfn abs {\n if it < 0 { return -it; }\n return it;\n}\n```\n",
28
+ "true": "`true` 是布尔字面量,表示逻辑真。\n",
29
+ "type": "`type` 用于获得值的类型名字符串。\n\n```mira\ntype(1); // \"number\"\nnil::type(); // \"nil\"(扩展调用写法)\n```\n",
30
+ "_": "`_` 是弃元关键字,用于在模式匹配中匹配并忽略任意值。\n\n```mira\nlet (_, y) = (1, 2); // y == 2\n\nfn head {\n match it {\n case [x, ..] { x }\n case _ { nil }\n }\n}\n```\n",
31
+ "while": "`while` 循环在条件为 `true` 时重复执行循环体。\n\n```mira\nlet mut i = 0;\nwhile i < 3 {\n i += 1;\n}\n```\n",
32
+ });
33
+ export const OPERATORS = Object.freeze({
34
+ __proto__: null,
35
+ "=": "`=` 用于赋值。\n\n---\n\n声明时初始化:\n\n```mira\nlet x = 1;\nconst @y = 2;\n```\n\n---\n\n对可变变量/可写字段赋值:\n\n```mira\nlet mut x = 1;\nx = x + 1;\n```\n",
36
+ "*": "`*` 用于乘法。\n\n```mira\n2 * 3; // 6\n```\n",
37
+ "*=": "`*=` 是复合赋值,`x *= y` 等价于 `x = x * y`。\n\n```mira\nlet mut x = 2;\nx *= 3;\n// x == 6\n```\n",
38
+ "{": "`{ }` 用于表达式块或 JSON 风格记录字面量。\n\n---\n\n表达式块:\n\n```mira\nlet x = { 1 + 2 };\n```\n\n---\n\n在 JSON 风格记录字面量中,键名必须使用引号括起来:\n\n```mira\nlet obj = { \"x\": 1, \"y\": 2, \"n\": nil };\n```\n\n注意:\n\n- JSON 风格记录字面量不能为空,要声明一个空记录,请用 `()`;\n- 键和值仍为 MiraScript 表达式,因此需要使用 `nil` 来表示空值,而不是 `null`。\n",
39
+ "}": "`{ }` 用于表达式块或 JSON 风格记录字面量。\n\n---\n\n表达式块:\n\n```mira\nlet x = { 1 + 2 };\n```\n\n---\n\n在 JSON 风格记录字面量中,键名必须使用引号括起来:\n\n```mira\nlet obj = { \"x\": 1, \"y\": 2, \"n\": nil };\n```\n\n注意:\n\n- JSON 风格记录字面量不能为空,要声明一个空记录,请用 `()`;\n- 键和值仍为 MiraScript 表达式,因此需要使用 `nil` 来表示空值,而不是 `null`。\n",
40
+ "[": "`[ ]` 用于数组字面量、索引访问与切片。\n\n---\n\n数组字面量:\n\n```mira\nlet arr = [1, 2, 3];\n```\n\n---\n\n索引访问:\n\n```mira\nlet first = arr[0];\nlet last = arr[-1];\nlet value = record[\"key\"];\n```\n\n---\n\n数组切片:\n\n```mira\nlet subarr1 = arr[0..1]; // 取前两个元素\nlet subarr2 = arr[..<-1]; // 取到倒数第一个元素(不含)\n```\n",
41
+ "]": "`[ ]` 用于数组字面量、索引访问与切片。\n\n---\n\n数组字面量:\n\n```mira\nlet arr = [1, 2, 3];\n```\n\n---\n\n索引访问:\n\n```mira\nlet first = arr[0];\nlet last = arr[-1];\nlet value = record[\"key\"];\n```\n\n---\n\n数组切片:\n\n```mira\nlet subarr1 = arr[0..1]; // 取前两个元素\nlet subarr2 = arr[..<-1]; // 取到倒数第一个元素(不含)\n```\n",
42
+ "^": "`^` 用于乘方,结合性为从右到左。\n\n```mira\n2 ^ 3; // 8\n2 ^ 3 ^ 2; // 2^(3^2)\n```\n",
43
+ "^=": "`^=` 是复合赋值,`x ^= y` 等价于 `x = x ^ y`。\n\n```mira\nlet mut x = 2;\nx ^= 3;\n// x == 8\n```\n",
44
+ ":": "`:` 用于记录字面量、条件表达式和插值格式。\n\n---\n\n在记录字面量中,`:` 用于分隔字段名和字段值。\n\n```mira\nlet r = (x: 1, y: 2);\n```\n\n---\n\n在条件表达式中,`:` 用于分隔条件的不同分支。\n\n```mira\nlet status = score >= 60 ? \"及格\" : \"不及格\";\n```\n\n---\n\n在插值格式中,`:` 用于指定格式化选项。在指定格式化选项时,必须使用圆括号 `$(expr:format)`。\n\n```mira\ndebug_print(\"π 的值约为 $(PI:.2)\"); // 输出: π 的值约为 3.14\n```\n",
45
+ "::": "`::` 用于扩展调用。\n\n```mira\n\"Hello\"::chars()::join(\"\");\n// 相当于 join(chars(\"Hello\"), \"\");\n```\n",
46
+ ",": "`,` 用于分隔参数、数组元素、记录字段等。\n\n```mira\nlet arr = [1, 2, 3];\nlet r = (a: 1, b: 2);\n\nfn f(a, b, c) { a + b + c }\nf(1, 2, 3);\n```\n",
47
+ ".": "`.` 用于成员访问。\n\n```mira\nlet r = (a: 1);\nr.a; // 1\nr.b; // nil\n\nlet arr = [10, 20];\narr.0; // 10\narr.2; // nil\n```\n",
48
+ "==": "使用 `==` 运算符可以比较两个值是否严格相等。\n\n---\n\n对于原始值,如果它们的类型和值都相同,则认为它们相等。\n\n```mira\n5 == 5; // true\n\"hello\" == \"hello\"; // true\ntrue == true; // true\n5 == \"5\"; // false\n```\n\n特别地,对于 `number` 类型的值 `nan`,它与任何值都不相等,包括它自己。\n\n```mira\nnan == nan; // false\n```\n\n---\n\n对于 `array` 和 `record`,只有他们的元素和属性都相等时,才认为它们相等。\n\n```mira\n[1, 2, 3] == [1, 2, 3]; // true\n(a: 1, b: 2) == (a: 1, b: 2); // true\n[1, 2, 3] == [1, 2, 4]; // false\n```\n\n---\n\n对于 `function` `module` 和 `extern`,只有它们引用的是同一个对象时,才认为它们相等。\n\n```mira\nlet fn1 = fn() { return 1; };\nlet fn2 = fn() { return 1; };\nfn1 == fn1; // true\nfn1 == fn2; // false\n```\n",
49
+ "!": "`!` 既可以作为前缀逻辑非,也可以作为后缀非空断言。\n\n---\n\n逻辑非:\n\n```mira\n!x // x 必须是 boolean\n```\n\n---\n\n非空断言:\n\n```mira\n\nlet x = nil;\nx!; // panic\n```\n",
50
+ ">": "`>` 用于“大于”比较。\n\n```mira\n2 > 1; // true\n\"b\" > \"a\"; // true\n```\n",
51
+ ">=": "`>=` 用于“大于等于”比较。\n\n```mira\n2 >= 2; // true\n```\n",
52
+ "..<": "`..<` 表示右开区间范围,包含起点,不包含终点。\n\n```mira\n[1..<3]; // [1, 2]\n\nlet arr = [10, 20, 30, 40];\narr[1..<3]; // [20, 30]\n```\n",
53
+ "<": "`<` 用于“小于”比较。\n\n```mira\n1 < 2; // true\n```\n",
54
+ "<=": "`<=` 用于“小于等于”比较。\n\n```mira\n2 <= 2; // true\n```\n",
55
+ "&&": "`&&` 是短路逻辑与,操作数必须是 `boolean`。\n\n```mira\nfalse && (1 / 0); // 右侧不会被求值\n```\n",
56
+ "&&=": "`&&=` 是短路复合赋值,只有当左侧为 `true` 时才会计算并赋值右侧。\n\n```mira\nlet mut b = true;\nb &&= false;\n// b == false\n```\n",
57
+ "||": "`||` 是短路逻辑或,操作数必须是 `boolean`。\n\n```mira\ntrue || (1 / 0); // 右侧不会被求值\n```\n",
58
+ "||=": "`||=` 是短路复合赋值,只有当左侧为 `false` 时才会计算并赋值右侧。\n\n```mira\nlet mut b = false;\nb ||= true;\n// b == true\n```\n",
59
+ "-": "`-` 用于减法(中缀)或一元负号(前缀)。\n\n```mira\n5 - 2; // 3\n-1; // -1\n```\n",
60
+ "-=": "`-=` 是复合赋值,`x -= y` 等价于 `x = x - y`。\n\n```mira\nlet mut x = 3;\nx -= 1;\n// x == 2\n```\n",
61
+ "!=": "`!=` 判断两个值是否不相等,等价于 `!(x == y)`。\n\n```mira\n1 != 2; // true\n1 != 1; // false\n```\n",
62
+ "??": "`??` 是空合并,当左侧为 `nil` 时返回右侧,否则返回左侧。\n\n```mira\nnil ?? 1; // 1\n0 ?? 1; // 0\n```\n",
63
+ "??=": "`??=` 是空合并复合赋值,仅当左侧为 `nil` 时才会赋值右侧。\n\n```mira\nlet mut n = nil;\nn ??= 5;\n// n == 5\n\nn ??= 10;\n// n 仍然是 5\n```\n",
64
+ "(": "`( )` 用于分组表达式、函数调用参数列表,以及记录字面量。\n\n---\n\n分组表达式,控制计算顺序:\n\n```mira\nlet result = (1 + 2) * 3; // 先计算 1 + 2,然后乘以 3\n```\n\n---\n\n函数声明和调用:\n\n```mira\nfn add(a, b) { a + b }\nlet sum = add(1, 2);\n```\n\n---\n\n记录字面量:\n\n```mira\nlet record = (a: 1, b: 2);\nlet empty = (); // 空记录\n```\n\n---\n\n对于省略键名的单元素记录,必须添加逗号以区别于分组表达式。\n\n```mira\nlet single = (1,)\n```\n",
65
+ ")": "`( )` 用于分组表达式、函数调用参数列表,以及记录字面量。\n\n---\n\n分组表达式,控制计算顺序:\n\n```mira\nlet result = (1 + 2) * 3; // 先计算 1 + 2,然后乘以 3\n```\n\n---\n\n函数声明和调用:\n\n```mira\nfn add(a, b) { a + b }\nlet sum = add(1, 2);\n```\n\n---\n\n记录字面量:\n\n```mira\nlet record = (a: 1, b: 2);\nlet empty = (); // 空记录\n```\n\n---\n\n对于省略键名的单元素记录,必须添加逗号以区别于分组表达式。\n\n```mira\nlet single = (1,)\n```\n",
66
+ "%": "`%` 用于取余。\n\n```mira\n5 % 2; // 1\n```\n",
67
+ "%=": "`%=` 是复合赋值:`x %= y` 等价于 `x = x % y`。\n\n```mira\nlet mut x = 5;\nx %= 2;\n// x == 1\n```\n",
68
+ "+": "`+` 用于加法(中缀)或一元正号(前缀)。\n\n```mira\n1 + 2; // 3\n+1; // 1\n```\n",
69
+ "+=": "`+=` 是复合赋值,`x += y` 等价于 `x = x + y`。\n\n```mira\nlet mut x = 1;\nx += 2;\n// x == 3\n```\n",
70
+ "?": "`?` 用于条件表达式(三元表达式):`cond ? thenExpr : elseExpr`。\n\n```mira\nfn sign { it > 0 ? 1 : it < 0 ? -1 : 0 }\n```\n",
71
+ "?:": "`?:` 用于记录字面量的“可选字段”,当值为 `nil` 时省略该字段。\n\n```mira\n(a?: 1, b?: nil); // (a: 1)\n\n// 省略不会删除已经通过展开引入的同名字段\n(..(a: 1), a?: nil); // (a: 1)\n```\n",
72
+ ";": "`;` 用于结束语句。MiraScript 以表达式为主,但在多语句块中常用 `;` 分隔。\n\n```mira\nlet sum = {\n let x = 1;\n let y = 2;\n x + y\n};\n```\n",
73
+ "/": "`/` 用于除法。\n\n```mira\n6 / 3; // 2\n```\n",
74
+ "/=": "`/=` 是复合赋值,`x /= y` 等价于 `x = x / y`。\n\n```mira\nlet mut x = 6;\nx /= 3;\n// x == 2\n```\n",
75
+ "..": "`..` 表示闭区间范围,或在数组/记录字面量及函数调用中表示展开。\n\n---\n\n表示数组字面量、切片和循环的范围:\n\n```mira\nlet arr = [1..3]; // arr = [1, 2, 3]\nlet slice = arr[0..1]; // slice = [1, 2]\n\nfor i in 1..3 {\n // i 依次为 1, 2, 3\n}\n```\n\n---\n\n展开数组/记录或函数调用:\n\n```mira\nlet arr = [1, ..[2, 3]]; // arr = [1, 2, 3]\nlet rec1 = (a: 1, ..(b: 2, c: 3)); // rec1 = (a: 1, b: 2, c: 3)\n// 同名键以最后一个为准\nlet rec2 = (..(1, 2), ..(3, 4, 5)); // rec2 = (0: 3, 1: 4, 2: 5)\n\nlet result = sum(..[1, 2, 3]); // 等同于 sum(1, 2, 3)\n```\n",
76
+ "=~": "`=~` 是“近似相等”,用于数值容差比较和字符串归一化比较。\n\n---\n\n对于 `number` 类型,当两个操作数的相对误差**或**绝对误差小于 `1e-15` 时,返回 `true`,否则返回 `false`。\n\n如果其中一个操作数为 `number` 类型,另一个操作数在比较前也会自动转换为 `number` 类型。\n\n```mira\n0.1 + 0.2 =~ 0.3; // true\n1 =~ \"1\"; // true\n```\n\n---\n\n对于 `string` 类型,`=~` 运算符进行大小写不敏感的[正规化(NFC)](https://unicode.org/reports/tr15/)比较。\n\n```mira\n\"café\" =~ \"CAFÉ\"; // true\n```\n",
77
+ "!~": "`!~` 是 `=~` 的否定形式(不近似相等)。\n\n```mira\n1 !~ 2; // true\n\"a\" !~ \"A\"; // false\n```\n",
78
+ });
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@mirascript/help",
3
+ "version": "0.1.40",
4
+ "author": "CloudPSS",
5
+ "license": "MIT",
6
+ "description": "Help documentation for Mirascript core language.",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": "./dist/index.js",
12
+ "./package.json": "./package.json"
13
+ },
14
+ "devDependencies": {
15
+ "js-yaml": "^4.1.1"
16
+ },
17
+ "scripts": {
18
+ "build": "pnpm clean && node ./scripts/build.js",
19
+ "clean": "rimraf dist"
20
+ }
21
+ }
@@ -0,0 +1,165 @@
1
+ import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { load } from 'js-yaml';
4
+
5
+ const packageRoot = path.resolve(import.meta.dirname, '..');
6
+ const srcRoot = path.join(packageRoot, 'src');
7
+ const distRoot = path.join(packageRoot, 'dist');
8
+
9
+ /**
10
+ * Front-matter driven docs.
11
+ *
12
+ * Each markdown file under `src/keyword` and `src/operator` must have:
13
+ *
14
+ * ---
15
+ * token: "..." # actual token used in source code
16
+ * ---
17
+ */
18
+
19
+ /**
20
+ * Read a markdown file under `src/`.
21
+ * @param {string} relativePath
22
+ * @returns {Promise<string>}
23
+ */
24
+ async function readMarkdown(relativePath) {
25
+ const fullPath = path.join(srcRoot, relativePath);
26
+ return readFile(fullPath, 'utf8');
27
+ }
28
+
29
+ const FRONT_MATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n/;
30
+
31
+ /**
32
+ * Extract front-matter and strip it from markdown.
33
+ * @param {string} markdown
34
+ * @param {string} relativePath
35
+ * @returns {{ attributes: Record<string, unknown>, body: string }}
36
+ */
37
+ function splitFrontMatter(markdown, relativePath) {
38
+ const m = FRONT_MATTER_RE.exec(markdown);
39
+ if (!m) {
40
+ throw new Error(`Missing front-matter in ${relativePath}. Add token/order mapping.`);
41
+ }
42
+
43
+ const attributes = load(m[1]);
44
+ let body = markdown.slice(m[0].length);
45
+ // Trim leading newlines and tailing newlines
46
+ body = body.replace(/^\r?\n+/, '').replace(/\r?\n+$/, '') + '\n';
47
+ return { attributes, body };
48
+ }
49
+
50
+ /**
51
+ * Load docs under a folder like `keyword` or `operator`.
52
+ * @param {string} folder
53
+ * @returns {Promise<Array<[string, string]>>}
54
+ */
55
+ async function loadDocsFromFolder(folder) {
56
+ const dirPath = path.join(srcRoot, folder);
57
+ const dirents = await readdir(dirPath, { withFileTypes: true });
58
+
59
+ /** @type {Array<{ token: string; order: number; body: string; file: string }>} */
60
+ const items = [];
61
+
62
+ /**
63
+ * Check and add an item.
64
+ * @param {{ token: string | string[]; body: string; reserved: boolean; file: string }} item
65
+ */
66
+ function putItem(item) {
67
+ if (Array.isArray(item.token)) {
68
+ for (const token of item.token) {
69
+ items.push({ token, body: item.body, reserved: item.reserved, file: item.file });
70
+ }
71
+ return;
72
+ }
73
+ if (typeof item.token != 'string' || !item.token.length) {
74
+ throw new TypeError(`Invalid front-matter field 'token' in ${item.file}`);
75
+ }
76
+ if (item.reserved) {
77
+ return; // skip reserved tokens
78
+ }
79
+ items.push(item);
80
+ }
81
+
82
+ for (const dirent of dirents) {
83
+ if (!dirent.isFile()) continue;
84
+ if (!dirent.name.endsWith('.md')) continue;
85
+
86
+ const relativePath = path.posix.join(folder, dirent.name);
87
+ const markdown = await readMarkdown(relativePath);
88
+ const { attributes, body } = splitFrontMatter(markdown, relativePath);
89
+ const { token, reserved } = attributes;
90
+ putItem({ token, body, reserved: Boolean(reserved), file: relativePath });
91
+ }
92
+
93
+ const seenToken = new Set();
94
+ /** @type {Array<[string, string]>} */
95
+ const entries = [];
96
+ for (const item of items) {
97
+ if (seenToken.has(item.token)) {
98
+ throw new Error(`Duplicate token '${item.token}' (found in ${item.file})`);
99
+ }
100
+ seenToken.add(item.token);
101
+ entries.push([item.token, item.body]);
102
+ }
103
+
104
+ return entries;
105
+ }
106
+
107
+ /**
108
+ * Render an object literal with string keys and raw markdown values.
109
+ * @param {Array<[string, string]>} entries
110
+ * @returns {string}
111
+ */
112
+ function renderObjectLiteral(entries) {
113
+ const lines = entries.map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)},`);
114
+ lines.unshift(' __proto__: null,');
115
+ return `Object.freeze({\n${lines.join('\n')}\n})`;
116
+ }
117
+
118
+ /**
119
+ * Render a `.d.ts` object type with explicit string-literal keys.
120
+ * @param {Array<[string, string]>} entries
121
+ * @returns {string}
122
+ */
123
+ function renderDtsObjectType(entries) {
124
+ const lines = entries.map(([k]) => ` readonly ${JSON.stringify(k)}: string;`);
125
+ return `{\n${lines.join('\n')}\n}`;
126
+ }
127
+
128
+ /**
129
+ * Build `dist/index.js` and `dist/index.d.ts`.
130
+ * @returns {Promise<void>}
131
+ */
132
+ async function main() {
133
+ const keywordEntries = await loadDocsFromFolder('keyword');
134
+ const operatorEntries = await loadDocsFromFolder('operator');
135
+
136
+ await mkdir(distRoot, { recursive: true });
137
+
138
+ const js = [
139
+ '/* Generated by scripts/build.js. Do not edit manually. */',
140
+ '',
141
+ `export const KEYWORDS = ${renderObjectLiteral(keywordEntries)};`,
142
+ `export const OPERATORS = ${renderObjectLiteral(operatorEntries)};`,
143
+ '',
144
+ ].join('\n');
145
+
146
+ const dts = [
147
+ '/* Generated by scripts/build.js. Do not edit manually. */',
148
+ '',
149
+ `export declare const KEYWORDS: ${renderDtsObjectType(keywordEntries)};`,
150
+ `export declare const OPERATORS: ${renderDtsObjectType(operatorEntries)};`,
151
+ '',
152
+ 'export type Keyword = keyof typeof KEYWORDS;',
153
+ 'export type Operator = keyof typeof OPERATORS;',
154
+ '',
155
+ ].join('\n');
156
+
157
+ await writeFile(path.join(distRoot, 'index.js'), js, 'utf8');
158
+ await writeFile(path.join(distRoot, 'index.d.ts'), dts, 'utf8');
159
+ }
160
+
161
+ main().catch((err) => {
162
+ // eslint-disable-next-line no-console
163
+ console.error(err);
164
+ process.exitCode = 1;
165
+ });
@@ -0,0 +1,26 @@
1
+ ---
2
+ token: 'and'
3
+ ---
4
+
5
+ `and` 用于在模式匹配中组合多个模式,也可以作为 `&&` 运算符的替代写法。
6
+
7
+ ---
8
+
9
+ 逻辑与模式:
10
+
11
+ ```mira
12
+ fn is_month(month) {
13
+ month is >= 1 and <= 12
14
+ }
15
+ ```
16
+
17
+ ---
18
+
19
+ 逻辑与运算符:
20
+
21
+ ```mira
22
+ fn is_adult(age) {
23
+ // 等同于 age >= 18 && age <= 65
24
+ age >= 18 and age <= 65
25
+ }
26
+ ```
@@ -0,0 +1,32 @@
1
+ ---
2
+ token: 'break'
3
+ ---
4
+
5
+ `break` 用于提前退出 `for` / `while` / `loop`。
6
+
7
+ ---
8
+
9
+ 基本用法
10
+
11
+ ```mira
12
+ let mut i = 0;
13
+ loop {
14
+ i += 1;
15
+ break;
16
+ }
17
+ ```
18
+
19
+ ---
20
+
21
+ 从循环中返回一个值
22
+
23
+ ```mira
24
+ let mut i = 0;
25
+ let result = loop {
26
+ i += 1;
27
+ if i == 10 {
28
+ break i * 2;
29
+ }
30
+ };
31
+ // result 的值是 20
32
+ ```
@@ -0,0 +1,16 @@
1
+ ---
2
+ token: 'case'
3
+ ---
4
+
5
+ `case` 是 `match` 表达式中的分支。
6
+
7
+ ```mira
8
+ fn age_group(age) {
9
+ match age {
10
+ case 0..12 { "child"}
11
+ case 13..19 { "teenager" }
12
+ case 20..64 { "adult" }
13
+ case _ { "senior" }
14
+ }
15
+ }
16
+ ```
@@ -0,0 +1,10 @@
1
+ ---
2
+ token: 'const'
3
+ ---
4
+
5
+ `const` 用于声明常量。常量名必须以 `@` 开头。
6
+
7
+ ```mira
8
+ const @PI = 3.14159;
9
+ // @PI = 0; // 错误:常量不可重新赋值
10
+ ```
@@ -0,0 +1,14 @@
1
+ ---
2
+ token: 'continue'
3
+ ---
4
+
5
+ `continue` 用于跳过本次循环剩余部分,进入下一次循环。
6
+
7
+ ```mira
8
+ let mut sum = 0;
9
+ for i in 1..5 {
10
+ if i % 2 == 0 { continue; }
11
+ sum += i;
12
+ }
13
+ // sum == 1 + 3 + 5
14
+ ```
@@ -0,0 +1,6 @@
1
+ ---
2
+ token: 'effect'
3
+ reserved: true
4
+ ---
5
+
6
+ `effect` 是保留关键字。
@@ -0,0 +1,32 @@
1
+ ---
2
+ token: 'else'
3
+ ---
4
+
5
+ `else` 用于 `if` 表达式,也可用作 `while` 和 `for` 循环的可选分支。
6
+
7
+ ---
8
+
9
+ 作为 `if` 表达式的分支
10
+
11
+ ```mira
12
+ let x = if false { 1 } else { 2 }; // 2
13
+ ```
14
+
15
+ ---
16
+
17
+ 作为循环的可选分支
18
+
19
+ ```mira
20
+ let mut i = 0;
21
+ let result = while i < 5 {
22
+ i += 1;
23
+ if i == 6 {
24
+ // 使用 break 语句提前退出循环,并返回一个值
25
+ break i * 2;
26
+ }
27
+ } else {
28
+ // 当循环正常结束时执行
29
+ 100
30
+ };
31
+ // result 的值是 100
32
+ ```
@@ -0,0 +1,5 @@
1
+ ---
2
+ token: 'false'
3
+ ---
4
+
5
+ `false` 是布尔字面量,表示逻辑假。
@@ -0,0 +1,6 @@
1
+ ---
2
+ token: 'finally'
3
+ reserved: true
4
+ ---
5
+
6
+ `finally` 是保留关键字。
@@ -0,0 +1,35 @@
1
+ ---
2
+ token: 'fn'
3
+ ---
4
+
5
+ 使用 `fn` 关键字定义一个函数或函数表达式。
6
+
7
+ ---
8
+
9
+ 定义一个简单的函数:
10
+
11
+ ```mira
12
+ fn add(a, b) {
13
+ return a + b;
14
+ }
15
+ ```
16
+
17
+ ---
18
+
19
+ 定义一个变量,并使用函数表达式初始化:
20
+
21
+ ```mira
22
+ let multiply = fn(x, y) {
23
+ return x * y;
24
+ };
25
+ ```
26
+
27
+ ---
28
+
29
+ 当函数只有一个参数时,可以省略括号,并用 `it` 引用该参数。
30
+
31
+ ```mira
32
+ fn square {
33
+ return it * it;
34
+ }
35
+ ```
@@ -0,0 +1,43 @@
1
+ ---
2
+ token: 'for'
3
+ ---
4
+
5
+ `for` 用于遍历可迭代对象。
6
+
7
+ ---
8
+
9
+ 遍历一个范围:
10
+
11
+ ```mira
12
+ let mut sum = 0;
13
+ for i in 1..3 { // 或者 1..<4
14
+ sum += i;
15
+ }
16
+ // sum == 6
17
+ ```
18
+
19
+ ---
20
+
21
+ 遍历一个数组:
22
+
23
+ ```mira
24
+ let arr = [10, 20, 30];
25
+ let mut sum = 0;
26
+ for value in arr {
27
+ sum += value;
28
+ }
29
+ // sum == 60
30
+ ```
31
+
32
+ ---
33
+
34
+ 遍历一个记录:
35
+
36
+ ```mira
37
+ let record = (a: 1, b: 2, c: 3);
38
+ let mut sum = 0;
39
+ for key in record {
40
+ sum += record[key];
41
+ }
42
+ // sum == 6
43
+ ```
@@ -0,0 +1,16 @@
1
+ ---
2
+ token: 'global'
3
+ ---
4
+
5
+ `global` 表示全局对象(全局命名空间)。通常用于读取全局变量或判断某个全局键是否存在。
6
+
7
+ ```mira
8
+ // 访问全局变量
9
+ global.some_name;
10
+
11
+ // 动态访问全局变量
12
+ global['some_name'];
13
+
14
+ // 判断键是否存在
15
+ 'some_name' in global;
16
+ ```
@@ -0,0 +1,6 @@
1
+ ---
2
+ token: 'handle'
3
+ reserved: true
4
+ ---
5
+
6
+ `handle` 是保留关键字。
@@ -0,0 +1,40 @@
1
+ ---
2
+ token: 'if'
3
+ ---
4
+
5
+ `if` 用于 `if` 表达式或 `match` 表达式的守卫条件。
6
+
7
+ ---
8
+
9
+ `if` 表达式根据条件选择分支。条件必须是 `boolean`。
10
+
11
+ ```mira
12
+ let x = if 1 > 0 { "pos" } else { "neg" };
13
+ ```
14
+
15
+ ---
16
+
17
+ 使用 `else if` 添加多个条件分支:
18
+
19
+ ```mira
20
+ let x = if 1 > 2 {
21
+ "greater"
22
+ } else if 1 == 2 {
23
+ "equal"
24
+ } else {
25
+ "less"
26
+ };
27
+ ```
28
+
29
+ ---
30
+
31
+ 在 `match` 表达式中使用 `if` 作为守卫条件:
32
+
33
+ ```mira
34
+ let num = 10;
35
+ let result = match num {
36
+ case n if n % 2 == 0 { "even" }
37
+ case n { "odd" }
38
+ };
39
+ // result 的值是 "even"
40
+ ```