diff --git a/README.md b/README.md index 246280a1b..320de8e91 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,9 @@ sudo rm -rf /usr/local/share/meevax | Target Name | Description |:-------------------|:-- -| `all` (default) | Build shared-library `libmeevax.0.4.50.so` and executable `meevax`. +| `all` (default) | Build shared-library `libmeevax.0.4.58.so` and executable `meevax`. | `test` | Test executable `meevax`. -| `package` | Generate debian package `meevax_0.4.50_amd64.deb`. +| `package` | Generate debian package `meevax_0.4.58_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` @@ -120,7 +120,7 @@ __(1)__ Meevax installed by `make install` cannot be uninstalled by the system's ## Usage ``` -Meevax Lisp System, version 0.4.50 +Meevax Lisp System, version 0.4.58 Usage: meevax [OPTION...] [FILE...] diff --git a/VERSION b/VERSION index 6aed7c397..f96de0bf2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.50 +0.4.58 diff --git a/include/meevax/kernel/configurator.hpp b/include/meevax/kernel/configurator.hpp index 35ebc1759..6d58d3de6 100644 --- a/include/meevax/kernel/configurator.hpp +++ b/include/meevax/kernel/configurator.hpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -33,133 +34,161 @@ inline namespace kernel { friend environment; + explicit configurator() + {} + IMPORT(environment, evaluate, NIL); IMPORT(environment, load, NIL); - IMPORT(environment, print, const); IMPORT(environment, read, NIL); + USING_STATIC(environment, print); + template using dispatcher = std::unordered_map; - const dispatcher short_options, short_options_with_arguments; + public: + static inline auto batch = false; + static inline auto debug = false; + static inline auto interactive = true; + static inline auto trace = false; + static inline auto verbose = false; - const dispatcher long_options, long_options_with_arguments; + static auto display_version() -> void + { + print("Meevax Lisp ", version()); + } - public: - bool batch = false; - bool debug = false; - bool interactive = false; - bool trace = false; - bool verbose = false; + static auto display_help() -> void + { + display_version(); + print(); + print("Usage: meevax [OPTION...] [FILE...]"); + print(); + print("Options:"); + print(" -b, --batch Suppress any system output."); + print(" -d, --debug Display detailed informations for developers."); + print(" -e, --evaluate=STRING Read and evaluate given STRING at configuration step."); + print(" -h, --help Display this help text and exit."); + print(" -i, --interactive Take over control of root environment."); + print(" -l, --load=FILENAME Same as -e '(load FILENAME)'"); + print(" -t, --trace Display stacks of virtual machine for each steps."); + print(" -v, --version Display version information and exit."); + print(" --verbose Display detailed informations."); + print(" -w, --write=OBJECT Same as -e '(write OBJECT)'"); + } - explicit configurator() - : short_options - { - std::make_pair('b', [this](auto&&...) - { - return make(batch = true); - }), + private: + static inline const dispatcher short_options + { + std::make_pair('b', [](auto&&...) + { + return make(batch = true); + }), - std::make_pair('d', [this](auto&&...) - { - return make(debug = true); - }), + std::make_pair('d', [](auto&&...) + { + return make(debug = true); + }), - std::make_pair('h', [this](auto&&...) -> lvalue - { - display_help(); - throw exit_status::success; - }), + std::make_pair('h', [](auto&&...) -> lvalue + { + configurator::display_help(); + throw exit_status::success; + }), - std::make_pair('i', [this](auto&&...) - { - return make(interactive = true); - }), + std::make_pair('i', [](auto&&...) + { + return make(interactive = true); + }), - std::make_pair('v', [this](auto&&...) -> lvalue - { - display_version(); - throw exit_status::success; - }), - } + std::make_pair('v', [](auto&&...) -> lvalue + { + configurator::display_version(); + throw exit_status::success; + }), + }; - , short_options_with_arguments - { - std::make_pair('e', [this](const_reference x, auto&&...) - { - return print(evaluate(x)), unspecified_object; - }), + static inline const dispatcher short_options_with_arguments + { + std::make_pair('e', [](const_reference x, auto&&...) + { + print(interaction_environment().as().evaluate(x)); + return unspecified_object; + }), - std::make_pair('l', [this](const_reference x, auto&&...) - { - return load(x.as_const()); - }), + std::make_pair('l', [](const_reference x, auto&&...) + { + return interaction_environment().as().load(x.as_const()); + }), - std::make_pair('w', [this](const_reference x, auto&&...) - { - return print(x), unspecified_object; - }), - } + std::make_pair('w', [](const_reference x, auto&&...) + { + print(x); + return unspecified_object; + }), + }; - , long_options - { - std::make_pair("batch", [this](auto&&...) - { - return make(batch = true); - }), + static inline const dispatcher long_options + { + std::make_pair("batch", [](auto&&...) + { + return make(batch = true); + }), - std::make_pair("debug", [this](auto&&...) - { - return make(debug = true); - }), + std::make_pair("debug", [](auto&&...) + { + return make(debug = true); + }), - std::make_pair("help", [this](auto&&...) -> lvalue - { - display_help(); - throw exit_status::success; - }), + std::make_pair("help", [](auto&&...) -> lvalue + { + display_help(); + throw exit_status::success; + }), - std::make_pair("interactive", [this](auto&&...) - { - return make(interactive = true); - }), + std::make_pair("interactive", [](auto&&...) + { + return make(interactive = true); + }), - std::make_pair("trace", [this](auto&&...) - { - return make(trace = true); - }), + std::make_pair("trace", [](auto&&...) + { + return make(trace = true); + }), - std::make_pair("verbose", [this](auto&&...) - { - return make(verbose = true); - }), + std::make_pair("verbose", [](auto&&...) + { + return make(verbose = true); + }), - std::make_pair("version", [this](auto&&...) -> lvalue - { - display_version(); - throw exit_status::success; - }), - } + std::make_pair("version", [](auto&&...) -> lvalue + { + display_version(); + throw exit_status::success; + }), + }; - , long_options_with_arguments - { - std::make_pair("evaluate", [this](const_reference x, auto&&...) - { - return print(evaluate(x)), unspecified_object; - }), + static inline const dispatcher long_options_with_arguments + { + std::make_pair("evaluate", [](const_reference x, auto&&...) + { + print(interaction_environment().as().evaluate(x)); + return unspecified_object; + }), - std::make_pair("load", [this](const_reference x, auto&&...) - { - return load(x.as_const()); - }), + std::make_pair("load", [](const_reference x, auto&&...) + { + return interaction_environment().as().load(x.as_const()); + }), - std::make_pair("write", [this](const_reference x, auto&&...) - { - return print(x), unspecified_object; - }), - } - {} + std::make_pair("write", [](const_reference x, auto&&...) + { + print(x); + return unspecified_object; + }), + }; + public: auto configure(const int argc, char const* const* const argv) { return configure({ argv + 1, argv + argc }); @@ -169,11 +198,7 @@ inline namespace kernel { static std::regex const pattern { R"(--(\w[-\w]+)(=(.*))?|-([\w]+))" }; - if (std::empty(args)) - { - interactive = true; - } - else for (auto current_option = std::begin(args); current_option != std::end(args); ++current_option) [&]() + for (auto current_option = std::begin(args); current_option != std::end(args); ++current_option) [&]() { std::smatch analysis {}; @@ -185,7 +210,7 @@ inline namespace kernel // std::cout << header("") << "analysis[3] = " << analysis[3] << std::endl; // std::cout << header("") << "analysis[4] = " << analysis[4] << std::endl; - if (auto const current_short_options = analysis.str(4); not current_short_options.empty()) + if (auto const& current_short_options = analysis.str(4); not current_short_options.empty()) { for (auto current_short_option = std::cbegin(current_short_options); current_short_option != std::cend(current_short_options); ++current_short_option) { @@ -210,7 +235,8 @@ inline namespace kernel } else { - throw error(make(cat, "unknown short-option -", *current_short_option)); + throw error(make("unknown short-option"), + make(*current_short_option)); } } } @@ -237,41 +263,19 @@ inline namespace kernel } else { - throw error(make(cat, "unknown long-option: ", *current_option)); + throw error(make("unknown long-option"), + make(*current_option)); } } else { + interactive = false; return load(*current_option); } return unspecified_object; }(); } - - auto display_version() const -> void - { - print("Meevax Lisp ", version()); - } - - auto display_help() const -> void - { - display_version(); - print(); - print("Usage: meevax [OPTION...] [FILE...]"); - print(); - print("Options:"); - print(" -b, --batch Suppress any system output."); - print(" -d, --debug Display detailed informations for developers."); - print(" -e, --evaluate=STRING Read and evaluate given STRING at configuration step."); - print(" -h, --help Display this help text and exit."); - print(" -i, --interactive Take over control of root environment."); - print(" -l, --load=FILENAME Same as -e '(load FILENAME)'"); - print(" -t, --trace Display stacks of virtual machine for each steps."); - print(" -v, --version Display version information and exit."); - print(" --verbose Display detailed informations."); - print(" -w, --write=OBJECT Same as -e '(write OBJECT)'"); - } }; } // namespace kernel } // namespace meevax diff --git a/include/meevax/kernel/environment.hpp b/include/meevax/kernel/environment.hpp index f57e8ab41..8c7ee5d37 100644 --- a/include/meevax/kernel/environment.hpp +++ b/include/meevax/kernel/environment.hpp @@ -55,11 +55,11 @@ inline namespace kernel { (import(xs), ...); - define("set-batch!", [this](let const& xs, auto&&...) { return batch = select(car(xs)); }); - define("set-debug!", [this](let const& xs, auto&&...) { return debug = select(car(xs)); }); - define("set-interactive!", [this](let const& xs, auto&&...) { return interactive = select(car(xs)); }); - define("set-trace!", [this](let const& xs, auto&&...) { return trace = select(car(xs)); }); - define("set-verbose!", [this](let const& xs, auto&&...) { return verbose = select(car(xs)); }); + // define("set-batch!", [this](let const& xs, auto&&...) { return batch = select(car(xs)); }); + // define("set-debug!", [this](let const& xs, auto&&...) { return debug = select(car(xs)); }); + // define("set-interactive!", [this](let const& xs, auto&&...) { return interactive = select(car(xs)); }); + // define("set-trace!", [this](let const& xs, auto&&...) { return trace = select(car(xs)); }); + // define("set-verbose!", [this](let const& xs, auto&&...) { return verbose = select(car(xs)); }); } auto operator [](const_reference) -> const_reference; diff --git a/include/meevax/kernel/interaction_environment.hpp b/include/meevax/kernel/interaction_environment.hpp new file mode 100644 index 000000000..cec72e3df --- /dev/null +++ b/include/meevax/kernel/interaction_environment.hpp @@ -0,0 +1,30 @@ +/* + 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_INTERACTION_ENVIRONMENT_HPP +#define INCLUDED_MEEVAX_KERNEL_INTERACTION_ENVIRONMENT_HPP + +#include + +namespace meevax +{ +inline namespace kernel +{ + auto interaction_environment() -> const_reference; +} // namespace kernel +} // namespace meevax + +#endif // INCLUDED_MEEVAX_KERNEL_INTERACTION_ENVIRONMENT_HPP diff --git a/include/meevax/kernel/library.hpp b/include/meevax/kernel/library.hpp index 45a455887..5c2919261 100644 --- a/include/meevax/kernel/library.hpp +++ b/include/meevax/kernel/library.hpp @@ -24,8 +24,6 @@ namespace meevax { inline namespace kernel { - auto interaction_environment() -> const_reference; - struct library : public environment { std::vector export_specs; diff --git a/include/meevax/kernel/machine.hpp b/include/meevax/kernel/machine.hpp index 856cfb14d..a00662782 100644 --- a/include/meevax/kernel/machine.hpp +++ b/include/meevax/kernel/machine.hpp @@ -29,15 +29,17 @@ namespace meevax { inline namespace kernel { - template + template class machine // TR-SECD machine. { - friend environment; + friend Environment; machine() {} - IMPORT(environment, fork, const); + IMPORT(Environment, fork, const); + + using environment = Environment; protected: let s, // stack (holding intermediate results and return address) diff --git a/include/meevax/kernel/writer.hpp b/include/meevax/kernel/writer.hpp index 5baecdc38..ed1efa393 100644 --- a/include/meevax/kernel/writer.hpp +++ b/include/meevax/kernel/writer.hpp @@ -33,38 +33,38 @@ inline namespace kernel public: template - auto write(std::ostream & os, Ts&&... xs) const -> std::ostream & + static auto write(std::ostream & os, Ts&&... xs) -> std::ostream & { return (os << ... << xs); } template - auto write(const_reference x, Ts&&... xs) const -> decltype(auto) + static auto write(const_reference x, Ts&&... xs) -> decltype(auto) { return write(x.as(), std::forward(xs)...); } template - auto print(Ts&&... xs) const -> decltype(auto) + static auto print(Ts&&... xs) -> decltype(auto) { return write(standard_output, std::forward(xs)..., '\n'); } public: - auto null_port() const -> const_reference + static auto null_port() -> const_reference { let static port = make("/dev/null"); return port; } - auto verbose_port() const -> const_reference + static auto verbose_port() -> const_reference { - return static_cast(*this).verbose ? standard_output : null_port(); + return Environment::verbose ? standard_output : null_port(); } - auto debug_port() const -> const_reference + static auto debug_port() -> const_reference { - return static_cast(*this).debug ? standard_error : null_port(); + return Environment::debug ? standard_error : null_port(); } }; } // namespace kernel diff --git a/include/meevax/utility/module.hpp b/include/meevax/utility/module.hpp index 6df353ad8..fea3b9c6c 100644 --- a/include/meevax/utility/module.hpp +++ b/include/meevax/utility/module.hpp @@ -30,4 +30,12 @@ static_assert(true) #define EXPORT(M, SYMBOL) using M::SYMBOL +#define USING_STATIC(TYPE, FUNCTION) \ +template \ +static auto FUNCTION(Ts&&... xs) -> decltype(auto) \ +{ \ + return TYPE::FUNCTION(std::forward(xs)...); \ +} \ +static_assert(true) + #endif // INCLUDED_MEEVAX_UTILITY_MODULE_HPP diff --git a/src/kernel/environment.cpp b/src/kernel/environment.cpp index adc88dea6..e6697b516 100644 --- a/src/kernel/environment.cpp +++ b/src/kernel/environment.cpp @@ -90,11 +90,6 @@ inline namespace kernel define(binding.as().symbol(), binding.as().load()); } - - if (interactive) - { - print(faint("; ", length(bindings), " identifiers imported.")); - } } auto environment::define(const_reference name, const_reference value) -> void @@ -152,14 +147,7 @@ inline namespace kernel auto environment::execute() -> lvalue { - if (trace) - { - return machine::execute(); - } - else - { - return machine::execute(); - } + return trace ? machine::execute() : machine::execute(); } auto environment::execute(const_reference code) -> lvalue diff --git a/src/kernel/interaction_environment.cpp b/src/kernel/interaction_environment.cpp new file mode 100644 index 000000000..34a79151a --- /dev/null +++ b/src/kernel/interaction_environment.cpp @@ -0,0 +1,30 @@ +/* + 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 +{ + auto interaction_environment() -> const_reference + { + let static const interaction_environment = make(); + return interaction_environment; + } +} // namespace kernel +} // namespace meevax diff --git a/src/kernel/library.cpp b/src/kernel/library.cpp index 7ff756f0f..a21b278eb 100644 --- a/src/kernel/library.cpp +++ b/src/kernel/library.cpp @@ -15,18 +15,13 @@ */ #include +#include #include namespace meevax { inline namespace kernel { - auto interaction_environment() -> const_reference - { - let static const interaction_environment = make(); - return interaction_environment; - } - library::library(syntax_library_t) { define("begin", machine::begin); diff --git a/src/main.cpp b/src/main.cpp index c065cde12..0aca95e72 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ limitations under the License. */ +#include #include #include diff --git a/test/environment.cpp b/test/environment.cpp index 48bd547bd..e37e87981 100644 --- a/test/environment.cpp +++ b/test/environment.cpp @@ -1,6 +1,7 @@ #undef NDEBUG #include +#include #include auto main() -> int