Env: Add string/number conversion functions
This commit is contained in:
Vendored
+83
-7
@@ -4,6 +4,9 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <charconv> // std::from_chars, std::to_chars
|
||||||
|
#include <system_error> // std::errc
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "env/macro.h"
|
#include "env/macro.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -12,6 +15,79 @@ namespace blaze {
|
|||||||
|
|
||||||
void Environment::loadConvert()
|
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
|
// (symbol "foo") -> foo
|
||||||
ADD_FUNCTION(
|
ADD_FUNCTION(
|
||||||
"symbol",
|
"symbol",
|
||||||
@@ -22,9 +98,9 @@ void Environment::loadConvert()
|
|||||||
return *begin;
|
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
|
// (keyword "foo") -> :foo
|
||||||
@@ -32,20 +108,20 @@ void Environment::loadConvert()
|
|||||||
ADD_FUNCTION(
|
ADD_FUNCTION(
|
||||||
"keyword",
|
"keyword",
|
||||||
{
|
{
|
||||||
CHECK_ARG_COUNT_IS("symbol", SIZE(), 1);
|
CHECK_ARG_COUNT_IS("keyword", SIZE(), 1);
|
||||||
|
|
||||||
if (is<Keyword>(begin->get())) {
|
if (is<Keyword>(begin->get())) {
|
||||||
return *begin;
|
return *begin;
|
||||||
}
|
}
|
||||||
else if (is<Number>(begin->get())) {
|
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