diff --git a/src/blaze/env/environment.cpp b/src/blaze/env/environment.cpp index 3d96aaa..681a361 100644 --- a/src/blaze/env/environment.cpp +++ b/src/blaze/env/environment.cpp @@ -88,6 +88,7 @@ void Environment::loadFunctions() loadCompare(); loadConvert(); loadFormat(); + loadMath(); loadMeta(); loadMutable(); loadOperators(); diff --git a/src/blaze/env/environment.h b/src/blaze/env/environment.h index 4bcda6d..e31211e 100644 --- a/src/blaze/env/environment.h +++ b/src/blaze/env/environment.h @@ -51,6 +51,7 @@ private: static void loadCompare(); static void loadConvert(); static void loadFormat(); + static void loadMath(); static void loadMeta(); static void loadMutable(); static void loadOperators(); diff --git a/src/blaze/env/functions/math.cpp b/src/blaze/env/functions/math.cpp new file mode 100644 index 0000000..a281ba1 --- /dev/null +++ b/src/blaze/env/functions/math.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023 Riyyi + * + * SPDX-License-Identifier: MIT + */ + +#include // std::sin +#include // sdt::numeric_limits +#include // std::static_pointer_cast + +#include "blaze/ast.h" +#include "blaze/env/macro.h" +#include "blaze/util.h" + +namespace blaze { + +void Environment::loadMath() +{ +#define MATH_MAX_MIN(variant, limit, operator) \ + { \ + CHECK_ARG_COUNT_AT_LEAST(#variant, SIZE(), 1); \ + \ + int64_t number = std::numeric_limits::limit(); \ + double decimal = std::numeric_limits::limit(); \ + \ + for (auto it = begin; it != end; ++it) { \ + IS_VALUE(Numeric, (*it)); \ + if (is(it->get())) { \ + auto it_numeric = std::static_pointer_cast(*it)->number(); \ + if (it_numeric operator number) { \ + number = it_numeric; \ + } \ + } \ + else { \ + auto it_numeric = std::static_pointer_cast(*it)->decimal(); \ + if (it_numeric operator decimal) { \ + decimal = it_numeric; \ + } \ + } \ + } \ + \ + if (number operator decimal) { \ + return makePtr(number); \ + } \ + \ + return makePtr(decimal); \ + } + + ADD_FUNCTION( + "max", "number...", + "Return largest of all arguments, where NUMBER is a number or decimal.", + MATH_MAX_MIN(max, lowest, >)); + ADD_FUNCTION( + "min", "number...", + "Return smallest of all arguments, where NUMBER is a number or decimal.", + MATH_MAX_MIN(min, max, <)); + +#define MATH_COS_SIN(variant) \ + { \ + CHECK_ARG_COUNT_IS(#variant, SIZE(), 1); \ + \ + auto value = *begin; \ + IS_VALUE(Numeric, value); \ + if (is(begin->get())) { \ + return makePtr(std::variant((double)std::static_pointer_cast(value)->number())); \ + } \ + \ + return makePtr(std::variant(std::static_pointer_cast(value)->decimal())); \ + } + + ADD_FUNCTION( + "cos", "arg", + "Return the cosine of ARG.", + MATH_COS_SIN(cos)); + + ADD_FUNCTION( + "sin", "arg", + "Return the sine of ARG.", + MATH_COS_SIN(sin)); +} + +} // namespace blaze diff --git a/src/blaze/env/functions/other.cpp b/src/blaze/env/functions/other.cpp index 7e99d11..5a16127 100644 --- a/src/blaze/env/functions/other.cpp +++ b/src/blaze/env/functions/other.cpp @@ -4,8 +4,11 @@ * SPDX-License-Identifier: MIT */ -#include // std::chrono::sytem_clock -#include // int64_t +#include // std::chrono::sytem_clock +#include // int64_t +#include // std::filesystem::current_path + +#include "ruc/file.h" #include "blaze/ast.h" #include "blaze/env/macro.h" @@ -17,10 +20,35 @@ namespace blaze { void Environment::loadOther() { + ADD_FUNCTION( + "pwd", "", + "Return the full filename of the current working directory.", + { + CHECK_ARG_COUNT_IS("pwd", SIZE(), 0); + + auto path = std::filesystem::current_path().string(); + return makePtr(path); + }); + + ADD_FUNCTION( + "slurp", "", + "Read file contents", + { + CHECK_ARG_COUNT_IS("slurp", SIZE(), 1); + + VALUE_CAST(node, String, (*begin)); + std::string path = node->data(); + + auto file = ruc::File(path); + + return makePtr(file.data()); + }); + + // ----------------------------------------- + // (throw x) ADD_FUNCTION( - "throw", - "", + "throw", "", "", { CHECK_ARG_COUNT_IS("throw", SIZE(), 1); @@ -34,8 +62,7 @@ void Environment::loadOther() // (time-ms) ADD_FUNCTION( - "time-ms", - "", + "time-ms", "", "", { CHECK_ARG_COUNT_IS("time-ms", SIZE(), 0); diff --git a/src/blaze/env/functions/repl.cpp b/src/blaze/env/functions/repl.cpp index 36dd6c4..499bb54 100644 --- a/src/blaze/env/functions/repl.cpp +++ b/src/blaze/env/functions/repl.cpp @@ -6,8 +6,6 @@ #include -#include "ruc/file.h" - #include "blaze/ast.h" #include "blaze/env/macro.h" #include "blaze/repl.h" @@ -31,22 +29,6 @@ void Environment::loadRepl() return Repl::read(input); }); - // Read file contents - ADD_FUNCTION( - "slurp", - "", - "", - { - CHECK_ARG_COUNT_IS("slurp", SIZE(), 1); - - VALUE_CAST(node, String, (*begin)); - std::string path = node->data(); - - auto file = ruc::File(path); - - return makePtr(file.data()); - }); - // Prompt readline ADD_FUNCTION( "readline",