import type { Vertex } from './vertex'; import { SpreadsheetVertex } from './spreadsheet_vertex'; import type { SpreadsheetVertexBase, CalculationResult, GraphCallbacks } from './spreadsheet_vertex_base'; import type { StateLeafVertex } from './state_leaf_vertex'; import type { ICellAddress, IArea, UnionValue } from '../../../treb-base-types/src/index'; import { Area } from '../../../treb-base-types/src/index'; import type { DataModel } from '../../../treb-data-model/src/index'; import { CalculationLeafVertex } from './calculation_leaf_vertex'; export type LeafVertex = StateLeafVertex | CalculationLeafVertex; export type { StateLeafVertex }; export declare enum GraphStatus { OK = 0, Loop = 1, CalculationError = 2 } /** * graph is now abstract, as we are extending it with the calculator. */ export declare abstract class Graph implements GraphCallbacks { /** * list of vertices, indexed by address as [sheet id][column][row] */ vertices: Array>>; volatile_list: SpreadsheetVertexBase[]; calculation_list: SpreadsheetVertexBase[]; spill_data: { area: IArea; vertex: StateLeafVertex; }[]; protected abstract readonly model: DataModel; /** * where is the loop in the graph (or at least the first one we found)? */ loop_hint?: string; leaf_vertices: Set; /** lock down access */ private dirty_list; /** flag set on add edge */ private loop_check_required; IsSpreadsheetVertex(vertex: Vertex): vertex is SpreadsheetVertex; /** * flush the graph, calculation tree and cells reference */ FlushTree(): void; ResolveArrayHead(address: ICellAddress): ICellAddress; /** * iterate vertices * @param area */ IterateVertices(area: IArea, create?: boolean): Generator; /** overload */ GetVertex(address: ICellAddress, create: true): SpreadsheetVertex; /** overload */ GetVertex(address: ICellAddress, create?: boolean): SpreadsheetVertex | undefined; /** deletes the vertex at this address. */ RemoveVertex(address: ICellAddress): void; /** removes all edges, for rebuilding. leaves value/formula as-is. */ ResetVertex(address: ICellAddress): void; RIBcount: number; /** * resets the vertex by removing inbound edges and clearing formula flag. * we have an option to set dirty because they get called together * frequently, saves a lookup. */ ResetInbound(address: ICellAddress, set_dirty?: boolean, create?: boolean, remove?: boolean): void; /** * reset all vertices. this method is used so we can run the loop check * as part of the graph calculation, instead of requiring the separate call. */ ResetLoopState(): void; /** * global check returns true if there is any loop. this is more efficient * than detecting loops on every call to AddEdge. uses the color algorithm * from CLRS. * * UPDATE we switched to a stack-based check because we were hitting * recursion limits, although that seemed to only happen in workers -- * perhaps they have different stack [in the malloc sense] sizes? in any * event, I think the version below is now stable. * * @param force force a check, for dev/debug */ LoopCheck(force?: boolean): boolean; /** * render address as string; this is for reporting loops */ RenderAddress(address?: ICellAddress): string; /** * new array vertices */ protected CompositeAddArrayEdge(u: Area, vertex: Vertex): void; AddLeafVertexArrayEdge(u: Area, vertex: LeafVertex): void; /** * new array vertices */ AddArrayEdge(u: Area, v: ICellAddress): void; /** adds an edge from u -> v */ AddEdge(u: ICellAddress, v: ICellAddress): void; /** removes edge from u -> v */ RemoveEdge(u: ICellAddress, v: ICellAddress): void; /** * not used? remove * @deprecated */ SetAreaDirty(area: IArea): void; SetVertexDirty(vertex: SpreadsheetVertexBase): void; /** sets dirty */ SetDirty(address: ICellAddress): void; /** * adds a leaf vertex to the graph. this implies that someone else is * managing and maintaining these vertices: we only need references. */ AddLeafVertex(vertex: LeafVertex): void; /** removes vertex */ RemoveLeafVertex(vertex: LeafVertex): void; /** * adds an edge from u -> v where v is a leaf vertex. this doesn't use * the normal semantics, and you must pass in the actual vertex instead * of an address. * * there is no loop check (leaves are not allowed to have outbound * edges). */ AddLeafVertexEdge(u: ICellAddress, v: LeafVertex): GraphStatus; /** removes edge from u -> v */ RemoveLeafVertexEdge(u: ICellAddress, v: LeafVertex): void; InitializeGraph(): void; /** runs calculation */ Recalculate(): void; abstract CalculationCallback(vertex: SpreadsheetVertexBase): CalculationResult; abstract SpreadCallback(vertex: SpreadsheetVertexBase, value: UnionValue): void; abstract SpillCallback(vertex: SpreadsheetVertexBase, value: UnionValue): void; protected abstract CheckVolatile(vertex: SpreadsheetVertex): boolean; }