@specs-feup/lara
Version:
A js port of the popular framework for building source-to-source compilers
152 lines • 4.77 kB
JavaScript
import { wrapJoinPoint } from "../LaraJoinPoint.js";
import Weaver from "./Weaver.js";
/**
* Object which provides low-level join point-related methods.
*/
export default class JoinPoints {
/**
*
* @returns the current root node of the AST
*/
static root() {
return wrapJoinPoint(Weaver.getWeaverEngine().getRootJp());
}
/**
* Converts an AST node to a JointPoint.
*
*/
static toJoinPoint(node) {
throw new Error("JoinPoints.toJoinPoint: not implemented");
}
/**
*
* @returns all the children of the given node
*/
static _all_children($jp) {
return $jp.children;
}
/**
*
* @returns all the descendants of the given node
*/
static _all_descendants($jp) {
return $jp.descendants;
}
/**
*
* @returns all the nodes that are inside the scope of a given node
*/
static _all_scope_nodes($jp) {
return $jp.scopeNodes;
}
/**
*
* @returns all the descendants of the given node, in post order
*/
static _all_descendants_postorder($jp, includeSelf = false) {
const result = [];
for (const child of JoinPoints._all_children($jp)) {
result.push(...JoinPoints._all_descendants_postorder(child, true));
}
if (includeSelf) {
result.push($jp);
}
return result;
}
/**
*
* @returns the nodes inside the scope of the given node.
*/
static scope($jp, jpType) {
return JoinPoints._getNodes(jpType, JoinPoints._all_scope_nodes($jp));
}
/**
*
* @returns the children of the given node, according to the AST
*/
static children($jp, jpType) {
return JoinPoints._getNodes(jpType, JoinPoints._all_children($jp));
}
/**
*
* @returns the descendants of the given node, according to the AST, preorder traversal
*/
static descendants($jp, jpType) {
return JoinPoints._getNodes(jpType, JoinPoints._all_descendants($jp));
}
/**
*
* @returns the descendants of the given node, according to the AST, postorder traversal
*/
static descendantsPostorder($jp, jpType) {
return JoinPoints._getNodes(jpType, JoinPoints._all_descendants_postorder($jp));
}
/**
*
* @returns the nodes related with the given node, according to the search function
*/
static _getNodes(jpType, $allJps = []) {
// TODO: This function can be optimized by using streaming
if (jpType === undefined) {
return $allJps;
}
return $allJps.filter((jp) => jpType.isInstance(jp));
}
/**
* Iterates of attributeNames, returns the first value that is not null or undefined.
* If no value is found for the given attributes, returns undefined
*
* @deprecated Just don't...
*/
static getAttribute($jp, attributeNames) {
for (const attribute of attributeNames) {
const value = Object.getOwnPropertyDescriptor($jp, attribute)?.value;
if (value !== undefined) {
return value;
}
}
return undefined;
}
/**
* Helper method of getAttribute which throws an exception if no value is found
*
* @deprecated Just don't...
*/
static getAttributeStrict($jp, attributeNames) {
const value = this.getAttribute($jp, attributeNames);
if (value === undefined) {
throw ("Could not find any of the given attributes in " +
$jp.toString() +
":" +
attributeNames.join(", "));
}
return value;
}
/**
* Converts the join point to a string of code. Expects attribute 'code' to exist.
*
* @param $jp - join point to convert to code.
*
* @returns a String with the code representation of this join point.
*/
static getCode($jp) {
const property = "code";
for (let obj = $jp; obj !== null; obj = Object.getPrototypeOf(obj)) {
const descriptor = Object.getOwnPropertyDescriptor(obj, property);
if (descriptor !== undefined) {
let attributeValue = undefined;
if (Object.getOwnPropertyDescriptor(descriptor, "get")) {
return descriptor.get?.call?.($jp);
}
else if (Object.getOwnPropertyDescriptor(descriptor, "value")) {
return descriptor.value;
}
else {
continue;
}
}
}
throw "JoinPoints.getCode(): expected attribute 'code' to exist";
}
}
//# sourceMappingURL=JoinPoints.js.map