From 9db041946e8e95deb63892e3250ef35da09a112f Mon Sep 17 00:00:00 2001 From: Riyyi Date: Sun, 5 Nov 2023 14:35:32 +0100 Subject: [PATCH] Env: Add string/number conversion functions --- src/env/functions/convert.cpp | 90 ++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/src/env/functions/convert.cpp b/src/env/functions/convert.cpp index 697e286..9fc5aad 100644 --- a/src/env/functions/convert.cpp +++ b/src/env/functions/convert.cpp @@ -4,6 +4,9 @@ * SPDX-License-Identifier: MIT */ +#include // std::from_chars, std::to_chars +#include // std::errc + #include "ast.h" #include "env/macro.h" #include "util.h" @@ -12,6 +15,79 @@ namespace blaze { void Environment::loadConvert() { + // (number-to-string 123) -> "123" + ADD_FUNCTION( + "number-to-string", + { + CHECK_ARG_COUNT_IS("number-to-string", SIZE(), 1); + + VALUE_CAST(number, Number, (*begin)); + + char result[32]; + auto conversion = std::to_chars(result, + result + sizeof(result), + number->number()); + if (conversion.ec != std::errc()) { + return makePtr(Constant::Nil); + } + + return makePtr(std::string(result, conversion.ptr - result)); + }); + + // (string-to-char "123") -> 49 + ADD_FUNCTION( + "string-to-char", + { + CHECK_ARG_COUNT_IS("string-to-char", SIZE(), 1); + + VALUE_CAST(string_value, String, (*begin)); + std::string data = string_value->data(); + + return makePtr(data.c_str()[0]); + }); + + // (string-to-number "123") -> 123 + ADD_FUNCTION( + "string-to-number", + { + CHECK_ARG_COUNT_IS("string-to-number", SIZE(), 1); + + VALUE_CAST(string_value, String, (*begin)); + std::string data = string_value->data(); + + int64_t result; + auto conversion = std::from_chars(data.c_str(), + data.c_str() + data.size(), + result); + if (conversion.ec != std::errc()) { + return makePtr(Constant::Nil); + } + + return makePtr(result); + }); + +#define STRING_TO_COLLECTION(name, type) \ + { \ + CHECK_ARG_COUNT_IS(name, SIZE(), 1); \ + \ + VALUE_CAST(string_value, String, (*begin)); \ + std::string data = string_value->data(); \ + \ + ValueVector nodes(data.size()); \ + for (size_t i = 0; i < data.size(); ++i) { \ + nodes.at(i) = makePtr(data.c_str()[i]); \ + } \ + \ + return makePtr(nodes); \ + } + + // (string-to-list "foo") -> (102 111 111) + // (string-to-vector "foo") -> [102 111 111] + ADD_FUNCTION("string-to-list", STRING_TO_COLLECTION("string-to-list", List)); + ADD_FUNCTION("string-to-vector", STRING_TO_COLLECTION("string-to-vector", Vector)); + + // ------------------------------------- + // (symbol "foo") -> foo ADD_FUNCTION( "symbol", @@ -22,9 +98,9 @@ void Environment::loadConvert() return *begin; } - VALUE_CAST(stringValue, String, (*begin)); + VALUE_CAST(string_value, String, (*begin)); - return makePtr(stringValue->data()); + return makePtr(string_value->data()); }); // (keyword "foo") -> :foo @@ -32,20 +108,20 @@ void Environment::loadConvert() ADD_FUNCTION( "keyword", { - CHECK_ARG_COUNT_IS("symbol", SIZE(), 1); + CHECK_ARG_COUNT_IS("keyword", SIZE(), 1); if (is(begin->get())) { return *begin; } else if (is(begin->get())) { - VALUE_CAST(numberValue, Number, (*begin)); + VALUE_CAST(number_value, Number, (*begin)); - return makePtr(numberValue->number()); + return makePtr(number_value->number()); } - VALUE_CAST(stringValue, String, (*begin)); + VALUE_CAST(string_value, String, (*begin)); - return makePtr(stringValue->data()); + return makePtr(string_value->data()); }); }