jpsx 0.1.16
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/README.md +242 -0
- package/dist/api/__tests__/compile.test.d.ts +2 -0
- package/dist/api/__tests__/compile.test.d.ts.map +1 -0
- package/dist/api/__tests__/compile.test.js +336 -0
- package/dist/api/__tests__/runtime.test.d.ts +2 -0
- package/dist/api/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/api/__tests__/runtime.test.js +275 -0
- package/dist/api/advanced.d.ts +100 -0
- package/dist/api/advanced.d.ts.map +1 -0
- package/dist/api/advanced.js +192 -0
- package/dist/api/benchmark.d.ts +87 -0
- package/dist/api/benchmark.d.ts.map +1 -0
- package/dist/api/benchmark.js +147 -0
- package/dist/api/index.d.ts +88 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +304 -0
- package/dist/ast/types.d.ts +141 -0
- package/dist/ast/types.d.ts.map +1 -0
- package/dist/ast/types.js +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +155 -0
- package/dist/cli.js +30 -0
- package/dist/generator/generator.d.ts +3 -0
- package/dist/generator/generator.d.ts.map +1 -0
- package/dist/generator/generator.js +175 -0
- package/dist/lexer/lexer.d.ts +3 -0
- package/dist/lexer/lexer.d.ts.map +1 -0
- package/dist/lexer/lexer.js +23 -0
- package/dist/lexer/tokenizer.d.ts +9 -0
- package/dist/lexer/tokenizer.d.ts.map +1 -0
- package/dist/lexer/tokenizer.js +240 -0
- package/dist/parser/grammar.d.ts +29 -0
- package/dist/parser/grammar.d.ts.map +1 -0
- package/dist/parser/grammar.js +312 -0
- package/dist/parser/parser.d.ts +4 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +47 -0
- package/dist/runtime/index.d.ts +24 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +108 -0
- package/dist/transformer/transformer.d.ts +3 -0
- package/dist/transformer/transformer.d.ts.map +1 -0
- package/dist/transformer/transformer.js +318 -0
- package/package.json +54 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { compile } from "../index.js";
|
|
2
|
+
describe("Runtime Functions - Execution Tests", () => {
|
|
3
|
+
// Helper to execute compiled code and capture output
|
|
4
|
+
const executeCode = (source) => {
|
|
5
|
+
const logs = [];
|
|
6
|
+
const originalLog = console.log;
|
|
7
|
+
console.log = (...args) => {
|
|
8
|
+
logs.push(args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' '));
|
|
9
|
+
};
|
|
10
|
+
try {
|
|
11
|
+
const result = compile(source, {
|
|
12
|
+
format: "iife",
|
|
13
|
+
runtimeMode: "inline",
|
|
14
|
+
moduleName: "TestModule"
|
|
15
|
+
});
|
|
16
|
+
// Execute in isolated context
|
|
17
|
+
eval(result.code);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
console.log = originalLog;
|
|
21
|
+
}
|
|
22
|
+
return logs;
|
|
23
|
+
};
|
|
24
|
+
describe("print() function", () => {
|
|
25
|
+
test("should print string", () => {
|
|
26
|
+
const output = executeCode('print("Hello World")');
|
|
27
|
+
expect(output).toContain("Hello World");
|
|
28
|
+
});
|
|
29
|
+
test("should print numbers", () => {
|
|
30
|
+
const output = executeCode('print(42)');
|
|
31
|
+
expect(output).toContain("42");
|
|
32
|
+
});
|
|
33
|
+
test("should print multiple arguments", () => {
|
|
34
|
+
const output = executeCode('print("Answer:", 42)');
|
|
35
|
+
expect(output[0]).toContain("Answer:");
|
|
36
|
+
expect(output[0]).toContain("42");
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe("range() function", () => {
|
|
40
|
+
test("should generate range with single argument", () => {
|
|
41
|
+
const output = executeCode(`
|
|
42
|
+
numbers = range(5)
|
|
43
|
+
for n in numbers:
|
|
44
|
+
print(n)
|
|
45
|
+
`);
|
|
46
|
+
expect(output).toHaveLength(5);
|
|
47
|
+
expect(output).toEqual(["0", "1", "2", "3", "4"]);
|
|
48
|
+
});
|
|
49
|
+
test("should generate range with start and stop", () => {
|
|
50
|
+
const output = executeCode(`
|
|
51
|
+
numbers = range(2, 5)
|
|
52
|
+
for n in numbers:
|
|
53
|
+
print(n)
|
|
54
|
+
`);
|
|
55
|
+
expect(output).toEqual(["2", "3", "4"]);
|
|
56
|
+
});
|
|
57
|
+
test("should generate range with step", () => {
|
|
58
|
+
const output = executeCode(`
|
|
59
|
+
numbers = range(0, 10, 2)
|
|
60
|
+
for n in numbers:
|
|
61
|
+
print(n)
|
|
62
|
+
`);
|
|
63
|
+
expect(output).toEqual(["0", "2", "4", "6", "8"]);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe("sum() function", () => {
|
|
67
|
+
test("should sum array of numbers", () => {
|
|
68
|
+
const output = executeCode(`
|
|
69
|
+
numbers = [1, 2, 3, 4, 5]
|
|
70
|
+
total = sum(numbers)
|
|
71
|
+
print(total)
|
|
72
|
+
`);
|
|
73
|
+
expect(output).toContain("15");
|
|
74
|
+
});
|
|
75
|
+
test("should sum range", () => {
|
|
76
|
+
const output = executeCode(`
|
|
77
|
+
total = sum(range(1, 11))
|
|
78
|
+
print(total)
|
|
79
|
+
`);
|
|
80
|
+
expect(output).toContain("55");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe("len() function", () => {
|
|
84
|
+
test("should return length of array", () => {
|
|
85
|
+
const output = executeCode(`
|
|
86
|
+
arr = [1, 2, 3, 4, 5]
|
|
87
|
+
print(len(arr))
|
|
88
|
+
`);
|
|
89
|
+
expect(output).toContain("5");
|
|
90
|
+
});
|
|
91
|
+
test("should return length of string", () => {
|
|
92
|
+
const output = executeCode(`
|
|
93
|
+
text = "Hello"
|
|
94
|
+
print(len(text))
|
|
95
|
+
`);
|
|
96
|
+
expect(output).toContain("5");
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
describe("min() and max() functions", () => {
|
|
100
|
+
test("should find minimum", () => {
|
|
101
|
+
const output = executeCode(`
|
|
102
|
+
numbers = [5, 2, 8, 1, 9]
|
|
103
|
+
print(min(numbers))
|
|
104
|
+
`);
|
|
105
|
+
expect(output).toContain("1");
|
|
106
|
+
});
|
|
107
|
+
test("should find maximum", () => {
|
|
108
|
+
const output = executeCode(`
|
|
109
|
+
numbers = [5, 2, 8, 1, 9]
|
|
110
|
+
print(max(numbers))
|
|
111
|
+
`);
|
|
112
|
+
expect(output).toContain("9");
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
describe("sorted() function", () => {
|
|
116
|
+
test("should sort array ascending", () => {
|
|
117
|
+
const output = executeCode(`
|
|
118
|
+
numbers = [5, 2, 8, 1, 9]
|
|
119
|
+
sorted_nums = sorted(numbers)
|
|
120
|
+
print(sorted_nums)
|
|
121
|
+
`);
|
|
122
|
+
expect(output[0]).toContain("1");
|
|
123
|
+
expect(output[0]).toContain("9");
|
|
124
|
+
});
|
|
125
|
+
test("should sort array descending", () => {
|
|
126
|
+
const output = executeCode(`
|
|
127
|
+
numbers = [5, 2, 8, 1, 9]
|
|
128
|
+
sorted_nums = sorted(numbers, True)
|
|
129
|
+
print(sorted_nums[0])
|
|
130
|
+
`);
|
|
131
|
+
expect(output[0]).toContain("9");
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe("Type conversion functions", () => {
|
|
135
|
+
test("str() should convert to string", () => {
|
|
136
|
+
const output = executeCode(`
|
|
137
|
+
num = 42
|
|
138
|
+
text = str(num)
|
|
139
|
+
print(text)
|
|
140
|
+
`);
|
|
141
|
+
expect(output).toContain("42");
|
|
142
|
+
});
|
|
143
|
+
test("int() should convert to integer", () => {
|
|
144
|
+
const output = executeCode(`
|
|
145
|
+
text = "42"
|
|
146
|
+
num = int(text)
|
|
147
|
+
print(num)
|
|
148
|
+
`);
|
|
149
|
+
expect(output).toContain("42");
|
|
150
|
+
});
|
|
151
|
+
test("float() should convert to float", () => {
|
|
152
|
+
const output = executeCode(`
|
|
153
|
+
text = "3.14"
|
|
154
|
+
num = float(text)
|
|
155
|
+
print(num)
|
|
156
|
+
`);
|
|
157
|
+
expect(output).toContain("3.14");
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe("List comprehensions", () => {
|
|
161
|
+
test("should execute simple list comprehension", () => {
|
|
162
|
+
const output = executeCode(`
|
|
163
|
+
numbers = [x * 2 for x in range(5)]
|
|
164
|
+
print(numbers)
|
|
165
|
+
`);
|
|
166
|
+
expect(output[0]).toContain("0");
|
|
167
|
+
expect(output[0]).toContain("8");
|
|
168
|
+
});
|
|
169
|
+
test("should execute nested list comprehension", () => {
|
|
170
|
+
const output = executeCode(`
|
|
171
|
+
squares = [x * x for x in range(1, 6)]
|
|
172
|
+
for s in squares:
|
|
173
|
+
print(s)
|
|
174
|
+
`);
|
|
175
|
+
expect(output).toEqual(["1", "4", "9", "16", "25"]);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
describe("Functions", () => {
|
|
179
|
+
test("should define and call function", () => {
|
|
180
|
+
const output = executeCode(`
|
|
181
|
+
def greet(name):
|
|
182
|
+
return "Hello, " + name
|
|
183
|
+
|
|
184
|
+
message = greet("World")
|
|
185
|
+
print(message)
|
|
186
|
+
`);
|
|
187
|
+
expect(output).toContain("Hello, World");
|
|
188
|
+
});
|
|
189
|
+
test("should handle multiple parameters", () => {
|
|
190
|
+
const output = executeCode(`
|
|
191
|
+
def add(a, b):
|
|
192
|
+
return a + b
|
|
193
|
+
|
|
194
|
+
result = add(5, 3)
|
|
195
|
+
print(result)
|
|
196
|
+
`);
|
|
197
|
+
expect(output).toContain("8");
|
|
198
|
+
});
|
|
199
|
+
test("should support recursion", () => {
|
|
200
|
+
const output = executeCode(`
|
|
201
|
+
def factorial(n):
|
|
202
|
+
if n <= 1:
|
|
203
|
+
return 1
|
|
204
|
+
return n * factorial(n - 1)
|
|
205
|
+
|
|
206
|
+
result = factorial(5)
|
|
207
|
+
print(result)
|
|
208
|
+
`);
|
|
209
|
+
expect(output).toContain("120");
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
describe("Control Flow", () => {
|
|
213
|
+
test("should execute if-else", () => {
|
|
214
|
+
const output = executeCode(`
|
|
215
|
+
x = 10
|
|
216
|
+
if x > 5:
|
|
217
|
+
print("big")
|
|
218
|
+
else:
|
|
219
|
+
print("small")
|
|
220
|
+
`);
|
|
221
|
+
expect(output).toContain("big");
|
|
222
|
+
});
|
|
223
|
+
test("should execute for loops", () => {
|
|
224
|
+
const output = executeCode(`
|
|
225
|
+
for i in range(3):
|
|
226
|
+
print(i)
|
|
227
|
+
`);
|
|
228
|
+
expect(output).toEqual(["0", "1", "2"]);
|
|
229
|
+
});
|
|
230
|
+
test("should execute while loops", () => {
|
|
231
|
+
const output = executeCode(`
|
|
232
|
+
x = 0
|
|
233
|
+
while x < 3:
|
|
234
|
+
print(x)
|
|
235
|
+
x = x + 1
|
|
236
|
+
`);
|
|
237
|
+
expect(output).toEqual(["0", "1", "2"]);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
describe("Complex Programs", () => {
|
|
241
|
+
test("should calculate fibonacci", () => {
|
|
242
|
+
const output = executeCode(`
|
|
243
|
+
def fib(n):
|
|
244
|
+
if n <= 1:
|
|
245
|
+
return n
|
|
246
|
+
return fib(n - 1) + fib(n - 2)
|
|
247
|
+
|
|
248
|
+
result = fib(10)
|
|
249
|
+
print(result)
|
|
250
|
+
`);
|
|
251
|
+
expect(output).toContain("55");
|
|
252
|
+
});
|
|
253
|
+
test("should filter even numbers", () => {
|
|
254
|
+
const output = executeCode(`
|
|
255
|
+
numbers = range(10)
|
|
256
|
+
evens = [x for x in numbers if x % 2 == 0]
|
|
257
|
+
print(evens)
|
|
258
|
+
`);
|
|
259
|
+
expect(output[0]).toContain("0");
|
|
260
|
+
expect(output[0]).toContain("8");
|
|
261
|
+
});
|
|
262
|
+
test("should combine multiple operations", () => {
|
|
263
|
+
const output = executeCode(`
|
|
264
|
+
def square(x):
|
|
265
|
+
return x * x
|
|
266
|
+
|
|
267
|
+
numbers = range(1, 6)
|
|
268
|
+
squares = [square(x) for x in numbers]
|
|
269
|
+
total = sum(squares)
|
|
270
|
+
print(total)
|
|
271
|
+
`);
|
|
272
|
+
expect(output).toContain("55");
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { CompileOptions, CompileResult } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Compile with caching support
|
|
4
|
+
*
|
|
5
|
+
* @param source - JPS source code
|
|
6
|
+
* @param options - Compilation options
|
|
7
|
+
* @param cacheKey - Optional cache key (defaults to source hash)
|
|
8
|
+
* @returns Compiled result (from cache if available)
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const result = compileWithCache(source, options, 'my-file.jps');
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function compileWithCache(source: string, options?: CompileOptions, cacheKey?: string): CompileResult;
|
|
16
|
+
/**
|
|
17
|
+
* Clear the compilation cache
|
|
18
|
+
*
|
|
19
|
+
* @param cacheKey - Optional key to clear (clears all if not provided)
|
|
20
|
+
*/
|
|
21
|
+
export declare function clearCache(cacheKey?: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* Get cache statistics
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCacheStats(): {
|
|
26
|
+
size: number;
|
|
27
|
+
entries: string[];
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Watch a file for changes and recompile
|
|
31
|
+
*
|
|
32
|
+
* @param filePath - Path to JPS file to watch
|
|
33
|
+
* @param options - Compilation options
|
|
34
|
+
* @param callback - Function called on each compilation
|
|
35
|
+
* @returns Function to stop watching
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const stopWatching = watch('script.jps', {}, (result, error) => {
|
|
40
|
+
* if (error) console.error(error);
|
|
41
|
+
* else console.log(result.code);
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // Later: stop watching
|
|
45
|
+
* stopWatching();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function watch(filePath: string, options: CompileOptions | undefined, callback: (result: CompileResult | null, error: Error | null) => void): () => void;
|
|
49
|
+
/**
|
|
50
|
+
* Compile a file and write output to disk
|
|
51
|
+
*
|
|
52
|
+
* @param inputPath - Input JPS file path
|
|
53
|
+
* @param outputPath - Output JS file path (optional, defaults to .js extension)
|
|
54
|
+
* @param options - Compilation options
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* await compileFile('script.jps', 'script.js', {
|
|
59
|
+
* format: 'esm',
|
|
60
|
+
* runtimeMode: 'external'
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function compileFile(inputPath: string, outputPath?: string, options?: CompileOptions): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Compile multiple files
|
|
67
|
+
*
|
|
68
|
+
* @param files - Array of file paths or {input, output} objects
|
|
69
|
+
* @param options - Compilation options
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* await compileFiles([
|
|
74
|
+
* { input: 'src/main.jps', output: 'dist/main.js' },
|
|
75
|
+
* { input: 'src/util.jps', output: 'dist/util.js' }
|
|
76
|
+
* ], { format: 'esm' });
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function compileFiles(files: Array<string | {
|
|
80
|
+
input: string;
|
|
81
|
+
output?: string;
|
|
82
|
+
}>, options?: CompileOptions): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Batch compile with progress tracking
|
|
85
|
+
*
|
|
86
|
+
* @param files - Array of file paths
|
|
87
|
+
* @param options - Compilation options
|
|
88
|
+
* @param onProgress - Progress callback
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* await batchCompile(
|
|
93
|
+
* ['file1.jps', 'file2.jps', 'file3.jps'],
|
|
94
|
+
* { format: 'esm' },
|
|
95
|
+
* (completed, total) => console.log(`${completed}/${total}`)
|
|
96
|
+
* );
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare function batchCompile(files: string[], options?: CompileOptions, onProgress?: (completed: number, total: number) => void): Promise<void>;
|
|
100
|
+
//# sourceMappingURL=advanced.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advanced.d.ts","sourceRoot":"","sources":["../../src/api/advanced.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AASpE;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,MAAM,GAChB,aAAa,CAkBf;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAMlD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAKnE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,KAAK,CACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,YAAK,EAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,GACpE,MAAM,IAAI,CA2BZ;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACzD,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAUf;AAeD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,GAAE,cAAmB,EAC5B,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACtD,OAAO,CAAC,IAAI,CAAC,CAWf"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { compile } from "./index.js";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
/**
|
|
5
|
+
* Cache for compiled results
|
|
6
|
+
*/
|
|
7
|
+
const compilationCache = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Compile with caching support
|
|
10
|
+
*
|
|
11
|
+
* @param source - JPS source code
|
|
12
|
+
* @param options - Compilation options
|
|
13
|
+
* @param cacheKey - Optional cache key (defaults to source hash)
|
|
14
|
+
* @returns Compiled result (from cache if available)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const result = compileWithCache(source, options, 'my-file.jps');
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function compileWithCache(source, options = {}, cacheKey) {
|
|
22
|
+
const key = cacheKey || hashSource(source);
|
|
23
|
+
const cached = compilationCache.get(key);
|
|
24
|
+
// Check if cache is valid
|
|
25
|
+
if (cached && cached.source === source) {
|
|
26
|
+
return cached.result;
|
|
27
|
+
}
|
|
28
|
+
// Compile and cache
|
|
29
|
+
const result = compile(source, options);
|
|
30
|
+
compilationCache.set(key, {
|
|
31
|
+
source,
|
|
32
|
+
result,
|
|
33
|
+
timestamp: Date.now()
|
|
34
|
+
});
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Clear the compilation cache
|
|
39
|
+
*
|
|
40
|
+
* @param cacheKey - Optional key to clear (clears all if not provided)
|
|
41
|
+
*/
|
|
42
|
+
export function clearCache(cacheKey) {
|
|
43
|
+
if (cacheKey) {
|
|
44
|
+
compilationCache.delete(cacheKey);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
compilationCache.clear();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get cache statistics
|
|
52
|
+
*/
|
|
53
|
+
export function getCacheStats() {
|
|
54
|
+
return {
|
|
55
|
+
size: compilationCache.size,
|
|
56
|
+
entries: Array.from(compilationCache.keys())
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Watch a file for changes and recompile
|
|
61
|
+
*
|
|
62
|
+
* @param filePath - Path to JPS file to watch
|
|
63
|
+
* @param options - Compilation options
|
|
64
|
+
* @param callback - Function called on each compilation
|
|
65
|
+
* @returns Function to stop watching
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const stopWatching = watch('script.jps', {}, (result, error) => {
|
|
70
|
+
* if (error) console.error(error);
|
|
71
|
+
* else console.log(result.code);
|
|
72
|
+
* });
|
|
73
|
+
*
|
|
74
|
+
* // Later: stop watching
|
|
75
|
+
* stopWatching();
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export function watch(filePath, options = {}, callback) {
|
|
79
|
+
const absolutePath = path.resolve(filePath);
|
|
80
|
+
// Initial compilation
|
|
81
|
+
try {
|
|
82
|
+
const source = fs.readFileSync(absolutePath, 'utf-8');
|
|
83
|
+
const result = compile(source, options);
|
|
84
|
+
callback(result, null);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
callback(null, error);
|
|
88
|
+
}
|
|
89
|
+
// Watch for changes
|
|
90
|
+
const watcher = fs.watchFile(absolutePath, { interval: 1000 }, () => {
|
|
91
|
+
try {
|
|
92
|
+
const source = fs.readFileSync(absolutePath, 'utf-8');
|
|
93
|
+
const result = compile(source, options);
|
|
94
|
+
callback(result, null);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
callback(null, error);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
// Return stop function
|
|
101
|
+
return () => {
|
|
102
|
+
fs.unwatchFile(absolutePath);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Compile a file and write output to disk
|
|
107
|
+
*
|
|
108
|
+
* @param inputPath - Input JPS file path
|
|
109
|
+
* @param outputPath - Output JS file path (optional, defaults to .js extension)
|
|
110
|
+
* @param options - Compilation options
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* await compileFile('script.jps', 'script.js', {
|
|
115
|
+
* format: 'esm',
|
|
116
|
+
* runtimeMode: 'external'
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export async function compileFile(inputPath, outputPath, options = {}) {
|
|
121
|
+
const source = await fs.promises.readFile(inputPath, 'utf-8');
|
|
122
|
+
const result = compile(source, options);
|
|
123
|
+
const output = outputPath || inputPath.replace(/\.jps$/, '.js');
|
|
124
|
+
await fs.promises.writeFile(output, result.code, 'utf-8');
|
|
125
|
+
// Write source map if enabled
|
|
126
|
+
if (result.map) {
|
|
127
|
+
await fs.promises.writeFile(output + '.map', result.map, 'utf-8');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Compile multiple files
|
|
132
|
+
*
|
|
133
|
+
* @param files - Array of file paths or {input, output} objects
|
|
134
|
+
* @param options - Compilation options
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* await compileFiles([
|
|
139
|
+
* { input: 'src/main.jps', output: 'dist/main.js' },
|
|
140
|
+
* { input: 'src/util.jps', output: 'dist/util.js' }
|
|
141
|
+
* ], { format: 'esm' });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export async function compileFiles(files, options = {}) {
|
|
145
|
+
await Promise.all(files.map(file => {
|
|
146
|
+
if (typeof file === 'string') {
|
|
147
|
+
return compileFile(file, undefined, options);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
return compileFile(file.input, file.output, options);
|
|
151
|
+
}
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Simple hash function for caching
|
|
156
|
+
*/
|
|
157
|
+
function hashSource(source) {
|
|
158
|
+
let hash = 0;
|
|
159
|
+
for (let i = 0; i < source.length; i++) {
|
|
160
|
+
const char = source.charCodeAt(i);
|
|
161
|
+
hash = ((hash << 5) - hash) + char;
|
|
162
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
163
|
+
}
|
|
164
|
+
return hash.toString(36);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Batch compile with progress tracking
|
|
168
|
+
*
|
|
169
|
+
* @param files - Array of file paths
|
|
170
|
+
* @param options - Compilation options
|
|
171
|
+
* @param onProgress - Progress callback
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* await batchCompile(
|
|
176
|
+
* ['file1.jps', 'file2.jps', 'file3.jps'],
|
|
177
|
+
* { format: 'esm' },
|
|
178
|
+
* (completed, total) => console.log(`${completed}/${total}`)
|
|
179
|
+
* );
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export async function batchCompile(files, options = {}, onProgress) {
|
|
183
|
+
let completed = 0;
|
|
184
|
+
const total = files.length;
|
|
185
|
+
for (const file of files) {
|
|
186
|
+
await compileFile(file, undefined, options);
|
|
187
|
+
completed++;
|
|
188
|
+
if (onProgress) {
|
|
189
|
+
onProgress(completed, total);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { CompileOptions } from "./index.js";
|
|
2
|
+
export interface BenchmarkResult {
|
|
3
|
+
totalTime: number;
|
|
4
|
+
averageTime: number;
|
|
5
|
+
minTime: number;
|
|
6
|
+
maxTime: number;
|
|
7
|
+
iterations: number;
|
|
8
|
+
throughput: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Benchmark compilation performance
|
|
12
|
+
*
|
|
13
|
+
* @param source - JPS source code to compile
|
|
14
|
+
* @param options - Compilation options
|
|
15
|
+
* @param iterations - Number of iterations (default: 100)
|
|
16
|
+
* @returns Benchmark results
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const result = benchmark('print("Hello")', {}, 1000);
|
|
21
|
+
* console.log(`Average: ${result.averageTime}ms`);
|
|
22
|
+
* console.log(`Throughput: ${result.throughput} ops/sec`);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function benchmark(source: string, options?: CompileOptions, iterations?: number): BenchmarkResult;
|
|
26
|
+
/**
|
|
27
|
+
* Compare performance across different options
|
|
28
|
+
*
|
|
29
|
+
* @param source - JPS source code
|
|
30
|
+
* @param optionsArray - Array of options to compare
|
|
31
|
+
* @param iterations - Number of iterations per test
|
|
32
|
+
* @returns Array of benchmark results
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const results = comparePerformance(
|
|
37
|
+
* 'print("test")',
|
|
38
|
+
* [
|
|
39
|
+
* { format: 'esm', runtimeMode: 'inline' },
|
|
40
|
+
* { format: 'esm', runtimeMode: 'external' },
|
|
41
|
+
* { format: 'iife', runtimeMode: 'inline' }
|
|
42
|
+
* ]
|
|
43
|
+
* );
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function comparePerformance(source: string, optionsArray: CompileOptions[], iterations?: number): Array<{
|
|
47
|
+
options: CompileOptions;
|
|
48
|
+
result: BenchmarkResult;
|
|
49
|
+
}>;
|
|
50
|
+
/**
|
|
51
|
+
* Profile compilation stages
|
|
52
|
+
*
|
|
53
|
+
* @param source - JPS source code
|
|
54
|
+
* @param options - Compilation options
|
|
55
|
+
* @returns Timing for each compilation stage
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const profile = profileCompilation('def foo(): return 42');
|
|
60
|
+
* console.log(profile);
|
|
61
|
+
* // {
|
|
62
|
+
* // tokenize: 0.5ms,
|
|
63
|
+
* // parse: 1.2ms,
|
|
64
|
+
* // transform: 0.3ms,
|
|
65
|
+
* // generate: 0.8ms,
|
|
66
|
+
* // total: 2.8ms
|
|
67
|
+
* // }
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function profileCompilation(source: string, options?: CompileOptions): Record<string, number>;
|
|
71
|
+
/**
|
|
72
|
+
* Memory usage profiling
|
|
73
|
+
*
|
|
74
|
+
* @param source - JPS source code
|
|
75
|
+
* @param options - Compilation options
|
|
76
|
+
* @returns Memory usage information (if available)
|
|
77
|
+
*/
|
|
78
|
+
export declare function profileMemory(source: string, options?: CompileOptions): {
|
|
79
|
+
before: number;
|
|
80
|
+
after: number;
|
|
81
|
+
delta: number;
|
|
82
|
+
} | null;
|
|
83
|
+
/**
|
|
84
|
+
* Format benchmark results for display
|
|
85
|
+
*/
|
|
86
|
+
export declare function formatBenchmarkResult(result: BenchmarkResult): string;
|
|
87
|
+
//# sourceMappingURL=benchmark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../../src/api/benchmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,cAAc,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,EAC5B,UAAU,GAAE,MAAY,GACvB,eAAe,CA8BjB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAAE,EAC9B,UAAU,GAAE,MAAY,GACvB,KAAK,CAAC;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,eAAe,CAAA;CAAE,CAAC,CAK7D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgCxB;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,cAAmB,GAC3B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAezD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CASrE"}
|