aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md376
1 files changed, 37 insertions, 339 deletions
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  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  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