redscript-mc 1.2.27 → 1.2.28
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 +24 -13
- package/README.zh.md +16 -5
- package/dist/__tests__/cli.test.js +13 -13
- package/dist/__tests__/optimizer-advanced.test.js +4 -4
- package/dist/cli.js +13 -5
- package/dist/codegen/mcfunction/index.d.ts +4 -0
- package/dist/codegen/mcfunction/index.js +9 -4
- package/dist/compile.d.ts +4 -0
- package/dist/compile.js +9 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -6
- package/dist/lowering/index.d.ts +3 -0
- package/dist/lowering/index.js +95 -65
- package/dist/optimizer/commands.d.ts +1 -0
- package/dist/optimizer/commands.js +18 -11
- package/dist/optimizer/structure.d.ts +1 -0
- package/dist/optimizer/structure.js +6 -1
- package/editors/vscode/package-lock.json +3 -3
- package/editors/vscode/package.json +1 -1
- package/examples/math-showcase.mcrs +146 -0
- package/examples/readme-demo.mcrs +92 -0
- package/package.json +1 -1
- package/src/__tests__/cli.test.ts +13 -13
- package/src/__tests__/optimizer-advanced.test.ts +4 -4
- package/src/cli.ts +14 -5
- package/src/codegen/mcfunction/index.ts +14 -5
- package/src/compile.ts +15 -2
- package/src/index.ts +17 -7
- package/src/lowering/index.ts +95 -64
- package/src/optimizer/commands.ts +18 -12
- package/src/optimizer/structure.ts +6 -2
|
@@ -20,8 +20,14 @@ export interface CommandFunction {
|
|
|
20
20
|
commands: IRCommand[]
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
// Matches scoreboard reads for LICM/CSE — objective is captured in group 2
|
|
24
|
+
// so the optimizer can reconstruct the command with the same objective.
|
|
25
|
+
let _OBJ_PATTERN = 'rs'
|
|
26
|
+
export function setOptimizerObjective(obj: string): void { _OBJ_PATTERN = obj }
|
|
27
|
+
|
|
28
|
+
function scoreboardReadRe(): RegExp {
|
|
29
|
+
return new RegExp(`^execute store result score (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} run scoreboard players get (\\S+) (\\S+)$`)
|
|
30
|
+
}
|
|
25
31
|
const SCOREBOARD_WRITE_RE =
|
|
26
32
|
/^(?:scoreboard players (?:set|add|remove|reset)\s+(\S+)\s+(\S+)|scoreboard players operation\s+(\S+)\s+(\S+)\s+[+\-*/%]?= )/
|
|
27
33
|
const EXECUTE_STORE_SCORE_RE =
|
|
@@ -130,7 +136,7 @@ function applyLICMInternal(functions: CommandFunction[]): Partial<OptimizationSt
|
|
|
130
136
|
const scoreboardWrites = new Set<string>()
|
|
131
137
|
|
|
132
138
|
for (const inner of loopFn.commands) {
|
|
133
|
-
const readMatch = inner.cmd.match(
|
|
139
|
+
const readMatch = inner.cmd.match(scoreboardReadRe())
|
|
134
140
|
if (readMatch) {
|
|
135
141
|
const [, temp, player, objective] = readMatch
|
|
136
142
|
const key = `${player} ${objective}`
|
|
@@ -147,7 +153,7 @@ function applyLICMInternal(functions: CommandFunction[]): Partial<OptimizationSt
|
|
|
147
153
|
for (const info of readInfo.values()) {
|
|
148
154
|
const matches = inner.cmd.match(TEMP_RE) ?? []
|
|
149
155
|
const usageCount = matches.filter(name => name === info.temp).length
|
|
150
|
-
const isDef = inner.cmd.startsWith(`execute store result score ${info.temp}
|
|
156
|
+
const isDef = inner.cmd.startsWith(`execute store result score ${info.temp} ${_OBJ_PATTERN} run scoreboard players get `)
|
|
151
157
|
if (!isDef) {
|
|
152
158
|
info.uses += usageCount
|
|
153
159
|
}
|
|
@@ -172,7 +178,7 @@ function applyLICMInternal(functions: CommandFunction[]): Partial<OptimizationSt
|
|
|
172
178
|
const rewrittenLoopCommands: IRCommand[] = []
|
|
173
179
|
|
|
174
180
|
for (const inner of loopFn.commands) {
|
|
175
|
-
const readMatch = inner.cmd.match(
|
|
181
|
+
const readMatch = inner.cmd.match(scoreboardReadRe())
|
|
176
182
|
if (readMatch && hoistedTemps.has(readMatch[1])) {
|
|
177
183
|
continue
|
|
178
184
|
}
|
|
@@ -182,7 +188,7 @@ function applyLICMInternal(functions: CommandFunction[]): Partial<OptimizationSt
|
|
|
182
188
|
loopFn.commands = rewrittenLoopCommands
|
|
183
189
|
nextCommands.push(
|
|
184
190
|
...hoistable.map(item => ({
|
|
185
|
-
cmd: `execute store result score ${item.temp}
|
|
191
|
+
cmd: `execute store result score ${item.temp} ${_OBJ_PATTERN} run scoreboard players get ${item.player} ${item.objective}`,
|
|
186
192
|
})),
|
|
187
193
|
command
|
|
188
194
|
)
|
|
@@ -198,9 +204,9 @@ function applyLICMInternal(functions: CommandFunction[]): Partial<OptimizationSt
|
|
|
198
204
|
|
|
199
205
|
function extractArithmeticExpression(commands: IRCommand[], index: number): { key: string; dst: string } | null {
|
|
200
206
|
const assign =
|
|
201
|
-
commands[index]?.cmd.match(
|
|
202
|
-
commands[index]?.cmd.match(
|
|
203
|
-
const op = commands[index + 1]?.cmd.match(
|
|
207
|
+
commands[index]?.cmd.match(new RegExp(`^scoreboard players operation (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} = (\\$[A-Za-z0-9_]+|\\$const_-?\\d+) ${_OBJ_PATTERN}$`)) ??
|
|
208
|
+
commands[index]?.cmd.match(new RegExp(`^scoreboard players set (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} (-?\\d+)$`))
|
|
209
|
+
const op = commands[index + 1]?.cmd.match(new RegExp(`^scoreboard players operation (\\$[A-Za-z0-9_]+) ${_OBJ_PATTERN} ([+\\-*/%]=) (\\$[A-Za-z0-9_]+|\\$const_-?\\d+) ${_OBJ_PATTERN}$`))
|
|
204
210
|
if (!assign || !op || assign[1] !== op[1]) {
|
|
205
211
|
return null
|
|
206
212
|
}
|
|
@@ -234,14 +240,14 @@ function applyCSEInternal(functions: CommandFunction[]): Partial<OptimizationSta
|
|
|
234
240
|
|
|
235
241
|
for (let i = 0; i < commands.length; i++) {
|
|
236
242
|
const command = commands[i]
|
|
237
|
-
const readMatch = command.cmd.match(
|
|
243
|
+
const readMatch = command.cmd.match(scoreboardReadRe())
|
|
238
244
|
if (readMatch) {
|
|
239
245
|
const [, dst, player, objective] = readMatch
|
|
240
246
|
const key = `${player} ${objective}`
|
|
241
247
|
const cached = readCache.get(key)
|
|
242
248
|
if (cached) {
|
|
243
249
|
stats.cseRedundantReads = (stats.cseRedundantReads ?? 0) + 1
|
|
244
|
-
rewritten.push({ ...command, cmd: `scoreboard players operation ${dst}
|
|
250
|
+
rewritten.push({ ...command, cmd: `scoreboard players operation ${dst} ${_OBJ_PATTERN} = ${cached} ${_OBJ_PATTERN}` })
|
|
245
251
|
} else {
|
|
246
252
|
readCache.set(key, dst)
|
|
247
253
|
rewritten.push(command)
|
|
@@ -255,7 +261,7 @@ function applyCSEInternal(functions: CommandFunction[]): Partial<OptimizationSta
|
|
|
255
261
|
if (expr) {
|
|
256
262
|
const cached = exprCache.get(expr.key)
|
|
257
263
|
if (cached) {
|
|
258
|
-
rewritten.push({ ...commands[i], cmd: `scoreboard players operation ${expr.dst}
|
|
264
|
+
rewritten.push({ ...commands[i], cmd: `scoreboard players operation ${expr.dst} ${_OBJ_PATTERN} = ${cached} ${_OBJ_PATTERN}` })
|
|
259
265
|
stats.cseArithmetic = (stats.cseArithmetic ?? 0) + 1
|
|
260
266
|
i += 1
|
|
261
267
|
} else {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { IRBlock, IRCommand, IRFunction, IRInstr, Operand, Terminator } from '../ir/types'
|
|
2
|
-
import { createEmptyOptimizationStats, mergeOptimizationStats, optimizeCommandFunctions, type OptimizationStats } from './commands'
|
|
2
|
+
import { createEmptyOptimizationStats, mergeOptimizationStats, optimizeCommandFunctions, setOptimizerObjective, type OptimizationStats } from './commands'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
let OBJ = 'rs'
|
|
5
|
+
export function setStructureObjective(obj: string): void {
|
|
6
|
+
OBJ = obj
|
|
7
|
+
setOptimizerObjective(obj)
|
|
8
|
+
}
|
|
5
9
|
const INLINE_THRESHOLD = 8
|
|
6
10
|
|
|
7
11
|
const BOP_OP: Record<string, string> = {
|