@ugo-studio/jspp 0.2.6 → 0.2.7
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/dist/analysis/typeAnalyzer.js +56 -24
- package/dist/ast/symbols.js +28 -19
- package/dist/cli/index.js +1 -1
- package/dist/core/codegen/class-handlers.js +8 -8
- package/dist/core/codegen/control-flow-handlers.js +17 -7
- package/dist/core/codegen/declaration-handlers.js +21 -9
- package/dist/core/codegen/expression-handlers.js +558 -126
- package/dist/core/codegen/function-handlers.js +101 -108
- package/dist/core/codegen/helpers.js +28 -7
- package/dist/core/codegen/index.js +6 -4
- package/dist/core/codegen/literal-handlers.js +4 -2
- package/dist/core/codegen/statement-handlers.js +39 -19
- package/package.json +1 -1
- package/src/prelude/any_value.hpp +89 -59
- package/src/prelude/any_value_access.hpp +1 -1
- package/src/prelude/any_value_helpers.hpp +85 -43
- package/src/prelude/index.hpp +1 -0
- package/src/prelude/library/array.hpp +3 -2
- package/src/prelude/types.hpp +8 -8
- package/src/prelude/utils/access.hpp +62 -6
- package/src/prelude/utils/assignment_operators.hpp +14 -14
- package/src/prelude/utils/log_any_value/array.hpp +0 -15
- package/src/prelude/utils/log_any_value/primitives.hpp +2 -0
- package/src/prelude/utils/operators.hpp +117 -474
- package/src/prelude/utils/operators_primitive.hpp +337 -0
- package/src/prelude/values/helpers/array.hpp +4 -4
- package/src/prelude/values/helpers/async_iterator.hpp +2 -2
- package/src/prelude/values/helpers/function.hpp +3 -3
- package/src/prelude/values/helpers/iterator.hpp +2 -2
- package/src/prelude/values/helpers/object.hpp +3 -3
- package/src/prelude/values/helpers/promise.hpp +1 -1
- package/src/prelude/values/helpers/string.hpp +1 -1
- package/src/prelude/values/helpers/symbol.hpp +1 -1
- package/src/prelude/values/prototypes/array.hpp +1125 -853
- package/src/prelude/values/prototypes/async_iterator.hpp +32 -14
- package/src/prelude/values/prototypes/function.hpp +30 -18
- package/src/prelude/values/prototypes/iterator.hpp +40 -17
- package/src/prelude/values/prototypes/number.hpp +119 -62
- package/src/prelude/values/prototypes/object.hpp +10 -4
- package/src/prelude/values/prototypes/promise.hpp +167 -109
- package/src/prelude/values/prototypes/string.hpp +407 -231
- package/src/prelude/values/prototypes/symbol.hpp +45 -23
|
@@ -3,6 +3,41 @@ import { isBuiltinObject, shouldIgnoreStatement, } from "../core/codegen/helpers
|
|
|
3
3
|
import { CompilerError } from "../core/error.js";
|
|
4
4
|
import { Traverser } from "../core/traverser.js";
|
|
5
5
|
import { Scope, ScopeManager } from "./scope.js";
|
|
6
|
+
function getParameterType(node) {
|
|
7
|
+
if (node.type) {
|
|
8
|
+
switch (node.type.kind) {
|
|
9
|
+
case ts.SyntaxKind.StringKeyword:
|
|
10
|
+
return "string";
|
|
11
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
12
|
+
return "number";
|
|
13
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
14
|
+
return "boolean";
|
|
15
|
+
case ts.SyntaxKind.AnyKeyword:
|
|
16
|
+
return "any";
|
|
17
|
+
case ts.SyntaxKind.VoidKeyword:
|
|
18
|
+
return "void";
|
|
19
|
+
case ts.SyntaxKind.ObjectKeyword:
|
|
20
|
+
return "object";
|
|
21
|
+
case ts.SyntaxKind.SymbolKeyword:
|
|
22
|
+
return "symbol";
|
|
23
|
+
case ts.SyntaxKind.UndefinedKeyword:
|
|
24
|
+
return "undefined";
|
|
25
|
+
case ts.SyntaxKind.UnknownKeyword:
|
|
26
|
+
return "unknown";
|
|
27
|
+
case ts.SyntaxKind.NeverKeyword:
|
|
28
|
+
return "never";
|
|
29
|
+
case ts.SyntaxKind.ArrayType:
|
|
30
|
+
return "array";
|
|
31
|
+
case ts.SyntaxKind.FunctionType:
|
|
32
|
+
return "function";
|
|
33
|
+
}
|
|
34
|
+
if (ts.isTypeReferenceNode(node.type)) {
|
|
35
|
+
return node.type.typeName.getText();
|
|
36
|
+
}
|
|
37
|
+
return node.type.getText();
|
|
38
|
+
}
|
|
39
|
+
return "auto";
|
|
40
|
+
}
|
|
6
41
|
export class TypeAnalyzer {
|
|
7
42
|
traverser = new Traverser();
|
|
8
43
|
scopeManager = new ScopeManager();
|
|
@@ -206,18 +241,17 @@ export class TypeAnalyzer {
|
|
|
206
241
|
this.functionTypeInfo.set(node, funcType);
|
|
207
242
|
this.scopeManager.enterScope(node);
|
|
208
243
|
this.nodeToScope.set(node, this.scopeManager.currentScope);
|
|
209
|
-
//
|
|
244
|
+
// Define parameters in the new scope
|
|
210
245
|
node.parameters.forEach((p) => {
|
|
211
|
-
if (p.getText() == "this") {
|
|
246
|
+
if (p.getText() == "this") { // Catch invalid parameters
|
|
212
247
|
throw new CompilerError("Cannot use 'this' as a parameter name.", p, "SyntaxError");
|
|
213
248
|
}
|
|
249
|
+
this.scopeManager.define(p.name.getText(), {
|
|
250
|
+
type: getParameterType(p),
|
|
251
|
+
isParameter: true,
|
|
252
|
+
declaration: p,
|
|
253
|
+
});
|
|
214
254
|
});
|
|
215
|
-
// Define parameters in the new scope
|
|
216
|
-
node.parameters.forEach((p) => this.scopeManager.define(p.name.getText(), {
|
|
217
|
-
type: "auto",
|
|
218
|
-
isParameter: true,
|
|
219
|
-
declaration: p,
|
|
220
|
-
}));
|
|
221
255
|
this.functionStack.push(node);
|
|
222
256
|
}
|
|
223
257
|
},
|
|
@@ -245,18 +279,17 @@ export class TypeAnalyzer {
|
|
|
245
279
|
if (node.name) {
|
|
246
280
|
this.scopeManager.define(node.name.getText(), funcType);
|
|
247
281
|
}
|
|
248
|
-
//
|
|
282
|
+
// Define parameters in the new scope
|
|
249
283
|
node.parameters.forEach((p) => {
|
|
250
|
-
if (p.getText() == "this") {
|
|
284
|
+
if (p.getText() == "this") { // Catch invalid parameters
|
|
251
285
|
throw new CompilerError("Cannot use 'this' as a parameter name.", p, "SyntaxError");
|
|
252
286
|
}
|
|
287
|
+
this.scopeManager.define(p.name.getText(), {
|
|
288
|
+
type: getParameterType(p),
|
|
289
|
+
isParameter: true,
|
|
290
|
+
declaration: p,
|
|
291
|
+
});
|
|
253
292
|
});
|
|
254
|
-
// Define parameters in the new scope
|
|
255
|
-
node.parameters.forEach((p) => this.scopeManager.define(p.name.getText(), {
|
|
256
|
-
type: "auto",
|
|
257
|
-
isParameter: true,
|
|
258
|
-
declaration: p,
|
|
259
|
-
}));
|
|
260
293
|
this.functionStack.push(node);
|
|
261
294
|
}
|
|
262
295
|
},
|
|
@@ -285,18 +318,17 @@ export class TypeAnalyzer {
|
|
|
285
318
|
}
|
|
286
319
|
this.scopeManager.enterScope(node);
|
|
287
320
|
this.nodeToScope.set(node, this.scopeManager.currentScope);
|
|
288
|
-
//
|
|
321
|
+
// Define parameters in the new scope
|
|
289
322
|
node.parameters.forEach((p) => {
|
|
290
|
-
if (p.getText() == "this") {
|
|
323
|
+
if (p.getText() == "this") { // Catch invalid parameters
|
|
291
324
|
throw new CompilerError("Cannot use 'this' as a parameter name.", p, "SyntaxError");
|
|
292
325
|
}
|
|
326
|
+
this.scopeManager.define(p.name.getText(), {
|
|
327
|
+
type: getParameterType(p),
|
|
328
|
+
isParameter: true,
|
|
329
|
+
declaration: p,
|
|
330
|
+
});
|
|
293
331
|
});
|
|
294
|
-
// Define parameters in the new scope
|
|
295
|
-
node.parameters.forEach((p) => this.scopeManager.define(p.name.getText(), {
|
|
296
|
-
type: "auto",
|
|
297
|
-
isParameter: true,
|
|
298
|
-
declaration: p,
|
|
299
|
-
}));
|
|
300
332
|
this.functionStack.push(node);
|
|
301
333
|
}
|
|
302
334
|
},
|
package/dist/ast/symbols.js
CHANGED
|
@@ -10,13 +10,11 @@ export var DeclarationType;
|
|
|
10
10
|
export class DeclaredSymbol {
|
|
11
11
|
type;
|
|
12
12
|
checks;
|
|
13
|
-
|
|
13
|
+
features;
|
|
14
14
|
constructor(type) {
|
|
15
15
|
this.type = type;
|
|
16
|
-
this.checks = {
|
|
17
|
-
|
|
18
|
-
};
|
|
19
|
-
this.func = null;
|
|
16
|
+
this.checks = { initialized: false };
|
|
17
|
+
this.features = {};
|
|
20
18
|
}
|
|
21
19
|
get isMutable() {
|
|
22
20
|
return this.type === DeclarationType.let ||
|
|
@@ -28,13 +26,11 @@ export class DeclaredSymbol {
|
|
|
28
26
|
...update,
|
|
29
27
|
};
|
|
30
28
|
}
|
|
31
|
-
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
: null;
|
|
29
|
+
updateFeatures(update) {
|
|
30
|
+
this.features = {
|
|
31
|
+
...this.features,
|
|
32
|
+
...update,
|
|
33
|
+
};
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
36
|
export class DeclaredSymbols {
|
|
@@ -54,21 +50,34 @@ export class DeclaredSymbols {
|
|
|
54
50
|
}
|
|
55
51
|
add(name, value) {
|
|
56
52
|
const sym = new DeclaredSymbol(value.type);
|
|
57
|
-
if (value.checks
|
|
53
|
+
if (value.checks)
|
|
58
54
|
sym.updateChecked(value.checks);
|
|
59
|
-
if (value.
|
|
60
|
-
sym.
|
|
55
|
+
if (value.features)
|
|
56
|
+
sym.updateFeatures(value.features);
|
|
61
57
|
return this.symbols.set(name, sym);
|
|
62
58
|
}
|
|
63
59
|
update(name, update) {
|
|
64
60
|
const sym = this.get(name);
|
|
65
61
|
if (sym) {
|
|
66
|
-
if (update.type
|
|
62
|
+
if (update.type)
|
|
67
63
|
sym.type = update.type;
|
|
68
|
-
if (update.checks
|
|
64
|
+
if (update.checks)
|
|
69
65
|
sym.updateChecked(update.checks);
|
|
70
|
-
if (update.
|
|
71
|
-
sym.
|
|
66
|
+
if (update.features) {
|
|
67
|
+
sym.updateFeatures(update.features);
|
|
68
|
+
}
|
|
69
|
+
return this.symbols.set(name, sym);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
set(name, update) {
|
|
73
|
+
const sym = this.get(name);
|
|
74
|
+
if (sym) {
|
|
75
|
+
if (update.type)
|
|
76
|
+
sym.type = update.type;
|
|
77
|
+
if (update.checks)
|
|
78
|
+
sym.checks = update.checks;
|
|
79
|
+
if (update.features)
|
|
80
|
+
sym.features = update.features;
|
|
72
81
|
return this.symbols.set(name, sym);
|
|
73
82
|
}
|
|
74
83
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { spawn } from "child_process";
|
|
|
3
3
|
import fs from "fs/promises";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import pkg from "../../package.json" with { type: "json" };
|
|
6
|
-
import { Interpreter } from "../index.js";
|
|
7
6
|
import { CompilerError } from "../core/error.js";
|
|
7
|
+
import { Interpreter } from "../index.js";
|
|
8
8
|
import { parseArgs } from "./args.js";
|
|
9
9
|
import { COLORS } from "./colors.js";
|
|
10
10
|
import { getLatestMtime } from "./file-utils.js";
|
|
@@ -32,11 +32,11 @@ export function visitClassDeclaration(node, context) {
|
|
|
32
32
|
const constructor = node.members.find(ts.isConstructorDeclaration);
|
|
33
33
|
let constructorLambda = "";
|
|
34
34
|
if (constructor) {
|
|
35
|
-
constructorLambda = this.
|
|
35
|
+
constructorLambda = this.generateWrappedLambda(this.generateLambdaComponents(constructor, {
|
|
36
36
|
...classContext,
|
|
37
37
|
isInsideFunction: true,
|
|
38
38
|
lambdaName: className,
|
|
39
|
-
}, { isClass: true });
|
|
39
|
+
}, { isClass: true }));
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
42
42
|
// Default constructor
|
|
@@ -75,10 +75,10 @@ export function visitClassDeclaration(node, context) {
|
|
|
75
75
|
isObjectLiteralExpression: true, // Reuse this flag to handle computed properties
|
|
76
76
|
});
|
|
77
77
|
const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
|
|
78
|
-
const methodLambda = this.
|
|
78
|
+
const methodLambda = this.generateWrappedLambda(this.generateLambdaComponents(member, {
|
|
79
79
|
...classContext,
|
|
80
80
|
isInsideFunction: true,
|
|
81
|
-
});
|
|
81
|
+
}));
|
|
82
82
|
if (isStatic) {
|
|
83
83
|
code +=
|
|
84
84
|
`${this.indent()}(*${className}).set_own_property(${methodName}, ${methodLambda});\n`;
|
|
@@ -94,10 +94,10 @@ export function visitClassDeclaration(node, context) {
|
|
|
94
94
|
isObjectLiteralExpression: true,
|
|
95
95
|
});
|
|
96
96
|
const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
|
|
97
|
-
const lambda = this.
|
|
97
|
+
const lambda = this.generateWrappedLambda(this.generateLambdaComponents(member, {
|
|
98
98
|
...classContext,
|
|
99
99
|
isInsideFunction: true,
|
|
100
|
-
});
|
|
100
|
+
}));
|
|
101
101
|
if (isStatic) {
|
|
102
102
|
code +=
|
|
103
103
|
`${this.indent()}(*${className}).define_getter(${methodName}, ${lambda});\n`;
|
|
@@ -113,10 +113,10 @@ export function visitClassDeclaration(node, context) {
|
|
|
113
113
|
isObjectLiteralExpression: true,
|
|
114
114
|
});
|
|
115
115
|
const isStatic = member.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword);
|
|
116
|
-
const lambda = this.
|
|
116
|
+
const lambda = this.generateWrappedLambda(this.generateLambdaComponents(member, {
|
|
117
117
|
...classContext,
|
|
118
118
|
isInsideFunction: true,
|
|
119
|
-
});
|
|
119
|
+
}));
|
|
120
120
|
if (isStatic) {
|
|
121
121
|
code +=
|
|
122
122
|
`${this.indent()}(*${className}).define_setter(${methodName}, ${lambda});\n`;
|
|
@@ -440,19 +440,29 @@ export function visitSwitchStatement(node, context) {
|
|
|
440
440
|
this.markSymbolAsInitialized(funcName, globalScopeSymbols, localScopeSymbols);
|
|
441
441
|
// Generate native name
|
|
442
442
|
const nativeName = this.generateUniqueName(`__${funcName}_native_`, hoistedSymbols);
|
|
443
|
-
hoistedSymbols.update(funcName, {
|
|
444
|
-
|
|
445
|
-
|
|
443
|
+
hoistedSymbols.update(funcName, {
|
|
444
|
+
features: {
|
|
445
|
+
native: {
|
|
446
|
+
type: "lambda",
|
|
447
|
+
name: nativeName,
|
|
448
|
+
parameters: this.validateFunctionParams(stmt.parameters),
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
// Generate lambda components
|
|
453
|
+
const lambdaComps = this.generateLambdaComponents(stmt, contextForFunctions, {
|
|
446
454
|
isAssignment: true,
|
|
447
|
-
generateOnlyLambda: true,
|
|
448
455
|
nativeName,
|
|
456
|
+
noTypeSignature: true,
|
|
449
457
|
});
|
|
450
|
-
|
|
458
|
+
// Generate native lambda
|
|
459
|
+
const nativeLambda = this.generateNativeLambda(lambdaComps);
|
|
460
|
+
code += `${this.indent()}auto ${nativeName} = ${nativeLambda};\n`;
|
|
451
461
|
// Generate AnyValue wrapper
|
|
452
462
|
if (this.isFunctionUsedAsValue(stmt, node) ||
|
|
453
463
|
this.isFunctionUsedBeforeDeclaration(funcName, node)) {
|
|
454
|
-
const
|
|
455
|
-
code += `${this.indent()}*${funcName} = ${
|
|
464
|
+
const wrappedLambda = this.generateWrappedLambda(lambdaComps);
|
|
465
|
+
code += `${this.indent()}*${funcName} = ${wrappedLambda};\n`;
|
|
456
466
|
}
|
|
457
467
|
});
|
|
458
468
|
let firstIf = true;
|
|
@@ -38,24 +38,34 @@ export function visitVariableDeclaration(node, context) {
|
|
|
38
38
|
initText = this.getDerefCode(initText, varName, context, initTypeInfo);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
else if (ts.isArrowFunction(initExpr)
|
|
41
|
+
else if (ts.isArrowFunction(initExpr) ||
|
|
42
|
+
(ts.isFunctionExpression(initExpr) && !initExpr.name)) {
|
|
42
43
|
const initContext = {
|
|
43
44
|
...context,
|
|
44
45
|
lambdaName: name, // Use the variable name as function name
|
|
45
46
|
};
|
|
46
|
-
// Generate and update self name
|
|
47
47
|
const nativeName = this.generateUniqueName(`__${name}_native_`, context.localScopeSymbols, context.globalScopeSymbols);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
// Mark before further visits
|
|
49
|
+
context.localScopeSymbols.update(name, {
|
|
50
|
+
features: {
|
|
51
|
+
native: {
|
|
52
|
+
type: "lambda",
|
|
53
|
+
name: nativeName,
|
|
54
|
+
parameters: this.validateFunctionParams(initExpr.parameters),
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
// Generate lambda components
|
|
59
|
+
const lambdaComps = this.generateLambdaComponents(initExpr, initContext, {
|
|
51
60
|
isAssignment: true,
|
|
52
|
-
generateOnlyLambda: true,
|
|
53
61
|
nativeName,
|
|
62
|
+
noTypeSignature: true,
|
|
54
63
|
});
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
const nativeLambda = this.generateNativeLambda(lambdaComps);
|
|
65
|
+
// Generate native lambda
|
|
66
|
+
nativeLambdaCode = `auto ${nativeName} = ${nativeLambda}`;
|
|
57
67
|
// Generate AnyValue wrapper
|
|
58
|
-
initText = this.
|
|
68
|
+
initText = this.generateWrappedLambda(lambdaComps);
|
|
59
69
|
}
|
|
60
70
|
initializer = " = " + initText;
|
|
61
71
|
}
|
|
@@ -67,6 +77,8 @@ export function visitVariableDeclaration(node, context) {
|
|
|
67
77
|
: (typeInfo.needsHeapAllocation && !shouldSkipDeref
|
|
68
78
|
? `*${name}`
|
|
69
79
|
: name);
|
|
80
|
+
if (nativeLambdaCode)
|
|
81
|
+
nativeLambdaCode += `;\n${this.indent()}`;
|
|
70
82
|
if (isLetOrConst) {
|
|
71
83
|
// If there's no initializer, it should be assigned undefined.
|
|
72
84
|
if (!initializer) {
|