diff options
Diffstat (limited to 'doc/docs/doc/README.md')
-rwxr-xr-x | doc/docs/doc/README.md | 574 |
1 files changed, 511 insertions, 63 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index c4518bf..f0d67a5 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md | |||
@@ -16,19 +16,29 @@ Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ]. | |||
16 | ### An Overview of YueScript | 16 | ### An Overview of YueScript |
17 | ```moonscript | 17 | ```moonscript |
18 | -- import syntax | 18 | -- import syntax |
19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
20 | 20 | ||
21 | -- object literals | 21 | -- object literals |
22 | inventory = | 22 | inventory = |
23 | equipment: | 23 | equipment: |
24 | * "sword" | 24 | - "sword" |
25 | * "shield" | 25 | - "shield" |
26 | items: | 26 | items: |
27 | * name: "potion" | 27 | - name: "potion" |
28 | count: 10 | 28 | count: 10 |
29 | * name: "bread" | 29 | - name: "bread" |
30 | count: 3 | 30 | count: 3 |
31 | 31 | ||
32 | -- list comprehension | ||
33 | map = (arr, action) -> | ||
34 | [action item for item in *arr] | ||
35 | |||
36 | filter = (arr, cond) -> | ||
37 | [item for item in *arr when cond item] | ||
38 | |||
39 | reduce = (arr, init, action): init -> | ||
40 | init = action init, item for item in *arr | ||
41 | |||
32 | -- pipe operator | 42 | -- pipe operator |
33 | [1, 2, 3] | 43 | [1, 2, 3] |
34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本" | |||
51 | <YueDisplay> | 61 | <YueDisplay> |
52 | <pre> | 62 | <pre> |
53 | -- import syntax | 63 | -- import syntax |
54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
55 | 65 | ||
56 | -- object literals | 66 | -- object literals |
57 | inventory = | 67 | inventory = |
58 | equipment: | 68 | equipment: |
59 | * "sword" | 69 | - "sword" |
60 | * "shield" | 70 | - "shield" |
61 | items: | 71 | items: |
62 | * name: "potion" | 72 | - name: "potion" |
63 | count: 10 | 73 | count: 10 |
64 | * name: "bread" | 74 | - name: "bread" |
65 | count: 3 | 75 | count: 3 |
66 | 76 | ||
77 | -- list comprehension | ||
78 | map = (arr, action) -> | ||
79 | [action item for item in *arr] | ||
80 | |||
81 | filter = (arr, cond) -> | ||
82 | [item for item in *arr when cond item] | ||
83 | |||
84 | reduce = (arr, init, action): init -> | ||
85 | init = action init, item for item in *arr | ||
86 | |||
67 | -- pipe operator | 87 | -- pipe operator |
68 | [1, 2, 3] | 88 | [1, 2, 3] |
69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本" | |||
132 | 152 | ||
133 |  Use YueScript module in Lua: | 153 |  Use YueScript module in Lua: |
134 | 154 | ||
135 | * **Case 1** | 155 | * **Case 1** |
136 | Require "your_yuescript_entry.yue" in Lua. | 156 | Require "your_yuescript_entry.yue" in Lua. |
137 | ```Lua | 157 | ```Lua |
138 | require("yue")("your_yuescript_entry") | 158 | require("yue")("your_yuescript_entry") |
139 | ``` | 159 | ``` |
140 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. | 160 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. |
141 | 161 | ||
142 | * **Case 2** | 162 | * **Case 2** |
143 | Require YueScript module and rewite message by hand. | 163 | Require YueScript module and rewite message by hand. |
144 | ```lua | 164 | ```lua |
145 | local yue = require("yue") | 165 | local yue = require("yue") |
@@ -151,7 +171,7 @@ end, function(err) | |||
151 | end) | 171 | end) |
152 | ``` | 172 | ``` |
153 | 173 | ||
154 | * **Case 3** | 174 | * **Case 3** |
155 | Use the YueScript compiler function in Lua. | 175 | Use the YueScript compiler function in Lua. |
156 | ```lua | 176 | ```lua |
157 | local yue = require("yue") | 177 | local yue = require("yue") |
@@ -203,12 +223,12 @@ Usage: yue [options|files|directories] ... | |||
203 | Execute without options to enter REPL, type symbol '$' | 223 | Execute without options to enter REPL, type symbol '$' |
204 | in a single line to start/stop multi-line mode | 224 | in a single line to start/stop multi-line mode |
205 | ``` | 225 | ``` |
206 |   Use cases: | 226 |   Use cases: |
207 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** | 227 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** |
208 |   Compile and save results to a target path: **yue -t /target/path/ .** | 228 |   Compile and save results to a target path: **yue -t /target/path/ .** |
209 |   Compile and reserve debug info: **yue -l .** | 229 |   Compile and reserve debug info: **yue -l .** |
210 |   Compile and generate minified codes: **yue -m .** | 230 |   Compile and generate minified codes: **yue -m .** |
211 |   Execute raw codes: **yue -e 'print 123'** | 231 |   Execute raw codes: **yue -e 'print 123'** |
212 |   Execute a YueScript file: **yue -e main.yue** | 232 |   Execute a YueScript file: **yue -e main.yue** |
213 | 233 | ||
214 | ## Macro | 234 | ## Macro |
@@ -424,6 +444,54 @@ print "Valid enum type:", $BodyType Static | |||
424 | </pre> | 444 | </pre> |
425 | </YueDisplay> | 445 | </YueDisplay> |
426 | 446 | ||
447 | ### Argument Validation | ||
448 | |||
449 | You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time. | ||
450 | |||
451 | ```moonscript | ||
452 | macro printNumAndStr = (num `Num, str `String) -> | | ||
453 | print( | ||
454 | #{num} | ||
455 | #{str} | ||
456 | ) | ||
457 | |||
458 | $printNumAndStr 123, "hello" | ||
459 | ``` | ||
460 | <YueDisplay> | ||
461 | <pre> | ||
462 | macro printNumAndStr = (num `Num, str `String) -> | | ||
463 | print( | ||
464 | #{num} | ||
465 | #{str} | ||
466 | ) | ||
467 | |||
468 | $printNumAndStr 123, "hello" | ||
469 | </pre> | ||
470 | </YueDisplay> | ||
471 | |||
472 | If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place. | ||
473 | |||
474 | ```moonscript | ||
475 | macro printNumAndStr = (num, str) -> | ||
476 | error "expected Num as first argument" unless $is_ast Num, num | ||
477 | error "expected String as second argument" unless $is_ast String, str | ||
478 | "print(#{num}, #{str})" | ||
479 | |||
480 | $printNumAndStr 123, "hello" | ||
481 | ``` | ||
482 | <YueDisplay> | ||
483 | <pre> | ||
484 | macro printNumAndStr = (num, str) -> | ||
485 | error "expected Num as first argument" unless $is_ast Num, num | ||
486 | error "expected String as second argument" unless $is_ast String, str | ||
487 | "print(#{num}, #{str})" | ||
488 | |||
489 | $printNumAndStr 123, "hello" | ||
490 | </pre> | ||
491 | </YueDisplay> | ||
492 | |||
493 | For more details about available AST nodes, please refer to the uppercased definitions in [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp). | ||
494 | |||
427 | ## Operator | 495 | ## Operator |
428 | 496 | ||
429 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. | 497 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. |
@@ -566,11 +634,26 @@ merge = {...a, ...b} | |||
566 | </pre> | 634 | </pre> |
567 | </YueDisplay> | 635 | </YueDisplay> |
568 | 636 | ||
637 | ### Table Reversed Indexing | ||
638 | |||
639 | You can use the **#** operator to get the last elements of a table. | ||
640 | |||
641 | ```moonscript | ||
642 | last = data.items[#] | ||
643 | second_last = data.items[#-1] | ||
644 | ``` | ||
645 | <YueDisplay> | ||
646 | <pre> | ||
647 | last = data.items[#] | ||
648 | second_last = data.items[#-1] | ||
649 | </pre> | ||
650 | </YueDisplay> | ||
651 | |||
569 | ### Metatable | 652 | ### Metatable |
570 | 653 | ||
571 | The **<>** operator can be used as a shortcut for metatable manipulation. | 654 | The **<>** operator can be used as a shortcut for metatable manipulation. |
572 | 655 | ||
573 | * **Metatable Creation** | 656 | * **Metatable Creation** |
574 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. | 657 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. |
575 | 658 | ||
576 | ```moonscript | 659 | ```moonscript |
@@ -606,7 +689,7 @@ close _ = <close>: -> print "out of scope" | |||
606 | </pre> | 689 | </pre> |
607 | </YueDisplay> | 690 | </YueDisplay> |
608 | 691 | ||
609 | * **Metatable Accessing** | 692 | * **Metatable Accessing** |
610 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. | 693 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. |
611 | 694 | ||
612 | ```moonscript | 695 | ```moonscript |
@@ -630,7 +713,7 @@ print tb.item | |||
630 | </pre> | 713 | </pre> |
631 | </YueDisplay> | 714 | </YueDisplay> |
632 | 715 | ||
633 | * **Metatable Destructure** | 716 | * **Metatable Destructure** |
634 | Destruct metatable with metamethod key surrounded by **<>**. | 717 | Destruct metatable with metamethod key surrounded by **<>**. |
635 | 718 | ||
636 | ```moonscript | 719 | ```moonscript |
@@ -732,34 +815,45 @@ a ??= false | |||
732 | 815 | ||
733 | ### Implicit Object | 816 | ### Implicit Object |
734 | 817 | ||
735 | You can write a list of implicit structures that starts with the symbol **\*** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. | 818 | You can write a list of implicit structures that starts with the symbol **\*** or **-** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. |
819 | |||
736 | ```moonscript | 820 | ```moonscript |
821 | -- assignment with implicit object | ||
737 | list = | 822 | list = |
738 | * 1 | 823 | * 1 |
739 | * 2 | 824 | * 2 |
740 | * 3 | 825 | * 3 |
741 | 826 | ||
827 | -- function call with implicit object | ||
742 | func | 828 | func |
743 | * 1 | 829 | * 1 |
744 | * 2 | 830 | * 2 |
745 | * 3 | 831 | * 3 |
746 | 832 | ||
833 | -- return with implicit object | ||
834 | f = -> | ||
835 | return | ||
836 | * 1 | ||
837 | * 2 | ||
838 | * 3 | ||
839 | |||
840 | -- table with implicit object | ||
747 | tb = | 841 | tb = |
748 | name: "abc" | 842 | name: "abc" |
749 | 843 | ||
750 | values: | 844 | values: |
751 | * "a" | 845 | - "a" |
752 | * "b" | 846 | - "b" |
753 | * "c" | 847 | - "c" |
754 | 848 | ||
755 | objects: | 849 | objects: |
756 | * name: "a" | 850 | - name: "a" |
757 | value: 1 | 851 | value: 1 |
758 | func: => @value + 1 | 852 | func: => @value + 1 |
759 | tb: | 853 | tb: |
760 | fieldA: 1 | 854 | fieldA: 1 |
761 | 855 | ||
762 | * name: "b" | 856 | - name: "b" |
763 | value: 2 | 857 | value: 2 |
764 | func: => @value + 2 | 858 | func: => @value + 2 |
765 | tb: { } | 859 | tb: { } |
@@ -767,32 +861,42 @@ tb = | |||
767 | ``` | 861 | ``` |
768 | <YueDisplay> | 862 | <YueDisplay> |
769 | <pre> | 863 | <pre> |
864 | -- assignment with implicit object | ||
770 | list = | 865 | list = |
771 | * 1 | 866 | * 1 |
772 | * 2 | 867 | * 2 |
773 | * 3 | 868 | * 3 |
774 | 869 | ||
870 | -- function call with implicit object | ||
775 | func | 871 | func |
776 | * 1 | 872 | * 1 |
777 | * 2 | 873 | * 2 |
778 | * 3 | 874 | * 3 |
779 | 875 | ||
876 | -- return with implicit object | ||
877 | f = -> | ||
878 | return | ||
879 | * 1 | ||
880 | * 2 | ||
881 | * 3 | ||
882 | |||
883 | -- table with implicit object | ||
780 | tb = | 884 | tb = |
781 | name: "abc" | 885 | name: "abc" |
782 | 886 | ||
783 | values: | 887 | values: |
784 | * "a" | 888 | - "a" |
785 | * "b" | 889 | - "b" |
786 | * "c" | 890 | - "c" |
787 | 891 | ||
788 | objects: | 892 | objects: |
789 | * name: "a" | 893 | - name: "a" |
790 | value: 1 | 894 | value: 1 |
791 | func: => @value + 1 | 895 | func: => @value + 1 |
792 | tb: | 896 | tb: |
793 | fieldA: 1 | 897 | fieldA: 1 |
794 | 898 | ||
795 | * name: "b" | 899 | - name: "b" |
796 | value: 2 | 900 | value: 2 |
797 | func: => @value + 2 | 901 | func: => @value + 2 |
798 | tb: { } | 902 | tb: { } |
@@ -860,7 +964,7 @@ do | |||
860 | 964 | ||
861 | The export statement offers a concise way to define modules. | 965 | The export statement offers a concise way to define modules. |
862 | 966 | ||
863 | * **Named Export** | 967 | * **Named Export** |
864 | Named export will define a local variable as well as adding a field in the exported table. | 968 | Named export will define a local variable as well as adding a field in the exported table. |
865 | 969 | ||
866 | ```moonscript | 970 | ```moonscript |
@@ -924,7 +1028,7 @@ export["a-b-c"] = 123 | |||
924 | </pre> | 1028 | </pre> |
925 | </YueDisplay> | 1029 | </YueDisplay> |
926 | 1030 | ||
927 | * **Unnamed Export** | 1031 | * **Unnamed Export** |
928 | Unnamed export will add the target item into the array part of the exported table. | 1032 | Unnamed export will add the target item into the array part of the exported table. |
929 | 1033 | ||
930 | ```moonscript | 1034 | ```moonscript |
@@ -954,7 +1058,7 @@ export with tmp | |||
954 | </pre> | 1058 | </pre> |
955 | </YueDisplay> | 1059 | </YueDisplay> |
956 | 1060 | ||
957 | * **Default Export** | 1061 | * **Default Export** |
958 | Using the **default** keyword in export statement to replace the exported table with any thing. | 1062 | Using the **default** keyword in export statement to replace the exported table with any thing. |
959 | 1063 | ||
960 | ```moonscript | 1064 | ```moonscript |
@@ -1202,7 +1306,7 @@ If the destructuring statement is complicated, feel free to spread it out over a | |||
1202 | </pre> | 1306 | </pre> |
1203 | </YueDisplay> | 1307 | </YueDisplay> |
1204 | 1308 | ||
1205 | It’s common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: | 1309 | It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: |
1206 | 1310 | ||
1207 | ```moonscript | 1311 | ```moonscript |
1208 | {:concat, :insert} = table | 1312 | {:concat, :insert} = table |
@@ -1246,6 +1350,52 @@ You can use `_` as placeholder when doing a list destructuring: | |||
1246 | </pre> | 1350 | </pre> |
1247 | </YueDisplay> | 1351 | </YueDisplay> |
1248 | 1352 | ||
1353 | ### Range Destructuring | ||
1354 | |||
1355 | You can use the spread operator `...` in list destructuring to capture a range of values. This is useful when you want to extract specific elements from the beginning and end of a list while collecting the rest in between. | ||
1356 | |||
1357 | ```moonscript | ||
1358 | orders = ["first", "second", "third", "fourth", "last"] | ||
1359 | [first, ...bulk, last] = orders | ||
1360 | print first -- prints: first | ||
1361 | print bulk -- prints: {"second", "third", "fourth"} | ||
1362 | print last -- prints: last | ||
1363 | ``` | ||
1364 | <YueDisplay> | ||
1365 | <pre> | ||
1366 | orders = ["first", "second", "third", "fourth", "last"] | ||
1367 | [first, ...bulk, last] = orders | ||
1368 | print first -- prints: first | ||
1369 | print bulk -- prints: {"second", "third", "fourth"} | ||
1370 | print last -- prints: last | ||
1371 | </pre> | ||
1372 | </YueDisplay> | ||
1373 | |||
1374 | The spread operator can be used in different positions to capture different ranges, and you can use `_` as a placeholder for the values you don't want to capture: | ||
1375 | |||
1376 | ```moonscript | ||
1377 | -- Capture everything after first element | ||
1378 | [first, ...rest] = orders | ||
1379 | |||
1380 | -- Capture everything before last element | ||
1381 | [...start, last] = orders | ||
1382 | |||
1383 | -- Capture things except the middle elements | ||
1384 | [first, ..._, last] = orders | ||
1385 | ``` | ||
1386 | <YueDisplay> | ||
1387 | <pre> | ||
1388 | -- Capture everything after first element | ||
1389 | [first, ...rest] = orders | ||
1390 | |||
1391 | -- Capture everything before last element | ||
1392 | [...start, last] = orders | ||
1393 | |||
1394 | -- Capture things except the middle elements | ||
1395 | [first, ..._, last] = orders | ||
1396 | </pre> | ||
1397 | </YueDisplay> | ||
1398 | |||
1249 | ### Destructuring In Other Places | 1399 | ### Destructuring In Other Places |
1250 | 1400 | ||
1251 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: | 1401 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: |
@@ -1475,6 +1625,47 @@ catch err | |||
1475 | </pre> | 1625 | </pre> |
1476 | </YueDisplay> | 1626 | </YueDisplay> |
1477 | 1627 | ||
1628 | ### Try? | ||
1629 | |||
1630 | `try?` is a simplified use for error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, return nil instead of error object otherwise. | ||
1631 | |||
1632 | ```moonscript | ||
1633 | a, b, c = try? func! | ||
1634 | |||
1635 | -- with nil coalescing operator | ||
1636 | a = (try? func!) ?? "default" | ||
1637 | |||
1638 | -- as function argument | ||
1639 | f try? func! | ||
1640 | |||
1641 | -- with catch block | ||
1642 | f try? | ||
1643 | print 123 | ||
1644 | func! | ||
1645 | catch e | ||
1646 | print e | ||
1647 | e | ||
1648 | ``` | ||
1649 | <YueDisplay> | ||
1650 | <pre> | ||
1651 | a, b, c = try? func! | ||
1652 | |||
1653 | -- with nil coalescing operator | ||
1654 | a = (try? func!) ?? "default" | ||
1655 | |||
1656 | -- as function argument | ||
1657 | f try? func! | ||
1658 | |||
1659 | -- with catch block | ||
1660 | f try? | ||
1661 | print 123 | ||
1662 | func! | ||
1663 | catch e | ||
1664 | print e | ||
1665 | e | ||
1666 | </pre> | ||
1667 | </YueDisplay> | ||
1668 | |||
1478 | ## Attributes | 1669 | ## Attributes |
1479 | 1670 | ||
1480 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. | 1671 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. |
@@ -1503,6 +1694,19 @@ const {:a, :b, c, d} = tb | |||
1503 | </pre> | 1694 | </pre> |
1504 | </YueDisplay> | 1695 | </YueDisplay> |
1505 | 1696 | ||
1697 | You can also declare a global variable to be `const`. | ||
1698 | |||
1699 | ```moonscript | ||
1700 | global const Constant = 123 | ||
1701 | -- Constant = 1 | ||
1702 | ``` | ||
1703 | <YueDisplay> | ||
1704 | <pre> | ||
1705 | global const Constant = 123 | ||
1706 | -- Constant = 1 | ||
1707 | </pre> | ||
1708 | </YueDisplay> | ||
1709 | |||
1506 | ## Literals | 1710 | ## Literals |
1507 | 1711 | ||
1508 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. | 1712 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. |
@@ -1535,12 +1739,73 @@ You can use underscores in a number literal to increase readability. | |||
1535 | ```moonscript | 1739 | ```moonscript |
1536 | integer = 1_000_000 | 1740 | integer = 1_000_000 |
1537 | hex = 0xEF_BB_BF | 1741 | hex = 0xEF_BB_BF |
1742 | binary = 0B10011 | ||
1538 | ``` | 1743 | ``` |
1539 | <YueDisplay> | 1744 | <YueDisplay> |
1540 | 1745 | ||
1541 | <pre> | 1746 | <pre> |
1542 | integer = 1_000_000 | 1747 | integer = 1_000_000 |
1543 | hex = 0xEF_BB_BF | 1748 | hex = 0xEF_BB_BF |
1749 | binary = 0B10011 | ||
1750 | </pre> | ||
1751 | </YueDisplay> | ||
1752 | |||
1753 | ### YAML Multiline String | ||
1754 | |||
1755 | The `|` prefix introduces a YAML-style multiline string literal: | ||
1756 | |||
1757 | ```moonscript | ||
1758 | str = | | ||
1759 | key: value | ||
1760 | list: | ||
1761 | - item1 | ||
1762 | - #{expr} | ||
1763 | ``` | ||
1764 | <YueDisplay> | ||
1765 | <pre> | ||
1766 | str = | | ||
1767 | key: value | ||
1768 | list: | ||
1769 | - item1 | ||
1770 | - #{expr} | ||
1771 | </pre> | ||
1772 | </YueDisplay> | ||
1773 | |||
1774 | This allows writing structured multiline text conveniently. All line breaks and indentation are preserved relative to the first non-empty line, and expressions inside `#{...}` are interpolated automatically as `tostring(expr)`. | ||
1775 | |||
1776 | YAML Multiline String automatically detects the common leading whitespace prefix (minimum indentation across all non-empty lines) and removes it from all lines. This makes it easy to indent your code visually without affecting the resulting string content. | ||
1777 | |||
1778 | ```moonscript | ||
1779 | fn = -> | ||
1780 | str = | | ||
1781 | foo: | ||
1782 | bar: baz | ||
1783 | return str | ||
1784 | ``` | ||
1785 | <YueDisplay> | ||
1786 | <pre> | ||
1787 | fn = -> | ||
1788 | str = | | ||
1789 | foo: | ||
1790 | bar: baz | ||
1791 | return str | ||
1792 | </pre> | ||
1793 | </YueDisplay> | ||
1794 | |||
1795 | Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures. | ||
1796 | |||
1797 | All special characters like quotes (`"`) and backslashes (`\`) in the YAMLMultiline block are automatically escaped so that the generated Lua string is syntactically valid and behaves as expected. | ||
1798 | |||
1799 | ```moonscript | ||
1800 | str = | | ||
1801 | path: "C:\Program Files\App" | ||
1802 | note: 'He said: "#{Hello}!"' | ||
1803 | ``` | ||
1804 | <YueDisplay> | ||
1805 | <pre> | ||
1806 | str = | | ||
1807 | path: "C:\Program Files\App" | ||
1808 | note: 'He said: "#{Hello}!"' | ||
1544 | </pre> | 1809 | </pre> |
1545 | </YueDisplay> | 1810 | </YueDisplay> |
1546 | 1811 | ||
@@ -1902,22 +2167,22 @@ x * 2 | |||
1902 | </pre> | 2167 | </pre> |
1903 | </YueDisplay> | 2168 | </YueDisplay> |
1904 | 2169 | ||
1905 | If you wish to have further code after your backcalls, you can set them aside with a do statement. | 2170 | If you wish to have further code after your backcalls, you can set them aside with a do statement. And the parentheses can be omitted with non-fat arrow functions. |
1906 | 2171 | ||
1907 | ```moonscript | 2172 | ```moonscript |
1908 | result, msg = do | 2173 | result, msg = do |
1909 | (data) <- readAsync "filename.txt" | 2174 | data <- readAsync "filename.txt" |
1910 | print data | 2175 | print data |
1911 | (info) <- processAsync data | 2176 | info <- processAsync data |
1912 | check info | 2177 | check info |
1913 | print result, msg | 2178 | print result, msg |
1914 | ``` | 2179 | ``` |
1915 | <YueDisplay> | 2180 | <YueDisplay> |
1916 | <pre> | 2181 | <pre> |
1917 | result, msg = do | 2182 | result, msg = do |
1918 | (data) <- readAsync "filename.txt" | 2183 | data <- readAsync "filename.txt" |
1919 | print data | 2184 | print data |
1920 | (info) <- processAsync data | 2185 | info <- processAsync data |
1921 | check info | 2186 | check info |
1922 | print result, msg | 2187 | print result, msg |
1923 | </pre> | 2188 | </pre> |
@@ -2248,6 +2513,45 @@ slice = [item for item in *items[,,2]] | |||
2248 | </pre> | 2513 | </pre> |
2249 | </YueDisplay> | 2514 | </YueDisplay> |
2250 | 2515 | ||
2516 | Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table. | ||
2517 | |||
2518 | ```moonscript | ||
2519 | -- take the last 4 items | ||
2520 | slice = [item for item in *items[-4,-1]] | ||
2521 | ``` | ||
2522 | <YueDisplay> | ||
2523 | <pre> | ||
2524 | -- take the last 4 items | ||
2525 | slice = [item for item in *items[-4,-1]] | ||
2526 | </pre> | ||
2527 | </YueDisplay> | ||
2528 | |||
2529 | The step size can also be negative, which means that the items are taken in reverse order. | ||
2530 | |||
2531 | ```moonscript | ||
2532 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2533 | ``` | ||
2534 | <YueDisplay> | ||
2535 | <pre> | ||
2536 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
2537 | </pre> | ||
2538 | </YueDisplay> | ||
2539 | |||
2540 | #### Slicing Expression | ||
2541 | |||
2542 | Slicing can also be used as an expression. This is useful for getting a sub-list of a table. | ||
2543 | |||
2544 | ```moonscript | ||
2545 | -- take the 2nd and 4th items as a new list | ||
2546 | sub_list = items[2, 4] | ||
2547 | ``` | ||
2548 | <YueDisplay> | ||
2549 | <pre> | ||
2550 | -- take the 2nd and 4th items as a new list | ||
2551 | sub_list = items[2, 4] | ||
2552 | </pre> | ||
2553 | </YueDisplay> | ||
2554 | |||
2251 | ## For Loop | 2555 | ## For Loop |
2252 | 2556 | ||
2253 | There are two for loop forms, just like in Lua. A numeric one and a generic one: | 2557 | There are two for loop forms, just like in Lua. A numeric one and a generic one: |
@@ -2324,6 +2628,23 @@ doubled_evens = for i = 1, 20 | |||
2324 | </pre> | 2628 | </pre> |
2325 | </YueDisplay> | 2629 | </YueDisplay> |
2326 | 2630 | ||
2631 | In addition, for loops support break with a return value, allowing the loop itself to be used as an expression that exits early with a meaningful result. | ||
2632 | |||
2633 | For example, to find the first number greater than 10: | ||
2634 | |||
2635 | ```moonscript | ||
2636 | first_large = for n in *numbers | ||
2637 | break n if n > 10 | ||
2638 | ``` | ||
2639 | <YueDisplay> | ||
2640 | <pre> | ||
2641 | first_large = for n in *numbers | ||
2642 | break n if n > 10 | ||
2643 | </pre> | ||
2644 | </YueDisplay> | ||
2645 | |||
2646 | This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions. | ||
2647 | |||
2327 | You can also filter values by combining the for loop expression with the continue statement. | 2648 | You can also filter values by combining the for loop expression with the continue statement. |
2328 | 2649 | ||
2329 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. | 2650 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. |
@@ -2345,7 +2666,7 @@ print func_b! -- prints table object | |||
2345 | </pre> | 2666 | </pre> |
2346 | </YueDisplay> | 2667 | </YueDisplay> |
2347 | 2668 | ||
2348 | This is done to avoid the needless creation of tables for functions that don’t need to return the results of the loop. | 2669 | This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop. |
2349 | 2670 | ||
2350 | ## Repeat Loop | 2671 | ## Repeat Loop |
2351 | 2672 | ||
@@ -2624,28 +2945,26 @@ reader\parse_line! until reader\eof! | |||
2624 | 2945 | ||
2625 | ## Switch | 2946 | ## Switch |
2626 | 2947 | ||
2627 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. | 2948 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. In switch statement, you can also use assignment expression to store temporary variable value. |
2628 | 2949 | ||
2629 | ```moonscript | 2950 | ```moonscript |
2630 | name = "Dan" | 2951 | switch name := "Dan" |
2631 | switch name | ||
2632 | when "Robert" | 2952 | when "Robert" |
2633 | print "You are Robert" | 2953 | print "You are Robert" |
2634 | when "Dan", "Daniel" | 2954 | when "Dan", "Daniel" |
2635 | print "Your name, it's Dan" | 2955 | print "Your name, it's Dan" |
2636 | else | 2956 | else |
2637 | print "I don't know about your name" | 2957 | print "I don't know about you with name #{name}" |
2638 | ``` | 2958 | ``` |
2639 | <YueDisplay> | 2959 | <YueDisplay> |
2640 | <pre> | 2960 | <pre> |
2641 | name = "Dan" | 2961 | switch name := "Dan" |
2642 | switch name | ||
2643 | when "Robert" | 2962 | when "Robert" |
2644 | print "You are Robert" | 2963 | print "You are Robert" |
2645 | when "Dan", "Daniel" | 2964 | when "Dan", "Daniel" |
2646 | print "Your name, it's Dan" | 2965 | print "Your name, it's Dan" |
2647 | else | 2966 | else |
2648 | print "I don't know about your name" | 2967 | print "I don't know about you with name #{name}" |
2649 | </pre> | 2968 | </pre> |
2650 | </YueDisplay> | 2969 | </YueDisplay> |
2651 | 2970 | ||
@@ -2676,7 +2995,7 @@ next_number = switch b | |||
2676 | </pre> | 2995 | </pre> |
2677 | </YueDisplay> | 2996 | </YueDisplay> |
2678 | 2997 | ||
2679 | We can use the then keyword to write a switch’s when block on a single line. No extra keyword is needed to write the else block on a single line. | 2998 | We can use the then keyword to write a switch's when block on a single line. No extra keyword is needed to write the else block on a single line. |
2680 | 2999 | ||
2681 | ```moonscript | 3000 | ```moonscript |
2682 | msg = switch math.random(1, 5) | 3001 | msg = switch math.random(1, 5) |
@@ -2722,7 +3041,7 @@ else | |||
2722 | </pre> | 3041 | </pre> |
2723 | </YueDisplay> | 3042 | </YueDisplay> |
2724 | 3043 | ||
2725 | It is worth noting the order of the case comparison expression. The case’s expression is on the left hand side. This can be useful if the case’s expression wants to overwrite how the comparison is done by defining an eq metamethod. | 3044 | It is worth noting the order of the case comparison expression. The case's expression is on the left hand side. This can be useful if the case's expression wants to overwrite how the comparison is done by defining an eq metamethod. |
2726 | 3045 | ||
2727 | ### Table Matching | 3046 | ### Table Matching |
2728 | 3047 | ||
@@ -2782,6 +3101,123 @@ switch item | |||
2782 | </pre> | 3101 | </pre> |
2783 | </YueDisplay> | 3102 | </YueDisplay> |
2784 | 3103 | ||
3104 | You can also match against array elements, table fields, and even nested structures with array or table literals. | ||
3105 | |||
3106 | Match against array elements. | ||
3107 | |||
3108 | ```moonscript | ||
3109 | switch tb | ||
3110 | when [1, 2, 3] | ||
3111 | print "1, 2, 3" | ||
3112 | when [1, b, 3] | ||
3113 | print "1, #{b}, 3" | ||
3114 | when [1, 2, b = 3] -- b has a default value | ||
3115 | print "1, 2, #{b}" | ||
3116 | ``` | ||
3117 | <YueDisplay> | ||
3118 | <pre> | ||
3119 | switch tb | ||
3120 | when [1, 2, 3] | ||
3121 | print "1, 2, 3" | ||
3122 | when [1, b, 3] | ||
3123 | print "1, #{b}, 3" | ||
3124 | when [1, 2, b = 3] -- b has a default value | ||
3125 | print "1, 2, #{b}" | ||
3126 | </pre> | ||
3127 | </YueDisplay> | ||
3128 | |||
3129 | Match against table fields with destructuring. | ||
3130 | |||
3131 | ```moonscript | ||
3132 | switch tb | ||
3133 | when success: true, :result | ||
3134 | print "success", result | ||
3135 | when success: false | ||
3136 | print "failed", result | ||
3137 | else | ||
3138 | print "invalid" | ||
3139 | ``` | ||
3140 | <YueDisplay> | ||
3141 | <pre> | ||
3142 | switch tb | ||
3143 | when success: true, :result | ||
3144 | print "success", result | ||
3145 | when success: false | ||
3146 | print "failed", result | ||
3147 | else | ||
3148 | print "invalid" | ||
3149 | </pre> | ||
3150 | </YueDisplay> | ||
3151 | |||
3152 | Match against nested table structures. | ||
3153 | |||
3154 | ```moonscript | ||
3155 | switch tb | ||
3156 | when data: {type: "success", :content} | ||
3157 | print "success", content | ||
3158 | when data: {type: "error", :content} | ||
3159 | print "failed", content | ||
3160 | else | ||
3161 | print "invalid" | ||
3162 | ``` | ||
3163 | <YueDisplay> | ||
3164 | <pre> | ||
3165 | switch tb | ||
3166 | when data: {type: "success", :content} | ||
3167 | print "success", content | ||
3168 | when data: {type: "error", :content} | ||
3169 | print "failed", content | ||
3170 | else | ||
3171 | print "invalid" | ||
3172 | </pre> | ||
3173 | </YueDisplay> | ||
3174 | |||
3175 | Match against array of tables. | ||
3176 | |||
3177 | ```moonscript | ||
3178 | switch tb | ||
3179 | when [ | ||
3180 | {a: 1, b: 2} | ||
3181 | {a: 3, b: 4} | ||
3182 | {a: 5, b: 6} | ||
3183 | fourth | ||
3184 | ] | ||
3185 | print "matched", fourth | ||
3186 | ``` | ||
3187 | <YueDisplay> | ||
3188 | <pre> | ||
3189 | switch tb | ||
3190 | when [ | ||
3191 | {a: 1, b: 2} | ||
3192 | {a: 3, b: 4} | ||
3193 | {a: 5, b: 6} | ||
3194 | fourth | ||
3195 | ] | ||
3196 | print "matched", fourth | ||
3197 | </pre> | ||
3198 | </YueDisplay> | ||
3199 | |||
3200 | Match against a list and capture a range of elements. | ||
3201 | |||
3202 | ```moonscript | ||
3203 | segments = ["admin", "users", "logs", "view"] | ||
3204 | switch segments | ||
3205 | when [...groups, resource, action] | ||
3206 | print "Group:", groups -- prints: {"admin", "users"} | ||
3207 | print "Resource:", resource -- prints: "logs" | ||
3208 | print "Action:", action -- prints: "view" | ||
3209 | ``` | ||
3210 | <YueDisplay> | ||
3211 | <pre> | ||
3212 | segments = ["admin", "users", "logs", "view"] | ||
3213 | switch segments | ||
3214 | when [...groups, resource, action] | ||
3215 | print "Group:", groups -- prints: {"admin", "users"} | ||
3216 | print "Resource:", resource -- prints: "logs" | ||
3217 | print "Action:", action -- prints: "view" | ||
3218 | </pre> | ||
3219 | </YueDisplay> | ||
3220 | |||
2785 | ## Object Oriented Programming | 3221 | ## Object Oriented Programming |
2786 | 3222 | ||
2787 | In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. | 3223 | In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. |
@@ -2913,7 +3349,7 @@ class BackPack extends Inventory | |||
2913 | 3349 | ||
2914 | Here we extend our Inventory class, and limit the amount of items it can carry. | 3350 | Here we extend our Inventory class, and limit the amount of items it can carry. |
2915 | 3351 | ||
2916 | In this example, we don’t define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. | 3352 | In this example, we don't define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. |
2917 | 3353 | ||
2918 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. | 3354 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. |
2919 | 3355 | ||
@@ -3000,13 +3436,13 @@ print BackPack.size -- prints 10 | |||
3000 | 3436 | ||
3001 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. | 3437 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. |
3002 | 3438 | ||
3003 | The class object can be called like a function in order to create new instances. That’s how we created instances of classes in the examples above. | 3439 | The class object can be called like a function in order to create new instances. That's how we created instances of classes in the examples above. |
3004 | 3440 | ||
3005 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. | 3441 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. |
3006 | 3442 | ||
3007 | The class object’s metatable reads properties from the base if they don’t exist in the class object. This means we can access functions and properties directly from the class. | 3443 | The class object's metatable reads properties from the base if they don't exist in the class object. This means we can access functions and properties directly from the class. |
3008 | 3444 | ||
3009 | It is important to note that assigning to the class object does not assign into the base, so it’s not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. | 3445 | It is important to note that assigning to the class object does not assign into the base, so it's not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. |
3010 | 3446 | ||
3011 | The class object has a couple special properties: | 3447 | The class object has a couple special properties: |
3012 | 3448 | ||
@@ -3079,7 +3515,7 @@ print Counter.count -- prints 2 | |||
3079 | </pre> | 3515 | </pre> |
3080 | </YueDisplay> | 3516 | </YueDisplay> |
3081 | 3517 | ||
3082 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. | 3518 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax. |
3083 | 3519 | ||
3084 | ```moonscript | 3520 | ```moonscript |
3085 | @@hello 1,2,3,4 | 3521 | @@hello 1,2,3,4 |
@@ -3094,7 +3530,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl | |||
3094 | 3530 | ||
3095 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. | 3531 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. |
3096 | 3532 | ||
3097 | Here is an alternative way to create a class variable compared to what’s described above: | 3533 | Here is an alternative way to create a class variable compared to what's described above: |
3098 | 3534 | ||
3099 | ```moonscript | 3535 | ```moonscript |
3100 | class Things | 3536 | class Things |
@@ -3360,19 +3796,19 @@ In this usage, with can be seen as a special form of the K combinator. | |||
3360 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | 3796 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. |
3361 | 3797 | ||
3362 | ```moonscript | 3798 | ```moonscript |
3363 | with str = "Hello" | 3799 | with str := "Hello" |
3364 | print "original:", str | 3800 | print "original:", str |
3365 | print "upper:", \upper! | 3801 | print "upper:", \upper! |
3366 | ``` | 3802 | ``` |
3367 | <YueDisplay> | 3803 | <YueDisplay> |
3368 | <pre> | 3804 | <pre> |
3369 | with str = "Hello" | 3805 | with str := "Hello" |
3370 | print "original:", str | 3806 | print "original:", str |
3371 | print "upper:", \upper! | 3807 | print "upper:", \upper! |
3372 | </pre> | 3808 | </pre> |
3373 | </YueDisplay> | 3809 | </YueDisplay> |
3374 | 3810 | ||
3375 | Accessing special keys with `[]` in a `with` statement. | 3811 | You can access special keys with `[]` in a `with` statement. |
3376 | 3812 | ||
3377 | ```moonscript | 3813 | ```moonscript |
3378 | with tb | 3814 | with tb |
@@ -3395,6 +3831,18 @@ with tb | |||
3395 | </pre> | 3831 | </pre> |
3396 | </YueDisplay> | 3832 | </YueDisplay> |
3397 | 3833 | ||
3834 | `with?` is an enhanced version of `with` syntax, which introduces an existential check to safely access objects that may be nil without explicit null checks. | ||
3835 | |||
3836 | ```moonscript | ||
3837 | with? obj | ||
3838 | print obj.name | ||
3839 | ``` | ||
3840 | <YueDisplay> | ||
3841 | <pre> | ||
3842 | with? obj | ||
3843 | print obj.name | ||
3844 | </pre> | ||
3845 | </YueDisplay> | ||
3398 | 3846 | ||
3399 | ## Do | 3847 | ## Do |
3400 | 3848 | ||
@@ -3415,7 +3863,7 @@ print var -- nil here | |||
3415 | </pre> | 3863 | </pre> |
3416 | </YueDisplay> | 3864 | </YueDisplay> |
3417 | 3865 | ||
3418 | YueScript’s **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. | 3866 | YueScript's **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. |
3419 | 3867 | ||
3420 | ```moonscript | 3868 | ```moonscript |
3421 | counter = do | 3869 | counter = do |
@@ -3541,7 +3989,7 @@ print i -- will print 0 | |||
3541 | </pre> | 3989 | </pre> |
3542 | </YueDisplay> | 3990 | </YueDisplay> |
3543 | 3991 | ||
3544 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn’t clear what names have already been declared. | 3992 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn't clear what names have already been declared. |
3545 | 3993 | ||
3546 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. | 3994 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. |
3547 | 3995 | ||