Score
0
Watch 4 Star 3 Fork 0

Li Jin / MoonPlusC++MIT

Join us
Explore and code with more than 5 million developers,Free private repositories !:)
Sign up
用C++重写的Moonscript编译器。 spread retract

  • C 56.4%
  • C++ 39.7%
  • MoonScript 2.7%
  • Makefile 1.1%
  • CMake 0.1%
Clone or download
Loading...
README.md

MoonPlus

CI
MoonPlus is a compiler with features from Moonscript language 0.5.0 and implementing new features to make Moonscript more up to date.

Since original Moonscript has been used to write web framework lapis and run a few business web sites like itch.io and 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.

So 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.

Features

  • No other dependencies needed except modified parserlib library from Achilleas Margaritis with some performance enhancement. lpeg library is no longer needed.
  • Written in C++17.
  • Support full Moonscript language features, generate the same Lua codes with original compiler.
  • Reserve line numbers from Moonscript sources in compiled Lua codes to help with debugging.

Installation

Install luarocks, a package manager for Lua modules. Then install Lua module with

> luarocks install moonplus

Usage

require("moonp")("main") -- require `main.moon`

local moonp = require("moonp")
print(moonp.to_lua[[
f = ->
  print "hello world"
f!
]],{
  implicit_return_root = true,
  reserve_line_number = false,
  lint_global = false
})

Changes

The 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.

  • Add goto statement support.

  • Add macro functions.

-- file 'macro.moon'
export macro block config = (debugging = true)->
  global debugMode = debugging == "true"
  ""

export macro block asserts = (cond)->
  debugMode and "assert #{cond}" or ""

export macro expr assert = (cond)->
  debugMode and "assert #{cond}" or "#{cond}"

$config!

-- file 'main.moon'
import 'macro' as {:$config, :$assert, :$asserts}

macro expr and = (...)-> "#{ table.concat {...}, ' and ' }"

$asserts item ~= nil
$config false
value = $assert item

if $and f1!, f2!, f3!
  print "OK"

Compiles to:

-- file 'macro.moon'
local _module_0 = { }
return _module_0

-- file 'main.moon'
assert(item ~= nil)
local value = item
if (f1() and f2() and f3()) then
  print("OK")
end
  • Move old export statement functions to global statement to match the local statement.

  • 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:

-- file 'Config.moon'
export default {flag:1, value:"x"}

-- file 'Utils.moon'
export map = (items, func)-> [func item for item in *items]
export filter = (items, func)-> [item for item in *items when func item]

-- file 'main.moon'
import 'Config' as {:flag, :value}
import 'Utils' as {:map, :filter}

Compiles to:

-- file 'Config.moon'
local _module_0 = nil
_module_0 = {
  flag = 1,
  value = "x"
}
return _module_0

-- file 'Utils.moon'
local _module_0 = { }
local map
map = function(items, func)
  local _accum_0 = { }
  local _len_0 = 1
  for _index_0 = 1, #items do
    local item = items[_index_0]
    _accum_0[_len_0] = func(item)
    _len_0 = _len_0 + 1
  end
  return _accum_0
end
_module_0["map"] = map
local filter
filter = function(items, func)
  local _accum_0 = { }
  local _len_0 = 1
  for _index_0 = 1, #items do
    local item = items[_index_0]
    if func(item) then
      _accum_0[_len_0] = item
      _len_0 = _len_0 + 1
    end
  end
  return _accum_0
end
_module_0["filter"] = filter
return _module_0

-- file 'main.moon'
local flag, value
do
  local _obj_0 = require('Config')
  flag, value = _obj_0.flag, _obj_0.value
end
local map, filter
do
  local _obj_0 = require('Utils')
  map, filter = _obj_0.map, _obj_0.filter
end
  • Add multi-line comment support.

  • Usage for symbol \ to escape new line. Will compile codes:

str = --[[
   This is a multi line comment.
   It's OK.
]] strA \ -- comment 1
   .. strB \ -- comment 2
   .. strC

func --[[ip]] "192.168.126.110", --[[port]] 3000

  to:

local str = strA .. strB .. strC
func("192.168.126.110", 3000)
  • Back call features with new operator and syntax. For example:
{1,2,3} \
  |> map((x)-> x * 2) \
  |> filter((x)-> x > 4) \
  |> reduce(0, (a,b)-> a + b) \
  |> print

do
  (data) <- http.get "ajaxtest"
  body[".result"]\html data
  (processed) <- http.post "ajaxprocess", data
  body[".result"]\append processed
  print "done"

  will be compiled to:

print(reduce(filter(map({
  1,
  2,
  3
}, function(x)
  return x * 2
end), function(x)
  return x > 4
end), 0, function(a, b)
  return a + b
end))
do
  http.get("ajaxtest", function(data)
    body[".result"]:html(data)
    return http.post("ajaxprocess", data, function(processed)
      body[".result"]:append(processed)
      return print("done")
    end)
  end)
end
  • Existential operator support. Generate codes from:
func?!

x = tab?.value

print abc?["hello world"]?.xyz

if print and x?
  print x

  to:

if func ~= nil then
  func()
end
local x
if tab ~= nil then
  x = tab.value
end
print((function()
  if abc ~= nil then
    local _obj_0 = abc["hello world"]
    if _obj_0 ~= nil then
      return _obj_0.xyz
    end
    return nil
  end
  return nil
end)())
if print and (x ~= nil) then
  print(x)
end
  • More usages for import keyword. Will compile codes from:
import 'module'
import "module.part"
import "d-a-s-h-e-s"
import "player" as Player
import "lpeg" as {:C, :Ct, :Cmt}

  to:

local module = require('module')
local part = require("module.part")
local d_a_s_h_e_s = require("d-a-s-h-e-s")
local Player = require("player")
local C, Ct, Cmt
do
  local _obj_0 = require("lpeg")
  C, Ct, Cmt = _obj_0.C, _obj_0.Ct, _obj_0.Cmt
end
  • Can do slash call with Lua keywords. Generate codes from:
c.repeat.if\then("xyz")\else res

  to:

local _call_3 = c["repeat"]["if"]
local _call_4 = _call_3["then"](_call_3, "xyz")
_call_4["else"](_call_4, res)
  • Feature of Reusing variable which helps generate reduced Lua codes. For example, MoonPlus will generate codes from:
with leaf
  .world 1,2,3

with leaf
  g = .what.is.this
  print g

for x in *something
  print x

  to:

leaf.world(1, 2, 3)
do
  local g = leaf.what.is.this
  print(g)
end
for _index_0 = 1, #something do
  local x = something[_index_0]
  print(x)
end

  instead of:

do
  local _with_0 = leaf
  _with_0.world(1, 2, 3)
end
do
  local _with_0 = leaf
  local g = _with_0.what.is.this
end
local _list_0 = something
for _index_0 = 1, #_list_0 do
  local x = _list_0[_index_0]
  print(x)
end
  • Expression list appears at the middle of code block is not allowed. For codes like:
-- Moonscript 0.5.0
f = (x)->
  "abc",123 -- valid meaningless codes
  x + 1

in original Moonscript compiles to:

local f
f = function(x)
 local _ = "abc", 123 -- report error in MoonPlus
 return x + 1
end

This feature may lead to some silenced errors. For example:

-- expected codes
tree\addChild with Node!
  \addChild subNode
  
-- in original Moonscript, codes will still run after adding a break
tree\addChild
with Node!
   \addChild subNode

the original Moonscript will compile these codes to:

-- expected codes
tree:addChild((function()
  do
    local _with_0 = Node()
    _with_0:addChild(subNode)
    return _with_0
  end
end)())

-- codes added with a break will still run
local _ -- report error in MoonPlus instead of creating
do      -- an anonymous function to bind the object method
  local _base_0 = tree
  local _fn_0 = _base_0.addChild
  _ = function(...)
    return _fn_0(_base_0, ...)
  end
end
do
  local _with_0 = Node()
  _with_0:addChild(subNode)
end

Standalone Compiler Usage

Test compiler with make test. Run moonp complier in project folder with:

make
./moonp -h

License

MIT

Comments ( 0 )

Sign in for post a comment

C++
1
https://gitee.com/pig/MoonPlus.git
git@gitee.com:pig/MoonPlus.git
pig
MoonPlus
MoonPlus
master

Help Search

220309 7019f5b6 1899542 220318 4015cbb9 1899542