UNPKG

@specs-feup/kadabra

Version:

A Java source-to-source compiler written in Typescript

200 lines 5.65 kB
import Query from "@specs-feup/lara/api/weaver/Query.js"; import { Class, Method, Return } from "../Joinpoints.js"; /** * Opens a window with the AST of Spoon. * * @param name - The name of the AST window. */ export function showAST(name = "Spoon Tree") { const app = Query.root(); app.showAST(name); } /** * Converts a primitive type to its wrapper class. * * @param type - The primitive type to convert. * @returns An object containing the wrapper class and whether the type is primitive. */ export function convertPrimitive(type) { let wrapper; let isPrimitive = true; switch (type) { case "bool": wrapper = "Boolean"; break; case "int": wrapper = "Integer"; break; case "char": wrapper = "Character"; break; case "void": case "byte": case "short": case "long": case "float": case "double": wrapper = type.charAt(0).toUpperCase() + type.slice(1); break; default: wrapper = type; isPrimitive = false; break; } return { wrapper, isPrimitive }; } /** * Converts a primitive type to its wrapper class as a string. * * @param type - The primitive type to convert. * @returns The wrapper class as a string. */ export function primitive2Class(type) { switch (type) { case "bool": return "Boolean"; case "int": return "Integer"; case "char": return "Character"; case "void": case "byte": case "short": case "long": case "float": case "double": return type.charAt(0).toUpperCase() + type.slice(1); default: return type; } } /** * Inserts multiple print statements in the main method of a class. * * @param messages - The messages to print. */ export function printOnMain(...messages) { for (const message of messages) { beforeExitMain(`System.out.println(${JSON.stringify(message)});`); } } /** * Inserts a print statement in the main method of a class. * * @param message - The message to print. */ export function printOnMain2(message) { for (const $method of Query.search(Class).search(Method, "main")) { beforeExit($method, `System.out.println(${message});`); } } /** * Inserts code before the exit of the main method. * * @param code - The code to insert. */ export function beforeExitMain(code) { for (const $method of Query.search(Class).search(Method, "main")) { beforeExit($method, code); } } /** * Inserts code before the exit of a method. * * @param method - The method join point. * @param code - The code to insert. */ export function beforeExit(method, code) { let inserted = false; // Try to insert before return statements for (const stmt of Query.searchFrom(method.body, Return)) { stmt.insertBefore(code); inserted = true; } if (inserted) return; // Try to insert after the last statement (for void methods) if (method.body.lastStmt !== undefined) { method.body.lastStmt.insertAfter(code); return; } // Else, insert into an empty method method.body.insertReplace(code); } /** * Generates API names for concurrent package components. * * @returns An object containing the API names. */ export function getAPINames() { return { concurrentPackage: "weaver.kadabra.concurrent", channel: "weaver.kadabra.concurrent.KadabraChannel", thread: "weaver.kadabra.concurrent.KadabraThread", product: "weaver.kadabra.concurrent.Product", }; } /** * Generates code to retrieve an integer property from the system. * * @param name - The name of the property. * @param defaultValue - The default value of the property (optional). * @returns The generated code as a string. */ export function integerProperty(name, defaultValue) { let code = `Integer.parseInt(System.getProperty(${JSON.stringify(name)}`; if (defaultValue !== undefined) { code += `, "${defaultValue}\\"`; } return code + "))"; } /** * Retrieves methods based on class and method names. * * @param className - The name of the class. * @param methodName - The name of the method. * @returns An array of method join points. */ export function getMethod(className = ".*", methodName) { if (methodName === undefined) { methodName = className; className = ".*"; } let methods = undefined; const search = Query.search(Class, (cls) => RegExp(className).exec(cls.qualifiedName) !== null).search(Method, methodName); for (const method of search) { if (methods === undefined) { methods = method; } else if (Array.isArray(methods)) { methods.push(method); } else { methods = [methods, method]; } } return methods; } /** * Retrieves classes based on class names. * * @param className - The name of the class. * @returns An array of class join points. */ export function getClass(className = ".*") { let classes = undefined; const search = Query.search(Class, (cls) => RegExp(className).exec(cls.qualifiedName) !== null); for (const cls of search) { if (classes === undefined) { classes = cls; } else if (Array.isArray(classes)) { classes.push(cls); } else { classes = [classes, cls]; } } return classes; } //# sourceMappingURL=Utils.js.map