lt-script 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 LT Language Authors
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.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # LT Language Compiler
2
+
3
+ A compiler for the LT language, targeting FiveM Lua.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g lt-compiler
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ ltc help
15
+ ```
16
+
17
+ ### Compiler
18
+
19
+ ```bash
20
+ ltc build <sourceDir> <outDir>
21
+ ```
22
+
23
+ ### Watch Mode
24
+
25
+ ```bash
26
+ ltc watch <sourceDir> <outDir>
27
+ ```
28
+
29
+ ## Features
30
+
31
+ - Transpiles LT to Lua 5.4 (FiveM compatible)
32
+ - Supports static typing syntax (transpiled to comments or checked)
33
+ - FiveM native function support
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ import { compile } from '../index.js';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { getAllFiles, ensureDirectoryExistence } from './utils.js';
6
+ const args = process.argv.slice(2);
7
+ const command = args[0];
8
+ if (!command) {
9
+ printUsage();
10
+ process.exit(1);
11
+ }
12
+ switch (command) {
13
+ case 'watch':
14
+ handleWatch(args.slice(1));
15
+ break;
16
+ case 'build':
17
+ handleBuild(args.slice(1));
18
+ break;
19
+ default:
20
+ console.error(`Unknown command: ${command}`);
21
+ printUsage();
22
+ process.exit(1);
23
+ }
24
+ function printUsage() {
25
+ console.log(`
26
+ Usage:
27
+ ltc watch <targetDir> # Watches <targetDir>/src and builds to <targetDir>/build
28
+ ltc watch <sourceDir> <outDir> # Watches <sourceDir> and builds to <outDir>
29
+ ltc build <targetDir> # Builds <targetDir>/src to <targetDir>/build once
30
+ ltc build <sourceDir> <outDir> # Builds <sourceDir> to <outDir> once
31
+ `);
32
+ }
33
+ function parsePaths(cmdArgs) {
34
+ if (cmdArgs.length === 0)
35
+ return null;
36
+ let srcDir = '';
37
+ let outDir = '';
38
+ const target = cmdArgs[0];
39
+ if (cmdArgs.length === 1) {
40
+ // Convention mode: ltc watch lt-fuel
41
+ const potentialSrc = path.join(target, 'src');
42
+ if (fs.existsSync(potentialSrc) && fs.statSync(potentialSrc).isDirectory()) {
43
+ srcDir = potentialSrc;
44
+ outDir = path.join(target, 'build');
45
+ console.log(`[LT] Auto-detected structure. Source: ${srcDir}, Output: ${outDir}`);
46
+ }
47
+ else {
48
+ // Fallback? Or strict?
49
+ // If just passing a folder that HAS .lt files but no src/ folder?
50
+ // Let's assume strict src/build convention for single argument or error
51
+ console.error(`[LT] Error: Could not find 'src' directory in '${target}'.`);
52
+ console.error(` Please use 'ltc ${command} <sourceDir> <outDir>' for explicit paths.`);
53
+ return null;
54
+ }
55
+ }
56
+ else {
57
+ // Explicit mode
58
+ srcDir = cmdArgs[0];
59
+ outDir = cmdArgs[1];
60
+ }
61
+ // Resolve to absolute
62
+ srcDir = path.resolve(srcDir);
63
+ outDir = path.resolve(outDir);
64
+ if (!fs.existsSync(srcDir)) {
65
+ console.error(`[LT] Error: Source directory '${srcDir}' does not exist.`);
66
+ return null;
67
+ }
68
+ return { srcDir, outDir };
69
+ }
70
+ function compileFile(srcPath, srcRoot, outRoot) {
71
+ try {
72
+ const relative = path.relative(srcRoot, srcPath);
73
+ const outPath = path.join(outRoot, relative.replace(/\.lt$/, '.lua'));
74
+ console.log(`[LT] Compiling: ${relative}`);
75
+ const content = fs.readFileSync(srcPath, 'utf-8');
76
+ const start = performance.now();
77
+ const lua = compile(content);
78
+ const end = performance.now();
79
+ ensureDirectoryExistence(outPath);
80
+ fs.writeFileSync(outPath, lua, 'utf8');
81
+ console.log(`[LT] ✓ Success (${(end - start).toFixed(2)}ms)`);
82
+ }
83
+ catch (e) {
84
+ console.error(`[LT] ✗ Error compiling ${srcPath}:`);
85
+ console.error(e.message);
86
+ }
87
+ }
88
+ function handleBuild(cmdArgs) {
89
+ const paths = parsePaths(cmdArgs);
90
+ if (!paths)
91
+ process.exit(1);
92
+ const { srcDir, outDir } = paths;
93
+ console.log(`[LT] Building from '${srcDir}' to '${outDir}'...`);
94
+ const files = getAllFiles(srcDir, '.lt');
95
+ files.forEach(file => compileFile(file, srcDir, outDir));
96
+ console.log(`[LT] Build complete. ${files.length} files processed.`);
97
+ }
98
+ function handleWatch(cmdArgs) {
99
+ const paths = parsePaths(cmdArgs);
100
+ if (!paths)
101
+ process.exit(1);
102
+ const { srcDir, outDir } = paths;
103
+ // Initial build
104
+ handleBuild(cmdArgs);
105
+ console.log(`[LT] Watching for changes in '${srcDir}'...`);
106
+ let fsWait = null;
107
+ // Recursive watch
108
+ fs.watch(srcDir, { recursive: true }, (event, filename) => {
109
+ if (!filename)
110
+ return;
111
+ // Windows/Mac returning filename
112
+ if (!filename.endsWith('.lt'))
113
+ return; // Ignore non-lt files
114
+ const fullPath = path.join(srcDir, filename);
115
+ if (fsWait)
116
+ clearTimeout(fsWait);
117
+ fsWait = setTimeout(() => {
118
+ fsWait = null;
119
+ if (fs.existsSync(fullPath)) {
120
+ // Modified or Created
121
+ compileFile(fullPath, srcDir, outDir);
122
+ }
123
+ else {
124
+ // Deleted
125
+ const relative = path.relative(srcDir, fullPath);
126
+ const outPath = path.join(outDir, relative.replace(/\.lt$/, '.lua'));
127
+ if (fs.existsSync(outPath)) {
128
+ fs.unlinkSync(outPath);
129
+ console.log(`[LT] Removed: ${relative.replace(/\.lt$/, '.lua')}`);
130
+ }
131
+ }
132
+ }, 100); // 100ms debounce
133
+ });
134
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getAllFiles(dir: string, extension: string, fileList?: string[]): string[];
2
+ export declare function ensureDirectoryExistence(filePath: string): void;
@@ -0,0 +1,26 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ export function getAllFiles(dir, extension, fileList = []) {
4
+ const files = fs.readdirSync(dir);
5
+ files.forEach(file => {
6
+ const filePath = path.join(dir, file);
7
+ const stat = fs.statSync(filePath);
8
+ if (stat.isDirectory()) {
9
+ getAllFiles(filePath, extension, fileList);
10
+ }
11
+ else {
12
+ if (path.extname(file) === extension) {
13
+ fileList.push(filePath);
14
+ }
15
+ }
16
+ });
17
+ return fileList;
18
+ }
19
+ export function ensureDirectoryExistence(filePath) {
20
+ const dirname = path.dirname(filePath);
21
+ if (fs.existsSync(dirname)) {
22
+ return;
23
+ }
24
+ ensureDirectoryExistence(dirname);
25
+ fs.mkdirSync(dirname);
26
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,42 @@
1
+ import { compile } from '../index.js';
2
+ import * as fs from 'fs';
3
+ const args = process.argv.slice(2);
4
+ if (args.length === 0) {
5
+ console.error("Usage: node watch.js <file.lt>");
6
+ process.exit(1);
7
+ }
8
+ const sourcePath = args[0];
9
+ const targetPath = sourcePath.replace(/\.lt$/, '.lua');
10
+ if (!fs.existsSync(sourcePath)) {
11
+ console.error(`Error: File '${sourcePath}' not found.`);
12
+ process.exit(1);
13
+ }
14
+ console.log(`[LT] Watching '${sourcePath}'...`);
15
+ function recompile() {
16
+ try {
17
+ console.log(`[LT] File changed. Compiling...`);
18
+ const content = fs.readFileSync(sourcePath, 'utf-8');
19
+ const start = performance.now();
20
+ const lua = compile(content);
21
+ const end = performance.now();
22
+ fs.writeFileSync(targetPath, lua, 'utf8');
23
+ console.log(`[LT] ✓ Success! (${(end - start).toFixed(2)}ms) -> ${targetPath}`);
24
+ }
25
+ catch (e) {
26
+ console.error(`[LT] ✗ Error: ${e.message}`);
27
+ }
28
+ }
29
+ // Initial compile
30
+ recompile();
31
+ // Watch for changes with debouncing and error recovery
32
+ let fsWait = null;
33
+ fs.watch(sourcePath, (event) => {
34
+ if (event === 'change') {
35
+ if (fsWait)
36
+ clearTimeout(fsWait);
37
+ fsWait = setTimeout(() => {
38
+ fsWait = null;
39
+ recompile();
40
+ }, 150); // Increased debounce for stability
41
+ }
42
+ });
@@ -0,0 +1,59 @@
1
+ import * as AST from '../parser/AST.js';
2
+ /**
3
+ * LT → Lua Code Emitter
4
+ * Generates clean, readable Lua 5.4 code
5
+ */
6
+ export declare class LuaEmitter {
7
+ private indent;
8
+ private output;
9
+ private tempId;
10
+ private usedVars;
11
+ private nextTemp;
12
+ emit(program: AST.Program): string;
13
+ private analyzeUsages;
14
+ private emitStatement;
15
+ private emitVariableDecl;
16
+ private hasSideEffects;
17
+ private emitArrayLiteral;
18
+ private emitAssignment;
19
+ private emitCompoundAssignment;
20
+ private emitIfStmt;
21
+ private emitForStmt;
22
+ private emitRangeForStmt;
23
+ private emitWhileStmt;
24
+ private emitReturnStmt;
25
+ private emitGuardStmt;
26
+ private emitSafeCall;
27
+ private emitThreadStmt;
28
+ private emitLoopStmt;
29
+ private emitWaitStmt;
30
+ private emitTimeoutStmt;
31
+ private emitIntervalStmt;
32
+ private emitTryCatch;
33
+ private emitEmitStmt;
34
+ private emitEventHandler;
35
+ private emitFunctionDecl;
36
+ private emitSwitchStmt;
37
+ private emitExportDecl;
38
+ private emitCommandStmt;
39
+ private emitExpr;
40
+ private emitInterpolatedString;
41
+ private emitBinaryExpr;
42
+ private emitUnaryExpr;
43
+ private emitCallExpr;
44
+ private emitMemberExpr;
45
+ private emitOptionalChain;
46
+ private emitNullCoalesce;
47
+ private emitArrowFunc;
48
+ private emitFunctionExpr;
49
+ private emitTableLiteral;
50
+ private emitVectorLiteral;
51
+ private emitUpdateExpr;
52
+ private emitConditionalExpr;
53
+ private emitStatementInline;
54
+ private hasContinue;
55
+ private emitBlock;
56
+ private emitBlockWithContinue;
57
+ private line;
58
+ private isSimpleExpr;
59
+ }