@specs-feup/clava
Version:
A C/C++ source-to-source compiler written in Typescript
244 lines (209 loc) • 6.69 kB
text/typescript
import { wrapJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js";
import Io from "@specs-feup/lara/api/lara/Io.js";
import JavaInterop from "@specs-feup/lara/api/lara/JavaInterop.js";
import { JavaClasses } from "@specs-feup/lara/api/lara/util/JavaTypes.js";
import Query from "@specs-feup/lara/api/weaver/Query.js";
import Weaver from "@specs-feup/lara/api/weaver/Weaver.js";
import WeaverOptions from "@specs-feup/lara/api/weaver/WeaverOptions.js";
import { FileJp, Include, Joinpoint, Program } from "../Joinpoints.js";
import ClavaJavaTypes from "./ClavaJavaTypes.js";
import ClavaDataStore from "./util/ClavaDataStore.js";
export default class Clava {
/**
* Enables/disables library SpecsLogger for printing.
* <p>
* By default, is disabled.
*/
static useSpecsLogger = false;
/**
* Returns the standard being used for compilation.
*/
static getStandard() {
return Clava.getProgram().standard;
}
static isCxx() {
return Clava.getProgram().isCxx;
}
static rebuild() {
return Clava.getProgram().rebuild();
}
static rebuildFuzzy() {
Clava.getProgram().rebuildFuzzy();
}
/**
* @returns The folder of the first input source element, either itself, if a folder, or the parent folder, if it is a file.
*/
static getBaseFolder(): string {
return Clava.getProgram().baseFolder;
}
/**
* @returns The folder where the code represented by the AST will be written at the end of execution.
*/
static getWeavingFolder(): string {
return Clava.getProgram().weavingFolder;
}
/**
* @param $file - The file to add to the AST.
*/
static addFile($file: FileJp) {
Clava.getProgram().addFile($file);
}
/**
* @param path - Path to an existing source file that will be added to the AST. If the file does not exists, throws an exception.
*/
static addExistingFile(path: string | JavaClasses.File) {
const file = Io.getPath(path);
if (!file.isFile()) {
throw new Error(
"Clava.addExistingFile(): path " +
path.toString() +
" does not represent an existing file"
);
}
const $file = wrapJoinPoint(
ClavaJavaTypes.AstFactory.file(file.getAbsolutePath(), "")
) as FileJp;
Clava.addFile($file);
}
private static cLinkageBegin = `
extern "C" {
private static cLinkageEnd = `
}
/**
* Launches a Clava weaving session.
* @param args - The arguments to pass to the weaver, as if it was launched from the command-line
* @returns True if the weaver execution without problems, false otherwise
*/
static runClava(args: string | any[]): boolean {
// If string, separate arguments
if (typeof args === "string") {
args = ClavaJavaTypes.ArgumentsParser.newCommandLine().parse(args);
}
return ClavaJavaTypes.ClavaWeaverLauncher.execute(args);
}
/**
* Launches several Clava weaving sessions in parallel.
*
* @param argsLists - An array where each element is an array with the arguments to pass to the weaver, as if it was launched from the command-line
* @param threads - Number of threads to use
* @param clavaCommand - The command we should use to call Clava (e.g., /usr/local/bin/clava)
*
* @returns The results of each execution
*/
static runClavaParallel(
argsLists: string[][],
threads = -1,
clavaCommand: string | string[] = ["clava"]
) {
if (typeof clavaCommand === "string") {
clavaCommand = [clavaCommand];
}
const jsonStrings: string[] =
ClavaJavaTypes.ClavaWeaverLauncher.executeParallel(
argsLists,
threads,
JavaInterop.arrayToStringList(clavaCommand),
Clava.getData().getContextFolder().getAbsolutePath()
);
// Read each json file into its own object
const results = jsonStrings.map((jsonString) => JSON.parse(jsonString));
return results;
}
/**
* Creates a clone of the current AST and pushes the clone to the top of the current AST stack. If a $program join point is passed, that join point is added to the top of the stack instead.
*
* @param $program - program to push to the AST.
*/
static pushAst($program?: Program) {
if ($program === undefined) {
Clava.getProgram().push();
return;
}
Weaver.getWeaverEngine().pushAst($program.node);
}
/**
* Discards the AST at the top of the current AST stack.
*/
static popAst() {
Clava.getProgram().pop();
}
/**
* Clears all ASTs except for the one at the top of the stack. If there is one of none AST on the stack does nothing.
*/
static clearAstHistory() {
Weaver.getWeaverEngine().clearAppHistory();
}
/**
* The current number of elements in the AST stack.
*/
static getStackSize() {
return Weaver.getWeaverEngine().getStackSize();
}
/**
* Looks for a join point in the current AST.
*
* @param $jp - A join point from any AST
* @returns The equivalent join point from the AST at the top of the current AST stack
*/
static findJp($jp: Joinpoint) {
// Get file
const $file = $jp.getAncestor("file");
if ($file === undefined) {
console.error(
"Could not find a file for '" + $jp.joinPointType + "'",
"Clava.findJp"
);
return undefined;
}
const $newJp = ClavaJavaTypes.CxxWeaverApi.findJp(
$file.filepath,
$jp.astId
);
if ($newJp === null) {
console.error(
"Could not find the given '" +
$jp.joinPointType +
"' in the current AST. Please verify if a rebuild was done",
"Clava.findJp"
);
return undefined;
}
return $newJp;
}
/**
* Writes the code of the current AST to the given folder.
*/
static writeCode(outputFoldername: string) {
const outputFolder = Io.mkdir(outputFoldername);
ClavaJavaTypes.CxxWeaverApi.writeCode(outputFolder);
return outputFolder;
}
/**
* @returns DataStore with the data of the current weaver
*/
static getData() {
return new ClavaDataStore(WeaverOptions.getData());
}
/**
* @returns The join point $program.
*/
static getProgram() {
return Query.root() as Program;
}
/**
*
* @returns A list of join points representing available user includes
*/
static getAvailableIncludes(): JavaClasses.List<Include> {
return ClavaJavaTypes.CxxWeaverApi.getAvailableUserIncludes();
}
/**
*
* @returns {J#Set<String>} A set with paths to the include folders of the current configuration.
*/
static getIncludeFolders() {
return ClavaJavaTypes.CxxWeaverApi.getIncludeFolders();
}
}