@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
98 lines (97 loc) • 4.69 kB
TypeScript
/**
* The decoration module is tasked with taking an R-ast given by a {@link RNode} and
*
* 1. assigning a unique id to each node (see {@link IdGenerator})
* 2. transforming the AST into a doubly linked tree using the ids (so it stays serializable)
*
* The main entry point is {@link decorateAst}.
*
* @module
*/
import type { NoInfo, RNode } from '../model';
import type { SourceRange } from '../../../../../util/range';
import { BiMap } from '../../../../../util/collections/bimap';
import type { MergeableRecord } from '../../../../../util/objects';
import { RoleInParent } from './role';
import type { NodeId } from './node-id';
import type { RDelimiter } from '../nodes/info/r-delimiter';
/**
* A function that given an RNode returns a (guaranteed) unique id for it
* @param data - the node to generate an id for
*
* @returns a unique id for the given node
*/
export type IdGenerator<OtherInfo> = (data: RNode<OtherInfo>) => NodeId;
/**
* The simplest id generator which just increments a number on each call.
*/
export declare function deterministicCountingIdGenerator(id?: number): () => NodeId;
export declare function deterministicPrefixIdGenerator(prefix: string, id?: number): () => NodeId;
export declare function sourcedDeterministicCountingIdGenerator(path: string, location: SourceRange, start?: number): () => NodeId;
/**
* Generates the location id, used by {@link deterministicLocationIdGenerator}.
*
* @param data - the node to generate an id for, must have location information
*/
export declare function nodeToLocationId<OtherInfo>(data: RNode<OtherInfo> | RDelimiter): NodeId;
/**
* Generates unique ids based on the locations of the node (see {@link nodeToLocationId}).
* If a node has no location information, it will be assigned a unique counter-value.
*
* @param start - the start value for the counter, in case nodes do not have location information
*/
export declare function deterministicLocationIdGenerator<OtherInfo>(start?: number): IdGenerator<OtherInfo>;
export interface ParentContextInfo extends MergeableRecord {
role: RoleInParent;
/**
* The nesting of the node in the AST
*
* The root node has a nesting of 0, nested function calls, loops etc. will increase the nesting
*/
nesting: number;
/**
* 0-based index of the child in the parent (code semantics, e.g., for an if-then-else, the condition will be 0, the then-case will be 1, ...)
*
* The index is adaptive, that means that if the name of an argument exists, it will have index 0, and the value will have index 1.
* But if the argument is unnamed, its value will get the index 0 instead.
*/
index: number;
}
export interface ParentInformation extends ParentContextInfo {
/** uniquely identifies an AST-Node */
id: NodeId;
/** Links to the parent node, using an id so that the AST stays serializable */
parent: NodeId | undefined;
}
export type RNodeWithParent<OtherInfo = NoInfo> = RNode<OtherInfo & ParentInformation>;
export type AstIdMap<OtherInfo = NoInfo> = BiMap<NodeId, RNodeWithParent<OtherInfo>>;
/**
* Contains the normalized AST as a doubly linked tree
* and a map from ids to nodes so that parent links can be chased easily.
*/
export interface NormalizedAst<OtherInfo = ParentInformation, Node = RNode<OtherInfo & ParentInformation>> {
/** Bidirectional mapping of ids to the corresponding nodes and the other way */
idMap: AstIdMap<OtherInfo>;
/** The root of the AST with parent information */
ast: Node;
/** marks whether the AST contains potential syntax errors */
hasError?: boolean;
}
export interface NormalizedAstDecorationConfiguration<OtherInfo> {
/** The id generator: must generate a unique id für each passed node */
getId?: IdGenerator<OtherInfo>;
/** the path to the file this AST was extracted from will be added to the nodes */
file?: string;
}
/**
* Covert the given AST into a doubly linked tree while assigning ids (so it stays serializable).
*
* @param ast - The root of the AST to convert
* @param getId - The id generator: must generate a unique id für each passed node
* @param file - the path to the file this AST was extracted from will be added to the nodes
*
* @typeParam OtherInfo - The original decoration of the ast nodes (probably is nothing as the id decoration is most likely the first step to be performed after extraction)
*
* @returns A decorated AST based on the input and the id provider.
*/
export declare function decorateAst<OtherInfo = NoInfo>(ast: RNode<OtherInfo>, { getId, file }: NormalizedAstDecorationConfiguration<OtherInfo>): NormalizedAst<OtherInfo & ParentInformation>;