diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a871a603b..50915f941 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -14,11 +14,11 @@ jobs: matrix: compiler: [ g++, clang++ ] configuration: [ Debug, Release ] - system: [ ubuntu-20.04, ubuntu-22.04 ] + system: [ ubuntu-22.04, ubuntu-24.04, macos-14 ] steps: - uses: actions/checkout@v3 - - run: ./script/setup.sh --all + - run: ./script/setup-${{ matrix.system }}.sh --all - run: cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.configuration }} - - run: cmake --build build --target develop + - run: cmake --build build --target continuous-integration - run: cmake -B example/build -S example -DCMAKE_BUILD_TYPE=${{ matrix.configuration }} - - run: cmake --build example/build --target develop + - run: cmake --build example/build --target continuous-integration diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 34a013e6a..b5f75c368 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -9,7 +9,7 @@ jobs: steps: - uses: actions/checkout@v3 - run: echo "VERSION=$(cat VERSION)" >> $GITHUB_ENV - - run: ./script/setup.sh + - run: ./script/setup-ubuntu.sh - run: cmake -B build -DCMAKE_BUILD_TYPE=Release - run: cmake --build build --target package - run: gh release create v${{ env.VERSION }} build/meevax_${{ env.VERSION }}_amd64.deb --title "Version ${{ env.VERSION }}" diff --git a/.gitignore b/.gitignore index ce0ee6f47..41995e26c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.DS_Store basis/src build document diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e92ccc68..205b4830f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,8 @@ -cmake_minimum_required(VERSION 3.16.3) # Ubuntu 20.04 LTS default +cmake_minimum_required(VERSION 3.22.1) # Ubuntu 22.04 LTS default execute_process( - COMMAND head -c -1 ${CMAKE_CURRENT_SOURCE_DIR}/VERSION + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/VERSION + COMMAND tr -d \n OUTPUT_VARIABLE CURRENT_VERSION) project(meevax @@ -12,44 +13,42 @@ project(meevax include(GNUInstallDirs) -string(JOIN " " ${PROJECT_NAME}_RELEASE_PLUS +string(JOIN " " ${PROJECT_NAME}_UNSTABLE_OPTIONS + # "-flto" # This optimization causes a problem in Apple Clang 15.0.0 where some static inline data members are no longer unique. It is unclear whether this is a code issue or a compiler issue. # "-fmerge-all-constants" # This optimization is very effective in reducing binary size, but non-standard to the C++ standard. # "-march=native" # This optimization causes "Illegal instruction" error (is Valgrind's bug) on CI. # "-mtune=native" ) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic -pipe") set(CMAKE_CXX_FLAGS_DEBUG "-Og -gdwarf-4") # NOTE: The `-gdwarf-4` option is set due to the following issues with Clang 14 and Valgrind versions below 3.20: https://bugzilla.mozilla.org/show_bug.cgi?id=1758782 set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") -set(CMAKE_CXX_FLAGS_RELEASE "-O3 -flto -DNDEBUG ${${PROJECT_NAME}_RELEASE_PLUS}") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG ${${PROJECT_NAME}_UNSTABLE_OPTIONS}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -gdwarf-4") -set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wpedantic -pipe") -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) set(CMAKE_VERBOSE_MAKEFILE OFF) -# ---- Configure --------------------------------------------------------------- - -include(TestBigEndian) - -TEST_BIG_ENDIAN(IS_BIG_ENDIAN) # Use CMAKE_CXX_BYTE_ORDER if CMake >= 3.20 - -if(${IS_BIG_ENDIAN}) - set(${PROJECT_NAME}_BYTE_ORDER "big-endian") -else() - set(${PROJECT_NAME}_BYTE_ORDER "little-endian") +if(CMAKE_SYSTEM_NAME STREQUAL Darwin) + set(CMAKE_INSTALL_RPATH "@executable_path/../${CMAKE_INSTALL_LIBDIR}") endif() +# ---- CONFIGURE --------------------------------------------------------------- + execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/script/unicode.sh --digit-value OUTPUT_VARIABLE ${PROJECT_NAME}_UNICODE_DIGIT_VALUE) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/script/unicode.sh --downcase OUTPUT_VARIABLE ${PROJECT_NAME}_UNICODE_DOWNCASE) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/script/unicode.sh --property OUTPUT_VARIABLE ${PROJECT_NAME}_UNICODE_PROPERTY) execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/script/unicode.sh --upcase OUTPUT_VARIABLE ${PROJECT_NAME}_UNICODE_UPCASE) execute_process( - COMMAND head -c -1 ${CMAKE_CURRENT_SOURCE_DIR}/configure/help.txt + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/configure/help.txt + COMMAND tr \n \r + COMMAND sed s/\r$// + COMMAND tr \r \n OUTPUT_VARIABLE ${PROJECT_NAME}_HELP) file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/include/${PROJECT_NAME}/unicode/digit_value.hpp "${${PROJECT_NAME}_UNICODE_DIGIT_VALUE}") @@ -63,7 +62,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure/Doxyfile ${CMAKE_CURRENT configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure/README.md ${CMAKE_CURRENT_SOURCE_DIR}/README.md) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/kernel/version.cpp) -# ---- Target basis ------------------------------------------------------------ +# ---- TARGET basis ------------------------------------------------------------ file(GLOB ${PROJECT_NAME}_BASIS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/basis/*.ss) @@ -90,7 +89,7 @@ set_target_properties(basis PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} LINK_FLAGS_RELEASE -s) -# ---- Target kernel ----------------------------------------------------------- +# ---- TARGET kernel ----------------------------------------------------------- add_library(kernel SHARED) @@ -100,7 +99,11 @@ target_sources(kernel PRIVATE ${${PROJECT_NAME}_KERNEL_SOURCES}) target_include_directories(kernel PUBLIC $ - PUBLIC $) + PUBLIC $ + PUBLIC $<$:/opt/homebrew/include>) + +target_link_directories(kernel + PUBLIC $<$:/opt/homebrew/lib>) target_link_libraries(kernel PRIVATE ${CMAKE_DL_LIBS} @@ -112,7 +115,7 @@ set_target_properties(kernel PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR} LINK_FLAGS_RELEASE -s) -# ---- Target shell ------------------------------------------------------------ +# ---- TARGET shell ------------------------------------------------------------ add_executable(shell) @@ -124,7 +127,7 @@ set_target_properties(shell PROPERTIES OUTPUT_NAME ${PROJECT_NAME} # Rename shell => meevax LINK_FLAGS_RELEASE -s) -# ---- CMake Package ----------------------------------------------------------- +# ---- TARGET install ---------------------------------------------------------- include(CMakePackageConfigHelpers) @@ -132,8 +135,6 @@ write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake COMPATIBILITY SameMajorVersion) -# ---- Target install ---------------------------------------------------------- - install( # /usr/lib/libmeevax TARGETS basis kernel EXPORT ${PROJECT_NAME}-config @@ -159,74 +160,73 @@ install( # /usr/share/meevax/meevax-config-version.cmake FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}) -# ---- Target package ---------------------------------------------------------- +# ---- TARGET uninstall -------------------------------------------------------- -set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Tatsuya Yamasaki") -set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) -set(CPACK_GENERATOR DEB) -set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) -set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) -set(CPACK_THREADS 0) +add_custom_target(uninstall + COMMAND sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME} + COMMAND sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} + COMMAND sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME}* + COMMAND sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}) -include(CPack) +# ---- TARGET package ---------------------------------------------------------- -# ---- Target test ------------------------------------------------------------- - -enable_testing() +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Tatsuya Yamasaki") + set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + set(CPACK_GENERATOR DEB) + set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE) + set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_SOURCE_DIR}/README.md) + include(CPack) +endif() -find_program(${PROJECT_NAME}_MEMORY_CHECK_COMMAND valgrind) +# ---- TARGET test ------------------------------------------------------------- -set(${PROJECT_NAME}_MEMORY_CHECK_OPTIONS - --error-exitcode=1 # = EXIT_FAILURE) - --leak-check=full - --quiet - --show-leak-kinds=all) +enable_testing() -file(GLOB ${PROJECT_NAME}_TEST_SS ${CMAKE_CURRENT_SOURCE_DIR}/test/*.ss) +find_program(${PROJECT_NAME}_VALGRIND valgrind) -foreach(EACH IN LISTS ${PROJECT_NAME}_TEST_SS) - get_filename_component(FILENAME ${EACH} NAME_WE) - add_test( - NAME ${FILENAME} - COMMAND ${${PROJECT_NAME}_MEMORY_CHECK_COMMAND} - ${${PROJECT_NAME}_MEMORY_CHECK_OPTIONS} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/meevax - ${EACH}) -endforeach() +if(${PROJECT_NAME}_VALGRIND STREQUAL ${PROJECT_NAME}_VALGRIND-NOTFOUND) + set(${PROJECT_NAME}_TEST "") +else() + set(${PROJECT_NAME}_TEST ${${PROJECT_NAME}_VALGRIND} --error-exitcode=1 --leak-check=full --quiet --show-leak-kinds=all) +endif() file(GLOB ${PROJECT_NAME}_TEST_CPP ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp) +file(GLOB ${PROJECT_NAME}_TEST_SH ${CMAKE_CURRENT_SOURCE_DIR}/test/*.sh) +file(GLOB ${PROJECT_NAME}_TEST_SS ${CMAKE_CURRENT_SOURCE_DIR}/test/*.ss) foreach(EACH IN LISTS ${PROJECT_NAME}_TEST_CPP) get_filename_component(FILENAME ${EACH} NAME_WE) add_executable(test_${FILENAME} ${EACH}) target_link_libraries(test_${FILENAME} PRIVATE basis kernel) target_compile_options(test_${FILENAME} PUBLIC -Wno-deprecated-declarations) - add_test( - NAME test/${FILENAME} - COMMAND ${${PROJECT_NAME}_MEMORY_CHECK_COMMAND} - ${${PROJECT_NAME}_MEMORY_CHECK_OPTIONS} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_${FILENAME}) + add_test(NAME test/${FILENAME} COMMAND ${${PROJECT_NAME}_TEST} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_${FILENAME}) endforeach() -file(GLOB ${PROJECT_NAME}_TEST_SH ${CMAKE_CURRENT_SOURCE_DIR}/test/*.sh) - foreach(EACH IN LISTS ${PROJECT_NAME}_TEST_SH) get_filename_component(FILENAME ${EACH} NAME_WE) - add_test( - NAME ${FILENAME} - COMMAND ${${PROJECT_NAME}_MEMORY_CHECK_COMMAND} - ${${PROJECT_NAME}_MEMORY_CHECK_OPTIONS} - ${EACH} - ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/meevax) + add_test(NAME ${FILENAME} COMMAND ${${PROJECT_NAME}_TEST} ${EACH} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/meevax) endforeach() -# ---- Additional Targets ------------------------------------------------------ +foreach(EACH IN LISTS ${PROJECT_NAME}_TEST_SS) + get_filename_component(FILENAME ${EACH} NAME_WE) + add_test(NAME ${FILENAME} COMMAND ${${PROJECT_NAME}_TEST} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/meevax ${EACH}) +endforeach() -execute_process(COMMAND nproc OUTPUT_VARIABLE ${PROJECT_NAME}_NPROC) +# ---- TARGET continuous-integration ------------------------------------------- -add_custom_target(develop - COMMAND ${CMAKE_MAKE_PROGRAM} -j${${PROJECT_NAME}_NPROC} - COMMAND ${CMAKE_MAKE_PROGRAM} test ARGS=-j${${PROJECT_NAME}_NPROC} - COMMAND ${CMAKE_MAKE_PROGRAM} package - COMMAND sudo dpkg -i ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_${PROJECT_VERSION}_amd64.deb) +if(CMAKE_SYSTEM_NAME STREQUAL Linux) + execute_process(COMMAND nproc OUTPUT_VARIABLE ${PROJECT_NAME}_NPROC) + add_custom_target(continuous-integration + COMMAND ${CMAKE_MAKE_PROGRAM} -j${${PROJECT_NAME}_NPROC} + COMMAND ${CMAKE_MAKE_PROGRAM} test ARGS=-j${${PROJECT_NAME}_NPROC} + COMMAND ${CMAKE_MAKE_PROGRAM} package + COMMAND sudo dpkg -i ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_${PROJECT_VERSION}_amd64.deb) +else() + execute_process(COMMAND sysctl -n hw.ncpu OUTPUT_VARIABLE ${PROJECT_NAME}_NCPU) + add_custom_target(continuous-integration + COMMAND ${CMAKE_MAKE_PROGRAM} -j${${PROJECT_NAME}_NCPU} + COMMAND ${CMAKE_MAKE_PROGRAM} test ARGS=-j${${PROJECT_NAME}_NCPU} + COMMAND sudo ${CMAKE_MAKE_PROGRAM} install) +endif() diff --git a/README.md b/README.md index 53b6ff623..0b928f1e9 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,6 @@ library is installed as a CMake package for [easy linking](./example/CMakeLists.txt), and [any C++ classes can be used from Lisp-1 scripts](./example/example.ss) [via simple stubs](example/example.cpp). -### Releases - -Latest release is [here](https://github.com/yamacir-kit/meevax/releases). - ### Features - Traditional SECD machine [[2](#Landin-1964)]. @@ -45,87 +41,68 @@ Procedures for each standard are provided by the following R7RS-style libraries: |:--------:|--------------| | R4RS | [`(scheme r4rs)`](./basis/r4rs.ss) | R5RS | [`(scheme r5rs)`](./basis/r5rs.ss) -| R7RS | [`(scheme base)`](./basis/r7rs.ss) [`(scheme box)`](./basis/r7rs.ss) [`(scheme case-lambda)`](./basis/r7rs.ss) [`(scheme char)`](./basis/r7rs.ss) [`(scheme complex)`](./basis/r7rs.ss) [`(scheme cxr)`](./basis/r7rs.ss) [`(scheme eval)`](./basis/r7rs.ss) [`(scheme file)`](./basis/r7rs.ss) [`(scheme inexact)`](./basis/r7rs.ss) [`(scheme lazy)`](./basis/r7rs.ss) [`(scheme list)`](./basis/r7rs.ss) [`(scheme load)`](./basis/r7rs.ss) [`(scheme process-context)`](./basis/r7rs.ss) [`(scheme read)`](./basis/r7rs.ss) [`(scheme repl)`](./basis/r7rs.ss) [`(scheme time)`](./basis/r7rs.ss) [`(scheme write)`](./basis/r7rs.ss) +| R7RS | [`(scheme base)`](./basis/r7rs.ss) [`(scheme box)`](./basis/r7rs.ss) [`(scheme case-lambda)`](./basis/r7rs.ss) [`(scheme char)`](./basis/r7rs.ss) [`(scheme complex)`](./basis/r7rs.ss) [`(scheme cxr)`](./basis/r7rs.ss) [`(scheme eval)`](./basis/r7rs.ss) [`(scheme file)`](./basis/r7rs.ss) [`(scheme flonum)`](./basis/r7rs.ss) [`(scheme inexact)`](./basis/r7rs.ss) [`(scheme lazy)`](./basis/r7rs.ss) [`(scheme list)`](./basis/r7rs.ss) [`(scheme load)`](./basis/r7rs.ss) [`(scheme process-context)`](./basis/r7rs.ss) [`(scheme read)`](./basis/r7rs.ss) [`(scheme repl)`](./basis/r7rs.ss) [`(scheme time)`](./basis/r7rs.ss) [`(scheme write)`](./basis/r7rs.ss) ### SRFIs -| Number | Title | Library name | Note | -|--------------------------------------------------------:|--------------------------------------------------------|-------------------------------------|------------------------------------| -| [ 0](https://srfi.schemers.org/srfi-0/srfi-0.html) | Feature-based conditional expansion construct | [`(srfi 0)`](./basis/srfi-0.ss) | R7RS 4.2.1 | -| [ 1](https://srfi.schemers.org/srfi-1/srfi-1.html) | List Library | [`(srfi 1)`](./basis/srfi-1.ss) | [`(scheme list)`](./basis/r7rs.ss) | -| [ 4](https://srfi.schemers.org/srfi-4/srfi-4.html) | Homogeneous numeric vector datatypes | [`(srfi 4)`](./basis/srfi-4.ss) | R7RS 6.9 | -| [ 6](https://srfi.schemers.org/srfi-6/srfi-6.html) | Basic String Ports | [`(srfi 6)`](./basis/srfi-6.ss) | R7RS 6.13 | -| [ 8](https://srfi.schemers.org/srfi-8/srfi-8.html) | receive: Binding to multiple values | [`(srfi 8)`](./basis/srfi-8.ss) | | -| [ 9](https://srfi.schemers.org/srfi-9/srfi-9.html) | Defining Record Types | [`(srfi 9)`](./basis/srfi-9.ss) | R7RS 5.5 | -| [ 10](https://srfi.schemers.org/srfi-10/srfi-10.html) | #, external form | | | -| [ 11](https://srfi.schemers.org/srfi-11/srfi-11.html) | Syntax for receiving multiple values | [`(srfi 11)`](./basis/srfi-11.ss) | R7RS 4.2.2 | -| [ 16](https://srfi.schemers.org/srfi-16/srfi-16.html) | Syntax for procedures of variable arity | [`(srfi 16)`](./basis/srfi-16.ss) | R7RS 4.2.9 | -| [ 23](https://srfi.schemers.org/srfi-23/srfi-23.html) | Error reporting mechanism | [`(srfi 23)`](./basis/srfi-23.ss) | R7RS 6.11 | -| [ 30](https://srfi.schemers.org/srfi-30/srfi-30.html) | Nested Multi-line Comments | | R7RS 2.2 | -| [ 31](https://srfi.schemers.org/srfi-31/srfi-31.html) | A special form rec for recursive evaluation | [`(srfi 31)`](./basis/srfi-31.ss) | | -| [ 34](https://srfi.schemers.org/srfi-34/srfi-34.html) | Exception Handling for Programs | [`(srfi 34)`](./basis/srfi-34.ss) | R7RS 6.11 | -| [ 38](https://srfi.schemers.org/srfi-38/srfi-38.html) | External Representation for Data With Shared Structure | [`(srfi 38)`](./basis/srfi-38.ss) | R7RS 6.13.3 | -| [ 39](https://srfi.schemers.org/srfi-39/srfi-39.html) | Parameter objects | [`(srfi 39)`](./basis/srfi-39.ss) | R7RS 4.2.6 | -| [ 45](https://srfi.schemers.org/srfi-45/srfi-45.html) | Primitives for Expressing Iterative Lazy Algorithms | [`(srfi 45)`](./basis/srfi-45.ss) | R7RS 4.2.5 | -| [ 62](https://srfi.schemers.org/srfi-62/srfi-62.html) | S-expression comments | | R7RS 2.2 | -| [ 78](https://srfi.schemers.org/srfi-78/srfi-78.html) | Lightweight testing | [`(srfi 78)`](./basis/srfi-78.ss) | Except `check-ec` | -| [ 87](https://srfi.schemers.org/srfi-87/srfi-87.html) | => in case clauses | | R7RS 4.2.1 | -| [ 98](https://srfi.schemers.org/srfi-98/srfi-98.html) | An interface to access environment variables | [`(srfi 98)`](./basis/srfi-98.ss) | R7RS 6.14 | -| [111](https://srfi.schemers.org/srfi-111/srfi-111.html) | Boxes | [`(srfi 111)`](./basis/srfi-111.ss) | [`(scheme box)`](./basis/r7rs.ss) | -| [149](https://srfi.schemers.org/srfi-149/srfi-149.html) | Basic syntax-rules template extensions | [`(srfi 149)`](./basis/srfi-149.ss) | R7RS 4.3.2 | +| Number | Title | Library name | Note | +|--------------------------------------------------------:|--------------------------------------------------------|-------------------------------------|--------------------------------------| +| [ 0](https://srfi.schemers.org/srfi-0/srfi-0.html) | Feature-based conditional expansion construct | [`(srfi 0)`](./basis/srfi-0.ss) | R7RS 4.2.1 | +| [ 1](https://srfi.schemers.org/srfi-1/srfi-1.html) | List Library | [`(srfi 1)`](./basis/srfi-1.ss) | [`(scheme list)`](./basis/r7rs.ss) | +| [ 4](https://srfi.schemers.org/srfi-4/srfi-4.html) | Homogeneous numeric vector datatypes | [`(srfi 4)`](./basis/srfi-4.ss) | R7RS 6.9 | +| [ 6](https://srfi.schemers.org/srfi-6/srfi-6.html) | Basic String Ports | [`(srfi 6)`](./basis/srfi-6.ss) | R7RS 6.13 | +| [ 8](https://srfi.schemers.org/srfi-8/srfi-8.html) | receive: Binding to multiple values | [`(srfi 8)`](./basis/srfi-8.ss) | | +| [ 9](https://srfi.schemers.org/srfi-9/srfi-9.html) | Defining Record Types | [`(srfi 9)`](./basis/srfi-9.ss) | R7RS 5.5 | +| [ 10](https://srfi.schemers.org/srfi-10/srfi-10.html) | #, external form | | | +| [ 11](https://srfi.schemers.org/srfi-11/srfi-11.html) | Syntax for receiving multiple values | [`(srfi 11)`](./basis/srfi-11.ss) | R7RS 4.2.2 | +| [ 16](https://srfi.schemers.org/srfi-16/srfi-16.html) | Syntax for procedures of variable arity | [`(srfi 16)`](./basis/srfi-16.ss) | R7RS 4.2.9 | +| [ 23](https://srfi.schemers.org/srfi-23/srfi-23.html) | Error reporting mechanism | [`(srfi 23)`](./basis/srfi-23.ss) | R7RS 6.11 | +| [ 30](https://srfi.schemers.org/srfi-30/srfi-30.html) | Nested Multi-line Comments | | R7RS 2.2 | +| [ 31](https://srfi.schemers.org/srfi-31/srfi-31.html) | A special form rec for recursive evaluation | [`(srfi 31)`](./basis/srfi-31.ss) | | +| [ 34](https://srfi.schemers.org/srfi-34/srfi-34.html) | Exception Handling for Programs | [`(srfi 34)`](./basis/srfi-34.ss) | R7RS 6.11 | +| [ 38](https://srfi.schemers.org/srfi-38/srfi-38.html) | External Representation for Data With Shared Structure | [`(srfi 38)`](./basis/srfi-38.ss) | R7RS 6.13.3 | +| [ 39](https://srfi.schemers.org/srfi-39/srfi-39.html) | Parameter objects | [`(srfi 39)`](./basis/srfi-39.ss) | R7RS 4.2.6 | +| [ 45](https://srfi.schemers.org/srfi-45/srfi-45.html) | Primitives for Expressing Iterative Lazy Algorithms | [`(srfi 45)`](./basis/srfi-45.ss) | R7RS 4.2.5 | +| [ 62](https://srfi.schemers.org/srfi-62/srfi-62.html) | S-expression comments | | R7RS 2.2 | +| [ 78](https://srfi.schemers.org/srfi-78/srfi-78.html) | Lightweight testing | [`(srfi 78)`](./basis/srfi-78.ss) | Except `check-ec` | +| [ 87](https://srfi.schemers.org/srfi-87/srfi-87.html) | => in case clauses | | R7RS 4.2.1 | +| [ 98](https://srfi.schemers.org/srfi-98/srfi-98.html) | An interface to access environment variables | [`(srfi 98)`](./basis/srfi-98.ss) | R7RS 6.14 | +| [111](https://srfi.schemers.org/srfi-111/srfi-111.html) | Boxes | [`(srfi 111)`](./basis/srfi-111.ss) | [`(scheme box)`](./basis/r7rs.ss) | +| [144](https://srfi.schemers.org/srfi-144/srfi-144.html) | Flonums | [`(srfi 144)`](./basis/srfi-144.ss) | [`(scheme flonum)`](./basis/r7rs.ss) | +| [149](https://srfi.schemers.org/srfi-149/srfi-149.html) | Basic syntax-rules template extensions | [`(srfi 149)`](./basis/srfi-149.ss) | R7RS 4.3.2 | ## Installation ### Requirements -- [GCC](https://gcc.gnu.org/) (>= 9.4.0) or [Clang](https://clang.llvm.org/) (>= 11.0.0) -- [CMake](https://cmake.org/) (>= 3.16.3) +- [GCC](https://gcc.gnu.org/) (>= 11.4.0) or [Clang](https://clang.llvm.org/) (>= 14.0.0) +- [CMake](https://cmake.org/) (>= 3.22.1) - [GNU Make](http://savannah.gnu.org/projects/make) - [GNU Binutils](https://www.gnu.org/software/binutils/) - [GNU Multiple Precision Arithmetic Library (GMP)](https://gmplib.org/) -### Install +### Releases -``` bash -cmake -B build -DCMAKE_BUILD_TYPE=Release -cd build -make package -sudo apt install build/meevax_0.5.223_amd64.deb -``` +Latest release is [here](https://github.com/yamacir-kit/meevax/releases). -or +### Instruction + +First, generate a Makefile using CMake with the following command: ``` bash cmake -B build -DCMAKE_BUILD_TYPE=Release cd build -make install -``` - -### Uninstall - -If you installed with `sudo apt install`, - -``` bash -sudo apt remove meevax -``` - -or if you installed with `make install`, - -``` bash -sudo rm -rf /usr/local/bin/meevax -sudo rm -rf /usr/local/include/meevax -sudo rm -rf /usr/local/lib/libmeevax* -sudo rm -rf /usr/local/share/meevax ``` -### CMake targets +Then, select one of the following targets and `make` it according to your purpose. In most cases, `make install` will be the one you choose. -| Target Name | Description +| Target | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.0.5.223.so` and executable `meevax` -| `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_0.5.223_amd64.deb` -| `install` | Copy files into `/usr/local` directly +| `all` | Build shared-library `libmeevax.0.5.304.so` and executable `meevax`. +| `install` | Copy files into `/usr/local` directly. +| `package` | Generate debian package `meevax_0.5.304_amd64.deb` (only Ubuntu). The generated package can be installed by `sudo apt install build/meevax_0.5.304_amd64.deb`. +| `test` | Test executable `meevax`. This target requires Valgrind to be installed. +| `uninstall` | Remove files copied to `/usr/local` directly by target `install`. ## Usage diff --git a/VERSION b/VERSION index f4db0830e..053f8ec38 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.5.223 +0.5.304 diff --git a/basis/meevax.ss b/basis/meevax.ss index 914877bf1..13ef11ac8 100644 --- a/basis/meevax.ss +++ b/basis/meevax.ss @@ -27,18 +27,18 @@ (define (er-macro-transformer f) (lambda (form use-env mac-env) - (define cache '()) - (f form - (lambda (x) - ((lambda (pare) - (if pare - (cdr pare) - (begin (set! cache (cons (cons x (make-syntactic-closure mac-env '() x)) - cache)) - (cdar cache)))) - (assq x cache))) - (lambda (x y) - (identifier=? use-env x use-env y))))))) + (define renames '()) + (define (rename x) + ((lambda (it) + (if it + (cdr it) + (begin (set! renames (cons (cons x (make-syntactic-closure mac-env '() x)) + renames)) + (cdar renames)))) + (assq x renames))) + (define (compare x y) + (identifier=? use-env x use-env y)) + (f form rename compare))))) (define-library (meevax continuation) (import (only (meevax context) emergency-exit) diff --git a/basis/r7rs.ss b/basis/r7rs.ss index 7b5d562d4..e0487b8ab 100644 --- a/basis/r7rs.ss +++ b/basis/r7rs.ss @@ -421,6 +421,28 @@ open-binary-input-file open-binary-output-file open-input-file open-output-file with-input-from-file with-output-to-file)) +(define-library (scheme flonum) + (import (srfi 144)) + (export fl-e fl-1/e fl-e-2 fl-e-pi/4 fl-log2-e fl-log10-e fl-log-2 fl-1/log-2 + fl-log-3 fl-log-pi fl-log-10 fl-1/log-10 fl-pi fl-1/pi fl-2pi fl-pi/2 + fl-pi/4 fl-pi-squared fl-degree fl-2/pi fl-2/sqrt-pi fl-sqrt-2 + fl-sqrt-3 fl-sqrt-5 fl-sqrt-10 fl-1/sqrt-2 fl-cbrt-2 fl-cbrt-3 + fl-4thrt-2 fl-phi fl-log-phi fl-1/log-phi fl-euler fl-e-euler + fl-sin-1 fl-cos-1 fl-gamma-1/2 fl-gamma-1/3 fl-gamma-2/3 fl-greatest + fl-least fl-epsilon fl-fast-fl+* fl-integer-exponent-zero + fl-integer-exponent-nan flonum fladjacent flcopysign make-flonum + flinteger-fraction flexponent flinteger-exponent + flnormalized-fraction-exponent flsign-bit flonum? fl=? fl? + fl<=? fl>=? flunordered? flinteger? flzero? flpositive? flnegative? + flodd? fleven? flfinite? flinfinite? flnan? flnormalized? + fldenormalized? flmax flmin fl+ fl* fl+* fl- fl/ flabs flabsdiff + flposdiff flsgn flnumerator fldenominator flfloor flceiling flround + fltruncate flexp flexp2 flexp-1 flsquare flsqrt flcbrt flhypot flexpt + fllog fllog1+ fllog2 fllog10 make-fllog-base flsin flcos fltan flasin + flacos flatan flsinh flcosh fltanh flasinh flacosh flatanh flquotient + flremainder flremquo flgamma flloggamma flfirst-bessel + flsecond-bessel flerf flerfc)) + (define-library (scheme inexact) (import (only (meevax inexact) finite? infinite? nan?) (only (scheme r5rs) exp log sin cos tan asin acos atan sqrt)) diff --git a/basis/srfi-144.ss b/basis/srfi-144.ss new file mode 100644 index 000000000..d137b821d --- /dev/null +++ b/basis/srfi-144.ss @@ -0,0 +1,325 @@ +(define-library (srfi 144) + (import (only (meevax binary64) + binary64-denormalized? binary64-epsilon binary64-exponent + binary64-fractional-part binary64-fused-multiply-add + binary64-greatest binary64-integer-log-binary + binary64-integral-part binary64-least binary64-log-binary + binary64-max binary64-min binary64-normalized-fraction + binary64-normalized? binary64-remquo binary64-sign-bit binary64?) + (only (meevax inexact) + acosh asinh atanh copysign cosh cyl_bessel_j cyl_neumann e erf erfc + euler expm1 fabs ldexp lgamma log1p nextafter phi pi sinh tanh + tgamma) + (only (scheme base) + * + - / < <= = > >= and car cdr ceiling cond-expand define + denominator even? expt floor if inexact integer? lambda let + negative? numerator odd? or positive? quotient remainder round + square truncate values zero?) + (only (scheme inexact) + acos asin atan cos exp finite? infinite? log nan? sin sqrt tan)) + + (export fl-e fl-1/e fl-e-2 fl-e-pi/4 fl-log2-e fl-log10-e fl-log-2 fl-1/log-2 + fl-log-3 fl-log-pi fl-log-10 fl-1/log-10 fl-pi fl-1/pi fl-2pi fl-pi/2 + fl-pi/4 fl-pi-squared fl-degree fl-2/pi fl-2/sqrt-pi fl-sqrt-2 + fl-sqrt-3 fl-sqrt-5 fl-sqrt-10 fl-1/sqrt-2 fl-cbrt-2 fl-cbrt-3 + fl-4thrt-2 fl-phi fl-log-phi fl-1/log-phi fl-euler fl-e-euler + fl-sin-1 fl-cos-1 fl-gamma-1/2 fl-gamma-1/3 fl-gamma-2/3 + + fl-greatest fl-least fl-epsilon fl-fast-fl+* fl-integer-exponent-zero + fl-integer-exponent-nan + + flonum fladjacent flcopysign make-flonum + + flinteger-fraction flexponent flinteger-exponent + flnormalized-fraction-exponent flsign-bit + + flonum? fl=? fl? fl<=? fl>=? flunordered? flinteger? flzero? + flpositive? flnegative? flodd? fleven? flfinite? flinfinite? flnan? + flnormalized? fldenormalized? + + flmax flmin fl+ fl* fl+* fl- fl/ flabs flabsdiff flposdiff flsgn + flnumerator fldenominator flfloor flceiling flround fltruncate + + flexp flexp2 flexp-1 flsquare flsqrt flcbrt flhypot flexpt fllog + fllog1+ fllog2 fllog10 make-fllog-base + + flsin flcos fltan flasin flacos flatan flsinh flcosh fltanh flasinh + flacosh flatanh + + flquotient flremainder flremquo + + flgamma flloggamma flfirst-bessel flsecond-bessel flerf flerfc) + + (begin (define fl-e e) + + (define fl-1/e (/ 1 e)) + + (define fl-e-2 7.38905609893065) ; (define fl-e-2 (expt e 2)) yields 1 ULP error + + (define fl-e-pi/4 (expt e (/ pi 4))) + + (define fl-log2-e (log e 2)) + + (define fl-log10-e 0.4342944819032518) ; (define fl-log10-e (log e 10)) yields 1 ULP error + + (define fl-log-2 (log 2)) + + (define fl-1/log-2 (/ 1 (log 2))) + + (define fl-log-3 (log 3)) + + (define fl-log-pi (log pi)) + + (define fl-log-10 (log 10)) + + (define fl-1/log-10 0.4342944819032518) ; (define fl-1/log-10 (/ 1 (log 10))) yields 1 ULP error + + (define fl-pi pi) + + (define fl-1/pi (/ 1 pi)) + + (define fl-2pi (* 2 pi)) + + (define fl-pi/2 (/ pi 2)) + + (define fl-pi/4 (/ pi 4)) + + (define fl-pi-squared (expt pi 2)) + + (define fl-degree (/ pi 180)) + + (define fl-2/pi (/ 2 pi)) + + (define fl-2/sqrt-pi (/ 2 (sqrt pi))) + + (define fl-sqrt-2 (sqrt 2)) + + (define fl-sqrt-3 (sqrt 3)) + + (define fl-sqrt-5 (sqrt 5)) + + (define fl-sqrt-10 (sqrt 10)) + + (define fl-1/sqrt-2 (/ 1 (sqrt 2))) + + (define fl-cbrt-2 (expt 2 (/ 1 3))) + + (define fl-cbrt-3 (expt 3 (/ 1 3))) + + (define fl-4thrt-2 (expt 2 (/ 1 4))) + + (define fl-phi phi) + + (define fl-log-phi (log phi)) + + (define fl-1/log-phi 2.07808692123502753) ; (define fl-1/log-phi (/ 1 fl-log-phi)) yields 1 ULP error + + (define fl-euler euler) + + (define fl-e-euler (expt e euler)) + + (define fl-sin-1 (sin 1)) + + (define fl-cos-1 (cos 1)) + + (define fl-gamma-1/2 (tgamma (/ 1 2))) + + (define fl-gamma-1/3 2.67893853470774763) ; (define fl-gamma-1/3 (tgamma (/ 1 3))) yields 1 ULP error + + (define fl-gamma-2/3 (tgamma (/ 2 3))) + + (define fl-greatest binary64-greatest) + + (define fl-least binary64-least) + + (define fl-epsilon binary64-epsilon) + + (define fl-fast-fl+* + (cond-expand + (FP_FAST_FMA #f) + (else #f))) + + (define fl-integer-exponent-zero (binary64-integer-log-binary 0.0)) + + (define fl-integer-exponent-nan (binary64-integer-log-binary +nan.0)) + + (define flonum inexact) + + (define fladjacent nextafter) + + (define flcopysign copysign) + + (define make-flonum ldexp) + + (define (flinteger-fraction x) + (values (binary64-integral-part x) + (binary64-fractional-part x))) + + (define flexponent binary64-log-binary) + + (define flinteger-exponent binary64-integer-log-binary) + + (define (flnormalized-fraction-exponent x) + (values (binary64-normalized-fraction x) + (binary64-exponent x))) + + (define (flsign-bit x) + (if (binary64-sign-bit x) 1 0)) + + (define flonum? binary64?) + + (define fl=? =) + + (define fl? >) + + (define fl<=? <=) + + (define fl>=? >=) + + (define (flunordered? x y) + (or (nan? x) + (nan? y))) + + (define (flinteger? x) + (and (binary64? x) + (integer? x))) + + (define flzero? zero?) + + (define flpositive? positive?) + + (define flnegative? negative?) + + (define flodd? odd?) + + (define fleven? even?) + + (define flfinite? finite?) + + (define flinfinite? infinite?) + + (define flnan? nan?) + + (define flnormalized? binary64-normalized?) + + (define fldenormalized? binary64-denormalized?) + + (define flmax binary64-max) + + (define flmin binary64-min) + + (define fl+ +) + + (define fl* *) + + (define fl+* binary64-fused-multiply-add) + + (define fl- -) + + (define fl/ /) + + (define flabs fabs) + + (define (flabsdiff x y) + (flabs (- x y))) + + (define (flposdiff x y) + (flmax (fl- x y) 0.0)) + + (define (flsgn x) + (flcopysign 1.0 x)) + + (define flnumerator numerator) + + (define fldenominator denominator) + + (define flfloor floor) + + (define flceiling ceiling) + + (define flround round) + + (define fltruncate truncate) + + (define flexp exp) + + (define (flexp2 x) + (expt 2 x)) + + (define flexp-1 expm1) + + (define flsquare square) + + (define flsqrt sqrt) + + (define (flcbrt x) + (expt x (/ 1 3))) + + (define (flhypot x y) + (sqrt (+ (square x) + (square y)))) + + (define flexpt expt) + + (define fllog log) + + (define fllog1+ log1p) + + (define (fllog2 x) + (log x 2)) + + (define (fllog10 x) + (log x 10)) + + (define (make-fllog-base b) + (lambda (x) + (log x b))) + + (define flsin sin) + + (define flcos cos) + + (define fltan tan) + + (define flasin asin) + + (define flacos acos) + + (define flatan atan) + + (define flsinh sinh) + + (define flcosh cosh) + + (define fltanh tanh) + + (define flasinh asinh) + + (define flacosh acosh) + + (define flatanh atanh) + + (define flquotient quotient) + + (define flremainder remainder) + + (define (flremquo x y) + (let ((rq (binary64-remquo x y))) + (values (car rq) + (cdr rq)))) + + (define flgamma tgamma) + + (define (flloggamma x) + (values (lgamma x) + (if (positive? (tgamma x)) 1.0 -1.0))) + + (define flfirst-bessel cyl_bessel_j) + + (define flsecond-bessel cyl_neumann) + + (define flerf erf) + + (define flerfc erfc))) diff --git a/configure/README.md b/configure/README.md index ecad4d688..43fc4ac48 100644 --- a/configure/README.md +++ b/configure/README.md @@ -15,10 +15,6 @@ library is installed as a CMake package for [easy linking](./example/CMakeLists.txt), and [any C++ classes can be used from Lisp-1 scripts](./example/example.ss) [via simple stubs](example/example.cpp). -### Releases - -Latest release is [here](https://github.com/yamacir-kit/meevax/releases). - ### Features - Traditional SECD machine [[2](#Landin-1964)]. @@ -45,87 +41,68 @@ Procedures for each standard are provided by the following R7RS-style libraries: |:--------:|--------------| | R4RS | [`(scheme r4rs)`](./basis/r4rs.ss) | R5RS | [`(scheme r5rs)`](./basis/r5rs.ss) -| R7RS | [`(scheme base)`](./basis/r7rs.ss) [`(scheme box)`](./basis/r7rs.ss) [`(scheme case-lambda)`](./basis/r7rs.ss) [`(scheme char)`](./basis/r7rs.ss) [`(scheme complex)`](./basis/r7rs.ss) [`(scheme cxr)`](./basis/r7rs.ss) [`(scheme eval)`](./basis/r7rs.ss) [`(scheme file)`](./basis/r7rs.ss) [`(scheme inexact)`](./basis/r7rs.ss) [`(scheme lazy)`](./basis/r7rs.ss) [`(scheme list)`](./basis/r7rs.ss) [`(scheme load)`](./basis/r7rs.ss) [`(scheme process-context)`](./basis/r7rs.ss) [`(scheme read)`](./basis/r7rs.ss) [`(scheme repl)`](./basis/r7rs.ss) [`(scheme time)`](./basis/r7rs.ss) [`(scheme write)`](./basis/r7rs.ss) +| R7RS | [`(scheme base)`](./basis/r7rs.ss) [`(scheme box)`](./basis/r7rs.ss) [`(scheme case-lambda)`](./basis/r7rs.ss) [`(scheme char)`](./basis/r7rs.ss) [`(scheme complex)`](./basis/r7rs.ss) [`(scheme cxr)`](./basis/r7rs.ss) [`(scheme eval)`](./basis/r7rs.ss) [`(scheme file)`](./basis/r7rs.ss) [`(scheme flonum)`](./basis/r7rs.ss) [`(scheme inexact)`](./basis/r7rs.ss) [`(scheme lazy)`](./basis/r7rs.ss) [`(scheme list)`](./basis/r7rs.ss) [`(scheme load)`](./basis/r7rs.ss) [`(scheme process-context)`](./basis/r7rs.ss) [`(scheme read)`](./basis/r7rs.ss) [`(scheme repl)`](./basis/r7rs.ss) [`(scheme time)`](./basis/r7rs.ss) [`(scheme write)`](./basis/r7rs.ss) ### SRFIs -| Number | Title | Library name | Note | -|--------------------------------------------------------:|--------------------------------------------------------|-------------------------------------|------------------------------------| -| [ 0](https://srfi.schemers.org/srfi-0/srfi-0.html) | Feature-based conditional expansion construct | [`(srfi 0)`](./basis/srfi-0.ss) | R7RS 4.2.1 | -| [ 1](https://srfi.schemers.org/srfi-1/srfi-1.html) | List Library | [`(srfi 1)`](./basis/srfi-1.ss) | [`(scheme list)`](./basis/r7rs.ss) | -| [ 4](https://srfi.schemers.org/srfi-4/srfi-4.html) | Homogeneous numeric vector datatypes | [`(srfi 4)`](./basis/srfi-4.ss) | R7RS 6.9 | -| [ 6](https://srfi.schemers.org/srfi-6/srfi-6.html) | Basic String Ports | [`(srfi 6)`](./basis/srfi-6.ss) | R7RS 6.13 | -| [ 8](https://srfi.schemers.org/srfi-8/srfi-8.html) | receive: Binding to multiple values | [`(srfi 8)`](./basis/srfi-8.ss) | | -| [ 9](https://srfi.schemers.org/srfi-9/srfi-9.html) | Defining Record Types | [`(srfi 9)`](./basis/srfi-9.ss) | R7RS 5.5 | -| [ 10](https://srfi.schemers.org/srfi-10/srfi-10.html) | #, external form | | | -| [ 11](https://srfi.schemers.org/srfi-11/srfi-11.html) | Syntax for receiving multiple values | [`(srfi 11)`](./basis/srfi-11.ss) | R7RS 4.2.2 | -| [ 16](https://srfi.schemers.org/srfi-16/srfi-16.html) | Syntax for procedures of variable arity | [`(srfi 16)`](./basis/srfi-16.ss) | R7RS 4.2.9 | -| [ 23](https://srfi.schemers.org/srfi-23/srfi-23.html) | Error reporting mechanism | [`(srfi 23)`](./basis/srfi-23.ss) | R7RS 6.11 | -| [ 30](https://srfi.schemers.org/srfi-30/srfi-30.html) | Nested Multi-line Comments | | R7RS 2.2 | -| [ 31](https://srfi.schemers.org/srfi-31/srfi-31.html) | A special form rec for recursive evaluation | [`(srfi 31)`](./basis/srfi-31.ss) | | -| [ 34](https://srfi.schemers.org/srfi-34/srfi-34.html) | Exception Handling for Programs | [`(srfi 34)`](./basis/srfi-34.ss) | R7RS 6.11 | -| [ 38](https://srfi.schemers.org/srfi-38/srfi-38.html) | External Representation for Data With Shared Structure | [`(srfi 38)`](./basis/srfi-38.ss) | R7RS 6.13.3 | -| [ 39](https://srfi.schemers.org/srfi-39/srfi-39.html) | Parameter objects | [`(srfi 39)`](./basis/srfi-39.ss) | R7RS 4.2.6 | -| [ 45](https://srfi.schemers.org/srfi-45/srfi-45.html) | Primitives for Expressing Iterative Lazy Algorithms | [`(srfi 45)`](./basis/srfi-45.ss) | R7RS 4.2.5 | -| [ 62](https://srfi.schemers.org/srfi-62/srfi-62.html) | S-expression comments | | R7RS 2.2 | -| [ 78](https://srfi.schemers.org/srfi-78/srfi-78.html) | Lightweight testing | [`(srfi 78)`](./basis/srfi-78.ss) | Except `check-ec` | -| [ 87](https://srfi.schemers.org/srfi-87/srfi-87.html) | => in case clauses | | R7RS 4.2.1 | -| [ 98](https://srfi.schemers.org/srfi-98/srfi-98.html) | An interface to access environment variables | [`(srfi 98)`](./basis/srfi-98.ss) | R7RS 6.14 | -| [111](https://srfi.schemers.org/srfi-111/srfi-111.html) | Boxes | [`(srfi 111)`](./basis/srfi-111.ss) | [`(scheme box)`](./basis/r7rs.ss) | -| [149](https://srfi.schemers.org/srfi-149/srfi-149.html) | Basic syntax-rules template extensions | [`(srfi 149)`](./basis/srfi-149.ss) | R7RS 4.3.2 | +| Number | Title | Library name | Note | +|--------------------------------------------------------:|--------------------------------------------------------|-------------------------------------|--------------------------------------| +| [ 0](https://srfi.schemers.org/srfi-0/srfi-0.html) | Feature-based conditional expansion construct | [`(srfi 0)`](./basis/srfi-0.ss) | R7RS 4.2.1 | +| [ 1](https://srfi.schemers.org/srfi-1/srfi-1.html) | List Library | [`(srfi 1)`](./basis/srfi-1.ss) | [`(scheme list)`](./basis/r7rs.ss) | +| [ 4](https://srfi.schemers.org/srfi-4/srfi-4.html) | Homogeneous numeric vector datatypes | [`(srfi 4)`](./basis/srfi-4.ss) | R7RS 6.9 | +| [ 6](https://srfi.schemers.org/srfi-6/srfi-6.html) | Basic String Ports | [`(srfi 6)`](./basis/srfi-6.ss) | R7RS 6.13 | +| [ 8](https://srfi.schemers.org/srfi-8/srfi-8.html) | receive: Binding to multiple values | [`(srfi 8)`](./basis/srfi-8.ss) | | +| [ 9](https://srfi.schemers.org/srfi-9/srfi-9.html) | Defining Record Types | [`(srfi 9)`](./basis/srfi-9.ss) | R7RS 5.5 | +| [ 10](https://srfi.schemers.org/srfi-10/srfi-10.html) | #, external form | | | +| [ 11](https://srfi.schemers.org/srfi-11/srfi-11.html) | Syntax for receiving multiple values | [`(srfi 11)`](./basis/srfi-11.ss) | R7RS 4.2.2 | +| [ 16](https://srfi.schemers.org/srfi-16/srfi-16.html) | Syntax for procedures of variable arity | [`(srfi 16)`](./basis/srfi-16.ss) | R7RS 4.2.9 | +| [ 23](https://srfi.schemers.org/srfi-23/srfi-23.html) | Error reporting mechanism | [`(srfi 23)`](./basis/srfi-23.ss) | R7RS 6.11 | +| [ 30](https://srfi.schemers.org/srfi-30/srfi-30.html) | Nested Multi-line Comments | | R7RS 2.2 | +| [ 31](https://srfi.schemers.org/srfi-31/srfi-31.html) | A special form rec for recursive evaluation | [`(srfi 31)`](./basis/srfi-31.ss) | | +| [ 34](https://srfi.schemers.org/srfi-34/srfi-34.html) | Exception Handling for Programs | [`(srfi 34)`](./basis/srfi-34.ss) | R7RS 6.11 | +| [ 38](https://srfi.schemers.org/srfi-38/srfi-38.html) | External Representation for Data With Shared Structure | [`(srfi 38)`](./basis/srfi-38.ss) | R7RS 6.13.3 | +| [ 39](https://srfi.schemers.org/srfi-39/srfi-39.html) | Parameter objects | [`(srfi 39)`](./basis/srfi-39.ss) | R7RS 4.2.6 | +| [ 45](https://srfi.schemers.org/srfi-45/srfi-45.html) | Primitives for Expressing Iterative Lazy Algorithms | [`(srfi 45)`](./basis/srfi-45.ss) | R7RS 4.2.5 | +| [ 62](https://srfi.schemers.org/srfi-62/srfi-62.html) | S-expression comments | | R7RS 2.2 | +| [ 78](https://srfi.schemers.org/srfi-78/srfi-78.html) | Lightweight testing | [`(srfi 78)`](./basis/srfi-78.ss) | Except `check-ec` | +| [ 87](https://srfi.schemers.org/srfi-87/srfi-87.html) | => in case clauses | | R7RS 4.2.1 | +| [ 98](https://srfi.schemers.org/srfi-98/srfi-98.html) | An interface to access environment variables | [`(srfi 98)`](./basis/srfi-98.ss) | R7RS 6.14 | +| [111](https://srfi.schemers.org/srfi-111/srfi-111.html) | Boxes | [`(srfi 111)`](./basis/srfi-111.ss) | [`(scheme box)`](./basis/r7rs.ss) | +| [144](https://srfi.schemers.org/srfi-144/srfi-144.html) | Flonums | [`(srfi 144)`](./basis/srfi-144.ss) | [`(scheme flonum)`](./basis/r7rs.ss) | +| [149](https://srfi.schemers.org/srfi-149/srfi-149.html) | Basic syntax-rules template extensions | [`(srfi 149)`](./basis/srfi-149.ss) | R7RS 4.3.2 | ## Installation ### Requirements -- [GCC](https://gcc.gnu.org/) (>= 9.4.0) or [Clang](https://clang.llvm.org/) (>= 11.0.0) +- [GCC](https://gcc.gnu.org/) (>= 11.4.0) or [Clang](https://clang.llvm.org/) (>= 14.0.0) - [CMake](https://cmake.org/) (>= ${CMAKE_MINIMUM_REQUIRED_VERSION}) - [GNU Make](http://savannah.gnu.org/projects/make) - [GNU Binutils](https://www.gnu.org/software/binutils/) - [GNU Multiple Precision Arithmetic Library (GMP)](https://gmplib.org/) -### Install +### Releases -``` bash -cmake -B build -DCMAKE_BUILD_TYPE=Release -cd build -make package -sudo apt install build/${PROJECT_NAME}_${PROJECT_VERSION}_amd64.deb -``` +Latest release is [here](https://github.com/yamacir-kit/meevax/releases). -or +### Instruction + +First, generate a Makefile using CMake with the following command: ``` bash cmake -B build -DCMAKE_BUILD_TYPE=Release cd build -make install -``` - -### Uninstall - -If you installed with `sudo apt install`, - -``` bash -sudo apt remove meevax -``` - -or if you installed with `make install`, - -``` bash -sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME} -sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} -sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME}* -sudo rm -rf ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME} ``` -### CMake targets +Then, select one of the following targets and `make` it according to your purpose. In most cases, `make install` will be the one you choose. -| Target Name | Description +| Target | Description |-------------|------------- -| `all` | Build shared-library `libmeevax.${PROJECT_VERSION}.so` and executable `meevax` -| `test` | Test executable `meevax` -| `package` | Generate debian package `meevax_${PROJECT_VERSION}_amd64.deb` -| `install` | Copy files into `${CMAKE_INSTALL_PREFIX}` directly +| `all` | Build shared-library `libmeevax.${PROJECT_VERSION}.so` and executable `meevax`. +| `install` | Copy files into `${CMAKE_INSTALL_PREFIX}` directly. +| `package` | Generate debian package `meevax_${PROJECT_VERSION}_amd64.deb` (only Ubuntu). The generated package can be installed by `sudo apt install build/${PROJECT_NAME}_${PROJECT_VERSION}_amd64.deb`. +| `test` | Test executable `meevax`. This target requires Valgrind to be installed. +| `uninstall` | Remove files copied to `${CMAKE_INSTALL_PREFIX}` directly by target `install`. ## Usage @@ -139,52 +116,28 @@ See [LICENSE](./LICENSE). ## References -[1] John McCarthy. -Recursive functions of symbolic expressions and their computation by machine, Part I. -Communications of the ACM, 3(4):184--195, 1960. +[1] John McCarthy. [Recursive functions of symbolic expressions and their computation by machine, Part I](https://dl.acm.org/doi/10.1145/367177.367199). *[Communications of the ACM](https://dl.acm.org/toc/cacm/1960/3/4)*, 3(4):184--195, 1960. -[2] Peter J. Landin. -The Mechanical Evaluation of Expressions. -The Computor Journal, 6(4):308--320, 1964. +[2] Peter J. Landin. [The Mechanical Evaluation of Expressions](https://academic.oup.com/comjnl/article/6/4/308/375725). *[The Computor Journal](https://academic.oup.com/comjnl/issue/6/4)*, 6(4):308--320, 1964. -[3] Peter Henderson. -Functional Programming: Application and Implementation. -Prentice Hall, 1980. +[3] Peter Henderson. *[Functional Programming: Application and Implementation](https://archive.org/details/functionalprogra0000hend/mode/2up)*. Prentice Hall, 1980. -[4] Alan Bawden and Jonathan Rees. -Syntactic Closures. -In LFP '88: Proceedings of the 1988 ACM Conference on LISP and Functional Programming, pages 86--95, 1988. +[4] Alan Bawden and Jonathan Rees. [Syntactic Closures](https://dl.acm.org/doi/10.1145/62678.62687). In *[LFP '88: Proceedings of the 1988 ACM Conference on LISP and Functional Programming](https://dl.acm.org/doi/proceedings/10.1145/62678)*, pages 86--95, 1988. -[5] William Clinger and Jonathan Rees (Editors). -Revised4 Report on the Algorithmic Language Scheme. -ACM SIGPLAN LISP Pointers, IV(3):1--55, 1991. +[5] William Clinger and Jonathan Rees (Editors). [Revised4 Report on the Algorithmic Language Scheme](https://dl.acm.org/doi/10.1145/382130.382133). *[ACM SIGPLAN LISP Pointers](https://dl.acm.org/toc/sigplan-lisppointers/1991/IV/3)*, IV(3):1--55, 1991. -[6] Chris Hanson. -A Syntactic Closures Macro Facility. -ACM SIGPLAN LISP Pointers, IV(4):9--16, 1991. +[6] Chris Hanson. [A Syntactic Closures Macro Facility](https://dl.acm.org/doi/10.1145/1317265.1317267). *[ACM SIGPLAN LISP Pointers](https://dl.acm.org/toc/sigplan-lisppointers/1991/IV/4)*, IV(4):9--16, 1991. -[7] William Clinger. -Hygienic Macros Through Explicit Renaming. -ACM SIGPLAN LISP Pointers, IV(4):25--28, 1991. +[7] William Clinger. [Hygienic Macros Through Explicit Renaming](https://dl.acm.org/doi/10.1145/1317265.1317269). *[ACM SIGPLAN LISP Pointers](https://dl.acm.org/toc/sigplan-lisppointers/1991/IV/4)*, IV(4):25--28, 1991. -[8] William Clinger and Jonathan Rees. -Macros That Work. -In POPL '91: Proceedings of the 18th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, pages 155--162, 1991. +[8] William Clinger and Jonathan Rees. [Macros That Work](https://dl.acm.org/doi/10.1145/99583.99607). In *[POPL '91: Proceedings of the 18th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages](https://dl.acm.org/doi/proceedings/10.1145/99583)*, pages 155--162, 1991. -[9] Rechard Kelsey, William Clinger, and Jonathan Rees (Editors). -Revised5 Report on the Algorithmic Language Scheme. -ACM SIGPLAN Notices, 33(9):26--76, 1998. +[9] Rechard Kelsey, William Clinger, and Jonathan Rees (Editors). [Revised5 Report on the Algorithmic Language Scheme](https://dl.acm.org/doi/10.1145/290229.290234). *[ACM SIGPLAN Notices](https://dl.acm.org/toc/sigplan/1998/33/9)*, 33(9):26--76, 1998. -[10] William E. Kempf. -A garbage collection framework for C++, 2001. +[10] William E. Kempf. [A garbage collection framework for C++](https://www.codeproject.com/Articles/912/A-garbage-collection-framework-for-C), 2001. -[11] William E. Kempf. -A garbage collection framework for C++ - Part II, 2001. +[11] William E. Kempf. [A garbage collection framework for C++ - Part II](https://www.codeproject.com/Articles/938/A-garbage-collection-framework-for-C-Part-II), 2001. -[12] Michael D. Adams and R. Kent Dybvig. -Efficient Nondestructive Equality Checking for Trees and Graphs. -In ICFP '08: Proceedings of the 13th ACM SIGPLAN International Conference on Functional Programming, pages 179--188, 2008. +[12] Michael D. Adams and R. Kent Dybvig. [Efficient Nondestructive Equality Checking for Trees and Graphs](https://dl.acm.org/doi/10.1145/1411204.1411230). In *[ICFP '08: Proceedings of the 13th ACM SIGPLAN International Conference on Functional Programming](https://dl.acm.org/doi/proceedings/10.1145/1411204)*, pages 179--188, 2008. -[13] Alex Shinn, John Cowan, and Arthur A. Gleckler (Editors). -Revised7 Report on the Algorithmic Language Scheme. -Technical report, http://www.scheme-reports.org/, 2013. +[13] Alex Shinn, John Cowan, and Arthur A. Gleckler (Editors). [Revised7 Report on the Algorithmic Language Scheme](https://standards.scheme.org/official/r7rs.pdf). Technical report, http://www.scheme-reports.org/, 2013. diff --git a/configure/basis.cpp b/configure/basis.cpp index 2dc0cd7b1..7b8ad54c0 100644 --- a/configure/basis.cpp +++ b/configure/basis.cpp @@ -42,6 +42,7 @@ namespace meevax R"##(${srfi-78.ss})##", R"##(${srfi-98.ss})##", R"##(${srfi-111.ss})##", + R"##(${srfi-144.ss})##", R"##(${srfi-149.ss})##", }; } diff --git a/configure/version.cpp b/configure/version.cpp index 732ec34ab..3c314a36d 100644 --- a/configure/version.cpp +++ b/configure/version.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto help() noexcept -> std::string_view { @@ -39,9 +37,18 @@ inline namespace kernel make_symbol("${${PROJECT_NAME}_SYSTEM_NAME}"), make_symbol("${CMAKE_SYSTEM_PROCESSOR}"), make_symbol(memory::model::name()), - make_symbol("${${PROJECT_NAME}_BYTE_ORDER}"), + make_symbol(std::endian::native == std::endian::little ? "little-endian" : "big-endian"), make_symbol("${PROJECT_NAME}"), - make_symbol("${PROJECT_NAME}-${PROJECT_VERSION}")); + make_symbol("${PROJECT_NAME}-${PROJECT_VERSION}") + + #ifdef FP_FAST_FMA + , make_symbol("FP_FAST_FMA") + #endif + + #if __cpp_lib_math_special_functions + , make_symbol("__cpp_lib_math_special_functions") + #endif + ); return features; } @@ -51,5 +58,4 @@ inline namespace kernel let static const version = make_symbol("${PROJECT_VERSION}"); return version; } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index ddfccd93a..c8c989f22 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,8 +1,8 @@ -cmake_minimum_required(VERSION 3.16.3) # Ubuntu 20.04 LTS default +cmake_minimum_required(VERSION 3.22.1) # Ubuntu 22.04 LTS default project(example VERSION 0.0.0 LANGUAGES CXX) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) find_package(Meevax REQUIRED) # NOTE: case-insensitive @@ -22,5 +22,6 @@ set_property( TEST ${PROJECT_NAME} PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${CMAKE_CURRENT_BINARY_DIR}") -add_custom_target(develop COMMAND ${CMAKE_MAKE_PROGRAM} - COMMAND ${CMAKE_CTEST_COMMAND}) +add_custom_target(continuous-integration + COMMAND ${CMAKE_MAKE_PROGRAM} + COMMAND ${CMAKE_CTEST_COMMAND}) diff --git a/example/example.ss b/example/example.ss index 334502007..9cde255fb 100644 --- a/example/example.ss +++ b/example/example.ss @@ -7,34 +7,32 @@ (display (get-environment-variable "LD_LIBRARY_PATH")) (newline) -; ------------------------------------------------------------------------------ +(define libexample + (cond-expand (darwin "libexample.dylib") + (linux "libexample.so"))) (define dummy-procedure - (procedure "libexample.so" 'dummy_procedure)) + (procedure libexample 'dummy_procedure)) (check (procedure? dummy-procedure) => #t) (check (dummy-procedure 'hoge 42 #(1 2 3) 3.14) => 43) -; ------------------------------------------------------------------------------ - (define argument-length - (procedure "libexample.so" 'argument_length)) + (procedure libexample 'argument_length)) (check (procedure? argument-length) => #t) (check (argument-length 'hoge 42 #(1 2 3) 3.14) => 4) -; ------------------------------------------------------------------------------ - (define make-hoge - (procedure "libexample.so" 'make_hoge)) + (procedure libexample 'make_hoge)) (define hoge? - (procedure "libexample.so" 'is_hoge)) + (procedure libexample 'is_hoge)) (define hoge-value - (procedure "libexample.so" 'hoge_value)) + (procedure libexample 'hoge_value)) (check (procedure? make-hoge) => #t) diff --git a/include/meevax/bit/bit_cast.hpp b/include/meevax/bit/bit_cast.hpp deleted file mode 100644 index 09f16f66d..000000000 --- a/include/meevax/bit/bit_cast.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright 2018-2024 Tatsuya Yamasaki. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#ifndef INCLUDED_MEEVAX_BIT_BIT_CAST_HPP -#define INCLUDED_MEEVAX_BIT_BIT_CAST_HPP - -#include -#include - -namespace meevax -{ -inline namespace bit -{ - template , - std::is_trivially_copyable, - std::is_trivially_copyable, - std::is_trivially_constructible>>> - auto bit_cast(From const& from) noexcept - { - To to; - std::memcpy(&to, &from, sizeof from); - return to; - } -} // namespace bit -} // namespace meevax - -#endif // INCLUDED_MEEVAX_BIT_BIT_CAST_HPP diff --git a/include/meevax/bit/log2.hpp b/include/meevax/bit/log2.hpp deleted file mode 100644 index c6de7be60..000000000 --- a/include/meevax/bit/log2.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - Copyright 2018-2024 Tatsuya Yamasaki. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#ifndef INCLUDED_MEEVAX_BIT_LOG2_HPP -#define INCLUDED_MEEVAX_BIT_LOG2_HPP - -namespace meevax -{ -inline namespace bit -{ - template - constexpr auto log2(T x) noexcept -> T - { - return (x < 2) ? 1 : log2(x / 2) + 1; - } - - static_assert(log2(0b0001) == 1); - static_assert(log2(0b0010) == 2); - static_assert(log2(0b0011) == 2); - static_assert(log2(0b0100) == 3); - static_assert(log2(0b0101) == 3); - static_assert(log2(0b0110) == 3); - static_assert(log2(0b0111) == 3); - static_assert(log2(0b1000) == 4); -} // namespace bit -} // namespace meevax - -#endif // INCLUDED_MEEVAX_BIT_LOG2_HPP diff --git a/include/meevax/bitset/simple_bitset.hpp b/include/meevax/bitset/simple_bitset.hpp index 9ea4f7aab..db469ec6a 100644 --- a/include/meevax/bitset/simple_bitset.hpp +++ b/include/meevax/bitset/simple_bitset.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace bitset +namespace meevax::inline bitset { template struct simple_bitset : public std::array @@ -46,7 +44,6 @@ inline namespace bitset return (*this)[i]; } }; -} // namespace bitset -} // namespace meevax +} // namespace meevax::bitset #endif // INCLUDED_MEEVAX_BITSET_SIMPLE_BITSET_HPP diff --git a/include/meevax/chrono/duration.hpp b/include/meevax/chrono/duration.hpp index 4b3999961..2856fcd0f 100644 --- a/include/meevax/chrono/duration.hpp +++ b/include/meevax/chrono/duration.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace chrono +namespace meevax::inline chrono { using days = std::chrono::duration, std::chrono::hours::period>>; @@ -39,7 +37,6 @@ inline namespace chrono } auto operator <<(std::ostream &, std::chrono::nanoseconds) -> std::ostream &; -} // namespace chrono -} // namespace meevax +} // namespace meevax::chrono #endif // INCLUDED_MEEVAX_CHRONO_DURATION_HPP diff --git a/include/meevax/functional/combinator.hpp b/include/meevax/functional/combinator.hpp index 9aeec4f31..f2e4c9867 100644 --- a/include/meevax/functional/combinator.hpp +++ b/include/meevax/functional/combinator.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace functional +namespace meevax::inline functional { inline auto i = [](auto&& x) constexpr { @@ -41,7 +39,6 @@ inline namespace functional return curry(std::forward(f)) (std::forward(f)); }; -} // namespace functional -} // namespace meevax +} // namespace meevax::functional #endif // INCLUDED_MEEVAX_FUNCTIONAL_COMBINATOR_HPP diff --git a/include/meevax/functional/compose.hpp b/include/meevax/functional/compose.hpp index ada1c2c94..7f3385428 100644 --- a/include/meevax/functional/compose.hpp +++ b/include/meevax/functional/compose.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace functional +namespace meevax::inline functional { inline auto compose = [](auto&& f, auto&& g) constexpr { @@ -31,7 +29,6 @@ inline namespace functional return std::get<0>(fs)(std::get<1>(fs)(std::forward(xs)...)); }; }; -} // namespace functional -} // namespace meevax +} // namespace meevax::functional #endif // INCLUDED_MEEVAX_FUNCTIONAL_COMPOSE_HPP diff --git a/include/meevax/functional/curry.hpp b/include/meevax/functional/curry.hpp index b659549ca..6f67e1696 100644 --- a/include/meevax/functional/curry.hpp +++ b/include/meevax/functional/curry.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace functional +namespace meevax::inline functional { template constexpr auto curry(F&& f) -> decltype(auto) @@ -39,7 +37,6 @@ inline namespace functional }; }; } -} // namespace functional -} // namespace meevax +} // namespace meevax::functional #endif // INCLUDED_MEEVAX_FUNCTIONAL_CURRY_HPP diff --git a/include/meevax/iostream/escape_sequence.hpp b/include/meevax/iostream/escape_sequence.hpp index 0c09990a3..73745b843 100644 --- a/include/meevax/iostream/escape_sequence.hpp +++ b/include/meevax/iostream/escape_sequence.hpp @@ -22,9 +22,7 @@ #include #include -namespace meevax -{ -inline namespace iostream +namespace meevax::inline iostream { template struct escape_sequence @@ -110,7 +108,6 @@ inline namespace iostream } #undef DEFINE -} // namespace iostream -} // namespace meevax +} // namespace meevax::iostream #endif // INCLUDED_MEEVAX_IOSTREAM_ESCAPE_SEQUENCE_HPP diff --git a/include/meevax/iostream/is_console.hpp b/include/meevax/iostream/is_console.hpp index 31e1a4d18..656c42098 100644 --- a/include/meevax/iostream/is_console.hpp +++ b/include/meevax/iostream/is_console.hpp @@ -21,9 +21,7 @@ #include -namespace meevax -{ -inline namespace iostream +namespace meevax::inline iostream { inline auto is_console = [](std::ostream & os) { @@ -42,7 +40,6 @@ inline namespace iostream return false; } }; -} // namespace iostream -} // namespace meevax +} // namespace meevax::iostream #endif // INCLUDED_MEEVAX_IOSTREAM_IS_CONSOLE_HPP diff --git a/include/meevax/iostream/lexical_cast.hpp b/include/meevax/iostream/lexical_cast.hpp index d59ada057..f4d555153 100644 --- a/include/meevax/iostream/lexical_cast.hpp +++ b/include/meevax/iostream/lexical_cast.hpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace iostream +namespace meevax::inline iostream { template auto lexical_cast(Ts&&... xs) -> To @@ -55,7 +53,6 @@ inline namespace iostream throw std::runtime_error(what.str()); } } -} // namespace iostream -} // namespace meevax +} // namespace meevax::iostream #endif // INCLUDED_MEEVAX_IOSTREAM_LEXICAL_CAST_HPP diff --git a/include/meevax/iterator/index_iterator.hpp b/include/meevax/iterator/index_iterator.hpp index b75bb3bbc..0e990e328 100644 --- a/include/meevax/iterator/index_iterator.hpp +++ b/include/meevax/iterator/index_iterator.hpp @@ -23,9 +23,7 @@ #include #include -namespace meevax -{ -inline namespace iterator +namespace meevax::inline iterator { template struct index_iterator @@ -111,7 +109,6 @@ inline namespace iterator return not (a == b); } }; -} // namespace iterator -} // namespace meevax +} // namespace meevax::iterator #endif // INCLUDED_MEEVAX_ITERATOR_INDEX_ITERATOR_HPP diff --git a/include/meevax/kernel/binary_input_file_port.hpp b/include/meevax/kernel/binary_input_file_port.hpp index c24896966..c7779d618 100644 --- a/include/meevax/kernel/binary_input_file_port.hpp +++ b/include/meevax/kernel/binary_input_file_port.hpp @@ -22,9 +22,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct binary_input_file_port : public binary_input_port { @@ -52,7 +50,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, binary_input_file_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BINARY_INPUT_FILE_PORT_HPP diff --git a/include/meevax/kernel/binary_input_port.hpp b/include/meevax/kernel/binary_input_port.hpp index 07c1a27ef..3ce8ef3dd 100644 --- a/include/meevax/kernel/binary_input_port.hpp +++ b/include/meevax/kernel/binary_input_port.hpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct binary_input_port : public virtual binary_port, public virtual input_port { @@ -35,7 +33,6 @@ inline namespace kernel virtual auto peek() -> object = 0; }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BINARY_INPUT_PORT_HPP diff --git a/include/meevax/kernel/binary_output_file_port.hpp b/include/meevax/kernel/binary_output_file_port.hpp index 89359b3f5..2b97819cb 100644 --- a/include/meevax/kernel/binary_output_file_port.hpp +++ b/include/meevax/kernel/binary_output_file_port.hpp @@ -22,9 +22,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct binary_output_file_port : public binary_output_port { @@ -50,7 +48,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, binary_output_file_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BINARY_OUTPUT_FILE_PORT_HPP diff --git a/include/meevax/kernel/binary_output_port.hpp b/include/meevax/kernel/binary_output_port.hpp index 475bc4303..aae143952 100644 --- a/include/meevax/kernel/binary_output_port.hpp +++ b/include/meevax/kernel/binary_output_port.hpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct binary_output_port : public virtual binary_port, public virtual output_port { @@ -31,7 +29,6 @@ inline namespace kernel virtual auto put(u8vector const&) -> void = 0; }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BINARY_OUTPUT_PORT_HPP diff --git a/include/meevax/kernel/binary_port.hpp b/include/meevax/kernel/binary_port.hpp index 9665a205a..779728a8c 100644 --- a/include/meevax/kernel/binary_port.hpp +++ b/include/meevax/kernel/binary_port.hpp @@ -19,13 +19,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct binary_port : public virtual port {}; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BINARY_PORT_HPP diff --git a/include/meevax/kernel/boolean.hpp b/include/meevax/kernel/boolean.hpp index 74db373a7..6d7e216da 100644 --- a/include/meevax/kernel/boolean.hpp +++ b/include/meevax/kernel/boolean.hpp @@ -19,14 +19,11 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { let extern const t; let extern const f; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BOOLEAN_HPP diff --git a/include/meevax/kernel/boot.hpp b/include/meevax/kernel/boot.hpp index d7eaa7781..5606aff7c 100644 --- a/include/meevax/kernel/boot.hpp +++ b/include/meevax/kernel/boot.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto boot() -> void; @@ -37,7 +35,6 @@ inline namespace kernel } } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BOOT_HPP diff --git a/include/meevax/kernel/box.hpp b/include/meevax/kernel/box.hpp index 92bcdc4fc..4a64d181b 100644 --- a/include/meevax/kernel/box.hpp +++ b/include/meevax/kernel/box.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct box : public virtual pair // (value . null) { @@ -29,7 +27,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, box const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_BOX_HPP diff --git a/include/meevax/kernel/character.hpp b/include/meevax/kernel/character.hpp index 7ab3721a7..df247632b 100644 --- a/include/meevax/kernel/character.hpp +++ b/include/meevax/kernel/character.hpp @@ -22,9 +22,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct character { @@ -212,7 +210,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, character const&) -> std::ostream &; // write -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_CHARACTER_HPP diff --git a/include/meevax/kernel/closure.hpp b/include/meevax/kernel/closure.hpp index 1fc2bec9d..f6e2af977 100644 --- a/include/meevax/kernel/closure.hpp +++ b/include/meevax/kernel/closure.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct closure : public virtual pair { @@ -29,7 +27,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, closure const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_CLOSURE_HPP diff --git a/include/meevax/kernel/comparator.hpp b/include/meevax/kernel/comparator.hpp index 314696b73..66c943ae4 100644 --- a/include/meevax/kernel/comparator.hpp +++ b/include/meevax/kernel/comparator.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { inline auto eq = [](auto const& x, auto const& y) constexpr { @@ -34,7 +32,6 @@ inline namespace kernel }; auto equal(object const&, object const&) -> bool; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_COMPARATOR_HPP diff --git a/include/meevax/kernel/complex.hpp b/include/meevax/kernel/complex.hpp index e3417550f..108681df1 100644 --- a/include/meevax/kernel/complex.hpp +++ b/include/meevax/kernel/complex.hpp @@ -21,9 +21,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct complex : public virtual pair // ( . ) { @@ -37,7 +35,9 @@ inline namespace kernel auto real() const noexcept -> object const&; - explicit operator std::complex(); + explicit operator std::complex() const; + + explicit operator std::complex() const; }; auto operator <<(std::ostream &, complex const&) -> std::ostream &; @@ -49,7 +49,6 @@ inline namespace kernel auto magnitude(object const&) -> object; auto angle(object const&) -> object; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_COMPLEX_HPP diff --git a/include/meevax/kernel/conditional_expand.hpp b/include/meevax/kernel/conditional_expand.hpp index b213e0e55..fc3f7cdc5 100644 --- a/include/meevax/kernel/conditional_expand.hpp +++ b/include/meevax/kernel/conditional_expand.hpp @@ -19,12 +19,9 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto conditional_expand(object const&) -> object; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_CONDITIONAL_EXPAND_HPP diff --git a/include/meevax/kernel/configurator.hpp b/include/meevax/kernel/configurator.hpp index 252456a71..4df2625cf 100644 --- a/include/meevax/kernel/configurator.hpp +++ b/include/meevax/kernel/configurator.hpp @@ -24,9 +24,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { template struct configurator @@ -82,7 +80,7 @@ inline namespace kernel option("(l|load)", [this](auto read) { - static_cast(*this).load(read().template as()); + static_cast(*this).load(static_cast(read().template as())); }), option("(v|version)", [](auto) @@ -158,7 +156,6 @@ inline namespace kernel } } }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_CONFIGURATOR_HPP diff --git a/include/meevax/kernel/continuation.hpp b/include/meevax/kernel/continuation.hpp index 2a5762c10..e487807e8 100644 --- a/include/meevax/kernel/continuation.hpp +++ b/include/meevax/kernel/continuation.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct continuation : public virtual pair { @@ -29,7 +27,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, continuation const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_CONTINUATION_HPP diff --git a/include/meevax/kernel/describable.hpp b/include/meevax/kernel/describable.hpp index 51ff4a923..f56d8d4dd 100644 --- a/include/meevax/kernel/describable.hpp +++ b/include/meevax/kernel/describable.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct describable { @@ -32,7 +30,6 @@ inline namespace kernel : name { std::forward(xs)... } {} }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_DESCRIBABLE_HPP diff --git a/include/meevax/kernel/dynamic_environment.hpp b/include/meevax/kernel/dynamic_environment.hpp index ce7018e20..2bd741a3b 100644 --- a/include/meevax/kernel/dynamic_environment.hpp +++ b/include/meevax/kernel/dynamic_environment.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct dynamic_environment { @@ -83,7 +81,6 @@ inline namespace kernel auto run() -> object; }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_DYNAMIC_ENVIRONMENT_HPP diff --git a/include/meevax/kernel/environment.hpp b/include/meevax/kernel/environment.hpp index ce348e912..b95aa5654 100644 --- a/include/meevax/kernel/environment.hpp +++ b/include/meevax/kernel/environment.hpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct environment : public configurator , public dynamic_environment @@ -35,7 +33,7 @@ inline namespace kernel auto import(object const&) -> void; - auto load(std::string const&) -> void; + auto load(std::filesystem::path const&) -> void; }; auto operator <<(std::ostream &, environment const&) -> std::ostream &; @@ -43,7 +41,6 @@ inline namespace kernel extern template struct configurator; extern template struct syntactic_environment; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_ENVIRONMENT_HPP diff --git a/include/meevax/kernel/eof.hpp b/include/meevax/kernel/eof.hpp index 76e17f29f..c77edda93 100644 --- a/include/meevax/kernel/eof.hpp +++ b/include/meevax/kernel/eof.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct eof {}; @@ -29,7 +27,6 @@ inline namespace kernel let extern const eof_object; auto operator <<(std::ostream &, eof const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_EOF_HPP diff --git a/include/meevax/kernel/error.hpp b/include/meevax/kernel/error.hpp index e4f0822f8..c9e1c2398 100644 --- a/include/meevax/kernel/error.hpp +++ b/include/meevax/kernel/error.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct error : public virtual pair // ( . ) , public std::exception @@ -120,7 +118,6 @@ inline namespace kernel return EXIT_FAILURE; } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_ERROR_HPP diff --git a/include/meevax/kernel/exact_integer.hpp b/include/meevax/kernel/exact_integer.hpp index 3d2dff835..e4f417185 100644 --- a/include/meevax/kernel/exact_integer.hpp +++ b/include/meevax/kernel/exact_integer.hpp @@ -19,11 +19,11 @@ #include +#include // std::strlen + #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct exact_integer { @@ -39,23 +39,22 @@ inline namespace kernel explicit exact_integer(mpz_t const) noexcept; - explicit exact_integer(std::int8_t); - - explicit exact_integer(std::int16_t); - - explicit exact_integer(std::int32_t); - - explicit exact_integer(std::int64_t); - - explicit exact_integer(std::uint8_t); - - explicit exact_integer(std::uint16_t); - - explicit exact_integer(std::uint32_t); - - explicit exact_integer(std::uint64_t); - - explicit exact_integer(double); + template >> + explicit exact_integer(T x) + { + if constexpr (std::is_floating_point_v) + { + mpz_init_set_d(value, x); + } + else if constexpr (std::is_signed_v) + { + mpz_init_set_si(value, x); + } + else + { + mpz_init_set_ui(value, x); + } + } explicit exact_integer(std::string const&, int = 0); @@ -67,49 +66,50 @@ inline namespace kernel explicit operator bool() const; - operator std::int8_t() const; - - operator std::int16_t() const; - - operator std::int32_t() const; - - operator std::int64_t() const; - - operator std::uint8_t() const; - - operator std::uint16_t() const; - - operator std::uint32_t() const; - - operator std::uint64_t() const; - - explicit operator float() const; - - explicit operator double() const; + template >> + operator T() const + { + if constexpr (std::is_floating_point_v) + { + return mpz_get_d(value); + } + else if constexpr (std::is_signed_v) + { + return mpz_get_si(value); + } + else + { + return mpz_get_ui(value); + } + } - auto square_root() const -> std::tuple; + auto sqrt() const -> std::tuple; }; - auto operator ==(exact_integer const&, int const) -> bool; - auto operator !=(exact_integer const&, int const) -> bool; - auto operator < (exact_integer const&, int const) -> bool; - auto operator <=(exact_integer const&, int const) -> bool; - auto operator > (exact_integer const&, int const) -> bool; - auto operator >=(exact_integer const&, int const) -> bool; - - auto operator ==(exact_integer const&, signed long const) -> bool; - auto operator !=(exact_integer const&, signed long const) -> bool; - auto operator < (exact_integer const&, signed long const) -> bool; - auto operator <=(exact_integer const&, signed long const) -> bool; - auto operator > (exact_integer const&, signed long const) -> bool; - auto operator >=(exact_integer const&, signed long const) -> bool; - - auto operator ==(exact_integer const&, unsigned long const) -> bool; - auto operator !=(exact_integer const&, unsigned long const) -> bool; - auto operator < (exact_integer const&, unsigned long const) -> bool; - auto operator <=(exact_integer const&, unsigned long const) -> bool; - auto operator > (exact_integer const&, unsigned long const) -> bool; - auto operator >=(exact_integer const&, unsigned long const) -> bool; + #define DEFINE_COMPARISON_OPERATOR(SYMBOL) \ + template >> \ + auto operator SYMBOL(exact_integer const& a, T b) \ + { \ + if constexpr (std::is_floating_point_v) \ + { \ + return mpz_cmp_d(a.value, b) SYMBOL 0; \ + } \ + else if constexpr (std::is_signed_v) \ + { \ + return mpz_cmp_si(a.value, b) SYMBOL 0; \ + } \ + else \ + { \ + return mpz_cmp_ui(a.value, b) SYMBOL 0; \ + } \ + } static_assert(true) + + DEFINE_COMPARISON_OPERATOR(==); + DEFINE_COMPARISON_OPERATOR(!=); + DEFINE_COMPARISON_OPERATOR(< ); + DEFINE_COMPARISON_OPERATOR(<=); + DEFINE_COMPARISON_OPERATOR(> ); + DEFINE_COMPARISON_OPERATOR(>=); auto operator <<(std::ostream &, exact_integer const&) -> std::ostream &; @@ -129,7 +129,6 @@ inline namespace kernel }; let extern const e0, e1; // Frequently used exact-integer values. -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_EXACT_INTEGER_HPP diff --git a/include/meevax/kernel/ghost.hpp b/include/meevax/kernel/ghost.hpp index ead7c2b4f..d7607b099 100644 --- a/include/meevax/kernel/ghost.hpp +++ b/include/meevax/kernel/ghost.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct ghost { @@ -33,7 +31,6 @@ inline namespace kernel let extern const unspecified; let extern const undefined; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_GHOST_HPP diff --git a/include/meevax/kernel/homogeneous_vector.hpp b/include/meevax/kernel/homogeneous_vector.hpp index 5b0822600..2ffc676c6 100644 --- a/include/meevax/kernel/homogeneous_vector.hpp +++ b/include/meevax/kernel/homogeneous_vector.hpp @@ -23,22 +23,23 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { template - struct homogeneous_vector + struct homogeneous_vector : private std::valarray { - std::valarray valarray; + using std::valarray::operator []; + using std::valarray::size; + using std::valarray::valarray; + using typename std::valarray::value_type; - homogeneous_vector() = default; + auto valarray() -> decltype(auto) { return static_cast &>(*this); } + auto valarray() const -> decltype(auto) { return static_cast const&>(*this); } - // list->@vector - explicit homogeneous_vector(object xs) - : valarray(length(xs)) + explicit homogeneous_vector(from_list_tag, let xs) + : std::valarray(length(xs)) { - std::generate(std::begin(valarray), std::end(valarray), [&]() mutable + std::generate(std::begin(*this), std::end(*this), [&]() mutable { let const x = car(xs); xs = cdr(xs); @@ -46,61 +47,20 @@ inline namespace kernel }); } - // make-@vector - explicit homogeneous_vector(std::size_t size, object const& x) - : valarray(input_cast(x), size) - {} - - // @vector-copy - explicit homogeneous_vector(homogeneous_vector const& v, std::size_t begin, std::size_t end) - : valarray(v.valarray[std::slice(begin, begin < end ? end - begin : 0, 1)]) - {} - - // @vector-copy - explicit homogeneous_vector(homogeneous_vector const& v, std::size_t begin = 0) - : homogeneous_vector { v, begin, v.valarray.size() } - {} - - // @vector-append - explicit homogeneous_vector(homogeneous_vector const& a, homogeneous_vector const& b) - : valarray(a.valarray.size() + b.valarray.size()) - { - slice(0, a.valarray.size()) = a.valarray; - slice(b.valarray.size(), valarray.size()) = b.valarray; - } - - // string->u8vector - explicit homogeneous_vector(T const* data, std::size_t size) - : valarray(data, size) - {} - - // get-output-u8vector - explicit homogeneous_vector(std::vector const& v) - : valarray(v.data(), v.size()) - {} - - template - explicit homogeneous_vector(Iterator begin, Iterator end) - : valarray(std::distance(begin, end)) - { - std::copy(begin, end, std::begin(valarray)); - } - - static auto tag() -> decltype(auto) + static auto tag() -> auto const& { - auto static const tag = lexical_cast(std::is_integral_v ? std::is_signed_v ? 's' : 'u' : 'f', sizeof(T) * CHAR_BIT); + auto static const tag = (std::is_integral_v ? std::is_signed_v ? "s" : "u" : "f") + std::to_string(sizeof(T) * CHAR_BIT); return tag; } - template + template > static auto input_cast(object const& x) -> T { - using Us = std::tuple; - - if constexpr (I < std::tuple_size_v) + if constexpr (I < std::tuple_size_v) { - using U = std::tuple_element_t; - return x.is() ? static_cast(x.as()) : input_cast(x); + using type_i = std::tuple_element_t; + + return x.is() ? static_cast(x.as()) : input_cast(x); } else { @@ -112,16 +72,6 @@ inline namespace kernel { return make, T, exact_integer>>(x); } - - auto slice(std::size_t begin, std::size_t end, std::size_t stride = 1) -> decltype(auto) - { - return valarray[std::slice(begin, end - begin, stride)]; - } - - auto slice(std::size_t begin = 0) -> decltype(auto) - { - return slice(begin, valarray.size()); - } }; template @@ -133,7 +83,7 @@ inline namespace kernel auto whitespace = ""; - for (auto const& value : datum.valarray) + for (auto value : datum.valarray()) { output << std::exchange(whitespace, " ") << cyan(homogeneous_vector::output_cast(value)); } @@ -149,7 +99,7 @@ inline namespace kernel return std::all_of(std::begin(xs), std::end(xs), [](auto x) { return x; }); }; - return check(a.valarray == b.valarray); + return check(a.valarray() == b.valarray()); } using s8vector = homogeneous_vector; @@ -171,7 +121,6 @@ inline namespace kernel using f32vector = homogeneous_vector; using f64vector = homogeneous_vector; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_HOMOGENEOUS_VECTOR_HPP diff --git a/include/meevax/kernel/identifier.hpp b/include/meevax/kernel/identifier.hpp index de36684f2..23eb63472 100644 --- a/include/meevax/kernel/identifier.hpp +++ b/include/meevax/kernel/identifier.hpp @@ -17,13 +17,10 @@ #ifndef INCLUDED_MEEVAX_KERNEL_IDENTIFIER_HPP #define INCLUDED_MEEVAX_KERNEL_IDENTIFIER_HPP -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct identifier {}; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_IDENTIFIER_HPP diff --git a/include/meevax/kernel/identity.hpp b/include/meevax/kernel/identity.hpp index eb144eaf4..ba4d23a82 100644 --- a/include/meevax/kernel/identity.hpp +++ b/include/meevax/kernel/identity.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct absolute : public virtual pair // ( . ) { @@ -49,7 +47,6 @@ inline namespace kernel { return false; // for free-identifier=? } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_IDENTITY_HPP diff --git a/include/meevax/kernel/include.hpp b/include/meevax/kernel/include.hpp index e0383d66c..0afdb9ad7 100644 --- a/include/meevax/kernel/include.hpp +++ b/include/meevax/kernel/include.hpp @@ -19,12 +19,9 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto include(object const&, bool = true, object const& = nullptr) -> object; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INCLUDE_HPP diff --git a/include/meevax/kernel/input_file_port.hpp b/include/meevax/kernel/input_file_port.hpp index 3150daed4..0526b03a9 100644 --- a/include/meevax/kernel/input_file_port.hpp +++ b/include/meevax/kernel/input_file_port.hpp @@ -21,9 +21,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct input_file_port : public textual_input_port { @@ -49,7 +47,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, input_file_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INPUT_FILE_PORT_HPP diff --git a/include/meevax/kernel/input_homogeneous_vector_port.hpp b/include/meevax/kernel/input_homogeneous_vector_port.hpp index d278932f9..99f0a0705 100644 --- a/include/meevax/kernel/input_homogeneous_vector_port.hpp +++ b/include/meevax/kernel/input_homogeneous_vector_port.hpp @@ -23,9 +23,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { template struct input_homogeneous_vector_port : public binary_input_port @@ -33,7 +31,7 @@ inline namespace kernel std::deque deque; explicit input_homogeneous_vector_port(homogeneous_vector const& v) - : deque(std::begin(v.valarray), std::end(v.valarray)) + : deque(std::begin(v.valarray()), std::end(v.valarray())) {} auto close() -> void override @@ -61,7 +59,8 @@ inline namespace kernel } else { - let const v = make>(deque.begin(), std::next(deque.begin(), size)); + let const v = make>(direct_initialization, size); + std::copy(deque.begin(), std::next(deque.begin(), size), std::begin(v.as>().valarray())); deque.erase(deque.begin(), std::next(deque.begin(), size)); return v; } @@ -97,7 +96,6 @@ inline namespace kernel } using input_u8vector_port = input_homogeneous_vector_port; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INPUT_HOMOGENEOUS_VECTOR_PORT_HPP diff --git a/include/meevax/kernel/input_port.hpp b/include/meevax/kernel/input_port.hpp index e6ffd6ea7..1e1bc8ee4 100644 --- a/include/meevax/kernel/input_port.hpp +++ b/include/meevax/kernel/input_port.hpp @@ -19,13 +19,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct input_port : public virtual port {}; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INPUT_PORT_HPP diff --git a/include/meevax/kernel/input_string_port.hpp b/include/meevax/kernel/input_string_port.hpp index 2cd6bd2cf..d97844ed6 100644 --- a/include/meevax/kernel/input_string_port.hpp +++ b/include/meevax/kernel/input_string_port.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct input_string_port : public textual_input_port { @@ -47,7 +45,6 @@ namespace literals { auto operator ""_r(char const*, std::size_t) -> object; } // namespace literals -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INPUT_STRING_PORT_HPP diff --git a/include/meevax/kernel/instruction.hpp b/include/meevax/kernel/instruction.hpp index 6847c5df4..cdf3c3659 100644 --- a/include/meevax/kernel/instruction.hpp +++ b/include/meevax/kernel/instruction.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { enum class instruction { @@ -51,7 +49,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, instruction const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INSTRUCTION_HPP diff --git a/include/meevax/kernel/interaction_environment.hpp b/include/meevax/kernel/interaction_environment.hpp index 4fc778b59..7da467b09 100644 --- a/include/meevax/kernel/interaction_environment.hpp +++ b/include/meevax/kernel/interaction_environment.hpp @@ -19,12 +19,9 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto interaction_environment() -> object const&; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_INTERACTION_ENVIRONMENT_HPP diff --git a/include/meevax/kernel/library.hpp b/include/meevax/kernel/library.hpp index 3721f4fb2..26380afa7 100644 --- a/include/meevax/kernel/library.hpp +++ b/include/meevax/kernel/library.hpp @@ -17,12 +17,12 @@ #ifndef INCLUDED_MEEVAX_KERNEL_LIBRARY_HPP #define INCLUDED_MEEVAX_KERNEL_LIBRARY_HPP +#include + #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct library : public environment { @@ -60,10 +60,6 @@ inline namespace kernel auto operator <<(std::ostream &, library const&) -> std::ostream &; - /* - In order to improve the usability of the help procedure, it is desirable - to sort by library name in lexicographical order. - */ auto libraries() -> std::map &; template @@ -78,7 +74,6 @@ inline namespace kernel return interaction_environment().as().define(name, std::forward(xs)...); } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_LIBRARY_HPP diff --git a/include/meevax/kernel/list.hpp b/include/meevax/kernel/list.hpp index 27cbb781a..2a92741a6 100644 --- a/include/meevax/kernel/list.hpp +++ b/include/meevax/kernel/list.hpp @@ -20,10 +20,15 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { + struct from_list_tag + { + explicit from_list_tag() = default; + }; + + inline constexpr from_list_tag from_list {}; + inline auto list = [](auto&&... xs) constexpr { return (std::forward(xs) | ... | nullptr); @@ -153,7 +158,6 @@ inline namespace kernel } auto longest_common_tail(let const&, let const&) -> object const&; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_LIST_HPP diff --git a/include/meevax/kernel/number.hpp b/include/meevax/kernel/number.hpp index 1dd0ba0d7..4e5aaf229 100644 --- a/include/meevax/kernel/number.hpp +++ b/include/meevax/kernel/number.hpp @@ -77,13 +77,8 @@ inline namespace kernel auto operator + (exact_integer const&, complex const&) -> complex; auto operator - (exact_integer const&, complex const&) -> complex; auto operator / (exact_integer const&, complex const&) -> complex; - auto operator % (exact_integer const&, complex const&) -> complex; auto operator ==(exact_integer const&, complex const&) -> bool; auto operator !=(exact_integer const&, complex const&) -> bool; - auto operator < (exact_integer const&, complex const&) -> bool; - auto operator <=(exact_integer const&, complex const&) -> bool; - auto operator > (exact_integer const&, complex const&) -> bool; - auto operator >=(exact_integer const&, complex const&) -> bool; auto operator * (ratio const&, exact_integer const&) -> ratio; auto operator + (ratio const&, exact_integer const&) -> ratio; @@ -137,13 +132,8 @@ inline namespace kernel auto operator - (ratio const&, complex const&) -> complex; auto operator * (ratio const&, complex const&) -> complex; auto operator / (ratio const&, complex const&) -> complex; - auto operator % (ratio const&, complex const&) -> complex; auto operator ==(ratio const&, complex const&) -> bool; auto operator !=(ratio const&, complex const&) -> bool; - auto operator < (ratio const&, complex const&) -> bool; - auto operator <=(ratio const&, complex const&) -> bool; - auto operator > (ratio const&, complex const&) -> bool; - auto operator >=(ratio const&, complex const&) -> bool; auto operator + (float, exact_integer const&) -> float; auto operator - (float, exact_integer const&) -> float; @@ -173,13 +163,8 @@ inline namespace kernel auto operator - (float, complex const&) -> complex; auto operator * (float, complex const&) -> complex; auto operator / (float, complex const&) -> complex; - auto operator % (float, complex const&) -> complex; auto operator ==(float, complex const&) -> bool; auto operator !=(float, complex const&) -> bool; - auto operator < (float, complex const&) -> bool; - auto operator <=(float, complex const&) -> bool; - auto operator > (float, complex const&) -> bool; - auto operator >=(float, complex const&) -> bool; auto operator + (double, exact_integer const&) -> double; auto operator - (double, exact_integer const&) -> double; @@ -209,73 +194,43 @@ inline namespace kernel auto operator - (double, complex const&) -> complex; auto operator * (double, complex const&) -> complex; auto operator / (double, complex const&) -> complex; - auto operator % (double, complex const&) -> complex; auto operator ==(double, complex const&) -> bool; auto operator !=(double, complex const&) -> bool; - auto operator < (double, complex const&) -> bool; - auto operator <=(double, complex const&) -> bool; - auto operator > (double, complex const&) -> bool; - auto operator >=(double, complex const&) -> bool; auto operator + (complex const&, complex const&) -> complex; auto operator - (complex const&, complex const&) -> complex; auto operator * (complex const&, complex const&) -> complex; auto operator / (complex const&, complex const&) -> complex; - auto operator % (complex const&, complex const&) -> complex; auto operator ==(complex const&, complex const&) -> bool; auto operator !=(complex const&, complex const&) -> bool; - auto operator < (complex const&, complex const&) -> bool; - auto operator <=(complex const&, complex const&) -> bool; - auto operator > (complex const&, complex const&) -> bool; - auto operator >=(complex const&, complex const&) -> bool; auto operator + (complex const&, float) -> complex; auto operator - (complex const&, float) -> complex; auto operator * (complex const&, float) -> complex; auto operator / (complex const&, float) -> complex; - auto operator % (complex const&, float) -> complex; auto operator ==(complex const&, float) -> bool; auto operator !=(complex const&, float) -> bool; - auto operator < (complex const&, float) -> bool; - auto operator <=(complex const&, float) -> bool; - auto operator > (complex const&, float) -> bool; - auto operator >=(complex const&, float) -> bool; auto operator + (complex const&, double) -> complex; auto operator - (complex const&, double) -> complex; auto operator * (complex const&, double) -> complex; auto operator / (complex const&, double) -> complex; - auto operator % (complex const&, double) -> complex; auto operator ==(complex const&, double) -> bool; auto operator !=(complex const&, double) -> bool; - auto operator < (complex const&, double) -> bool; - auto operator <=(complex const&, double) -> bool; - auto operator > (complex const&, double) -> bool; - auto operator >=(complex const&, double) -> bool; auto operator + (complex const&, ratio const&) -> complex; auto operator - (complex const&, ratio const&) -> complex; auto operator * (complex const&, ratio const&) -> complex; auto operator / (complex const&, ratio const&) -> complex; - auto operator % (complex const&, ratio const&) -> complex; auto operator ==(complex const&, ratio const&) -> bool; auto operator !=(complex const&, ratio const&) -> bool; - auto operator < (complex const&, ratio const&) -> bool; - auto operator <=(complex const&, ratio const&) -> bool; - auto operator > (complex const&, ratio const&) -> bool; - auto operator >=(complex const&, ratio const&) -> bool; auto operator + (complex const&, exact_integer const&) -> complex; auto operator - (complex const&, exact_integer const&) -> complex; auto operator * (complex const&, exact_integer const&) -> complex; auto operator / (complex const&, exact_integer const&) -> complex; - auto operator % (complex const&, exact_integer const&) -> complex; auto operator ==(complex const&, exact_integer const&) -> bool; auto operator !=(complex const&, exact_integer const&) -> bool; - auto operator < (complex const&, exact_integer const&) -> bool; - auto operator <=(complex const&, exact_integer const&) -> bool; - auto operator > (complex const&, exact_integer const&) -> bool; - auto operator >=(complex const&, exact_integer const&) -> bool; auto operator + (object const&, object const&) -> object; auto operator - (object const&, object const&) -> object; @@ -293,23 +248,6 @@ inline namespace kernel auto make_number(std::string const&, int = 10) -> object; - template - auto inexact_cast(T&& x) -> decltype(auto) - { - if constexpr (std::is_same_v, complex>) - { - return std::complex(std::forward(x)); - } - else if constexpr (std::is_floating_point_v>) - { - return std::forward(x); - } - else - { - return static_cast(std::forward(x)); - } - } - template auto inexact_equals(T const& x, U const& y) { @@ -383,10 +321,6 @@ inline namespace number auto is_even(object const&) -> bool; - auto max(object const&) -> object; - - auto min(object const&) -> object; - auto abs(object const&) -> object; auto quotient(object const&, object const&) -> object; @@ -407,11 +341,15 @@ inline namespace number auto denominator(object const&) -> object; + auto ldexp(object const&, object const&) -> object; + + auto number_to_string(object const&, int) -> object; + auto floor(object const&) -> object; - auto ceil(object const&) -> object; + auto ceiling(object const&) -> object; - auto trunc(object const&) -> object; + auto truncate(object const&) -> object; auto round(object const&) -> object; @@ -427,7 +365,7 @@ inline namespace number auto atan(object const&) -> object; - auto atan(object const&, object const&) -> object; + auto atan2(object const&, object const&) -> object; auto sinh(object const&) -> object; @@ -445,7 +383,27 @@ inline namespace number auto log(object const&) -> object; - auto number_to_string(object const&, int) -> object; + auto fabs(object const&) -> object; + + auto expm1(object const&) -> object; + + auto log1p(object const&) -> object; + + auto tgamma(object const&) -> object; + + auto lgamma(object const&) -> object; + + auto erf(object const&) -> object; + + auto erfc(object const&) -> object; + + auto copysign(object const&, object const&) -> object; + + auto nextafter(object const&, object const&) -> object; + + auto cyl_bessel_j(object const&, object const&) -> object; + + auto cyl_neumann(object const&, object const&) -> object; } // namespace number } // namespace kernel } // namespace meevax diff --git a/include/meevax/kernel/optimizer.hpp b/include/meevax/kernel/optimizer.hpp index 56a8066d4..8cc8d82cb 100644 --- a/include/meevax/kernel/optimizer.hpp +++ b/include/meevax/kernel/optimizer.hpp @@ -19,12 +19,9 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto optimize(object) -> object; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_OPTIMIZER_HPP diff --git a/include/meevax/kernel/output_file_port.hpp b/include/meevax/kernel/output_file_port.hpp index 95000450e..01a32d739 100644 --- a/include/meevax/kernel/output_file_port.hpp +++ b/include/meevax/kernel/output_file_port.hpp @@ -21,9 +21,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct output_file_port : public textual_output_port { @@ -45,7 +43,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, output_file_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_OUTPUT_FILE_PORT_HPP diff --git a/include/meevax/kernel/output_homogeneous_vector_port.hpp b/include/meevax/kernel/output_homogeneous_vector_port.hpp index 5479c6d74..a5b0bf04e 100644 --- a/include/meevax/kernel/output_homogeneous_vector_port.hpp +++ b/include/meevax/kernel/output_homogeneous_vector_port.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { template struct output_homogeneous_vector_port : public binary_output_port @@ -49,7 +47,7 @@ inline namespace kernel auto put(u8vector const& v) -> void override { - std::copy(std::begin(v.valarray), std::end(v.valarray), std::back_inserter(vector)); + std::copy(std::begin(v.valarray()), std::end(v.valarray()), std::back_inserter(vector)); } }; @@ -60,7 +58,6 @@ inline namespace kernel } using output_u8vector_port = output_homogeneous_vector_port; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_OUTPUT_HOMOGENEOUS_VECTOR_PORT_HPP diff --git a/include/meevax/kernel/output_port.hpp b/include/meevax/kernel/output_port.hpp index 81f94ac88..da2bc6b72 100644 --- a/include/meevax/kernel/output_port.hpp +++ b/include/meevax/kernel/output_port.hpp @@ -19,15 +19,12 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct output_port : public virtual port { virtual auto flush() -> void = 0; }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_OUTPUT_PORT_HPP diff --git a/include/meevax/kernel/output_string_port.hpp b/include/meevax/kernel/output_string_port.hpp index 3dc93dea8..50a9812e7 100644 --- a/include/meevax/kernel/output_string_port.hpp +++ b/include/meevax/kernel/output_string_port.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct output_string_port : public textual_output_port { @@ -40,7 +38,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, output_string_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_OUTPUT_STRING_PORT_HPP diff --git a/include/meevax/kernel/pair.hpp b/include/meevax/kernel/pair.hpp index ebe317594..a122e03a8 100644 --- a/include/meevax/kernel/pair.hpp +++ b/include/meevax/kernel/pair.hpp @@ -23,15 +23,13 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { using null = std::nullptr_t; struct pair; - using default_collector = collector; + using default_collector = collector; using object = default_collector::mutator; @@ -163,7 +161,7 @@ inline namespace kernel auto write(std::ostream &) const -> std::ostream & override; - auto view() const noexcept -> memory::view override + auto view() const noexcept -> std::pair override { return { this, sizeof(*this) }; } @@ -280,8 +278,7 @@ inline namespace kernel inline constexpr auto caddddr = compose(car, cddddr); inline constexpr auto cdddddr = compose(cdr, cddddr); -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel template <> struct std::hash diff --git a/include/meevax/kernel/port.hpp b/include/meevax/kernel/port.hpp index fb31a9669..95546f931 100644 --- a/include/meevax/kernel/port.hpp +++ b/include/meevax/kernel/port.hpp @@ -17,9 +17,7 @@ #ifndef INCLUDED_MEEVAX_KERNEL_PORT_HPP #define INCLUDED_MEEVAX_KERNEL_PORT_HPP -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct port { @@ -27,7 +25,6 @@ inline namespace kernel virtual auto is_open() const -> bool = 0; }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_PORT_HPP diff --git a/include/meevax/kernel/procedure.hpp b/include/meevax/kernel/procedure.hpp index 2e1cc458e..e46014aee 100644 --- a/include/meevax/kernel/procedure.hpp +++ b/include/meevax/kernel/procedure.hpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct primitive : public describable { @@ -149,7 +147,6 @@ inline namespace kernel template using procedure = procedure_traits; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_PROCEDURE_HPP diff --git a/include/meevax/kernel/ratio.hpp b/include/meevax/kernel/ratio.hpp index ef55b8bdc..b904b3e2d 100644 --- a/include/meevax/kernel/ratio.hpp +++ b/include/meevax/kernel/ratio.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct ratio { @@ -48,11 +46,14 @@ inline namespace kernel auto numerator() const -> exact_integer; + explicit operator int() const; + + explicit operator float() const; + explicit operator double() const; }; auto operator <<(std::ostream &, ratio const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_RATIO_HPP diff --git a/include/meevax/kernel/standard_error_port.hpp b/include/meevax/kernel/standard_error_port.hpp index 2d39cb900..2434bb0d9 100644 --- a/include/meevax/kernel/standard_error_port.hpp +++ b/include/meevax/kernel/standard_error_port.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct standard_error_port : public textual_output_port { @@ -33,7 +31,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, standard_error_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_STANDARD_ERROR_PORT_HPP diff --git a/include/meevax/kernel/standard_input_port.hpp b/include/meevax/kernel/standard_input_port.hpp index 293fdb4b2..100a2b8b4 100644 --- a/include/meevax/kernel/standard_input_port.hpp +++ b/include/meevax/kernel/standard_input_port.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct standard_input_port : public textual_input_port { @@ -37,7 +35,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, standard_input_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_STANDARD_INPUT_PORT_HPP diff --git a/include/meevax/kernel/standard_output_port.hpp b/include/meevax/kernel/standard_output_port.hpp index ce2a775be..0de6ced36 100644 --- a/include/meevax/kernel/standard_output_port.hpp +++ b/include/meevax/kernel/standard_output_port.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct standard_output_port : public textual_output_port { @@ -33,7 +31,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, standard_output_port const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_STANDARD_OUTPUT_PORT_HPP diff --git a/include/meevax/kernel/string.hpp b/include/meevax/kernel/string.hpp index fba993a54..bf7c63bac 100644 --- a/include/meevax/kernel/string.hpp +++ b/include/meevax/kernel/string.hpp @@ -17,13 +17,12 @@ #ifndef INCLUDED_MEEVAX_KERNEL_STRING_HPP #define INCLUDED_MEEVAX_KERNEL_STRING_HPP +#include #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct string : private std::vector { @@ -45,17 +44,14 @@ inline namespace kernel explicit string(std::string const&); + explicit operator std::filesystem::path() const; + operator std::string() const; - friend auto operator ==(string const& lhs, string const& rhs) { return static_cast const&>(lhs) == static_cast const&>(rhs); } - friend auto operator < (string const& lhs, string const& rhs) { return static_cast const&>(lhs) < static_cast const&>(rhs); } - friend auto operator > (string const& lhs, string const& rhs) { return static_cast const&>(lhs) > static_cast const&>(rhs); } - friend auto operator <=(string const& lhs, string const& rhs) { return static_cast const&>(lhs) <= static_cast const&>(rhs); } - friend auto operator >=(string const& lhs, string const& rhs) { return static_cast const&>(lhs) >= static_cast const&>(rhs); } + auto operator <=>(string const&) const = default; }; auto operator <<(std::ostream &, string const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_STRING_HPP diff --git a/include/meevax/kernel/symbol.hpp b/include/meevax/kernel/symbol.hpp index 58143de71..a65c1a712 100644 --- a/include/meevax/kernel/symbol.hpp +++ b/include/meevax/kernel/symbol.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct symbol : public identifier { @@ -40,12 +38,6 @@ inline namespace kernel }; auto operator + (symbol const&, symbol const&) -> std::string; - auto operator ==(symbol const&, symbol const&) -> bool; - auto operator !=(symbol const&, symbol const&) -> bool; - auto operator < (symbol const&, symbol const&) -> bool; - auto operator <=(symbol const&, symbol const&) -> bool; - auto operator > (symbol const&, symbol const&) -> bool; - auto operator >=(symbol const&, symbol const&) -> bool; auto operator <<(std::ostream &, symbol const&) -> std::ostream &; @@ -58,7 +50,6 @@ inline namespace kernel auto symbols() -> std::unordered_map &; auto make_symbol(std::string const&) -> object const&; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_SYMBOL_HPP diff --git a/include/meevax/kernel/syntactic_environment.hpp b/include/meevax/kernel/syntactic_environment.hpp index 0595663db..ff844d2dc 100644 --- a/include/meevax/kernel/syntactic_environment.hpp +++ b/include/meevax/kernel/syntactic_environment.hpp @@ -24,9 +24,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { template struct syntactic_environment : public virtual pair // ( . ) @@ -138,12 +136,12 @@ inline namespace kernel struct syntax : public describable { auto (*expand)(syntactic_environment const&, - object const& expression, + object const& form, object const& bound_variables, renamer &) -> object; auto (*generate)(syntactic_environment &, - object const& /* expression */, + object const& /* form */, object const& /* bound_variables */, object const& /* continuation */, bool /* tail */) -> object; @@ -159,8 +157,8 @@ inline namespace kernel struct constructor : private object { - explicit constructor(let const& expression) - : object { expression } + explicit constructor(let const& form) + : object { form } {} template @@ -191,9 +189,9 @@ inline namespace kernel } }; - #define CONS typename syntax::constructor(expression).cons + #define CONS typename syntax::constructor(form).cons - #define LIST typename syntax::constructor(expression).list + #define LIST typename syntax::constructor(form).list friend auto operator <<(std::ostream & os, syntax const& datum) -> std::ostream & { @@ -205,64 +203,64 @@ inline namespace kernel { #define EXPANDER(NAME) \ auto NAME([[maybe_unused]] syntactic_environment const& expander, \ - object const& expression, \ + object const& form, \ [[maybe_unused]] object const& bound_variables, \ [[maybe_unused]] renamer & rename) -> object static EXPANDER(quote) { - return expression; + return form; } static EXPANDER(quote_syntax) { - return expression; + return form; } static EXPANDER(call) { - return CONS(expander.expand(car(expression), + return CONS(expander.expand(car(form), bound_variables, rename), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } static EXPANDER(operand) { - if (expression.is()) + if (form.is()) { - return CONS(expander.expand(car(expression), + return CONS(expander.expand(car(form), bound_variables, rename), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } else { - return expander.expand(expression, bound_variables, rename); + return expander.expand(form, bound_variables, rename); } } static EXPANDER(lambda) { - let const& formals = rename(cadr(expression)); + let const& formals = rename(cadr(form)); - return CONS(rename(car(expression)) /* lambda */, + return CONS(rename(car(form)) /* lambda */, CONS(formals, body(expander, - cddr(expression), + cddr(form), cons(formals, bound_variables), rename))); } static EXPANDER(body) { - if (auto [binding_specs, sequence] = expander.sweep(expression, bound_variables); binding_specs) + if (auto [binding_specs, sequence] = expander.sweep(form, bound_variables); binding_specs) { /* (letrec* ) @@ -326,18 +324,18 @@ inline namespace kernel static EXPANDER(conditional) { - return CONS(rename(car(expression)), + return CONS(rename(car(form)), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } static EXPANDER(set) { - return CONS(rename(car(expression)), + return CONS(rename(car(form)), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } @@ -345,7 +343,7 @@ inline namespace kernel static EXPANDER(include) { return expander.expand(CONS(corename("begin"), - meevax::include(cadr(expression))), + meevax::include(cadr(form))), bound_variables, rename); } @@ -353,7 +351,7 @@ inline namespace kernel static EXPANDER(include_case_insensitive) { return expander.expand(CONS(corename("begin"), - meevax::include(cadr(expression), false)), + meevax::include(cadr(form), false)), bound_variables, rename); } @@ -361,16 +359,16 @@ inline namespace kernel static EXPANDER(conditional_expand) { return expander.expand(CONS(corename("begin"), - meevax::conditional_expand(cdr(expression))), + meevax::conditional_expand(cdr(form))), bound_variables, rename); } static EXPANDER(letrec) { - let const extended_bound_variables = cons(map(car, cadr(expression)), bound_variables); + let const extended_bound_variables = cons(map(car, cadr(form)), bound_variables); - return CONS(car(expression), + return CONS(car(form), map([&](let const& binding) { return LIST(car(binding), @@ -378,28 +376,28 @@ inline namespace kernel extended_bound_variables, rename)); }, - cadr(expression)), + cadr(form)), body(expander, - cddr(expression), + cddr(form), extended_bound_variables, rename)); } static EXPANDER(sequence) { - if (expression.is()) + if (form.is()) { - return CONS(expander.expand(car(expression), + return CONS(expander.expand(car(form), bound_variables, rename), sequence(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } else { - return expander.expand(expression, bound_variables, rename); + return expander.expand(form, bound_variables, rename); } } @@ -414,11 +412,11 @@ inline namespace kernel current_environment)); }; - let const formals = map(formal, cadr(expression)); + let const formals = map(formal, cadr(form)); return expander.expand(LIST(CONS(corename("lambda"), formals, - cddr(expression) /* body */)), + cddr(form) /* body */)), bound_variables, rename); } @@ -434,13 +432,13 @@ inline namespace kernel current_environment)); }; - let const formals = map(formal, cadr(expression)); + let const formals = map(formal, cadr(form)); car(current_environment) = cons(formals, bound_variables); return expander.expand(LIST(CONS(corename("lambda"), formals, - cddr(expression) /* body */)), + cddr(form) /* body */)), bound_variables, rename); } @@ -449,21 +447,21 @@ inline namespace kernel { if (bound_variables.is()) { - if (cadr(expression).is()) // (define ( . ) ) + if (cadr(form).is()) // (define ( . ) ) { - return LIST(rename(car(expression)), - caadr(expression) /* variable */, + return LIST(rename(car(form)), + caadr(form) /* variable */, expander.expand(CONS(corename("lambda"), - cdadr(expression) /* formals */, - cddr(expression) /* body */), + cdadr(form) /* formals */, + cddr(form) /* body */), bound_variables, rename)); } else // (define ) { - return CONS(rename(car(expression)), - cadr(expression), - cddr(expression) ? LIST(expander.expand(caddr(expression), + return CONS(rename(car(form)), + cadr(form), + cddr(form) ? LIST(expander.expand(caddr(form), bound_variables, rename)) : unit); @@ -477,36 +475,36 @@ inline namespace kernel static EXPANDER(define_syntax) { - return LIST(rename(car(expression)), - cadr(expression), - expander.expand(caddr(expression), + return LIST(rename(car(form)), + cadr(form), + expander.expand(caddr(form), bound_variables, rename)); } static EXPANDER(call_with_current_continuation) { - return CONS(rename(car(expression)), + return CONS(rename(car(form)), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } static EXPANDER(current) { - return CONS(rename(car(expression)), + return CONS(rename(car(form)), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } static EXPANDER(install) { - return CONS(rename(car(expression)), + return CONS(rename(car(form)), operand(expander, - cdr(expression), + cdr(form), bound_variables, rename)); } @@ -518,30 +516,30 @@ inline namespace kernel { #define GENERATOR(NAME) \ auto NAME([[maybe_unused]] syntactic_environment & generator, \ - [[maybe_unused]] object const& expression, \ + [[maybe_unused]] object const& form, \ [[maybe_unused]] object const& bound_variables, \ [[maybe_unused]] object const& continuation, \ [[maybe_unused]] bool tail = false) -> object static GENERATOR(quote) { - return CONS(make(instruction::load_constant), car(expression).is() ? car(expression).as().form - : car(expression), + return CONS(make(instruction::load_constant), car(form).is() ? car(form).as().form + : car(form), continuation); } static GENERATOR(quote_syntax) { - return CONS(make(instruction::load_constant), car(expression), + return CONS(make(instruction::load_constant), car(form), continuation); } static GENERATOR(call) { return operand(generator, - cdr(expression), + cdr(form), bound_variables, - generator.generate(car(expression), + generator.generate(car(form), bound_variables, tail ? LIST(make(instruction::tail_call)) : CONS(make(instruction::call), continuation))); @@ -549,19 +547,19 @@ inline namespace kernel static GENERATOR(operand) { - if (expression.is()) + if (form.is()) { return operand(generator, - cdr(expression), + cdr(form), bound_variables, - generator.generate(car(expression), + generator.generate(car(form), bound_variables, CONS(make(instruction::cons), continuation))); } else { - return generator.generate(expression, bound_variables, continuation); + return generator.generate(form, bound_variables, continuation); } } @@ -569,28 +567,28 @@ inline namespace kernel { return CONS(make(instruction::load_closure), body(generator, - cdr(expression), - cons(car(expression), bound_variables), // Extend scope. + cdr(form), + cons(car(form), bound_variables), // Extend scope. LIST(make(instruction::return_))), continuation); } static GENERATOR(body) { - if (cdr(expression).template is()) + if (cdr(form).template is()) { - return generator.generate(car(expression), + return generator.generate(car(form), bound_variables, continuation, true); } else { - return generator.generate(car(expression), + return generator.generate(car(form), bound_variables, CONS(make(instruction::drop), body(generator, - cdr(expression), + cdr(form), bound_variables, continuation)), false); @@ -603,49 +601,49 @@ inline namespace kernel { assert(lexical_cast(continuation) == "(return)"); - return generator.generate(car(expression), // + return generator.generate(car(form), // bound_variables, LIST(make(instruction::tail_select), - generator.generate(cadr(expression), + generator.generate(cadr(form), bound_variables, continuation, tail), - cddr(expression) ? generator.generate(caddr(expression), - bound_variables, - continuation, - tail) - : LIST(make(instruction::load_constant), unspecified, // If yields a false value and no is specified, then the result of the expression is unspecified. - make(instruction::return_)))); + cddr(form) ? generator.generate(caddr(form), + bound_variables, + continuation, + tail) + : LIST(make(instruction::load_constant), unspecified, // If yields a false value and no is specified, then the result of the expression is unspecified. + make(instruction::return_)))); } else { - return generator.generate(car(expression), // + return generator.generate(car(form), // bound_variables, CONS(make(instruction::select), - generator.generate(cadr(expression), + generator.generate(cadr(form), bound_variables, LIST(make(instruction::join))), - cddr(expression) ? generator.generate(caddr(expression), - bound_variables, - LIST(make(instruction::join))) - : LIST(make(instruction::load_constant), unspecified, // If yields a false value and no is specified, then the result of the expression is unspecified. - make(instruction::join)), + cddr(form) ? generator.generate(caddr(form), + bound_variables, + LIST(make(instruction::join))) + : LIST(make(instruction::load_constant), unspecified, // If yields a false value and no is specified, then the result of the expression is unspecified. + make(instruction::join)), continuation)); } } static GENERATOR(set) { - if (let const& identity = generator.identify(car(expression), bound_variables); identity.is()) + if (let const& identity = generator.identify(car(form), bound_variables); identity.is()) { - return generator.generate(cadr(expression), + return generator.generate(cadr(form), bound_variables, CONS(make(instruction::store_relative), identity, continuation)); } else if (identity.is()) { - return generator.generate(cadr(expression), + return generator.generate(cadr(form), bound_variables, CONS(make(instruction::store_variadic), identity, continuation)); @@ -654,7 +652,7 @@ inline namespace kernel { assert(identity.is()); - return generator.generate(cadr(expression), + return generator.generate(cadr(form), bound_variables, CONS(make(instruction::store_absolute), identity, continuation)); @@ -671,14 +669,14 @@ inline namespace kernel { assert(not tail or lexical_cast(continuation) == "(return)"); - let const formals = map(car, car(expression)); + let const formals = map(car, car(form)); return CONS(make(instruction::dummy), operand(generator, - map(cadr, car(expression)), + map(cadr, car(form)), cons(formals, bound_variables), lambda(generator, - cons(formals, cdr(expression)), // ( ) + cons(formals, cdr(form)), // ( ) bound_variables, tail ? LIST(make(instruction::tail_letrec)) : CONS(make(instruction::letrec), continuation)))); @@ -686,9 +684,9 @@ inline namespace kernel static GENERATOR(sequence) { - if (cdr(expression).is()) // is tail sequence + if (cdr(form).is()) // is tail sequence { - return generator.generate(car(expression), + return generator.generate(car(form), bound_variables, continuation, tail); @@ -704,13 +702,13 @@ inline namespace kernel separately and then combined with the compiled result of the remaining expressions by append. */ - let const& head = generator.generate(car(expression), // Head expression or definition + let const& head = generator.generate(car(form), // Head expression or definition bound_variables, unit); return append(head, CONS(make(instruction::drop), // Pop result of head expression sequence(generator, - cdr(expression), // Rest expression or definitions + cdr(form), // Rest expression or definitions bound_variables, continuation, tail))); @@ -725,19 +723,19 @@ inline namespace kernel { assert(bound_variables.is()); // This has been checked on previous passes. - assert(not car(expression).is()); // This has been checked on previous passes. + assert(not car(form).is()); // This has been checked on previous passes. - return generator.generate(cdr(expression) ? cadr(expression) : unspecified, + return generator.generate(cdr(form) ? cadr(form) : unspecified, bound_variables, - CONS(make(instruction::store_absolute), generator.identify(car(expression), bound_variables), + CONS(make(instruction::store_absolute), generator.identify(car(form), bound_variables), continuation)); } static GENERATOR(define_syntax) { - let identity = generator.identify(car(expression), unit); + let identity = generator.identify(car(form), unit); - cdr(identity) = make(Environment().execute(generator.generate(cadr(expression), + cdr(identity) = make(Environment().execute(generator.generate(cadr(form), bound_variables)), make(bound_variables, generator.second)); @@ -748,12 +746,12 @@ inline namespace kernel static GENERATOR(call_with_current_continuation) { - assert(expression.is()); - assert(cdr(expression).is()); + assert(form.is()); + assert(cdr(form).is()); return CONS(make(instruction::load_continuation), continuation, - generator.generate(car(expression), + generator.generate(car(form), bound_variables, LIST(make(instruction::tail_call)), // The first argument passed to call-with-current-continuation must be called via a tail call. tail)); @@ -761,15 +759,15 @@ inline namespace kernel static GENERATOR(current) { - return CONS(make(instruction::current), car(expression), + return CONS(make(instruction::current), car(form), continuation); } static GENERATOR(install) { - return generator.generate(cadr(expression), + return generator.generate(cadr(form), bound_variables, - CONS(make(instruction::install), car(expression), + CONS(make(instruction::install), car(form), continuation)); } @@ -779,19 +777,17 @@ inline namespace kernel using pair::pair; template - inline auto compile(object const& expression, + inline auto compile(object const& form, object const& bound_variables, Ts&&... xs) -> decltype(auto) { - return generate(expand(expression, - bound_variables, - default_rename), + return generate(expand(form, bound_variables, default_rename), bound_variables, std::forward(xs)...); } - inline auto compile(object const& expression) -> decltype(auto) + inline auto compile(object const& form) -> decltype(auto) { - return compile(expression, first); + return compile(form, first); } static auto core() -> auto const& @@ -854,23 +850,23 @@ inline namespace kernel return define::type>(std::forward(xs)...); } - inline auto expand(object const& expression, + inline auto expand(object const& form, object const& bound_variables, renamer & rename) const -> object try { - if (not expression.is()) + if (not form.is()) { - if (expression.is()) + if (form.is()) { - if (let const& identity = identify(expression, bound_variables); identity == f) + if (let const& identity = identify(form, bound_variables); identity == f) { - return expression.as().expand(bound_variables, rename); + return form.as().expand(bound_variables, rename); } } - return expression.is_also() ? rename(expression) : expression; + return form.is_also() ? rename(form) : form; } - else if (let const& identity = identify(car(expression), bound_variables); identity.is()) + else if (let const& identity = identify(car(form), bound_variables); identity.is()) { if (cdr(identity).is()) { @@ -893,40 +889,40 @@ inline namespace kernel assert(cddr(identity).is()); let const transformed = Environment().apply(cadr(identity), - expression, + form, make(bound_variables, second), cddr(identity)); - syntax::contexts[transformed.get()] = expression; + syntax::contexts[transformed.get()] = form; return expand(transformed, bound_variables, rename); } else if (cdr(identity).is()) { - return cdr(identity).as().expand(*this, expression, bound_variables, rename); + return cdr(identity).as().expand(*this, form, bound_variables, rename); } } - return expander::call(*this, expression, bound_variables, rename); + return expander::call(*this, form, bound_variables, rename); } catch (error & e) { - e.detail(error::in::expanding, expression).raise(); + e.detail(error::in::expanding, form).raise(); return unspecified; } - inline auto generate(object const& expression, + inline auto generate(object const& form, object const& bound_variables, object const& continuation = list(make(instruction::stop)), bool tail = false) -> object try { - if (not expression.is()) + if (not form.is()) { - if (expression.is_also()) + if (form.is_also()) { - assert(expression.is() or expression.is()); + assert(form.is() or form.is()); - if (let const& identity = identify(expression, bound_variables); identity.is()) + if (let const& identity = identify(form, bound_variables); identity.is()) { return CONS(make(instruction::load_relative), identity, continuation); } @@ -942,21 +938,21 @@ inline namespace kernel } else // is { - return CONS(make(instruction::load_constant), expression, continuation); + return CONS(make(instruction::load_constant), form, continuation); } } - else if (let const& identity = std::as_const(*this).identify(car(expression), bound_variables); identity.is() and cdr(identity).is()) + else if (let const& identity = std::as_const(*this).identify(car(form), bound_variables); identity.is() and cdr(identity).is()) { - return cdr(identity).as().generate(*this, cdr(expression), bound_variables, continuation, tail); + return cdr(identity).as().generate(*this, cdr(form), bound_variables, continuation, tail); } else { - return generator::call(*this, expression, bound_variables, continuation, tail); + return generator::call(*this, form, bound_variables, continuation, tail); } } catch (error & e) { - e.detail(error::in::generating, expression).raise(); + e.detail(error::in::generating, form).raise(); return unspecified; } @@ -1151,7 +1147,6 @@ inline namespace kernel return xs; } }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_SYNTACTIC_ENVIRONMENT_HPP diff --git a/include/meevax/kernel/textual_input_port.hpp b/include/meevax/kernel/textual_input_port.hpp index 7cbb75df9..eb6d0f314 100644 --- a/include/meevax/kernel/textual_input_port.hpp +++ b/include/meevax/kernel/textual_input_port.hpp @@ -25,9 +25,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct textual_input_port : public virtual textual_port, public virtual input_port { @@ -210,7 +208,6 @@ inline namespace kernel '|', // 0x7C '}'); // 0x7D } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_TEXTUAL_INPUT_PORT_HPP diff --git a/include/meevax/kernel/textual_output_port.hpp b/include/meevax/kernel/textual_output_port.hpp index f8b54c596..173965c76 100644 --- a/include/meevax/kernel/textual_output_port.hpp +++ b/include/meevax/kernel/textual_output_port.hpp @@ -22,9 +22,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct textual_output_port : public virtual textual_port, public virtual output_port { @@ -40,7 +38,6 @@ inline namespace kernel explicit virtual operator std::ostream &() = 0; }; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_TEXTUAL_OUTPUT_PORT_HPP diff --git a/include/meevax/kernel/textual_port.hpp b/include/meevax/kernel/textual_port.hpp index 522e392e6..3cbcafd6c 100644 --- a/include/meevax/kernel/textual_port.hpp +++ b/include/meevax/kernel/textual_port.hpp @@ -19,13 +19,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct textual_port : public virtual port {}; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_TEXTUAL_PORT_HPP diff --git a/include/meevax/kernel/transformer.hpp b/include/meevax/kernel/transformer.hpp index 580f709bc..7b07d4bf4 100644 --- a/include/meevax/kernel/transformer.hpp +++ b/include/meevax/kernel/transformer.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct transformer : public virtual pair // ( . ) { @@ -29,7 +27,6 @@ inline namespace kernel }; auto operator <<(std::ostream &, transformer const&) -> std::ostream &; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_TRANSFORMER_HPP diff --git a/include/meevax/kernel/vector.hpp b/include/meevax/kernel/vector.hpp index e2cd5b02b..5a0c0b65d 100644 --- a/include/meevax/kernel/vector.hpp +++ b/include/meevax/kernel/vector.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct heterogeneous_vector : private std::vector { @@ -46,7 +44,6 @@ inline namespace kernel using vector = heterogeneous_vector; auto make_vector(object const&) -> object; // list->vector -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_VECTOR_HPP diff --git a/include/meevax/kernel/version.hpp b/include/meevax/kernel/version.hpp index 59fa108c1..e1a5748bb 100644 --- a/include/meevax/kernel/version.hpp +++ b/include/meevax/kernel/version.hpp @@ -22,16 +22,13 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto help() noexcept -> std::string_view; auto features() -> object const&; auto version() -> object const&; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_KERNEL_VERSION_HPP diff --git a/include/meevax/map/simple_flat_map.hpp b/include/meevax/map/simple_flat_map.hpp index b833cf7c3..1c0e70682 100644 --- a/include/meevax/map/simple_flat_map.hpp +++ b/include/meevax/map/simple_flat_map.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace map +namespace meevax::inline map { template struct simple_flat_map : public std::vector> @@ -43,7 +41,6 @@ inline namespace map return this->emplace(std::forward(xs)...); } }; -} // namespace map -} // namespace meevax +} // namespace meevax::map #endif // INCLUDED_MEEVAX_MAP_SIMPLE_FLAT_MAP_HPP diff --git a/include/meevax/memory/allocator.hpp b/include/meevax/memory/allocator.hpp index cee480b6b..b8498699e 100644 --- a/include/meevax/memory/allocator.hpp +++ b/include/meevax/memory/allocator.hpp @@ -22,9 +22,7 @@ #include #include // std::exchange -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { /* Simple Segregated Storage Allocator @@ -32,16 +30,16 @@ inline namespace memory template > class allocator { - struct alignas(T) chunk + union chunk { chunk * tail; + + T value; }; struct block { - static constexpr auto chunk_size = std::max(sizeof(T), sizeof(chunk)); - - std::uint8_t data[chunk_size * Capacity::value] = {}; + std::uint8_t data[sizeof(chunk) * Capacity::value] = {}; std::size_t size = Capacity::value; @@ -58,7 +56,7 @@ class allocator auto pop() { - return data + chunk_size * --size; + return data + sizeof(chunk) * --size; } }; @@ -123,7 +121,6 @@ class allocator free_list = reinterpret_cast(p); } }; -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_ALLOCATOR_HPP diff --git a/include/meevax/memory/collector.hpp b/include/meevax/memory/collector.hpp index 370bf8448..4e2669f9d 100644 --- a/include/meevax/memory/collector.hpp +++ b/include/meevax/memory/collector.hpp @@ -17,13 +17,10 @@ #ifndef INCLUDED_MEEVAX_MEMORY_COLLECTOR_HPP #define INCLUDED_MEEVAX_MEMORY_COLLECTOR_HPP -#if __unix__ #include // dlopen, dlclose, dlerror -#else -#error -#endif #include // std::allocator +#include #include #include @@ -35,11 +32,21 @@ #include #include -namespace meevax +namespace meevax::inline memory { -inline namespace memory -{ - using view = std::pair; // TODO Adapt to C++20's std::range concept + struct direct_initialization_tag + { + explicit direct_initialization_tag() = default; + }; + + inline constexpr direct_initialization_tag direct_initialization {}; + + struct list_initialization_tag + { + explicit list_initialization_tag() = default; + }; + + inline constexpr list_initialization_tag list_initialization {}; /* This mark-and-sweep garbage collector is based on the implementation of @@ -62,7 +69,7 @@ inline namespace memory virtual auto write(std::ostream &) const -> std::ostream & = 0; - virtual auto view() const noexcept -> memory::view = 0; + virtual auto view() const noexcept -> std::pair = 0; auto contains(void const* const data) const noexcept { @@ -95,11 +102,19 @@ inline namespace memory static inline auto allocator = allocator_type(); + template + explicit constexpr binder(direct_initialization_tag, Us&&... xs) + : std::conditional_t and std::is_constructible_v, Top, Bound>(std::forward(xs)...) + {} + + template + explicit constexpr binder(list_initialization_tag, Us&&... xs) + : std::conditional_t and std::is_constructible_v, Top, Bound> { std::forward(xs)... } + {} + template explicit constexpr binder(Us&&... xs) - : std::conditional_t and std::is_constructible_v, Top, Bound> { - std::forward(xs)... - } + : binder { list_initialization, std::forward(xs)... } {} ~binder() override = default; @@ -140,7 +155,7 @@ inline namespace memory } } - auto view() const noexcept -> memory::view override + auto view() const noexcept -> std::pair override { return { this, sizeof(*this) }; } @@ -152,8 +167,7 @@ inline namespace memory auto operator delete(void * data) noexcept -> void { - using pointer = typename std::allocator_traits::pointer; - allocator.deallocate(reinterpret_cast(data), 1); + allocator.deallocate(reinterpret_cast::pointer>(data), 1); } }; @@ -169,6 +183,7 @@ inline namespace memory { if (*this) { + assert(not mutators.contains(this)); mutators.insert(this); } } @@ -178,6 +193,7 @@ inline namespace memory { if (top) { + assert(not mutators.contains(this)); mutators.insert(this); } } @@ -191,8 +207,9 @@ inline namespace memory ~mutator() { - if (not cleared) + if (pointer::operator bool() and not cleared) { + assert(mutators.contains(this)); mutators.erase(this); } } @@ -209,22 +226,38 @@ inline namespace memory return *this; } - auto reset(mutator const& other) -> void + auto reset(mutator const& after) -> void { - if (pointer::reset(other); other) + auto const before = pointer::operator bool(); + + pointer::reset(after); + + if (before) { - mutators.insert(this); + if (not after) + { + assert(mutators.contains(this)); + mutators.erase(this); + } } - else + else if (after) { - mutators.erase(this); + assert(not mutators.contains(this)); + mutators.insert(this); } } auto reset(std::nullptr_t = nullptr) -> void { + auto const before = pointer::operator bool(); + pointer::reset(); - mutators.erase(this); + + if (before) + { + assert(mutators.contains(this)); + mutators.erase(this); + } } template @@ -285,7 +318,7 @@ inline namespace memory { if (pointer::dereferenceable()) { - return *this ? pointer::get()->compare(rhs.get()) : rhs.is(); + return *this ? pointer::unsafe_get()->compare(rhs.get()) : rhs.is(); } else { @@ -310,7 +343,7 @@ inline namespace memory { if (pointer::dereferenceable()) { - return *this ? pointer::get()->type() : typeid(std::nullptr_t); + return *this ? pointer::unsafe_get()->type() : typeid(std::nullptr_t); } else { @@ -322,7 +355,7 @@ inline namespace memory { if (pointer::dereferenceable()) { - return *this ? pointer::get()->write(os) : os << magenta("()"); + return *this ? pointer::unsafe_get()->write(os) : os << magenta("()"); } else { @@ -337,32 +370,32 @@ inline namespace memory inline auto begin() { - return *this ? pointer::get()->begin() : typename Top::iterator(); + return *this ? pointer::unsafe_get()->begin() : typename Top::iterator(); } inline auto begin() const { - return *this ? pointer::get()->cbegin() : typename Top::const_iterator(); + return *this ? pointer::unsafe_get()->cbegin() : typename Top::const_iterator(); } inline auto cbegin() const { - return *this ? pointer::get()->cbegin() : typename Top::const_iterator(); + return *this ? pointer::unsafe_get()->cbegin() : typename Top::const_iterator(); } inline auto end() { - return *this ? pointer::get()->end() : typename Top::iterator(); + return *this ? pointer::unsafe_get()->end() : typename Top::iterator(); } inline auto end() const { - return *this ? pointer::get()->cend() : typename Top::const_iterator(); + return *this ? pointer::unsafe_get()->cend() : typename Top::const_iterator(); } inline auto cend() const { - return *this ? pointer::get()->cend() : typename Top::const_iterator(); + return *this ? pointer::unsafe_get()->cend() : typename Top::const_iterator(); } }; @@ -372,7 +405,9 @@ inline namespace memory 0x0000'0000'0000'0000 ~ 0x7FFF'FFFF'FFFF'FFFF */ template - using pointer_set = integer_set; + using pointer_set = integer_set; private: static inline pointer_set objects {}; @@ -381,32 +416,10 @@ inline namespace memory static inline std::size_t allocation = 0; - static inline std::size_t threshold = 8_MiB; + static inline std::size_t threshold = 128_MiB; static inline std::unordered_map> dynamic_linked_libraries {}; - struct mutators_view - { - std::uintptr_t address; - - std::size_t size; - - constexpr mutators_view(view const& v) - : address { reinterpret_cast(v.first) } - , size { v.second } - {} - - auto begin() const noexcept - { - return mutators.lower_bound(reinterpret_cast(address)); - } - - auto end() const noexcept - { - return mutators.lower_bound(reinterpret_cast(address + size)); - } - }; - public: collector() = delete; @@ -449,9 +462,10 @@ inline namespace memory static auto clear() -> void { - for (auto&& object : objects) + for (auto const& object : objects) { delete object; + assert(objects.contains(object)); objects.erase(object); } } @@ -515,7 +529,7 @@ inline namespace memory static auto mark() noexcept -> pointer_set { - auto is_root_object = [begin = objects.begin()](mutator const* given) // TODO INEFFICIENT! + auto is_root = [begin = objects.begin()](mutator const* given) { /* If the given mutator is a non-root object, then an object containing @@ -531,44 +545,66 @@ inline namespace memory return iter == begin or not (*--iter)->contains(given); }; - auto marked_objects = pointer_set(); - - for (auto&& mutator : mutators) + struct mutators_view { - assert(mutator); - assert(mutator->get()); + void const* data; - if (not marked_objects.contains(mutator->get()) and is_root_object(mutator)) + std::size_t size; + + explicit constexpr mutators_view(std::pair const& p) + : data { p.first } + , size { p.second } + {} + + auto begin() const noexcept { - mark(mutator->get(), marked_objects); + return mutators.lower_bound(reinterpret_cast(data)); } - } - return marked_objects; - } - - static auto mark(top const* const object, pointer_set & marked_objects) noexcept -> void - { - assert(object); + auto end() const noexcept + { + return mutators.lower_bound(reinterpret_cast(reinterpret_cast(data) + size)); + } + }; - assert(objects.contains(object)); + auto reachables = pointer_set(); - if (not marked_objects.contains(object)) + for (auto const& mutator : mutators) { - marked_objects.insert(object); + assert(mutator); + assert(mutator->unsafe_get()); - for (auto each : mutators_view(object->view())) + if (auto object = mutator->unsafe_get(); not reachables.contains(object) and is_root(mutator)) { - mark(each->get(), marked_objects); + auto queue = std::queue(); + + for (queue.push(object); not queue.empty(); queue.pop()) + { + if (not reachables.contains(queue.front())) + { + reachables.insert(queue.front()); + + for (auto const& mutator : mutators_view(queue.front()->view())) + { + assert(mutator); + assert(mutator->unsafe_get()); + + queue.push(mutator->unsafe_get()); + } + } + } } } + + return reachables; } - static auto sweep(pointer_set && marked_objects) -> void + static auto sweep(pointer_set && reachables) -> void { - for (auto marked_object : marked_objects) + for (auto reachable : reachables) { - objects.erase(marked_object); + assert(objects.contains(reachable)); + objects.erase(reachable); } for (auto object : objects) @@ -576,10 +612,9 @@ inline namespace memory delete object; } - objects.swap(marked_objects); + objects.swap(reachables); } }; -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_COLLECTOR_HPP diff --git a/include/meevax/memory/integer_set.hpp b/include/meevax/memory/integer_set.hpp index a9f2a2e56..125803f6d 100644 --- a/include/meevax/memory/integer_set.hpp +++ b/include/meevax/memory/integer_set.hpp @@ -17,21 +17,23 @@ #ifndef INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP #define INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP +#include +#include #include #include // CHAR_BIT #include #include #include -#include -#include - -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { template - constexpr auto compressible_bitwidth_of = std::is_pointer_v ? log2(alignof(std::remove_pointer_t)) - 1 : 0; + constexpr auto compressible_bitwidth_of = std::is_pointer_v ? std::bit_width(alignof(std::remove_pointer_t)) - 1 : 0; + + constexpr auto operator ""_u64(unsigned long long int value) + { + return static_cast(value); + } template struct integer_set @@ -46,13 +48,13 @@ inline namespace memory subset * data[N] = {}; - std::size_t max = 0; + static inline std::size_t hint = 0; struct const_iterator { using value_type = T; - using difference_type = std::ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = T *; @@ -62,63 +64,68 @@ inline namespace memory subset const* const* data = nullptr; - std::size_t max = 0; - std::size_t i = std::numeric_limits::max(); typename subset::const_iterator iter; constexpr const_iterator() = default; - explicit const_iterator(integer_set const* container, std::size_t i, std::uintptr_t j = 0) noexcept - : data { container->data } - , max { container->max } + template + explicit const_iterator(subset const* const* data, std::size_t i, Ts&&... xs) noexcept + : data { data } , i { i } { assert(i <= N); - increment_unless_truthy(j); + increment_unless_truthy(std::forward(xs)...); } - explicit const_iterator(integer_set const* container) noexcept - : data { container->data } - , max { container->max } + explicit const_iterator(subset const* const* data) noexcept + : data { data } , i { N } { decrement_unless_truthy(); assert(iter.data); } - auto increment_unless_truthy(std::uintptr_t j = 0) noexcept -> void + template + auto increment_unless_truthy(Ts&&... xs) noexcept -> void { assert(data); - if (good()) + if constexpr (0 < sizeof...(Ts)) { - if (data[i] and (iter = data[i]->lower_bound(j)).good()) + if (not operator bool() or not data[i] or not (iter = data[i]->lower_bound(std::forward(xs)...))) { - return; + ++i; + increment_unless_truthy(); } - else for (++i; i <= max; ++i) + } + else + { + if (operator bool()) { - if (data[i] and (iter = data[i]->lower_bound(0)).good()) + for (; i <= hint; ++i) { - return; + if (data[i] and (iter = data[i]->lower_bound(0))) + { + return; + } } + + i = N; } - i = N; + iter = {}; } - - iter = {}; } auto decrement_unless_truthy() noexcept -> void { assert(data); - for (i = std::min(i, N - 1); good(); --i) + for (i = std::min(i, N - 1); operator bool(); --i) { - if (data[i] and (iter = typename subset::const_iterator(data[i])).good()) + if (data[i] and (iter = typename subset::const_iterator(data[i]->data))) { return; } @@ -129,7 +136,7 @@ inline namespace memory auto operator ++() noexcept -> auto & { - if (++iter; not iter.good()) + if (not ++iter) { ++i; increment_unless_truthy(); @@ -144,7 +151,7 @@ inline namespace memory { decrement_unless_truthy(); } - else if (--iter; not iter.good()) + else if (not --iter) { --i; decrement_unless_truthy(); @@ -153,31 +160,20 @@ inline namespace memory return *this; } - auto operator *() const noexcept -> T + constexpr auto operator *() const noexcept -> T { - assert(good()); - return reinterpret_cast((i << (Es + ...) bitor *iter) << compressible_bitwidth_of); + assert(operator bool()); + return reinterpret_cast((i << (Es + ...) | *iter) << compressible_bitwidth_of); } - auto good() const noexcept -> bool + constexpr operator bool() const noexcept { - assert(data); return i < N; } - auto at_end() const noexcept -> bool - { - return not data or not good() or iter.at_end(); - } - - auto is_same_index(const_iterator const& other) const noexcept -> bool - { - return i == other.i and iter.is_same_index(other.iter); - } - friend auto operator ==(const_iterator const& a, const_iterator const& b) noexcept { - return a.is_same_index(b) or (a.at_end() and b.at_end()); + return not b ? not a : a.i == b.i and a.iter == b.iter; } friend auto operator !=(const_iterator const& a, const_iterator const& b) noexcept @@ -186,31 +182,6 @@ inline namespace memory } }; - static constexpr auto split(T p) noexcept - { - static_assert(E + (Es + ...) <= sizeof(T) * CHAR_BIT); - - struct big_endian - { - std::uintptr_t ignore : sizeof(std::uintptr_t) * CHAR_BIT - E - (Es + ...); - std::uintptr_t key : E - compressible_bitwidth_of; - std::uintptr_t value : (Es + ...); - std::uintptr_t : compressible_bitwidth_of; - }; - - struct little_endian - { - std::uintptr_t : compressible_bitwidth_of; - std::uintptr_t value : (Es + ...); - std::uintptr_t key : E - compressible_bitwidth_of; - std::uintptr_t ignore : sizeof(std::uintptr_t) * CHAR_BIT - E - (Es + ...); - }; - - const auto bits = bit_cast(p); - - return std::make_pair(bits.key, bits.value); - } - ~integer_set() { for (auto datum : data) @@ -219,48 +190,98 @@ inline namespace memory } } - auto insert(T value) + template + static constexpr auto split(std::uintptr_t x) { - if (auto [i, j] = split(value); data[i]) + constexpr auto mask = (static_cast(1) << X) - 1; + + constexpr auto width = (Xs + ... + compressible_bitwidth_of); + + if constexpr (0 < sizeof...(Xs)) { - data[i]->insert(j); + return std::tuple_cat(std::make_tuple(x >> width & mask), split(x)); } else { - max = std::max(max, i); - data[i] = new subset(); - data[i]->insert(j); + return std::make_tuple(x >> width & mask); } } - auto erase(T value) noexcept + template + auto insert(std::size_t i, Ts&&... xs) noexcept { - if (auto [i, j] = split(value); data[i]) + if (not data[i]) { - data[i]->erase(j); + hint = std::max(hint, i); + data[i] = new subset(); } + + data[i]->insert(std::forward(xs)...); } - auto contains(T value) noexcept -> bool + auto insert(T value) noexcept + { + return std::apply([this](auto&&... xs) + { + return this->insert(std::forward(xs)...); + }, + split(reinterpret_cast(value))); + } + + template + auto erase(std::size_t i, Ts&&... xs) noexcept + { + assert(data[i]); + data[i]->erase(std::forward(xs)...); + } + + auto erase(T value) noexcept { - auto [i, j] = split(value); - return data[i] and data[i]->contains(j); + return std::apply([this](auto&&... xs) + { + return this->erase(std::forward(xs)...); + }, + split(reinterpret_cast(value))); + } + + template + constexpr auto contains(std::size_t i, Ts&&... xs) const noexcept + { + return data[i] and data[i]->contains(std::forward(xs)...); + } + + constexpr auto contains(T value) const noexcept -> bool + { + return std::apply([this](auto&&... xs) + { + return this->contains(std::forward(xs)...); + }, + split(reinterpret_cast(value))); } auto begin() const noexcept { - return const_iterator(this, 0); + return const_iterator(data, 0); } auto end() const noexcept { - return const_iterator(this, N); + return const_iterator(data, N); + } + + template + auto lower_bound(std::size_t i, Ts&&... xs) const noexcept + { + return const_iterator(data, i, std::forward(xs)...); } auto lower_bound(T value) const noexcept { - auto [i, j] = split(value); - return const_iterator(this, i, j); + return std::apply([this](auto&&... xs) + { + return this->lower_bound(std::forward(xs)...); + }, + split(reinterpret_cast(value))); } auto size() const noexcept -> std::size_t @@ -277,17 +298,27 @@ inline namespace memory template struct integer_set { - static_assert(std::is_same_v); + static_assert(std::is_same_v); + + static constexpr auto N = 1_u64 << E; + + static constexpr auto Q = N / 64; - static constexpr auto N = 1ul << E; + static constexpr auto R = 63; - std::uint64_t data[N / 64] {}; + std::uint64_t data[Q] {}; + + static constexpr auto split = [](auto x) + { + return std::make_pair(reinterpret_cast(x) / 64, + reinterpret_cast(x) % 64); + }; struct const_iterator { using value_type = T; - using difference_type = std::ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = T *; @@ -301,20 +332,23 @@ inline namespace memory auto increment_unless_truthy() noexcept { - if (auto i = index / 64; i < N/64) + if (operator bool()) { - if (auto datum = data[i] & (~0ul << index % 64); datum) + auto [q, r] = split(index); + + if (auto b = std::countr_zero(data[q] & (~0_u64 << r)); b != 64) { - index = i * 64 + __builtin_ctzl(datum); - assert(data[index / 64] & (1ul << index % 64)); + index = q * 64 + b; + assert(data[index / 64] & (1_u64 << index % 64)); return; } - else while (++i < N/64) + + while (++q < Q) { - if (auto datum = data[i]; datum) + if (auto b = std::countr_zero(data[q]); b != 64) { - index = i * 64 + __builtin_ctzl(datum); - assert(data[index / 64] & (1ul << index % 64)); + index = q * 64 + b; + assert(data[index / 64] & (1_u64 << index % 64)); return; } } @@ -322,25 +356,28 @@ inline namespace memory index = N; - assert(not good()); + assert(not operator bool()); } auto decrement_unless_truthy() noexcept { - if (auto i = index / 64; i < N/64) + if (operator bool()) { - if (auto datum = data[i] & (~0ul >> (63 - index % 64)); datum) + auto [q, r] = split(index); + + if (auto b = std::countl_zero(data[q] & (~0_u64 >> (R - r))); b != 64) { - index = i * 64 + (63 - __builtin_clzl(datum)); - assert(data[index / 64] & (1ul << index % 64)); + index = q * 64 + R - b; + assert(data[index / 64] & (1_u64 << index % 64)); return; } - else while (--i < N/64) + + while (--q < Q) { - if (auto datum = data[i]; datum) + if (auto b = std::countl_zero(data[q]); b != 64) { - index = i * 64 + (63 - __builtin_clzl(datum)); - assert(data[index / 64] & (1ul << index % 64)); + index = q * 64 + R - b; + assert(data[index / 64] & (1_u64 << index % 64)); return; } } @@ -348,20 +385,20 @@ inline namespace memory index = N; - assert(not good()); + assert(not operator bool()); } constexpr const_iterator() = default; - explicit const_iterator(integer_set const* container, std::size_t i) noexcept - : data { container->data } - , index { i } + explicit const_iterator(std::uint64_t const* data, std::size_t index) noexcept + : data { data } + , index { index } { increment_unless_truthy(); } - explicit const_iterator(integer_set const* container) noexcept - : data { container->data } + explicit const_iterator(std::uint64_t const* data) noexcept + : data { data } , index { N - 1 } { decrement_unless_truthy(); @@ -381,31 +418,20 @@ inline namespace memory return *this; } - auto operator *() const noexcept + constexpr auto operator *() const noexcept { - assert(good()); + assert(operator bool()); return reinterpret_cast(index); } - auto good() const noexcept -> bool + constexpr operator bool() const noexcept { - assert(data); return index < N; } - auto at_end() const noexcept -> bool - { - return not data or not good(); - } - - auto is_same_index(const_iterator const& other) const noexcept -> bool - { - return index == other.index; - } - friend auto operator ==(const_iterator const& a, const_iterator const& b) noexcept { - return a.is_same_index(b) or (a.at_end() and b.at_end()); + return not b ? not a : a.index == b.index; } friend auto operator !=(const_iterator const& a, const_iterator const& b) noexcept @@ -416,31 +442,27 @@ inline namespace memory auto insert(T value) noexcept { - auto i = reinterpret_cast(value) / 64; - auto j = reinterpret_cast(value) % 64; - data[i] |= (1ul << j); + auto [q, r] = split(value); + data[q] |= (1_u64 << r); } auto erase(T value) noexcept { - auto i = reinterpret_cast(value) / 64; - auto j = reinterpret_cast(value) % 64; - data[i] &= ~(1ul << j); + auto [q, r] = split(value); + data[q] &= ~(1_u64 << r); } auto contains(T value) noexcept -> bool { - auto i = reinterpret_cast(value) / 64; - auto j = reinterpret_cast(value) % 64; - return data[i] & (1ul << j); + auto [q, r] = split(value); + return data[q] & (1_u64 << r); } auto lower_bound(T value) const noexcept { - return const_iterator(this, reinterpret_cast(value)); + return const_iterator(data, reinterpret_cast(value)); } }; -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_INTEGER_SET_HPP diff --git a/include/meevax/memory/literal.hpp b/include/meevax/memory/literal.hpp index 7649bc4d5..34e41526b 100644 --- a/include/meevax/memory/literal.hpp +++ b/include/meevax/memory/literal.hpp @@ -17,9 +17,7 @@ #ifndef INCLUDED_MEEVAX_MEMORY_LITERAL_HPP #define INCLUDED_MEEVAX_MEMORY_LITERAL_HPP -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { constexpr auto operator ""_KiB(unsigned long long size) { @@ -30,7 +28,6 @@ inline namespace memory { return size * 1024 * 1024; } -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_LITERAL_HPP diff --git a/include/meevax/memory/model.hpp b/include/meevax/memory/model.hpp index 889c1e94e..d11120390 100644 --- a/include/meevax/memory/model.hpp +++ b/include/meevax/memory/model.hpp @@ -17,9 +17,7 @@ #ifndef INCLUDED_MEEVAX_MEMORY_MODEL_HPP #define INCLUDED_MEEVAX_MEMORY_MODEL_HPP -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { struct model { @@ -35,7 +33,6 @@ inline namespace memory static auto name() -> char const*; }; -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_MODEL_HPP diff --git a/include/meevax/memory/nan_boxing_pointer.hpp b/include/meevax/memory/nan_boxing_pointer.hpp index ffe4c4358..df38ad2ff 100644 --- a/include/meevax/memory/nan_boxing_pointer.hpp +++ b/include/meevax/memory/nan_boxing_pointer.hpp @@ -17,18 +17,17 @@ #ifndef INCLUDED_MEEVAX_MEMORY_NAN_BOXING_POINTER_HPP #define INCLUDED_MEEVAX_MEMORY_NAN_BOXING_POINTER_HPP -#include +#include #include +#include #include +#include #include #include -#include #include -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { static_assert(std::numeric_limits::is_iec559 and sizeof(double) == 8); @@ -74,31 +73,24 @@ inline namespace memory constexpr nan_boxing_pointer(nan_boxing_pointer const&) = default; - auto reset(nan_boxing_pointer const& value) -> void - { - data = value.data; - } - #define DEFINE(TYPE, ...) \ explicit nan_boxing_pointer(TYPE const& value __VA_ARGS__) noexcept \ - : data { reinterpret_cast( \ - signature_##TYPE | bit_cast>(value)) } \ + : data { reinterpret_cast(signature_##TYPE | std::bit_cast>(value)) } \ {} \ \ auto reset(TYPE const& value __VA_ARGS__) noexcept -> void \ { \ - data = reinterpret_cast( \ - signature_##TYPE | bit_cast>(value)); \ - } static_assert(true) - - DEFINE(double, ); - DEFINE(T1, ); - DEFINE(T2, ); - DEFINE(T3, ); - DEFINE(T4, ); - DEFINE(T5, ); - DEFINE(T6, ); - DEFINE(pointer, = nullptr); + data = reinterpret_cast(signature_##TYPE | std::bit_cast>(value)); \ + } + + DEFINE(double, ) + DEFINE(T1, ) + DEFINE(T2, ) + DEFINE(T3, ) + DEFINE(T4, ) + DEFINE(T5, ) + DEFINE(T6, ) + DEFINE(pointer, = nullptr) #undef DEFINE @@ -111,22 +103,22 @@ inline namespace memory auto operator ->() const { - return get(); + return unsafe_get(); } auto operator *() const -> auto const& { - return *get(); + return *unsafe_get(); } auto operator *() -> auto & { - return *get(); + return *unsafe_get(); } explicit operator bool() const noexcept { - return get() != nullptr; + return dereferenceable() ? unsafe_get() != nullptr : false; } template @@ -134,13 +126,11 @@ inline namespace memory { if constexpr (std::is_same_v, double>) { - return bit_cast(data); + return std::bit_cast(data); } else { - return bit_cast>( - static_cast)>>( - reinterpret_cast(data) & mask_payload)); + return std::bit_cast>(static_cast)>>(payload())); } } @@ -156,7 +146,7 @@ inline namespace memory auto get() const noexcept -> pointer { - return dereferenceable() ? reinterpret_cast(reinterpret_cast(data) & mask_payload) : nullptr; + return dereferenceable() ? unsafe_get() : nullptr; } template @@ -165,6 +155,16 @@ inline namespace memory return type() == typeid(std::decay_t); } + auto reset(nan_boxing_pointer const& value) -> void + { + data = value.data; + } + + auto payload() const noexcept + { + return reinterpret_cast(data) & mask_payload; + } + auto signature() const noexcept { return reinterpret_cast(data) & mask_signature; @@ -191,6 +191,11 @@ inline namespace memory } } + auto unsafe_get() const noexcept + { + return reinterpret_cast(payload()); + } + auto write(std::ostream & os) const -> std::ostream & { switch (signature()) @@ -228,7 +233,7 @@ inline namespace memory } else { - return os << std::fixed << std::setprecision(17) << cyan(value); + return os << std::fixed << std::setprecision(std::numeric_limits::max_digits10) << cyan(value); } } } @@ -247,8 +252,7 @@ inline namespace memory { return not x.compare(y); } -} // namespace memory -} // namespace meevax +} // namespace meevax::memory template struct std::hash> diff --git a/include/meevax/memory/pointer_set.hpp b/include/meevax/memory/pointer_set.hpp index 94ce4a2fe..a299a5dc9 100644 --- a/include/meevax/memory/pointer_set.hpp +++ b/include/meevax/memory/pointer_set.hpp @@ -27,15 +27,12 @@ #include #include -#include #include #include #include #include -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { inline namespace v1 { @@ -53,7 +50,7 @@ inline namespace v1 { std::uintptr_t const value; - static constexpr auto width = log2(alignof(std::remove_pointer_t)) - 1; + static constexpr auto width = std::bit_width(alignof(std::remove_pointer_t)) - 1; constexpr compact_pointer(Pointer p) : value { reinterpret_cast(p) >> width } @@ -296,7 +293,6 @@ namespace v2 struct pointer_set : integer_set {}; } // namespace v2 -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_POINTER_SET_HPP diff --git a/include/meevax/memory/simple_pointer.hpp b/include/meevax/memory/simple_pointer.hpp index 17862c7c4..b27d02182 100644 --- a/include/meevax/memory/simple_pointer.hpp +++ b/include/meevax/memory/simple_pointer.hpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { template struct simple_pointer @@ -78,8 +76,7 @@ inline namespace memory { return x.get() != y.get(); } -} // namespace memory -} // namespace meevax +} // namespace meevax::memory template struct std::hash> diff --git a/include/meevax/memory/tagged_pointer.hpp b/include/meevax/memory/tagged_pointer.hpp index a3f788e38..e174a75ec 100644 --- a/include/meevax/memory/tagged_pointer.hpp +++ b/include/meevax/memory/tagged_pointer.hpp @@ -17,15 +17,13 @@ #ifndef INCLUDED_MEEVAX_MEMORY_TAGGED_POINTER_HPP #define INCLUDED_MEEVAX_MEMORY_TAGGED_POINTER_HPP +#include #include -#include #include #include -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { template , @@ -41,14 +39,14 @@ inline namespace memory explicit constexpr tagged_pointer(T_##TAG const& value) \ : simple_pointer { \ reinterpret_cast( \ - static_cast(bit_cast>(value)) << 32 | TAG) } \ + static_cast(std::bit_cast>(value)) << 32 | TAG) } \ {} \ \ auto operator =(T_##TAG const& value) -> auto & \ { \ simple_pointer::data \ = reinterpret_cast( \ - static_cast(bit_cast>(value)) << 32 | TAG); \ + static_cast(std::bit_cast>(value)) << 32 | TAG); \ return *this; \ } \ \ @@ -87,8 +85,8 @@ inline namespace memory template auto as() const { - return bit_cast>( - static_cast)>>( + return std::bit_cast>( + static_cast)>>( reinterpret_cast(simple_pointer::data) >> 32)); } @@ -123,7 +121,6 @@ inline namespace memory } } }; -} // namespace memory -} // namespace meevax +} // namespace meevax::memory #endif // INCLUDED_MEEVAX_MEMORY_TAGGED_POINTER_HPP diff --git a/include/meevax/type_traits/integer.hpp b/include/meevax/type_traits/integer.hpp index 7d24bfa7c..0513675ea 100644 --- a/include/meevax/type_traits/integer.hpp +++ b/include/meevax/type_traits/integer.hpp @@ -20,27 +20,67 @@ #include #include -namespace meevax +namespace meevax::inline type_traits { -inline namespace type_traits -{ - template - using intN_t = std::conditional_t>>>; - - static_assert(std::is_same_v, std::int8_t>); - static_assert(std::is_same_v, std::int16_t>); - static_assert(std::is_same_v, std::int32_t>); - static_assert(std::is_same_v, std::int64_t>); - - template - using uintN_t = std::conditional_t>>>; -} // namespace type_traits -} // namespace meevax + template + struct int8n; + + template <> + struct int8n<1> + { + using type = std::int8_t; + }; + + template <> + struct int8n<2> + { + using type = std::int16_t; + }; + + template <> + struct int8n<4> + { + using type = std::int32_t; + }; + + template <> + struct int8n<8> + { + using type = std::int64_t; + }; + + template + using int8n_t = typename int8n::type; + + template + struct uint8n; + + template <> + struct uint8n<1> + { + using type = std::uint8_t; + }; + + template <> + struct uint8n<2> + { + using type = std::uint16_t; + }; + + template <> + struct uint8n<4> + { + using type = std::uint32_t; + }; + + template <> + struct uint8n<8> + { + using type = std::uint64_t; + }; + + template + using uint8n_t = typename uint8n::type; +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_INTEGER_HPP diff --git a/include/meevax/type_traits/is_array_subscriptable.hpp b/include/meevax/type_traits/is_array_subscriptable.hpp index 0a2224da8..c608fda05 100644 --- a/include/meevax/type_traits/is_array_subscriptable.hpp +++ b/include/meevax/type_traits/is_array_subscriptable.hpp @@ -19,22 +19,22 @@ #include -namespace meevax -{ -inline namespace type_traits +namespace meevax::inline type_traits { template + [[deprecated]] struct is_array_subscriptable : public std::false_type {}; template + [[deprecated]] struct is_array_subscriptable()[std::declval()])>> : public std::true_type {}; template + [[deprecated]] inline constexpr auto is_array_subscriptable_v = is_array_subscriptable::value; -} // namespace type_traits -} // namespace meevax +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_IS_ARRAY_SUBSCRIPTABLE_HPP diff --git a/include/meevax/type_traits/is_dereferenceable.hpp b/include/meevax/type_traits/is_dereferenceable.hpp index 1ec3e18cf..381b7fa2c 100644 --- a/include/meevax/type_traits/is_dereferenceable.hpp +++ b/include/meevax/type_traits/is_dereferenceable.hpp @@ -19,20 +19,19 @@ #include -namespace meevax -{ -inline namespace type_traits +namespace meevax::inline type_traits { template + [[deprecated]] struct is_dereferenceable : public std::false_type {}; template + [[deprecated]] struct is_dereferenceable())>> : public std::true_type {}; -} // namespace type_traits -} // namespace meevax +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_IS_DEREFERENCEABLE_HPP diff --git a/include/meevax/type_traits/is_equality_comparable.hpp b/include/meevax/type_traits/is_equality_comparable.hpp index 9fd6ed4b3..badca8464 100644 --- a/include/meevax/type_traits/is_equality_comparable.hpp +++ b/include/meevax/type_traits/is_equality_comparable.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace type_traits +namespace meevax::inline type_traits { template struct is_equality_comparable @@ -40,7 +38,6 @@ inline namespace type_traits template inline constexpr bool is_equality_comparable_v = is_equality_comparable::value; -} // namespace type_traits -} // namespace meevax +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_IS_EQUALITY_COMPARABLE_HPP diff --git a/include/meevax/type_traits/is_output_streamable.hpp b/include/meevax/type_traits/is_output_streamable.hpp index eff1212c1..fe43b563c 100644 --- a/include/meevax/type_traits/is_output_streamable.hpp +++ b/include/meevax/type_traits/is_output_streamable.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace type_traits +namespace meevax::inline type_traits { template struct is_output_streamable : public std::false_type @@ -35,7 +33,6 @@ inline namespace type_traits template inline constexpr auto is_output_streamable_v = is_output_streamable::value; -} // namespace type_traits -} // namespace meevax +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_IS_OUTPUT_STREAMABLE_HPP diff --git a/include/meevax/type_traits/is_reference_wrapper.hpp b/include/meevax/type_traits/is_reference_wrapper.hpp index e49419765..2a6820944 100644 --- a/include/meevax/type_traits/is_reference_wrapper.hpp +++ b/include/meevax/type_traits/is_reference_wrapper.hpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace type_traits +namespace meevax::inline type_traits { template struct is_reference_wrapper @@ -32,7 +30,6 @@ inline namespace type_traits struct is_reference_wrapper> : public std::true_type {}; -} // namespace type_traits -} // namespace meevax +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_IS_REFERENCE_WRAPPER_HPP diff --git a/include/meevax/utility/combination.hpp b/include/meevax/utility/combination.hpp index 7908694df..9d4a81d83 100644 --- a/include/meevax/utility/combination.hpp +++ b/include/meevax/utility/combination.hpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { template struct make_combination; @@ -36,7 +34,6 @@ inline namespace kernel template using combination = typename make_combination, std::make_index_sequence>::type; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel #endif // INCLUDED_MEEVAX_UTILITY_COMBINATION_HPP diff --git a/include/meevax/utility/demangle.hpp b/include/meevax/utility/demangle.hpp index 684571fd9..ee6738372 100644 --- a/include/meevax/utility/demangle.hpp +++ b/include/meevax/utility/demangle.hpp @@ -20,14 +20,11 @@ #include #include -namespace meevax -{ -inline namespace utility +namespace meevax::inline utility { auto demangle(char const* const name) -> std::string; auto demangle(std::type_info const&) -> std::string; -} // namespace utility -} // namespace meevax +} // namespace meevax::utility #endif // INCLUDED_MEEVAX_UTILITY_DEMANGLE_HPP diff --git a/include/meevax/utility/hexdump.hpp b/include/meevax/utility/hexdump.hpp index e625262f2..d559072a0 100644 --- a/include/meevax/utility/hexdump.hpp +++ b/include/meevax/utility/hexdump.hpp @@ -17,13 +17,12 @@ #ifndef INCLUDED_MEEVAX_UTILITY_HEXDUMP #define INCLUDED_MEEVAX_UTILITY_HEXDUMP -#include // std::hex, +#include // std::endian +#include // std::hex #include // std::ostream #include // std::vector -namespace meevax -{ -inline namespace utility +namespace meevax::inline utility { template struct hexdump @@ -37,13 +36,21 @@ inline namespace utility } {} - // TODO UPDATE WITH STD::ENDIAN (C++20) auto operator()(std::ostream & os) const -> std::ostream & { - for (auto iter = data.rbegin(); iter != data.rend(); ++iter) // little endian - // for (auto iter = data.begin(); iter != data.end(); ++iter) // big endian + if constexpr (std::endian::native == std::endian::little) { - os << std::setw(2) << std::setfill('0') << std::hex << static_cast(*iter) << " "; + for (auto iter = data.rbegin(); iter != data.rend(); ++iter) + { + os << std::setw(2) << std::setfill('0') << std::hex << static_cast(*iter) << " "; + } + } + else + { + for (auto iter = data.begin(); iter != data.end(); ++iter) + { + os << std::setw(2) << std::setfill('0') << std::hex << static_cast(*iter) << " "; + } } return os; @@ -55,7 +62,6 @@ inline namespace utility { return hexdump(os); } -} // namespace utility -} // namespace meevax +} // namespace meevax::utility #endif // INCLUDED_MEEVAX_UTILITY_HEXDUMP diff --git a/include/meevax/utility/unwrap_reference_wrapper.hpp b/include/meevax/utility/unwrap_reference_wrapper.hpp index 9578d43e3..e742409ca 100644 --- a/include/meevax/utility/unwrap_reference_wrapper.hpp +++ b/include/meevax/utility/unwrap_reference_wrapper.hpp @@ -22,9 +22,7 @@ #include -namespace meevax -{ -inline namespace type_traits +namespace meevax::inline type_traits { inline auto unwrap_reference_wrapper = [](auto&& value) -> decltype(auto) { @@ -37,7 +35,6 @@ inline namespace type_traits return std::forward(value); } }; -} // namespace type_traits -} // namespace meevax +} // namespace meevax::type_traits #endif // INCLUDED_MEEVAX_TYPE_TRAITS_UNWRAP_REFERENCE_WRAPPER_HPP diff --git a/script/repl.sh b/script/repl.sh deleted file mode 100755 index e902e5bae..000000000 --- a/script/repl.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -e - - -export RLWRAP_EDITOR='vim -c "set filetype=scheme"' - -rlwrap --break-chars "(){}[].,;#@|'\`\"" \ - --complete-filenames \ - --multi-line \ - --quote-characters "\"" \ - meevax -i "$@" diff --git a/script/setup-macos-14.sh b/script/setup-macos-14.sh new file mode 120000 index 000000000..93f928f11 --- /dev/null +++ b/script/setup-macos-14.sh @@ -0,0 +1 @@ +setup-macos.sh \ No newline at end of file diff --git a/script/setup-macos.sh b/script/setup-macos.sh new file mode 100755 index 000000000..f9a325a75 --- /dev/null +++ b/script/setup-macos.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +required() +{ + echo gmp +} + +optional() +{ + echo gcc +} + +documentation() +{ + echo bibtex2html # script/references.sh + echo doxygen + echo pandoc # script/references.sh +} + +brew update + +if test "$#" -eq 0 +then + required | xargs brew install +else + for each in "$@" + do + case "$each" in + -a | --all ) ( required && optional && documentation ) | xargs brew install ;; + -d | --documentation ) ( documentation ) | xargs brew install ;; + -o | --optional ) ( optional ) | xargs brew install ;; + -r | --required ) ( required ) | xargs brew install ;; + esac + done +fi diff --git a/script/setup-ubuntu-22.04.sh b/script/setup-ubuntu-22.04.sh new file mode 120000 index 000000000..3a2605f79 --- /dev/null +++ b/script/setup-ubuntu-22.04.sh @@ -0,0 +1 @@ +setup-ubuntu.sh \ No newline at end of file diff --git a/script/setup-ubuntu-24.04.sh b/script/setup-ubuntu-24.04.sh new file mode 120000 index 000000000..3a2605f79 --- /dev/null +++ b/script/setup-ubuntu-24.04.sh @@ -0,0 +1 @@ +setup-ubuntu.sh \ No newline at end of file diff --git a/script/setup.sh b/script/setup-ubuntu.sh similarity index 81% rename from script/setup.sh rename to script/setup-ubuntu.sh index ab0455a22..98a769696 100755 --- a/script/setup.sh +++ b/script/setup-ubuntu.sh @@ -8,18 +8,18 @@ required() optional() { - echo kcachegrind - echo massif-visualizer + echo kcachegrind # script/callgrind.sh + echo massif-visualizer # script/massif.sh echo valgrind } documentation() { - echo bibtex2html - echo doxygen - wget -q https://github.com/jgm/pandoc/releases/download/3.3/pandoc-3.3-1-amd64.deb -P /tmp - echo /tmp/pandoc-3.3-1-amd64.deb + + echo bibtex2html # script/references.sh + echo doxygen + echo /tmp/pandoc-3.3-1-amd64.deb # script/references.sh } sudo apt update diff --git a/script/update.sh b/script/update.sh index a1d92b6f3..650ab7c45 100755 --- a/script/update.sh +++ b/script/update.sh @@ -8,16 +8,11 @@ build() { rm -rf "$1/build" cmake -B "$1/build" -S "$@" - cmake --build "$1/build" --target develop + cmake --build "$1/build" --target continuous-integration } echo "0.5.$(($(git rev-list --no-merges --count HEAD) - 3681))" > "$root/VERSION" -if dpkg --status meevax -then - sudo dpkg --purge meevax -fi - build "$root" "$@" build "$root/example" "$@" diff --git a/src/chrono/duration.cpp b/src/chrono/duration.cpp index 9a8b4f052..b5461e553 100644 --- a/src/chrono/duration.cpp +++ b/src/chrono/duration.cpp @@ -18,9 +18,7 @@ #include -namespace meevax -{ -inline namespace chrono +namespace meevax::inline chrono { auto operator <<(std::ostream & os, std::chrono::nanoseconds nanoseconds) -> std::ostream & { @@ -55,5 +53,4 @@ inline namespace chrono return os; } -} // namespace chrono -} // namespace meevax +} // namespace meevax::chrono diff --git a/src/kernel/binary_input_file_port.cpp b/src/kernel/binary_input_file_port.cpp index 32f8e544e..771506868 100644 --- a/src/kernel/binary_input_file_port.cpp +++ b/src/kernel/binary_input_file_port.cpp @@ -18,9 +18,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto binary_input_file_port::close() -> void { @@ -48,12 +46,12 @@ inline namespace kernel { if (auto buffer = std::vector(size); ifstream.read(reinterpret_cast(buffer.data()), size)) { - return make(buffer); + return make(direct_initialization, buffer.data(), buffer.size()); } else { buffer.resize(ifstream.gcount()); - return make(buffer); + return make(direct_initialization, buffer.data(), buffer.size()); } } @@ -78,5 +76,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("open-binary-input-file ", datum.name) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/binary_output_file_port.cpp b/src/kernel/binary_output_file_port.cpp index 2e7ff9455..028ba632e 100644 --- a/src/kernel/binary_output_file_port.cpp +++ b/src/kernel/binary_output_file_port.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto binary_output_file_port::close() -> void { @@ -43,7 +41,7 @@ inline namespace kernel auto binary_output_file_port::put(u8vector const& v) -> void { - for (auto u8 : v.valarray) + for (auto u8 : v.valarray()) { ofstream.write(reinterpret_cast(&u8), 1); } @@ -53,5 +51,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("open-binary-output-file ", datum.name) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/boolean.cpp b/src/kernel/boolean.cpp index 474e49422..acb1e75bb 100644 --- a/src/kernel/boolean.cpp +++ b/src/kernel/boolean.cpp @@ -17,12 +17,9 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { let const t = make(true); let const f = make(false); -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/boot.cpp b/src/kernel/boot.cpp index 8f8ba9004..90aba7752 100644 --- a/src/kernel/boot.cpp +++ b/src/kernel/boot.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -35,12 +36,36 @@ #include #include -namespace meevax -{ -inline namespace kernel +extern char ** environ; // for procedure get-environment-variables + +namespace meevax::inline kernel { auto boot() -> void { + #define EXPORT1(IDENTIFIER) \ + library.define(#IDENTIFIER, [](let const& xs) \ + { \ + return IDENTIFIER(car(xs)); \ + }) + + #define EXPORT2(IDENTIFIER) \ + library.define(#IDENTIFIER, [](let const& xs) \ + { \ + return IDENTIFIER(car(xs), cadr(xs)); \ + }) + + #define EXPORT1_RENAME(IDENTIFIER1, IDENTIFIER2) \ + library.define(IDENTIFIER2, [](let const& xs) \ + { \ + return IDENTIFIER1(car(xs)); \ + }) + + #define EXPORT2_RENAME(IDENTIFIER1, IDENTIFIER2) \ + library.define(IDENTIFIER2, [](let const& xs) \ + { \ + return IDENTIFIER1(car(xs), cadr(xs)); \ + }) + define("(meevax boolean)", [](library & library) { library.define("boolean?", [](let const& xs) @@ -260,25 +285,10 @@ inline namespace kernel radius * sin(angle)); }); - library.define("real-part", [](let const& xs) - { - return real_part(car(xs)); - }); - - library.define("imag-part", [](let const& xs) - { - return imag_part(car(xs)); - }); - - library.define("magnitude", [](let const& xs) - { - return magnitude(car(xs)); - }); - - library.define("angle", [](let const& xs) - { - return angle(car(xs)); - }); + EXPORT1(angle); + EXPORT1(magnitude); + EXPORT1_RENAME(imag_part, "imag-part"); + EXPORT1_RENAME(real_part, "real-part"); }); define("(meevax context)", [](library & library) @@ -314,20 +324,9 @@ inline namespace kernel define("(meevax comparator)", [](library & library) { - library.define("eq?", [](let const& xs) - { - return eq(car(xs), cadr(xs)); - }); - - library.define("eqv?", [](let const& xs) - { - return eqv(car(xs), cadr(xs)); - }); - - library.define("equal?", [](let const& xs) - { - return equal(car(xs), cadr(xs)); - }); + EXPORT2_RENAME(eq, "eq?"); + EXPORT2_RENAME(equal, "equal?"); + EXPORT2_RENAME(eqv, "eqv?"); }); define("(meevax core)", [](library & library) @@ -367,7 +366,7 @@ inline namespace kernel library.define("load", [](let const& xs) { - return car(xs).as().load(cadr(xs).as()); + return car(xs).as().load(static_cast(cadr(xs).as())); }); }); @@ -429,114 +428,182 @@ inline namespace kernel define("(meevax inexact)", [](library & library) { - library.define("finite?", [](let const& xs) - { - return is_finite(car(xs)); - }); - - library.define("infinite?", [](let const& xs) - { - return is_infinite(car(xs)); - }); - - library.define("nan?", [](let const& xs) + library.define("log", [](let const& xs) { - return is_nan(car(xs)); - }); + switch (length(xs)) + { + case 1: + return log(car(xs)); - library.define("exp", [](let const& xs) - { - return exp(car(xs)); - }); + case 2: + return log(car(xs)) / log(cadr(xs)); - library.define("sqrt", [](let const& xs) - { - return sqrt(car(xs)); + default: + throw error(make("procedure log takes one or two arguments, but got"), xs); + } }); - library.define("log", [](let const& xs) + library.define("atan", [](let const& xs) { switch (length(xs)) { case 1: - return log(car(xs)); + return atan(car(xs)); case 2: - return log(car(xs)) / log(cadr(xs)); + return atan2(car(xs), cadr(xs)); default: - throw error(make("procedure log takes one or two arguments, but got"), xs); + throw error(make("procedure atan takes one or two arguments, but got"), xs); } }); - library.define("sin", [](let const& xs) + EXPORT1(acos); + EXPORT1(acosh); + EXPORT1(asin); + EXPORT1(asinh); + EXPORT1(atanh); + EXPORT1(cos); + EXPORT1(cosh); + EXPORT1(erf); + EXPORT1(erfc); + EXPORT1(exp); + EXPORT1(expm1); + EXPORT1(fabs); + EXPORT1(lgamma); + EXPORT1(log1p); + EXPORT1(sin); + EXPORT1(sinh); + EXPORT1(sqrt); + EXPORT1(tan); + EXPORT1(tanh); + EXPORT1(tgamma); + + EXPORT1_RENAME(is_finite, "finite?"); + EXPORT1_RENAME(is_infinite, "infinite?"); + EXPORT1_RENAME(is_nan, "nan?"); + + EXPORT2(copysign); + EXPORT2(cyl_bessel_j); + EXPORT2(cyl_neumann); + EXPORT2(ldexp); + EXPORT2(nextafter); + + library.define("e", std::numbers::e); + + library.define("pi", std::numbers::pi); + + library.define("euler", std::numbers::egamma); + + library.define("phi", std::numbers::phi); + }); + + define("(meevax binary32)", [](library & library) + { + library.define("binary32?", [](let const& xs) { - return sin(car(xs)); + return std::numeric_limits::is_iec559 and car(xs).is(); }); + }); - library.define("cos", [](let const& xs) + define("(meevax binary64)", [](library & library) + { + library.define("binary64?", [](let const& xs) { - return cos(car(xs)); + return std::numeric_limits::is_iec559 and car(xs).is(); }); - library.define("tan", [](let const& xs) + library.define("binary64-least", std::numeric_limits::min()); + + library.define("binary64-greatest", std::numeric_limits::max()); + + library.define("binary64-epsilon", std::numeric_limits::epsilon()); + + library.define("binary64-integral-part", [](let const& xs) { - return tan(car(xs)); + auto integral_part = 0.0; + std::modf(car(xs).as(), &integral_part); + return make(integral_part); }); - library.define("asin", [](let const& xs) + library.define("binary64-fractional-part", [](let const& xs) { - return asin(car(xs)); + auto integral_part = 0.0; + return make(std::modf(car(xs).as(), &integral_part)); }); - library.define("acos", [](let const& xs) + library.define("binary64-log-binary", [](let const& xs) { - return acos(car(xs)); + return make(std::logb(car(xs).as())); }); - library.define("atan", [](let const& xs) + library.define("binary64-integer-log-binary", [](let const& xs) { - switch (length(xs)) - { - case 1: - return atan(car(xs)); + return make(std::ilogb(car(xs).as())); + }); - case 2: - return atan(car(xs), cadr(xs)); + library.define("binary64-normalized-fraction", [](let const& xs) + { + auto exponent = 0; + return make(std::frexp(car(xs).as(), &exponent)); + }); - default: - throw error(make("procedure atan takes one or two arguments, but got"), xs); - } + library.define("binary64-exponent", [](let const& xs) + { + auto exponent = 0; + std::frexp(car(xs).as(), &exponent); + return make(exponent); }); - library.define("sinh", [](let const& xs) + library.define("binary64-sign-bit", [](let const& xs) { - return sinh(car(xs)); + return make(std::signbit(car(xs).as())); }); - library.define("cosh", [](let const& xs) + library.define("binary64-normalized?", [](let const& xs) { - return cosh(car(xs)); + return std::fpclassify(car(xs).as()) == FP_NORMAL; }); - library.define("tanh", [](let const& xs) + library.define("binary64-denormalized?", [](let const& xs) { - return tanh(car(xs)); + return std::fpclassify(car(xs).as()) == FP_SUBNORMAL; }); - library.define("asinh", [](let const& xs) + library.define("binary64-max", [](let const& xs) { - return asinh(car(xs)); + auto max = -std::numeric_limits::infinity(); + + for (let const& x : xs) + { + max = std::fmax(max, x.as()); + } + + return make(max); + }); + + library.define("binary64-min", [](let const& xs) + { + auto min = std::numeric_limits::infinity(); + + for (let const& x : xs) + { + min = std::fmin(min, x.as()); + } + + return make(min); }); - library.define("acosh", [](let const& xs) + library.define("binary64-fused-multiply-add", [](let const& xs) { - return acosh(car(xs)); + return make(std::fma(car(xs).as(), cadr(xs).as(), caddr(xs).as())); }); - library.define("atanh", [](let const& xs) + library.define("binary64-remquo", [](let const& xs) { - return atanh(car(xs)); + auto quotient = 0; + auto remainder = std::remquo(car(xs).as(), cadr(xs).as(), "ient); + return cons(make(remainder), make(quotient)); }); }); @@ -547,10 +614,7 @@ inline namespace kernel return car(xs).is(); }); - library.define("list?", [](let const& xs) - { - return is_list(car(xs)); - }); + EXPORT1_RENAME(is_list, "list?"); library.define("list", [](let const& xs) { @@ -590,10 +654,7 @@ inline namespace kernel } }); - library.define("circular-list?", [](let const& xs) - { - return is_circular_list(car(xs)); - }); + EXPORT1_RENAME(is_circular_list, "circular-list?"); library.define("circular-list", [](let & xs) { @@ -601,10 +662,7 @@ inline namespace kernel return xs; }); - library.define("dotted-list?", [](let const& xs) - { - return is_dotted_list(car(xs)); - }); + EXPORT1_RENAME(is_dotted_list, "dotted-list?"); library.define("null-list?", [](let const& xs) { @@ -618,15 +676,9 @@ inline namespace kernel } }); - library.define("last", [](let const& xs) - { - return last(car(xs)); - }); + EXPORT1(last); - library.define("last-pair", [](let const& xs) - { - return last_pair(car(xs)); - }); + EXPORT1_RENAME(last_pair, "last-pair"); library.define("length", [](let const& xs) { @@ -652,23 +704,33 @@ inline namespace kernel library.define("append!", [](let & xs) { - return std::accumulate(xs.begin(), xs.end(), unit, [](let & x, let const& y) { return append(x, y); }); - }); + auto append = [](auto append, let & x, let & xs) -> auto & + { + if (xs.is()) + { + return x; + } + else if (x.is()) + { + return x = append(append, car(xs), cdr(xs)); + } + else + { + return meevax::append(x, append(append, car(xs), cdr(xs))); + } + }; - library.define("append-reverse", [](let const& xs) - { - return append_reverse(car(xs), cadr(xs)); + return not xs.is() ? xs : append(append, car(xs), cdr(xs)); }); + EXPORT2_RENAME(append_reverse, "append-reverse"); + library.define("append-reverse!", [](let & xs) { return append_reverse(car(xs), cadr(xs)); }); - library.define("reverse", [](let const& xs) - { - return reverse(car(xs)); - }); + EXPORT1(reverse); library.define("reverse!", [](let & xs) { @@ -682,14 +744,27 @@ inline namespace kernel library.define("concatenate!", [](let & xs) { - return std::accumulate(car(xs).begin(), car(xs).end(), unit, [](let & x, let const& y) { return append(x, y); }); - }); + auto concatenate = [](auto concatenate, let & x, let & xs) -> auto & + { + if (xs.is()) + { + return x; + } + else if (x.is()) + { + return x = concatenate(concatenate, car(xs), cdr(xs)); + } + else + { + return meevax::append(x, concatenate(concatenate, car(xs), cdr(xs))); + } + }; - library.define("list-copy", [](let const& xs) - { - return list_copy(car(xs)); + return not xs.is() ? xs : concatenate(concatenate, caar(xs), cdar(xs)); }); + EXPORT1_RENAME(list_copy, "list-copy"); + library.define("list-tail", [](let const& xs) { return tail(car(xs), cadr(xs).as()); @@ -700,55 +775,16 @@ inline namespace kernel return head(car(xs), cadr(xs).as()); }); - library.define("first", [](let const& xs) - { - return head(car(xs), 0); - }); - - library.define("second", [](let const& xs) - { - return head(car(xs), 1); - }); - - library.define("third", [](let const& xs) - { - return head(car(xs), 2); - }); - - library.define("fourth", [](let const& xs) - { - return head(car(xs), 3); - }); - - library.define("fifth", [](let const& xs) - { - return head(car(xs), 4); - }); - - library.define("sixth", [](let const& xs) - { - return head(car(xs), 5); - }); - - library.define("seventh", [](let const& xs) - { - return head(car(xs), 6); - }); - - library.define("eighth", [](let const& xs) - { - return head(car(xs), 7); - }); - - library.define("ninth", [](let const& xs) - { - return head(car(xs), 8); - }); - - library.define("tenth", [](let const& xs) - { - return head(car(xs), 9); - }); + library.define("first", [](let const& xs) { return head(car(xs), 0); }); + library.define("second", [](let const& xs) { return head(car(xs), 1); }); + library.define("third", [](let const& xs) { return head(car(xs), 2); }); + library.define("fourth", [](let const& xs) { return head(car(xs), 3); }); + library.define("fifth", [](let const& xs) { return head(car(xs), 4); }); + library.define("sixth", [](let const& xs) { return head(car(xs), 5); }); + library.define("seventh", [](let const& xs) { return head(car(xs), 6); }); + library.define("eighth", [](let const& xs) { return head(car(xs), 7); }); + library.define("ninth", [](let const& xs) { return head(car(xs), 8); }); + library.define("tenth", [](let const& xs) { return head(car(xs), 9); }); library.define("take", [](let const& xs) { @@ -780,73 +816,28 @@ inline namespace kernel return drop_right(car(xs), cadr(xs).as()); }); - library.define("memq", [](let const& xs) - { - return memq(car(xs), cadr(xs)); - }); - - library.define("memv", [](let const& xs) - { - return memv(car(xs), cadr(xs)); - }); - - library.define("assq", [](let const& xs) - { - return assq(car(xs), cadr(xs)); - }); - - library.define("assv", [](let const& xs) - { - return assv(car(xs), cadr(xs)); - }); + EXPORT2(memq); + EXPORT2(memv); + EXPORT2(assq); + EXPORT2(assv); library.define("alist-cons", [](let const& xs) { return alist_cons(car(xs), cadr(xs), caddr(xs)); }); - library.define("alist-copy", [](let const& xs) - { - return alist_copy(car(xs)); - }); + EXPORT1_RENAME(alist_copy, "alist-copy"); }); define("(meevax number)", [](library & library) { - library.define("number?", [](let const& xs) - { - return is_complex(car(xs)); - }); - - library.define("complex?", [](let const& xs) - { - return is_complex(car(xs)); - }); - - library.define("real?", [](let const& xs) - { - return is_real(car(xs)); - }); - - library.define("rational?", [](let const& xs) - { - return is_rational(car(xs)); - }); - - library.define("integer?", [](let const& xs) - { - return is_integer(car(xs)); - }); - - library.define("exact?", [](let const& xs) - { - return is_exact(car(xs)); - }); - - library.define("inexact?", [](let const& xs) - { - return is_inexact(car(xs)); - }); + EXPORT1_RENAME(is_complex, "number?"); + EXPORT1_RENAME(is_complex, "complex?"); + EXPORT1_RENAME(is_real, "real?"); + EXPORT1_RENAME(is_rational, "rational?"); + EXPORT1_RENAME(is_integer, "integer?"); + EXPORT1_RENAME(is_exact, "exact?"); + EXPORT1_RENAME(is_inexact, "inexact?"); library.define("exact-integer?", [](let const& xs) { @@ -878,39 +869,34 @@ inline namespace kernel return std::adjacent_find(xs.begin(), xs.end(), less_than) == xs.end(); }); - library.define("zero?", [](let const& xs) - { - return is_zero(car(xs)); - }); - - library.define("positive?", [](let const& xs) - { - return is_positive(car(xs)); - }); - - library.define("negative?", [](let const& xs) - { - return is_negative(car(xs)); - }); - - library.define("odd?", [](let const& xs) - { - return is_odd(car(xs)); - }); - - library.define("even?", [](let const& xs) - { - return is_even(car(xs)); - }); + EXPORT1_RENAME(is_zero, "zero?"); + EXPORT1_RENAME(is_positive, "positive?"); + EXPORT1_RENAME(is_negative, "negative?"); + EXPORT1_RENAME(is_odd, "odd?"); + EXPORT1_RENAME(is_even, "even?"); library.define("max", [](let const& xs) { - return max(xs); + if (auto iter = std::max_element(xs.begin(), xs.end(), less_than); iter != xs.end()) + { + return std::any_of(xs.begin(), xs.end(), is_inexact) ? inexact(*iter) : *iter; + } + else + { + return unspecified; + } }); library.define("min", [](let const& xs) { - return min(xs); + if (auto iter = std::min_element(xs.begin(), xs.end(), less_than); iter != xs.end()) + { + return std::any_of(xs.begin(), xs.end(), is_inexact) ? inexact(*iter) : *iter; + } + else + { + return unspecified; + } }); library.define("+", [](let const& xs) @@ -947,25 +933,10 @@ inline namespace kernel } }); - library.define("abs", [](let const& xs) - { - return abs(car(xs)); - }); - - library.define("quotient", [](let const& xs) - { - return quotient(car(xs), cadr(xs)); - }); - - library.define("remainder", [](let const& xs) - { - return remainder(car(xs), cadr(xs)); - }); - - library.define("modulo", [](let const& xs) - { - return modulo(car(xs), cadr(xs)); - }); + EXPORT1(abs); + EXPORT2(quotient); + EXPORT2(remainder); + EXPORT2(modulo); library.define("gcd", [](let const& xs) { @@ -997,58 +968,24 @@ inline namespace kernel } }); - library.define("numerator", [](let const& xs) - { - return numerator(car(xs)); - }); - - library.define("denominator", [](let const& xs) - { - return denominator(car(xs)); - }); - - library.define("floor", [](let const& xs) - { - return floor(car(xs)); - }); - - library.define("ceiling", [](let const& xs) - { - return ceil(car(xs)); - }); - - library.define("truncate", [](let const& xs) - { - return trunc(car(xs)); - }); - - library.define("round", [](let const& xs) - { - return round(car(xs)); - }); + EXPORT1(numerator); + EXPORT1(denominator); + EXPORT1(floor); + EXPORT1(ceiling); + EXPORT1(truncate); + EXPORT1(round); library.define("exact-integer-square-root", [](let const& xs) { - auto&& [s, r] = car(xs).as().square_root(); + auto&& [s, r] = car(xs).as().sqrt(); return cons(make(std::forward(s)), make(std::forward(r))); }); - library.define("expt", [](let const& xs) - { - return pow(car(xs), cadr(xs)); - }); - - library.define("exact", [](let const& xs) - { - return exact(car(xs)); - }); - - library.define("inexact", [](let const& xs) - { - return inexact(car(xs)); - }); + EXPORT2_RENAME(pow, "expt"); + EXPORT1(exact); + EXPORT1(inexact); library.define("number->string", [](let const& xs) { @@ -1093,10 +1030,7 @@ inline namespace kernel return not car(xs).is(); }); - library.define("cons", [](let const& xs) - { - return cons(car(xs), cadr(xs)); - }); + EXPORT2(cons); library.define("cons*", [](let & xs) { @@ -1128,49 +1062,39 @@ inline namespace kernel return cons(cadr(xs), car(xs)); }); - library.define("car", [](let const& xs) { return car(car(xs)); }); - library.define("cdr", [](let const& xs) { return cdr(car(xs)); }); - - library.define("caar", [](let const& xs) { return caar(car(xs)); }); - library.define("cadr", [](let const& xs) { return cadr(car(xs)); }); - library.define("cdar", [](let const& xs) { return cdar(car(xs)); }); - library.define("cddr", [](let const& xs) { return cddr(car(xs)); }); - - library.define("caaar", [](let const& xs) { return caaar(car(xs)); }); - library.define("caadr", [](let const& xs) { return caadr(car(xs)); }); - library.define("cadar", [](let const& xs) { return cadar(car(xs)); }); - library.define("caddr", [](let const& xs) { return caddr(car(xs)); }); - library.define("cdaar", [](let const& xs) { return cdaar(car(xs)); }); - library.define("cdadr", [](let const& xs) { return cdadr(car(xs)); }); - library.define("cddar", [](let const& xs) { return cddar(car(xs)); }); - library.define("cdddr", [](let const& xs) { return cdddr(car(xs)); }); - - library.define("caaaar", [](let const& xs) { return caaaar(car(xs)); }); - library.define("caaadr", [](let const& xs) { return caaadr(car(xs)); }); - library.define("caadar", [](let const& xs) { return caadar(car(xs)); }); - library.define("caaddr", [](let const& xs) { return caaddr(car(xs)); }); - library.define("cadaar", [](let const& xs) { return cadaar(car(xs)); }); - library.define("cadadr", [](let const& xs) { return cadadr(car(xs)); }); - library.define("caddar", [](let const& xs) { return caddar(car(xs)); }); - library.define("cadddr", [](let const& xs) { return cadddr(car(xs)); }); - library.define("cdaaar", [](let const& xs) { return cdaaar(car(xs)); }); - library.define("cdaadr", [](let const& xs) { return cdaadr(car(xs)); }); - library.define("cdadar", [](let const& xs) { return cdadar(car(xs)); }); - library.define("cdaddr", [](let const& xs) { return cdaddr(car(xs)); }); - library.define("cddaar", [](let const& xs) { return cddaar(car(xs)); }); - library.define("cddadr", [](let const& xs) { return cddadr(car(xs)); }); - library.define("cdddar", [](let const& xs) { return cdddar(car(xs)); }); - library.define("cddddr", [](let const& xs) { return cddddr(car(xs)); }); - - library.define("set-car!", [](let & xs) - { - caar(xs) = cadr(xs); - }); - - library.define("set-cdr!", [](let & xs) - { - cdar(xs) = cadr(xs); - }); + EXPORT1(car); + EXPORT1(cdr); + EXPORT1(caar); + EXPORT1(cadr); + EXPORT1(cdar); + EXPORT1(cddr); + EXPORT1(caaar); + EXPORT1(caadr); + EXPORT1(cadar); + EXPORT1(caddr); + EXPORT1(cdaar); + EXPORT1(cdadr); + EXPORT1(cddar); + EXPORT1(cdddr); + EXPORT1(caaaar); + EXPORT1(caaadr); + EXPORT1(caadar); + EXPORT1(caaddr); + EXPORT1(cadaar); + EXPORT1(cadadr); + EXPORT1(caddar); + EXPORT1(cadddr); + EXPORT1(cdaaar); + EXPORT1(cdaadr); + EXPORT1(cdadar); + EXPORT1(cdaddr); + EXPORT1(cddaar); + EXPORT1(cddadr); + EXPORT1(cdddar); + EXPORT1(cddddr); + + library.define("set-car!", [](let & xs) { caar(xs) = cadr(xs); }); + library.define("set-cdr!", [](let & xs) { cdar(xs) = cadr(xs); }); }); define("(meevax port)", [](library & library) @@ -1272,7 +1196,8 @@ inline namespace kernel library.define("get-output-u8vector", [](let const& xs) { - return make(car(xs).as().vector); + return make(car(xs).as().vector.data(), + car(xs).as().vector.size()); }); library.define("eof-object?", [](let const& xs) @@ -1873,10 +1798,7 @@ inline namespace kernel } }); - library.define("list->vector", [](let const& xs) - { - return make_vector(car(xs)); - }); + EXPORT1_RENAME(make_vector, "list->vector"); library.define("vector->string", [](let const& xs) { @@ -2031,10 +1953,10 @@ inline namespace kernel define("(meevax vector homogeneous)", [](library & library) { - #define DEFINE_VECTOR(TAG) \ + #define DEFINE_VECTOR_AUX(TAG, VECTOR) \ library.define(#TAG "vector?", [](let const& xs) \ { \ - return car(xs).is(); \ + return car(xs).is(); \ }); \ \ library.define("make-" #TAG "vector", [](let const& xs) \ @@ -2042,10 +1964,10 @@ inline namespace kernel switch (length(xs)) \ { \ case 1: \ - return make(car(xs).as(), unspecified); \ + return make(direct_initialization, static_cast(0), car(xs).as()); \ \ case 2: \ - return make(car(xs).as(), cadr(xs)); \ + return make(direct_initialization, VECTOR::input_cast(cadr(xs)), car(xs).as()); \ \ default: \ throw error(make("procedure make-" #TAG "vector takes one or two arguments, but got"), xs); \ @@ -2054,22 +1976,22 @@ inline namespace kernel \ library.define(#TAG "vector", [](let const& xs) \ { \ - return make(xs); \ + return make(from_list, xs); \ }); \ \ library.define(#TAG "vector-length", [](let const& xs) \ { \ - return make(car(xs).as().valarray.size()); \ + return make(car(xs).as().size()); \ }); \ \ library.define(#TAG "vector-ref", [](let const& xs) \ { \ - return TAG##vector::output_cast(car(xs).as().valarray[cadr(xs).as()]); \ + return VECTOR::output_cast(car(xs).as()[cadr(xs).as()]); \ }); \ \ library.define(#TAG "vector-set!", [](let const& xs) \ { \ - car(xs).as().valarray[cadr(xs).as()] = TAG##vector::input_cast(caddr(xs)); \ + car(xs).as()[cadr(xs).as()] = VECTOR::input_cast(caddr(xs)); \ }); \ \ library.define(#TAG "vector-copy", [](let const& xs) \ @@ -2077,16 +1999,29 @@ inline namespace kernel switch (length(xs)) \ { \ case 1: \ - return make(car(xs).as()); \ + { \ + std::size_t begin = 0; \ + std::size_t end = car(xs).as().size(); \ + assert(begin <= end); \ + return make(car(xs).as()[std::slice(begin, end - begin, 1)]); \ + } \ \ case 2: \ - return make(car(xs).as(), \ - cadr(xs).as()); \ + { \ + std::size_t begin = cadr(xs).as(); \ + std::size_t end = car(xs).as().size(); \ + assert(begin <= end); \ + return make(car(xs).as()[std::slice(begin, end - begin, 1)]); \ + } \ \ case 3: \ - return make(car(xs).as(), \ - cadr(xs).as(), \ - caddr(xs).as()); \ + { \ + std::size_t begin = cadr(xs).as(); \ + std::size_t end = caddr(xs).as(); \ + assert(begin <= end); \ + return make(car(xs).as()[std::slice(begin, end - begin, 1)]); \ + } \ + \ default: \ throw error(make("procedure " #TAG "vector-copy takes one to three arguments, but got"), xs); \ } \ @@ -2097,19 +2032,33 @@ inline namespace kernel switch (length(xs)) \ { \ case 3: \ - car(xs).as().slice(cadr(xs).as()) = \ - caddr(xs).as().slice(); \ + { \ + std::size_t at = cadr(xs).as(); \ + std::size_t begin = 0; \ + std::size_t end = caddr(xs).as().size(); \ + assert(begin <= end); \ + car(xs).as()[std::slice(at, end - begin, 1)] = caddr(xs).as()[std::slice(begin, end - begin, 1)]; \ + } \ break; \ \ case 4: \ - car(xs).as().slice(cadr(xs).as()) = \ - caddr(xs).as().slice(cadddr(xs).as()); \ + { \ + std::size_t at = cadr(xs).as(); \ + std::size_t begin = cadddr(xs).as(); \ + std::size_t end = caddr(xs).as().size(); \ + assert(begin <= end); \ + car(xs).as()[std::slice(at, end - begin, 1)] = caddr(xs).as()[std::slice(begin, end - begin, 1)]; \ + } \ break; \ \ case 5: \ - car(xs).as().slice(cadr(xs).as()) = \ - caddr(xs).as().slice(cadddr(xs).as(), \ - caddddr(xs).as()); \ + { \ + std::size_t at = cadr(xs).as(); \ + std::size_t begin = cadddr(xs).as(); \ + std::size_t end = caddddr(xs).as(); \ + assert(begin <= end); \ + car(xs).as()[std::slice(at, end - begin, 1)] = caddr(xs).as()[std::slice(begin, end - begin, 1)]; \ + } \ break; \ \ default: \ @@ -2119,8 +2068,12 @@ inline namespace kernel \ library.define(#TAG "vector-append", [](let const& xs) \ { \ - return make(car(xs).as(), \ - cadr(xs).as()); \ + auto const& a = car(xs).as(); \ + auto const& b = cadr(xs).as(); \ + let const c = make(direct_initialization, a.size() + b.size()); \ + c.as()[std::slice(0, a.size(), 1)] = a.valarray(); \ + c.as()[std::slice(a.size(), b.size(), 1)] = b.valarray(); \ + return c; \ }); \ \ library.define(#TAG "vector->list", [](let const& xs) \ @@ -2129,7 +2082,7 @@ inline namespace kernel { \ auto xcons = [](auto&& x, auto&& y) \ { \ - return cons(TAG##vector::output_cast(y), x); \ + return cons(VECTOR::output_cast(y), x); \ }; \ \ return reverse(std::accumulate(std::next(std::begin(v), a), \ @@ -2139,17 +2092,17 @@ inline namespace kernel switch (length(xs)) \ { \ case 1: \ - return list(car(xs).as().valarray, \ + return list(car(xs).as().valarray(), \ 0, \ - car(xs).as().valarray.size()); \ + car(xs).as().size()); \ \ case 2: \ - return list(car(xs).as().valarray, \ + return list(car(xs).as().valarray(), \ cadr(xs).as(), \ - car(xs).as().valarray.size()); \ + car(xs).as().size()); \ \ case 3: \ - return list(car(xs).as().valarray, \ + return list(car(xs).as().valarray(), \ cadr(xs).as(), \ caddr(xs).as()); \ \ @@ -2160,14 +2113,17 @@ inline namespace kernel \ library.define("list->" #TAG "vector", [](let const& xs) \ { \ - return make(car(xs)); \ + return make(from_list, car(xs)); \ }) + #define DEFINE_VECTOR(TAG) DEFINE_VECTOR_AUX(TAG, TAG##vector) + DEFINE_VECTOR(s8); DEFINE_VECTOR(s16); DEFINE_VECTOR(s32); DEFINE_VECTOR(s64); DEFINE_VECTOR(u8); DEFINE_VECTOR(u16); DEFINE_VECTOR(u32); DEFINE_VECTOR(u64); DEFINE_VECTOR(f32); DEFINE_VECTOR(f64); #undef DEFINE_VECTOR + #undef DEFINE_VECTOR_AUX library.define("u8vector->string", [](let const& xs) { @@ -2181,20 +2137,23 @@ inline namespace kernel switch (length(xs)) { case 1: - std::for_each(std::begin(car(xs).as().valarray), - std::end(car(xs).as().valarray), + std::for_each(std::begin(car(xs).as().valarray()), + std::end(car(xs).as().valarray()), print); break; case 2: - std::for_each(std::next(std::begin(car(xs).as().valarray), cadr(xs).as()), - std::end(car(xs).as().valarray), + std::for_each(std::next(std::begin(car(xs).as().valarray()), + cadr(xs).as()), + std::end(car(xs).as().valarray()), print); break; case 3: - std::for_each(std::next(std::begin(car(xs).as().valarray), cadr(xs).as()), - std::next(std::begin(car(xs).as().valarray), caddr(xs).as()), + std::for_each(std::next(std::begin(car(xs).as().valarray()), + cadr(xs).as()), + std::next(std::begin(car(xs).as().valarray()), + caddr(xs).as()), print); break; @@ -2257,5 +2216,4 @@ inline namespace kernel }); }); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/box.cpp b/src/kernel/box.cpp index ba7624005..e53aec6c4 100644 --- a/src/kernel/box.cpp +++ b/src/kernel/box.cpp @@ -16,13 +16,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, box const& datum) -> std::ostream & { return os << magenta("#,(") << green("box ") << datum.first << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/character.cpp b/src/kernel/character.cpp index 107b8c49f..e91b1f7c2 100644 --- a/src/kernel/character.cpp +++ b/src/kernel/character.cpp @@ -19,9 +19,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { character::operator std::string() const { @@ -79,11 +77,4 @@ inline namespace kernel return os << cyan(static_cast(datum)); } } - - static_assert(std::is_pod_v); - - static_assert(std::is_standard_layout_v); - - static_assert(std::is_trivial_v); -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/closure.cpp b/src/kernel/closure.cpp index e5c9d58a6..e549dc7a0 100644 --- a/src/kernel/closure.cpp +++ b/src/kernel/closure.cpp @@ -16,13 +16,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, closure const& datum) -> std::ostream & { return os << magenta("#,(") << green("closure ") << faint("#;", &datum) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/comparator.cpp b/src/kernel/comparator.cpp index 60013845b..da61e9cb9 100644 --- a/src/kernel/comparator.cpp +++ b/src/kernel/comparator.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto find(object & b) -> object & { @@ -100,5 +98,4 @@ inline namespace kernel auto forest = std::unordered_map(); return equal(x, y, forest); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/complex.cpp b/src/kernel/complex.cpp index 659d61be9..4a7ff74a7 100644 --- a/src/kernel/complex.cpp +++ b/src/kernel/complex.cpp @@ -19,9 +19,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { complex::complex(std::string const& token, int radix) { @@ -70,13 +68,52 @@ inline namespace kernel return first; } - complex::operator std::complex() + complex::operator std::complex() const + { + assert(is_real(real())); + assert(is_real(imag())); + + auto to_int = [](let const& x) + { + if (x.is()) + { + return static_cast(x.as()); + } + else if (x.is()) + { + return static_cast(x.as()); + } + else + { + assert(x.is()); + return static_cast(x.as()); + } + }; + + return std::complex(to_int(exact(real())), + to_int(exact(imag()))); + } + + complex::operator std::complex() const { assert(is_real(real())); assert(is_real(imag())); - return std::complex(inexact(real()).as(), - inexact(imag()).as()); + auto to_double = [](let const& x) + { + if (x.is()) + { + return x.as(); + } + else + { + assert(x.is()); + return static_cast(x.as()); + } + }; + + return std::complex(to_double(inexact(real())), + to_double(inexact(imag()))); } auto operator <<(std::ostream & os, complex const& z) -> std::ostream & @@ -127,8 +164,7 @@ inline namespace kernel auto angle(object const& x) -> object { - return atan(real_part(x), - imag_part(x)); + return atan2(real_part(x), + imag_part(x)); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/conditional_expand.cpp b/src/kernel/conditional_expand.cpp index 4907176a7..aa93cc5bf 100644 --- a/src/kernel/conditional_expand.cpp +++ b/src/kernel/conditional_expand.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto test(object const& requirement) -> bool { @@ -70,5 +68,4 @@ inline namespace kernel throw error(make("no matching clauses were found"), clauses); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/continuation.cpp b/src/kernel/continuation.cpp index 49cdda9d2..e02811e29 100644 --- a/src/kernel/continuation.cpp +++ b/src/kernel/continuation.cpp @@ -16,13 +16,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, continuation const& datum) -> std::ostream & { return os << magenta("#,(") << green("continuation ") << faint(";#", std::addressof(datum)) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/dynamic_environment.cpp b/src/kernel/dynamic_environment.cpp index 62264a1a6..9223ec560 100644 --- a/src/kernel/dynamic_environment.cpp +++ b/src/kernel/dynamic_environment.cpp @@ -22,9 +22,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto dynamic_environment::execute(object const& control) -> object { @@ -505,5 +503,4 @@ inline namespace kernel } } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/environment.cpp b/src/kernel/environment.cpp index 4b0fc8227..39e5afd08 100644 --- a/src/kernel/environment.cpp +++ b/src/kernel/environment.cpp @@ -19,9 +19,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto environment::evaluate(object const& expression) -> object try { @@ -245,9 +243,9 @@ inline namespace kernel } } - auto environment::load(std::string const& s) -> void + auto environment::load(std::filesystem::path const& p) -> void { - if (auto input = input_file_port(s); input.is_open()) + if (auto input = input_file_port(p); input.is_open()) { for (let const& x : input) { @@ -257,7 +255,7 @@ inline namespace kernel else { throw file_error(make("failed to open file"), - make(s)); + make(p)); } } @@ -269,5 +267,4 @@ inline namespace kernel template struct configurator; template struct syntactic_environment; -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/eof.cpp b/src/kernel/eof.cpp index 3d94b1220..0881728fc 100644 --- a/src/kernel/eof.cpp +++ b/src/kernel/eof.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { let const eof_object = make(); @@ -26,5 +24,4 @@ inline namespace kernel { return os << magenta("#,(") << green("eof-object") << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/error.cpp b/src/kernel/error.cpp index ec56ed6b2..c3d5aa776 100644 --- a/src/kernel/error.cpp +++ b/src/kernel/error.cpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto error::irritants() const noexcept -> object const& { @@ -190,5 +188,4 @@ inline namespace kernel return os << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/exact_integer.cpp b/src/kernel/exact_integer.cpp index 3c498d050..c9d420386 100644 --- a/src/kernel/exact_integer.cpp +++ b/src/kernel/exact_integer.cpp @@ -20,9 +20,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { let const e0 = make(0); let const e1 = make(1); @@ -53,51 +51,6 @@ inline namespace kernel mpz_init_set(value, z); } - exact_integer::exact_integer(std::int8_t si) - { - mpz_init_set_si(value, si); - } - - exact_integer::exact_integer(std::int16_t si) - { - mpz_init_set_si(value, si); - } - - exact_integer::exact_integer(std::int32_t si) - { - mpz_init_set_si(value, si); - } - - exact_integer::exact_integer(std::int64_t si) - { - mpz_init_set_si(value, si); - } - - exact_integer::exact_integer(std::uint8_t ui) - { - mpz_init_set_ui(value, ui); - } - - exact_integer::exact_integer(std::uint16_t ui) - { - mpz_init_set_ui(value, ui); - } - - exact_integer::exact_integer(std::uint32_t ui) - { - mpz_init_set_ui(value, ui); - } - - exact_integer::exact_integer(std::uint64_t ui) - { - mpz_init_set_ui(value, ui); - } - - exact_integer::exact_integer(double d) - { - mpz_init_set_d(value, d); - } - exact_integer::exact_integer(std::string const& s, int radix) { if (mpz_init_set_str(value, (s.at(0) == '+' ? s.substr(1) : s).c_str(), radix)) @@ -136,87 +89,15 @@ inline namespace kernel return (*value)._mp_size; } - exact_integer::operator std::int8_t() const - { - return mpz_get_si(value); - } - - exact_integer::operator std::int16_t() const - { - return mpz_get_si(value); - } - - exact_integer::operator std::int32_t() const - { - return mpz_get_si(value); - } - - exact_integer::operator std::int64_t() const - { - return mpz_get_si(value); - } - - exact_integer::operator std::uint8_t() const - { - return mpz_get_ui(value); - } - - exact_integer::operator std::uint16_t() const - { - return mpz_get_ui(value); - } - - exact_integer::operator std::uint32_t() const - { - return mpz_get_ui(value); - } - - exact_integer::operator std::uint64_t() const - { - return mpz_get_ui(value); - } - - exact_integer::operator float() const - { - return mpz_get_d(value); - } - - exact_integer::operator double() const - { - return mpz_get_d(value); - } - - auto exact_integer::square_root() const -> std::tuple + auto exact_integer::sqrt() const -> std::tuple { exact_integer s, r; mpz_rootrem(s.value, r.value, value, 2); return std::make_tuple(s, r); } - auto operator ==(exact_integer const& a, int const b) -> bool { return a == static_cast(b); } - auto operator !=(exact_integer const& a, int const b) -> bool { return a != static_cast(b); } - auto operator < (exact_integer const& a, int const b) -> bool { return a < static_cast(b); } - auto operator <=(exact_integer const& a, int const b) -> bool { return a <= static_cast(b); } - auto operator > (exact_integer const& a, int const b) -> bool { return a > static_cast(b); } - auto operator >=(exact_integer const& a, int const b) -> bool { return a >= static_cast(b); } - - auto operator ==(exact_integer const& a, signed long const b) -> bool { return mpz_cmp_si(a.value, b) == 0; } - auto operator !=(exact_integer const& a, signed long const b) -> bool { return mpz_cmp_si(a.value, b) != 0; } - auto operator < (exact_integer const& a, signed long const b) -> bool { return mpz_cmp_si(a.value, b) < 0; } - auto operator <=(exact_integer const& a, signed long const b) -> bool { return mpz_cmp_si(a.value, b) <= 0; } - auto operator > (exact_integer const& a, signed long const b) -> bool { return mpz_cmp_si(a.value, b) > 0; } - auto operator >=(exact_integer const& a, signed long const b) -> bool { return mpz_cmp_si(a.value, b) >= 0; } - - auto operator ==(exact_integer const& a, unsigned long const b) -> bool { return mpz_cmp_ui(a.value, b) == 0; } - auto operator !=(exact_integer const& a, unsigned long const b) -> bool { return mpz_cmp_ui(a.value, b) != 0; } - auto operator < (exact_integer const& a, unsigned long const b) -> bool { return mpz_cmp_ui(a.value, b) < 0; } - auto operator <=(exact_integer const& a, unsigned long const b) -> bool { return mpz_cmp_ui(a.value, b) <= 0; } - auto operator > (exact_integer const& a, unsigned long const b) -> bool { return mpz_cmp_ui(a.value, b) > 0; } - auto operator >=(exact_integer const& a, unsigned long const b) -> bool { return mpz_cmp_ui(a.value, b) >= 0; } - auto operator <<(std::ostream & os, exact_integer const& datum) -> std::ostream & { return os << cyan(std::unique_ptr(mpz_get_str(nullptr, 10, datum.value)).get()); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/ghost.cpp b/src/kernel/ghost.cpp index eefff637c..589ba02e4 100644 --- a/src/kernel/ghost.cpp +++ b/src/kernel/ghost.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, ghost const& ghost) -> std::ostream & { @@ -28,5 +26,4 @@ inline namespace kernel let const unspecified = make("unspecified"); let const undefined = make("undefined"); -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/identity.cpp b/src/kernel/identity.cpp index df5a8df5c..6f447147d 100644 --- a/src/kernel/identity.cpp +++ b/src/kernel/identity.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, absolute const& datum) -> std::ostream & { @@ -32,5 +30,4 @@ inline namespace kernel return os << blue(datum.first); } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/include.cpp b/src/kernel/include.cpp index df0e0485b..24fc0f8b4 100644 --- a/src/kernel/include.cpp +++ b/src/kernel/include.cpp @@ -19,9 +19,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto include(object const& names, bool case_sensitive, object const& xs) -> object { @@ -53,5 +51,4 @@ inline namespace kernel return reverse(xs); } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/input_file_port.cpp b/src/kernel/input_file_port.cpp index 52a3222d1..23ddddbf2 100644 --- a/src/kernel/input_file_port.cpp +++ b/src/kernel/input_file_port.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto input_file_port::close() -> void { @@ -44,5 +42,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("open-input-file ") << string(datum.name) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/input_string_port.cpp b/src/kernel/input_string_port.cpp index a9e0b251f..a1bae3a3f 100644 --- a/src/kernel/input_string_port.cpp +++ b/src/kernel/input_string_port.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto input_string_port::close() -> void {} @@ -51,5 +49,4 @@ namespace literals return input_string_port(s).read(); } } // namespace literals -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/instruction.cpp b/src/kernel/instruction.cpp index e2e1d9dc3..c09e0744d 100644 --- a/src/kernel/instruction.cpp +++ b/src/kernel/instruction.cpp @@ -18,9 +18,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, instruction const& datum) -> std::ostream & { @@ -55,5 +53,4 @@ inline namespace kernel return os; } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/interaction_environment.cpp b/src/kernel/interaction_environment.cpp index f1ce7ed85..518baf58b 100644 --- a/src/kernel/interaction_environment.cpp +++ b/src/kernel/interaction_environment.cpp @@ -17,14 +17,11 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto interaction_environment() -> object const& { let static const interaction_environment = make(); return interaction_environment; } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/library.cpp b/src/kernel/library.cpp index 7a2e65e59..5e6a27876 100644 --- a/src/kernel/library.cpp +++ b/src/kernel/library.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { library::library(object const& declarations) : declarations { declarations } @@ -106,5 +104,4 @@ inline namespace kernel static auto libraries = std::map(); return libraries; } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/list.cpp b/src/kernel/list.cpp index 4b35dd936..c76b6c84c 100644 --- a/src/kernel/list.cpp +++ b/src/kernel/list.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto make_list(std::size_t size, object const& x) -> object { @@ -441,5 +439,4 @@ inline namespace kernel return length(x) < length(y) ? y : x; } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/number.cpp b/src/kernel/number.cpp index ffd3f37f2..6c79b5711 100644 --- a/src/kernel/number.cpp +++ b/src/kernel/number.cpp @@ -24,9 +24,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator + (exact_integer const& a, exact_integer const& b) -> exact_integer { exact_integer n; mpz_add(n.value, a.value, b.value); return n; } auto operator - (exact_integer const& a, exact_integer const& b) -> exact_integer { exact_integer n; mpz_sub(n.value, a.value, b.value); return n; } @@ -44,7 +42,7 @@ inline namespace kernel auto operator - (exact_integer const& a, ratio const& b) -> ratio { ratio q; mpq_sub(q.value, ratio(a).value, b.value); return q; } auto operator * (exact_integer const& a, ratio const& b) -> ratio { ratio q; mpq_mul(q.value, ratio(a).value, b.value); return q; } auto operator / (exact_integer const& a, ratio const& b) -> ratio { ratio q; mpq_div(q.value, ratio(a).value, b.value); return q; } - auto operator % (exact_integer const& , ratio const& ) -> ratio { throw std::invalid_argument("unsupported operation"); } + auto operator % (exact_integer const& , ratio const& ) -> ratio { throw std::invalid_argument("unimplemented operation"); } auto operator ==(exact_integer const& a, ratio const& b) -> bool { return 0 == mpq_cmp_z(b.value, a.value); } auto operator !=(exact_integer const& a, ratio const& b) -> bool { return 0 != mpq_cmp_z(b.value, a.value); } auto operator < (exact_integer const& a, ratio const& b) -> bool { return 0 < mpq_cmp_z(b.value, a.value); } @@ -52,23 +50,23 @@ inline namespace kernel auto operator > (exact_integer const& a, ratio const& b) -> bool { return 0 > mpq_cmp_z(b.value, a.value); } auto operator >=(exact_integer const& a, ratio const& b) -> bool { return 0 >= mpq_cmp_z(b.value, a.value); } - auto operator + (exact_integer const& a, float b) -> float { return inexact_cast(a) + b; } - auto operator - (exact_integer const& a, float b) -> float { return inexact_cast(a) - b; } - auto operator * (exact_integer const& a, float b) -> float { return inexact_cast(a) * b; } - auto operator / (exact_integer const& a, float b) -> float { return inexact_cast(a) / b; } - auto operator % (exact_integer const& a, float b) -> float { return std::remainder(inexact_cast(a), b); } - auto operator ==(exact_integer const& a, float b) -> bool { return inexact_equals(inexact_cast(a), b); } + auto operator + (exact_integer const& a, float b) -> float { return static_cast(a) + b; } + auto operator - (exact_integer const& a, float b) -> float { return static_cast(a) - b; } + auto operator * (exact_integer const& a, float b) -> float { return static_cast(a) * b; } + auto operator / (exact_integer const& a, float b) -> float { return static_cast(a) / b; } + auto operator % (exact_integer const& a, float b) -> float { return std::remainder(static_cast(a), b); } + auto operator ==(exact_integer const& a, float b) -> bool { return inexact_equals(static_cast(a), b); } auto operator !=(exact_integer const& a, float b) -> bool { return not (a == b); } - auto operator < (exact_integer const& a, float b) -> bool { return inexact_cast(a) < b; } - auto operator <=(exact_integer const& a, float b) -> bool { return inexact_cast(a) <= b; } - auto operator > (exact_integer const& a, float b) -> bool { return inexact_cast(a) > b; } - auto operator >=(exact_integer const& a, float b) -> bool { return inexact_cast(a) >= b; } - - auto operator + (exact_integer const& a, double b) -> double { return inexact_cast(a) + b; } - auto operator - (exact_integer const& a, double b) -> double { return inexact_cast(a) - b; } - auto operator * (exact_integer const& a, double b) -> double { return inexact_cast(a) * b; } - auto operator / (exact_integer const& a, double b) -> double { return inexact_cast(a) / b; } - auto operator % (exact_integer const& a, double b) -> double { return std::remainder(inexact_cast(a), b); } + auto operator < (exact_integer const& a, float b) -> bool { return static_cast(a) < b; } + auto operator <=(exact_integer const& a, float b) -> bool { return static_cast(a) <= b; } + auto operator > (exact_integer const& a, float b) -> bool { return static_cast(a) > b; } + auto operator >=(exact_integer const& a, float b) -> bool { return static_cast(a) >= b; } + + auto operator + (exact_integer const& a, double b) -> double { return static_cast(a) + b; } + auto operator - (exact_integer const& a, double b) -> double { return static_cast(a) - b; } + auto operator * (exact_integer const& a, double b) -> double { return static_cast(a) * b; } + auto operator / (exact_integer const& a, double b) -> double { return static_cast(a) / b; } + auto operator % (exact_integer const& a, double b) -> double { return std::remainder(static_cast(a), b); } auto operator ==(exact_integer const& a, double b) -> bool { return mpz_cmp_d(a.value, b) == 0; } auto operator !=(exact_integer const& a, double b) -> bool { return mpz_cmp_d(a.value, b) != 0; } auto operator < (exact_integer const& a, double b) -> bool { return mpz_cmp_d(a.value, b) < 0; } @@ -80,19 +78,14 @@ inline namespace kernel auto operator - (exact_integer const& a, complex const& b) -> complex { return complex(make(a), e0) - b; } auto operator * (exact_integer const& a, complex const& b) -> complex { return complex(make(a), e0) * b; } auto operator / (exact_integer const& a, complex const& b) -> complex { return complex(make(a), e0) / b; } - auto operator % (exact_integer const& , complex const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(exact_integer const& a, complex const& b) -> bool { return complex(make(a), e0) == b; } auto operator !=(exact_integer const& a, complex const& b) -> bool { return complex(make(a), e0) != b; } - auto operator < (exact_integer const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(exact_integer const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (exact_integer const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(exact_integer const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } auto operator + (ratio const& a, exact_integer const& b) -> ratio { ratio q; mpq_add(q.value, a.value, ratio(b).value); return q; } auto operator - (ratio const& a, exact_integer const& b) -> ratio { ratio q; mpq_sub(q.value, a.value, ratio(b).value); return q; } auto operator * (ratio const& a, exact_integer const& b) -> ratio { ratio q; mpq_mul(q.value, a.value, ratio(b).value); return q; } auto operator / (ratio const& a, exact_integer const& b) -> ratio { ratio q; mpq_div(q.value, a.value, ratio(b).value); return q; } - auto operator % (ratio const& , exact_integer const& ) -> ratio { throw std::invalid_argument("unsupported operation"); } + auto operator % (ratio const& , exact_integer const& ) -> ratio { throw std::invalid_argument("unimplemented operation"); } auto operator ==(ratio const& a, exact_integer const& b) -> bool { return mpq_cmp_z(a.value, b.value) == 0; } auto operator !=(ratio const& a, exact_integer const& b) -> bool { return mpq_cmp_z(a.value, b.value) != 0; } auto operator < (ratio const& a, exact_integer const& b) -> bool { return mpq_cmp_z(a.value, b.value) < 0; } @@ -104,7 +97,7 @@ inline namespace kernel auto operator - (ratio const& a, ratio const& b) -> ratio { ratio q; mpq_sub(q.value, a.value, b.value); return q; } auto operator * (ratio const& a, ratio const& b) -> ratio { ratio q; mpq_mul(q.value, a.value, b.value); return q; } auto operator / (ratio const& a, ratio const& b) -> ratio { ratio q; mpq_div(q.value, a.value, b.value); return q; } - auto operator % (ratio const& , ratio const& ) -> ratio { throw std::invalid_argument("unsupported operation"); } + auto operator % (ratio const& , ratio const& ) -> ratio { throw std::invalid_argument("unimplemented operation"); } auto operator ==(ratio const& a, ratio const& b) -> bool { return mpq_cmp(a.value, b.value) == 0; } auto operator !=(ratio const& a, ratio const& b) -> bool { return mpq_cmp(a.value, b.value) != 0; } auto operator < (ratio const& a, ratio const& b) -> bool { return mpq_cmp(a.value, b.value) < 0; } @@ -112,83 +105,73 @@ inline namespace kernel auto operator > (ratio const& a, ratio const& b) -> bool { return mpq_cmp(a.value, b.value) > 0; } auto operator >=(ratio const& a, ratio const& b) -> bool { return mpq_cmp(a.value, b.value) >= 0; } - auto operator + (ratio const& a, float b) -> float { return inexact_cast(a) + b; } - auto operator - (ratio const& a, float b) -> float { return inexact_cast(a) - b; } - auto operator * (ratio const& a, float b) -> float { return inexact_cast(a) * b; } - auto operator / (ratio const& a, float b) -> float { return inexact_cast(a) / b; } - auto operator % (ratio const& a, float b) -> float { return std::remainder(inexact_cast(a), b); } - auto operator ==(ratio const& a, float b) -> bool { return inexact_equals(inexact_cast(a), b); } + auto operator + (ratio const& a, float b) -> float { return static_cast(a) + b; } + auto operator - (ratio const& a, float b) -> float { return static_cast(a) - b; } + auto operator * (ratio const& a, float b) -> float { return static_cast(a) * b; } + auto operator / (ratio const& a, float b) -> float { return static_cast(a) / b; } + auto operator % (ratio const& a, float b) -> float { return std::remainder(static_cast(a), b); } + auto operator ==(ratio const& a, float b) -> bool { return inexact_equals(static_cast(a), b); } auto operator !=(ratio const& a, float b) -> bool { return not (a == b); } - auto operator < (ratio const& a, float b) -> bool { return inexact_cast(a) < b; } - auto operator <=(ratio const& a, float b) -> bool { return inexact_cast(a) <= b; } - auto operator > (ratio const& a, float b) -> bool { return inexact_cast(a) > b; } - auto operator >=(ratio const& a, float b) -> bool { return inexact_cast(a) >= b; } - - auto operator + (ratio const& a, double b) -> double { return inexact_cast(a) + b; } - auto operator - (ratio const& a, double b) -> double { return inexact_cast(a) - b; } - auto operator * (ratio const& a, double b) -> double { return inexact_cast(a) * b; } - auto operator / (ratio const& a, double b) -> double { return inexact_cast(a) / b; } - auto operator % (ratio const& a, double b) -> double { return std::remainder(inexact_cast(a), b); } - auto operator ==(ratio const& a, double b) -> bool { return inexact_equals(inexact_cast(a), b); } + auto operator < (ratio const& a, float b) -> bool { return static_cast(a) < b; } + auto operator <=(ratio const& a, float b) -> bool { return static_cast(a) <= b; } + auto operator > (ratio const& a, float b) -> bool { return static_cast(a) > b; } + auto operator >=(ratio const& a, float b) -> bool { return static_cast(a) >= b; } + + auto operator + (ratio const& a, double b) -> double { return static_cast(a) + b; } + auto operator - (ratio const& a, double b) -> double { return static_cast(a) - b; } + auto operator * (ratio const& a, double b) -> double { return static_cast(a) * b; } + auto operator / (ratio const& a, double b) -> double { return static_cast(a) / b; } + auto operator % (ratio const& a, double b) -> double { return std::remainder(static_cast(a), b); } + auto operator ==(ratio const& a, double b) -> bool { return inexact_equals(static_cast(a), b); } auto operator !=(ratio const& a, double b) -> bool { return not (a == b); } - auto operator < (ratio const& a, double b) -> bool { return inexact_cast(a) < b; } - auto operator <=(ratio const& a, double b) -> bool { return inexact_cast(a) <= b; } - auto operator > (ratio const& a, double b) -> bool { return inexact_cast(a) > b; } - auto operator >=(ratio const& a, double b) -> bool { return inexact_cast(a) >= b; } + auto operator < (ratio const& a, double b) -> bool { return static_cast(a) < b; } + auto operator <=(ratio const& a, double b) -> bool { return static_cast(a) <= b; } + auto operator > (ratio const& a, double b) -> bool { return static_cast(a) > b; } + auto operator >=(ratio const& a, double b) -> bool { return static_cast(a) >= b; } auto operator + (ratio const& a, complex const& b) -> complex { return complex(make(a), e0) + b; } auto operator - (ratio const& a, complex const& b) -> complex { return complex(make(a), e0) - b; } auto operator * (ratio const& a, complex const& b) -> complex { return complex(make(a), e0) * b; } auto operator / (ratio const& a, complex const& b) -> complex { return complex(make(a), e0) / b; } - auto operator % (ratio const& , complex const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(ratio const& a, complex const& b) -> bool { return complex(make(a), e0) == b; } auto operator !=(ratio const& a, complex const& b) -> bool { return complex(make(a), e0) != b; } - auto operator < (ratio const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(ratio const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (ratio const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(ratio const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - - auto operator + (float a, exact_integer const& b) -> float { return a + inexact_cast(b); } - auto operator - (float a, exact_integer const& b) -> float { return a - inexact_cast(b); } - auto operator * (float a, exact_integer const& b) -> float { return a * inexact_cast(b); } - auto operator / (float a, exact_integer const& b) -> float { return a / inexact_cast(b); } - auto operator % (float a, exact_integer const& b) -> float { return std::remainder(a, inexact_cast(b)); } - auto operator ==(float a, exact_integer const& b) -> bool { return inexact_equals(a, inexact_cast(b)); } + + auto operator + (float a, exact_integer const& b) -> float { return a + static_cast(b); } + auto operator - (float a, exact_integer const& b) -> float { return a - static_cast(b); } + auto operator * (float a, exact_integer const& b) -> float { return a * static_cast(b); } + auto operator / (float a, exact_integer const& b) -> float { return a / static_cast(b); } + auto operator % (float a, exact_integer const& b) -> float { return std::remainder(a, static_cast(b)); } + auto operator ==(float a, exact_integer const& b) -> bool { return inexact_equals(a, static_cast(b)); } auto operator !=(float a, exact_integer const& b) -> bool { return not (a == b); } - auto operator < (float a, exact_integer const& b) -> bool { return a < inexact_cast(b); } - auto operator <=(float a, exact_integer const& b) -> bool { return a <= inexact_cast(b); } - auto operator > (float a, exact_integer const& b) -> bool { return a > inexact_cast(b); } - auto operator >=(float a, exact_integer const& b) -> bool { return a >= inexact_cast(b); } - - auto operator + (float a, ratio const& b) -> float { return a + inexact_cast(b); } - auto operator - (float a, ratio const& b) -> float { return a - inexact_cast(b); } - auto operator * (float a, ratio const& b) -> float { return a * inexact_cast(b); } - auto operator / (float a, ratio const& b) -> float { return a / inexact_cast(b); } - auto operator % (float a, ratio const& b) -> float { return std::remainder(a, inexact_cast(b)); } - auto operator ==(float a, ratio const& b) -> bool { return inexact_equals(a, inexact_cast(b)); } + auto operator < (float a, exact_integer const& b) -> bool { return a < static_cast(b); } + auto operator <=(float a, exact_integer const& b) -> bool { return a <= static_cast(b); } + auto operator > (float a, exact_integer const& b) -> bool { return a > static_cast(b); } + auto operator >=(float a, exact_integer const& b) -> bool { return a >= static_cast(b); } + + auto operator + (float a, ratio const& b) -> float { return a + static_cast(b); } + auto operator - (float a, ratio const& b) -> float { return a - static_cast(b); } + auto operator * (float a, ratio const& b) -> float { return a * static_cast(b); } + auto operator / (float a, ratio const& b) -> float { return a / static_cast(b); } + auto operator % (float a, ratio const& b) -> float { return std::remainder(a, static_cast(b)); } + auto operator ==(float a, ratio const& b) -> bool { return inexact_equals(a, static_cast(b)); } auto operator !=(float a, ratio const& b) -> bool { return not (a == b); } - auto operator < (float a, ratio const& b) -> bool { return a < inexact_cast(b); } - auto operator <=(float a, ratio const& b) -> bool { return a <= inexact_cast(b); } - auto operator > (float a, ratio const& b) -> bool { return a > inexact_cast(b); } - auto operator >=(float a, ratio const& b) -> bool { return a >= inexact_cast(b); } + auto operator < (float a, ratio const& b) -> bool { return a < static_cast(b); } + auto operator <=(float a, ratio const& b) -> bool { return a <= static_cast(b); } + auto operator > (float a, ratio const& b) -> bool { return a > static_cast(b); } + auto operator >=(float a, ratio const& b) -> bool { return a >= static_cast(b); } auto operator + (float a, complex const& b) -> complex { return complex(make(a), e0) + b; } auto operator - (float a, complex const& b) -> complex { return complex(make(a), e0) - b; } auto operator * (float a, complex const& b) -> complex { return complex(make(a), e0) * b; } auto operator / (float a, complex const& b) -> complex { return complex(make(a), e0) / b; } - auto operator % (float , complex const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(float a, complex const& b) -> bool { return complex(make(a), e0) == b; } auto operator !=(float a, complex const& b) -> bool { return complex(make(a), e0) != b; } - auto operator < (float , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(float , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (float , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(float , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - - auto operator + (double a, exact_integer const& b) -> double { return a + inexact_cast(b); } - auto operator - (double a, exact_integer const& b) -> double { return a - inexact_cast(b); } - auto operator * (double a, exact_integer const& b) -> double { return a * inexact_cast(b); } - auto operator / (double a, exact_integer const& b) -> double { return a / inexact_cast(b); } - auto operator % (double a, exact_integer const& b) -> double { return std::remainder(a, inexact_cast(b)); } + + auto operator + (double a, exact_integer const& b) -> double { return a + static_cast(b); } + auto operator - (double a, exact_integer const& b) -> double { return a - static_cast(b); } + auto operator * (double a, exact_integer const& b) -> double { return a * static_cast(b); } + auto operator / (double a, exact_integer const& b) -> double { return a / static_cast(b); } + auto operator % (double a, exact_integer const& b) -> double { return std::remainder(a, static_cast(b)); } auto operator ==(double a, exact_integer const& b) -> bool { return mpz_cmp_d(b.value, a) == 0; } auto operator !=(double a, exact_integer const& b) -> bool { return mpz_cmp_d(b.value, a) != 0; } auto operator < (double a, exact_integer const& b) -> bool { return mpz_cmp_d(b.value, a) > 0; } @@ -196,89 +179,59 @@ inline namespace kernel auto operator > (double a, exact_integer const& b) -> bool { return mpz_cmp_d(b.value, a) < 0; } auto operator >=(double a, exact_integer const& b) -> bool { return mpz_cmp_d(b.value, a) <= 0; } - auto operator + (double a, ratio const& b) -> double { return a + inexact_cast(b); } - auto operator - (double a, ratio const& b) -> double { return a - inexact_cast(b); } - auto operator * (double a, ratio const& b) -> double { return a * inexact_cast(b); } - auto operator / (double a, ratio const& b) -> double { return a / inexact_cast(b); } - auto operator % (double a, ratio const& b) -> double { return std::remainder(a, inexact_cast(b)); } - auto operator ==(double a, ratio const& b) -> bool { return inexact_equals(a, inexact_cast(b)); } + auto operator + (double a, ratio const& b) -> double { return a + static_cast(b); } + auto operator - (double a, ratio const& b) -> double { return a - static_cast(b); } + auto operator * (double a, ratio const& b) -> double { return a * static_cast(b); } + auto operator / (double a, ratio const& b) -> double { return a / static_cast(b); } + auto operator % (double a, ratio const& b) -> double { return std::remainder(a, static_cast(b)); } + auto operator ==(double a, ratio const& b) -> bool { return inexact_equals(a, static_cast(b)); } auto operator !=(double a, ratio const& b) -> bool { return not (a == b); } - auto operator < (double a, ratio const& b) -> bool { return a < inexact_cast(b); } - auto operator <=(double a, ratio const& b) -> bool { return a <= inexact_cast(b); } - auto operator > (double a, ratio const& b) -> bool { return a > inexact_cast(b); } - auto operator >=(double a, ratio const& b) -> bool { return a >= inexact_cast(b); } + auto operator < (double a, ratio const& b) -> bool { return a < static_cast(b); } + auto operator <=(double a, ratio const& b) -> bool { return a <= static_cast(b); } + auto operator > (double a, ratio const& b) -> bool { return a > static_cast(b); } + auto operator >=(double a, ratio const& b) -> bool { return a >= static_cast(b); } auto operator + (double a, complex const& b) -> complex { return complex(make(a), e0) + b; } auto operator - (double a, complex const& b) -> complex { return complex(make(a), e0) - b; } auto operator * (double a, complex const& b) -> complex { return complex(make(a), e0) * b; } auto operator / (double a, complex const& b) -> complex { return complex(make(a), e0) / b; } - auto operator % (double , complex const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(double a, complex const& b) -> bool { return complex(make(a), e0) == b; } auto operator !=(double a, complex const& b) -> bool { return complex(make(a), e0) != b; } - auto operator < (double , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(double , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (double , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(double , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } auto operator + (complex const& a, complex const& b) -> complex { return complex(a.real() + b.real(), a.imag() + b.imag()); } auto operator - (complex const& a, complex const& b) -> complex { return complex(a.real() - b.real(), a.imag() - b.imag()); } auto operator * (complex const& a, complex const& b) -> complex { return complex(a.real() * b.real() - a.imag() * b.imag(), a.imag() * b.real() + a.real() * b.imag()); } auto operator / (complex const& a, complex const& b) -> complex { auto x = a.real() * b.real() + a.imag() * b.imag(); auto y = a.imag() * b.real() - a.real() * b.imag(); auto d = b.real() * b.real() + b.imag() * b.imag(); return complex(x / d, y / d); } - auto operator % (complex const& , complex const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(complex const& a, complex const& b) -> bool { return equals(a.real(), b.real()) and equals(a.imag(), b.imag()); } auto operator !=(complex const& a, complex const& b) -> bool { return not (a == b); } - auto operator < (complex const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(complex const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (complex const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(complex const& , complex const& ) -> bool { throw std::invalid_argument("unsupported operation"); } auto operator + (complex const& a, float b) -> complex { return a + complex(make(b), e0); } auto operator - (complex const& a, float b) -> complex { return a - complex(make(b), e0); } auto operator * (complex const& a, float b) -> complex { return a * complex(make(b), e0); } auto operator / (complex const& a, float b) -> complex { return a / complex(make(b), e0); } - auto operator % (complex const& , float ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(complex const& a, float b) -> bool { return a == complex(make(b), e0); } auto operator !=(complex const& a, float b) -> bool { return a != complex(make(b), e0); } - auto operator < (complex const& , float ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(complex const& , float ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (complex const& , float ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(complex const& , float ) -> bool { throw std::invalid_argument("unsupported operation"); } auto operator + (complex const& a, double b) -> complex { return a + complex(make(b), e0); } auto operator - (complex const& a, double b) -> complex { return a - complex(make(b), e0); } auto operator * (complex const& a, double b) -> complex { return a * complex(make(b), e0); } auto operator / (complex const& a, double b) -> complex { return a / complex(make(b), e0); } - auto operator % (complex const& , double ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(complex const& a, double b) -> bool { return a == complex(make(b), e0); } auto operator !=(complex const& a, double b) -> bool { return a != complex(make(b), e0); } - auto operator < (complex const& , double ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(complex const& , double ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (complex const& , double ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(complex const& , double ) -> bool { throw std::invalid_argument("unsupported operation"); } auto operator + (complex const& a, ratio const& b) -> complex { return a + complex(make(b), e0); } auto operator - (complex const& a, ratio const& b) -> complex { return a - complex(make(b), e0); } auto operator * (complex const& a, ratio const& b) -> complex { return a * complex(make(b), e0); } auto operator / (complex const& a, ratio const& b) -> complex { return a / complex(make(b), e0); } - auto operator % (complex const& , ratio const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(complex const& a, ratio const& b) -> bool { return a == complex(make(b), e0); } auto operator !=(complex const& a, ratio const& b) -> bool { return a != complex(make(b), e0); } - auto operator < (complex const& , ratio const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(complex const& , ratio const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (complex const& , ratio const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(complex const& , ratio const& ) -> bool { throw std::invalid_argument("unsupported operation"); } auto operator + (complex const& a, exact_integer const& b) -> complex { return a + complex(make(b), e0); } auto operator - (complex const& a, exact_integer const& b) -> complex { return a - complex(make(b), e0); } auto operator * (complex const& a, exact_integer const& b) -> complex { return a * complex(make(b), e0); } auto operator / (complex const& a, exact_integer const& b) -> complex { return a / complex(make(b), e0); } - auto operator % (complex const& , exact_integer const& ) -> complex { throw std::invalid_argument("unsupported operation"); } auto operator ==(complex const& a, exact_integer const& b) -> bool { return a == complex(make(b), e0); } auto operator !=(complex const& a, exact_integer const& b) -> bool { return a != complex(make(b), e0); } - auto operator < (complex const& , exact_integer const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator <=(complex const& , exact_integer const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator > (complex const& , exact_integer const& ) -> bool { throw std::invalid_argument("unsupported operation"); } - auto operator >=(complex const& , exact_integer const& ) -> bool { throw std::invalid_argument("unsupported operation"); } template auto canonicalize(T&& x) -> decltype(auto) @@ -302,16 +255,22 @@ inline namespace kernel } } - template - auto apply([[maybe_unused]] F f, object const& x) -> object - { - using Ts = std::tuple; + using complex_number = std::tuple; + + using complex_numbers = combination; - if constexpr (I < std::tuple_size_v) + using real_number = std::tuple; + + using real_numbers = combination; + + template + auto apply_to([[maybe_unused]] F f, object const& x) -> object + { + if constexpr (I < std::tuple_size_v) { - using T = std::tuple_element_t; + using type_i = std::tuple_element_t; - return x.is() ? canonicalize(f(x.as())) : apply(f, x); + return x.is() ? canonicalize(f(x.as())) : apply_to(f, x); } else { @@ -319,17 +278,15 @@ inline namespace kernel } } - template - auto apply([[maybe_unused]] F f, object const& x, object const& y) -> object + template + auto apply_to([[maybe_unused]] F f, object const& x, object const& y) -> object { - using Ts = combination; - - if constexpr (I < std::tuple_size_v) + if constexpr (I < std::tuple_size_v) { - using T = std::tuple_element_t<0, std::tuple_element_t>; - using U = std::tuple_element_t<1, std::tuple_element_t>; + using type_i_0 = std::tuple_element_t<0, std::tuple_element_t>; + using type_i_1 = std::tuple_element_t<1, std::tuple_element_t>; - return x.is() and y.is() ? canonicalize(f(x.as(), y.as())) : apply(f, x, y); + return x.is() and y.is() ? canonicalize(f(x.as(), y.as())) : apply_to(f, x, y); } else { @@ -337,16 +294,14 @@ inline namespace kernel } } - template + template auto test([[maybe_unused]] F f, object const& x) -> bool { - using Ts = std::tuple; - - if constexpr (I < std::tuple_size_v) + if constexpr (I < std::tuple_size_v) { - using T = std::tuple_element_t; + using type_i = std::tuple_element_t; - return x.is() ? f(x.as()) : test(f, x); + return x.is() ? f(x.as()) : test(f, x); } else { @@ -354,17 +309,15 @@ inline namespace kernel } } - template + template auto test([[maybe_unused]] F f, object const& x, object const& y) -> bool { - using Ts = combination; - - if constexpr (I < std::tuple_size_v) + if constexpr (I < std::tuple_size_v) { - using T = std::tuple_element_t<0, std::tuple_element_t>; - using U = std::tuple_element_t<1, std::tuple_element_t>; + using type_i_0 = std::tuple_element_t<0, std::tuple_element_t>; + using type_i_1 = std::tuple_element_t<1, std::tuple_element_t>; - return x.is() and y.is() ? f(x.as(), y.as()) : test(f, x, y); + return x.is() and y.is() ? f(x.as(), y.as()) : test(f, x, y); } else { @@ -374,31 +327,28 @@ inline namespace kernel auto operator +(object const& x, object const& y) -> object { - return apply(std::plus(), x, y); + return apply_to(std::plus(), x, y); } auto operator -(object const& x, object const& y) -> object { - return apply(std::minus(), x, y); + return apply_to(std::minus(), x, y); } auto operator *(object const& x, object const& y) -> object { - return apply(std::multiplies(), x, y); + return apply_to(std::multiplies(), x, y); } auto operator /(object const& x, object const& y) -> object { - return apply(std::divides(), x, y); + return apply_to(std::divides(), x, y); } auto operator % (object const& x, object const& y) -> object { - auto f = [](auto&& x, auto&& y) + auto f = [](T const& x, U const& y) { - using T = std::decay_t; - using U = std::decay_t; - if constexpr (std::is_floating_point_v and std::is_floating_point_v) { @@ -410,7 +360,7 @@ inline namespace kernel } }; - return apply(f, x, y); + return apply_to(f, x, y); } auto make_integer(std::string const& literal, int radix) -> object @@ -445,34 +395,51 @@ inline namespace kernel { "-inf.0", -std::numeric_limits::infinity() }, { "+nan.0", +std::numeric_limits::quiet_NaN() }, { "-nan.0", -std::numeric_limits::quiet_NaN() }, - - // SRFI-144 - { "fl-e", M_E }, - { "fl-log2-e", M_LOG2E }, - { "fl-log10-e", M_LOG10E }, - { "fl-log-2", M_LN2 }, - { "fl-1/log-2", M_LN2 }, - { "fl-log-10", M_LN10 }, - { "fl-1/log-10", M_LN10 }, - { "fl-pi", M_PI }, - { "fl-1/pi", M_1_PI }, - { "fl-pi/2", M_PI_2 }, - { "fl-pi/4", M_PI_4 }, - { "fl-2/pi", M_2_PI }, - { "fl-2/sqrt-pi", M_2_SQRTPI }, - { "fl-sqrt-2", M_SQRT2 }, - { "fl-1/sqrt-2", M_SQRT1_2 }, }; - auto static const pattern = std::regex(R"(([+-]?(?:\d+\.?|\d*\.\d+))([DEFLSdefls][+-]?\d+)?)"); + auto static const pattern = std::regex(R"([+-]?(?:\d+\.?|\d*\.\d+)(?:([DEFdef])[+-]?\d+)?)"); if (auto iter = constants.find(literal); iter != constants.end()) { return make(iter->second); } - else if (std::regex_match(literal, pattern)) + else if (auto result = std::smatch(); std::regex_match(literal, result, pattern)) { - return make(lexical_cast(literal)); + /* + R7RS 6.2.5. Syntax of numerical constants + + In systems with inexact numbers of varying precisions it can be + useful to specify the precision of a constant. For this purpose, + implementations may accept numerical constants written with an + exponent marker that indicates the desired precision of the inexact + representation. If so, the letter s, f, d, or l, meaning short, + single, double, or long precision, respectively, can be used in + place of e. The default precision has at least as much precision as + double, but implementations may allow this default to be set by the + user. + */ + assert(result.ready()); + assert(result.size() == 2); + + if (result[1].matched) + { + assert(result[1].length() == 1); + + switch (*result[1].first) + { + case 'D': case 'd': + case 'E': case 'e': + default: + return make(std::stod(literal)); + + case 'F': case 'f': + return make(std::stof(literal.substr().replace(result.position(1), 1, "e"))); + } + } + else + { + return make(lexical_cast(literal)); + } } else { @@ -514,7 +481,7 @@ inline namespace number return inexact_equals(std::forward(xs)...); }; - return test(f, x, y); + return test(f, x, y); } auto not_equals(object const& x, object const& y) -> bool @@ -524,7 +491,7 @@ inline namespace number auto less_than(object const& x, object const& y) -> bool { - return test(std::less(), x, y); + return test(std::less(), x, y); } auto less_than_or_equals(object const& x, object const& y) -> bool @@ -534,7 +501,7 @@ inline namespace number auto greater_than(object const& x, object const& y) -> bool { - return test(std::greater(), x, y); + return test(std::greater(), x, y); } auto greater_than_or_equals(object const& x, object const& y) -> bool @@ -544,10 +511,8 @@ inline namespace number auto exact(object const& x) -> object { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return complex(exact(x.real()), @@ -563,15 +528,13 @@ inline namespace number } }; - return apply(f, x); + return apply_to(f, x); } auto inexact(object const& x) -> object { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return complex(inexact(x.real()), @@ -579,11 +542,11 @@ inline namespace number } else { - return inexact_cast(std::forward(x)); + return static_cast(std::forward(x)); } }; - return apply(f, x); + return apply_to(f, x); } auto is_complex(object const& x) -> bool @@ -593,15 +556,13 @@ inline namespace number return true; }; - return test(f, x); + return test(f, x); } auto is_real(object const& x) -> bool { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return equals(x.imag(), e0); @@ -612,15 +573,13 @@ inline namespace number } }; - return test(f, x); + return test(f, x); } auto is_rational(object const& x) -> bool { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_floating_point_v) { return not std::isnan(x) and @@ -633,15 +592,13 @@ inline namespace number } }; - return test(f, x); + return test(f, x); } auto is_integer(object const& x) -> bool { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return equals(x.imag(), e0) and is_integer(x.real()); @@ -660,15 +617,13 @@ inline namespace number } }; - return test(f, x); + return test(f, x); } auto is_exact(object const& x) -> bool { - auto f = [](auto const& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return is_exact(x.real()) and is_exact(x.imag()); @@ -679,7 +634,7 @@ inline namespace number } }; - return test(f, x); + return test(f, x); } auto is_inexact(object const& x) -> bool @@ -694,10 +649,8 @@ inline namespace number auto is_infinite(object const& x) -> bool { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return is_infinite(x.real()) or @@ -713,15 +666,13 @@ inline namespace number } }; - return test(f, x); + return test(f, x); } auto is_nan(object const& x) -> bool { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { return is_nan(x.real()) or @@ -737,7 +688,7 @@ inline namespace number } }; - return test(f, x); + return test(f, x); } auto is_zero(object const& x) -> bool @@ -766,36 +717,10 @@ inline namespace number return is_zero(remainder(x, e2)); } - auto max(object const& xs) -> object - { - if (auto iter = std::max_element(xs.begin(), xs.end(), less_than); iter != xs.end()) - { - return std::any_of(xs.begin(), xs.end(), is_inexact) ? inexact(*iter) : *iter; - } - else - { - return unspecified; - } - } - - auto min(object const& xs) -> object - { - if (auto iter = std::min_element(xs.begin(), xs.end(), less_than); iter != xs.end()) - { - return std::any_of(xs.begin(), xs.end(), is_inexact) ? inexact(*iter) : *iter; - } - else - { - return unspecified; - } - } - auto abs(object const& x) -> object { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { exact_integer i {}; @@ -806,6 +731,10 @@ inline namespace number { return std::abs(std::forward(x)); } + else if constexpr (std::is_same_v) + { + return sqrt(x.real() * x.real() + x.imag() * x.imag()); + } else { static auto const zero = static_cast(0); @@ -813,12 +742,12 @@ inline namespace number } }; - return apply(f, x); + return apply_to(f, x); } auto quotient(object const& x, object const& y) -> object { - return trunc(x / y); + return truncate(x / y); } auto remainder(object const& x, object const& y) -> object @@ -843,30 +772,28 @@ inline namespace number auto sqrt(object const& x) -> object { - auto f = [](auto&& x) + auto f = [](T const& x) { - using T = std::decay_t; - if constexpr (std::is_same_v) { - auto const z = std::sqrt(inexact_cast(std::forward(x))); + auto const z = std::sqrt(static_cast>(x)); return complex(make(z.real()), make(z.imag())); } else { - auto sqrt = [](auto&& x) + auto sqrt = [](auto const& x) { if constexpr (std::is_same_v) { - auto const [s, r] = x.square_root(); + auto const [s, r] = x.sqrt(); - return r == 0 ? make(s) : make(std::sqrt(inexact_cast(x))); + return r == 0 ? make(s) : make(std::sqrt(static_cast(x))); } else { - return make(std::sqrt(inexact_cast(std::forward(x)))); + return make(std::sqrt(static_cast(x))); } }; @@ -875,21 +802,30 @@ inline namespace number } }; - return apply(f, x); + return apply_to(f, x); } auto pow(object const& x, object const& y) -> object { - auto f = [](auto&& x, auto&& y) + auto f = [](T const& x, U const& y) { - using T = std::decay_t; - using U = std::decay_t; - if constexpr (std::is_same_v or std::is_same_v) { - auto const z = std::pow(inexact_cast(std::forward(x)), - inexact_cast(std::forward(y))); + auto inexact = [](auto&& x) + { + if constexpr (std::is_same_v, complex>) + { + return static_cast>(std::forward(x)); + } + else + { + return static_cast(std::forward(x)); + } + }; + + auto const z = std::pow(inexact(std::forward(x)), + inexact(std::forward(y))); return complex(make(z.real()), make(z.imag())); @@ -903,12 +839,12 @@ inline namespace number } else { - return std::pow(inexact_cast(std::forward(x)), - inexact_cast(std::forward(y))); + return std::pow(static_cast(std::forward(x)), + static_cast(std::forward(y))); } }; - return apply(f, x, y); + return apply_to(f, x, y); } auto numerator(object const& x) -> object @@ -947,121 +883,153 @@ inline namespace number } } - #define DEFINE(ROUND) \ - auto ROUND(object const& x) -> object \ + auto ldexp(object const& x, object const& y) -> object + { + auto f = [](auto&& x, auto&& y) + { + return std::ldexp(static_cast(std::forward(x)), + static_cast(std::forward(y))); + }; + + return apply_to(f, x, y); + } + + auto number_to_string(object const& x, int radix) -> object + { + auto f = [radix](T const& x) + { + if constexpr (std::is_floating_point_v) + { + return string("TODO"); + } + else if constexpr (std::is_same_v) + { + return string(std::unique_ptr(mpz_get_str(nullptr, radix, x.value)).get()); + } + else + { + return string("TODO"); + } + }; + + return apply_to(f, x); + } + + #define DEFINE_EXACTNESS_PRESERVED_COMPLEX1(NAME, CMATH) \ + auto NAME(object const& x) -> object \ { \ - auto f = [](auto&& x) \ + auto f = [](T const& x) \ { \ - using T = std::decay_t; \ - \ if constexpr (std::is_floating_point_v) \ { \ - return std::ROUND(inexact_cast(std::forward(x))); \ + return CMATH(x); \ } \ else if constexpr (std::is_same_v) \ { \ - return exact_integer(std::ROUND(inexact_cast(std::forward(x)))); \ + return exact_integer(CMATH(static_cast(x))); \ } \ else if constexpr (std::is_same_v) \ { \ - return std::forward(x); \ + return x; \ } \ else \ { \ - return complex(ROUND(x.real()), \ - ROUND(x.imag())); \ + return complex(NAME(x.real()), \ + NAME(x.imag())); \ } \ }; \ \ - return apply(f, x); \ - } \ - static_assert(true) - - DEFINE(floor); - DEFINE(ceil); - DEFINE(trunc); - DEFINE(round); + return apply_to(f, x); \ + } - #undef DEFINE + DEFINE_EXACTNESS_PRESERVED_COMPLEX1(ceiling, std::ceil) + DEFINE_EXACTNESS_PRESERVED_COMPLEX1(floor, std::floor) + DEFINE_EXACTNESS_PRESERVED_COMPLEX1(round, std::round) + DEFINE_EXACTNESS_PRESERVED_COMPLEX1(truncate, std::trunc) - #define DEFINE(CMATH) \ + #define DEFINE_COMPLEX1(CMATH) \ auto CMATH(object const& x) -> object \ { \ - auto f = [](auto&& x) \ + auto f = [](T const& x) \ { \ - using T = std::decay_t; \ - \ if constexpr (std::is_same_v) \ { \ - auto const z = std::CMATH(inexact_cast(std::forward(x))); \ + auto const z = std::CMATH(static_cast>(std::forward(x))); \ \ return complex(make(z.real()), \ make(z.imag())); \ } \ else \ { \ - return std::CMATH(inexact_cast(std::forward(x))); \ + return std::CMATH(static_cast(std::forward(x))); \ } \ }; \ \ - return apply(f, x); \ - } \ - static_assert(true) - - DEFINE(sin); DEFINE(asin); DEFINE(sinh); DEFINE(asinh); - DEFINE(cos); DEFINE(acos); DEFINE(cosh); DEFINE(acosh); - DEFINE(tan); DEFINE(atan); DEFINE(tanh); DEFINE(atanh); - - DEFINE(exp); - DEFINE(log); - - #undef DEFINE + return apply_to(f, x); \ + } - auto atan(object const& x, object const& y) -> object - { - auto f = [](auto&& x, auto&& y) - { - using T = std::decay_t; - using U = std::decay_t; + DEFINE_COMPLEX1(acos) + DEFINE_COMPLEX1(acosh) + DEFINE_COMPLEX1(asin) + DEFINE_COMPLEX1(asinh) + DEFINE_COMPLEX1(atan) + DEFINE_COMPLEX1(atanh) + DEFINE_COMPLEX1(cos) + DEFINE_COMPLEX1(cosh) + DEFINE_COMPLEX1(exp) + DEFINE_COMPLEX1(log) + DEFINE_COMPLEX1(sin) + DEFINE_COMPLEX1(sinh) + DEFINE_COMPLEX1(tan) + DEFINE_COMPLEX1(tanh) + + #define DEFINE_REAL1(CMATH) \ + auto CMATH(object const& x) -> object \ + { \ + auto f = [](auto&& x) \ + { \ + return std::CMATH(static_cast(std::forward(x))); \ + }; \ + \ + return apply_to(f, x); \ + } - if constexpr (std::is_same_v or - std::is_same_v) - { - throw std::invalid_argument("not a real number"); - return std::numeric_limits::quiet_NaN(); - } - else - { - return std::atan2(inexact_cast(std::forward(x)), - inexact_cast(std::forward(y))); - } - }; + DEFINE_REAL1(erf) + DEFINE_REAL1(erfc) + DEFINE_REAL1(expm1) + DEFINE_REAL1(fabs) + DEFINE_REAL1(lgamma) + DEFINE_REAL1(log1p) + DEFINE_REAL1(tgamma) - return apply(f, x, y); + #define DEFINE_REAL2(CMATH) \ + auto CMATH(object const& x, object const& y) -> object \ + { \ + auto f = [](auto&& x, auto&& y) \ + { \ + return std::CMATH(static_cast(std::forward(x)), \ + static_cast(std::forward(y))); \ + }; \ + \ + return apply_to(f, x, y); \ } - auto number_to_string(object const& x, int radix) -> object - { - auto f = [radix](auto&& x) - { - using T = std::decay_t; - - if constexpr (std::is_floating_point_v) - { - return string("TODO"); - } - else if constexpr (std::is_same_v) - { - return string(std::unique_ptr(mpz_get_str(nullptr, radix, x.value)).get()); - } - else - { - return string("TODO"); - } - }; + DEFINE_REAL2(atan2) + DEFINE_REAL2(copysign) + DEFINE_REAL2(nextafter) - return apply(f, x); + #define DEFINE_UNPROVIDED_REAL2(CMATH) \ + auto CMATH(object const&, object const&) -> object \ + { \ + throw error(make("The mathematical special function std::" #CMATH " is not provided in this environment.")); \ } + + #if __cpp_lib_math_special_functions + DEFINE_REAL2(cyl_bessel_j) + DEFINE_REAL2(cyl_neumann) + #else + DEFINE_UNPROVIDED_REAL2(cyl_bessel_j) + DEFINE_UNPROVIDED_REAL2(cyl_neumann) + #endif } // namespace number -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/optimizer.cpp b/src/kernel/optimizer.cpp index daa39b23b..8e895106e 100644 --- a/src/kernel/optimizer.cpp +++ b/src/kernel/optimizer.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { struct analysis { @@ -214,5 +212,4 @@ inline namespace kernel return code; } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/output_file_port.cpp b/src/kernel/output_file_port.cpp index 04a3f10f3..1e0af4c0a 100644 --- a/src/kernel/output_file_port.cpp +++ b/src/kernel/output_file_port.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto output_file_port::close() -> void { @@ -39,5 +37,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("open-output-file ") << datum.name << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/output_string_port.cpp b/src/kernel/output_string_port.cpp index 90b0bdec7..abf841485 100644 --- a/src/kernel/output_string_port.cpp +++ b/src/kernel/output_string_port.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto output_string_port::close() -> void {} @@ -38,5 +36,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("open-output-string ") << string(datum.ostringstream.str()) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/pair.cpp b/src/kernel/pair.cpp index 8e0e83dfa..c7a156efc 100644 --- a/src/kernel/pair.cpp +++ b/src/kernel/pair.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { let unit = nullptr; @@ -73,5 +71,4 @@ inline namespace kernel return os << magenta(")"); } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/procedure.cpp b/src/kernel/procedure.cpp index ef62ecc20..6daa10d4c 100644 --- a/src/kernel/procedure.cpp +++ b/src/kernel/procedure.cpp @@ -16,13 +16,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, primitive const& datum) -> std::ostream & { return os << magenta("#,(") << green("procedure ") << datum.name << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/ratio.cpp b/src/kernel/ratio.cpp index b6405a4ab..0a3774007 100644 --- a/src/kernel/ratio.cpp +++ b/src/kernel/ratio.cpp @@ -18,9 +18,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { ratio::ratio() { @@ -89,6 +87,16 @@ inline namespace kernel return exact_integer(mpq_numref(value)); } + ratio::operator int() const + { + return mpq_get_d(value); + } + + ratio::operator float() const + { + return mpq_get_d(value); + } + ratio::operator double() const { return mpq_get_d(value); @@ -105,5 +113,4 @@ inline namespace kernel return os << cyan(std::unique_ptr(mpq_get_str(nullptr, 10, datum.value), free).get()); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/standard_error_port.cpp b/src/kernel/standard_error_port.cpp index c5c7eabb8..a80e26dc2 100644 --- a/src/kernel/standard_error_port.cpp +++ b/src/kernel/standard_error_port.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto standard_error_port::close() -> void {} @@ -37,5 +35,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("standard-error") << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/standard_input_port.cpp b/src/kernel/standard_input_port.cpp index 4351b0187..623185cd5 100644 --- a/src/kernel/standard_input_port.cpp +++ b/src/kernel/standard_input_port.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { standard_input_port::standard_input_port() { @@ -47,5 +45,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("standard-input") << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/standard_output_port.cpp b/src/kernel/standard_output_port.cpp index dfd7cecfb..45fb5932b 100644 --- a/src/kernel/standard_output_port.cpp +++ b/src/kernel/standard_output_port.cpp @@ -16,9 +16,7 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto standard_output_port::close() -> void {} @@ -37,5 +35,4 @@ inline namespace kernel { return output << magenta("#,(") << blue("standard-output") << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/string.cpp b/src/kernel/string.cpp index 763adbe6d..8157c9758 100644 --- a/src/kernel/string.cpp +++ b/src/kernel/string.cpp @@ -19,9 +19,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { string::string(std::string const& s) { @@ -34,6 +32,11 @@ inline namespace kernel } } + string::operator std::filesystem::path() const + { + return operator std::string(); + } + string::operator std::string() const { std::string result; @@ -82,5 +85,4 @@ inline namespace kernel return os << cyan("\""); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/symbol.cpp b/src/kernel/symbol.cpp index 866659fc8..d4ddff969 100644 --- a/src/kernel/symbol.cpp +++ b/src/kernel/symbol.cpp @@ -19,22 +19,13 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator +(symbol const& a, symbol const& b) -> std::string { return a.name + b.name; } - auto operator ==(symbol const& a, symbol const& b) -> bool { return a.name == b.name; } - auto operator !=(symbol const& a, symbol const& b) -> bool { return a.name != b.name; } - auto operator < (symbol const& a, symbol const& b) -> bool { return a.name < b.name; } - auto operator <=(symbol const& a, symbol const& b) -> bool { return a.name <= b.name; } - auto operator > (symbol const& a, symbol const& b) -> bool { return a.name > b.name; } - auto operator >=(symbol const& a, symbol const& b) -> bool { return a.name >= b.name; } - auto operator <<(std::ostream & os, symbol const& datum) -> std::ostream & { if (datum.name.empty()) @@ -73,5 +64,4 @@ inline namespace kernel make(name)); } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/textual_input_port.cpp b/src/kernel/textual_input_port.cpp index 53a61a9bf..9e7ca2fb3 100644 --- a/src/kernel/textual_input_port.cpp +++ b/src/kernel/textual_input_port.cpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { textual_input_port::iterator::iterator(textual_input_port & input) : input { std::addressof(input) } @@ -392,10 +390,10 @@ inline namespace kernel switch (std::stoi(take_character_while(is_digit, character('0')))) { case 32: - return make(read()); + return make(from_list, read()); case 64: - return make(read()); + return make(from_list, read()); default: take_token(c2); @@ -419,16 +417,16 @@ inline namespace kernel switch (auto n = take_character_while(is_digit); std::stoi(n)) { case 8: - return make(read()); + return make(from_list, read()); case 16: - return make(read()); + return make(from_list, read()); case 32: - return make(read()); + return make(from_list, read()); case 64: - return make(read()); + return make(from_list, read()); default: throw read_error(make("An unknown literal expression was encountered"), @@ -443,16 +441,16 @@ inline namespace kernel switch (auto const n = take_character_while(is_digit); std::stoi(n)) { case 8: - return make(read()); + return make(from_list, read()); case 16: - return make(read()); + return make(from_list, read()); case 32: - return make(read()); + return make(from_list, read()); case 64: - return make(read()); + return make(from_list, read()); default: throw read_error(make("An unknown literal expression was encountered"), @@ -692,5 +690,4 @@ inline namespace kernel throw read_error(make("an end of file is encountered after the beginning of an object's external representation, but the external representation is incomplete and therefore not parsable")); } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/textual_output_port.cpp b/src/kernel/textual_output_port.cpp index 34cb91722..c04de6091 100644 --- a/src/kernel/textual_output_port.cpp +++ b/src/kernel/textual_output_port.cpp @@ -17,9 +17,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto textual_output_port::flush() -> void { @@ -74,5 +72,4 @@ inline namespace kernel os << x; } } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/transformer.cpp b/src/kernel/transformer.cpp index b6e41ee79..f0a5e1295 100644 --- a/src/kernel/transformer.cpp +++ b/src/kernel/transformer.cpp @@ -16,13 +16,10 @@ #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator <<(std::ostream & os, transformer const& datum) -> std::ostream & { return os << magenta("#,(") << green("transformer ") << faint("#;", &datum) << magenta(")"); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/kernel/vector.cpp b/src/kernel/vector.cpp index 72bd231b4..75bef3d3e 100644 --- a/src/kernel/vector.cpp +++ b/src/kernel/vector.cpp @@ -21,9 +21,7 @@ #include #include -namespace meevax -{ -inline namespace kernel +namespace meevax::inline kernel { auto operator ==(heterogeneous_vector const& v, heterogeneous_vector const& u) -> bool { @@ -49,5 +47,4 @@ inline namespace kernel { return make(xs.begin(), xs.end()); } -} // namespace kernel -} // namespace meevax +} // namespace meevax::kernel diff --git a/src/main.cpp b/src/main.cpp index abaf2a308..4df72a3f9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,7 +50,7 @@ auto main(int const argc, char const* const* const argv) -> int { try { - std::cout << u8"\u03bb> " << e.evaluate(standard_input_port().read()) << std::endl; + std::cout << "> " << e.evaluate(standard_input_port().read()) << std::endl; } catch (error const& error) { diff --git a/src/memory/model.cpp b/src/memory/model.cpp index 99b903677..b68dd8b96 100644 --- a/src/memory/model.cpp +++ b/src/memory/model.cpp @@ -19,9 +19,7 @@ #include -namespace meevax -{ -inline namespace memory +namespace meevax::inline memory { auto model::name() -> char const* { @@ -50,5 +48,4 @@ inline namespace memory throw std::logic_error("unknown C data model"); } } -} // namespace memory -} // namespace meevax +} // namespace meevax::memory diff --git a/src/utility/demangle.cpp b/src/utility/demangle.cpp index d686c8063..c7bfb0024 100644 --- a/src/utility/demangle.cpp +++ b/src/utility/demangle.cpp @@ -22,9 +22,7 @@ #include -namespace meevax -{ -inline namespace utility +namespace meevax::inline utility { auto demangle(char const* const name) -> std::string { @@ -47,5 +45,4 @@ inline namespace utility { return demangle(info.name()); } -} // namespace utility -} // namespace meevax +} // namespace meevax::utility diff --git a/test/bitset.cpp b/test/bitset.cpp index 5e471199b..4d77c4c9c 100644 --- a/test/bitset.cpp +++ b/test/bitset.cpp @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/test/number.ss b/test/number.ss new file mode 100644 index 000000000..6b6ac8a5b --- /dev/null +++ b/test/number.ss @@ -0,0 +1,105 @@ +(import (scheme base) + (scheme inexact) + (scheme process-context) + (only (meevax binary32) binary32?) + (only (meevax binary64) binary64?) + (srfi 78) + (srfi 144)) + +(check (real? 1.0e0) => #t) +(check (binary32? 1.0e0) => #f) +(check (binary64? 1.0e0) => #t) + +(check (real? 1.0f0) => #t) +(check (binary32? 1.0f0) => #t) +(check (binary64? 1.0f0) => #f) + +(check (real? 1.0d0) => #t) +(check (binary32? 1.0d0) => #f) +(check (binary64? 1.0d0) => #t) + +(check (rational? 1/3) => #t) +(check (rational? 0.5) => #t) + +(check (+ 1 2 3) (=> =) 6) +(check (number? (+ 1 2 3)) => #t) +(check (complex? (+ 1 2 3)) => #t) +(check (real? (+ 1 2 3)) => #t) +(check (rational? (+ 1 2 3)) => #t) +(check (integer? (+ 1 2 3)) => #t) +(check (exact? (+ 1 2 3)) => #t) +(check (inexact? (+ 1 2 3)) => #f) + +(check (+ 1 1/2) (=> =) 3/2) +(check (number? (+ 1 1/2)) => #t) +(check (complex? (+ 1 1/2)) => #t) +(check (real? (+ 1 1/2)) => #t) +(check (rational? (+ 1 1/2)) => #t) +(check (integer? (+ 1 1/2)) => #f) +(check (exact? (+ 1 1/2)) => #t) +(check (inexact? (+ 1 1/2)) => #f) + +(check (* 2 1/2) (=> =) 1) +(check (number? (* 2 1/2)) => #t) +(check (complex? (* 2 1/2)) => #t) +(check (real? (* 2 1/2)) => #t) +(check (rational? (* 2 1/2)) => #t) +(check (integer? (* 2 1/2)) => #t) +(check (exact? (* 2 1/2)) => #t) +(check (inexact? (* 2 1/2)) => #f) + +(check (+ 1/3 1/3 1/3) (=> =) 1) +(check (number? (+ 1/3 1/3 1/3)) => #t) +(check (complex? (+ 1/3 1/3 1/3)) => #t) +(check (real? (+ 1/3 1/3 1/3)) => #t) +(check (rational? (+ 1/3 1/3 1/3)) => #t) +(check (integer? (+ 1/3 1/3 1/3)) => #t) +(check (exact? (+ 1/3 1/3 1/3)) => #t) +(check (inexact? (+ 1/3 1/3 1/3)) => #f) + +(check (+ 1 1.0) (=> =) 2.0) +(check (+ 1.0 1 ) (=> =) 2.0) + +(check (+ 1 1/2) (=> =) 3/2) +(check (+ 1.0 1/2) (=> =) 1.5) + +(check (+ 1/2 1 ) (=> =) 3/2) +(check (+ 1/2 1.0) (=> =) 1.5) + +(check (* 2 1/2) (=> =) 1 ) +(check (* 2.0 1/2) (=> =) 1.0) + +(check (modulo 13 4) => 1) +(check (modulo -13 4) => 3) +(check (modulo 13 -4) => -3) +(check (modulo -13 -4) => -1) + +(check (remainder 13 4) => 1) +(check (remainder -13 4) => -1) +(check (remainder 13 -4) => 1) +(check (remainder -13 -4) => -1) +(check (remainder -13 -4.0) => -1.0) ; inexact + +(check (log 0.0) => -inf.0) + +(check (sin 0) (=> =) 0) +(check (sin (/ fl-pi 6)) (=> =) 0.5) +; (check (sin (/ fl-pi 4)) (=> =) 0.707107) +; (check (sin (/ fl-pi 3)) (=> =) 0.866025) +(check (sin (/ fl-pi 2)) (=> =) 1) +; (check (sin fl-pi) (=> =) 0) + +(check (atan 0.0 1.0) => 0.000000) +; (check (atan 1.0 1.0) => 0.785398) +; (check (atan 1.0 0.0) => 1.570796) +; (check (atan 1.0 -1.0) => 2.356194) +; (check (atan 0.0 -1.0) => 3.141593) +; (check (atan -1.0 -1.0) => -2.356194) +; (check (atan -1.0 0.0) => -1.570796) +; (check (atan -1.0 1.0) => -0.785398) + +(check (exact 0.333333) => 3002396749180579/9007199254740992) + +(check-report) + +(exit (check-passed? 66)) diff --git a/test/numerical-operations.ss b/test/numerical-operations.ss deleted file mode 100644 index 4e5ae4dd9..000000000 --- a/test/numerical-operations.ss +++ /dev/null @@ -1,114 +0,0 @@ -(import (scheme base) - (scheme inexact) - (scheme process-context) - (srfi 78)) - -; ---- 6.2.6. Numerical operations --------------------------------------------- - -(check (rational? 1/3) => #t) -(check (rational? 0.5) => #t) - -(let ((x (+ 1 2 3))) - - (check x => 6) - - (check (number? x) => #t) - (check (complex? x) => #t) - (check (real? x) => #t) - (check (rational? x) => #t) - (check (integer? x) => #t) - - (check (exact? x) => #t) - (check (inexact? x) => #f) - ) - -(let ((x (+ 1 1/2))) - - (check x (=> =) 3/2) - - (check (number? x) => #t) - (check (complex? x) => #t) - (check (real? x) => #t) - (check (rational? x) => #t) - (check (integer? x) => #f) - - (check (exact? x) => #t) - (check (inexact? x) => #f) - ) - -(let ((x (* 2 1/2))) - - (check x (=> =) 1) - - (check (number? x) => #t) - (check (complex? x) => #t) - (check (real? x) => #t) - (check (rational? x) => #t) - (check (integer? x) => #t) - - (check (exact? x) => #t) - (check (inexact? x) => #f) - ) - -(let ((x (+ 1/3 1/3 1/3))) - - (check x (=> =) 1) - - (check (number? x) => #t) - (check (complex? x) => #t) - (check (real? x) => #t) - (check (rational? x) => #t) - (check (integer? x) => #t) - - (check (exact? x) => #t) - (check (inexact? x) => #f) - ) - -(check (+ 1 1.0) (=> =) 2.0) -(check (+ 1.0 1 ) (=> =) 2.0) - -(check (+ 1 1/2) (=> =) 3/2) -(check (+ 1.0 1/2) (=> =) 1.5) - -(check (+ 1/2 1 ) (=> =) 3/2) -(check (+ 1/2 1.0) (=> =) 1.5) - -(check (* 2 1/2) (=> =) 1 ) -(check (* 2.0 1/2) (=> =) 1.0) - -(check (modulo 13 4) => 1) -(check (modulo -13 4) => 3) -(check (modulo 13 -4) => -3) -(check (modulo -13 -4) => -1) - -(check (remainder 13 4) => 1) -(check (remainder -13 4) => -1) -(check (remainder 13 -4) => 1) -(check (remainder -13 -4) => -1) -(check (remainder -13 -4.0) => -1.0) ; inexact - -(check (log 0.0) => -inf.0) - -(check (sin 0) (=> =) 0) -(check (sin (/ fl-pi 6)) (=> =) 0.5) -; (check (sin (/ fl-pi 4)) (=> =) 0.707107) -; (check (sin (/ fl-pi 3)) (=> =) 0.866025) -(check (sin (/ fl-pi 2)) (=> =) 1) -; (check (sin fl-pi) (=> =) 0) - -(check (atan 0.0 1.0) => 0.000000) -; (check (atan 1.0 1.0) => 0.785398) -; (check (atan 1.0 0.0) => 1.570796) -; (check (atan 1.0 -1.0) => 2.356194) -; (check (atan 0.0 -1.0) => 3.141593) -; (check (atan -1.0 -1.0) => -2.356194) -; (check (atan -1.0 0.0) => -1.570796) -; (check (atan -1.0 1.0) => -0.785398) - -(check (exact 0.333333) => 3002396749180579/9007199254740992) - -; ---- SRFI-78 ----------------------------------------------------------------- - -(check-report) - -(exit (check-passed? 57)) diff --git a/test/r7rs.ss b/test/r7rs.ss index c8f4d1cef..73511944c 100644 --- a/test/r7rs.ss +++ b/test/r7rs.ss @@ -749,7 +749,7 @@ (check (eqv? (lambda (x) x) (lambda (y) y)) => #f) ; unspecified -(check (eqv? 1.0e0 1.0f0) => #t) ; unspecified +(check (eqv? 1.0e0 1.0f0) => #f) ; unspecified (check (eqv? +nan.0 +nan.0) => #t) ; unspecified diff --git a/test/srfi-144.ss b/test/srfi-144.ss new file mode 100644 index 000000000..a82b060cd --- /dev/null +++ b/test/srfi-144.ss @@ -0,0 +1,388 @@ +(import (only (meevax inexact) acosh asinh atanh cosh sinh tanh) + (scheme base) + (scheme inexact) + (scheme process-context) + (srfi 78) + (srfi 144)) + +(check fl-e => 2.718281828459045) + +(check fl-1/e => 0.3678794411714423215955238) + +(check fl-e-2 => 7.38905609893065) + +(check fl-e-pi/4 => 2.1932800507380154566) + +(check fl-log2-e => 1.4426950408889634073599246810018921374266) + +(check fl-log10-e => 0.4342944819032518276511289) + +(check fl-log-2 => 0.6931471805599453094172321) + +(check fl-1/log-2 => 1.4426950408889634073599246810018921374266) + +(check fl-log-3 => 1.0986122886681096913952452) + +(check fl-log-pi => 1.144729885849400174143427) + +(check fl-log-10 => 2.3025850929940456840179915) + +(check fl-1/log-10 => 0.4342944819032518276511289189166050822944) + +(check fl-pi => 3.1415926535897932384626433832795028841972) + +(check fl-1/pi => 0.3183098861837906715377675267450287240689) + +(check fl-2pi => 6.283185307179586476925287) + +(check fl-pi/2 => 1.570796326794896619231322) + +(check fl-pi/4 => 0.7853981633974483096156608) + +(check fl-pi-squared => 9.869604401089358618834491) + +(check fl-degree => 0.0174532925199432957692369076848861271344) + +(check fl-2/pi => 0.6366197723675814) + +(check fl-2/sqrt-pi => 1.1283791670955126) + +(check fl-sqrt-2 => 1.4142135623730950488016887242096980785697) + +(check fl-sqrt-3 => 1.7320508075688772935274463415058723669428) + +(check fl-sqrt-5 => 2.2360679774997896964091736687311762354406) + +(check fl-sqrt-10 => 3.1622776601683793319988935444327185337196) + +(check fl-1/sqrt-2 => 0.7071067811865475) + +(check fl-cbrt-2 => 1.2599210498948731647672106072782283505703) + +(check fl-cbrt-3 => 1.4422495703074083823216383107801095883919) + +(check fl-4thrt-2 => 1.1892071150027210667174999705604759152930) + +(check fl-phi => 1.6180339887498948482045868343656381177203) + +(check fl-log-phi => 0.4812118250596034474977589134243684231352) + +(check fl-1/log-phi => 2.0780869212350275376013226061177957677422) + +(check fl-euler => 0.5772156649015328606065120900824024310422) + +(check fl-e-euler => 1.7810724179901979852365041031071795491696) + +(check fl-sin-1 => 0.8414709848078965066525023216302989996226) + +(check fl-cos-1 => 0.5403023058681397174009366074420766037323) + +(check fl-gamma-1/2 => 1.7724538509055160272981674833411451827975) + +(check fl-gamma-1/3 => 2.6789385347077476336556929409746776441287) + +(check fl-gamma-2/3 => 1.3541179394264004169452880281545137855193) + +(check (flonum? fl-greatest) => #t) +(check (flonum? fl-least) => #t) + +(check (< 0.0 0.0) => #f) + +(check (< 0.0 fl-least) => #t) + +(check (flonum? fl-epsilon) => #t) + +(check (boolean? fl-fast-fl+*) => #t) + +(check (exact-integer? fl-integer-exponent-zero) => #t) +(check (exact-integer? fl-integer-exponent-nan) => #t) + +(check (= (flonum 22/7) fl-pi) => #f) +(check (= (flonum 333/106) fl-pi) => #f) +(check (= (flonum 355/113) fl-pi) => #f) +(check (= (flonum 52163/16604) fl-pi) => #f) +(check (= (flonum 103993/33102) fl-pi) => #f) +(check (= (flonum 104348/33215) fl-pi) => #f) +(check (= (flonum 245850922/78256779) fl-pi) => #t) + +(check (fladjacent 0.0 1.0) (=> =) fl-least) + +(check (< 0.0 (fladjacent 0.0 1.0) fl-epsilon 1.0 (+ 1.0 fl-epsilon) fl-greatest +inf.0) => #t) + +(check (flcopysign 0.0 +inf.0) => 0.0) +(check (flcopysign 0.0 -inf.0) => -0.0) + +(check (make-flonum 3.0 4) => 48.0) + +(call-with-values + (lambda () (flinteger-fraction 3.14)) + (lambda (integral fractional) + (check integral (=> =) 3.0) + (check fractional (=> =) 0.14))) + +(check (flexponent 48.0) => 5.0) +(check (flexponent -48.0) => 5.0) + +(check (flinteger-exponent 48.0) => 5) +(check (flinteger-exponent -48.0) => 5) + +(call-with-values + (lambda () (flnormalized-fraction-exponent 48.0)) + (lambda (fraction exponent) + (check fraction => 0.75) + (check exponent => 6))) + +(check (flsign-bit 3.14) => 0) +(check (flsign-bit -3.14) => 1) + +(check (flonum? 1.0) => #t) +(check (flonum? 1.0f0) => #f) + +(check (procedure? fl=?) => #t) + +(check (procedure? fl #t) + +(check (procedure? fl>?) => #t) + +(check (procedure? fl<=?) => #t) + +(check (procedure? fl>=?) => #t) + +(check (flunordered? 1.0 2.0) => #f) +(check (flunordered? 1.0 +nan.0) => #t) + +(check (flinteger? 3.14) => #f) +(check (flinteger? 1.0) => #t) + +(check (procedure? flzero?) => #t) + +(check (procedure? flpositive?) => #t) + +(check (procedure? flnegative?) => #t) + +(check (procedure? flodd?) => #t) + +(check (procedure? fleven?) => #t) + +(check (procedure? flfinite?) => #t) + +(check (procedure? flinfinite?) => #t) + +(check (procedure? flnan?) => #t) + +(check (flnormalized? 1.0) => #t) + +(check (fldenormalized? (/ fl-least 2)) => #t) + +(check (flmax) => -inf.0) +(check (flmax 0.0) => 0.0) +(check (flmax -1.0 0.0 1.0) => 1.0) + +(check (flmin) => +inf.0) +(check (flmin 0.0) => 0.0) +(check (flmin -1.0 0.0 1.0) => -1.0) + +(check (procedure? fl+) => #t) + +(check (procedure? fl*) => #t) + +(check (fl+* 2.0 3.0 4.0) => 10.0) + +(check (procedure? fl-) => #t) + +(check (procedure? fl/) => #t) + +(check (flabs -0.0) => +0.0) +(check (flabs -inf.0) => +inf.0) +(check (flabs +inf.0) => +inf.0) + +(check (flabsdiff 0.0 1.0) => 1.0) +(check (flabsdiff +inf.0 -inf.0) => +inf.0) +(check (flabsdiff -inf.0 +inf.0) => +inf.0) +(check (flposdiff 3.0 4.0) => 0.0) + +(check (flsgn +inf.0) => 1.0) +(check (flsgn -inf.0) => -1.0) +(check (flsgn +0.0) => 1.0) +(check (flsgn -0.0) => -1.0) + +(check (numerator 2.25) => 9.0) + +(check (numerator -2.25) => -9.0) + +(check (denominator 2.25) => 4.0) + +(check (denominator -2.25) => 4.0) + +(check (procedure? flfloor) => #t) + +(check (procedure? flceiling) => #t) + +(check (procedure? flround) => #t) + +(check (procedure? fltruncate) => #t) + +(check (flexp -0.0) => 1.0) +(check (flexp 0.0) => 1.0) +(check (flexp 1.0) => fl-e) + +(check (flexp2 -0.0) => 1.0) +(check (flexp2 0.0) => 1.0) +(check (flexp2 fl-log2-e) => fl-e) + +(check (fl+ 1.0 (flexp-1 fl-least)) => 1.0) + +(check (flsquare -0.0) => 0.0) +(check (flsquare 0.0) => 0.0) +(check (flsquare 1.0) => 1.0) +(check (flsquare 2.0) => 4.0) + +(check (flsqrt -0.0) => -0.0) +(check (flsqrt 0.0) => 0.0) +(check (flsqrt 1.0) => 1.0) +(check (flsqrt 2.0) => fl-sqrt-2) +(check (flsqrt 3.0) => fl-sqrt-3) +(check (flsqrt 5.0) => fl-sqrt-5) +(check (flsqrt 10.0) => fl-sqrt-10) + +(check (flcbrt 0.0) => 0.0) +(check (flcbrt 1.0) => 1.0) +(check (flcbrt 1.0) => 1.0) +(check (flcbrt 2.0) => fl-cbrt-2) +(check (flcbrt 3.0) => fl-cbrt-3) + +(check (flhypot 0.0 0.0) => 0.0) +(check (flhypot 0.0 1.0) => 1.0) +(check (flhypot 0.0 -1.0) => 1.0) +(check (flhypot 1.0 1.0) => fl-sqrt-2) +(check (flhypot 1.0 2.0) => fl-sqrt-5) +(check (flhypot 1.0 3.0) => fl-sqrt-10) + +(check (flexpt 0.0 0.0) => 1.0) +(check (flexpt 1.0 0.0) => 1.0) +(check (flexpt 2.0 1.0) => 2.0) +(check (flexpt 2.0 2.0) => 4.0) +(check (flexpt 2.0 3.0) => 8.0) + +(check (fllog 0.0) => -inf.0) +(check (fllog 1.0) => 0.0) +(check (fllog fl-phi) => fl-log-phi) +(check (fllog 2.0) => fl-log-2) +(check (fllog 3.0) => fl-log-3) +(check (fllog fl-pi) => fl-log-pi) +(check (fllog 10.0) => fl-log-10) + +(check (fllog1+ 0.0) => 0.0) +(check (fllog1+ fl-least) (=> =) 0.0) +(check (fllog1+ 1.0) => fl-log-2) +(check (fllog1+ 2.0) (=> =) fl-log-3) +(check (fllog1+ 9.0) => fl-log-10) + +(check (fllog2 0.0) => -inf.0) +(check (fllog2 1.0) => 0.0) +(check (fllog2 2.0) => 1.0) +(check (fllog2 fl-e) => fl-log2-e) +(check (fllog2 +inf.0) => +inf.0) + +(check (fllog10 0.0) => -inf.0) +(check (fllog10 1.0) => 0.0) +(check (fllog10 10.0) => 1.0) +(check (fllog10 fl-e) (=> =) fl-log10-e) +(check (fllog10 +inf.0) => +inf.0) + +(check ((make-fllog-base 2.0) 0.0) => -inf.0) +(check ((make-fllog-base 2.0) 1.0) => 0.0) +(check ((make-fllog-base 2.0) 2.0) => 1.0) +(check ((make-fllog-base 2.0) fl-e) => fl-log2-e) +(check ((make-fllog-base 2.0) +inf.0) => +inf.0) + +(check ((make-fllog-base 10.0) 0.0) => -inf.0) +(check ((make-fllog-base 10.0) 1.0) => 0.0) +(check ((make-fllog-base 10.0) 10.0) => 1.0) +(check ((make-fllog-base 10.0) fl-e) (=> =) fl-log10-e) +(check ((make-fllog-base 10.0) +inf.0) => +inf.0) + +(check flsin => sin) + +(check flcos => cos) + +(check fltan => tan) + +(check flasin => asin) + +(check flacos => acos) + +(check flatan => atan) + +(check flsinh => sinh) + +(check flcosh => cosh) + +(check fltanh => tanh) + +(check flasinh => asinh) + +(check flacosh => acosh) + +(check flatanh => atanh) + +(check (flquotient 3.14 0.5) => 6.0) +(check (flquotient -3.14 0.5) => -6.0) +(check (flquotient 3.14 -0.5) => -6.0) +(check (flquotient -3.14 -0.5) => 6.0) + +(check (flremainder 3.14 0.5) (=> =) 0.14) +(check (flremainder -3.14 0.5) (=> =) -0.14) +(check (flremainder 3.14 -0.5) (=> =) 0.14) +(check (flremainder -3.14 -0.5) (=> =) -0.14) + +(call-with-values (lambda () (flremquo 5.0 2.0 )) (lambda (r q) (check q => 2) (check r => 1.0))) +(call-with-values (lambda () (flremquo 6.0 4.0 )) (lambda (r q) (check q => 2) (check r => -2.0))) +(call-with-values (lambda () (flremquo 6.3 3.0 )) (lambda (r q) (check q => 2) (check r (=> =) 0.3))) +(call-with-values (lambda () (flremquo 6.3 -3.0 )) (lambda (r q) (check q => -2) (check r (=> =) 0.3))) +(call-with-values (lambda () (flremquo -6.3 3.0 )) (lambda (r q) (check q => -2) (check r (=> =) -0.3))) +(call-with-values (lambda () (flremquo -6.3 -3.0 )) (lambda (r q) (check q => 2) (check r (=> =) -0.3))) +(call-with-values (lambda () (flremquo 6.3 3.15)) (lambda (r q) (check q => 2) (check r => 0.0))) +(call-with-values (lambda () (flremquo 6.0 2.0 )) (lambda (r q) (check q => 3) (check r => 0.0))) + +(check (flgamma 0.5) => fl-gamma-1/2) +(check (flgamma 2/3) => fl-gamma-2/3) + +(call-with-values (lambda () (flloggamma 0.0)) (lambda (value sign) (check value => +inf.0) (check sign => 1.0))) +(call-with-values (lambda () (flloggamma 0.5)) (lambda (value sign) (check value (=> =) (log fl-gamma-1/2)) (check sign => 1.0))) +(call-with-values (lambda () (flloggamma 1.0)) (lambda (value sign) (check value => 0.0) (check sign => 1.0))) +(call-with-values (lambda () (flloggamma +inf.0)) (lambda (value sign) (check value => +inf.0) (check sign => 1.0))) + +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 0.0 (* 0/3 fl-pi))) (else 1.0 )) => 1.0 ) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 0.0 (* 1/3 fl-pi))) (else 0.74407197075292975)) => 0.74407197075292975) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 0.0 (* 2/3 fl-pi))) (else 0.16979382182100766)) => 0.16979382182100766) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 0.5 (* 0/3 fl-pi))) (else 0.0 )) => 0.0 ) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 0.5 (* 1/3 fl-pi))) (else 0.67523723711782946)) => 0.67523723711782946) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 0.5 (* 2/3 fl-pi))) (else 0.47746482927568606)) => 0.47746482927568606) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 1.0 (* 0/3 fl-pi))) (else 0.0 )) => 0.0 ) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 1.0 (* 1/3 fl-pi))) (else 0.45503061147236740)) => 0.45503061147236740) +(check (cond-expand (__cpp_lib_math_special_functions (flfirst-bessel 1.0 (* 2/3 fl-pi))) (else 0.56886896392288921)) => 0.56886896392288921) + +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 0.0 (* 0/3 fl-pi))) (else -inf.0 )) => -inf.0 ) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 0.0 (* 1/3 fl-pi))) (else 0.12417445819941761)) => 0.12417445819941761) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 0.0 (* 2/3 fl-pi))) (else 0.51799555016845289)) => 0.51799555016845289) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 0.5 (* 0/3 fl-pi))) (else -inf.0 )) => -inf.0 ) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 0.5 (* 1/3 fl-pi))) (else -0.38984840061683823)) => -0.38984840061683823) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 0.5 (* 2/3 fl-pi))) (else 0.27566444771089593)) => 0.27566444771089593) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 1.0 (* 0/3 fl-pi))) (else -inf.0 )) => -inf.0 ) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 1.0 (* 1/3 fl-pi))) (else -0.74108949656080647)) => -0.74108949656080647) +(check (cond-expand (__cpp_lib_math_special_functions (flsecond-bessel 1.0 (* 2/3 fl-pi))) (else -0.05472495339562021)) => -0.05472495339562021) + +(check (flerf -inf.0) => -1.0) +(check (flerf 0.0) => 0.0) +(check (flerf 1.0) (=> =) 0.8427007929497149) +(check (flerf +inf.0) => 1.0) + +(check (flerfc -inf.0) => 2.0) +(check (flerfc 0.0) => 1.0) +(check (flerfc 1.0) (=> =) 0.15729920705028513) +(check (flerfc +inf.0) => 0.0) + +(check-report) + +(exit (check-passed? 258))