@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
100 lines (99 loc) • 4.9 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 { RType } from '../type';
import type { NodeId } from './node-id';
import type { RDelimiter } from '../nodes/info/r-delimiter';
import type { RProject } from '../nodes/r-project';
/**
* 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: RProject<OtherInfo> | RNode<OtherInfo>) => NodeId;
/**
* The simplest id generator which just increments a number on each call.
*/
export declare function deterministicCountingIdGenerator(id?: number): () => NodeId;
/**
* Generates ids with a fixed prefix and an incrementing counter.
*/
export declare function deterministicPrefixIdGenerator(prefix: string, id?: number): () => NodeId;
/**
* Generates ids with a fixed source path and location information as prefix and an incrementing counter.
*/
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, contexts listed in ${@link nestForElement} 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 = RProject<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;
}
/**
* Node types for which the nesting score will be increased
*/
export declare const nestForElement: ReadonlySet<RType>;
export interface NormalizedAstDecorationConfiguration<OtherInfo> {
/** The id generator: must generate a unique id für each passed node */
getId?: IdGenerator<OtherInfo>;
}
/**
* Covert the given AST into a doubly linked tree while assigning ids (so it stays serializable).
* @param project - The AST to decorate
* @param getId - The id generator: must generate a unique id für each passed node
* @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>(project: RProject<OtherInfo>, { getId }: NormalizedAstDecorationConfiguration<OtherInfo>): NormalizedAst<OtherInfo & ParentInformation>;