@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
73 lines (72 loc) • 4.4 kB
TypeScript
import type { DeepReadonly } from 'ts-essentials';
import type { RNode } from '../model';
import type { RNumber } from '../nodes/r-number';
import type { RString } from '../nodes/r-string';
import type { RLogical } from '../nodes/r-logical';
import type { RSymbol } from '../nodes/r-symbol';
import type { RAccess } from '../nodes/r-access';
import type { RBinaryOp } from '../nodes/r-binary-op';
import type { RPipe } from '../nodes/r-pipe';
import type { RUnaryOp } from '../nodes/r-unary-op';
import type { RFunctionCall } from '../nodes/r-function-call';
import { EmptyArgument } from '../nodes/r-function-call';
import type { RForLoop } from '../nodes/r-for-loop';
import type { RWhileLoop } from '../nodes/r-while-loop';
import type { RRepeatLoop } from '../nodes/r-repeat-loop';
import type { RNext } from '../nodes/r-next';
import type { RBreak } from '../nodes/r-break';
import type { RComment } from '../nodes/r-comment';
import type { RLineDirective } from '../nodes/r-line-directive';
import type { RIfThenElse } from '../nodes/r-if-then-else';
import type { RExpressionList } from '../nodes/r-expression-list';
import type { RFunctionDefinition } from '../nodes/r-function-definition';
import type { RArgument } from '../nodes/r-argument';
import type { RParameter } from '../nodes/r-parameter';
/**
* Called during the down-pass, will pe propagated to children and used in the up-pass (see {@link StatefulFoldFunctions}).
* <p>
* Exists for leafs as well for consistency reasons.
*/
export type DownFold<Info, Down> = (node: RNode<Info>, down: Down) => Down;
/**
* All fold functions besides `down` are called after the down-pass in conventional fold-fashion.
* The `down` argument holds information obtained during the down-pass, issued by the `down` function.
*/
export interface StatefulFoldFunctions<Info, Down, Up> {
down: DownFold<Info, Down>;
foldNumber: (num: RNumber<Info>, down: Down) => Up;
foldString: (str: RString<Info>, down: Down) => Up;
foldLogical: (logical: RLogical<Info>, down: Down) => Up;
foldSymbol: (symbol: RSymbol<Info>, down: Down) => Up;
foldAccess: (node: RAccess<Info>, name: Up, access: readonly (typeof EmptyArgument | Up)[], down: Down) => Up;
foldBinaryOp: (op: RBinaryOp<Info>, lhs: Up, rhs: Up, down: Down) => Up;
foldPipe: (op: RPipe<Info>, lhs: Up, rhs: Up, down: Down) => Up;
foldUnaryOp: (op: RUnaryOp<Info>, operand: Up, down: Down) => Up;
loop: {
foldFor: (loop: RForLoop<Info>, variable: Up, vector: Up, body: Up, down: Down) => Up;
foldWhile: (loop: RWhileLoop<Info>, condition: Up, body: Up, down: Down) => Up;
foldRepeat: (loop: RRepeatLoop<Info>, body: Up, down: Down) => Up;
foldNext: (next: RNext<Info>, down: Down) => Up;
foldBreak: (next: RBreak<Info>, down: Down) => Up;
};
other: {
foldComment: (comment: RComment<Info>, down: Down) => Up;
foldLineDirective: (comment: RLineDirective<Info>, down: Down) => Up;
};
/** The `otherwise` argument is `undefined` if the `else` branch is missing */
foldIfThenElse: (ifThenExpr: RIfThenElse<Info>, cond: Up, then: Up, otherwise: Up | undefined, down: Down) => Up;
foldExprList: (exprList: RExpressionList<Info>, grouping: [start: Up, end: Up] | undefined, expressions: Up[], down: Down) => Up;
functions: {
foldFunctionDefinition: (definition: RFunctionDefinition<Info>, params: Up[], body: Up, down: Down) => Up;
/** folds named and unnamed function calls */
foldFunctionCall: (call: RFunctionCall<Info>, functionNameOrExpression: Up, args: (Up | typeof EmptyArgument)[], down: Down) => Up;
/** The `name` is `undefined` if the argument is unnamed, the value, if we have something like `x=,...` */
foldArgument: (argument: RArgument<Info>, name: Up | undefined, value: Up | undefined, down: Down) => Up;
/** The `defaultValue` is `undefined` if the argument was not initialized with a default value */
foldParameter: (parameter: RParameter<Info>, name: Up, defaultValue: Up | undefined, down: Down) => Up;
};
}
/**
* Folds in old functional-fashion over the AST structure but allowing for a down function which can pass context to child nodes.
*/
export declare function foldAstStateful<Info, Down, Up>(ast: RNode<Info>, down: Down, folds: DeepReadonly<StatefulFoldFunctions<Info, Down, Up>>): Up;