diff --git a/packages/cxx-frontend/src/Parser.ts b/packages/cxx-frontend/src/Parser.ts index b1f90742..33bacd24 100644 --- a/packages/cxx-frontend/src/Parser.ts +++ b/packages/cxx-frontend/src/Parser.ts @@ -22,7 +22,7 @@ import initCxx, { cxx } from "./cxx"; import { Unit } from "./Unit"; import { AST } from "./AST"; -interface ParseParams { +interface ParserParams { /** * Path to the file to parse. */ @@ -32,6 +32,12 @@ interface ParseParams { * Source code to parse. */ source: string; + + resolve?: ( + name: string, + kind: "quoted" | "angled", + next: boolean, + ) => Promise; } export class Parser { @@ -69,8 +75,8 @@ export class Parser { return cxx !== undefined && cxx !== null; } - constructor(options: ParseParams) { - const { path, source } = options; + constructor(options: ParserParams) { + const { path, source, resolve } = options; if (typeof path !== "string") { throw new TypeError("expected parameter 'path' of type 'string'"); @@ -80,14 +86,14 @@ export class Parser { throw new TypeError("expected parameter 'source' of type 'string'"); } - this.#unit = cxx.createUnit(source, path); + this.#unit = cxx.createUnit(source, path, { resolve }); } - parse() { + async parse() { if (!this.#unit) { return; } - this.#unit.parse(); + await this.#unit.parse(); this.#ast = AST.from(this.#unit.getHandle(), this); } diff --git a/packages/cxx-frontend/src/Preprocessor.ts b/packages/cxx-frontend/src/Preprocessor.ts index 34b55171..e6713ed9 100644 --- a/packages/cxx-frontend/src/Preprocessor.ts +++ b/packages/cxx-frontend/src/Preprocessor.ts @@ -22,11 +22,6 @@ import { cxx } from "./cxx"; interface PreprocessorOptions { systemIncludePaths?: string[]; - - fs?: { - existsSync(path: string): boolean; - readFileSync(path: string): string; - }; } export class Preprocessor { @@ -39,7 +34,7 @@ export class Preprocessor { * * @param source */ - constructor({ systemIncludePaths, fs }: PreprocessorOptions = {}) { + constructor({ systemIncludePaths }: PreprocessorOptions = {}) { this.#control = new cxx.Control(); this.#diagnosticClient = new cxx.DiagnosticsClient(); this.#handle = new cxx.Preprocessor(this.#control, this.#diagnosticClient); @@ -48,13 +43,6 @@ export class Preprocessor { systemIncludePaths?.forEach((path) => { this.#handle.addIncludePath(path); }); - - if (fs) { - const { existsSync, readFileSync } = fs; - - this.#handle.setCanResolveFiles(true); - this.#handle.setup(existsSync, readFileSync); - } } /** diff --git a/packages/cxx-frontend/src/Unit.ts b/packages/cxx-frontend/src/Unit.ts index 5e522e63..a28d7cda 100644 --- a/packages/cxx-frontend/src/Unit.ts +++ b/packages/cxx-frontend/src/Unit.ts @@ -22,7 +22,7 @@ import { Diagnostic } from "./Diagnostic"; export interface Unit { delete(): void; - parse(): boolean; + parse(): Promise; getHandle(): number; getUnitHandle(): number; getDiagnostics(): Diagnostic[]; diff --git a/packages/cxx-frontend/src/cxx-js.d.ts b/packages/cxx-frontend/src/cxx-js.d.ts index 4c2f9930..b1f0a6d2 100644 --- a/packages/cxx-frontend/src/cxx-js.d.ts +++ b/packages/cxx-frontend/src/cxx-js.d.ts @@ -83,6 +83,14 @@ interface Lexer { tokenText(): string; } +interface Api { + resolve?: ( + name: string, + kind: "quoted" | "angled", + isIncludeNext: boolean, + ) => Promise; +} + export type CXX = { Control: Control; DiagnosticsClient: DiagnosticsClient; @@ -90,7 +98,7 @@ export type CXX = { Lexer: Lexer; TranslationUnit: TranslationUnit; - createUnit(source: string, path: string): Unit; + createUnit(source: string, path: string, api: Api): Unit; getASTKind(handle: number): number; getASTSlot(handle: number, slot: number): number; getASTSlotKind(handle: number, slot: number): ASTSlotKind; diff --git a/src/js/cxx/api.cc b/src/js/cxx/api.cc index 1dfcfe08..a1cf6474 100644 --- a/src/js/cxx/api.cc +++ b/src/js/cxx/api.cc @@ -32,6 +32,7 @@ #include #include +#include #include using namespace emscripten; @@ -61,42 +62,121 @@ struct DiagnosticsClient final : cxx::DiagnosticsClient { struct WrappedUnit { std::unique_ptr diagnosticsClient; std::unique_ptr unit; + val api; - WrappedUnit(std::string source, std::string filename) { + WrappedUnit(std::string source, std::string filename, val api = {}) + : api(api) { diagnosticsClient = std::make_unique(); + unit = std::make_unique(diagnosticsClient.get()); + if (auto preprocessor = unit->preprocessor()) { - preprocessor->setCanResolveFiles(false); + preprocessor->setCanResolveFiles(true); } - unit->setSource(std::move(source), std::move(filename)); + unit->beginPreprocessing(std::move(source), std::move(filename)); + } + + auto getUnitHandle() const -> std::intptr_t { + return (std::intptr_t)unit.get(); } - std::intptr_t getUnitHandle() const { return (std::intptr_t)unit.get(); } + auto getHandle() const -> std::intptr_t { return (std::intptr_t)unit->ast(); } - std::intptr_t getHandle() const { return (std::intptr_t)unit->ast(); } + auto getDiagnostics() const -> val { return diagnosticsClient->messages; } - val getDiagnostics() const { return diagnosticsClient->messages; } + auto parse() -> val { + val resolve = val::undefined(); + + if (!api.isUndefined()) { + resolve = api["resolve"]; + } + + struct { + auto operator()(const cxx::SystemInclude& include) -> val { + return val(include.fileName); + } + auto operator()(const cxx::QuoteInclude& include) -> val { + return val(include.fileName); + } + } getHeaderName; + + struct { + val quoted{"quoted"}; + val angled{"angled"}; + + auto operator()(const cxx::SystemInclude& include) -> val { + return angled; + } + auto operator()(const cxx::QuoteInclude& include) -> val { + return quoted; + } + } getIncludeType; + + while (true) { + auto state = unit->continuePreprocessing(); + + if (std::holds_alternative(state)) break; + + if (auto pendingInclude = std::get_if(&state)) { + if (resolve.isUndefined()) { + pendingInclude->resolveWith(std::nullopt); + continue; + } + + auto header = std::visit(getHeaderName, pendingInclude->include); + auto includeType = std::visit(getIncludeType, pendingInclude->include); + + val resolved = co_await resolve(header, includeType, + pendingInclude->isIncludeNext); + + if (resolved.isString()) { + pendingInclude->resolveWith(resolved.as()); + } else { + pendingInclude->resolveWith(std::nullopt); + } + + } else if (auto pendingHasIncludes = + std::get_if(&state)) { + for (auto& request : pendingHasIncludes->requests) { + if (resolve.isUndefined()) { + request.setExists(false); + continue; + } + + auto header = std::visit(getHeaderName, request.include); + auto includeType = std::visit(getIncludeType, request.include); + + val resolved = + co_await resolve(header, includeType, request.isIncludeNext); + + request.setExists(resolved.isString()); + } + } + } + + unit->endPreprocessing(); - bool parse() { unit->parse(); - return true; + + co_return val{true}; } }; -std::string getTokenText(std::intptr_t handle, std::intptr_t unitHandle) { +auto getTokenText(std::intptr_t handle, std::intptr_t unitHandle) + -> std::string { auto unit = reinterpret_cast(unitHandle); auto text = unit->tokenText(cxx::SourceLocation(handle)); return text; } -int getTokenKind(std::intptr_t handle, std::intptr_t unitHandle) { +auto getTokenKind(std::intptr_t handle, std::intptr_t unitHandle) -> int { auto unit = reinterpret_cast(unitHandle); auto kind = unit->tokenKind(cxx::SourceLocation(handle)); return static_cast(kind); } -val getTokenLocation(std::intptr_t handle, std::intptr_t unitHandle) { +auto getTokenLocation(std::intptr_t handle, std::intptr_t unitHandle) -> val { auto unit = reinterpret_cast(unitHandle); cxx::SourceLocation loc(handle); @@ -114,71 +194,71 @@ val getTokenLocation(std::intptr_t handle, std::intptr_t unitHandle) { return result; } -val getStartLocation(std::intptr_t handle, std::intptr_t unitHandle) { +auto getStartLocation(std::intptr_t handle, std::intptr_t unitHandle) -> val { auto ast = reinterpret_cast(handle); const auto loc = ast->firstSourceLocation(); if (!loc) return {}; return getTokenLocation(loc.index(), unitHandle); } -val getEndLocation(std::intptr_t handle, std::intptr_t unitHandle) { +auto getEndLocation(std::intptr_t handle, std::intptr_t unitHandle) -> val { auto ast = reinterpret_cast(handle); const auto loc = ast->lastSourceLocation().previous(); if (!loc) return {}; return getTokenLocation(loc.index(), unitHandle); } -val getIdentifierValue(std::intptr_t handle) { +auto getIdentifierValue(std::intptr_t handle) -> val { auto id = reinterpret_cast(handle); if (!id) return {}; return val(id->value()); } -val getLiteralValue(std::intptr_t handle) { +auto getLiteralValue(std::intptr_t handle) -> val { auto id = reinterpret_cast(handle); if (!id) return {}; return val(id->value()); } -int getASTKind(std::intptr_t handle) { +auto getASTKind(std::intptr_t handle) -> int { return static_cast(((cxx::AST*)handle)->kind()); } -int getListValue(std::intptr_t handle) { +auto getListValue(std::intptr_t handle) -> int { auto list = reinterpret_cast*>(handle); return std::intptr_t(list->value); } -std::intptr_t getListNext(std::intptr_t handle) { +auto getListNext(std::intptr_t handle) -> std::intptr_t { auto list = reinterpret_cast*>(handle); return std::intptr_t(list->next); } -std::intptr_t getASTSlot(std::intptr_t handle, int slot) { +auto getASTSlot(std::intptr_t handle, int slot) -> std::intptr_t { auto ast = reinterpret_cast(handle); auto [value, slotKind, slotNameIndex, slotCount] = getSlot(ast, slot); return value; } -int getASTSlotKind(std::intptr_t handle, int slot) { +auto getASTSlotKind(std::intptr_t handle, int slot) -> int { auto ast = reinterpret_cast(handle); auto [value, slotKind, slotNameIndex, slotCount] = getSlot(ast, slot); return static_cast(slotKind); } -int getASTSlotName(std::intptr_t handle, int slot) { +auto getASTSlotName(std::intptr_t handle, int slot) -> int { auto ast = reinterpret_cast(handle); auto [value, slotKind, slotName, slotCount] = getSlot(ast, slot); return static_cast(slotName); } -int getASTSlotCount(std::intptr_t handle, int slot) { +auto getASTSlotCount(std::intptr_t handle, int slot) -> int { auto ast = reinterpret_cast(handle); auto [value, slotKind, slotNameIndex, slotCount] = getSlot(ast, slot); return static_cast(slotCount); } -WrappedUnit* createUnit(std::string source, std::string filename) { +auto createUnit(std::string source, std::string filename) -> WrappedUnit* { auto wrapped = new WrappedUnit(std::move(source), std::move(filename)); return wrapped; @@ -196,17 +276,6 @@ auto lexerNext(cxx::Lexer& lexer) -> int { return static_cast(lexer.next()); } -void preprocessorSetup(cxx::Preprocessor& preprocessor, val fileExistsFn, - val readFileFn) { - preprocessor.setFileExistsFunction([fileExistsFn](std::string fileName) { - return fileExistsFn(fileName).as(); - }); - - preprocessor.setReadFileFunction([readFileFn](std::string fileName) { - return readFileFn(fileName).as(); - }); -} - auto preprocesorPreprocess(cxx::Preprocessor& preprocessor, std::string source, std::string filename) -> std::string { std::vector tokens; @@ -241,7 +310,6 @@ auto register_preprocessor(const char* name = "Preprocessor") return class_(name) .constructor() .function("preprocess", &preprocesorPreprocess) - .function("setup", &preprocessorSetup) .function("addIncludePath", &cxx::Preprocessor::addSystemIncludePath) .function("defineMacro", &cxx::Preprocessor::defineMacro) .function("undefineMacro", &cxx::Preprocessor::undefMacro) @@ -283,7 +351,7 @@ auto register_translation_unit(const char* name = "TranslationUnit") } // namespace -EMSCRIPTEN_BINDINGS(my_module) { +EMSCRIPTEN_BINDINGS(cxx) { register_control(); register_diagnostics_client(); register_preprocessor(); diff --git a/src/parser/cxx/cxx_fwd.h b/src/parser/cxx/cxx_fwd.h index b9deef94..0586158e 100644 --- a/src/parser/cxx/cxx_fwd.h +++ b/src/parser/cxx/cxx_fwd.h @@ -20,7 +20,6 @@ #pragma once -#include #include namespace cxx { diff --git a/src/parser/cxx/literals.h b/src/parser/cxx/literals.h index 8d87a11d..83166396 100644 --- a/src/parser/cxx/literals.h +++ b/src/parser/cxx/literals.h @@ -20,6 +20,7 @@ #include +#include #include #include diff --git a/src/parser/cxx/preprocessor.cc b/src/parser/cxx/preprocessor.cc index 68c3ac07..2730eb4e 100644 --- a/src/parser/cxx/preprocessor.cc +++ b/src/parser/cxx/preprocessor.cc @@ -687,7 +687,6 @@ struct Preprocessor::Private { Control *control_ = nullptr; DiagnosticsClient *diagnosticsClient_ = nullptr; CommentHandler *commentHandler_ = nullptr; - PreprocessorDelegate *delegate_ = nullptr; bool canResolveFiles_ = true; std::vector systemIncludePaths_; std::vector quoteIncludePaths_; @@ -702,8 +701,6 @@ struct Preprocessor::Private { std::vector skipping_; std::string_view date_; std::string_view time_; - std::function fileExists_; - std::function readFile_; std::function willIncludeHeader_; std::vector buffers_; struct Dep { @@ -713,7 +710,7 @@ struct Preprocessor::Private { bool exists = false; }; std::vector dependencies_; - std::function continuation_; + std::functionstd::optional> continuation_; int localCount_ = 0; int counter_ = 0; @@ -1004,12 +1001,10 @@ struct Preprocessor::Private { } [[nodiscard]] auto fileExists(const fs::path &file) const -> bool { - if (fileExists_) return fileExists_(file.string()); return fs::exists(file); } [[nodiscard]] auto readFile(const fs::path &file) const -> std::string { - if (readFile_) return readFile_(file.string()); std::ifstream in(file); std::ostringstream out; out << in.rdbuf(); @@ -1021,12 +1016,23 @@ struct Preprocessor::Private { [[nodiscard]] auto checkPragmaOnceProtected(TokList *ts) const -> bool; struct Resolve { + enum struct Mode { + kFirst, + kAll, + }; + const Private *d; bool wantNextInlude; bool didFindCurrentPath = false; std::optional firstMatch; + Mode mode; + std::vector candidates; + + Resolve(const Resolve &other) = delete; + auto operator=(const Resolve &other) -> Resolve & = delete; - Resolve(const Private *d, bool next) : d(d), wantNextInlude(next) {} + Resolve(const Private *d, bool next, Mode mode = Mode::kFirst) + : d(d), wantNextInlude(next), mode(mode) {} [[nodiscard]] auto search(auto view, const std::string &headerName) -> std::optional { @@ -1049,7 +1055,9 @@ struct Preprocessor::Private { continue; } - return path.string(); + if (mode == Mode::kFirst) return path.string(); + + candidates.push_back(path.string()); } return std::nullopt; @@ -1060,22 +1068,29 @@ struct Preprocessor::Private { const auto &headerName = include.fileName; // search in the current path - if (auto p = search(std::views::single(d->currentPath_), headerName)) { + if (auto p = search(std::views::single(d->currentPath_), headerName); + mode == Mode::kFirst && p) { return p; } // search in the quote include paths - if (auto p = search(d->quoteIncludePaths_, headerName)) { + if (auto p = search(d->quoteIncludePaths_, headerName); + mode == Mode::kFirst && p) { return p; } // fallback to system include paths - if (auto p = search(d->systemIncludePaths_, headerName)) { + if (auto p = search(d->systemIncludePaths_, headerName); + mode == Mode::kFirst && p) { return p; } if (wantNextInlude && !didFindCurrentPath) { - return firstMatch->string(); + if (mode == Mode::kFirst) + return firstMatch->string(); + else { + candidates.push_back(firstMatch->string()); + } } return std::nullopt; @@ -1088,7 +1103,10 @@ struct Preprocessor::Private { } if (wantNextInlude && !didFindCurrentPath) { - return firstMatch->string(); + if (mode == Mode::kFirst) + return firstMatch->string(); + else + candidates.push_back(firstMatch->string()); } return std::nullopt; @@ -1163,7 +1181,7 @@ struct Preprocessor::Private { }; struct ParsedIfDirective { - std::function resume; + std::functionstd::optional> resume; }; using ParsedDirective = @@ -1175,9 +1193,6 @@ struct Preprocessor::Private { [[nodiscard]] auto parseIncludeDirective(TokList *directive, TokList *ts) -> std::optional; - [[nodiscard]] auto findOrCreateSourceFile(const Include &include, - bool isIncludeNext) -> SourceFile *; - [[nodiscard]] auto findOrCreateSourceFile(const std::string &fileName) -> SourceFile *; @@ -1680,13 +1695,22 @@ auto Preprocessor::Private::expand( if (auto parsedInclude = std::get_if(&parsedDirective)) { - PendingInclude status{ + PendingInclude nextState{ .preprocessor = *preprocessor_, .include = parsedInclude->header, .isIncludeNext = parsedInclude->includeNext, .loc = parsedInclude->loc, }; + nextState.candidates = [=, this]() -> std::vector { + auto resolve = + Resolve{this, parsedInclude->includeNext, Resolve::Mode::kAll}; + + (void)std::visit(resolve, parsedInclude->header); + + return resolve.candidates; + }; + // suspend the current file and start processing the continuation buffers_.push_back(Buffer{ .source = source, @@ -1698,7 +1722,7 @@ auto Preprocessor::Private::expand( // reset the token stream, so we can start processing the continuation it = last; - return status; + return nextState; } else if (auto directive = std::get_if(&parsedDirective)) { // suspend and resolve the dependencies @@ -1825,7 +1849,7 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start) } else { auto expression = prepareConstantExpression(ts); - auto resume = [=, this] { + auto resume = [=, this]() -> std::optional { const auto value = evaluateConstantExpression(expression); if (value) { @@ -1833,6 +1857,7 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start) } else { pushState(std::tuple(true, !skipping)); } + return std::nullopt; }; if (dependencies_.empty()) { @@ -1852,7 +1877,7 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start) } else { auto expression = prepareConstantExpression(ts); - auto resume = [=, this] { + auto resume = [=, this]() -> std::optional { const auto value = evaluateConstantExpression(expression); if (value) { @@ -1860,6 +1885,8 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start) } else { setState(std::tuple(true, evaluating)); } + + return std::nullopt; }; if (dependencies_.empty()) { @@ -1994,17 +2021,6 @@ auto Preprocessor::Private::parseIncludeDirective(TokList *directive, return std::nullopt; } -auto Preprocessor::Private::findOrCreateSourceFile(const Include &include, - bool isIncludeNext) - -> SourceFile * { - if (auto path = resolve(include, isIncludeNext)) { - auto sourceFile = findOrCreateSourceFile(path.value()); - return sourceFile; - } - - return nullptr; -} - auto Preprocessor::Private::findOrCreateSourceFile(const std::string &fileName) -> SourceFile * { if (auto it = ifndefProtectedFiles_.find(fileName); @@ -2860,14 +2876,6 @@ void Preprocessor::setCommentHandler(CommentHandler *commentHandler) { d->commentHandler_ = commentHandler; } -auto Preprocessor::delegate() const -> PreprocessorDelegate * { - return d->delegate_; -} - -void Preprocessor::setDelegate(PreprocessorDelegate *delegate) { - d->delegate_ = delegate; -} - auto Preprocessor::canResolveFiles() const -> bool { return d->canResolveFiles_; } @@ -2892,16 +2900,6 @@ void Preprocessor::setOmitLineMarkers(bool omitLineMarkers) { d->omitLineMarkers_ = omitLineMarkers; } -void Preprocessor::setFileExistsFunction( - std::function fileExists) { - d->fileExists_ = std::move(fileExists); -} - -void Preprocessor::setReadFileFunction( - std::function readFile) { - d->readFile_ = std::move(readFile); -} - void Preprocessor::setOnWillIncludeHeader( std::function willIncludeHeader) { d->willIncludeHeader_ = std::move(willIncludeHeader); @@ -2944,19 +2942,31 @@ void PendingInclude::resolveWith(std::optional fileName) const { return; } - auto continuation = d->findOrCreateSourceFile(*fileName); - if (!continuation) return; + auto resume = [=]() -> std::optional { + auto continuation = d->findOrCreateSourceFile(*fileName); + if (!continuation) return std::nullopt; - // make the continuation the current file - fs::path dirpath = fs::path(continuation->fileName); - dirpath.remove_filename(); + // make the continuation the current file + auto dirpath = fs::path(continuation->fileName); + dirpath.remove_filename(); - d->buffers_.push_back(Preprocessor::Private::Buffer{ - .source = continuation, - .currentPath = dirpath, - .ts = continuation->tokens, - .includeDepth = d->includeDepth_ + 1, - }); + d->buffers_.push_back(Preprocessor::Private::Buffer{ + .source = continuation, + .currentPath = dirpath, + .ts = continuation->tokens, + .includeDepth = d->includeDepth_ + 1, + }); + + return std::nullopt; + }; + + auto sourceFile = d->findSourceFile(*fileName); + if (sourceFile) { + resume(); + return; + } + + d->continuation_ = std::move(resume); } void Preprocessor::beginPreprocessing(std::string source, std::string fileName, @@ -2987,7 +2997,7 @@ void Preprocessor::beginPreprocessing(std::string source, std::string fileName, void Preprocessor::endPreprocessing(std::vector &tokens) { // consume the continuation if there is one - std::function continuation; + std::functionstd::optional> continuation; std::swap(continuation, d->continuation_); if (continuation) continuation(); @@ -3005,9 +3015,12 @@ void Preprocessor::endPreprocessing(std::vector &tokens) { auto Preprocessor::continuePreprocessing(std::vector &tokens) -> PreprocessingState { // consume the continuation if there is one - std::function continuation; + std::function()> continuation; std::swap(continuation, d->continuation_); - if (continuation) continuation(); + if (continuation) { + auto next = continuation(); + if (next) return *next; + } auto emitToken = [&](const Tok *tk) { d->finalizeToken(tokens, tk); }; diff --git a/src/parser/cxx/preprocessor.h b/src/parser/cxx/preprocessor.h index 96fc5906..c888e5b3 100644 --- a/src/parser/cxx/preprocessor.h +++ b/src/parser/cxx/preprocessor.h @@ -47,11 +47,6 @@ class CommentHandler { const Token &token) = 0; }; -class PreprocessorDelegate { - public: - virtual ~PreprocessorDelegate() = default; -}; - class Preprocessor { public: Preprocessor(Preprocessor &&) noexcept = default; @@ -65,9 +60,6 @@ class Preprocessor { [[nodiscard]] auto commentHandler() const -> CommentHandler *; void setCommentHandler(CommentHandler *commentHandler); - [[nodiscard]] auto delegate() const -> PreprocessorDelegate *; - void setDelegate(PreprocessorDelegate *delegate); - [[nodiscard]] auto canResolveFiles() const -> bool; void setCanResolveFiles(bool canResolveFiles); @@ -77,9 +69,6 @@ class Preprocessor { [[nodiscard]] auto omitLineMarkers() const -> bool; void setOmitLineMarkers(bool omitLineMarkers); - void setFileExistsFunction(std::function fileExists); - void setReadFileFunction(std::function readFile); - void setOnWillIncludeHeader( std::function willIncludeHeader); diff --git a/src/parser/cxx/preprocessor_fwd.h b/src/parser/cxx/preprocessor_fwd.h index 97935a9e..dadd4747 100644 --- a/src/parser/cxx/preprocessor_fwd.h +++ b/src/parser/cxx/preprocessor_fwd.h @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -56,6 +57,7 @@ struct PendingInclude { Include include; bool isIncludeNext = false; void *loc = nullptr; + std::functionstd::vector> candidates; void resolveWith(std::optional fileName) const; }; diff --git a/templates/cxx-parse-esm/index.js b/templates/cxx-parse-esm/index.js index ef36bd98..35d74052 100644 --- a/templates/cxx-parse-esm/index.js +++ b/templates/cxx-parse-esm/index.js @@ -51,7 +51,7 @@ async function main() { const parser = new Parser({ source, path: "source.cc" }); - parser.parse(); + await parser.parse(); const diagnostics = parser.getDiagnostics(); diff --git a/templates/cxx-parse/index.js b/templates/cxx-parse/index.js index 0b93622e..fb83b0a4 100644 --- a/templates/cxx-parse/index.js +++ b/templates/cxx-parse/index.js @@ -22,6 +22,8 @@ const { Parser, AST, ASTKind, ASTSlot } = require("cxx-frontend"); const { readFileSync } = require("fs"); const source = ` +#include + template concept CanAdd = requires(T n) { n + n; @@ -40,12 +42,15 @@ int main() { async function main() { const wasmBinaryFile = require.resolve("cxx-frontend/dist/wasm/cxx-js.wasm"); - const wasmBinary = readFileSync(wasmBinaryFile); - await Parser.init({ wasm: wasmBinary }); + const wasm = readFileSync(wasmBinaryFile); + await Parser.init({ wasm }); - const parser = new Parser({ source, path: "source.cc" }); + const parser = new Parser({ + source, + path: "source.cc", + }); - parser.parse(); + await parser.parse(); const diagnostics = parser.getDiagnostics();