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,564 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================
|
|
3
|
+
// GGLang — Tree-Walking Interpreter
|
|
4
|
+
// Executes the AST produced by the parser, walking each node
|
|
5
|
+
// and evaluating expressions / executing statements.
|
|
6
|
+
// ============================================================
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.Interpreter = void 0;
|
|
42
|
+
const types_1 = require("./types");
|
|
43
|
+
const environment_1 = require("./environment");
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
// ============================================================
|
|
46
|
+
// Internal Signal Classes
|
|
47
|
+
// These extend Error so they can be thrown and caught to unwind
|
|
48
|
+
// the call stack for control flow (break, continue, return).
|
|
49
|
+
// They are NOT user-visible errors.
|
|
50
|
+
// ============================================================
|
|
51
|
+
/** Thrown when a `rage_quit` (break) statement is executed */
|
|
52
|
+
class BreakSignal extends Error {
|
|
53
|
+
constructor() {
|
|
54
|
+
super('break');
|
|
55
|
+
this.name = 'BreakSignal';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Thrown when a `respawn` (continue) statement is executed */
|
|
59
|
+
class ContinueSignal extends Error {
|
|
60
|
+
constructor() {
|
|
61
|
+
super('continue');
|
|
62
|
+
this.name = 'ContinueSignal';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Thrown when a `loot` (return) statement is executed, carrying the return value */
|
|
66
|
+
class ReturnSignal extends Error {
|
|
67
|
+
constructor(returnValue) {
|
|
68
|
+
super('return');
|
|
69
|
+
this.name = 'ReturnSignal';
|
|
70
|
+
this.returnValue = returnValue;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// ============================================================
|
|
74
|
+
// Synchronous stdin reader (cross-platform)
|
|
75
|
+
// Reads one line from stdin by reading byte-by-byte from fd 0.
|
|
76
|
+
// Works on both Windows and Unix without external dependencies.
|
|
77
|
+
// ============================================================
|
|
78
|
+
function readInputSync(promptText) {
|
|
79
|
+
process.stdout.write(promptText);
|
|
80
|
+
const buf = Buffer.alloc(1);
|
|
81
|
+
let str = '';
|
|
82
|
+
let bytesRead;
|
|
83
|
+
const fd = process.stdin.fd;
|
|
84
|
+
// Read byte by byte until we hit a newline or EOF
|
|
85
|
+
try {
|
|
86
|
+
do {
|
|
87
|
+
bytesRead = fs.readSync(fd, buf, 0, 1, null);
|
|
88
|
+
if (bytesRead > 0) {
|
|
89
|
+
const char = buf.toString('utf8', 0, 1);
|
|
90
|
+
if (char === '\n')
|
|
91
|
+
break;
|
|
92
|
+
if (char === '\r')
|
|
93
|
+
continue;
|
|
94
|
+
str += char;
|
|
95
|
+
}
|
|
96
|
+
} while (bytesRead > 0);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// If stdin is not readable (e.g. piped and exhausted), return empty
|
|
100
|
+
}
|
|
101
|
+
return str;
|
|
102
|
+
}
|
|
103
|
+
// ============================================================
|
|
104
|
+
// Interpreter Class
|
|
105
|
+
// ============================================================
|
|
106
|
+
class Interpreter {
|
|
107
|
+
constructor() {
|
|
108
|
+
this.globalEnv = new environment_1.Environment();
|
|
109
|
+
}
|
|
110
|
+
// ---- Public Entry Point ----
|
|
111
|
+
/**
|
|
112
|
+
* Executes a parsed GGLang program.
|
|
113
|
+
* Iterates over every statement in the program body and executes it
|
|
114
|
+
* within the global environment.
|
|
115
|
+
*
|
|
116
|
+
* @param program - The AST root node (Program)
|
|
117
|
+
*/
|
|
118
|
+
execute(program) {
|
|
119
|
+
for (const stmt of program.body) {
|
|
120
|
+
this.executeStatement(stmt, this.globalEnv);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ---- Statement Execution ----
|
|
124
|
+
/**
|
|
125
|
+
* Dispatches a statement to its corresponding handler based on type.
|
|
126
|
+
*
|
|
127
|
+
* @param stmt - The AST statement node
|
|
128
|
+
* @param env - The current environment scope
|
|
129
|
+
*/
|
|
130
|
+
executeStatement(stmt, env) {
|
|
131
|
+
switch (stmt.type) {
|
|
132
|
+
case 'VariableDeclaration':
|
|
133
|
+
this.executeVariableDeclaration(stmt, env);
|
|
134
|
+
break;
|
|
135
|
+
case 'AssignmentStatement':
|
|
136
|
+
this.executeAssignment(stmt, env);
|
|
137
|
+
break;
|
|
138
|
+
case 'CompoundAssignmentStatement':
|
|
139
|
+
this.executeCompoundAssignment(stmt, env);
|
|
140
|
+
break;
|
|
141
|
+
case 'PrintStatement':
|
|
142
|
+
this.executePrint(stmt, env);
|
|
143
|
+
break;
|
|
144
|
+
case 'IfStatement':
|
|
145
|
+
this.executeIf(stmt, env);
|
|
146
|
+
break;
|
|
147
|
+
case 'WhileStatement':
|
|
148
|
+
this.executeWhile(stmt, env);
|
|
149
|
+
break;
|
|
150
|
+
case 'BreakStatement':
|
|
151
|
+
throw new BreakSignal();
|
|
152
|
+
case 'ContinueStatement':
|
|
153
|
+
throw new ContinueSignal();
|
|
154
|
+
case 'FunctionDeclaration':
|
|
155
|
+
this.executeFunctionDeclaration(stmt, env);
|
|
156
|
+
break;
|
|
157
|
+
case 'ReturnStatement':
|
|
158
|
+
this.executeReturn(stmt, env);
|
|
159
|
+
break;
|
|
160
|
+
case 'ThrowStatement':
|
|
161
|
+
this.executeThrow(stmt, env);
|
|
162
|
+
break;
|
|
163
|
+
case 'TryCatchStatement':
|
|
164
|
+
this.executeTryCatch(stmt, env);
|
|
165
|
+
break;
|
|
166
|
+
case 'ExpressionStatement':
|
|
167
|
+
this.evaluateExpression(stmt.expression, env);
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
// Exhaustiveness check — should never happen with valid AST
|
|
171
|
+
throw new types_1.GGRuntimeError(`Unknown statement type: ${stmt.type}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// ---- Individual Statement Handlers ----
|
|
175
|
+
/**
|
|
176
|
+
* equip / artifact — Declare a new variable or constant.
|
|
177
|
+
*/
|
|
178
|
+
executeVariableDeclaration(stmt, env) {
|
|
179
|
+
const value = this.evaluateExpression(stmt.value, env);
|
|
180
|
+
env.declare(stmt.name, value, stmt.constant);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* name = expr — Assign a new value to an existing variable.
|
|
184
|
+
*/
|
|
185
|
+
executeAssignment(stmt, env) {
|
|
186
|
+
const value = this.evaluateExpression(stmt.value, env);
|
|
187
|
+
env.set(stmt.name, value);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* name += expr (and -=, *=, /=) — Compound assignment.
|
|
191
|
+
* Reads the current value, applies the operator, and writes back.
|
|
192
|
+
*/
|
|
193
|
+
executeCompoundAssignment(stmt, env) {
|
|
194
|
+
const current = env.get(stmt.name);
|
|
195
|
+
const operand = this.evaluateExpression(stmt.value, env);
|
|
196
|
+
let result;
|
|
197
|
+
// Determine the base operator from the compound operator
|
|
198
|
+
switch (stmt.operator) {
|
|
199
|
+
case '+=':
|
|
200
|
+
// Support string concatenation with +=
|
|
201
|
+
if (typeof current === 'string' || typeof operand === 'string') {
|
|
202
|
+
result = String(current ?? 'phantom') + String(operand ?? 'phantom');
|
|
203
|
+
}
|
|
204
|
+
else if (typeof current === 'number' && typeof operand === 'number') {
|
|
205
|
+
result = current + operand;
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
throw new types_1.GGRuntimeError(`Cannot apply '+=' to ${typeof current} and ${typeof operand}`, stmt.line);
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
case '-=':
|
|
212
|
+
result = this.assertNumber(current, stmt.line) - this.assertNumber(operand, stmt.line);
|
|
213
|
+
break;
|
|
214
|
+
case '*=':
|
|
215
|
+
result = this.assertNumber(current, stmt.line) * this.assertNumber(operand, stmt.line);
|
|
216
|
+
break;
|
|
217
|
+
case '/=':
|
|
218
|
+
{
|
|
219
|
+
const divisor = this.assertNumber(operand, stmt.line);
|
|
220
|
+
if (divisor === 0) {
|
|
221
|
+
throw new types_1.GGRuntimeError('Division by zero! The void consumes all.', stmt.line);
|
|
222
|
+
}
|
|
223
|
+
result = this.assertNumber(current, stmt.line) / divisor;
|
|
224
|
+
}
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
throw new types_1.GGRuntimeError(`Unknown compound operator: ${stmt.operator}`, stmt.line);
|
|
228
|
+
}
|
|
229
|
+
env.set(stmt.name, result);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* broadcast(expr) — Print a value to stdout with GGLang formatting.
|
|
233
|
+
* Strings are printed without surrounding quotes.
|
|
234
|
+
* null → 'phantom', true → 'victory', false → 'defeat'
|
|
235
|
+
*/
|
|
236
|
+
executePrint(stmt, env) {
|
|
237
|
+
const value = this.evaluateExpression(stmt.value, env);
|
|
238
|
+
console.log(this.formatValue(value));
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* quest / side_quest / retreat — Conditional branching.
|
|
242
|
+
*/
|
|
243
|
+
executeIf(stmt, env) {
|
|
244
|
+
// Check the main condition
|
|
245
|
+
if (this.isTruthy(this.evaluateExpression(stmt.condition, env))) {
|
|
246
|
+
this.executeBlock(stmt.body, env);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
// Check each else-if (side_quest) clause
|
|
250
|
+
for (const clause of stmt.elseIfClauses) {
|
|
251
|
+
if (this.isTruthy(this.evaluateExpression(clause.condition, env))) {
|
|
252
|
+
this.executeBlock(clause.body, env);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Fall through to else (retreat) body, if present
|
|
257
|
+
if (stmt.elseBody) {
|
|
258
|
+
this.executeBlock(stmt.elseBody, env);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* grind { ... } — While loop with break/continue support.
|
|
263
|
+
*/
|
|
264
|
+
executeWhile(stmt, env) {
|
|
265
|
+
while (this.isTruthy(this.evaluateExpression(stmt.condition, env))) {
|
|
266
|
+
try {
|
|
267
|
+
this.executeBlock(stmt.body, env);
|
|
268
|
+
}
|
|
269
|
+
catch (signal) {
|
|
270
|
+
if (signal instanceof BreakSignal) {
|
|
271
|
+
break; // Exit the loop
|
|
272
|
+
}
|
|
273
|
+
if (signal instanceof ContinueSignal) {
|
|
274
|
+
continue; // Skip to next iteration
|
|
275
|
+
}
|
|
276
|
+
throw signal; // Re-throw anything else (ReturnSignal, errors, etc.)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* skill name(params) { ... } — Declare a function with closure capture.
|
|
282
|
+
* The function remembers the environment where it was declared.
|
|
283
|
+
*/
|
|
284
|
+
executeFunctionDeclaration(stmt, env) {
|
|
285
|
+
const func = {
|
|
286
|
+
type: 'function',
|
|
287
|
+
name: stmt.name,
|
|
288
|
+
params: stmt.params,
|
|
289
|
+
body: stmt.body,
|
|
290
|
+
closure: env, // Capture the current environment for closure
|
|
291
|
+
};
|
|
292
|
+
env.declare(stmt.name, func, false);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* loot expr — Return a value from a function.
|
|
296
|
+
* Throws a ReturnSignal that carries the return value up the stack.
|
|
297
|
+
*/
|
|
298
|
+
executeReturn(stmt, env) {
|
|
299
|
+
const value = stmt.value
|
|
300
|
+
? this.evaluateExpression(stmt.value, env)
|
|
301
|
+
: null;
|
|
302
|
+
throw new ReturnSignal(value);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* glitch expr — Throw a runtime error with a user-defined message.
|
|
306
|
+
*/
|
|
307
|
+
executeThrow(stmt, env) {
|
|
308
|
+
const value = this.evaluateExpression(stmt.value, env);
|
|
309
|
+
throw new types_1.GGRuntimeError(String(value ?? 'phantom'), stmt.line);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* boss_fight { ... } revive(err) { ... } — Try/catch for error handling.
|
|
313
|
+
* Only catches GGRuntimeError (user-level errors), not internal signals.
|
|
314
|
+
*/
|
|
315
|
+
executeTryCatch(stmt, env) {
|
|
316
|
+
try {
|
|
317
|
+
this.executeBlock(stmt.tryBody, env);
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
if (error instanceof types_1.GGRuntimeError) {
|
|
321
|
+
// Create a new scope for the catch block with the error variable
|
|
322
|
+
const catchEnv = new environment_1.Environment(env);
|
|
323
|
+
catchEnv.declare(stmt.catchParam, error.message, false);
|
|
324
|
+
this.executeBlock(stmt.catchBody, catchEnv);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
// Re-throw internal signals (BreakSignal, ContinueSignal, ReturnSignal)
|
|
328
|
+
// and any truly unexpected errors
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// ---- Expression Evaluation ----
|
|
334
|
+
/**
|
|
335
|
+
* Evaluates an expression node and returns its runtime value.
|
|
336
|
+
*
|
|
337
|
+
* @param expr - The AST expression node
|
|
338
|
+
* @param env - The current environment scope
|
|
339
|
+
* @returns The evaluated RuntimeValue
|
|
340
|
+
*/
|
|
341
|
+
evaluateExpression(expr, env) {
|
|
342
|
+
switch (expr.type) {
|
|
343
|
+
case 'NumberLiteral':
|
|
344
|
+
return expr.value;
|
|
345
|
+
case 'StringLiteral':
|
|
346
|
+
return expr.value;
|
|
347
|
+
case 'BooleanLiteral':
|
|
348
|
+
return expr.value;
|
|
349
|
+
case 'NullLiteral':
|
|
350
|
+
return null;
|
|
351
|
+
case 'Identifier':
|
|
352
|
+
return env.get(expr.name);
|
|
353
|
+
case 'BinaryExpression':
|
|
354
|
+
return this.evaluateBinaryExpression(expr, env);
|
|
355
|
+
case 'UnaryExpression':
|
|
356
|
+
return this.evaluateUnaryExpression(expr, env);
|
|
357
|
+
case 'LogicalExpression':
|
|
358
|
+
return this.evaluateLogicalExpression(expr, env);
|
|
359
|
+
case 'CallExpression':
|
|
360
|
+
return this.evaluateCallExpression(expr, env);
|
|
361
|
+
default:
|
|
362
|
+
throw new types_1.GGRuntimeError(`Unknown expression type: ${expr.type}`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Evaluates binary expressions: arithmetic, comparison, and string concatenation.
|
|
367
|
+
*/
|
|
368
|
+
evaluateBinaryExpression(expr, env) {
|
|
369
|
+
const left = this.evaluateExpression(expr.left, env);
|
|
370
|
+
const right = this.evaluateExpression(expr.right, env);
|
|
371
|
+
switch (expr.operator) {
|
|
372
|
+
// ---- Arithmetic / String Concatenation ----
|
|
373
|
+
case '+':
|
|
374
|
+
// String concatenation if either operand is a string
|
|
375
|
+
if (typeof left === 'string' || typeof right === 'string') {
|
|
376
|
+
return this.formatValue(left) + this.formatValue(right);
|
|
377
|
+
}
|
|
378
|
+
if (typeof left === 'number' && typeof right === 'number') {
|
|
379
|
+
return left + right;
|
|
380
|
+
}
|
|
381
|
+
throw new types_1.GGRuntimeError(`Cannot add ${typeof left} and ${typeof right}`);
|
|
382
|
+
case '-':
|
|
383
|
+
return this.assertNumber(left) - this.assertNumber(right);
|
|
384
|
+
case '*':
|
|
385
|
+
return this.assertNumber(left) * this.assertNumber(right);
|
|
386
|
+
case '/':
|
|
387
|
+
{
|
|
388
|
+
const divisor = this.assertNumber(right);
|
|
389
|
+
if (divisor === 0) {
|
|
390
|
+
throw new types_1.GGRuntimeError('Division by zero! The void consumes all.');
|
|
391
|
+
}
|
|
392
|
+
return this.assertNumber(left) / divisor;
|
|
393
|
+
}
|
|
394
|
+
case '%':
|
|
395
|
+
{
|
|
396
|
+
const mod = this.assertNumber(right);
|
|
397
|
+
if (mod === 0) {
|
|
398
|
+
throw new types_1.GGRuntimeError('Modulo by zero! The void consumes all.');
|
|
399
|
+
}
|
|
400
|
+
return this.assertNumber(left) % mod;
|
|
401
|
+
}
|
|
402
|
+
// ---- Comparison ----
|
|
403
|
+
case '==':
|
|
404
|
+
return left === right;
|
|
405
|
+
case '!=':
|
|
406
|
+
return left !== right;
|
|
407
|
+
case '>':
|
|
408
|
+
return this.assertNumber(left) > this.assertNumber(right);
|
|
409
|
+
case '<':
|
|
410
|
+
return this.assertNumber(left) < this.assertNumber(right);
|
|
411
|
+
case '>=':
|
|
412
|
+
return this.assertNumber(left) >= this.assertNumber(right);
|
|
413
|
+
case '<=':
|
|
414
|
+
return this.assertNumber(left) <= this.assertNumber(right);
|
|
415
|
+
default:
|
|
416
|
+
throw new types_1.GGRuntimeError(`Unknown operator: ${expr.operator}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Evaluates unary expressions: negation (-) and logical not (!).
|
|
421
|
+
*/
|
|
422
|
+
evaluateUnaryExpression(expr, env) {
|
|
423
|
+
const operand = this.evaluateExpression(expr.operand, env);
|
|
424
|
+
switch (expr.operator) {
|
|
425
|
+
case '-':
|
|
426
|
+
return -this.assertNumber(operand);
|
|
427
|
+
case '!':
|
|
428
|
+
return !this.isTruthy(operand);
|
|
429
|
+
default:
|
|
430
|
+
throw new types_1.GGRuntimeError(`Unknown unary operator: ${expr.operator}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Evaluates logical expressions with short-circuit semantics.
|
|
435
|
+
* && returns the first falsy value or the last value.
|
|
436
|
+
* || returns the first truthy value or the last value.
|
|
437
|
+
*/
|
|
438
|
+
evaluateLogicalExpression(expr, env) {
|
|
439
|
+
const left = this.evaluateExpression(expr.left, env);
|
|
440
|
+
switch (expr.operator) {
|
|
441
|
+
case '&&':
|
|
442
|
+
// Short-circuit: if left is falsy, return left without evaluating right
|
|
443
|
+
if (!this.isTruthy(left))
|
|
444
|
+
return left;
|
|
445
|
+
return this.evaluateExpression(expr.right, env);
|
|
446
|
+
case '||':
|
|
447
|
+
// Short-circuit: if left is truthy, return left without evaluating right
|
|
448
|
+
if (this.isTruthy(left))
|
|
449
|
+
return left;
|
|
450
|
+
return this.evaluateExpression(expr.right, env);
|
|
451
|
+
default:
|
|
452
|
+
throw new types_1.GGRuntimeError(`Unknown logical operator: ${expr.operator}`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Evaluates a function call expression.
|
|
457
|
+
* Handles the built-in 'interact' function (reads user input from stdin)
|
|
458
|
+
* and user-defined functions (with closure support).
|
|
459
|
+
*/
|
|
460
|
+
evaluateCallExpression(expr, env) {
|
|
461
|
+
// ---- Built-in: interact(prompt?) ----
|
|
462
|
+
// Reads a line from stdin. Optionally takes a prompt string.
|
|
463
|
+
if (expr.callee === 'interact') {
|
|
464
|
+
const promptArg = expr.arguments.length > 0
|
|
465
|
+
? this.evaluateExpression(expr.arguments[0], env)
|
|
466
|
+
: '';
|
|
467
|
+
const promptText = typeof promptArg === 'string' ? promptArg : this.formatValue(promptArg);
|
|
468
|
+
return readInputSync(promptText);
|
|
469
|
+
}
|
|
470
|
+
// ---- User-defined function ----
|
|
471
|
+
const callee = env.get(expr.callee);
|
|
472
|
+
if (callee === null || typeof callee !== 'object' || callee.type !== 'function') {
|
|
473
|
+
throw new types_1.GGRuntimeError(`'${expr.callee}' is not a skill (function)! Cannot call it.`, expr.line);
|
|
474
|
+
}
|
|
475
|
+
const func = callee;
|
|
476
|
+
// Validate argument count
|
|
477
|
+
if (expr.arguments.length !== func.params.length) {
|
|
478
|
+
throw new types_1.GGRuntimeError(`Skill '${func.name}' expects ${func.params.length} argument(s) but got ${expr.arguments.length}.`, expr.line);
|
|
479
|
+
}
|
|
480
|
+
// Evaluate arguments
|
|
481
|
+
const args = expr.arguments.map((arg) => this.evaluateExpression(arg, env));
|
|
482
|
+
// Create a new scope with the function's closure as parent (lexical scoping)
|
|
483
|
+
const funcEnv = new environment_1.Environment(func.closure);
|
|
484
|
+
// Bind parameters to argument values
|
|
485
|
+
for (let i = 0; i < func.params.length; i++) {
|
|
486
|
+
funcEnv.declare(func.params[i], args[i], false);
|
|
487
|
+
}
|
|
488
|
+
// Execute the function body and catch ReturnSignal for the return value
|
|
489
|
+
try {
|
|
490
|
+
for (const bodyStmt of func.body) {
|
|
491
|
+
this.executeStatement(bodyStmt, funcEnv);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
catch (signal) {
|
|
495
|
+
if (signal instanceof ReturnSignal) {
|
|
496
|
+
return signal.returnValue;
|
|
497
|
+
}
|
|
498
|
+
throw signal; // Re-throw errors, BreakSignal, etc.
|
|
499
|
+
}
|
|
500
|
+
// If no return statement was reached, the function returns null (phantom)
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
// ---- Helper Methods ----
|
|
504
|
+
/**
|
|
505
|
+
* Executes a block of statements in a new child scope.
|
|
506
|
+
* This ensures variables declared inside the block don't leak out.
|
|
507
|
+
*/
|
|
508
|
+
executeBlock(body, parentEnv) {
|
|
509
|
+
const blockEnv = new environment_1.Environment(parentEnv);
|
|
510
|
+
for (const stmt of body) {
|
|
511
|
+
this.executeStatement(stmt, blockEnv);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Determines the truthiness of a GGLang value.
|
|
516
|
+
* - false, null, 0, and "" are falsy
|
|
517
|
+
* - Everything else (including functions) is truthy
|
|
518
|
+
*/
|
|
519
|
+
isTruthy(value) {
|
|
520
|
+
if (value === null)
|
|
521
|
+
return false;
|
|
522
|
+
if (typeof value === 'boolean')
|
|
523
|
+
return value;
|
|
524
|
+
if (typeof value === 'number')
|
|
525
|
+
return value !== 0;
|
|
526
|
+
if (typeof value === 'string')
|
|
527
|
+
return value.length > 0;
|
|
528
|
+
return true; // Functions are truthy
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Asserts that a value is a number, throwing a runtime error if not.
|
|
532
|
+
* Used by arithmetic operators to enforce type safety.
|
|
533
|
+
*/
|
|
534
|
+
assertNumber(value, line) {
|
|
535
|
+
if (typeof value !== 'number') {
|
|
536
|
+
throw new types_1.GGRuntimeError(`Expected a number but got ${typeof value} (${this.formatValue(value)})`, line);
|
|
537
|
+
}
|
|
538
|
+
return value;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Formats a RuntimeValue for display (used by broadcast and string coercion).
|
|
542
|
+
* - Strings are returned as-is (no surrounding quotes)
|
|
543
|
+
* - null → 'phantom'
|
|
544
|
+
* - true → 'victory', false → 'defeat'
|
|
545
|
+
* - Numbers are stringified normally
|
|
546
|
+
* - Functions show as '<skill name>'
|
|
547
|
+
*/
|
|
548
|
+
formatValue(value) {
|
|
549
|
+
if (value === null)
|
|
550
|
+
return 'phantom';
|
|
551
|
+
if (typeof value === 'boolean')
|
|
552
|
+
return value ? 'victory' : 'defeat';
|
|
553
|
+
if (typeof value === 'number')
|
|
554
|
+
return String(value);
|
|
555
|
+
if (typeof value === 'string')
|
|
556
|
+
return value;
|
|
557
|
+
if (typeof value === 'object' && value.type === 'function') {
|
|
558
|
+
return `<skill ${value.name}>`;
|
|
559
|
+
}
|
|
560
|
+
return String(value);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
exports.Interpreter = Interpreter;
|
|
564
|
+
//# sourceMappingURL=interpreter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../src/interpreter.ts"],"names":[],"mappings":"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"}
|
package/dist/lexer.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Token } from "./types";
|
|
2
|
+
export declare class Lexer {
|
|
3
|
+
/** Source code being tokenized */
|
|
4
|
+
private source;
|
|
5
|
+
/** List of tokens produced so far */
|
|
6
|
+
private tokens;
|
|
7
|
+
/** Current cursor position in the source string */
|
|
8
|
+
private cursor;
|
|
9
|
+
/** Current line number (1-based) */
|
|
10
|
+
private line;
|
|
11
|
+
/** Current column number (1-based) */
|
|
12
|
+
private column;
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Tokenize the given source code string and return an array
|
|
16
|
+
* of Token objects. The array always ends with an EOF token.
|
|
17
|
+
*/
|
|
18
|
+
tokenize(source: string): Token[];
|
|
19
|
+
/**
|
|
20
|
+
* Identify and consume the next token starting at the current cursor.
|
|
21
|
+
*/
|
|
22
|
+
private scanToken;
|
|
23
|
+
/** Returns true when the cursor has reached (or passed) the end of source. */
|
|
24
|
+
private isAtEnd;
|
|
25
|
+
/** Return the character at the cursor WITHOUT advancing. */
|
|
26
|
+
private peek;
|
|
27
|
+
/** Return the character one past the cursor, or empty string if at end. */
|
|
28
|
+
private peekNext;
|
|
29
|
+
/**
|
|
30
|
+
* Consume the current character and advance cursor, line, and column.
|
|
31
|
+
* Returns the consumed character.
|
|
32
|
+
*/
|
|
33
|
+
private advance;
|
|
34
|
+
private isWhitespace;
|
|
35
|
+
private isDigit;
|
|
36
|
+
/** Letters and underscore — valid start of an identifier. */
|
|
37
|
+
private isAlpha;
|
|
38
|
+
/** Letters, digits, and underscore — valid continuation of an identifier. */
|
|
39
|
+
private isAlphaNumeric;
|
|
40
|
+
private addToken;
|
|
41
|
+
/**
|
|
42
|
+
* Try to match a two-character operator string.
|
|
43
|
+
* Returns the TokenType if it matches, or null otherwise.
|
|
44
|
+
*/
|
|
45
|
+
private matchTwoCharOp;
|
|
46
|
+
/**
|
|
47
|
+
* Match a single-character operator or punctuation symbol.
|
|
48
|
+
* Returns the TokenType if it matches, or null otherwise.
|
|
49
|
+
*/
|
|
50
|
+
private matchSingleCharOp;
|
|
51
|
+
/**
|
|
52
|
+
* Read a number literal (integer or floating-point).
|
|
53
|
+
* Examples: 42, 3.14
|
|
54
|
+
*/
|
|
55
|
+
private readNumber;
|
|
56
|
+
/**
|
|
57
|
+
* Read a string literal enclosed by the given quote character.
|
|
58
|
+
* Supports escape sequences: \n, \t, \\, \", \'
|
|
59
|
+
* Throws GGLexerError on unterminated strings.
|
|
60
|
+
*/
|
|
61
|
+
private readString;
|
|
62
|
+
/**
|
|
63
|
+
* Read an identifier or keyword.
|
|
64
|
+
* Identifiers start with a letter or underscore, then continue
|
|
65
|
+
* with letters, digits, or underscores.
|
|
66
|
+
*/
|
|
67
|
+
private readIdentifier;
|
|
68
|
+
/** Skip a single-line comment (// ... until end of line). */
|
|
69
|
+
private skipLineComment;
|
|
70
|
+
/**
|
|
71
|
+
* Skip a block comment (/* ... * /).
|
|
72
|
+
* Throws GGLexerError if the comment is never closed.
|
|
73
|
+
*/
|
|
74
|
+
private skipBlockComment;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=lexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../src/lexer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAA2B,MAAM,SAAS,CAAC;AA6BzD,qBAAa,KAAK;IAChB,kCAAkC;IAClC,OAAO,CAAC,MAAM,CAAS;IACvB,qCAAqC;IACrC,OAAO,CAAC,MAAM,CAAU;IACxB,mDAAmD;IACnD,OAAO,CAAC,MAAM,CAAS;IACvB,oCAAoC;IACpC,OAAO,CAAC,IAAI,CAAS;IACrB,sCAAsC;IACtC,OAAO,CAAC,MAAM,CAAS;;IAcvB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE;IA4BjC;;OAEG;IACH,OAAO,CAAC,SAAS;IAqEjB,8EAA8E;IAC9E,OAAO,CAAC,OAAO;IAIf,4DAA4D;IAC5D,OAAO,CAAC,IAAI;IAIZ,2EAA2E;IAC3E,OAAO,CAAC,QAAQ;IAKhB;;;OAGG;IACH,OAAO,CAAC,OAAO;IAkBf,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,OAAO;IAIf,6DAA6D;IAC7D,OAAO,CAAC,OAAO;IAQf,6EAA6E;IAC7E,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,QAAQ;IAahB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAgBtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAqBlB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAgElB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAsBtB,6DAA6D;IAC7D,OAAO,CAAC,eAAe;IAYvB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;CAwBzB"}
|