├── .hgignore ├── LICENSE ├── Makefile ├── README.md ├── helpers.js ├── index.js ├── lua-lltk ├── assign-hazard-1.lua ├── assign-hazard-2.lua ├── closure-1.lua ├── closure-3.lua ├── closure-3b.lua ├── concatenate-1.lua ├── concatenate-2.lua ├── expr-bracket-1.lua ├── expr-logical-1.lua ├── expr-logical-2.lua ├── expr-logical-3.lua ├── expr-return-1.lua ├── expr-var-return-1.lua ├── for-statement-1.lua ├── for-statement-2.lua ├── for-statement-4.lua ├── forin-1.lua ├── forin-2.lua ├── forin-4.lua ├── func-assign-1.lua ├── func-assign-2.lua ├── func-assign-3.lua ├── func-declaration-1.lua ├── func-empty-1.lua ├── func-vararg-1.lua ├── function-rec.lua ├── function-tailrec.lua ├── if-1.lua ├── logical-tests-1.lua ├── logical-tests-2.lua ├── logical-tests-3.lua ├── logical-tests-3b.lua ├── logical-tests-3c.lua ├── logical-tests-3d.lua ├── logical-tests-4.lua ├── logical-tests-4b.lua ├── logical-tests-5.lua ├── logical-tests-6.lua ├── logical-value-1.lua ├── logical-value-2.lua ├── mixed-assign-1.lua ├── mixed-assign-2.lua ├── mixed-assign-3.lua ├── multi-assign-1.lua ├── multi-assign-2b.lua ├── multi-call-1.lua ├── multi-call-2.lua ├── multi-returns-1.lua ├── nested-ifs-1.lua ├── nested-ifs-2.lua ├── nested-ifs-3.lua ├── nested-ifs-4.lua ├── not-operator-1.lua ├── not-operator-2.lua ├── not-operator-3.lua ├── not-operator-4.lua ├── printf-1.lua ├── rand-init.lua ├── repeat-1.lua ├── repeat-test-1.lua ├── repeat-test-2.lua ├── send-epression-call-1.lua ├── send-epression-call-2.lua ├── string-escapes-1.lua ├── struct-assign-1.lua ├── table-1.lua ├── table-2.lua ├── table-3.lua ├── table-4.lua ├── table-5.lua ├── test-1.lua ├── test-2.lua ├── test-3.lua ├── test-4.lua ├── test-5.lua ├── test-6.lua ├── test-7.lua ├── test-8.lua ├── test-9.lua ├── vararg-pack-1.lua ├── vararg-pack-2.lua ├── vararg-pack-3.lua ├── vararg-pack-4.lua ├── vararg-pack-5.lua ├── while-loop-1.lua ├── while-loop-2.lua └── while-loop-2b.lua ├── lua-testmore ├── 000-sanity.t ├── 001-if.t ├── 002-table.t ├── 011-while.t ├── 012-repeat.t ├── 014-fornum.t └── 015-forlist.t ├── lua-tests ├── and-with-nil.lua ├── bisect.lua ├── bulk-assign.lua ├── closure.lua ├── complex.lua ├── count.lua ├── dotdotdot.lua ├── fib.lua ├── hello.lua ├── iter.lua ├── life.lua ├── mt.lua ├── multi-return.lua ├── nbody.lua ├── nodouble.lua ├── oop.lua ├── optest.lua ├── scope.lua ├── singleton.lua ├── sort.lua ├── specnorm.lua ├── sums.lua ├── trees.lua └── ycombinator.lua ├── lua.pegjs ├── package.json ├── public ├── escodegen.browser.js ├── index.html ├── stdlib.js └── ui-ace.js ├── server.js ├── test.lua └── test_spec.js /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | node_modules 4 | public/ui-ace.js 5 | dist/* 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Rob Blanckaert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: public/piler.js public/piler.js.min public/stdlib.js.min 2 | cp public/piler.js dist/parser.js 3 | cp public/piler.min.js dist/parser.min.js 4 | cp public/stdlib{,.min}.js dist 5 | 6 | 7 | public/piler.js: lua.pegjs helpers.js 8 | cat helpers.js lua.pegjs | pegjs -e this.parser > public/piler.js 9 | 10 | public/piler.js.min: public/piler.js 11 | uglifyjs public/piler.js -o public/piler.min.js 12 | 13 | public/stdlib.js.min: public/stdlib.js 14 | uglifyjs public/stdlib.js -o public/stdlib.min.js 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lua2JS 2 | 3 | A Lua parser and standard library targeting the [Mozilla Parser API][parserapi] AST. 4 | 5 | [parserapi]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API 6 | 7 | ## Installing 8 | 9 | Generated and minified sources are available on NPM 10 | 11 | ```sh 12 | npm install lua2js 13 | ``` 14 | 15 | ## Dependencies 16 | 17 | - *Development*: peg.js 18 | - *Runtime*: None =) 19 | 20 | ## Compatibility 21 | 22 | Many lua programs run unmodified on lua2js. See the `lua-tests` folder for some examples. 23 | 24 | ### JavaScript <-> Lua 25 | 26 | When the `luaCalls` option is on, the arguments to javascript functions will be adjusted in the following ways: 27 | 28 | - If the function was being called with : syntax, the variable that would be passed as `self` is used as `this` 29 | - If a LuaTable is passed as an argument if the table only has numeric entries, an array will be passed. If there are no numeric entire, a javascript object will be passed. If both are present, the LuaTable object will be passed. 30 | - If the last argument is a function that returned multiple values, they will be unpacked as normal. 31 | 32 | ### Lua Syntax Not Supported (Yet) 33 | 34 | - Long form strings and comments will choke on internal `]]`'s even when using the `[==[` syntax. 35 | - The `goto` statement and labels from lua 5.2 are unimplemented. 36 | - The global environment doesn't exist in `_ENV` or `_G`. 37 | 38 | ### Lua Runtime Standard Library 39 | 40 | - `pairs` `ipairs` `next` all work on both lua tables and javascript objects/arrays 41 | - MetaTable and operator overloading work on LuaTables 42 | 43 | ### Lua Standard Library Holes 44 | 45 | - `getmetatable` and `setmetatable` only work on LuaTable's 46 | - `requires` and `package` interface tables are missing. 47 | - The `debug` library is missing. 48 | - The `coroutine` library is missing (and no runtime support for coroutines exists)` 49 | - The `bit32` library from lua 5.2 is incomplete. 50 | - `string.format` is less powerful then the lua version. 51 | - Pattern matching (`string.find`, `string.match`, `string.gsub`) is unimplemented. 52 | - Code loading (`load`, `dostring`, `dofile`, etc...) is unimplemented. 53 | 54 | 55 | 56 | ## Parser Options 57 | 58 | **Boolean Options** 59 | 60 | - `decorateLuaObjects`: Mark lua functions so `__lua.call` can call them differently. Also the `{}` syntax will create a LuaTable object instead of a normal javascript object. 61 | - `encloseWithFunctions`: Protect variable scoping by creating functions and calling them. 62 | - `forceVar`: Forbid generation of `let` statements to maintain ES5 compatibility. 63 | - `loose`: Try not to throw parse errors, and collect them in `ast.errors` instead. 64 | - `luaCalls`: Rewrite function calls to use `__lua.call` to fix-up various lua<->javascript calling convention differences. 65 | - `luaOperators`: Use functions in the standard library instead of conventional operators to improve Lua compatibility. (e.g. `a+b` becomes `__lua.add(a,b)`) 66 | - `noSharedObjects`: Make sure all AST nodes are unique objects. Can prevent bugs when performing transformations on the returned AST. 67 | - `allowRegularFunctions`: Normally all functions are emitted in `something = function() { ... }` format. Enable this to emit the more normal (but sometimes less compatible) `function something() { ... }`. 68 | 69 | ## Testing 70 | 71 | You can run a suite of tests using the `npm test` command. The tests require having `nodeunit` installed globally and a working Lua interpreter on your path. The tests fall into three categories. 72 | 73 | - **Simple Tests**: These are contained in an array toward the top of `test.js` and test simple lua programs without the Lua interpreter. 74 | - `./lua-tests/`: A collection of various lua programs from around the internet. These are interpreted in node and their output compared against the systems lua interpreter. 75 | - `./lua-testmore/`: Selected tests from the lua-TestMore project. Similar to the above. 76 | 77 | ## License 78 | 79 | Code and documentation copyright 2014 Rob Blanckaert. Code released under [the MIT license](LICENSE). -------------------------------------------------------------------------------- /helpers.js: -------------------------------------------------------------------------------- 1 | { 2 | function listHelper(a,b,c) { return a == null ? [] : [a].concat(b.map(function(b) { return b[c || 2]; })); } 3 | function opt(name, def) { return name in options ? options[name] : def } 4 | 5 | function expandMultiStatements(list) { 6 | var out = []; 7 | for ( var i = 0; i < list.length; ++i ) { 8 | var value = list[i]; 9 | if (value instanceof Array) out = out.concat(value); 10 | else out.push(value); 11 | } 12 | return out; 13 | } 14 | 15 | function wrapNode(obj, hasScope) { 16 | hasScope = !!hasScope 17 | obj.loc = location(); 18 | obj.hasScope = hasScope; 19 | obj.text = text(); 20 | return obj; 21 | } 22 | 23 | function eUntermIfEmpty(what, type, end, start) { 24 | if ( what.length == 0 ) return eUnterminated(type, end, start); 25 | return true; 26 | } 27 | 28 | function eUnterminated(type, end, start) { 29 | var loc = start !== undefined || location(); 30 | var xline = loc ? loc.start.line : start.loc.start.line; 31 | var xcol = loc ? loc.start.column : start.loc.start.column; 32 | 33 | eMsg("`" + (end || "end") + "` expected (to close " + type + " at " + xline + ":" + xcol + ")" ); 34 | return true; 35 | } 36 | 37 | function eMsg(why) { 38 | if ( !opt("loose", false) ) error(why); 39 | errors.push({msg: why, loc: location()}); 40 | return true; 41 | } 42 | 43 | var opPrecedence = { 44 | "^": 10, 45 | "not": 9, 46 | "*": 8, "/": 8, "%": 8, "//": 8, 47 | "+": 7, "-": 7, 48 | "..": 6, 49 | "<": 5, ">": 5, ">=": 5, "<=": 5, "==": 5, "~=": 5, 50 | "and": 4, 51 | "or": 3 52 | } 53 | 54 | function precedenceClimber(tokens, lhs, min) { 55 | while ( true ) { 56 | if ( tokens.length == 0 ) return lhs; 57 | var op = tokens[0]; 58 | var prec = opPrecedence[op]; 59 | if ( prec < min ) return lhs; 60 | tokens.shift(); 61 | 62 | var rhs = tokens.shift(); 63 | while ( true ) { 64 | var peek = tokens[0]; 65 | if ( peek == null || opPrecedence[peek] <= prec ) break; 66 | rhs = precedenceClimber(tokens, rhs, opPrecedence[peek]); 67 | } 68 | 69 | lhs = bhelper.binaryExpression(op, lhs, rhs); 70 | } 71 | 72 | } 73 | 74 | var errors; 75 | 76 | function init() { 77 | errors = []; 78 | } 79 | 80 | var builder = { 81 | assignmentExpression: function(op, left, right) { return wrapNode({type: "AssignmentExpression", operator: op, left: left, right: right }); }, 82 | binaryExpression: function(op, left, right) { 83 | return wrapNode({type: (op == '||' || op == '&&') ? "LogicalExpression" : "BinaryExpression", operator: op, left: left, right: right }); 84 | }, 85 | blockStatement: function(body) { return wrapNode({ type: "BlockStatement", body: body}); }, 86 | callExpression: function(callee, args) { return wrapNode({ type: "CallExpression", callee: callee, arguments: args}); }, 87 | emptyStatement: function() { return wrapNode({ type: "EmptyStatement" }); }, 88 | functionDeclaration: function(name, args, body, isGenerator, isExpression) { 89 | return wrapNode({type: "FunctionDeclaration", id: name, params: args, body: body, generator: isGenerator, expression: isExpression }); 90 | }, 91 | memberExpression: function(obj, prop, isComputed) { return wrapNode({ type:"MemberExpression", object: obj, property: prop, computed: isComputed }); }, 92 | variableDeclaration: function(kind, decls) { return { type: "VariableDeclaration", declarations: decls, kind: opt("forceVar", true) ? "var" : kind } }, 93 | functionExpression: function(name, args, body) { return { type: "FunctionExpression", name: name, body: body, params: args } }, 94 | returnStatement: function(arg) { return wrapNode({type: "ReturnStatement", argument: arg}); } 95 | }; 96 | 97 | var i = function(n) { return { type: "Identifier", name: n}; } 98 | var id = i; 99 | var tmpVarCtr = 0; 100 | 101 | function clone(obj) { 102 | return JSON.parse(JSON.stringify(obj)); 103 | } 104 | 105 | 106 | 107 | function finalize(ast) { 108 | if ( opt("loose", false) ) ast.errors = errors; 109 | 110 | if ( opt("useStrict", false) ) { 111 | ast.body.unshift({ 112 | type: "ExpressionStatement", 113 | expression: { type: "Literal", value: "use strict" } 114 | }); 115 | } 116 | 117 | if ( opt("noSharedObjects", true) ) return clone(ast); 118 | return ast; 119 | } 120 | 121 | var bhelper = { 122 | blockStatement: function(body) { 123 | return builder.blockStatement(expandMultiStatements(body)); 124 | }, 125 | tempName: function() { 126 | return i("__lua$tmpvar$" + (++tmpVarCtr)); 127 | }, 128 | tempVar: function(exp) { 129 | return { type: "VariableDeclarator", id: bhelper.tempName(), init: exp }; 130 | }, 131 | assign: function(target, exp) { 132 | var out = builder.assignmentExpression("=", target, exp); 133 | if ( target.type == "MemberExpression" && opt("luaOperators", false) ) { 134 | var prop = target.property; 135 | if ( !target.computed ) prop = {"type": "Literal", "value": prop.name, loc: prop.loc, range: prop.range }; 136 | 137 | var helper; 138 | var nue = bhelper.translateExpressionIfNeeded(target.object); 139 | 140 | if ( target.object.type == "Identifier" ) helper = target.object.name; 141 | 142 | if ( helper === undefined ) { 143 | nue = bhelper.luaOperator("indexAssign", nue, prop, exp); 144 | } else { 145 | nue = bhelper.luaOperator("indexAssign", nue, prop, exp, {type:"Literal", value: helper}); 146 | } 147 | 148 | out = nue; 149 | } 150 | 151 | return { 152 | type: "ExpressionStatement", 153 | expression: out 154 | }; 155 | }, 156 | encloseDecls: function(body /*, decls...*/) { 157 | var decls = Array.prototype.slice.call(arguments, 1); 158 | return bhelper.encloseDeclsEx.apply(this, [body, opt("encloseWithFunctions", true) ].concat(decls)); 159 | }, 160 | encloseDeclsEx: function(body, enclose /*, decls...*/) { 161 | var decls = Array.prototype.slice.call(arguments, 2); 162 | var vals = []; 163 | var names = []; 164 | for ( var k in decls ) { 165 | var v = decls[k]; 166 | vals.push(v.init); 167 | names.push(v.id); 168 | } 169 | 170 | if ( enclose ) { 171 | return { 172 | expression: builder.callExpression( 173 | builder.functionExpression(null, names, bhelper.blockStatement(body)), 174 | vals 175 | ), 176 | type: "ExpressionStatement" 177 | } 178 | } else { 179 | if ( decls.length < 1 ) return body; 180 | return bhelper.blockStatement([ builder.variableDeclaration("let", decls) ].concat(body)); 181 | } 182 | }, 183 | encloseDeclsUnpack: function(body, names, explist, force) { 184 | 185 | if ( force || opt("encloseWithFunctions", true) ) { 186 | return { 187 | expression: builder.callExpression( 188 | builder.memberExpression( 189 | builder.functionExpression(null, names, builder.blockStatement(body)), 190 | i("apply") 191 | ), 192 | [{type: "Literal", value: null}, bhelper.luaOperatorA("expandArgList", explist)] 193 | ), 194 | type: "ExpressionStatement" 195 | } 196 | } else { 197 | var decls = []; 198 | for ( var idx in names ) { 199 | decls.push({ 200 | type: "VariableDeclarator", 201 | id: names[idx], 202 | init: idx.id 203 | }); 204 | } 205 | return bhelper.blockStatement([ 206 | builder.variableDeclaration("let", decls), 207 | bhelper.bulkAssign(names, explist) 208 | ].concat(body)); 209 | } 210 | }, 211 | bulkAssign: function(names, explist) { 212 | var temps = []; 213 | var body = []; 214 | for ( var i = 0; i < names.length; ++i ) { 215 | temps[i] = bhelper.tempName(); 216 | } 217 | 218 | // If we are refrencing a previously set value in a bulk assign as a property 219 | // we want to use the old value to look up the index, so we will pull that from 220 | // the temp var passed in 221 | var extra = 0; 222 | for ( var i = 0; i < names.length; ++i ) { 223 | var exp = names[i]; 224 | if ( exp.type == "MemberExpression" && exp.property.type == "Identifier" ) { 225 | for ( var j = 0; j < i; ++j) { 226 | if ( names[j].name == exp.property.name ) { 227 | var holding = bhelper.tempName(); 228 | temps.unshift(holding); 229 | explist.unshift(exp.property); 230 | exp.property = holding; 231 | ++extra; 232 | } 233 | } 234 | } 235 | } 236 | 237 | for ( var i = 0; i < names.length; ++i ) { 238 | body[i] = bhelper.assign(names[i], temps[i+extra]); 239 | } 240 | 241 | if ( names.length > 1 ) { 242 | return bhelper.encloseDeclsUnpack(body, temps, explist, true); 243 | } else { 244 | var value = explist[0]; 245 | if ( value.type == "CallExpression" ) value = bhelper.luaOperator("oneValue", value); 246 | return bhelper.assign(names[0], value); 247 | } 248 | 249 | }, 250 | luaOperator: function(op /*, args */) { 251 | var o = builder.callExpression( 252 | builder.memberExpression(i("__lua"), i(op)), 253 | Array.prototype.slice.call(arguments, 1) 254 | ); 255 | o.internal = true; 256 | return o; 257 | }, 258 | luaOperatorA: function(op, args) { 259 | var o = builder.callExpression( 260 | builder.memberExpression(i("__lua"), i(op)), 261 | args 262 | ); 263 | o.internal = true; 264 | return o; 265 | }, 266 | binaryExpression: function(op, a, b) { 267 | if ( opt("luaOperators", false) && op != "and" && op != "or" ) { 268 | var map = {"+": "add", "-": "sub", "*": "mul", "/": "div", "//": "intdiv", "^": "pow", "%":"mod", 269 | "..": "concat", "==": "eq", "<": "lt", "<=": "lte", ">": "gt", ">=": "gte", "~=": "ne", 270 | "and": "and", "or": "or" 271 | }; 272 | 273 | return bhelper.luaOperator(map[op], a, b); 274 | } else { 275 | if ( op == "~=" ) op = "!="; 276 | else if ( op == ".." ) op = "+"; 277 | else if ( op == "or" ) op = "||"; 278 | else if ( op == "and" ) op = "&&"; 279 | else if ( op == "//" ) op = "/"; 280 | 281 | a = bhelper.luaOperator("oneValue", a); 282 | b = bhelper.luaOperator("oneValue", b); 283 | 284 | return builder.binaryExpression(op, a, b); 285 | } 286 | }, 287 | callExpression: function(callee, args) { 288 | if ( opt("luaCalls", false) ) { 289 | var that = {"type": "ThisExpression" }; 290 | if ( callee.type == "MemberExpression" ) that = {"type":"Literal", "value": null}; 291 | var flags = 0; 292 | if ( callee.selfSuggar ) { 293 | flags = flags | 1; 294 | } 295 | 296 | if ( opt('decorateLuaObjects', false) ) { 297 | flags = flags | 2; 298 | } 299 | 300 | var flagso = {"type": "Literal", "value": flags}; 301 | var helper = null; 302 | 303 | if ( callee.type == "Identifier" ) helper = callee.name; 304 | else if ( callee.type == "MemberExpression" && !callee.computed ) helper = callee.property.name; 305 | 306 | helper = {"type": "Literal", "value": helper}; 307 | 308 | if ( callee.selfSuggar ) { 309 | if ( callee.object.type == "Identifier" ) { 310 | //Dont bother making a function if we are just an identifer. 311 | var rcallee = bhelper.translateExpressionIfNeeded(callee) 312 | return bhelper.luaOperator.apply(bhelper, ["call", flagso , rcallee, callee.object, helper].concat(args)); 313 | 314 | } else { 315 | var tmp = bhelper.tempVar(bhelper.translateExpressionIfNeeded(callee.object)); 316 | 317 | var rexpr = builder.memberExpression(tmp.id, callee.property, callee.computed); 318 | var rcallee = bhelper.translateExpressionIfNeeded(rexpr); 319 | var expr = bhelper.luaOperator.apply(bhelper, ["call", flagso, rcallee, tmp.id, helper].concat(args)); 320 | return bhelper.encloseDeclsEx([ 321 | builder.returnStatement( 322 | expr 323 | ) 324 | ], true, tmp).expression; 325 | 326 | } 327 | } else { 328 | var rcallee = bhelper.translateExpressionIfNeeded(callee) 329 | if ( rcallee.type == "Identifier" && rcallee.name == "assert" ) { 330 | args.push({type: "Literal", value: args[0].text || "?"}) 331 | } 332 | return bhelper.luaOperator.apply(bhelper, ["call", flagso , rcallee, that, helper].concat(args)); 333 | } 334 | } else { 335 | return builder.callExpression(callee, args); 336 | } 337 | }, 338 | memberExpression: function(obj, prop, isComputed) { 339 | if ( opt("luaOperators", false) && !isComputed ) { 340 | var helper; 341 | if ( obj.type == "Identifier") helper = obj.name; 342 | 343 | if ( helper == undefined ) { 344 | return bhelper.luaOperator("index", obj, prop); 345 | } else { 346 | return bhelper.luaOperator("index", obj, prop, {type:"Literal", value: helper}); 347 | } 348 | } 349 | return builder.memberExpression(obj, prop, isComputed); 350 | }, 351 | translateExpressionIfNeeded: function(exp) { 352 | if ( !opt("luaOperators", false) ) return exp; 353 | if ( exp.type == "MemberExpression" ) { 354 | var prop = exp.property; 355 | if ( !exp.computed ) prop = {"type": "Literal", value: prop.name }; 356 | var nu = bhelper.memberExpression(bhelper.translateExpressionIfNeeded(exp.object), prop, false); 357 | nu.origional = exp; 358 | nu.loc = exp.loc; 359 | return nu; 360 | } 361 | 362 | return exp; 363 | }, 364 | injectRest: function(block, count) { 365 | block.unshift(builder.variableDeclaration("let", [ 366 | { 367 | type: "VariableDeclarator", 368 | id: {type: "Identifier", name:"__lua$rest"}, 369 | init: bhelper.luaOperator("rest", 370 | {type: "Identifier", name:"arguments"}, 371 | {type: "Literal", value:count} 372 | ) 373 | } 374 | ])); 375 | }, 376 | valueProvdier: function(statement) { 377 | return builder.functionExpression(null, [], bhelper.blockStatement([ 378 | builder.returnStatement(statement) 379 | ])); 380 | } 381 | } 382 | 383 | } 384 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var peg = require("pegjs"); 2 | var gen = require("escodegen"); 3 | var fs = require("fs"); 4 | var vm = require("vm"); 5 | 6 | var helpers = fs.readFileSync("helpers.js").toString(); 7 | var lang = fs.readFileSync("lua.pegjs").toString(); 8 | var parser = peg.buildParser(helpers + lang); 9 | 10 | 11 | var AST; 12 | try { 13 | AST = parser.parse(fs.readFileSync(process.argv[2]).toString(), {forceVar: true, decorateLuaObjects: true, luaCalls: true, luaOperators: true }); 14 | } catch ( e ) { 15 | console.dir(e); 16 | return; 17 | } 18 | 19 | var src = "(function() " + gen.generate(AST) + "())"; 20 | 21 | console.log(src); 22 | 23 | vm.runInNewContext(src, require('./public/stdlib.js'), "vm"); 24 | -------------------------------------------------------------------------------- /lua-lltk/assign-hazard-1.lua: -------------------------------------------------------------------------------- 1 | local t = {3, 7} 2 | local i = #t + 1 3 | t[i], t = 5, 11 4 | print(t) 5 | 6 | -------------------------------------------------------------------------------- /lua-lltk/assign-hazard-2.lua: -------------------------------------------------------------------------------- 1 | local t = {3, 7} 2 | local i = #t + 1 3 | t[i], i = 5, 11 4 | print(t[1], t[2], t[3], i) 5 | 6 | -------------------------------------------------------------------------------- /lua-lltk/closure-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | local a, b, c 3 | local function boo(z) 4 | a, b = z*z + 1, z - 1 5 | end 6 | boo(x * y - x + y) 7 | c = x + y 8 | return a * b * c 9 | end 10 | 11 | print(foo(3, 7)) -------------------------------------------------------------------------------- /lua-lltk/closure-3.lua: -------------------------------------------------------------------------------- 1 | local function foo(n) 2 | local f 3 | for k = n, n + 10 do 4 | if k % 7 == 0 then 5 | f = function(x) return k + x end 6 | break 7 | end 8 | end 9 | return f 10 | end 11 | 12 | local f = foo(1) 13 | print(f(3)) 14 | -------------------------------------------------------------------------------- /lua-lltk/closure-3b.lua: -------------------------------------------------------------------------------- 1 | 2 | local function foo(n) 3 | local f 4 | local s = 0 5 | for k = 1, n do 6 | local ksq, kc, kq = k*k, k^3, k^4 7 | if k % 7 == 0 then 8 | local kq = k/7 + 1 9 | f = function(x) return x + k end 10 | return f 11 | end 12 | local kadd = kc - kq 13 | s = s + kadd 14 | end 15 | return f 16 | end 17 | 18 | local f = foo(10) 19 | print(f(3)) 20 | -------------------------------------------------------------------------------- /lua-lltk/concatenate-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, flag) 2 | return a .. (flag and 'boom' or 'pst') 3 | end 4 | 5 | print(foo('ciao', true), foo('ciao', false)) -------------------------------------------------------------------------------- /lua-lltk/concatenate-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, b, c) 2 | return a .. b .. c 3 | end 4 | 5 | print(foo('ciao', 'ciccio', 'boum')) 6 | -------------------------------------------------------------------------------- /lua-lltk/expr-bracket-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(x) 2 | return x, x + 1, 2*x 3 | end 4 | 5 | local function prova(...) 6 | return ... 7 | end 8 | 9 | local function one(...) 10 | return (...) 11 | end 12 | 13 | local function single_value(x) 14 | return (foo(x)) 15 | end 16 | 17 | local function alls(x) 18 | return foo(x) 19 | end 20 | 21 | print(foo(2)) 22 | print( (foo(2)) ) 23 | 24 | print(alls(foo(2))) 25 | print(single_value(foo(2))) 26 | 27 | print( one(foo(2)) ) 28 | 29 | print( prova(foo(2)) ) 30 | -------------------------------------------------------------------------------- /lua-lltk/expr-logical-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | return x < y and x*x or y*y 3 | end 4 | 5 | local x, y = 3, 7 6 | print(foo(x, y)) 7 | -------------------------------------------------------------------------------- /lua-lltk/expr-logical-2.lua: -------------------------------------------------------------------------------- 1 | local function boo(a, b) 2 | if b then return a else return a + 1 end 3 | end 4 | 5 | local function foo(x, y) 6 | local z = x + y 7 | return boo(z, x < y and x or y) 8 | end 9 | 10 | print(foo(3, 7)) 11 | -------------------------------------------------------------------------------- /lua-lltk/expr-logical-3.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | return (x < y and x*x or y*y) + 2*x*y + 7 3 | end 4 | 5 | print(foo(3, 7), foo(7, 3)) 6 | -------------------------------------------------------------------------------- /lua-lltk/expr-return-1.lua: -------------------------------------------------------------------------------- 1 | local function f1(x, y, z) 2 | return y 3 | end 4 | 5 | local function f2(x, y, z) 6 | return x, y, z 7 | end 8 | 9 | local function f3(x, y, z) 10 | return x + y + z 11 | end 12 | 13 | local u = 7 14 | local function f4(x) 15 | return x + u 16 | end 17 | 18 | local function f5(x) 19 | return u 20 | end 21 | 22 | local a, b, c = 3, 5, 21 23 | print(f1(a, b, c)) 24 | print(f2(a, b, c)) 25 | print(f3(a, b, c)) 26 | print(f4(a)) 27 | print(f5(a)) 28 | -------------------------------------------------------------------------------- /lua-lltk/expr-var-return-1.lua: -------------------------------------------------------------------------------- 1 | local function multi(...) 2 | return ... 3 | end 4 | 5 | local function onearg1(x, ...) 6 | print("onearg1", x) 7 | return x, ... 8 | end 9 | 10 | local function onearg2(x, ...) 11 | print("onearg2", x) 12 | return ... 13 | end 14 | 15 | local a, b, c = 3, 7, 21 16 | print(multi(a, b, c)) 17 | print(onearg1(a, b, c)) 18 | print(onearg2(a, b, c)) 19 | -------------------------------------------------------------------------------- /lua-lltk/for-statement-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(n) 2 | local sum = 0 3 | for i = 1, n do 4 | sum = sum + i*i 5 | end 6 | return sum 7 | end 8 | 9 | print(foo(10)) 10 | -------------------------------------------------------------------------------- /lua-lltk/for-statement-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(n) 2 | local sum = 0 3 | for i = n, n*n+n, n+1 do 4 | sum = sum + i*i 5 | end 6 | return sum 7 | end 8 | 9 | print(foo(10)) 10 | -------------------------------------------------------------------------------- /lua-lltk/for-statement-4.lua: -------------------------------------------------------------------------------- 1 | local foo = function() 2 | return 4 3 | end 4 | 5 | for i = 1, foo() do 6 | print("A", i) 7 | end 8 | 9 | for i = 1, 4 do 10 | print("B", i) 11 | end 12 | -------------------------------------------------------------------------------- /lua-lltk/forin-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(ls) 2 | local sum = 0 3 | for i, v in ipairs(ls) do 4 | sum = sum + v*v 5 | end 6 | return sum 7 | end 8 | 9 | print(foo {1, 3, 7, 12}) 10 | -------------------------------------------------------------------------------- /lua-lltk/forin-2.lua: -------------------------------------------------------------------------------- 1 | local function squares_iter(ls, i) 2 | if i + 1 <= #ls then 3 | local v = ls[i + 1] 4 | return i + 1, v, v*v 5 | end 6 | end 7 | 8 | local function squares(ls) 9 | return squares_iter, ls, 0 10 | end 11 | 12 | local function foo(ls) 13 | local s, ssq = 0, 0 14 | for i, v, vsq in squares(ls) do 15 | s = s + v 16 | ssq = ssq + vsq 17 | end 18 | return s, ssq 19 | end 20 | 21 | print(foo {3, 7, -2, 5}) 22 | -------------------------------------------------------------------------------- /lua-lltk/forin-4.lua: -------------------------------------------------------------------------------- 1 | -- Use a very weak pseudo-number generator just for testing purpose. 2 | local function my_random(s) 3 | s.x = (16807 * s.x) % 2147483647 4 | return s.x 5 | end 6 | 7 | local function my_iter(s, i) 8 | if i < 20 then return i + 1, my_random(s) end 9 | end 10 | 11 | local function foo() 12 | local s = { x = 13 } 13 | for i, value in my_iter, s, 0 do 14 | print(i, value) 15 | end 16 | end 17 | 18 | foo() 19 | -------------------------------------------------------------------------------- /lua-lltk/func-assign-1.lua: -------------------------------------------------------------------------------- 1 | local a, b = 3, 7 2 | 3 | local function foo(k) 4 | return 2*k + 1 5 | end 6 | 7 | print(foo(a)) 8 | -------------------------------------------------------------------------------- /lua-lltk/func-assign-2.lua: -------------------------------------------------------------------------------- 1 | local foo 2 | 3 | local function init(choice) 4 | if choice == 1 then 5 | function foo(x) 6 | return x*x + 1 7 | end 8 | else 9 | function foo(x) 10 | return x 11 | end 12 | end 13 | end 14 | 15 | init(1) 16 | print(foo(3)) 17 | -------------------------------------------------------------------------------- /lua-lltk/func-assign-3.lua: -------------------------------------------------------------------------------- 1 | local foo = function(k) return k*k+1 end 2 | print(foo(3)) 3 | -------------------------------------------------------------------------------- /lua-lltk/func-declaration-1.lua: -------------------------------------------------------------------------------- 1 | local foo = {} 2 | 3 | function foo.bar(x) 4 | return x*x + 1 5 | end 6 | 7 | print(foo.bar(4)) 8 | -------------------------------------------------------------------------------- /lua-lltk/func-empty-1.lua: -------------------------------------------------------------------------------- 1 | local function func() 2 | end 3 | 4 | print(".", func(), ".") 5 | 6 | -------------------------------------------------------------------------------- /lua-lltk/func-vararg-1.lua: -------------------------------------------------------------------------------- 1 | local format = string.format 2 | 3 | local function printf(fmt, ...) 4 | print(format(fmt, ...)) 5 | end 6 | 7 | local name = "Ciccio" 8 | printf("Ciao %s, come stai ?", name) 9 | local a, b = 3.25, 225 10 | printf("Some numbers, float: %g, integer: %i", a, b) 11 | 12 | -------------------------------------------------------------------------------- /lua-lltk/function-rec.lua: -------------------------------------------------------------------------------- 1 | local function fact(n) 2 | if n <= 1 then 3 | return 1 4 | else 5 | return n * fact(n-1) 6 | end 7 | end 8 | 9 | print(fact(5)) 10 | -------------------------------------------------------------------------------- /lua-lltk/function-tailrec.lua: -------------------------------------------------------------------------------- 1 | local function fact(n, accu) 2 | if n <= 1 then 3 | return accu 4 | else 5 | return fact(n - 1, n * accu) 6 | end 7 | end 8 | 9 | print(fact(5, 1)) 10 | -------------------------------------------------------------------------------- /lua-lltk/if-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if x < y then 3 | return x + y 4 | else 5 | return x - y 6 | end 7 | end 8 | 9 | print(foo(3,7), foo(7,3)) 10 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, b) 2 | local x 3 | if a < b then x = 0 end 4 | if a > b then x = 1 end 5 | if a <= b then x = 2 end 6 | if a >= b then x = 3 end 7 | if a == b then x = 4 end 8 | if a ~= b then x = 5 end 9 | if not (a < b) then x = 6 end 10 | return x 11 | end 12 | 13 | local x, y = 7, 3 14 | print(foo(x, y), foo(y, x), foo(x, x)) 15 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, b) 2 | if 2 * a + b then print('boom') end 3 | end 4 | 5 | local x, y = 7, 3 6 | foo(x, y) 7 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-3.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | local a = (x < y) and (x*x < y*y) 3 | return a 4 | end 5 | 6 | print(foo(3, 7), foo(7, 3)) 7 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-3b.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if (x < y) and (x*x < y*y) then 3 | print('boom') 4 | end 5 | end 6 | 7 | local x, y = 3, 7 8 | foo(x, y) 9 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-3c.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if (x < y) or (x*x < y*y) then 3 | print('boom') 4 | end 5 | end 6 | 7 | local x, y = 3, 7 8 | foo(x, y) 9 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-3d.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | local c = (x < y) 3 | return c 4 | end 5 | 6 | local x, y = 3, 7 7 | print(foo(x, y)) 8 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-4.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, b) 2 | return not (a + b) 3 | end 4 | 5 | local x, y = 7, 3 6 | print(foo(x, y), foo(y, x)) 7 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-4b.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, b) 2 | return not (a < b) 3 | end 4 | 5 | local x, y = 7, 3 6 | print(foo(x, y), foo(y, x)) 7 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-5.lua: -------------------------------------------------------------------------------- 1 | local pi = 3.14 2 | 3 | local jit = nil 4 | if jit and jit.status then 5 | print("JIT!") 6 | end 7 | 8 | print(pi) 9 | -------------------------------------------------------------------------------- /lua-lltk/logical-tests-6.lua: -------------------------------------------------------------------------------- 1 | local function foo(a, b, c, d) 2 | a = a or 1 3 | b = b + 2*d + c 4 | c = c + 1 5 | return a + b*c + 2*d 6 | end 7 | 8 | local sum = 0 9 | for k = 1, 400 do 10 | sum = sum + foo(k, -2, 3, k + 1) 11 | end 12 | print(sum) 13 | 14 | -------------------------------------------------------------------------------- /lua-lltk/logical-value-1.lua: -------------------------------------------------------------------------------- 1 | local function foo1(x, y) 2 | return x < y and x + y 3 | end 4 | 5 | local function foo1bis(x, y, somef) 6 | return x < y and somef(x, y) 7 | end 8 | 9 | local function foo2(x, y) 10 | return x < y and x == y 11 | end 12 | 13 | local function foo3(x, y) 14 | return x < y or x - y 15 | end 16 | 17 | local function foo4(x, y) 18 | return x < y or x == y 19 | end 20 | 21 | local function diff(a, b) return a - b end 22 | 23 | local x, y = 3, 7 24 | print(foo1(x, y), foo1(y, x)) 25 | print(foo1bis(x, y, diff), foo1bis(y, x, diff)) 26 | print(foo2(x, y), foo2(y, x)) 27 | print(foo3(x, y), foo3(y, x)) 28 | print(foo4(x, y), foo4(y, x)) -------------------------------------------------------------------------------- /lua-lltk/logical-value-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if x < y and x == y then 3 | return x 4 | else 5 | return y 6 | end 7 | end 8 | 9 | local function boo(x, y) 10 | if x < y or x == y then 11 | return x 12 | else 13 | return y 14 | end 15 | end 16 | 17 | local x, y = 3, 7 18 | print(foo(x, y), foo(y, x)) 19 | print(boo(x, y), boo(y, x)) 20 | -------------------------------------------------------------------------------- /lua-lltk/mixed-assign-1.lua: -------------------------------------------------------------------------------- 1 | local x = {} 2 | for k = 1, 10 do 3 | k, x[k] = k + 1, k*k + 1 4 | end 5 | print(x[1], x[2], x[3]) 6 | -------------------------------------------------------------------------------- /lua-lltk/mixed-assign-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(k) 2 | return k*k, 2*k + 1 3 | end 4 | 5 | local x = 3 6 | local a, b, c 7 | a, b, c = 13, foo(x) 8 | print(a, b, c) 9 | -------------------------------------------------------------------------------- /lua-lltk/mixed-assign-3.lua: -------------------------------------------------------------------------------- 1 | local function foo(k) 2 | return k*k, 2*k + 1 3 | end 4 | 5 | local a, b 6 | a, b = 13, foo(3) 7 | print(a, b) 8 | -------------------------------------------------------------------------------- /lua-lltk/multi-assign-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(k) 2 | return k, k*k, 2*k + 1 3 | end 4 | 5 | local x = 3 6 | local a, b, c = foo(x) 7 | print(a, b, c) -------------------------------------------------------------------------------- /lua-lltk/multi-assign-2b.lua: -------------------------------------------------------------------------------- 1 | local function foo(v, i) 2 | v.f[i+1], v.x, v.s[i] = i*i, i+5, 7*i 3 | end 4 | 5 | local v = { } 6 | v.f, v.s, ciao = v, v, 'ciccio' 7 | foo(v, 1) 8 | print(#v, v[1], v[2]) 9 | -------------------------------------------------------------------------------- /lua-lltk/multi-call-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(k) 2 | return k, k*k, 2*k + 1 3 | end 4 | 5 | print(foo(3)) 6 | -------------------------------------------------------------------------------- /lua-lltk/multi-call-2.lua: -------------------------------------------------------------------------------- 1 | local format = string.format 2 | 3 | local function printf(...) 4 | print(format(...)) 5 | end 6 | 7 | printf("%s %d", 'ciccio', 124) 8 | -------------------------------------------------------------------------------- /lua-lltk/multi-returns-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(k) 2 | return k, k*k, 2*k+1 3 | end 4 | 5 | local function give(n) 6 | local k = 3*n + 2 7 | return foo(k) 8 | end 9 | 10 | print(give(5)) 11 | -------------------------------------------------------------------------------- /lua-lltk/nested-ifs-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if x < y then 3 | if x*x < y*y then 4 | return x*x 5 | else 6 | return y*y 7 | end 8 | else 9 | return x + y 10 | end 11 | end 12 | 13 | print(foo(3, 4), foo(4, 3)) 14 | -------------------------------------------------------------------------------- /lua-lltk/nested-ifs-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if x < y then 3 | if x*x < y*y then 4 | return x*x 5 | else 6 | return y*y 7 | end 8 | else 9 | if x + y < x - y then 10 | return x 11 | else 12 | return y 13 | end 14 | end 15 | end 16 | 17 | print(foo(3, 4), foo(4, 3)) 18 | -------------------------------------------------------------------------------- /lua-lltk/nested-ifs-3.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if x < y then 3 | if x*x < y*y then 4 | if x + y < x - y then 5 | return x 6 | else 7 | return y 8 | end 9 | else 10 | return y*y 11 | end 12 | else 13 | return x + y 14 | end 15 | end 16 | 17 | print(foo(3, 4), foo(4, 3)) 18 | -------------------------------------------------------------------------------- /lua-lltk/nested-ifs-4.lua: -------------------------------------------------------------------------------- 1 | local function foo(x, y) 2 | if x < y then 3 | return x + y 4 | elseif x + y < x - y then 5 | return x - y 6 | elseif x * y < x / y then 7 | return x * y 8 | else 9 | return x / y 10 | end 11 | end 12 | 13 | print(string.format("%f\t%f", foo(3, 4), foo(4, 3))) 14 | -------------------------------------------------------------------------------- /lua-lltk/not-operator-1.lua: -------------------------------------------------------------------------------- 1 | print((not true) and 10) 2 | -------------------------------------------------------------------------------- /lua-lltk/not-operator-2.lua: -------------------------------------------------------------------------------- 1 | print((not true) and 10, (not false) and 10, (not true) or 10, (not false) or 10) 2 | -------------------------------------------------------------------------------- /lua-lltk/not-operator-3.lua: -------------------------------------------------------------------------------- 1 | local a = (7 % 2 == 1) 2 | local b = (8 % 2 == 1) 3 | print(not a, (not a) and 10, (not a) or 10) 4 | print(not b, (not b) and 10, (not b) or 10) 5 | -------------------------------------------------------------------------------- /lua-lltk/not-operator-4.lua: -------------------------------------------------------------------------------- 1 | local a = (7 % 2 == 1) 2 | local b = (8 % 2 == 1) 3 | local c = (9 % 2 == 1) 4 | 5 | if not a then print("a") else print("b") end 6 | if not a and 10 then print("a") else print("b") end 7 | if not a or 10 then print("a") else print("b") end 8 | 9 | if not b then print("a") else print("b") end 10 | if not b and 10 then print("a") else print("b") end 11 | if not b or 10 then print("a") else print("b") end 12 | 13 | if (not a) and b or c then print("a") else print("b") end 14 | if (not a) and (not b or c) or c then print("a") else print("b") end 15 | if (not a or c) and not b or c then print("a") else print("b") end 16 | 17 | if (not b) and a or b then print("a") else print("b") end 18 | if (not b) and (not c or b) or b then print("a") else print("b") end 19 | if (not b or a) and not c or b then print("a") else print("b") end 20 | -------------------------------------------------------------------------------- /lua-lltk/printf-1.lua: -------------------------------------------------------------------------------- 1 | 2 | local s1 = "Hello" 3 | local s2 = "Ciccio" 4 | 5 | local format = string.format 6 | 7 | local some_table = { pi = 3.14 } 8 | 9 | local function printf(...) 10 | io.write(format(...)) 11 | end 12 | 13 | printf("I say: %s %s!\n", s1, s2) 14 | -------------------------------------------------------------------------------- /lua-lltk/rand-init.lua: -------------------------------------------------------------------------------- 1 | local function darray() return {} end 2 | local iarray = darray 3 | 4 | local rand, rand_init 5 | 6 | local jit = nil 7 | 8 | if jit and jit.status and jit.status() then 9 | -- LJ2 has bit operations and zero-based arrays (internally). 10 | local bit = require("bit") 11 | local band, sar = bit.band, bit.arshift 12 | function rand_init(seed) 13 | local Rm, Rj, Ri = iarray(17), 16, 11 14 | for i=0,16 do Rm[i] = 0 end 15 | for i=16,0,-1 do 16 | seed = band(seed*9069, 0x7fffffff) 17 | Rm[i] = seed 18 | end 19 | function rand() 20 | local i = band(Ri+1, sar(Ri-16, 31)) 21 | local j = band(Rj+1, sar(Rj-16, 31)) 22 | Ri, Rj = i, j 23 | local k = band(Rm[i] - Rm[j], 0x7fffffff) 24 | Rm[j] = k 25 | return k * (1.0/2147483647.0) 26 | end 27 | end 28 | else 29 | function rand_init(seed) 30 | local Rm, Rj = {}, 1 31 | for i=1,17 do Rm[i] = 0 end 32 | for i=17,1,-1 do 33 | seed = (seed*9069) % (2^31) 34 | Rm[i] = seed 35 | end 36 | function rand() 37 | local j, m = Rj, Rm 38 | local h = j - 5 39 | if h < 1 then h = h + 17 end 40 | local k = m[h] - m[j] 41 | if k < 0 then k = k + 2147483647 end 42 | m[j] = k 43 | if j < 17 then Rj = j + 1 else Rj = 1 end 44 | return k * (1.0/2147483647.0) 45 | end 46 | end 47 | end 48 | 49 | rand_init(15) 50 | for k = 1, 10 do 51 | print(string.format("%f", rand())) 52 | end 53 | -------------------------------------------------------------------------------- /lua-lltk/repeat-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(n) 2 | local i, sum = 1, 0 3 | repeat 4 | sum = sum + i*i 5 | i = i + 1 6 | until i > 10 7 | return sum 8 | end 9 | 10 | print(foo(10)) 11 | -------------------------------------------------------------------------------- /lua-lltk/repeat-test-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(n) 2 | local sum = 0 3 | local i = 1 4 | repeat 5 | sum = sum + i*i 6 | i = i + 1 7 | until i > n 8 | return sum 9 | end 10 | 11 | print(foo(20)) 12 | -------------------------------------------------------------------------------- /lua-lltk/repeat-test-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(n) 2 | local sum = 0 3 | local i = 1 4 | local test 5 | repeat 6 | sum = sum + i*i 7 | i = i + 1 8 | test = i > n and 1 9 | until test 10 | return sum 11 | end 12 | 13 | print(foo(20)) 14 | -------------------------------------------------------------------------------- /lua-lltk/send-epression-call-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(self, k) 2 | return k * self.value 3 | end 4 | 5 | local obj = { value = 3.141592, foo = foo } 6 | print(obj:foo(2)) 7 | -------------------------------------------------------------------------------- /lua-lltk/send-epression-call-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(self, k) 2 | return k * self.value 3 | end 4 | 5 | local function create_obj(x) 6 | return { value = x, foo = foo } 7 | end 8 | 9 | print(create_obj(3.141592):foo(2)) 10 | -------------------------------------------------------------------------------- /lua-lltk/string-escapes-1.lua: -------------------------------------------------------------------------------- 1 | print("foo\z bar") 2 | print("foo\z 3 | bar") 4 | print("foo\ 5 | bar") 6 | print("\97") 7 | print("\"\'\\") 8 | print("\x65") 9 | 10 | -------------------------------------------------------------------------------- /lua-lltk/struct-assign-1.lua: -------------------------------------------------------------------------------- 1 | local function init(x) 2 | return {name= 'foo', value = x*x} 3 | end 4 | 5 | local s = init(2.5) 6 | local v = s.value 7 | print(v) 8 | -------------------------------------------------------------------------------- /lua-lltk/table-1.lua: -------------------------------------------------------------------------------- 1 | local name = 'secret' 2 | local t = { pi = 3.14, ciao = 'Hello!', [name] = 'sshhhh....' } 3 | print(t.pi, t.ciao, t.secret) 4 | -------------------------------------------------------------------------------- /lua-lltk/table-2.lua: -------------------------------------------------------------------------------- 1 | local t = { pi = 3.14, ciao = 'hello', 3, 7, 'boo', 21 } 2 | print(t.pi, t[1], t[2], t[3], t[4]) 3 | -------------------------------------------------------------------------------- /lua-lltk/table-3.lua: -------------------------------------------------------------------------------- 1 | local x, y = 3, 4 2 | local t = {[y-x] = 1, [2*x-y] = 4, [x] = 9, [y] = 16, [2*y-x] = 25 } 3 | print(t[1], t[2], t[3], t[4], t[5]) 4 | -------------------------------------------------------------------------------- /lua-lltk/table-4.lua: -------------------------------------------------------------------------------- 1 | local t = { pi = 3.14, ciao = 'hello', 1, list = {3, 7, 'boum'}, 4, 9} 2 | print(t.pi, t[1], t[2], t[3], #t.list) 3 | -------------------------------------------------------------------------------- /lua-lltk/table-5.lua: -------------------------------------------------------------------------------- 1 | local t = {[0] = 7, 9, 14, 17} 2 | for k = 0, 3 do print(t[k]) end 3 | 4 | -------------------------------------------------------------------------------- /lua-lltk/test-1.lua: -------------------------------------------------------------------------------- 1 | local x = {} 2 | for k = 1, 10 do 3 | x[k] = k*k + 1 4 | end 5 | for k = 1, 10 do print(x[k]) end 6 | 7 | -------------------------------------------------------------------------------- /lua-lltk/test-2.lua: -------------------------------------------------------------------------------- 1 | local k = "foo" 2 | k = tonumber(k) and "foo" or k 3 | print("K", k) 4 | 5 | -------------------------------------------------------------------------------- /lua-lltk/test-3.lua: -------------------------------------------------------------------------------- 1 | local a, b = 3, 5 2 | local foo = {} 3 | 4 | foo.a, foo.b = a, b 5 | 6 | print(foo.a, foo.b) 7 | 8 | -------------------------------------------------------------------------------- /lua-lltk/test-4.lua: -------------------------------------------------------------------------------- 1 | local k = "foo" 2 | function some_f(s) return string.byte(s) end 3 | k = tonumber(k) or some_f(k) or k 4 | print("K", k) 5 | 6 | -------------------------------------------------------------------------------- /lua-lltk/test-5.lua: -------------------------------------------------------------------------------- 1 | local a 2 | a = a and 15 3 | local b 4 | b = b or 10 5 | print(a, b) 6 | 7 | 8 | -------------------------------------------------------------------------------- /lua-lltk/test-6.lua: -------------------------------------------------------------------------------- 1 | local a 2 | local b 3 | a = b or 12 4 | print(a, b) 5 | 6 | -------------------------------------------------------------------------------- /lua-lltk/test-7.lua: -------------------------------------------------------------------------------- 1 | local a 2 | a = "something" and ("'" .. type(a)) 3 | print(a) 4 | 5 | -------------------------------------------------------------------------------- /lua-lltk/test-8.lua: -------------------------------------------------------------------------------- 1 | local a 2 | a = nil or ("'" .. type(a)) 3 | print(a) 4 | 5 | -------------------------------------------------------------------------------- /lua-lltk/test-9.lua: -------------------------------------------------------------------------------- 1 | local a = 5 2 | a = (a > 10) or a+1 3 | print(a) 4 | -------------------------------------------------------------------------------- /lua-lltk/vararg-pack-1.lua: -------------------------------------------------------------------------------- 1 | local function foo(...) 2 | local arg = {...} 3 | for k = 1, #arg do 4 | print(arg[k]) 5 | end 6 | end 7 | 8 | foo("hello", "boy") 9 | 10 | -------------------------------------------------------------------------------- /lua-lltk/vararg-pack-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(msg, ...) 2 | local arg = {...} 3 | print(msg) 4 | for k = 1, #arg do 5 | print(arg[k]) 6 | end 7 | end 8 | 9 | foo("Hey!", "hello", "boy") 10 | 11 | -------------------------------------------------------------------------------- /lua-lltk/vararg-pack-3.lua: -------------------------------------------------------------------------------- 1 | local function foo(msg, ...) 2 | local arg = {"wait", "a", "moment", ...} 3 | print(msg) 4 | for k = 1, #arg do 5 | print(arg[k]) 6 | end 7 | end 8 | 9 | foo("Hey", "hello", "boy") 10 | 11 | -------------------------------------------------------------------------------- /lua-lltk/vararg-pack-4.lua: -------------------------------------------------------------------------------- 1 | local function foo(x) 2 | return x, 2*x, x^2-1 3 | end 4 | 5 | local function boo(x) 6 | local arg = { foo(x) } 7 | for k = 1, #arg do 8 | print(arg[k]) 9 | end 10 | end 11 | 12 | boo(7) 13 | 14 | -------------------------------------------------------------------------------- /lua-lltk/vararg-pack-5.lua: -------------------------------------------------------------------------------- 1 | local function foo(...) 2 | local arg = {..., "friend"} 3 | for k = 1, #arg do 4 | print(arg[k]) 5 | end 6 | end 7 | 8 | foo("hello", "boy") 9 | 10 | -------------------------------------------------------------------------------- /lua-lltk/while-loop-1.lua: -------------------------------------------------------------------------------- 1 | local sum = 0 2 | local i = 1 3 | while i < 10 do 4 | sum = sum + i*i 5 | i = i + 1 6 | end 7 | print(sum) 8 | -------------------------------------------------------------------------------- /lua-lltk/while-loop-2.lua: -------------------------------------------------------------------------------- 1 | local function foo(k) 2 | return k*k < 49 3 | end 4 | 5 | local sum = 0 6 | local i = 1 7 | while i < 10 and foo(i) do 8 | sum = sum + i*i 9 | i = i + 1 10 | end 11 | print(sum) 12 | -------------------------------------------------------------------------------- /lua-lltk/while-loop-2b.lua: -------------------------------------------------------------------------------- 1 | local sum = 0 2 | local i = 1 3 | while i < 10 and i*i < 49 do 4 | sum = sum + i*i 5 | i = i + 1 6 | end 7 | print(sum) 8 | -------------------------------------------------------------------------------- /lua-testmore/000-sanity.t: -------------------------------------------------------------------------------- 1 | #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua test suite 14 | 15 | =head2 Synopsis 16 | 17 | % prove 000-sanity.t 18 | 19 | =head2 Description 20 | 21 | =cut 22 | 23 | ]] 24 | 25 | function f (n) 26 | return n + 1 27 | end 28 | 29 | function g (m, p) 30 | return m + p 31 | end 32 | 33 | print('1..9') 34 | print("ok 1 -") 35 | print('ok', 2, "- list") 36 | print("ok " .. 3 .. " - concatenation") 37 | i = 4 38 | print("ok " .. i .. " - var") 39 | i = i + 1 40 | print("ok " .. i .. " - var incr") 41 | print("ok " .. i+1 .. " - expr") 42 | j = f(i + 1) 43 | print("ok " .. j .. " - call f") 44 | k = g(i, 3) 45 | print("ok " .. k .. " - call g") 46 | 47 | 48 | --[[ 49 | 50 | Requires let 51 | 52 | local print = print 53 | 54 | ]]-- 55 | 56 | print("ok 9 - local") 57 | 58 | -- Local Variables: 59 | -- mode: lua 60 | -- lua-indent-level: 4 61 | -- fill-column: 100 62 | -- End: 63 | -- vim: ft=lua expandtab shiftwidth=4: 64 | -------------------------------------------------------------------------------- /lua-testmore/001-if.t: -------------------------------------------------------------------------------- 1 | #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua if statement 14 | 15 | =head2 Synopsis 16 | 17 | % prove 001-if.t 18 | 19 | =head2 Description 20 | 21 | See "Lua 5.1 Reference Manual", section 2.4.4 "Control Structures", 22 | L. 23 | 24 | See "Programming in Lua", section 4.3 "Control Structures". 25 | 26 | =cut 27 | 28 | ]] 29 | 30 | print("1..6") 31 | 32 | if true then 33 | print("ok 1") 34 | else 35 | print("not ok 1") 36 | end 37 | 38 | if not true then 39 | print("not ok 2") 40 | else 41 | print("ok 2") 42 | end 43 | 44 | a = 12 45 | b = 34 46 | if a < b then 47 | print("ok 3") 48 | else 49 | print("not ok 3") 50 | end 51 | 52 | a = 0 53 | b = 4 54 | if a < b then 55 | print("ok 4") 56 | elseif a == b then 57 | print("not ok 4") 58 | else 59 | print("not ok 4") 60 | end 61 | 62 | a = 5 63 | b = 5 64 | if a < b then 65 | print("not ok 5") 66 | elseif a == b then 67 | print("ok 5") 68 | else 69 | print("not ok 5") 70 | end 71 | 72 | a = 10 73 | b = 6 74 | if a < b then 75 | print("not ok 6") 76 | elseif a == b then 77 | print("not ok 6") 78 | else 79 | print("ok 6") 80 | end 81 | 82 | -- Local Variables: 83 | -- mode: lua 84 | -- lua-indent-level: 4 85 | -- fill-column: 100 86 | -- End: 87 | -- vim: ft=lua expandtab shiftwidth=4: 88 | -------------------------------------------------------------------------------- /lua-testmore/002-table.t: -------------------------------------------------------------------------------- 1 | -- #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua table 14 | 15 | =head2 Synopsis 16 | 17 | % prove 002-table.t 18 | 19 | =head2 Description 20 | 21 | See "Programming in Lua", section 2.5 "Tables". 22 | 23 | =cut 24 | 25 | ]] 26 | 27 | print("1..8") 28 | 29 | a = {"ok 1", "ok 2", "ok 3"} 30 | print(a[1]) 31 | i = 2 32 | print(a[i]) 33 | print(a[i+1]) 34 | if #a == 3 then 35 | print("ok 4 - len") 36 | else 37 | print("not ok 4") 38 | end 39 | if a[7] == nil then 40 | print("ok 5") 41 | else 42 | print("not ok 5") 43 | end 44 | 45 | t = {a=10, b=100} 46 | if t['a'] == 10 then 47 | print("ok 6") 48 | else 49 | print("not ok 6") 50 | end 51 | if t.b == 100 then 52 | print("ok 7") 53 | else 54 | print("not ok 7") 55 | end 56 | if t.z == nil then 57 | print("ok 8") 58 | else 59 | print("not ok 8") 60 | end 61 | 62 | -- Local Variables: 63 | -- mode: lua 64 | -- lua-indent-level: 4 65 | -- fill-column: 100 66 | -- End: 67 | -- vim: ft=lua expandtab shiftwidth=4: 68 | -------------------------------------------------------------------------------- /lua-testmore/011-while.t: -------------------------------------------------------------------------------- 1 | -- #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua while statement 14 | 15 | =head2 Synopsis 16 | 17 | % prove 011-while.t 18 | 19 | =head2 Description 20 | 21 | See "Lua 5.1 Reference Manual", section 2.4.4 "Control Structures", 22 | L. 23 | 24 | See "Programming in Lua", section 4.3 "Control Structures". 25 | 26 | =cut 27 | 28 | ]] 29 | 30 | print("1..11") 31 | 32 | a = {} 33 | local i = 1 34 | while a[i] do 35 | i = i + 1 36 | end 37 | if i == 1 then 38 | print("ok 1 - while empty") 39 | else 40 | print("not ok 1 - " .. i) 41 | end 42 | 43 | a = {"ok 2 - while ", "ok 3", "ok 4"} 44 | local i = 1 45 | while a[i] do 46 | print(a[i]) 47 | i = i + 1 48 | end 49 | 50 | a = {"ok 5 - with break", "ok 6", "stop", "more"} 51 | local i = 1 52 | while a[i] do 53 | if a[i] == 'stop' then break end 54 | print(a[i]) 55 | i = i + 1 56 | end 57 | if i == 3 then 58 | print("ok 7 - break") 59 | else 60 | print("not ok 7 - " .. i) 61 | end 62 | 63 | x = 3 64 | local i = 1 65 | while i<=x do 66 | print("ok " .. 7+i) 67 | i = i + 1 68 | end 69 | if i == 4 then 70 | print("ok 11") 71 | else 72 | print("not ok 11 - " .. i) 73 | end 74 | 75 | -- Local Variables: 76 | -- mode: lua 77 | -- lua-indent-level: 4 78 | -- fill-column: 100 79 | -- End: 80 | -- vim: ft=lua expandtab shiftwidth=4: 81 | -------------------------------------------------------------------------------- /lua-testmore/012-repeat.t: -------------------------------------------------------------------------------- 1 | -- #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua repeat statement 14 | 15 | =head2 Synopsis 16 | 17 | % prove 012-repeat.t 18 | 19 | =head2 Description 20 | 21 | See "Lua 5.1 Reference Manual", section 2.4.4 "Control Structures", 22 | L. 23 | 24 | See "Programming in Lua", section 4.3 "Control Structures". 25 | 26 | =cut 27 | 28 | ]] 29 | 30 | print("1..7") 31 | 32 | a = {"ok 1 - repeat", "ok 2", "ok 3"} 33 | local i = 0 34 | repeat 35 | i = i + 1 36 | if a[i] then 37 | print(a[i]) 38 | end 39 | until not a[i] 40 | if i == 4 then 41 | print("ok 4") 42 | else 43 | print("not ok 4 - " .. i) 44 | end 45 | 46 | a = {"ok 5 - with break", "ok 6", 'stop', 'more'} 47 | local i = 0 48 | repeat 49 | i = i + 1 50 | if a[i] == 'stop' then break end 51 | print(a[i]) 52 | until not a[i] 53 | if a[i] == 'stop' then 54 | print("ok 7 - break") 55 | else 56 | print("not ok 7 - " .. a[i]) 57 | end 58 | 59 | -- Local Variables: 60 | -- mode: lua 61 | -- lua-indent-level: 4 62 | -- fill-column: 100 63 | -- End: 64 | -- vim: ft=lua expandtab shiftwidth=4: 65 | -------------------------------------------------------------------------------- /lua-testmore/014-fornum.t: -------------------------------------------------------------------------------- 1 | -- #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua for statement 14 | 15 | =head2 Synopsis 16 | 17 | % prove 014-fornum.t 18 | 19 | =head2 Description 20 | 21 | See "Lua 5.1 Reference Manual", section 2.4.5 "For Statement", 22 | L. 23 | 24 | See "Programming in Lua", section 4.3 "Control Structures". 25 | 26 | =cut 27 | 28 | --]] 29 | local jit = false 30 | 31 | print("1..36") 32 | 33 | for i = 1, 10, 2 do 34 | print("ok " .. (i+1)/2 .. " - for 1, 10, 2") 35 | end 36 | 37 | for i = 1, 10, 2 do 38 | function f () 39 | print("ok " .. (i+11)/2 .. " - for 1, 10, 2 lex") 40 | end 41 | f() 42 | end 43 | 44 | function f (i) 45 | print("ok " .. (i+21)/2 .. " - for 1, 10, 2 !lex") 46 | end 47 | for i = 1, 10, 2 do 48 | f(i) 49 | end 50 | 51 | for i = 3, 5 do 52 | print("ok " .. 13+i .. " - for 3, 5") 53 | i = i + 1 54 | end 55 | 56 | for i = 5, 1, -1 do 57 | print("ok " .. 24-i .. " - for 5, 1, -1") 58 | end 59 | 60 | for i = 5, 5 do 61 | print("ok " .. 19+i .. " - for 5, 5") 62 | end 63 | 64 | for i = 5, 5, -1 do 65 | print("ok " .. 20+i .. " - for 5, 5, -1") 66 | end 67 | 68 | v = false 69 | for i = 5, 3 do 70 | v = true 71 | end 72 | if v then 73 | print("not ok 26 - for 5, 3") 74 | else 75 | print("ok 26 - for 5, 3") 76 | end 77 | 78 | v = false 79 | for i = 5, 7, -1 do 80 | v = true 81 | end 82 | if v then 83 | print("not ok 27 - for 5, 7, -1") 84 | else 85 | print("ok 27 - for 5, 7, -1") 86 | end 87 | 88 | v = false 89 | for i = 5, 7, 0 do 90 | v = true 91 | break -- avoid infinite loop with LuaJIT 92 | end 93 | if jit then 94 | print("not ok 28 - for 5, 7, 0 # TODO # LuaJIT intentional.") 95 | elseif v then 96 | print("not ok 28 - for 5, 7, 0") 97 | else 98 | print("ok 28 - for 5, 7, 0") 99 | end 100 | 101 | v = nil 102 | for i = 1, 10, 2 do 103 | if i > 4 then break end 104 | print("ok " .. (i+57)/2 .. " - for break") 105 | v = i 106 | end 107 | if v == 3 then 108 | print("ok 31 - break") 109 | else 110 | print("not ok 31 - " .. v) 111 | end 112 | 113 | local function first() return 1 end 114 | local function limit() return 8 end 115 | local function step() return 2 end 116 | for i = first(), limit(), step() do 117 | print("ok " .. (i+63)/2 .. " - with functions") 118 | end 119 | 120 | 121 | 122 | --[[ 123 | 124 | Requires Var 125 | 126 | local a = {} 127 | for i = 1, 10 do 128 | a[i] = function () return i end 129 | end 130 | local v = a[5]() 131 | if v == 5 then 132 | print("ok 36 - for & upval") 133 | else 134 | print("not ok 36 - for & upval") 135 | print("#", v) 136 | end 137 | 138 | 139 | ]]-- 140 | 141 | -- Local Variables: 142 | -- mode: lua 143 | -- lua-indent-level: 4 144 | -- fill-column: 100 145 | -- End: 146 | -- vim: ft=lua expandtab shiftwidth=4: 147 | -------------------------------------------------------------------------------- /lua-testmore/015-forlist.t: -------------------------------------------------------------------------------- 1 | -- #! /usr/bin/lua 2 | -- 3 | -- lua-TestMore : 4 | -- 5 | -- Copyright (C) 2009, Perrad Francois 6 | -- 7 | -- This code is licensed under the terms of the MIT/X11 license, 8 | -- like Lua itself. 9 | -- 10 | 11 | --[[ 12 | 13 | =head1 Lua for statement 14 | 15 | =head2 Synopsis 16 | 17 | % prove 015-forlist.t 18 | 19 | =head2 Description 20 | 21 | See "Lua 5.1 Reference Manual", section 2.4.5 "For Statement", 22 | L. 23 | 24 | See "Programming in Lua", section 4.3 "Control Structures". 25 | 26 | =cut 27 | 28 | --]] 29 | 30 | print("1..18") 31 | 32 | a = {"ok 1 - for ipairs", "ok 2 - for ipairs", "ok 3 - for ipairs"} 33 | for _, v in ipairs(a) do 34 | print(v) 35 | end 36 | for i, v in ipairs(a) do 37 | print("ok " .. 3+i .. " - for ipairs") 38 | end 39 | 40 | r = false 41 | t = {a=10, b=100} 42 | for i, v in ipairs(t) do 43 | print(i, v) 44 | r = true 45 | end 46 | if r then 47 | print("not ok 7 - for ipairs (hash)") 48 | else 49 | print("ok 7 - for ipairs (hash)") 50 | end 51 | 52 | for k in pairs(a) do 53 | print("ok " .. 7+k .. " - for pairs") 54 | end 55 | 56 | local i = 1 57 | for k in pairs(t) do 58 | if k == 'a' or k == 'b' then 59 | print("ok " .. 10+i .. " - for pairs (hash)") 60 | else 61 | print("not ok " .. 10+i .. " - " .. k) 62 | end 63 | i = i + 1 64 | end 65 | 66 | a = {"ok 13 - for break", "ok 14 - for break", "stop", "more"} 67 | local i 68 | for _, v in ipairs(a) do 69 | if v == "stop" then break end 70 | print(v) 71 | i = _ 72 | end 73 | if i == 2 then 74 | print("ok 15 - break") 75 | else 76 | print("not ok 15 - " .. i) 77 | end 78 | 79 | 80 | --[[ 81 | 82 | Requires scoping 83 | 84 | local a = {"ok 16 - for & upval", "ok 17 - for & upval", "ok 18 - for & upval"} 85 | local b = {} 86 | for i, v in ipairs(a) do 87 | b[i] = function () return v end 88 | end 89 | for i, v in ipairs(a) do 90 | local r = b[i]() 91 | if r == a[i] then 92 | print(r) 93 | else 94 | print("not " .. a[i]) 95 | print("#", r) 96 | end 97 | end 98 | ]]-- 99 | 100 | -- Local Variables: 101 | -- mode: lua 102 | -- lua-indent-level: 4 103 | -- fill-column: 100 104 | -- End: 105 | -- vim: ft=lua expandtab shiftwidth=4: 106 | -------------------------------------------------------------------------------- /lua-tests/and-with-nil.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | function go() 5 | local a 6 | print(a and a.b) 7 | end 8 | 9 | local none, err = pcall(go) 10 | 11 | if err then print(err) else print("OK") end 12 | 13 | 14 | -------------------------------------------------------------------------------- /lua-tests/bisect.lua: -------------------------------------------------------------------------------- 1 | -- bisect.lua 2 | -- bisection method for solving non-linear equations 3 | 4 | -- With Parens Added =/ 5 | -- Global variables made local 6 | -- Trim function added for rounding 7 | 8 | local delta=1e-6 -- tolerance 9 | local n 10 | 11 | function trim(x) 12 | return ( math.floor(x * 1000000) ) / 1000000.0 13 | end 14 | 15 | function bisect(f,a,b,fa,fb) 16 | local c=(a+b)/2 17 | print(n," c=",trim(c)," a=",trim(a)," b=",trim(b),"\n") 18 | if (c==a) or (c==b) or ((math.abs(a-b)) < delta) then return c,b-a end 19 | n=n+1 20 | local fc=f(c) 21 | if (fa*fc)<0 then return bisect(f,a,c,fa,fc) else return bisect(f,c,b,fc,fb) end 22 | end 23 | 24 | -- find root of f in the inverval [a,b]. needs f(a)*f(b)<0 25 | function solve(f,a,b) 26 | n=0 27 | local z,e=bisect(f,a,b,f(a),f(b)) 28 | print(n,trim(z),trim(e),trim(f(z))) 29 | end 30 | 31 | -- our function 32 | function f(x) 33 | return ((x*x*x)-x)-1 34 | end 35 | 36 | -- find zero in [1,2] 37 | solve(f,1,2) 38 | -------------------------------------------------------------------------------- /lua-tests/bulk-assign.lua: -------------------------------------------------------------------------------- 1 | local function b() return 1,2,3 end 2 | local x, y, z = b(), b() 3 | 4 | print(x,y,z) 5 | 6 | x,y,w,z = b() 7 | 8 | print(x,z) 9 | 10 | x = b() 11 | print(x) -------------------------------------------------------------------------------- /lua-tests/closure.lua: -------------------------------------------------------------------------------- 1 | function muler(n) 2 | local amt = n+1 3 | return function(x) return x * amt end 4 | end 5 | 6 | local double = muler(1); 7 | print(double(3)) 8 | print(double(4)) 9 | 10 | 11 | -------------------------------------------------------------------------------- /lua-tests/complex.lua: -------------------------------------------------------------------------------- 1 | -- Complex 2 | -- from luajs.org 3 | 4 | local Complex 5 | Complex = { 6 | __add = function(a, b) 7 | return Complex.new(a.r+b.r, a.i+b.i) 8 | end, 9 | __mul = function(a, b) 10 | return Complex.new(a.r*b.r-a.i*b.i, a.r*b.i+a.i*b.r) 11 | end, 12 | __eq = function(a, b) 13 | return a.r == b.r and a.i == b.i 14 | end, 15 | __tostring = function(a) 16 | return "<"..a.r..","..a.i..">" 17 | end 18 | } 19 | 20 | Complex.new = function(r, i) 21 | local ret = {r=r, i=i} 22 | setmetatable(ret, Complex) 23 | return ret 24 | end 25 | 26 | local a = Complex.new(1, 0) 27 | local b = Complex.new(0, 1) 28 | 29 | print(a+b) 30 | print(a*b) 31 | print(a*b == b) 32 | -------------------------------------------------------------------------------- /lua-tests/count.lua: -------------------------------------------------------------------------------- 1 | local x = "tacos" 2 | print(#x) 3 | -------------------------------------------------------------------------------- /lua-tests/dotdotdot.lua: -------------------------------------------------------------------------------- 1 | function test(...) 2 | return {...} 3 | end 4 | 5 | x = test(1,2,3,4,5) 6 | -- y = {unpack({1,2,3,4,5}),7,8,9,unpack({10,11,12,13,14})} 7 | 8 | y = {1,2,3} 9 | 10 | print("X") 11 | for k,v in pairs(x) do print(k,v) end 12 | 13 | 14 | print() 15 | print("Y" ) 16 | for k,v in pairs(y) do print(k,v) end 17 | -------------------------------------------------------------------------------- /lua-tests/fib.lua: -------------------------------------------------------------------------------- 1 | -- From http://en.literateprograms.org/Fibonacci_numbers_(Lua) 2 | 3 | function fastfib(n) 4 | fibs={1,1} 5 | 6 | for i=3,n do 7 | fibs[i]=fibs[i-1]+fibs[i-2] 8 | end 9 | 10 | return fibs[n] 11 | end 12 | 13 | for i=10,30 do 14 | print('->', i, fastfib(i)) 15 | end -------------------------------------------------------------------------------- /lua-tests/hello.lua: -------------------------------------------------------------------------------- 1 | print "Hello World!" 2 | print "How are you?" 3 | 4 | i = 10 5 | repeat 6 | print("hi " .. i) 7 | i = i -1 8 | until i < 0 -------------------------------------------------------------------------------- /lua-tests/iter.lua: -------------------------------------------------------------------------------- 1 | function iter() 2 | return function(c, x) 3 | if (x ~= nil) and (x < 10) then return x + 1, x - 1 end 4 | return nil 5 | end, 1, 0 6 | 7 | end 8 | 9 | for k,v in iter() do 10 | print(k,v) 11 | end 12 | -------------------------------------------------------------------------------- /lua-tests/life.lua: -------------------------------------------------------------------------------- 1 | -- life.lua 2 | -- original by Dave Bollinger posted to lua-l 3 | -- modified to use ANSI terminal escape sequences 4 | -- modified to use for instead of while 5 | 6 | local write=print 7 | 8 | ALIVE="¥" DEAD="þ" 9 | ALIVE="O" DEAD="-" 10 | 11 | function delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary 12 | for i=1,10000 do end 13 | -- local i=os.clock()+1 while(os.clock() 0 do 42 | local xm1,x,xp1,xi=self.w-1,self.w,1,self.w 43 | while xi > 0 do 44 | local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] + 45 | self[y][xm1] + self[y][xp1] + 46 | self[yp1][xm1] + self[yp1][x] + self[yp1][xp1] 47 | next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0 48 | xm1,x,xp1,xi = x,xp1,xp1+1,xi-1 49 | end 50 | ym1,y,yp1,yi = y,yp1,yp1+1,yi-1 51 | end 52 | end 53 | 54 | -- output the array to screen 55 | function _CELLS:draw() 56 | local out="" -- accumulate to reduce flicker 57 | for y=1,self.h do 58 | for x=1,self.w do 59 | out=out..(((self[y][x]>0) and ALIVE) or DEAD) 60 | end 61 | out=out.."\n" 62 | end 63 | write(out) 64 | end 65 | 66 | -- constructor 67 | function CELLS(w,h) 68 | local c = ARRAY2D(w,h) 69 | c.spawn = _CELLS.spawn 70 | c.evolve = _CELLS.evolve 71 | c.draw = _CELLS.draw 72 | return c 73 | end 74 | 75 | -- 76 | -- shapes suitable for use with spawn() above 77 | -- 78 | HEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 } 79 | GLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 } 80 | EXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 } 81 | FISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 } 82 | BUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 } 83 | 84 | -- the main routine 85 | function LIFE(w,h) 86 | -- create two arrays 87 | local thisgen = CELLS(w,h) 88 | local nextgen = CELLS(w,h) 89 | 90 | -- create some life 91 | -- about 1000 generations of fun, then a glider steady-state 92 | thisgen:spawn(GLIDER,5,4) 93 | thisgen:spawn(EXPLODE,25,10) 94 | thisgen:spawn(FISH,4,12) 95 | 96 | -- run until break 97 | local gen=1 98 | write("\027[2J") -- ANSI clear screen 99 | while 1 do 100 | thisgen:evolve(nextgen) 101 | thisgen,nextgen = nextgen,thisgen 102 | write("\027[H") -- ANSI home cursor 103 | thisgen:draw() 104 | write("Life - generation ",gen,"\n") 105 | gen=gen+1 106 | if gen>20 then break end 107 | --delay() -- no delay 108 | end 109 | end 110 | 111 | LIFE(40,20) -------------------------------------------------------------------------------- /lua-tests/mt.lua: -------------------------------------------------------------------------------- 1 | local x = {value = 5} 2 | 3 | local mt = { 4 | __add = function (lhs, rhs) -- "add" event handler 5 | return lhs.value * rhs.value - 1 6 | end 7 | } 8 | 9 | setmetatable(x, mt) -- use "mt" as the metatable for "x" 10 | 11 | local y = x + x 12 | 13 | print(y) 14 | 15 | local func_example = setmetatable({}, {__index = function (t, k) 16 | return "key doesn't exist" 17 | end}) 18 | 19 | local fallback_tbl = setmetatable({ 20 | foo = "bar" 21 | }, {__index=func_example}) 22 | 23 | local fallback_example = setmetatable({}, {__index=fallback_tbl}) 24 | 25 | print(func_example[1]) --> key doesn't exist 26 | print(fallback_example.foo) --> bar 27 | print(fallback_example[123]) --> 456 28 | print(fallback_example[456]) --> key doesn't exist 29 | 30 | 31 | -------------------------------------------------------------------------------- /lua-tests/multi-return.lua: -------------------------------------------------------------------------------- 1 | function values() 2 | return 1,2,"buckle my shoe" 3 | end 4 | 5 | function echo(...) 6 | print(...) 7 | return ... 8 | end 9 | 10 | print(values()) 11 | print(values(), 'and done') 12 | 13 | print(pcall(echo,'presenting', values())) 14 | print(pcall(echo,'presenting', values(), "act")) -------------------------------------------------------------------------------- /lua-tests/nbody.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | -- modified by Geoff Leyland 5 | -- modified by Mario Pernici 6 | 7 | -- Need to fix floating point dif between JS/Lua 8 | function trim(x) 9 | return ( math.floor(x * 100000) ) / 100000.0 10 | end 11 | 12 | 13 | sun = {} 14 | jupiter = {} 15 | saturn = {} 16 | uranus = {} 17 | neptune = {} 18 | 19 | local sqrt = math.sqrt 20 | 21 | local PI = 3.141592653589793 22 | local SOLAR_MASS = 4 * PI * PI 23 | local DAYS_PER_YEAR = 365.24 24 | sun.x = 0.0 25 | sun.y = 0.0 26 | sun.z = 0.0 27 | sun.vx = 0.0 28 | sun.vy = 0.0 29 | sun.vz = 0.0 30 | sun.mass = SOLAR_MASS 31 | jupiter.x = 4.84143144246472090e+00 32 | jupiter.y = -1.16032004402742839e+00 33 | jupiter.z = -1.03622044471123109e-01 34 | jupiter.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR 35 | jupiter.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR 36 | jupiter.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR 37 | jupiter.mass = 9.54791938424326609e-04 * SOLAR_MASS 38 | saturn.x = 8.34336671824457987e+00 39 | saturn.y = 4.12479856412430479e+00 40 | saturn.z = -4.03523417114321381e-01 41 | saturn.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR 42 | saturn.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR 43 | saturn.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR 44 | saturn.mass = 2.85885980666130812e-04 * SOLAR_MASS 45 | uranus.x = 1.28943695621391310e+01 46 | uranus.y = -1.51111514016986312e+01 47 | uranus.z = -2.23307578892655734e-01 48 | uranus.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR 49 | uranus.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR 50 | uranus.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR 51 | uranus.mass = 4.36624404335156298e-05 * SOLAR_MASS 52 | neptune.x = 1.53796971148509165e+01 53 | neptune.y = -2.59193146099879641e+01 54 | neptune.z = 1.79258772950371181e-01 55 | neptune.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR 56 | neptune.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR 57 | neptune.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR 58 | neptune.mass = 5.15138902046611451e-05 * SOLAR_MASS 59 | 60 | local bodies = {sun,jupiter,saturn,uranus,neptune} 61 | 62 | local function advance(bodies, nbody, dt) 63 | for i=1,nbody do 64 | local bi = bodies[i] 65 | local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass 66 | local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz 67 | for j=i+1,nbody do 68 | local bj = bodies[j] 69 | local dx, dy, dz = bix-bj.x, biy-bj.y, biz-bj.z 70 | local dist2 = dx*dx + dy*dy + dz*dz 71 | local mag = sqrt(dist2) 72 | mag = dt / (mag * dist2) 73 | local bm = bj.mass*mag 74 | bivx = bivx - (dx * bm) 75 | bivy = bivy - (dy * bm) 76 | bivz = bivz - (dz * bm) 77 | bm = bimass*mag 78 | bj.vx = bj.vx + (dx * bm) 79 | bj.vy = bj.vy + (dy * bm) 80 | bj.vz = bj.vz + (dz * bm) 81 | end 82 | bi.vx = bivx 83 | bi.vy = bivy 84 | bi.vz = bivz 85 | bi.x = bix + dt * bivx 86 | bi.y = biy + dt * bivy 87 | bi.z = biz + dt * bivz 88 | end 89 | end 90 | 91 | local function energy(bodies, nbody) 92 | local e = 0 93 | for i=1,nbody do 94 | local bi = bodies[i] 95 | local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass 96 | e = e + (0.5 * bim * (vx*vx + vy*vy + vz*vz)) 97 | for j=i+1,nbody do 98 | local bj = bodies[j] 99 | local dx, dy, dz = bi.x-bj.x, bi.y-bj.y, bi.z-bj.z 100 | local distance = sqrt(dx*dx + dy*dy + dz*dz) 101 | e = e - ((bim * bj.mass) / distance) 102 | end 103 | end 104 | return e 105 | end 106 | 107 | local function offsetMomentum(b, nbody) 108 | local px, py, pz = 0, 0, 0 109 | for i=1,nbody do 110 | local bi = b[i] 111 | local bim = bi.mass 112 | px = px + (bi.vx * bim) 113 | py = py + (bi.vy * bim) 114 | pz = pz + (bi.vz * bim) 115 | end 116 | --b[1].vx = -px / SOLAR_MASS 117 | --b[1].vy = -py / SOLAR_MASS 118 | --b[1].vz = -pz / SOLAR_MASS 119 | end 120 | 121 | local N = 1000 122 | local nbody = #bodies 123 | 124 | offsetMomentum(bodies, nbody) 125 | io.write( string.format("%s",trim(energy(bodies, nbody))), "\n") 126 | for i=1,N do advance(bodies, nbody, 0.01) end 127 | io.write( string.format("%s",trim(energy(bodies, nbody))), "\n") 128 | 129 | -------------------------------------------------------------------------------- /lua-tests/nodouble.lua: -------------------------------------------------------------------------------- 1 | function o(self) print("o", #self) end 2 | function x() print("x") return {z=o} end 3 | 4 | x():z(x) -------------------------------------------------------------------------------- /lua-tests/oop.lua: -------------------------------------------------------------------------------- 1 | -- account.lua 2 | -- from PiL 1, Chapter 16 3 | 4 | Account = {balance = 0} 5 | 6 | function Account:new (o, name) 7 | o = o or {name=name} 8 | setmetatable(o, self) 9 | self.__index = self 10 | return o 11 | end 12 | 13 | function Account:deposit (v) 14 | self.balance = self.balance + v 15 | end 16 | 17 | function Account:withdraw (v) 18 | if v > self.balance then error("insufficient funds on account "..self.name) end 19 | self.balance = self.balance - v 20 | end 21 | 22 | function Account:show (title) 23 | print(title or "", self.name, self.balance) 24 | end 25 | 26 | a = Account:new(nil,"demo") 27 | a:show("after creation") 28 | a:deposit(1000.00) 29 | a:show("after deposit") 30 | a:withdraw(100.00) 31 | a:show("after withdraw") 32 | 33 | 34 | -------------------------------------------------------------------------------- /lua-tests/optest.lua: -------------------------------------------------------------------------------- 1 | local function p(x) 2 | return x 3 | end 4 | assert(1 < 3) 5 | assert(1 <= 3) 6 | assert(3 <= 3) 7 | assert(3 > 1) 8 | assert(3 >= 3) 9 | assert(3 >= 3) 10 | assert(p(1) < 3) 11 | assert(p(1) <= 3) 12 | assert(p(3) <= 3) 13 | assert(p(3) > 1) 14 | assert(p(3) >= 3) 15 | assert(p(3) >= 3) 16 | assert(1 < p(3)) 17 | assert(1 <= p(3)) 18 | assert(3 <= p(3)) 19 | assert(3 > p(1)) 20 | assert(3 >= p(3)) 21 | assert(3 >= p(3)) 22 | assert(p(1) < p(3)) 23 | assert(p(1) <= p(3)) 24 | assert(p(3) <= p(3)) 25 | assert(p(3) > p(1)) 26 | assert(p(3) >= p(3)) 27 | assert(p(3) >= p(3)) -------------------------------------------------------------------------------- /lua-tests/scope.lua: -------------------------------------------------------------------------------- 1 | local pooja = 1 2 | function x() 3 | pooja = 10 4 | local pooja = 6 5 | print(pooja) 6 | end 7 | x() 8 | print(pooja) 9 | 10 | -------------------------------------------------------------------------------- /lua-tests/singleton.lua: -------------------------------------------------------------------------------- 1 | -- Singleton 2 | -- from luajs.org 3 | 4 | do 5 | local instance 6 | function getInstance() 7 | instance = instance or {} 8 | instance.x = instance.x or 1 9 | return instance 10 | end 11 | -- TODO: var hoeisting strikes again! 12 | -- local instance = {x = 3} 13 | end 14 | 15 | print(getInstance().x) 16 | getInstance().x = 6 17 | print(getInstance().x) 18 | -------------------------------------------------------------------------------- /lua-tests/sort.lua: -------------------------------------------------------------------------------- 1 | -- two implementations of a sort function 2 | -- this is an example only. Lua has now a built-in function "sort" 3 | 4 | -- extracted from Programming Pearls, page 110 5 | function qsort(x,l,u,f) 6 | if ly end) 58 | show("after reverse selection sort",x) 59 | qsort(x,1,n,function (x,y) return x", i, sum(i)) 9 | end 10 | -------------------------------------------------------------------------------- /lua-tests/trees.lua: -------------------------------------------------------------------------------- 1 | -- The Computer Language Benchmarks Game 2 | -- http://benchmarksgame.alioth.debian.org/ 3 | -- contributed by Mike Pall 4 | 5 | local function BottomUpTree(item, depth) 6 | if depth > 0 then 7 | local i = item + item 8 | depth = depth - 1 9 | local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) 10 | return { item, left, right } 11 | else 12 | return { item } 13 | end 14 | end 15 | 16 | local function ItemCheck(tree) 17 | if tree[2] then 18 | return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) 19 | else 20 | return tree[1] 21 | end 22 | end 23 | 24 | local N = 10 25 | local mindepth = 4 26 | local maxdepth = mindepth + 2 27 | if maxdepth < N then maxdepth = N end 28 | 29 | do 30 | local stretchdepth = maxdepth + 1 31 | local stretchtree = BottomUpTree(0, stretchdepth) 32 | print(stretchdepth, ItemCheck(stretchtree)) 33 | end 34 | 35 | local longlivedtree = BottomUpTree(0, maxdepth) 36 | 37 | for depth = mindepth,maxdepth,2 do 38 | local iterations = 2 ^ (maxdepth - depth + mindepth) 39 | local check = 0 40 | for i=1,iterations do 41 | check = check + ItemCheck(BottomUpTree(1, depth)) + 42 | ItemCheck(BottomUpTree(-1, depth)) 43 | end 44 | print(iterations*2, depth, check) 45 | end 46 | 47 | print("long lived tree of depth ", maxdepth, ItemCheck(longlivedtree)) -------------------------------------------------------------------------------- /lua-tests/ycombinator.lua: -------------------------------------------------------------------------------- 1 | -- Y Combinator 2 | -- from luajs.org 3 | 4 | local function Y(f) 5 | local function _1(u) 6 | return u(u) 7 | end 8 | 9 | local function _2(x) 10 | return f(function(...) 11 | return x(x)(...) 12 | end) 13 | end 14 | 15 | return _1(_2) 16 | end 17 | 18 | local function F(f) 19 | return function(x) 20 | if x == 0 then 21 | return 1 22 | end 23 | return x * f (x - 1) 24 | end 25 | end 26 | 27 | local factorial = Y(F) 28 | print(factorial(3)) -------------------------------------------------------------------------------- /lua.pegjs: -------------------------------------------------------------------------------- 1 | /* Helpers include here by build script */ 2 | 3 | start = &{ init(); return true; } ("#" [^\n]* "\n")? ws? t:BlockStatement ws? { return finalize(t); } 4 | ws = ([ \r\t\n] / "--[" balstringinsde "]" / ("--" ( [^\n]* "\n" / .* ) )) + 5 | scws = (ws? ";" ws?)+ / ws 6 | BlockStatement = 7 | r:ReturnStatement 8 | { 9 | return builder.blockStatement([r]) 10 | } / 11 | list:StatementList ret:(scws+ ReturnStatement)? 12 | { 13 | list = expandMultiStatements(list); 14 | return builder.blockStatement(ret === null ? list : list.concat([ret[1]])); 15 | } 16 | StatementList = 17 | a:Statement? b:(scws+ Statement )* (ws? ";")* 18 | { 19 | if ( a === null ) return []; 20 | if ( b === null ) return a; 21 | return listHelper(a,b,1); 22 | } 23 | ReservedWord = rw:("if" / "then" / "elseif" / "else" / "do" / "end" / "return" / "local" / "nil" / "true" / "false" 24 | / "function" / "not" / "break" / "for" / "until" / "while" / binop / unop) ![a-z] { return rw } 25 | Name = !(ReservedWord) a:$([a-zA-Z_][a-zA-Z0-9_]*) { return a; } 26 | Number = $([0-9]+("." [0-9]+)?) 27 | stringchar = 28 | "\\" c:[abfrntv'"\\] { return { 29 | "n": "\n", 30 | "b": "\b", 31 | "f": "\f", 32 | "r": "\r", 33 | "t": "\t", 34 | "v": "\v", 35 | '"': '"', 36 | "'": "'", 37 | "\\": "\\" 38 | }[c] } / 39 | "\\\n" { return "\n" } / 40 | "\\\z" ws { return "" } / 41 | "\\x" a:$[0-9a-f] b:$[0-9a-f] { return String.fromCharCode(parseInt('0x' + a + b)); } / 42 | "\\" a:$[0-9] b:$[0-9]? c:$[0-9]? { return String.fromCharCode(parseInt('' + a + b + c)); } / 43 | "\\" { error('Invalid Escape Sequence') } / 44 | $[^'"'] 45 | singlequote = [\'] { return wrapNode({}); } 46 | doublequote = [\"] { return wrapNode({}); } 47 | String = 48 | s:doublequote r:(stringchar/"'") * e:(doublequote) &{ return eUntermIfEmpty(e,"string","\"",s); } { return r.join(''); } / 49 | s:singlequote r:(stringchar/'"') * e:(singlequote) &{ return eUntermIfEmpty(e,"string","'",s); } { return r.join(''); } / 50 | "[" s: balstringinsde "]" { return s; } 51 | balstringinsde = 52 | "=" a:balstringinsde "=" { return a; } / 53 | "[" [\n]? a:$(!("]" "="* "]") .)* "]" { return a;} 54 | Statement = 55 | s: ( 56 | Debugger / BreakStatement / 57 | NumericFor / 58 | ForEach / 59 | RepeatUntil / 60 | WhileStatement / 61 | IfStatement / 62 | ExpressionStatement / 63 | DoEndGrouped / 64 | LocalAssingment / 65 | FunctionDeclaration / 66 | LocalFunction / 67 | !(ws? ReservedWord) e:$Expression &{ return eMsg("Found an expression but expected a statement: " + e)} { return builder.emptyStatement(); } / 68 | !(ws? ReservedWord) e:$Identifier &{ return eMsg("`=` expected")} { return builder.emptyStatement(); } / 69 | !(ws? ReservedWord) e:$[^\n\t\r ] [^\n]* ([\n]/!.) &{ return eMsg("Parser error near `" + e + "`"); } { return builder.emptyStatement(); } 70 | ) 71 | Debugger = 72 | "debugger" 73 | { return {type: "ExpressionStatement", expression: {type: "Identifier", name:"debugger; "} } } 74 | DoEndGrouped = 75 | start:do ws b:(BlockStatement ws)? end:("end") & { return eUntermIfEmpty(end, "do", "end", start); } 76 | { return b ? b[0] : {type: "BlockStatement", body: []}; } 77 | 78 | if = "if" { return wrapNode({}); } 79 | do = "do" { return wrapNode({}); } 80 | for = "for" { return wrapNode({}); } 81 | function = "function" { return wrapNode({}); } 82 | NumericFor = 83 | start:for ws a:Identifier ws? "=" ws? b:Expression ws? "," ws? c:Expression d:( ws? "," ws? Expression )? ws? "do" ws? body:(BlockStatement ws)? end:("end") &{ return eUntermIfEmpty(end, "for", "end", start); } 84 | { 85 | var amount = d == null ? {type: "Literal", value: 1 } : d[3]; 86 | var start = bhelper.tempVar(b); 87 | var updateBy = bhelper.tempVar(amount); 88 | var testValue = bhelper.tempVar(c); 89 | var idx = bhelper.tempVar(); 90 | var update = builder.assignmentExpression("=", idx.id, bhelper.binaryExpression("+", idx.id, updateBy.id)); 91 | var texp; 92 | if ( false ) { 93 | texp = bhelper.binaryExpression("<=", idx.id, testValue.id) 94 | } else { 95 | texp = bhelper.luaOperator("forcomp", updateBy.id, idx.id, testValue.id); 96 | } 97 | 98 | if ( !body ) body = {type: "BlockStatement", body: []}; 99 | else body = body[0]; 100 | 101 | body.body.unshift(builder.variableDeclaration("let",[ 102 | { 103 | type: "VariableDeclarator", 104 | id: a, 105 | init: idx.id 106 | } 107 | ])); 108 | var out = { 109 | type: "ForStatement", 110 | init: builder.variableDeclaration("let", [ 111 | { 112 | type: "VariableDeclarator", 113 | id: idx.id, 114 | init: start.id, 115 | } 116 | ]), 117 | body: body, 118 | update: update, 119 | test: texp, 120 | loc: location() 121 | }; 122 | return bhelper.encloseDecls([out], start, updateBy, testValue); 123 | } 124 | ForEach = 125 | start:for ws a:namelist ws "in" ws b:explist ws "do" ws? c:BlockStatement ws? end:("end") & { return eUntermIfEmpty(end, "for", "end", start); } 126 | { 127 | var statements = []; 128 | var nil = {type: "Literal", value: null }; 129 | var uf = {type: "Identifier", name: 'undefined' }; 130 | var iterator = bhelper.tempName(); 131 | var context = bhelper.tempName(); 132 | var curent = bhelper.tempName(); 133 | var v1 = a[0]; 134 | var varlist = []; 135 | for ( var idx in a ) { 136 | varlist.push({type: "VariableDeclarator", id: a[idx] }); 137 | } 138 | var call = builder.callExpression(iterator,[context, curent]); 139 | var assign; 140 | //if ( a.length > 1 ) { 141 | assign = bhelper.bulkAssign(a, [call]) 142 | //} else { 143 | // assign = bhelper.assign(v1, call); 144 | //} 145 | var nullish = function(v) { 146 | return builder.binaryExpression("||", builder.binaryExpression("===", v1, nil), builder.binaryExpression("===", v1, uf)) 147 | } 148 | statements.push(builder.variableDeclaration("let", varlist)); 149 | statements.push({ 150 | type: "WhileStatement", 151 | test: {type: "Literal", value: true}, 152 | body: bhelper.blockStatement([ 153 | assign, 154 | { type: "IfStatement", test: nullish(v1), consequent: {type: "BreakStatement" } }, 155 | bhelper.assign(curent, v1), 156 | c.body 157 | ]) 158 | }); 159 | return bhelper.encloseDeclsUnpack(statements, [iterator, context, curent], b); 160 | } 161 | LocalAssingment = 162 | "local" ws left:namelist ws? "=" ws? right:explist 163 | { 164 | var result = builder.variableDeclaration("let", []); 165 | if ( !opt('decorateLuaObjects', false) || ( left.length < 2 && right.length < 2 )) { 166 | var i = 0; 167 | for ( ; i < left.length; ++i ) { 168 | if ( i !== right.length - 1 || i === left.length - 1 ) { 169 | if ( right[i] !== undefined && right[i].type === "CallExpression" ) { 170 | right[i] = bhelper.luaOperator("oneValue", right[i]); 171 | } 172 | result.declarations.push({ 173 | type: "VariableDeclarator", 174 | id: left[i], 175 | init: right[i] 176 | }); 177 | } else if ( right[i].type === "Identifier" || right[i].type === "Literal" ) { 178 | result.declarations.push({ 179 | type: "VariableDeclarator", 180 | id: left[i], 181 | init: right[i] 182 | }); 183 | } else { 184 | left = left.slice(i); 185 | result.declarations = result.declarations.concat(left.map(x => { 186 | return { type: "VariableDeclarator", id: x }; 187 | })); 188 | var assign = bhelper.bulkAssign(left, [ right[i] ]); 189 | return [result, assign]; 190 | } 191 | } 192 | var moreExpr = []; 193 | for ( ; i < right.length; ++i ) { 194 | if (right[i].type === "CallExpression") { 195 | moreExpr.push(right[i]); 196 | } 197 | } 198 | return moreExpr.length ? [ result ].concat({ 199 | type: "ExpressionStatement", 200 | expression: { 201 | type: "SequenceExpression", 202 | expressions: moreExpr 203 | } 204 | }) : result; 205 | } else { 206 | var assign = bhelper.bulkAssign(left, right); 207 | for ( var i = 0; i < left.length; ++i ) { 208 | result.declarations.push({ 209 | type: "VariableDeclarator", 210 | id: left[i] 211 | }); 212 | } 213 | return [result, assign]; 214 | } 215 | }/ 216 | "local" ws left:namelist 217 | { 218 | var result = builder.variableDeclaration("let", []); 219 | for ( var i = 0; i < left.length; ++i ) { 220 | result.declarations.push({ 221 | type: "VariableDeclarator", 222 | id: left[i] 223 | }); 224 | } 225 | return result; 226 | } 227 | AssignmentExpression = 228 | left:varlist ws? "=" ws? right:explist 229 | { 230 | // if ( left.length < 2 ) return bhelper.assign(left[0], right[0]).expression; 231 | return bhelper.bulkAssign(left, right).expression; 232 | } 233 | BreakStatement = 234 | "break" 235 | { return { 236 | "type": "BreakStatement", 237 | loc: location() 238 | } } 239 | ExpressionStatement = 240 | e:(AssignmentExpression/CallExpression) 241 | { return { 242 | type: "ExpressionStatement", 243 | expression: e, 244 | loc: location() 245 | } } 246 | elseif = "elseif" ws test:Expression ws "then" ws then:BlockStatement { return wrapNode({test: test, then:then}); } 247 | IfStatement = 248 | start:if ws test:Expression ws 249 | ("then" / &{ return eUnterminated("if","then"); } ) ws then:BlockStatement 250 | elzeifs:( ws? elseif )* 251 | elze:( ws? "else" ws BlockStatement )? ws? end:("end") &{ return eUntermIfEmpty(end, "if", "end", start); } 252 | { 253 | var result = { type: "IfStatement", test: test, consequent: then, loc: location() } 254 | var last = result; 255 | for ( var idx in elzeifs ) { 256 | var elif = elzeifs[idx][1]; 257 | var nue = { type: "IfStatement", test: elif.test, consequent: elif.then, loc: elif.loc, range: elif.range } 258 | last.alternate = nue; 259 | last = nue; 260 | } 261 | if ( elze !== null ) last.alternate = elze[3]; 262 | return result; 263 | } 264 | ReturnStatement = 265 | "return" ws argument:explist 266 | { 267 | var arg; 268 | if ( argument == null ) { } 269 | else if ( argument.length == 1 ) arg = argument[0]; 270 | else if ( argument.length > 1 ) { 271 | arg = bhelper.luaOperatorA("makeMultiReturn", argument); 272 | } 273 | return { 274 | type: "ReturnStatement", 275 | argument: arg, 276 | loc: location() 277 | } 278 | } / 279 | "return" 280 | { 281 | return { 282 | type: "ReturnStatement", 283 | loc: location() } 284 | } 285 | WhileStatement = 286 | "while" ws test:Expression ws "do" ws body:(BlockStatement ws)? ( "end" / & { return eUnterminated("if"); } ) 287 | { return { 288 | type: "WhileStatement", 289 | test: test, 290 | body: body ? body[0] : {type: "EmptyStatement"}, 291 | loc: location() 292 | } } 293 | RepeatUntil = 294 | "repeat" ws body:(BlockStatement ws)? ( "until" / & { return eUnterminated("repeat", "until"); } ) ws test:( Expression / &{return eMsg("repeat until needs terminations criteria"); }) 295 | { return { 296 | type: "DoWhileStatement", 297 | test: { 298 | type: "UnaryExpression", 299 | operator: "!", 300 | argument: test, 301 | prefix: true, 302 | loc: test.loc 303 | }, 304 | body: body ? body[0] : {type: "EmptyStatement"}, 305 | loc: location() 306 | } } 307 | That = "that" { return { "type": "ThisExpression" }; } 308 | SimpleExpression = ( 309 | RestExpression / FunctionExpression / CallExpression / That / Identifier / Literal / 310 | ObjectExpression / UnaryExpression / ParenExpr ) 311 | Expression = AssignmentExpression / BinSimpleExpression 312 | BinSimpleExpression = 313 | a:(MemberExpression/SimpleExpression) b:( ws? op:binop ws? (MemberExpression/SimpleExpression) )* 314 | { 315 | a = bhelper.translateExpressionIfNeeded(a); 316 | if ( b === null ) return a; 317 | var tokens = []; 318 | for ( var idx in b ) { 319 | var v = b[idx]; 320 | tokens.push(v[1]); 321 | tokens.push(bhelper.translateExpressionIfNeeded(v[3])); 322 | } 323 | return precedenceClimber(tokens, a, 1); 324 | } 325 | unop = $("-" / "not" / "#") 326 | binop = $("+" / "-" / "==" / ">=" / "<=" / "~=" / ">" / "<" / ".." / "and" / "or" / "*" / "//" / "/" / "%" / "^" ) 327 | prefixexp = 328 | funcname / '(' ws? e:Expression ws? ')' { return e; } 329 | CallExpression = 330 | !("function" ws? "(") who:prefixexp a:(ws? (":" Identifier )? callsuffix)+ 331 | { 332 | var left = who 333 | for ( var idx = 0; idx < a.length; ++idx ) { 334 | var v = a[idx]; 335 | if ( v[1] != null ) { 336 | left = builder.memberExpression(left, v[1][1], false); 337 | left.selfSuggar = true; 338 | } 339 | left = bhelper.callExpression(left,v[2]); 340 | } 341 | return left; 342 | } 343 | callsuffix = 344 | a:args { return a; } / 345 | b:ObjectExpression { return [b]; } / 346 | c:String { return [{type: "Literal", value: c, loc: location() }]; } 347 | ParenExpr = "(" ws? a:Expression ws? ")" { 348 | // Wraping a call in ()'s reduces it to a singel value 349 | if ( a.type == "CallExpression" ) { 350 | return bhelper.luaOperator("oneValue", a); 351 | } else if ( a.type == "Identifier" && a.name == "__lua$rest" ) { 352 | return bhelper.luaOperator("oneValue", a); 353 | } 354 | return a; 355 | } 356 | RestExpression = 357 | "..." { 358 | return wrapNode({type: "Identifier", name: "__lua$rest"}); 359 | } 360 | funcname = 361 | a:(That/Identifier) b:( funcnamesuffix )* 362 | { 363 | var selfSuggar = false; 364 | if ( b.length == 0 ) return a; 365 | var left = a; 366 | for ( var i in b ) { 367 | left = builder.memberExpression(left, b[i].exp, b[i].computed); 368 | if ( b[i].suggar ) left.selfSuggar = true; 369 | } 370 | return left; 371 | } 372 | funcnamesuffix = 373 | ws? p:[.:] ws? e:Identifier 374 | { 375 | return {exp: e, suggar: p == ':', computed: false } 376 | } / 377 | ws? "[" ws? e:Expression ws? "]" 378 | { 379 | return {exp: e, suggar: false, computed: true } 380 | } 381 | explist = 382 | a:Expression b:(ws? "," ws? e:(Expression / &{ return eMsg("Malformed argument list."); } ))* 383 | { 384 | return listHelper(a,b,3); 385 | } 386 | varlist = 387 | a:var b:(ws? "," ws? e:var)* 388 | { 389 | return listHelper(a,b,3); 390 | } 391 | namelist = 392 | a:Identifier b:(ws? "," ws? e:Identifier)* 393 | { 394 | return listHelper(a,b,3); 395 | } 396 | args = 397 | "(" ws? a:explist ws? (")" / &{return eUnterminated(")", "argument list"); }) 398 | { 399 | return a; 400 | } / 401 | "(" ws? (")" / &{return eUnterminated(")", "argument list"); }) 402 | { 403 | return [] 404 | } 405 | var = MemberExpression / Identifier 406 | MemberExpression = 407 | a:(CallExpression/SimpleExpression) b:indexer c:indexer* 408 | { 409 | var left = builder.memberExpression(a, b[0], b[1]); 410 | for ( var idx in c ) { 411 | left = builder.memberExpression(left, c[idx][0], c[idx][1]); 412 | } 413 | return left; 414 | } 415 | indexer = 416 | ws? "[" ws? b:Expression ws? "]" { return [b, true]; } / 417 | ws? "." b:SimpleExpression { return [b,false]; } 418 | ObjectExpression = 419 | "{" ws? f:field? s:(ws? ("," / ";") ws? field)* ws? (("," / ";") ws?)? "}" 420 | { 421 | var result; 422 | var props = listHelper(f,s,3); 423 | var arrProps = []; 424 | var kvProps = []; 425 | for ( var idx in props ) { 426 | var p = props[idx]; 427 | if ( p.key === undefined ) { 428 | arrProps.push(p.value); 429 | } else { 430 | p.kind = "init"; 431 | kvProps.push(p); 432 | } 433 | } 434 | if ( opt('decorateLuaObjects', false) ) { 435 | var last = false; 436 | if (kvProps.length) { 437 | result = { type: "ArrayExpression", elements: kvProps.map(p => { 438 | return { type: "ArrayExpression", elements: [p.key, p.value] }; 439 | }) }; 440 | } else { 441 | last = true; 442 | result = { type:"Literal", value: null }; 443 | } 444 | return bhelper.luaOperator.apply(bhelper, ["makeTable", result, 445 | { type: "Literal", value: last }, { 446 | type: "ArrayExpression", 447 | elements: arrProps 448 | }]); 449 | } else { 450 | result = { 451 | loc: location() 452 | }; 453 | if (kvProps.length) { 454 | result.type = "ObjectExpression"; 455 | result.properties = arrProps.map((val, idx) => { 456 | return { 457 | key: { type: "Literal", value: idx + 1 }, 458 | kind: "init", 459 | value: val 460 | } 461 | }).concat(kvProps) 462 | } else { 463 | var lastProp, arrRes; 464 | arrProps.forEach((cur, ind) => { 465 | if (cur.type === 'CallExpression' || cur.name === '__lua$rest') { 466 | if (ind === arrProps.length - 1) { 467 | lastProp = arrProps.splice(ind, 1); 468 | lastProp = cur.name !== '__lua$rest' ? lastProp : [{ 469 | type: "MemberExpression", 470 | object: cur, 471 | property: { type: "Identifier", name: "values" } 472 | }]; 473 | } else { 474 | arrProps[ind] = bhelper.luaOperator("oneValue", cur); 475 | } 476 | } 477 | }); 478 | var arrRes = { 479 | type: "ArrayExpression", 480 | elements: arrProps 481 | }; 482 | if (lastProp) { 483 | result = builder.callExpression({ 484 | type: "MemberExpression", 485 | object: arrRes, 486 | property: { type: "Identifier", name: "concat" } 487 | }, lastProp); 488 | } else { 489 | Object.assign(result, arrRes); 490 | } 491 | } 492 | return result; 493 | } 494 | } 495 | field = 496 | /* Otherwise we think it might be a multi assignment */ 497 | n:(Literal/Identifier) ws? "=" ws? v:(BinSimpleExpression) 498 | { 499 | if ( n.type == "Identifier" ) n = {type: "Literal", value: n.name}; 500 | return { key: n, value: v }; 501 | }/ 502 | v:BinSimpleExpression ws? 503 | { 504 | return { value: v }; 505 | }/ 506 | ws? "[" ws? k:Expression ws? "]" ws? "=" ws? v:BinSimpleExpression 507 | { 508 | return { key: k, value: v, computed: true }; 509 | } 510 | FunctionDeclaration = 511 | start:function ws? name:funcname ws? f:funcbody ws? end:("end") & { return eUntermIfEmpty(end, "function", "end", start); } 512 | { 513 | if ( name.type != "MemberExpression" && opt("allowRegularFunctions", false) ) { 514 | //TODO: this would need to be decorated 515 | return builder.functionDeclaration(name, f.params, f.body); 516 | } 517 | //TODO: Translate member expression into call 518 | var params = f.params.slice(0); 519 | if ( name.selfSuggar ) params = [{type: "Identifier", name: "self"}].concat(f.params); 520 | if ( f.rest ) { 521 | bhelper.injectRest(f.body.body, params.length); 522 | } 523 | var out = builder.functionExpression(null, params, f.body) 524 | if ( opt('decorateLuaObjects', false) ) { 525 | out = bhelper.luaOperator("makeFunction", out); 526 | } 527 | return bhelper.assign(name, out); 528 | } 529 | LocalFunction = 530 | "local" ws start:function ws? name:funcname ws? f:funcbody ws? end:("end") & { return eUntermIfEmpty(end, "function", "end", start); } 531 | { 532 | if ( f.rest ) { 533 | bhelper.injectRest(f.body.body, f.params.length); 534 | } 535 | if ( opt("allowRegularFunctions", false) ) 536 | return builder.functionDeclaration(name, f.params, f.body); 537 | var func = builder.functionExpression(name, f.params, f.body); 538 | if ( opt('decorateLuaObjects', false) ) { 539 | func = bhelper.luaOperator("makeFunction", func); 540 | } 541 | var decl = {type: "VariableDeclarator", id: name, init: func}; 542 | var out = builder.variableDeclaration("let", [ decl ]); 543 | return out; 544 | } 545 | FunctionExpression = 546 | f:funcdef 547 | { 548 | var result = { 549 | type: "FunctionExpression", 550 | body: f.body, 551 | params: f.params, 552 | loc:location() } 553 | if ( f.rest ) { 554 | bhelper.injectRest(f.body.body, f.params.length) 555 | } 556 | if ( opt('decorateLuaObjects', false) ) { 557 | return bhelper.luaOperator("makeFunction", result); 558 | } else { 559 | return result; 560 | } 561 | } 562 | funcdef = 563 | start:function ws? b:funcbody ws? end:("end") & { return eUntermIfEmpty(end, "function", "end", start); } { return b; } 564 | funcbody = 565 | "(" ws? p:paramlist ws? rest:("," ws? "..." ws?)? ")" ws? body:BlockStatement 566 | { 567 | return { params: p, body: body, rest: rest != null } 568 | } / 569 | "(" ws? "..." ws? ")" ws? body:BlockStatement 570 | { 571 | return { params: [], body: body, rest: true } 572 | } 573 | paramlist = 574 | a:Identifier ws? b:("," ws? Identifier)* 575 | { 576 | return listHelper(a,b); 577 | } / 578 | ws? { 579 | return [] 580 | } 581 | UnaryExpression = 582 | o:unop ws? e:(MemberExpression/SimpleExpression/Expression) 583 | { 584 | var ops = {"not": "!", "-": "-", "#": "#" } 585 | if ( o == "#" ) { 586 | e = bhelper.translateExpressionIfNeeded(e); 587 | return bhelper.luaOperator("count", e); 588 | } 589 | return { 590 | type: "UnaryExpression", 591 | operator: ops[o], 592 | argument: bhelper.translateExpressionIfNeeded(e), 593 | prefix: true, 594 | loc: location() 595 | } 596 | } 597 | Identifier = 598 | name:Name 599 | { return { 600 | type: "Identifier", 601 | name: name, 602 | loc: location() 603 | } } 604 | Literal = 605 | a: ("nil" / "false" / "true") 606 | { 607 | var values = {"nil": null, "false": false, "true": true} 608 | return wrapNode({ type: "Literal", value: values[a] }) 609 | } / 610 | b: Number [eE] c:$(("-" / "+")? [0-9]+) 611 | { 612 | return wrapNode({ type: "Literal", value: parseFloat(b) * Math.pow(10, parseInt(c)) }) 613 | } / 614 | a: "0" [Xx] b:$([0-9a-fA-F]+) 615 | { 616 | return wrapNode({ type: "Literal", value: parseInt(b, 16) }) 617 | } / 618 | b: Number 619 | { 620 | return wrapNode({ type: "Literal", value: parseFloat(b) }) 621 | } / 622 | s: String 623 | { 624 | return wrapNode({ type: "Literal", value: s }) 625 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lua2js", 3 | "version": "0.0.9", 4 | "description": "Lua 2 Javascript Transpiler", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "set DEBUG=express:* & node server.js", 8 | "test": "jasmine-node ./test_spec.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "http://github.com/basicer/lua2js-dist" 13 | }, 14 | "author": "Rob Blancakert", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/basicer/lua2js/issues" 18 | }, 19 | "homepage": "https://github.com/basicer/lua2js-dist", 20 | "devDependencies": { 21 | "escodegen": "^1.12.1", 22 | "express": "^4.12.0", 23 | "jasmine-node": "^1.14.5", 24 | "pegjs": "^0.10.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Lua 2 JS 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Options 43 | Evaluate 44 | 45 | Lua 2 JS 46 | 47 | 48 | 49 | 50 | 58 | 59 | 60 | 61 | 69 | {{error}} 70 | 71 | 72 | 73 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | × 83 | Parser Options 84 | 85 | 86 | JavaScript Compat 87 | 88 | 89 | 90 | Force 'var' instead of 'let' 91 | Use library functions for operators 92 | Enclose scopes in functions 93 | 94 | 95 | Decorate Lua objects 96 | Proxy function calls 97 | 98 | 99 | 100 | Error Handeling 101 | 102 | 103 | 104 | Loose Mode 105 | 106 | 107 | Use Strict 108 | 109 | 110 | 111 | 114 | 115 | 116 | 117 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /public/stdlib.js: -------------------------------------------------------------------------------- 1 | var env = {}; 2 | 3 | Object.defineProperty(Array.prototype, 'merge', { 4 | configurable: true, 5 | value: function(arr2) { 6 | var arr1Length = this.length; 7 | var arr2Length = arr2.length; 8 | // Pre allocate size 9 | this.length = this.length + arr2Length; 10 | // Add arr2 items to arr1 11 | for(var i = 0; i < arr2Length; i++){ 12 | this[arr1Length + i] = arr2[i]; 13 | } 14 | } 15 | }); 16 | 17 | function LuaArgList(v) { 18 | this.values = v; 19 | }; 20 | Object.defineProperty(LuaArgList.prototype, "__luaType", {value: "argList", enumerable: false}); 21 | 22 | var __lua = (function() { 23 | 24 | // Yoinked from underscore. 25 | var isJSArray = Array.isArray || function(obj) { return toString.call(obj) === '[object Array]'; }; 26 | 27 | function type(what) { 28 | if ( what === null || what === undefined ) return "nil"; 29 | var t = typeof what; 30 | if ( t == "object" ) return "table"; 31 | return t; 32 | } 33 | 34 | function numberForArith(n) { 35 | if ( type(n) == "number" ) return n; 36 | else if ( typeof n == "string" ) { 37 | n = parseInt(n); 38 | if ( !isNaN(n) ) return n; 39 | } 40 | 41 | throw "attempt to perform arithmetic on a " + type(n) + " value: " + n; 42 | } 43 | 44 | function makeString(a) { 45 | a = oneValue(a); 46 | 47 | var mtf = lookupMetaTable(a, "__tostring"); 48 | if ( mtf !== null ) return mtf(a); 49 | 50 | if ( a === undefined || a === null ) return "nil"; 51 | if ( a instanceof LuaTable ) { 52 | return "table: 0x" + a.id; 53 | } else if ( typeof a == "number" ) { 54 | if ( ~~a == a ) return a.toString(); 55 | var rep = a.toPrecision(); 56 | if ( rep.length > 14 ) return a.toPrecision(14); 57 | return rep; 58 | } 59 | return "" + a; 60 | } 61 | 62 | function add(a,b) { 63 | a = oneValue(a); b = oneValue(b); 64 | 65 | var mtf = lookupMetaTableBin(a, b, "__add"); 66 | if ( mtf !== null ) return mtf(a,b); 67 | 68 | return numberForArith(a) + numberForArith(b); 69 | } 70 | 71 | function sub(a,b) { 72 | a = oneValue(a); b = oneValue(b); 73 | 74 | var mtf = lookupMetaTableBin(a, b, "__sub"); 75 | if ( mtf !== null ) return mtf(a,b); 76 | 77 | return numberForArith(a) - numberForArith(b); 78 | } 79 | 80 | function mul(a,b) { 81 | a = oneValue(a); b = oneValue(b); 82 | 83 | var mtf = lookupMetaTableBin(a, b, "__mul"); 84 | if ( mtf !== null ) return mtf(a,b); 85 | 86 | return numberForArith(a) * numberForArith(b); 87 | } 88 | 89 | function div(a,b) { 90 | a = oneValue(a); b = oneValue(b); 91 | 92 | var mtf = lookupMetaTableBin(a, b, "__div"); 93 | if ( mtf !== null ) return mtf(a,b); 94 | 95 | return numberForArith(a) / numberForArith(b); 96 | } 97 | 98 | function intdiv(a,b) { 99 | a = oneValue(a); b = oneValue(b); 100 | 101 | var mtf = lookupMetaTableBin(a, b, "__idiv"); 102 | if ( mtf !== null ) return mtf(a,b); 103 | 104 | return ~~(numberForArith(a) / numberForArith(b)); 105 | } 106 | 107 | function mod(a,b) { 108 | a = oneValue(a); b = oneValue(b); 109 | 110 | var mtf = lookupMetaTableBin(a, b, "__mod"); 111 | if ( mtf !== null ) return mtf(a,b); 112 | 113 | var anum = numberForArith(a); 114 | var bnum = numberForArith(b); 115 | var jsmod = anum % bnum; 116 | return (jsmod == 0 || (anum > 0) == (bnum > 0)) ? jsmod : jsmod + bnum; 117 | } 118 | 119 | function pow(a,b) { 120 | a = oneValue(a); b = oneValue(b); 121 | 122 | var mtf = lookupMetaTableBin(a, b, "__pow"); 123 | if ( mtf !== null ) return mtf(a,b); 124 | 125 | return Math.pow(numberForArith(a),numberForArith(b)); 126 | } 127 | 128 | function concat(a,b) { 129 | a = oneValue(a); b = oneValue(b); 130 | 131 | var mtf = lookupMetaTableBin(a, b, "__concat"); 132 | if ( mtf !== null ) return mtf(a,b); 133 | if ( a === null || a === undefined || b === null || b === undefined ) 134 | throw "attempt to concatenate a nil value"; 135 | 136 | return makeString(a) + makeString(b); 137 | } 138 | 139 | function lte(a,b) { 140 | a = oneValue(a); b = oneValue(b); 141 | 142 | var mtf = lookupMetaTableBin(a, b, "__le"); 143 | if ( mtf !== null ) return mtf(a,b); 144 | 145 | return a <= b; 146 | } 147 | 148 | function lt(a,b) { 149 | a = oneValue(a); b = oneValue(b); 150 | 151 | var mtf = lookupMetaTableBin(a, b, "__lt"); 152 | if ( mtf !== null ) return mtf(a,b); 153 | 154 | return a < b; 155 | } 156 | 157 | function gte(a,b) { return lte(b,a); } 158 | function gt(a,b) { return lt(b,a); } 159 | 160 | 161 | function forcomp(d,a,b) { 162 | if ( d > 0 ) return a <= b; 163 | else if ( d < 0 ) return b <= a; 164 | else return false; 165 | } 166 | 167 | 168 | function eq(a,b) { 169 | a = oneValue(a); b = oneValue(b); 170 | 171 | var mtf = lookupMetaTableBin(a, b, "__eq"); 172 | if ( mtf !== null ) return mtf(a,b); 173 | 174 | 175 | if ( a === null || a === undefined ) { 176 | return ( b === null || b === undefined ); 177 | } 178 | if ( a === b ) return true; 179 | return false; 180 | } 181 | 182 | function ne(a,b) { return !eq(a,b); } 183 | 184 | function count(a) { 185 | if ( a instanceof LuaTable ) { 186 | var cnt = 0; 187 | while ( a.numeric[cnt] !== undefined ) ++cnt; 188 | return cnt; 189 | } 190 | return a.length; 191 | } 192 | 193 | function and(a,b) { return a && b; } 194 | function or(a,b) { return a || b; } 195 | 196 | // standard expand 197 | function expandA(what) { 198 | var out = []; 199 | var len = what.length; 200 | for ( var idx = 0; idx < len; idx++ ) { 201 | var v = what[idx]; 202 | if ( v instanceof LuaArgList ) { 203 | if ( idx < len - 1 ) { 204 | out.push(v.values[0]); 205 | } else { 206 | out.merge(v.values); 207 | } 208 | } else { 209 | out.push(v); 210 | } 211 | } 212 | return out; 213 | } 214 | 215 | // don't expand last arglist 216 | function expandB(what) { 217 | var out = []; 218 | for ( var v of what ) { 219 | if ( v instanceof LuaArgList ) { 220 | out.push(v.values[0]); 221 | } else { 222 | out.push(v); 223 | } 224 | } 225 | return out; 226 | } 227 | 228 | function expandArgList() { 229 | return expandA(arguments); 230 | } 231 | 232 | function call(flags, what, that, helper, ...rest ) { 233 | var injectSelf = !!(flags & 1); 234 | var detectLua = !!(flags & 2); 235 | 236 | var whatType = typeof what; 237 | if ( !what || (whatType !== 'function' && whatType !== 'object') ) { 238 | if ( helper === undefined ) throw "attempt to call a " + type(what) + " value"; 239 | else throw "attempt to call '" + helper + "' (a " + type(what) + " value)"; 240 | } 241 | 242 | if (whatType === 'function') { 243 | var isLuaFunction = true; 244 | if ( detectLua ) { 245 | isLuaFunction = what.__luaType === "function"; 246 | } 247 | 248 | var args = expandA(rest); 249 | if ( injectSelf && isLuaFunction ) { 250 | args.unshift(that); 251 | } 252 | 253 | if ( detectLua && !isLuaFunction ) { 254 | var args2 = []; 255 | for ( var i = 0; i < args.length; ++i ) { 256 | var a = args[i]; 257 | if ( a instanceof LuaTable ) { 258 | if ( a.numeric.length == 0 ) args2[i] = a.hash; 259 | else if ( Object.keys(a.hash).length == 0 ) args2[i] = a.numeric; 260 | else args2[i] = a; 261 | } else { 262 | args2[i] = a; 263 | } 264 | } 265 | args = args2; 266 | } 267 | return what.apply(that, args); 268 | } else { 269 | var mtf = lookupMetaTable(what, "__call"); 270 | if ( mtf !== null ) return mtf.apply(that, [ what ].concat(expandA(rest))); 271 | throw "attempt to call '" + helper + "' (a " + type(what) + " value)"; 272 | } 273 | } 274 | 275 | function rest(args, cnt) { 276 | return new LuaArgList(Array.prototype.slice.call(args, cnt)); 277 | } 278 | 279 | var id = 0; 280 | function LuaTable() { 281 | this.id = ++id; 282 | this.numeric = []; 283 | this.hash = {}; 284 | }; 285 | 286 | Object.defineProperty(LuaTable.prototype, "__luaType", {value: "table", enumerable: false}); 287 | Object.defineProperty(LuaTable.prototype, "toString", {value: function() { 288 | return makeString(this); 289 | }, enumerable: false}); 290 | 291 | function makeTable(t, allowExpand, numeric) { 292 | var out = new LuaTable(); 293 | 294 | if ( allowExpand ) { 295 | out.numeric = expandA(numeric); 296 | } else { 297 | out.numeric = expandB(numeric); 298 | } 299 | if ( !t ) return out; 300 | for ( var pair of t ) { 301 | var key = pair[0]; 302 | var val = pair[1]; 303 | if ( typeof key == "number" ) { 304 | out.numeric[key - 1] = val; 305 | } else { 306 | out.hash[key] = val; 307 | } 308 | } 309 | 310 | return out; 311 | } 312 | 313 | function makeFunction(f) { 314 | f.__luaType = "function"; 315 | return f; 316 | } 317 | 318 | // rawget and rawset helper functions 319 | function __ltRawSet (table, prop, value) { 320 | if ( typeof prop == "number") table.numeric[prop-1] = value; 321 | else table.hash[prop] = value; 322 | }; 323 | 324 | function __ltRawGet (table, prop) { 325 | if ( typeof prop == "number" ) return table.numeric[prop-1]; 326 | else return table.hash[prop]; 327 | } 328 | 329 | function __arrRawSet (table, prop, value) { 330 | if ( typeof prop == "number") table[prop-1] = value; 331 | else table[prop] = value; 332 | }; 333 | 334 | function __arrRawGet (table, prop) { 335 | if ( typeof prop == "number") return table[prop-1]; 336 | return table[prop]; 337 | }; 338 | 339 | function __objRawSet (table, prop, value) { 340 | return table[prop] = value; 341 | }; 342 | 343 | function __objRawGet (table, prop) { 344 | return table[prop]; 345 | }; 346 | 347 | function rawget(table, prop) { 348 | if ( table instanceof LuaTable ) { 349 | return __ltRawGet(table, prop); 350 | } else if ( isJSArray(table) ) { 351 | return __arrRawGet(table, prop); 352 | } else { // JS Object 353 | return __objRawGet(table, prop); 354 | } 355 | } 356 | 357 | function lookupMetaTable(table, entry) { 358 | if ( table && typeof table === "object" ) { 359 | if ( table.__metatable === undefined ) return null; 360 | 361 | var idx = rawget(table.__metatable, entry); 362 | if ( idx === null || idx === undefined ) return null; 363 | 364 | return idx; 365 | } 366 | 367 | return null; 368 | } 369 | 370 | function lookupMetaTableBin(a, b, entry) { 371 | var mt = lookupMetaTable(a, entry); 372 | if ( mt == null ) return lookupMetaTable(b, entry); 373 | return mt; 374 | } 375 | 376 | function index(table, prop, helper) { 377 | if ( table === null || table === undefined || typeof table !== "object" && 378 | !(typeof table === "function" && table.hasOwnProperty('prototype'))) { 379 | if ( helper == undefined ) { 380 | throw "attempt to index a " + type(table) + " value"; 381 | } else { 382 | var tt = type(table); 383 | if (tt === "string") return env.string[prop]; 384 | throw "attempt to index '" + helper + "' (a " + tt + " value)"; 385 | } 386 | } 387 | 388 | if ( prop === undefined || prop === null ) throw "table index is nil"; 389 | 390 | var rget; 391 | if ( table instanceof LuaTable ) { 392 | rget = __ltRawGet; 393 | } else if ( isJSArray(table) ) { 394 | rget = __arrRawGet; 395 | } else { // JS Object 396 | rget = __objRawGet; 397 | } 398 | // main logic 399 | var val = rget(table, prop); 400 | if ( table.__metatable === undefined || (val !== null && val !== undefined) ) { 401 | return val; 402 | } 403 | 404 | var idxfx = lookupMetaTable(table, "__index"); 405 | if ( idxfx == null ) return null; 406 | 407 | if ( typeof idxfx == "function" ) return oneValue(idxfx(table, prop)); 408 | return index(idxfx, prop); 409 | } 410 | 411 | function indexAssign(table, prop, value, helper) { 412 | if ( table === null || table === undefined || typeof table !== "object" ) { 413 | if ( helper == undefined ) { 414 | throw "attempt to index a " + type(table) + " value"; 415 | } else { 416 | throw "attempt to index '" + helper + "' (a " + type(table) + " value)"; 417 | } 418 | } 419 | 420 | if ( prop === undefined || prop === null ) throw "table index is nil"; 421 | 422 | var rset, rget; 423 | if ( table instanceof LuaTable ) { 424 | rset = __ltRawSet; 425 | rget = __ltRawGet; 426 | } else if ( isJSArray(table) ) { 427 | rset = __arrRawSet; 428 | rget = __arrRawGet; 429 | } else { // JS Object 430 | rset = __objRawSet; 431 | rget = __objRawGet; 432 | } 433 | // main logic 434 | if ( table.__metatable === undefined ) { 435 | return rset(table, prop, value); 436 | } 437 | 438 | var val = rget(table, prop) 439 | 440 | if ( val !== null && val !== undefined ) { 441 | return rset(table, prop, value); 442 | } 443 | 444 | var idx = table.__metatable.__newindex; 445 | if ( idx === null || idx === undefined ) { 446 | return rset(table, prop, value); 447 | } 448 | 449 | if ( typeof idx == "function" ) return idx(table, prop, value); 450 | else return indexAssign(idx, prop, value); 451 | } 452 | 453 | function oneValue(v) { 454 | if ( v instanceof LuaArgList ) return v.values[0]; 455 | return v; 456 | } 457 | 458 | function makeMultiReturn() { 459 | return new LuaArgList(expandA(arguments)); 460 | } 461 | 462 | function pcall(what /*, args... */ ) { 463 | try { 464 | var result = expandA([ what.apply(this, Array.prototype.slice.call(arguments, 1)) ]); 465 | result.unshift(true); 466 | return makeMultiReturn.apply(__lua, result); 467 | } catch ( e ) { 468 | return makeMultiReturn(false, e); 469 | } 470 | } 471 | 472 | function isTable(a) { return a instanceof LuaTable; } 473 | 474 | function mark(o) { 475 | var seen = []; 476 | function domark(o) { 477 | if ( o in seen ) return; 478 | seen.push(o); 479 | if ( typeof o == "object" ) for ( var idx in o ) domark(o[idx]); 480 | else if ( typeof o == "function" ) o.__luaType = "function"; 481 | 482 | } 483 | domark(o); 484 | } 485 | 486 | return { 487 | add, sub, mul, div, intdiv, mod, call, lte, lt, ne, gt, gte, eq, rawget, index, 488 | indexAssign, concat, makeTable, makeFunction, expandArgList, makeMultiReturn, 489 | count, and, or, rest, pcall, type, pow, isTable, mark, forcomp, makeString, 490 | oneValue, lookupMetaTable, isJSArray 491 | }; 492 | 493 | })(); 494 | 495 | this.__lua = __lua; 496 | 497 | env.tonumber = function (s, base) { 498 | if (base) return parseInt(s, base); 499 | if (isNaN(s)) { 500 | return parseFloat(s); 501 | } else { 502 | return s; 503 | } 504 | } 505 | env.tostring = __lua.makeString; 506 | 507 | env.string = (function() { 508 | /** 509 | * string helpers 510 | */ 511 | function checkString(s, num) { 512 | var type = typeof(s); 513 | if (type === "string") return s; 514 | if (type === 'number') return "" + s; 515 | throw(`bad argument #${num} to '${checkString.caller.name}' ` + 516 | `(string expected, got ${__lua.type(s)})`); 517 | } 518 | 519 | function makePattern(pat) { 520 | var classPat = /\[.*?[^%]\]/g; 521 | var inClass = []; 522 | for (var match of pat.matchAll(classPat)) { 523 | for (var k = match.index; k < match.index + match[0].length; k++) { 524 | inClass[k] = 1; 525 | } 526 | } 527 | pat = [...pat].map((x, i) => (x === '-' && !inClass[i] ? '*?' : x)).join(''); 528 | return pat.replace(/%(.)|\^|\$/g, function(m, p1, k) { 529 | if (p1 === 'a') { 530 | return inClass[k+1] ? 'A-Za-z' : '[A-Za-z]'; 531 | } else { 532 | return '\\' + p1; 533 | } 534 | }); 535 | } 536 | 537 | function makeReplace(newStr) { 538 | return newStr.replace(/%(.)/g, function(m, p1) { 539 | if (isNaN(p1)) { 540 | return p1; 541 | } else if (p1 === '0') { 542 | return '$&'; 543 | } else { 544 | return '$' + p1; 545 | } 546 | }); 547 | } 548 | 549 | function uncheckedSub(s, i, j) { 550 | if ( i === undefined || i === null ) i = 1; 551 | if ( j === undefined || j === null ) j = s.length; 552 | if ( i < 0 ) i += (s.length+1); 553 | if ( j < 0 ) j += (s.length+1); 554 | 555 | return s.substring(i-1,j); 556 | } 557 | 558 | /** 559 | * methods 560 | */ 561 | function byte(s, i, j) { 562 | s = checkString(s, 1); 563 | var chars = sub(s, i, j); 564 | var out = []; 565 | for ( var i = 0; i < chars.length; ++i ) out[i] = chars.charCodeAt(i); 566 | return __lua.makeMultiReturn.apply(__lua, out); 567 | } 568 | 569 | function char(/* arguments */) { 570 | var out = ""; 571 | for ( var i = 0; i < arguments.length; ++i ) { 572 | out += String.fromCharCode(arguments[i]|0); 573 | } 574 | return out; 575 | } 576 | 577 | function dump() {} 578 | 579 | function find(s, pat, init, plain) { 580 | s = checkString(s, 1); 581 | init = init && (init >= 0 ? init : init + s.length + 1); 582 | if (plain) { 583 | var start = s.indexOf(pat, init - 1) + 1; 584 | return start ? __lua.makeMultiReturn(start, start + pat.length) : null; 585 | } else { 586 | pat = new RegExp(makePattern(pat)); 587 | var res; 588 | if (init) { 589 | s = uncheckedSub(s, init); 590 | res = pat.exec(s); 591 | return res && __lua.makeMultiReturn(res.index + init, 592 | res.index + init + res[0].length - 1); 593 | } else { 594 | res = pat.exec(s); 595 | return res && __lua.makeMultiReturn(res.index + 1, 596 | res.index + res[0].length); 597 | } 598 | } 599 | } 600 | 601 | function match(s, pat, init) { 602 | s = checkString(s, 1); 603 | init = init && (init >= 0 ? init : init + s.length + 1); 604 | s = uncheckedSub(s, init); 605 | pat = new RegExp(makePattern(pat)); 606 | var res = pat.exec(s); 607 | return res && (res[1] !== undefined ? __lua.makeMultiReturn.apply(__lua, res.slice(1)) : res[0]); 608 | } 609 | 610 | function gmatch() {} 611 | function gsub(s, pat, repl, n) { 612 | s = checkString(s, 1); 613 | pat = new RegExp(makePattern(pat), 'g'); 614 | var type = __lua.type(repl); 615 | if (n) { 616 | return s; // TODO 617 | } else { 618 | if (type === 'string') { 619 | return s.replace(pat, makeReplace(repl)); 620 | } else if (type === 'table') { 621 | return s.replace(pat, function(m, p1) { 622 | if (p1) { 623 | return __lua.index(repl, p1, 'repl'); 624 | } else { 625 | return __lua.index(repl, m, 'repl'); 626 | } 627 | }); 628 | } else if (type === 'function') { 629 | return s.replace(pat, function(m, ...pArgs) { 630 | if (pArgs[0]) { 631 | return __lua.call(0, repl, this, 'repl', new LuaArgList(pArgs.slice(0, -2))); 632 | } else { 633 | return repl(m); 634 | } 635 | }); 636 | } 637 | } 638 | } 639 | 640 | function len(s) { 641 | s = checkString(__lua.oneValue(s), 1); 642 | return ("" + s).length; 643 | } 644 | function lower(s) { 645 | s = checkString(s, 1); 646 | return ("" + s).toLowerCase(); 647 | } 648 | function upper(s) { 649 | s = checkString(s, 1); 650 | return ("" + s).toUpperCase(); 651 | } 652 | 653 | function rep(s, n, sep) { 654 | s = checkString(s, 1); 655 | if (!n || n < 0) return ""; 656 | if (sep) { 657 | return s + (sep + s).repeat(n - 1); 658 | } else { 659 | return s.repeat(n); 660 | } 661 | } 662 | 663 | function reverse(s) { 664 | s = checkString(s, 1); 665 | return ("" + s).split("").reverse().join(""); 666 | } 667 | 668 | function sub(s, i, j) { 669 | s = checkString(s, 1); 670 | return uncheckedSub(s, i, j); 671 | } 672 | 673 | function format(format, etc) { 674 | var arg = arguments; 675 | var i = 1; 676 | return format.replace(/%([0-9.]+)?([%sfdgi])/g, function (m, w, t) { 677 | var r = null; 678 | if ( t == "%" ) return "%"; 679 | else if ( t == "s") r = arg[i++]; 680 | else if ( t == "d") r = parseInt(arg[i++]); 681 | else if ( t == "i") r = parseInt(arg[i++]); 682 | else if ( t == "f" ) r = arg[i++].toFixed(parseFloat(m[1]) || 6); 683 | else r = arg[i++]; 684 | r = "" + r; 685 | if ( parseInt(w) ) { 686 | var extra = parseInt(w) - r.length; 687 | if ( extra > 0 ) r = new Array(extra).join(" ") + r; 688 | } 689 | return r; 690 | }); 691 | } 692 | 693 | return { 694 | byte, char, dump, find, gmatch, gsub, len, lower, match, rep, reverse, 695 | sub, upper, format 696 | }; 697 | })(); 698 | 699 | 700 | 701 | 702 | env.table = { 703 | concat: function(table, sep, i, j) { 704 | sep = sep || ""; 705 | if ( __lua.isTable(table) ) { 706 | return table.numeric.slice(i-1, j).join(sep); 707 | } else if ( __lua.isJSArray(table) ) { 708 | return table.slice(i-1, j).join(sep); 709 | } 710 | }, 711 | insert: function(table, pos, value) { 712 | if (value) { 713 | if ( __lua.isTable(table) ) { 714 | return table.numeric[pos-1] = value; 715 | } else if ( __lua.isJSArray(table) ) { 716 | return table[pos-1] = value; 717 | } 718 | } else { 719 | value = pos; 720 | if ( __lua.isTable(table) ) { 721 | return table.numeric.push(value); 722 | } else if ( __lua.isJSArray(table) ) { 723 | return table.push(value); 724 | } 725 | } 726 | }, 727 | pack: function(/* arguments */) { 728 | return __lua.makeTable(null, false, Array.from(arguments)); 729 | }, 730 | remove: function(table, pos) { 731 | pos = pos ? pos-1 : -1; 732 | if ( __lua.isTable(table) ) { 733 | table.numeric.splice(pos, 1); 734 | } else if ( __lua.isJSArray(table) ) { 735 | table.splice(pos, 1); 736 | } 737 | }, 738 | sort: function(table, comp) { 739 | var tcomp; 740 | if (comp) { 741 | tcomp = function(a,b) { return comp(a,b) ? -1 : 1; }; 742 | } 743 | if ( __lua.isTable(table) ) { 744 | table.numeric.sort(tcomp); 745 | } else if ( __lua.isJSArray(table) ) { 746 | table.sort(tcomp); 747 | } 748 | }, 749 | unpack: function(table, i, j) { 750 | if ( i === undefined || i === null ) i = 1; 751 | if ( j === undefined || j === null ) j = __lua.count(table); 752 | 753 | var arr = []; 754 | if ( __lua.isTable(table) ) { 755 | for ( var a = i-1; a < j; ++a ) { 756 | arr.push(table.numeric[a]); 757 | } 758 | } else if ( __lua.isJSArray(table) ) { 759 | for ( var a = i-1; a < j; ++a ) { 760 | arr.push(table[a]); 761 | } 762 | } else { 763 | for ( var a = i; a <= j; ++a ) { 764 | arr.push(table[a]); 765 | } 766 | } 767 | 768 | return __lua.makeMultiReturn.apply(__lua, arr); 769 | } 770 | }; 771 | 772 | env.unpack = env.table.unpack; 773 | 774 | env.os = { 775 | clock: null, 776 | date: null, 777 | difftime: function difftime(t1,t2) { return t2 - t1; }, 778 | execute: null, 779 | exit: null, 780 | time: function time(table) { 781 | if ( table == null ) return new Date().getTime(); 782 | throw "Time given a table not implemented yet."; 783 | } 784 | }; 785 | 786 | env.io = { 787 | write: function() { env.print(...arguments); } 788 | }; 789 | env.print = function print() { console.log.apply(console, arguments); }; 790 | 791 | env.error = function error(s) { throw s; }; 792 | 793 | env.assert = function assert(what, msg, code) { 794 | if ( code === undefined ) { 795 | code = msg; 796 | msg = undefined; 797 | } 798 | 799 | if ( !!what ) return what; 800 | 801 | throw("Assertion Failed!! " + code); 802 | }; 803 | 804 | env.type = function type(what) { 805 | return __lua.type(what); 806 | }; 807 | 808 | 809 | env.pairs = function pairs(table) { 810 | 811 | var mtf = __lua.lookupMetaTable(table, "__pairs"); 812 | if ( mtf !== null ) return mtf(table); 813 | 814 | var list = []; 815 | if ( __lua.isTable(table) ) { 816 | for ( var i = 0; i < table.numeric.length; ++i ) table.numeric[i] && list.push([i + 1, i, table.numeric]); 817 | for ( var idx in table.hash ) list.push([idx, idx, table.hash]); 818 | } else if ( __lua.isJSArray(table) ) { 819 | for ( var i in table ) { 820 | list.push([isNaN(i) ? i : parseInt(i) + 1, i, table]); 821 | } 822 | } else { 823 | var keys = Object.keys(table); 824 | for ( var idx in keys ) list.push([keys[idx], keys[idx], table]); 825 | } 826 | 827 | return __lua.makeMultiReturn(function(handle, cur) { 828 | if ( handle.length < 1 ) return null; 829 | var nfo = handle.shift(); 830 | var k = nfo[0]; 831 | var v = nfo[2][nfo[1]]; 832 | return __lua.makeMultiReturn(k,v); 833 | }, list, null); 834 | }; 835 | 836 | env.ipairs = function ipairs(table) { 837 | 838 | var mtf = __lua.lookupMetaTable(table, "__ipairs"); 839 | if ( mtf !== null ) return mtf(table); 840 | 841 | return __lua.makeMultiReturn(function ipairsitr(table, cur) { 842 | cur = cur + 1; 843 | if ( __lua.isJSArray(table) ) { 844 | if ( table.length < cur ) return null; 845 | return __lua.makeMultiReturn(cur, table[cur-1]); 846 | } else if ( __lua.isTable(table) ) { 847 | if ( table.numeric[cur-1] === null || table.numeric[cur-1] === undefined ) return null; 848 | return __lua.makeMultiReturn(cur, table.numeric[cur-1]); 849 | } else { 850 | return table[cur-1]; 851 | } 852 | }, table, 0); 853 | }; 854 | 855 | env.next = function next(table, cur) { 856 | if ( __lua.isTable(table) ) { 857 | var list = []; 858 | for ( var i = 0; i < table.numeric.length; ++i ) list.push([i + 1, table.numeric[i]]); 859 | for ( var tidx in table.hash ) list.push([tidx, table.hash[tidx]]); 860 | var trigger = false; 861 | for ( var i = 0; i < list.length; ++i ) { 862 | var itm = list[i]; 863 | if ( cur === null || cur === undefined || trigger ) { 864 | if ( itm[1] !== undefined && itm[1] !== null ) 865 | return __lua.makeMultiReturn(itm[0], itm[1]); 866 | } 867 | if ( cur === itm[0] ) trigger = true; 868 | } 869 | 870 | return null; 871 | } else { 872 | var listk = Object.keys(table); 873 | var trigger = false; 874 | for ( var i = 0; i < listk.length; ++i ) { 875 | var idx = listk[i]; 876 | var sidx = idx; 877 | if ( typeof sidx == "number" ) sidx = sidx = 1; 878 | if ( cur === null || cur === undefined || trigger ) return __lua.makeMultiReturn(idx, table[sidx]); 879 | if ( cur === idx ) trigger = true; 880 | } 881 | return null; 882 | } 883 | }; 884 | 885 | env.pcall = this.__lua.pcall; 886 | 887 | env.rawequals = function rawequals(a,b) { return a == b; }; 888 | env.rawget = __lua.rawget; 889 | env.rawset = function rawset(table, prop, val) { 890 | if ( table instanceof LuaTable ) { 891 | if ( typeof prop == "number" ) return table.numeric[prop - 1] = val; 892 | else return table.hash[prop] = val; 893 | } 894 | return table[prop] = val; 895 | }; 896 | 897 | env.something = function something(table) { 898 | var array = []; 899 | var idx = 1; 900 | while ( table[idx] !== undefined ) { 901 | array.push(table[idx]); 902 | ++idx; 903 | } 904 | return __lua.makeMultiReturn.apply(__lua, array); 905 | }; 906 | env.math = Object.assign(Object.create(Math), { 907 | huge: Infinity, 908 | pi: Math.PI, 909 | fmod: function (value, modulo) { return value % modulo; }, 910 | modf: function (value) { 911 | var ip = Math.trunc(value); 912 | return __lua.makeMultiReturn(ip, value - ip); 913 | }, 914 | ldexp: function (mantissa, exponent) { 915 | var steps = Math.min(3, Math.ceil(Math.abs(exponent) / 1023)); 916 | var result = mantissa; 917 | for (var i = 0; i < steps; i++) 918 | result *= Math.pow(2, Math.floor((exponent + i) / steps)); 919 | return result; 920 | }, 921 | random: function(m, n) { 922 | if (m) { 923 | if (n) { 924 | return m + Math.floor(Math.random() * (n - m + 1)); 925 | } else { 926 | return Math.floor(Math.random() * m); 927 | } 928 | } else { 929 | return Math.random(); 930 | } 931 | }, 932 | randomseed: () => {} 933 | }); 934 | 935 | env.setmetatable = function setmetatable(target, meta) { 936 | Object.defineProperty(target, "__metatable", {value: meta, enumerable: false, configurable: true }); 937 | return target; 938 | }; 939 | 940 | env.getmetatable = function getmetatable(taget, meta) { 941 | return taget.__metatable; 942 | }; 943 | 944 | var reduce = function reduce(arr, op) { 945 | if ( arr.length < 1 ) return undefined; 946 | var val = arr[0]; 947 | for ( var i = 1; i < arr.length; ++i ) { 948 | val = op(val, arr[i]); 949 | } 950 | return val; 951 | }; 952 | 953 | env.bit32 = { 954 | band: function band() { return reduce(arguments, function(a,b) { return a & b; }); }, 955 | bor: function bor() { return reduce(arguments, function(a,b) { return a | b; }); }, 956 | bxor: function bxor() { return reduce(arguments, function(a,b) { return a ^ b; }); }, 957 | 958 | rshift: function rshift(b, disp) { return b >> disp; } 959 | }; 960 | 961 | env.require = function require(what) { 962 | if ( what == "bit" ) return env.bit32; 963 | if ( what == "bit32" ) return env.bit32; 964 | throw "Module " + what + " not found"; 965 | }; 966 | 967 | __lua.mark(env); 968 | __lua.env = env; 969 | 970 | if (typeof window === "undefined") { 971 | for ( var idx in env ) exports[idx] = env[idx]; 972 | } 973 | -------------------------------------------------------------------------------- /public/ui-ace.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Binds a ACE Editor widget 5 | */ 6 | angular.module('ui.ace', []) 7 | .constant('uiAceConfig', {}) 8 | .directive('uiAce', ['uiAceConfig', function (uiAceConfig) { 9 | 10 | if (angular.isUndefined(window.ace)) { 11 | throw new Error('ui-ace need ace to work... (o rly?)'); 12 | } 13 | 14 | /** 15 | * Sets editor options such as the wrapping mode or the syntax checker. 16 | * 17 | * The supported options are: 18 | * 19 | * 20 | * showGutter 21 | * useWrapMode 22 | * onLoad 23 | * theme 24 | * mode 25 | * 26 | * 27 | * @param acee 28 | * @param session ACE editor session 29 | * @param {object} opts Options to be set 30 | */ 31 | var setOptions = function(acee, session, opts) { 32 | 33 | // Boolean options 34 | if (angular.isDefined(opts.showGutter)) { 35 | acee.renderer.setShowGutter(opts.showGutter); 36 | } 37 | if (angular.isDefined(opts.useWrapMode)) { 38 | session.setUseWrapMode(opts.useWrapMode); 39 | } 40 | if (angular.isDefined(opts.showInvisibles)) { 41 | acee.renderer.setShowInvisibles(opts.showInvisibles); 42 | } 43 | if (angular.isDefined(opts.showIndentGuides)) { 44 | acee.renderer.setDisplayIndentGuides(opts.showIndentGuides); 45 | } 46 | if (angular.isDefined(opts.useSoftTabs)) { 47 | session.setUseSoftTabs(opts.useSoftTabs); 48 | } 49 | 50 | // commands 51 | if (angular.isDefined(opts.disableSearch) && opts.disableSearch) { 52 | acee.commands.addCommands([ 53 | { 54 | name: 'unfind', 55 | bindKey: { 56 | win: 'Ctrl-F', 57 | mac: 'Command-F' 58 | }, 59 | exec: function () { 60 | return false; 61 | }, 62 | readOnly: true 63 | } 64 | ]); 65 | } 66 | 67 | // onLoad callback 68 | if (angular.isFunction(opts.onLoad)) { 69 | opts.onLoad(acee); 70 | } 71 | 72 | // Basic options 73 | if (angular.isString(opts.theme)) { 74 | acee.setTheme('ace/theme/' + opts.theme); 75 | } 76 | if (angular.isString(opts.mode)) { 77 | session.setMode('ace/mode/' + opts.mode); 78 | } 79 | }; 80 | 81 | return { 82 | restrict: 'EA', 83 | require: '?ngModel', 84 | link: function (scope, elm, attrs, ngModel) { 85 | 86 | /** 87 | * Corresponds the uiAceConfig ACE configuration. 88 | * @type object 89 | */ 90 | var options = uiAceConfig.ace || {}; 91 | 92 | /** 93 | * uiAceConfig merged with user options via json in attribute or data binding 94 | * @type object 95 | */ 96 | var opts = angular.extend({}, options, scope.$eval(attrs.uiAce)); 97 | 98 | /** 99 | * ACE editor 100 | * @type object 101 | */ 102 | var acee = window.ace.edit(elm[0]); 103 | 104 | /** 105 | * ACE editor session. 106 | * @type object 107 | * @see [EditSession]{@link http://ace.c9.io/#nav=api&api=edit_session} 108 | */ 109 | var session = acee.getSession(); 110 | 111 | /** 112 | * Reference to a change listener created by the listener factory. 113 | * @function 114 | * @see listenerFactory.onChange 115 | */ 116 | var onChangeListener; 117 | 118 | /** 119 | * Reference to a blur listener created by the listener factory. 120 | * @function 121 | * @see listenerFactory.onBlur 122 | */ 123 | var onBlurListener; 124 | 125 | /** 126 | * Calls a callback by checking its existing. The argument list 127 | * is variable and thus this function is relying on the arguments 128 | * object. 129 | * @throws {Error} If the callback isn't a function 130 | */ 131 | var executeUserCallback = function () { 132 | 133 | /** 134 | * The callback function grabbed from the array-like arguments 135 | * object. The first argument should always be the callback. 136 | * 137 | * @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments} 138 | * @type {*} 139 | */ 140 | var callback = arguments[0]; 141 | 142 | /** 143 | * Arguments to be passed to the callback. These are taken 144 | * from the array-like arguments object. The first argument 145 | * is stripped because that should be the callback function. 146 | * 147 | * @see [arguments]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments} 148 | * @type {Array} 149 | */ 150 | var args = Array.prototype.slice.call(arguments, 1); 151 | 152 | if (angular.isDefined(callback)) { 153 | scope.$apply(function () { 154 | if (angular.isFunction(callback)) { 155 | callback(args); 156 | } else { 157 | throw new Error('ui-ace use a function as callback.'); 158 | } 159 | }); 160 | } 161 | }; 162 | 163 | /** 164 | * Listener factory. Until now only change listeners can be created. 165 | * @type object 166 | */ 167 | var listenerFactory = { 168 | /** 169 | * Creates a change listener which propagates the change event 170 | * and the editor session to the callback from the user option 171 | * onChange. It might be exchanged during runtime, if this 172 | * happens the old listener will be unbound. 173 | * 174 | * @param callback callback function defined in the user options 175 | * @see onChangeListener 176 | */ 177 | onChange: function (callback) { 178 | return function (e) { 179 | var newValue = session.getValue(); 180 | if (newValue !== scope.$eval(attrs.value) && !scope.$$phase && !scope.$root.$$phase) { 181 | if (angular.isDefined(ngModel)) { 182 | scope.$apply(function () { 183 | ngModel.$setViewValue(newValue); 184 | }); 185 | } 186 | executeUserCallback(callback, e, acee); 187 | } 188 | }; 189 | }, 190 | /** 191 | * Creates a blur listener which propagates the editor session 192 | * to the callback from the user option onBlur. It might be 193 | * exchanged during runtime, if this happens the old listener 194 | * will be unbound. 195 | * 196 | * @param callback callback function defined in the user options 197 | * @see onBlurListener 198 | */ 199 | onBlur: function (callback) { 200 | return function () { 201 | executeUserCallback(callback, acee); 202 | }; 203 | } 204 | }; 205 | 206 | attrs.$observe('readonly', function (value) { 207 | acee.setReadOnly(value === 'true'); 208 | }); 209 | 210 | // Value Blind 211 | if (angular.isDefined(ngModel)) { 212 | ngModel.$formatters.push(function (value) { 213 | if (angular.isUndefined(value) || value === null) { 214 | return ''; 215 | } 216 | else if (angular.isObject(value) || angular.isArray(value)) { 217 | throw new Error('ui-ace cannot use an object or an array as a model'); 218 | } 219 | return value; 220 | }); 221 | 222 | ngModel.$render = function () { 223 | session.setValue(ngModel.$viewValue); 224 | }; 225 | } 226 | 227 | // set the options here, even if we try to watch later, if this 228 | // line is missing things go wrong (and the tests will also fail) 229 | setOptions(acee, session, opts); 230 | 231 | // Listen for option updates 232 | scope.$watch( attrs.uiAce, function() { 233 | opts = angular.extend({}, options, scope.$eval(attrs.uiAce)); 234 | 235 | // unbind old change listener 236 | session.removeListener('change', onChangeListener); 237 | 238 | // bind new change listener 239 | onChangeListener = listenerFactory.onChange(opts.onChange); 240 | session.on('change', onChangeListener); 241 | 242 | // unbind old blur listener 243 | //session.removeListener('blur', onBlurListener); 244 | acee.removeListener('blur', onBlurListener); 245 | 246 | // bind new blur listener 247 | onBlurListener = listenerFactory.onBlur(opts.onBlur); 248 | acee.on('blur', onBlurListener); 249 | 250 | setOptions(acee, session, opts); 251 | }, /* deep watch */ true ); 252 | 253 | // EVENTS 254 | onChangeListener = listenerFactory.onChange(opts.onChange); 255 | session.on('change', onChangeListener); 256 | 257 | onBlurListener = listenerFactory.onBlur(opts.onBlur); 258 | acee.on('blur', onBlurListener); 259 | 260 | elm.on('$destroy', function () { 261 | acee.session.$stopWorker(); 262 | acee.destroy(); 263 | }); 264 | 265 | scope.$watch(function() { 266 | return [elm[0].offsetWidth, elm[0].offsetHeight]; 267 | }, function() { 268 | acee.resize(); 269 | acee.renderer.updateFull(); 270 | }, true); 271 | 272 | } 273 | }; 274 | }]); 275 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | 4 | var peg = require("pegjs"); 5 | var gen = require("escodegen"); 6 | var fs = require("fs"); 7 | 8 | var helpers = fs.readFileSync("helpers.js").toString(); 9 | var lang = fs.readFileSync("lua.pegjs").toString(); 10 | var parser = peg.generate(helpers + lang, {output: 'source'}); 11 | 12 | app.get('/piler.js', function(req,res) { 13 | res.setHeader('content-type', 'text/javascript'); 14 | res.write("window.parser = "); 15 | res.write(parser); 16 | res.end(); 17 | }); 18 | 19 | app.use(express.static(__dirname + '/public')); 20 | 21 | app.listen(4000); 22 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | local pooja = {} 2 | -------------------------------------------------------------------------------- /test_spec.js: -------------------------------------------------------------------------------- 1 | var peg = require("pegjs"); 2 | var gen = require("escodegen"); 3 | var fs = require("fs"); 4 | var vm = require("vm"); 5 | 6 | 7 | var helpers = fs.readFileSync("helpers.js").toString(); 8 | var lang = fs.readFileSync("lua.pegjs").toString(); 9 | var parser = peg.generate(helpers + lang); 10 | var exec = require('child_process').exec; 11 | 12 | function leval(src) { 13 | var AST; 14 | try { 15 | AST = parser.parse(src, {forceVar: true, decorateLuaObjects: true, luaCalls: true, luaOperators: true, encloseWithFunctions: false }); 16 | } catch ( e ) { 17 | return JSON.stringify(e); 18 | } 19 | 20 | return function(code) { 21 | //console.log(code); 22 | return function() { return "(function() " + code + ")()"; } 23 | }(gen.generate(AST)); 24 | } 25 | 26 | tests = [ 27 | [" return 10" , 10], 28 | ["return 10" , 10], 29 | ["return 20 ", 20], 30 | [ 31 | ['if true then', 32 | ' return "yum"', 33 | 'else ', 34 | ' return "ouch"', 35 | 'end'], "yum" 36 | ], 37 | ['if 0 then return "yum" else return "ouch" end', "ouch" ], 38 | ['add = function(a,b) return a+b end return add(2,5)', 7], 39 | ['function add(a,b) return a+b end return add(2,5)', 7], 40 | [ 41 | [ 42 | 'function fastfib(n)', 43 | 'fibs = {1,1}', 44 | 'local i = 2', 45 | 'while i < n do', 46 | ' i = i + 1', 47 | ' fibs[i] = fibs[i-1] + fibs[i-2]', 48 | 'end', 49 | 'return fibs[n]', 50 | 'end', 51 | 'return fastfib(10)' 52 | ], 55 53 | ], 54 | [ 55 | [ 56 | 'local total = 0', 57 | 'for i=1,20,3 do total = total + i end', 58 | 'return total' 59 | ], 70 60 | ], 61 | [ 62 | [ 63 | 'eval("var a = [1,2,3]")', 64 | 'return a[1]' 65 | ],1 66 | ], 67 | [ 68 | [ 69 | 'eval("var a = [1,2,3]")', 70 | 'a[2] = 7', 71 | 'return eval("a.toString()")' 72 | ],"1,7,3" 73 | ], 74 | [ 75 | [ 76 | 'eval("var ct = function(w) { return \'!\' + w + \'!\' + (typeof w); }")', 77 | 'function add(a,b) return 7 + a + b, b - a end', 78 | 'local sum = add(2,3)', 79 | 'return ct(sum)', 80 | ],"!12!number" 81 | ], 82 | [ 83 | [ 84 | 'function add(a,b) return a*a+b*b,0 end', 85 | 'local o = add(3,4)', 86 | 'return ("a" .. o .. add(5,12))' 87 | ], 'a25169' 88 | ], 89 | [ 90 | [ 91 | 'eval("var json = function(w) { return JSON.stringify(w); }")', 92 | 'function g() return {x=1, y=20} end', 93 | 'o = g()', 94 | 'return json(o) .. " " .. eval("(function(x) { return x.__luaType; })(o)")', 95 | ],'{"x":1,"y":20} table' 96 | ], 97 | [ 98 | [ 99 | 'eval("var array = [1,1,2,5,7];")', 100 | 'return array[4]' 101 | ],5 102 | ], 103 | [ 104 | [ 105 | 'eval("var array = [1,1,2,5,7];")', 106 | 'out = "pairs"', 107 | 'for k,v in pairs(array) do out = out .. " " .. k .. "," .. v end', 108 | 'return out' 109 | ],'pairs 1,1 2,1 3,2 4,5 5,7' 110 | ], 111 | [ 112 | [ 113 | 'eval("var array = [1,1,2,5,7];")', 114 | 'out = "ipairs"', 115 | 'for k,v in ipairs(array) do out = out .. " " .. k .. "," .. v end', 116 | 'return out' 117 | ],'ipairs 1,1 2,1 3,2 4,5 5,7' 118 | ], 119 | [ 120 | ['while false do end'], 121 | void 0 122 | ] 123 | 124 | ]; 125 | 126 | function makenv() { 127 | var goodies = require("./public/stdlib.js"); 128 | return (function(stdout) { 129 | var env = {}; 130 | for ( var i in goodies ) env[i] = goodies[i]; 131 | 132 | env.getStdOut = function() { return stdout; } 133 | env.io = { 134 | write: function() { 135 | Array.prototype.forEach.call(arguments, function(s,i) { 136 | stdout = stdout + s; 137 | }); 138 | } 139 | }; 140 | 141 | env.print = function() { 142 | var s = Array.prototype.slice.call(arguments) 143 | .map(function(x) { return env.tostring(x); }) 144 | .join("\t"); 145 | 146 | env.io.write(s + "\n"); 147 | //console.log(s); 148 | }; 149 | 150 | env.__lua.mark(env); 151 | 152 | return env; 153 | })(""); 154 | 155 | } 156 | 157 | describe("Simple Tests", function() { 158 | var idx = 0; 159 | tests.forEach(function(nfo) { 160 | var code = nfo[0]; 161 | var result = nfo[1] 162 | it("testSimple" + idx++, function(done) { 163 | if ( typeof(code) != "string" ) code = code.join("\n"); 164 | 165 | var v = leval(code); 166 | expect(typeof(v)).toEqual("function"); 167 | var env = makenv(); 168 | var a = vm.runInNewContext(v(), makenv(), "vm"); 169 | expect(a).toEqual(result); 170 | done(); 171 | }); 172 | 173 | }); 174 | }); 175 | 176 | function testDirectory(dir) { 177 | return function() { 178 | fs.readdirSync(dir).forEach(function(f) { 179 | it(dir + '/' + f, function(done) { 180 | var code = fs.readFileSync(dir + '/' + f).toString(); 181 | //console.log("Start " + f); 182 | var v = leval(code); 183 | if ( typeof(v) != "function" ) throw v; 184 | 185 | (function(env) { 186 | var a = vm.runInNewContext(v(), env, "vm"); 187 | exec('lua ' + dir + '/' + f, function(err, stdout, stderr) { 188 | if ( stderr !== "" ) expect(false).toBe(true); 189 | expect(env.getStdOut()).toEqual(stdout.replace(/\r\n/g,"\n")); 190 | done(); 191 | }); 192 | 193 | })(makenv()); 194 | //console.log("End " + f); 195 | }); 196 | }); 197 | }; 198 | } 199 | 200 | describe("Lua Tests", testDirectory('./lua-tests')); 201 | 202 | describe("Lua More Tests", testDirectory('./lua-testmore')); 203 | 204 | describe("Lua Lang ToolKit", testDirectory('./lua-lltk')); 205 | 206 | 207 | --------------------------------------------------------------------------------
{{error}} 70 |