/** * The helpers that read a tree rather than describe one: the structural walk, * the two questions the parser, formatter and CLI ask about a statement, the * module's startup code, a test's emitted name, and the direct-await traversal. * * Everything here is a *reader*. The nodes it reads are declared in `nodes/`, * and nothing in `nodes/` reads back. */ import type { Span } from "../source.ts"; import type { AstNode, Expression, Program, Statement } from "./nodes/base.ts"; import type { TestDeclaration } from "./nodes/statements.ts"; export declare function isModuleDeclarationStatement(statement: Statement): boolean; /** * Whether the statement heads a suite of its own. * * Three readers need this one answer and had a copy each: the parser, which * refuses a block header as the whole of an inline `header: statement` body; * the formatter, which decides where a compact suite may be kept; and the * application-entry migration, which may only wrap a statement the inline * `@main:` body accepts. */ export declare function statementOwnsBlock(statement: Statement): boolean; /** * The module's startup code as it stands at the top level, which is where a * module that has no `@main` region keeps it. * * The parser refuses these statements outright once a `@main` exists, and the * CLI's application-entry contract refuses a *missing* `@main` — the same rule * read from its two ends. This is published so that the second end can tell the * one shape it can migrate mechanically from the shapes it must hand back. */ export interface ModuleStartupStatement { /** The statement's author span. */ readonly span: Span; /** `statementOwnsBlock`, carried so a caller holding no AST can still ask. */ readonly opensBlock: boolean; } export interface ModuleStartupCode { /** The top-level statements that are not declarations, in source order. */ readonly statements: readonly ModuleStartupStatement[]; /** True when the last of them is the module's final top-level statement — nothing declared follows it. */ readonly trailing: boolean; } export declare function moduleStartupCode(program: Program): ModuleStartupCode; /** The generated function name a `test "name":` block emits and the runner calls. */ export declare function testFunctionName(statement: TestDeclaration): string; /** * Every node under `root`, in source order, whatever shape it has. * * The walk is structural: it descends through arrays and objects without * asking what they are, so it reaches a container the day the parser produces * one — a new class member, a new statement form, an extension node this * package has never heard of — with nothing here to update. Only nodes are * reported, but the descent is unconditional, so an expression parked on a * shape that carries no `kind` of its own (a `Parameter`, a `MatchCase`) is * still reached through it. * * A pass that must not *miss* something walks with this instead of writing a * second switch over the node kinds it happens to remember. A-010: dependency * discovery kept such a switch, and `try`, `using`, `test "…":`, class * getters, `@dispose:` and `@iterate:` were all outside the module graph — * `@iterate:` from the day D68 added it, because a hand-kept copy of the AST * starts drifting the moment the AST grows. That copy compiled, exited 0, and * turned a module that exists and loads into `null`. */ export declare function astNodes(root: unknown): Generator; /** `astNodes` narrowed to one node kind, so a caller keeps the node's type. */ export declare function astNodesOfKind(root: unknown, kind: Node["kind"]): Generator; export type DirectAwaitExpressionExtension = (expression: Expression, contains: (expression: Expression) => boolean) => boolean | undefined; export type DirectAwaitStatementExtension = (statement: Statement, containsExpression: (expression: Expression) => boolean, containsBlock: (statements: readonly Statement[]) => boolean) => boolean | undefined; /** * Whether a block awaits in its own frame. A nested function or arrow owns its * awaits, so the walk stops at every declaration boundary. D43 item 69 uses * this to decide whether releasing a `@dispose` value needs an async scope. */ export declare function blockContainsDirectAwait(statements: readonly Statement[], expressionExtension?: DirectAwaitExpressionExtension, statementExtension?: DirectAwaitStatementExtension): boolean; export declare function statementContainsDirectAwait(statement: Statement, expressionExtension?: DirectAwaitExpressionExtension, statementExtension?: DirectAwaitStatementExtension): boolean; export declare function expressionContainsDirectAwait(expression: Expression, extension?: DirectAwaitExpressionExtension): boolean; //# sourceMappingURL=walk.d.ts.map