gglang 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 +21 -0
- package/README.md +158 -0
- package/dist/environment.d.ts +45 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +95 -0
- package/dist/environment.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +199 -0
- package/dist/index.js.map +1 -0
- package/dist/interpreter.d.ts +121 -0
- package/dist/interpreter.d.ts.map +1 -0
- package/dist/interpreter.js +564 -0
- package/dist/interpreter.js.map +1 -0
- package/dist/lexer.d.ts +76 -0
- package/dist/lexer.d.ts.map +1 -0
- package/dist/lexer.js +371 -0
- package/dist/lexer.js.map +1 -0
- package/dist/parser.d.ts +64 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +543 -0
- package/dist/parser.js.map +1 -0
- package/dist/types.d.ts +205 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +92 -0
- package/dist/types.js.map +1 -0
- package/docs/DOCUMENTATION.md +904 -0
- package/package.json +37 -0
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
<
|
|
10
|
+
2. [Language Basics](#language-basics)
|
|
11
|
+
3. [Variables & Constants](#variables--constants)
|
|
12
|
+
4. [Data Types](#data-types)
|
|
13
|
+
5. [Operators](#operators)
|
|
14
|
+
6. [Control Flow](#control-flow)
|
|
15
|
+
7. [Loops](#loops)
|
|
16
|
+
8. [Functions](#functions)
|
|
17
|
+
9. [Input / Output](#input--output)
|
|
18
|
+
10. [Error Handling](#error-handling)
|
|
19
|
+
11. [Complete Example Programs](#complete-example-programs)
|
|
20
|
+
12. [Keyword Reference Table](#keyword-reference-table)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Getting Started
|
|
25
|
+
|
|
26
|
+
### Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Clone the repository
|
|
30
|
+
git clone <repo-url>
|
|
31
|
+
cd toy-programming-language
|
|
32
|
+
|
|
33
|
+
# Install dependencies
|
|
34
|
+
npm install
|
|
35
|
+
|
|
36
|
+
# Build the project
|
|
37
|
+
npm run build
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Running a GGLang File
|
|
41
|
+
|
|
42
|
+
GGLang source files use the `.gg` extension. To run a program:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm start -- path/to/your/program.gg
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For example:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm start -- examples/hello.gg
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Using the REPL
|
|
55
|
+
|
|
56
|
+
Launch the interactive Read-Eval-Print Loop by running without arguments:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm start
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
In the REPL, you can type GGLang expressions and statements directly and see results immediately. Type `exit` or press `Ctrl+C` to quit.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Language Basics
|
|
67
|
+
|
|
68
|
+
### Program Structure
|
|
69
|
+
|
|
70
|
+
Every GGLang program is wrapped in a `spawn { }` block. This is the entry point โ like a player spawning into the game world.
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
spawn {
|
|
74
|
+
// Your code goes here
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Everything outside `spawn { }` is ignored. You must have exactly one `spawn` block.
|
|
79
|
+
|
|
80
|
+
### Comments
|
|
81
|
+
|
|
82
|
+
GGLang supports two styles of comments:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
// This is a single-line comment
|
|
86
|
+
|
|
87
|
+
/*
|
|
88
|
+
This is a
|
|
89
|
+
multi-line comment
|
|
90
|
+
*/
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Semicolons
|
|
94
|
+
|
|
95
|
+
Statements must end with a semicolon (`;`).
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
equip x = 10; // โ
Correct
|
|
99
|
+
broadcast("hello"); // โ
Correct
|
|
100
|
+
equip y = 20 // โ Missing semicolon
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Blocks
|
|
104
|
+
|
|
105
|
+
Code blocks are delimited by curly braces `{ }`. They are used with control flow statements, loops, functions, and error handling.
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
quest (x > 0) {
|
|
109
|
+
broadcast("positive");
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Variables & Constants
|
|
116
|
+
|
|
117
|
+
### Variables: `equip`
|
|
118
|
+
|
|
119
|
+
Use `equip` to declare a mutable variable โ like equipping an item to your inventory.
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
spawn {
|
|
123
|
+
equip health = 100;
|
|
124
|
+
equip playerName = "Hero";
|
|
125
|
+
equip isAlive = victory;
|
|
126
|
+
|
|
127
|
+
// Variables can be reassigned
|
|
128
|
+
health = 75;
|
|
129
|
+
playerName = "Champion";
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Variables must be initialized at declaration. They can be reassigned at any time.
|
|
134
|
+
|
|
135
|
+
### Constants: `artifact`
|
|
136
|
+
|
|
137
|
+
Use `artifact` to declare an immutable constant โ artifacts are permanent relics that never change.
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
spawn {
|
|
141
|
+
artifact maxHealth = 100;
|
|
142
|
+
artifact gameName = "Dungeon Quest";
|
|
143
|
+
artifact PI = 3.14159;
|
|
144
|
+
|
|
145
|
+
// maxHealth = 200; // โ Error! Artifacts cannot be reassigned
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Scope
|
|
150
|
+
|
|
151
|
+
Variables and constants are block-scoped. A variable declared inside a block is only accessible within that block and its nested blocks.
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
spawn {
|
|
155
|
+
equip outer = "I'm outside";
|
|
156
|
+
|
|
157
|
+
quest (victory) {
|
|
158
|
+
equip inner = "I'm inside";
|
|
159
|
+
broadcast(outer); // โ
Can access outer variable
|
|
160
|
+
broadcast(inner); // โ
Can access inner variable
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
broadcast(outer); // โ
Still accessible
|
|
164
|
+
// broadcast(inner); // โ Error! inner is not defined here
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Data Types
|
|
171
|
+
|
|
172
|
+
GGLang supports four primitive data types:
|
|
173
|
+
|
|
174
|
+
### Numbers
|
|
175
|
+
|
|
176
|
+
Integer and floating-point numbers. No distinction between the two.
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
spawn {
|
|
180
|
+
equip age = 25;
|
|
181
|
+
equip pi = 3.14159;
|
|
182
|
+
equip negative = -42;
|
|
183
|
+
equip zero = 0;
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Strings
|
|
188
|
+
|
|
189
|
+
Text enclosed in double quotes (`"`) or single quotes (`'`). Strings can be concatenated with `+`.
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
spawn {
|
|
193
|
+
equip greeting = "Hello, World!";
|
|
194
|
+
equip name = 'GGLang';
|
|
195
|
+
equip full = greeting + " Welcome to " + name + "!";
|
|
196
|
+
|
|
197
|
+
// Numbers are auto-converted when concatenated with strings
|
|
198
|
+
equip level = 5;
|
|
199
|
+
broadcast("You are level " + level); // "You are level 5"
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Booleans
|
|
204
|
+
|
|
205
|
+
`victory` for true, `defeat` for false.
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
spawn {
|
|
209
|
+
equip isWinning = victory;
|
|
210
|
+
equip isGameOver = defeat;
|
|
211
|
+
|
|
212
|
+
quest (isWinning) {
|
|
213
|
+
broadcast("You're winning!");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Null
|
|
219
|
+
|
|
220
|
+
`phantom` represents the absence of a value โ like a phantom, there's nothing there.
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
spawn {
|
|
224
|
+
equip result = phantom;
|
|
225
|
+
|
|
226
|
+
quest (result == phantom) {
|
|
227
|
+
broadcast("Nothing here... ๐ป");
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Operators
|
|
235
|
+
|
|
236
|
+
### Arithmetic Operators
|
|
237
|
+
|
|
238
|
+
| Operator | Description | Example | Result |
|
|
239
|
+
|----------|--------------- |---------------|--------|
|
|
240
|
+
| `+` | Addition | `10 + 3` | `13` |
|
|
241
|
+
| `-` | Subtraction | `10 - 3` | `7` |
|
|
242
|
+
| `*` | Multiplication | `10 * 3` | `30` |
|
|
243
|
+
| `/` | Division | `10 / 3` | `3.33โฆ`|
|
|
244
|
+
| `%` | Modulo | `10 % 3` | `1` |
|
|
245
|
+
|
|
246
|
+
The `+` operator also works for string concatenation:
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
"Hello" + " " + "World" // "Hello World"
|
|
250
|
+
"Level: " + 5 // "Level: 5"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Comparison Operators
|
|
254
|
+
|
|
255
|
+
| Operator | Description | Example | Result |
|
|
256
|
+
|----------|-----------------------|------------|-----------|
|
|
257
|
+
| `==` | Equal to | `5 == 5` | `victory` |
|
|
258
|
+
| `!=` | Not equal to | `5 != 3` | `victory` |
|
|
259
|
+
| `>` | Greater than | `5 > 3` | `victory` |
|
|
260
|
+
| `<` | Less than | `5 < 3` | `defeat` |
|
|
261
|
+
| `>=` | Greater than or equal | `5 >= 5` | `victory` |
|
|
262
|
+
| `<=` | Less than or equal | `3 <= 5` | `victory` |
|
|
263
|
+
|
|
264
|
+
### Logical Operators
|
|
265
|
+
|
|
266
|
+
| Operator | Description | Example | Result |
|
|
267
|
+
|----------|-------------|----------------------------|-----------|
|
|
268
|
+
| `&&` | Logical AND | `victory && defeat` | `defeat` |
|
|
269
|
+
| `\|\|` | Logical OR | `victory \|\| defeat` | `victory` |
|
|
270
|
+
| `!` | Logical NOT | `!defeat` | `victory` |
|
|
271
|
+
|
|
272
|
+
### Assignment Operators
|
|
273
|
+
|
|
274
|
+
| Operator | Description | Equivalent To |
|
|
275
|
+
|----------|---------------------|---------------|
|
|
276
|
+
| `=` | Assignment | `x = 5` |
|
|
277
|
+
| `+=` | Add and assign | `x = x + 5` |
|
|
278
|
+
| `-=` | Subtract and assign | `x = x - 5` |
|
|
279
|
+
| `*=` | Multiply and assign | `x = x * 5` |
|
|
280
|
+
| `/=` | Divide and assign | `x = x / 5` |
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
spawn {
|
|
284
|
+
equip score = 0;
|
|
285
|
+
score += 10; // score is now 10
|
|
286
|
+
score *= 2; // score is now 20
|
|
287
|
+
score -= 5; // score is now 15
|
|
288
|
+
score /= 3; // score is now 5
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Operator Precedence
|
|
293
|
+
|
|
294
|
+
From **highest** to **lowest** precedence:
|
|
295
|
+
|
|
296
|
+
| Precedence | Operators | Description |
|
|
297
|
+
|------------|---------------------|----------------------|
|
|
298
|
+
| 1 (highest)| `!`, unary `-` | Logical NOT, negation |
|
|
299
|
+
| 2 | `*`, `/`, `%` | Multiplication, Division, Modulo |
|
|
300
|
+
| 3 | `+`, `-` | Addition, Subtraction |
|
|
301
|
+
| 4 | `>`, `<`, `>=`, `<=`| Comparison |
|
|
302
|
+
| 5 | `==`, `!=` | Equality |
|
|
303
|
+
| 6 | `&&` | Logical AND |
|
|
304
|
+
| 7 (lowest) | `\|\|` | Logical OR |
|
|
305
|
+
|
|
306
|
+
Use parentheses `( )` to override precedence:
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
equip result = (2 + 3) * 4; // 20, not 14
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Control Flow
|
|
315
|
+
|
|
316
|
+
### `quest` (if)
|
|
317
|
+
|
|
318
|
+
Execute a block of code when a condition is `victory` (true).
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
spawn {
|
|
322
|
+
equip health = 75;
|
|
323
|
+
|
|
324
|
+
quest (health > 50) {
|
|
325
|
+
broadcast("You're doing fine!");
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### `side_quest` (else if)
|
|
331
|
+
|
|
332
|
+
Check additional conditions when the previous `quest` or `side_quest` was `defeat` (false).
|
|
333
|
+
|
|
334
|
+
```
|
|
335
|
+
spawn {
|
|
336
|
+
equip score = 85;
|
|
337
|
+
|
|
338
|
+
quest (score >= 90) {
|
|
339
|
+
broadcast("S Rank! ๐");
|
|
340
|
+
} side_quest (score >= 80) {
|
|
341
|
+
broadcast("A Rank! โญ");
|
|
342
|
+
} side_quest (score >= 70) {
|
|
343
|
+
broadcast("B Rank");
|
|
344
|
+
} side_quest (score >= 60) {
|
|
345
|
+
broadcast("C Rank");
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
### `retreat` (else)
|
|
351
|
+
|
|
352
|
+
The fallback block when all previous conditions are `defeat`.
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
spawn {
|
|
356
|
+
equip level = 3;
|
|
357
|
+
|
|
358
|
+
quest (level >= 10) {
|
|
359
|
+
broadcast("You are a veteran!");
|
|
360
|
+
} side_quest (level >= 5) {
|
|
361
|
+
broadcast("You are experienced.");
|
|
362
|
+
} retreat {
|
|
363
|
+
broadcast("You are a beginner.");
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Nesting
|
|
369
|
+
|
|
370
|
+
Control flow statements can be nested:
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
spawn {
|
|
374
|
+
equip class = "mage";
|
|
375
|
+
equip level = 15;
|
|
376
|
+
|
|
377
|
+
quest (class == "mage") {
|
|
378
|
+
quest (level >= 10) {
|
|
379
|
+
broadcast("You can cast Fireball! ๐ฅ");
|
|
380
|
+
} retreat {
|
|
381
|
+
broadcast("Keep training your magic...");
|
|
382
|
+
}
|
|
383
|
+
} side_quest (class == "warrior") {
|
|
384
|
+
broadcast("Swing that sword! โ๏ธ");
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Loops
|
|
392
|
+
|
|
393
|
+
### `grind` (while)
|
|
394
|
+
|
|
395
|
+
Repeat a block of code as long as a condition is `victory` (true). Perfect for grinding levels.
|
|
396
|
+
|
|
397
|
+
```
|
|
398
|
+
spawn {
|
|
399
|
+
equip level = 1;
|
|
400
|
+
|
|
401
|
+
grind (level <= 10) {
|
|
402
|
+
broadcast("Level " + level + " reached!");
|
|
403
|
+
level += 1;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
broadcast("Max level! ๐");
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### `rage_quit` (break)
|
|
411
|
+
|
|
412
|
+
Exit a loop immediately โ you've had enough.
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
spawn {
|
|
416
|
+
equip attempts = 0;
|
|
417
|
+
|
|
418
|
+
grind (victory) { // Infinite loop
|
|
419
|
+
attempts += 1;
|
|
420
|
+
broadcast("Attempt #" + attempts);
|
|
421
|
+
|
|
422
|
+
quest (attempts >= 5) {
|
|
423
|
+
broadcast("That's it, I'm done!");
|
|
424
|
+
rage_quit;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
broadcast("Rage quit after " + attempts + " attempts.");
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### `respawn` (continue)
|
|
433
|
+
|
|
434
|
+
Skip the rest of the current iteration and jump to the next one โ like respawning to try again.
|
|
435
|
+
|
|
436
|
+
```
|
|
437
|
+
spawn {
|
|
438
|
+
equip i = 0;
|
|
439
|
+
|
|
440
|
+
grind (i < 10) {
|
|
441
|
+
i += 1;
|
|
442
|
+
|
|
443
|
+
// Skip even numbers
|
|
444
|
+
quest (i % 2 == 0) {
|
|
445
|
+
respawn;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
broadcast(i); // Only prints odd numbers: 1, 3, 5, 7, 9
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### Loop Patterns
|
|
454
|
+
|
|
455
|
+
**Counting loop:**
|
|
456
|
+
```
|
|
457
|
+
equip i = 0;
|
|
458
|
+
grind (i < 10) {
|
|
459
|
+
// do something
|
|
460
|
+
i += 1;
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Sentinel loop (until condition):**
|
|
465
|
+
```
|
|
466
|
+
equip input = "";
|
|
467
|
+
grind (input != "quit") {
|
|
468
|
+
input = interact("Enter command (or 'quit'): ");
|
|
469
|
+
broadcast("You entered: " + input);
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
**Infinite loop with break:**
|
|
474
|
+
```
|
|
475
|
+
grind (victory) {
|
|
476
|
+
// do something
|
|
477
|
+
quest (someCondition) {
|
|
478
|
+
rage_quit;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## Functions
|
|
486
|
+
|
|
487
|
+
### `skill` (function)
|
|
488
|
+
|
|
489
|
+
Define reusable skills (functions) with `skill`. Functions can accept parameters and return values.
|
|
490
|
+
|
|
491
|
+
```
|
|
492
|
+
spawn {
|
|
493
|
+
skill greet(name) {
|
|
494
|
+
broadcast("Hello, " + name + "! ๐");
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
greet("Player"); // "Hello, Player! ๐"
|
|
498
|
+
greet("GGLang"); // "Hello, GGLang! ๐"
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### `loot` (return)
|
|
503
|
+
|
|
504
|
+
Return a value from a skill using `loot` โ the reward for executing the skill.
|
|
505
|
+
|
|
506
|
+
```
|
|
507
|
+
spawn {
|
|
508
|
+
skill add(a, b) {
|
|
509
|
+
loot a + b;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
skill square(n) {
|
|
513
|
+
loot n * n;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
equip sum = add(3, 4); // 7
|
|
517
|
+
equip squared = square(5); // 25
|
|
518
|
+
broadcast(add(10, square(3))); // 19
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Multiple Parameters
|
|
523
|
+
|
|
524
|
+
Functions can take any number of parameters:
|
|
525
|
+
|
|
526
|
+
```
|
|
527
|
+
spawn {
|
|
528
|
+
skill calculateDamage(base, level, multiplier) {
|
|
529
|
+
loot base + (level * multiplier);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
equip damage = calculateDamage(10, 5, 1.5);
|
|
533
|
+
broadcast("Damage dealt: " + damage); // "Damage dealt: 17.5"
|
|
534
|
+
}
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
### Early Return
|
|
538
|
+
|
|
539
|
+
`loot` immediately exits the function, like returning loot and leaving the dungeon:
|
|
540
|
+
|
|
541
|
+
```
|
|
542
|
+
spawn {
|
|
543
|
+
skill absoluteValue(n) {
|
|
544
|
+
quest (n < 0) {
|
|
545
|
+
loot -n;
|
|
546
|
+
}
|
|
547
|
+
loot n;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
broadcast(absoluteValue(-42)); // 42
|
|
551
|
+
broadcast(absoluteValue(7)); // 7
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Recursion
|
|
556
|
+
|
|
557
|
+
Skills can call themselves โ perfect for recursive algorithms:
|
|
558
|
+
|
|
559
|
+
```
|
|
560
|
+
spawn {
|
|
561
|
+
// Factorial using recursion
|
|
562
|
+
skill factorial(n) {
|
|
563
|
+
quest (n <= 1) {
|
|
564
|
+
loot 1;
|
|
565
|
+
}
|
|
566
|
+
loot n * factorial(n - 1);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
broadcast("5! = " + factorial(5)); // "5! = 120"
|
|
570
|
+
broadcast("10! = " + factorial(10)); // "10! = 3628800"
|
|
571
|
+
}
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
### Functions Without Return
|
|
575
|
+
|
|
576
|
+
If a skill doesn't use `loot`, it implicitly returns `phantom`:
|
|
577
|
+
|
|
578
|
+
```
|
|
579
|
+
spawn {
|
|
580
|
+
skill sayHello() {
|
|
581
|
+
broadcast("Hello!");
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
equip result = sayHello();
|
|
585
|
+
broadcast(result); // phantom
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## Input / Output
|
|
592
|
+
|
|
593
|
+
### `broadcast` (print)
|
|
594
|
+
|
|
595
|
+
Output a value to the console. Accepts any data type.
|
|
596
|
+
|
|
597
|
+
```
|
|
598
|
+
spawn {
|
|
599
|
+
broadcast("Hello, World!"); // String
|
|
600
|
+
broadcast(42); // Number
|
|
601
|
+
broadcast(victory); // Boolean
|
|
602
|
+
broadcast(3 + 4); // Expression result
|
|
603
|
+
broadcast("Score: " + 100); // String concatenation
|
|
604
|
+
}
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### `interact` (input)
|
|
608
|
+
|
|
609
|
+
Read input from the user. `interact` takes an optional prompt string and returns the user's input as a string.
|
|
610
|
+
|
|
611
|
+
```
|
|
612
|
+
spawn {
|
|
613
|
+
equip name = interact("What is your name? ");
|
|
614
|
+
equip age = interact("How old are you? ");
|
|
615
|
+
|
|
616
|
+
broadcast("Hello, " + name + "! You are " + age + " years old.");
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
> **Note:** `interact` always returns a **string**. If you need a number, you may need to use it in an arithmetic context where auto-conversion occurs.
|
|
621
|
+
|
|
622
|
+
---
|
|
623
|
+
|
|
624
|
+
## Error Handling
|
|
625
|
+
|
|
626
|
+
### `boss_fight` / `revive` (try / catch)
|
|
627
|
+
|
|
628
|
+
Wrap risky code in a `boss_fight` block. If a `glitch` (error) is thrown, execution jumps to the `revive` block.
|
|
629
|
+
|
|
630
|
+
```
|
|
631
|
+
spawn {
|
|
632
|
+
boss_fight {
|
|
633
|
+
broadcast("Entering the boss room...");
|
|
634
|
+
glitch "The boss is too powerful!";
|
|
635
|
+
broadcast("This line never executes.");
|
|
636
|
+
} revive (error) {
|
|
637
|
+
broadcast("Caught a glitch: " + error);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
broadcast("Game continues after recovery.");
|
|
641
|
+
}
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
**Output:**
|
|
645
|
+
```
|
|
646
|
+
Entering the boss room...
|
|
647
|
+
Caught a glitch: The boss is too powerful!
|
|
648
|
+
Game continues after recovery.
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### `glitch` (throw)
|
|
652
|
+
|
|
653
|
+
Throw an error with a message. This immediately exits the current execution and jumps to the nearest `revive` block.
|
|
654
|
+
|
|
655
|
+
```
|
|
656
|
+
spawn {
|
|
657
|
+
skill divide(a, b) {
|
|
658
|
+
quest (b == 0) {
|
|
659
|
+
glitch "Cannot divide by zero!";
|
|
660
|
+
}
|
|
661
|
+
loot a / b;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
boss_fight {
|
|
665
|
+
broadcast(divide(10, 2)); // 5
|
|
666
|
+
broadcast(divide(10, 0)); // Throws!
|
|
667
|
+
} revive (err) {
|
|
668
|
+
broadcast("Error: " + err);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### Nested Error Handling
|
|
674
|
+
|
|
675
|
+
`boss_fight` blocks can be nested. The innermost `revive` catches the error:
|
|
676
|
+
|
|
677
|
+
```
|
|
678
|
+
spawn {
|
|
679
|
+
boss_fight {
|
|
680
|
+
broadcast("Outer boss fight...");
|
|
681
|
+
|
|
682
|
+
boss_fight {
|
|
683
|
+
broadcast("Inner boss fight...");
|
|
684
|
+
glitch "Inner glitch!";
|
|
685
|
+
} revive (e) {
|
|
686
|
+
broadcast("Inner revive caught: " + e);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
broadcast("Outer continues normally.");
|
|
690
|
+
} revive (e) {
|
|
691
|
+
broadcast("Outer revive caught: " + e);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
**Output:**
|
|
697
|
+
```
|
|
698
|
+
Outer boss fight...
|
|
699
|
+
Inner boss fight...
|
|
700
|
+
Inner revive caught: Inner glitch!
|
|
701
|
+
Outer continues normally.
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
### Unhandled Glitches
|
|
705
|
+
|
|
706
|
+
If a `glitch` is thrown outside of any `boss_fight`, the program crashes with an error message:
|
|
707
|
+
|
|
708
|
+
```
|
|
709
|
+
spawn {
|
|
710
|
+
glitch "Fatal error!";
|
|
711
|
+
// Program terminates here
|
|
712
|
+
}
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
## Complete Example Programs
|
|
718
|
+
|
|
719
|
+
### Hello World
|
|
720
|
+
|
|
721
|
+
```
|
|
722
|
+
// hello.gg โ Your first GGLang program
|
|
723
|
+
spawn {
|
|
724
|
+
broadcast("Hello, World!");
|
|
725
|
+
broadcast("Welcome to GGLang! ๐ฎ");
|
|
726
|
+
}
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
### FizzBuzz
|
|
730
|
+
|
|
731
|
+
```
|
|
732
|
+
// fizzbuzz.gg โ The classic interview question, GGLang style
|
|
733
|
+
spawn {
|
|
734
|
+
equip i = 1;
|
|
735
|
+
grind (i <= 30) {
|
|
736
|
+
quest (i % 15 == 0) {
|
|
737
|
+
broadcast("FizzBuzz");
|
|
738
|
+
} side_quest (i % 3 == 0) {
|
|
739
|
+
broadcast("Fizz");
|
|
740
|
+
} side_quest (i % 5 == 0) {
|
|
741
|
+
broadcast("Buzz");
|
|
742
|
+
} retreat {
|
|
743
|
+
broadcast(i);
|
|
744
|
+
}
|
|
745
|
+
i = i + 1;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
### Fibonacci (Recursive)
|
|
751
|
+
|
|
752
|
+
```
|
|
753
|
+
// fibonacci.gg โ Fibonacci with recursion
|
|
754
|
+
spawn {
|
|
755
|
+
skill fibonacci(n) {
|
|
756
|
+
quest (n <= 1) {
|
|
757
|
+
loot n;
|
|
758
|
+
}
|
|
759
|
+
loot fibonacci(n - 1) + fibonacci(n - 2);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
equip i = 0;
|
|
763
|
+
grind (i <= 15) {
|
|
764
|
+
broadcast("fibonacci(" + i + ") = " + fibonacci(i));
|
|
765
|
+
i = i + 1;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
### Number Guessing Game
|
|
771
|
+
|
|
772
|
+
```
|
|
773
|
+
// guess.gg โ Guess the secret number
|
|
774
|
+
spawn {
|
|
775
|
+
artifact secret = 7;
|
|
776
|
+
artifact maxAttempts = 5;
|
|
777
|
+
|
|
778
|
+
broadcast("๐ฎ Guess the number between 1 and 10!");
|
|
779
|
+
broadcast("You have " + maxAttempts + " attempts.");
|
|
780
|
+
|
|
781
|
+
equip attempts = 0;
|
|
782
|
+
equip won = defeat;
|
|
783
|
+
|
|
784
|
+
grind (attempts < maxAttempts && won == defeat) {
|
|
785
|
+
attempts += 1;
|
|
786
|
+
equip guess = interact("Attempt " + attempts + "/" + maxAttempts + " โ Enter your guess: ");
|
|
787
|
+
|
|
788
|
+
quest (guess == secret) {
|
|
789
|
+
broadcast("๐ Correct! You won in " + attempts + " attempts!");
|
|
790
|
+
won = victory;
|
|
791
|
+
} side_quest (guess < secret) {
|
|
792
|
+
broadcast("๐ Too low! Try higher.");
|
|
793
|
+
} retreat {
|
|
794
|
+
broadcast("๐ Too high! Try lower.");
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
quest (won == defeat) {
|
|
799
|
+
broadcast("๐ Game over! The number was " + secret + ".");
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
### Calculator
|
|
805
|
+
|
|
806
|
+
```
|
|
807
|
+
// calculator.gg โ A simple calculator
|
|
808
|
+
spawn {
|
|
809
|
+
skill calculate(a, op, b) {
|
|
810
|
+
quest (op == "+") {
|
|
811
|
+
loot a + b;
|
|
812
|
+
} side_quest (op == "-") {
|
|
813
|
+
loot a - b;
|
|
814
|
+
} side_quest (op == "*") {
|
|
815
|
+
loot a * b;
|
|
816
|
+
} side_quest (op == "/") {
|
|
817
|
+
quest (b == 0) {
|
|
818
|
+
glitch "Division by zero!";
|
|
819
|
+
}
|
|
820
|
+
loot a / b;
|
|
821
|
+
} side_quest (op == "%") {
|
|
822
|
+
loot a % b;
|
|
823
|
+
} retreat {
|
|
824
|
+
glitch "Unknown operator: " + op;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
broadcast("๐งฎ GGLang Calculator");
|
|
829
|
+
broadcast("Type 'quit' to exit.");
|
|
830
|
+
|
|
831
|
+
grind (victory) {
|
|
832
|
+
equip a = interact("Enter first number (or 'quit'): ");
|
|
833
|
+
quest (a == "quit") {
|
|
834
|
+
rage_quit;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
equip op = interact("Enter operator (+, -, *, /, %): ");
|
|
838
|
+
equip b = interact("Enter second number: ");
|
|
839
|
+
|
|
840
|
+
boss_fight {
|
|
841
|
+
equip result = calculate(a, op, b);
|
|
842
|
+
broadcast("๐ Result: " + a + " " + op + " " + b + " = " + result);
|
|
843
|
+
} revive (err) {
|
|
844
|
+
broadcast("โ Error: " + err);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
broadcast("Thanks for calculating! GG ๐ฎ");
|
|
849
|
+
}
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
---
|
|
853
|
+
|
|
854
|
+
## Keyword Reference Table
|
|
855
|
+
|
|
856
|
+
| GGLang Keyword | Traditional Equivalent | Description |
|
|
857
|
+
|---|---|---|
|
|
858
|
+
| `spawn { }` | `main()` / program start | Entry point โ player spawns into the game |
|
|
859
|
+
| `equip` | `let` / `var` | Declare a mutable variable |
|
|
860
|
+
| `artifact` | `const` | Declare an immutable constant |
|
|
861
|
+
| `broadcast` | `print` / `console.log` | Output a value to the console |
|
|
862
|
+
| `interact("โฆ")` | `input` / `readline` | Read user input (returns string) |
|
|
863
|
+
| `quest` | `if` | Conditional โ embark on a quest |
|
|
864
|
+
| `side_quest` | `else if` | Alternative conditional path |
|
|
865
|
+
| `retreat` | `else` | Fallback when all conditions fail |
|
|
866
|
+
| `grind` | `while` | Loop โ keep grinding |
|
|
867
|
+
| `rage_quit` | `break` | Exit the loop immediately |
|
|
868
|
+
| `respawn` | `continue` | Skip to the next loop iteration |
|
|
869
|
+
| `skill` | `function` | Define a reusable function |
|
|
870
|
+
| `loot` | `return` | Return a value from a function |
|
|
871
|
+
| `victory` | `true` | Boolean true |
|
|
872
|
+
| `defeat` | `false` | Boolean false |
|
|
873
|
+
| `phantom` | `null` | Absence of a value |
|
|
874
|
+
| `boss_fight` | `try` | Attempt risky code |
|
|
875
|
+
| `revive` | `catch` | Handle an error |
|
|
876
|
+
| `glitch` | `throw` | Throw an error |
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
## Supported Operators โ Quick Reference
|
|
881
|
+
|
|
882
|
+
| Category | Operators |
|
|
883
|
+
|---|---|
|
|
884
|
+
| **Arithmetic** | `+` `-` `*` `/` `%` |
|
|
885
|
+
| **Comparison** | `==` `!=` `>` `<` `>=` `<=` |
|
|
886
|
+
| **Logical** | `&&` `\|\|` `!` |
|
|
887
|
+
| **Assignment** | `=` `+=` `-=` `*=` `/=` |
|
|
888
|
+
|
|
889
|
+
---
|
|
890
|
+
|
|
891
|
+
## File Extension
|
|
892
|
+
|
|
893
|
+
All GGLang source files use the `.gg` extension.
|
|
894
|
+
|
|
895
|
+
```
|
|
896
|
+
my_program.gg
|
|
897
|
+
hello.gg
|
|
898
|
+
adventure.gg
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
---
|
|
902
|
+
|
|
903
|
+
*GG! ๐ฎ โ Happy coding with GGLang!*
|
|
904
|
+
]]>
|