diff --git a/README.md b/README.md index 4b1ec45b6..72b3eb067 100644 --- a/README.md +++ b/README.md @@ -105,9 +105,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |:-------------------|:-- -| `all` (default) | Build shared-library `libmeevax.0.4.209.so` and executable `meevax`. +| `all` (default) | Build shared-library `libmeevax.0.4.232.so` and executable `meevax`. | `test` | Test executable `meevax`. -| `package` | Generate debian package `meevax_0.4.209_amd64.deb`. +| `package` | Generate debian package `meevax_0.4.232_amd64.deb`. | `install` | Copy files into `/usr/local` __(1)__. | `install.deb` | `all` + `package` + `sudo apt install .deb` | `safe-install.deb` | `all` + `test` + `package` + `sudo apt install .deb` @@ -122,7 +122,7 @@ __(1)__ Meevax installed by `make install` cannot be uninstalled by the system's ## Usage ``` -Meevax Lisp System, version 0.4.209 +Meevax Lisp System, version 0.4.232 Usage: meevax [OPTION...] [FILE...] diff --git a/VERSION b/VERSION index 5e440409c..2a4561f41 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.209 +0.4.232 diff --git a/basis/r7rs.ss b/basis/r7rs.ss index 7ab11c823..0be4d47f6 100644 --- a/basis/r7rs.ss +++ b/basis/r7rs.ss @@ -433,27 +433,28 @@ (define-library (scheme inexact) (import (only (meevax inexact) finite? infinite? nan?) (only (scheme r5rs) exp log sin cos tan asin acos atan sqrt)) - (export finite? - infinite? - nan? - exp - log - sin - cos - tan - asin - acos - atan - sqrt)) + (export finite? infinite? nan? exp log sin cos tan asin acos atan sqrt)) (define-library (scheme complex) - (export make-rectangular - make-polar - real-part - imag-part - angle - ) - ) + (import (meevax complex) + (scheme base) + (scheme inexact)) + + (export make-rectangular make-polar real-part imag-part magnitude angle) + + (begin (define (make-polar magnitude angle) + (make-rectangular (* magnitude (cos angle)) + (* magnitude (sin angle)))) + + (define (magnitude z) + (let ((re (real-part z)) + (im (imag-part z))) + (sqrt (+ (* re re) + (* im im))))) + + (define (angle z) + (atan (imag-part z) + (real-part z))))) (define-library (scheme cxr) (import (meevax pair)) diff --git a/configure/version.cpp b/configure/version.cpp index 9cb1d7bb5..bb65dc8da 100644 --- a/configure/version.cpp +++ b/configure/version.cpp @@ -61,7 +61,7 @@ inline namespace kernel let static const features = list( make("r4rs"), make("exact-closed"), - // make("exact-complex"), + make("exact-complex"), make("ieee-float"), // make("full-unicode"), make("ratios"), diff --git a/include/meevax/iostream/escape_sequence.hpp b/include/meevax/iostream/escape_sequence.hpp index 48ce97d30..36c61d5cb 100644 --- a/include/meevax/iostream/escape_sequence.hpp +++ b/include/meevax/iostream/escape_sequence.hpp @@ -33,9 +33,9 @@ inline namespace iostream std::tuple< typename std::conditional< - not std::is_reference::value or std::is_scalar::type>::value, - typename std::decay::type, - std::reference_wrapper::type> + not std::is_reference_v or std::is_scalar_v>, + std::decay_t, + std::reference_wrapper> >::type... > references; diff --git a/include/meevax/iostream/lexical_cast.hpp b/include/meevax/iostream/lexical_cast.hpp index 27fa81dad..4d21faacf 100644 --- a/include/meevax/iostream/lexical_cast.hpp +++ b/include/meevax/iostream/lexical_cast.hpp @@ -30,7 +30,7 @@ inline namespace iostream { if (std::stringstream ss; (ss << ... << xs)) { - if constexpr (std::is_same::type, std::string>::value) + if constexpr (std::is_same_v, std::string>) { return ss.str(); } diff --git a/include/meevax/kernel/character.hpp b/include/meevax/kernel/character.hpp index 15398c519..3965a4511 100644 --- a/include/meevax/kernel/character.hpp +++ b/include/meevax/kernel/character.hpp @@ -59,7 +59,7 @@ inline namespace kernel return codepoint; } - explicit operator external_representation() const; // write-char (for display) + explicit operator std::string() const; // write-char (for display) }; auto operator <<(std::ostream &, character const&) -> std::ostream &; // write diff --git a/include/meevax/kernel/complex.hpp b/include/meevax/kernel/complex.hpp index 2024e58d2..6c6698342 100644 --- a/include/meevax/kernel/complex.hpp +++ b/include/meevax/kernel/complex.hpp @@ -17,6 +17,9 @@ #ifndef INCLUDED_MEEVAX_KERNEL_COMPLEX_HPP #define INCLUDED_MEEVAX_KERNEL_COMPLEX_HPP +#include +#include + #include #include @@ -28,13 +31,15 @@ inline namespace kernel { using pair::pair; - auto real() const noexcept -> const_reference; + explicit complex(std::string const&, int = 10); - auto real() noexcept -> reference; + auto canonicalize() const -> value_type; auto imag() const noexcept -> const_reference; - auto imag() noexcept -> reference; + auto real() const noexcept -> const_reference; + + explicit operator std::complex(); }; auto operator <<(std::ostream &, complex const&) -> std::ostream &; diff --git a/include/meevax/kernel/constant.hpp b/include/meevax/kernel/constant.hpp deleted file mode 100644 index 246d29741..000000000 --- a/include/meevax/kernel/constant.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2018-2022 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_KERNEL_CONSTANT_HPP -#define INCLUDED_MEEVAX_KERNEL_CONSTANT_HPP - -#include - -namespace meevax -{ -inline namespace kernel -{ - extern std::unordered_map const constants; -} // namespace kernel -} // namespace meevax - -#endif // INCLUDED_MEEVAX_KERNEL_CONSTANT_HPP diff --git a/include/meevax/kernel/environment.hpp b/include/meevax/kernel/environment.hpp index b3bcabd8c..3bd1e1c97 100644 --- a/include/meevax/kernel/environment.hpp +++ b/include/meevax/kernel/environment.hpp @@ -46,7 +46,7 @@ inline namespace kernel explicit environment(environment const&) = default; - template ...)> + template ...)> explicit environment(Ts&&... xs) { (import(xs), ...); @@ -88,9 +88,9 @@ inline namespace kernel auto import_(const_reference) -> void; - auto import_(external_representation const&) -> void; + auto import_(std::string const&) -> void; - auto load(external_representation const&) -> value_type; + auto load(std::string const&) -> value_type; auto resolve(const_reference) -> value_type; diff --git a/include/meevax/kernel/error.hpp b/include/meevax/kernel/error.hpp index 5dc227806..7b5e35b4b 100644 --- a/include/meevax/kernel/error.hpp +++ b/include/meevax/kernel/error.hpp @@ -52,7 +52,7 @@ inline namespace kernel virtual auto raise() const -> void; - virtual auto what() const -> external_representation; + virtual auto what() const -> std::string; }; auto operator <<(std::ostream &, error const&) -> std::ostream &; @@ -97,7 +97,7 @@ inline namespace kernel catch (std::exception const& error) { - std::cerr << "; error" << error.what() << std::endl; + std::cerr << "; error " << std::quoted(error.what()) << std::endl; return underlying_cast(exit_status::failure); } diff --git a/include/meevax/kernel/exact_integer.hpp b/include/meevax/kernel/exact_integer.hpp index daba883ea..3d7a70ea9 100644 --- a/include/meevax/kernel/exact_integer.hpp +++ b/include/meevax/kernel/exact_integer.hpp @@ -47,13 +47,13 @@ inline namespace kernel explicit exact_integer(double); - explicit exact_integer(external_representation const&, int = 0); + explicit exact_integer(std::string const&, int = 0); auto operator=(exact_integer const&) -> exact_integer &; auto operator=(exact_integer &&) noexcept -> exact_integer &; - auto operator=(external_representation const&) -> exact_integer &; + auto operator=(std::string const&) -> exact_integer &; operator int() const; diff --git a/include/meevax/kernel/ghost.hpp b/include/meevax/kernel/ghost.hpp index 84295706f..17e59eb0b 100644 --- a/include/meevax/kernel/ghost.hpp +++ b/include/meevax/kernel/ghost.hpp @@ -25,7 +25,7 @@ inline namespace kernel { struct ghost { - external_representation const name; + std::string const name; }; auto operator <<(std::ostream &, ghost const&) -> std::ostream &; diff --git a/include/meevax/kernel/heterogeneous.hpp b/include/meevax/kernel/heterogeneous.hpp index f370e7f41..8f297bb82 100644 --- a/include/meevax/kernel/heterogeneous.hpp +++ b/include/meevax/kernel/heterogeneous.hpp @@ -151,7 +151,7 @@ inline namespace kernel template inline auto is() const { - return type() == typeid(typename std::decay::type); + return type() == typeid(std::decay_t); } template )> diff --git a/include/meevax/kernel/library.hpp b/include/meevax/kernel/library.hpp index adc5ab031..1f7127e64 100644 --- a/include/meevax/kernel/library.hpp +++ b/include/meevax/kernel/library.hpp @@ -49,17 +49,17 @@ inline namespace kernel auto export_(const_reference) -> void; - auto export_(external_representation const&) -> void; + auto export_(std::string const&) -> void; auto resolve() -> const_reference; }; auto operator <<(std::ostream &, library const&) -> std::ostream &; - extern std::unordered_map libraries; + extern std::unordered_map libraries; template - auto define_library(external_representation const& name, Ts&&... xs) + auto define_library(std::string const& name, Ts&&... xs) { return libraries.emplace(name, std::forward(xs)...); } diff --git a/include/meevax/kernel/machine.hpp b/include/meevax/kernel/machine.hpp index 5df266afe..4c11ebea8 100644 --- a/include/meevax/kernel/machine.hpp +++ b/include/meevax/kernel/machine.hpp @@ -882,7 +882,7 @@ inline namespace kernel { if (current_context.is_tail) { - assert(lexical_cast(current_continuation) == "(return)"); + assert(lexical_cast(current_continuation) == "(return)"); return compile(context(), current_environment, diff --git a/include/meevax/kernel/number.hpp b/include/meevax/kernel/number.hpp index 0363d66ff..bac05f62b 100644 --- a/include/meevax/kernel/number.hpp +++ b/include/meevax/kernel/number.hpp @@ -79,6 +79,18 @@ inline namespace kernel auto operator > (exact_integer const&, double) -> bool; auto operator >=(exact_integer const&, double) -> bool; + 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&) -> 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; auto operator - (ratio const&, exact_integer const&) -> ratio; @@ -127,6 +139,18 @@ inline namespace kernel auto operator > (ratio const&, double) -> bool; auto operator >=(ratio const&, double) -> bool; + 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&) -> 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; auto operator * (float, exact_integer const&) -> float; @@ -151,6 +175,18 @@ inline namespace kernel auto operator > (float, ratio const&) -> bool; auto operator >=(float, ratio const&) -> bool; + 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&) -> 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; auto operator * (double, exact_integer const&) -> double; @@ -175,11 +211,144 @@ inline namespace kernel auto operator > (double, ratio const&) -> bool; auto operator >=(double, ratio const&) -> bool; - auto operator +(const_reference, const_reference) -> value_type; - auto operator -(const_reference, const_reference) -> value_type; - auto operator *(const_reference, const_reference) -> value_type; - auto operator /(const_reference, const_reference) -> value_type; - auto operator %(const_reference, const_reference) -> value_type; + 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&) -> 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 + (const_reference, const_reference) -> value_type; + auto operator - (const_reference, const_reference) -> value_type; + auto operator * (const_reference, const_reference) -> value_type; + auto operator / (const_reference, const_reference) -> value_type; + auto operator % (const_reference, const_reference) -> value_type; + + using plus = std::plus; + + using minus = std::minus; + + using multiplies = std::multiplies; + + using divides = std::divides; + + struct modulus + { + template + auto operator ()(T&& x, U&& y) const + { + if constexpr (std::is_floating_point_v> and + std::is_floating_point_v>) + { + return std::fmod(x, y); + } + else + { + return x % y; + } + } + }; + + struct equal_to + { + template + auto operator ()(T&& x, U&& y) const + { + if constexpr (std::is_floating_point_v> and + std::is_floating_point_v>) + { + if (std::isnan(x) and std::isnan(y)) + { + return true; + } + else if (std::isinf(x) or std::isinf(y)) + { + return x == y; + } + else + { + return std::abs(x - y) <= std::numeric_limits() - std::declval())>::epsilon(); + } + } + else + { + return x == y; + } + } + }; + + using less = std::less; + + using less_equal = std::less_equal; + + using greater = std::greater; + + using greater_equal = std::greater_equal; template struct application @@ -187,38 +356,43 @@ inline namespace kernel static inline constexpr F f {}; template - auto finish(T&& z) -> decltype(auto) + auto canonicalize(T&& x) -> decltype(auto) { - if constexpr (std::is_same_v, value_type>) + if constexpr (std::is_same_v, value_type>) { - return std::forward(z); + return std::forward(x); } - else if constexpr (std::is_same_v, ratio>) + else if constexpr (std::is_same_v, complex>) + { + return x.canonicalize(); + } + else if constexpr (std::is_same_v, ratio>) { - if (z.denominator() == 1) + if (x.denominator() == 1) { - return make(z.numerator()); + return make(x.numerator()); } else { - return make(std::forward(z)); + return make(std::forward(x)); } } else { - return make(std::forward(z)); + return make(std::forward(x)); } } auto operator ()(const_reference x) -> value_type { - return finish(f(x.as>>())); + return canonicalize(f(x.as>>())); } - auto operator ()(const_reference x, const_reference y) -> value_type + auto operator ()(const_reference x, + const_reference y) -> value_type { - return finish(f(x.as>>(), - y.as>>())); + return canonicalize(f(x.as>>(), + y.as>>())); } }; @@ -234,6 +408,7 @@ inline namespace kernel { type_index<1>(typeid(ratio )), application() }, { type_index<1>(typeid(float )), application() }, { type_index<1>(typeid(double )), application() }, + { type_index<1>(typeid(complex )), application() }, }; return apply.at(type_index<1>(x.type()))(x); @@ -249,10 +424,11 @@ inline namespace kernel std::function > apply { - APPLY(exact_integer, exact_integer), APPLY(exact_integer, ratio), APPLY(exact_integer, float), APPLY(exact_integer, double), - APPLY(ratio, exact_integer), APPLY(ratio, ratio), APPLY(ratio, float), APPLY(ratio, double), - APPLY(float, exact_integer), APPLY(float, ratio), APPLY(float, float), APPLY(float, double), - APPLY(double, exact_integer), APPLY(double, ratio), APPLY(double, float), APPLY(double, double), + APPLY(exact_integer, exact_integer), APPLY(exact_integer, ratio), APPLY(exact_integer, float), APPLY(exact_integer, double), APPLY(exact_integer, complex), + APPLY(ratio, exact_integer), APPLY(ratio, ratio), APPLY(ratio, float), APPLY(ratio, double), APPLY(ratio, complex), + APPLY(float, exact_integer), APPLY(float, ratio), APPLY(float, float), APPLY(float, double), APPLY(float, complex), + APPLY(double, exact_integer), APPLY(double, ratio), APPLY(double, float), APPLY(double, double), APPLY(double, complex), + APPLY(complex, exact_integer), APPLY(complex, ratio), APPLY(complex, float), APPLY(complex, double), APPLY(complex, complex), }; #undef APPLY @@ -260,77 +436,57 @@ inline namespace kernel return apply.at(type_index<2>(x.type(), y.type()))(x, y); } - struct exact + template )> + auto inexact_cast(U&& x) -> decltype(auto) { - template - auto operator ()(T&& x) const -> decltype(auto) + if constexpr (std::is_same_v, complex>) { - if constexpr (std::is_floating_point_v>) - { - return ratio(std::forward(x)); - } - else - { - return std::forward(x); - } + return std::complex(std::forward(x)); } - } inline constexpr exact_cast; + else if constexpr (std::is_floating_point_v>) + { + return std::forward(x); + } + else + { + return static_cast(std::forward(x)); + } + } - struct inexact + struct exact { template - auto operator ()(T const& x) const -> decltype(auto) + auto operator ()(T&& x) const -> decltype(auto) { - if constexpr (std::is_floating_point_v>) - { - return std::forward(x); - } - else + if constexpr (std::is_same_v, complex>) { - return static_cast(std::forward(x)); + return complex(apply(x.real()), + apply(x.imag())); } - } - } inline constexpr inexact_cast; - - struct equal_to - { - template - auto operator ()(T&& x, U&& y) const - { - if constexpr (std::is_floating_point_v> and std::is_floating_point_v>) + else if constexpr (std::is_floating_point_v>) { - if (std::isnan(x) and std::isnan(y)) - { - return true; - } - else if (std::isinf(x) or std::isinf(y)) - { - return x == y; - } - else - { - return std::abs(x - y) <= std::numeric_limits() - std::declval())>::epsilon(); - } + return ratio(std::forward(x)); } else { - return x == y; + return std::forward(x); } } }; - struct modulus + struct inexact { - template - auto operator ()(T&& x, U&& y) const + template + auto operator ()(T&& x) const -> decltype(auto) { - if constexpr (std::is_floating_point_v> and std::is_floating_point_v>) + if constexpr (std::is_same_v, complex>) { - return std::remainder(x, y); + return complex(apply(x.real()), + apply(x.imag())); } else { - return x % y; + return inexact_cast(std::forward(x)); } } }; @@ -347,9 +503,16 @@ inline namespace kernel struct is_real { template - constexpr auto operator ()(T&&) const + constexpr auto operator ()(T&& x) const { - return not std::is_same_v, complex>; + if constexpr (std::is_same_v, complex>) + { + return apply(x.imag(), e0).template as(); + } + else + { + return true; + } } }; @@ -364,7 +527,8 @@ inline namespace kernel } else { - return std::is_same_v, exact_integer> or std::is_same_v, ratio>; + return std::is_same_v, exact_integer> or + std::is_same_v, ratio>; } } }; @@ -372,9 +536,13 @@ inline namespace kernel struct is_integer { template - auto operator ()(T&& x) const + constexpr auto operator ()(T&& x) const { - if constexpr (std::is_floating_point_v>) + if constexpr (std::is_same_v, complex>) + { + return apply(x.imag(), e0).template as() and apply(x.real()).template as(); + } + else if constexpr (std::is_floating_point_v>) { return x == std::trunc(x); } @@ -389,35 +557,33 @@ inline namespace kernel } }; - struct is_finite + struct is_infinite { template constexpr auto operator ()(T&& x) const { - if constexpr (std::is_floating_point_v>) + if constexpr (std::is_same_v, complex>) { - return not std::isinf(x); + return apply(x.real()).template as() or + apply(x.imag()).template as(); + } + else if constexpr (std::is_floating_point_v>) + { + return std::isinf(x); } else { - return true; + return false; } } }; - struct is_infinite + struct is_finite { template constexpr auto operator ()(T&& x) const { - if constexpr (std::is_floating_point_v>) - { - return std::isinf(x); - } - else - { - return false; - } + return not std::invoke(is_infinite(), std::forward(x)); } }; @@ -426,7 +592,12 @@ inline namespace kernel template constexpr auto operator ()(T&& x) const { - if constexpr (std::is_floating_point_v>) + if constexpr (std::is_same_v, complex>) + { + return apply(x.real()).template as() or + apply(x.imag()).template as(); + } + else if constexpr (std::is_floating_point_v>) { return std::isnan(x); } @@ -440,20 +611,29 @@ inline namespace kernel struct sqrt { template - auto operator ()(T const& x) const - { - return std::sqrt(inexact_cast(x)); - } - - auto operator ()(exact_integer const& x) const + constexpr auto operator ()(T&& x) const -> decltype(auto) { - if (auto&& [s, r] = exact_integer_sqrt(x); r == 0) + if constexpr (std::is_same_v, complex>) { - return make(s); + auto const z = std::sqrt(inexact_cast(std::forward(x))); + return complex(make(z.real()), make(z.imag())); } else { - return make(operator ()(x)); + auto sqrt = [](auto&& x) + { + if constexpr (std::is_same_v, exact_integer>) + { + auto const [s, r] = exact_integer_sqrt(x); + return r == 0 ? make(s) : make(std::sqrt(inexact_cast(x))); + } + else + { + return make(std::sqrt(inexact_cast(x))); + } + }; + + return x < exact_integer(0) ? make(e0, sqrt(exact_integer(0) - x)) : sqrt(x); } } }; @@ -461,16 +641,46 @@ inline namespace kernel struct expt { template - auto operator ()(T const& x, U const& y) const -> decltype(auto) + auto operator ()(T&& x, U&& y) const -> decltype(auto) { - return std::pow(inexact_cast(x), inexact_cast(y)); + if constexpr (std::is_same_v, complex> or + std::is_same_v, complex>) + { + auto const z = std::pow(inexact_cast(std::forward(x)), + inexact_cast(std::forward(y))); + return complex(make(z.real()), make(z.imag())); + } + else if constexpr (std::is_same_v, exact_integer> and + std::is_same_v, exact_integer>) + { + exact_integer result {}; + mpz_pow_ui(result.value, x.value, static_cast(y)); + return result; + } + else + { + return std::pow(inexact_cast(std::forward(x)), + inexact_cast(std::forward(y))); + } } + }; - auto operator ()(exact_integer const& base, exact_integer const& exponent) const + struct atan2 + { + template + auto operator ()(T&& x, U&& y) const -> decltype(auto) { - exact_integer result {}; - mpz_pow_ui(result.value, base.value, static_cast(exponent)); - return result; + if constexpr (std::is_same_v, complex> or + std::is_same_v, complex>) + { + throw std::invalid_argument("unsupported operation"); + return e0; // dummy return value. + } + else + { + return std::atan2(inexact_cast(std::forward(x)), + inexact_cast(std::forward(y))); + } } }; @@ -478,19 +688,24 @@ inline namespace kernel struct ROUND \ { \ template \ - auto operator ()(T const& x) const \ + constexpr auto operator ()(T&& x) const \ { \ - return std::ROUND(inexact_cast(x)); \ - } \ - \ - auto operator ()(exact_integer const& x) const -> auto const& \ - { \ - return x; \ - } \ - \ - auto operator ()(ratio const& x) const \ - { \ - return exact_integer(operator ()(x)); \ + if constexpr (std::is_floating_point_v>) \ + { \ + return std::ROUND(inexact_cast(x)); \ + } \ + else if constexpr (std::is_same_v, ratio>) \ + { \ + return exact_integer(std::ROUND(inexact_cast(x))); \ + } \ + else if constexpr (std::is_same_v, exact_integer>) \ + { \ + return std::forward(x); \ + } \ + else \ + { \ + return complex(apply(x.real()), apply(x.imag())); \ + } \ } \ } @@ -504,17 +719,24 @@ inline namespace kernel #define DEFINE(CMATH) \ struct CMATH \ { \ - template \ - auto operator ()(Ts&&... xs) const \ + template \ + auto operator ()(T&& x) const \ { \ - return std::CMATH(inexact_cast(std::forward(xs))...); \ + if constexpr (std::is_same_v, complex>) \ + { \ + auto const z = std::CMATH(inexact_cast(std::forward(x))); \ + return complex(make(z.real()), make(z.imag())); \ + } \ + else \ + { \ + return std::CMATH(inexact_cast(std::forward(x))); \ + } \ } \ } 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(atan2); DEFINE(exp); DEFINE(log); diff --git a/include/meevax/kernel/object.hpp b/include/meevax/kernel/object.hpp index 3d4ca3d72..afe3cab7f 100644 --- a/include/meevax/kernel/object.hpp +++ b/include/meevax/kernel/object.hpp @@ -58,7 +58,7 @@ inline namespace kernel template auto make(T&& x) { - return value_type::allocate::type>(std::forward(x)); + return value_type::allocate>(std::forward(x)); } } // namespace kernel } // namespace meevax diff --git a/include/meevax/kernel/overview.hpp b/include/meevax/kernel/overview.hpp index c96b96f67..ea272d156 100644 --- a/include/meevax/kernel/overview.hpp +++ b/include/meevax/kernel/overview.hpp @@ -49,8 +49,6 @@ inline namespace kernel using null = std::nullptr_t; - using external_representation = std::string; - [[noreturn]] auto raise(std::string const&) -> void; // error.hpp } // namespace kernel diff --git a/include/meevax/kernel/ratio.hpp b/include/meevax/kernel/ratio.hpp index 1b6a04d5f..e732a16e2 100644 --- a/include/meevax/kernel/ratio.hpp +++ b/include/meevax/kernel/ratio.hpp @@ -42,7 +42,7 @@ inline namespace kernel explicit ratio(double); - explicit ratio(external_representation const&, int = 10); + explicit ratio(std::string const&, int = 10); auto denominator() const -> exact_integer; diff --git a/include/meevax/kernel/reader.hpp b/include/meevax/kernel/reader.hpp index d9a564e71..8b100fa66 100644 --- a/include/meevax/kernel/reader.hpp +++ b/include/meevax/kernel/reader.hpp @@ -18,7 +18,6 @@ #define INCLUDED_MEEVAX_KERNEL_READER_HPP #include -#include #include #include #include @@ -33,9 +32,9 @@ inline namespace kernel { auto get_codepoint(std::istream &) -> character::int_type; - auto get_delimited_elements(std::istream & is, character::int_type) -> string; + auto get_delimited_elements(std::istream &, character::int_type) -> string; - auto get_token(std::istream &) -> external_representation; + auto get_token(std::istream &) -> std::string; auto ignore_nested_block_comment(std::istream &) -> std::istream &; @@ -43,6 +42,16 @@ inline namespace kernel auto read_string_literal(std::istream &) -> value_type; + auto string_to_integer(std::string const&, int = 10) -> value_type; + + auto string_to_rational(std::string const&, int = 10) -> value_type; + + auto string_to_real(std::string const&, int = 10) -> value_type; + + auto string_to_complex(std::string const&, int = 10) -> value_type; + + auto string_to_number(std::string const&, int = 10) -> value_type; + template class reader { @@ -56,7 +65,7 @@ inline namespace kernel using char_type = typename std::istream::char_type; public: - static inline std::unordered_map symbols {}; + static inline std::unordered_map symbols {}; inline auto char_ready() const { @@ -98,7 +107,7 @@ inline namespace kernel return string_to_symbol(get_delimited_elements(is.putback(c), c)); case 'b': // (string->number (read) 2) - return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 2); + return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 2); case 'c': // Common Lisp { @@ -108,7 +117,7 @@ inline namespace kernel } case 'd': - return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 10); + return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 10); case 'e': return apply(read(is)); // NOTE: Same as #,(exact (read)) @@ -121,14 +130,14 @@ inline namespace kernel return apply(read(is)); // NOTE: Same as #,(inexact (read)) case 'o': - return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 8); + return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 8); case 't': get_token(is); return t; case 'x': - return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 16); + return string_to_number(is.peek() == '#' ? lexical_cast(read(is)) : get_token(is), 16); case '(': is.putback(c); @@ -228,46 +237,13 @@ inline namespace kernel return read(standard_input); } - inline auto read(external_representation const& s) -> value_type // NOTE: Specifying `decltype(auto)` causes a `undefined reference to ...` error in GCC-7. + inline auto read(std::string const& s) -> value_type // NOTE: Specifying `decltype(auto)` causes a `undefined reference to ...` error in GCC-7. { auto port = std::stringstream(s); return read(port); } - static auto string_to_number(external_representation const& token, int radix = 10) - { - try - { - return make(token, radix); - } - catch (...) - { - try - { - return make(ratio(token, radix)); - } - catch (...) - { - try - { - return make(lexical_cast(token)); - } - catch (...) - { - if (auto iter = constants.find(token); iter != std::end(constants)) - { - return iter->second; - } - else - { - throw read_error(make("not a number"), make(token)); - } - } - } - } - } - - static auto string_to_symbol(external_representation const& name) -> const_reference + static auto string_to_symbol(std::string const& name) -> const_reference { if (auto const iter = symbols.find(name); iter != std::end(symbols)) { diff --git a/include/meevax/kernel/string.hpp b/include/meevax/kernel/string.hpp index 279c6201e..74a63d161 100644 --- a/include/meevax/kernel/string.hpp +++ b/include/meevax/kernel/string.hpp @@ -29,7 +29,7 @@ inline namespace kernel explicit string() = default; - explicit string(external_representation const&); + explicit string(std::string const&); /* (list->string list) procedure @@ -152,7 +152,7 @@ inline namespace kernel */ auto set(const_reference, const_reference) -> void; - operator external_representation() const; // write-string (for display) + operator std::string() const; // write-string (for display) }; auto operator ==(string const&, string const&) -> bool; diff --git a/include/meevax/kernel/symbol.hpp b/include/meevax/kernel/symbol.hpp index 7e9e4293e..221ef590f 100644 --- a/include/meevax/kernel/symbol.hpp +++ b/include/meevax/kernel/symbol.hpp @@ -35,7 +35,7 @@ inline namespace kernel : value { std::forward(xs)... } {} - operator external_representation() const noexcept + operator std::string() const noexcept { return value; } diff --git a/include/meevax/memory/nan_boxing_pointer.hpp b/include/meevax/memory/nan_boxing_pointer.hpp index 36d24179f..7067effc9 100644 --- a/include/meevax/memory/nan_boxing_pointer.hpp +++ b/include/meevax/memory/nan_boxing_pointer.hpp @@ -45,9 +45,9 @@ inline namespace memory typename T_0b111 = std::integral_constant> struct nan_boxing_pointer { - using element_type = typename std::decay::type; + using element_type = std::decay_t; - using pointer = typename std::add_pointer::type; + using pointer = std::add_pointer_t; pointer data; @@ -131,14 +131,14 @@ inline namespace memory template auto as() const { - if constexpr (std::is_same::type>::value) + if constexpr (std::is_same_v, float64>) { return bit_cast(data); } else { - return bit_cast::type>( - static_cast::type)>>( + return bit_cast>( + static_cast)>>( reinterpret_cast(data) & mask_payload)); } } @@ -161,7 +161,7 @@ inline namespace memory template auto is() const noexcept { - return type() == typeid(typename std::decay::type); + return type() == typeid(std::decay_t); } auto signature() const noexcept @@ -221,15 +221,15 @@ inline namespace memory default: if (auto value = as(); std::isnan(value)) { - return os << yellow("+nan.0"); + return os << cyan("+nan.0"); } else if (std::isinf(value)) { - return os << yellow(0 < value ? '+' : '-', "inf.0"); + return os << cyan(0 < value ? '+' : '-', "inf.0"); } else { - return os << std::fixed << std::setprecision(17) << yellow(value); + return os << std::fixed << std::setprecision(17) << cyan(value); } } } diff --git a/include/meevax/memory/tagged_pointer.hpp b/include/meevax/memory/tagged_pointer.hpp index eae8f41f7..896dc5421 100644 --- a/include/meevax/memory/tagged_pointer.hpp +++ b/include/meevax/memory/tagged_pointer.hpp @@ -87,15 +87,15 @@ inline namespace memory template auto as() const { - return bit_cast::type>( - static_cast::type)>>( + return bit_cast>( + static_cast)>>( reinterpret_cast(simple_pointer::data) >> 32)); } template auto is() const noexcept { - return type() == typeid(typename std::decay::type); + return type() == typeid(std::decay_t); } constexpr auto tag() const noexcept @@ -109,7 +109,7 @@ inline namespace memory { #define DEFINE(TAG) \ case TAG: \ - return typeid(typename std::decay::type) + return typeid(std::decay_t) DEFINE(0b001); DEFINE(0b010); diff --git a/include/meevax/type_traits/underlying_cast.hpp b/include/meevax/type_traits/underlying_cast.hpp index 6e4f4bf2f..f9f3d6052 100644 --- a/include/meevax/type_traits/underlying_cast.hpp +++ b/include/meevax/type_traits/underlying_cast.hpp @@ -26,13 +26,13 @@ inline namespace type_traits template )> constexpr auto underlying_cast(T x) { - return static_cast::type>(x); + return static_cast>(x); } template constexpr auto underlying_decrement(T && value) { - return typename std::decay::type(underlying_cast(value) - 1); + return std::decay_t(underlying_cast(value) - 1); } } // namespace type_traits } // namespace meevax diff --git a/include/meevax/utility/overload.hpp b/include/meevax/utility/overload.hpp index 9f7044c98..4323d1027 100644 --- a/include/meevax/utility/overload.hpp +++ b/include/meevax/utility/overload.hpp @@ -34,7 +34,7 @@ inline namespace utility overloads(Ts&&...) -> overloads; template - constexpr auto overload(Ts&&... xs) -> overloads::type> + constexpr auto overload(Ts&&... xs) -> overloads> { return { std::forward(xs)... }; } diff --git a/src/kernel/character.cpp b/src/kernel/character.cpp index 771845438..a1e11111f 100644 --- a/src/kernel/character.cpp +++ b/src/kernel/character.cpp @@ -22,7 +22,7 @@ namespace meevax { inline namespace kernel { - character::operator external_representation() const + character::operator std::string() const { std::array bytes {}; @@ -75,7 +75,7 @@ inline namespace kernel case 0x7F: return os << cyan("delete" ); default: - return os << cyan(static_cast(datum)); + return os << cyan(static_cast(datum)); } } diff --git a/src/kernel/complex.cpp b/src/kernel/complex.cpp index 706b9c9ad..e571547c7 100644 --- a/src/kernel/complex.cpp +++ b/src/kernel/complex.cpp @@ -14,21 +14,48 @@ limitations under the License. */ -#include #include +#include namespace meevax { inline namespace kernel { - auto complex::real() const noexcept -> const_reference + complex::complex(std::string const& token, int radix) { - return first; + std::regex static const rectangular { R"(([+-]?.*)([+-].*)i)" }; + + std::regex static const polar { R"(([+-]?.*)@([+-]?.*))" }; + + if (std::smatch result; std::regex_match(token, result, rectangular)) + { + std::get<0>(*this) = string_to_real(result[1].length() == 0 ? "0" : result.str(1), radix); + std::get<1>(*this) = string_to_real(result[2].length() == 1 ? result.str(2) + "1" : result.str(2), radix); + } + else if (std::regex_match(token, result, polar)) + { + auto const magnitude = string_to_real(result.str(1), radix); + auto const angle = string_to_real(result.str(2), radix); + + std::get<0>(*this) = magnitude * apply(angle); + std::get<1>(*this) = magnitude * apply(angle); + } + else + { + throw std::invalid_argument("not a complex number"); + } } - auto complex::real() noexcept -> reference + auto complex::canonicalize() const -> value_type { - return first; + if (apply(imag(), e0).as()) + { + return real(); + } + else + { + return make(*this); + } } auto complex::imag() const noexcept -> const_reference @@ -36,14 +63,43 @@ inline namespace kernel return second; } - auto complex::imag() noexcept -> reference + auto complex::real() const noexcept -> const_reference { - return second; + return first; + } + + complex::operator std::complex() + { + assert(apply(real())); + assert(apply(imag())); + + return std::complex(apply(real()).as(), + apply(imag()).as()); } auto operator <<(std::ostream & os, complex const& z) -> std::ostream & { - return os << z.real() << cyan(apply>(e0, z.imag()).as() ? '+' : '-') << z.imag() << cyan("i"); + if (apply(z.imag(), e0).as()) + { + return os << z.real(); + } + else + { + auto explicitly_signed = [](auto const& number) + { + switch (auto const s = lexical_cast(number); s[0]) + { + case '+': + case '-': + return s; + + default: + return "+" + s; + } + }; + + return os << z.real() << cyan(explicitly_signed(z.imag()), "i"); + } } } // namespace kernel } // namespace meevax diff --git a/src/kernel/constant.cpp b/src/kernel/constant.cpp deleted file mode 100644 index bd5e11b28..000000000 --- a/src/kernel/constant.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright 2018-2022 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. -*/ - -#include -#include - -namespace meevax -{ -inline namespace kernel -{ - std::unordered_map const constants - { - // R7RS 7.1.1. Lexical structure - { "+inf.0", make(+std::numeric_limits::infinity()) }, - { "-inf.0", make(-std::numeric_limits::infinity()) }, - - { "+nan.0", make(+std::numeric_limits::quiet_NaN()) }, - { "-nan.0", make(-std::numeric_limits::quiet_NaN()) }, - - // SRFI-144 - { "fl-e", make(M_E ) }, - { "fl-log2-e", make(M_LOG2E ) }, - { "fl-log10-e", make(M_LOG10E ) }, - { "fl-log-2", make(M_LN2 ) }, - { "fl-1/log-2", make(M_LN2 ) }, - { "fl-log-10", make(M_LN10 ) }, - { "fl-1/log-10", make(M_LN10 ) }, - { "fl-pi", make(M_PI ) }, - { "fl-1/pi", make(M_1_PI ) }, - { "fl-pi/2", make(M_PI_2 ) }, - { "fl-pi/4", make(M_PI_4 ) }, - { "fl-2/pi", make(M_2_PI ) }, - { "fl-2/sqrt-pi", make(M_2_SQRTPI) }, - { "fl-sqrt-2", make(M_SQRT2 ) }, - { "fl-1/sqrt-2", make(M_SQRT1_2 ) }, - }; -} // namespace kernel -} // namespace meevax diff --git a/src/kernel/environment.cpp b/src/kernel/environment.cpp index 0c66ccc0d..8fdc97380 100644 --- a/src/kernel/environment.cpp +++ b/src/kernel/environment.cpp @@ -26,7 +26,7 @@ inline namespace kernel (*this)[name] = value; } - auto environment::define(external_representation const& name, const_reference value) -> void + auto environment::define(std::string const& name, const_reference value) -> void { define(string_to_symbol(name), value); } @@ -36,7 +36,7 @@ inline namespace kernel if (expression.is() and car(expression).is() and car(expression).as().value == "define-library") { - define_library(lexical_cast(cadr(expression)), cddr(expression)); + define_library(lexical_cast(cadr(expression)), cddr(expression)); return cadr(expression); } else if (expression.is() and car(expression).is() @@ -205,7 +205,7 @@ inline namespace kernel return rename(cadr(declaration)) (cddr(declaration)); } - else if (auto iter = libraries.find(lexical_cast(declaration)); iter != std::end(libraries)) + else if (auto iter = libraries.find(lexical_cast(declaration)); iter != std::end(libraries)) { return std::get<1>(*iter).resolve(); } @@ -233,12 +233,12 @@ inline namespace kernel } } - auto environment::import_(external_representation const& import_set) -> void + auto environment::import_(std::string const& import_set) -> void { import_(read(import_set)); } - auto environment::load(external_representation const& s) -> value_type + auto environment::load(std::string const& s) -> value_type { if (let port = make(s); port and port.as().is_open()) { diff --git a/src/kernel/error.cpp b/src/kernel/error.cpp index a6c4f214f..0b7048e10 100644 --- a/src/kernel/error.cpp +++ b/src/kernel/error.cpp @@ -35,11 +35,11 @@ inline namespace kernel throw *this; } - auto error::what() const -> external_representation + auto error::what() const -> std::string { std::stringstream ss {}; - ss << "error: " << static_cast(message().as()); + ss << "error: " << static_cast(message().as()); if (irritants()) { @@ -61,7 +61,7 @@ inline namespace kernel return os << magenta(")"); } - auto raise(external_representation const& message) -> void + auto raise(std::string const& message) -> void { throw error(make(message)); } diff --git a/src/kernel/exact_integer.cpp b/src/kernel/exact_integer.cpp index 38e20a53d..8ef3c69fd 100644 --- a/src/kernel/exact_integer.cpp +++ b/src/kernel/exact_integer.cpp @@ -71,12 +71,12 @@ inline namespace kernel mpz_init_set_d(value, rhs); } - exact_integer::exact_integer(external_representation const& s, int radix) + exact_integer::exact_integer(std::string const& s, int radix) { - if (mpz_init_set_str(value, s.c_str(), radix)) + if (mpz_init_set_str(value, (s.at(0) == '+' ? s.substr(1) : s).c_str(), radix)) { mpz_clear(value); - throw error(); + throw std::invalid_argument("not a integer"); } } @@ -92,11 +92,11 @@ inline namespace kernel return *this; } - auto exact_integer::operator=(external_representation const& s) -> exact_integer & + auto exact_integer::operator=(std::string const& s) -> exact_integer & { if (mpz_set_str(value, s.c_str(), 0)) { - throw error(make("invalid argument"), make(s)); + throw std::invalid_argument(s); } else { diff --git a/src/kernel/library.cpp b/src/kernel/library.cpp index e4bb7750d..f0c5f99b0 100644 --- a/src/kernel/library.cpp +++ b/src/kernel/library.cpp @@ -59,6 +59,31 @@ inline namespace kernel library.export_("char-codepoint"); }); + define_library("(meevax complex)", [](library & library) + { + library.define("make-rectangular", [](let const& xs) + { + assert(apply(car(xs))); + assert(apply(cadr(xs))); + + return make(car(xs), cadr(xs)); + }); + + library.define("real-part", [](let const& xs) + { + return car(xs).as().real(); + }); + + library.define("imag-part", [](let const& xs) + { + return car(xs).as().imag(); + }); + + library.export_("make-rectangular"); + library.export_("real-part"); + library.export_("imag-part"); + }); + define_library("(meevax context)", [](library & library) { library.define("emergency-exit", [](let const& xs) @@ -534,38 +559,37 @@ inline namespace kernel }) == std::end(xs); \ }) - DEFINE(= , equal_to ); - DEFINE(!=, std::not_equal_to ); - DEFINE(< , std::less ); - DEFINE(<=, std::less_equal ); - DEFINE(> , std::greater ); - DEFINE(>=, std::greater_equal); + DEFINE(= , equal_to ); + DEFINE(< , less ); + DEFINE(<=, less_equal ); + DEFINE(> , greater ); + DEFINE(>=, greater_equal); #undef DEFINE library.define("+", [](let const& xs) { - return std::accumulate(std::begin(xs), std::end(xs), e0, std::plus()); + return std::accumulate(std::begin(xs), std::end(xs), e0, plus()); }); library.define("*", [](let const& xs) { - return std::accumulate(std::begin(xs), std::end(xs), e1, std::multiplies()); + return std::accumulate(std::begin(xs), std::end(xs), e1, multiplies()); }); #define DEFINE(SYMBOL, FUNCTION, BASIS) \ library.define(SYMBOL, [](let const& xs) \ { \ - return cdr(xs).is() ? std::accumulate(std::begin(cdr(xs)), std::end(xs), car(xs), [](auto&& a, auto&& b) \ + return cdr(xs).is() ? std::accumulate(std::next(std::begin(xs)), std::end(xs), car(xs), [](auto&& a, auto&& b) \ { \ - return FUNCTION(a, b); \ + return FUNCTION()(a, b); \ }) \ - : FUNCTION(BASIS, car(xs)); \ + : FUNCTION()(BASIS, car(xs)); \ }) - DEFINE("-", std::minus (), e0); - DEFINE("/", std::divides(), e1); - DEFINE("%", std::modulus(), e1); + DEFINE("-", minus , e0); + DEFINE("/", divides, e1); + DEFINE("%", modulus, e1); #undef DEFINE @@ -938,7 +962,7 @@ inline namespace kernel library.define("put-char", [](let const& xs) { - cadr(xs).as() << static_cast(car(xs).as()); + cadr(xs).as() << static_cast(car(xs).as()); return unspecified; }); @@ -1064,16 +1088,16 @@ inline namespace kernel return std::adjacent_find( \ std::begin(xs), std::end(xs), [](let const& a, let const& b) \ { \ - return not COMPARE(a.as_const().codepoints, \ - b.as_const().codepoints); \ + return not COMPARE()(a.as_const().codepoints, \ + b.as_const().codepoints); \ }) == std::end(xs); \ } - library.define("string=?", STRING_COMPARE(std::equal_to ())); - library.define("string())); - library.define("string<=?", STRING_COMPARE(std::less_equal ())); - library.define("string>?", STRING_COMPARE(std::greater ())); - library.define("string>=?", STRING_COMPARE(std::greater_equal())); + library.define("string=?", STRING_COMPARE(equal_to )); + library.define("string("string<=?", STRING_COMPARE(less_equal )); + library.define("string>?", STRING_COMPARE(greater )); + library.define("string>=?", STRING_COMPARE(greater_equal)); #undef STRING_COMPARE @@ -1280,7 +1304,7 @@ inline namespace kernel { if (x.is()) { - std::cout << static_cast(x.as()); + std::cout << static_cast(x.as()); } else { @@ -1369,7 +1393,7 @@ inline namespace kernel export_specs = cons(export_spec, export_specs); } - auto library::export_(external_representation const& export_spec) -> void + auto library::export_(std::string const& export_spec) -> void { export_(read(export_spec)); } @@ -1400,6 +1424,6 @@ inline namespace kernel return os << library.global(); } - std::unordered_map libraries {}; + std::unordered_map libraries {}; } // namespace kernel } // namespace meevax diff --git a/src/kernel/number.cpp b/src/kernel/number.cpp index 06cdd5220..126ad3649 100644 --- a/src/kernel/number.cpp +++ b/src/kernel/number.cpp @@ -14,7 +14,6 @@ limitations under the License. */ -#include #include namespace meevax @@ -37,7 +36,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 error(make("unsupported operation"), unit); } + auto operator % (exact_integer const& , ratio const& ) -> ratio { throw std::invalid_argument("unsupported operation"); } auto operator ==(exact_integer const& a, ratio const& b) -> bool { return mpq_cmp_z(b.value, a.value) == 0; } auto operator !=(exact_integer const& a, ratio const& b) -> bool { return mpq_cmp_z(b.value, a.value) != 0; } auto operator < (exact_integer const& a, ratio const& b) -> bool { return mpq_cmp_z(b.value, a.value) > 0; } @@ -69,11 +68,23 @@ inline namespace kernel 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, 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& 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 error(make("unsupported operation"), unit); } + auto operator % (ratio const& , exact_integer const& ) -> ratio { throw std::invalid_argument("unsupported 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; } @@ -85,7 +96,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 error(make("unsupported operation"), unit); } + auto operator % (ratio const& , ratio const& ) -> ratio { throw std::invalid_argument("unsupported 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; } @@ -117,6 +128,18 @@ inline namespace kernel 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, 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); } @@ -141,6 +164,18 @@ inline namespace kernel 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, 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); } @@ -165,10 +200,82 @@ inline namespace kernel 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 +(const_reference x, const_reference y) -> value_type { return apply>(x, y); } - auto operator -(const_reference x, const_reference y) -> value_type { return apply>(x, y); } - auto operator *(const_reference x, const_reference y) -> value_type { return apply>(x, y); } - auto operator /(const_reference x, const_reference y) -> value_type { return apply>(x, y); } - auto operator %(const_reference x, const_reference y) -> value_type { return apply< modulus >(x, y); } + 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 apply(a.real(), b.real()).as() and apply(a.imag(), b.imag()).as(); } + 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"); } + + auto operator + (const_reference x, const_reference y) -> value_type { return apply(x, y); } + auto operator - (const_reference x, const_reference y) -> value_type { return apply(x, y); } + auto operator * (const_reference x, const_reference y) -> value_type { return apply(x, y); } + auto operator / (const_reference x, const_reference y) -> value_type { return apply(x, y); } + auto operator % (const_reference x, const_reference y) -> value_type { return apply(x, y); } } // namespace kernel } // namespace meevax diff --git a/src/kernel/port.cpp b/src/kernel/port.cpp index bdc9eeb9b..47abe9acc 100644 --- a/src/kernel/port.cpp +++ b/src/kernel/port.cpp @@ -45,7 +45,7 @@ inline namespace kernel #undef DEFINE #define DEFINE(TYPENAME, FILE_STREAM, NAME) \ - TYPENAME::TYPENAME(external_representation const& name) \ + TYPENAME::TYPENAME(std::string const& name) \ : description { name } \ , FILE_STREAM { name } \ {} \ diff --git a/src/kernel/ratio.cpp b/src/kernel/ratio.cpp index fc5880337..fd218ab34 100644 --- a/src/kernel/ratio.cpp +++ b/src/kernel/ratio.cpp @@ -61,14 +61,14 @@ inline namespace kernel mpq_set_d(value, x); } - ratio::ratio(external_representation const& token, int radix) + ratio::ratio(std::string const& token, int radix) { // std::regex static const pattern { "([+-]?[0-9a-f]+)/([0-9a-f]+)" }; if (mpq_init(value); mpq_set_str(value, token.c_str(), radix)) { mpq_clear(value); - throw error(); + throw std::invalid_argument("not a ratio"); } else { diff --git a/src/kernel/reader.cpp b/src/kernel/reader.cpp index 6f014c903..2ebeffbf9 100644 --- a/src/kernel/reader.cpp +++ b/src/kernel/reader.cpp @@ -16,7 +16,6 @@ #include #include -#include namespace meevax { @@ -122,7 +121,7 @@ inline namespace kernel case 't': s.codepoints.emplace_back('\t'); break; case 'v': s.codepoints.emplace_back('\v'); break; case 'x': - if (auto token = external_representation(); std::getline(is, token, ';')) + if (auto token = std::string(); std::getline(is, token, ';')) { s.codepoints.emplace_back(lexical_cast(std::hex, token)); } @@ -196,7 +195,7 @@ inline namespace kernel auto read_character_literal(std::istream & is) -> value_type { - std::unordered_map static const character_names { + std::unordered_map static const character_names { { "alarm" , 0x07 }, { "backspace", 0x08 }, { "delete" , 0x7F }, @@ -243,5 +242,97 @@ inline namespace kernel { return make(get_delimited_elements(is, '"')); } + + auto string_to_integer(std::string const& token, int radix) -> value_type + { + return make(token, radix); + } + + auto string_to_rational(std::string const& token, int radix) -> value_type + { + try + { + return string_to_integer(token, radix); + } + catch (...) + { + return make(ratio(token, radix)); + } + } + + auto string_to_real(std::string const& token, int radix) -> value_type + { + try + { + return string_to_rational(token, radix); + } + catch (...) + { + std::unordered_map static const constants + { + // R7RS 7.1.1. Lexical structure + { "+inf.0", +std::numeric_limits::infinity() }, + { "-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 }, + }; + + std::regex static const pattern { R"(([+-]?(?:\d+\.?|\d*\.\d+))([DEFLSdefls][+-]?\d+)?)" }; + + if (auto iter = constants.find(token); iter != std::end(constants)) + { + return make(iter->second); + } + else if (std::regex_match(token, pattern)) + { + return make(lexical_cast(token)); + } + else + { + throw std::invalid_argument("not a real number"); + } + } + } + + auto string_to_complex(std::string const& token, int radix) -> value_type + { + try + { + return string_to_real(token, radix); + } + catch (...) + { + return make(complex(token, radix)); + } + } + + auto string_to_number(std::string const& token, int radix) -> value_type + { + try + { + return string_to_complex(token, radix); + } + catch (...) + { + throw std::invalid_argument("not a number"); + } + } } // namespace kernel } // namespace meevax diff --git a/src/kernel/string.cpp b/src/kernel/string.cpp index 49dcf3946..dd3ecba40 100644 --- a/src/kernel/string.cpp +++ b/src/kernel/string.cpp @@ -25,7 +25,7 @@ namespace meevax { inline namespace kernel { - string::string(external_representation const& s) + string::string(std::string const& s) { for (auto port = std::stringstream(s); not character::is_eof(port.peek()); codepoints.emplace_back(get_codepoint(port))); } @@ -112,13 +112,13 @@ inline namespace kernel codepoints.at(k.as()) = c.as(); } - string::operator external_representation() const + string::operator std::string() const { - external_representation result; + std::string result; for (character const& each : codepoints) { - result.append(static_cast(each)); + result.append(static_cast(each)); } return result; diff --git a/src/kernel/syntax.cpp b/src/kernel/syntax.cpp index 79d58ac36..6b9f7a763 100644 --- a/src/kernel/syntax.cpp +++ b/src/kernel/syntax.cpp @@ -20,7 +20,7 @@ namespace meevax { inline namespace kernel { - syntax::syntax(external_representation const& name, function_type const& compile) + syntax::syntax(std::string const& name, function_type const& compile) : description { name } , compile { compile } {} diff --git a/src/main.cpp b/src/main.cpp index 1588f98a1..89f9d6682 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,7 +33,17 @@ auto main(int const argc, char const* const* const argv) -> int if (main.interactive) { main.display_version(); - main.import_("(scheme r5rs)"); + main.import_("(scheme base)"); + main.import_("(scheme char)"); + main.import_("(scheme complex)"); + main.import_("(scheme cxr)"); + main.import_("(scheme eval)"); + main.import_("(scheme inexact)"); + main.import_("(scheme lazy)"); + main.import_("(scheme load)"); + main.import_("(scheme process-context)"); + main.import_("(scheme read)"); + main.import_("(scheme write)"); } while (main.interactive and main.char_ready()) diff --git a/test/list.cpp b/test/list.cpp index d91c57514..1da9c62f2 100644 --- a/test/list.cpp +++ b/test/list.cpp @@ -12,24 +12,24 @@ auto main() -> int c = make("c"), d = make("d"); - assert(lexical_cast(cons(a, unit)) == "(a)"); - assert(lexical_cast(cons(list(a), list(b, c, d))) == "((a) b c d)"); - assert(lexical_cast(cons(make("a"), list(b, c))) == "(\"a\" b c)"); - assert(lexical_cast(cons(a, make(3))) == "(a . 3)"); - assert(lexical_cast(cons(list(a, b), c)) == "((a b) . c)"); + assert(lexical_cast(cons(a, unit)) == "(a)"); + assert(lexical_cast(cons(list(a), list(b, c, d))) == "((a) b c d)"); + assert(lexical_cast(cons(make("a"), list(b, c))) == "(\"a\" b c)"); + assert(lexical_cast(cons(a, make(3))) == "(a . 3)"); + assert(lexical_cast(cons(list(a, b), c)) == "((a b) . c)"); - assert(lexical_cast(list(a, make(3 + 4), c)) == "(a 7 c)"); - assert(lexical_cast(list()) == "()"); + assert(lexical_cast(list(a, make(3 + 4), c)) == "(a 7 c)"); + assert(lexical_cast(list()) == "()"); - assert(lexical_cast(xcons(list(b, c), a)) == "(a b c)"); + assert(lexical_cast(xcons(list(b, c), a)) == "(a b c)"); - assert(lexical_cast(make_list(4, c)) == "(c c c c)"); + assert(lexical_cast(make_list(4, c)) == "(c c c c)"); - assert(lexical_cast(list_tabulate(4, [](auto&&... xs) { return make(xs...); })) == "(0 1 2 3)"); + assert(lexical_cast(list_tabulate(4, [](auto&&... xs) { return make(xs...); })) == "(0 1 2 3)"); let x1 = list(a, b, c); let x2 = list_copy(x1); - assert(lexical_cast(x2) == "(a b c)"); + assert(lexical_cast(x2) == "(a b c)"); assert(not eq(x1, x2)); let x = circular_list(a, b, c); diff --git a/test/nan_boxing_pointer.cpp b/test/nan_boxing_pointer.cpp index b0369638e..aeef00482 100644 --- a/test/nan_boxing_pointer.cpp +++ b/test/nan_boxing_pointer.cpp @@ -125,8 +125,8 @@ auto main() -> int } { - assert(lexical_cast(make(3.14)) == "3.14000000000000012"); - assert(lexical_cast(make(42)) == "42"); + assert(lexical_cast(make(3.14)) == "3.14000000000000012"); + assert(lexical_cast(make(42)) == "42"); } { diff --git a/test/r5rs.ss b/test/r5rs.ss index cfa836056..df38c4cdf 100644 --- a/test/r5rs.ss +++ b/test/r5rs.ss @@ -388,13 +388,13 @@ ; ---- 6.2.5 ------------------------------------------------------------------- -(check (complex? 3+4i) => #t) +; (check (complex? 3+4i) => #t) (check (complex? 3) => #t) (check (real? 3) => #t) -(check (real? -2.5+0.0i) => #t) +; (check (real? -2.5+0.0i) => #t) (check (real? #e1e10) => #t) @@ -402,7 +402,7 @@ (check (rational? 6/3) => #t) -(check (integer? 3+0i) => #t) +; (check (integer? 3+0i) => #t) (check (integer? 3.0) => #t) @@ -954,4 +954,4 @@ (check-report) -(exit (check-passed? 288)) +(exit (check-passed? 285)) diff --git a/test/r7rs.ss b/test/r7rs.ss index 3fa3da2af..3b59e0e64 100644 --- a/test/r7rs.ss +++ b/test/r7rs.ss @@ -438,7 +438,7 @@ ; (define range ; (case-lambda ; ((e) (range 0 e)) -; ((b e) (do ((r ’() (cons e r)) +; ((b e) (do ((r '() (cons e r)) ; (e (- e 1) (- e 1))) ; ((< e b) r))))) @@ -826,15 +826,15 @@ ; ---- 6.2.6. ------------------------------------------------------------------ -; (check (complex? 3+4i) => #t) +(check (complex? 3+4i) => #t) (check (complex? 3) => #t) (check (real? 3) => #t) -; (check (real? -2.5+0i) => #t) +(check (real? -2.5+0i) => #t) -; (check (real? -2.5+0.0i) => #t) +(check (real? -2.5+0.0i) => #t) (check (real? #e1e10) => #t) @@ -850,7 +850,7 @@ (check (rational? 6/3) => #t) -; (check (integer? 3+0i) => #t) +(check (integer? 3+0i) => #t) (check (integer? 3.0) => #t) @@ -872,7 +872,7 @@ (check (finite? +inf.0) => #f) -; (check (finite? 3.0+inf.0i) => #f) +(check (finite? 3.0+inf.0i) => #f) (check (infinite? 3) => #f) @@ -880,15 +880,15 @@ (check (infinite? +nan.0) => #f) -; (check (infinite? 3.0+inf.0i) => #t) +(check (infinite? 3.0+inf.0i) => #t) (check (nan? +nan.0) => #t) (check (nan? 32) => #f) -; (check (nan? +nan.0+5.0i) => #t) +(check (nan? +nan.0+5.0i) => #t) -; (check (nan? 1+2i) => #f) +(check (nan? 1+2i) => #f) (check (zero? 0/1) => #t) @@ -982,7 +982,7 @@ (check (sqrt 9) => 3) -; (check (sqrt -1) => +i) +(check (sqrt -1) => +i) ; (check (exact-integer-sqrt 4) => #,(values 2 0)) @@ -1555,4 +1555,4 @@ (check-report) -(exit (check-passed? 383)) +(exit (check-passed? 392))