From 1251b33a3a48166ce9d5208d6d6145883d39f94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 13:13:03 +0200 Subject: [PATCH 01/53] adopting some best practices for cmake * tests: check for BUILD_TESTING **and** THORIN_BUILD_TESTING * Debug as default: populate GUI options --- CMakeLists.txt | 22 +++++++++++----------- docs/README.md | 16 ++++++++-------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7b321c3f1..dea8fc0e49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(Thorin VERSION 1.9.0) if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type (default Debug)" FORCE) + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() if(MSVC) @@ -44,15 +45,6 @@ endif() list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) include(Thorin) -find_program(MEMORYCHECK_COMMAND valgrind) -set(VALGRIND_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") # needs to be BEFORE "include(CTest)" -include(CTest) -if(BUILD_TESTING AND THORIN_BUILD_TESTING) - include(GoogleTest) - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - add_subdirectory(modules/googletest EXCLUDE_FROM_ALL) -endif() - set(ABSL_PROPAGATE_CXX_STD ON) set(ABSL_USE_EXTERNAL_GOOGLETEST ON) set(ABSL_ENABLE_INSTALL ON) @@ -73,7 +65,15 @@ if(THORIN_BUILD_EXAMPLES) add_subdirectory(examples) endif() -if(BUILD_TESTING AND THORIN_BUILD_TESTING) +if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR THORIN_BUILD_TESTING) AND BUILD_TESTING) + find_program(MEMORYCHECK_COMMAND valgrind) + set(VALGRIND_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") # needs to be BEFORE "include(CTest)" + include(CTest) + + include(GoogleTest) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + add_subdirectory(modules/googletest EXCLUDE_FROM_ALL) + add_subdirectory(gtest) add_subdirectory(lit) endif() diff --git a/docs/README.md b/docs/README.md index e0ba571853..8a66946d4c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -82,14 +82,14 @@ cmake --build build -j $(nproc) -t install ### Build Switches -| CMake Switch | Options | Default | Comment | -|-------------------------|------------------------------------------|--------------|-------------------------------------------------------------------------------------| -| `CMAKE_BUILD_TYPE` | `Debug` \| `Release` \| `RelWithDebInfo` | `Debug` | Build type. | -| `CMAKE_INSTALL_PREFIX` | | `/usr/local` | Install prefix. | -| `THORIN_BUILD_DOCS` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build the documentation
(requires Doxygen). | -| `THORIN_BUILD_EXAMPLES` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build the examples. | -| `THORIN_BUILD_TESTING` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build all of Thorin's own tests. | -| `THORIN_ENABLE_CHECKS` | `ON` \| `OFF` | `ON` | If `ON`, enables expensive runtime checks
(requires `CMAKE_BUILD_TYPE=Debug`). | +| CMake Switch | Options | Default | Comment | +|-------------------------|------------------------------------------|--------------|---------------------------------------------------------------------------------------| +| `CMAKE_BUILD_TYPE` | `Debug` \| `Release` \| `RelWithDebInfo` | `Debug` | Build type. | +| `CMAKE_INSTALL_PREFIX` | | `/usr/local` | Install prefix. | +| `THORIN_BUILD_DOCS` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build the documentation
(requires Doxygen). | +| `THORIN_BUILD_EXAMPLES` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build the examples. | +| `THORIN_BUILD_TESTING` | `ON` \| `OFF` | `OFF` | If `ON` **and** `BUILD_TESTING` is `ON`, Thorin will build all of Thorin's own tests. | +| `THORIN_ENABLE_CHECKS` | `ON` \| `OFF` | `ON` | If `ON`, enables expensive runtime checks
(requires `CMAKE_BUILD_TYPE=Debug`). | ## Dependencies From 1f8f1abab2320e7cfbb7b87cc69e6b301c96b319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 14:29:14 +0200 Subject: [PATCH 02/53] cmake: use quotes for paths --- CMakeLists.txt | 36 ++++++++++++++++++++---------------- docs/CMakeLists.txt | 27 +++++++++++++-------------- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dea8fc0e49..f7281d96ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,9 +17,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") option(BUILD_SHARED_LIBS "Build shared libraries." ON) option(THORIN_BUILD_DOCS "If ON, Thorin will build the documentation (requires Doxygen)." OFF) @@ -42,7 +42,7 @@ else() add_compile_options(-Wall -Wextra) endif() -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") include(Thorin) set(ABSL_PROPAGATE_CXX_STD ON) @@ -90,22 +90,26 @@ include(CMakePackageConfigHelpers) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/thorin-config-version.cmake" VERSION ${Thorin_VERSION} - COMPATIBILITY SameMajorVersion -) + COMPATIBILITY SameMajorVersion) set(THORIN_CMAKE_INSTALL_DIR lib/cmake/thorin) -install(FILES cmake/Thorin.cmake DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) -install(EXPORT install_exports FILE "thorin-targets.cmake" NAMESPACE thorin:: DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) +install( + FILES cmake/Thorin.cmake + DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") + +install( + EXPORT install_exports + FILE thorin-targets.cmake + NAMESPACE thorin:: + DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") configure_package_config_file( - ${PROJECT_SOURCE_DIR}/cmake/thorin-config.cmake.in - ${PROJECT_BINARY_DIR}/thorin-config.cmake - INSTALL_DESTINATION ${THORIN_CMAKE_INSTALL_DIR} -) + "${PROJECT_SOURCE_DIR}/cmake/thorin-config.cmake.in" + "${PROJECT_BINARY_DIR}/thorin-config.cmake" + INSTALL_DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) install(FILES - ${PROJECT_BINARY_DIR}/thorin-config.cmake - ${PROJECT_BINARY_DIR}/thorin-config-version.cmake - DESTINATION ${THORIN_CMAKE_INSTALL_DIR} -) + "${PROJECT_BINARY_DIR}/thorin-config.cmake" + "${PROJECT_BINARY_DIR}/thorin-config-version.cmake" + DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 42b7915f6c..d6a26e14c0 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -1,22 +1,22 @@ -set(CLI_HELP ${CMAKE_CURRENT_BINARY_DIR}/cli-help.sh) +set(CLI_HELP "${CMAKE_CURRENT_BINARY_DIR}/cli-help.sh") add_custom_command( OUTPUT ${CLI_HELP} COMMAND thorin --help > ${CLI_HELP} DEPENDS thorin COMMENT "Generating help text of Thorin's CLI" -) -set(DOXYFILE ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) -set(DOXY_LAYOUT ${CMAKE_CURRENT_BINARY_DIR}/DoxygenLayout.xml) -set(DOXY_INDEX_HTML ${CMAKE_CURRENT_BINARY_DIR}/html/index.html) + +set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") +set(DOXY_LAYOUT "${CMAKE_CURRENT_BINARY_DIR}/DoxygenLayout.xml") +set(DOXY_INDEX_HTML "${CMAKE_CURRENT_BINARY_DIR}/html/index.html") set(DOXY_EXTRA_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/cli.md - ${CMAKE_CURRENT_SOURCE_DIR}/coding.md - ${CMAKE_CURRENT_SOURCE_DIR}/dev.md - ${CMAKE_CURRENT_SOURCE_DIR}/langref.md - ${CMAKE_CURRENT_SOURCE_DIR}/passes.md - ${CMAKE_CURRENT_SOURCE_DIR}/README.md -) + "${CMAKE_CURRENT_SOURCE_DIR}/cli.md" + "${CMAKE_CURRENT_SOURCE_DIR}/coding."md + "${CMAKE_CURRENT_SOURCE_DIR}/dev.md" + "${CMAKE_CURRENT_SOURCE_DIR}/langref".md + "${CMAKE_CURRENT_SOURCE_DIR}/passes.m"d + "${CMAKE_CURRENT_SOURCE_DIR}/README.md") + string(REPLACE ";" " " DOXY_EXTRA_FILES_CONFIG "${DOXY_EXTRA_FILES}") configure_file(Doxyfile.in ${DOXYFILE} @ONLY) configure_file(DoxygenLayout.xml.in ${DOXY_LAYOUT} @ONLY) @@ -27,7 +27,6 @@ add_custom_command( MAIN_DEPENDENCY ${DOXYFILE} DEPENDS thorin ${CLI_HELP} ${DOXY_EXTRA_FILES} ${DOXY_LAYOUT} COMMENT "Generating Doxygen HTML documentation" - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -) + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}") add_custom_target(docs ALL DEPENDS ${DOXY_INDEX_HTML} ${THORIN_PLUGIN_LIST}) From 5807912c0e91deb44b200c85367598e219bf465c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 15:14:03 +0200 Subject: [PATCH 03/53] oops --- docs/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index d6a26e14c0..7237e30b89 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -11,10 +11,10 @@ set(DOXY_LAYOUT "${CMAKE_CURRENT_BINARY_DIR}/DoxygenLayout.xml") set(DOXY_INDEX_HTML "${CMAKE_CURRENT_BINARY_DIR}/html/index.html") set(DOXY_EXTRA_FILES "${CMAKE_CURRENT_SOURCE_DIR}/cli.md" - "${CMAKE_CURRENT_SOURCE_DIR}/coding."md + "${CMAKE_CURRENT_SOURCE_DIR}/coding.md" "${CMAKE_CURRENT_SOURCE_DIR}/dev.md" - "${CMAKE_CURRENT_SOURCE_DIR}/langref".md - "${CMAKE_CURRENT_SOURCE_DIR}/passes.m"d + "${CMAKE_CURRENT_SOURCE_DIR}/langref.md" + "${CMAKE_CURRENT_SOURCE_DIR}/passes.md" "${CMAKE_CURRENT_SOURCE_DIR}/README.md") string(REPLACE ";" " " DOXY_EXTRA_FILES_CONFIG "${DOXY_EXTRA_FILES}") From 56c15e5fc6475bde44d59a18a45d5766cc590431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 15:35:17 +0200 Subject: [PATCH 04/53] cmake: refactoring --- CMakeLists.txt | 20 +++++++++++--------- cmake/Thorin.cmake | 23 +++++++++++++++++++---- docs/CMakeLists.txt | 2 +- thorin/CMakeLists.txt | 27 +++++++++++++++++++-------- 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f7281d96ea..59da4d8995 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,13 @@ cmake_minimum_required(VERSION 3.20 FATAL_ERROR) + project(Thorin VERSION 1.9.0) +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") +include(Thorin) + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build." FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") @@ -42,9 +49,6 @@ else() add_compile_options(-Wall -Wextra) endif() -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") -include(Thorin) - set(ABSL_PROPAGATE_CXX_STD ON) set(ABSL_USE_EXTERNAL_GOOGLETEST ON) set(ABSL_ENABLE_INSTALL ON) @@ -85,24 +89,22 @@ if(THORIN_BUILD_DOCS) endif() endif() -include(CMakePackageConfigHelpers) - write_basic_package_version_file( "${PROJECT_BINARY_DIR}/thorin-config-version.cmake" VERSION ${Thorin_VERSION} COMPATIBILITY SameMajorVersion) -set(THORIN_CMAKE_INSTALL_DIR lib/cmake/thorin) +set(THORIN_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/thorin") install( FILES cmake/Thorin.cmake - DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") + DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) install( - EXPORT install_exports + EXPORT thorin_exports FILE thorin-targets.cmake NAMESPACE thorin:: - DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") + DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) configure_package_config_file( "${PROJECT_SOURCE_DIR}/cmake/thorin-config.cmake.in" diff --git a/cmake/Thorin.cmake b/cmake/Thorin.cmake index b984af9a85..33fbb21c08 100644 --- a/cmake/Thorin.cmake +++ b/cmake/Thorin.cmake @@ -132,10 +132,25 @@ function(add_thorin_plugin) ) if(${PARSED_INSTALL}) - install(TARGETS thorin_${PLUGIN} EXPORT install_exports LIBRARY DESTINATION lib/thorin RUNTIME DESTINATION lib/thorin INCLUDES DESTINATION include) - install(FILES ${THORIN_FILE_LIB_DIR} DESTINATION lib/thorin) - install(FILES ${PLUGIN_H} DESTINATION include/dialects/${PLUGIN}) - install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN} DESTINATION include/dialects FILES_MATCHING PATTERN *.h) + install( + TARGETS thorin_${PLUGIN} + EXPORT thorin_exports + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/thorin" + RUNTIME DESTINATION "${CMAKE_INSTALL_LIBDIR}/thorin" + INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + + install( + FILES ${THORIN_FILE_LIB_DIR} + DESTINATION lib/thorin) + + install( + FILES ${PLUGIN_H} + DESTINATION "include/dialects/${PLUGIN}") + + install( + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${PLUGIN} " + DESTINATION include/dialects + FILES_MATCHING PATTERN *.h) endif() if(TARGET thorin_all_plugins) add_dependencies(thorin_all_plugins thorin_${PLUGIN}) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index 7237e30b89..13ca19b64c 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -4,7 +4,7 @@ add_custom_command( OUTPUT ${CLI_HELP} COMMAND thorin --help > ${CLI_HELP} DEPENDS thorin - COMMENT "Generating help text of Thorin's CLI" + COMMENT "Generating help text of Thorin's CLI") set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile") set(DOXY_LAYOUT "${CMAKE_CURRENT_BINARY_DIR}/DoxygenLayout.xml") diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index e88d86be06..6dec8b0c1c 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -97,10 +97,9 @@ add_library(libthorin set_target_properties(libthorin PROPERTIES PREFIX "") -get_target_property(libthorin_HEADERS libthorin SOURCES) -list(FILTER libthorin_HEADERS INCLUDE REGEX ".*\.h") - -configure_file(config.h.in ${CMAKE_BINARY_DIR}/include/thorin/config.h) +configure_file( + config.h.in + "${CMAKE_BINARY_DIR}/include/thorin/config.h") target_include_directories(libthorin PUBLIC @@ -125,7 +124,19 @@ if(MSVC AND BUILD_SHARED_LIBS) target_compile_definitions(libthorin PUBLIC ABSL_CONSUME_DLL) endif() -install(TARGETS libthorin EXPORT install_exports INCLUDES DESTINATION include) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DESTINATION include FILES_MATCHING PATTERN "*.h") -install(FILES ${CMAKE_BINARY_DIR}/include/thorin/config.h DESTINATION include/thorin) -install(FILES ${PROJECT_SOURCE_DIR}/modules/half/include/half.hpp DESTINATION include) +install( + TARGETS libthorin + EXPORT thorin_exports + INCLUDES DESTINATION include) + +install( + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DESTINATION include FILES_MATCHING PATTERN "*.h") + +install( + FILES "${CMAKE_BINARY_DIR}/include/thorin/config.h" + DESTINATION include/thorin) + +install( + FILES "${PROJECT_SOURCE_DIR}/modules/half/include/half.hpp" + DESTINATION include) From 9787a7a954a88fa449451315c6156f8ce5abd97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 16:02:14 +0200 Subject: [PATCH 05/53] PROJECT*DIR -> CMAKE_CURRENT*DIR This makes thorin as submodule via add_subdirectory more robust. --- CMakeLists.txt | 10 +++++----- thorin/CMakeLists.txt | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59da4d8995..49fde42966 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ if(THORIN_BUILD_DOCS) endif() write_basic_package_version_file( - "${PROJECT_BINARY_DIR}/thorin-config-version.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config-version.cmake" VERSION ${Thorin_VERSION} COMPATIBILITY SameMajorVersion) @@ -107,11 +107,11 @@ install( DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) configure_package_config_file( - "${PROJECT_SOURCE_DIR}/cmake/thorin-config.cmake.in" - "${PROJECT_BINARY_DIR}/thorin-config.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/thorin-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" INSTALL_DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) install(FILES - "${PROJECT_BINARY_DIR}/thorin-config.cmake" - "${PROJECT_BINARY_DIR}/thorin-config-version.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config-version.cmake" DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 6dec8b0c1c..54613dc473 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -104,8 +104,8 @@ configure_file( target_include_directories(libthorin PUBLIC $ # for config.h - $ # for thorin/* - $ + $ # for thorin/* + $ $ ) @@ -138,5 +138,5 @@ install( DESTINATION include/thorin) install( - FILES "${PROJECT_SOURCE_DIR}/modules/half/include/half.hpp" + FILES "${CMAKE_CURRENT_SOURCE_DIR}/modules/half/include/half.hpp" DESTINATION include) From 0e003305b5e79043a2952a320fd8eec0dcea7967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 16:05:53 +0200 Subject: [PATCH 06/53] fix paths --- thorin/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 54613dc473..bd707c1d1c 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -103,9 +103,9 @@ configure_file( target_include_directories(libthorin PUBLIC - $ # for config.h - $ # for thorin/* - $ + $ # for config.h + $ # for thorin/* + $ $ ) @@ -138,5 +138,5 @@ install( DESTINATION include/thorin) install( - FILES "${CMAKE_CURRENT_SOURCE_DIR}/modules/half/include/half.hpp" + FILES "${CMAKE_CURRENT_SOURCE_DIR}/../modules/half/include/half.hpp" DESTINATION include) From 137079c0fa38a9e8a06cfa70b735cdd7296761a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 16:41:46 +0200 Subject: [PATCH 07/53] cmake: consistent style * install_exports -> thorin_exports --- CMakeLists.txt | 19 ++++++++++--------- cli/CMakeLists.txt | 8 +++++--- cmake/Thorin.cmake | 2 +- dialects/CMakeLists.txt | 11 ----------- examples/CMakeLists.txt | 2 +- lit/CMakeLists.txt | 8 +++----- thorin/CMakeLists.txt | 33 +++++++++++++++------------------ 7 files changed, 35 insertions(+), 48 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49fde42966..f501afa822 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,26 +92,27 @@ endif() write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/thorin-config-version.cmake" VERSION ${Thorin_VERSION} - COMPATIBILITY SameMajorVersion) - + COMPATIBILITY SameMajorVersion +) set(THORIN_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/thorin") install( FILES cmake/Thorin.cmake - DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) - + DESTINATION ${THORIN_CMAKE_INSTALL_DIR} +) install( EXPORT thorin_exports FILE thorin-targets.cmake NAMESPACE thorin:: - DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) - + DESTINATION ${THORIN_CMAKE_INSTALL_DIR} +) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/thorin-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" - INSTALL_DESTINATION ${THORIN_CMAKE_INSTALL_DIR}) - + INSTALL_DESTINATION ${THORIN_CMAKE_INSTALL_DIR} +) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/thorin-config-version.cmake" - DESTINATION "${THORIN_CMAKE_INSTALL_DIR}") + DESTINATION "${THORIN_CMAKE_INSTALL_DIR}" +) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index e48be69eac..07b15c6ad6 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,7 +1,9 @@ -add_executable(thorin - main.cpp) +add_executable(thorin main.cpp) target_link_libraries(thorin libthorin lyra) set_target_properties(thorin PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -install(TARGETS thorin EXPORT install_exports) +install( + TARGETS thorin + EXPORT thorin_exports +) diff --git a/cmake/Thorin.cmake b/cmake/Thorin.cmake index 33fbb21c08..edbf88f9b6 100644 --- a/cmake/Thorin.cmake +++ b/cmake/Thorin.cmake @@ -45,7 +45,7 @@ and passes to identify the axioms. header to be up-to-date. - `INSTALL`: Specify, if the plugin description, plugin and headers shall be installed with `make install`. - To export the targets, the export name `install_exports` has to be + To export the targets, the export name `thorin_exports` has to be exported accordingly (see [install(EXPORT ..)](https://cmake.org/cmake/help/latest/command/install.html#export)) diff --git a/dialects/CMakeLists.txt b/dialects/CMakeLists.txt index 7345764a34..d61939d66b 100644 --- a/dialects/CMakeLists.txt +++ b/dialects/CMakeLists.txt @@ -12,7 +12,6 @@ add_thorin_plugin(affine core INSTALL ) - add_thorin_plugin(autodiff SOURCES autodiff/autodiff.cpp @@ -37,7 +36,6 @@ add_thorin_plugin(autodiff mem INSTALL ) - add_thorin_plugin(clos SOURCES clos/clos.cpp @@ -62,7 +60,6 @@ add_thorin_plugin(clos core INSTALL ) - add_thorin_plugin(compile SOURCES compile/compile.cpp @@ -74,7 +71,6 @@ add_thorin_plugin(compile compile/pass/internal_cleanup.h INSTALL ) - add_thorin_plugin(core SOURCES core/core.cpp @@ -89,7 +85,6 @@ add_thorin_plugin(core clos INSTALL ) - add_thorin_plugin(demo SOURCES demo/demo.cpp @@ -99,7 +94,6 @@ add_thorin_plugin(demo compile INSTALL ) - add_thorin_plugin(direct SOURCES direct/direct.cpp @@ -166,8 +160,6 @@ add_thorin_plugin(mem core INSTALL ) - - add_thorin_plugin(refly SOURCES refly/refly.h @@ -180,7 +172,6 @@ add_thorin_plugin(refly compile INSTALL ) - add_thorin_plugin(regex SOURCES regex/regex.h @@ -195,8 +186,6 @@ add_thorin_plugin(regex compile INSTALL ) - - add_thorin_plugin(opt SOURCES opt/opt.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 81e4ad9e75..1df0c6f723 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,4 +4,4 @@ target_link_libraries(hello libthorin) set_target_properties(hello PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/examples") add_dependencies(hello compile core) -install(TARGETS hello EXPORT install_exports) +install(TARGETS hello EXPORT thorin_exports) diff --git a/lit/CMakeLists.txt b/lit/CMakeLists.txt index 8fa83c7008..012d3686a8 100644 --- a/lit/CMakeLists.txt +++ b/lit/CMakeLists.txt @@ -9,8 +9,6 @@ endif() configure_file(lit.site.cfg.py.in lit.site.cfg.py @ONLY) add_custom_target(check - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/lit" "${CMAKE_CURRENT_BINARY_DIR}" -v --timeout=300 - DEPENDS thorin thorin_all_plugins) - -# We don't want to test python for memory leaks.. :/ -# add_test(NAME lit COMMAND python3 "${CMAKE_CURRENT_SOURCE_DIR}/lit" "${CMAKE_CURRENT_BINARY_DIR}" -v) + COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/lit" "${CMAKE_CURRENT_BINARY_DIR}" -v --timeout=300 + DEPENDS thorin thorin_all_plugins +) diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index bd707c1d1c..f3b590f920 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -94,13 +94,17 @@ add_library(libthorin util/utf8.h util/util.h ) - set_target_properties(libthorin PROPERTIES PREFIX "") +target_compile_features(libthorin PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) # make property public. + +if(MSVC AND BUILD_SHARED_LIBS) + target_compile_definitions(libthorin PUBLIC ABSL_CONSUME_DLL) +endif() configure_file( config.h.in - "${CMAKE_BINARY_DIR}/include/thorin/config.h") - + "${CMAKE_BINARY_DIR}/include/thorin/config.h" +) target_include_directories(libthorin PUBLIC $ # for config.h @@ -108,7 +112,6 @@ target_include_directories(libthorin $ $ ) - target_link_libraries(libthorin PUBLIC absl::btree @@ -117,26 +120,20 @@ target_link_libraries(libthorin rang ${CMAKE_DL_LIBS} ) - -target_compile_features(libthorin PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) # make property public. - -if(MSVC AND BUILD_SHARED_LIBS) - target_compile_definitions(libthorin PUBLIC ABSL_CONSUME_DLL) -endif() - install( TARGETS libthorin EXPORT thorin_exports - INCLUDES DESTINATION include) - + INCLUDES DESTINATION include +) install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DESTINATION include FILES_MATCHING PATTERN "*.h") - + DESTINATION include FILES_MATCHING PATTERN "*.h" +) install( FILES "${CMAKE_BINARY_DIR}/include/thorin/config.h" - DESTINATION include/thorin) - + DESTINATION include/thorin +) install( FILES "${CMAKE_CURRENT_SOURCE_DIR}/../modules/half/include/half.hpp" - DESTINATION include) + DESTINATION include +) From 681a33855485e0198616028875e498bb180cadba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 17:11:23 +0200 Subject: [PATCH 08/53] cleanup --- CMakeLists.txt | 27 ++++++++++++--------------- thorin/CMakeLists.txt | 5 ++++- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f501afa822..6698cb739b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,25 +94,22 @@ write_basic_package_version_file( VERSION ${Thorin_VERSION} COMPATIBILITY SameMajorVersion ) -set(THORIN_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/thorin") - -install( - FILES cmake/Thorin.cmake - DESTINATION ${THORIN_CMAKE_INSTALL_DIR} +configure_package_config_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/thorin-config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/thorin" ) install( EXPORT thorin_exports FILE thorin-targets.cmake NAMESPACE thorin:: - DESTINATION ${THORIN_CMAKE_INSTALL_DIR} -) -configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/thorin-config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" - INSTALL_DESTINATION ${THORIN_CMAKE_INSTALL_DIR} + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/thorin" ) -install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/thorin-config-version.cmake" - DESTINATION "${THORIN_CMAKE_INSTALL_DIR}" +install( + FILES + cmake/Thorin.cmake + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/thorin-config-version.cmake" + DESTINATION + "${CMAKE_INSTALL_LIBDIR}/cmake/thorin" ) diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index f3b590f920..92f6123a0a 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -123,7 +123,10 @@ target_link_libraries(libthorin install( TARGETS libthorin EXPORT thorin_exports - INCLUDES DESTINATION include + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) install( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} From 478c4b475046c88e375c41a6ab259bd2f896d902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 29 Sep 2023 21:31:21 +0200 Subject: [PATCH 09/53] remove THORIN_BUILD_TESTING option simply use the global BUILD_TESTING option --- .github/workflows/linux.yml | 4 ++-- .github/workflows/macos.yml | 2 +- .github/workflows/windows.yml | 2 +- CMakeLists.txt | 31 ++++++++++++++++--------------- docs/README.md | 6 +++--- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 5d1147d2a8..18c481733f 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -62,11 +62,11 @@ jobs: - name: Configure Debug if: matrix.build-type == 'Debug' - run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DTHORIN_BUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON + run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON - name: Configure Release if: matrix.build-type == 'Release' - run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DTHORIN_BUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DTHORIN_LIT_WITH_VALGRIND=ON + run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DTHORIN_LIT_WITH_VALGRIND=ON - name: Build run: cmake --build ${{github.workspace}}/build -v diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 38e1a1e8fc..65852c54dc 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -26,7 +26,7 @@ jobs: override_cache_key: mac-latest-ccache-${{matrix.build-type}} - name: Configure - run: CC=gcc-11 CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DTHORIN_BUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=$(dirname $(which python3)) + run: CC=gcc-11 CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=$(dirname $(which python3)) - name: Cache LLVM and Clang id: cache-llvm diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 0a4fb40a18..b30b9991d5 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -42,7 +42,7 @@ jobs: set CXX=cl.exe python -c "import sys; import os; print(os.path.dirname(sys.executable))" > tmpPath set /p PYTHON_PATH= < tmpPath - cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DTHORIN_BUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=%PYTHON_PATH% + cmake -B ${{github.workspace}}/build -G Ninja -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=%PYTHON_PATH% - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v1.6.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6698cb739b..e8829b839a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(Thorin VERSION 1.9.0) +include(CMakeDependentOption) include(CMakePackageConfigHelpers) include(GNUInstallDirs) @@ -31,8 +32,6 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") option(BUILD_SHARED_LIBS "Build shared libraries." ON) option(THORIN_BUILD_DOCS "If ON, Thorin will build the documentation (requires Doxygen)." OFF) option(THORIN_BUILD_EXAMPLES "If ON, Thorin will build examples." OFF) -option(THORIN_BUILD_TESTING "If ON, Thorin will build all of Thorin's own tests." OFF) -option(THORIN_LIT_WITH_VALGRIND "If ON, the Thorin CLI in the lit tests will be run under valgrind." OFF) option(THORIN_INSTALL_DEPENDENCIES "If ON, Thorin's dependencies will be installed alongside Thorin (use when not installing globally)." OFF) message(STATUS "Build type: ${CMAKE_BUILD_TYPE}; shared libs: ${BUILD_SHARED_LIBS}") @@ -49,6 +48,21 @@ else() add_compile_options(-Wall -Wextra) endif() +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + find_program(MEMORYCHECK_COMMAND valgrind) + set(VALGRIND_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") + option(BUILD_TESTING "Build lit and unit tests." OFF) # needs to be BEFORE "include(CTest)" + include(CTest) + cmake_dependent_option(THORIN_LIT_WITH_VALGRIND "If ON, the Thorin CLI in the lit tests will be run under valgrind." OFF "BUILD_TESTING" OFF) + if(BUILD_TESTING) + include(GoogleTest) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + add_subdirectory(modules/googletest EXCLUDE_FROM_ALL) + add_subdirectory(gtest) + add_subdirectory(lit) + endif() +endif() + set(ABSL_PROPAGATE_CXX_STD ON) set(ABSL_USE_EXTERNAL_GOOGLETEST ON) set(ABSL_ENABLE_INSTALL ON) @@ -69,19 +83,6 @@ if(THORIN_BUILD_EXAMPLES) add_subdirectory(examples) endif() -if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR THORIN_BUILD_TESTING) AND BUILD_TESTING) - find_program(MEMORYCHECK_COMMAND valgrind) - set(VALGRIND_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") # needs to be BEFORE "include(CTest)" - include(CTest) - - include(GoogleTest) - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - add_subdirectory(modules/googletest EXCLUDE_FROM_ALL) - - add_subdirectory(gtest) - add_subdirectory(lit) -endif() - if(THORIN_BUILD_DOCS) find_package(Doxygen REQUIRED dot) if(DOXYGEN_FOUND) diff --git a/docs/README.md b/docs/README.md index 8a66946d4c..1b79ed7a5f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -86,9 +86,9 @@ cmake --build build -j $(nproc) -t install |-------------------------|------------------------------------------|--------------|---------------------------------------------------------------------------------------| | `CMAKE_BUILD_TYPE` | `Debug` \| `Release` \| `RelWithDebInfo` | `Debug` | Build type. | | `CMAKE_INSTALL_PREFIX` | | `/usr/local` | Install prefix. | -| `THORIN_BUILD_DOCS` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build the documentation
(requires Doxygen). | -| `THORIN_BUILD_EXAMPLES` | `ON` \| `OFF` | `OFF` | If `ON`, Thorin will build the examples. | -| `THORIN_BUILD_TESTING` | `ON` \| `OFF` | `OFF` | If `ON` **and** `BUILD_TESTING` is `ON`, Thorin will build all of Thorin's own tests. | +| `THORIN_BUILD_DOCS` | `ON` \| `OFF` | `OFF` | If `ON`, build the documentation
(requires Doxygen). | +| `THORIN_BUILD_EXAMPLES` | `ON` \| `OFF` | `OFF` | If `ON`, build the examples. | +| `BUILD_TESTING` | `ON` \| `OFF` | `OFF` | If `ON`, build all unit and lit tests. | | `THORIN_ENABLE_CHECKS` | `ON` \| `OFF` | `ON` | If `ON`, enables expensive runtime checks
(requires `CMAKE_BUILD_TYPE=Debug`). | ## Dependencies From b1afd2f4c82b7514cfe4a1911a716abd3e916f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 02:40:20 +0200 Subject: [PATCH 10/53] modules -> external + added leissa/fe --- .gitmodules | 15 +++++++++------ CMakeLists.txt | 14 +++++++------- docs/Doxyfile.in | 16 ++++++++-------- external/fe | 1 + {modules => external/modules}/abseil-cpp | 0 .../modules}/doxygen-awesome-css | 0 {modules => external/modules}/googletest | 0 {modules => external/modules}/half | 0 {modules => external/modules}/lyra | 0 {modules => external/modules}/rang | 0 thorin/CMakeLists.txt | 4 ++-- 11 files changed, 27 insertions(+), 23 deletions(-) create mode 160000 external/fe rename {modules => external/modules}/abseil-cpp (100%) rename {modules => external/modules}/doxygen-awesome-css (100%) rename {modules => external/modules}/googletest (100%) rename {modules => external/modules}/half (100%) rename {modules => external/modules}/lyra (100%) rename {modules => external/modules}/rang (100%) diff --git a/.gitmodules b/.gitmodules index 26cb620918..b8f5a37362 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,18 +1,21 @@ [submodule "abseil-cpp"] - path = modules/abseil-cpp + path = external/modules/abseil-cpp url = ../../abseil/abseil-cpp [submodule "doxygen-awesome-css"] - path = modules/doxygen-awesome-css + path = external/modules/doxygen-awesome-css url = ../../jothepro/doxygen-awesome-css.git [submodule "googletest"] - path = modules/googletest + path = external/modules/googletest url = ../../google/googletest.git [submodule "half"] - path = modules/half + path = external/modules/half url = ../../AnyDSL/half.git [submodule "lyra"] - path = modules/lyra + path = external/modules/lyra url = ../../bfgroup/lyra.git [submodule "modules/rang"] - path = modules/rang + path = external/modules/rang url = ../../agauniyal/rang.git +[submodule "external/fe"] + path = external/fe + url = ../../leissa/fe.git diff --git a/CMakeLists.txt b/CMakeLists.txt index e8829b839a..26d2569c45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) if(BUILD_TESTING) include(GoogleTest) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - add_subdirectory(modules/googletest EXCLUDE_FROM_ALL) + add_subdirectory(external/googletest EXCLUDE_FROM_ALL) add_subdirectory(gtest) add_subdirectory(lit) endif() @@ -67,13 +67,13 @@ set(ABSL_PROPAGATE_CXX_STD ON) set(ABSL_USE_EXTERNAL_GOOGLETEST ON) set(ABSL_ENABLE_INSTALL ON) if(NOT THORIN_INSTALL_DEPENDENCIES) - add_subdirectory(modules/abseil-cpp EXCLUDE_FROM_ALL) - add_subdirectory(modules/rang EXCLUDE_FROM_ALL) - add_subdirectory(modules/lyra EXCLUDE_FROM_ALL) + add_subdirectory(external/abseil-cpp EXCLUDE_FROM_ALL) + add_subdirectory(external/rang EXCLUDE_FROM_ALL) + add_subdirectory(external/lyra EXCLUDE_FROM_ALL) else() - add_subdirectory(modules/abseil-cpp) - add_subdirectory(modules/rang) - add_subdirectory(modules/lyra) + add_subdirectory(external/abseil-cpp) + add_subdirectory(external/rang) + add_subdirectory(external/lyra) endif() add_subdirectory(thorin) add_subdirectory(cli) diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index e6acb9ca98..03578cb102 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -1337,11 +1337,11 @@ HTML_STYLESHEET = # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = modules/doxygen-awesome-css/doxygen-awesome.css \ - modules/doxygen-awesome-css/doxygen-awesome-sidebar-only.css \ - modules/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css \ - modules/doxygen-awesome-css/doxygen-awesome-interactive-toc.js \ - modules/doxygen-awesome-css/doxygen-custom/custom.css +HTML_EXTRA_STYLESHEET = external/doxygen-awesome-css/doxygen-awesome.css \ + external/doxygen-awesome-css/doxygen-awesome-sidebar-only.css \ + external/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css \ + external/doxygen-awesome-css/doxygen-awesome-interactive-toc.js \ + external/doxygen-awesome-css/doxygen-custom/custom.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1351,9 +1351,9 @@ HTML_EXTRA_STYLESHEET = modules/doxygen-awesome-css/doxygen-awesome.css \ # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = modules/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js \ - modules/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js \ - modules/doxygen-awesome-css/doxygen-awesome-paragraph-link.js +HTML_EXTRA_FILES = external/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js \ + external/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js \ + external/doxygen-awesome-css/doxygen-awesome-paragraph-link.js # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. diff --git a/external/fe b/external/fe new file mode 160000 index 0000000000..6f8f5148f7 --- /dev/null +++ b/external/fe @@ -0,0 +1 @@ +Subproject commit 6f8f5148f726658e4d99f45aa140bd4061f646d0 diff --git a/modules/abseil-cpp b/external/modules/abseil-cpp similarity index 100% rename from modules/abseil-cpp rename to external/modules/abseil-cpp diff --git a/modules/doxygen-awesome-css b/external/modules/doxygen-awesome-css similarity index 100% rename from modules/doxygen-awesome-css rename to external/modules/doxygen-awesome-css diff --git a/modules/googletest b/external/modules/googletest similarity index 100% rename from modules/googletest rename to external/modules/googletest diff --git a/modules/half b/external/modules/half similarity index 100% rename from modules/half rename to external/modules/half diff --git a/modules/lyra b/external/modules/lyra similarity index 100% rename from modules/lyra rename to external/modules/lyra diff --git a/modules/rang b/external/modules/rang similarity index 100% rename from modules/rang rename to external/modules/rang diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 92f6123a0a..0583e102b3 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -109,7 +109,7 @@ target_include_directories(libthorin PUBLIC $ # for config.h $ # for thorin/* - $ + $ $ ) target_link_libraries(libthorin @@ -137,6 +137,6 @@ install( DESTINATION include/thorin ) install( - FILES "${CMAKE_CURRENT_SOURCE_DIR}/../modules/half/include/half.hpp" + FILES "${CMAKE_CURRENT_SOURCE_DIR}/../external/half/include/half.hpp" DESTINATION include ) From 0e9e08743e9fb76410e8870f66df98af2d7751d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 03:27:23 +0200 Subject: [PATCH 11/53] thorin_exports -> thorin-targets --- CMakeLists.txt | 3 +-- cli/CMakeLists.txt | 7 +------ cmake/Thorin.cmake | 4 ++-- docs/coding.md | 2 +- examples/CMakeLists.txt | 2 +- thorin/CMakeLists.txt | 2 +- 6 files changed, 7 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8829b839a..6f393226c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,8 +101,7 @@ configure_package_config_file( INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/thorin" ) install( - EXPORT thorin_exports - FILE thorin-targets.cmake + EXPORT thorin-targets NAMESPACE thorin:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/thorin" ) diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt index 07b15c6ad6..7923d161df 100644 --- a/cli/CMakeLists.txt +++ b/cli/CMakeLists.txt @@ -1,9 +1,4 @@ add_executable(thorin main.cpp) - target_link_libraries(thorin libthorin lyra) - set_target_properties(thorin PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") -install( - TARGETS thorin - EXPORT thorin_exports -) +install(TARGETS thorin EXPORT thorin-targets) diff --git a/cmake/Thorin.cmake b/cmake/Thorin.cmake index edbf88f9b6..ee92b3ff71 100644 --- a/cmake/Thorin.cmake +++ b/cmake/Thorin.cmake @@ -45,7 +45,7 @@ and passes to identify the axioms. header to be up-to-date. - `INSTALL`: Specify, if the plugin description, plugin and headers shall be installed with `make install`. - To export the targets, the export name `thorin_exports` has to be + To export the targets, the export name `thorin-targets` has to be exported accordingly (see [install(EXPORT ..)](https://cmake.org/cmake/help/latest/command/install.html#export)) @@ -134,7 +134,7 @@ function(add_thorin_plugin) if(${PARSED_INSTALL}) install( TARGETS thorin_${PLUGIN} - EXPORT thorin_exports + EXPORT thorin-targets LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/thorin" RUNTIME DESTINATION "${CMAKE_INSTALL_LIBDIR}/thorin" INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") diff --git a/docs/coding.md b/docs/coding.md index 1e9c050aa7..8e436c439f 100644 --- a/docs/coding.md +++ b/docs/coding.md @@ -236,5 +236,5 @@ containing the axiom declarations. header to be up-to-date. - `INSTALL`: Specify, if the plugin description, plugin and headers shall be installed with `make install`. - To export the targets, the export name `install_exports` has to be + To export the targets, the export name `thorin-targets` has to be exported accordingly (see [install(EXPORT ..)](https://cmake.org/cmake/help/latest/command/install.html#export)) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1df0c6f723..2891f7608a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -4,4 +4,4 @@ target_link_libraries(hello libthorin) set_target_properties(hello PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/examples") add_dependencies(hello compile core) -install(TARGETS hello EXPORT thorin_exports) +install(TARGETS hello EXPORT thorin-targets) diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 92f6123a0a..3a111da22c 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -122,7 +122,7 @@ target_link_libraries(libthorin ) install( TARGETS libthorin - EXPORT thorin_exports + EXPORT thorin-targets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} From 61e0c4c7a94607a3532a50574add74f3e513b56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 03:35:17 +0200 Subject: [PATCH 12/53] thorin/util/assert.h -> fe/assert.h --- CMakeLists.txt | 7 ++- cli/main.cpp | 2 +- cmake/thorin-config.cmake.in | 1 + .../auxiliary/autodiff_rewrite_inner.cpp | 2 - dialects/clos/phase/clos_conv.cpp | 2 +- dialects/core/be/ll.cpp | 18 +++--- dialects/core/normalizers.cpp | 10 ++-- dialects/math/math.h | 7 +-- dialects/math/normalizers.cpp | 59 +++++++------------ dialects/mem/pass/fp/copy_prop.cpp | 4 +- dialects/regex/normalizers_regex.cpp | 3 +- dialects/regex/pass/lower_regex.cpp | 2 - examples/hello.cpp | 2 +- external/fe | 2 +- gtest/lexer.cpp | 3 +- gtest/restricted_dep_types.cpp | 4 +- gtest/test.cpp | 4 +- thorin/CMakeLists.txt | 4 +- thorin/analyses/domtree.cpp | 8 +-- thorin/analyses/looptree.cpp | 14 ++--- thorin/axiom.h | 16 ++--- thorin/check.cpp | 2 +- thorin/def.cpp | 10 ++-- thorin/def.h | 4 +- thorin/dump.cpp | 11 ++-- thorin/fe/ast.cpp | 4 +- thorin/fe/ast.h | 3 - thorin/fe/lexer.cpp | 6 +- thorin/fe/lexer.h | 5 +- thorin/fe/parser.cpp | 14 ++--- thorin/fe/parser.h | 4 +- thorin/fe/scopes.cpp | 4 +- thorin/fe/scopes.h | 4 -- thorin/fe/tok.cpp | 24 ++++---- thorin/fe/tok.h | 8 +-- thorin/util/assert.h | 40 ------------- thorin/util/bitset.cpp | 14 ++--- thorin/util/log.cpp | 4 +- thorin/util/log.h | 8 +-- thorin/util/print.cpp | 4 +- thorin/util/print.h | 38 +++++------- thorin/util/utf8.cpp | 2 +- thorin/util/util.h | 41 +++++-------- thorin/world.h | 6 +- 44 files changed, 166 insertions(+), 268 deletions(-) delete mode 100644 thorin/util/assert.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 26d2569c45..d9e5c6a79f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,14 +66,17 @@ endif() set(ABSL_PROPAGATE_CXX_STD ON) set(ABSL_USE_EXTERNAL_GOOGLETEST ON) set(ABSL_ENABLE_INSTALL ON) +set(FE_ABSL ON) if(NOT THORIN_INSTALL_DEPENDENCIES) add_subdirectory(external/abseil-cpp EXCLUDE_FROM_ALL) - add_subdirectory(external/rang EXCLUDE_FROM_ALL) + add_subdirectory(external/fe EXCLUDE_FROM_ALL) add_subdirectory(external/lyra EXCLUDE_FROM_ALL) + add_subdirectory(external/rang EXCLUDE_FROM_ALL) else() add_subdirectory(external/abseil-cpp) - add_subdirectory(external/rang) + add_subdirectory(external/fe) add_subdirectory(external/lyra) + add_subdirectory(external/rang) endif() add_subdirectory(thorin) add_subdirectory(cli) diff --git a/cli/main.cpp b/cli/main.cpp index 77a4c49c85..976ab8fd44 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -130,7 +130,7 @@ int main(int argc, char** argv) { auto path = fs::path(input); world.set(path.filename().replace_extension().string()); - auto parser = fe::Parser(world); + auto parser = Parser(world); parser.import(input, os[Md]); if (flags.bootstrap) { diff --git a/cmake/thorin-config.cmake.in b/cmake/thorin-config.cmake.in index 4c836ea169..6b523eb20d 100644 --- a/cmake/thorin-config.cmake.in +++ b/cmake/thorin-config.cmake.in @@ -3,6 +3,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) include(../absl/abslConfig) +include(../fe/fe-config) include(../rang/rang-config) include(thorin-targets) set(THORIN_TARGET_NAMESPACE "thorin::") diff --git a/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp b/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp index c219d34600..d5e4781bce 100644 --- a/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp +++ b/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp @@ -3,8 +3,6 @@ #include "thorin/tuple.h" -#include "thorin/util/assert.h" - #include "dialects/autodiff/autodiff.h" #include "dialects/autodiff/pass/autodiff_eval.h" #include "dialects/core/core.h" diff --git a/dialects/clos/phase/clos_conv.cpp b/dialects/clos/phase/clos_conv.cpp index ce555cf9d6..1b6c3992a3 100644 --- a/dialects/clos/phase/clos_conv.cpp +++ b/dialects/clos/phase/clos_conv.cpp @@ -240,7 +240,7 @@ const Def* ClosConv::rewrite(const Def* def, Def2Def& subst) { return map(def->rebuild(w, new_type, new_ops)); } - thorin::unreachable(); + fe::unreachable(); } Def* ClosConv::rewrite_mut(Def* mut, const Def* new_type, Def2Def& subst) { diff --git a/dialects/core/be/ll.cpp b/dialects/core/be/ll.cpp index 4c1f552d76..fe09493b94 100644 --- a/dialects/core/be/ll.cpp +++ b/dialects/core/be/ll.cpp @@ -171,7 +171,7 @@ std::string Emitter::convert(const Def* type) { case 16: return types_[type] = "half"; case 32: return types_[type] = "float"; case 64: return types_[type] = "double"; - default: unreachable(); + default: fe::unreachable(); } } else if (auto ptr = match(type)) { auto [pointee, addr_space] = ptr->args<2>(); @@ -214,7 +214,7 @@ std::string Emitter::convert(const Def* type) { } print(s, "}}"); } else { - unreachable(); + fe::unreachable(); } if (name.empty()) return types_[type] = s.str(); @@ -529,13 +529,13 @@ std::string Emitter::emit_bb(BB& bb, const Def* def) { break; } case 64: hex = lit->get(); break; - default: unreachable(); + default: fe::unreachable(); } s << "0x" << std::setfill('0') << std::setw(16) << std::right << std::hex << hex; return s.str(); } - unreachable(); + fe::unreachable(); } else if (def->isa()) { return "undef"; } else if (auto top = def->isa()) { @@ -635,7 +635,7 @@ std::string Emitter::emit_bb(BB& bb, const Def* def) { case core::ncmp::l: op += "ult"; break; case core::ncmp::le: op += "ule"; break; // clang-format on - default: unreachable(); + default: fe::unreachable(); } return bb.assign(name, "{} i64 {}, {}", op, a, b); @@ -667,7 +667,7 @@ std::string Emitter::emit_bb(BB& bb, const Def* def) { case core::bit2:: iff: return bb.assign(name, "and {} {}, {}", neg(a), b); case core::bit2::niff: return bb.assign(name, "or {} {}, {}", neg(a), b); // clang-format on - default: unreachable(); + default: fe::unreachable(); } } else if (auto shr = match(def)) { auto [a, b] = shr->args<2>([this](auto def) { return emit(def); }); @@ -729,7 +729,7 @@ std::string Emitter::emit_bb(BB& bb, const Def* def) { case core::icmp::ul: op += "ult"; break; case core::icmp::ule: op += "ule"; break; // clang-format on - default: unreachable(); + default: fe::unreachable(); } return bb.assign(name, "{} {} {}, {}", op, t, a, b); @@ -922,7 +922,7 @@ std::string Emitter::emit_bb(BB& bb, const Def* def) { case math::tri::cos: f += "cos"; break; case math::tri::tan: f += "tan"; break; case math::tri::ahFF: error("this axiom is supposed to be unused"); - default: unreachable(); + default: fe::unreachable(); } if (tri.sub() & sub_t(math::tri::h)) f += "h"; @@ -1008,7 +1008,7 @@ std::string Emitter::emit_bb(BB& bb, const Def* def) { case math::cmp::uge: op += "uge"; break; case math::cmp::une: op += "une"; break; // clang-format on - default: unreachable(); + default: fe::unreachable(); } return bb.assign(name, "{} {} {}, {}", op, t, a, b); diff --git a/dialects/core/normalizers.cpp b/dialects/core/normalizers.cpp index 01bc0bba29..225f2f4f86 100644 --- a/dialects/core/normalizers.cpp +++ b/dialects/core/normalizers.cpp @@ -293,7 +293,7 @@ template Ref normalize_ncmp(Ref type, Ref callee, Ref arg) { case ncmp::le: return world.lit_nat(*la <= *lb); case ncmp::g : return world.lit_nat(*la > *lb); case ncmp::ge: return world.lit_nat(*la >= *lb); - default: unreachable(); + default: fe::unreachable(); } // clang-format on } @@ -349,7 +349,7 @@ template Ref normalize_bit1(Ref type, Ref c, Ref a) { switch (id) { case bit1::f: return world.lit_idx(*ls, 0); case bit1::t: return world.lit_idx(*ls, *ls - 1_u64); - case bit1::id: unreachable(); + case bit1::id: fe::unreachable(); default: break; } @@ -400,7 +400,7 @@ template Ref normalize_bit2(Ref type, Ref c, Ref arg) { case bit2::nxor: return world.lit_idx_mod(*ls, ~(*la ^ *lb)); case bit2:: iff: return world.lit_idx_mod(*ls, ~ *la | *lb); case bit2::niff: return world.lit_idx (*ls, *la & ~*lb); - default: unreachable(); + default: fe::unreachable(); } } @@ -516,7 +516,7 @@ template Ref normalize_wrap(Ref type, Ref c, Ref arg) { switch (id) { case wrap::sub: return a; // a - 0 -> a case wrap::shl: return a; // a >> 0 -> a - default: unreachable(); + default: fe::unreachable(); // add, mul are commutative, the literal has been normalized to the left } } @@ -656,7 +656,7 @@ template Ref normalize_trait(Ref nat, Ref callee, Ref type) { case 16: return world.lit_nat(2); case 32: return world.lit_nat(4); case 64: return world.lit_nat(8); - default: unreachable(); + default: fe::unreachable(); } } else if (type->isa() || type->isa()) { u64 offset = 0; diff --git a/dialects/math/math.h b/dialects/math/math.h index 486d42597c..9a31bc24c1 100644 --- a/dialects/math/math.h +++ b/dialects/math/math.h @@ -63,8 +63,7 @@ inline Ref type_f(World& w, nat_t p, nat_t e) { auto le = w.lit_nat(e); return type_f(w.tuple({lp, le})); } -template -inline auto match_f(Ref def) { +template inline auto match_f(Ref def) { if (auto f_ty = match(def)) { auto [p, e] = f_ty->arg()->projs<2>([](auto op) { return Lit::isa(op); }); if (p && e && *p == P && *e == E) return f_ty; @@ -95,7 +94,7 @@ const Lit* lit_f(World& w, R val) { else if constexpr (sizeof(R) == 2) return w.lit(w.annex(), thorin::bitcast(val)); else if constexpr (sizeof(R) == 4) return w.lit(w.annex(), thorin::bitcast(val)); else if constexpr (sizeof(R) == 8) return w.lit(w.annex(), thorin::bitcast(val)); - else unreachable(); + else fe::unreachable(); } inline const Lit* lit_f(World& w, nat_t width, thorin::f64 val) { @@ -103,7 +102,7 @@ inline const Lit* lit_f(World& w, nat_t width, thorin::f64 val) { case 16: assert(thorin::f64(thorin::f16(thorin::f32(val))) == val && "loosing precision"); return lit_f(w, thorin::f16(thorin::f32(val))); case 32: assert(thorin::f64(thorin::f32( (val))) == val && "loosing precision"); return lit_f(w, thorin::f32( (val))); case 64: assert(thorin::f64(thorin::f64( (val))) == val && "loosing precision"); return lit_f(w, thorin::f64( (val))); - default: unreachable(); + default: fe::unreachable(); } } // clang-format on diff --git a/dialects/math/normalizers.cpp b/dialects/math/normalizers.cpp index 49a039e85b..8926876f6f 100644 --- a/dialects/math/normalizers.cpp +++ b/dialects/math/normalizers.cpp @@ -8,8 +8,7 @@ namespace { // TODO move to normalize.h or so? // Swap Lit to left - or smaller gid, if no lit present. -template -void commute(Id id, const Def*& a, const Def*& b) { +template void commute(Id id, const Def*& a, const Def*& b) { if (::thorin::is_commutative(id)) { if (b->isa() || (a->gid() > b->gid() && !a->isa())) std::swap(a, b); } @@ -48,7 +47,7 @@ Res fold(u64 a) { else if constexpr (id == tri::asinh) return asinh(x); else if constexpr (id == tri::acosh) return acosh(x); else if constexpr (id == tri::atanh) return atanh(x); - else unreachable(); + else fe::unreachable(); } else if constexpr (std::is_same_v) { if constexpr (false) {} else if constexpr (id == rt::sq) return std::sqrt(x); @@ -62,7 +61,7 @@ Res fold(u64 a) { else if constexpr (id == exp::log ) return std::log (x); else if constexpr (id == exp::log2 ) return std::log2 (x); else if constexpr (id == exp::log10) return std::log10(x); - else unreachable(); + else fe::unreachable(); } else if constexpr (std::is_same_v) { if constexpr (false) {} else if constexpr (id == er::f ) return std::erf (x); @@ -109,7 +108,7 @@ Ref fold(World& world, Ref type, const Def* a) { case i: res = fold(la->get()); break; THORIN_16_32_64(CODE) #undef CODE - default: unreachable(); + default: fe::unreachable(); } return world.lit(type, *res); @@ -158,8 +157,7 @@ Res fold(u64 a, u64 b) { } // clang-format on -template -Ref fold(World& world, Ref type, const Def* a) { +template Ref fold(World& world, Ref type, const Def* a) { if (a->isa()) return world.bot(type); if (auto la = Lit::isa(a)) { @@ -170,7 +168,7 @@ Ref fold(World& world, Ref type, const Def* a) { case i: res = fold(*la); break; THORIN_16_32_64(CODE) #undef CODE - default: unreachable(); + default: fe::unreachable(); } return world.lit(type, *res); @@ -180,8 +178,7 @@ Ref fold(World& world, Ref type, const Def* a) { } // Note that @p a and @p b are passed by reference as fold also commutes if possible. -template -Ref fold(World& world, Ref type, const Def*& a, const Def*& b) { +template Ref fold(World& world, Ref type, const Def*& a, const Def*& b) { if (a->isa() || b->isa()) return world.bot(type); if (auto la = Lit::isa(a)) { @@ -193,7 +190,7 @@ Ref fold(World& world, Ref type, const Def*& a, const Def*& b) { case i: res = fold(*la, *lb); break; THORIN_16_32_64(CODE) #undef CODE - default: unreachable(); + default: fe::unreachable(); } return world.lit(type, *res); @@ -215,8 +212,7 @@ Ref fold(World& world, Ref type, const Def*& a, const Def*& b) { /// (3) a op (lz op w) -> lz op (a op w) /// (4) (lx op y) op b -> lx op (y op b) /// ``` -template -Ref reassociate(Id id, World& world, [[maybe_unused]] const App* ab, Ref a, Ref b) { +template Ref reassociate(Id id, World& world, [[maybe_unused]] const App* ab, Ref a, Ref b) { if (!is_associative(id)) return nullptr; if (auto xy = match(id, a)) { @@ -254,8 +250,7 @@ Ref reassociate(Id id, World& world, [[maybe_unused]] const App* ab, Ref a, Ref return nullptr; } -template -Res fold(u64 a) { +template Res fold(u64 a) { using S = std::conditional_t, std::conditional_t, w2f>>; using D = std::conditional_t, std::conditional_t, w2f>>; return D(bitcast(a)); @@ -263,8 +258,7 @@ Res fold(u64 a) { } // namespace -template -Ref normalize_arith(Ref type, Ref c, Ref arg) { +template Ref normalize_arith(Ref type, Ref c, Ref arg) { auto& world = type->world(); auto callee = c->as(); auto [a, b] = arg->projs<2>(); @@ -305,7 +299,7 @@ Ref normalize_arith(Ref type, Ref c, Ref arg) { case arith::sub: return a; // a - 0 -> a case arith::div: break; case arith::rem: break; - default: unreachable(); + default: fe::unreachable(); // add, mul are commutative, the literal has been normalized to the left } } @@ -328,8 +322,7 @@ Ref normalize_arith(Ref type, Ref c, Ref arg) { return world.raw_app(type, callee, {a, b}); } -template -Ref normalize_extrema(Ref type, Ref c, Ref arg) { +template Ref normalize_extrema(Ref type, Ref c, Ref arg) { auto& world = type->world(); auto callee = c->as(); auto [a, b] = arg->projs<2>(); @@ -349,8 +342,7 @@ Ref normalize_extrema(Ref type, Ref c, Ref arg) { return world.raw_app(type, c, arg); } -template -Ref normalize_tri(Ref type, Ref c, Ref arg) { +template Ref normalize_tri(Ref type, Ref c, Ref arg) { auto& world = type->world(); if (auto lit = fold(world, type, arg)) return lit; return world.raw_app(type, c, arg); @@ -363,36 +355,31 @@ Ref normalize_pow(Ref type, Ref c, Ref arg) { return world.raw_app(type, c, arg); } -template -Ref normalize_rt(Ref type, Ref c, Ref arg) { +template Ref normalize_rt(Ref type, Ref c, Ref arg) { auto& world = type->world(); if (auto lit = fold(world, type, arg)) return lit; return world.raw_app(type, c, arg); } -template -Ref normalize_exp(Ref type, Ref c, Ref arg) { +template Ref normalize_exp(Ref type, Ref c, Ref arg) { auto& world = type->world(); if (auto lit = fold(world, type, arg)) return lit; return world.raw_app(type, c, arg); } -template -Ref normalize_er(Ref type, Ref c, Ref arg) { +template Ref normalize_er(Ref type, Ref c, Ref arg) { auto& world = type->world(); if (auto lit = fold(world, type, arg)) return lit; return world.raw_app(type, c, arg); } -template -Ref normalize_gamma(Ref type, Ref c, Ref arg) { +template Ref normalize_gamma(Ref type, Ref c, Ref arg) { auto& world = type->world(); if (auto lit = fold(world, type, arg)) return lit; return world.raw_app(type, c, arg); } -template -Ref normalize_cmp(Ref type, Ref c, Ref arg) { +template Ref normalize_cmp(Ref type, Ref c, Ref arg) { auto& world = type->world(); auto callee = c->as(); auto [a, b] = arg->projs<2>(); @@ -404,8 +391,7 @@ Ref normalize_cmp(Ref type, Ref c, Ref arg) { return world.raw_app(type, callee, {a, b}); } -template -Ref normalize_conv(Ref dst_t, Ref c, Ref x) { +template Ref normalize_conv(Ref dst_t, Ref c, Ref x) { auto& world = dst_t->world(); auto callee = c->as(); auto s_t = x->type()->as(); @@ -443,7 +429,7 @@ Ref normalize_conv(Ref dst_t, Ref c, Ref x) { M(32, 1) M(32, 8) M(32, 16) M(32, 32) M(32, 64) M(64, 1) M(64, 8) M(64, 16) M(64, 32) M(64, 64) - else unreachable(); + else fe::unreachable(); // clang-format on return world.lit(d_t, *res); } @@ -458,8 +444,7 @@ Ref normalize_abs(Ref type, Ref c, Ref arg) { return world.raw_app(type, c, arg); } -template -Ref normalize_round(Ref type, Ref c, Ref arg) { +template Ref normalize_round(Ref type, Ref c, Ref arg) { auto& world = type->world(); if (auto lit = fold(world, type, arg)) return lit; return world.raw_app(type, c, arg); diff --git a/dialects/mem/pass/fp/copy_prop.cpp b/dialects/mem/pass/fp/copy_prop.cpp index 75ab595ad9..9acc5d2bb3 100644 --- a/dialects/mem/pass/fp/copy_prop.cpp +++ b/dialects/mem/pass/fp/copy_prop.cpp @@ -43,7 +43,7 @@ Ref CopyProp::rewrite(Ref def) { new_doms.emplace_back(var_lam->var(n, i)->type()); new_args.emplace_back(app->arg(n, i)); break; - default: unreachable(); + default: fe::unreachable(); } } @@ -74,7 +74,7 @@ Ref CopyProp::rewrite(Ref def) { case Lattice::Dead: return proxy(var_lam->var(n, i)->type(), {var_lam, world().lit_nat(i)}, Varxy); case Lattice::Prop: return args[i]; case Lattice::Keep: return prop_lam->var(j++); - default: unreachable(); + default: fe::unreachable(); } }); diff --git a/dialects/regex/normalizers_regex.cpp b/dialects/regex/normalizers_regex.cpp index 679822b14b..1d1550f42e 100644 --- a/dialects/regex/normalizers_regex.cpp +++ b/dialects/regex/normalizers_regex.cpp @@ -4,12 +4,13 @@ #include #include +#include + #include "thorin/axiom.h" #include "thorin/def.h" #include "thorin/tuple.h" #include "thorin/world.h" -#include "thorin/util/assert.h" #include "thorin/util/loc.h" #include "thorin/util/log.h" diff --git a/dialects/regex/pass/lower_regex.cpp b/dialects/regex/pass/lower_regex.cpp index eae767fc70..0a04f65df0 100644 --- a/dialects/regex/pass/lower_regex.cpp +++ b/dialects/regex/pass/lower_regex.cpp @@ -2,8 +2,6 @@ #include "thorin/def.h" -#include "thorin/util/assert.h" - #include "dialects/core/core.h" #include "dialects/direct/direct.h" #include "dialects/mem/mem.h" diff --git a/examples/hello.cpp b/examples/hello.cpp index 3149edf327..b1234257f7 100644 --- a/examples/hello.cpp +++ b/examples/hello.cpp @@ -14,7 +14,7 @@ int main(int, char**) { auto& world = driver.world(); driver.log().set(&std::cerr).set(Log::Level::Debug); - auto parser = fe::Parser(world); + auto parser = Parser(world); for (auto plugin : {"compile", "core"}) parser.plugin(plugin); // .Cn [%mem.M, I32, %mem.Ptr (I32, 0) .Cn [%mem.M, I32]] diff --git a/external/fe b/external/fe index 6f8f5148f7..1555369eb4 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 6f8f5148f726658e4d99f45aa140bd4061f646d0 +Subproject commit 1555369eb4d997a6136c6a932431dad4340c6f3c diff --git a/gtest/lexer.cpp b/gtest/lexer.cpp index 4de1deb40b..5e183fe5bf 100644 --- a/gtest/lexer.cpp +++ b/gtest/lexer.cpp @@ -9,7 +9,6 @@ using namespace std::literals; using namespace thorin; -using namespace thorin::fe; TEST(Lexer, Toks) { Driver driver; @@ -104,7 +103,7 @@ TEST_P(Real, sign) { case 0: break; case 1: s.insert(0, "+"sv); break; case 2: s.insert(0, "-"sv); break; - default: unreachable(); + default: fe::unreachable(); } std::istringstream is(s); diff --git a/gtest/restricted_dep_types.cpp b/gtest/restricted_dep_types.cpp index 3ca68b4eb1..ff7f6ddf5f 100644 --- a/gtest/restricted_dep_types.cpp +++ b/gtest/restricted_dep_types.cpp @@ -30,7 +30,7 @@ TEST(RestrictedDependentTypes, join_singleton) { auto test_on_world = [](auto test) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); for (auto plugin : {"compile", "mem", "core", "math"}) parser.plugin(plugin); auto i32_t = w.type_int(32); @@ -223,7 +223,7 @@ TEST(RestrictedDependentTypes, join_singleton) { TEST(RestrictedDependentTypes, ll) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); for (auto plugin : {"compile", "mem", "core", "math"}) parser.plugin(plugin); auto mem_t = w.annex(); diff --git a/gtest/test.cpp b/gtest/test.cpp index 1fe6fa4a71..e51e700bb0 100644 --- a/gtest/test.cpp +++ b/gtest/test.cpp @@ -17,7 +17,7 @@ using namespace thorin; TEST(Zip, fold) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); std::istringstream iss(".plugin core;" ".let _32 = 4294967296;" @@ -87,7 +87,7 @@ TEST(Annex, split) { TEST(trait, idx) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); parser.plugin("core"); EXPECT_EQ(Lit::as(op(core::trait::size, w.type_idx(0x0000'0000'0000'00FF_n))), 1); diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 0583e102b3..6f989d5930 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -70,7 +70,6 @@ add_library(libthorin phase/phase.cpp phase/phase.h util/array.h - util/assert.h util/bitset.cpp util/bitset.h util/cast.h @@ -117,8 +116,7 @@ target_link_libraries(libthorin absl::btree absl::flat_hash_map absl::flat_hash_set absl::node_hash_map absl::node_hash_set - rang - ${CMAKE_DL_LIBS} + fe rang ${CMAKE_DL_LIBS} ) install( TARGETS libthorin diff --git a/thorin/analyses/domtree.cpp b/thorin/analyses/domtree.cpp index b0b6c62a99..49b3b00f9b 100644 --- a/thorin/analyses/domtree.cpp +++ b/thorin/analyses/domtree.cpp @@ -2,8 +2,7 @@ namespace thorin { -template -void DomTreeBase::create() { +template void DomTreeBase::create() { // Cooper et al, 2001. A Simple, Fast Dominance Algorithm. http://www.cs.rice.edu/~keith/EMBED/dom.pdf idoms_[cfg().entry()] = cfg().entry(); @@ -15,7 +14,7 @@ void DomTreeBase::create() { goto outer_loop; } } - unreachable(); + fe::unreachable(); outer_loop:; } @@ -37,8 +36,7 @@ outer_loop:; for (auto n : cfg().reverse_post_order().skip_front()) children_[idom(n)].push_back(n); } -template -void DomTreeBase::depth(const CFNode* n, int i) { +template void DomTreeBase::depth(const CFNode* n, int i) { depth_[n] = i; for (auto child : children(n)) depth(child, i + 1); } diff --git a/thorin/analyses/looptree.cpp b/thorin/analyses/looptree.cpp index 798f8c2937..63b2333996 100644 --- a/thorin/analyses/looptree.cpp +++ b/thorin/analyses/looptree.cpp @@ -28,8 +28,7 @@ enum { }; } // namespace -template -class LoopTreeBuilder { +template class LoopTreeBuilder { public: using Base = typename LoopTree::Base; using Leaf = typename LoopTree::Leaf; @@ -104,8 +103,7 @@ class LoopTreeBuilder { std::vector stack_; }; -template -void LoopTreeBuilder::build() { +template void LoopTreeBuilder::build() { for (const auto& n : cfg().reverse_post_order()) // clear all flags states_[n] = 0; @@ -114,8 +112,7 @@ void LoopTreeBuilder::build() { recurse(head, {cfg().entry()}, 1); } -template -void LoopTreeBuilder::recurse(Head* parent, Span heads, int depth) { +template void LoopTreeBuilder::recurse(Head* parent, Span heads, int depth) { size_t curr_new_child = 0; for (const auto& head : heads) { set_.clear(); @@ -207,12 +204,11 @@ LoopTree::LoopTree(const CFG& cfg) /// @name std::ostream operator ///@{ -template -std::ostream& operator<<(std::ostream& os, const typename LoopTree::Base* n) { +template std::ostream& operator<<(std::ostream& os, const typename LoopTree::Base* n) { using LT = LoopTree; if (auto l = n->template isa()) return print(os, "<{} | dfs: {}", l->cf_node(), l->index()); if (auto h = n->template isa()) return print(os, "[{, }]", h->cf_nodes()); - unreachable(); + fe::unreachable(); } ///@} diff --git a/thorin/axiom.h b/thorin/axiom.h index 6cd6c93971..7605c79d0e 100644 --- a/thorin/axiom.h +++ b/thorin/axiom.h @@ -1,8 +1,8 @@ #pragma once -#include "thorin/plugin.h" +#include -#include "thorin/util/assert.h" +#include "thorin/plugin.h" namespace thorin { @@ -54,8 +54,7 @@ class Axiom : public Def { ///@} /// Type of Match::def_. - template - struct Match { + template struct Match { using type = App; }; @@ -67,8 +66,7 @@ template concept annex_with_subs = Annex::Num != 0; template concept annex_without_subs = Annex::Num == 0; // clang-format on -template -class Match { +template class Match { static_assert(Annex::Num != size_t(-1), "invalid number of sub tags"); static_assert(Annex::Base != flags_t(-1), "invalid axiom base"); @@ -104,8 +102,7 @@ class Match { /// @name match/force ///@{ /// @see @ref cast_axiom -template -auto match(Ref def) { +template auto match(Ref def) { using D = typename Axiom::Match::type; auto [axiom, curry, _] = Axiom::get(def); bool cond = axiom && curry == 0 && axiom->base() == Annex::Base; @@ -115,8 +112,7 @@ auto match(Ref def) { return Match(axiom, def->as()); } -template -auto match(Id id, Ref def) { +template auto match(Id id, Ref def) { using D = typename Axiom::Match::type; auto [axiom, curry, _] = Axiom::get(def); bool cond = axiom && curry == 0 && axiom->flags() == (flags_t)id; diff --git a/thorin/check.cpp b/thorin/check.cpp index 9310d722d0..51f90409cb 100644 --- a/thorin/check.cpp +++ b/thorin/check.cpp @@ -77,7 +77,7 @@ bool Infer::eliminate(Array refs) { #ifdef THORIN_ENABLE_CHECKS template bool Check::fail() { - if (infer && world().flags().break_on_alpha_unequal) breakpoint(); + if (infer && world().flags().break_on_alpha_unequal) fe::breakpoint(); return false; } #endif diff --git a/thorin/def.cpp b/thorin/def.cpp index 40427a702b..831749d7bd 100644 --- a/thorin/def.cpp +++ b/thorin/def.cpp @@ -81,8 +81,8 @@ UMax::UMax(World& world, Defs ops) * rebuild */ -Ref Infer ::rebuild(World&, Ref, Defs ) const { unreachable(); } -Ref Global ::rebuild(World&, Ref, Defs ) const { unreachable(); } +Ref Infer ::rebuild(World&, Ref, Defs ) const { fe::unreachable(); } +Ref Global ::rebuild(World&, Ref, Defs ) const { fe::unreachable(); } Ref Idx ::rebuild(World& w, Ref , Defs ) const { return w.type_idx(); } Ref Nat ::rebuild(World& w, Ref , Defs ) const { return w.type_nat(); } Ref Univ ::rebuild(World& w, Ref , Defs ) const { return w.univ(); } @@ -129,7 +129,7 @@ Pi* Pi ::stub(World& w, Ref t) { return w.mut_pi (t, is_implicit()) ->s Sigma* Sigma ::stub(World& w, Ref t) { return w.mut_sigma(t, num_ops()) ->set(dbg()); } template TBound* TBound::stub(World& w, Ref t) { return w.mut_bound(t, num_ops()); } -template TExt * TExt ::stub(World& , Ref ) { unreachable(); } +template TExt * TExt ::stub(World& , Ref ) { fe::unreachable(); } /* * instantiate templates @@ -248,7 +248,7 @@ std::string_view Def::node_name() const { case Node::op: return #abbr; THORIN_NODE(CODE) #undef CODE - default: unreachable(); + default: fe::unreachable(); } } @@ -291,7 +291,7 @@ Ref Def::var() { if (isa()) return w.var(this, this); if (isa()) return nullptr; if (isa()) return nullptr; - unreachable(); + fe::unreachable(); } bool Def::is_term() const { diff --git a/thorin/def.h b/thorin/def.h index 15de588187..09c1cf99e6 100644 --- a/thorin/def.h +++ b/thorin/def.h @@ -3,6 +3,8 @@ #include #include +#include + #include "thorin/config.h" #include "thorin/util/array.h" @@ -453,7 +455,7 @@ class Def : public RuntimeCast { /// @name Rebuild ///@{ - virtual Def* stub(World&, Ref) { unreachable(); } + virtual Def* stub(World&, Ref) { fe::unreachable(); } /// Def::rebuild%s this Def while using @p new_op as substitute for its @p i'th Def::op virtual Ref rebuild(World& w, Ref type, Defs ops) const = 0; diff --git a/thorin/dump.cpp b/thorin/dump.cpp index 45fd18e339..55cafb1023 100644 --- a/thorin/dump.cpp +++ b/thorin/dump.cpp @@ -1,10 +1,11 @@ #include +#include + #include "thorin/driver.h" #include "thorin/analyses/deptree.h" #include "thorin/fe/tok.h" -#include "thorin/util/assert.h" #include "thorin/util/util.h" using namespace std::literals; @@ -89,10 +90,10 @@ template struct LRPrec { friend std::ostream& operator<<(std::ostream& os, const LRPrec& p) { if constexpr (L) { - if (Inline(p.l) && fe::Tok::prec(fe::Tok::prec(p.r))[0] > fe::Tok::prec(p.r)) return print(os, "({})", p.l); + if (Inline(p.l) && Tok::prec(Tok::prec(p.r))[0] > Tok::prec(p.r)) return print(os, "({})", p.l); return print(os, "{}", p.l); } else { - if (Inline(p.r) && fe::Tok::prec(p.l) > fe::Tok::prec(fe::Tok::prec(p.l))[1]) return print(os, "({})", p.r); + if (Inline(p.r) && Tok::prec(p.l) > Tok::prec(Tok::prec(p.l))[1]) return print(os, "({})", p.r); return print(os, "{}", p.r); } } @@ -215,7 +216,7 @@ void Dumper::dump(Def* mut) { if (def->isa()) return ".Arr"; if (def->isa()) return ".pack"; if (def->isa()) return ".Pi"; - unreachable(); + fe::unreachable(); }; auto mut_op0 = [&](const Def* def) -> std::ostream& { @@ -223,7 +224,7 @@ void Dumper::dump(Def* mut) { if (auto arr = def->isa()) return print(os, ", {}", arr->shape()); if (auto pack = def->isa()) return print(os, ", {}", pack->shape()); if (auto pi = def->isa()) return print(os, ", {}", pi->dom()); - unreachable(); + fe::unreachable(); }; if (!mut->is_set()) { diff --git a/thorin/fe/ast.cpp b/thorin/fe/ast.cpp index 4470cfc29e..b8ec0d1d2d 100644 --- a/thorin/fe/ast.cpp +++ b/thorin/fe/ast.cpp @@ -7,7 +7,7 @@ #include "thorin/fe/scopes.h" -namespace thorin::fe { +namespace thorin { /* * bind @@ -87,4 +87,4 @@ const Def* TuplePtrn::type(World& world, Def2Fields& def2fields) const { return type_ = sigma; } -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/ast.h b/thorin/fe/ast.h index 65762ad73a..9b2abfbf02 100644 --- a/thorin/fe/ast.h +++ b/thorin/fe/ast.h @@ -13,8 +13,6 @@ class Infer; class Sigma; class World; -namespace fe { - class Scopes; using Def2Fields = DefMap>; @@ -76,5 +74,4 @@ class TuplePtrn : public Ptrn { Def* decl_ = nullptr; }; -} // namespace fe } // namespace thorin diff --git a/thorin/fe/lexer.cpp b/thorin/fe/lexer.cpp index a44c901ff5..19c2c80c87 100644 --- a/thorin/fe/lexer.cpp +++ b/thorin/fe/lexer.cpp @@ -4,7 +4,7 @@ using namespace std::literals; -namespace thorin::fe { +namespace thorin { using Tag = Tok::Tag; @@ -281,7 +281,7 @@ void Lexer::parse_digits(int base /*= 10*/) { case 8: while (accept_if([](int i) { return '0' <= i && i <= '7'; })) {} break; case 10: while (accept_if(isdigit)) {} break; case 16: while (accept_if(isxdigit)) {} break; - default: unreachable(); + default: fe::unreachable(); } }; @@ -355,4 +355,4 @@ void Lexer::emit_md(bool start_of_file) { Sym Lexer::sym() { return world().sym(str_); } -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/lexer.h b/thorin/fe/lexer.h index 9c78df56e9..5171a5c28b 100644 --- a/thorin/fe/lexer.h +++ b/thorin/fe/lexer.h @@ -9,9 +9,6 @@ namespace thorin { class World; -} - -namespace thorin::fe { class Lexer : public utf8::Lexer<3> { using Super = utf8::Lexer<3>; @@ -63,4 +60,4 @@ class Lexer : public utf8::Lexer<3> { std::optional cache_ = std::nullopt; }; -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index 833539621a..45d05bfa8e 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -16,7 +16,7 @@ using namespace std::string_literals; -namespace thorin::fe { +namespace thorin { using Tag = Tok::Tag; @@ -386,7 +386,7 @@ Pi* Parser::parse_pi_expr(Pi* outer) { case Tag::T_Pi: entity = "dependent function type"; break; case Tag::K_Cn: entity = "continuation type"; break; case Tag::K_Fn: entity = "returning continuation type"; break; - default: unreachable(); + default: fe::unreachable(); } Pi* first = nullptr; @@ -423,7 +423,7 @@ Pi* Parser::parse_pi_expr(Pi* outer) { pi->unset()->set_dom(last); break; } - default: unreachable(); + default: fe::unreachable(); } for (auto pi : pis | std::ranges::views::reverse) { @@ -451,7 +451,7 @@ Lam* Parser::parse_lam(bool is_decl) { case Tag::K_lam: entity = "function declaration"; break; case Tag::K_con: entity = "continuation declaration"; break; case Tag::K_fun: entity = "returning continuation declaration"; break; - default: unreachable(); + default: fe::unreachable(); } // clang-format on @@ -539,7 +539,7 @@ Lam* Parser::parse_lam(bool is_decl) { scopes_.bind({ret_loc, return_}, new_var->proj(2, 1)->set(Dbg{ret_loc, return_})); break; } - default: unreachable(); + default: fe::unreachable(); } auto [_, first, __] = funs.front(); @@ -625,7 +625,7 @@ Ref Parser::parse_lit_expr() { case Tag::L_f: break; case Tag::T_bot: return world().bot(type)->set(track.loc()); case Tag::T_top: return world().top(type)->set(track.loc()); - default: unreachable(); + default: fe::unreachable(); } // clang-format on return world().lit(type, tok.lit_u())->set(track.loc()); @@ -1014,4 +1014,4 @@ void Parser::parse_pi_decl() { expect(Tag::T_semicolon, "end of a pi declaration"); } -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/parser.h b/thorin/fe/parser.h index 95720e0559..9adc440034 100644 --- a/thorin/fe/parser.h +++ b/thorin/fe/parser.h @@ -6,7 +6,7 @@ #include "thorin/fe/lexer.h" #include "thorin/fe/scopes.h" -namespace thorin::fe { +namespace thorin { /// Parses Thorin code into the provided World. /// @@ -182,4 +182,4 @@ class Parser { Sym return_; }; -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/scopes.cpp b/thorin/fe/scopes.cpp index c1cf68f62c..db76e27d80 100644 --- a/thorin/fe/scopes.cpp +++ b/thorin/fe/scopes.cpp @@ -2,7 +2,7 @@ #include "thorin/world.h" -namespace thorin::fe { +namespace thorin { void Scopes::pop() { assert(!scopes_.empty()); @@ -36,4 +36,4 @@ void Scopes::bind(Scope* scope, Dbg dbg, const Def* def, bool rebind) { } } -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/scopes.h b/thorin/fe/scopes.h index a745a065fd..ceef844b9f 100644 --- a/thorin/fe/scopes.h +++ b/thorin/fe/scopes.h @@ -7,9 +7,6 @@ namespace thorin { class Def; - -namespace fe { - class Ptrn; class Scopes { @@ -31,5 +28,4 @@ class Scopes { std::deque scopes_; }; -} // namespace fe } // namespace thorin diff --git a/thorin/fe/tok.cpp b/thorin/fe/tok.cpp index 57d656d686..501165a34c 100644 --- a/thorin/fe/tok.cpp +++ b/thorin/fe/tok.cpp @@ -1,11 +1,11 @@ #include "thorin/fe/tok.h" +#include + #include "thorin/lam.h" #include "thorin/tuple.h" -#include "thorin/util/assert.h" - -namespace thorin::fe { +namespace thorin { std::string_view Tok::tag2str(Tok::Tag tag) { switch (tag) { @@ -14,9 +14,9 @@ std::string_view Tok::tag2str(Tok::Tag tag) { THORIN_KEY(CODE) THORIN_TOK(CODE) #undef CODE - case Tag::Nil: unreachable(); + case Tag::Nil: fe::unreachable(); } - unreachable(); + fe::unreachable(); } /// @name std::ostream operator @@ -28,13 +28,13 @@ std::ostream& operator<<(std::ostream& os, Tok tok) { ///@} // clang-format off -fe::Tok::Prec Tok::prec(const Def* def) { - if (def->isa()) return fe::Tok::Prec::Arrow; - if (def->isa()) return fe::Tok::Prec::App; - if (def->isa()) return fe::Tok::Prec::Extract; - if (def->isa()) return fe::Tok::Prec::Lit; - return fe::Tok::Prec::Bot; +Tok::Prec Tok::prec(const Def* def) { + if (def->isa()) return Tok::Prec::Arrow; + if (def->isa()) return Tok::Prec::App; + if (def->isa()) return Tok::Prec::Extract; + if (def->isa()) return Tok::Prec::Lit; + return Tok::Prec::Bot; } // clang-format on -} // namespace thorin::fe +} // namespace thorin diff --git a/thorin/fe/tok.h b/thorin/fe/tok.h index 732000f477..4c46253833 100644 --- a/thorin/fe/tok.h +++ b/thorin/fe/tok.h @@ -1,6 +1,7 @@ #pragma once -#include "thorin/util/assert.h" +#include + #include "thorin/util/loc.h" #include "thorin/util/sym.h" #include "thorin/util/types.h" @@ -10,8 +11,6 @@ namespace thorin { class Def; class Lit; -namespace fe { - // clang-format off #define THORIN_KEY(m) \ m(K_module, ".module") \ @@ -118,7 +117,7 @@ class Tok { switch (p) { #define CODE(l, p, r) \ case Prec::p: return {Prec::l, Prec::r}; - default: unreachable(); + default: fe::unreachable(); THORIN_PREC(CODE) #undef CODE } @@ -195,5 +194,4 @@ class Tok { }; }; -} // namespace fe } // namespace thorin diff --git a/thorin/util/assert.h b/thorin/util/assert.h deleted file mode 100644 index 75ea209f96..0000000000 --- a/thorin/util/assert.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include - -namespace thorin { - -/// @name Debug Helpers -///@{ -// see https://stackoverflow.com/a/65258501 -#ifdef __GNUC__ // GCC 4.8+, Clang, Intel and other compilers compatible with GCC (-std=c++0x or above) -[[noreturn]] inline __attribute__((always_inline)) void unreachable() { - assert(false); - __builtin_unreachable(); -} -#elif defined(_MSC_VER) // MSVC -[[noreturn]] __forceinline void unreachable() { - assert(false); - __assume(false); -} -#else // ??? -inline void unreachable() { assert(false); } -#endif - -#if (defined(__clang__) || defined(__GNUC__)) && (defined(__x86_64__) || defined(__i386__)) -inline void breakpoint() { asm("int3"); } -#else -inline void breakpoint() { - volatile int* p = nullptr; - *p = 42; -} -#endif -///@} - -} // namespace thorin - -#ifndef NDEBUG -# define assert_unused(x) assert(x) -#else -# define assert_unused(x) ((void)(0 && (x))) -#endif diff --git a/thorin/util/bitset.cpp b/thorin/util/bitset.cpp index fdd818ad35..0bd6aafe84 100644 --- a/thorin/util/bitset.cpp +++ b/thorin/util/bitset.cpp @@ -2,14 +2,14 @@ #include -#include "thorin/util/assert.h" +#include namespace thorin { namespace { inline uint64_t begin_mask(uint64_t i) { return -1_u64 << (i % 64_u64); } inline uint64_t end_mask(uint64_t i) { return ~begin_mask(i); } -} +} // namespace void BitSet::dealloc() const { if (num_words_ != 1) delete[] words_; @@ -24,9 +24,8 @@ size_t BitSet::count() const { bool BitSet::operator==(const BitSet& other) const { auto n = std::min(this->num_words(), other.num_words()); - for (size_t i = 0; i != n; ++i) { + for (size_t i = 0; i != n; ++i) if (this->words()[i] != other.words()[i]) return false; - } const uint64_t* w; size_t m; @@ -38,9 +37,8 @@ bool BitSet::operator==(const BitSet& other) const { m = other.num_words(); } - for (size_t i = n; i != m; ++i) { + for (size_t i = n; i != m; ++i) if (w[i] != 0) return false; - } return true; } @@ -93,8 +91,8 @@ void BitSet::ensure_capacity(size_t i) const { size_t num_new_words = (i + 64_s) / 64_s; if (num_new_words > num_words_) { num_new_words = std::bit_ceil(num_new_words); - assert(num_new_words >= num_words_ * 2_s && - "num_new_words must be a power of two at least twice of num_words_"); + assert(num_new_words >= num_words_ * 2_s + && "num_new_words must be a power of two at least twice of num_words_"); uint64_t* new_words = new uint64_t[num_new_words]; // copy over and fill rest with zero diff --git a/thorin/util/log.cpp b/thorin/util/log.cpp index 3744d77979..01607b010b 100644 --- a/thorin/util/log.cpp +++ b/thorin/util/log.cpp @@ -10,7 +10,7 @@ std::string_view Log::level2acro(Level level) { case Level::Info: return "I"; case Level::Warn: return "W"; case Level::Error: return "E"; - default: unreachable(); + default: fe::unreachable(); } } @@ -21,7 +21,7 @@ rang::fg Log::level2color(Level level) { case Level::Info: return rang::fg::green; case Level::Warn: return rang::fg::magenta; case Level::Error: return rang::fg::red; - default: unreachable(); + default: fe::unreachable(); } } // clang-format on diff --git a/thorin/util/log.h b/thorin/util/log.h index b73dee5f2c..2a669f25ba 100644 --- a/thorin/util/log.h +++ b/thorin/util/log.h @@ -45,8 +45,7 @@ class Log { ///@{ /// Output @p fmt to Log::ostream; does nothing if Log::ostream is `nullptr`. /// @see @ref fmt "Formatted Output", @ref log "Logging Macros" - template - void log(Level level, Loc loc, const char* fmt, Args&&... args) const { + template void log(Level level, Loc loc, const char* fmt, Args&&... args) const { if (ostream_ && level <= max_level_) { std::ostringstream oss; print(ostream(), "{}{}:{}{}:{} ", level2color(level), level2acro(level), rang::fg::gray, loc, @@ -54,12 +53,11 @@ class Log { print(ostream(), fmt, std::forward(args)...) << std::endl; #ifdef THORIN_ENABLE_CHECKS if ((level == Level::Error && flags().break_on_error) || (level == Level::Warn && flags().break_on_warn)) - breakpoint(); + fe::breakpoint(); #endif } } - template - void log(Level level, const char* file, uint16_t line, const char* fmt, Args&&... args) { + template void log(Level level, const char* file, uint16_t line, const char* fmt, Args&&... args) { auto path = fs::path(file); log(level, Loc(&path, line), fmt, std::forward(args)...); } diff --git a/thorin/util/print.cpp b/thorin/util/print.cpp index fba8fbdc76..fac12066d0 100644 --- a/thorin/util/print.cpp +++ b/thorin/util/print.cpp @@ -11,12 +11,12 @@ std::ostream& print(std::ostream& os, const char* s) { if (detail::match2nd(os, next, s, '{')) continue; while (*s && *s != '}') s++; assert(*s != '}' && "invalid format string for 'streamf': missing argument(s)"); - unreachable(); + fe::unreachable(); break; case '}': if (detail::match2nd(os, next, s, '}')) continue; assert(false && "unmatched/unescaped closing brace '}' in format string"); - unreachable(); + fe::unreachable(); default: os << *s++; } } diff --git a/thorin/util/print.h b/thorin/util/print.h index f0b14a0c02..69efafdeba 100644 --- a/thorin/util/print.h +++ b/thorin/util/print.h @@ -7,7 +7,7 @@ #include #include -#include "thorin/util/assert.h" +#include namespace thorin { namespace detail { @@ -17,12 +17,11 @@ concept Printable = requires(std::ostream& os, T a) { os << a; }; template concept Elemable = requires(T elem) { - elem.range; - elem.f; - }; + elem.range; + elem.f; +}; -template -std::ostream& range(std::ostream& os, const R& r, F f, const char* sep = ", ") { +template std::ostream& range(std::ostream& os, const R& r, F f, const char* sep = ", ") { const char* cur_sep = ""; for (const auto& elem : r) { for (auto i = cur_sep; *i != '\0'; ++i) os << *i; @@ -80,8 +79,7 @@ bool match2nd(std::ostream& os, const char* next, const char*& s, const char c); /// @see Tab /// Use with print to output complicated `std::ranges::range`s. -template -struct Elem { +template struct Elem { Elem(const R& range, const F& f) : range(range) , f(f) {} @@ -92,8 +90,7 @@ struct Elem { std::ostream& print(std::ostream& os, const char* s); ///< Base case. -template -std::ostream& print(std::ostream& os, const char* s, T&& t, Args&&... args) { +template std::ostream& print(std::ostream& os, const char* s, T&& t, Args&&... args) { while (*s != '\0') { auto next = s + 1; @@ -129,26 +126,24 @@ std::ostream& print(std::ostream& os, const char* s, T&& t, Args&&... args) { case '}': if (detail::match2nd(os, next, s, '}')) continue; assert(false && "unmatched/unescaped closing brace '}' in format string"); - unreachable(); + fe::unreachable(); default: os << *s++; } } assert(false && "invalid format string for 's'"); - unreachable(); + fe::unreachable(); } /// Wraps thorin::print to output a formatted `std:string`. -template -std::string fmt(const char* s, Args&&... args) { +template std::string fmt(const char* s, Args&&... args) { std::ostringstream os; print(os, s, std::forward(args)...); return os.str(); } /// Wraps thorin::print to throw `T` with a formatted message. -template -[[noreturn]] void error(const char* fmt, Args&&... args) { +template [[noreturn]] void error(const char* fmt, Args&&... args) { std::ostringstream oss; print(oss << "error: ", fmt, std::forward(args)...); throw T(oss.str()); @@ -163,7 +158,7 @@ template if (!(condition)) { \ thorin::errf("{}:{}: assertion: ", __FILE__, __LINE__); \ thorin::errln(__VA_ARGS__); \ - thorin::breakpoint(); \ + fe::breakpoint(); \ } \ } while (false) #endif @@ -197,19 +192,16 @@ class Tab { ///@{ /// Wraps thorin::print to prefix it with indentation. /// @see @ref fmt "Formatted Output" - template - std::ostream& print(std::ostream& os, const char* s, Args&&... args) { + template std::ostream& print(std::ostream& os, const char* s, Args&&... args) { for (size_t i = 0; i < indent_; ++i) os << tab_; return thorin::print(os, s, std::forward(args)...); } /// Same as Tab::print but **prepends** a `std::endl` to @p os. - template - std::ostream& lnprint(std::ostream& os, const char* s, Args&&... args) { + template std::ostream& lnprint(std::ostream& os, const char* s, Args&&... args) { return print(os << std::endl, s, std::forward(args)...); } /// Same as Tab::print but **appends** a `std::endl` to @p os. - template - std::ostream& println(std::ostream& os, const char* s, Args&&... args) { + template std::ostream& println(std::ostream& os, const char* s, Args&&... args) { return print(os, s, std::forward(args)...) << std::endl; } ///@} diff --git a/thorin/util/utf8.cpp b/thorin/util/utf8.cpp index 8f1cbc7265..3f4f6fbf1e 100644 --- a/thorin/util/utf8.cpp +++ b/thorin/util/utf8.cpp @@ -1,6 +1,6 @@ #include "thorin/util/utf8.h" -#include "thorin/util/assert.h" +#include namespace thorin::utf8 { diff --git a/thorin/util/util.h b/thorin/util/util.h index 89ab9067bc..65a4e39b7a 100644 --- a/thorin/util/util.h +++ b/thorin/util/util.h @@ -9,8 +9,8 @@ #include #include #include +#include -#include "thorin/util/assert.h" #include "thorin/util/hash.h" namespace thorin { @@ -18,14 +18,12 @@ namespace thorin { /// @name Utility Functions ///@{ -template -inline T& lazy_init(const This* self, std::unique_ptr& ptr) { +template inline T& lazy_init(const This* self, std::unique_ptr& ptr) { return *(ptr ? ptr : ptr = std::make_unique(*self)); } /// A bitcast from @p src of type @p S to @p D. -template -inline D bitcast(const S& src) { +template inline D bitcast(const S& src) { D dst; auto s = reinterpret_cast(&src); auto d = reinterpret_cast(&dst); @@ -39,8 +37,7 @@ inline D bitcast(const S& src) { return dst; } -template -bool get_sign(T val) { +template bool get_sign(T val) { static_assert(std::is_integral(), "get_sign only supported for signed and unsigned integer types"); if constexpr (std::is_signed()) return val < 0; @@ -58,8 +55,7 @@ inline u64 pad(u64 offset, u64 align) { /// @name Algorithms ///@{ -template -I binary_find(I begin, I end, T val, Cmp cmp) { +template I binary_find(I begin, I end, T val, Cmp cmp) { auto i = std::lower_bound(begin, end, val, cmp); return (i != end && !(cmp(val, *i))) ? i : end; } @@ -79,15 +75,13 @@ inline void find_and_replace(std::string& str, std::string_view what, std::strin /// @name Helpers for Containers ///@{ -template -auto pop(S& s) -> decltype(s.top(), typename S::value_type()) { +template auto pop(S& s) -> decltype(s.top(), typename S::value_type()) { auto val = s.top(); s.pop(); return val; } -template -auto pop(Q& q) -> decltype(q.front(), typename Q::value_type()) { +template auto pop(Q& q) -> decltype(q.front(), typename Q::value_type()) { auto val = q.front(); q.pop(); return val; @@ -96,8 +90,7 @@ auto pop(Q& q) -> decltype(q.front(), typename Q::value_type()) { /// Yields pointer to element (or the element itself if it is already a pointer), if found and `nullptr` otherwise. /// @warning If the element is **not** already a pointer, this lookup will simply take the address of this element. /// This means that, e.g., a rehash of an `absl::flat_hash_map` will invalidate this pointer. -template -auto lookup(const C& container, const K& key) { +template auto lookup(const C& container, const K& key) { auto i = container.find(key); if constexpr (std::is_pointer_v) return i != container.end() ? i->second : nullptr; @@ -106,16 +99,14 @@ auto lookup(const C& container, const K& key) { } /// Invokes `emplace` on @p container, asserts that insertion actually happened, and returns the iterator. -template -auto assert_emplace(C& container, Args&&... args) { +template auto assert_emplace(C& container, Args&&... args) { auto [i, ins] = container.emplace(std::forward(args)...); assert_unused(ins); return i; } ///@} -template -class unique_stack { +template class unique_stack { public: using T = typename std::remove_reference_t::value_type; @@ -140,8 +131,7 @@ class unique_stack { std::stack stack_; }; -template -class unique_queue { +template class unique_queue { public: using T = typename std::remove_reference_t::value_type; @@ -171,18 +161,15 @@ class unique_queue { std::queue queue_; }; -template -struct GIDHash { +template struct GIDHash { size_t operator()(T p) const { return murmur3(p->gid()); }; }; -template -struct GIDEq { +template struct GIDEq { bool operator()(T a, T b) const { return a->gid() == b->gid(); } }; -template -struct GIDLt { +template struct GIDLt { bool operator()(T a, T b) const { return a->gid() < b->gid(); } }; diff --git a/thorin/world.h b/thorin/world.h index b4102fae58..762d5b5892 100644 --- a/thorin/world.h +++ b/thorin/world.h @@ -456,7 +456,7 @@ class World { assert(!def->isa_mut()); #ifdef THORIN_ENABLE_CHECKS if (flags().trace_gids) outln("{}: {} - {}", def->node_name(), def->gid(), def->flags()); - if (flags().reeval_breakpoints && breakpoints().contains(def->gid())) thorin::breakpoint(); + if (flags().reeval_breakpoints && breakpoints().contains(def->gid())) fe::breakpoint(); #endif if (is_frozen()) { --state_.pod.curr_gid; @@ -471,7 +471,7 @@ class World { return static_cast(*i); } #ifdef THORIN_ENABLE_CHECKS - if (!flags().reeval_breakpoints && breakpoints().contains(def->gid())) thorin::breakpoint(); + if (!flags().reeval_breakpoints && breakpoints().contains(def->gid())) fe::breakpoint(); #endif def->finalize(); return def; @@ -482,7 +482,7 @@ class World { if (auto loc = emit_loc()) def->set(loc); #ifdef THORIN_ENABLE_CHECKS if (flags().trace_gids) outln("{}: {} - {}", def->node_name(), def->gid(), def->flags()); - if (breakpoints().contains(def->gid())) thorin::breakpoint(); + if (breakpoints().contains(def->gid())) fe::breakpoint(); #endif assert_emplace(move_.defs, def); return def; From 344e41860badb6e94350bd877cdc117a3abf1bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 04:12:32 +0200 Subject: [PATCH 13/53] submodules --- .gitmodules | 20 ++++++++++---------- external/fe | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitmodules b/.gitmodules index b8f5a37362..db674a9835 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,21 +1,21 @@ [submodule "abseil-cpp"] - path = external/modules/abseil-cpp + path = external/abseil-cpp url = ../../abseil/abseil-cpp [submodule "doxygen-awesome-css"] - path = external/modules/doxygen-awesome-css + path = external/doxygen-awesome-css url = ../../jothepro/doxygen-awesome-css.git +[submodule "external/fe"] + path = external/fe + url = ../../leissa/fe.git [submodule "googletest"] - path = external/modules/googletest + path = external/googletest url = ../../google/googletest.git [submodule "half"] - path = external/modules/half + path = external/half url = ../../AnyDSL/half.git [submodule "lyra"] - path = external/modules/lyra + path = external/lyra url = ../../bfgroup/lyra.git -[submodule "modules/rang"] - path = external/modules/rang +[submodule "rang"] + path = external/rang url = ../../agauniyal/rang.git -[submodule "external/fe"] - path = external/fe - url = ../../leissa/fe.git diff --git a/external/fe b/external/fe index 1555369eb4..c837cc95e4 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 1555369eb4d997a6136c6a932431dad4340c6f3c +Subproject commit c837cc95e48b2aee9ac5265256eb383036e6fa97 From 1c35e0c4bcf7b5b9d5158f593bdc463d5d24718e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 11:48:07 +0200 Subject: [PATCH 14/53] moving submodules around --- .gitmodules | 2 +- external/{modules => }/abseil-cpp | 0 external/{modules => }/doxygen-awesome-css | 0 external/{modules => }/googletest | 0 external/{modules => }/half | 0 external/{modules => }/lyra | 0 external/{modules => }/rang | 0 7 files changed, 1 insertion(+), 1 deletion(-) rename external/{modules => }/abseil-cpp (100%) rename external/{modules => }/doxygen-awesome-css (100%) rename external/{modules => }/googletest (100%) rename external/{modules => }/half (100%) rename external/{modules => }/lyra (100%) rename external/{modules => }/rang (100%) diff --git a/.gitmodules b/.gitmodules index db674a9835..c3a17b5e11 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,7 +4,7 @@ [submodule "doxygen-awesome-css"] path = external/doxygen-awesome-css url = ../../jothepro/doxygen-awesome-css.git -[submodule "external/fe"] +[submodule "fe"] path = external/fe url = ../../leissa/fe.git [submodule "googletest"] diff --git a/external/modules/abseil-cpp b/external/abseil-cpp similarity index 100% rename from external/modules/abseil-cpp rename to external/abseil-cpp diff --git a/external/modules/doxygen-awesome-css b/external/doxygen-awesome-css similarity index 100% rename from external/modules/doxygen-awesome-css rename to external/doxygen-awesome-css diff --git a/external/modules/googletest b/external/googletest similarity index 100% rename from external/modules/googletest rename to external/googletest diff --git a/external/modules/half b/external/half similarity index 100% rename from external/modules/half rename to external/half diff --git a/external/modules/lyra b/external/lyra similarity index 100% rename from external/modules/lyra rename to external/lyra diff --git a/external/modules/rang b/external/rang similarity index 100% rename from external/modules/rang rename to external/rang From 25d0d7c6652a65d8aeabe2edfec2bce606175d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 12:05:23 +0200 Subject: [PATCH 15/53] thorin/util/cast.h -> fe/cast.h --- external/fe | 2 +- thorin/CMakeLists.txt | 1 - thorin/analyses/looptree.h | 5 +++-- thorin/def.h | 4 ++-- thorin/util/cast.h | 45 -------------------------------------- 5 files changed, 6 insertions(+), 51 deletions(-) delete mode 100644 thorin/util/cast.h diff --git a/external/fe b/external/fe index c837cc95e4..d0a53f3737 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit c837cc95e48b2aee9ac5265256eb383036e6fa97 +Subproject commit d0a53f3737e468d77412702ffcadd637e7ea0fd8 diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 5b549fcbb4..13d76a1dbd 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -72,7 +72,6 @@ add_library(libthorin util/array.h util/bitset.cpp util/bitset.h - util/cast.h util/dl.cpp util/dl.h util/hash.cpp diff --git a/thorin/analyses/looptree.h b/thorin/analyses/looptree.h index e9dc027f3e..dfee073955 100644 --- a/thorin/analyses/looptree.h +++ b/thorin/analyses/looptree.h @@ -2,9 +2,10 @@ #include +#include + #include "thorin/analyses/cfg.h" #include "thorin/util/array.h" -#include "thorin/util/cast.h" namespace thorin { @@ -24,7 +25,7 @@ class LoopTree { /// The header CFNode%s are the set of CFNode%s not dominated by any other CFNode within the loop. /// The root node is a LoopTree::Head without any CFNode%s but further children and `depth_ -1`. /// Thus, the forest is pooled into a tree. - class Base : public RuntimeCast { + class Base : public fe::RuntimeCast { public: Base(Head* parent, int depth, const std::vector&); virtual ~Base() = default; diff --git a/thorin/def.h b/thorin/def.h index 09c1cf99e6..50cfce5de8 100644 --- a/thorin/def.h +++ b/thorin/def.h @@ -4,11 +4,11 @@ #include #include +#include #include "thorin/config.h" #include "thorin/util/array.h" -#include "thorin/util/cast.h" #include "thorin/util/hash.h" #include "thorin/util/loc.h" #include "thorin/util/print.h" @@ -202,7 +202,7 @@ private: \ /// ``` /// @attention This means that any subclass of Def **must not** introduce additional members. /// @see @ref mut -class Def : public RuntimeCast { +class Def : public fe::RuntimeCast { private: Def& operator=(const Def&) = delete; Def(const Def&) = delete; diff --git a/thorin/util/cast.h b/thorin/util/cast.h deleted file mode 100644 index aa46de30a3..0000000000 --- a/thorin/util/cast.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include - -namespace thorin { - -namespace detail { -template -concept Nodeable = requires(T n) { - T::Node; - n.node(); - }; -} // namespace detail - -/// Inherit from this class using [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern), -/// for some nice `dynamic_cast`-style wrappers. -template -class RuntimeCast { -public: - // clang-format off - /// `static_cast` with debug check. - template T* as() { assert(isa()); return static_cast(this); } - - /// `dynamic_cast`. - /// If @p T isa thorin::detail::Nodeable, it will use `node()`, otherwise a `dynamic_cast`. - template - T* isa() { - if constexpr (detail::Nodeable) { - return static_cast(this)->node() == T::Node ? static_cast(this) : nullptr; - } else { - return dynamic_cast(static_cast(this)); - } - } - - /// Yields `B*` if it is *either* @p T or @p U and `nullptr* otherwise. - template B* isa() { return (isa() || isa()) ? static_cast(this) : nullptr; } - - template const T* as() const { return const_cast(this)->template as(); } ///< `const` version. - template const T* isa() const { return const_cast(this)->template isa(); } ///< `const` version. - template const B* isa() const { return const_cast(this)->template isa(); } ///< `const` version. - // clang-format on -}; - -} // namespace thorin From 14d49a9c285af1c4516a7e7b087b0e29b464f058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 12:46:42 +0200 Subject: [PATCH 16/53] doxygen fixes --- docs/dev.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/dev.md b/docs/dev.md index 2bc10c1c20..9a1e5435fc 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -75,7 +75,7 @@ Methods beginning with #### Upcast -[Def::isa](@ref thorin::RuntimeCast::isa)/[Def::as](@ref thorin::RuntimeCast::as) allows for an *upcast* that matches both *mutables* and *immutables*: +[Def::isa](@ref thorin::Def::isa)/[Def::as](@ref thorin::Def::as) allows for an *upcast* that matches both *mutables* and *immutables*: ```cpp void foo(Ref def) { if (auto sigma = def->isa()) { @@ -129,7 +129,7 @@ void foo(Ref def) { auto lam = def->as(); } ``` -Checking via [Def::isa](@ref thorin::RuntimeCast::isa)/[Def::as](@ref thorin::RuntimeCast::as) a `Def*` has the same effect as using [Def::isa_mut](@ref thorin::Def::isa_mut)/[Def::isa_mut](@ref thorin::Def::as_mut) since the scrutinee must be already a *mutable* due to the lack of the `const` qualifier: +Checking via [Def::isa](@ref thorin::Def::isa)/[Def::as](@ref thorin::Def::as) a `Def*` has the same effect as using [Def::isa_mut](@ref thorin::Def::isa_mut)/[Def::isa_mut](@ref thorin::Def::as_mut) since the scrutinee must be already a *mutable* due to the lack of the `const` qualifier: ```cpp void foo(Def* def) { // note the lack of "const" here if (auto sigma = def->isa()) { From 7d2ff92821f9fb18cde16405a88ca32b0241348f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 13:29:15 +0200 Subject: [PATCH 17/53] use fe/loc.h and fe/sym.h --- dialects/regex/normalizers_regex.cpp | 1 - docs/dev.md | 4 +- thorin/CMakeLists.txt | 5 +- thorin/be/h/bootstrap.h | 2 +- thorin/def.h | 2 +- thorin/driver.h | 4 +- thorin/fe/lexer.h | 2 +- thorin/fe/scopes.h | 4 +- thorin/fe/tok.h | 3 +- thorin/util/{loc.cpp => dbg.cpp} | 9 +- thorin/util/dbg.h | 48 +++++++++++ thorin/util/loc.h | 86 ------------------- thorin/util/log.h | 2 +- thorin/util/sym.h | 118 --------------------------- thorin/util/utf8.h | 2 +- thorin/world.h | 2 +- 16 files changed, 66 insertions(+), 228 deletions(-) rename thorin/util/{loc.cpp => dbg.cpp} (78%) create mode 100644 thorin/util/dbg.h delete mode 100644 thorin/util/loc.h delete mode 100644 thorin/util/sym.h diff --git a/dialects/regex/normalizers_regex.cpp b/dialects/regex/normalizers_regex.cpp index 1d1550f42e..c8aad0f46d 100644 --- a/dialects/regex/normalizers_regex.cpp +++ b/dialects/regex/normalizers_regex.cpp @@ -11,7 +11,6 @@ #include "thorin/tuple.h" #include "thorin/world.h" -#include "thorin/util/loc.h" #include "thorin/util/log.h" #include "dialects/regex/autogen.h" diff --git a/docs/dev.md b/docs/dev.md index 9a1e5435fc..388460d601 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -75,7 +75,7 @@ Methods beginning with #### Upcast -[Def::isa](@ref thorin::Def::isa)/[Def::as](@ref thorin::Def::as) allows for an *upcast* that matches both *mutables* and *immutables*: +`Def::isa`/`Def::as` allows for an *upcast* that matches both *mutables* and *immutables*: ```cpp void foo(Ref def) { if (auto sigma = def->isa()) { @@ -129,7 +129,7 @@ void foo(Ref def) { auto lam = def->as(); } ``` -Checking via [Def::isa](@ref thorin::Def::isa)/[Def::as](@ref thorin::Def::as) a `Def*` has the same effect as using [Def::isa_mut](@ref thorin::Def::isa_mut)/[Def::isa_mut](@ref thorin::Def::as_mut) since the scrutinee must be already a *mutable* due to the lack of the `const` qualifier: +Checking via `Def::isa`/`Def::as` a `Def*` has the same effect as using [Def::isa_mut](@ref thorin::Def::isa_mut)/[Def::isa_mut](@ref thorin::Def::as_mut) since the scrutinee must be already a *mutable* due to the lack of the `const` qualifier: ```cpp void foo(Def* def) { // note the lack of "const" here if (auto sigma = def->isa()) { diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 13d76a1dbd..05dfce3f63 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -72,19 +72,18 @@ add_library(libthorin util/array.h util/bitset.cpp util/bitset.h + util/dbg.cpp + util/dbg.h util/dl.cpp util/dl.h util/hash.cpp util/hash.h util/indexmap.h util/indexset.h - util/loc.cpp - util/loc.h util/log.cpp util/log.h util/print.cpp util/print.h - util/sym.h util/sys.cpp util/sys.h util/types.h diff --git a/thorin/be/h/bootstrap.h b/thorin/be/h/bootstrap.h index 8065fa2920..a0820affb6 100644 --- a/thorin/be/h/bootstrap.h +++ b/thorin/be/h/bootstrap.h @@ -2,7 +2,7 @@ #include -#include "thorin/util/sym.h" +#include "thorin/util/dbg.h" namespace thorin { diff --git a/thorin/def.h b/thorin/def.h index 50cfce5de8..b4c6f551d9 100644 --- a/thorin/def.h +++ b/thorin/def.h @@ -10,7 +10,7 @@ #include "thorin/util/array.h" #include "thorin/util/hash.h" -#include "thorin/util/loc.h" +#include "thorin/util/dbg.h" #include "thorin/util/print.h" #include "thorin/util/util.h" diff --git a/thorin/driver.h b/thorin/driver.h index fbc5f0a7c3..2deeeab03e 100644 --- a/thorin/driver.h +++ b/thorin/driver.h @@ -14,7 +14,7 @@ namespace thorin { /// Some "global" variables needed all over the place. /// Well, there are not really global - that's the point of this class. -class Driver : public SymPool { +class Driver : public fe::SymPool { public: Driver(); @@ -86,7 +86,7 @@ class Driver : public SymPool { Passes passes_; Normalizers normalizers_; std::deque> imports_; - SymMap> plugin2annexes_; + fe::SymMap> plugin2annexes_; }; } // namespace thorin diff --git a/thorin/fe/lexer.h b/thorin/fe/lexer.h index 5171a5c28b..6de86fd2fd 100644 --- a/thorin/fe/lexer.h +++ b/thorin/fe/lexer.h @@ -56,7 +56,7 @@ class Lexer : public utf8::Lexer<3> { World& world_; std::ostream* md_; bool out_ = true; - SymMap keywords_; + fe::SymMap keywords_; std::optional cache_ = std::nullopt; }; diff --git a/thorin/fe/scopes.h b/thorin/fe/scopes.h index ceef844b9f..43c7d70be1 100644 --- a/thorin/fe/scopes.h +++ b/thorin/fe/scopes.h @@ -2,7 +2,7 @@ #include -#include "thorin/util/loc.h" +#include "thorin/util/dbg.h" namespace thorin { @@ -11,7 +11,7 @@ class Ptrn; class Scopes { public: - using Scope = SymMap>; + using Scope = fe::SymMap>; Scopes() { push(); /* root scope */ } diff --git a/thorin/fe/tok.h b/thorin/fe/tok.h index 4c46253833..6b7a693fd3 100644 --- a/thorin/fe/tok.h +++ b/thorin/fe/tok.h @@ -2,8 +2,7 @@ #include -#include "thorin/util/loc.h" -#include "thorin/util/sym.h" +#include "thorin/util/dbg.h" #include "thorin/util/types.h" namespace thorin { diff --git a/thorin/util/loc.cpp b/thorin/util/dbg.cpp similarity index 78% rename from thorin/util/loc.cpp rename to thorin/util/dbg.cpp index 6c33e09e0e..f2d89c0ef1 100644 --- a/thorin/util/loc.cpp +++ b/thorin/util/dbg.cpp @@ -1,6 +1,6 @@ -#include "thorin/util/loc.h" +#include "thorin/util/dbg.h" -namespace thorin { +namespace fe { std::ostream& operator<<(std::ostream& os, const Pos pos) { if (pos.row) { @@ -24,7 +24,4 @@ std::ostream& operator<<(std::ostream& os, const Loc loc) { return os << ""; } -void Pos::dump() { std::cout << *this << std::endl; } -void Loc::dump() { std::cout << *this << std::endl; } - -} // namespace thorin +} // namespace fe diff --git a/thorin/util/dbg.h b/thorin/util/dbg.h new file mode 100644 index 0000000000..47db52cfc8 --- /dev/null +++ b/thorin/util/dbg.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include +#include + +#include +#include + +#include "thorin/util/print.h" + +namespace fe { + +/// @name std::ostream operator +///@{ +std::ostream& operator<<(std::ostream&, const Pos); +std::ostream& operator<<(std::ostream&, const Loc); +///@} + +} + +namespace thorin { + +namespace fs = std::filesystem; + +using fe::Loc; +using fe::Pos; +using fe::Sym; + +/// @name Formatted Output +///@{ +/// Prefixes error message with `: error: `. +template +[[noreturn]] void error(Loc loc, const char* fmt, Args&&... args) { + std::ostringstream o; + print(o, "{}: error: ", loc); + print(o, fmt, std::forward(args)...); + throw T(o.str()); +} +///@} + +struct Dbg { + Loc loc; + Sym sym; +}; + +} // namespace thorin diff --git a/thorin/util/loc.h b/thorin/util/loc.h deleted file mode 100644 index 848a11995f..0000000000 --- a/thorin/util/loc.h +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "thorin/util/print.h" -#include "thorin/util/sym.h" - -namespace thorin { - -namespace fs = std::filesystem; - -struct Pos { - Pos() = default; - Pos(uint16_t row) - : row(row) {} - Pos(uint16_t row, uint16_t col) - : row(row) - , col(col) {} - - explicit operator bool() const { return row; } - bool operator==(Pos other) const { return row == other.row && col == other.col; } - void dump(); - - uint16_t row = 0; - uint16_t col = 0; -}; - -/// Loc%ation in a File. -/// @warning Loc::path is only a pointer and it is your job to guarantee -/// that the underlying `std::filesystem::path` outlives this Loc%ation. -/// In Thorin itself, the Driver takes care of this. -struct Loc { - Loc() = default; - Loc(const fs::path* path, Pos begin, Pos finis) - : path(path) - , begin(begin) - , finis(finis) {} - Loc(const fs::path* file, Pos pos) - : Loc(file, pos, pos) {} - Loc(Pos begin, Pos finis) - : Loc(nullptr, begin, finis) {} - Loc(Pos pos) - : Loc(nullptr, pos, pos) {} - - Loc anew_begin() const { return {path, begin, begin}; } - Loc anew_finis() const { return {path, finis, finis}; } - Loc operator+(Loc loc) const { return {path, begin, loc.finis}; } - explicit operator bool() const { return (bool)begin; } - /// @note Loc::path is only checked via pointer equality. - bool operator==(Loc other) const { return begin == other.begin && finis == other.finis && path == other.path; } - void dump(); - - const fs::path* path = nullptr; - Pos begin = {}; - Pos finis = {}; - ///< It's called `finis` because it refers to the **last** character within this Loc%ation. - /// In the STL the word `end` refers to the position of something that is one element **past** the end. -}; - -/// @name Formatted Output -///@{ -/// Prefixes error message with `: error: `. -template -[[noreturn]] void error(Loc loc, const char* fmt, Args&&... args) { - std::ostringstream o; - print(o, "{}: error: ", loc); - print(o, fmt, std::forward(args)...); - throw T(o.str()); -} -///@} - -/// @name std::ostream operator -///@{ -std::ostream& operator<<(std::ostream&, const Pos); -std::ostream& operator<<(std::ostream&, const Loc); -///@} - -struct Dbg { - Loc loc; - Sym sym; -}; - -} // namespace thorin diff --git a/thorin/util/log.h b/thorin/util/log.h index 2a669f25ba..e9e51f6971 100644 --- a/thorin/util/log.h +++ b/thorin/util/log.h @@ -5,7 +5,7 @@ #include "thorin/flags.h" -#include "thorin/util/loc.h" +#include "thorin/util/dbg.h" namespace thorin { diff --git a/thorin/util/sym.h b/thorin/util/sym.h deleted file mode 100644 index 8bdc2ed50d..0000000000 --- a/thorin/util/sym.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -namespace thorin { - -/// A Sym%bol just wraps a `const std::string*`, so pass Sym itself around as value. -/// With the exception of the empty string, you should only create Sym%bols via SymPool::sym. -/// This in turn will toss all Sym%bols into a big hash set. -/// This makes Sym::operator== and Sym::operator!= an O(1) operation. -/// The empty string is internally handled as `nullptr`. -/// Thus, you can create a Sym%bol representing an empty string without having access to the SymPool. -/// @note The empty string, `nullptr`, and `"\0"` are all identified as Sym::Sym(). -class Sym { -private: - Sym(const std::string* ptr) - : ptr_(ptr) { - assert(ptr == nullptr || !ptr->empty()); - } - -public: - Sym() = default; - - /// @name begin/end - ///@{ - /// Useful for range-based for. - /// Will give you `std::string::const_iterator` - yes **const**; you are not supposed to mutate hashed strings. - auto begin() const { return (*this)->cbegin(); } - auto end() const { return (*this)->cend(); } - ///@} - - /// @name Comparisons - ///@{ - auto operator<=>(char c) const { - if ((*this)->size() == 0) return std::strong_ordering::less; - auto cmp = (*this)[0] <=> c; - if ((*this)->size() == 1) return cmp; - return cmp == 0 ? std::strong_ordering::greater : cmp; - } - auto operator==(char c) const { return (*this) <=> c == std::strong_ordering::equal; } - auto operator<=>(Sym other) const { return **this <=> *other; } - bool operator==(Sym other) const { return this->ptr_ == other.ptr_; } - bool operator!=(Sym other) const { return this->ptr_ != other.ptr_; } - ///@} - - /// @name Cast Operators - ///@{ - operator std::string_view() const { return ptr_ ? *ptr_ : std::string_view(); } - operator const std::string&() const { return *this->operator->(); } - explicit operator bool() const { return ptr_; } - ///@} - - /// @name Access Operators - ///@{ - char operator[](size_t i) const { return ((const std::string&)(*this))[i]; } - const std::string& operator*() const { return *this->operator->(); } - const std::string* operator->() const { - static std::string empty; - return ptr_ ? ptr_ : ∅ - } - ///@} - - template - friend H AbslHashValue(H h, Sym sym) { - return H::combine(std::move(h), sym.ptr_); - } - -private: - const std::string* ptr_ = nullptr; - - friend class SymPool; -}; - -/// @name std::ostream operator -///@{ -inline std::ostream& operator<<(std::ostream& o, const Sym sym) { return o << *sym; } -///@} - -/// Hash set where all strings - wrapped in Sym%bol - live in. -/// You can access the SymPool from Driver. -class SymPool { -public: - SymPool() = default; - SymPool(const SymPool&) = delete; - SymPool(SymPool&& other) - : pool_(std::move(other.pool_)) {} - - /// @name sym - ///@{ - Sym sym(std::string_view s) { return s.empty() ? Sym() : &*pool_.emplace(s).first; } - Sym sym(const char* s) { return s == nullptr || *s == '\0' ? Sym() : &*pool_.emplace(s).first; } - Sym sym(std::string s) { return s.empty() ? Sym() : &*pool_.emplace(std::move(s)).first; } - ///@} - - friend void swap(SymPool& p1, SymPool& p2) { - using std::swap; - swap(p1.pool_, p2.pool_); - } - -private: - absl::node_hash_set pool_; -}; - -/// @name Sym -///@{ -/// Set/Map is keyed by pointer - which is hashed in SymPool. -template -using SymMap = absl::flat_hash_map; -using SymSet = absl::flat_hash_set; -using Syms = std::deque; -///@} - -} // namespace thorin diff --git a/thorin/util/utf8.h b/thorin/util/utf8.h index dc08550d75..d2b8a52a09 100644 --- a/thorin/util/utf8.h +++ b/thorin/util/utf8.h @@ -4,7 +4,7 @@ #include #include -#include "thorin/util/loc.h" +#include "thorin/util/dbg.h" #include "thorin/util/types.h" namespace thorin::utf8 { diff --git a/thorin/world.h b/thorin/world.h index 762d5b5892..239efd6e97 100644 --- a/thorin/world.h +++ b/thorin/world.h @@ -17,7 +17,7 @@ #include "thorin/util/hash.h" #include "thorin/util/log.h" -#include "thorin/util/sym.h" +#include "thorin/util/dbg.h" namespace thorin { class Driver; From e8c09607d4143c72cb176fc138367c4e6ea4bc4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 13:47:10 +0200 Subject: [PATCH 18/53] docs fix --- docs/langref.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/langref.md b/docs/langref.md index cbe70e66d7..979fb5c385 100644 --- a/docs/langref.md +++ b/docs/langref.md @@ -162,17 +162,17 @@ The following tables comprise all production rules: ### Declarations {#decl} -| LHS | RHS | Comment | Thorin Class | -|-----|------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|-----------------------------------------------------| -| d | `.let` (p \| A) `=` e `;` | let | - | -| d | `.lam` n (`.`? p)+ (`:` ecodom)? ( `=` d\* e)? `;` | lambda declarations | [Lam](@ref thorin::Lam) | -| d | `.con` n (`.`? p)+ ( `=` d\* e)? `;` | continuation declarations | [Lam](@ref thorin::Lam) | -| d | `.fun` n (`.`? p)+ (`:` eret)? ( `=` d\* e)? `;` | function declarations | [Lam](@ref thorin::Lam) | -| d | `.Pi` n (`:` etype)? (`=` e)? `;` | Pi declaration | [Pi](@ref thorin::Pi) | -| d | `.Sigma` n (`:` etype )? (`,` Larity)? (`=` b[ ])? `;` | sigma declaration | [Sigma](@ref thorin::Sigma) | -| d | `.ax` A `:` etype (`(` sa `,` ... `,` sa `)`)?
(`,` 𝖨normalizer)? (`,` Lcurry)? (`,` Ltrip)? `;` | axiom | [Axiom](@ref thorin::Axiom) | -| n | 𝖨 \| A | identifier or annex name | [Sym](@ref thorin::Sym)/[Annex](@ref thorin::Annex) | -| sa | 𝖨 (`=` 𝖨 `,` ... `,` 𝖨)? | subtag with aliases | | +| LHS | RHS | Comment | Thorin Class | +|-----|------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|---------------------------------------| +| d | `.let` (p \| A) `=` e `;` | let | - | +| d | `.lam` n (`.`? p)+ (`:` ecodom)? ( `=` d\* e)? `;` | lambda declarations | [Lam](@ref thorin::Lam) | +| d | `.con` n (`.`? p)+ ( `=` d\* e)? `;` | continuation declarations | [Lam](@ref thorin::Lam) | +| d | `.fun` n (`.`? p)+ (`:` eret)? ( `=` d\* e)? `;` | function declarations | [Lam](@ref thorin::Lam) | +| d | `.Pi` n (`:` etype)? (`=` e)? `;` | Pi declaration | [Pi](@ref thorin::Pi) | +| d | `.Sigma` n (`:` etype )? (`,` Larity)? (`=` b[ ])? `;` | sigma declaration | [Sigma](@ref thorin::Sigma) | +| d | `.ax` A `:` etype (`(` sa `,` ... `,` sa `)`)?
(`,` 𝖨normalizer)? (`,` Lcurry)? (`,` Ltrip)? `;` | axiom | [Axiom](@ref thorin::Axiom) | +| n | 𝖨 \| A | identifier or annex name | `fe::Sym`/[Annex](@ref thorin::Annex) | +| sa | 𝖨 (`=` 𝖨 `,` ... `,` 𝖨)? | subtag with aliases | | @note An elided type of a `.Pi` or `.Sigma` declaration defaults to `*`. @@ -251,18 +251,18 @@ This is particularly useful, when dealing with memory: #### Literals & Co. -| LHS | RHS | Comment | Thorin Class | -|-----|-----------------------------|--------------------------------------|-----------------------------------------------------| -| e | L (`:` etype)? | literal | [Lit](@ref thorin::Lit) | -| e | Xn | literal of type `.Idx n` | [Lit](@ref thorin::Lit) | -| e | `.ff` | alias for `0_2` | [Lit](@ref thorin::Lit) | -| e | `.tt` | alias for `1_2` | [Lit](@ref thorin::Lit) | -| e | C | character literal of type `.Idx 256` | [Lit](@ref thorin::Lit) | -| e | S | string tuple of type `«n; .Idx 256»` | [Tuple](@ref thorin::Tuple) | -| e | `⊥` (`:` etype)? | bottom | [Bot](@ref thorin::Bot) | -| e | `⊤` (`:` etype)? | top | [Top](@ref thorin::Top) | -| e | n | identifier or annex name | [Sym](@ref thorin::Sym)/[Annex](@ref thorin::Annex) | -| e | `{` d\* e `}` | blocks | - | +| LHS | RHS | Comment | Thorin Class | +|-----|-----------------------------|--------------------------------------|---------------------------------------| +| e | L (`:` etype)? | literal | [Lit](@ref thorin::Lit) | +| e | Xn | literal of type `.Idx n` | [Lit](@ref thorin::Lit) | +| e | `.ff` | alias for `0_2` | [Lit](@ref thorin::Lit) | +| e | `.tt` | alias for `1_2` | [Lit](@ref thorin::Lit) | +| e | C | character literal of type `.Idx 256` | [Lit](@ref thorin::Lit) | +| e | S | string tuple of type `«n; .Idx 256»` | [Tuple](@ref thorin::Tuple) | +| e | `⊥` (`:` etype)? | bottom | [Bot](@ref thorin::Bot) | +| e | `⊤` (`:` etype)? | top | [Top](@ref thorin::Top) | +| e | n | identifier or annex name | `fe::Sym`/[Annex](@ref thorin::Annex) | +| e | `{` d\* e `}` | blocks | - | @note An elided type of * a literal defaults to `.Nat`, From a081deb227a944a603d267bea52045f70b2a417c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 15:54:44 +0200 Subject: [PATCH 19/53] porting World::arena_ to fe::Arena --- external/fe | 2 +- thorin/world.h | 110 +++++++++++++++---------------------------------- 2 files changed, 34 insertions(+), 78 deletions(-) diff --git a/external/fe b/external/fe index d0a53f3737..69ca3f60f8 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit d0a53f3737e468d77412702ffcadd637e7ea0fd8 +Subproject commit 69ca3f60f84589a1c686ce489949aef39a042be8 diff --git a/thorin/world.h b/thorin/world.h index 239efd6e97..48b326c60b 100644 --- a/thorin/world.h +++ b/thorin/world.h @@ -5,6 +5,8 @@ #include #include +#include + #include #include @@ -451,7 +453,7 @@ class World { /// @name Put into Sea of Nodes ///@{ template const T* unify(size_t num_ops, Args&&... args) { - auto def = arena_.allocate(num_ops, std::forward(args)...); + auto def = allocate(num_ops, std::forward(args)...); if (auto loc = emit_loc()) def->set(loc); assert(!def->isa_mut()); #ifdef THORIN_ENABLE_CHECKS @@ -461,13 +463,13 @@ class World { if (is_frozen()) { --state_.pod.curr_gid; auto i = move_.defs.find(def); - arena_.deallocate(def); + deallocate(def); if (i != move_.defs.end()) return static_cast(*i); return nullptr; } if (auto [i, ins] = move_.defs.emplace(def); !ins) { - arena_.deallocate(def); + deallocate(def); return static_cast(*i); } #ifdef THORIN_ENABLE_CHECKS @@ -478,7 +480,7 @@ class World { } template T* insert(size_t num_ops, Args&&... args) { - auto def = arena_.allocate(num_ops, std::forward(args)...); + auto def = allocate(num_ops, std::forward(args)...); if (auto loc = emit_loc()) def->set(loc); #ifdef THORIN_ENABLE_CHECKS if (flags().trace_gids) outln("{}: {} - {}", def->node_name(), def->gid(), def->flags()); @@ -487,87 +489,41 @@ class World { assert_emplace(move_.defs, def); return def; } - ///@} - - Driver* driver_; - State state_; - - class Arena { - public: - Arena() - : root_(new Zone) // don't use 'new Zone()' - we keep the allocated Zone uninitialized - , curr_(root_.get()) {} - - struct Zone { - static const size_t Size = 1024 * 1024 - sizeof(std::unique_ptr); // 1MB - sizeof(next) - char buffer[Size]; - std::unique_ptr next; - }; #if (!defined(_MSC_VER) && defined(NDEBUG)) - struct Lock { - Lock() { assert((guard_ = !guard_) && "you are not allowed to recursively invoke allocate"); } - ~Lock() { guard_ = !guard_; } - static bool guard_; - }; + struct Lock { + Lock() { assert((guard_ = !guard_) && "you are not allowed to recursively invoke allocate"); } + ~Lock() { guard_ = !guard_; } + static bool guard_; + }; #else - struct Lock { - ~Lock() {} - }; + struct Lock { + ~Lock() {} + }; #endif - template T* allocate(size_t num_ops, Args&&... args) { - static_assert(sizeof(Def) == sizeof(T), - "you are not allowed to introduce any additional data in subclasses of Def"); - Lock lock; - size_t num_bytes = num_bytes_of(num_ops); - num_bytes = align(num_bytes); - assert(num_bytes < Zone::Size); - - if (index_ + num_bytes >= Zone::Size) { - auto zone = new Zone; - curr_->next.reset(zone); - curr_ = zone; - index_ = 0; - } - - auto result = new (curr_->buffer + index_) T(std::forward(args)...); - assert(result->num_ops() == num_ops); - index_ += num_bytes; - assert(index_ % alignof(T) == 0); - - return result; - } - - template void deallocate(const T* def) { - size_t num_bytes = num_bytes_of(def->num_ops()); - num_bytes = align(num_bytes); - def->~T(); - if (ptrdiff_t(index_ - num_bytes) > 0) // don't care otherwise - index_ -= num_bytes; - assert(index_ % alignof(T) == 0); - } - static constexpr size_t align(size_t n) { return (n + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1); } + template T* allocate(size_t num_ops, Args&&... args) { + static_assert(sizeof(Def) == sizeof(T), + "you are not allowed to introduce any additional data in subclasses of Def"); + Lock lock; + auto ptr = arena_.allocate(num_bytes_of(num_ops)); + auto res = new (ptr) T(std::forward(args)...); + assert(res->num_ops() == num_ops); + return res; + } - template static constexpr size_t num_bytes_of(size_t num_ops) { - size_t result = sizeof(Def) + sizeof(void*) * num_ops; - return align(result); - } + template void deallocate(const T* def) { + size_t n = num_bytes_of(def->num_ops()); + def->~T(); + arena_.deallocate(n); + } - friend void swap(Arena& a1, Arena& a2) { - using std::swap; - // clang-format off - swap(a1.root_, a2.root_); - swap(a1.curr_, a2.curr_); - swap(a1.index_, a2.index_); - // clang-format on - } + template static constexpr size_t num_bytes_of(size_t num_ops) { return sizeof(Def) + sizeof(void*) * num_ops; } + ///@} - private: - std::unique_ptr root_; - Zone* curr_; - size_t index_ = 0; - } arena_; + Driver* driver_; + State state_; + fe::Arena<> arena_; struct SeaHash { size_t operator()(const Def* def) const { return def->hash(); }; From 7b1020720c6637152f76ef4e7409aa6d861d38aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 16:11:47 +0200 Subject: [PATCH 20/53] compile fix --- thorin/world.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/thorin/world.cpp b/thorin/world.cpp index 6f2e658fe7..5d296460da 100644 --- a/thorin/world.cpp +++ b/thorin/world.cpp @@ -43,7 +43,7 @@ const Def* infer_sigma(World& world, Defs ops) { */ #if (!defined(_MSC_VER) && defined(NDEBUG)) -bool World::Arena::Lock::guard_ = false; +bool World::Lock::guard_ = false; #endif World::World(Driver* driver, const State& state) From 1427ba78ac7cea95685030d59fbc45739fe9a575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 20:57:15 +0200 Subject: [PATCH 21/53] fe: bump --- external/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/fe b/external/fe index 69ca3f60f8..0dc8d0ae8d 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 69ca3f60f84589a1c686ce489949aef39a042be8 +Subproject commit 0dc8d0ae8d7e3003cb6a842b918c32ec5ca12d97 From 7fc6e49cd807ee4cd827a457e2fd462227919e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 22:04:48 +0200 Subject: [PATCH 22/53] thorin/util/utf8.* -> fe/utf.8 / fe/lexer.h --- external/fe | 2 +- gtest/lexer.cpp | 36 ------------- thorin/CMakeLists.txt | 2 - thorin/fe/lexer.cpp | 73 +++++++++++++-------------- thorin/fe/lexer.h | 23 ++++++--- thorin/util/utf8.cpp | 52 ------------------- thorin/util/utf8.h | 114 ------------------------------------------ 7 files changed, 52 insertions(+), 250 deletions(-) delete mode 100644 thorin/util/utf8.cpp delete mode 100644 thorin/util/utf8.h diff --git a/external/fe b/external/fe index 0dc8d0ae8d..7bb03e094e 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 0dc8d0ae8d7e3003cb6a842b918c32ec5ca12d97 +Subproject commit 7bb03e094e685870c57ff79d71b5142a18018152 diff --git a/gtest/lexer.cpp b/gtest/lexer.cpp index 5e183fe5bf..36dcafeceb 100644 --- a/gtest/lexer.cpp +++ b/gtest/lexer.cpp @@ -35,32 +35,6 @@ TEST(Lexer, Toks) { EXPECT_TRUE(lexer.lex().isa(Tok::Tag::M_eof)); } -TEST(Lexer, Loc) { - Driver driver; - std::istringstream is(" test abc def if \nwhile λ foo "); - Lexer lexer(driver.world(), is); - auto t1 = lexer.lex(); - auto t2 = lexer.lex(); - auto t3 = lexer.lex(); - auto t4 = lexer.lex(); - auto t5 = lexer.lex(); - auto t6 = lexer.lex(); - auto t7 = lexer.lex(); - auto t8 = lexer.lex(); - EXPECT_EQ(fmt("{} {} {} {} {} {} {} {}", t1, t2, t3, t4, t5, t6, t7, t8), "test abc def if while λ foo "); - - // clang-format off - EXPECT_EQ(t1.loc(), Loc({1, 2}, {1, 5})); - EXPECT_EQ(t2.loc(), Loc({1, 8}, {1, 10})); - EXPECT_EQ(t3.loc(), Loc({1, 15}, {1, 17})); - EXPECT_EQ(t4.loc(), Loc({1, 19}, {1, 20})); - EXPECT_EQ(t5.loc(), Loc({2, 1}, {2, 5})); - EXPECT_EQ(t6.loc(), Loc({2, 7}, {2, 7})); - EXPECT_EQ(t7.loc(), Loc({2, 9}, {2, 11})); - EXPECT_EQ(t8.loc(), Loc({2, 14}, {2, 14})); - // clang-format on -} - TEST(Lexer, Errors) { Driver driver; std::istringstream is1("asdf \xc0\xc0"); @@ -134,14 +108,4 @@ TEST_P(Real, sign) { EXPECT_ANY_THROW(l2.lex()); } -TEST(Lexer, utf8) { - std::ostringstream oss; - utf8::decode(oss, U'a'); - utf8::decode(oss, U'£'); - utf8::decode(oss, U'λ'); - utf8::decode(oss, U'𐄂'); - utf8::decode(oss, U'𐀮'); - EXPECT_EQ(oss.str(), "a£λ𐄂𐀮"); -} - INSTANTIATE_TEST_SUITE_P(Lexer, Real, testing::Range(0, 3)); diff --git a/thorin/CMakeLists.txt b/thorin/CMakeLists.txt index 05dfce3f63..dbf39633ca 100644 --- a/thorin/CMakeLists.txt +++ b/thorin/CMakeLists.txt @@ -87,8 +87,6 @@ add_library(libthorin util/sys.cpp util/sys.h util/types.h - util/utf8.cpp - util/utf8.h util/util.h ) set_target_properties(libthorin PROPERTIES PREFIX "") diff --git a/thorin/fe/lexer.cpp b/thorin/fe/lexer.cpp index 19c2c80c87..fecde81d68 100644 --- a/thorin/fe/lexer.cpp +++ b/thorin/fe/lexer.cpp @@ -39,16 +39,15 @@ Tok Lexer::lex() { return *cache; } - loc_.begin = ahead().pos; - str_.clear(); + begin(); #if defined(_WIN32) && !defined(NDEBUG) // isspace asserts otherwise if (accept_if([](int c) { return (c & ~0xFF) == 0 ? isspace(c) : false; })) continue; #else if (accept_if(isspace)) continue; #endif - if (accept(utf8::Err)) error(loc_, "invalid UTF-8 character"); - if (accept(utf8::EoF)) return tok(Tag::M_eof); + if (accept(0)) error(loc_, "invalid UTF-8 character"); + if (accept(fe::utf8::EoF)) return tok(Tag::M_eof); // clang-format off // delimiters @@ -139,7 +138,7 @@ Tok Lexer::lex() { continue; } - if (accept('\"', false)) { + if (accept('\"')) { while (lex_char() != '"') {} str_.pop_back(); // remove final '"' return {loc_, Tag::M_str, sym()}; @@ -167,15 +166,15 @@ Tok Lexer::lex() { continue; } if (accept('/')) { - while (ahead() != utf8::EoF && ahead() != '\n') next(); + while (ahead() != fe::utf8::EoF && ahead() != '\n') next(); continue; } - error({loc_.path, ahead().pos}, "invalid input char '/'; maybe you wanted to start a comment?"); + error({loc_.path, peek_}, "invalid input char '/'; maybe you wanted to start a comment?"); continue; } - error({loc_.path, ahead().pos}, "invalid input char '{}'", (char)ahead()); + error({loc_.path, peek_}, "invalid input char '{}'", (char)ahead()); next(); } } @@ -205,21 +204,21 @@ std::optional Lexer::parse_lit() { int base = 10; std::optional sign; - if (accept('+', false)) { + if (accept('+')) { sign = false; - } else if (accept('-', false)) { + } else if (accept('-')) { if (accept('>')) return tok(Tag::T_arrow); sign = true; } // prefix starting with '0' - if (accept('0', false)) { - if (accept('b', false)) base = 2; - else if (accept('B', false)) base = 2; - else if (accept('o', false)) base = 8; - else if (accept('O', false)) base = 8; - else if (accept('x', false)) base = 16; - else if (accept('X', false)) base = 16; + if (accept('0')) { + if (accept('b')) base = 2; + else if (accept('B')) base = 2; + else if (accept('o')) base = 8; + else if (accept('O')) base = 8; + else if (accept('x')) base = 16; + else if (accept('X')) base = 16; } parse_digits(base); @@ -234,7 +233,7 @@ std::optional Lexer::parse_lit() { } auto m = strtoull(mod.c_str(), nullptr, 10); return Tok{loc_, world().lit_idx_mod(m, i)}; - } else if (accept('_', false)) { + } else if (accept('_')) { auto i = strtoull(str_.c_str(), nullptr, 10); str_.clear(); if (accept_if(isdigit)) { @@ -298,34 +297,34 @@ bool Lexer::parse_exp(int base /*= 10*/) { // clang-format on char8_t Lexer::lex_char() { - if (accept('\\', false)) { + if (accept('\\')) { // clang-format off if (false) {} - else if (accept('\'', false)) str_ += '\''; - else if (accept('\\', false)) str_ += '\\'; - else if (accept( '"', false)) str_ += '\"'; - else if (accept( '0', false)) str_ += '\0'; - else if (accept( 'a', false)) str_ += '\a'; - else if (accept( 'b', false)) str_ += '\b'; - else if (accept( 'f', false)) str_ += '\f'; - else if (accept( 'n', false)) str_ += '\n'; - else if (accept( 'r', false)) str_ += '\r'; - else if (accept( 't', false)) str_ += '\t'; - else if (accept( 'v', false)) str_ += '\v'; - else error(loc_.anew_finis(), "invalid escape character '\\{}'", (char)ahead().c32); + else if (accept('\'')) str_ += '\''; + else if (accept('\\')) str_ += '\\'; + else if (accept( '"')) str_ += '\"'; + else if (accept( '0')) str_ += '\0'; + else if (accept( 'a')) str_ += '\a'; + else if (accept( 'b')) str_ += '\b'; + else if (accept( 'f')) str_ += '\f'; + else if (accept( 'n')) str_ += '\n'; + else if (accept( 'r')) str_ += '\r'; + else if (accept( 't')) str_ += '\t'; + else if (accept( 'v')) str_ += '\v'; + else error(loc_.anew_finis(), "invalid escape character '\\{}'", (char)ahead()); // clang-format on return str_.back(); } auto c = next(); str_ += c; - if (isascii(c.c32)) return c.c32; - error(loc_, "invalid character '{}'", (char)c.c32); + if (isascii(c)) return c; + error(loc_, "invalid character '{}'", (char)c); } void Lexer::eat_comments() { while (true) { - while (ahead() != utf8::EoF && ahead() != '*') next(); - if (accept(utf8::EoF)) { + while (ahead() != fe::utf8::EoF && ahead() != '*') next(); + if (accept(fe::utf8::EoF)) { error(loc_, "non-terminated multiline comment"); return; } @@ -343,11 +342,11 @@ void Lexer::emit_md(bool start_of_file) { accept(' '); out_ = true; - while (ahead() != utf8::EoF && ahead() != '\n') next(); + while (ahead() != fe::utf8::EoF && ahead() != '\n') next(); accept('\n'); } while (start_md()); - if (ahead() == utf8::EoF) + if (ahead() == fe::utf8::EoF) out_ = false; else md_fence(); diff --git a/thorin/fe/lexer.h b/thorin/fe/lexer.h index 6de86fd2fd..0f3aaa512c 100644 --- a/thorin/fe/lexer.h +++ b/thorin/fe/lexer.h @@ -4,14 +4,15 @@ #include +#include + #include "thorin/fe/tok.h" -#include "thorin/util/utf8.h" namespace thorin { class World; -class Lexer : public utf8::Lexer<3> { - using Super = utf8::Lexer<3>; +class Lexer : public fe::Lexer<3> { + using Super = fe::Lexer<3>; public: /// Creates a lexer to read Thorin files (see [Lexical Structure](@ref lex)). @@ -24,14 +25,20 @@ class Lexer : public utf8::Lexer<3> { Tok lex(); private: - Char next() override { + /// Invoke before assembling the next token. + void begin() { + loc_.begin = peek_; + str_.clear(); + } + + char32_t next() { auto res = Super::next(); if (md_ && out_) { - if (res.c32 == utf8::EoF) { + if (res == fe::utf8::EoF) { *md_ << "\n```\n"; out_ = false; - } else if (res.c32 != utf8::Err) { - bool success = utf8::decode(*md_, res.c32); + } else if (res) { + bool success = fe::utf8::encode(*md_, res); assert_unused(success); } } @@ -47,7 +54,7 @@ class Lexer : public utf8::Lexer<3> { void parse_digits(int base = 10); bool parse_exp(int base = 10); void eat_comments(); - bool start_md() const { return ahead(0).c32 == '/' && ahead(1).c32 == '/' && ahead(2).c32 == '/'; } + bool start_md() const { return ahead(0) == '/' && ahead(1) == '/' && ahead(2) == '/'; } void emit_md(bool start_of_file = false); void md_fence() { if (md_) *md_ << "```\n"; diff --git a/thorin/util/utf8.cpp b/thorin/util/utf8.cpp deleted file mode 100644 index 3f4f6fbf1e..0000000000 --- a/thorin/util/utf8.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "thorin/util/utf8.h" - -#include - -namespace thorin::utf8 { - -namespace { -// and, or -std::ostream& ao(std::ostream& os, char32_t c32, char32_t a = 0b00111111_u32, char32_t o = 0b10000000_u32) { - return os << char((c32 & a) | o); -} -} // namespace - -size_t num_bytes(char8_t c) { - if ((c & 0b10000000_u8) == 0b00000000_u8) return 1; - if ((c & 0b11100000_u8) == 0b11000000_u8) return 2; - if ((c & 0b11110000_u8) == 0b11100000_u8) return 3; - if ((c & 0b11111000_u8) == 0b11110000_u8) return 4; - return 0; -} - -char32_t encode(std::istream& is) { - char32_t result = is.get(); - if (result == EoF) return result; - - switch (auto n = utf8::num_bytes(result)) { - case 0: return {}; - case 1: return result; - default: - result = utf8::first(result, n); - - for (size_t i = 1; i != n; ++i) - if (auto x = utf8::is_valid(is.get())) - result = utf8::append(result, *x); - else - return Err; - } - - return result; -} - -bool decode(std::ostream& os, char32_t c32) { - // clang-format off - if (c32 <= 0x00007f_u32) { ao(os, c32 , 0b11111111_u32, 0b00000000_u32); return true; } - if (c32 <= 0x0007ff_u32) { ao(ao(os, c32 >> 6, 0b00011111_u32, 0b11000000_u32), c32); return true; } - if (c32 <= 0x00ffff_u32) { ao(ao(ao(os, c32 >> 12, 0b00001111_u32, 0b11100000_u32), c32 >> 6), c32); return true; } - if (c32 <= 0x10ffff_u32) { ao(ao(ao(ao(os, c32 >> 18, 0b00000111_u32, 0b11110000_u32), c32 >> 12), c32 >> 6), c32); return true; } - // clang-format on - return false; -} - -} // namespace thorin::utf8 diff --git a/thorin/util/utf8.h b/thorin/util/utf8.h deleted file mode 100644 index d2b8a52a09..0000000000 --- a/thorin/util/utf8.h +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "thorin/util/dbg.h" -#include "thorin/util/types.h" - -namespace thorin::utf8 { - -static constexpr size_t Max = 4; ///< Maximal number of `char8_t`s of an UTF-8 byte sequence. -static constexpr char32_t BOM = 0xfeff_u32; ///< [Byte Order Mark](https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8). -static constexpr char32_t EoF = (char32_t)std::istream::traits_type::eof(); ///< End of File. -static constexpr char32_t Err = (char32_t)-2; ///< Erroneous UTF char. - -/// Returns the expected number of bytes for an UTF-8 char sequence by inspecting the first byte. -/// Retuns @c 0 if invalid. -size_t num_bytes(char8_t c); - -/// Append @p b to @p c for converting UTF-8 to UTF-32. -inline char32_t append(char32_t c, char32_t b) { return (c << 6_u32) | (b & 0b00111111_u32); } - -/// Get relevant bits of first UTF-8 byte @p c of a @em multi-byte sequence consisting of @p num bytes. -inline char32_t first(char32_t c, char32_t num) { return c & (0b00011111_u32 >> (num - 2_u32)); } - -/// Is the 2nd, 3rd, or 4th byte of an UTF-8 byte sequence valid? -inline std::optional is_valid(char8_t c) { - return (c & 0b11000000_u8) == 0b10000000_u8 ? (c & 0b00111111_u8) : std::optional(); -} - -/// Encodes the next sequence of bytes from @p is as UTF-32. -/// @returns `std::nullopt` on error. -char32_t encode(std::istream& is); - -/// Decodes the UTF-32 char @p c to UTF-8 and writes the sequence of bytes to @p os. -/// @returns `false` on error. -bool decode(std::ostream& os, char32_t c); - -template -class Lexer { -public: - Lexer(std::istream& istream, const fs::path* path) - : istream_(istream) - , loc_(path, {0, 0}) { - ahead_.back().pos = {1, 0}; - for (size_t i = 0; i != Max_Ahead; ++i) next(); - accept(BOM); // eat utf-8 BOM if present - } - virtual ~Lexer() {} - -protected: - struct Char { - Char() = default; - Char(char32_t c32, Pos pos) - : c32(c32) - , pos(pos) {} - - operator char32_t() const { return c32; } - char32_t c32; - Pos pos; - }; - - Char ahead(size_t i = 0) const { - assert(i < Max_Ahead); - return ahead_[i]; - } - - virtual Char next() { - auto result = ahead(); - auto prev = ahead_.back().pos; - - for (size_t i = 0; i < Max_Ahead - 1; ++i) ahead_[i] = ahead_[i + 1]; - auto& back = ahead_.back(); - back.pos = prev; - back.c32 = utf8::encode(istream_); - - if (back.c32 == '\n') { - ++back.pos.row; - back.pos.col = 0; - } else if (back.c32 == EoF) { - /* do nothing */ - } else { - ++back.pos.col; - } - - loc_.finis = result.pos; - return result; - } - - /// Yields consumed Char if @p pred holds. - /// In this case, invoke @p next() and append to Lexer::str_ (if @p append is *true). - template - std::optional accept_if(Pred pred, bool append = true) { - auto c = ahead(); - if (pred(c)) { - if (append) str_ += c; - next(); - return c; - } - return {}; - } - - std::optional accept(char32_t val, bool append = true) { - return accept_if([val](char32_t p) { return p == val; }, append); - } - - std::istream& istream_; - Loc loc_; - std::string str_; - std::array ahead_; -}; - -} // namespace thorin::utf8 From 32fb6cb07984d2d4c2a3006c7d99c94cd1858875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 2 Oct 2023 22:48:56 +0200 Subject: [PATCH 23/53] bug fixes --- external/fe | 2 +- thorin/fe/lexer.h | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/external/fe b/external/fe index 7bb03e094e..54232926b8 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 7bb03e094e685870c57ff79d71b5142a18018152 +Subproject commit 54232926b8272a9d0e26a3d526bf5374900a5af0 diff --git a/thorin/fe/lexer.h b/thorin/fe/lexer.h index 0f3aaa512c..3140bec9b5 100644 --- a/thorin/fe/lexer.h +++ b/thorin/fe/lexer.h @@ -11,8 +11,8 @@ namespace thorin { class World; -class Lexer : public fe::Lexer<3> { - using Super = fe::Lexer<3>; +class Lexer : public fe::Lexer<3, Lexer> { + using Super = fe::Lexer<3, Lexer>; public: /// Creates a lexer to read Thorin files (see [Lexical Structure](@ref lex)). @@ -25,12 +25,6 @@ class Lexer : public fe::Lexer<3> { Tok lex(); private: - /// Invoke before assembling the next token. - void begin() { - loc_.begin = peek_; - str_.clear(); - } - char32_t next() { auto res = Super::next(); if (md_ && out_) { @@ -65,6 +59,8 @@ class Lexer : public fe::Lexer<3> { bool out_ = true; fe::SymMap keywords_; std::optional cache_ = std::nullopt; + + friend class fe::Lexer<3, Lexer>; }; } // namespace thorin From 7795b25392e0780b4aacf8f8604f156454346dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 01:04:00 +0200 Subject: [PATCH 24/53] wip: porting Parser to fe --- external/fe | 2 +- thorin/fe/parser.cpp | 28 ++++++++++++++-------------- thorin/fe/parser.h | 15 ++++++--------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/external/fe b/external/fe index 54232926b8..7a1225fa5b 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 54232926b8272a9d0e26a3d526bf5374900a5af0 +Subproject commit 7a1225fa5b5567488243e08cc207e3227d284280 diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index 45d05bfa8e..f52b1800ee 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -26,7 +26,7 @@ using Tag = Tok::Tag; Tok Parser::lex() { auto result = ahead(); - prev() = result.loc(); + prev_ = result.loc(); for (size_t i = 0; i < Max_Ahead - 1; ++i) ahead(i) = ahead(i + 1); ahead(Max_Ahead - 1) = lexer().lex(); return result; @@ -91,13 +91,13 @@ void Parser::import(std::istream& is, const fs::path* path, std::ostream* md) { if (!is) error("cannot read file '{}'", *path); lexers_.emplace(world(), is, path, md); - auto state = state_; + auto state = std::pair(prev_, ahead_); for (size_t i = 0; i != Max_Ahead; ++i) ahead(i) = lexer().lex(); - prev() = Loc(path, {1, 1}); + prev_ = Loc(path, {1, 1}); parse_module(); - state_ = state; + std::tie(prev_, ahead_) = state; lexers_.pop(); } @@ -128,7 +128,7 @@ void Parser::parse_plugin() { Dbg Parser::parse_id(std::string_view ctxt) { if (auto id = accept(Tag::M_id)) return id->dbg(); syntax_err("identifier", ctxt); - return {prev(), world().sym("")}; + return {prev_, world().sym("")}; } std::pair Parser::parse_name(std::string_view ctxt) { @@ -136,7 +136,7 @@ std::pair Parser::parse_name(std::string_view ctxt) { if (auto tok = accept(Tag::M_id)) return {tok->dbg(), false}; syntax_err("identifier or annex name", ctxt); return { - {prev(), world().sym("")}, + {prev_, world().sym("")}, false }; } @@ -274,7 +274,7 @@ Ref Parser::parse_primary_expr(std::string_view ctxt) { case Tag::K_ret: return parse_ret_expr(); case Tag::M_anx: case Tag::M_id: return scopes_.find(lex().dbg()); - case Tag::M_str: return world().tuple(lex().sym())->set(prev()); + case Tag::M_str: return world().tuple(lex().sym())->set(prev_); default: if (ctxt.empty()) return nullptr; syntax_err("primary expression", ctxt); @@ -455,7 +455,7 @@ Lam* Parser::parse_lam(bool is_decl) { } // clang-format on - auto [dbg, anx] = is_decl ? parse_name(entity) : std::pair(Dbg{prev(), anonymous_}, false); + auto [dbg, anx] = is_decl ? parse_name(entity) : std::pair(Dbg{prev_, anonymous_}, false); auto outer = scopes_.curr(); Lam* decl = nullptr; @@ -566,8 +566,8 @@ Lam* Parser::parse_lam(bool is_decl) { auto body = accept(Tag::T_assign) ? parse_decls("body of a "s + entity) : nullptr; if (!body) { - if (!is_decl) error(prev(), "body of a {}", entity); - if (auto [_, __, filter] = funs.back(); filter) error(prev(), "cannot specify filter of a {}", entity); + if (!is_decl) error(prev_, "body of a {}", entity); + if (auto [_, __, filter] = funs.back(); filter) error(prev_, "cannot specify filter of a {}", entity); } // filter defaults to .tt for everything except the actual continuation of con/cn/fun/fn; here we use .ff as default @@ -607,7 +607,7 @@ Ref Parser::parse_ret_expr() { return world().app(cn, {arg, lam}); } - error(prev(), "continuation of the ret expression is not a returning continuation but has type '{}'", cn->type()); + error(prev_, "continuation of the ret expression is not a returning continuation but has type '{}'", cn->type()); } Ref Parser::parse_lit_expr() { @@ -633,8 +633,8 @@ Ref Parser::parse_lit_expr() { if (tok.tag() == Tag::T_bot) return world().bot(world().type())->set(track.loc()); if (tok.tag() == Tag::T_top) return world().top(world().type())->set(track.loc()); - if (tok.tag() == Tag::L_s) error(prev(), ".Nat literal specified as signed but must be unsigned"); - if (tok.tag() == Tag::L_f) error(prev(), ".Nat literal specified as floating-point but must be unsigned"); + if (tok.tag() == Tag::L_s) error(prev_, ".Nat literal specified as signed but must be unsigned"); + if (tok.tag() == Tag::L_f) error(prev_, ".Nat literal specified as floating-point but must be unsigned"); return world().lit_nat(tok.lit_u())->set(track.loc()); } @@ -883,7 +883,7 @@ void Parser::parse_ax_decl() { world().register_annex(p | (flags_t(t) << 8_u64) | flags_t(s), axiom); for (auto& alias : sub) { auto sym = world().sym(*dbg.sym + "."s + *alias); - scopes_.bind({prev(), sym}, axiom); + scopes_.bind({prev_, sym}, axiom); } ++s; } diff --git a/thorin/fe/parser.h b/thorin/fe/parser.h index 9adc440034..b4398ce163 100644 --- a/thorin/fe/parser.h +++ b/thorin/fe/parser.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "thorin/driver.h" #include "thorin/fe/ast.h" @@ -26,7 +28,7 @@ namespace thorin { /// /// * If default argument is **elided** we have the same behavior as in 1. /// * If default argument is **provided** we have the same behavior as in 2. -class Parser { +class Parser : public fe::Parser { public: Parser(World& world) : world_(world) @@ -50,7 +52,7 @@ class Parser { : parser_(parser) , pos_(pos) {} - Loc loc() const { return {parser_.prev().path, pos_, parser_.prev().finis}; } + Loc loc() const { return {parser_.prev_.path, pos_, parser_.prev_.finis}; } Dbg dbg(Sym sym) const { return {loc(), sym}; } private: @@ -58,8 +60,6 @@ class Parser { Pos pos_; }; - Loc& prev() { return state_.prev; } - /// Factory method to build a Parser::Tracker. Tracker tracker() { return Tracker(*this, ahead().loc().begin); } ///@} @@ -69,7 +69,7 @@ class Parser { /// Get lookahead. Tok& ahead(size_t i = 0) { assert(i < Max_Ahead); - return state_.ahead[i]; + return ahead_[i]; } Lexer& lexer() { return lexers_.top(); } @@ -172,10 +172,7 @@ class Parser { World& world_; std::stack lexers_; - struct { - Loc prev; - Ahead ahead; ///< SLL look ahead - } state_; + Ahead ahead_; ///< SLL look ahead Scopes scopes_; Def2Fields def2fields_; Sym anonymous_; From 0cc22d0c724431515026561ed815e049f7b3ad26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 12:52:12 +0200 Subject: [PATCH 25/53] wip: porting to fe::Parser --- external/fe | 2 +- thorin/fe/parser.cpp | 6 +++--- thorin/fe/parser.h | 14 +++----------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/external/fe b/external/fe index 7a1225fa5b..24461d7894 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 7a1225fa5b5567488243e08cc207e3227d284280 +Subproject commit 24461d7894b8652823d00e419cac3e3e074d9d14 diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index f52b1800ee..6a30be10c0 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -27,8 +27,7 @@ using Tag = Tok::Tag; Tok Parser::lex() { auto result = ahead(); prev_ = result.loc(); - for (size_t i = 0; i < Max_Ahead - 1; ++i) ahead(i) = ahead(i + 1); - ahead(Max_Ahead - 1) = lexer().lex(); + ahead_.put(lexer().lex()); return result; } @@ -93,7 +92,8 @@ void Parser::import(std::istream& is, const fs::path* path, std::ostream* md) { lexers_.emplace(world(), is, path, md); auto state = std::pair(prev_, ahead_); - for (size_t i = 0; i != Max_Ahead; ++i) ahead(i) = lexer().lex(); + ahead_.reset(); + for (size_t i = 0; i != Look_Ahead; ++i) ahead(i) = lexer().lex(); prev_ = Loc(path, {1, 1}); parse_module(); diff --git a/thorin/fe/parser.h b/thorin/fe/parser.h index b4398ce163..9bc75a8582 100644 --- a/thorin/fe/parser.h +++ b/thorin/fe/parser.h @@ -10,6 +10,8 @@ namespace thorin { +constexpr size_t Look_Ahead = 2; + /// Parses Thorin code into the provided World. /// /// The logic behind the various parse methods is as follows: @@ -28,7 +30,7 @@ namespace thorin { /// /// * If default argument is **elided** we have the same behavior as in 1. /// * If default argument is **provided** we have the same behavior as in 2. -class Parser : public fe::Parser { +class Parser : public fe::Parser { public: Parser(World& world) : world_(world) @@ -66,12 +68,6 @@ class Parser : public fe::Parser { /// @name get next token ///@{ - /// Get lookahead. - Tok& ahead(size_t i = 0) { - assert(i < Max_Ahead); - return ahead_[i]; - } - Lexer& lexer() { return lexers_.top(); } bool main() const { return lexers_.size() == 1; } @@ -167,12 +163,8 @@ class Parser : public fe::Parser { [[noreturn]] void syntax_err(std::string_view what, std::string_view ctxt) { syntax_err(what, ahead(), ctxt); } ///@} - static constexpr size_t Max_Ahead = 2; ///< maximum lookahead - using Ahead = std::array; - World& world_; std::stack lexers_; - Ahead ahead_; ///< SLL look ahead Scopes scopes_; Def2Fields def2fields_; Sym anonymous_; From c0f79d058a149b26f28990cfd3c432448fb1151e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 14:09:42 +0200 Subject: [PATCH 26/53] more porting to fe::Parser --- external/fe | 2 +- thorin/fe/parser.cpp | 29 ++++++++--------------------- thorin/fe/parser.h | 36 +++--------------------------------- 3 files changed, 12 insertions(+), 55 deletions(-) diff --git a/external/fe b/external/fe index 24461d7894..832470dbc5 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 24461d7894b8652823d00e419cac3e3e074d9d14 +Subproject commit 832470dbc5b24981c5dca1bf7f90bde2cf672324 diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index 6a30be10c0..85b3d848bf 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -24,18 +24,6 @@ using Tag = Tok::Tag; * helpers */ -Tok Parser::lex() { - auto result = ahead(); - prev_ = result.loc(); - ahead_.put(lexer().lex()); - return result; -} - -std::optional Parser::accept(Tag tag) { - if (tag != ahead().tag()) return {}; - return lex(); -} - Tok Parser::expect(Tag tag, std::string_view ctxt) { if (ahead().tag() == tag) return lex(); @@ -92,8 +80,7 @@ void Parser::import(std::istream& is, const fs::path* path, std::ostream* md) { lexers_.emplace(world(), is, path, md); auto state = std::pair(prev_, ahead_); - ahead_.reset(); - for (size_t i = 0; i != Look_Ahead; ++i) ahead(i) = lexer().lex(); + init(); prev_ = Loc(path, {1, 1}); parse_module(); @@ -699,7 +686,7 @@ std::unique_ptr Parser::parse_ptrn(Tag delim_l, std::string_view ctxt, Tok sym = eat(Tag::M_id).sym(); eat(Tag::T_colon); auto type = parse_expr(ctxt, prec); - return std::make_unique(track.dbg(sym), rebind, type); + return std::make_unique(dbg(track, sym), rebind, type); } else { // p -> s b -> e where e == id // p -> 's @@ -707,18 +694,18 @@ std::unique_ptr Parser::parse_ptrn(Tag delim_l, std::string_view ctxt, Tok // p -> s // p -> 's sym = eat(Tag::M_id).sym(); - return std::make_unique(track.dbg(sym), rebind, nullptr); + return std::make_unique(dbg(track, sym), rebind, nullptr); } else { // b -> e where e == id auto type = parse_expr(ctxt, prec); - return std::make_unique(track.dbg(sym), rebind, type); + return std::make_unique(dbg(track, sym), rebind, type); } } } else if (b) { // b -> e where e != id if (backtick) error(backtick->loc(), "you can only prefix identifiers with backtick for rebinding"); auto type = parse_expr(ctxt, prec); - return std::make_unique(track.dbg(sym), rebind, type); + return std::make_unique(dbg(track, sym), rebind, type); } else if (!ctxt.empty()) { // p -> ↯ syntax_err("pattern", ctxt); @@ -770,14 +757,14 @@ std::unique_ptr Parser::parse_tuple_ptrn(Tracker track, bool rebind, } auto [_, r] = Tok::prec(Tok::Prec::App); auto expr = parse_infix_expr(track, lhs, r); - ptrn = std::make_unique(track.dbg(anonymous_), false, expr); + ptrn = std::make_unique(dbg(track, anonymous_), false, expr); } else { ptrn = parse_ptrn(delim_l, "element of a tuple pattern"); auto type = ptrn->type(world(), def2fields_); if (b) { // If we are able to parse more stuff, we got an expression instead of just a binder. if (auto expr = parse_infix_expr(track, type); expr != type) - ptrn = std::make_unique(track.dbg(anonymous_), false, expr); + ptrn = std::make_unique(dbg(track, anonymous_), false, expr); } } @@ -789,7 +776,7 @@ std::unique_ptr Parser::parse_tuple_ptrn(Tracker track, bool rebind, scopes_.pop(); // TODO parse type - return std::make_unique(track.dbg(sym), rebind, std::move(ptrns), nullptr, std::move(infers), decl); + return std::make_unique(dbg(track, sym), rebind, std::move(ptrns), nullptr, std::move(infers), decl); } /* diff --git a/thorin/fe/parser.h b/thorin/fe/parser.h index 9bc75a8582..af3d85b565 100644 --- a/thorin/fe/parser.h +++ b/thorin/fe/parser.h @@ -45,47 +45,15 @@ class Parser : public fe::Parser { const Scopes& scopes() const { return scopes_; } private: - /// @name Tracker - ///@{ - /// Trick to easily keep track of Loc%ations. - class Tracker { - public: - Tracker(Parser& parser, const Pos& pos) - : parser_(parser) - , pos_(pos) {} - - Loc loc() const { return {parser_.prev_.path, pos_, parser_.prev_.finis}; } - Dbg dbg(Sym sym) const { return {loc(), sym}; } - - private: - Parser& parser_; - Pos pos_; - }; - - /// Factory method to build a Parser::Tracker. - Tracker tracker() { return Tracker(*this, ahead().loc().begin); } - ///@} + Dbg dbg(const Tracker& tracker, Sym sym) const { return {tracker.loc(), sym}; } /// @name get next token ///@{ Lexer& lexer() { return lexers_.top(); } - bool main() const { return lexers_.size() == 1; } - - /// Invoke Lexer to retrieve next Tok%en. - Tok lex(); - - /// If Parser::ahead() is a @p tag, Parser::lex(), and return `true`. - std::optional accept(Tok::Tag tag); /// Parser::lex Parser::ahead() which must be a @p tag. /// Issue err%or with @p ctxt otherwise. Tok expect(Tok::Tag tag, std::string_view ctxt); - - /// Consume Parser::ahead which must be a @p tag; asserts otherwise. - Tok eat([[maybe_unused]] Tok::Tag tag) { - assert(tag == ahead().tag() && "internal parser error"); - return lex(); - } ///@} /// @name parse misc @@ -169,6 +137,8 @@ class Parser : public fe::Parser { Def2Fields def2fields_; Sym anonymous_; Sym return_; + + friend class fe::Parser; }; } // namespace thorin From 514d54668cabffa5811a038e72c0ae93f723de02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 15:00:24 +0200 Subject: [PATCH 27/53] using default impl for Pos/Loc ostream operators --- external/fe | 2 +- thorin/util/dbg.cpp | 28 +--------------------------- thorin/util/dbg.h | 10 ---------- 3 files changed, 2 insertions(+), 38 deletions(-) diff --git a/external/fe b/external/fe index 832470dbc5..c18082448b 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 832470dbc5b24981c5dca1bf7f90bde2cf672324 +Subproject commit c18082448b138b02675244b0cab598c15dff13f3 diff --git a/thorin/util/dbg.cpp b/thorin/util/dbg.cpp index f2d89c0ef1..59ea0409d2 100644 --- a/thorin/util/dbg.cpp +++ b/thorin/util/dbg.cpp @@ -1,27 +1 @@ -#include "thorin/util/dbg.h" - -namespace fe { - -std::ostream& operator<<(std::ostream& os, const Pos pos) { - if (pos.row) { - if (pos.col) return os << pos.row << ':' << pos.col; - return os << pos.row; - } - return os << ""; -} - -std::ostream& operator<<(std::ostream& os, const Loc loc) { - if (loc) { - os << (loc.path ? *loc.path : "") << ':' << loc.begin; - if (loc.begin != loc.finis) { - if (loc.begin.row != loc.finis.row) - os << '-' << loc.finis; - else - os << '-' << loc.finis.col; - } - return os; - } - return os << ""; -} - -} // namespace fe +#include diff --git a/thorin/util/dbg.h b/thorin/util/dbg.h index 47db52cfc8..d752eca7c9 100644 --- a/thorin/util/dbg.h +++ b/thorin/util/dbg.h @@ -10,16 +10,6 @@ #include "thorin/util/print.h" -namespace fe { - -/// @name std::ostream operator -///@{ -std::ostream& operator<<(std::ostream&, const Pos); -std::ostream& operator<<(std::ostream&, const Loc); -///@} - -} - namespace thorin { namespace fs = std::filesystem; From b5519be88d4abc1df8bb77661eb455177f9872e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 15:08:28 +0200 Subject: [PATCH 28/53] simplify --- external/fe | 2 +- thorin/fe/parser.cpp | 13 +++++-------- thorin/fe/parser.h | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/external/fe b/external/fe index c18082448b..46534f57c9 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit c18082448b138b02675244b0cab598c15dff13f3 +Subproject commit 46534f57c94af983017661c1d21223173273e87c diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index 85b3d848bf..11dd28b722 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -77,15 +77,12 @@ void Parser::import(std::istream& is, const fs::path* path, std::ostream* md) { world().VLOG("reading: {}", path ? path->string() : ""s); if (!is) error("cannot read file '{}'", *path); - lexers_.emplace(world(), is, path, md); - auto state = std::pair(prev_, ahead_); - - init(); - prev_ = Loc(path, {1, 1}); - + auto state = std::tuple(prev_, ahead_, lexer_); + auto lexer = Lexer(world(), is, path, md); + lexer_ = &lexer; + init(path); parse_module(); - std::tie(prev_, ahead_) = state; - lexers_.pop(); + std::tie(prev_, ahead_, lexer_) = state; } void Parser::plugin(fs::path path) { diff --git a/thorin/fe/parser.h b/thorin/fe/parser.h index af3d85b565..cf57f4352a 100644 --- a/thorin/fe/parser.h +++ b/thorin/fe/parser.h @@ -49,7 +49,7 @@ class Parser : public fe::Parser { /// @name get next token ///@{ - Lexer& lexer() { return lexers_.top(); } + Lexer& lexer() { return *lexer_; } /// Parser::lex Parser::ahead() which must be a @p tag. /// Issue err%or with @p ctxt otherwise. @@ -132,7 +132,7 @@ class Parser : public fe::Parser { ///@} World& world_; - std::stack lexers_; + Lexer* lexer_ = nullptr; Scopes scopes_; Def2Fields def2fields_; Sym anonymous_; From 84bf1374aec9e49371a4b3b6b06eee279493754b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 16:07:40 +0200 Subject: [PATCH 29/53] porting to fe::Parser::expect --- external/fe | 2 +- thorin/fe/parser.cpp | 17 ----------------- thorin/fe/parser.h | 18 +++++++++--------- 3 files changed, 10 insertions(+), 27 deletions(-) diff --git a/external/fe b/external/fe index 46534f57c9..98470ed1f4 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 46534f57c94af983017661c1d21223173273e87c +Subproject commit 98470ed1f421d98c8c3adb29c51b20ae4bd15632 diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index 11dd28b722..a684b49918 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -20,23 +20,6 @@ namespace thorin { using Tag = Tok::Tag; -/* - * helpers - */ - -Tok Parser::expect(Tag tag, std::string_view ctxt) { - if (ahead().tag() == tag) return lex(); - - std::string msg("'"); - msg.append(Tok::tag2str(tag)).append("'"); - syntax_err(msg, ctxt); - return {}; -} - -void Parser::syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt) { - error(tok.loc(), "expected {}, got '{}' while parsing {}", what, tok, ctxt); -} - /* * entry points */ diff --git a/thorin/fe/parser.h b/thorin/fe/parser.h index cf57f4352a..bdac7c3dda 100644 --- a/thorin/fe/parser.h +++ b/thorin/fe/parser.h @@ -46,16 +46,8 @@ class Parser : public fe::Parser { private: Dbg dbg(const Tracker& tracker, Sym sym) const { return {tracker.loc(), sym}; } - - /// @name get next token - ///@{ Lexer& lexer() { return *lexer_; } - /// Parser::lex Parser::ahead() which must be a @p tag. - /// Issue err%or with @p ctxt otherwise. - Tok expect(Tok::Tag tag, std::string_view ctxt); - ///@} - /// @name parse misc ///@{ void parse_module(); @@ -125,10 +117,18 @@ class Parser : public fe::Parser { ///@{ /// Issue an error message of the form: /// "expected \, got '\\' while parsing \" - [[noreturn]] void syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt); + [[noreturn]] void syntax_err(std::string_view what, const Tok& tok, std::string_view ctxt) { + error(tok.loc(), "expected {}, got '{}' while parsing {}", what, tok, ctxt); + } /// Same above but uses @p ahead() as @p tok. [[noreturn]] void syntax_err(std::string_view what, std::string_view ctxt) { syntax_err(what, ahead(), ctxt); } + + [[noreturn]] void syntax_err(Tok::Tag tag, std::string_view ctxt) { + std::string msg("'"); + msg.append(Tok::tag2str(tag)).append("'"); + syntax_err(msg, ctxt); + } ///@} World& world_; From 689d8a29742f1a51e9f3840e1b375468c18004ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 19:27:49 +0200 Subject: [PATCH 30/53] bump --- external/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/fe b/external/fe index 98470ed1f4..7dde32db68 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 98470ed1f421d98c8c3adb29c51b20ae4bd15632 +Subproject commit 7dde32db68ad74fca526aafb7976a83fe7e1f4b7 From 2aed9ba6999c497ff9d29bbd98b5109251e47cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 3 Oct 2023 21:21:44 +0200 Subject: [PATCH 31/53] refactor --- gtest/lexer.cpp | 4 ++-- thorin/fe/lexer.cpp | 2 +- thorin/fe/parser.cpp | 2 +- thorin/fe/tok.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gtest/lexer.cpp b/gtest/lexer.cpp index 36dcafeceb..4ce268e9d4 100644 --- a/gtest/lexer.cpp +++ b/gtest/lexer.cpp @@ -32,7 +32,7 @@ TEST(Lexer, Toks) { EXPECT_TRUE(lexer.lex().isa(Tok::Tag::K_Pi)); EXPECT_TRUE(lexer.lex().isa(Tok::Tag::T_lm)); EXPECT_TRUE(lexer.lex().isa(Tok::Tag::T_Pi)); - EXPECT_TRUE(lexer.lex().isa(Tok::Tag::M_eof)); + EXPECT_TRUE(lexer.lex().isa(Tok::Tag::EoF)); } TEST(Lexer, Errors) { @@ -61,7 +61,7 @@ TEST(Lexer, Eof) { std::istringstream is(""); Lexer lexer(driver.world(), is); - for (int i = 0; i < 10; i++) EXPECT_TRUE(lexer.lex().isa(Tok::Tag::M_eof)); + for (int i = 0; i < 10; i++) EXPECT_TRUE(lexer.lex().isa(Tok::Tag::EoF)); } class Real : public testing::TestWithParam {}; diff --git a/thorin/fe/lexer.cpp b/thorin/fe/lexer.cpp index fecde81d68..edbbc89b90 100644 --- a/thorin/fe/lexer.cpp +++ b/thorin/fe/lexer.cpp @@ -47,7 +47,7 @@ Tok Lexer::lex() { if (accept_if(isspace)) continue; #endif if (accept(0)) error(loc_, "invalid UTF-8 character"); - if (accept(fe::utf8::EoF)) return tok(Tag::M_eof); + if (accept(fe::utf8::EoF)) return tok(Tag::EoF); // clang-format off // delimiters diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index a684b49918..e47e7985b2 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -34,7 +34,7 @@ void Parser::parse_module() { break; parse_decls({}); - expect(Tag::M_eof, "module"); + expect(Tag::EoF, "module"); }; void Parser::import(fs::path name, std::ostream* md) { diff --git a/thorin/fe/tok.h b/thorin/fe/tok.h index 6b7a693fd3..87f9a8dfbc 100644 --- a/thorin/fe/tok.h +++ b/thorin/fe/tok.h @@ -43,6 +43,7 @@ constexpr auto Num_Keys = size_t(0) THORIN_KEY(CODE); #undef CODE #define THORIN_TOK(m) \ + m(EoF, "") \ /* literals */ \ m(L_s, "") \ m(L_u, "" ) \ @@ -50,7 +51,6 @@ constexpr auto Num_Keys = size_t(0) THORIN_KEY(CODE); m(L_f, "") \ m(L_c, "" ) \ /* misc */ \ - m(M_eof, "" ) \ m(M_id, "") \ m(M_anx, "") \ m(M_str, "" ) \ From 3c572e162560d20259b472bcdabf4250a513e8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Thu, 5 Oct 2023 00:30:06 +0200 Subject: [PATCH 32/53] bump --- external/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/fe b/external/fe index 7dde32db68..24d6d02667 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 7dde32db68ad74fca526aafb7976a83fe7e1f4b7 +Subproject commit 24d6d026679996a427342be371991a38784baebb From d1ef41238e1f2176e10c2d1342dfce2dc85785e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 6 Oct 2023 18:06:24 +0200 Subject: [PATCH 33/53] bump fe and use newer compilers in workflows --- .github/workflows/linux.yml | 14 +++++++------- .github/workflows/macos.yml | 12 ++++++++++-- external/fe | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 18c481733f..30f4775634 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -26,7 +26,7 @@ jobs: path: | ./llvm key: llvm-14.0.0-ubuntu - + - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v1.6.0 with: @@ -45,10 +45,10 @@ jobs: - name: Install newest g++, valgrind run: | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update - sudo apt-get install g++-11 valgrind - export CXX=g++-11 + sudo apt-get install g++-13 valgrind + export CXX=g++-13 sudo python -m pip install lit psutil sudo ln -s ${{github.workspace}}/bin/FileCheck-x86_64-ubuntu /usr/bin/FileCheck sudo chmod +x /usr/bin/FileCheck @@ -62,11 +62,11 @@ jobs: - name: Configure Debug if: matrix.build-type == 'Debug' - run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON - + run: CXX=g++-13 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON + - name: Configure Release if: matrix.build-type == 'Release' - run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DTHORIN_LIT_WITH_VALGRIND=ON + run: CXX=g++-13 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DTHORIN_LIT_WITH_VALGRIND=ON - name: Build run: cmake --build ${{github.workspace}}/build -v diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 65852c54dc..f8b3f373d3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -25,8 +25,16 @@ jobs: ccache_options: max_size=500M override_cache_key: mac-latest-ccache-${{matrix.build-type}} + - name: Install LLVM and Clang + run: brew install llvm@16 + - name: Configure - run: CC=gcc-11 CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=$(dirname $(which python3)) + run: | + CXX="/usr/local/opt/llvm/bin/clang" \ + CXX="/usr/local/opt/llvm/bin/clang++" \ + CXXFLAGS="-stdlib=libc++ -fexperimental-library" \ + LDFLAGS="-L/usr/local/opt/llvm/lib/c++ -Wl,-rpath,/usr/local/opt/llvm/lib/c++" \ + cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=$(dirname $(which python3)) - name: Cache LLVM and Clang id: cache-llvm @@ -51,7 +59,7 @@ jobs: file: FileCheck-x86_64-mac path: ${{github.workspace}}/bin token: ${{ secrets.GITHUB_TOKEN }} - + - name: Install LIT run: | python3 -m pip install lit psutil diff --git a/external/fe b/external/fe index 24d6d02667..bf64aa05f0 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 24d6d026679996a427342be371991a38784baebb +Subproject commit bf64aa05f0246ae06855dfe5e2305a2fb553dd05 From fe72c16ea520440ed2b3efd8fcfc7e95388582af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 6 Oct 2023 18:34:56 +0200 Subject: [PATCH 34/53] workflows --- .github/workflows/doxygen.yml | 8 ++++---- .github/workflows/macos.yml | 2 +- external/fe | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index e537e692d6..8bbfbd02d9 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -18,11 +18,11 @@ jobs: - name: Install newest g++, graphviz, texlive run: | - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update - sudo apt-get install g++-11 graphviz texlive-latex-base texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra + sudo apt-get install g++-13 graphviz texlive-latex-base texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra - export CXX=g++-11 + export CXX=g++-13 - name: Install Doxygen run: | @@ -38,7 +38,7 @@ jobs: mv ghostscript-10.0.0-linux-x86_64/gs-1000-linux-x86_64 ${HOME}/.local/bin/gs - name: Configure - run: CXX=g++-11 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Debug -DTHORIN_BUILD_DOCS=ON -DDOXYGEN_EXECUTABLE=${{github.workspace}}/doxygen-1.9.5/bin/doxygen + run: CXX=g++-13 cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Debug -DTHORIN_BUILD_DOCS=ON -DDOXYGEN_EXECUTABLE=${{github.workspace}}/doxygen-1.9.5/bin/doxygen - name: Build run: cmake --build ${{github.workspace}}/build -v --target docs diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f8b3f373d3..c8e9fe332d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -30,7 +30,7 @@ jobs: - name: Configure run: | - CXX="/usr/local/opt/llvm/bin/clang" \ + CC="/usr/local/opt/llvm/bin/clang" \ CXX="/usr/local/opt/llvm/bin/clang++" \ CXXFLAGS="-stdlib=libc++ -fexperimental-library" \ LDFLAGS="-L/usr/local/opt/llvm/lib/c++ -Wl,-rpath,/usr/local/opt/llvm/lib/c++" \ diff --git a/external/fe b/external/fe index bf64aa05f0..f0b6738a73 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit bf64aa05f0246ae06855dfe5e2305a2fb553dd05 +Subproject commit f0b6738a73b41aeffff42b18b4df465c4c782390 From 471f0a2c9827d896ecff3b66abb303e349c4b83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 6 Oct 2023 18:38:42 +0200 Subject: [PATCH 35/53] macos: bump to latest --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index c8e9fe332d..2e6ecafcbe 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -8,7 +8,7 @@ on: jobs: build-and-test: name: Build and test ${{matrix.build-type}} mode - runs-on: macos-11 + runs-on: macos-latest strategy: matrix: build-type: [Debug, Release] From d09df4e189d23d80d0d18bcba18464e4be0d5637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 6 Oct 2023 18:46:02 +0200 Subject: [PATCH 36/53] macos fix --- .github/workflows/macos.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 2e6ecafcbe..230b096646 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -30,7 +30,6 @@ jobs: - name: Configure run: | - CC="/usr/local/opt/llvm/bin/clang" \ CXX="/usr/local/opt/llvm/bin/clang++" \ CXXFLAGS="-stdlib=libc++ -fexperimental-library" \ LDFLAGS="-L/usr/local/opt/llvm/lib/c++ -Wl,-rpath,/usr/local/opt/llvm/lib/c++" \ From a67c6bb134ae0168fdc35f3e6d6c51cb5777d9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 6 Oct 2023 18:55:45 +0200 Subject: [PATCH 37/53] macos --- .github/workflows/macos.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 230b096646..f20a5f9d1a 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -30,9 +30,10 @@ jobs: - name: Configure run: | - CXX="/usr/local/opt/llvm/bin/clang++" \ + CC="/usr/local/opt/llvm@16/bin/clang" \ + CXX="/usr/local/opt/llvm@16/bin/clang++" \ CXXFLAGS="-stdlib=libc++ -fexperimental-library" \ - LDFLAGS="-L/usr/local/opt/llvm/lib/c++ -Wl,-rpath,/usr/local/opt/llvm/lib/c++" \ + LDFLAGS="-L/usr/local/opt/llvm@16/lib/c++ -Wl,-rpath,/usr/local/opt/llvm@16/lib/c++" \ cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=$(dirname $(which python3)) - name: Cache LLVM and Clang From f40bf6f885ca4472c5171a0e47e5f920d7e50118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Sat, 7 Oct 2023 01:20:50 +0200 Subject: [PATCH 38/53] porting to new FE API --- external/fe | 2 +- thorin/world.h | 35 +++++++++++++++++------------------ 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/external/fe b/external/fe index f0b6738a73..f376e3615f 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit f0b6738a73b41aeffff42b18b4df465c4c782390 +Subproject commit f376e3615f78dc0003063652954815265756c626 diff --git a/thorin/world.h b/thorin/world.h index 48b326c60b..c99fde2cfd 100644 --- a/thorin/world.h +++ b/thorin/world.h @@ -5,10 +5,9 @@ #include #include -#include - #include #include +#include #include "thorin/axiom.h" #include "thorin/check.h" @@ -17,9 +16,9 @@ #include "thorin/lattice.h" #include "thorin/tuple.h" +#include "thorin/util/dbg.h" #include "thorin/util/hash.h" #include "thorin/util/log.h" -#include "thorin/util/dbg.h" namespace thorin { class Driver; @@ -453,7 +452,8 @@ class World { /// @name Put into Sea of Nodes ///@{ template const T* unify(size_t num_ops, Args&&... args) { - auto def = allocate(num_ops, std::forward(args)...); + auto state = arena_.state(); + auto def = allocate(num_ops, std::forward(args)...); if (auto loc = emit_loc()) def->set(loc); assert(!def->isa_mut()); #ifdef THORIN_ENABLE_CHECKS @@ -463,13 +463,13 @@ class World { if (is_frozen()) { --state_.pod.curr_gid; auto i = move_.defs.find(def); - deallocate(def); + deallocate(state, def); if (i != move_.defs.end()) return static_cast(*i); return nullptr; } if (auto [i, ins] = move_.defs.emplace(def); !ins) { - deallocate(def); + deallocate(state, def); return static_cast(*i); } #ifdef THORIN_ENABLE_CHECKS @@ -479,6 +479,11 @@ class World { return def; } + template void deallocate(fe::Arena::State state, const T* ptr) { + ptr->~T(); + arena_.deallocate(state); + } + template T* insert(size_t num_ops, Args&&... args) { auto def = allocate(num_ops, std::forward(args)...); if (auto loc = emit_loc()) def->set(loc); @@ -504,26 +509,20 @@ class World { template T* allocate(size_t num_ops, Args&&... args) { static_assert(sizeof(Def) == sizeof(T), - "you are not allowed to introduce any additional data in subclasses of Def"); + "you are not allowed to introduce any additional data in subclasses of Def"); Lock lock; - auto ptr = arena_.allocate(num_bytes_of(num_ops)); - auto res = new (ptr) T(std::forward(args)...); + arena_.align(alignof(T)); + size_t num_bytes = sizeof(Def) + sizeof(void*) * num_ops; + auto ptr = arena_.allocate(num_bytes); + auto res = new (ptr) T(std::forward(args)...); assert(res->num_ops() == num_ops); return res; } - - template void deallocate(const T* def) { - size_t n = num_bytes_of(def->num_ops()); - def->~T(); - arena_.deallocate(n); - } - - template static constexpr size_t num_bytes_of(size_t num_ops) { return sizeof(Def) + sizeof(void*) * num_ops; } ///@} Driver* driver_; State state_; - fe::Arena<> arena_; + fe::Arena arena_; struct SeaHash { size_t operator()(const Def* def) const { return def->hash(); }; From 81fba8265090ee850083b903ab20c50e7181e546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 9 Oct 2023 02:03:57 +0200 Subject: [PATCH 39/53] porting to new API --- .../autodiff/auxiliary/autodiff_rewrite_inner.cpp | 8 ++++---- .../autodiff/auxiliary/autodiff_rewrite_toplevel.cpp | 2 +- dialects/clos/phase/clos_conv.cpp | 2 +- dialects/compile/pass/internal_cleanup.cpp | 2 +- dialects/core/be/ll.cpp | 2 +- dialects/direct/pass/ds2cps.cpp | 2 +- dialects/matrix/pass/lower_matrix_highlevel.cpp | 4 ++-- dialects/opt/opt.cpp | 6 +++--- external/fe | 2 +- thorin/be/dot/dot.cpp | 4 ++-- thorin/def.cpp | 6 +++--- thorin/driver.cpp | 4 ++-- thorin/driver.h | 2 +- thorin/dump.cpp | 2 +- thorin/fe/parser.cpp | 8 ++++---- thorin/lam.cpp | 4 ++-- thorin/pass/fp/eta_exp.cpp | 2 +- thorin/plugin.cpp | 2 +- thorin/util/dl.cpp | 12 ++++++------ thorin/util/dl.h | 4 ++-- thorin/world.cpp | 4 ++-- thorin/world.h | 2 +- 22 files changed, 43 insertions(+), 43 deletions(-) diff --git a/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp b/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp index d5e4781bce..11fd9016d3 100644 --- a/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp +++ b/dialects/autodiff/auxiliary/autodiff_rewrite_inner.cpp @@ -40,8 +40,8 @@ Ref AutoDiffEval::augment_lam(Lam* lam, Lam* f, Lam* f_diff) { } // TODO: better fix (another pass as analysis?) // TODO: handle open functions - if (Lam::isa_basicblock(lam) || lam->sym()->find("ret") != std::string::npos - || lam->sym()->find("_cont") != std::string::npos) { + if (Lam::isa_basicblock(lam) || lam->sym().view().find("ret") != std::string::npos + || lam->sym().view().find("_cont") != std::string::npos) { // A open continuation behaves the same as return: // ``` // cont: Cn[X] @@ -58,7 +58,7 @@ Ref AutoDiffEval::augment_lam(Lam* lam, Lam* f, Lam* f_diff) { world.DLOG("pb type is {}", pb_ty); auto aug_ty = world.cn({aug_dom, pb_ty}); world.DLOG("augmented type is {}", aug_ty); - auto aug_lam = world.mut_lam(aug_ty)->set("aug_"s + *lam->sym()); + auto aug_lam = world.mut_lam(aug_ty)->set("aug_"s + lam->sym().str()); auto aug_var = aug_lam->var((nat_t)0); augmented[lam->var()] = aug_var; augmented[lam] = aug_lam; // TODO: only one of these two @@ -361,7 +361,7 @@ Ref AutoDiffEval::augment_(Ref def, Lam* f, Lam* f_diff) { world.DLOG("Augment axiom: {} : {}", ax, ax->type()); world.DLOG("axiom curry: {}", ax->curry()); world.DLOG("axiom flags: {}", ax->flags()); - std::string diff_name = ax->sym(); + auto diff_name = ax->sym().str(); find_and_replace(diff_name, ".", "_"); find_and_replace(diff_name, "%", ""); diff_name = "internal_diff_" + diff_name; diff --git a/dialects/autodiff/auxiliary/autodiff_rewrite_toplevel.cpp b/dialects/autodiff/auxiliary/autodiff_rewrite_toplevel.cpp index 4f63bfcb67..f7d82a800c 100644 --- a/dialects/autodiff/auxiliary/autodiff_rewrite_toplevel.cpp +++ b/dialects/autodiff/auxiliary/autodiff_rewrite_toplevel.cpp @@ -9,7 +9,7 @@ Ref AutoDiffEval::derive_(Ref def) { auto lam = def->as_mut(); // TODO check if mutable world.DLOG("Derive lambda: {}", def); auto deriv_ty = autodiff_type_fun_pi(lam->type()); - auto deriv = world.mut_lam(deriv_ty)->set(*lam->sym() + "_deriv"); + auto deriv = world.mut_lam(deriv_ty)->set(lam->sym().str() + "_deriv"); // We first pre-register the derivatives. // This knowledge is needed for recursion. diff --git a/dialects/clos/phase/clos_conv.cpp b/dialects/clos/phase/clos_conv.cpp index 1b6c3992a3..77bfd1ea36 100644 --- a/dialects/clos/phase/clos_conv.cpp +++ b/dialects/clos/phase/clos_conv.cpp @@ -136,7 +136,7 @@ void ClosConv::rewrite_body(Lam* new_lam, Def2Def& subst) { } else { for (size_t i = 0; i < num_fvs; i++) { auto fv = env->op(i); - auto sym = w.sym("fv_"s + (fv->sym() ? *fv->sym() : std::to_string(i))); + auto sym = w.sym("fv_"s + (fv->sym() ? fv->sym().str() : std::to_string(i))); subst.emplace(fv, env_param->proj(i)->set(sym)); } } diff --git a/dialects/compile/pass/internal_cleanup.cpp b/dialects/compile/pass/internal_cleanup.cpp index beb9c44228..0af497a79f 100644 --- a/dialects/compile/pass/internal_cleanup.cpp +++ b/dialects/compile/pass/internal_cleanup.cpp @@ -8,7 +8,7 @@ namespace thorin::compile { void InternalCleanup::enter() { Lam* lam = curr_mut(); - if (lam->sym()->starts_with(prefix_)) { + if (lam->sym().view().starts_with(prefix_)) { lam->make_internal(); world().DLOG("internalized {}", lam); } diff --git a/dialects/core/be/ll.cpp b/dialects/core/be/ll.cpp index fe09493b94..f77064b70a 100644 --- a/dialects/core/be/ll.cpp +++ b/dialects/core/be/ll.cpp @@ -147,7 +147,7 @@ std::string Emitter::id(const Def* def, bool force_bb /*= false*/) const { if (auto lam = def->isa_mut(); lam && !force_bb) { if (lam->type()->ret_pi()) { if (lam->is_external() || !lam->is_set()) - return "@"s + *lam->sym(); // TODO or use is_internal or sth like that? + return "@"s + lam->sym().str(); // TODO or use is_internal or sth like that? return "@"s + lam->unique_name(); } } diff --git a/dialects/direct/pass/ds2cps.cpp b/dialects/direct/pass/ds2cps.cpp index 5c3aa26a74..44c51aa85b 100644 --- a/dialects/direct/pass/ds2cps.cpp +++ b/dialects/direct/pass/ds2cps.cpp @@ -65,7 +65,7 @@ Ref DS2CPS::rewrite_lam(Lam* lam) { auto cps_ty = world().cn(sigma); world().DLOG("cps type: {}", cps_ty); - auto cps_lam = world().mut_lam(cps_ty)->set(*lam->sym() + "_cps"); + auto cps_lam = world().mut_lam(cps_ty)->set(lam->sym().str() + "_cps"); // rewrite vars of new function // calls handled separately diff --git a/dialects/matrix/pass/lower_matrix_highlevel.cpp b/dialects/matrix/pass/lower_matrix_highlevel.cpp index 9b264b62e2..007e3f2348 100644 --- a/dialects/matrix/pass/lower_matrix_highlevel.cpp +++ b/dialects/matrix/pass/lower_matrix_highlevel.cpp @@ -15,8 +15,8 @@ namespace thorin::matrix { namespace { std::optional internal_function_of_axiom(const Axiom* axiom, Ref meta_args, Ref args) { - auto& world = axiom->world(); - std::string name = *axiom->sym(); + auto& world = axiom->world(); + auto name = axiom->sym().str(); find_and_replace(name, ".", "_"); find_and_replace(name, "%", ""); name = INTERNAL_PREFIX + name; diff --git a/dialects/opt/opt.cpp b/dialects/opt/opt.cpp index 33462b9c02..20c529fde4 100644 --- a/dialects/opt/opt.cpp +++ b/dialects/opt/opt.cpp @@ -22,10 +22,10 @@ extern "C" THORIN_EXPORT Plugin thorin_get_plugin() { auto else_phase = args[3]; auto name = plugin_axiom->sym(); // name has the form %opt.tag auto [_, tag, __] = Annex::split(world, name); // where tag = [plugin]_plugin - auto plugin = driver.sym(tag->substr(0, tag->find('_'))); // we want to extract the plugin - bool is_loaded = driver.is_loaded(plugin); + auto plugin = tag.view().substr(0, tag.view().find('_')); // we want to extract the plugin + bool is_loaded = driver.is_loaded(driver.sym(plugin)); - assert(tag->find('_') != std::string_view::npos && "plugin_phase: invalid plugin name"); + assert(tag.view().find('_') != std::string_view::npos && "plugin_phase: invalid plugin name"); world.DLOG("plugin_phase for: {}", plugin_axiom->sym()); world.DLOG("plugin: {}", plugin); world.DLOG("contained: {}", is_loaded); diff --git a/external/fe b/external/fe index f376e3615f..77fc14ccf2 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit f376e3615f78dc0003063652954815265756c626 +Subproject commit 77fc14ccf2f430998cdefd6c350808c9262b2fd5 diff --git a/thorin/be/dot/dot.cpp b/thorin/be/dot/dot.cpp index f01535b330..bdc7e6de7c 100644 --- a/thorin/be/dot/dot.cpp +++ b/thorin/be/dot/dot.cpp @@ -82,7 +82,7 @@ void Emitter::emit_epilogue(Lam* lam) { } std::string Emitter::emit_bb(BB&, const Def* def) { - if (auto lam = def->isa()) return lam->sym(); + if (auto lam = def->isa()) return lam->sym().str(); print(ostream_, "\"{}:{}\" [label=\"", def->node_name(), def->unique_name()); stream_def_(ostream_, def); @@ -104,7 +104,7 @@ std::string Emitter::prepare(const Scope& scope) { emit_cluster_start(ostream_, lam); - return lam->sym(); + return lam->sym().str(); } void Emitter::finalize(const Scope&) { ostream_ << "}\n"; } diff --git a/thorin/def.cpp b/thorin/def.cpp index 831749d7bd..8fe853cf40 100644 --- a/thorin/def.cpp +++ b/thorin/def.cpp @@ -260,12 +260,12 @@ Defs Def::extended_ops() const { #ifndef NDEBUG const Def* Def::debug_prefix(std::string prefix) const { - dbg_.sym = world().sym(prefix + *sym()); + dbg_.sym = world().sym(prefix + sym().str()); return this; } const Def* Def::debug_suffix(std::string suffix) const { - dbg_.sym = world().sym(*sym() + suffix); + dbg_.sym = world().sym(sym().str() + suffix); return this; } #endif @@ -413,7 +413,7 @@ bool Def::is_set() const { void Def::make_external() { return world().make_external(this); } void Def::make_internal() { return world().make_internal(this); } -std::string Def::unique_name() const { return *sym() + "_"s + std::to_string(gid()); } +std::string Def::unique_name() const { return sym().str() + "_"s + std::to_string(gid()); } nat_t Def::num_tprojs() const { if (auto a = isa_lit_arity(); a && *a < world().flags().scalerize_threshold) return *a; diff --git a/thorin/driver.cpp b/thorin/driver.cpp index 813e3b80df..fc8254c920 100644 --- a/thorin/driver.cpp +++ b/thorin/driver.cpp @@ -59,7 +59,7 @@ void Driver::load(Sym name) { } Plugin::Handle handle{nullptr, dl::close}; - if (auto path = fs::path{*name}; path.is_absolute() && fs::is_regular_file(path)) handle.reset(dl::open(*name)); + if (auto path = fs::path{*name}; path.is_absolute() && fs::is_regular_file(path)) handle.reset(dl::open(name)); if (!handle) { for (const auto& path : search_paths()) { for (auto name_variants = get_plugin_name_variants(name); const auto& name_variant : name_variants) { @@ -67,7 +67,7 @@ void Driver::load(Sym name) { std::error_code ignore; if (bool reg_file = fs::is_regular_file(full_path, ignore); reg_file && !ignore) { auto path_str = full_path.string(); - if (handle.reset(dl::open(path_str)); handle) break; + if (handle.reset(dl::open(path_str.c_str())); handle) break; } } if (handle) break; diff --git a/thorin/driver.h b/thorin/driver.h index 2deeeab03e..b7d95d1edc 100644 --- a/thorin/driver.h +++ b/thorin/driver.h @@ -56,7 +56,7 @@ class Driver : public fe::SymPool { /// Otherwise, "name", "libthorin_name.so" (Linux, Mac), "thorin_name.dll" (Win) /// are searched for in Driver::search_paths(). void load(Sym name); - void load(std::string name) { return load(sym(std::move(name))); } + void load(const std::string& name) { return load(sym(name)); } bool is_loaded(Sym sym) const { return lookup(plugins_, sym); } ///@} diff --git a/thorin/dump.cpp b/thorin/dump.cpp index 55cafb1023..2d1aea43e4 100644 --- a/thorin/dump.cpp +++ b/thorin/dump.cpp @@ -30,7 +30,7 @@ Def* isa_decl(const Def* def) { } std::string id(const Def* def) { - if (def->is_external() || (!def->is_set() && def->isa())) return def->sym(); + if (def->is_external() || (!def->is_set() && def->isa())) return def->sym().str(); return def->unique_name(); } diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index e47e7985b2..6285997cc7 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -110,7 +110,7 @@ std::pair Parser::parse_name(std::string_view ctxt) { void Parser::register_annex(Dbg dbg, Ref def) { auto [plugin, tag, sub] = Annex::split(world(), dbg.sym); - auto name = world().sym("%"s + *plugin + "."s + *tag); + auto name = world().sym("%"s + plugin.str() + "."s + tag.str()); auto&& [annex, is_new] = driver().name2annex(name, plugin, tag, dbg.loc); plugin_t p = *Annex::mangle(plugin); tag_t t = annex.tag_id; @@ -659,7 +659,7 @@ std::unique_ptr Parser::parse_ptrn(Tag delim_l, std::string_view ctxt, Tok if (ahead().isa(Tag::D_paren_l) || ahead().isa(Tag::D_brckt_l)) return parse_tuple_ptrn(track, rebind, sym); else - syntax_err("tuple pattern after '" + *sym + "::'", ctxt); + syntax_err("tuple pattern after '" + sym.str() + "::'", ctxt); } else if (ahead(1).isa(Tag::T_colon)) { // p -> s: e b -> s: e // p -> 's: e b -> 's: e @@ -844,12 +844,12 @@ void Parser::parse_ax_decl() { scopes_.bind(dbg, axiom); } else { for (const auto& sub : new_subs) { - auto name = world().sym(*dbg.sym + "."s + *sub.front()); + auto name = world().sym(dbg.sym.str() + "."s + sub.front().str()); auto norm = driver().normalizer(p, t, s); auto axiom = world().axiom(norm, curry, trip, type, p, t, s)->set(track.loc(), name); world().register_annex(p | (flags_t(t) << 8_u64) | flags_t(s), axiom); for (auto& alias : sub) { - auto sym = world().sym(*dbg.sym + "."s + *alias); + auto sym = world().sym(dbg.sym.str() + "."s + alias.str()); scopes_.bind({prev_, sym}, axiom); } ++s; diff --git a/thorin/lam.cpp b/thorin/lam.cpp index 492f898ce0..a4c61967b0 100644 --- a/thorin/lam.cpp +++ b/thorin/lam.cpp @@ -75,8 +75,8 @@ const Def* compose_cn(const Def* f, const Def* g) { auto H = world.cn({A, world.cn(C)}); auto Hcont = world.cn(B); - auto h = world.mut_lam(H)->set("comp_"s + *f->sym() + "_"s + *g->sym()); - auto hcont = world.mut_lam(Hcont)->set("comp_"s + *f->sym() + "_"s + *g->sym() + "_cont"s); + auto h = world.mut_lam(H)->set("comp_"s + f->sym().str() + "_"s + g->sym().str()); + auto hcont = world.mut_lam(Hcont)->set("comp_"s + f->sym().str() + "_"s + g->sym().str() + "_cont"s); h->app(true, g, {h->var((nat_t)0), hcont}); diff --git a/thorin/pass/fp/eta_exp.cpp b/thorin/pass/fp/eta_exp.cpp index f86be61a30..8b84680fd4 100644 --- a/thorin/pass/fp/eta_exp.cpp +++ b/thorin/pass/fp/eta_exp.cpp @@ -42,7 +42,7 @@ Ref EtaExp::rewrite(Ref def) { Lam* EtaExp::eta_exp(Lam* lam) { auto exp = lam->stub(world(), lam->type()); exp2orig_.emplace(exp, lam); - exp->debug_suffix("eta_"s + *lam->sym()); + exp->debug_suffix("eta_"s + lam->sym().str()); exp->app(false, lam, exp->var()); if (eta_red_) eta_red_->mark_irreducible(exp); return exp; diff --git a/thorin/plugin.cpp b/thorin/plugin.cpp index 27f5398f03..152719284f 100644 --- a/thorin/plugin.cpp +++ b/thorin/plugin.cpp @@ -7,7 +7,7 @@ using namespace std::literals; namespace thorin { std::optional Annex::mangle(Sym s) { - auto n = s->size(); + auto n = s.size(); if (n > Max_Plugin_Size) return {}; u64 result = 0; diff --git a/thorin/util/dl.cpp b/thorin/util/dl.cpp index a7d0f5b2b4..05958c0ff0 100644 --- a/thorin/util/dl.cpp +++ b/thorin/util/dl.cpp @@ -22,9 +22,9 @@ std::string_view extension() { #endif } -void* open(const std::string& file) { +void* open(const char* file) { #ifdef _WIN32 - if (HMODULE handle = LoadLibraryA(file.c_str())) { + if (HMODULE handle = LoadLibraryA(file)) { return static_cast(handle); } else { error("could not load plugin '{}' due to error '{}'\n" @@ -32,7 +32,7 @@ void* open(const std::string& file) { file, GetLastError()); } #else - if (void* handle = dlopen(file.c_str(), RTLD_NOW)) + if (void* handle = dlopen(file, RTLD_NOW)) return handle; else if (auto err = dlerror()) error("could not load plugin '{}' due to error '{}'\n", file, err); @@ -41,9 +41,9 @@ void* open(const std::string& file) { #endif } -void* get(void* handle, const std::string& symbol) { +void* get(void* handle, const char* symbol) { #ifdef _WIN32 - if (auto addr = GetProcAddress(static_cast(handle), symbol.c_str())) { + if (auto addr = GetProcAddress(static_cast(handle), symbol)) { return reinterpret_cast(addr); } else { error("could not find symbol '{}' in plugin due to error '{}'\n" @@ -52,7 +52,7 @@ void* get(void* handle, const std::string& symbol) { } #else dlerror(); // clear error state - void* addr = dlsym(handle, symbol.c_str()); + void* addr = dlsym(handle, symbol); if (auto err = dlerror()) error("could not find symbol '{}' in plugin due to error '{}' \n", symbol, err); else diff --git a/thorin/util/dl.h b/thorin/util/dl.h index 6668ca235f..e963fa8cff 100644 --- a/thorin/util/dl.h +++ b/thorin/util/dl.h @@ -7,8 +7,8 @@ namespace thorin::dl { std::string_view extension(); ///< `".dll"` or `".so"` -void* open(const std::string& filename); -void* get(void* handle, const std::string& symbol_name); +void* open(const char* filename); +void* get(void* handle, const char* symbol_name); void close(void* handle); } // namespace thorin::dl diff --git a/thorin/world.cpp b/thorin/world.cpp index 5d296460da..543d55197f 100644 --- a/thorin/world.cpp +++ b/thorin/world.cpp @@ -86,7 +86,7 @@ Flags& World::flags() { return driver().flags(); } Sym World::sym(const char* s) { return driver().sym(s); } Sym World::sym(std::string_view s) { return driver().sym(s); } -Sym World::sym(std::string s) { return driver().sym(std::move(s)); } +Sym World::sym(const std::string& s) { return driver().sym(s); } const Def* World::register_annex(flags_t f, const Def* def) { auto plugin = Annex::demangle(*this, f); @@ -528,7 +528,7 @@ Ref World::test(Ref value, Ref probe, Ref match, Ref clash) { Ref World::singleton(Ref inner_type) { return unify(1, this->type<1>(), inner_type); } Sym World::append_suffix(Sym symbol, std::string suffix) { - auto name = *symbol; + auto name = symbol.str(); auto pos = name.find(suffix); if (pos != std::string::npos) { diff --git a/thorin/world.h b/thorin/world.h index c99fde2cfd..934dcc09bf 100644 --- a/thorin/world.h +++ b/thorin/world.h @@ -103,7 +103,7 @@ class World { ///@{ Sym sym(std::string_view); Sym sym(const char*); - Sym sym(std::string); + Sym sym(const std::string&); /// Appends a @p suffix or an increasing number if the suffix already exists. Sym append_suffix(Sym name, std::string suffix); ///@} From 498f650800d5a9f1a30d63a29ac750f055a72f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Mon, 9 Oct 2023 02:16:09 +0200 Subject: [PATCH 40/53] msvc fix --- external/fe | 2 +- thorin/dump.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/external/fe b/external/fe index 77fc14ccf2..709ded33bf 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 77fc14ccf2f430998cdefd6c350808c9262b2fd5 +Subproject commit 709ded33bf87c3ed11208813179591d576a354d1 diff --git a/thorin/dump.cpp b/thorin/dump.cpp index 2d1aea43e4..b4a479062a 100644 --- a/thorin/dump.cpp +++ b/thorin/dump.cpp @@ -407,7 +407,7 @@ void World::write(const char* file) { } void World::write() { - auto file = std::string(name()) + ".thorin"s; + auto file = name().str() + ".thorin"s; write(file.c_str()); } From 04193d990dadc96fd64f933a04a8b9f676feafa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 10 Oct 2023 13:59:05 +0200 Subject: [PATCH 41/53] bump --- external/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/fe b/external/fe index 709ded33bf..32fdb43feb 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 709ded33bf87c3ed11208813179591d576a354d1 +Subproject commit 32fdb43febe7375360e49ac4ea0eb00787f5fb61 From 1b8efd3c9b5b9910f4ab1ec749f9df84cdd9f13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Tue, 10 Oct 2023 23:47:33 +0200 Subject: [PATCH 42/53] bump --- external/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/fe b/external/fe index 32fdb43feb..552699527c 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 32fdb43febe7375360e49ac4ea0eb00787f5fb61 +Subproject commit 552699527cec63a02a923479da582f1a689a8703 From 9f9941cff997e42e23bf5272693d3781c0e08e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Wed, 11 Oct 2023 00:36:16 +0200 Subject: [PATCH 43/53] bump --- external/fe | 2 +- thorin/driver.cpp | 3 ++- thorin/fe/parser.cpp | 4 ++-- thorin/pass/optimize.cpp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/external/fe b/external/fe index 552699527c..5629088a8e 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 552699527cec63a02a923479da582f1a689a8703 +Subproject commit 5629088a8ef1cbb5c87a86ead4a5f11a7e48b10e diff --git a/thorin/driver.cpp b/thorin/driver.cpp index fc8254c920..30de829a16 100644 --- a/thorin/driver.cpp +++ b/thorin/driver.cpp @@ -59,7 +59,8 @@ void Driver::load(Sym name) { } Plugin::Handle handle{nullptr, dl::close}; - if (auto path = fs::path{*name}; path.is_absolute() && fs::is_regular_file(path)) handle.reset(dl::open(name)); + if (auto path = fs::path{name.view()}; path.is_absolute() && fs::is_regular_file(path)) + handle.reset(dl::open(name)); if (!handle) { for (const auto& path : search_paths()) { for (auto name_variants = get_plugin_name_variants(name); const auto& name_variant : name_variants) { diff --git a/thorin/fe/parser.cpp b/thorin/fe/parser.cpp index 6285997cc7..5c016205a8 100644 --- a/thorin/fe/parser.cpp +++ b/thorin/fe/parser.cpp @@ -82,14 +82,14 @@ void Parser::parse_import() { eat(Tag::K_import); auto name = expect(Tag::M_id, "import name"); expect(Tag::T_semicolon, "end of import"); - import(*name.sym()); + import(name.sym().view()); } void Parser::parse_plugin() { eat(Tag::K_plugin); auto name = expect(Tag::M_id, "plugin name"); expect(Tag::T_semicolon, "end of import"); - plugin(*name.sym()); + plugin(name.sym().view()); } Dbg Parser::parse_id(std::string_view ctxt) { diff --git a/thorin/pass/optimize.cpp b/thorin/pass/optimize.cpp index 9532739a96..019c627413 100644 --- a/thorin/pass/optimize.cpp +++ b/thorin/pass/optimize.cpp @@ -30,7 +30,7 @@ void optimize(World& world) { auto externals = world.externals(); // copy for (auto [_, def] : externals) { if (auto lam = def->isa(); lam && lam->num_doms() == 0) { - if (*lam->codom()->sym() == "%compile.Pipeline") { + if (lam->codom()->sym().view() == "%compile.Pipeline") { if (!compilation) compilation = lam; def->make_internal(); } From 6b93400266a075a689af9f1fc9c7dfd566f949be Mon Sep 17 00:00:00 2001 From: fodinabor <5982050+fodinabor@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:19:37 +0200 Subject: [PATCH 44/53] [CI] Test release-downloader for FileCheck --- .github/workflows/macos.yml | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f20a5f9d1a..14b99ea068 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -36,28 +36,13 @@ jobs: LDFLAGS="-L/usr/local/opt/llvm@16/lib/c++ -Wl,-rpath,/usr/local/opt/llvm@16/lib/c++" \ cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build-type}} -DBUILD_TESTING=ON -DTHORIN_BUILD_EXAMPLES=ON -DPython3_ROOT_DIR=$(dirname $(which python3)) - - name: Cache LLVM and Clang - id: cache-llvm - uses: actions/cache@v3 - with: - path: | - ./llvm - key: llvm-14.0.0-mac - - - name: Install LLVM and Clang - uses: KyleMayes/install-llvm-action@v1.6.0 - with: - version: "14.0.0" - cached: ${{ steps.cache-llvm.outputs.cache-hit }} - - name: Install FileCheck - uses: i3h/download-release-asset@v1 + uses: robinraju/release-downloader@v1.8 with: - owner: fodinabor - repo: FileCheckBuild - tag: latest - file: FileCheck-x86_64-mac - path: ${{github.workspace}}/bin + repository: "fodinabor/FileCheckBuild" + latest: true + fileName: FileCheck-x86_64-mac + out-file-path:: bin token: ${{ secrets.GITHUB_TOKEN }} - name: Install LIT From 96f733a1c340336a2f18ecb9a29b77a579b54915 Mon Sep 17 00:00:00 2001 From: fodinabor <5982050+fodinabor@users.noreply.github.com> Date: Wed, 11 Oct 2023 15:26:18 +0200 Subject: [PATCH 45/53] [CI] fix syntax --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 14b99ea068..00aee451b7 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -42,7 +42,7 @@ jobs: repository: "fodinabor/FileCheckBuild" latest: true fileName: FileCheck-x86_64-mac - out-file-path:: bin + out-file-path: bin token: ${{ secrets.GITHUB_TOKEN }} - name: Install LIT From f53ac6c959b8ef9f2de6262cff378d849ff51a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Wed, 11 Oct 2023 20:54:30 +0200 Subject: [PATCH 46/53] does this make macos happy? --- thorin/check.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/thorin/check.cpp b/thorin/check.cpp index 51f90409cb..115e23c0a5 100644 --- a/thorin/check.cpp +++ b/thorin/check.cpp @@ -252,4 +252,9 @@ void Pi::check() { error(type(), "declared sort '{}' of function type does not match inferred one '{}'", type(), t); } +#ifndef DOXYGEN +template bool Check::alpha_(Ref, Ref); +template bool Check::alpha_(Ref, Ref); +#endif + } // namespace thorin From 8cdbd71e674c58897343dbe38800170c69fe117f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Wed, 11 Oct 2023 21:15:17 +0200 Subject: [PATCH 47/53] clang: compile fix --- dialects/math/normalizers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dialects/math/normalizers.cpp b/dialects/math/normalizers.cpp index 8926876f6f..3dc188fca8 100644 --- a/dialects/math/normalizers.cpp +++ b/dialects/math/normalizers.cpp @@ -1,5 +1,7 @@ #include +#include + #include "dialects/math/math.h" namespace thorin::math { From c34d4e816e3e043e838ab7d609f99bc464ced6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Wed, 11 Oct 2023 21:34:35 +0200 Subject: [PATCH 48/53] clang + isunordered + half: next try --- dialects/math/normalizers.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dialects/math/normalizers.cpp b/dialects/math/normalizers.cpp index 3dc188fca8..33e663d164 100644 --- a/dialects/math/normalizers.cpp +++ b/dialects/math/normalizers.cpp @@ -1,7 +1,5 @@ #include -#include - #include "dialects/math/math.h" namespace thorin::math { @@ -147,8 +145,9 @@ Res fold(u64 a, u64 b) { } else if constexpr (std::is_same_v) { return std::pow(a, b); } else if constexpr (std::is_same_v) { + using std::isunordered; bool res = false; - res |= ((id & cmp::u) != cmp::f) && std::isunordered(x, y); + res |= ((id & cmp::u) != cmp::f) && isunordered(x, y); res |= ((id & cmp::g) != cmp::f) && x > y; res |= ((id & cmp::l) != cmp::f) && x < y; res |= ((id & cmp::e) != cmp::f) && x == y; From 4431ae587019ed3a6197105bd9591d08c9a284b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Thu, 2 Nov 2023 10:58:51 +0100 Subject: [PATCH 49/53] adjust to new API --- gtest/automaton.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/gtest/automaton.cpp b/gtest/automaton.cpp index 3daf71d847..e55d63f36d 100644 --- a/gtest/automaton.cpp +++ b/gtest/automaton.cpp @@ -157,7 +157,7 @@ using namespace thorin; TEST(Automaton, Regex2NFA) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); for (auto plugin : {"compile", "mem", "core", "math", "regex"}) parser.plugin(plugin); auto pattern = w.call( @@ -170,7 +170,7 @@ TEST(Automaton, Regex2NFA) { TEST(Automaton, Regex2NFAAorBplusA) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); for (auto plugin : {"compile", "mem", "core", "math", "regex"}) parser.plugin(plugin); auto pattern = w.call( @@ -190,14 +190,15 @@ TEST(Automaton, Regex2NFAAorBplusA) { TEST(Automaton, Regex2NFA1or5or9) { Driver driver; World& w = driver.world(); - auto parser = fe::Parser(w); + auto parser = Parser(w); for (auto plugin : {"compile", "mem", "core", "math", "regex"}) parser.plugin(plugin); - // %regex.disj 2 (%regex.disj 2 (%regex.range ‹2; 49:(.Idx 256)›, %regex.range ‹2; 53:(.Idx 256)›), %regex.range ‹2; 57:(.Idx 256)›) - auto pattern = w.call( - 2, w.tuple({w.call( - 2, w.tuple({w.call(w.lit_idx(256, '1')), - w.call(w.lit_idx(256, '5'))})), w.call(w.lit_idx(256, '9'))})); // (a & b) + // %regex.disj 2 (%regex.disj 2 (%regex.range ‹2; 49:(.Idx 256)›, %regex.range ‹2; 53:(.Idx 256)›), %regex.range ‹2; + // 57:(.Idx 256)›) + auto pattern + = w.call(2, w.tuple({w.call(2, w.tuple({w.call(w.lit_idx(256, '1')), + w.call(w.lit_idx(256, '5'))})), + w.call(w.lit_idx(256, '9'))})); // (a & b) pattern->dump(10); auto nfa = regex::regex2nfa(pattern); std::cout << *nfa; From 61e647adab8e792aecc2d968533172d5e11ebb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Thu, 2 Nov 2023 18:39:33 +0100 Subject: [PATCH 50/53] gtest/regex: fix cmake dependency problem --- dialects/regex/regex.h | 4 ++-- gtest/CMakeLists.txt | 5 ++--- gtest/automaton.cpp | 1 - 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/dialects/regex/regex.h b/dialects/regex/regex.h index 2142fcd1fc..a39987be5c 100644 --- a/dialects/regex/regex.h +++ b/dialects/regex/regex.h @@ -1,9 +1,9 @@ #pragma once #include "dialects/regex/autogen.h" + namespace thorin { -template<> -struct Axiom::Match { +template<> struct Axiom::Match { using type = Axiom; }; } // namespace thorin diff --git a/gtest/CMakeLists.txt b/gtest/CMakeLists.txt index 2c62397e64..f2415dba17 100644 --- a/gtest/CMakeLists.txt +++ b/gtest/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(thorin-gtest target_link_libraries(thorin-gtest gtest_main libthorin) gtest_discover_tests (thorin-gtest TEST_PREFIX "thorin." DISCOVERY_TIMEOUT 60) -add_dependencies(thorin-gtest thorin_clos thorin_core thorin_compile thorin_math thorin_mem thorin_regex) +add_dependencies(thorin-gtest thorin_clos thorin_core thorin_compile thorin_math thorin_mem) target_include_directories(thorin-gtest PRIVATE ${CMAKE_BINARY_DIR}/include) add_executable(thorin-regex-gtest @@ -23,6 +23,5 @@ add_executable(thorin-regex-gtest target_link_libraries(thorin-regex-gtest gtest_main libthorin) gtest_discover_tests (thorin-regex-gtest TEST_PREFIX "thorin-regex-gtest." DISCOVERY_TIMEOUT 60) -add_dependencies(thorin-regex-gtest thorin_clos thorin_core thorin_compile thorin_math thorin_mem) +add_dependencies(thorin-regex-gtest thorin_clos thorin_core thorin_compile thorin_math thorin_mem thorin_regex) target_include_directories(thorin-regex-gtest PRIVATE ${CMAKE_BINARY_DIR}/include) - diff --git a/gtest/automaton.cpp b/gtest/automaton.cpp index e55d63f36d..08b7fbc1df 100644 --- a/gtest/automaton.cpp +++ b/gtest/automaton.cpp @@ -7,7 +7,6 @@ #include "thorin/fe/parser.h" -#include "dialects/regex/autogen.h" #include "dialects/regex/pass/dfa.h" #include "dialects/regex/pass/dfamin.h" #include "dialects/regex/pass/nfa.h" From 95ecefaf84bfdb46a34abfdaf477cdf96abdc07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Thu, 2 Nov 2023 19:02:09 +0100 Subject: [PATCH 51/53] FE:bump to v0.2.1 --- external/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/fe b/external/fe index 5629088a8e..2b545bfc2e 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 5629088a8ef1cbb5c87a86ead4a5f11a7e48b10e +Subproject commit 2b545bfc2e0feb98a6a4170322233bea76b4b49d From fbcbd616625d085718691f1299c74e9a9be5f571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 3 Nov 2023 21:51:42 +0100 Subject: [PATCH 52/53] use new API --- external/fe | 2 +- thorin/fe/lexer.cpp | 61 +++++++++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/external/fe b/external/fe index 2b545bfc2e..19daa85f3e 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 2b545bfc2e0feb98a6a4170322233bea76b4b49d +Subproject commit 19daa85f3e59b047d8781f9dee812ad8d73ba3c6 diff --git a/thorin/fe/lexer.cpp b/thorin/fe/lexer.cpp index edbbc89b90..3979423c07 100644 --- a/thorin/fe/lexer.cpp +++ b/thorin/fe/lexer.cpp @@ -6,10 +6,10 @@ using namespace std::literals; namespace thorin { -using Tag = Tok::Tag; +namespace utf8 = fe::utf8; +using Tag = Tok::Tag; namespace { -bool issign(char32_t i) { return i == '+' || i == '-'; } bool issubscsr(char32_t i) { return U'₀' <= i && i <= U'₉'; } } // namespace @@ -39,15 +39,11 @@ Tok Lexer::lex() { return *cache; } - begin(); + start(); -#if defined(_WIN32) && !defined(NDEBUG) // isspace asserts otherwise - if (accept_if([](int c) { return (c & ~0xFF) == 0 ? isspace(c) : false; })) continue; -#else - if (accept_if(isspace)) continue; -#endif - if (accept(0)) error(loc_, "invalid UTF-8 character"); - if (accept(fe::utf8::EoF)) return tok(Tag::EoF); + if (accept(utf8::EoF)) return tok(Tag::EoF); + if (accept_if(utf8::isspace)) continue; + if (accept(utf8::Null)) error(loc_, "invalid UTF-8 character"); // clang-format off // delimiters @@ -122,7 +118,7 @@ Tok Lexer::lex() { return {loc().anew_begin(), Tag::T_dot}; } - if (accept_if(isdigit)) { + if (accept_if(utf8::isdigit)) { parse_digits(); parse_exp(); return {loc_, f64(strtod(str_.c_str(), nullptr))}; @@ -149,7 +145,7 @@ Tok Lexer::lex() { return {loc, Tag::M_id, sym()}; } - if (isdigit(ahead()) || issign(ahead())) { + if (utf8::isdigit(ahead()) || utf8::any('+', '-')(ahead())) { if (auto lit = parse_lit()) return *lit; continue; } @@ -166,7 +162,7 @@ Tok Lexer::lex() { continue; } if (accept('/')) { - while (ahead() != fe::utf8::EoF && ahead() != '\n') next(); + while (ahead() != utf8::EoF && ahead() != '\n') next(); continue; } @@ -174,7 +170,7 @@ Tok Lexer::lex() { continue; } - error({loc_.path, peek_}, "invalid input char '{}'", (char)ahead()); + error({loc_.path, peek_}, "invalid input char '{}'", utf8::Char32(ahead())); next(); } } @@ -192,8 +188,8 @@ Loc Lexer::cache_trailing_dot() { } bool Lexer::lex_id() { - if (accept_if([](int i) { return i == '_' || isalpha(i); })) { - while (accept_if([](int i) { return i == '_' || i == '.' || isalnum(i); })) {} + if (accept_if([](char32_t c) { return c == '_' || utf8::isalpha(c); })) { + while (accept_if([](char32_t c) { return c == '_' || c == '.' || utf8::isalnum(c); })) {} return true; } return false; @@ -236,7 +232,7 @@ std::optional Lexer::parse_lit() { } else if (accept('_')) { auto i = strtoull(str_.c_str(), nullptr, 10); str_.clear(); - if (accept_if(isdigit)) { + if (accept_if(utf8::isdigit)) { parse_digits(10); auto m = strtoull(str_.c_str(), nullptr, 10); return Tok{loc_, world().lit_idx_mod(m, i)}; @@ -276,19 +272,24 @@ std::optional Lexer::parse_lit() { void Lexer::parse_digits(int base /*= 10*/) { switch (base) { - case 2: while (accept_if([](int i) { return '0' <= i && i <= '1'; })) {} break; - case 8: while (accept_if([](int i) { return '0' <= i && i <= '7'; })) {} break; - case 10: while (accept_if(isdigit)) {} break; - case 16: while (accept_if(isxdigit)) {} break; + // clang-format off + case 2: while (accept_if(utf8::isbdigit)) {} break; + case 8: while (accept_if(utf8::isodigit)) {} break; + case 10: while (accept_if(utf8::isdigit)) {} break; + case 16: while (accept_if(utf8::isxdigit)) {} break; + // clang-format on default: fe::unreachable(); } }; +template inline auto _any(T... args) { + return [=](char32_t c) { return utf8::any(c, args...); }; +} + bool Lexer::parse_exp(int base /*= 10*/) { - if (accept_if(base == 10 ? [](int i) { return i == 'e' || i == 'E'; } - : [](int i) { return i == 'p' || i == 'P'; })) { - accept_if(issign); - if (!isdigit(ahead())) error(loc_, "exponent has no digits"); + if (accept_if(base == 10 ? utf8::any('e', 'E') : utf8::any('p', 'P'))) { + accept_if(utf8::any('+', '-')); + if (!utf8::isdigit(ahead())) error(loc_, "exponent has no digits"); parse_digits(); return true; } @@ -317,14 +318,14 @@ char8_t Lexer::lex_char() { } auto c = next(); str_ += c; - if (isascii(c)) return c; + if (utf8::isascii(c)) return c; error(loc_, "invalid character '{}'", (char)c); } void Lexer::eat_comments() { while (true) { - while (ahead() != fe::utf8::EoF && ahead() != '*') next(); - if (accept(fe::utf8::EoF)) { + while (ahead() != utf8::EoF && ahead() != '*') next(); + if (accept(utf8::EoF)) { error(loc_, "non-terminated multiline comment"); return; } @@ -342,11 +343,11 @@ void Lexer::emit_md(bool start_of_file) { accept(' '); out_ = true; - while (ahead() != fe::utf8::EoF && ahead() != '\n') next(); + while (ahead() != utf8::EoF && ahead() != '\n') next(); accept('\n'); } while (start_md()); - if (ahead() == fe::utf8::EoF) + if (ahead() == utf8::EoF) out_ = false; else md_fence(); From af193ba1ccb6b62bed627685557179d805b13888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Fri, 3 Nov 2023 23:47:09 +0100 Subject: [PATCH 53/53] porting to new FE API + test case --- external/fe | 2 +- gtest/lexer.cpp | 5 ++++- thorin/fe/lexer.cpp | 33 +++++++++++++-------------------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/external/fe b/external/fe index 19daa85f3e..a3a403d57a 160000 --- a/external/fe +++ b/external/fe @@ -1 +1 @@ -Subproject commit 19daa85f3e59b047d8781f9dee812ad8d73ba3c6 +Subproject commit a3a403d57a8f215c98d4b462f6750b7de0aa4eee diff --git a/gtest/lexer.cpp b/gtest/lexer.cpp index 4ce268e9d4..5da63f5780 100644 --- a/gtest/lexer.cpp +++ b/gtest/lexer.cpp @@ -12,7 +12,7 @@ using namespace thorin; TEST(Lexer, Toks) { Driver driver; - std::istringstream is("{ } ( ) [ ] ‹ › « » : , . .lam .Pi λ Π"); + std::istringstream is("{ } ( ) [ ] ‹ › « » : , . .lam .Pi λ Π 23₀₁₂₃₄₅₆₇₈₉"); Lexer lexer(driver.world(), is); EXPECT_TRUE(lexer.lex().isa(Tok::Tag::D_brace_l)); @@ -32,7 +32,10 @@ TEST(Lexer, Toks) { EXPECT_TRUE(lexer.lex().isa(Tok::Tag::K_Pi)); EXPECT_TRUE(lexer.lex().isa(Tok::Tag::T_lm)); EXPECT_TRUE(lexer.lex().isa(Tok::Tag::T_Pi)); + auto tok = lexer.lex(); + EXPECT_TRUE(tok.isa(Tok::Tag::L_i)); EXPECT_TRUE(lexer.lex().isa(Tok::Tag::EoF)); + EXPECT_EQ(tok.lit_i(), driver.world().lit_idx(123456789, 23)); } TEST(Lexer, Errors) { diff --git a/thorin/fe/lexer.cpp b/thorin/fe/lexer.cpp index 3979423c07..224ecafb22 100644 --- a/thorin/fe/lexer.cpp +++ b/thorin/fe/lexer.cpp @@ -9,10 +9,6 @@ namespace thorin { namespace utf8 = fe::utf8; using Tag = Tok::Tag; -namespace { -bool issubscsr(char32_t i) { return U'₀' <= i && i <= U'₉'; } -} // namespace - Lexer::Lexer(World& world, std::istream& istream, const fs::path* path /*= nullptr*/, std::ostream* md /*= nullptr*/) : Super(istream, path) , world_(world) @@ -42,7 +38,7 @@ Tok Lexer::lex() { start(); if (accept(utf8::EoF)) return tok(Tag::EoF); - if (accept_if(utf8::isspace)) continue; + if (accept(utf8::isspace)) continue; if (accept(utf8::Null)) error(loc_, "invalid UTF-8 character"); // clang-format off @@ -118,7 +114,7 @@ Tok Lexer::lex() { return {loc().anew_begin(), Tag::T_dot}; } - if (accept_if(utf8::isdigit)) { + if (accept(utf8::isdigit)) { parse_digits(); parse_exp(); return {loc_, f64(strtod(str_.c_str(), nullptr))}; @@ -188,8 +184,8 @@ Loc Lexer::cache_trailing_dot() { } bool Lexer::lex_id() { - if (accept_if([](char32_t c) { return c == '_' || utf8::isalpha(c); })) { - while (accept_if([](char32_t c) { return c == '_' || c == '.' || utf8::isalnum(c); })) {} + if (accept([](char32_t c) { return c == '_' || utf8::isalpha(c); })) { + while (accept([](char32_t c) { return c == '_' || c == '.' || utf8::isalnum(c); })) {} return true; } return false; @@ -220,19 +216,16 @@ std::optional Lexer::parse_lit() { parse_digits(base); if (!sign && base == 10) { - if (issubscsr(ahead())) { + if (utf8::isrange(ahead(), U'₀', U'₉')) { auto i = strtoull(str_.c_str(), nullptr, 10); std::string mod; - while (issubscsr(ahead())) { - mod += ahead() - U'₀' + '0'; - next(); - } + while (utf8::isrange(ahead(), U'₀', U'₉')) mod += next() - U'₀' + '0'; auto m = strtoull(mod.c_str(), nullptr, 10); return Tok{loc_, world().lit_idx_mod(m, i)}; } else if (accept('_')) { auto i = strtoull(str_.c_str(), nullptr, 10); str_.clear(); - if (accept_if(utf8::isdigit)) { + if (accept(utf8::isdigit)) { parse_digits(10); auto m = strtoull(str_.c_str(), nullptr, 10); return Tok{loc_, world().lit_idx_mod(m, i)}; @@ -273,10 +266,10 @@ std::optional Lexer::parse_lit() { void Lexer::parse_digits(int base /*= 10*/) { switch (base) { // clang-format off - case 2: while (accept_if(utf8::isbdigit)) {} break; - case 8: while (accept_if(utf8::isodigit)) {} break; - case 10: while (accept_if(utf8::isdigit)) {} break; - case 16: while (accept_if(utf8::isxdigit)) {} break; + case 2: while (accept(utf8::isbdigit)) {} break; + case 8: while (accept(utf8::isodigit)) {} break; + case 10: while (accept(utf8::isdigit)) {} break; + case 16: while (accept(utf8::isxdigit)) {} break; // clang-format on default: fe::unreachable(); } @@ -287,8 +280,8 @@ template inline auto _any(T... args) { } bool Lexer::parse_exp(int base /*= 10*/) { - if (accept_if(base == 10 ? utf8::any('e', 'E') : utf8::any('p', 'P'))) { - accept_if(utf8::any('+', '-')); + if (accept(base == 10 ? utf8::any('e', 'E') : utf8::any('p', 'P'))) { + accept(utf8::any('+', '-')); if (!utf8::isdigit(ahead())) error(loc_, "exponent has no digits"); parse_digits(); return true;