@tilua/compiler 6.1.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -22
- package/dist/{chunk-574KDV5W.js → chunk-NM3EVX2J.js} +566 -82
- package/dist/cli.cjs +569 -91
- package/dist/cli.js +4 -10
- package/dist/index.cjs +566 -83
- package/dist/index.d.cts +165 -115
- package/dist/index.d.ts +165 -115
- package/dist/index.js +1 -2
- package/package.json +2 -2
- package/runtime/json.luau +255 -0
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# @tilua/compiler
|
|
2
2
|
|
|
3
3
|
Compiles a [tilua](https://marketplace.visualstudio.com/search?term=tilua)
|
|
4
|
-
project to one
|
|
4
|
+
project to one Lua file — Lua that runs on Lua 5.1 to 5.4, LuaJIT and Luau
|
|
5
|
+
alike, or Luau where a library says the project is Luau (see [Lua and
|
|
6
|
+
Luau](#lua-and-luau)). Each file is parsed by
|
|
5
7
|
[`@tilua/parser`](https://www.npmjs.com/package/@tilua/parser), its AST lowered
|
|
6
8
|
to a `luau-parser` AST, and that AST printed by `luau-parser`.
|
|
7
9
|
|
|
@@ -12,7 +14,7 @@ npx tilua src/main.tilua --out build/main.luau
|
|
|
12
14
|
|
|
13
15
|
```
|
|
14
16
|
tilua <entry> [--out <file>] [--output single|chunks|modules] [--config <tilua.config.json>]
|
|
15
|
-
[--noCheck]
|
|
17
|
+
[--noCheck]
|
|
16
18
|
```
|
|
17
19
|
|
|
18
20
|
Every module the entry imports is bundled in. Problems are reported as
|
|
@@ -38,7 +40,7 @@ const result = await bundle({
|
|
|
38
40
|
// A config file's path, or its contents:
|
|
39
41
|
config: { types: ["roblox"], paths: { "@shared/*": ["src/shared/*"] } },
|
|
40
42
|
})
|
|
41
|
-
result.code // the
|
|
43
|
+
result.code // the Lua bundle, unless a module failed
|
|
42
44
|
result.files // [{ path, code, modules }] — one, unless `output` says otherwise
|
|
43
45
|
result.diagnostics // { file, line, column, message, category: "syntax" | "module" | "type" | "config" }
|
|
44
46
|
|
|
@@ -56,10 +58,10 @@ JavaScript module the build loads.
|
|
|
56
58
|
|
|
57
59
|
## What becomes what
|
|
58
60
|
|
|
59
|
-
| tilua |
|
|
61
|
+
| tilua | Lua |
|
|
60
62
|
|---|---|
|
|
61
63
|
| `const { a, b } = value` | `local a, b = value.a, value.b` |
|
|
62
|
-
| `const [x, ...rest] = list` | `local x = list[1]; local rest =
|
|
64
|
+
| `const [x, ...rest] = list` | `local x = list[1]; local rest = tilua_move(list, 2, #list, 1, {})` — `table.move` where the Lua has it; `{}` written down as an array |
|
|
63
65
|
| `const { a = 1 } = t` | `local a = t.a; if a == nil then a = 1 end` |
|
|
64
66
|
| `[1, 2]` / `{ a: 1, b }` | `tilua_asArray({ 1, 2 })` / `{ a = 1, b = b }` — see `typeof` below |
|
|
65
67
|
| `typeof v` | `tilua_typeof(v)`, or `tilua_typeof(v, "array")` where `v`'s type already says which table it is |
|
|
@@ -99,22 +101,33 @@ JavaScript module the build loads.
|
|
|
99
101
|
| `x as T`, `x satisfies T`, types, `interface`, `export type { … }`, `declare` | removed |
|
|
100
102
|
| `names:filter(f)` | whatever the type library that declared `filter` says — see below |
|
|
101
103
|
|
|
102
|
-
## Lua
|
|
104
|
+
## Lua and Luau
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
The compiler knows Lua. What it writes is Lua 5.1's syntax, and runs on Lua
|
|
107
|
+
5.1 to 5.4, LuaJIT and Luau alike: `table.move`, `table.unpack` and `typeof`
|
|
108
|
+
are used where the Lua has them and stood in for where it does not.
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
|
113
|
-
|
|
110
|
+
A Lua with more syntax is a type library's to say — its lowering lists it
|
|
111
|
+
(`syntax`, see [What a type library lowers](#what-a-type-library-lowers)). `@tilua-types/luau` says
|
|
112
|
+
Luau's, and `@tilua-types/roblox` loads it, so a Roblox project is written as
|
|
113
|
+
Luau without asking:
|
|
114
|
+
|
|
115
|
+
| written | Lua (no library) | Luau (`"types": ["luau"]`, or `["roblox"]`) |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `a += b`, `a // b` | `a = a + (b)`, `math.floor(a / (b))` | as written |
|
|
118
|
+
| `continue` | a `break` out of a one-pass `repeat` | as written |
|
|
119
|
+
| `c ? a : b`, `a?.b`, `a ?? b` | `and`/`or` where neither arm can be `false`, else a function called on the spot | `if c then a else b` |
|
|
120
|
+
| `for (const x in xs)` | `ipairs(xs)` where `xs` is an array by its type; otherwise `tilua_each(xs)`, which walks a table as Luau would — its `__iter` if it has one, `next` if not | `for _, x in xs do` |
|
|
121
|
+
| `1_000`, `0b101` | plain numbers | as written |
|
|
122
|
+
| `@native` and other attributes | dropped | kept |
|
|
123
|
+
| another file of the bundle | `loadfile` | `require` by path |
|
|
114
124
|
|
|
115
|
-
An object's `freeze` does nothing
|
|
116
|
-
|
|
117
|
-
builds a program
|
|
125
|
+
An object's `freeze` does nothing on a Lua without `table.freeze`, and
|
|
126
|
+
`isFrozen` answers `false`. `npm test` with `LUA51` naming a Lua 5.1
|
|
127
|
+
interpreter builds a program both ways and checks they print the same.
|
|
128
|
+
|
|
129
|
+
The config's `target` is gone: `"target": "lua51"` is now what every build
|
|
130
|
+
is, and `"luau"` is `"types": ["luau"]`.
|
|
118
131
|
|
|
119
132
|
## `typeof`, arrays and objects
|
|
120
133
|
|
|
@@ -249,6 +262,14 @@ declared as). An answer can `prepend` Luau expressions ahead of the written
|
|
|
249
262
|
arguments. `globalCall` and `globalValue` answer for a global, such as
|
|
250
263
|
`print(x)` or a bare `print`. A runtime can read `__LINES__` to reach the
|
|
251
264
|
bundle's line map, and wraps a new array it answers with in `__ARRAY__(...)`. See the `@tilua/parser` README for the details.
|
|
265
|
+
|
|
266
|
+
A library for a Lua with more syntax than 5.1's lists it, and the output uses
|
|
267
|
+
it (see [Lua and Luau](#lua-and-luau)):
|
|
268
|
+
|
|
269
|
+
```js
|
|
270
|
+
export default { syntax: ["compoundAssignment", "continue", "ifExpression", "floorDivision",
|
|
271
|
+
"iteration", "attributes", "numberLiterals", "requireByPath"] }
|
|
272
|
+
```
|
|
252
273
|
The standard library's own lowering (src/standard.ts) is written with these
|
|
253
274
|
hooks too; `"noLib": true` leaves it out with the library.
|
|
254
275
|
|
|
@@ -334,6 +355,32 @@ Modules follow ES module rules, including when they import each other:
|
|
|
334
355
|
loaded by calling it. The path is a string literal; the module it names is
|
|
335
356
|
part of the bundle like any other.
|
|
336
357
|
|
|
358
|
+
## Tree shaking
|
|
359
|
+
|
|
360
|
+
`"treeShaking": true` in `tilua.config.json` (or `bundle({ treeShaking })`)
|
|
361
|
+
leaves out of the bundle what the entry never reaches:
|
|
362
|
+
|
|
363
|
+
- **Declarations nothing reads.** A top-level function, class or `const`
|
|
364
|
+
that nothing kept reads, and whose value costs nothing to leave unmade — a
|
|
365
|
+
literal, a function, a class whose statics are not calls. A `const` made by
|
|
366
|
+
a call stays: the call is something the module does.
|
|
367
|
+
- **Exports nothing imports.** `import { a }` reads `a`, `M.a` reads `a` of
|
|
368
|
+
`import * as M`, and anything else done with `M` — or `import("./x")` —
|
|
369
|
+
reads every export. `export { a } from` and `export * from` pass a read on;
|
|
370
|
+
the entry's exports are always read.
|
|
371
|
+
- **Modules nothing needs.** A module none of whose exports are read, and
|
|
372
|
+
that does nothing as it runs, is not bundled. One that does something —
|
|
373
|
+
prints, registers, connects — still runs where it is imported, as an ES
|
|
374
|
+
module does, even if nothing it exports is read.
|
|
375
|
+
- **Runtime functions nothing calls.** The language's and the libraries'
|
|
376
|
+
runtime tables keep the members the program calls, and what those call:
|
|
377
|
+
`xs:map(f):join(",")` brings `map` and `join`, not the rest of the array
|
|
378
|
+
methods.
|
|
379
|
+
|
|
380
|
+
Off by default: what is left out is decided from the code, and code that
|
|
381
|
+
reaches a module by a name only the running program knows — `G.require` of a
|
|
382
|
+
string built at runtime — is not something it can see.
|
|
383
|
+
|
|
337
384
|
## Several files
|
|
338
385
|
|
|
339
386
|
`"output"` in `tilua.config.json` (or `--output`, or `bundle({ output })`)
|
|
@@ -373,12 +420,12 @@ that file, once, the first time one of its modules is asked for — by an
|
|
|
373
420
|
`import()`, or by an `import` statement in a module that was itself loaded
|
|
374
421
|
late. So a file costs nothing until then.
|
|
375
422
|
|
|
376
|
-
How a file is loaded
|
|
423
|
+
How a file is loaded depends on the Lua (see [Lua and Luau](#lua-and-luau)):
|
|
377
424
|
|
|
378
|
-
|
|
|
425
|
+
| Lua | loads a file with |
|
|
379
426
|
|---|---|
|
|
380
|
-
|
|
|
381
|
-
| `
|
|
427
|
+
| any | `loadfile(folder .. "main_src_shop.luau")()(G)`, where `folder` is the entry's own, read off `debug.getinfo` |
|
|
428
|
+
| Luau (`requireByPath`) | `require("./main_src_shop")(G)` — `require` by path, read from the entry's own file. In Roblox each file is a ModuleScript beside the entry's |
|
|
382
429
|
|
|
383
430
|
Either way the files have to stay where they were written, relative to the
|
|
384
431
|
entry's.
|