redscript-mc 2.2.1 → 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 +31 -0
- package/README.md +18 -2
- 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/__tests__/tuner/engine.test.d.ts +4 -0
- package/dist/src/__tests__/tuner/engine.test.js +232 -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/tuner/adapters/ln-polynomial.d.ts +23 -0
- package/dist/src/tuner/adapters/ln-polynomial.js +142 -0
- package/dist/src/tuner/adapters/sqrt-newton.d.ts +28 -0
- package/dist/src/tuner/adapters/sqrt-newton.js +125 -0
- package/dist/src/tuner/cli.d.ts +5 -0
- package/dist/src/tuner/cli.js +168 -0
- package/dist/src/tuner/engine.d.ts +17 -0
- package/dist/src/tuner/engine.js +215 -0
- package/dist/src/tuner/metrics.d.ts +15 -0
- package/dist/src/tuner/metrics.js +51 -0
- package/dist/src/tuner/simulator.d.ts +35 -0
- package/dist/src/tuner/simulator.js +78 -0
- package/dist/src/tuner/types.d.ts +32 -0
- package/dist/src/tuner/types.js +6 -0
- package/dist/src/typechecker/index.js +5 -0
- package/docs/STDLIB_ROADMAP.md +142 -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/__tests__/tuner/engine.test.ts +260 -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/bigint.mcrs +155 -192
- package/src/stdlib/bits.mcrs +158 -0
- package/src/stdlib/color.mcrs +160 -0
- package/src/stdlib/geometry.mcrs +124 -0
- package/src/stdlib/list.mcrs +96 -0
- package/src/stdlib/math.mcrs +227 -0
- package/src/stdlib/math_hp.mcrs +65 -0
- package/src/stdlib/random.mcrs +67 -0
- package/src/stdlib/signal.mcrs +112 -0
- package/src/stdlib/timer.mcrs +32 -0
- package/src/stdlib/vec.mcrs +27 -0
- package/src/tuner/adapters/ln-polynomial.ts +147 -0
- package/src/tuner/adapters/sqrt-newton.ts +135 -0
- package/src/tuner/cli.ts +158 -0
- package/src/tuner/engine.ts +272 -0
- package/src/tuner/metrics.ts +66 -0
- package/src/tuner/simulator.ts +69 -0
- package/src/tuner/types.ts +44 -0
- package/src/typechecker/index.ts +6 -0
- package/docs/ARCHITECTURE.zh.md +0 -1088
- package/docs/COMPILATION_STATS.md +0 -142
- package/docs/IMPLEMENTATION_GUIDE.md +0 -512
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Nelder-Mead simplex optimization engine for hyperparameter tuning.
|
|
4
|
+
* Suitable for continuous parameter spaces without gradient information.
|
|
5
|
+
* Supports mixed-integer parameters.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.search = search;
|
|
9
|
+
exports.searchSA = searchSA;
|
|
10
|
+
const metrics_1 = require("./metrics");
|
|
11
|
+
/**
|
|
12
|
+
* Apply integer constraints to parameters.
|
|
13
|
+
*/
|
|
14
|
+
function applyIntegerConstraints(coords, specs) {
|
|
15
|
+
return coords.map((v, i) => {
|
|
16
|
+
const spec = specs[i];
|
|
17
|
+
// Clamp to range
|
|
18
|
+
const clamped = Math.max(spec.range[0], Math.min(spec.range[1], v));
|
|
19
|
+
return spec.integer ? Math.round(clamped) : clamped;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Convert coordinate array to params record.
|
|
24
|
+
*/
|
|
25
|
+
function coordsToParams(coords, specs) {
|
|
26
|
+
const params = {};
|
|
27
|
+
for (let i = 0; i < specs.length; i++) {
|
|
28
|
+
params[specs[i].name] = coords[i];
|
|
29
|
+
}
|
|
30
|
+
return params;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Evaluate a point using the adapter.
|
|
34
|
+
*/
|
|
35
|
+
function scorePoint(coords, specs, adapter) {
|
|
36
|
+
const constrained = applyIntegerConstraints(coords, specs);
|
|
37
|
+
const params = coordsToParams(constrained, specs);
|
|
38
|
+
const metrics = (0, metrics_1.evaluate)(adapter, params);
|
|
39
|
+
return metrics.maxError;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run Nelder-Mead optimization.
|
|
43
|
+
*/
|
|
44
|
+
function search(adapter, budget = 10000, onProgress) {
|
|
45
|
+
const specs = adapter.params;
|
|
46
|
+
const n = specs.length;
|
|
47
|
+
if (n === 0) {
|
|
48
|
+
// No params to optimize
|
|
49
|
+
const params = coordsToParams([], specs);
|
|
50
|
+
const metrics = (0, metrics_1.evaluate)(adapter, params);
|
|
51
|
+
return {
|
|
52
|
+
params,
|
|
53
|
+
maxError: metrics.maxError,
|
|
54
|
+
mae: metrics.mae,
|
|
55
|
+
rmse: metrics.rmse,
|
|
56
|
+
budgetUsed: 0,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Nelder-Mead parameters
|
|
60
|
+
const alpha = 1.0; // reflection
|
|
61
|
+
const gamma = 2.0; // expansion
|
|
62
|
+
const rho = 0.5; // contraction
|
|
63
|
+
const sigma = 0.5; // shrink
|
|
64
|
+
// Initialize simplex with n+1 points
|
|
65
|
+
const simplex = [];
|
|
66
|
+
// Start point: midpoint of each parameter range
|
|
67
|
+
const startCoords = specs.map(s => (s.range[0] + s.range[1]) / 2);
|
|
68
|
+
simplex.push({
|
|
69
|
+
coords: startCoords,
|
|
70
|
+
score: scorePoint(startCoords, specs, adapter),
|
|
71
|
+
});
|
|
72
|
+
// Generate remaining n points by perturbing each dimension
|
|
73
|
+
for (let i = 0; i < n; i++) {
|
|
74
|
+
const coords = [...startCoords];
|
|
75
|
+
const span = specs[i].range[1] - specs[i].range[0];
|
|
76
|
+
// Perturb by 20% of the range
|
|
77
|
+
coords[i] = startCoords[i] + span * 0.2;
|
|
78
|
+
simplex.push({
|
|
79
|
+
coords,
|
|
80
|
+
score: scorePoint(coords, specs, adapter),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
let iteration = 0;
|
|
84
|
+
while (iteration < budget) {
|
|
85
|
+
// Sort simplex by score (ascending = better)
|
|
86
|
+
simplex.sort((a, b) => a.score - b.score);
|
|
87
|
+
const best = simplex[0];
|
|
88
|
+
const worst = simplex[n];
|
|
89
|
+
const secondWorst = simplex[n - 1];
|
|
90
|
+
if (onProgress && iteration % 100 === 0) {
|
|
91
|
+
onProgress(iteration, best.score);
|
|
92
|
+
}
|
|
93
|
+
// Check convergence: if all scores are the same, we're stuck
|
|
94
|
+
if (simplex[n].score - simplex[0].score < 1e-15 &&
|
|
95
|
+
iteration > 100) {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
// Compute centroid of all but worst
|
|
99
|
+
const centroid = new Array(n).fill(0);
|
|
100
|
+
for (let i = 0; i < n; i++) {
|
|
101
|
+
for (let j = 0; j < n; j++) {
|
|
102
|
+
centroid[j] += simplex[i].coords[j] / n;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Reflection
|
|
106
|
+
const reflected = centroid.map((c, j) => c + alpha * (c - worst.coords[j]));
|
|
107
|
+
const reflectedScore = scorePoint(reflected, specs, adapter);
|
|
108
|
+
iteration++;
|
|
109
|
+
if (reflectedScore < best.score) {
|
|
110
|
+
// Expansion
|
|
111
|
+
const expanded = centroid.map((c, j) => c + gamma * (reflected[j] - c));
|
|
112
|
+
const expandedScore = scorePoint(expanded, specs, adapter);
|
|
113
|
+
iteration++;
|
|
114
|
+
if (expandedScore < reflectedScore) {
|
|
115
|
+
simplex[n] = { coords: expanded, score: expandedScore };
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
simplex[n] = { coords: reflected, score: reflectedScore };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (reflectedScore < secondWorst.score) {
|
|
122
|
+
simplex[n] = { coords: reflected, score: reflectedScore };
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Contraction
|
|
126
|
+
const useReflected = reflectedScore < worst.score;
|
|
127
|
+
const contractionBase = useReflected ? reflected : worst.coords;
|
|
128
|
+
const contracted = centroid.map((c, j) => c + rho * (contractionBase[j] - c));
|
|
129
|
+
const contractedScore = scorePoint(contracted, specs, adapter);
|
|
130
|
+
iteration++;
|
|
131
|
+
if (contractedScore < (useReflected ? reflectedScore : worst.score)) {
|
|
132
|
+
simplex[n] = { coords: contracted, score: contractedScore };
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
// Shrink
|
|
136
|
+
for (let i = 1; i <= n; i++) {
|
|
137
|
+
simplex[i].coords = simplex[0].coords.map((c, j) => c + sigma * (simplex[i].coords[j] - c));
|
|
138
|
+
simplex[i].score = scorePoint(simplex[i].coords, specs, adapter);
|
|
139
|
+
iteration++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Sort final simplex
|
|
145
|
+
simplex.sort((a, b) => a.score - b.score);
|
|
146
|
+
const bestCoords = applyIntegerConstraints(simplex[0].coords, specs);
|
|
147
|
+
const bestParams = coordsToParams(bestCoords, specs);
|
|
148
|
+
const finalMetrics = (0, metrics_1.evaluate)(adapter, bestParams);
|
|
149
|
+
return {
|
|
150
|
+
params: bestParams,
|
|
151
|
+
maxError: finalMetrics.maxError,
|
|
152
|
+
mae: finalMetrics.mae,
|
|
153
|
+
rmse: finalMetrics.rmse,
|
|
154
|
+
budgetUsed: iteration,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Simulated Annealing search strategy.
|
|
159
|
+
* More robust than Nelder-Mead for integer parameters and multimodal objectives.
|
|
160
|
+
* Uses 3 independent restarts, taking the global best.
|
|
161
|
+
*/
|
|
162
|
+
function searchSA(adapter, budget, onProgress) {
|
|
163
|
+
const RESTARTS = 3;
|
|
164
|
+
const budgetPerRun = Math.floor(budget / RESTARTS);
|
|
165
|
+
let globalBest = null;
|
|
166
|
+
for (let r = 0; r < RESTARTS; r++) {
|
|
167
|
+
// Random initialisation within param ranges
|
|
168
|
+
let current = {};
|
|
169
|
+
for (const p of adapter.params) {
|
|
170
|
+
current[p.name] = p.range[0] + Math.random() * (p.range[1] - p.range[0]);
|
|
171
|
+
if (p.integer)
|
|
172
|
+
current[p.name] = Math.round(current[p.name]);
|
|
173
|
+
}
|
|
174
|
+
// T: 1.0 → 1e-4 over budgetPerRun iterations
|
|
175
|
+
let T = 1.0;
|
|
176
|
+
const cooling = Math.pow(1e-4, 1 / budgetPerRun);
|
|
177
|
+
let currentError = (0, metrics_1.evaluate)(adapter, current).maxError;
|
|
178
|
+
let bestLocal = { params: { ...current }, error: currentError };
|
|
179
|
+
for (let i = 0; i < budgetPerRun; i++) {
|
|
180
|
+
T *= cooling;
|
|
181
|
+
// Perturb one random param by ±10% of its range
|
|
182
|
+
const neighbor = { ...current };
|
|
183
|
+
const spec = adapter.params[Math.floor(Math.random() * adapter.params.length)];
|
|
184
|
+
const step = (spec.range[1] - spec.range[0]) * 0.1 * (Math.random() * 2 - 1);
|
|
185
|
+
neighbor[spec.name] = Math.max(spec.range[0], Math.min(spec.range[1], neighbor[spec.name] + step));
|
|
186
|
+
if (spec.integer)
|
|
187
|
+
neighbor[spec.name] = Math.round(neighbor[spec.name]);
|
|
188
|
+
const neighborError = (0, metrics_1.evaluate)(adapter, neighbor).maxError;
|
|
189
|
+
const delta = neighborError - currentError;
|
|
190
|
+
if (delta < 0 || Math.random() < Math.exp(-delta / T)) {
|
|
191
|
+
current = neighbor;
|
|
192
|
+
currentError = neighborError;
|
|
193
|
+
}
|
|
194
|
+
if (currentError < bestLocal.error) {
|
|
195
|
+
bestLocal = { params: { ...current }, error: currentError };
|
|
196
|
+
}
|
|
197
|
+
const globalIter = r * budgetPerRun + i;
|
|
198
|
+
if (onProgress && globalIter % 100 === 0) {
|
|
199
|
+
onProgress(globalIter, globalBest?.error ?? bestLocal.error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (!globalBest || bestLocal.error < globalBest.error) {
|
|
203
|
+
globalBest = bestLocal;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const finalMetrics = (0, metrics_1.evaluate)(adapter, globalBest.params);
|
|
207
|
+
return {
|
|
208
|
+
params: globalBest.params,
|
|
209
|
+
maxError: finalMetrics.maxError,
|
|
210
|
+
mae: finalMetrics.mae,
|
|
211
|
+
rmse: finalMetrics.rmse,
|
|
212
|
+
budgetUsed: budget,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error metrics for tuner adapters.
|
|
3
|
+
*/
|
|
4
|
+
import { TunerAdapter } from './types';
|
|
5
|
+
export interface EvaluationResult {
|
|
6
|
+
maxError: number;
|
|
7
|
+
mae: number;
|
|
8
|
+
rmse: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Evaluate an adapter with given params across all sample inputs.
|
|
12
|
+
* Returns max_error, mae, and rmse relative to the reference function.
|
|
13
|
+
* Penalizes overflow by returning Infinity for all metrics.
|
|
14
|
+
*/
|
|
15
|
+
export declare function evaluate(adapter: TunerAdapter, params: Record<string, number>): EvaluationResult;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Error metrics for tuner adapters.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.evaluate = evaluate;
|
|
7
|
+
/**
|
|
8
|
+
* Evaluate an adapter with given params across all sample inputs.
|
|
9
|
+
* Returns max_error, mae, and rmse relative to the reference function.
|
|
10
|
+
* Penalizes overflow by returning Infinity for all metrics.
|
|
11
|
+
*/
|
|
12
|
+
function evaluate(adapter, params) {
|
|
13
|
+
const inputs = adapter.sampleInputs();
|
|
14
|
+
let maxError = 0;
|
|
15
|
+
let sumAbsError = 0;
|
|
16
|
+
let sumSqError = 0;
|
|
17
|
+
let count = 0;
|
|
18
|
+
for (const input of inputs) {
|
|
19
|
+
const simResult = adapter.simulate(input, params);
|
|
20
|
+
const refResult = adapter.reference(input);
|
|
21
|
+
// Penalize overflow or NaN
|
|
22
|
+
if (!isFinite(simResult) || isNaN(simResult)) {
|
|
23
|
+
return { maxError: Infinity, mae: Infinity, rmse: Infinity };
|
|
24
|
+
}
|
|
25
|
+
if (!isFinite(refResult) || isNaN(refResult)) {
|
|
26
|
+
continue; // skip degenerate reference points
|
|
27
|
+
}
|
|
28
|
+
// Both are in fixed-point; normalize to compare in floating-point units
|
|
29
|
+
const SCALE = 10000;
|
|
30
|
+
const simFloat = simResult / SCALE;
|
|
31
|
+
const refFloat = refResult / SCALE;
|
|
32
|
+
const absError = Math.abs(simFloat - refFloat);
|
|
33
|
+
if (absError === Infinity) {
|
|
34
|
+
return { maxError: Infinity, mae: Infinity, rmse: Infinity };
|
|
35
|
+
}
|
|
36
|
+
if (absError > maxError)
|
|
37
|
+
maxError = absError;
|
|
38
|
+
sumAbsError += absError;
|
|
39
|
+
sumSqError += absError * absError;
|
|
40
|
+
count++;
|
|
41
|
+
}
|
|
42
|
+
if (count === 0) {
|
|
43
|
+
return { maxError: Infinity, mae: Infinity, rmse: Infinity };
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
maxError,
|
|
47
|
+
mae: sumAbsError / count,
|
|
48
|
+
rmse: Math.sqrt(sumSqError / count),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MC int32 arithmetic simulation.
|
|
3
|
+
* Minecraft scoreboards use 32-bit signed integers (Java int).
|
|
4
|
+
*/
|
|
5
|
+
export declare const INT32_MAX = 2147483647;
|
|
6
|
+
export declare const INT32_MIN = -2147483648;
|
|
7
|
+
/**
|
|
8
|
+
* Truncate to int32 using JavaScript bitwise (same as Java int cast).
|
|
9
|
+
*/
|
|
10
|
+
export declare function i32(x: number): number;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a value is within int32 range (before truncation).
|
|
13
|
+
*/
|
|
14
|
+
export declare function isOverflow(x: number): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Fixed-point multiply: compute i32(i32(a * b) / scale).
|
|
17
|
+
* Returns Infinity if overflow is detected before truncation.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fixedMul(a: number, b: number, scale: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Safe i32 addition - returns Infinity on overflow.
|
|
22
|
+
*/
|
|
23
|
+
export declare function safeAdd(a: number, b: number): number;
|
|
24
|
+
/**
|
|
25
|
+
* Safe i32 subtraction - returns Infinity on overflow.
|
|
26
|
+
*/
|
|
27
|
+
export declare function safeSub(a: number, b: number): number;
|
|
28
|
+
/**
|
|
29
|
+
* Safe i32 multiply - returns Infinity on overflow.
|
|
30
|
+
*/
|
|
31
|
+
export declare function safeMul(a: number, b: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Safe i32 division - returns Infinity on division by zero.
|
|
34
|
+
*/
|
|
35
|
+
export declare function safeDiv(a: number, b: number): number;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MC int32 arithmetic simulation.
|
|
4
|
+
* Minecraft scoreboards use 32-bit signed integers (Java int).
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.INT32_MIN = exports.INT32_MAX = void 0;
|
|
8
|
+
exports.i32 = i32;
|
|
9
|
+
exports.isOverflow = isOverflow;
|
|
10
|
+
exports.fixedMul = fixedMul;
|
|
11
|
+
exports.safeAdd = safeAdd;
|
|
12
|
+
exports.safeSub = safeSub;
|
|
13
|
+
exports.safeMul = safeMul;
|
|
14
|
+
exports.safeDiv = safeDiv;
|
|
15
|
+
exports.INT32_MAX = 2147483647;
|
|
16
|
+
exports.INT32_MIN = -2147483648;
|
|
17
|
+
/**
|
|
18
|
+
* Truncate to int32 using JavaScript bitwise (same as Java int cast).
|
|
19
|
+
*/
|
|
20
|
+
function i32(x) {
|
|
21
|
+
return x | 0;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Check if a value is within int32 range (before truncation).
|
|
25
|
+
*/
|
|
26
|
+
function isOverflow(x) {
|
|
27
|
+
return x > exports.INT32_MAX || x < exports.INT32_MIN || !isFinite(x) || isNaN(x);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fixed-point multiply: compute i32(i32(a * b) / scale).
|
|
31
|
+
* Returns Infinity if overflow is detected before truncation.
|
|
32
|
+
*/
|
|
33
|
+
function fixedMul(a, b, scale) {
|
|
34
|
+
const product = a * b;
|
|
35
|
+
if (isOverflow(product))
|
|
36
|
+
return Infinity;
|
|
37
|
+
const truncated = i32(product);
|
|
38
|
+
const divided = truncated / scale;
|
|
39
|
+
if (isOverflow(divided))
|
|
40
|
+
return Infinity;
|
|
41
|
+
return i32(divided);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Safe i32 addition - returns Infinity on overflow.
|
|
45
|
+
*/
|
|
46
|
+
function safeAdd(a, b) {
|
|
47
|
+
const result = a + b;
|
|
48
|
+
if (isOverflow(result))
|
|
49
|
+
return Infinity;
|
|
50
|
+
return i32(result);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Safe i32 subtraction - returns Infinity on overflow.
|
|
54
|
+
*/
|
|
55
|
+
function safeSub(a, b) {
|
|
56
|
+
const result = a - b;
|
|
57
|
+
if (isOverflow(result))
|
|
58
|
+
return Infinity;
|
|
59
|
+
return i32(result);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Safe i32 multiply - returns Infinity on overflow.
|
|
63
|
+
*/
|
|
64
|
+
function safeMul(a, b) {
|
|
65
|
+
const result = a * b;
|
|
66
|
+
if (isOverflow(result))
|
|
67
|
+
return Infinity;
|
|
68
|
+
return i32(result);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Safe i32 division - returns Infinity on division by zero.
|
|
72
|
+
*/
|
|
73
|
+
function safeDiv(a, b) {
|
|
74
|
+
if (b === 0)
|
|
75
|
+
return Infinity;
|
|
76
|
+
return i32(a / b);
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=simulator.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the redscript tuner system.
|
|
3
|
+
*/
|
|
4
|
+
export interface ParamSpec {
|
|
5
|
+
name: string;
|
|
6
|
+
range: [number, number];
|
|
7
|
+
integer: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ResultMeta {
|
|
10
|
+
maxError: number;
|
|
11
|
+
mae: number;
|
|
12
|
+
rmse: number;
|
|
13
|
+
estimatedCmds: number;
|
|
14
|
+
tuneDate: string;
|
|
15
|
+
budgetUsed: number;
|
|
16
|
+
}
|
|
17
|
+
export interface TunerAdapter {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
params: ParamSpec[];
|
|
21
|
+
simulate(input: number, params: Record<string, number>): number;
|
|
22
|
+
reference(input: number): number;
|
|
23
|
+
sampleInputs(): number[];
|
|
24
|
+
generateCode(params: Record<string, number>, meta: ResultMeta): string;
|
|
25
|
+
}
|
|
26
|
+
export interface SearchResult {
|
|
27
|
+
params: Record<string, number>;
|
|
28
|
+
maxError: number;
|
|
29
|
+
mae: number;
|
|
30
|
+
rmse: number;
|
|
31
|
+
budgetUsed: number;
|
|
32
|
+
}
|
|
@@ -535,6 +535,11 @@ class TypeChecker {
|
|
|
535
535
|
this.checkExpr(expr.obj);
|
|
536
536
|
this.checkExpr(expr.value);
|
|
537
537
|
break;
|
|
538
|
+
case 'index_assign':
|
|
539
|
+
this.checkExpr(expr.obj);
|
|
540
|
+
this.checkExpr(expr.index);
|
|
541
|
+
this.checkExpr(expr.value);
|
|
542
|
+
break;
|
|
538
543
|
case 'index':
|
|
539
544
|
this.checkExpr(expr.obj);
|
|
540
545
|
this.checkExpr(expr.index);
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# RedScript Standard Library Roadmap
|
|
2
|
+
|
|
3
|
+
> 目标:覆盖卡儿数学库(large_number)的所有核心功能,但以 RedScript 语言提供干净的 API。
|
|
4
|
+
> 参考分析:`docs/LARGE_NUMBER_ANALYSIS.md`(本地,不追踪到 git)
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 当前 stdlib 状态(2026-03-17)
|
|
9
|
+
|
|
10
|
+
| 文件 | 内容 | 状态 |
|
|
11
|
+
|------|------|------|
|
|
12
|
+
| `math.mcrs` | abs/sign/clamp/lerp/ln/sqrt_fx/exp_fx/sin_fixed/cos_fixed/isqrt/gcd/lcm... | ✅ |
|
|
13
|
+
| `math_hp.mcrs` | sin_hp/cos_hp(实体旋转,高精度),init_trig | ✅框架/⚠️return值待修 |
|
|
14
|
+
| `random.mcrs` | LCG: next_lcg/random_range/random_bool; PCG: pcg_next/pcg_output | ✅ |
|
|
15
|
+
| `vec.mcrs` | 2D/3D dot/cross/length/distance/normalize/lerp/atan2/rotate/add/sub/scale | ✅ |
|
|
16
|
+
| `color.mcrs` | rgb_pack/unpack, rgb_lerp, hsl_to_r/g/b, rgb_to_h/s/l | ✅ |
|
|
17
|
+
| `bits.mcrs` | bit_and/or/xor/not, bit_shl/shr, bit_get/set/clear/toggle, popcount | ✅ |
|
|
18
|
+
| `list.mcrs` | sort3, min/max/avg (3/5), weighted utilities | ✅ |
|
|
19
|
+
| `geometry.mcrs` | AABB/sphere/cylinder contains, parabola, angle helpers, MC sun angle | ✅ |
|
|
20
|
+
| `signal.mcrs` | uniform, normal_approx12, exp_dist, bernoulli, weighted2/3 | ✅ |
|
|
21
|
+
| `bigint.mcrs` | 96-bit base-10000: add/sub/mul/div/cmp, int32↔bigint3 conversion | ✅ |
|
|
22
|
+
| `combat.mcrs` | damage/kill-check | ✅(原有) |
|
|
23
|
+
| `player.mcrs` | health/alive/range | ✅(原有) |
|
|
24
|
+
| `cooldown.mcrs` | per-player cooldown tracking | ✅(原有) |
|
|
25
|
+
| `timer.mcrs` | Timer static allocation | ✅(原有) |
|
|
26
|
+
| `strings.mcrs` | string utilities | ✅(原有) |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Batch 1 — 纯整数,无需新语言特性(当前可做)
|
|
31
|
+
|
|
32
|
+
### `stdlib/math.mcrs` 补充
|
|
33
|
+
- [x] `abs`, `sign`, `clamp`, `lerp`, `pow2`
|
|
34
|
+
- [x] `ln(x: int): int` — SA-tuned atanh 级数,max_error 0.000557
|
|
35
|
+
- [x] `sqrt_fx(x: int): int` — 基于 isqrt,固定点 ×10000
|
|
36
|
+
- [x] `exp_fx(x: int): int` — Horner-form Taylor + 2^k 缩放,固定点 ×10000
|
|
37
|
+
|
|
38
|
+
### `stdlib/math_hp.mcrs`(新建,框架就绪)
|
|
39
|
+
- [x] `init_trig()` — 初始化 Marker 实体(用户在 `@load` 里调用)
|
|
40
|
+
- [x] `sin_hp`, `cos_hp` — 框架 + `@require_on_load(init_trig)` 就绪
|
|
41
|
+
- [ ] 真正实现 — 需要 `@raw` / `@builtin` 语言特性(emit 层内嵌 mcfunction)
|
|
42
|
+
|
|
43
|
+
### `stdlib/random.mcrs`
|
|
44
|
+
- [x] `next_lcg(seed: int): int`
|
|
45
|
+
- [x] `random_range(seed, lo, hi)`
|
|
46
|
+
- [x] `random_bool(seed: int): int`
|
|
47
|
+
|
|
48
|
+
### `stdlib/random.mcrs`(已完成)
|
|
49
|
+
- [x] `next_lcg(seed: int): int`
|
|
50
|
+
- [x] `random_range(seed, lo, hi)`
|
|
51
|
+
- [x] `random_bool(seed: int): int`
|
|
52
|
+
|
|
53
|
+
### `stdlib/vec.mcrs` 补充
|
|
54
|
+
- [x] `Vec2`, `Vec3`, `dot2`, `dot3`, `dist2_sq`, `dist3_sq`
|
|
55
|
+
- [ ] `add2`, `sub2`, `scale2`(Vec2 加减缩放)
|
|
56
|
+
- [ ] `add3`, `sub3`, `scale3`(Vec3 加减缩放)
|
|
57
|
+
- [ ] `cross3(a, b: Vec3): Vec3` — 叉积
|
|
58
|
+
|
|
59
|
+
### `stdlib/color.mcrs`(新建)
|
|
60
|
+
- [ ] `rgb_to_int(r, g, b: int): int` — 打包成单个 int
|
|
61
|
+
- [ ] `int_to_r/g/b(c: int): int` — 解包
|
|
62
|
+
- [ ] `hsl_to_rgb(h, s, l: int): (int, int, int)` — 需要元组返回值
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Batch 2 — 需要位运算支持(语言特性 PR 先)
|
|
67
|
+
|
|
68
|
+
> 依赖:编译器支持 `^`、`>>`、`<<` 运算符(目前 scoreboard 没有原生位运算,需要编译器层模拟或降级)
|
|
69
|
+
|
|
70
|
+
### `stdlib/random.mcrs` 升级
|
|
71
|
+
- [ ] `next_pcg(state: int): int` — PCG 算法(比 LCG 质量好,需要 `^` 和 `>>` )
|
|
72
|
+
- [ ] `next_xorshift(x: int): int` — Xorshift(仅需 `^`、`>>`、`<<`)
|
|
73
|
+
|
|
74
|
+
### `stdlib/bits.mcrs`(新建)
|
|
75
|
+
- [ ] `bit_and(a, b: int): int` — 用加法模拟(慢但正确)
|
|
76
|
+
- [ ] `bit_or(a, b: int): int`
|
|
77
|
+
- [ ] `bit_xor(a, b: int): int`
|
|
78
|
+
- [ ] `bit_shift_left(x, n: int): int` — 乘以 2^n
|
|
79
|
+
- [ ] `bit_shift_right(x, n: int): int` — 除以 2^n
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Batch 3 — 需要数组完整支持
|
|
84
|
+
|
|
85
|
+
> 依赖:数组 literal 初始化完整实现(目前只有读取,写入走 workaround)
|
|
86
|
+
|
|
87
|
+
### `stdlib/list.mcrs`(新建)
|
|
88
|
+
- [ ] 基于 NBT list 的动态数组
|
|
89
|
+
- [ ] `list_push`, `list_pop`, `list_get`, `list_set`, `list_len`
|
|
90
|
+
- [ ] `list_sort_int` — 冒泡排序(整数)
|
|
91
|
+
- [ ] `list_sum`, `list_min`, `list_max`
|
|
92
|
+
|
|
93
|
+
### `stdlib/math.mcrs` — 查表升级
|
|
94
|
+
- [ ] `ln` 升级为查表 + 插值(需要 `@precompute` 或 `@load` 初始化 NBT list)
|
|
95
|
+
- [ ] `sin`/`cos` 高精度版(查表 + 和角公式)
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Batch 4 — 高级数学(长期)
|
|
100
|
+
|
|
101
|
+
### `stdlib/bigint.mcrs`
|
|
102
|
+
- [ ] 万进制 int 数组大数(基于 NBT int array)
|
|
103
|
+
- [ ] 大数加减乘
|
|
104
|
+
- [ ] 大数除以整数(竖式法)
|
|
105
|
+
|
|
106
|
+
### `stdlib/geometry.mcrs`
|
|
107
|
+
- [ ] `parabola_shoot` — 抛物线弹道(给定目标点和时间计算初速度)
|
|
108
|
+
- [ ] `cone_select` — 圆锥选区
|
|
109
|
+
- [ ] `midpoint3` — 三维中点
|
|
110
|
+
|
|
111
|
+
### `stdlib/signal.mcrs`
|
|
112
|
+
- [ ] `normal_dist_approx` — 正态分布近似(12个均匀分布相加)
|
|
113
|
+
- [ ] `exponential_dist` — 指数分布随机变量
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Tuner 覆盖计划
|
|
118
|
+
|
|
119
|
+
以下函数需要 `redscript tune` 生成最优系数:
|
|
120
|
+
|
|
121
|
+
| 函数 | Adapter | 目标精度 |
|
|
122
|
+
|------|---------|---------|
|
|
123
|
+
| `ln` | `ln-polynomial`(已有) | < 0.001 |
|
|
124
|
+
| `sqrt` | `sqrt-newton`(待写) | < 0.001 |
|
|
125
|
+
| `exp` | `exp-polynomial`(待写) | < 0.001 |
|
|
126
|
+
| `sin`/`cos` | `sincos-table`(待写) | < 0.0001 |
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 语言特性依赖清单
|
|
131
|
+
|
|
132
|
+
| 特性 | 依赖的 stdlib | 难度 | 状态 |
|
|
133
|
+
|------|-------------|------|------|
|
|
134
|
+
| `@raw` / `@builtin` 内嵌 mcfunction | `sin_hp`/`cos_hp` 实现 | 中 | ❌ TODO |
|
|
135
|
+
| 位运算 `^>><< ` | random PCG, bits | 中 | ❌ TODO |
|
|
136
|
+
| 数组 literal 初始化 | list, bigint | 中 | ❌ TODO(读取已修,写入待做) |
|
|
137
|
+
| 元组返回值 | color(hsl_to_rgb)| 中 | ❌ TODO |
|
|
138
|
+
| `@precompute` 装饰器 | 高精度 sin/cos/ln | 高 | ❌ 长期 |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
*生成于 2026-03-17 · 奇尔沙治*
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redscript-vscode",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.34",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "redscript-vscode",
|
|
9
|
-
"version": "1.2.
|
|
9
|
+
"version": "1.2.34",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"redscript": "file:../../",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"../..": {
|
|
26
26
|
"name": "redscript-mc",
|
|
27
|
-
"version": "2.
|
|
27
|
+
"version": "2.4.0",
|
|
28
28
|
"license": "MIT",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"vscode-languageserver": "^9.0.1",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "redscript-vscode",
|
|
3
3
|
"displayName": "RedScript for Minecraft",
|
|
4
4
|
"description": "Syntax highlighting, error diagnostics, and language support for RedScript — a compiler targeting Minecraft Java Edition",
|
|
5
|
-
"version": "1.2.
|
|
5
|
+
"version": "1.2.34",
|
|
6
6
|
"publisher": "bkmashiro",
|
|
7
7
|
"icon": "icon.png",
|
|
8
8
|
"license": "MIT",
|