From a441762f8ff62e5f42f3a5c3cef21e841314db08 Mon Sep 17 00:00:00 2001 From: Dario Gabriel Lipicar Date: Fri, 12 Jun 2026 15:18:06 -0300 Subject: [PATCH] generator: distribute the LIDL frontend for external generators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First step of moving ALL Qt glue emission out of this repo into logos-qt-sdk's logos-qt-generator (cpp-sdk's generator keeps only the Qt-free outputs: std typed wrappers, logos_sdk umbrella, cdylib impl-exports, LIDL derivation). - Shared emit helpers (lidlToPascalCase, lidlTypeToQt, lidlTypeToStd, lidlIsStdConvertible) move to a new lidl_emit_common.{h,cpp} unit, used by both generators. - The frontend set (AST, lexer, parser, serializer, validator, impl-header parser, emit-common) is installed under share/lidl-frontend/ — the qt generator compiles these sources in directly, so the two tools share one frontend without a binary ABI. --- cpp-generator/CMakeLists.txt | 22 +++++ .../experimental/lidl_emit_common.cpp | 94 +++++++++++++++++++ cpp-generator/experimental/lidl_emit_common.h | 13 +++ .../experimental/lidl_gen_client.cpp | 43 +-------- .../experimental/lidl_gen_provider.cpp | 48 +--------- nix/bin.nix | 13 +++ tests/experimental/CMakeLists.txt | 1 + 7 files changed, 145 insertions(+), 89 deletions(-) create mode 100644 cpp-generator/experimental/lidl_emit_common.cpp create mode 100644 cpp-generator/experimental/lidl_emit_common.h diff --git a/cpp-generator/CMakeLists.txt b/cpp-generator/CMakeLists.txt index 3b6a755..73329f4 100644 --- a/cpp-generator/CMakeLists.txt +++ b/cpp-generator/CMakeLists.txt @@ -13,6 +13,7 @@ add_executable(logos-cpp-generator main.cpp legacy/main.cpp legacy/generator_lib.cpp + experimental/lidl_emit_common.cpp experimental/lidl_lexer.cpp experimental/lidl_parser.cpp experimental/lidl_serializer.cpp @@ -61,3 +62,24 @@ target_include_directories(logos-cpp-generator PRIVATE set_target_properties(logos-cpp-generator PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" ) + +# ── LIDL frontend distribution ─────────────────────────────────────────────── +# logos-qt-sdk's logos-qt-generator (which emits ALL Qt glue: universal, +# cdylib, ui) compiles these sources directly — source-level sharing keeps the +# two generators on one frontend without a binary-ABI coupling. +install(FILES + experimental/lidl_ast.h + experimental/lidl_lexer.h + experimental/lidl_lexer.cpp + experimental/lidl_parser.h + experimental/lidl_parser.cpp + experimental/lidl_serializer.h + experimental/lidl_serializer.cpp + experimental/lidl_validator.h + experimental/lidl_validator.cpp + experimental/impl_header_parser.h + experimental/impl_header_parser.cpp + experimental/lidl_emit_common.h + experimental/lidl_emit_common.cpp + DESTINATION share/lidl-frontend +) diff --git a/cpp-generator/experimental/lidl_emit_common.cpp b/cpp-generator/experimental/lidl_emit_common.cpp new file mode 100644 index 0000000..83af2a1 --- /dev/null +++ b/cpp-generator/experimental/lidl_emit_common.cpp @@ -0,0 +1,94 @@ +#include "lidl_emit_common.h" + +QString lidlToPascalCase(const QString& name) +{ + QString out; + bool cap = true; + for (QChar c : name) { + if (!c.isLetterOrNumber()) { cap = true; continue; } + if (cap) { out.append(c.toUpper()); cap = false; } + else { out.append(c.toLower()); } + } + if (out.isEmpty()) return QString("Module"); + return out; +} + +QString lidlTypeToQt(const TypeExpr& te) +{ + switch (te.kind) { + case TypeExpr::Primitive: + if (te.name == "void") return "void"; + if (te.name == "tstr") return "QString"; + if (te.name == "bstr") return "QByteArray"; + if (te.name == "int") return "int"; + if (te.name == "uint") return "int"; + if (te.name == "float64") return "double"; + if (te.name == "bool") return "bool"; + if (te.name == "result") return "LogosResult"; + if (te.name == "any") return "QVariant"; + return "QVariant"; + case TypeExpr::Array: + if (te.elements.size() == 1 + && te.elements[0].kind == TypeExpr::Primitive + && te.elements[0].name == "tstr") { + return "QStringList"; + } + return "QVariantList"; + case TypeExpr::Map: + return "QVariantMap"; + case TypeExpr::Optional: + return "QVariant"; + case TypeExpr::Named: + return "QVariant"; + } + return "QVariant"; +} + +bool lidlIsStdConvertible(const TypeExpr& te) +{ + if (te.kind == TypeExpr::Primitive) { + return te.name == "tstr" || te.name == "bstr" + || te.name == "int" || te.name == "uint" + || te.name == "float64" || te.name == "bool"; + } + if (te.kind == TypeExpr::Array && te.elements.size() == 1) { + const TypeExpr& elem = te.elements[0]; + if (elem.kind == TypeExpr::Primitive) { + return elem.name == "tstr" || elem.name == "bstr" + || elem.name == "int" || elem.name == "uint" + || elem.name == "float64" || elem.name == "bool"; + } + } + return false; +} + +QString lidlTypeToStd(const TypeExpr& te) +{ + if (te.kind == TypeExpr::Primitive) { + if (te.name == "tstr") return "std::string"; + if (te.name == "bstr") return "std::vector"; + if (te.name == "int") return "int64_t"; + if (te.name == "uint") return "uint64_t"; + if (te.name == "float64") return "double"; + if (te.name == "bool") return "bool"; + if (te.name == "result") return "LogosResult"; + if (te.name == "any") return "QVariant"; + return "QVariant"; + } + if (te.kind == TypeExpr::Array && te.elements.size() == 1) { + const TypeExpr& elem = te.elements[0]; + if (elem.kind == TypeExpr::Primitive) { + if (elem.name == "tstr") return "std::vector"; + if (elem.name == "bstr") return "std::vector>"; + if (elem.name == "int") return "std::vector"; + if (elem.name == "uint") return "std::vector"; + if (elem.name == "float64") return "std::vector"; + if (elem.name == "bool") return "std::vector"; + } + return "QVariantList"; + } + if (te.kind == TypeExpr::Map) return "QVariantMap"; + if (te.kind == TypeExpr::Optional) return "QVariant"; + if (te.kind == TypeExpr::Named) return "QVariant"; + return "QVariant"; +} diff --git a/cpp-generator/experimental/lidl_emit_common.h b/cpp-generator/experimental/lidl_emit_common.h new file mode 100644 index 0000000..ac366c6 --- /dev/null +++ b/cpp-generator/experimental/lidl_emit_common.h @@ -0,0 +1,13 @@ +// Shared emit helpers used by every code-emitting backend (the Qt-free +// client/wrapper generation here in cpp-sdk AND the Qt glue generation in +// logos-qt-sdk's logos-qt-generator). Distributed with the LIDL frontend +// sources (share/lidl-frontend/) so external generators compile them in. +#pragma once + +#include +#include "lidl_ast.h" + +QString lidlToPascalCase(const QString& name); +QString lidlTypeToQt(const TypeExpr& te); +QString lidlTypeToStd(const TypeExpr& te); +bool lidlIsStdConvertible(const TypeExpr& te); diff --git a/cpp-generator/experimental/lidl_gen_client.cpp b/cpp-generator/experimental/lidl_gen_client.cpp index 8fb5a70..c5bfbab 100644 --- a/cpp-generator/experimental/lidl_gen_client.cpp +++ b/cpp-generator/experimental/lidl_gen_client.cpp @@ -1,4 +1,5 @@ #include "lidl_gen_client.h" +#include "lidl_emit_common.h" #include "lidl_parser.h" #include "lidl_validator.h" @@ -14,49 +15,7 @@ // Helpers // --------------------------------------------------------------------------- -QString lidlToPascalCase(const QString& name) -{ - QString out; - bool cap = true; - for (QChar c : name) { - if (!c.isLetterOrNumber()) { cap = true; continue; } - if (cap) { out.append(c.toUpper()); cap = false; } - else { out.append(c.toLower()); } - } - if (out.isEmpty()) return QString("Module"); - return out; -} -QString lidlTypeToQt(const TypeExpr& te) -{ - switch (te.kind) { - case TypeExpr::Primitive: - if (te.name == "void") return "void"; - if (te.name == "tstr") return "QString"; - if (te.name == "bstr") return "QByteArray"; - if (te.name == "int") return "int"; - if (te.name == "uint") return "int"; - if (te.name == "float64") return "double"; - if (te.name == "bool") return "bool"; - if (te.name == "result") return "LogosResult"; - if (te.name == "any") return "QVariant"; - return "QVariant"; - case TypeExpr::Array: - if (te.elements.size() == 1 - && te.elements[0].kind == TypeExpr::Primitive - && te.elements[0].name == "tstr") { - return "QStringList"; - } - return "QVariantList"; - case TypeExpr::Map: - return "QVariantMap"; - case TypeExpr::Optional: - return "QVariant"; - case TypeExpr::Named: - return "QVariant"; - } - return "QVariant"; -} static bool isRefType(const QString& qt) { diff --git a/cpp-generator/experimental/lidl_gen_provider.cpp b/cpp-generator/experimental/lidl_gen_provider.cpp index 4f2898b..0d5e55d 100644 --- a/cpp-generator/experimental/lidl_gen_provider.cpp +++ b/cpp-generator/experimental/lidl_gen_provider.cpp @@ -1,4 +1,5 @@ #include "lidl_gen_provider.h" +#include "lidl_emit_common.h" #include "lidl_gen_client.h" // lidlToPascalCase, lidlTypeToQt #include "lidl_parser.h" #include "lidl_serializer.h" @@ -16,54 +17,7 @@ // Type mapping: LIDL → C++ std types // --------------------------------------------------------------------------- -bool lidlIsStdConvertible(const TypeExpr& te) -{ - if (te.kind == TypeExpr::Primitive) { - return te.name == "tstr" || te.name == "bstr" - || te.name == "int" || te.name == "uint" - || te.name == "float64" || te.name == "bool"; - } - if (te.kind == TypeExpr::Array && te.elements.size() == 1) { - const TypeExpr& elem = te.elements[0]; - if (elem.kind == TypeExpr::Primitive) { - return elem.name == "tstr" || elem.name == "bstr" - || elem.name == "int" || elem.name == "uint" - || elem.name == "float64" || elem.name == "bool"; - } - } - return false; -} -QString lidlTypeToStd(const TypeExpr& te) -{ - if (te.kind == TypeExpr::Primitive) { - if (te.name == "tstr") return "std::string"; - if (te.name == "bstr") return "std::vector"; - if (te.name == "int") return "int64_t"; - if (te.name == "uint") return "uint64_t"; - if (te.name == "float64") return "double"; - if (te.name == "bool") return "bool"; - if (te.name == "result") return "LogosResult"; - if (te.name == "any") return "QVariant"; - return "QVariant"; - } - if (te.kind == TypeExpr::Array && te.elements.size() == 1) { - const TypeExpr& elem = te.elements[0]; - if (elem.kind == TypeExpr::Primitive) { - if (elem.name == "tstr") return "std::vector"; - if (elem.name == "bstr") return "std::vector>"; - if (elem.name == "int") return "std::vector"; - if (elem.name == "uint") return "std::vector"; - if (elem.name == "float64") return "std::vector"; - if (elem.name == "bool") return "std::vector"; - } - return "QVariantList"; - } - if (te.kind == TypeExpr::Map) return "QVariantMap"; - if (te.kind == TypeExpr::Optional) return "QVariant"; - if (te.kind == TypeExpr::Named) return "QVariant"; - return "QVariant"; -} // --------------------------------------------------------------------------- // Conversion helpers: Qt type ↔ std type diff --git a/nix/bin.nix b/nix/bin.nix index 9f93bda..0bad7a9 100644 --- a/nix/bin.nix +++ b/nix/bin.nix @@ -32,6 +32,19 @@ pkgs.stdenv.mkDerivation { if [ -f build-generator/bin/logos-cpp-generator ]; then cp build-generator/bin/logos-cpp-generator $out/bin/ fi + + # LIDL frontend sources for external generators (logos-qt-sdk's + # logos-qt-generator compiles these in — source-level sharing, no + # binary ABI between the two generators). + mkdir -p $out/share/lidl-frontend + cp cpp-generator/experimental/lidl_ast.h \ + cpp-generator/experimental/lidl_lexer.h cpp-generator/experimental/lidl_lexer.cpp \ + cpp-generator/experimental/lidl_parser.h cpp-generator/experimental/lidl_parser.cpp \ + cpp-generator/experimental/lidl_serializer.h cpp-generator/experimental/lidl_serializer.cpp \ + cpp-generator/experimental/lidl_validator.h cpp-generator/experimental/lidl_validator.cpp \ + cpp-generator/experimental/impl_header_parser.h cpp-generator/experimental/impl_header_parser.cpp \ + cpp-generator/experimental/lidl_emit_common.h cpp-generator/experimental/lidl_emit_common.cpp \ + $out/share/lidl-frontend/ runHook postInstall ''; diff --git a/tests/experimental/CMakeLists.txt b/tests/experimental/CMakeLists.txt index ab0abb2..aabe1b0 100644 --- a/tests/experimental/CMakeLists.txt +++ b/tests/experimental/CMakeLists.txt @@ -18,6 +18,7 @@ add_executable(experimental_tests test_impl_header_parser.cpp # Sources under test + ${EXPERIMENTAL_SRC_DIR}/lidl_emit_common.cpp ${EXPERIMENTAL_SRC_DIR}/lidl_lexer.cpp ${EXPERIMENTAL_SRC_DIR}/lidl_parser.cpp ${EXPERIMENTAL_SRC_DIR}/lidl_validator.cpp