aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md51
-rwxr-xr-xdoc/docs/doc/README.md89
-rw-r--r--src/yuescript/yue_compiler.cpp9
-rw-r--r--src/yuescript/yue_parser.cpp18
4 files changed, 148 insertions, 19 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33c038b..dedd8e7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,57 @@
2 2
3The implementation for the original Moonscript language 0.5.0 can be found in the `0.5.0` branch of Yuescript. The Moonscript with fixes and new features is in the main branch of Yuescript. Here are the changelogs for each Yuescript version. 3The implementation for the original Moonscript language 0.5.0 can be found in the `0.5.0` branch of Yuescript. The Moonscript with fixes and new features is in the main branch of Yuescript. Here are the changelogs for each Yuescript version.
4 4
5## v0.15.12
6
7### Added Features
8
9* yue.to_ast(): Reserve comment nodes followed by a statement in AST structures.
10* Added `while` clause line decorator.
11 ```moonscript
12 reader\parse_line! until reader\eof!
13 ```
14 compiles to:
15 ```lua
16 while not reader:eof() do
17 reader:parse_line()
18 end
19 ```
20* Supported underscores in number literal. `1_000_000`, `0xFF_EF_06`
21* Refactored some error messages with details instead of just "syntax error".
22* Added chaining assignment. `a = b = c = 0`
23
24### Fixed Issues
25
26* Change metable accessing operator to `<>` instead of postfix `#`.
27 ```moonscript
28 <>: mt = tb
29 mt = tb.<>
30 a = <>: mt, value: 1
31 b = :<add>, value: 2
32 close _ = <close>: -> print "out of scope"
33 ```
34 compiles to:
35 ```lua
36 local mt = getmetatable(tb)
37 mt = getmetatable(tb)
38 local a = setmetatable({
39 value = 1
40 }, mt)
41 local b = setmetatable({
42 value = 2
43 }, {
44 __add = add
45 })
46 local _ <close> = setmetatable({ }, {
47 __close = function()
48 return print("out of scope")
49 end
50 })
51 ```
52* Refactor `continue` keyword implementation with goto statement when targeting Lua version 5.2 and higher.
53* Skip utf-8 bom in parser.
54* Fixed classes don't inherits metamethods properly.
55
5## v0.14.5 56## v0.14.5
6 57
7### Added Features 58### Added Features
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index f23a407..df9002d 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -671,13 +671,14 @@ tb =
671 671
672### Import 672### Import
673 673
674The import statement is a syntax sugar for requiring a module or help extracting items from an imported module. 674The import statement is a syntax sugar for requiring a module or help extracting items from an imported module. The imported items are const by default.
675 675
676```moonscript 676```moonscript
677-- used as table destructure 677-- used as table destructuring
678do 678do
679 import C, Ct, Cmt from require "lpeg"
680 import insert, concat from table 679 import insert, concat from table
680 -- report error when assigning to insert, concat
681 import C, Ct, Cmt from require "lpeg"
681 682
682-- shortcut for requring a module 683-- shortcut for requring a module
683do 684do
@@ -686,7 +687,7 @@ do
686 import "d-a-s-h-e-s" 687 import "d-a-s-h-e-s"
687 import "module.part" 688 import "module.part"
688 689
689-- requring module with aliasing or table destruction 690-- requring module with aliasing or table destructuring
690do 691do
691 import "player" as PlayerModule 692 import "player" as PlayerModule
692 import "lpeg" as :C, :Ct, :Cmt 693 import "lpeg" as :C, :Ct, :Cmt
@@ -694,10 +695,11 @@ do
694``` 695```
695<YueDisplay> 696<YueDisplay>
696<pre> 697<pre>
697-- used as table destruction 698-- used as table destructuring
698do 699do
699 import C, Ct, Cmt from require "lpeg"
700 import insert, concat from table 700 import insert, concat from table
701 -- report error when assigning to insert, concat
702 import C, Ct, Cmt from require "lpeg"
701 703
702-- shortcut for requring a module 704-- shortcut for requring a module
703do 705do
@@ -706,7 +708,7 @@ do
706 import "d-a-s-h-e-s" 708 import "d-a-s-h-e-s"
707 import "module.part" 709 import "module.part"
708 710
709-- requring module with aliasing or table destruction 711-- requring module with aliasing or table destructuring
710do 712do
711 import "player" as PlayerModule 713 import "player" as PlayerModule
712 import "lpeg" as :C, :Ct, :Cmt 714 import "lpeg" as :C, :Ct, :Cmt
@@ -843,6 +845,20 @@ arg or= "default value"
843</pre> 845</pre>
844</YueDisplay> 846</YueDisplay>
845 847
848### Chaining Assignment
849
850You can do chaining assignment to assign multiple items to hold the same value.
851```moonscript
852a = b = c = d = e = 0
853x = y = z = f!
854```
855<YueDisplay>
856<pre>
857a = b = c = d = e = 0
858x = y = z = f!
859</pre>
860</YueDisplay>
861
846### Explicit Locals 862### Explicit Locals
847```moonscript 863```moonscript
848do 864do
@@ -1114,7 +1130,7 @@ else
1114</pre> 1130</pre>
1115</YueDisplay> 1131</YueDisplay>
1116 1132
1117If assignment with extra return values. 1133If assignment with multiple return values. Only the first value is getting checked, other values are scoped.
1118```moonscript 1134```moonscript
1119if success, result = pcall -> "get result without problems" 1135if success, result = pcall -> "get result without problems"
1120 print result -- variable result is scoped 1136 print result -- variable result is scoped
@@ -1246,7 +1262,7 @@ catch err
1246 1262
1247## Attributes 1263## Attributes
1248 1264
1249The syntax support for Lua 5.4 attributes. 1265Syntax support for Lua 5.4 attributes. But you can use still use `const` declaration and get constant check functioning when targeting Lua versions below 5.4.
1250 1266
1251```moonscript 1267```moonscript
1252const a = 123 1268const a = 123
@@ -1284,6 +1300,22 @@ print "I am #{math.random! * 100}% sure."
1284</pre> 1300</pre>
1285</YueDisplay> 1301</YueDisplay>
1286 1302
1303### Number Literals
1304
1305You can use underscores in a number literal to increase readability.
1306
1307```moonscript
1308integer = 1_000_000
1309hex = 0xEF_BB_BF
1310```
1311<YueDisplay>
1312
1313<pre>
1314integer = 1_000_000
1315hex = 0xEF_BB_BF
1316</pre>
1317</YueDisplay>
1318
1287## Function Literals 1319## Function Literals
1288 1320
1289All functions are created using a function expression. A simple function is denoted using the arrow: **->**. 1321All functions are created using a function expression. A simple function is denoted using the arrow: **->**.
@@ -2302,6 +2334,21 @@ print "item: ", item for item in *items
2302</pre> 2334</pre>
2303</YueDisplay> 2335</YueDisplay>
2304 2336
2337And with while loops:
2338
2339```moonscript
2340game\update! while game\isRunning!
2341
2342reader\parse_line! until reader\eof!
2343```
2344<YueDisplay>
2345<pre>
2346game\update! while game\isRunning!
2347
2348reader\parse_line! until reader\eof!
2349</pre>
2350</YueDisplay>
2351
2305## Switch 2352## Switch
2306 2353
2307The 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. 2354The 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.
@@ -2975,6 +3022,30 @@ with str = "Hello"
2975</pre> 3022</pre>
2976</YueDisplay> 3023</YueDisplay>
2977 3024
3025Accessing special keys with `[]` in a `with` statement.
3026
3027```moonscript
3028with tb
3029 [1] = 1
3030 print [2]
3031 with [abc]
3032 [3] = [2]\func!
3033 ["key-name"] = value
3034 [] = "abc" -- appending to "tb"
3035```
3036<YueDisplay>
3037<pre>
3038with tb
3039 [1] = 1
3040 print [2]
3041 with [abc]
3042 [3] = [2]\func!
3043 ["key-name"] = value
3044 [] = "abc" -- appending to "tb"
3045</pre>
3046</YueDisplay>
3047
3048
2978## Do 3049## Do
2979 3050
2980When used as a statement, do works just like it does in Lua. 3051When used as a statement, do works just like it does in Lua.
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 4072974..f5436d1 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -59,7 +59,7 @@ namespace yue {
59 59
60typedef std::list<std::string> str_list; 60typedef std::list<std::string> str_list;
61 61
62const std::string_view version = "0.15.11"sv; 62const std::string_view version = "0.15.12"sv;
63const std::string_view extension = "yue"sv; 63const std::string_view extension = "yue"sv;
64 64
65class YueCompilerImpl { 65class YueCompilerImpl {
@@ -3769,7 +3769,7 @@ private:
3769 if (!_enableReturn.top()) { 3769 if (!_enableReturn.top()) {
3770 ast_node* target = returnNode->valueList.get(); 3770 ast_node* target = returnNode->valueList.get();
3771 if (!target) target = returnNode; 3771 if (!target) target = returnNode;
3772 throw std::logic_error(_info.errorMessage("illegal return statement here"sv, target)); 3772 throw std::logic_error(_info.errorMessage("can not mix use of return and export statements in module scope"sv, target));
3773 } 3773 }
3774 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { 3774 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) {
3775 if (valueList->exprs.size() == 1) { 3775 if (valueList->exprs.size() == 1) {
@@ -8008,8 +8008,11 @@ private:
8008 8008
8009 void transformChainAssign(ChainAssign_t* chainAssign, str_list& out) { 8009 void transformChainAssign(ChainAssign_t* chainAssign, str_list& out) {
8010 auto x = chainAssign; 8010 auto x = chainAssign;
8011 str_list temp;
8012 auto value = chainAssign->assign->values.front(); 8011 auto value = chainAssign->assign->values.front();
8012 if (chainAssign->assign->values.size() != 1) {
8013 throw std::logic_error(_info.errorMessage("only one right value expected"sv, value));
8014 }
8015 str_list temp;
8013 bool constVal = false; 8016 bool constVal = false;
8014 if (auto simpleVal = simpleSingleValueFrom(value)) { 8017 if (auto simpleVal = simpleSingleValueFrom(value)) {
8015 constVal = ast_is<const_value_t, Num_t>(simpleVal->value); 8018 constVal = ast_is<const_value_t, Num_t>(simpleVal->value);
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index b1f29a9..c8b974f 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -532,17 +532,21 @@ YueParser::YueParser() {
532 return true; 532 return true;
533 }) >> (pl::user(Space >> export_default >> Exp, [](const item_t& item) { 533 }) >> (pl::user(Space >> export_default >> Exp, [](const item_t& item) {
534 State* st = reinterpret_cast<State*>(item.user_data); 534 State* st = reinterpret_cast<State*>(item.user_data);
535 bool isValid = !st->exportDefault && st->exportCount == 1; 535 if (st->exportDefault) {
536 throw ParserError("export default has already been declared", *item.begin, *item.end);
537 }
538 if (st->exportCount > 1) {
539 throw ParserError("there are items already been exported", *item.begin, *item.end);
540 }
536 st->exportDefault = true; 541 st->exportDefault = true;
537 return isValid; 542 return true;
538 }) 543 })
539 | (not_(Space >> export_default) >> pl::user(true_(), [](const item_t& item) { 544 | (not_(Space >> export_default) >> pl::user(true_(), [](const item_t& item) {
540 State* st = reinterpret_cast<State*>(item.user_data); 545 State* st = reinterpret_cast<State*>(item.user_data);
541 if (st->exportDefault && st->exportCount > 1) { 546 if (st->exportDefault && st->exportCount > 1) {
542 return false; 547 throw ParserError("can not export more items when export default has been declared", *item.begin, *item.end);
543 } else {
544 return true;
545 } 548 }
549 return true;
546 }) >> ExpList >> -Assign) 550 }) >> ExpList >> -Assign)
547 | Space >> pl::user(Macro, [](const item_t& item) { 551 | Space >> pl::user(Macro, [](const item_t& item) {
548 State* st = reinterpret_cast<State*>(item.user_data); 552 State* st = reinterpret_cast<State*>(item.user_data);
@@ -631,7 +635,7 @@ YueParser::YueParser() {
631 ) | arg_table_block; 635 ) | arg_table_block;
632 636
633 leading_spaces_error = pl::user(+space_one >> expr('(') >> Exp >> +(sym(',') >> Exp) >> sym(')'), [](const item_t& item) { 637 leading_spaces_error = pl::user(+space_one >> expr('(') >> Exp >> +(sym(',') >> Exp) >> sym(')'), [](const item_t& item) {
634 throw ParserError("write invoke arguments in parentheses without leading spaces or leading spaces without parentheses", *item.begin, *item.end); 638 throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses", *item.begin, *item.end);
635 return false; 639 return false;
636 }); 640 });
637 641
@@ -707,7 +711,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) {
707 res.codes = std::make_unique<input>(); 711 res.codes = std::make_unique<input>();
708 *(res.codes) = _converter.from_bytes(&codes.front(), &codes.back() + 1); 712 *(res.codes) = _converter.from_bytes(&codes.front(), &codes.back() + 1);
709 } catch (const std::range_error&) { 713 } catch (const std::range_error&) {
710 res.error = "Invalid text encoding."sv; 714 res.error = "invalid text encoding"sv;
711 return res; 715 return res;
712 } 716 }
713 error_list errors; 717 error_list errors;