import type { Any } from '../interface'; import type { DvalaModule } from '../builtin/modules/interface'; import type { SourceMap, SymbolNode, UserDefinedSymbolNode } from '../parser/types'; import type { SourceCodeInfo } from '../tokenizer/token'; import type { Context, LookUpResult } from './interface'; interface CreateContextStackParams { globalContext?: Context; contexts?: Context[]; globalModuleScope?: boolean; } export type ContextStack = ContextStackImpl; /** * Resolves a file import path to source code. * * Called by the evaluator when it encounters `import("./path")`, `import("../path")`, * or `import("/path")`. Bare module names like `import("math")` are handled separately * as built-in modules and never reach the resolver. * * @param importPath - The import path as written in the source code (e.g. `"./lib/math"`) * @param fromDir - The directory of the file containing the import expression. * For the top-level file this is `fileResolverBaseDir`; for nested imports it's * the resolved directory of the importing file. * @returns The file's source code as a string * @throws Should throw if the file cannot be found */ export type FileResolver = (importPath: string, fromDir: string) => string; export declare class ContextStackImpl { private _contexts; globalContext: Context; private modules; private valueModules; pure: boolean; sourceMap?: SourceMap; fileResolver?: FileResolver; /** Directory of the currently evaluating file — used to resolve relative imports */ currentFileDir: string; /** Node ID allocator — shared with the parser so runtime imports get unique IDs */ allocateNodeId?: () => number; /** Whether debug mode (source map building) is active */ debug: boolean; private _resolvingFiles; constructor({ contexts, modules, valueModules, pure, sourceMap, fileResolver, currentFileDir, resolvingFiles, allocateNodeId, debug, }: { contexts: Context[]; modules?: Map; valueModules?: Map; pure?: boolean; sourceMap?: SourceMap; fileResolver?: FileResolver; currentFileDir?: string; resolvingFiles?: Set; allocateNodeId?: () => number; debug?: boolean; }); resolve(nodeId: number): SourceCodeInfo | undefined; /** Get the raw context chain for serialization. */ getContextsRaw(): Context[]; /** Get the top-level module scope as plain key→value bindings. */ getModuleScopeBindings(): Record; /** * Find the index of globalContext in the _contexts array. * Returns -1 if not found (should not happen in valid state). */ getGlobalContextIndex(): number; /** * Create a ContextStack from deserialized data. * `contexts` is the restored context chain (already resolved). * `globalContextIndex` identifies which element is the globalContext. */ static fromDeserialized(params: { contexts: Context[]; globalContextIndex: number; modules?: Map; pure: boolean; }): ContextStackImpl; /** * Replace the contexts array and globalContext. Used during deserialization * to fill in resolved context data after circular references are handled. */ setContextsFromDeserialized(contexts: Context[], globalContextIndex: number): void; getModule(name: string): DvalaModule | undefined; getValueModule(name: string): { value: unknown; found: boolean; }; registerValueModule(name: string, value: unknown): void; isResolvingFile(path: string): boolean; markFileResolving(path: string): void; unmarkFileResolving(path: string): void; create(context: Context): ContextStack; /** * Create a new ContextStack that shares all outer scopes but has an * independent shallow copy of the innermost context (`_contexts[0]`). * * Used for multi-shot continuations: `addValues` only mutates `_contexts[0]`, * so each resume call must get its own copy of that context. Without this, * the second resume would see bindings added by the first resume and throw * "Cannot redefine value". */ withCopiedTopContext(): ContextStack; new(context: Context): ContextStack; addValues(values: Record, sourceCodeInfo: SourceCodeInfo | undefined): void; getValue(name: string): unknown; lookUp(node: UserDefinedSymbolNode): LookUpResult; lookUpByName(name: string): LookUpResult; evaluateSymbol(node: SymbolNode): Any; } export declare function createContextStack(params?: CreateContextStackParams, modules?: Map, pure?: boolean, sourceMap?: SourceMap, fileResolver?: FileResolver, currentFileDir?: string, allocateNodeId?: () => number, debug?: boolean): ContextStack; export {};