UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

120 lines (119 loc) 6.63 kB
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, 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 { 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'; import { RProject } from '../r-bridge/lang-4.x/ast/model/nodes/r-project'; 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 | RType.Project>; /** * 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 | RProject<Info>>): 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 {};