Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,32 @@ jobs:

- name: Parse C++ source files (WASI toolchain)
run: |
for i in src/parser/cxx/*.cc src/frontend/cxx/*.cc; do
for i in src/parser/cxx/*.cc src/lsp/cxx/lsp/*.cc src/frontend/cxx/*.cc; do
echo "Parsing $i"
./build/src/frontend/cxx \
-I src/parser \
-I src/lsp \
-I build/_deps/fmt-src/include \
-I build/_deps/utfcpp-src/source \
-I build/_deps/flatbuffers-src/include \
-I build/_deps/nlohmann_json-src/include \
-I build/src/parser \
-DCXX_NO_FILESYSTEM \
$i
done

- name: Parse C++ source files (Linux toolchain)
run: |
for i in src/parser/cxx/*.cc src/frontend/cxx/*.cc; do
for i in src/parser/cxx/*.cc src/lsp/cxx/lsp/*.cc src/frontend/cxx/*.cc; do
echo "Parsing $i"
./build/src/frontend/cxx \
-toolchain linux \
-I src/parser \
-I src/lsp \
-I build/_deps/fmt-src/include \
-I build/_deps/utfcpp-src/source \
-I build/_deps/flatbuffers-src/include \
-I build/_deps/nlohmann_json-src/include \
-I build/src/parser \
$i
done
Expand Down Expand Up @@ -153,14 +157,16 @@ jobs:

- name: Parse C++ source files (macOS toolchain)
run: |
for i in src/parser/cxx/*.cc src/frontend/cxx/*.cc; do
for i in src/parser/cxx/*.cc src/lsp/cxx/lsp/*.cc src/frontend/cxx/*.cc; do
echo "Parsing $i"
./build/src/frontend/cxx \
-toolchain macos \
-I src/parser \
-I src/lsp \
-I build/_deps/fmt-src/include \
-I build/_deps/utfcpp-src/source \
-I build/_deps/flatbuffers-src/include \
-I build/_deps/nlohmann_json-src/include \
-I build/src/parser \
$i
done
Expand Down Expand Up @@ -195,18 +201,21 @@ jobs:
run: |
PATH=~/wasmtime-v${{ env.WASMTIME_VERSION }}-x86_64-linux:$PATH

for i in src/parser/cxx/*.cc src/frontend/cxx/*.cc; do
for i in src/parser/cxx/*.cc src/lsp/cxx/lsp/*.cc src/frontend/cxx/*.cc; do
echo "Parsing $i"
wasmtime \
--dir=src::/src \
--dir=build.wasi/_deps::/build.wasi/_deps \
--dir=build.wasi/src/parser::build.wasi/src/parser \
--dir=build.wasi/src/lsp::build.wasi/src/lsp \
--dir=build.wasi/install/usr::/usr \
build.wasi/install/usr/bin/cxx.wasm \
-I src/parser \
-I src/lsp \
-I build.wasi/_deps/fmt-src/include \
-I build.wasi/_deps/utfcpp-src/source \
-I build.wasi/_deps/flatbuffers-src/include \
-I build.wasi/_deps/nlohmann_json-src/include \
-I build.wasi/src/parser \
-DCXX_NO_FILESYSTEM \
$i
Expand Down
48 changes: 44 additions & 4 deletions packages/cxx-gen-lsp/src/gen_requests_cc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,63 @@ class RequestGenerator {
}

if (isRequest(request) && request.result) {
const resultTypeName = typeName.replace(/Request$/, "Response");
const responseTypeName = typeName.replace(/Request$/, "Response");
const resultTypeName = toCppType(request.result);

this.emit();
this.emit(`auto ${resultTypeName}::id() const -> std::variant<long, std::string> {`);
this.emit(`auto ${responseTypeName}::id() const -> std::variant<long, std::string> {`);
this.emit(` const auto& id = repr_->at("id");`);
this.emit(` if (id.is_string()) return id.get<std::string>();`);
this.emit(` return id.get<long>();`);
this.emit(`}`);
this.emit();
this.emit(`auto ${resultTypeName}::id(long id) -> ${resultTypeName}& {`);
this.emit(`auto ${responseTypeName}::id(long id) -> ${responseTypeName}& {`);
this.emit(` (*repr_)["id"] = id;`);
this.emit(` return *this;`);
this.emit(`}`);
this.emit();
this.emit(`auto ${resultTypeName}::id(std::string id) -> ${resultTypeName}& {`);
this.emit(`auto ${responseTypeName}::id(std::string id) -> ${responseTypeName}& {`);
this.emit(` (*repr_)["id"] = std::move(id);`);
this.emit(` return *this;`);
this.emit(`}`);
this.emit();
this.emit(`auto ${responseTypeName}::result() const -> ${resultTypeName} {`);
switch (request.result.kind) {
case "base": {
if (request.result.name === "null") {
this.emit(` return nullptr;`);
} else {
this.emit(` return repr_->at("result").get<${toCppType(request.result)}>(); // base`);
}
break;
}

case "reference": {
if (this.structByName.has(request.result.name)) {
this.emit(` if (!repr_->contains("result")) (*repr_)["result"] = nullptr;`);
this.emit(` return ${resultTypeName}(repr_->at("result")); // reference`);
} else {
this.emit(` lsp_runtime_error("${responseTypeName}::result() - not implemented yet");`);
}
break;
}

default: {
this.emit(` lsp_runtime_error("${responseTypeName}::result() - not implemented yet");`);
}
} // swtch
this.emit(`}`);
this.emit();
this.emit(`auto ${responseTypeName}::result(${resultTypeName} result) -> ${responseTypeName}& {`);
switch (request.result.kind) {
case "base":
this.emit(` (*repr_)["result"] = std::move(result); // base`);
break;
default:
this.emit(` lsp_runtime_error("${responseTypeName}::result() - not implemented yet");`);
} // switch
this.emit(` return *this;`);
this.emit(`}`);
}
});

Expand Down
45 changes: 45 additions & 0 deletions packages/cxx-gen-lsp/src/gen_requests_h.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,22 @@ export function gen_requests_h({ model, outputDirectory }: { model: MetaModel; o

const requestsAndNotifications: Array<Request | Notification> = [...model.requests, ...model.notifications];

emit();
emit(`#define FOR_EACH_LSP_REQUEST_TYPE(V) \\`);
model.requests.forEach((request, index) => {
const nameWithoutSuffix = request.typeName.replace(/Request$/, "");
const sep = index + 1 < model.requests.length ? " \\" : "";
emit(` V(${nameWithoutSuffix}, "${request.method}")${sep}`);
});

emit();
emit(`#define FOR_EACH_LSP_NOTIFICATION_TYPE(V) \\`);
model.notifications.forEach((notification, index) => {
const nameWithoutSuffix = notification.typeName.replace(/Notification$/, "");
const sep = index + 1 < model.notifications.length ? " \\" : "";
emit(` V(${nameWithoutSuffix}, "${notification.method}")${sep}`);
});

requestsAndNotifications.forEach((request) => {
const typeName = request.typeName;
emit();
Expand Down Expand Up @@ -89,6 +105,35 @@ export function gen_requests_h({ model, outputDirectory }: { model: MetaModel; o
}
});

emit();
emit(`template <typename Visitor>`);
emit(`auto visitRequest(Visitor&& visitor, const LSPRequest& request, const std::string_view& method) -> void {`);
emit(`#define PROCESS_REQUEST_TYPE(NAME, METHOD) \\`);
emit(` if (method == METHOD) \\`);
emit(` return visitor(static_cast<const NAME##Request&>(request));`);
emit();
emit(`FOR_EACH_LSP_REQUEST_TYPE(PROCESS_REQUEST_TYPE)`);
emit();
emit(`#undef PROCESS_REQUEST_TYPE`);
emit();
emit(` lsp_runtime_error("unknown request type");`);
emit(`}`);
emit();
emit(`template <typename Visitor>`);
emit(
`auto visitNotification(Visitor&& visitor, const LSPRequest& notification, const std::string_view& method) -> void {`,
);
emit(`#define PROCESS_NOTIFICATION_TYPE(NAME, METHOD) \\`);
emit(` if (method == METHOD) \\`);
emit(` return visitor(static_cast<const NAME##Notification&>(notification));`);
emit();
emit(`FOR_EACH_LSP_NOTIFICATION_TYPE(PROCESS_NOTIFICATION_TYPE)`);
emit();
emit(`#undef PROCESS_NOTIFICATION_TYPE`);
emit();
emit(` lsp_runtime_error("unknown notification type");`);
emit(`}`);

emit();
emit(`}`);

Expand Down
2 changes: 1 addition & 1 deletion src/frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ aux_source_directory(cxx SOURCES)

add_executable(cxx ${SOURCES})

target_link_libraries(cxx cxx-parser)
target_link_libraries(cxx cxx-parser cxx-lsp)

if(EMSCRIPTEN)
target_link_options(cxx PUBLIC
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/cxx/cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ std::vector<CLIOptionDescr> options{

{"-verify", "Verify the diagnostic messages", &CLI::opt_verify},

{"-lsp", "Start Language Server", &CLI::opt_lsp},

{"-v", "Show commands to run and use verbose output", &CLI::opt_v},

};
Expand Down
1 change: 1 addition & 0 deletions src/frontend/cxx/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class CLI {
bool opt_verify = false;
bool opt_v = false;
bool opt_emit_ast = false;
bool opt_lsp = false;

void parse(int& argc, char**& argv);

Expand Down
13 changes: 9 additions & 4 deletions src/frontend/cxx/frontend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <format>

#include "ast_printer.h"
#include "lsp_server.h"
#include "verify_diagnostics_client.h"

// std
Expand Down Expand Up @@ -304,17 +305,21 @@ auto main(int argc, char* argv[]) -> int {

const auto& inputFiles = cli.positionals();

if (inputFiles.empty()) {
if (!cli.opt_lsp && inputFiles.empty()) {
std::cerr << "cxx: no input files" << std::endl
<< "Usage: cxx [options] file..." << std::endl;
return EXIT_FAILURE;
}

int existStatus = EXIT_SUCCESS;

for (const auto& fileName : inputFiles) {
if (!runOnFile(cli, fileName)) {
existStatus = EXIT_FAILURE;
if (cli.opt_lsp) {
existStatus = lsp::startServer(cli);
} else {
for (const auto& fileName : inputFiles) {
if (!runOnFile(cli, fileName)) {
existStatus = EXIT_FAILURE;
}
}
}

Expand Down
Loading