leafo / moonscript Goto Github PK
View Code? Open in Web Editor NEW:crescent_moon: A language that compiles to Lua
Home Page: https://moonscript.org
:crescent_moon: A language that compiles to Lua
Home Page: https://moonscript.org
I noticed that for loop variables are not recognized as being locals when they are the target of assignments.
To illustrate, the following moonscript:
for k,v in ipairs t
v = v .. 'foo'
Transpiles down to:
for k, v in ipairs(t) do
local v = v .. 'foo'
end
When I would have expected the following Lua output:
for k, v in ipairs(t) do
v = v .. 'foo'
end
i = 1
j = i; i+=1
print j
this code will print 2, because moon think , and ; are all the separator of multi-value :(
Isn't semicolon just the separator of sentence?
The summary is here.
u already know that there is extremely large population which hates python due to its significant whitespace issue, including myself. It just backtracking to 1970s.
"Boo programming language" has two modes- one python inspired syntax (white space significant) and another whitespace agnostic mode
why can't it be offered by you
moon -nowhite file1.moon (using commandline switch OR a switch in API)
can process "begin.. end" blocks to convert them to tabs internally
or still better,
moon file1.moonx (moonx file extension will show that it has to be processed in whitespace agnostic mode) (I WILL PREFER THIS FILE EXTENSION BASED APPROACH)
or, moonx file1.moonx
in api also, if you have parse_code("moon_filename") , then you can extend it as parse_codex("moonx_filename") to deal with whitespace agnostic mode.
but why are you hampering the adoption of your language , just because you want to force people to use the whitespace issue , which is an editor/IDE issue to make it as a language source syntax issue. Still wherever or internet, it is discussed there are always two big camps (python guys and non-python(ruby,lua,groovy,C++,vb.net,C# etc) guys fighting this whitespace issue.
THIS significant whitespace is just plain braindead, we (me , my friends, my colleagues) just can not stand it, it just stinks.
It took me a lot of time to track down the source of a problem, and I came to this:
a -= b - c
Produces the following:
a = a - b - c
While, to me, it should obviously produce:
a = a - (b - c)
Same goes for other listed operators.
A shortcut for tbl[#tbl + 1] = item
would be handy, it quite frequently appears in the code. What do you think?
Something like tbl << item
maybe
Use the well-known Lua idiom (see http://lua-users.org/wiki/LuaStyleGuide)
To append to an array, it can be terser and more efficient to do
t[#t+1] = v
rather thantable.insert(t, v)
.
In lua, you can introduce new scope easily with do ... end
, it would be nice to do the same in MoonScript.
Ideally, I want something like this to work:
myFunction = do
hidden = { a: 1, b: 2, c: 3 }
(key) -> hidden[key]
Which would compile into something along the lines of this:
local myFunction
do
local hidden = { a = 1, b = 2, c = 3 }
myFunction = function (key)
return hidden[key]
end
end
Or
local myFunction = (function ()
local hidden = { a = 1, b = 2, c = 3 }
return function (key)
return hidden[key]
end
end)()
class Test
new: (param) =>
print param
clone: =>
assert @__class == Test
@__class 'test2'
Test 'test3'
c = @__class
c 'test4'
t = Test 'test1'
t\clone!
prints:
test1
table: 0x12e8c40
test3
test4
Is it a bug? I think calling @__class should work same as assigning @__class to a variable and then calling it.
Btw it translates to
assert(self.__class == Test)
self:__class('test2')
Test('test3')
local c = self.__class
return c('test4')
Suppose I have a table, key is student's name, value is a table of 4 scores.
names_scores = {
["Amy"]: {61, 75, 70, 82}
["Bob"]: {91, 58, 75, 81}
["Cathy"]: {99, 91, 85, 88}
["David"]: {55, 40, 62, 48}
["Eddie"]: {78, 70, 72, 64}
}
Now, I want to generate a new table, key is student's name, value is average score. The resulting table should be like this:
names_avg = {
["Cathy"]: 90.75
["David"]: 51.25
["Amy"]: 72
["Eddie"]: 71
["Bob"]: 76.25
}
I could use for loop to achieve this.
names_avg = {}
for name, scores in pairs names_scores
avg = 0
for i, score in ipairs scores
avg += score
avg /= #scores
names_avg[name] = avg
But, can I use table comprehension to do this kind of thing?
I'm trying to use moonscript-0.1.0-1 installed with LuaRocks 2.0.4.1 on my Windows 7 computer.
"moonc" or "moon" always fail with the following error, whatever the command-line arguments are:
lua: fatal error: `C:\LuaRocks/share/lua/5.1//alt_getopt.lua:75: attempt to get length of local 'arg' (a nil value)
stack traceback:
C:\LuaRocks/share/lua/5.1//alt_getopt.lua:75: in function 'get_ordered_opts'
C:\LuaRocks/share/lua/5.1//alt_getopt.lua:156: in function 'get_opts'
[string "..."]:11: in main chunk'
The following is possible in lua, but causes a parse error in MoonScript. It could be handy, as I use the pattern in lua frequently.
a = b = c
Which sets both a
and b
to c
.
For an actual use case,
someTable.name = localValue = somethingElse
Which, ideally would turn into
local localValue
someTable.name = localValue = somethingElse
or something along those lines.
Hi!
I'd like to extend a moonscript class with an ordinary metatable. Say,
Base = {__index: ...} class Foo extends Base
What should be Base
for extends
to work properly? Or, how can I manually chain them both?
TIA,
--Vladimir
Hi!
The following expression foo @
meaning calling foo
with current self
doesn't compile. Bug or feature?
TIA,
--Vladimir
I've spent more time in static languages, so I occasionally incorrectly add a type before a variable, as in:
string a = ""
Unfortunately this crashes moonc / moon :(.
Steps to reproduce:
$ cat > file.moon
string a = ""
^D
$ moonc file.moon
./file.moon Compile error: .../share/luarocks/share/lua/5.1/moonscript/compile.lua:347: Failed to compile value: {[7] "assign", {"a"}, {{[11] "string", """, ""}}}
stack traceback:
[C]: in function 'error'
.../share/luarocks/share/lua/5.1/moonscript/compile.lua:347: in function 'value'
.../share/luarocks/share/lua/5.1/moonscript/compile.lua:362: in function <.../share/luarocks/share/lua/5.1/moonscript/compile.lua:355>
.../share/luarocks/share/lua/5.1/moonscript/compile.lua:365: in function 'values'
.../luarocks/share/lua/5.1/moonscript/compile/value.lua:108: in function 'chain_item'
.../luarocks/share/lua/5.1/moonscript/compile/value.lua:134: in function <.../luarocks/share/lua/5.1/moonscript/compile/value.lua:92>
(tail call): ?
.../share/luarocks/share/lua/5.1/moonscript/compile.lua:387: in function 'stm'
.../share/luarocks/share/lua/5.1/moonscript/compile.lua:524: in function <.../share/luarocks/share/lua/5.1/moonscript/compile.lua:520>
[1] >> string a = ""
EDIT: I'm on version 0.2.0 release
Sorry to be the bearer of bad news :)
Hi!
In order to suppress implicit returning of the last expression result i use closing return
(verbatim). However, it goes intact in the resulting Lua code, which is simply redundant. Can you consider treating closing return
as just sign to suppress implicit returning?
TIA,
--Vladimir
In MoonScript, to define a table one need to write:
some_values = {
name: "Bill",
age: 200,
["favorite food"]: "rice"
}
Comparison that, in CoffeeScript, curly brackets a not required:
some_values =
name: "Bill"
age: 200
"favorite food": "rice"
Why not use something conciser, like CoffeeScirpt?
Or even:
table =: 1,2,3,4
table =
"name" : "string"
table::
n: 1
table2::
1
2
3
Not entirely sure if this is a feature or a bug, but metamethods defined in a class do not work in child classes. e.g.
class Foo
new: =>
__tostring: =>
return "foo!"
class Bar extends Foo
new: =>
print tostring Foo! -- prints "foo!"
print tostring Bar! -- prints "table: 0x..."
You can get the inheritance to work just by adding
__tostring:=>super!
to the child class, but it seems a little kludgey
I looked closer at the actual class code generated and it looks like the parent class'
__base
is no longer added as a metatable to the child's__base
-- if it were it seems like the metamethods should inherit just fine.
-- Strike that, yes it does! Still doesn't work though, and I have no idea why.
Using 0.1, for example gives a parsing error:
Script:
print 0.1
Error:
/usr/bin/lua: .../.luarocks/share/lua/5.1//moonscript/init.lua:24: Parse error: Failed to parse:
[1] >> print 0.1 (0)
stack traceback:
[C]: in function 'error'
.../.luarocks/share/lua/5.1//moonscript/init.lua:24: in function 'moon_chunk'
...uarocks/lib/luarocks/rocks/moonscript/dev-1/bin/moon:48: in main chunk
[C]: ?
Hi! Feature request here. I use "return _M"-style module implementation (it's actually preferred way) with classes:
_M = {}
class Sprite
--...
_M.Sprite = Sprite
return _M
So _M.Sprite = Sprite
is really boilerplate. Could you please extend class declaration syntax like this? -
class _M.Sprite
--...
on ubuntu 10.04 LTS , i did
apt-get install luarocks
luarocks install lpeg
luarocks install luafilesystem
luarocks install alt-getopt
luarocks build http://moonscript.org/rocks/moonscript-0.1.0-1.rockspec
everything is done successfully.NOW. typing "moon" on bash prompt gives following error
/usr/bin/lua: /usr/local/share/lua/5.1//moonscript/errors.lua:2: module 'moonscript' not found:
no field package.preload['moonscript']
no file '/usr/local/share/lua/5.1//moonscript.lua'
no file '/usr/local/share/lua/5.1//moonscript/init.lua'
no file '/root/.luarocks/share/lua/5.1//moonscript.lua'
no file '/root/.luarocks/share/lua/5.1//moonscript/init.lua'
no file '/usr/local/share/lua/5.1//moonscript.lua'
no file '/usr/local/share/lua/5.1//moonscript/init.lua'
no file '/root/.luarocks/share/lua/5.1//moonscript.lua'
no file '/root/.luarocks/share/lua/5.1//moonscript/init.lua'
no file '/usr/share/lua/5.1//moonscript.lua'
no file '/usr/share/lua/5.1//moonscript/init.lua'
no file './moonscript.lua'
no file '/usr/local/share/lua/5.1/moonscript.lua'
no file '/usr/local/share/lua/5.1/moonscript/init.lua'
no file '/usr/local/lib/lua/5.1/moonscript.lua'
no file '/usr/local/lib/lua/5.1/moonscript/init.lua'
no file '/usr/share/lua/5.1/moonscript.lua'
no file '/usr/share/lua/5.1/moonscript/init.lua'
no file '/usr/local/lib/lua/5.1//moonscript.so'
no file '/root/.luarocks/lib/lua/5.1//moonscript.so'
no file '/usr/local/lib/lua/5.1//moonscript.so'
no file '/root/.luarocks/lib/lua/5.1//moonscript.so'
no file './moonscript.so'
no file '/usr/local/lib/lua/5.1/moonscript.so'
no file '/usr/lib/lua/5.1/moonscript.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
[C]: in function 'require'
/usr/local/share/lua/5.1//moonscript/errors.lua:2: in main chunk
[C]: in function 'require'
...r/local/lib/luarocks/rocks/moonscript/dev-1/bin/moon:4: in main chunk
[C]: ?
HERE, why there are two forward slashes (//) in the debug output "/usr/local/share/lua/5.1//moonscript/errors.lua" ( see after /usr/local/share/lua/5.1 )
ALSO ADDITIOALLY I DID, ls /usr/local/share/lua/5.1/moonscript
compile compile.lua data.lua dump.lua errors.lua parse.lua transform.lua types.lua util.lua version.lua
THERE IS NO moonscript.lua here.
Hi, reading moonscript code, I noticed there are no comments at all. That's pretty troublesome for one that wishes to change things up. Some comments inside the code could be very helpful for the curious developer.
Hi!
Noticed the absense (or am unaware) of the following patterns:
local foo, bar
-- what would be moonscript for this?export foo = () -> 'bar'
. Allowed is first to export foo
and then foo = () -> 'bar'
. In modules it's natural to define local variables and functions and then export
them at the bottom of the file.Please, comment
TIA,
--Vladimir
I know MoonScript replace ':' with '' to call an instance method, but I think it's sooooooo weird.
As most language, '' meant escape. So, try to read:
file\read
vs
file.read
vs
file:read
When reading code, I think the first way is hardest.
and try these code:
obj1\method2 "\01\002\010"
And, I don't think so use ':' to assigning a value to key in a table is better than '='.
So, why not keep ':' and '=' behavior?
It's bad idea to change the operator behavior, it make hard to port code between Lua and Moonscript,
also make people more confused.
Hi!
How do I do block comments in moonscript? Apart from their vanilla usage, they are handy in switching off blocks of code while debugging.
TIA,
--Vladimir
The unexpected behavior is demonstrated here: http://moonscript.org/compiler/#a
In a with statement, if you leave the parenthesis off after a method call to a nested object, the method is invoked on the "with" object, rather than the indicated target. So:
with foo
.prop\send msg
Becomes:
do
local _with_0 = self.foo
_with_0.prop(_with_0:send(msg))
return _with_0
end
But,
with foo
.prop\send(msg)
Becomes:
do
local _with_0 = self.foo
_with_0.prop:send(msg)
return _with_0
end
this for item in *items do print item
should compile to this
local _list_0 = items
local _end_list = #items
if _end_list > 0 then
for _index_0 = 1, #_list_0 do
local item = _list_0[_index_0]
print(item)
end
end
In the reference manual, http://moonscript.org/reference/#object_oriented_programming, it says:
All properties of a class are shared among the instances. This is fine for functions, but for other types of objects, undesired results may occur.
Then how could one do object-oriented programming? All properties(instance variables) are shared among all instances?
Nice language. :)
Use case:
cache = {}
func = (key) ->
value = cache[key]
if value ~= nil
value
else
cache[key] = value + 1
Expected compilation:
local cache = { }
local func
func = function(key)
local value = cache[key]
if value ~= nil then
return value
else
local _result = value + 1
cache[key] = _result
return _result
end
end
Current compilation:
local cache = { }
local func
func = function(key)
local value = cache[key]
if value ~= nil then
return value
else
cache[key] = value + 1
end
end
I read through the reference manual. It seems that moonscript's doesn't support the semantics of static class variable, which is common in most OOP languages( ex. C++, Java).
I come up with my own implementation as the following. If anyone know a better way do it, please leave comments. Thank you.
class Stone
static: { scount: 0 }
new: =>
@static.scount+=1
print 'scount = ', @static.scount
s1= Stone()
s2= Stone()
s3= Stone()
s4= Stone()
s5= Stone()
print 'total stones = ', Stone.static.scount
Although it's pure syntactical sugar that could be handled by if not
, sometimes unless
would read significantly better.
unless value
value = calculate!
or
value = calculate! unless value
Could compile into
if not value then
value = calculate()
end
It would be a great addition to have a word quoting operator which splits on whitespace, like qw{}
in Perl or %w{}
from Ruby.
I see this as a much needed feature for the class implementation in Moonscript.
A great thing would be the ability to manipulate the base table through the static initializer.
It will be extremely useful for applying macros to the base class, or when it has to be registered with a function.
As an example, I've had to paste this 10 times and modify 8 parts every time.
SetStrength: (val) => @str = val self\ReportPropertyChange "str", val AddStrength: (val) => @str += val self\ReportPropertyChange "str", val GetStrength: => return @str
And I'm going to have a bad time if that will ever need to be modified.
Of course, having the static initializers would bring up many more possibilities.
P.S. Please don't use something like "Init" or "Initialize" for the static initializer. In the game I am programming for, those are used for initializing certain table-based object types, and it can't be the only game.
And don't forget about inheritance. Static initializers of the base class should apply to it's children too.
Currently, @name
works as self.name
, but for a non-constant key, @[key]
would be a nice syntactical sugar for self[key]
.
Reproducible with example from docs in online compiler:
if hello = os.getenv "hello"
print "You have hello", hello
elseif world = os.getenv "world"
print "you have world", world
else
print "nothing :("
result:
./web_moon.lua:67: Compile error: /app/packages/share/lua/5.1/moonscript/types.lua:259: unknown key: `__class` on node type: `if`
stack traceback:
[C]: in function 'error'
/app/packages/share/lua/5.1/moonscript/types.lua:259: in function </app/packages/share/lua/5.1/moonscript/types.lua:255>
/app/packages/share/lua/5.1/moonscript/util.lua:10: in function 'type'
/app/packages/share/lua/5.1/moonscript/transform.lua:185: in function 'apply_to_last'
/app/packages/share/lua/5.1/moonscript/transform.lua:645: in function 'transformer'
/app/packages/share/lua/5.1/moonscript/transform.lua:360: in function </app/packages/share/lua/5.1/moonscript/transform.lua:351>
(tail call): ?
(tail call): ?
/app/packages/share/lua/5.1/moonscript/transform.lua:196: in function </app/packages/share/lua/5.1/moonscript/transform.lua:190>
(tail call): ?
/app/packages/share/lua/5.1/moonscript/transform.lua:743: in function 'transformer'
/app/packages/share/lua/5.1/moonscript/transform.lua:360: in function </app/packages/share/lua/5.1/moonscript/transform.lua:351>
...
(tail call): ?
/app/packages/share/lua/5.1/moonscript/transform.lua:645: in function 'transformer'
/app/packages/share/lua/5.1/moonscript/transform.lua:360: in function </app/packages/share/lua/5.1/moonscript/transform.lua:351>
(tail call): ?
(tail call): ?
/app/packages/share/lua/5.1/moonscript/transform.lua:196: in function </app/packages/share/lua/5.1/moonscript/transform.lua:190>
(tail call): ?
(tail call): ?
/app/packages/share/lua/5.1/moonscript/compile.lua:591: in function </app/packages/share/lua/5.1/moonscript/compile.lua:589>
(tail call): ?
[6] >> print "nothing :("
Failed to parse:
[163] >> for k, v in next, self (0)
This simply doesn't work.
Using next, self
instead of pairs self
is faster, and that speed gain is needed in time-critical code.
I have a C program that runs a Lua file via Lua C API (LuaJIT actually). This Lua file loads Moonscript files this way:
-- it's init.lua
require "moonscript"
require "moonscript.errors"
local textures = assert(require 'src/textures') --it's .moon file
To have nice traceback we do like in bin/moon:
local function pb(err)
local trace = debug.traceback()
print(moonscript.errors.rewrite_traceback(trace, err))
os.exit(1)
end
xpcall(run, pb) --"run" is some local function that calls other functions from .moon files
if false
with error
call at bottom so you can run it without other required file. This is obviously not handled by our xpcall wrapper (error is called at include time) but reported line is wrong too, maybe you could check how parser handles such file please..In lua I can do this:
b = 'key_b'
t = {
a = 'a',
[b] = 'b' ,
}
for k, v in pairs(t) do print(k,v) end
and it prints
a a
key_b b
But in MoonScript the following
b = 'key_b'
t =
a: 'a'
[b]: 'b'
print k,v for k, v in pairs t
gives me
a a
b b
It is because moonc generates
b = 'key_b'
t = {
a = 'a',
b = 'b' ,
}
instead of the following:
b = 'key_b'
t = {
a = 'a',
[b] = 'b' ,
}
Interesting enough, moonc does generate the key between [ ] when the key is a
literal (number, table, function or string).
in my knowlegde, luarocks is not compatible with luajit. It would be great to see moonscript's performance on luajit.
Hi!
Imho, back-slash style of method invocation is not eye pleasant. Back-slashes mean escaping of special characters in most languages.
Wonder if we could allow instance:method(...)
syntax instead? We have such double meaning for -
, which when used immediately before a token means negation, otherwise subtraction. Likewise, MoonScript's instance:method(...)
could compile to Lua's instance:method(...)
, while instance: method(...)
could compile like at present, to {instance = method(...)}
.
What do you think?
TIA,
--Vladimir
If I make a class with no explicit constructor, the __init method looks like this:
__init = function(self, ...)
if _parent_0 then
return _parent_0.__init(self, ...)
end
end,
But if I declare the constructor, it looks like this:
__init = function(self)
self[privateKey] = { }
self[privateKey].IReportPropertyChange_hooks = { }
self[privateKey].IReportPropertyChange_values = { }
end,
I obviously see a problem here with the class implementation.
The parent's __init must be called before the child's __init algorithm under all circumstances.
I was counting on that and I've been having headaches with my code not working, thinking that I messed up somewhere. This turned out to be the problem.
The first parms default value needs to by wrapped in parentheses in order to not return a moonc compile error if it is a reference to a variable.
class Test
new: =>
@v1 = '1'
@v2 = '2'
testFunc: (a =(@v1), b = @v2) =>
print a .. b
Test!\testFunc!
atm you must do export foo; foo = bar
also export foo,bar,baz = 1,2,3 should work here
(IMO, do with it what you will)
btw great job
In the reference manual regarding about table slicing:
Any of the slice arguments can be left off to use a sensible default. In this example, if the max index is left off it defaults to the length of the table. This will take everything but the first element:
slice = [item for item in *items[1:]]
"but the first element"?
The code will get all of items, am I right?
class Foo
new: (a, @b, @c = 123) =>
--some code
works like:
class Foo
new: (a, b, c = 123) =>
@b = b
@c = c
--some code
There's similar feature in Coffeescript and it's quite useful, many classes has such duplication:
class .Bone
new: (name, texture_path, z, ..blabla) =>
@name = name
@z = z
@texture_path = texture_path
Statements like
if blah
-- indented
else
bleh
are invalid at the moment. So if one wants to e.g. quickly comment out the line in such block (or even to have an empty block), one have to add some stub code and it can't be just nil
if one doesn't want to return
cause it translates to return nil
.
So, maybe translate
if foo
--
to
if foo then
end
or introduce some noop statement like ;
(;
is already allowed, maybe reuse it?) or pass
(like in Python)
Right:
print 4+2-(2+3)
print (4+2)- (2+3)
print (4+2) - (2+3)
Error:
print (4+2) -(2+3)
print (4+2)-(2+3)
Error output:
moon: 1.moon:1(1): attempt to call a number value
stack traceback:
1.moon:1(1): in main chunk
Hi,
This works with Lua:
#!/usr/bin/lua
print("hi")
But fails with Moonscript:
#!/usr/bin/moon
print "hi"
When run:
./test.lua
hi
./test.moon
/usr/bin/lua: /usr/share/lua/5.1//moonscript/init.lua:24: Parse error: Failed to parse:
[1] >> #!/usr/bin/moon (0)
stack traceback:
[C]: in function 'error'
/usr/share/lua/5.1//moonscript/init.lua:24: in function 'moon_chunk'
/usr/lib/luarocks/rocks/moonscript/dev-1/bin/moon:48: in main chunk
[C]: ?
It would be great if moon also would support shebang on the first line.
See LuaDist/moonscript@bc16247 for the changes I needed to do to get current master to run correctly in LuaDist.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.