Env: Add string/number conversion functions
This commit is contained in:
Vendored
+83
-7
@@ -4,6 +4,9 @@
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <charconv> // std::from_chars, std::to_chars
|
||||
#include <system_error> // 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>(Constant::Nil);
|
||||
}
|
||||
|
||||
return makePtr<String>(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<Number>(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>(Constant::Nil);
|
||||
}
|
||||
|
||||
return makePtr<Number>(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<Number>(data.c_str()[i]); \
|
||||
} \
|
||||
\
|
||||
return makePtr<type>(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<Symbol>(stringValue->data());
|
||||
return makePtr<Symbol>(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<Keyword>(begin->get())) {
|
||||
return *begin;
|
||||
}
|
||||
else if (is<Number>(begin->get())) {
|
||||
VALUE_CAST(numberValue, Number, (*begin));
|
||||
VALUE_CAST(number_value, Number, (*begin));
|
||||
|
||||
return makePtr<Keyword>(numberValue->number());
|
||||
return makePtr<Keyword>(number_value->number());
|
||||
}
|
||||
|
||||
VALUE_CAST(stringValue, String, (*begin));
|
||||
VALUE_CAST(string_value, String, (*begin));
|
||||
|
||||
return makePtr<Keyword>(stringValue->data());
|
||||
return makePtr<Keyword>(string_value->data());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user