Skip to content

Commit

Permalink
Update interpreter
Browse files Browse the repository at this point in the history
  • Loading branch information
HenryAWE committed May 27, 2024
1 parent b0ad7c5 commit 4a8cf55
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 60 deletions.
18 changes: 0 additions & 18 deletions example/playground/ipapilio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,23 +139,6 @@ void ipapilio::addf()
{
std::string str_val = detail::input(std::cin, "addf");

#ifndef PAPILIO_STDLIB_LIBCPP
long double val;
auto result = std::from_chars(
std::to_address(str_val.begin()),
std::to_address(str_val.end()),
val
);
if(result.ec != std::errc())
{
papilio::println(
papilio::fg(papilio::color::red) | papilio::style::bold,
"Bad value: {}",
std::make_error_code(result.ec).message()
);
return;
}
#else
float val;
try
{
Expand All @@ -180,7 +163,6 @@ void ipapilio::addf()
);
return;
}
#endif

m_args.push(val);
papilio::println(
Expand Down
43 changes: 8 additions & 35 deletions include/papilio/script/interpreter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
#include <charconv>
#include "../core.hpp"
#include "../access.hpp"
#ifdef PAPILIO_STDLIB_LIBCPP
// from_chars of libc++ is broken, use stringstream as a fallback.
# include <sstream>
#endif

namespace papilio::script
{
Expand Down Expand Up @@ -41,11 +37,7 @@ namespace detail
class variable_base
{
public:
#ifndef PAPILIO_PLATFORM_EMSCRIPTEN
using float_type = long double;
#else
using float_type = float;
#endif

protected:
[[noreturn]]
Expand Down Expand Up @@ -105,7 +97,7 @@ class basic_variable : public detail::variable_base
}
else if constexpr(floating_point<arg_type>)
{
return variant_type(in_place_type<float_type>, arg);
return variant_type(in_place_type<float_type>, static_cast<float_type>(arg));
}
else if constexpr(basic_string_like<arg_type, CharT>)
{
Expand Down Expand Up @@ -144,7 +136,7 @@ class basic_variable : public detail::variable_base

template <std::floating_point T>
basic_variable(T f)
: m_var(std::in_place_type<float_type>, f)
: m_var(std::in_place_type<float_type>, static_cast<float_type>(f))
{}

basic_variable(string_container_type str)
Expand Down Expand Up @@ -517,6 +509,8 @@ PAPILIO_EXPORT class script_base
static bool is_field_name_end_ch(char32_t ch) noexcept;

static char32_t get_esc_ch(char32_t ch) noexcept;

static float chars_to_float(const char* start, const char* stop);
};

PAPILIO_EXPORT template <typename CharT, bool Debug = false>
Expand Down Expand Up @@ -721,41 +715,20 @@ class basic_interpreter_base : public script_base
return std::make_pair(value, start);
}

template <std::floating_point T>
static T conv_float_impl(const char* start, const char* stop)
{
T val = static_cast<T>(0);

#ifndef PAPILIO_STDLIB_LIBCPP
std::from_chars(start, stop, val);
return val;

#else
// from_chars of libc++ is broken, use stringstream as a fallback.
std::stringstream ss(std::string(start, stop));

ss.imbue(std::locale::classic());
ss >> val;

return val;
#endif
}

// Converts [start, stop) to a floating point
template <std::floating_point T>
static T conv_float(iterator start, iterator stop)
static float conv_float(iterator start, iterator stop)
{
if constexpr(char8_like<char_type>)
{
return conv_float_impl<T>(
return chars_to_float(
std::bit_cast<const char*>(start.base()),
std::bit_cast<const char*>(stop.base())
);
}
else
{
std::string tmp = string_ref_type(start, stop).to_string();
return conv_float_impl<T>(
return chars_to_float(
std::to_address(tmp.begin()),
std::to_address(tmp.end())
);
Expand Down Expand Up @@ -1244,7 +1217,7 @@ class basic_interpreter :
iterator float_end = std::find_if_not(int_end, stop, utf::is_digit);

using float_type = typename variable_type::float_type;
float_type val = my_base::template conv_float<float_type>(
float_type val = my_base::conv_float(
start, float_end
);

Expand Down
51 changes: 47 additions & 4 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
#include <papilio/script/interpreter.hpp>
#include <papilio/detail/prefix.hpp>
#ifdef PAPILIO_STDLIB_LIBCPP
// from_chars of libc++ is broken, use stringstream as a fallback.
# include <sstream>
# define PAPILIO_ENABLE_LIBCPP_CHARCONV_WORKAROUND 1
#endif

namespace papilio::script
{
bad_variable_access::~bad_variable_access() = default;

invalid_conversion::~invalid_conversion() = default;

static const char* to_cstr(script_error_code ec) noexcept
static std::string_view script_ec_to_sv(script_error_code ec) noexcept
{
using namespace std::literals;
using enum script_error_code;

#define PAPILIO_SCRIPT_ERR(code, msg) \
case code: return msg
case code: return msg##sv

switch(ec)
{
Expand All @@ -33,12 +39,12 @@ static const char* to_cstr(script_error_code ec) noexcept

std::string to_string(script_error_code ec)
{
return to_cstr(ec);
return std::string(script_ec_to_sv(ec));
}

std::ostream& operator<<(std::ostream& os, script_error_code ec)
{
os << to_cstr(ec);
os << script_ec_to_sv(ec);
return os;
}

Expand Down Expand Up @@ -114,6 +120,43 @@ char32_t script_base::get_esc_ch(char32_t ch) noexcept
return ch;
}
}

float script_base::chars_to_float(const char* start, const char* stop)
{
#ifndef PAPILIO_ENABLE_LIBCPP_CHARCONV_WORKAROUND
// Ordinary implementation using <charconv>

float val;
auto result = std::from_chars(
start, stop, val, std::chars_format::fixed
);
if(result.ec != std::errc())
{
throw std::runtime_error("invalid float");
}

return val;

#else
// PAPILIO_ENABLE_LIBCPP_CHARCONV_WORKAROUND is defined
// Workaround for libc++ using <sstream>

std::stringstream ss;
ss.imbue(std::locale::classic());
ss.write(start, stop - start);

float val;
ss >> val;

if(!ss.good())
{
throw std::runtime_error("invalid float");
}

return val;

#endif
}
} // namespace papilio::script

#include <papilio/detail/suffix.hpp>
6 changes: 3 additions & 3 deletions test/test_script_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ TEST(variable, equal)
{
variable var1 = 1.0f;
variable var2 = 1.1f;
EXPECT_TRUE(var1.equal(var2, 0.11L));
EXPECT_TRUE(var1.equal(var2, 0.11f));
}

{
Expand Down Expand Up @@ -203,8 +203,8 @@ TEST(variable, access)
variable var = 10.0f;
ASSERT_TRUE(var.get_if<variable::float_type>());

EXPECT_DOUBLE_EQ(static_cast<double>(*var.get_if<variable::float_type>()), 10.0);
EXPECT_DOUBLE_EQ(static_cast<double>(var.get<variable::float_type>()), 10.0);
EXPECT_FLOAT_EQ(*var.get_if<float>(), 10.0f);
EXPECT_FLOAT_EQ(var.get<float>(), 10.0f);

EXPECT_THROW((void)var.get<bool>(), bad_variable_access);

Expand Down

0 comments on commit 4a8cf55

Please sign in to comment.