decompile = ({ prompt: "fix tests", time: 1726546383668 } &&
async function decompile(variables) {
if (!variables || variables.length == 0)
throw new Error("no variables to decompile");
try {
if (
variables[0]._inputs.length == 1 &&
variables[0]._module !== variables[0]._inputs[0]._module
) {
const module_name = findModuleName(
variables[0]._module._scope,
variables[0]._inputs[0]._module
);
const import_aliasses = await Promise.all(
variables.map(async (v) => {
const importedName = await findImportedName(v);
return importedName == v._name
? v._name
: `${importedName} as ${v._name}`;
})
);
return `import {${import_aliasses.join(", ")}} from "${module_name}"`;
}
const variable = variables[0];
const name = variable._name;
const compiled =
typeof variable._definition == "string"
? variable._definition
: variable._definition.toString();
const inputs = variable._inputs.map((i) =>
typeof i == "string" ? i : i._name
);
const wrappedCode = "(" + compiled + ")";
const comments = [],
tokens = [];
let parsed = acorn.parse(wrappedCode, {
ecmaVersion: 2022,
sourceType: "module",
ranges: true,
onComment: comments,
onToken: tokens
});
parsed = escodegen.attachComments(parsed, comments, tokens);
const functionExpression = parsed.body[0].expression;
const body = functionExpression.body;
let varName = name;
let prefix = "";
// Handle special variables
if (name) {
if (name.startsWith("initial ")) {
prefix = "mutable ";
varName = name.replace(/^initial /, "");
} else if (name.startsWith("mutable ")) {
prefix = "mutable ";
varName = name.replace(/^mutable /, "");
} else if (name.startsWith("viewof ")) {
prefix = "viewof ";
varName = name.replace(/^viewof /, "");
}
}
let expression = "";
if (
body.type === "BlockStatement" &&
body.body.length === 1 &&
body.body[0].type === "ReturnStatement" &&
comments.length == 0
) {
// If the body is a single ReturnStatement, decompile its argument
if (wrappedCode[body.body[0].argument.start] == "{") {
// bugfix if the body is an object literal we need to escape it
expression = `(${escodegen.generate(body.body[0].argument, {
comment: true
})})`;
} else {
expression = escodegen.generate(body.body[0].argument, {
comment: true
});
}
} else {
// For other types, decompile the whole body
expression = escodegen.generate(body, { comment: true });
}
let source = `${varName ? `${prefix}${varName} = ` : ""}${expression}`;
// replace mutable and viewofs
let id = 0;
inputs.forEach((input, idx) => {
if (input.startsWith("mutable ")) {
source = source.replaceAll(`$${id++}.value`, input);
} else if (input.startsWith("viewof ")) {
source = source.replaceAll(`$${id++}`, input);
} else if (input == "@variable") {
source = source.replaceAll(`$${id++}`, input);
}
});
return source;
} catch (e) {
debugger;
throw e;
}
})