aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-03-29 21:46:36 +0800
committerLi Jin <dragon-fly@qq.com>2020-03-29 21:46:36 +0800
commit147893cdbf00d40ebda6b7840d3734ccda294347 (patch)
tree574a5d732fa776aa8cb2d32398a108acfd047c6b
parent13c5e230e0fb1e64ddd0e4cd348aac2bd291bdb9 (diff)
downloadyuescript-147893cdbf00d40ebda6b7840d3734ccda294347.tar.gz
yuescript-147893cdbf00d40ebda6b7840d3734ccda294347.tar.bz2
yuescript-147893cdbf00d40ebda6b7840d3734ccda294347.zip
update readme, add changelogs.
-rw-r--r--CHANGELOG.md427
-rw-r--r--README.md376
-rw-r--r--makefile2
3 files changed, 465 insertions, 340 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..5ec9a47
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,427 @@
1# Changelog
2
3The implementation for original Moonscript language 0.5.0 can be found in the `0.5.0` branch of MoonPlus. The Moonscript with fixes and new features is in the master branch of MoonPlus. Here are the changelogs for each MoonPlus version.
4
5
6
7## v0.3.7
8
9### Fixed Issues
10
11* Fix macro type mismatch issue.
12* Fix line break issue in macro, disable macro declaration outside the root scope.
13* Fix existential operator issue when used in operator-value list.
14
15
16
17### Added Features
18
19* Add support for macro system expanding to Lua codes directly.
20* Add goto statement support.
21* `moonp` now supports recursively traversing any directory and compiling any moon file in the path.
22* `moonp` now supports REPL functions for Moonscript.
23
24
25
26### Changed Hehaviors
27
28* Remove else clause support from if-else line decorator syntax which makes users confused.
29
30
31
32## v0.3.0
33
34### Added Features
35
36* Add macro functions.
37```Moonscript
38-- file 'macro.moon'
39export macro block config = (debugging = true)->
40 global debugMode = debugging == "true"
41 ""
42
43export macro block asserts = (cond)->
44 debugMode and "assert #{cond}" or ""
45
46export macro expr assert = (cond)->
47 debugMode and "assert #{cond}" or "#{cond}"
48
49$config!
50
51-- file 'main.moon'
52import 'macro' as {:$config, :$assert, :$asserts}
53
54macro expr and = (...)-> "#{ table.concat {...}, ' and ' }"
55
56$asserts item ~= nil
57$config false
58value = $assert item
59
60if $and f1!, f2!, f3!
61 print "OK"
62```
63 Compiles to:
64```Lua
65-- file 'macro.moon'
66local _module_0 = { }
67return _module_0
68
69-- file 'main.moon'
70assert(item ~= nil)
71local value = item
72if (f1() and f2() and f3()) then
73 print("OK")
74end
75```
76
77
78
79## v0.2.0
80
81### Fixed Issues
82
83* Fix some cases when using backcall with assignment.
84* Fix a case that complier crashes with empty code body.
85* Force forward declaration of variable for assigning local function.
86
87From original Moonscript compiler:
88
89* [#390](https://github.com/leafo/moonscript/issues/390) Many lists are not allowed to be multiline
90
91
92
93### Added Features
94
95* Allow value lists in for and local statement to be multiline.
96* `moonp` now compiles source files in multiple threads to speed up compilation.
97* Add placeholder support for backcall operator.
98* Add placeholder support for backcall statement.
99* Add fat arrow support for backcall statement.
100* Add option to compile MoonPlus as a Lua C lib. Got MoonPlus released to `Luarocks`.
101* Move old `export` statement functions to `global` statement to match the `local` statement.
102* Change `export` statement behavier to support module management. Moon codes with `export` statement can not explicit return values in root scope. And codes with `export default` can export only one value as the module content. Use cases:
103```Moonscript
104-- file 'Config.moon'
105export default {flag:1, value:"x"}
106
107-- file 'Utils.moon'
108export map = (items, func)-> [func item for item in *items]
109export filter = (items, func)-> [item for item in *items when func item]
110
111-- file 'main.moon'
112import 'Config' as {:flag, :value}
113import 'Utils' as {:map, :filter}
114```
115Compiles to:
116```Lua
117-- file 'Config.moon'
118local _module_0 = nil
119_module_0 = {
120 flag = 1,
121 value = "x"
122}
123return _module_0
124
125-- file 'Utils.moon'
126local _module_0 = { }
127local map
128map = function(items, func)
129 local _accum_0 = { }
130 local _len_0 = 1
131 for _index_0 = 1, #items do
132 local item = items[_index_0]
133 _accum_0[_len_0] = func(item)
134 _len_0 = _len_0 + 1
135 end
136 return _accum_0
137end
138_module_0["map"] = map
139local filter
140filter = function(items, func)
141 local _accum_0 = { }
142 local _len_0 = 1
143 for _index_0 = 1, #items do
144 local item = items[_index_0]
145 if func(item) then
146 _accum_0[_len_0] = item
147 _len_0 = _len_0 + 1
148 end
149 end
150 return _accum_0
151end
152_module_0["filter"] = filter
153return _module_0
154
155-- file 'main.moon'
156local flag, value
157do
158 local _obj_0 = require('Config')
159 flag, value = _obj_0.flag, _obj_0.value
160end
161local map, filter
162do
163 local _obj_0 = require('Utils')
164 map, filter = _obj_0.map, _obj_0.filter
165end
166```
167
168
169
170## v0.1.0
171
172### Fixed Issues
173
174Fix issues in original Moonscript compiler:
175* [#122](https://github.com/leafo/moonscript/issues/122) use of ? symbol
176* [#155](https://github.com/leafo/moonscript/issues/151) wish moon could support: function?()
177* [#156](https://github.com/leafo/moonscript/issues/156) About the 'import' statement
178* [#375](https://github.com/leafo/moonscript/issues/375) assignment in line decorators
179* [#384](https://github.com/leafo/moonscript/issues/384) The @ and @@ accessors do not escape Lua keywords
180
181
182
183### Added Features
184
185* Multi-line comment support.
186
187* Usage for symbol `\` to escape new line. Will compile codes:
188```Moonscript
189str = --[[
190 This is a multi line comment.
191 It's OK.
192]] strA \ -- comment 1
193 .. strB \ -- comment 2
194 .. strC
195
196func --[[ip]] "192.168.126.110", --[[port]] 3000
197```
198&emsp;&emsp;to:
199```Lua
200local str = strA .. strB .. strC
201func("192.168.126.110", 3000)
202```
203
204* Back call features with new operator and syntax. For example:
205```Moonscript
206{1,2,3} \
207 |> map((x)-> x * 2) \
208 |> filter((x)-> x > 4) \
209 |> reduce(0, (a,b)-> a + b) \
210 |> print
211
212do
213 (data) <- http.get "ajaxtest"
214 body[".result"]\html data
215 (processed) <- http.post "ajaxprocess", data
216 body[".result"]\append processed
217 print "done"
218```
219&emsp;&emsp;will be compiled to:
220```Lua
221print(reduce(filter(map({
222 1,
223 2,
224 3
225}, function(x)
226 return x * 2
227end), function(x)
228 return x > 4
229end), 0, function(a, b)
230 return a + b
231end))
232do
233 http.get("ajaxtest", function(data)
234 body[".result"]:html(data)
235 return http.post("ajaxprocess", data, function(processed)
236 body[".result"]:append(processed)
237 return print("done")
238 end)
239 end)
240end
241```
242
243* Existential operator support. Generate codes from:
244```Moonscript
245func?!
246
247x = tab?.value
248
249print abc?["hello world"]?.xyz
250
251if print and x?
252 print x
253```
254&emsp;&emsp;to:
255```Lua
256if func ~= nil then
257 func()
258end
259local x
260if tab ~= nil then
261 x = tab.value
262end
263print((function()
264 if abc ~= nil then
265 local _obj_0 = abc["hello world"]
266 if _obj_0 ~= nil then
267 return _obj_0.xyz
268 end
269 return nil
270 end
271 return nil
272end)())
273if print and (x ~= nil) then
274 print(x)
275end
276```
277
278* More usages for `import` keyword. Will compile codes from:
279```Moonscript
280import 'module'
281import "module.part"
282import "d-a-s-h-e-s"
283import "player" as Player
284import "lpeg" as {:C, :Ct, :Cmt}
285```
286&emsp;&emsp;to:
287```Lua
288local module = require('module')
289local part = require("module.part")
290local d_a_s_h_e_s = require("d-a-s-h-e-s")
291local Player = require("player")
292local C, Ct, Cmt
293do
294 local _obj_0 = require("lpeg")
295 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
296end
297```
298
299* Can do slash call with Lua keywords. Generate codes from:
300```Moonscript
301c.repeat.if\then("xyz")\else res
302```
303&emsp;&emsp;to:
304```Lua
305local _call_3 = c["repeat"]["if"]
306local _call_4 = _call_3["then"](_call_3, "xyz")
307_call_4["else"](_call_4, res)
308```
309
310
311
312### Changed Hehaviors
313
314* Left part of update statement will now accept only one assignable expression.
315* Expression list appears in the middle of code block is not allowed. For codes like:
316
317```Moonscript
318-- Moonscript 0.5.0
319f = (x)->
320 "abc",123 -- valid meaningless codes
321 x + 1
322```
323
324in original Moonscript compiles to:
325
326```Lua
327local f
328f = function(x)
329 local _ = "abc", 123 -- report error in MoonPlus
330 return x + 1
331end
332```
333
334This feature may lead to some silenced errors. For example:
335
336```Moonscript
337-- expected codes
338tree\addChild with Node!
339 \addChild subNode
340
341-- in original Moonscript, codes will still run
342-- after adding a break by mistake
343tree\addChild
344with Node!
345 \addChild subNode
346```
347
348the original Moonscript will compile these codes to:
349
350```Lua
351-- expected codes
352tree:addChild((function()
353 do
354 local _with_0 = Node()
355 _with_0:addChild(subNode)
356 return _with_0
357 end
358end)())
359
360-- codes added with a break will still run
361local _ -- report error in MoonPlus instead of creating
362do -- an anonymous function to bind the object method
363 local _base_0 = tree
364 local _fn_0 = _base_0.addChild
365 _ = function(...)
366 return _fn_0(_base_0, ...)
367 end
368end
369do
370 local _with_0 = Node()
371 _with_0:addChild(subNode)
372end
373```
374
375* Reusing variables which helps generate reduced Lua codes.
376
377 For example, MoonPlus will generate codes from:
378
379```Moonscript
380with leaf
381 .world 1,2,3
382
383with leaf
384 g = .what.is.this
385 print g
386
387for x in *something
388 print x
389```
390
391&emsp;&emsp;to:
392
393```Lua
394leaf.world(1, 2, 3)
395do
396 local g = leaf.what.is.this
397 print(g)
398end
399for _index_0 = 1, #something do
400 local x = something[_index_0]
401 print(x)
402end
403```
404
405&emsp;&emsp;instead of:
406
407```lua
408do
409 local _with_0 = leaf
410 _with_0.world(1, 2, 3)
411end
412do
413 local _with_0 = leaf
414 local g = _with_0.what.is.this
415end
416local _list_0 = something
417for _index_0 = 1, #_list_0 do
418 local x = _list_0[_index_0]
419 print(x)
420end
421```
422
423
424
425## v0.0.1
426
427Implemented full features from Moonscript 0.5.0.
diff --git a/README.md b/README.md
index c8159c4..14a3718 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,13 @@
1# MoonPlus 1# MoonPlus
2 2
3![CI](https://github.com/pigpigyyy/MoonPlus/workflows/build-test/badge.svg) 3![CI](https://github.com/pigpigyyy/MoonPlus/workflows/build-test/badge.svg)
4MoonPlus is a compiler with features from [Moonscript language](https://github.com/leafo/moonscript) 0.5.0 and implementing new features to make Moonscript more up to date. 4MoonPlus is a compiler with features from [Moonscript language](https://github.com/leafo/moonscript) 0.5.0 and adopting new features to make Moonscript more up to date.
5
6Since original Moonscript has been used to write web framework [lapis](https://github.com/leafo/lapis) and run a few business web sites like [itch.io](https://itch.io) and [streak.club](https://streak.club) with some large code bases. The original language is getting too hard to adopt new features for those may break the stablility for existing applications.
7
8So MoonPlus is a new code base for pushing the language to go forward and being a playground to try introducing new language syntax or programing paradigms to make Moonscript language more expressive and productive.
5 9
6Since original Moonscript has been used to write web framework [lapis](https://github.com/leafo/lapis) and run a few business web sites like [itch.io](https://itch.io) and [streak.club](https://streak.club) with some large code bases. The original language is getting too hard to adopt new language features for those may break the stablility for existing applications.
7 10
8So MoonPlus is a new code base for pushing the language to go forward and may be a playground to try introducing new language syntax or programing paradigms to make Moonscript language more expressive and productive.
9 11
10## Features 12## Features
11 13
@@ -13,374 +15,70 @@ So MoonPlus is a new code base for pushing the language to go forward and may be
13* Written in C++17. 15* Written in C++17.
14* Support full Moonscript language features, generate the same Lua codes with original compiler. 16* Support full Moonscript language features, generate the same Lua codes with original compiler.
15* Reserve line numbers from Moonscript sources in compiled Lua codes to help with debugging. 17* Reserve line numbers from Moonscript sources in compiled Lua codes to help with debugging.
18* See other details in the [changelog](./CHANGELOG.md).
19
20
16 21
17## Installation 22## Installation & Usage
23
24* **Lua Module**
25
26 Install [luarocks](https://luarocks.org), a package manager for Lua modules. Then install it as a Lua module.
18 27
19Install [luarocks](https://luarocks.org), a package manager for Lua modules. Then install Lua module with
20```sh 28```sh
21> luarocks install moonplus 29> luarocks install moonplus
22``` 30```
23 31
24## Usage 32&emsp;&emsp;Require the module in Lua:
25 33
26```Lua 34```Lua
27require("moonp")("main") -- require `main.moon` 35require("moonp")("main") -- require `main.moon`
28 36
29local moonp = require("moonp") 37local moonp = require("moonp")
30print(moonp.to_lua[[ 38local codes, err, globals = moonp.to_lua([[
31f = -> 39f = ->
32 print "hello world" 40 print "hello world"
33f! 41f!
34]],{ 42]],{
35 implicit_return_root = true, 43 implicit_return_root = true,
36 reserve_line_number = false, 44 reserve_line_number = true,
37 lint_global = false 45 lint_global = true
38}) 46})
39``` 47```
40 48
41## Changes
42
43The original Moonscript language 0.5.0 support can be found in the `0.5.0` branch. Moonscript with new features is in the master branch. Here are the new features introduced in MoonPlus.
44
45* Add goto statement support.
46
47* Add macro functions.
48```Moonscript
49-- file 'macro.moon'
50export macro block config = (debugging = true)->
51 global debugMode = debugging == "true"
52 ""
53
54export macro block asserts = (cond)->
55 debugMode and "assert #{cond}" or ""
56
57export macro expr assert = (cond)->
58 debugMode and "assert #{cond}" or "#{cond}"
59
60$config!
61
62-- file 'main.moon'
63import 'macro' as {:$config, :$assert, :$asserts}
64
65macro expr and = (...)-> "#{ table.concat {...}, ' and ' }"
66
67$asserts item ~= nil
68$config false
69value = $assert item
70
71if $and f1!, f2!, f3!
72 print "OK"
73```
74 Compiles to:
75```Lua
76-- file 'macro.moon'
77local _module_0 = { }
78return _module_0
79
80-- file 'main.moon'
81assert(item ~= nil)
82local value = item
83if (f1() and f2() and f3()) then
84 print("OK")
85end
86```
87
88* Move old `export` statement functions to `global` statement to match the `local` statement.
89
90* Change `export` statement behavier to support module management. Moon codes with `export` statement can not explicit return values in root scope. And codes with `export default` can export only one value as the module content. Use cases:
91```Moonscript
92-- file 'Config.moon'
93export default {flag:1, value:"x"}
94
95-- file 'Utils.moon'
96export map = (items, func)-> [func item for item in *items]
97export filter = (items, func)-> [item for item in *items when func item]
98
99-- file 'main.moon'
100import 'Config' as {:flag, :value}
101import 'Utils' as {:map, :filter}
102```
103Compiles to:
104```Lua
105-- file 'Config.moon'
106local _module_0 = nil
107_module_0 = {
108 flag = 1,
109 value = "x"
110}
111return _module_0
112
113-- file 'Utils.moon'
114local _module_0 = { }
115local map
116map = function(items, func)
117 local _accum_0 = { }
118 local _len_0 = 1
119 for _index_0 = 1, #items do
120 local item = items[_index_0]
121 _accum_0[_len_0] = func(item)
122 _len_0 = _len_0 + 1
123 end
124 return _accum_0
125end
126_module_0["map"] = map
127local filter
128filter = function(items, func)
129 local _accum_0 = { }
130 local _len_0 = 1
131 for _index_0 = 1, #items do
132 local item = items[_index_0]
133 if func(item) then
134 _accum_0[_len_0] = item
135 _len_0 = _len_0 + 1
136 end
137 end
138 return _accum_0
139end
140_module_0["filter"] = filter
141return _module_0
142
143-- file 'main.moon'
144local flag, value
145do
146 local _obj_0 = require('Config')
147 flag, value = _obj_0.flag, _obj_0.value
148end
149local map, filter
150do
151 local _obj_0 = require('Utils')
152 map, filter = _obj_0.map, _obj_0.filter
153end
154```
155
156* Add multi-line comment support.
157
158* Usage for symbol `\` to escape new line. Will compile codes:
159```Moonscript
160str = --[[
161 This is a multi line comment.
162 It's OK.
163]] strA \ -- comment 1
164 .. strB \ -- comment 2
165 .. strC
166
167func --[[ip]] "192.168.126.110", --[[port]] 3000
168```
169&emsp;&emsp;to:
170```Lua
171local str = strA .. strB .. strC
172func("192.168.126.110", 3000)
173```
174
175* Back call features with new operator and syntax. For example:
176```Moonscript
177{1,2,3} \
178 |> map((x)-> x * 2) \
179 |> filter((x)-> x > 4) \
180 |> reduce(0, (a,b)-> a + b) \
181 |> print
182
183do
184 (data) <- http.get "ajaxtest"
185 body[".result"]\html data
186 (processed) <- http.post "ajaxprocess", data
187 body[".result"]\append processed
188 print "done"
189```
190&emsp;&emsp;will be compiled to:
191```Lua
192print(reduce(filter(map({
193 1,
194 2,
195 3
196}, function(x)
197 return x * 2
198end), function(x)
199 return x > 4
200end), 0, function(a, b)
201 return a + b
202end))
203do
204 http.get("ajaxtest", function(data)
205 body[".result"]:html(data)
206 return http.post("ajaxprocess", data, function(processed)
207 body[".result"]:append(processed)
208 return print("done")
209 end)
210 end)
211end
212```
213
214* Existential operator support. Generate codes from:
215```Moonscript
216func?!
217 49
218x = tab?.value
219 50
220print abc?["hello world"]?.xyz
221 51
222if print and x? 52* **Binary Tool**
223 print x
224```
225&emsp;&emsp;to:
226```Lua
227if func ~= nil then
228 func()
229end
230local x
231if tab ~= nil then
232 x = tab.value
233end
234print((function()
235 if abc ~= nil then
236 local _obj_0 = abc["hello world"]
237 if _obj_0 ~= nil then
238 return _obj_0.xyz
239 end
240 return nil
241 end
242 return nil
243end)())
244if print and (x ~= nil) then
245 print(x)
246end
247```
248 53
249* More usages for `import` keyword. Will compile codes from: 54 Clone this repo, then build and install executable with:
250```Moonscript
251import 'module'
252import "module.part"
253import "d-a-s-h-e-s"
254import "player" as Player
255import "lpeg" as {:C, :Ct, :Cmt}
256```
257&emsp;&emsp;to:
258```Lua
259local module = require('module')
260local part = require("module.part")
261local d_a_s_h_e_s = require("d-a-s-h-e-s")
262local Player = require("player")
263local C, Ct, Cmt
264do
265 local _obj_0 = require("lpeg")
266 C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
267end
268```
269 55
270* Can do slash call with Lua keywords. Generate codes from: 56```sh
271```Moonscript 57> make install
272c.repeat.if\then("xyz")\else res
273```
274&emsp;&emsp;to:
275```Lua
276local _call_3 = c["repeat"]["if"]
277local _call_4 = _call_3["then"](_call_3, "xyz")
278_call_4["else"](_call_4, res)
279``` 58```
280 59
281* Feature of `Reusing variable` which helps generate reduced Lua codes. For example, MoonPlus will generate codes from: 60&emsp;&emsp;Use MoonPlus tool with:
282```Moonscript
283with leaf
284 .world 1,2,3
285
286with leaf
287 g = .what.is.this
288 print g
289
290for x in *something
291 print x
292```
293&emsp;&emsp;to:
294```Lua
295leaf.world(1, 2, 3)
296do
297 local g = leaf.what.is.this
298 print(g)
299end
300for _index_0 = 1, #something do
301 local x = something[_index_0]
302 print(x)
303end
304```
305&emsp;&emsp;instead of:
306```lua
307do
308 local _with_0 = leaf
309 _with_0.world(1, 2, 3)
310end
311do
312 local _with_0 = leaf
313 local g = _with_0.what.is.this
314end
315local _list_0 = something
316for _index_0 = 1, #_list_0 do
317 local x = _list_0[_index_0]
318 print(x)
319end
320```
321 61
322* Expression list appears at the middle of code block is not allowed. For codes like: 62```sh
323```Moonscript 63> moonp -h
324-- Moonscript 0.5.0 64Usage: moonp [options|files|directories] ...
325f = (x)->
326 "abc",123 -- valid meaningless codes
327 x + 1
328```
329in original Moonscript compiles to:
330```Lua
331local f
332f = function(x)
333 local _ = "abc", 123 -- report error in MoonPlus
334 return x + 1
335end
336```
337 65
338This feature may lead to some silenced errors. For example: 66 -h Print this message
339```Moonscript 67 -e str Execute a file or raw codes
340-- expected codes 68 -t path Specify where to place compiled files
341tree\addChild with Node! 69 -o file Write output to file
342 \addChild subNode 70 -p Write output to standard out
343 71 -b Dump compile time (doesn't write output)
344-- in original Moonscript, codes will still run after adding a break 72 -l Write line numbers from source codes
345tree\addChild 73 -v Print version
346with Node! 74 -- Read from standard in, print to standard out
347 \addChild subNode 75 (Must be first and only argument)
348```
349the original Moonscript will compile these codes to:
350```Lua
351-- expected codes
352tree:addChild((function()
353 do
354 local _with_0 = Node()
355 _with_0:addChild(subNode)
356 return _with_0
357 end
358end)())
359 76
360-- codes added with a break will still run 77 Execute without options to enter REPL, type symbol '$'
361local _ -- report error in MoonPlus instead of creating 78 in a single line to start/stop multi-line mode
362do -- an anonymous function to bind the object method
363 local _base_0 = tree
364 local _fn_0 = _base_0.addChild
365 _ = function(...)
366 return _fn_0(_base_0, ...)
367 end
368end
369do
370 local _with_0 = Node()
371 _with_0:addChild(subNode)
372end
373``` 79```
374 80
375## Standalone Compiler Usage
376 81
377Test compiler with `make test`.
378Run `moonp` complier in project folder with:
379
380```shell
381make
382./moonp -h
383```
384 82
385## License 83## License
386MIT 84MIT
diff --git a/makefile b/makefile
index 41eb380..b8484a7 100644
--- a/makefile
+++ b/makefile
@@ -188,7 +188,7 @@ dirs:
188 188
189# Installs to the set path 189# Installs to the set path
190.PHONY: install 190.PHONY: install
191install: 191install: release
192 @echo "Installing to $(DESTDIR)$(INSTALL_PREFIX)/bin" 192 @echo "Installing to $(DESTDIR)$(INSTALL_PREFIX)/bin"
193 @$(INSTALL_PROGRAM) $(BIN_PATH)/$(BIN_NAME) $(DESTDIR)$(INSTALL_PREFIX)/bin 193 @$(INSTALL_PROGRAM) $(BIN_PATH)/$(BIN_NAME) $(DESTDIR)$(INSTALL_PREFIX)/bin
194 194