@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
125 lines (124 loc) • 6.63 kB
TypeScript
import type { NoInfo, RNode } from '../r-bridge/lang-4.x/ast/model/model';
import type { RExpressionList } from '../r-bridge/lang-4.x/ast/model/nodes/r-expression-list';
import type { RFunctionCall } from '../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import { EmptyArgument } from '../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import type { RFunctionDefinition } from '../r-bridge/lang-4.x/ast/model/nodes/r-function-definition';
import { RType } from '../r-bridge/lang-4.x/ast/model/type';
import type { RForLoop } from '../r-bridge/lang-4.x/ast/model/nodes/r-for-loop';
import type { RWhileLoop } from '../r-bridge/lang-4.x/ast/model/nodes/r-while-loop';
import type { RRepeatLoop } from '../r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop';
import type { RIfThenElse } from '../r-bridge/lang-4.x/ast/model/nodes/r-if-then-else';
import type { RBinaryOp } from '../r-bridge/lang-4.x/ast/model/nodes/r-binary-op';
import type { RPipe } from '../r-bridge/lang-4.x/ast/model/nodes/r-pipe';
import type { RUnaryOp } from '../r-bridge/lang-4.x/ast/model/nodes/r-unary-op';
import type { RParameter } from '../r-bridge/lang-4.x/ast/model/nodes/r-parameter';
import type { RArgument } from '../r-bridge/lang-4.x/ast/model/nodes/r-argument';
import type { RAccess } from '../r-bridge/lang-4.x/ast/model/nodes/r-access';
import type { RLogical } from '../r-bridge/lang-4.x/ast/model/nodes/r-logical';
import type { RBreak } from '../r-bridge/lang-4.x/ast/model/nodes/r-break';
import type { RComment } from '../r-bridge/lang-4.x/ast/model/nodes/r-comment';
import type { RNext } from '../r-bridge/lang-4.x/ast/model/nodes/r-next';
import type { RNumber } from '../r-bridge/lang-4.x/ast/model/nodes/r-number';
import type { RLineDirective } from '../r-bridge/lang-4.x/ast/model/nodes/r-line-directive';
import type { RString } from '../r-bridge/lang-4.x/ast/model/nodes/r-string';
import type { RSymbol } from '../r-bridge/lang-4.x/ast/model/nodes/r-symbol';
type FoldOfType<T extends RType, Returns = void, Info = NoInfo> = (node: Extract<RNode<Info>, {
type: T;
}>) => Returns;
/** explicitly excludes types that are not visitable */
export type FoldableRType = Exclude<RType, RType.Delimiter>;
/**
* Describes the fold functions for each node type.
*/
export type NormalizedAstFold<Returns = void, Info = NoInfo> = {
[K in FoldableRType as `fold${Capitalize<K>}`]: FoldOfType<K, Returns, Info>;
};
/**
* Describes the type of a mapping object,
* which maps the type of the normalized AST node to the corresponding fold function.
*/
export type FittingNormalizedAstFold<Returns = void, Info = NoInfo> = Readonly<{
[K in FoldableRType]: FoldOfType<K, Returns, Info>;
}>;
export type SingleOrArrayOrNothing<T> = T | readonly (T | null | undefined)[] | null | undefined;
export type EntryExitVisitor<Info> = ((node: RNode<Info>) => void) | undefined;
/**
* Default implementation of a fold over the normalized AST (using the classic fold traversal).
* To modify the behavior, please extend this class and overwrite the methods of interest.
* You can control the value passing (`Returns` generic)
* by providing sensible Monoid behavior overwriting the {@link DefaultNormalizedAstFold#concat|concat} method
* and supplying the empty value in the constructor.
*
* @note By providing `entry` and `exit` you can use this as an extension to the simpler {@link visitAst} function but without
* the early termination within the visitors (for this, you can overwrite the respective `fold*` methods).
*
* @example First you want to create your own fold:
*
* ```ts
* let marker = false;
* class MyNumberFold<Info> extends DefaultNormalizedAstFold<void, Info> {
* override foldRNumber(node: RNumber<Info>) {
* super.foldRNumber(node);
* marker = true;
* }
* }
* ```
* This one does explicitly not use the return functionality (and hence acts more as a conventional visitor).
* Now let us suppose we have a normalized AST as an {@link RNode} in the variable `ast`
* and want to check if the AST contains a number:
*
* ```ts
* const result = new MyNumberFold().fold(ast);
* ```
*
* Please take a look at the corresponding tests or the wiki pages for more information on how to use this fold.
*/
export declare class DefaultNormalizedAstFold<Returns = void, Info = NoInfo> implements NormalizedAstFold<Returns, Info> {
protected readonly enter: EntryExitVisitor<Info>;
protected readonly exit: EntryExitVisitor<Info>;
protected readonly empty: Returns;
/**
* Empty must provide a sensible default whenever you want to have `Returns` as non-`void`
* (e.g., whenever you want your visitors to be able to return a value).
*/
constructor(empty: Returns, enter?: EntryExitVisitor<Info>, exit?: EntryExitVisitor<Info>);
/**
* Monoid::concat
*
*
* @see {@link https://en.wikipedia.org/wiki/Monoid}
* @see {@link DefaultNormalizedAstFold#concatAll|concatAll}
*/
protected concat(_a: Returns, _b: Returns): Returns;
/**
* overwrite this method, if you have a faster way to concat multiple nodes
*
* @see {@link DefaultNormalizedAstFold#concatAll|concatAll}
*/
protected concatAll(nodes: readonly Returns[]): Returns;
fold(nodes: SingleOrArrayOrNothing<RNode<Info> | typeof EmptyArgument>): Returns;
protected foldSingle(node: RNode<Info>): Returns;
foldRAccess(access: RAccess<Info>): Returns;
foldRArgument(argument: RArgument<Info>): Returns;
foldRBinaryOp(binaryOp: RBinaryOp<Info>): Returns;
foldRExpressionList(exprList: RExpressionList<Info>): Returns;
foldRForLoop(loop: RForLoop<Info>): Returns;
foldRFunctionCall(call: RFunctionCall<Info>): Returns;
foldRFunctionDefinition(definition: RFunctionDefinition<Info>): Returns;
foldRIfThenElse(ite: RIfThenElse<Info>): Returns;
foldRParameter(parameter: RParameter<Info>): Returns;
foldRPipe(pipe: RPipe<Info>): Returns;
foldRRepeatLoop(loop: RRepeatLoop<Info>): Returns;
foldRUnaryOp(unaryOp: RUnaryOp<Info>): Returns;
foldRWhileLoop(loop: RWhileLoop<Info>): Returns;
foldRBreak(_node: RBreak<Info>): Returns;
foldRComment(_node: RComment<Info>): Returns;
foldRLineDirective(_node: RLineDirective<Info>): Returns;
foldRLogical(_node: RLogical<Info>): Returns;
foldRNext(_node: RNext<Info>): Returns;
foldRNumber(_node: RNumber<Info>): Returns;
foldRString(_node: RString<Info>): Returns;
foldRSymbol(_node: RSymbol<Info>): Returns;
protected readonly folds: FittingNormalizedAstFold<Returns, Info>;
}
export {};