redscript-mc 2.3.0 → 2.4.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/CHANGELOG.md +11 -0
- package/dist/src/__tests__/array-dynamic.test.d.ts +12 -0
- package/dist/src/__tests__/array-dynamic.test.js +131 -0
- package/dist/src/__tests__/array-write.test.d.ts +11 -0
- package/dist/src/__tests__/array-write.test.js +149 -0
- package/dist/src/ast/types.d.ts +7 -0
- package/dist/src/emit/modules.js +5 -0
- package/dist/src/hir/lower.js +29 -0
- package/dist/src/hir/monomorphize.js +2 -0
- package/dist/src/hir/types.d.ts +9 -2
- package/dist/src/lir/lower.js +131 -0
- package/dist/src/mir/lower.js +73 -3
- package/dist/src/mir/macro.js +5 -0
- package/dist/src/mir/types.d.ts +12 -0
- package/dist/src/mir/verify.js +7 -0
- package/dist/src/optimizer/copy_prop.js +5 -0
- package/dist/src/optimizer/coroutine.js +12 -0
- package/dist/src/optimizer/dce.js +9 -0
- package/dist/src/optimizer/unroll.js +3 -0
- package/dist/src/parser/index.js +5 -0
- package/dist/src/typechecker/index.js +5 -0
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/package.json +1 -1
- package/src/__tests__/array-dynamic.test.ts +147 -0
- package/src/__tests__/array-write.test.ts +169 -0
- package/src/ast/types.ts +1 -0
- package/src/emit/modules.ts +5 -0
- package/src/hir/lower.ts +30 -0
- package/src/hir/monomorphize.ts +2 -0
- package/src/hir/types.ts +3 -1
- package/src/lir/lower.ts +151 -0
- package/src/mir/lower.ts +75 -3
- package/src/mir/macro.ts +5 -0
- package/src/mir/types.ts +2 -0
- package/src/mir/verify.ts +7 -0
- package/src/optimizer/copy_prop.ts +5 -0
- package/src/optimizer/coroutine.ts +9 -0
- package/src/optimizer/dce.ts +6 -0
- package/src/optimizer/unroll.ts +3 -0
- package/src/parser/index.ts +9 -0
- package/src/stdlib/list.mcrs +43 -72
- package/src/stdlib/math.mcrs +137 -0
- package/src/stdlib/timer.mcrs +32 -0
- package/src/typechecker/index.ts +6 -0
package/src/stdlib/math.mcrs
CHANGED
|
@@ -390,3 +390,140 @@ fn exp_fx(x: int): int {
|
|
|
390
390
|
}
|
|
391
391
|
return er;
|
|
392
392
|
}
|
|
393
|
+
|
|
394
|
+
// ─── Cubic root ──────────────────────────────────────────────────────────────
|
|
395
|
+
|
|
396
|
+
// cbrt_fx(x): integer cube root, returns floor(cbrt(x)).
|
|
397
|
+
// Uses Newton's method: g_next = (2*g + x/g²) / 3
|
|
398
|
+
// cbrt_fx(1000) = 10 (∛1000=10), cbrt_fx(27) = 3, cbrt_fx(8) = 2
|
|
399
|
+
fn cbrt_fx(x: int): int {
|
|
400
|
+
if (x <= 0) { return 0; }
|
|
401
|
+
let g: int = x / 3;
|
|
402
|
+
if (g <= 0) { g = 1; }
|
|
403
|
+
let i: int = 0;
|
|
404
|
+
while (i < 20) {
|
|
405
|
+
let g2: int = g * g;
|
|
406
|
+
if (g2 <= 0) { g2 = 1; }
|
|
407
|
+
let next: int = (2 * g + x / g2) / 3;
|
|
408
|
+
if (next == g) { i = 20; }
|
|
409
|
+
g = next;
|
|
410
|
+
if (g <= 0) { g = 1; }
|
|
411
|
+
i = i + 1;
|
|
412
|
+
}
|
|
413
|
+
return g;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// ─── Combinatorics ───────────────────────────────────────────────────────────
|
|
417
|
+
|
|
418
|
+
// factorial(n): n! for n ∈ [0, 12] (13! exceeds int32)
|
|
419
|
+
fn factorial(n: int): int {
|
|
420
|
+
if (n <= 1) { return 1; }
|
|
421
|
+
let r: int = 1;
|
|
422
|
+
let i: int = 2;
|
|
423
|
+
while (i <= n) { r = r * i; i = i + 1; }
|
|
424
|
+
return r;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// combinations(n, k): C(n,k) = n! / (k! * (n-k)!) for n ≤ 20, k ≤ n
|
|
428
|
+
// Uses multiplicative formula to avoid overflow: C(n,k) = ∏ (n-i)/(i+1) for i=0..k-1
|
|
429
|
+
fn combinations(n: int, k: int): int {
|
|
430
|
+
if (k <= 0) { return 1; }
|
|
431
|
+
if (k > n) { return 0; }
|
|
432
|
+
// Use smaller k for efficiency: C(n,k) == C(n, n-k)
|
|
433
|
+
let kk: int = k;
|
|
434
|
+
if (n - k < kk) { kk = n - k; }
|
|
435
|
+
let r: int = 1;
|
|
436
|
+
let i: int = 0;
|
|
437
|
+
while (i < kk) {
|
|
438
|
+
r = r * (n - i) / (i + 1);
|
|
439
|
+
i = i + 1;
|
|
440
|
+
}
|
|
441
|
+
return r;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ─── Logarithm ───────────────────────────────────────────────────────────────
|
|
445
|
+
|
|
446
|
+
// log10_fx(x): log base 10, fixed-point ×10000
|
|
447
|
+
// log10(x) = ln(x) / ln(10) ≈ ln(x) / 23026
|
|
448
|
+
fn log10_fx(x: int): int {
|
|
449
|
+
return ln(x) * 10000 / 23026;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// log2_fx(x): log base 2, fixed-point ×10000
|
|
453
|
+
// log2(x) = ln(x) / ln(2) ≈ ln(x) / 6931
|
|
454
|
+
fn log2_fx(x: int): int {
|
|
455
|
+
return ln(x) * 10000 / 6931;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// loga_fx(base_fx, x): log_base(x), fixed-point ×10000
|
|
459
|
+
// base_fx and x are both ×10000
|
|
460
|
+
// loga_fx(20000, 40000) ≈ 10000 (log_2(4) = 2, but ×10000 → 20000... wait)
|
|
461
|
+
// Actually: log_b(x) = ln(x) / ln(b), both ×10000, so result = ln(x)/ln(b) × 10000
|
|
462
|
+
fn loga_fx(base_fx: int, x: int): int {
|
|
463
|
+
let lb: int = ln(base_fx);
|
|
464
|
+
if (lb == 0) { return 0; }
|
|
465
|
+
return ln(x) * 10000 / lb;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// ─── Gamma function approximation ────────────────────────────────────────────
|
|
469
|
+
|
|
470
|
+
// gamma_int(n): Gamma(n) = (n-1)! for positive integers
|
|
471
|
+
fn gamma_int(n: int): int {
|
|
472
|
+
if (n <= 1) { return 1; }
|
|
473
|
+
return factorial(n - 1);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// ─── Linear equation solvers ─────────────────────────────────────────────────
|
|
477
|
+
|
|
478
|
+
// solve2x2_x(a, b, e, c, d, f): solve ax + by = e, cx + dy = f → return x × 10000
|
|
479
|
+
// Uses Cramer's rule. Returns 0 if determinant = 0 (singular system).
|
|
480
|
+
// a, b, c, d, e, f are integers (not fixed-point); result is fixed-point ×10000.
|
|
481
|
+
fn solve2x2_x(a: int, b: int, e: int, c: int, d: int, f: int): int {
|
|
482
|
+
let det: int = a * d - b * c;
|
|
483
|
+
if (det == 0) { return 0; }
|
|
484
|
+
return (e * d - b * f) * 10000 / det;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// solve2x2_y(a, b, e, c, d, f): same system, return y × 10000
|
|
488
|
+
fn solve2x2_y(a: int, b: int, e: int, c: int, d: int, f: int): int {
|
|
489
|
+
let det: int = a * d - b * c;
|
|
490
|
+
if (det == 0) { return 0; }
|
|
491
|
+
return (a * f - e * c) * 10000 / det;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// ─── Quadratic equation ───────────────────────────────────────────────────────
|
|
495
|
+
|
|
496
|
+
// quadratic_disc(a, b, c): discriminant b² - 4ac
|
|
497
|
+
// Returns > 0 (two real roots), 0 (one root), < 0 (no real roots)
|
|
498
|
+
fn quadratic_disc(a: int, b: int, c: int): int {
|
|
499
|
+
return b * b - 4 * a * c;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// quadratic_x1(a, b, c): larger root × 10000 using integer sqrt
|
|
503
|
+
// Only valid when discriminant >= 0
|
|
504
|
+
fn quadratic_x1(a: int, b: int, c: int): int {
|
|
505
|
+
if (a == 0) { return 0; }
|
|
506
|
+
let disc: int = b * b - 4 * a * c;
|
|
507
|
+
if (disc < 0) { return 0; }
|
|
508
|
+
let sq: int = isqrt(disc);
|
|
509
|
+
return (0 - b + sq) * 10000 / (2 * a);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// quadratic_x2(a, b, c): smaller root × 10000
|
|
513
|
+
fn quadratic_x2(a: int, b: int, c: int): int {
|
|
514
|
+
if (a == 0) { return 0; }
|
|
515
|
+
let disc: int = b * b - 4 * a * c;
|
|
516
|
+
if (disc < 0) { return 0; }
|
|
517
|
+
let sq: int = isqrt(disc);
|
|
518
|
+
return (0 - b - sq) * 10000 / (2 * a);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// ─── Fixed-point comparison helpers ──────────────────────────────────────────
|
|
522
|
+
|
|
523
|
+
// approx_eq(a, b, eps): 1 if |a - b| <= eps
|
|
524
|
+
fn approx_eq(a: int, b: int, eps: int): int {
|
|
525
|
+
let d: int = a - b;
|
|
526
|
+
if (d < 0) { d = 0 - d; }
|
|
527
|
+
if (d <= eps) { return 1; }
|
|
528
|
+
return 0;
|
|
529
|
+
}
|
package/src/stdlib/timer.mcrs
CHANGED
|
@@ -75,3 +75,35 @@ impl Timer {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
// ─── Tick-based stopwatch ─────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
// tick_to_seconds(ticks): convert MC ticks to seconds (20 ticks = 1 second)
|
|
82
|
+
fn tick_to_seconds(ticks: int): int {
|
|
83
|
+
return ticks / 20;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// tick_to_ms(ticks): convert ticks to milliseconds
|
|
87
|
+
fn tick_to_ms(ticks: int): int {
|
|
88
|
+
return ticks * 50;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// seconds_to_ticks(s): convert seconds to ticks
|
|
92
|
+
fn seconds_to_ticks(s: int): int {
|
|
93
|
+
return s * 20;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// format_time_s(ticks): ticks → seconds component (mod 60)
|
|
97
|
+
fn format_time_s(ticks: int): int {
|
|
98
|
+
return (ticks / 20) % 60;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// format_time_m(ticks): ticks → minutes component
|
|
102
|
+
fn format_time_m(ticks: int): int {
|
|
103
|
+
return (ticks / 1200) % 60;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// format_time_h(ticks): ticks → hours component
|
|
107
|
+
fn format_time_h(ticks: int): int {
|
|
108
|
+
return ticks / 72000;
|
|
109
|
+
}
|
package/src/typechecker/index.ts
CHANGED
|
@@ -619,6 +619,12 @@ export class TypeChecker {
|
|
|
619
619
|
this.checkExpr(expr.value)
|
|
620
620
|
break
|
|
621
621
|
|
|
622
|
+
case 'index_assign':
|
|
623
|
+
this.checkExpr(expr.obj)
|
|
624
|
+
this.checkExpr(expr.index)
|
|
625
|
+
this.checkExpr(expr.value)
|
|
626
|
+
break
|
|
627
|
+
|
|
622
628
|
case 'index':
|
|
623
629
|
this.checkExpr(expr.obj)
|
|
624
630
|
this.checkExpr(expr.index)
|