refactor: temporarily remove bitwise operations

This commit is contained in:
Asaki Yuki 2026-02-05 13:36:33 +07:00
parent 635285b8d0
commit 3c0f9b31c6
9 changed files with 192 additions and 184 deletions

View file

@ -4,7 +4,7 @@
*/ */
export const config = { export const config = {
packinfo: { packinfo: {
name: "AsaJS - Installer Test", name: "AsaJS",
description: "Create your Minecraft JSON-UI resource packs using JavaScript.", description: "Create your Minecraft JSON-UI resource packs using JavaScript.",
version: [4, 0, 1], version: [4, 0, 1],
}, },

View file

@ -0,0 +1,47 @@
import { RandomBindingString } from "../../components/Utils.js"
import { Binding } from "../../types/properties/value.js"
import { defaultFunctions } from "./Function.js"
import { GenBinding } from "./types.js"
export function intToBin(input: string) {
const { abs, negabs } = defaultFunctions
const ret = RandomBindingString(16)
const bindings: GenBinding[] = []
// negative bit
bindings.push({
source: `(${input} < 0)`,
target: `${ret}0`,
})
return {
ret,
bindings,
}
}
export function binToInt(input: Binding) {
const ret = RandomBindingString(16)
const bindings: GenBinding[] = []
const nevBind = (input + "0") as Binding
// Is reverse to positive
bindings.push({
source: `(-1 + ((${nevBind} = 0) * 2))`,
target: `${ret}0`,
})
bindings.push({
source: `(${Array.from({ length: 31 }, ($, i) => {
return `${input}${i + 1}`
}).join(" + ")})`,
target: ret,
})
return {
ret,
bindings,
}
}

View file

@ -1,5 +1,5 @@
import { RandomBindingString } from "../../components/Utils.js" import { RandomBindingString } from "../../components/Utils.js"
import { Parser } from "./Parser.js" import { intToBin } from "./Binary.js"
import { Expression, GenBinding } from "./types.js" import { Expression, GenBinding } from "./types.js"
type Callback = (...args: Expression[]) => { type Callback = (...args: Expression[]) => {
@ -13,24 +13,52 @@ function callFn(name: string, ...args: Expression[]) {
return FunctionMap.get(name)!(...args) return FunctionMap.get(name)!(...args)
} }
// Default Functions export const defaultFunctions = {
FunctionMap.set("abs", number => { /**
* Returns the absolute value of a number (the value without regard to whether it is positive or negative). For example, the absolute value of -5 is the same as the absolute value of 5.
* @param number
* @returns
*/
abs: number => {
const randomBinding = RandomBindingString(16) const randomBinding = RandomBindingString(16)
return { return {
genBindings: [{ source: `((-1 + (${number} > 0) * 2) * ${number})`, target: randomBinding }], genBindings: [{ source: `((-1 + (${number} > 0) * 2) * ${number})`, target: randomBinding }],
value: randomBinding, value: randomBinding,
} }
}) },
FunctionMap.set("new", expression => { /**
* Returns the negative absolute value of a number (the value without regard to whether it is positive or negative). For example, the absolute value of 5 is the same as the negative absolute value of -5.
* @param number
* @returns
*/
negabs: number => {
const randomBinding = RandomBindingString(16)
return {
genBindings: [{ source: `((-1 + (${number} < 0) * 2) * ${number})`, target: randomBinding }],
value: randomBinding,
}
},
/**
* Generate a new binding for expression
* @param expression
* @returns
*/
new: expression => {
const randomBinding = RandomBindingString(16) const randomBinding = RandomBindingString(16)
return { return {
genBindings: [{ source: expression, target: randomBinding }], genBindings: [{ source: expression, target: randomBinding }],
value: randomBinding, value: randomBinding,
} }
}) },
FunctionMap.set("sqrt", number => { /**
* Returns the square root of a number.
* @param number
* @returns
*/
sqrt: number => {
const rtn = RandomBindingString(16), const rtn = RandomBindingString(16),
$1 = RandomBindingString(16), $1 = RandomBindingString(16),
$2 = RandomBindingString(16) $2 = RandomBindingString(16)
@ -55,26 +83,40 @@ FunctionMap.set("sqrt", number => {
], ],
value: rtn, value: rtn,
} }
}) },
FunctionMap.set("translatable", key => { /**
* Return a translatable string
* @param key
* @returns
*/
translatable: key => {
return { return {
value: `'%' + ${key}`, value: `'%' + ${key}`,
} }
}) },
FunctionMap.set("bin", input => { /**
const { ret, bindings } = Parser.intToBin(input) * Return a binary of int32 number in string
* @param value
* @param bait
* @returns
*/
// bin: value => {
// const {} = intToBin(value)
bindings.push({ // return {
source: `'§z' + ${Array.from({ length: 30 }, (_, i) => `${ret}${30 - i - 1}`).join(" + ")}`, // value,
target: ret, // }
}) // },
return { genBindings: bindings, value: ret } /**
}) * Generate value bindings
* @param value
FunctionMap.set("bind", (value, bait) => { * @param bait
* @returns
*/
bind: (value, bait) => {
const ret = RandomBindingString(16) const ret = RandomBindingString(16)
if (!bait) { if (!bait) {
@ -85,10 +127,20 @@ FunctionMap.set("bind", (value, bait) => {
genBindings: [{ source: `((${bait} - ${bait}) + ${value})`, target: ret }], genBindings: [{ source: `((${bait} - ${bait}) + ${value})`, target: ret }],
value: ret, value: ret,
} }
}) },
FunctionMap.set("int", input => { /**
* Return a int of float number, because string in JSON-UI cannot read it.
* @param input
* @returns
*/
int: input => {
const ret = RandomBindingString(16)
return { return {
value: input, genBindings: [{ source: `${input}`, target: ret }],
value: ret,
} }
}) },
} satisfies Record<string, Callback>
Object.entries(defaultFunctions).forEach(([key, value]) => FunctionMap.set(key, value))

View file

@ -73,8 +73,11 @@ export function Lexer(input: string, start: number = 0, end?: number) {
if (input[index + 1] === "=") tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2)) if (input[index + 1] === "=") tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2))
else { else {
if (input[index] === input[index + 1]) { if (input[index] === input[index + 1]) {
if (input[index] !== "!") tokens.push(makeToken(input, TokenKind.OPERATOR, index++, 2)) if (input[index] !== "!") {
else tokens.push(makeToken(input, TokenKind.OPERATOR, index)) if (input[++index] === input[index + 1])
tokens.push(makeToken(input, TokenKind.OPERATOR, index++ - 1, 3))
else tokens.push(makeToken(input, TokenKind.OPERATOR, index - 1, 2))
} else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
} else tokens.push(makeToken(input, TokenKind.OPERATOR, index)) } else tokens.push(makeToken(input, TokenKind.OPERATOR, index))
} }
break break
@ -135,6 +138,7 @@ export function Lexer(input: string, start: number = 0, end?: number) {
value: `'${input.slice(start, index - 1)}'`, value: `'${input.slice(start, index - 1)}'`,
}, },
}) })
index--
break break
} }
} }
@ -199,12 +203,12 @@ export function Lexer(input: string, start: number = 0, end?: number) {
) )
throw new Error() throw new Error()
} }
tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1)) tokens.push(makeToken(input, TokenKind.INT, start, index - start + 1))
break break
} else if (numType === "b") { } else if (numType === "b") {
index += 2 index += 2
while (Checker.isBinaryChar(input[index + 1])) index++ while (Checker.isBinaryChar(input[index + 1])) index++
tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1)) tokens.push(makeToken(input, TokenKind.INT, start, index - start + 1))
if (start + 2 === index) { if (start + 2 === index) {
console.error( console.error(
`\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`, `\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`,
@ -215,7 +219,7 @@ export function Lexer(input: string, start: number = 0, end?: number) {
} else if (numType === "o") { } else if (numType === "o") {
index += 2 index += 2
while (Checker.isOctalChar(input[index + 1])) index++ while (Checker.isOctalChar(input[index + 1])) index++
tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1)) tokens.push(makeToken(input, TokenKind.INT, start, index - start + 1))
if (start + 2 === index) { if (start + 2 === index) {
console.error( console.error(
`\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`, `\x1b[31merror: ${input + "\n" + " ".repeat(index + 6) + "^"}\nInvalid character.\x1b[0m`,
@ -239,7 +243,7 @@ export function Lexer(input: string, start: number = 0, end?: number) {
while (Checker.isNumberChar(input[index + 1])) index++ while (Checker.isNumberChar(input[index + 1])) index++
} }
tokens.push(makeToken(input, TokenKind.NUMBER, start, index - start + 1)) tokens.push(makeToken(input, TokenKind.INT, start, index - start + 1))
} else if (Checker.isWordChar(token)) { } else if (Checker.isWordChar(token)) {
while (Checker.isWordChar(input[index + 1])) index++ while (Checker.isWordChar(input[index + 1])) index++
tokens.push(makeToken(input, TokenKind.WORD, start, index - start + 1)) tokens.push(makeToken(input, TokenKind.WORD, start, index - start + 1))

View file

@ -186,110 +186,13 @@ export class Parser {
} }
private parseBitwiseLogicExpression(): Expression { private parseBitwiseLogicExpression(): Expression {
let left = this.parseBitwiseShiftExpression(), // TODO
current return this.parseBitwiseShiftExpression()
while (
(current = this.at()) &&
this.at()?.kind === TokenKind.OPERATOR &&
["&", "|", "^"].includes(<string>current.value)
) {
const operator = this.eat()
const right = this.parsePrimaryExpression()
const cacheStr = `expr:${left}${operator.value}${right}`
if (this.cache.has(cacheStr)) {
return (left = this.cache.get(cacheStr) as Expression)
}
const ret = RandomBindingString(16)
this.cache.set(cacheStr, ret)
const leftBin = this.intToBin(left)
const rightBin = this.intToBin(right)
if (operator.value === "&") {
this.genBindings.push(
...Array.from({ length: 30 }, (_, i) => {
return {
source: `(${leftBin}${i} * ${rightBin}${i})`,
target: `${ret}${i}`,
}
}),
)
} else if (operator.value === "|") {
this.genBindings.push(
...Array.from({ length: 30 }, (_, i) => {
return {
source: `(${leftBin}${i} + ${rightBin}${i} - (${leftBin}${i} * ${rightBin}${i}))`,
target: `${ret}${i}`,
}
}),
)
} else {
this.genBindings.push(
...Array.from({ length: 30 }, (_, i) => {
return {
source: `(${leftBin}${i} + ${rightBin}${i} - 2 * (${leftBin}${i} * ${rightBin}${i}))`,
target: `${ret}${i}`,
}
}),
)
}
this.genBindings.push({
source: `(${Array.from({ length: 30 }, (_, i) => `(${ret}${i} * ${2 ** i})`).join(" + ")})`,
target: ret,
})
left = ret
}
return left
} }
private parseBitwiseShiftExpression(): Expression { private parseBitwiseShiftExpression(): Expression {
let left = this.parsePrimaryExpression(), // TODO
current return this.parsePrimaryExpression()
while (
(current = this.at()) &&
this.at()?.kind === TokenKind.OPERATOR &&
[">>", "<<"].includes(<string>current.value)
) {
const operator = this.eat()
const right = this.parsePrimaryExpression()
const cacheStr = `expr:${left}${operator.value}${right}`
if (this.cache.has(cacheStr)) {
return (left = this.cache.get(cacheStr) as Expression)
}
const ret = RandomBindingString(16)
this.cache.set(cacheStr, ret)
const leftBind = this.intToBin(left)
const op = operator.value === "<<" ? "-" : "+"
this.genBindings.push(
...Array.from({ length: 30 }, (_, i) => {
return {
source: `((0 * ${left}) + ('${leftBind}' + (${i} ${op} ${right})))`,
target: `${ret}${i}`,
}
}),
)
this.genBindings.push({
source: `(${Array.from({ length: 30 }, (_, i) => `(${ret}${i} * ${2 ** i})`).join(" + ")})`,
target: ret,
})
left = ret
}
return left
} }
private parsePrimaryExpression(): Expression { private parsePrimaryExpression(): Expression {
@ -307,7 +210,7 @@ export class Parser {
return `(${value})` return `(${value})`
} }
case TokenKind.NUMBER: { case TokenKind.INT: {
const numberToken = this.eat() const numberToken = this.eat()
switch (numberToken.value[1]) { switch (numberToken.value[1]) {
@ -390,7 +293,7 @@ export class Parser {
} }
default: default:
this.expect(TokenKind.NUMBER, "Unexpected token!") this.expect(TokenKind.INT, "Unexpected token!")
} }
return left.value return left.value
@ -404,7 +307,7 @@ export class Parser {
const args: Expression[] = [] const args: Expression[] = []
if (this.at().kind === TokenKind.COMMA) { if (this.at().kind === TokenKind.COMMA) {
this.expect(TokenKind.NUMBER, "Unexpected token!") this.expect(TokenKind.INT, "Unexpected token!")
} }
if (this.at().kind !== TokenKind.CLOSE_PARENTHESIS) { if (this.at().kind !== TokenKind.CLOSE_PARENTHESIS) {
@ -413,7 +316,7 @@ export class Parser {
while (this.at().kind === TokenKind.COMMA) { while (this.at().kind === TokenKind.COMMA) {
this.eat() this.eat()
if (this.at().kind === TokenKind.CLOSE_PARENTHESIS) { if (this.at().kind === TokenKind.CLOSE_PARENTHESIS) {
this.expect(TokenKind.NUMBER, "Unexpected token!") this.expect(TokenKind.INT, "Unexpected token!")
} }
args.push(this.parseExpression()) args.push(this.parseExpression())
} }

View file

@ -1,10 +1,12 @@
export enum TokenKind { export enum TokenKind {
VARIABLE, VARIABLE,
NUMBER,
STRING, STRING,
TEMPLATE_STRING, TEMPLATE_STRING,
WORD, WORD,
INT,
FLOAT,
OPEN_PARENTHESIS, OPEN_PARENTHESIS,
CLOSE_PARENTHESIS, CLOSE_PARENTHESIS,

View file

@ -67,6 +67,7 @@ if (isBuildMode) {
let first = true let first = true
process.on("beforeExit", async () => { process.on("beforeExit", async () => {
if (first) { if (first) {
first = false
await createBuildFolder() await createBuildFolder()
await buildUI() await buildUI()
if (isLinkMode) await linkToGame() if (isLinkMode) await linkToGame()
@ -85,7 +86,6 @@ if (isBuildMode) {
console.log("Install Path:", `\x1b[32m"${path.join(gamePath, await getBuildFolderName())}"\x1b[0m`) console.log("Install Path:", `\x1b[32m"${path.join(gamePath, await getBuildFolderName())}"\x1b[0m`)
console.log("=============================================================") console.log("=============================================================")
} }
first = false
}) })
} else if (isLinkMode) linkToGame() } else if (isLinkMode) linkToGame()
else if (unLinked) unlink() else if (unLinked) unlink()

View file

@ -169,7 +169,7 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
if (this.controls.size) { if (this.controls.size) {
obj.controls = [] obj.controls = []
this.controls.forEach((e, key) => obj.controls.push({ [key + e[0]]: e[1] })) this.controls.forEach((e, key) => obj.controls.push({ [key + e[0]]: FormatProperties(e[1]) }))
} }
return obj return obj

View file

@ -15,4 +15,4 @@ export { ItemAuxID } from "./types/enums/Items.js"
export { ArrayName, Operation } from "./types/properties/index.js" export { ArrayName, Operation } from "./types/properties/index.js"
export { Lexer } from "./compilers/bindings/Lexer.js" export * from "./compilers/bindings/Binary.js"