diff --git a/.github/workflows/build-asy-linux.yml b/.github/workflows/build-asy-linux.yml index 24b7c3868..e664b0caa 100644 --- a/.github/workflows/build-asy-linux.yml +++ b/.github/workflows/build-asy-linux.yml @@ -50,6 +50,8 @@ jobs: run: | echo set\(ASY_VERSION_SUFFIX \"/github-ci/ref=${{ github.sha }}\"\) > asy-pkg-version-suffix.cmake - run: cmake --build --preset linux/release --target asy-with-basefiles -j + - name: build misc files + run: cmake --build --preset linux/release-ccache --target asy-dist-misc-files -j - name: Archive build files uses: actions/upload-artifact@v4 with: @@ -57,6 +59,12 @@ jobs: path: | cmake-build-linux/release/asy cmake-build-linux/release/base + - name: Archive misc files + uses: actions/upload-artifact@v4 + with: + name: asy-miscfiles + path: | + cmake-build-linux/release/misc-output - name: Build Asymptote google test files run: cmake --build --preset linux/release --target asyCxxTests -j - name: Archive Asymptote gtest files @@ -121,6 +129,11 @@ jobs: with: name: asy-buildfiles path: tar-stage + - name: Download misc files + uses: actions/download-artifact@v4 + with: + name: asy-miscfiles + path: tar-stage/misc/ - name: Download asymptote.pdf uses: actions/download-artifact@v4 with: @@ -136,7 +149,7 @@ jobs: - name: Set asy's +x flag run: chmod +x tar-stage/asy - name: tar package - run: tar -C tar-stage -cvhf asymptote-build-linux.tar asy base examples doc + run: tar -C tar-stage -cvhf asymptote-build-linux.tar asy base examples doc misc - name: Archive Asymptote test files uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/build-asy-windows.yml b/.github/workflows/build-asy-windows.yml index 8219ed997..a0518b88a 100644 --- a/.github/workflows/build-asy-windows.yml +++ b/.github/workflows/build-asy-windows.yml @@ -101,6 +101,10 @@ jobs: run: | ${{ env.pwsh_initialize_devenv }} cmake --build cmake-build-msvc/release --target asy-with-basefiles -j + - name: Build misc files on windows + run: | + ${{ env.pwsh_initialize_devenv }} + cmake --build cmake-build-msvc/release --target asy-dist-misc-files -j - name: Archive Asymptote build uses: actions/upload-artifact@v4 with: @@ -109,6 +113,12 @@ jobs: cmake-build-msvc/release/asy.exe cmake-build-msvc/release/base cmake-build-msvc/release/*.dll + - name: Archive Asymptote misc files + uses: actions/upload-artifact@v4 + with: + name: asy-win-x64-miscfiles + path: | + cmake-build-msvc/release/misc-output - name: Build Asymptote google test run: | ${{ env.pwsh_initialize_devenv }} diff --git a/.github/workflows/package-asy-installer-win.yml b/.github/workflows/package-asy-installer-win.yml index 01f3e1702..1f7e7bf37 100644 --- a/.github/workflows/package-asy-installer-win.yml +++ b/.github/workflows/package-asy-installer-win.yml @@ -33,11 +33,17 @@ jobs: with: name: cmake-windows-gui-files path: GUI/ + - name: Download misc files + uses: actions/download-artifact@v4 + with: + name: asy-win-x64-miscfiles + path: | + cmake-build-msvc/release/misc-output - name: Download asymptote.pdf uses: actions/download-artifact@v4 with: name: asy-pdf-file - path: extfiles/ + path: asydoc/ - name: do cmake install run: cmake --install cmake-build-msvc/release --component asy-pre-nsis - name: Build installer file diff --git a/CMakeLists.txt b/CMakeLists.txt index e973b6652..0c5bdfa30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,11 @@ include(cmake-scripts/asy-base-files.cmake) add_custom_target(asy-basefiles DEPENDS ${ASY_OUTPUT_BASE_FILES}) add_custom_target(asy-with-basefiles ALL DEPENDS asy asy-basefiles) +# asy misc files +if (ENABLE_MISCFILES_GEN) + include(cmake-scripts/asy-misc-files.cmake) +endif() + # documentation generation if (ENABLE_DOCGEN) diff --git a/CMakePresets.json b/CMakePresets.json index caab06619..2d7a736f7 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -129,7 +129,7 @@ "inherits": ["msvc/release"], "cacheVariables": { "ENABLE_ASYMPTOTE_PDF_DOCGEN": "false", - "EXTERNAL_DOCUMENTATION_DIR": "${sourceDir}/extfiles" + "EXTERNAL_DOCUMENTATION_DIR": "${sourceDir}/asydoc" } }, { diff --git a/INSTALL-WIN.md b/INSTALL-WIN.md index 9046b7b13..65ce4b691 100644 --- a/INSTALL-WIN.md +++ b/INSTALL-WIN.md @@ -206,8 +206,8 @@ are present in the system. #### If using a pre-built `asymptote.pdf` -Place `asymptote.pdf` in the directory `/extfiles/`. -That is, the file `/extfiles/asymptote.pdf` is present. +Place `asymptote.pdf` in the directory `/asydoc/`. +That is, the file `/asydoc/asymptote.pdf` is present. After that, configure cmake with the preset `msvc/release-with-existing-asymptote-pdf` - that is, ```powershell diff --git a/LspCpp/.gitrepo b/LspCpp/.gitrepo index 5598c2727..9b4d69a1b 100644 --- a/LspCpp/.gitrepo +++ b/LspCpp/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:vectorgraphics/LspCpp branch = master - commit = 220a861ca2bfaf14fa402549ddcf484459f36406 - parent = f240306af01490de4880237ba21eff585cb07e52 + commit = d12eab466ee2c9eb8bb8925ec8482e374a880fcc + parent = 2c34fbcaf9d487f6fd7a9299649dbc9f76860e83 method = merge cmdver = 0.4.9 diff --git a/LspCpp/include/LibLsp/lsp/ClientPreferences.h b/LspCpp/include/LibLsp/lsp/ClientPreferences.h index c8920e449..cf1138ba8 100644 --- a/LspCpp/include/LibLsp/lsp/ClientPreferences.h +++ b/LspCpp/include/LibLsp/lsp/ClientPreferences.h @@ -139,10 +139,18 @@ class ClientPreferences return v3supported && isDynamicRegistrationSupported(textDocument.documentHighlight); } + bool isDocumentLinkDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.documentLink); + } + bool isFoldgingRangeDynamicRegistered() { return v3supported && isDynamicRegistrationSupported(textDocument.foldingRange); } + bool isInlayHintDynamicRegistered() { + return v3supported && isDynamicRegistrationSupported(textDocument.inlayHint); + } + bool isImplementationDynamicRegistered() { return v3supported && isDynamicRegistrationSupported(textDocument.implementation); } diff --git a/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h b/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h index e8624681b..67a9ae2e7 100644 --- a/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h +++ b/LspCpp/include/LibLsp/lsp/general/lsServerCapabilities.h @@ -380,6 +380,21 @@ MAKE_REFLECT_STRUCT(SemanticTokensWithRegistrationOptions, legend, range, full, using DocumentColorOptions = WorkDoneProgressOptions; using FoldingRangeOptions = WorkDoneProgressOptions; + +struct InlayHintOptions : WorkDoneProgressOptions { + + /** + * The server provides support to resolve additional + * information for an inlay hint item. + */ + optional resolveProvider; + + MAKE_SWAP_METHOD(InlayHintOptions, workDoneProgress, resolveProvider); + +}; + +MAKE_REFLECT_STRUCT(InlayHintOptions, workDoneProgress, resolveProvider) + struct lsServerCapabilities { // Defines how text documents are synced. Is either a detailed structure // defining each notification or for backwards compatibility the @@ -528,6 +543,14 @@ struct lsServerCapabilities { optional< std::pair< optional, optional > > monikerProvider; + /** + * The server provides inlay hints. + * + * @since 3.17.0 + */ + optional< std::pair< optional, + optional > > inlayHintProvider; + optional experimental; diff --git a/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h b/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h index 1523254d6..0c0c6a026 100644 --- a/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h +++ b/LspCpp/include/LibLsp/lsp/general/lsTextDocumentClientCapabilities.h @@ -668,6 +668,13 @@ struct lsTextDocumentClientCapabilities { // optional< DynamicRegistrationCapabilities > moniker; + // + // Capabilities specific to the `textDocument/inlayHint` request. + // + // @since 3.17.0 + // + optional< InlayHintClientCapabilities > inlayHint; + MAKE_SWAP_METHOD(lsTextDocumentClientCapabilities, synchronization, completion, @@ -687,7 +694,9 @@ struct lsTextDocumentClientCapabilities { documentLink, colorProvider, rename, publishDiagnostics, foldingRange, semanticHighlightingCapabilities, typeHierarchyCapabilities, - callHierarchy, selectionRange , linkedEditingRange, semanticTokens, moniker) + callHierarchy, selectionRange , linkedEditingRange, semanticTokens, moniker, + inlayHint + ) }; @@ -710,4 +719,6 @@ MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, documentLink, colorProvider, rename, publishDiagnostics, foldingRange, semanticHighlightingCapabilities, typeHierarchyCapabilities, - callHierarchy, selectionRange, linkedEditingRange, semanticTokens, moniker) + callHierarchy, selectionRange, linkedEditingRange, semanticTokens, moniker, + inlayHint +) diff --git a/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h b/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h index 4b48aec41..ca01a9cf5 100644 --- a/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h +++ b/LspCpp/include/LibLsp/lsp/general/lsWorkspaceClientCapabilites.h @@ -98,6 +98,25 @@ MAKE_REFLECT_STRUCT(DynamicRegistrationCapabilities, dynamicRegistration); +struct InlayHintLazyProperties { + optional< std::vector > properties; + + MAKE_SWAP_METHOD(InlayHintLazyProperties, properties) +}; + +MAKE_REFLECT_STRUCT(InlayHintLazyProperties, properties) + +struct InlayHintClientCapabilities { + // Whether inlay hints support dynamic registration. + optional dynamicRegistration; + + optional< InlayHintLazyProperties > resolveSupport; + + MAKE_SWAP_METHOD(InlayHintClientCapabilities, dynamicRegistration, resolveSupport); + +}; + +MAKE_REFLECT_STRUCT(InlayHintClientCapabilities, dynamicRegistration, resolveSupport) // Workspace specific client capabilities. struct SymbolKindCapabilities diff --git a/LspCpp/include/LibLsp/lsp/textDocument/document_link.h b/LspCpp/include/LibLsp/lsp/textDocument/document_link.h index 92f02b24f..c352c98e5 100644 --- a/LspCpp/include/LibLsp/lsp/textDocument/document_link.h +++ b/LspCpp/include/LibLsp/lsp/textDocument/document_link.h @@ -2,7 +2,9 @@ #include "LibLsp/JsonRpc/RequestInMessage.h" #include "LibLsp/JsonRpc/lsResponseMessage.h" - +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsRange.h" +#include "LibLsp/lsp/lsAny.h" namespace TextDocumentDocumentLink { diff --git a/LspCpp/include/LibLsp/lsp/textDocument/inlayHint.h b/LspCpp/include/LibLsp/lsp/textDocument/inlayHint.h new file mode 100644 index 000000000..cdb6a25c0 --- /dev/null +++ b/LspCpp/include/LibLsp/lsp/textDocument/inlayHint.h @@ -0,0 +1,169 @@ +#pragma once + +#include "LibLsp/JsonRpc/RequestInMessage.h" +#include "LibLsp/JsonRpc/lsResponseMessage.h" +#include "LibLsp/lsp/lsTextDocumentIdentifier.h" +#include "LibLsp/lsp/lsRange.h" +#include "LibLsp/lsp/location_type.h" +#include "LibLsp/lsp/lsCommand.h" +#include "LibLsp/lsp/lsTextEdit.h" +#include "LibLsp/lsp/lsAny.h" + +namespace TextDocumentInlayHint { + + struct Params { + // The text document + lsTextDocumentIdentifier textDocument; + // The visible document range for which inlay hints should be computed. + lsRange range; + + MAKE_SWAP_METHOD(Params, textDocument, range) + }; + +}; +MAKE_REFLECT_STRUCT(TextDocumentInlayHint::Params, textDocument, range); + + +struct lsInlayHintLabelPart { + + /** + * The value of this label part. + */ + std::string value; + + /** + * The tooltip text when you hover over this label part. Depending on + * the client capability `inlayHint.resolveSupport` clients might resolve + * this property late using the resolve request. + */ + optional tooltip; + + /** + * An optional source code location that represents this + * label part. + * + * The editor will use this location for the hover and for code navigation + * features: This part will become a clickable link that resolves to the + * definition of the symbol at the given location (not necessarily the + * location itself), it shows the hover that shows at the given location, + * and it shows a context menu with further code navigation commands. + * + * Depending on the client capability `inlayHint.resolveSupport` clients + * might resolve this property late using the resolve request. + */ + optional location; + + /** + * An optional command for this label part. + * + * Depending on the client capability `inlayHint.resolveSupport` clients + * might resolve this property late using the resolve request. + */ + optional> command; + + MAKE_SWAP_METHOD(lsInlayHintLabelPart, value, tooltip, location, command) + +}; + +MAKE_REFLECT_STRUCT(lsInlayHintLabelPart, value, tooltip, location, command); + +enum class lsInlayHintKind { + + // An inlay hint that for a type annotation. + Type = 1, + + // An inlay hint that is for a parameter. + Parameter = 2 + +}; + +MAKE_REFLECT_TYPE_PROXY(lsInlayHintKind); + +/** + * a inlay hint is displayed in the editor right next to normal code, it is only readable text + * that acts like a hint, for example parameter names in function calls are displayed in editors + * as inlay hints + */ +struct lsInlayHint { + + /** + * The position of this hint. + * + * If multiple hints have the same position, they will be shown in the order + * they appear in the response. + */ + lsPosition position; + + /** + * The label of this hint. A human readable string or an array of + * InlayHintLabelPart label parts. + * + * *Note* that neither the string nor the label part can be empty. + */ + std::string label; + + /** + * The kind of this hint. Can be omitted in which case the client + * should fall back to a reasonable default. + */ + optional kind; + + /** + * Optional text edits that are performed when accepting this inlay hint. + * + * *Note* that edits are expected to change the document so that the inlay + * hint (or its nearest variant) is now part of the document and the inlay + * hint itself is now obsolete. + * + * Depending on the client capability `inlayHint.resolveSupport` clients + * might resolve this property late using the resolve request. + */ + optional> textEdits; + + /** + * The tooltip text when you hover over this item. + * + * Depending on the client capability `inlayHint.resolveSupport` clients + * might resolve this property late using the resolve request. + */ + optional tooltip; + + /** + * Render padding before the hint. + * + * Note: Padding should use the editor's background color, not the + * background color of the hint itself. That means padding can be used + * to visually align/separate an inlay hint. + */ + optional paddingLeft; + + /** + * Render padding after the hint. + * + * Note: Padding should use the editor's background color, not the + * background color of the hint itself. That means padding can be used + * to visually align/separate an inlay hint. + */ + optional paddingRight; + + /** + * A data entry field that is preserved on an inlay hint between + * a `textDocument/inlayHint` and a `inlayHint/resolve` request. + */ + optional data; + + MAKE_SWAP_METHOD(lsInlayHint, position, label, kind, textEdits, tooltip, paddingLeft, paddingRight, data) + +}; + +MAKE_REFLECT_STRUCT(lsInlayHint, position, label, kind, textEdits, tooltip, paddingLeft, paddingRight, data) + + +DEFINE_REQUEST_RESPONSE_TYPE(td_inlayHint, TextDocumentInlayHint::Params, std::vector, "textDocument/inlayHint"); + + +/** + * The document link resolve request is sent from the client to the server to resolve the target of a given document link. + */ +DEFINE_REQUEST_RESPONSE_TYPE(td_inlayHintResolve, lsInlayHint, lsInlayHint, "inlayHint/resolve"); + diff --git a/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h b/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h index bb5cd1dc5..d7994318c 100644 --- a/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h +++ b/LspCpp/include/LibLsp/lsp/textDocument/signature_help.h @@ -6,11 +6,6 @@ #include "LibLsp/lsp/lsMarkedString.h" #include "LibLsp/lsp/lsTextDocumentPositionParams.h" -extern void Reflect(Reader& visitor, - std::pair, optional>& value); - - - // Represents a parameter of a callable-signature. A parameter can // have a label and a doc-comment. struct lsParameterInformation { diff --git a/LspCpp/src/lsp/lsp.cpp b/LspCpp/src/lsp/lsp.cpp index d070f22be..eb539c74e 100644 --- a/LspCpp/src/lsp/lsp.cpp +++ b/LspCpp/src/lsp/lsp.cpp @@ -25,6 +25,9 @@ #include "LibLsp/lsp/AbsolutePath.h" #ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif #include #else #include diff --git a/asymptote.spec b/asymptote.spec index 26fd6842b..458379d88 100644 --- a/asymptote.spec +++ b/asymptote.spec @@ -3,7 +3,7 @@ %global __python %{__python3} Name: asymptote -Version: 2.95 +Version: 2.96 Release: 1%{?dist} Summary: Descriptive vector graphics language diff --git a/base/rational.asy b/base/rational.asy index 068376fec..3a1105093 100644 --- a/base/rational.asy +++ b/base/rational.asy @@ -165,6 +165,30 @@ bool operator ==(rational[][] r, rational[][] s) return all(sequence(new bool(int i) {return r[i] == s[i];},r.length)); } +rational[] operator +(rational[] r, rational[] s) +{ + assert(r.length == s.length); + return sequence(new rational(int i) {return r[i]+s[i];},r.length); +} + +rational[] operator -(rational[] r, rational[] s) +{ + assert(r.length == s.length); + return sequence(new rational(int i) {return r[i]-s[i];},r.length); +} + +rational[] operator *(rational[] r, rational[] s) +{ + assert(r.length == s.length); + return sequence(new rational(int i) {return r[i]*s[i];},r.length); +} + +rational[] operator /(rational[] r, rational[] s) +{ + assert(r.length == s.length); + return sequence(new rational(int i) {return r[i]/s[i];},r.length); +} + bool[] operator <(rational[] r, rational s) { return sequence(new bool(int i) {return r[i] < s;},r.length); diff --git a/base/rationalSimplex.asy b/base/rationalSimplex.asy index b6ce98c4a..97ebffe0d 100644 --- a/base/rationalSimplex.asy +++ b/base/rationalSimplex.asy @@ -272,8 +272,6 @@ struct simplex { rational[] cB=phase1 ? new rational[m] : c[n-m:n]; rational[][] D=phase1 ? new rational[m+1][n+1] : E; if(phase1) { - write("n=",n); - write(Bindices); // Drive artificial variables out of basis. for(int i=0; i < m; ++i) { if(Bindices[i] > n) { diff --git a/build-scripts/build-asymptote b/build-scripts/build-asymptote index fb2b0551e..aab19e143 100755 --- a/build-scripts/build-asymptote +++ b/build-scripts/build-asymptote @@ -69,7 +69,7 @@ cp -a $BUILD/asymptote-$VERSION/doc/asymptote.sty $SHARED/asydoc make distclean rm -rf autom4te.cache cd /usr/local/share/doc/asymptote -cp -a *.pdf ../../man/man1/asy.1 $SHARED/asydoc +cp -a *.pdf ../../man/man1/asy.1 ../../asymptote/asy-keywords.el $SHARED/asydoc cp -a *.pdf ../../man/man1/asy.1 $BUILD/asymptote-$VERSION/doc cp -a /usr/local/share/info/asymptote/asymptote.info $SHARED/asydoc/png cp -a /usr/local/share/info/asymptote/asymptote.info $BUILD/asymptote-$VERSION/doc/png diff --git a/build-scripts/build-asymptote.ps1 b/build-scripts/build-asymptote.ps1 index a5043c625..45ed8fb0b 100644 --- a/build-scripts/build-asymptote.ps1 +++ b/build-scripts/build-asymptote.ps1 @@ -63,9 +63,32 @@ if (-Not $hasDocFiles) { # ---------------------------------------------------- # copy documentation files to asymptote directory +$localAsyDocRoot="$asymptoteRoot/asydoc" -New-Item -ItemType Directory -Path "$asymptoteRoot/extfiles" -Force -Copy-Item -Force -Recurse "$extfilesRoot/*" -Destination "$asymptoteRoot/extfiles" +if (-Not (Test-Path -Type Container $localAsyDocRoot)) +{ + New-Item -ItemType Directory -Path $localAsyDocRoot -Force +} + +foreach ($requiredDocFile in $requiredDocumentationFiles) +{ + $sourceDocFile="$extfilesRoot/$requiredDocFile" + $destDocFile="$localAsyDocRoot/$requiredDocFile" + + $docFileHash=Get-FileHash -Algorithm SHA256 -Path $sourceDocFile + if (Test-Path -Type Leaf "$destDocFile") + { + $asyDocFilehash=Get-FileHash -Algorithm SHA256 -Path $destDocFile + if ($docFileHash.Hash -eq $asyDocFilehash.Hash) + { + Write-Host "File $requiredDocFile exists in asydoc directory; not copying" + continue + } + } + + Write-Host "Copying $sourceDocFile to $destDocFile" + Copy-Item -Force $sourceDocFile -Destination $destDocFile +} # ---------------------------------------------------- # tools cache @@ -75,7 +98,7 @@ New-Item -ItemType Directory -Path $toolscacheRoot -Force $useToolsCacheVcpkg=$false # tools cache variables -$vcpkgSha256="e590c2b30c08caf1dd8d612ec602a003f9784b7d" +$vcpkgSha256="5e5d0e1cd7785623065e77eff011afdeec1a3574" # vcpkg if (-Not $env:VCPKG_ROOT) diff --git a/cmake-scripts/asy-misc-files.cmake b/cmake-scripts/asy-misc-files.cmake new file mode 100644 index 000000000..7ef74cf04 --- /dev/null +++ b/cmake-scripts/asy-misc-files.cmake @@ -0,0 +1,35 @@ +# Non-documentation, Non-core files for Asymptote +# This file is intended for any files that are generated by asy. + +# Additionally, ensure this file is included after asy target & base files target has been defined in +# CMakeLists.txt. + +set(ASY_MISC_FILES_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/misc-output) +file(MAKE_DIRECTORY ${ASY_MISC_FILES_OUT_DIR}) + +# asy.list +add_custom_command( + OUTPUT ${ASY_MISC_FILES_OUT_DIR}/asy.list + COMMAND ${PY3_INTERPRETER} ${ASY_SCRIPTS_DIR}/generate_asy_list_file.py + --asy-executable $ + --asy-base-dir=${ASY_BUILD_BASE_DIR} + --output-file ${ASY_MISC_FILES_OUT_DIR}/asy.list + DEPENDS asy ${ASY_OUTPUT_BASE_FILES} ${ASY_SCRIPTS_DIR}/generate_asy_list_file.py +) + + +# asy-keywords.el +add_custom_command( + OUTPUT ${ASY_MISC_FILES_OUT_DIR}/asy-keywords.el + COMMAND ${PERL_INTERPRETER} ${ASY_SCRIPTS_DIR}/asy-list.pl + --asy-list-file ${ASY_MISC_FILES_OUT_DIR}/asy.list + --revision ${ASY_VERSION} + --output-file ${ASY_MISC_FILES_OUT_DIR}/asy-keywords.el + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${ASY_MISC_FILES_OUT_DIR}/asy.list ${CMAKE_CURRENT_SOURCE_DIR}/camp.l ${ASY_SCRIPTS_DIR}/asy-list.pl +) + +set(ASY_OUTPUT_DIST_MISC_FILES + ${ASY_MISC_FILES_OUT_DIR}/asy-keywords.el +) +add_custom_target(asy-dist-misc-files DEPENDS ${ASY_OUTPUT_DIST_MISC_FILES}) diff --git a/cmake-scripts/options.cmake b/cmake-scripts/options.cmake index 51838bfa2..d3f720977 100644 --- a/cmake-scripts/options.cmake +++ b/cmake-scripts/options.cmake @@ -248,6 +248,14 @@ cmake_dependent_option( false ) +# misc files +option( + ENABLE_MISCFILES_GEN + "Enable generation of non-essential, non-documentation asymptote files (e.g. asy.list, asy-keywords.el) " + true +) + +# warnings if external docs dir is not given if (NOT EXTERNAL_DOCUMENTATION_DIR) if (NOT ENABLE_DOCGEN) message(STATUS "Build is not generating documentation. @@ -258,6 +266,13 @@ documentation files in a directory and specify this directory in EXTERNAL_DOCUME message(STATUS "Build is not generating asymptote.pdf. If you are planning on generating installation files, please make sure you have access to asymptote.pdf in a directory and specify this directory in EXTERNAL_DOCUMENTATION_DIR cache variable. +") + endif() + + if (NOT ENABLE_MISCFILES_GEN) + message(STATUS "Build is not generating non-essential, non-documentation asymptote files. +If you are planning on generating installation files, please make sure you have access to asy-keywords.el +in a directory and specify this directory in EXTERNAL_DOCUMENTATION_DIR cache variable. ") endif() endif() diff --git a/cmake-scripts/win32-pre-nsis-installer.cmake b/cmake-scripts/win32-pre-nsis-installer.cmake index df0875a93..3e5b8ccd3 100644 --- a/cmake-scripts/win32-pre-nsis-installer.cmake +++ b/cmake-scripts/win32-pre-nsis-installer.cmake @@ -62,6 +62,20 @@ install( ${ASY_NSIS_INSTALL_ARGUMENT} ) +# /base/asy-{init,mode}.el -> / +install( + FILES + ${ASY_SOURCE_BASE_DIR}/asy-init.el + ${ASY_SOURCE_BASE_DIR}/asy-mode.el + ${ASY_NSIS_INSTALL_ARGUMENT} +) + +# misc files -> / +install( + FILES ${ASY_OUTPUT_MISC_FILES} + ${ASY_NSIS_INSTALL_ARGUMENT} +) + # extra doc files install( FILES @@ -114,6 +128,11 @@ if (ASY_TEX_BUILD_ROOT) add_dependencies(asy-pre-nsis-targets docgen) endif() +if (ENABLE_MISCFILES_GEN) + add_dependencies(asy-pre-nsis-targets asy-dist-misc-files) +endif() + + macro(install_from_external_documentation_dir docfile_name) set(DOCFILE_LOCATION ${EXTERNAL_DOCUMENTATION_DIR}/${docfile_name}) message(STATUS "Using external documentation file at ${DOCFILE_LOCATION}") @@ -163,6 +182,19 @@ else() action_if_component_not_buildable("asymptote.pdf cannot be found and is not buildable") endif() +# asy-keywords.el (and potentially other misc files) +if (ENABLE_MISCFILES_GEN) + install( + FILES ${ASY_OUTPUT_DIST_MISC_FILES} + ${ASY_NSIS_INSTALL_ARGUMENT} + ) +elseif(EXTERNAL_DOCUMENTATION_DIR) + install_from_external_documentation_dir(asy-keywords.el) +else() + action_if_component_not_buildable("Non-essential, non-documentation asymptote files cannot be found") +endif() + + # README files install( FILES diff --git a/doc/asymptote.texi b/doc/asymptote.texi index d1bce2f7e..e2b1aae73 100644 --- a/doc/asymptote.texi +++ b/doc/asymptote.texi @@ -3307,8 +3307,8 @@ following foreground--background blending operations: "HardLight","ColorDodge","ColorBurn","Darken","Lighten","Difference", "Exclusion","Hue","Saturation","Color","Luminosity", @end verbatim -as described in -@url{https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf}. +as described in Tables 136 and 137 of +@url{https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf}. Since @code{PostScript} does not support transparency, this feature is only effective with the @code{-f pdf} output format option; other formats can be produced from the resulting @acronym{PDF} file with the @@ -5597,15 +5597,16 @@ returns the indices of all @code{true} values in the boolean array @code{a}; @cindex @code{search} @item int search(T[] a, T key) For built-in ordered types @code{T}, searches a sorted array -@code{a} of @code{n} elements for k, returning the index @code{i} +@code{a} of @code{n} elements for @code{key}, returning the index @code{i} if @code{a[i] <= key < a[i+1]}, @code{-1} if @code{key} is less than all elements of @code{a}, or @code{n-1} if @code{key} is greater than or equal to the last element of @code{a}; @cindex @code{search} @item int search(T[] a, T key, bool less(T i, T j)) -searches an array @code{a} sorted in ascending order such that element -@code{i} precedes element @code{j} if @code{less(i,j)} is true; +searches an array @code{a} for @code{key} sorted in ascending order +such that element @code{i} precedes element @code{j} if +@code{less(i,j)} is true; @cindex @code{copy} @item T[] copy(T[] a) diff --git a/generate_asy_list_file.py b/generate_asy_list_file.py new file mode 100644 index 000000000..e28191590 --- /dev/null +++ b/generate_asy_list_file.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +__doc__ = """ +Script to generate asy.list file. Equivalent to Makefile's asy-list.el file's logic +to generate asy.list. +""" + +import argparse +import pathlib +import subprocess as sp +from typing import Optional + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--asy-executable", required=True, help="Asymptote executable") + parser.add_argument("--asy-base-dir", required=True, help="Asymptote base dir") + parser.add_argument("--output-file", required=True, help="Output file") + return parser.parse_args() + + +def run_asy_list(asy_exec: str, base_dir: pathlib.Path, asy_file: Optional[str] = None): + base_args = [asy_exec, "-dir", str(base_dir), "-config", '""', "-render", "0", "-l"] + if asy_file is not None: + base_args.append(asy_file) + out_data = sp.run( + base_args, + stdout=sp.PIPE, + stderr=sp.PIPE, + universal_newlines=True, + check=True, + ) + return out_data.stdout + + +def base_file_to_be_included_in_list_file(base_file_name: str): + if base_file_name.startswith("plain") or base_file_name.startswith("three_"): + return False + if "map" in base_file_name: + return False + return True + + +def main(): + args = parse_args() + base_dir = pathlib.Path(args.asy_base_dir) + base_asy_list = run_asy_list(args.asy_executable, base_dir) + + base_file: pathlib.Path + base_files_to_generate_list = [ + base_file + for base_file in base_dir.glob("*.asy") + if base_file_to_be_included_in_list_file(base_file.name) + ] + base_file_asy_lists = [ + run_asy_list(args.asy_executable, base_dir, str(base_file)) + for base_file in base_files_to_generate_list + ] + with open(args.output_file, "w", encoding="utf-8") as fil: + fil.write(base_asy_list) + for asy_list_info in base_file_asy_lists: + fil.write(asy_list_info) + + +if __name__ == "__main__": + main() diff --git a/mathop.h b/mathop.h index d51c5741e..0b4438aac 100644 --- a/mathop.h +++ b/mathop.h @@ -242,6 +242,14 @@ struct mod { } }; +template <> +struct mod { + Int operator() (Int x, Int y, size_t i=0) { + if(y == 0) dividebyzero(i); + return imod(x,y); + } +}; + template struct quotient { Int operator() (Int x, Int y, size_t i=0) { diff --git a/mod.h b/mod.h index b441d08b7..745259091 100644 --- a/mod.h +++ b/mod.h @@ -20,22 +20,25 @@ inline double Mod(double x, double y) {return fmod(x,y);} template inline T portableMod(T x,T y) { -// Implementation-independent definition of mod; ensure that result has +// Implementation-independent definition of mod; ensure result has // same sign as divisor T val=Mod(x,y); - if((y > 0 && val < 0) || (y < 0 && val > 0)) val += y; - return val; + return ((y > 0 && val >= 0) || (y < 0 && val <= 0)) ? val : val+y; } -inline Int imod(Int x, Int y) -{ - return portableMod(x,y); +inline Int imod(Int x, size_t y) { + if((y & (y-1)) == 0) + return x & (y-1); // Use mask if y is a power of two + x %= (Int) y; + return (x >= 0) ? x : x+(Int) y; } -inline Int imod(Int i, size_t n) { - i %= (Int) n; - if(i < 0) i += (Int) n; - return i; +inline Int imod(Int x, Int y) +{ + if(y > 0) + return imod(x,(size_t) y); + else + return portableMod(x,y); } #endif diff --git a/tests/arith/integer.asy b/tests/arith/integer.asy index 5433f345b..004fe0935 100644 --- a/tests/arith/integer.asy +++ b/tests/arith/integer.asy @@ -22,6 +22,16 @@ assert(1#-2 == -1); assert(-1#-2 == 0); assert(-3#2 == -2); EndTest(); +StartTest("integer mod"); +assert(12%5 == 2); +assert(-12%5 == 3); +assert(12%-5 == -3); +assert(-12%-5 == -2); +assert(13%4 == 1); +assert(-13%4 == 3); +assert(13%-4 == -3); +assert(-13%-4 == -1); +EndTest(); StartTest("integer self ops"); { int x=3; assert(++x == 4); assert(x == 4); } { int x=3; assert(--x == 2); assert(x == 2); } diff --git a/tests/arith/pair.asy b/tests/arith/pair.asy index c815f28b2..a846859e5 100644 --- a/tests/arith/pair.asy +++ b/tests/arith/pair.asy @@ -1,20 +1,20 @@ import TestLib; StartTest("complex addition"); -assert((1,0)+(0,1)==(1,1)); +assert((1,0)+(0,1) == (1,1)); EndTest(); StartTest("complex subtraction"); -assert((1,0)-(0,1)==(1,-1)); +assert((1,0)-(0,1) == (1,-1)); EndTest(); StartTest("complex multiplication"); -assert((1,2)*(2,1)==(0,5)); +assert((1,2)*(2,1) == (0,5)); EndTest(); StartTest("complex division"); -assert((0,5)/(2,1)==(1,2)); +assert((0,5)/(2,1) == (1,2)); EndTest(); StartTest("length(pair)"); assert(length((0.0,1.0)) == 1.0); EndTest(); StartTest("conj()"); -assert(conj((0.0,1.0))==(0.0, -1.0)); +assert(conj((0.0,1.0)) == (0.0,-1.0)); EndTest(); diff --git a/tests/arith/real.asy b/tests/arith/real.asy index 1628258cf..8f874fb3c 100644 --- a/tests/arith/real.asy +++ b/tests/arith/real.asy @@ -16,3 +16,9 @@ EndTest(); StartTest("real division"); assert((4.0/2.0) == (2.0)); EndTest(); +StartTest("real mod"); +assert((12.0%5.0) == (2.0)); +assert((-12.0%5.0) == (3.0)); +assert((12.0%-5.0) == (-3.0)); +assert((-12.0%-5.0) == (-2.0)); +EndTest(); diff --git a/vcpkg.json b/vcpkg.json index d295b74f1..08b299aeb 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", - "builtin-baseline": "76d153790caf0592fce8fc4484aa6db18c7d00d4", + "builtin-baseline": "5e5d0e1cd7785623065e77eff011afdeec1a3574", "name": "asymptote", "version": "0.0-snapshot", "dependencies": [