diff --git a/CHANGELOG.md b/CHANGELOG.md index d0efc6548..45788ff72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added ### Changed +- Refactor the compiler API used to access AST store (#326) ### Fixed diff --git a/src/grammar/store.ts b/src/grammar/store.ts index 1fd8b01d7..e40d2cca0 100644 --- a/src/grammar/store.ts +++ b/src/grammar/store.ts @@ -1,10 +1,24 @@ -import { ASTConstant, ASTFunction, ASTNativeFunction, ASTType } from "./ast"; +import { + ASTProgram, + ASTConstant, + ASTFunction, + ASTNativeFunction, + ASTType, +} from "./ast"; import { CompilerContext, createContextStore } from "../context"; import { parse } from "./grammar"; import { TypeOrigin } from "../types/types"; -type ASTStore = { - sources: { code: string; path: string }[]; +export type TactSource = { code: string; path: string; origin: TypeOrigin }; + +/** + * Represents the storage for all AST-related data within the compiler context. + * @property functions AST entries representing top-level functions. + * @property constants AST entries representing top-level constant definitions. + * @property types AST entries representing structures, contracts, and traits. + */ +export type ASTStore = { + sources: TactSource[]; funcSources: { code: string; path: string }[]; functions: (ASTFunction | ASTNativeFunction)[]; constants: ASTConstant[]; @@ -13,6 +27,12 @@ type ASTStore = { const store = createContextStore(); +/** + * Retrieves the raw AST for the given context. + * @param ctx The compiler context from which the AST is retrieved. + * @throws Will throw an error if the AST is not found in the context. + * @returns The AST types associated with the context. + */ export function getRawAST(ctx: CompilerContext) { const r = store.get(ctx, "types"); if (!r) { @@ -21,33 +41,45 @@ export function getRawAST(ctx: CompilerContext) { return r; } +/** + * Parses multiple Tact source files into AST programs. + */ +export function parsePrograms(sources: TactSource[]) { + return sources.map((source) => + parse(source.code, source.path, source.origin), + ); +} + +/** + * Extends the compiler context by adding AST entries and source information from + * given sources and parsed programs. + * @returns The updated compiler context. + */ export function openContext( ctx: CompilerContext, - sources: { code: string; path: string; origin: TypeOrigin }[], + programs: ASTProgram[], + sources: TactSource[], funcSources: { code: string; path: string }[], ) { - const asts = sources.map((source) => - parse(source.code, source.path, source.origin), - ); const types: ASTType[] = []; const functions: (ASTNativeFunction | ASTFunction)[] = []; const constants: ASTConstant[] = []; - for (const a of asts) { - for (const e of a.entries) { + for (const program of programs) { + for (const entry of program.entries) { if ( - e.kind === "def_struct" || - e.kind === "def_contract" || - e.kind === "def_trait" || - e.kind === "primitive" + entry.kind === "def_struct" || + entry.kind === "def_contract" || + entry.kind === "def_trait" || + entry.kind === "primitive" ) { - types.push(e); + types.push(entry); } else if ( - e.kind === "def_function" || - e.kind === "def_native_function" + entry.kind === "def_function" || + entry.kind === "def_native_function" ) { - functions.push(e); - } else if (e.kind === "def_constant") { - constants.push(e); + functions.push(entry); + } else if (entry.kind === "def_constant") { + constants.push(entry); } } } @@ -61,15 +93,16 @@ export function openContext( return ctx; } -// Creates a mock context with the given AST elements needed for testing -// purposes +/** + * Creates a mock compiler context for testing, populated with predefined AST elements. + */ export function openMockContext( ctx: CompilerContext, types: ASTType[], functions: (ASTNativeFunction | ASTFunction)[], constants: ASTConstant[], ) { - const sources: { code: string; path: string }[] = []; + const sources: TactSource[] = []; const funcSources: { code: string; path: string }[] = []; ctx = store.set(ctx, "types", { sources, diff --git a/src/pipeline/precompile.ts b/src/pipeline/precompile.ts index 7d951e873..ffb0e954a 100644 --- a/src/pipeline/precompile.ts +++ b/src/pipeline/precompile.ts @@ -1,7 +1,7 @@ import { CompilerContext } from "../context"; import { resolveDescriptors } from "../types/resolveDescriptors"; import { resolveAllocations } from "../storage/resolveAllocation"; -import { openContext } from "../grammar/store"; +import { openContext, parsePrograms } from "../grammar/store"; import { resolveStatements } from "../types/resolveStatements"; import { resolveErrors } from "../types/resolveErrors"; import { resolveSignatures } from "../types/resolveSignatures"; @@ -17,8 +17,11 @@ export function precompile( // Load all sources const imported = resolveImports({ entrypoint, project, stdlib }); - // Perform initial compiler steps - ctx = openContext(ctx, imported.tact, imported.func); + // Parse AST entries from Tact sources + const programs = parsePrograms(imported.tact); + + // Add information about all the source code entries to the context + ctx = openContext(ctx, programs, imported.tact, imported.func); // First load type descriptors and check that // they all have valid signatures