@specs-feup/clava
Version:
A C/C++ source-to-source compiler written in Typescript
142 lines (126 loc) • 4.57 kB
text/typescript
import {
Expression,
Joinpoint,
ParenType,
PointerType,
Scope,
Statement,
Type,
VariableArrayType,
Varref,
} from "../Joinpoints.js";
import ClavaJoinPoints from "./ClavaJoinPoints.js";
import ClavaJavaTypes from "./ClavaJavaTypes.js";
/**
* Utility methods related with the type join points.
*
*/
export default class ClavaType {
/**
* @param type - The type to visit
* @param exprFunction - A function that receives an $expr join point
*
* @returns The $type after applying the given exprFunction to its $expr nodes. If any of the fields of the type is visited, a copy of the type is returned.
*/
static visitExprInTypeCopy(
$type: Type,
exprFunction: (expr: Expression) => void
): Type {
if ($type instanceof PointerType) {
const $typeCopy = $type.copy() as PointerType;
$typeCopy.setPointee(
ClavaType.visitExprInTypeCopy($typeCopy.pointee, exprFunction)
);
return $typeCopy;
}
if ($type instanceof ParenType) {
const $typeCopy = $type.copy() as ParenType;
$typeCopy.setDesugar(
ClavaType.visitExprInTypeCopy($typeCopy.desugar, exprFunction)
);
return $typeCopy;
}
if ($type instanceof VariableArrayType) {
const $typeCopy = $type.copy() as VariableArrayType;
$typeCopy.setSizeExpr($typeCopy.sizeExpr.copy() as Expression);
exprFunction($typeCopy.sizeExpr);
return $typeCopy;
}
return $type;
}
/**
* @param type - A type join point that will be visited looking for $expr join points. Any visited nodes in the type (e.g., desugar) will be copied, so that the returned varrefs can be safely modified.
* @param varrefs - An array (possibly empty) where the $varref join points found in the given type will be stored
*
* @returns A copy of the given $type, to which the varrefs refer to
*/
static getVarrefsInTypeCopy($type: Type, varrefs: Varref[]) {
const exprFunction = function ($expr: Expression) {
for (const $varref of $expr.getDescendantsAndSelf("varref") as Varref[]) {
varrefs.push($varref);
}
};
return ClavaType.visitExprInTypeCopy($type, exprFunction);
}
/**
* Makes sure the given parameter is an expression join point.
*
* @param $expression - If a string, returns a literal expression with the code of the string. Otherwise, returns $expression
* @param isOptional - If false and $expression is undefined, throws an exception. Otherwise, returns undefined if $expression is undefined.
*/
static asExpression(
$expression: Expression | undefined,
isOptional = false
): Expression | undefined {
if ($expression === undefined) {
if (isOptional) {
return undefined;
} else {
throw "ClavaType.asExpression: $expression is undefined. If this is allowed, set 'isOptional' to true.";
}
}
return $expression;
}
/**
* Makes sure the given parameter is a statement join point.
*
* @param code - If a string, returns a literal statement with the code of the string. Otherwise, tries to transform the given node to a $statement
* @param isOptional - If false and code is undefined, throws an exception. Otherwise, returns undefined if code is undefined.
*/
static asStatement(
code: Joinpoint | undefined,
isOptional = false
): Statement | undefined {
if (code === undefined) {
if (isOptional) {
return undefined;
} else {
throw "ClavaType.asStatement: code is undefined. If this is allowed, set 'isOptional' to true.";
}
}
const newStmtNode = ClavaJavaTypes.ClavaNodes.toStmt(code.node);
return ClavaJoinPoints.toJoinPoint(newStmtNode) as Statement;
}
/**
* Makes sure the given parameter is a type join point.
*
* @param $type - If a string, returns a literal type with the code of the string. Otherwise, returns $type
*
* @deprecated This method does not do anything, it is only kept for compatibility with the old API
*/
static asType($type: Type): Type {
return $type;
}
/**
* Makes sure the given parameter is a scope join point.
*
* @param code - If a string, returns a literal statement with the code of the string. Otherwise, returns $statement
*/
static asScope(code: Joinpoint | undefined): Scope {
const $newStmt = ClavaType.asStatement(code);
const newScopeNode = ClavaJavaTypes.ClavaNodes.toCompoundStmt(
$newStmt?.node
);
return ClavaJoinPoints.toJoinPoint(newScopeNode) as Scope;
}
}