From 7357769852ee88bfa88bd75711ebc38c5a5b0307 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:33:35 -0500 Subject: [PATCH 1/7] feat: local vars section --- docs/caveats.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/docs/caveats.md b/docs/caveats.md index 57a731e..2fd5e05 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -82,3 +82,75 @@ Even though iterating over object keys with `for ... in` does not guarantee orde ### Iterating an array with `for ... in` Not allowed. + +### Local Variable Limit + +In most cases, TSTL creates Lua code that declares variables using the `local` keyword, which makes the variables local to the function or block. In other words: + +```ts +const foo = 123; +``` + +Usually gets transpiled to: + +```lua +local foo = 123 +``` + +In JavaScript/TypeScript, there is no limit to the amount of variables that you can create. However, in Lua, there is a limit of 200 local variables at any point in time. For big TSTL programs, this can be a problem, causing a run-time error in production that the compiler will not catch! + +For example, imagine that a TSTL program consists of 250 individual features that are separated out into different feature classes, each in their own separate file. And upon program startup, all of the classes are instantiated: + +```ts +import { Feature1 } from "./features/Feature1"; +import { Feature2 } from "./features/Feature2"; +import { Feature3 } from "./features/Feature3"; +... +import { Feature101 } from "./features/Feature101"; + +const FEATURE_CLASSES = [ + Feature1, + Feature2, + Feature3, + ... + Feature101, +]; + +export function initProgram(): void { + for (const featureClass of FEATURE_CLASSES) { + new featureClass(); + } +} +``` + +Since each transpiled import statement creates two separate local variables, this would create 202 local variables, and the program would immediately crash upon first being loaded. + +You can solve this problem in a few different ways. For this specific pattern, we recommend using a [barrel file](https://basarat.gitbook.io/typescript/main-1/barrel), which is a file that contains only imports and exports. Specifically, our fixed program would look like this: + +```ts title=featureClasses.ts +export { Feature1 } from "./features/Feature1"; +export { Feature2 } from "./features/Feature1"; +export { Feature3 } from "./features/Feature1"; +... +export { Feature101 } from "./features/Feature101"; +``` + +```ts +import * as fc from "./featureClasses.ts"; + +const FEATURE_CLASSES = [ + fc.Feature1, + fc.Feature2, + fc.Feature3, + ... + fc.Feature101, +]; + +export function initProgram(): void { + for (const featureClass of FEATURE_CLASSES) { + new featureClass(); + } +} +``` + +Importatly, once we have a barrel file, we do not have to artificially split up the number of classes. This is because TSTL does not transpile exports with any local variables at all. Thus, we can have an unlimited number of classes inside of the barrel file without ever hitting the Lua local variable limit. From a61fad2a2c040372288172227c775db432a45680 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:37:02 -0500 Subject: [PATCH 2/7] Update caveats.md --- docs/caveats.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/caveats.md b/docs/caveats.md index 2fd5e05..7e49ebd 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -99,7 +99,7 @@ local foo = 123 In JavaScript/TypeScript, there is no limit to the amount of variables that you can create. However, in Lua, there is a limit of 200 local variables at any point in time. For big TSTL programs, this can be a problem, causing a run-time error in production that the compiler will not catch! -For example, imagine that a TSTL program consists of 250 individual features that are separated out into different feature classes, each in their own separate file. And upon program startup, all of the classes are instantiated: +For example, imagine that a TSTL program consists of 101 individual features that are separated out into different feature classes, each in their own separate file. And upon program startup, all of the classes are instantiated: ```ts import { Feature1 } from "./features/Feature1"; From 4c062ea1dca3e77c4108ba104d09c8f18f4e0adb Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:38:17 -0500 Subject: [PATCH 3/7] Update caveats.md --- docs/caveats.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/caveats.md b/docs/caveats.md index 7e49ebd..c9c6338 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -101,7 +101,7 @@ In JavaScript/TypeScript, there is no limit to the amount of variables that you For example, imagine that a TSTL program consists of 101 individual features that are separated out into different feature classes, each in their own separate file. And upon program startup, all of the classes are instantiated: -```ts +```ts title=main.ts import { Feature1 } from "./features/Feature1"; import { Feature2 } from "./features/Feature2"; import { Feature3 } from "./features/Feature3"; @@ -135,7 +135,7 @@ export { Feature3 } from "./features/Feature1"; export { Feature101 } from "./features/Feature101"; ``` -```ts +```ts title=main.ts import * as fc from "./featureClasses.ts"; const FEATURE_CLASSES = [ From 0a47ebee96bb997301385e1edd734baf8c5b1b6e Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:38:52 -0500 Subject: [PATCH 4/7] Update caveats.md --- docs/caveats.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/caveats.md b/docs/caveats.md index c9c6338..f0ea831 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -116,10 +116,8 @@ const FEATURE_CLASSES = [ Feature101, ]; -export function initProgram(): void { - for (const featureClass of FEATURE_CLASSES) { - new featureClass(); - } +for (const featureClass of FEATURE_CLASSES) { + new featureClass(); } ``` @@ -146,10 +144,8 @@ const FEATURE_CLASSES = [ fc.Feature101, ]; -export function initProgram(): void { - for (const featureClass of FEATURE_CLASSES) { - new featureClass(); - } +for (const featureClass of FEATURE_CLASSES) { + new featureClass(); } ``` From fef684c741aa7e36d203b3dc3d449da7cae7b959 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:42:19 -0500 Subject: [PATCH 5/7] fix: prettier --- docs/caveats.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/caveats.md b/docs/caveats.md index f0ea831..e2a5296 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -136,16 +136,10 @@ export { Feature101 } from "./features/Feature101"; ```ts title=main.ts import * as fc from "./featureClasses.ts"; -const FEATURE_CLASSES = [ - fc.Feature1, - fc.Feature2, - fc.Feature3, - ... - fc.Feature101, -]; +const FEATURE_CLASSES = [fc.Feature1, fc.Feature2, fc.Feature3, ...fc.Feature101]; for (const featureClass of FEATURE_CLASSES) { - new featureClass(); + new featureClass(); } ``` From e10aaf9c0dc48e17722212625aee301aac016573 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:44:16 -0500 Subject: [PATCH 6/7] fix: prettier --- docs/caveats.md | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/caveats.md b/docs/caveats.md index e2a5296..ed1d9a3 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -109,15 +109,15 @@ import { Feature3 } from "./features/Feature3"; import { Feature101 } from "./features/Feature101"; const FEATURE_CLASSES = [ - Feature1, - Feature2, - Feature3, - ... - Feature101, + Feature1, + Feature2, + Feature3, + ..., + Feature101, ]; for (const featureClass of FEATURE_CLASSES) { - new featureClass(); + new featureClass(); } ``` @@ -136,7 +136,13 @@ export { Feature101 } from "./features/Feature101"; ```ts title=main.ts import * as fc from "./featureClasses.ts"; -const FEATURE_CLASSES = [fc.Feature1, fc.Feature2, fc.Feature3, ...fc.Feature101]; +const FEATURE_CLASSES = [ + fc.Feature1, + fc.Feature2, + fc.Feature3, + ..., + fc.Feature101, +]; for (const featureClass of FEATURE_CLASSES) { new featureClass(); From 5cfad11c34f141bd40b04fb8e6ecfc5491cf18c5 Mon Sep 17 00:00:00 2001 From: James <5511220+Zamiell@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:45:43 -0500 Subject: [PATCH 7/7] fix: wording --- docs/caveats.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/caveats.md b/docs/caveats.md index ed1d9a3..09e9f3a 100644 --- a/docs/caveats.md +++ b/docs/caveats.md @@ -149,4 +149,4 @@ for (const featureClass of FEATURE_CLASSES) { } ``` -Importatly, once we have a barrel file, we do not have to artificially split up the number of classes. This is because TSTL does not transpile exports with any local variables at all. Thus, we can have an unlimited number of classes inside of the barrel file without ever hitting the Lua local variable limit. +Importatly, once we have a barrel file, we do not have to artificially split up the number of classes. This is because TSTL does not transpile exports with any local variables at all. Thus, we can have an unlimited number of exports inside of the barrel file without ever hitting the Lua local variable limit.