@specs-feup/kadabra
Version:
A Java source-to-source compiler written in Typescript
112 lines (99 loc) • 4.08 kB
text/typescript
import Query from "@specs-feup/lara/api/weaver/Query.js";
import KadabraJavaTypes from "./KadabraJavaTypes.js";
import { Assignment, Class, Field, LocalVariable } from "../Joinpoints.js";
import { LaraJoinPoint } from "@specs-feup/lara/api/LaraJoinPoint.js";
/**
* Utility methods related to searching join points and AST properties.
*/
export class KadabraAst {
private static _BINARY_OP_SET: Set<string> | undefined = undefined;
private static _UNARY_OP_SET: Set<string> | undefined = undefined;
/**
* Searches constant values. Currently, three types of constants are returned:
* - Class fields which are final and initialized when declared;
* - Assignments to final fields;
* - Local variables which are final and initialized when declared.
*
* @param startingPoint - The join point where the search for constants will start (inclusive).
* @returns An array of join points, which can either be a field, an assignment, or a local variable.
*/
static getConstantInitializations(
startingPoint?: LaraJoinPoint
): (Field | Assignment | LocalVariable)[] {
startingPoint ??= Query.root();
const constants: (Field | Assignment | LocalVariable)[] = [];
// Search for final fields with initializations
for (const field of Query.searchFromInclusive(startingPoint, Field)) {
if (field.init !== undefined && field.isFinal) {
constants.push(field);
}
}
// Search for assignments to final fields
for (const assign of Query.searchFromInclusive(
startingPoint,
Assignment
)) {
if (assign.lhs.isFinal) {
constants.push(assign);
}
}
// Search for final local variables with initializations
for (const localVar of Query.searchFromInclusive(
startingPoint,
LocalVariable
)) {
if (localVar.init !== undefined && localVar.isFinal) {
constants.push(localVar);
}
}
return constants;
}
/**
* Retrieves a set of valid binary operators.
*
* @returns A Set<string> with valid binary operators.
*/
static getBinaryOperators(): Set<string> {
if (this._BINARY_OP_SET === undefined) {
this._BINARY_OP_SET = new Set<string>();
for (const binaryOp of KadabraJavaTypes.OperatorUtils.getValidBinaryStrings()) {
this._BINARY_OP_SET.add(binaryOp);
}
}
return this._BINARY_OP_SET;
}
/**
* Retrieves a set of valid unary operators.
*
* @returns A Set<string> with valid unary operators.
*/
static getUnaryOperators(): Set<string> {
if (this._UNARY_OP_SET === undefined) {
this._UNARY_OP_SET = new Set<string>();
for (const unaryOp of KadabraJavaTypes.OperatorUtils.getValidUnaryStrings()) {
this._UNARY_OP_SET.add(unaryOp);
}
}
return this._UNARY_OP_SET;
}
/**
* Creates an object representing the class hierarchy of the current program.
*
* @returns A map where the keys are strings with the fully qualified name of the class,
* and the value is an array with class join points that are subclasses of the class represented by the key.
* If the map returns undefined, this means that the class has no subclasses.
*/
static getHierarchy(): Map<string, Class[]> {
const hierarchy: Map<string, Class[]> = new Map();
for (const cls of Query.search(Class)) {
const superClass = cls.superClass;
const subClasses = hierarchy.get(superClass);
if (subClasses === undefined) {
hierarchy.set(superClass, [cls]);
} else {
subClasses.push();
}
}
return hierarchy;
}
}