├── LICENSE ├── README.md ├── b95.wren ├── build.cmd ├── build ├── build.wren └── build_lib.wren ├── build_lib.cmd ├── lib ├── coroutine.wren ├── debug.wren ├── math.wren ├── string.wren ├── syntax.wren ├── table.wren ├── tuple.wren └── utf8.wren ├── test.cmd ├── test ├── block.lua ├── class.lua ├── condition.lua ├── coroutine.lua ├── function.lua ├── hello.lua ├── lib.lua ├── loop.lua ├── math.lua ├── string.lua ├── table.lua ├── test.wren ├── test_lib.wren └── utf8.lua ├── test_lib.cmd ├── util ├── lua.exe ├── syntax.lua └── test_syntax.lua └── wren.exe /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2019 - 2020 Tony Wang 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## B95 2 | 3 | **A [Lua](http://www.lua.org/) to [Wren](http://wren.io/) compiler in Wren** 4 | 5 | This library was born from the idea of using Lua in Wren project. There are not many ways possible: 6 | 7 | Making both Lua and Wren bindings at the native side. Requires extra coding; cannot use Wren objects from Lua, vice versa. 8 | 9 | Compiling Lua code to an intermediate denotion, then running it at the scripting side. Slow. 10 | 11 | Compiling Lua code to Wren VM instructions, then running it on the VM. Need to stick tightly to specific version of Wren implementation. 12 | 13 | Compiling Lua code to Wren source code, then running it through Wren. Why not. 14 | 15 | ### 1. How it works 16 | 17 | Lua's dynamic typing and scripting nature is quite similar to Wren. So the typing system, execution flow and memory management parts can be straightforward migrated. The main difference is that Wren uses a classy object model, but Lua uses prototyping. Anyway, it's still translatable with a little bit wrought work. 18 | 19 | #### 1.1 Syntax translation 20 | 21 | **Multiple assignment** 22 | 23 | B95 introduced an internal tuple helper for multiple assignment. Eg. 24 | 25 | ```lua 26 | a, b = b, a 27 | ``` 28 | 29 | compiles to 30 | 31 | ```dart 32 | var tmp_0 = LTuple.new(b, a) 33 | a = tmp_0[0] 34 | b = tmp_0[1] 35 | ``` 36 | 37 | Note: to unpack values properly from a tuple returned by some functions (eg. `coroutine.yield`), add an extra variable on the left side of assign operator to hint tuple unpacking. Eg. `_` in `somevar, _ = coroutine.yield(1, 2)`. Otherwise a single variable would get returned tuple object per se. 38 | 39 | **Function definition** 40 | 41 | `function func() end` in class compiles to `static func() { }`. 42 | 43 | `function func(self) end` in class compiles to `func() { }`. 44 | 45 | `function func() end` compiles to `func = Fn.new { | | }`. 46 | 47 | `function () end` compiles to `Fn.new { | | }`. 48 | 49 | **Function call** 50 | 51 | `Kls.func()` compiles to `Kls.func()`. 52 | 53 | `obj:func()` compiles to `obj.func()`. 54 | 55 | `obj.func()` compiles to `obj.func()`. 56 | 57 | Otherwise eg. with `obj['func']()`, compiles to `obj['func'].call()`. 58 | 59 | Note: use `call(func, args)` to hint for `func.call(args)`; `apply(method, args)` to hint for `method(args)`. 60 | 61 | #### 1.2 Library port 62 | 63 | Lua standard library is rewritten in Wren for B95's referencing. The source code of the port is in the "[lib](lib)" directory, and has been already built by "[build/build.wren](build/build.wren)", so generally you do not need to build it manually. 64 | 65 | #### 1.3 External registration 66 | 67 | Like widespread scripting languages, B95 allows using external function registration to extend the language. 68 | 69 | ### 2. How to use 70 | 71 | "[b95.wren](b95.wren)" is the only file of this compiler, just copy it to your project. B95 is close to the original Lua, such as table is used for anything complex, array starts from 1, etc. Moreover, B95 offers more natural class. 72 | 73 | #### 2.1 Dependency 74 | 75 | Wren 0.2.0 or above. 76 | 77 | There's a Windows executable "wren.exe" in the root directory of this repository, which was prebuilt via VC++ 2015 without modification to the official distribution. 78 | 79 | #### 2.2 Simple 80 | 81 | ```dart 82 | import "b95" for Lua 83 | 84 | var lua = Lua.new() 85 | var code = lua.compile("print('hello')") 86 | System.print(code.lines) 87 | ``` 88 | 89 | #### 2.3 Eval it 90 | 91 | ```dart 92 | import "io" for File 93 | import "meta" for Meta 94 | import "b95" for Lua 95 | 96 | var lua = Lua.new() 97 | var code = lua.compile(File.read("tests/hello.lua")) 98 | System.print(code.lines) 99 | Meta.eval(code.toString) 100 | ``` 101 | 102 | See `class Code` in "[b95.wren](b95.wren)" for details of the returned object by `Lua.compile`. 103 | 104 | #### 2.4 Class 105 | 106 | ```lua 107 | Klass = class( 108 | { 109 | -- Constructor `new` compiles to `construct new()`. 110 | new = function (self) 111 | end, 112 | 113 | -- Compiles to Wren getter/setter. 114 | field0 = 0, 115 | get_field1 = function (self) 116 | if self._field1 == nil then 117 | self._field1 = 0 118 | end 119 | 120 | return self._field1 121 | end, 122 | set_field1 = function (self, value) 123 | self._field1 = value 124 | end, 125 | 126 | -- Function without `self` compiles to static method. 127 | func0 = function (a, b) 128 | local c = a / b 129 | 130 | return c 131 | end, 132 | 133 | -- Function with `self` compiles to instance method. 134 | func1 = function (self, c, d) 135 | self['field0'] = c 136 | self.field1 = d 137 | end 138 | }, 139 | base -- Base class, optional. 140 | ) 141 | 142 | obj = new(Klass) -- Instantiate a class, compiles to `Klass.new()`. 143 | ``` 144 | 145 | This is also valid Lua syntax, so that it's possible to write compatible code both in B95 and (with the help of "[util/syntax.lua](util/syntax.lua)") in C-Lua. 146 | 147 | #### 2.5 Table 148 | 149 | ```lua 150 | tbl = { 'uno', 'dos', 'thres' } 151 | tbl['key'] = 'value' 152 | 153 | for k, v in pairs(tbl) do 154 | print(k, v) 155 | end 156 | 157 | print(length(tbl)) 158 | ``` 159 | 160 | #### 2.6 Importing 161 | 162 | ```lua 163 | obj = require 'path' 164 | ``` 165 | 166 | B95 invokes callback set by `Lua.onRequire` during compile time for customized importing. Eg. 167 | 168 | ```dart 169 | lua.onRequire( 170 | Fn.new { | path, klass | 171 | if (path == "bar" && klass == "foo") { 172 | return "import \"path\" for module" // This replaces matched requirement. 173 | } 174 | 175 | return null 176 | } 177 | ) 178 | ``` 179 | 180 | #### 2.7 Registering 181 | 182 | B95 invokes callback set by `Lua.onFunction` during compile time for customized functions. Eg. 183 | 184 | ```dart 185 | lua.onFunction( 186 | Fn.new { | module, func | 187 | if (module == "foo" && func == "bar") { 188 | return { "lib": null, "function": "lib.func" } // This replaces function invoking. 189 | } 190 | 191 | return null 192 | } 193 | ) 194 | ``` 195 | 196 | ### 3. Feature list 197 | 198 | | Syntax | Lua | B95 | 199 | |----|----|----| 200 | | `and`, `or`, `not` | ✓ | ✓ | 201 | | `local` | ✓ | ✓ | 202 | | `false`, `true` | ✓ | ✓ | 203 | | `nil` | ✓ | ✓ | 204 | | `if-then-elseif-else-end` | ✓ | ✓ | 205 | | `do-end` | ✓ | ✓ | 206 | | `for-do-end` | ✓ | ✓ | 207 | | `for-in-do-end` | ✓ | ✓ | 208 | | `while-do-end` | ✓ | ✓ | 209 | | `repeat-until` | ✓ | ✓ | 210 | | `break` | ✓ | ✓ | 211 | | `function` | ✓ | ✓ | 212 | | `return` | ✓ | ✓ | 213 | | `goto`, `::` | ✓ | | 214 | | `__add`, `__sub`, `__mul`, `__div`, `__mod` | ✓ | ✓ | 215 | | `__unm` | ✓ | ✓ | 216 | | `__idiv` | ✓ | | 217 | | `__pow` | ✓ | | 218 | | `__band` | ✓ | ✓ | 219 | | `__bor` | ✓ | ✓ | 220 | | `__bxor` | ✓ | ✓ | 221 | | `__bnot` | ✓ | | 222 | | `__shl`, `__shr` | ✓ | ✓ | 223 | | `__concat` | ✓ | ✓ | 224 | | `__len` | ✓ | | 225 | | `__eq`, `__lt`, `__le` | ✓ | ✓ | 226 | | `__index` | ✓ | | 227 | | `__newindex` | ✓ | | 228 | | `__call` | ✓ | ✓ | 229 | | `=` | ✓ | ✓ | 230 | | `+`, `-`, `*`, `/`, `%` | ✓ | ✓ | 231 | | `//` | ✓ | | 232 | | `^` | ✓ | | 233 | | `&` | ✓ | ✓ | 234 | | `\|` | ✓ | ✓ | 235 | | `~` | ✓ | ✓ (binary XOR only) | 236 | | `<<`, `>>` | ✓ | ✓ | 237 | | `#` | ✓ | | 238 | | `==`, `~=`, `<=`, `>=`, `<`, `>` | ✓ | ✓ | 239 | | `..` | ✓ | ✓ | 240 | | `...` | ✓ | | 241 | | `-- comment` | ✓ | ✓ | 242 | | `--[[ multiline`
`comment --]]` | ✓ | ✓ | 243 | | `require` | ✓ | ✓ | 244 | | `class` | | ✓ | 245 | | `new` | | ✓ | 246 | | `is` | | ✓ | 247 | 248 | | Lib | Lua | B95 | 249 | |----|----|----| 250 | | `assert(v [, message])` | ✓ | ✓ | 251 | | `collectgarbage([opt [, arg]])` | ✓ | ✓ | 252 | | `dofile([filename])` | ✓ | | 253 | | `error(message [, level])` | ✓ | ✓ | 254 | | `_G` | ✓ | | 255 | | `getmetatable(object)` | ✓ | | 256 | | `ipairs(t)` | ✓ | ✓ | 257 | | `load(chunk [, chunkname [, mode [, env]]])` | ✓ | | 258 | | `loadfile([filename [, mode [, env]]])` | ✓ | | 259 | | `next(table [, index])` | ✓ | ✓ (not recommended) | 260 | | `pairs(t)` | ✓ | ✓ | 261 | | `pcall(f [, arg1, ...])` | ✓ | | 262 | | `print(...)` | ✓ | ✓ | 263 | | `rawequal(v1, v2)` | ✓ | ✓ | 264 | | `rawget(table, index)` | ✓ | ✓ | 265 | | `rawlen(v)` | ✓ | ✓ | 266 | | `rawset(table, index, value)` | ✓ | ✓ | 267 | | `select(index, ...)` | ✓ | ✓ (partial) | 268 | | `setmetatable(table, metatable)` | ✓ | | 269 | | `tonumber(e [, base])` | ✓ | ✓ (partial) | 270 | | `tostring(v)` | ✓ | ✓ | 271 | | `type(v)` | ✓ | ✓ | 272 | | `xpcall(f, msgh [, arg1, ···])` | ✓ | | 273 | | `coroutine.create(f)` | ✓ | ✓ | 274 | | `coroutine.isyieldable()` | ✓ | ✓ | 275 | | `coroutine.resume(co [, val1, ...])` | ✓ | ✓ | 276 | | `coroutine.running()` | ✓ | ✓ | 277 | | `coroutine.status(co)` | ✓ | | 278 | | `coroutine.wrap(f)` | ✓ | | 279 | | `coroutine.yield(...)` | ✓ | ✓ | 280 | | `string.byte(s [, i [, j]])` | ✓ | ✓ | 281 | | `string.char(...)` | ✓ | ✓ | 282 | | `string.dump(function [, strip])` | ✓ | | 283 | | `string.find(s, pattern [, init [, plain]])` | ✓ | | 284 | | `string.format(formatstring, ...)` | ✓ | | 285 | | `string.gmatch(s, pattern)` | ✓ | | 286 | | `string.gsub(s, pattern, repl [, n])` | ✓ | | 287 | | `string.len(s)` | ✓ | ✓ | 288 | | `string.lower(s)` | ✓ | ✓ | 289 | | `string.match(s, pattern [, init])` | ✓ | | 290 | | `string.pack(fmt, v1, v2, ...)` | ✓ | | 291 | | `string.packsize(fmt)` | ✓ | | 292 | | `string.rep(s, n [, sep])` | ✓ | ✓ | 293 | | `string.reverse(s)` | ✓ | ✓ | 294 | | `string.sub(s, i [, j])` | ✓ | ✓ | 295 | | `string.unpack(fmt, s [, pos])` | ✓ | | 296 | | `string.upper(s)` | ✓ | ✓ | 297 | | `utf8.char(···)` | ✓ | ✓ | 298 | | `utf8.charpattern` | ✓ | | 299 | | `utf8.codes(s)` | ✓ | ✓ | 300 | | `utf8.codepoint(s [, i [, j]])` | ✓ | ✓ | 301 | | `utf8.len(s [, i [, j]])` | ✓ | ✓ | 302 | | `utf8.offset(s, n [, i])` | ✓ | | 303 | | `table.concat(list [, sep [, i [, j]]])` | ✓ | ✓ | 304 | | `table.insert(list, [pos,] value)` | ✓ | ✓ | 305 | | `table.move(a1, f, e, t [, a2])` | ✓ | | 306 | | `table.pack(...)` | ✓ | | 307 | | `table.remove(list [, pos])` | ✓ | ✓ | 308 | | `table.sort(list [, comp])` | ✓ | | 309 | | `table.unpack(list [, i [, j]])` | ✓ | | 310 | | `math.abs(x)` | ✓ | ✓ | 311 | | `math.acos(x)` | ✓ | ✓ | 312 | | `math.asin(x)` | ✓ | ✓ | 313 | | `math.atan(y [, x])` | ✓ | ✓ | 314 | | `math.ceil(x)` | ✓ | ✓ | 315 | | `math.cos(x)` | ✓ | ✓ | 316 | | `math.deg(x)` | ✓ | ✓ | 317 | | `math.exp(x)` | ✓ | ✓ | 318 | | `math.floor(x)` | ✓ | ✓ | 319 | | `math.fmod(x, y)` | ✓ | ✓ | 320 | | `math.huge` | ✓ | ✓ | 321 | | `math.log(x [, base])` | ✓ | ✓ | 322 | | `math.max(x, ...)` | ✓ | ✓ | 323 | | `math.maxinteger` | ✓ | | 324 | | `math.min(x, ...)` | ✓ | ✓ | 325 | | `math.mininteger` | ✓ | | 326 | | `math.modf(x)` | ✓ | ✓ | 327 | | `math.pi` | ✓ | ✓ | 328 | | `math.rad(x)` | ✓ | ✓ | 329 | | `math.random([m [, n]])` | ✓ | ✓ | 330 | | `math.randomseed(x)` | ✓ | ✓ | 331 | | `math.sin(x)` | ✓ | ✓ | 332 | | `math.sqrt(x)` | ✓ | ✓ | 333 | | `math.tan(x)` | ✓ | ✓ | 334 | | `math.tointeger(x)` | ✓ | ✓ | 335 | | `math.type(x)` | ✓ | ✓ | 336 | | `math.ult(m, n)` | ✓ | | 337 | | `io` | ✓ | | 338 | | `file` | ✓ | | 339 | | `os` | ✓ | | 340 | | `debug` | ✓ | | 341 | 342 | ### 4. Who is B95 343 | 344 | He is a [bird](https://en.wikipedia.org/wiki/B95_(bird)). 345 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | call wren.exe build\build.wren 3 | echo Ready! 4 | -------------------------------------------------------------------------------- /build/build.wren: -------------------------------------------------------------------------------- 1 | import "io" for File, FileFlags 2 | 3 | var libs = [ 4 | { 5 | "path": "lib/debug.wren", 6 | "tag": "// Debug patch.", 7 | "var": "__debug" 8 | }, 9 | { 10 | "path": "lib/tuple.wren", 11 | "tag": "// Tuple lib.", 12 | "var": "__tuple" 13 | }, 14 | { 15 | "path": "lib/syntax.wren", 16 | "tag": "// Syntax lib.", 17 | "var": "__syntax" 18 | }, 19 | { 20 | "path": "lib/coroutine.wren", 21 | "tag": "// Coroutine lib.", 22 | "var": "__coroutine" 23 | }, 24 | { 25 | "path": "lib/string.wren", 26 | "tag": "// String lib.", 27 | "var": "__string" 28 | }, 29 | { 30 | "path": "lib/utf8.wren", 31 | "tag": "// Utf8 lib.", 32 | "var": "__utf8" 33 | }, 34 | { 35 | "path": "lib/table.wren", 36 | "tag": "// Table lib.", 37 | "var": "__table" 38 | }, 39 | { 40 | "path": "lib/math.wren", 41 | "tag": "// Math lib.", 42 | "var": "__math" 43 | } 44 | ] 45 | 46 | var embed = Fn.new { | src, lib | 47 | var code = File.read(lib["path"]) 48 | code = code.replace("\\\"", "__squote__").replace("\"", "\\\"").replace("__squote__", "\\\\\\\"") // Escapes. 49 | code = code.replace("\t", " ") // Indent with space. 50 | var lns = code.split("\r\n") 51 | if (lns[lns.count - 1] == "") { 52 | lns = lns.take(lns.count - 1) 53 | } 54 | code = "\t\t\t" + lib["var"] + " = \"\" +\r\n" 55 | code = code + lns.map(Fn.new { | ln | "\t\t\t\t\"" + ln + "\\r\\n\"" }).join(" +\r\n") 56 | 57 | var begin = src.indexOf(lib["tag"]) 58 | var end = src.indexOf(lib["tag"], begin + 1) 59 | var head = src.take(begin + lib["tag"].count).join("") + "\r\n" 60 | var tail = " " + src.skip(end).join("") 61 | 62 | return head + code + tail 63 | } 64 | 65 | // Embeds './lib/*.wren' into './b95.wren'. 66 | var src = File.read("b95.wren") 67 | libs.each( 68 | Fn.new { | lib | 69 | var n = "\"" + lib["path"] + "\"" 70 | System.print("Embed library %(n).") 71 | 72 | src = embed.call(src, lib) 73 | } 74 | ) 75 | File.openWithFlags( 76 | "b95.wren", FileFlags.writeOnly | FileFlags.create | FileFlags.truncate, 77 | Fn.new { | file | 78 | file.writeBytes(src) 79 | } 80 | ) 81 | -------------------------------------------------------------------------------- /build/build_lib.wren: -------------------------------------------------------------------------------- 1 | import "io" for File, FileFlags 2 | 3 | var libs = [ 4 | { 5 | "path": "lib/debug.wren", 6 | "tag": "// Debug patch.", 7 | "var": "__debug" 8 | }, 9 | { 10 | "path": "lib/tuple.wren", 11 | "tag": "// Tuple lib.", 12 | "var": "__tuple" 13 | }, 14 | { 15 | "path": "lib/syntax.wren", 16 | "tag": "// Syntax lib.", 17 | "var": "__syntax" 18 | }, 19 | { 20 | "path": "lib/coroutine.wren", 21 | "tag": "// Coroutine lib.", 22 | "var": "__coroutine" 23 | }, 24 | { 25 | "path": "lib/string.wren", 26 | "tag": "// String lib.", 27 | "var": "__string" 28 | }, 29 | { 30 | "path": "lib/utf8.wren", 31 | "tag": "// Utf8 lib.", 32 | "var": "__utf8" 33 | }, 34 | { 35 | "path": "lib/table.wren", 36 | "tag": "// Table lib.", 37 | "var": "__table" 38 | }, 39 | { 40 | "path": "lib/math.wren", 41 | "tag": "// Math lib.", 42 | "var": "__math" 43 | } 44 | ] 45 | 46 | var embed = Fn.new { | src, lib | 47 | var code = File.read(lib["path"]) 48 | var begin = src.indexOf(lib["tag"]) 49 | var end = src.indexOf(lib["tag"], begin + 1) 50 | var head = src.take(begin + lib["tag"].count).join("") + "\r\n" 51 | var tail = src.skip(end).join("") 52 | 53 | return head + code + tail 54 | } 55 | 56 | // Embeds './lib/*.wren' into './test/test_lib.wren'. 57 | var src = File.read("test/test_lib.wren") 58 | libs.each( 59 | Fn.new { | lib | 60 | var n = "\"" + lib["path"] + "\"" 61 | System.print("Embed library %(n).") 62 | 63 | src = embed.call(src, lib) 64 | } 65 | ) 66 | File.openWithFlags( 67 | "test/test_lib.wren", FileFlags.writeOnly | FileFlags.create | FileFlags.truncate, 68 | Fn.new { | file | 69 | file.writeBytes(src) 70 | } 71 | ) 72 | -------------------------------------------------------------------------------- /build_lib.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | call wren.exe build\build_lib.wren 3 | echo Ready! 4 | -------------------------------------------------------------------------------- /lib/coroutine.wren: -------------------------------------------------------------------------------- 1 | // Coroutine begin. 2 | class LCoroutine { 3 | static temporary_ { 4 | var result = __temporary 5 | __temporary = null 6 | 7 | return result 8 | } 9 | static temporary_ = (value) { 10 | __temporary = value 11 | } 12 | 13 | static create(fiber) { 14 | var result = fiber 15 | if (fiber is Fn) { 16 | if (fiber.arity == 0) { 17 | result = Fiber.new { fiber.call() } 18 | } else if (fiber.arity == 1) { 19 | result = Fiber.new { | arg0 | fiber.call(arg0) } 20 | } else if (fiber.arity == 2) { 21 | result = Fiber.new { | argv | fiber.call(argv[0], argv[1]) } 22 | } else if (fiber.arity == 3) { 23 | result = Fiber.new { | argv | fiber.call(argv[0], argv[1], argv[2]) } 24 | } else if (fiber.arity == 4) { 25 | result = Fiber.new { | argv | fiber.call(argv[0], argv[1], argv[2], argv[3]) } 26 | } 27 | } 28 | 29 | return result 30 | } 31 | static wrap(f) { 32 | Fiber.abort("Not implemented.") 33 | } 34 | 35 | static resume(co) { 36 | if (co.isDone) { 37 | return LTuple.new(false, "Cannot resume dead coroutine.") 38 | } 39 | temporary_ = null 40 | 41 | return LTuple.new(true, co.call()) 42 | } 43 | static resume(co, arg0) { 44 | if (co.isDone) { 45 | return LTuple.new(false, "Cannot resume dead coroutine.") 46 | } 47 | temporary_ = arg0 48 | 49 | return LTuple.new(true, co.call(arg0)) 50 | } 51 | static resume(co, arg0, arg1) { 52 | if (co.isDone) { 53 | return LTuple.new(false, "Cannot resume dead coroutine.") 54 | } 55 | temporary_ = LTuple.new(arg0, arg1) 56 | 57 | return LTuple.new(true, co.call([ arg0, arg1 ])) 58 | } 59 | static resume(co, arg0, arg1, arg2) { 60 | if (co.isDone) { 61 | return LTuple.new(false, "Cannot resume dead coroutine.") 62 | } 63 | temporary_ = LTuple.new(arg0, arg1, arg2) 64 | 65 | return LTuple.new(true, co.call([ arg0, arg1, arg2 ])) 66 | } 67 | static resume(co, arg0, arg1, arg2, arg3) { // Supports up to 4 parameters. 68 | if (co.isDone) { 69 | return LTuple.new(false, "Cannot resume dead coroutine.") 70 | } 71 | temporary_ = LTuple.new(arg0, arg1, arg2, arg3) 72 | 73 | return LTuple.new(true, co.call([ arg0, arg1, arg2, arg3 ])) 74 | } 75 | static yield() { 76 | Fiber.yield() 77 | 78 | return temporary_ 79 | } 80 | static yield(arg0) { 81 | Fiber.yield(arg0) 82 | 83 | return temporary_ 84 | } 85 | static yield(arg0, arg1) { 86 | Fiber.yield(LTuple.new(arg0, arg1)) 87 | 88 | return temporary_ 89 | } 90 | static yield(arg0, arg1, arg2) { 91 | Fiber.yield(LTuple.new(arg0, arg1, arg2)) 92 | 93 | return temporary_ 94 | } 95 | static yield(arg0, arg1, arg2, arg3) { // Supports up to 4 parameters. 96 | Fiber.yield(LTuple.new(arg0, arg1, arg2, arg3)) 97 | 98 | return temporary_ 99 | } 100 | 101 | static isYieldable() { 102 | return true 103 | } 104 | static running() { 105 | return Fiber.current 106 | } 107 | static status(co) { 108 | Fiber.abort("Not implemented.") 109 | } 110 | } 111 | // Coroutine end. 112 | -------------------------------------------------------------------------------- /lib/debug.wren: -------------------------------------------------------------------------------- 1 | // Debug begin. 2 | class LDebug { 3 | construct new() { 4 | } 5 | 6 | lastLine { _lastLine } 7 | lastColumn { _lastColumn } 8 | setLastLocation(ln, col) { 9 | _lastLine = ln 10 | _lastColumn = col 11 | } 12 | } 13 | var ldebug = LDebug.new() 14 | // Debug end. 15 | -------------------------------------------------------------------------------- /lib/math.wren: -------------------------------------------------------------------------------- 1 | // Math begin. 2 | import "random" for Random 3 | 4 | class LMath { 5 | static abs(x) { 6 | return x.abs 7 | } 8 | static acos(x) { 9 | return x.acos 10 | } 11 | static asin(x) { 12 | return x.asin 13 | } 14 | static atan(y) { 15 | return y.atan 16 | } 17 | static atan(y, x) { 18 | return y.atan(x) 19 | } 20 | static ceil(x) { 21 | return x.ceil 22 | } 23 | static cos(x) { 24 | return x.cos 25 | } 26 | static deg(x) { 27 | return x / Num.pi * 180 28 | } 29 | static exp(x) { 30 | var e = 2.7182818284590452353602874713527 31 | 32 | return e.pow(x) 33 | } 34 | static floor(x) { 35 | return x.floor 36 | } 37 | static fmod(x, y) { 38 | return x - y * (x / y).floor 39 | } 40 | static huge { 41 | return 1 / 0 42 | } 43 | static log(x) { 44 | return x.log 45 | } 46 | static log(x, base) { 47 | return x.log / base.log 48 | } 49 | static max(arg0, arg1) { 50 | return arg0 > arg1 ? arg0 : arg1 51 | } 52 | static max(arg0, arg1, arg2) { 53 | return max(max(arg0, arg1), arg2) 54 | } 55 | static max(arg0, arg1, arg2, arg3) { 56 | return max(max(max(arg0, arg1), arg2), arg3) 57 | } 58 | static max(arg0, arg1, arg2, arg3, arg4) { 59 | return max(max(max(max(arg0, arg1), arg2), arg3), arg4) 60 | } 61 | static max(arg0, arg1, arg2, arg3, arg4, arg5) { 62 | return max(max(max(max(max(arg0, arg1), arg2), arg3), arg4), arg5) 63 | } 64 | static max(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 65 | return max(max(max(max(max(max(arg0, arg1), arg2), arg3), arg4), arg5), arg6) 66 | } 67 | static max(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 68 | return max(max(max(max(max(max(max(arg0, arg1), arg2), arg3), arg4), arg5), arg6), arg7) 69 | } 70 | static maxInteger { 71 | Fiber.abort("Not implemented.") 72 | } 73 | static min(arg0, arg1) { 74 | return arg0 < arg1 ? arg0 : arg1 75 | } 76 | static min(arg0, arg1, arg2) { 77 | return min(min(arg0, arg1), arg2) 78 | } 79 | static min(arg0, arg1, arg2, arg3) { 80 | return min(min(min(arg0, arg1), arg2), arg3) 81 | } 82 | static min(arg0, arg1, arg2, arg3, arg4) { 83 | return min(min(min(min(arg0, arg1), arg2), arg3), arg4) 84 | } 85 | static min(arg0, arg1, arg2, arg3, arg4, arg5) { 86 | return min(min(min(min(min(arg0, arg1), arg2), arg3), arg4), arg5) 87 | } 88 | static min(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 89 | return min(min(min(min(min(min(arg0, arg1), arg2), arg3), arg4), arg5), arg6) 90 | } 91 | static min(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 92 | return min(min(min(min(min(min(min(arg0, arg1), arg2), arg3), arg4), arg5), arg6), arg7) 93 | } 94 | static minInteger { 95 | Fiber.abort("Not implemented.") 96 | } 97 | static modf(x) { 98 | if (x < 0) { 99 | return [ -(-x).floor, x + (-x).floor ] 100 | } 101 | 102 | return [ x.floor, x - x.floor ] 103 | } 104 | static pi { 105 | return Num.pi 106 | } 107 | static pow(x, y) { 108 | return x.pow(y) 109 | } 110 | static rad(x) { 111 | return x / 180 * Num.pi 112 | } 113 | static random { 114 | if (__random == null) { 115 | __random = Random.new() 116 | } 117 | 118 | return __random 119 | } 120 | static random() { 121 | return random.float() 122 | } 123 | static random(n) { 124 | return random(1, n) 125 | } 126 | static random(m, n) { 127 | return random.int(m, n + 1) 128 | } 129 | static randomSeed(x) { 130 | __random = Random.new(x) 131 | } 132 | static sin(x) { 133 | return x.sin 134 | } 135 | static sqrt(x) { 136 | return x.sqrt 137 | } 138 | static tan(x) { 139 | return x.tan 140 | } 141 | static toInteger(x) { 142 | if (x is String) { 143 | x = Num.fromString(x) 144 | } 145 | if (x is Num && x.isInteger) { 146 | return x 147 | } 148 | 149 | return null 150 | } 151 | static type(x) { 152 | if (x is Num) { 153 | if (x.isInteger) { 154 | return "integer" 155 | } else { 156 | return "float" 157 | } 158 | } 159 | 160 | return null 161 | } 162 | static ult(m, n) { 163 | Fiber.abort("Not implemented.") 164 | } 165 | } 166 | 167 | class math { 168 | static huge { LMath.huge } 169 | static maxInteger { LMath.maxInteger } 170 | static minInteger { LMath.minInteger } 171 | static pi { LMath.pi } 172 | } 173 | // Math end. 174 | -------------------------------------------------------------------------------- /lib/string.wren: -------------------------------------------------------------------------------- 1 | // String begin. 2 | class LString { 3 | static byte(s) { 4 | return byte(s, 1) 5 | } 6 | static byte(s, i) { 7 | return byte(s, i, i)[1] 8 | } 9 | static byte(s, i, j) { 10 | return LTable.new(s.bytes.take(j).skip(i - 1)) 11 | } 12 | static char() { 13 | return "" 14 | } 15 | static char(arg0) { 16 | return String.fromCodePoint(arg0) 17 | } 18 | static char(arg0, arg1) { 19 | return char(arg0) + String.fromCodePoint(arg1) 20 | } 21 | static char(arg0, arg1, arg2) { 22 | return char(arg0, arg1) + String.fromCodePoint(arg2) 23 | } 24 | static char(arg0, arg1, arg2, arg3) { 25 | return char(arg0, arg1, arg2) + String.fromCodePoint(arg3) 26 | } 27 | static char(arg0, arg1, arg2, arg3, arg4) { 28 | return char(arg0, arg1, arg2, arg3) + String.fromCodePoint(arg4) 29 | } 30 | static char(arg0, arg1, arg2, arg3, arg4, arg5) { 31 | return char(arg0, arg1, arg2, arg3, arg4) + String.fromCodePoint(arg5) 32 | } 33 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 34 | return char(arg0, arg1, arg2, arg3, arg4, arg5) + String.fromCodePoint(arg6) 35 | } 36 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 37 | return char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) + String.fromCodePoint(arg7) 38 | } 39 | static dump(function) { 40 | Fiber.abort("Not implemented.") 41 | } 42 | static dump(function, strip) { 43 | Fiber.abort("Not implemented.") 44 | } 45 | static find(s, pattern) { 46 | Fiber.abort("Not implemented.") 47 | } 48 | static find(s, pattern, init) { 49 | Fiber.abort("Not implemented.") 50 | } 51 | static find(s, pattern, init, plain) { 52 | Fiber.abort("Not implemented.") 53 | } 54 | static format(formatstring) { 55 | Fiber.abort("Not implemented.") 56 | } 57 | static format(formatstring, arg0) { 58 | Fiber.abort("Not implemented.") 59 | } 60 | static format(formatstring, arg0, arg1) { 61 | Fiber.abort("Not implemented.") 62 | } 63 | static format(formatstring, arg0, arg1, arg2) { 64 | Fiber.abort("Not implemented.") 65 | } 66 | static format(formatstring, arg0, arg1, arg2, arg3) { 67 | Fiber.abort("Not implemented.") 68 | } 69 | static gmatch(s, pattern) { 70 | Fiber.abort("Not implemented.") 71 | } 72 | static gsub(s, pattern, repl) { 73 | Fiber.abort("Not implemented.") 74 | } 75 | static gsub(s, pattern, repl, n) { 76 | Fiber.abort("Not implemented.") 77 | } 78 | static len(s) { 79 | return s.count 80 | } 81 | static lower(s) { 82 | return s.map( 83 | Fn.new { | ch | 84 | if (ch.codePoints[0] >= "A".codePoints[0] && ch.codePoints[0] <= "Z".codePoints[0]) { 85 | return String.fromCodePoint(ch.codePoints[0] + ("a".codePoints[0] - "A".codePoints[0])) 86 | } 87 | 88 | return ch 89 | } 90 | ).join("") 91 | } 92 | static match(s, pattern) { 93 | Fiber.abort("Not implemented.") 94 | } 95 | static match(s, pattern, init) { 96 | Fiber.abort("Not implemented.") 97 | } 98 | static pack(fmt, v1, v2) { 99 | Fiber.abort("Not implemented.") 100 | } 101 | static packsize(fmt) { 102 | Fiber.abort("Not implemented.") 103 | } 104 | static rep(s, n) { 105 | return rep(s, n, "") 106 | } 107 | static rep(s, n, sep) { 108 | var result = "" 109 | for (i in 0...n) { 110 | result = result + s 111 | if (i != n - 1) { 112 | result = result + sep 113 | } 114 | } 115 | 116 | return result 117 | } 118 | static reverse(s) { 119 | var result = "" 120 | for (i in (s.count - 1)..0) { 121 | result = result + s[i] 122 | } 123 | 124 | return result 125 | } 126 | static sub(s, i) { 127 | return sub(s, i, s.count) 128 | } 129 | static sub(s, i, j) { 130 | return s.take(j).skip(i - 1).join("") 131 | } 132 | static unpack(fmt, s) { 133 | Fiber.abort("Not implemented.") 134 | } 135 | static unpack(fmt, s, pos) { 136 | Fiber.abort("Not implemented.") 137 | } 138 | static upper(s) { 139 | return s.map( 140 | Fn.new { | ch | 141 | if (ch.codePoints[0] >= "a".codePoints[0] && ch.codePoints[0] <= "z".codePoints[0]) { 142 | return String.fromCodePoint(ch.codePoints[0] + ("A".codePoints[0] - "a".codePoints[0])) 143 | } 144 | 145 | return ch 146 | } 147 | ).join("") 148 | } 149 | } 150 | // String end. 151 | -------------------------------------------------------------------------------- /lib/syntax.wren: -------------------------------------------------------------------------------- 1 | // Syntax begin. 2 | class LRange is Sequence { 3 | construct new(b, e, s) { 4 | _begin = b 5 | _end = e 6 | _step = s 7 | } 8 | 9 | iterate(iterator) { 10 | if (iterator == null) { 11 | iterator = _begin 12 | 13 | return iterator 14 | } 15 | iterator = iterator + _step 16 | if (_begin < _end) { 17 | if (iterator > _end) { 18 | return null 19 | } 20 | } else if (_begin > _end) { 21 | if (iterator < _end) { 22 | return null 23 | } 24 | } else if (_begin == _end) { 25 | return null 26 | } 27 | 28 | return iterator 29 | } 30 | iteratorValue(iterator) { 31 | return iterator 32 | } 33 | } 34 | 35 | class LIPairs is Sequence { 36 | construct new(tbl) { 37 | _table = tbl 38 | } 39 | 40 | iterate(iterator) { 41 | if (iterator == null) { 42 | iterator = 0 // 1-based. 43 | } 44 | iterator = iterator + 1 45 | if (iterator > _table.len__) { 46 | return null 47 | } 48 | 49 | return iterator 50 | } 51 | iteratorValue(iterator) { 52 | return LTuple.new(iterator, _table[iterator]) 53 | } 54 | } 55 | 56 | class LPairs is Sequence { 57 | construct new(tbl) { 58 | _table = tbl 59 | } 60 | 61 | iterate(iterator) { 62 | iterator = _table.iterate(iterator) 63 | 64 | return iterator 65 | } 66 | iteratorValue(iterator) { 67 | var kv = _table.iteratorValue(iterator) 68 | 69 | return LTuple.new(kv.key, kv.value) 70 | } 71 | } 72 | 73 | class LStd { 74 | static len(obj) { 75 | return obj.len__ 76 | } 77 | 78 | static assert(v) { 79 | assert(v, "Assertion.") 80 | } 81 | static assert(v, message) { 82 | if (!v) { 83 | Fiber.abort(message) 84 | } 85 | } 86 | static collectGarbage() { 87 | return System.gc() 88 | } 89 | static collectGarbage(opt) { 90 | return System.gc() 91 | } 92 | static collectGarbage(opt, arg) { 93 | return System.gc() 94 | } 95 | static doFile(filename) { 96 | Fiber.abort("Not implemented.") 97 | } 98 | static error(message) { 99 | error(message, 0) 100 | } 101 | static error(message, level) { 102 | Fiber.abort(message) 103 | } 104 | static getMetatable(object) { 105 | Fiber.abort("Not implemented.") 106 | } 107 | static load(chunk) { 108 | Fiber.abort("Not implemented.") 109 | } 110 | static load(chunk, chunkname) { 111 | Fiber.abort("Not implemented.") 112 | } 113 | static load(chunk, chunkname, mode) { 114 | Fiber.abort("Not implemented.") 115 | } 116 | static load(chunk, chunkname, mode, env) { 117 | Fiber.abort("Not implemented.") 118 | } 119 | static loadFile() { 120 | Fiber.abort("Not implemented.") 121 | } 122 | static loadFile(filename) { 123 | Fiber.abort("Not implemented.") 124 | } 125 | static loadFile(filename, mode) { 126 | Fiber.abort("Not implemented.") 127 | } 128 | static loadFile(filename, mode, env) { 129 | Fiber.abort("Not implemented.") 130 | } 131 | static next(table) { 132 | return next(table, null) 133 | } 134 | static next(table, index) { 135 | var iterator = table.iterate(null) 136 | if (!iterator) { 137 | return LTuple.new(null, null) 138 | } 139 | var kv = table.iteratorValue(iterator) 140 | if (index != null) { 141 | while (kv.key != index) { 142 | iterator = table.iterate(iterator) 143 | kv = table.iteratorValue(iterator) 144 | } 145 | iterator = table.iterate(iterator) 146 | if (iterator) { 147 | kv = table.iteratorValue(iterator) 148 | } else { 149 | return LTuple.new(null, null) 150 | } 151 | } 152 | 153 | return LTuple.new(kv.key, kv.value) 154 | } 155 | static pcall(f) { 156 | Fiber.abort("Not implemented.") 157 | } 158 | static pcall(f, arg0) { 159 | Fiber.abort("Not implemented.") 160 | } 161 | static pcall(f, arg0, arg1) { 162 | Fiber.abort("Not implemented.") 163 | } 164 | static pcall(f, arg0, arg1, arg2) { 165 | Fiber.abort("Not implemented.") 166 | } 167 | static pcall(f, arg0, arg1, arg2, arg3) { 168 | Fiber.abort("Not implemented.") 169 | } 170 | static print_(argv) { 171 | for (i in 0...argv.count) { 172 | if (argv[i] == null) { 173 | argv[i] = "nil" 174 | } else if (argv[i] is LTuple) { 175 | argv[i] = argv[i].join("\t") 176 | } 177 | } 178 | 179 | System.print(argv.join("\t")) 180 | } 181 | static print(arg0) { 182 | print_([ arg0 ]) 183 | } 184 | static print(arg0, arg1) { 185 | print_([ arg0, arg1 ]) 186 | } 187 | static print(arg0, arg1, arg2) { 188 | print_([ arg0, arg1, arg2 ]) 189 | } 190 | static print(arg0, arg1, arg2, arg3) { 191 | print_([ arg0, arg1, arg2, arg3 ]) 192 | } 193 | static print(arg0, arg1, arg2, arg3, arg4) { 194 | print_([ arg0, arg1, arg2, arg3, arg4 ]) 195 | } 196 | static print(arg0, arg1, arg2, arg3, arg4, arg5) { 197 | print_([ arg0, arg1, arg2, arg3, arg4, arg5 ]) 198 | } 199 | static print(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 200 | print_([ arg0, arg1, arg2, arg3, arg4, arg5, arg6 ]) 201 | } 202 | static print(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 203 | print_([ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 ]) 204 | } 205 | static rawEqual(v1, v2) { 206 | return v1 == v2 207 | } 208 | static rawGet(table, index) { 209 | return table[index] 210 | } 211 | static rawLen(v) { 212 | return v.len__ 213 | } 214 | static rawSet(table, index, value) { 215 | table[index] = value 216 | } 217 | static select_(index, argv) { 218 | if (index == "#") { 219 | return argv.count 220 | } 221 | var result = LTuple.new() 222 | if (index == 0) { 223 | return result 224 | } 225 | var s = index > 0 ? index - 1 : argv.count + index 226 | if (s < 0) { 227 | s = 0 228 | } 229 | result.ctor(argv.skip(s)) 230 | 231 | return result 232 | } 233 | static select(index) { 234 | return select_(index, [ ]) 235 | } 236 | static select(index, arg0) { 237 | return select_(index, [ arg0 ]) 238 | } 239 | static select(index, arg0, arg1) { 240 | return select_(index, [ arg0, arg1 ]) 241 | } 242 | static select(index, arg0, arg1, arg2) { 243 | return select_(index, [ arg0, arg1, arg2 ]) 244 | } 245 | static select(index, arg0, arg1, arg2, arg3) { 246 | return select_(index, [ arg0, arg1, arg2, arg3 ]) 247 | } 248 | static select(index, arg0, arg1, arg2, arg3, arg4) { 249 | return select_(index, [ arg0, arg1, arg2, arg3, arg4 ]) 250 | } 251 | static select(index, arg0, arg1, arg2, arg3, arg4, arg5) { 252 | return select_(index, [ arg0, arg1, arg2, arg3, arg4, arg5 ]) 253 | } 254 | static select(index, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 255 | return select_(index, [ arg0, arg1, arg2, arg3, arg4, arg5, arg6 ]) 256 | } 257 | static select(index, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 258 | return select_(index, [ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 ]) 259 | } 260 | static setMetatable(table, metatable) { 261 | Fiber.abort("Not implemented.") 262 | } 263 | static toNumber(e) { 264 | return Num.fromString(e) 265 | } 266 | static toNumber(e, base) { 267 | Fiber.abort("Not implemented.") 268 | } 269 | static toString(v) { 270 | return v.toString 271 | } 272 | static type(v) { 273 | if (v == null) { 274 | return "nil" 275 | } 276 | if (v is Num) { 277 | return "number" 278 | } 279 | if (v is String) { 280 | return "string" 281 | } 282 | if (v is Bool) { 283 | return "boolean" 284 | } 285 | if (v is Fn) { 286 | return "function" 287 | } 288 | if (v is Fiber) { 289 | return "function" 290 | } 291 | 292 | return "table" 293 | } 294 | 295 | static new(y) { 296 | return y.new() 297 | } 298 | static new(y, arg0) { 299 | return y.new(arg0) 300 | } 301 | static new(y, arg0, arg1) { 302 | return y.new(arg0, arg1) 303 | } 304 | static new(y, arg0, arg1, arg2) { 305 | return y.new(arg0, arg1, arg2) 306 | } 307 | static new(y, arg0, arg1, arg2, arg3) { 308 | return y.new(arg0, arg1, arg2, arg3) 309 | } 310 | static new(y, arg0, arg1, arg2, arg3, arg4) { 311 | return y.new(arg0, arg1, arg2, arg3, arg4) 312 | } 313 | static new(y, arg0, arg1, arg2, arg3, arg4, arg5) { 314 | return y.new(arg0, arg1, arg2, arg3, arg4, arg5) 315 | } 316 | static new(y, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 317 | return y.new(arg0, arg1, arg2, arg3, arg4, arg5, arg6) 318 | } 319 | static new(y, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 320 | return y.new(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 321 | } 322 | 323 | static isa(obj, y) { 324 | return obj is y 325 | } 326 | 327 | static call(func) { 328 | return func.call() 329 | } 330 | static call(func, arg0) { 331 | return func.call(arg0) 332 | } 333 | static call(func, arg0, arg1) { 334 | return func.call(arg0, arg1) 335 | } 336 | static call(func, arg0, arg1, arg2) { 337 | return func.call(arg0, arg1, arg2) 338 | } 339 | static call(func, arg0, arg1, arg2, arg3) { 340 | return func.call(arg0, arg1, arg2, arg3) 341 | } 342 | static call(func, arg0, arg1, arg2, arg3, arg4) { 343 | return func.call(arg0, arg1, arg2, arg3, arg4) 344 | } 345 | static call(func, arg0, arg1, arg2, arg3, arg4, arg5) { 346 | return func.call(arg0, arg1, arg2, arg3, arg4, arg5) 347 | } 348 | static call(func, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 349 | return func.call(arg0, arg1, arg2, arg3, arg4, arg5, arg6) 350 | } 351 | static call(func, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 352 | return func.call(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 353 | } 354 | 355 | static apply(arg) { 356 | return arg 357 | } 358 | } 359 | // Syntax end. 360 | -------------------------------------------------------------------------------- /lib/table.wren: -------------------------------------------------------------------------------- 1 | // Table begin. 2 | class LTable { 3 | static concat(list) { 4 | return concat(list, "") 5 | } 6 | static concat(list, sep) { 7 | return concat(list, sep, 1) 8 | } 9 | static concat(list, sep, i) { 10 | return concat(list, sep, i, list.len__) 11 | } 12 | static concat(list, sep, i, j) { 13 | var result = "" 14 | for (k in i..j) { 15 | result = result + list[k] 16 | if (k != j) { 17 | result = result + sep 18 | } 19 | } 20 | 21 | return result 22 | } 23 | static insert(list, value) { 24 | return insert(list, list.len__ + 1, value) 25 | } 26 | static insert(list, pos, value) { 27 | list[pos] = value 28 | } 29 | static move(a1, f, e, t) { 30 | Fiber.abort("Not implemented.") 31 | } 32 | static move(a1, f, e, t, a2) { 33 | Fiber.abort("Not implemented.") 34 | } 35 | static pack(arg0) { 36 | Fiber.abort("Not implemented.") 37 | } 38 | static remove(list) { 39 | return remove(list, list.len__) 40 | } 41 | static remove(list, pos) { 42 | var len = list.len__ 43 | if (pos <= 0 || pos > len) { 44 | return null 45 | } 46 | var result = list[pos] 47 | for (i in (pos + 1)...len) { 48 | list[i - 1] = list[i] 49 | } 50 | list[len] = null 51 | 52 | return result 53 | } 54 | static sort(list) { 55 | Fiber.abort("Not implemented.") 56 | } 57 | static sort(list, comp) { 58 | Fiber.abort("Not implemented.") 59 | } 60 | static unpack(list) { 61 | Fiber.abort("Not implemented.") 62 | } 63 | static unpack(list, i) { 64 | Fiber.abort("Not implemented.") 65 | } 66 | static unpack(list, i, j) { 67 | Fiber.abort("Not implemented.") 68 | } 69 | 70 | construct new() { 71 | _length = 0 72 | } 73 | construct new(obj) { 74 | _length = 0 75 | 76 | if (obj is List) { 77 | for (i in 0...obj.count) { 78 | this[i + 1] = obj[i] // 1-based. 79 | } 80 | } else if (obj is Map) { 81 | for (kv in obj) { 82 | this[kv.key] = kv.value 83 | } 84 | } else if (obj is Sequence) { 85 | var i = 0 86 | for (v in obj) { 87 | this[i + 1] = v // 1-based. 88 | i = i + 1 89 | } 90 | } 91 | } 92 | 93 | toString { 94 | if (len__ == data_.count) { 95 | var result = "" 96 | for (i in 1..len__) { 97 | result = result + data_[i].toString 98 | if (i != len__) { 99 | result = result + ", " 100 | } 101 | } 102 | 103 | return "{ " + result + " }" 104 | } 105 | 106 | return data_.toString 107 | } 108 | toWren { 109 | var result = null 110 | if (count == len__) { 111 | result = [ ] 112 | for (i in 0...count) { 113 | var v = this[i + 1] 114 | if (v is LTable) { 115 | v = v.toWren 116 | } 117 | result.add(v) // 1-based. 118 | } 119 | } else { 120 | result = { } 121 | for (kv in this) { 122 | var k = kv.key 123 | var v = kv.value 124 | if (k is LTable) { 125 | k = k.toWren 126 | } 127 | if (v is LTable) { 128 | v = v.toWren 129 | } 130 | result[k] = v 131 | } 132 | } 133 | 134 | return result 135 | } 136 | 137 | data_ { 138 | if (_data == null) { 139 | _data = { } 140 | } 141 | 142 | return _data 143 | } 144 | 145 | [index] { 146 | if (data_.containsKey(index)) { 147 | return data_[index] 148 | } 149 | 150 | return null 151 | } 152 | [index] = (value) { 153 | if (value == null) { 154 | if (data_.containsKey(index)) { 155 | data_.remove(index) 156 | } 157 | } else { 158 | data_[index] = value 159 | _length = -1 160 | } 161 | } 162 | 163 | count { 164 | return data_.count 165 | } 166 | isEmpty { 167 | return data_.isEmpty 168 | } 169 | clear() { 170 | data_.clear() 171 | } 172 | 173 | keys { 174 | return data_.keys 175 | } 176 | values { 177 | return data_.values 178 | } 179 | 180 | containsKey(key) { 181 | return data_.containsKey(key) 182 | } 183 | 184 | len__ { 185 | if (_length == -1) { 186 | for (i in 1..data_.count) { 187 | if (data_.containsKey(i)) { 188 | _length = i // 1-based. 189 | } else { 190 | break 191 | } 192 | } 193 | } 194 | 195 | return _length == -1 ? 0 : _length 196 | } 197 | 198 | iterate(iterator) { 199 | iterator = data_.iterate(iterator) 200 | 201 | return iterator 202 | } 203 | iteratorValue(iterator) { 204 | return data_.iteratorValue(iterator) 205 | } 206 | } // `LTable`. 207 | // Table end. 208 | -------------------------------------------------------------------------------- /lib/tuple.wren: -------------------------------------------------------------------------------- 1 | // Tuple begin. 2 | class LTuple { 3 | construct new() { 4 | ctor([ ]) 5 | } 6 | construct new(arg0) { 7 | ctor([ arg0 ]) 8 | } 9 | construct new(arg0, arg1) { 10 | ctor([ arg0, arg1 ]) 11 | } 12 | construct new(arg0, arg1, arg2) { 13 | ctor([ arg0, arg1, arg2 ]) 14 | } 15 | construct new(arg0, arg1, arg2, arg3) { 16 | ctor([ arg0, arg1, arg2, arg3 ]) 17 | } 18 | construct new(arg0, arg1, arg2, arg3, arg4) { 19 | ctor([ arg0, arg1, arg2, arg3, arg4 ]) 20 | } 21 | construct new(arg0, arg1, arg2, arg3, arg4, arg5) { 22 | ctor([ arg0, arg1, arg2, arg3, arg4, arg5 ]) 23 | } 24 | construct new(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 25 | ctor([ arg0, arg1, arg2, arg3, arg4, arg5, arg6 ]) 26 | } 27 | construct new(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 28 | ctor([ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 ]) 29 | } 30 | ctor(argv) { 31 | _args = [ ] 32 | for (arg in argv) { 33 | if (arg is LTuple) { 34 | _args = _args + arg.toList 35 | } else { 36 | _args.add(arg) 37 | } 38 | } 39 | } 40 | 41 | toString { 42 | return "< " + _args.join(", ") + " >" 43 | } 44 | toList { 45 | return _args.toList 46 | } 47 | 48 | [index] { 49 | return _args[index] 50 | } 51 | [index] = (value) { 52 | _args[index] = value 53 | } 54 | 55 | == (other) { 56 | if (!(other is LTuple) || count != other.count) { 57 | return false 58 | } 59 | for (i in 0...count) { 60 | if (this[i] != other[i]) { 61 | return false 62 | } 63 | } 64 | 65 | return true 66 | } 67 | != (other) { 68 | if (!(other is LTuple) || count != other.count) { 69 | return true 70 | } 71 | for (i in 0...count) { 72 | if (this[i] != other[i]) { 73 | return true 74 | } 75 | } 76 | 77 | return false 78 | } 79 | 80 | count { 81 | return _args.count 82 | } 83 | isEmpty { 84 | return _args.isEmpty 85 | } 86 | 87 | join(sep) { 88 | return _args.join(sep) 89 | } 90 | } 91 | // Tuple end. 92 | -------------------------------------------------------------------------------- /lib/utf8.wren: -------------------------------------------------------------------------------- 1 | // Utf8 begin. 2 | class LUtf8 { 3 | static char() { 4 | return "" 5 | } 6 | static char(arg0) { 7 | return String.fromCodePoint(arg0) 8 | } 9 | static char(arg0, arg1) { 10 | return char(arg0) + String.fromCodePoint(arg1) 11 | } 12 | static char(arg0, arg1, arg2) { 13 | return char(arg0, arg1) + String.fromCodePoint(arg2) 14 | } 15 | static char(arg0, arg1, arg2, arg3) { 16 | return char(arg0, arg1, arg2) + String.fromCodePoint(arg3) 17 | } 18 | static char(arg0, arg1, arg2, arg3, arg4) { 19 | return char(arg0, arg1, arg2, arg3) + String.fromCodePoint(arg4) 20 | } 21 | static char(arg0, arg1, arg2, arg3, arg4, arg5) { 22 | return char(arg0, arg1, arg2, arg3, arg4) + String.fromCodePoint(arg5) 23 | } 24 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 25 | return char(arg0, arg1, arg2, arg3, arg4, arg5) + String.fromCodePoint(arg6) 26 | } 27 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 28 | return char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) + String.fromCodePoint(arg7) 29 | } 30 | static charPattern { 31 | Fiber.abort("Not implemented.") 32 | } 33 | static codes(s) { 34 | return LIPairs.new(LTable.new(s.codePoints)) 35 | } 36 | static codepoint(s) { 37 | return codepoint(s, 1) 38 | } 39 | static codepoint(s, i) { 40 | return codepoint(s, i, i)[1] 41 | } 42 | static codepoint(s, i, j) { 43 | return LTable.new(s.codePoints.take(j).skip(i - 1)) 44 | } 45 | static len(s) { 46 | return s.count 47 | } 48 | static len(s, i) { 49 | return s.skip(i - 1).count 50 | } 51 | static len(s, i, j) { 52 | return s.take(j).skip(i - 1).count 53 | } 54 | static offset(s, n) { 55 | Fiber.abort("Not implemented.") 56 | } 57 | static offset(s, n, i) { 58 | Fiber.abort("Not implemented.") 59 | } 60 | } 61 | // Utf8 end. 62 | -------------------------------------------------------------------------------- /test.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | call wren.exe test\test.wren test/hello.lua 3 | call wren.exe test\test.wren test/block.lua 4 | call wren.exe test\test.wren test/loop.lua 5 | call wren.exe test\test.wren test/condition.lua 6 | call wren.exe test\test.wren test/function.lua 7 | call wren.exe test\test.wren test/class.lua 8 | call wren.exe test\test.wren test/lib.lua 9 | call wren.exe test\test.wren test/math.lua 10 | call wren.exe test\test.wren test/string.lua 11 | call wren.exe test\test.wren test/utf8.lua 12 | call wren.exe test\test.wren test/table.lua 13 | call wren.exe test\test.wren test/coroutine.lua 14 | echo Ready! 15 | -------------------------------------------------------------------------------- /test/block.lua: -------------------------------------------------------------------------------- 1 | do 2 | local i = 0 3 | 4 | function inc() 5 | i = i + 1 6 | 7 | return i 8 | end 9 | 10 | function dec() 11 | i = i - 1 12 | 13 | return i 14 | end 15 | 16 | print(inc()) 17 | print(dec()) 18 | end 19 | -------------------------------------------------------------------------------- /test/class.lua: -------------------------------------------------------------------------------- 1 | Base = class( 2 | { 3 | new = function (self) 4 | end, 5 | 6 | field0 = 0, 7 | get_field1 = function (self) 8 | if self._field1 == nil then 9 | self._field1 = 0 10 | end 11 | 12 | return self._field1 13 | end, 14 | set_field1 = function (self, value) 15 | self._field1 = value 16 | end, 17 | 18 | func0 = function (a, b) 19 | local c = a / b 20 | 21 | return c 22 | end, 23 | func1 = function (self, c, d) 24 | self['field0'] = c 25 | self.field1 = d 26 | end 27 | } 28 | ) 29 | 30 | Derived = class( 31 | { 32 | new = function (self) 33 | end 34 | }, 35 | Base 36 | ) 37 | 38 | foo = new(Base) 39 | bar = new(Derived) 40 | 41 | foo:func1(1, 2) 42 | bar:func1('1', '2') 43 | 44 | print(Base.func0(22, 7)) 45 | -------------------------------------------------------------------------------- /test/condition.lua: -------------------------------------------------------------------------------- 1 | n = 99999 2 | 3 | x = n * 2 - 1 4 | a = 1 - 1 / 3 5 | w = (x - 5) / 2 + 1 6 | u = 0 7 | v = 100 / w 8 | 9 | for y = 5, x, 2 do 10 | iy = (y - 1) / 4 11 | iy = math.floor(iy) 12 | if iy == (y - 1) / 4 then 13 | a = a + 1 / y 14 | else 15 | a = a - 1 / y 16 | end 17 | u = u + v 18 | end 19 | a = a * 4 20 | 21 | print('Pi = ', a) 22 | -------------------------------------------------------------------------------- /test/coroutine.lua: -------------------------------------------------------------------------------- 1 | co = coroutine.create( 2 | function (value1, value2) 3 | local tempvar1, tempvar2, tempvar3 = nil, nil, nil 4 | 5 | tempvar3 = 10 6 | print('Coroutine section 1', value1, value2, tempvar3) 7 | 8 | tempvar1, _ = coroutine.yield(value1 + 1, value2 + 1) 9 | tempvar3 = tempvar3 + value1 10 | print('Coroutine section 2', tempvar1, tempvar2, tempvar3) 11 | 12 | tempvar1, tempvar2 = coroutine.yield(value1 + value2, value1 - value2) 13 | tempvar3 = tempvar3 + value1 14 | print('Coroutine section 3', tempvar1, tempvar2, tempvar3) 15 | 16 | return value2, 'end' 17 | end 18 | ) 19 | 20 | print('main', coroutine.resume(co, 3, 2)) 21 | print('main', coroutine.resume(co, 12, 14)) 22 | print('main', coroutine.resume(co, 5, 6)) 23 | print('main', coroutine.resume(co, 10, 20)) 24 | 25 | --[[ 26 | Expected: 27 | coroutine section 1 3 2 10 28 | main true 4 3 29 | coroutine section 2 12 nil 13 30 | main true 5 1 31 | coroutine section 3 5 6 16 32 | main true 2 end 33 | main false cannot resume dead coroutine 34 | --]] 35 | -------------------------------------------------------------------------------- /test/function.lua: -------------------------------------------------------------------------------- 1 | function fib(n) 2 | if n <= 1 then 3 | return n 4 | else 5 | return fib(n - 1) + fib(n - 2) 6 | end 7 | end 8 | n = 10 9 | for i = 0, 10 do 10 | print(fib(i)) 11 | end 12 | 13 | local tbl = { 14 | func = function () 15 | print('Function in table.') 16 | end 17 | } 18 | tbl['func']() 19 | -------------------------------------------------------------------------------- /test/hello.lua: -------------------------------------------------------------------------------- 1 | print('hello' .. ' ' .. 'world') 2 | -------------------------------------------------------------------------------- /test/lib.lua: -------------------------------------------------------------------------------- 1 | assert(tonumber(tostring(42)) == 42) 2 | assert(type(nil) == 'nil') 3 | assert(type(22 / 7) == 'number') 4 | assert(type('hello') == 'string') 5 | assert(type({ }) == 'table') 6 | collectgarbage() 7 | -------------------------------------------------------------------------------- /test/loop.lua: -------------------------------------------------------------------------------- 1 | for i = 1, 3 do 2 | print(i) 3 | end 4 | 5 | for i = 1, 6, 2 do 6 | print(i) 7 | end 8 | 9 | for i = 3, 1 do 10 | print(i) 11 | end 12 | 13 | i = 3 14 | while i >= 1 do 15 | print(i) 16 | i = i - 1 17 | end 18 | 19 | i = 1 20 | repeat 21 | print(i) 22 | i = i + 1 23 | if i > 3 then 24 | break 25 | end 26 | until false 27 | 28 | tbl = { 'uno', 'dos', 'thres' } 29 | tbl['key'] = 'value' 30 | 31 | for i, v in ipairs(tbl) do 32 | print(i, v) 33 | end 34 | 35 | for k, v in pairs(tbl) do 36 | print(k, v) 37 | end 38 | 39 | k, v = next(tbl, nil) 40 | while k do 41 | print(k, v) 42 | k, v = next(tbl, k) 43 | end 44 | -------------------------------------------------------------------------------- /test/math.lua: -------------------------------------------------------------------------------- 1 | print(math.sin(0.5 * math.pi), math.sin(math.rad(0.5 * 180))) 2 | print(math.random()) 3 | print(math.sqrt(2)) 4 | print(math.max(1 + 3, 2 * 2, 1.5, -2, 42)) 5 | -------------------------------------------------------------------------------- /test/string.lua: -------------------------------------------------------------------------------- 1 | print(string.lower('HeLlO'), string.upper('HeLlO')) 2 | print(string.rep('x', 5)) 3 | print(string.len('hello' .. 'world')) 4 | print(string.byte('hello')) 5 | print(string.byte('hello', 2)) 6 | print(string.byte('hello', 2, 4)) 7 | print(string.sub('hello', 2, 4)) 8 | -------------------------------------------------------------------------------- /test/table.lua: -------------------------------------------------------------------------------- 1 | tbl = { 'uno', 'dos', 'thres' } 2 | tbl['key'] = 'value' 3 | for k, v in pairs(tbl) do 4 | print(k, v) 5 | end 6 | print(length(tbl)) 7 | -------------------------------------------------------------------------------- /test/test.wren: -------------------------------------------------------------------------------- 1 | import "io" for File 2 | import "meta" for Meta 3 | import "os" for Process 4 | 5 | import "../b95" for Lua 6 | 7 | var argv = Process.allArguments 8 | var src = File.read(argv[2]) 9 | System.print("[%(argv[2])]") 10 | 11 | var onreqr = Fn.new { | path, klass | 12 | return null 13 | } 14 | var onfunc = Fn.new { | module, func | 15 | return null 16 | } 17 | var lua = Lua.new().onRequire(onreqr).onFunction(onfunc) 18 | 19 | var dst = lua.compile(src) 20 | // System.print("[ast]\n%(dst.ast)") 21 | // System.print("[ops]\n%(dst.lines)") 22 | Meta.eval(dst.toString) 23 | -------------------------------------------------------------------------------- /test/test_lib.wren: -------------------------------------------------------------------------------- 1 | // Debug patch. 2 | // Debug begin. 3 | class LDebug { 4 | construct new() { 5 | } 6 | 7 | lastLine { _lastLine } 8 | lastColumn { _lastColumn } 9 | setLastLocation(ln, col) { 10 | _lastLine = ln 11 | _lastColumn = col 12 | } 13 | } 14 | var ldebug = LDebug.new() 15 | // Debug end. 16 | // Debug patch. 17 | // Tuple lib. 18 | // Tuple begin. 19 | class LTuple { 20 | construct new() { 21 | ctor([ ]) 22 | } 23 | construct new(arg0) { 24 | ctor([ arg0 ]) 25 | } 26 | construct new(arg0, arg1) { 27 | ctor([ arg0, arg1 ]) 28 | } 29 | construct new(arg0, arg1, arg2) { 30 | ctor([ arg0, arg1, arg2 ]) 31 | } 32 | construct new(arg0, arg1, arg2, arg3) { 33 | ctor([ arg0, arg1, arg2, arg3 ]) 34 | } 35 | construct new(arg0, arg1, arg2, arg3, arg4) { 36 | ctor([ arg0, arg1, arg2, arg3, arg4 ]) 37 | } 38 | construct new(arg0, arg1, arg2, arg3, arg4, arg5) { 39 | ctor([ arg0, arg1, arg2, arg3, arg4, arg5 ]) 40 | } 41 | construct new(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 42 | ctor([ arg0, arg1, arg2, arg3, arg4, arg5, arg6 ]) 43 | } 44 | construct new(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 45 | ctor([ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 ]) 46 | } 47 | ctor(argv) { 48 | _args = [ ] 49 | for (arg in argv) { 50 | if (arg is LTuple) { 51 | _args = _args + arg.toList 52 | } else { 53 | _args.add(arg) 54 | } 55 | } 56 | } 57 | 58 | toString { 59 | return "< " + _args.join(", ") + " >" 60 | } 61 | toList { 62 | return _args.toList 63 | } 64 | 65 | [index] { 66 | return _args[index] 67 | } 68 | [index] = (value) { 69 | _args[index] = value 70 | } 71 | 72 | == (other) { 73 | if (!(other is LTuple) || count != other.count) { 74 | return false 75 | } 76 | for (i in 0...count) { 77 | if (this[i] != other[i]) { 78 | return false 79 | } 80 | } 81 | 82 | return true 83 | } 84 | != (other) { 85 | if (!(other is LTuple) || count != other.count) { 86 | return true 87 | } 88 | for (i in 0...count) { 89 | if (this[i] != other[i]) { 90 | return true 91 | } 92 | } 93 | 94 | return false 95 | } 96 | 97 | count { 98 | return _args.count 99 | } 100 | isEmpty { 101 | return _args.isEmpty 102 | } 103 | 104 | join(sep) { 105 | return _args.join(sep) 106 | } 107 | } 108 | // Tuple end. 109 | // Tuple lib. 110 | // Syntax lib. 111 | // Syntax begin. 112 | class LRange is Sequence { 113 | construct new(b, e, s) { 114 | _begin = b 115 | _end = e 116 | _step = s 117 | } 118 | 119 | iterate(iterator) { 120 | if (iterator == null) { 121 | iterator = _begin 122 | 123 | return iterator 124 | } 125 | iterator = iterator + _step 126 | if (_begin < _end) { 127 | if (iterator > _end) { 128 | return null 129 | } 130 | } else if (_begin > _end) { 131 | if (iterator < _end) { 132 | return null 133 | } 134 | } else if (_begin == _end) { 135 | return null 136 | } 137 | 138 | return iterator 139 | } 140 | iteratorValue(iterator) { 141 | return iterator 142 | } 143 | } 144 | 145 | class LIPairs is Sequence { 146 | construct new(tbl) { 147 | _table = tbl 148 | } 149 | 150 | iterate(iterator) { 151 | if (iterator == null) { 152 | iterator = 0 // 1-based. 153 | } 154 | iterator = iterator + 1 155 | if (iterator > _table.len__) { 156 | return null 157 | } 158 | 159 | return iterator 160 | } 161 | iteratorValue(iterator) { 162 | return LTuple.new(iterator, _table[iterator]) 163 | } 164 | } 165 | 166 | class LPairs is Sequence { 167 | construct new(tbl) { 168 | _table = tbl 169 | } 170 | 171 | iterate(iterator) { 172 | iterator = _table.iterate(iterator) 173 | 174 | return iterator 175 | } 176 | iteratorValue(iterator) { 177 | var kv = _table.iteratorValue(iterator) 178 | 179 | return LTuple.new(kv.key, kv.value) 180 | } 181 | } 182 | 183 | class LStd { 184 | static len(obj) { 185 | return obj.len__ 186 | } 187 | 188 | static assert(v) { 189 | assert(v, "Assertion.") 190 | } 191 | static assert(v, message) { 192 | if (!v) { 193 | Fiber.abort(message) 194 | } 195 | } 196 | static collectGarbage() { 197 | return System.gc() 198 | } 199 | static collectGarbage(opt) { 200 | return System.gc() 201 | } 202 | static collectGarbage(opt, arg) { 203 | return System.gc() 204 | } 205 | static doFile(filename) { 206 | Fiber.abort("Not implemented.") 207 | } 208 | static error(message) { 209 | error(message, 0) 210 | } 211 | static error(message, level) { 212 | Fiber.abort(message) 213 | } 214 | static getMetatable(object) { 215 | Fiber.abort("Not implemented.") 216 | } 217 | static load(chunk) { 218 | Fiber.abort("Not implemented.") 219 | } 220 | static load(chunk, chunkname) { 221 | Fiber.abort("Not implemented.") 222 | } 223 | static load(chunk, chunkname, mode) { 224 | Fiber.abort("Not implemented.") 225 | } 226 | static load(chunk, chunkname, mode, env) { 227 | Fiber.abort("Not implemented.") 228 | } 229 | static loadFile() { 230 | Fiber.abort("Not implemented.") 231 | } 232 | static loadFile(filename) { 233 | Fiber.abort("Not implemented.") 234 | } 235 | static loadFile(filename, mode) { 236 | Fiber.abort("Not implemented.") 237 | } 238 | static loadFile(filename, mode, env) { 239 | Fiber.abort("Not implemented.") 240 | } 241 | static next(table) { 242 | return next(table, null) 243 | } 244 | static next(table, index) { 245 | var iterator = table.iterate(null) 246 | if (!iterator) { 247 | return LTuple.new(null, null) 248 | } 249 | var kv = table.iteratorValue(iterator) 250 | if (index != null) { 251 | while (kv.key != index) { 252 | iterator = table.iterate(iterator) 253 | kv = table.iteratorValue(iterator) 254 | } 255 | iterator = table.iterate(iterator) 256 | if (iterator) { 257 | kv = table.iteratorValue(iterator) 258 | } else { 259 | return LTuple.new(null, null) 260 | } 261 | } 262 | 263 | return LTuple.new(kv.key, kv.value) 264 | } 265 | static pcall(f) { 266 | Fiber.abort("Not implemented.") 267 | } 268 | static pcall(f, arg0) { 269 | Fiber.abort("Not implemented.") 270 | } 271 | static pcall(f, arg0, arg1) { 272 | Fiber.abort("Not implemented.") 273 | } 274 | static pcall(f, arg0, arg1, arg2) { 275 | Fiber.abort("Not implemented.") 276 | } 277 | static pcall(f, arg0, arg1, arg2, arg3) { 278 | Fiber.abort("Not implemented.") 279 | } 280 | static print_(argv) { 281 | for (i in 0...argv.count) { 282 | if (argv[i] == null) { 283 | argv[i] = "nil" 284 | } else if (argv[i] is LTuple) { 285 | argv[i] = argv[i].join("\t") 286 | } 287 | } 288 | 289 | System.print(argv.join("\t")) 290 | } 291 | static print(arg0) { 292 | print_([ arg0 ]) 293 | } 294 | static print(arg0, arg1) { 295 | print_([ arg0, arg1 ]) 296 | } 297 | static print(arg0, arg1, arg2) { 298 | print_([ arg0, arg1, arg2 ]) 299 | } 300 | static print(arg0, arg1, arg2, arg3) { 301 | print_([ arg0, arg1, arg2, arg3 ]) 302 | } 303 | static print(arg0, arg1, arg2, arg3, arg4) { 304 | print_([ arg0, arg1, arg2, arg3, arg4 ]) 305 | } 306 | static print(arg0, arg1, arg2, arg3, arg4, arg5) { 307 | print_([ arg0, arg1, arg2, arg3, arg4, arg5 ]) 308 | } 309 | static print(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 310 | print_([ arg0, arg1, arg2, arg3, arg4, arg5, arg6 ]) 311 | } 312 | static print(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 313 | print_([ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 ]) 314 | } 315 | static rawEqual(v1, v2) { 316 | return v1 == v2 317 | } 318 | static rawGet(table, index) { 319 | return table[index] 320 | } 321 | static rawLen(v) { 322 | return v.len__ 323 | } 324 | static rawSet(table, index, value) { 325 | table[index] = value 326 | } 327 | static select_(index, argv) { 328 | if (index == "#") { 329 | return argv.count 330 | } 331 | var result = LTuple.new() 332 | if (index == 0) { 333 | return result 334 | } 335 | var s = index > 0 ? index - 1 : argv.count + index 336 | if (s < 0) { 337 | s = 0 338 | } 339 | result.ctor(argv.skip(s)) 340 | 341 | return result 342 | } 343 | static select(index) { 344 | return select_(index, [ ]) 345 | } 346 | static select(index, arg0) { 347 | return select_(index, [ arg0 ]) 348 | } 349 | static select(index, arg0, arg1) { 350 | return select_(index, [ arg0, arg1 ]) 351 | } 352 | static select(index, arg0, arg1, arg2) { 353 | return select_(index, [ arg0, arg1, arg2 ]) 354 | } 355 | static select(index, arg0, arg1, arg2, arg3) { 356 | return select_(index, [ arg0, arg1, arg2, arg3 ]) 357 | } 358 | static select(index, arg0, arg1, arg2, arg3, arg4) { 359 | return select_(index, [ arg0, arg1, arg2, arg3, arg4 ]) 360 | } 361 | static select(index, arg0, arg1, arg2, arg3, arg4, arg5) { 362 | return select_(index, [ arg0, arg1, arg2, arg3, arg4, arg5 ]) 363 | } 364 | static select(index, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 365 | return select_(index, [ arg0, arg1, arg2, arg3, arg4, arg5, arg6 ]) 366 | } 367 | static select(index, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 368 | return select_(index, [ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 ]) 369 | } 370 | static setMetatable(table, metatable) { 371 | Fiber.abort("Not implemented.") 372 | } 373 | static toNumber(e) { 374 | return Num.fromString(e) 375 | } 376 | static toNumber(e, base) { 377 | Fiber.abort("Not implemented.") 378 | } 379 | static toString(v) { 380 | return v.toString 381 | } 382 | static type(v) { 383 | if (v == null) { 384 | return "nil" 385 | } 386 | if (v is Num) { 387 | return "number" 388 | } 389 | if (v is String) { 390 | return "string" 391 | } 392 | if (v is Bool) { 393 | return "boolean" 394 | } 395 | if (v is Fn) { 396 | return "function" 397 | } 398 | if (v is Fiber) { 399 | return "function" 400 | } 401 | 402 | return "table" 403 | } 404 | 405 | static new(y) { 406 | return y.new() 407 | } 408 | static new(y, arg0) { 409 | return y.new(arg0) 410 | } 411 | static new(y, arg0, arg1) { 412 | return y.new(arg0, arg1) 413 | } 414 | static new(y, arg0, arg1, arg2) { 415 | return y.new(arg0, arg1, arg2) 416 | } 417 | static new(y, arg0, arg1, arg2, arg3) { 418 | return y.new(arg0, arg1, arg2, arg3) 419 | } 420 | static new(y, arg0, arg1, arg2, arg3, arg4) { 421 | return y.new(arg0, arg1, arg2, arg3, arg4) 422 | } 423 | static new(y, arg0, arg1, arg2, arg3, arg4, arg5) { 424 | return y.new(arg0, arg1, arg2, arg3, arg4, arg5) 425 | } 426 | static new(y, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 427 | return y.new(arg0, arg1, arg2, arg3, arg4, arg5, arg6) 428 | } 429 | static new(y, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 430 | return y.new(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 431 | } 432 | 433 | static isa(obj, y) { 434 | return obj is y 435 | } 436 | 437 | static call(func) { 438 | return func.call() 439 | } 440 | static call(func, arg0) { 441 | return func.call(arg0) 442 | } 443 | static call(func, arg0, arg1) { 444 | return func.call(arg0, arg1) 445 | } 446 | static call(func, arg0, arg1, arg2) { 447 | return func.call(arg0, arg1, arg2) 448 | } 449 | static call(func, arg0, arg1, arg2, arg3) { 450 | return func.call(arg0, arg1, arg2, arg3) 451 | } 452 | static call(func, arg0, arg1, arg2, arg3, arg4) { 453 | return func.call(arg0, arg1, arg2, arg3, arg4) 454 | } 455 | static call(func, arg0, arg1, arg2, arg3, arg4, arg5) { 456 | return func.call(arg0, arg1, arg2, arg3, arg4, arg5) 457 | } 458 | static call(func, arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 459 | return func.call(arg0, arg1, arg2, arg3, arg4, arg5, arg6) 460 | } 461 | static call(func, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 462 | return func.call(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) 463 | } 464 | 465 | static apply(arg) { 466 | return arg 467 | } 468 | } 469 | // Syntax end. 470 | // Syntax lib. 471 | // Coroutine lib. 472 | // Coroutine begin. 473 | class LCoroutine { 474 | static temporary_ { 475 | var result = __temporary 476 | __temporary = null 477 | 478 | return result 479 | } 480 | static temporary_ = (value) { 481 | __temporary = value 482 | } 483 | 484 | static create(fiber) { 485 | var result = fiber 486 | if (fiber is Fn) { 487 | if (fiber.arity == 0) { 488 | result = Fiber.new { fiber.call() } 489 | } else if (fiber.arity == 1) { 490 | result = Fiber.new { | arg0 | fiber.call(arg0) } 491 | } else if (fiber.arity == 2) { 492 | result = Fiber.new { | argv | fiber.call(argv[0], argv[1]) } 493 | } else if (fiber.arity == 3) { 494 | result = Fiber.new { | argv | fiber.call(argv[0], argv[1], argv[2]) } 495 | } else if (fiber.arity == 4) { 496 | result = Fiber.new { | argv | fiber.call(argv[0], argv[1], argv[2], argv[3]) } 497 | } 498 | } 499 | 500 | return result 501 | } 502 | static wrap(f) { 503 | Fiber.abort("Not implemented.") 504 | } 505 | 506 | static resume(co) { 507 | if (co.isDone) { 508 | return LTuple.new(false, "Cannot resume dead coroutine.") 509 | } 510 | temporary_ = null 511 | 512 | return LTuple.new(true, co.call()) 513 | } 514 | static resume(co, arg0) { 515 | if (co.isDone) { 516 | return LTuple.new(false, "Cannot resume dead coroutine.") 517 | } 518 | temporary_ = arg0 519 | 520 | return LTuple.new(true, co.call(arg0)) 521 | } 522 | static resume(co, arg0, arg1) { 523 | if (co.isDone) { 524 | return LTuple.new(false, "Cannot resume dead coroutine.") 525 | } 526 | temporary_ = LTuple.new(arg0, arg1) 527 | 528 | return LTuple.new(true, co.call([ arg0, arg1 ])) 529 | } 530 | static resume(co, arg0, arg1, arg2) { 531 | if (co.isDone) { 532 | return LTuple.new(false, "Cannot resume dead coroutine.") 533 | } 534 | temporary_ = LTuple.new(arg0, arg1, arg2) 535 | 536 | return LTuple.new(true, co.call([ arg0, arg1, arg2 ])) 537 | } 538 | static resume(co, arg0, arg1, arg2, arg3) { // Supports up to 4 parameters. 539 | if (co.isDone) { 540 | return LTuple.new(false, "Cannot resume dead coroutine.") 541 | } 542 | temporary_ = LTuple.new(arg0, arg1, arg2, arg3) 543 | 544 | return LTuple.new(true, co.call([ arg0, arg1, arg2, arg3 ])) 545 | } 546 | static yield() { 547 | Fiber.yield() 548 | 549 | return temporary_ 550 | } 551 | static yield(arg0) { 552 | Fiber.yield(arg0) 553 | 554 | return temporary_ 555 | } 556 | static yield(arg0, arg1) { 557 | Fiber.yield(LTuple.new(arg0, arg1)) 558 | 559 | return temporary_ 560 | } 561 | static yield(arg0, arg1, arg2) { 562 | Fiber.yield(LTuple.new(arg0, arg1, arg2)) 563 | 564 | return temporary_ 565 | } 566 | static yield(arg0, arg1, arg2, arg3) { // Supports up to 4 parameters. 567 | Fiber.yield(LTuple.new(arg0, arg1, arg2, arg3)) 568 | 569 | return temporary_ 570 | } 571 | 572 | static isYieldable() { 573 | return true 574 | } 575 | static running() { 576 | return Fiber.current 577 | } 578 | static status(co) { 579 | Fiber.abort("Not implemented.") 580 | } 581 | } 582 | // Coroutine end. 583 | // Coroutine lib. 584 | // String lib. 585 | // String begin. 586 | class LString { 587 | static byte(s) { 588 | return byte(s, 1) 589 | } 590 | static byte(s, i) { 591 | return byte(s, i, i)[1] 592 | } 593 | static byte(s, i, j) { 594 | return LTable.new(s.bytes.take(j).skip(i - 1)) 595 | } 596 | static char() { 597 | return "" 598 | } 599 | static char(arg0) { 600 | return String.fromCodePoint(arg0) 601 | } 602 | static char(arg0, arg1) { 603 | return char(arg0) + String.fromCodePoint(arg1) 604 | } 605 | static char(arg0, arg1, arg2) { 606 | return char(arg0, arg1) + String.fromCodePoint(arg2) 607 | } 608 | static char(arg0, arg1, arg2, arg3) { 609 | return char(arg0, arg1, arg2) + String.fromCodePoint(arg3) 610 | } 611 | static char(arg0, arg1, arg2, arg3, arg4) { 612 | return char(arg0, arg1, arg2, arg3) + String.fromCodePoint(arg4) 613 | } 614 | static char(arg0, arg1, arg2, arg3, arg4, arg5) { 615 | return char(arg0, arg1, arg2, arg3, arg4) + String.fromCodePoint(arg5) 616 | } 617 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 618 | return char(arg0, arg1, arg2, arg3, arg4, arg5) + String.fromCodePoint(arg6) 619 | } 620 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 621 | return char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) + String.fromCodePoint(arg7) 622 | } 623 | static dump(function) { 624 | Fiber.abort("Not implemented.") 625 | } 626 | static dump(function, strip) { 627 | Fiber.abort("Not implemented.") 628 | } 629 | static find(s, pattern) { 630 | Fiber.abort("Not implemented.") 631 | } 632 | static find(s, pattern, init) { 633 | Fiber.abort("Not implemented.") 634 | } 635 | static find(s, pattern, init, plain) { 636 | Fiber.abort("Not implemented.") 637 | } 638 | static format(formatstring) { 639 | Fiber.abort("Not implemented.") 640 | } 641 | static format(formatstring, arg0) { 642 | Fiber.abort("Not implemented.") 643 | } 644 | static format(formatstring, arg0, arg1) { 645 | Fiber.abort("Not implemented.") 646 | } 647 | static format(formatstring, arg0, arg1, arg2) { 648 | Fiber.abort("Not implemented.") 649 | } 650 | static format(formatstring, arg0, arg1, arg2, arg3) { 651 | Fiber.abort("Not implemented.") 652 | } 653 | static gmatch(s, pattern) { 654 | Fiber.abort("Not implemented.") 655 | } 656 | static gsub(s, pattern, repl) { 657 | Fiber.abort("Not implemented.") 658 | } 659 | static gsub(s, pattern, repl, n) { 660 | Fiber.abort("Not implemented.") 661 | } 662 | static len(s) { 663 | return s.count 664 | } 665 | static lower(s) { 666 | return s.map( 667 | Fn.new { | ch | 668 | if (ch.codePoints[0] >= "A".codePoints[0] && ch.codePoints[0] <= "Z".codePoints[0]) { 669 | return String.fromCodePoint(ch.codePoints[0] + ("a".codePoints[0] - "A".codePoints[0])) 670 | } 671 | 672 | return ch 673 | } 674 | ).join("") 675 | } 676 | static match(s, pattern) { 677 | Fiber.abort("Not implemented.") 678 | } 679 | static match(s, pattern, init) { 680 | Fiber.abort("Not implemented.") 681 | } 682 | static pack(fmt, v1, v2) { 683 | Fiber.abort("Not implemented.") 684 | } 685 | static packsize(fmt) { 686 | Fiber.abort("Not implemented.") 687 | } 688 | static rep(s, n) { 689 | return rep(s, n, "") 690 | } 691 | static rep(s, n, sep) { 692 | var result = "" 693 | for (i in 0...n) { 694 | result = result + s 695 | if (i != n - 1) { 696 | result = result + sep 697 | } 698 | } 699 | 700 | return result 701 | } 702 | static reverse(s) { 703 | var result = "" 704 | for (i in (s.count - 1)..0) { 705 | result = result + s[i] 706 | } 707 | 708 | return result 709 | } 710 | static sub(s, i) { 711 | return sub(s, i, s.count) 712 | } 713 | static sub(s, i, j) { 714 | return s.take(j).skip(i - 1).join("") 715 | } 716 | static unpack(fmt, s) { 717 | Fiber.abort("Not implemented.") 718 | } 719 | static unpack(fmt, s, pos) { 720 | Fiber.abort("Not implemented.") 721 | } 722 | static upper(s) { 723 | return s.map( 724 | Fn.new { | ch | 725 | if (ch.codePoints[0] >= "a".codePoints[0] && ch.codePoints[0] <= "z".codePoints[0]) { 726 | return String.fromCodePoint(ch.codePoints[0] + ("A".codePoints[0] - "a".codePoints[0])) 727 | } 728 | 729 | return ch 730 | } 731 | ).join("") 732 | } 733 | } 734 | // String end. 735 | // String lib. 736 | // Utf8 lib. 737 | // Utf8 begin. 738 | class LUtf8 { 739 | static char() { 740 | return "" 741 | } 742 | static char(arg0) { 743 | return String.fromCodePoint(arg0) 744 | } 745 | static char(arg0, arg1) { 746 | return char(arg0) + String.fromCodePoint(arg1) 747 | } 748 | static char(arg0, arg1, arg2) { 749 | return char(arg0, arg1) + String.fromCodePoint(arg2) 750 | } 751 | static char(arg0, arg1, arg2, arg3) { 752 | return char(arg0, arg1, arg2) + String.fromCodePoint(arg3) 753 | } 754 | static char(arg0, arg1, arg2, arg3, arg4) { 755 | return char(arg0, arg1, arg2, arg3) + String.fromCodePoint(arg4) 756 | } 757 | static char(arg0, arg1, arg2, arg3, arg4, arg5) { 758 | return char(arg0, arg1, arg2, arg3, arg4) + String.fromCodePoint(arg5) 759 | } 760 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 761 | return char(arg0, arg1, arg2, arg3, arg4, arg5) + String.fromCodePoint(arg6) 762 | } 763 | static char(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 764 | return char(arg0, arg1, arg2, arg3, arg4, arg5, arg6) + String.fromCodePoint(arg7) 765 | } 766 | static charPattern { 767 | Fiber.abort("Not implemented.") 768 | } 769 | static codes(s) { 770 | return LIPairs.new(LTable.new(s.codePoints)) 771 | } 772 | static codepoint(s) { 773 | return codepoint(s, 1) 774 | } 775 | static codepoint(s, i) { 776 | return codepoint(s, i, i)[1] 777 | } 778 | static codepoint(s, i, j) { 779 | return LTable.new(s.codePoints.take(j).skip(i - 1)) 780 | } 781 | static len(s) { 782 | return s.count 783 | } 784 | static len(s, i) { 785 | return s.skip(i - 1).count 786 | } 787 | static len(s, i, j) { 788 | return s.take(j).skip(i - 1).count 789 | } 790 | static offset(s, n) { 791 | Fiber.abort("Not implemented.") 792 | } 793 | static offset(s, n, i) { 794 | Fiber.abort("Not implemented.") 795 | } 796 | } 797 | // Utf8 end. 798 | // Utf8 lib. 799 | // Table lib. 800 | // Table begin. 801 | class LTable { 802 | static concat(list) { 803 | return concat(list, "") 804 | } 805 | static concat(list, sep) { 806 | return concat(list, sep, 1) 807 | } 808 | static concat(list, sep, i) { 809 | return concat(list, sep, i, list.len__) 810 | } 811 | static concat(list, sep, i, j) { 812 | var result = "" 813 | for (k in i..j) { 814 | result = result + list[k] 815 | if (k != j) { 816 | result = result + sep 817 | } 818 | } 819 | 820 | return result 821 | } 822 | static insert(list, value) { 823 | return insert(list, list.len__ + 1, value) 824 | } 825 | static insert(list, pos, value) { 826 | list[pos] = value 827 | } 828 | static move(a1, f, e, t) { 829 | Fiber.abort("Not implemented.") 830 | } 831 | static move(a1, f, e, t, a2) { 832 | Fiber.abort("Not implemented.") 833 | } 834 | static pack(arg0) { 835 | Fiber.abort("Not implemented.") 836 | } 837 | static remove(list) { 838 | return remove(list, list.len__) 839 | } 840 | static remove(list, pos) { 841 | var len = list.len__ 842 | if (pos <= 0 || pos > len) { 843 | return null 844 | } 845 | var result = list[pos] 846 | for (i in (pos + 1)...len) { 847 | list[i - 1] = list[i] 848 | } 849 | list[len] = null 850 | 851 | return result 852 | } 853 | static sort(list) { 854 | Fiber.abort("Not implemented.") 855 | } 856 | static sort(list, comp) { 857 | Fiber.abort("Not implemented.") 858 | } 859 | static unpack(list) { 860 | Fiber.abort("Not implemented.") 861 | } 862 | static unpack(list, i) { 863 | Fiber.abort("Not implemented.") 864 | } 865 | static unpack(list, i, j) { 866 | Fiber.abort("Not implemented.") 867 | } 868 | 869 | construct new() { 870 | _length = 0 871 | } 872 | construct new(obj) { 873 | _length = 0 874 | 875 | if (obj is List) { 876 | for (i in 0...obj.count) { 877 | this[i + 1] = obj[i] // 1-based. 878 | } 879 | } else if (obj is Map) { 880 | for (kv in obj) { 881 | this[kv.key] = kv.value 882 | } 883 | } else if (obj is Sequence) { 884 | var i = 0 885 | for (v in obj) { 886 | this[i + 1] = v // 1-based. 887 | i = i + 1 888 | } 889 | } 890 | } 891 | 892 | toString { 893 | if (len__ == data_.count) { 894 | var result = "" 895 | for (i in 1..len__) { 896 | result = result + data_[i].toString 897 | if (i != len__) { 898 | result = result + ", " 899 | } 900 | } 901 | 902 | return "{ " + result + " }" 903 | } 904 | 905 | return data_.toString 906 | } 907 | toWren { 908 | var result = null 909 | if (count == len__) { 910 | result = [ ] 911 | for (i in 0...count) { 912 | var v = this[i + 1] 913 | if (v is LTable) { 914 | v = v.toWren 915 | } 916 | result.add(v) // 1-based. 917 | } 918 | } else { 919 | result = { } 920 | for (kv in this) { 921 | var k = kv.key 922 | var v = kv.value 923 | if (k is LTable) { 924 | k = k.toWren 925 | } 926 | if (v is LTable) { 927 | v = v.toWren 928 | } 929 | result[k] = v 930 | } 931 | } 932 | 933 | return result 934 | } 935 | 936 | data_ { 937 | if (_data == null) { 938 | _data = { } 939 | } 940 | 941 | return _data 942 | } 943 | 944 | [index] { 945 | if (data_.containsKey(index)) { 946 | return data_[index] 947 | } 948 | 949 | return null 950 | } 951 | [index] = (value) { 952 | if (value == null) { 953 | if (data_.containsKey(index)) { 954 | data_.remove(index) 955 | } 956 | } else { 957 | data_[index] = value 958 | _length = -1 959 | } 960 | } 961 | 962 | count { 963 | return data_.count 964 | } 965 | isEmpty { 966 | return data_.isEmpty 967 | } 968 | clear() { 969 | data_.clear() 970 | } 971 | 972 | keys { 973 | return data_.keys 974 | } 975 | values { 976 | return data_.values 977 | } 978 | 979 | containsKey(key) { 980 | return data_.containsKey(key) 981 | } 982 | 983 | len__ { 984 | if (_length == -1) { 985 | for (i in 1..data_.count) { 986 | if (data_.containsKey(i)) { 987 | _length = i // 1-based. 988 | } else { 989 | break 990 | } 991 | } 992 | } 993 | 994 | return _length == -1 ? 0 : _length 995 | } 996 | 997 | iterate(iterator) { 998 | iterator = data_.iterate(iterator) 999 | 1000 | return iterator 1001 | } 1002 | iteratorValue(iterator) { 1003 | return data_.iteratorValue(iterator) 1004 | } 1005 | } // `LTable`. 1006 | // Table end. 1007 | // Table lib. 1008 | // Math lib. 1009 | // Math begin. 1010 | import "random" for Random 1011 | 1012 | class LMath { 1013 | static abs(x) { 1014 | return x.abs 1015 | } 1016 | static acos(x) { 1017 | return x.acos 1018 | } 1019 | static asin(x) { 1020 | return x.asin 1021 | } 1022 | static atan(y) { 1023 | return y.atan 1024 | } 1025 | static atan(y, x) { 1026 | return y.atan(x) 1027 | } 1028 | static ceil(x) { 1029 | return x.ceil 1030 | } 1031 | static cos(x) { 1032 | return x.cos 1033 | } 1034 | static deg(x) { 1035 | return x / Num.pi * 180 1036 | } 1037 | static exp(x) { 1038 | var e = 2.7182818284590452353602874713527 1039 | 1040 | return e.pow(x) 1041 | } 1042 | static floor(x) { 1043 | return x.floor 1044 | } 1045 | static fmod(x, y) { 1046 | return x - y * (x / y).floor 1047 | } 1048 | static huge { 1049 | return 1 / 0 1050 | } 1051 | static log(x) { 1052 | return x.log 1053 | } 1054 | static log(x, base) { 1055 | return x.log / base.log 1056 | } 1057 | static max(arg0, arg1) { 1058 | return arg0 > arg1 ? arg0 : arg1 1059 | } 1060 | static max(arg0, arg1, arg2) { 1061 | return max(max(arg0, arg1), arg2) 1062 | } 1063 | static max(arg0, arg1, arg2, arg3) { 1064 | return max(max(max(arg0, arg1), arg2), arg3) 1065 | } 1066 | static max(arg0, arg1, arg2, arg3, arg4) { 1067 | return max(max(max(max(arg0, arg1), arg2), arg3), arg4) 1068 | } 1069 | static max(arg0, arg1, arg2, arg3, arg4, arg5) { 1070 | return max(max(max(max(max(arg0, arg1), arg2), arg3), arg4), arg5) 1071 | } 1072 | static max(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 1073 | return max(max(max(max(max(max(arg0, arg1), arg2), arg3), arg4), arg5), arg6) 1074 | } 1075 | static max(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 1076 | return max(max(max(max(max(max(max(arg0, arg1), arg2), arg3), arg4), arg5), arg6), arg7) 1077 | } 1078 | static maxInteger { 1079 | Fiber.abort("Not implemented.") 1080 | } 1081 | static min(arg0, arg1) { 1082 | return arg0 < arg1 ? arg0 : arg1 1083 | } 1084 | static min(arg0, arg1, arg2) { 1085 | return min(min(arg0, arg1), arg2) 1086 | } 1087 | static min(arg0, arg1, arg2, arg3) { 1088 | return min(min(min(arg0, arg1), arg2), arg3) 1089 | } 1090 | static min(arg0, arg1, arg2, arg3, arg4) { 1091 | return min(min(min(min(arg0, arg1), arg2), arg3), arg4) 1092 | } 1093 | static min(arg0, arg1, arg2, arg3, arg4, arg5) { 1094 | return min(min(min(min(min(arg0, arg1), arg2), arg3), arg4), arg5) 1095 | } 1096 | static min(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 1097 | return min(min(min(min(min(min(arg0, arg1), arg2), arg3), arg4), arg5), arg6) 1098 | } 1099 | static min(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { // Supports up to 8 parameters. 1100 | return min(min(min(min(min(min(min(arg0, arg1), arg2), arg3), arg4), arg5), arg6), arg7) 1101 | } 1102 | static minInteger { 1103 | Fiber.abort("Not implemented.") 1104 | } 1105 | static modf(x) { 1106 | if (x < 0) { 1107 | return [ -(-x).floor, x + (-x).floor ] 1108 | } 1109 | 1110 | return [ x.floor, x - x.floor ] 1111 | } 1112 | static pi { 1113 | return Num.pi 1114 | } 1115 | static pow(x, y) { 1116 | return x.pow(y) 1117 | } 1118 | static rad(x) { 1119 | return x / 180 * Num.pi 1120 | } 1121 | static random { 1122 | if (__random == null) { 1123 | __random = Random.new() 1124 | } 1125 | 1126 | return __random 1127 | } 1128 | static random() { 1129 | return random.float() 1130 | } 1131 | static random(n) { 1132 | return random(1, n) 1133 | } 1134 | static random(m, n) { 1135 | return random.int(m, n + 1) 1136 | } 1137 | static randomSeed(x) { 1138 | __random = Random.new(x) 1139 | } 1140 | static sin(x) { 1141 | return x.sin 1142 | } 1143 | static sqrt(x) { 1144 | return x.sqrt 1145 | } 1146 | static tan(x) { 1147 | return x.tan 1148 | } 1149 | static toInteger(x) { 1150 | if (x is String) { 1151 | x = Num.fromString(x) 1152 | } 1153 | if (x is Num && x.isInteger) { 1154 | return x 1155 | } 1156 | 1157 | return null 1158 | } 1159 | static type(x) { 1160 | if (x is Num) { 1161 | if (x.isInteger) { 1162 | return "integer" 1163 | } else { 1164 | return "float" 1165 | } 1166 | } 1167 | 1168 | return null 1169 | } 1170 | static ult(m, n) { 1171 | Fiber.abort("Not implemented.") 1172 | } 1173 | } 1174 | 1175 | class math { 1176 | static huge { LMath.huge } 1177 | static maxInteger { LMath.maxInteger } 1178 | static minInteger { LMath.minInteger } 1179 | static pi { LMath.pi } 1180 | } 1181 | // Math end. 1182 | // Math lib. 1183 | 1184 | class Test { 1185 | static run() { 1186 | runLoop() 1187 | runLib() 1188 | runMath() 1189 | runString() 1190 | runUtf8() 1191 | runTable() 1192 | runCoroutine() 1193 | 1194 | System.print("OK") 1195 | } 1196 | 1197 | static runLoop() { 1198 | var sum = 0 1199 | 1200 | for (i in LRange.new(1, 3, 1)) { 1201 | sum = sum + i 1202 | } 1203 | assert(sum == 6, "`LRange` error.") 1204 | sum = 0 1205 | for (i in LRange.new(6, 1, -2)) { 1206 | sum = sum + i 1207 | } 1208 | assert(sum == 12, "`LRange` error.") 1209 | } 1210 | static runLib() { 1211 | assert(LStd.toNumber(LStd.toString(42)) == 42, "`Lib` error.") 1212 | assert(LStd.type(null) == "nil", "`Lib` error.") 1213 | assert(LStd.type(22 / 7) == "number", "`Lib` error.") 1214 | assert(LStd.type("hello") == "string", "`Lib` error.") 1215 | assert(LStd.type({ }) == "table", "`Lib` error.") 1216 | } 1217 | static runMath() { 1218 | var eq = Fn.new { | l, r | l == r } 1219 | 1220 | assert(eq.call(LMath.sin(0.5 * LMath.pi), (0.5 * Num.pi).sin), "`LMath` error.") 1221 | assert(eq.call(LMath.rad(0.5 * 180), 0.5 * Num.pi), "`LMath` error.") 1222 | assert(eq.call(LMath.sqrt(2), 2.sqrt), "`LMath` error.") 1223 | assert(eq.call(LMath.max(1 + 3, 2 * 2, 1.5, -2, 42), 42), "`LMath` error.") 1224 | } 1225 | static runString() { 1226 | assert(LString.lower("HeLlO") == "hello", "`LString` error.") 1227 | assert(LString.upper("HeLlO") == "HELLO", "`LString` error.") 1228 | assert(LString.rep("x", 5) == "xxxxx", "`LString` error.") 1229 | assert(LString.len("hello" + "world") == 10, "`LString` error.") 1230 | assert(LString.byte("hello") == 104, "`LString` error.") 1231 | assert(LString.byte("hello", 2) == 101, "`LString` error.") 1232 | assert(LString.byte("hello", 2, 4).count == 3, "`LString` error.") 1233 | assert(LString.sub("hello", 2, 4) == "ell", "`LString` error.") 1234 | } 1235 | static runUtf8() { 1236 | assert(LUtf8.len("hello") == 5, "`LUtf8` error.") 1237 | assert(LUtf8.codes("hello").reduce(0, Fn.new { | acc, i | acc + i[1] }) == 532, "`LUtf8` error.") 1238 | assert(LUtf8.codepoint("hello") == 104, "`LUtf8` error.") 1239 | assert(LUtf8.codepoint("hello", 2) == 101, "`LUtf8` error.") 1240 | assert(LUtf8.codepoint("hello", 2, 4).count == 3, "`LUtf8` error.") 1241 | } 1242 | static runTable() { 1243 | var sum = 0 1244 | var txt = "" 1245 | var tbl = null 1246 | 1247 | tbl = LTable.new( 1248 | { 1249 | 1: "uno", 2: "dos", 3: "thres", 4: "cuatro", 1250 | "key": "value" 1251 | } 1252 | ) 1253 | tbl[4] = null 1254 | tbl["nil"] = "something" 1255 | tbl["nil"] = null 1256 | assert(tbl.len__ == 3 && tbl.count == 4, "`LTable` error.") 1257 | 1258 | sum = 0 1259 | txt = "" 1260 | for (t in LIPairs.new(tbl)) { 1261 | var k = t[0] 1262 | var v = t[1] 1263 | sum = sum + k 1264 | txt = txt + v 1265 | } 1266 | assert(sum == 6 && txt.count == 11, "`LIPairs` error.") 1267 | txt = "" 1268 | for (t in LPairs.new(tbl)) { 1269 | var k = t[0] 1270 | var v = tbl[k] 1271 | txt = txt + v 1272 | } 1273 | assert(txt.count == 16, "`LPairs` error.") 1274 | } 1275 | static runCoroutine() { 1276 | var co = LCoroutine.create( 1277 | Fn.new { | n | 1278 | LCoroutine.yield(n + 1) 1279 | LCoroutine.yield(n + 2) 1280 | LCoroutine.yield(n + 3) 1281 | 1282 | return n + 4 1283 | } 1284 | ) 1285 | 1286 | assert(LCoroutine.resume(co, 42) == LTuple.new(true, 43), "`LCoroutine` error.") 1287 | assert(LCoroutine.resume(co, 42) == LTuple.new(true, 44), "`LCoroutine` error.") 1288 | assert(LCoroutine.resume(co, 42) == LTuple.new(true, 45), "`LCoroutine` error.") 1289 | assert(LCoroutine.resume(co, 42) == LTuple.new(true, 46), "`LCoroutine` error.") 1290 | assert(LCoroutine.resume(co, 42) == LTuple.new(false, "Cannot resume dead coroutine."), "`LCoroutine` error.") 1291 | } 1292 | 1293 | static assert(cond, msg) { 1294 | if (cond) { 1295 | return 1296 | } 1297 | System.print(msg) 1298 | } 1299 | } 1300 | 1301 | Test.run() 1302 | -------------------------------------------------------------------------------- /test/utf8.lua: -------------------------------------------------------------------------------- 1 | print(utf8.len('你好')) 2 | for i, v in utf8.codes('你好') do 3 | print(i, v) 4 | end 5 | print(utf8.codepoint('hello')) 6 | print(utf8.codepoint('hello', 2)) 7 | print(utf8.codepoint('hello', 2, 4)) 8 | -------------------------------------------------------------------------------- /test_lib.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | call wren.exe test\test_lib.wren 3 | echo Ready! 4 | -------------------------------------------------------------------------------- /util/lua.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paladin-t/b95/ac6c3daad833141bce1ef0bf56754b71b932a699/util/lua.exe -------------------------------------------------------------------------------- /util/syntax.lua: -------------------------------------------------------------------------------- 1 | function class(kls, base) 2 | if not base then 3 | base = { } 4 | end 5 | kls.__index = function (self, key) 6 | local get = function (this, key) 7 | local t = rawget(this, key) 8 | if t then return t end 9 | 10 | t = kls[key] 11 | if t then return t end 12 | 13 | return base[key] 14 | end 15 | 16 | local t = get(self, 'get_' .. key) 17 | if t then return t(self) end 18 | 19 | return get(self, key) 20 | end 21 | kls.__newindex = function (self, key, value) 22 | local t = rawget(self, 'set_' .. key) 23 | if t then return t(self, value) end 24 | 25 | rawset(self, key, value) 26 | end 27 | setmetatable(kls, base) 28 | 29 | return kls 30 | end 31 | 32 | function new(kls, ...) 33 | local obj = { } 34 | setmetatable(obj, kls) 35 | obj:new(...) 36 | 37 | return obj 38 | end 39 | 40 | function is(obj, kls) 41 | repeat 42 | if obj == kls then 43 | return true 44 | end 45 | obj = getmetatable(obj) 46 | until not obj 47 | 48 | return false 49 | end 50 | 51 | function call(fn, ...) 52 | return fn(...) 53 | end 54 | 55 | function apply(fn, ...) 56 | return fn(...) 57 | end 58 | 59 | function length(obj) 60 | return #obj 61 | end 62 | -------------------------------------------------------------------------------- /util/test_syntax.lua: -------------------------------------------------------------------------------- 1 | require 'syntax' 2 | 3 | Base = class( 4 | { 5 | new = function (self, name) 6 | self.name = name 7 | end, 8 | 9 | name = 'Base', 10 | get_age = function (self) 11 | return 16 12 | end, 13 | 14 | bark = function (self) 15 | print('Hello, I\'m ' .. self.name) 16 | end 17 | } 18 | ) 19 | Derived = class( 20 | { 21 | new = function (self, name) 22 | self.name = name 23 | end, 24 | 25 | name = 'Derived', 26 | age_ = 16, 27 | get_age = function (self) 28 | return self.age_ 29 | end, 30 | set_age = function (self, value) 31 | self.age_ = value 32 | end, 33 | 34 | fly = function (self) 35 | print('I can fly!') 36 | end 37 | }, 38 | Base 39 | ) 40 | 41 | local b = new(Base, 'Bob') 42 | local d = new(Derived, 'David') 43 | b:bark() 44 | d:bark() 45 | d:fly() 46 | 47 | print(is(b, Base), is(b, Derived)) 48 | print(is(d, Base), is(d, Derived)) 49 | 50 | print(b.age); b.age = 18; print(b.age) 51 | print(d.age); d.age = 18; print(d.age) 52 | 53 | call(function (a, b) print(a / b) end, 22, 7) 54 | 55 | print(length({ 1, 2, 3 })) 56 | -------------------------------------------------------------------------------- /wren.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paladin-t/b95/ac6c3daad833141bce1ef0bf56754b71b932a699/wren.exe --------------------------------------------------------------------------------