Skip to content

Commit 73355bb

Browse files
committed
feat(format builtin): support integer format specifiers when the given number can be represented as one
1 parent 23fb22e commit 73355bb

25 files changed

Lines changed: 130 additions & 15 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- `:l` / `:nl` to use `\n` as a separator,
1212
- `:?s` to format as an escaped quoted string,
1313
- `:s` to format as a quoted string
14+
- `format` can use format specifiers for integers: `b`, `#b`, `B`, `#B`, `c`, `d`, `o`, `x`, `#x`, `X`, and `#X` if the argument is an integer
1415

1516
### Changed
1617

src/arkreactor/Builtins/String.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include <Ark/Builtins/Builtins.hpp>
22

33
#include <utility>
4-
#include <string_view>
4+
#include <cmath>
55
#include <utf8.hpp>
66
#include <fmt/args.h>
77
#include <fmt/base.h>
@@ -17,6 +17,7 @@ struct value_wrapper
1717
{
1818
const Ark::Value& value;
1919
Ark::VM* vm_ptr;
20+
bool nested = false;
2021
};
2122

2223
template <>
@@ -27,6 +28,7 @@ struct fmt::formatter<value_wrapper>
2728
fmt::basic_string_view<char> closing_bracket_ = fmt::detail::string_literal<char, ']'> {};
2829
fmt::basic_string_view<char> separator_ = fmt::detail::string_literal<char, ' '> {};
2930
bool is_debug = false;
31+
bool is_literal_str = false;
3032
fmt::formatter<std::string> underlying_;
3133

3234
public:
@@ -89,6 +91,7 @@ struct fmt::formatter<value_wrapper>
8991
set_brackets(fmt::detail::string_literal<char, '"'> {},
9092
fmt::detail::string_literal<char, '"'> {});
9193
set_separator({});
94+
is_literal_str = true;
9295
}
9396
++it;
9497
return it;
@@ -133,18 +136,33 @@ struct fmt::formatter<value_wrapper>
133136
if (is_debug)
134137
return write_debug_string(out, it, end, value.vm_ptr);
135138

136-
out = fmt::detail::copy<char>(opening_bracket_, out);
139+
if ((is_literal_str && !value.nested) || !is_literal_str)
140+
out = fmt::detail::copy<char>(opening_bracket_, out);
141+
137142
for (int i = 0; it != end; ++it)
138143
{
139144
if (i > 0)
140145
out = fmt::detail::copy<char>(separator_, out);
141146
ctx.advance_to(out);
147+
142148
auto&& item = *it;
143-
auto formatted = item.toString(*value.vm_ptr);
144-
out = underlying_.format(formatted, ctx);
149+
if (item.valueType() == Ark::ValueType::List)
150+
{
151+
// if :s, do not put surrounding "" here
152+
format({ item, value.vm_ptr, /* nested= */ true }, ctx);
153+
}
154+
else
155+
{
156+
std::string formatted = item.toString(*value.vm_ptr);
157+
out = underlying_.format(formatted, ctx);
158+
}
159+
145160
++i;
146161
}
147-
out = detail::copy<char>(closing_bracket_, out);
162+
163+
if ((is_literal_str && !value.nested) || !is_literal_str)
164+
out = detail::copy<char>(closing_bracket_, out);
165+
148166
return out;
149167
}
150168
};
@@ -194,7 +212,13 @@ namespace Ark::internal::Builtins::String
194212
if (it->valueType() == ValueType::String)
195213
store.push_back(it->stringRef());
196214
else if (it->valueType() == ValueType::Number)
197-
store.push_back(it->number());
215+
{
216+
double int_part;
217+
if (std::modf(it->number(), &int_part) == 0.0)
218+
store.push_back(static_cast<long>(it->number()));
219+
else
220+
store.push_back(it->number());
221+
}
198222
else if (it->valueType() == ValueType::Nil)
199223
store.push_back("nil");
200224
else if (it->valueType() == ValueType::True)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(print (format "{:b}" 65.1))
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
format: can not format "{:b}" (1 argument provided) because of invalid format specifier
2+
3+
In file tests/unittests/resources/DiagnosticsSuite/runtime/format_double_b.ark:1
4+
1 | (print (format "{:b}" 65.1))
5+
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
6+
2 |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(print (format "{:c}" 65.1))
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
format: can not format "{:c}" (1 argument provided) because of invalid format specifier
2+
3+
In file tests/unittests/resources/DiagnosticsSuite/runtime/format_double_c.ark:1
4+
1 | (print (format "{:c}" 65.1))
5+
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
6+
2 |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(print (format "{:d}" 65.1))
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
format: can not format "{:d}" (1 argument provided) because of invalid format specifier
2+
3+
In file tests/unittests/resources/DiagnosticsSuite/runtime/format_double_d.ark:1
4+
1 | (print (format "{:d}" 65.1))
5+
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
6+
2 |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(print (format "{:#b}" 65.1))
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
format: can not format "{:#b}" (1 argument provided) because of invalid format specifier
2+
3+
In file tests/unittests/resources/DiagnosticsSuite/runtime/format_double_hashtag_b.ark:1
4+
1 | (print (format "{:#b}" 65.1))
5+
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
6+
2 |

0 commit comments

Comments
 (0)