@ugo-studio/jspp 0.2.6 → 0.2.8

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.
Files changed (43) hide show
  1. package/dist/analysis/typeAnalyzer.js +56 -24
  2. package/dist/ast/symbols.js +28 -19
  3. package/dist/cli/index.js +1 -1
  4. package/dist/core/codegen/class-handlers.js +8 -8
  5. package/dist/core/codegen/control-flow-handlers.js +17 -7
  6. package/dist/core/codegen/declaration-handlers.js +21 -9
  7. package/dist/core/codegen/expression-handlers.js +558 -126
  8. package/dist/core/codegen/function-handlers.js +101 -108
  9. package/dist/core/codegen/helpers.js +28 -7
  10. package/dist/core/codegen/index.js +6 -4
  11. package/dist/core/codegen/literal-handlers.js +4 -2
  12. package/dist/core/codegen/statement-handlers.js +39 -19
  13. package/package.json +1 -1
  14. package/scripts/precompile-headers.ts +8 -1
  15. package/src/prelude/any_value.hpp +89 -59
  16. package/src/prelude/any_value_access.hpp +1 -1
  17. package/src/prelude/any_value_helpers.hpp +85 -43
  18. package/src/prelude/index.hpp +1 -0
  19. package/src/prelude/library/array.hpp +3 -2
  20. package/src/prelude/types.hpp +8 -8
  21. package/src/prelude/utils/access.hpp +62 -6
  22. package/src/prelude/utils/assignment_operators.hpp +14 -14
  23. package/src/prelude/utils/log_any_value/array.hpp +0 -15
  24. package/src/prelude/utils/log_any_value/primitives.hpp +2 -0
  25. package/src/prelude/utils/operators.hpp +117 -474
  26. package/src/prelude/utils/operators_primitive.hpp +337 -0
  27. package/src/prelude/values/helpers/array.hpp +4 -4
  28. package/src/prelude/values/helpers/async_iterator.hpp +2 -2
  29. package/src/prelude/values/helpers/function.hpp +3 -3
  30. package/src/prelude/values/helpers/iterator.hpp +2 -2
  31. package/src/prelude/values/helpers/object.hpp +3 -3
  32. package/src/prelude/values/helpers/promise.hpp +1 -1
  33. package/src/prelude/values/helpers/string.hpp +1 -1
  34. package/src/prelude/values/helpers/symbol.hpp +1 -1
  35. package/src/prelude/values/prototypes/array.hpp +1125 -853
  36. package/src/prelude/values/prototypes/async_iterator.hpp +32 -14
  37. package/src/prelude/values/prototypes/function.hpp +30 -18
  38. package/src/prelude/values/prototypes/iterator.hpp +40 -17
  39. package/src/prelude/values/prototypes/number.hpp +119 -62
  40. package/src/prelude/values/prototypes/object.hpp +10 -4
  41. package/src/prelude/values/prototypes/promise.hpp +167 -109
  42. package/src/prelude/values/prototypes/string.hpp +407 -231
  43. 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
- // Catch invalid parameters
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
- // Catch invalid parameters
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
- // Catch invalid parameters
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
  },
@@ -10,13 +10,11 @@ export var DeclarationType;
10
10
  export class DeclaredSymbol {
11
11
  type;
12
12
  checks;
13
- func;
13
+ features;
14
14
  constructor(type) {
15
15
  this.type = type;
16
- this.checks = {
17
- initialized: false,
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
- updateFunc(update) {
32
- this.func = update
33
- ? {
34
- ...this.func,
35
- ...update,
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 !== undefined)
53
+ if (value.checks)
58
54
  sym.updateChecked(value.checks);
59
- if (value.func !== undefined)
60
- sym.updateFunc(value.func);
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 !== undefined)
62
+ if (update.type)
67
63
  sym.type = update.type;
68
- if (update.checks !== undefined)
64
+ if (update.checks)
69
65
  sym.updateChecked(update.checks);
70
- if (update.func !== undefined)
71
- sym.updateFunc(update.func);
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.generateLambda(constructor, {
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.generateLambda(member, {
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.generateLambda(member, {
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.generateLambda(member, {
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, { func: { nativeName } });
444
- // Generate lambda
445
- const lambda = this.generateLambda(stmt, contextForFunctions, {
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
- code += `${this.indent()}auto ${nativeName} = ${lambda};\n`;
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 fullExpression = this.generateFullLambdaExpression(stmt, contextForFunctions, nativeName, { isAssignment: true, noTypeSignature: true });
455
- code += `${this.indent()}*${funcName} = ${fullExpression};\n`;
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
- context.localScopeSymbols.update(name, { func: { nativeName } });
49
- // Generate lambda
50
- const lambda = this.generateLambda(initExpr, initContext, {
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
- nativeLambdaCode =
56
- `auto ${nativeName} = ${lambda};\n${this.indent()}`;
64
+ const nativeLambda = this.generateNativeLambda(lambdaComps);
65
+ // Generate native lambda
66
+ nativeLambdaCode = `auto ${nativeName} = ${nativeLambda}`;
57
67
  // Generate AnyValue wrapper
58
- initText = this.generateFullLambdaExpression(initExpr, initContext, nativeName, { isAssignment: true, noTypeSignature: true });
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) {