refactor: temporarily remove bitwise operations
This commit is contained in:
parent
635285b8d0
commit
3c0f9b31c6
9 changed files with 192 additions and 184 deletions
|
|
@ -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],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
47
src/compilers/bindings/Binary.ts
Normal file
47
src/compilers/bindings/Binary.ts
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
Reference in a new issue