-
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathllms.txt
More file actions
189 lines (139 loc) · 6.79 KB
/
llms.txt
File metadata and controls
189 lines (139 loc) · 6.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
TSSL Reference for LLMs
You are writing TSSL -- a TypeScript subset that transpiles to Fallout SSL.
Files use the .tssl extension. The transpiler converts TypeScript AST to SSL syntax.
Everything below describes what the transpiler supports and how it behaves.
=== VARIABLES ===
Top-level const NAME = value; -> #define NAME value (compile-time constant)
const inside function body -> variable NAME = value; (same as let)
let name = value; -> variable name = value; (runtime, function-scoped)
let name: type; -> variable name; (declaration only)
All variables are function-scoped (like var). Declaration+assignment in a let
is hoisted to function start and runs ONCE. To reset in a loop:
let x: number; // hoist declaration
for (...) { x = 0; } // assign in loop body
=== FUNCTIONS ===
function name(param: Type, param2 = default) { ... }
-> procedure name(variable param, variable param2 = default) begin ... end
Standalone calls to user-defined functions get "call" prefix automatically.
Return values work: return expr; -> return expr;
=== CONTROL FLOW ===
if (cond) { ... } else { ... } -> if (cond) then begin ... end else begin ... end
while (cond) { ... } -> while (cond) do begin ... end
for (let i = 0; i < n; i++) { } -> for (variable i = 0; i < n; i++) begin ... end
do { ... } while (cond); -> emulated with flag variable + while
for (const x of arr) { } -> foreach (variable x in arr) begin ... end
for (const [k, v] of m as [K,V][]) -> foreach (variable k: v in m) begin ... end
for (const k in obj) { } -> foreach (variable k in obj) begin ... end
switch (x) { case 1: ...; break; } -> switch (x) begin case 1: ... end
break; continue; return; -> break; continue; return;
=== OPERATORS ===
TypeScript SSL Description
&& and logical AND
|| or logical OR
! not logical NOT
& bwand bitwise AND
| bwor bitwise OR
^ bxor bitwise XOR
~ bnot bitwise NOT
== != < > <= >= unchanged
+ - * / % unchanged
= += -= *= /= unchanged
++ -- unchanged
? : ternary (supported)
=== ENUMS ===
enum DamageType { Normal = 0, Fire = 3 }
-> #define DamageType_Normal 0
-> #define DamageType_Fire 3
DamageType.Fire -> DamageType_Fire
Unused members are tree-shaken.
=== @inline FUNCTIONS ===
/** @inline */
function dude_tile() { return tile_num(dude_obj); }
-> #define dude_tile tile_num(dude_obj)
/** @inline */
function get_stat(who, stat) { return get_critter_stat(who, stat); }
-> #define get_stat(who, stat) get_critter_stat(who, stat)
Tag MUST be in JSDoc (/** */), not regular comments.
Zero-arg inline calls have parens stripped: dude_tile() -> dude_tile
=== SPECIAL FUNCTIONS ===
list(1, 2, 3) -> [1, 2, 3] (array literal)
map({[KEY]: val}) -> {KEY: val} (map literal)
sfall_typeof(x) -> typeof(x) (TS keyword workaround)
FLOAT1 -> 1.0 (esbuild strips .0 from literals)
=== IMPORTS ===
import { func } from "folib/sfall"; folib modules (typed engine wrappers)
import { helper } from "./my-lib"; local .ts files (bundled into output)
import { dude_obj } from "folib/base.d"; .d.ts files (stripped, declarations only)
// #include "headers/custom.h" magic comment -> #include in output
folib module mapping:
sfall/sfall.h -> folib/sfall
sfall/define_lite.h -> folib/sfall/define_lite
sfall/command_lite.h -> folib/sfall/command_lite
=== ENGINE PROCEDURES (preserved from tree-shaking) ===
start, map_enter_p_proc, map_exit_p_proc, map_update_p_proc,
create_p_proc, destroy_p_proc, critter_p_proc, combat_p_proc,
combat_is_starting_p_proc, combat_is_over_p_proc, damage_p_proc,
talk_p_proc, look_at_p_proc, description_p_proc, use_p_proc,
use_obj_on_p_proc, use_skill_on_p_proc, pickup_p_proc, drop_p_proc,
is_dropping_p_proc, push_p_proc, spatial_p_proc, timed_event_p_proc,
barter_p_proc, barter_init_p_proc, use_ad_on_p_proc, use_disad_on_p_proc
Functions passed to register_hook_proc/register_hook_proc_spec are also preserved.
=== FORBIDDEN (transpiler error) ===
try/catch/finally -> "try/catch is not supported in SSL"
Object/Array/JSON/Math/Date -> "X is not available in SSL runtime"
Promise/Map/Set/WeakMap/WeakSet/Symbol/Reflect/Proxy -> same error
let list = ...; let map = ...; -> "conflicts with folib export"
for (const [a,b,c] of ...) -> "must have exactly 2 elements"
None of these JS built-ins exist at runtime. The only runtime data structures
are sfall lists (flat arrays) and sfall maps (key-value stores), created with
folib's list() and map() helpers. No objects, classes, or other data structures.
=== UNSUPPORTED (broken output, no error) ===
Arrow functions () => {}
Template literals `${x}`
Optional chaining x?.y
Nullish coalescing x ?? y
Spread ...arr
Exponentiation x ** y
Destructuring (except 2-element for-of)
instanceof, new, await/async, yield/generators
Classes (runtime), decorators (runtime)
=== GOTCHAS ===
1. Variable hoisting: let x = val in a loop -> assignment runs once at function
start. Separate declaration (let x: type) from assignment (x = val).
2. Zero-arg externals: game_loaded() in TSSL -> game_loaded in SSL output.
You must write parens in TSSL. Without parens it's a reference, not a call.
3. No undefined, no objects: missing map keys return 0. Use == 0, not == undefined.
Only runtime data structures are sfall lists and sfall maps (folib's list()/map()).
4. Computed keys required: { [PID_GUN]: 9 } keeps constant.
{ PID_GUN: 9 } becomes string literal "PID_GUN".
5. Import aliasing: importing same function from different paths causes
esbuild renaming (func -> func2). Use one import path per function.
6. Float literals: esbuild strips .0 (1.0 -> 1). Use FLOAT1 * a / b
for float division.
7. @tra tag: add /** @tra filename.tra */ in a comment to set translation file.
Accepts both .tra and .msg extensions.
8. JSDoc on functions is preserved as SSL comments (extracted before bundling).
=== EXAMPLE ===
import { ndebug } from "folib";
import { game_loaded, register_hook_proc, HOOK_COMBATTURN } from "folib/sfall";
const MAX_HP = 100;
/** @inline */
function dude_tile(): number {
return tile_num(dude_obj);
}
let hookActive: number;
function start() {
if (game_loaded()) {
hookActive = 1;
register_hook_proc(HOOK_COMBATTURN, on_combat);
ndebug("Script loaded at tile " + dude_tile());
}
}
function on_combat() {
if (hookActive) {
// handle combat
}
}
=== COMPILATION ===
.tssl -> (esbuild bundle + transpiler) -> .ssl -> (sslc) -> .int
Press Ctrl+R in VSCode or use the transpile CLI.