October 8, 2009

kaLua

For years I have been searching for the "perfect" scripting language. I started with Unix shells and Tcl, migrated to Python, toyed with Javascript and Groovy, and lately I have ventured into the world of Lua. To me Javascript is one of the more elegant syntaxes. It is fairly simple with a good balance of words vs. puctuation. However, Javascript is designed for web pages and the various runtimes that are available are rather large and cumbersome. Lua's size is extremely attractive, and I like Lua's simple syntax and no-nonsense approach.
But I felt the language is too wordy. This is one of the turnoffs Ruby has as well. There is a good balance that can be reached between wordy, verbose languages (like Objective-C) and terse, cryptic languages (like Unix shell). I am constantly looking for that balance. Python is close, but I really dislike the "blocking via indent", even after programming in it for years; it never found a place in my heart.
So what's wrong with Lua? Not much, really, as long as you're not looking for a true OO language. But it's not perfect. For starters, Lua denotes blocks via do/end, function/end, and if/then/end keywords. To me, this makes the code too wordy. The density of words over punctuation is too great. I wanted to shift that balance, plus make the syntax a little closer to existing languages. There are some other constructs in Lua that strike me as odd or "old-fashioned". For example, the [[/]] pair to create multiline strings. I find the Python/Groovy approach of using triple quotes (""" or ''') much more appealing.
So I looked at the Lua parser code and it seemed simple enough. I started tweaking and adding things. Before I knew it, I had changed a great deal of the syntax.
Once I realized I had a new language on my hands, I needed a name. I have come up with "kaLua", which could stand for "Kick Ass" Lua, but it really is just the best I could come up with and still retain the "Lua". I'm all for changing this name. One alternative that stands out is Superscript.
kaLua is a derivative of Lua and is still very much Lua-like. It would be nice if it did not change existing syntax and merely added to it, but some things had to change. I'll describe these incompatible changes below. This document summarizes those changes made to Lua to create the kaLua almost-superset. Mind you, these changes come from a syntax snob, and many will dislike these changes. Syntax is a matter of taste; this is my taste. If it's not yours, then move along. I won't be offended.

Function Blocking

Functions can be declared like this in Lua:
function hello() print('hello world') end
and they can be declared anonymously (inline) like this:
if something then return function () print('hi') end end
kaLua adds curly brace blocking to function definitions. The above two could be written as:
function hello() { print('hello world') }
and
if something { return function () { print('hi') } }
It does not matter what line the {} characters are on; Lua is fairly insensitive to line breaks as opposed to some scripting languages.

If/then/elseif/else Blocking

Blocking for the if/... set of statements is a bit more complex, mainly because the current Lua syntax is somewhat inconsistent. You can have numerous "then" portions but only one "end":
if something then do_something() elseif something_else then do_another_thing() elseif something_else_yet then do_that_again() else last_ditch_effort() end
The blocks for each condition are separate contexts. To make this cleaner and clearer, kaLua adds support for braces and removes the useless "then" keyword:
if something { do_something() } elseif something_else { do_another_thing() } elseif something_else_yet { do_that_again() } else { last_ditch_effort() }
The braces do not have to appear on the same line or on a different line. Although you can continue to use the old style blocking, you have to be consistent within one if compound statement. In other words, you can't use braces in the if block and use the old style blocking in the else portion.

While Blocking

The while loop blocks via a do/end pair:
while something_is_true do something() end
kaLua adds an addition to support braces:
while something_is_true { something() }

Repeat/Until Blocking

Lua creates yet another form of blocking with the repeat/until pair:
x = 3 repeat print('repeat') x = x - 1 until x == 0
kaLua simply adds braces to form the block for consistency. The block creates a new context, and the condition in the until clause does have visibility to that context, even though it is physically outside the block.
x = 3 repeat { print('repeat') x = x - 1 } until x == 0

Standalone Blocks

Lua uses do/end blocks to create a nested context:
x = 'hello' do local x = 23 end
kaLua replaces the do/end pair with {}:
x = 'hello' { local x = 23 }

Function Calls

Lua supports 3 different syntaxes for making function calls:
x = callme("23") x = callme{f="23"} x = callme"23"
Of these, only the first one makes sense. The other two muddle up the language syntax and offer little advantage. I guess they are syntactic sugar, but they don't seem very "sweet" to me. The second two examples above are no longer supported. Only the following is allowed:
x = callme("23")
Because of the additional support for braces in the syntax, the second one conflicts with the updated grammar. The third function call form is just loopy; I hope no one really uses that.
If you need to pass a table as an argument, surround with parens like you would expect. In other words, function calls always involve parens. To me this is consistent and clean:
x = callme({f="23"})

Multiline Strings

Lua supports multiline strings with the [[/]] pair, and also supports nested multiline strings with [=[/]=], [==[/]==], etc pairs:
print([[this is a multiline string]]) print([=[ this is a [==[nested string]==] so there you have it]=])
The use of [[/]] is pretty ugly and uses the bracket characters where they would be best used for indexing. kaLua changes the multiline string to use the triple quote concept from Python and other languages:
print("""this is a multiline string""") print('''this is also a multi- line string''')
kaLua gets rid of the nested string format altogether. Its value is very dubious and it is extremely ugly. For an embedded language that prides itself on simplicity, this feature seems unnecessary.

Comments

Lua uses the -- characters to denote a single line comment, and --[[/]] for multiline comments:
-- this is a comment --[[ print("this code is commented out") ]]
kaLua changes these to more common comment sequences:
// this is a comment /* print("this code is commented out") */

Operators

Lua uses ~= for "not equals". kaLua adds a more common operator sequence !=

Summary

That sums up the additions and changes made to the Lua syntax. I have these changes implemented in a version of the library. I really haven't used it much and the code needs some more tweaking. I would like to make kaLua be a true superset of Lua and put back some of the things I removed. The only thing kaLua cannot support is the function call syntax that uses curly braces instead of parens. This is one feature of Lua that won't survive in kaLua.
There are a few other quirks of Lua I don't like, but will require a lot more thought and code mangling. The biggest offender to me is the "method call" syntax:
object:method(parms)
It's really not that bad, but I find it a little hokey. How else to do it? No idea. This is still better than:
object.method(object, parms)
It would be preferable that I can call it with a dot instead of the colon and have it just figure it out, and pass object as the self parameter:
object.method(parms)
If anyone is interested in getting a copy of kaLua, let me know via a comment or an email. If there is enough demand (which I don't expect), then I can post the code.

No comments:

Post a Comment