Compare std::wstring type and represent of wstring literal


#1

Hello!

As I am a korean, to use the wchar_t and std::wstring type is very important.

I want to write ChaiScript code using std::wstring type like below c++ code.

#include <iostream>

int testfunc(std::wstring s, std::wstring t)
{
    if(s==t)
    {
        std::cout << "1" << std::endl;
    }

    if(s[1]==t[1])
    {
        std::cout << "2" << std::endl;
    }

    if(s==L"aaaa")
    {
        std::cout << "3" << std::endl;
    }

    if(s[1]==L'b')
    {
        std::cout << "4" << std::endl;
    }

    return 5;
}

int main()
{
    std::cout << testfunc(std::wstring(L"abcd"), std::wstring(L"abbb"));

    return 0;
}

D:\TestWork\test_chaiscript>t6
2
4
5

To compare the instances of std::wstring type is good.

#include <iostream>
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>

int main()
{
    chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());

    chai.add(chaiscript::bootstrap::standard_library::string_type<std::wstring>("wstring"));

    std::cout << chai.eval<std::function<int (std::wstring, std::wstring)> >(
        "fun(s, t){"
        "   if(s==t){"
        "       print(\"1\");"
        "   }"
        "   return 3;"
        "}"
    )(std::wstring(L"abcd"), std::wstring(L"abaa"));

    return 0;
}

D:\TestWork\test_chaiscript>t5
3

[Problem 1]
To compare the instances of wchar_t type doesn’t work.

Do the compare operator method must be added?

        "   if(s[1]==t[1]){"
        "       print(\"2\");"
        "   }"

D:\TestWork\test_chaiscript>t5
terminate called after throwing an instance of 'chaiscript::exception::eval_error'
  what():  Error: "Error with numeric operator calling: =="

[Problem 2]
To compare the instance of std::wstring type with the literal of string type doesn’t work.
I cannot input the literal of wstring type.

Is it possible to input the literal of wstring type in ChaiScript?

        "   if(s==\"aaaa\"){"
        "       print(\"2\");"
        "   }"

D:\TestWork\test_chaiscript>t5
terminate called after throwing an instance of 'chaiscript::exception::eval_error'
  what():  Error: "Can not find appropriate '==' operator." With parameters: (wstring, const string)

[Problem 3]
To compare the instance of wchar_t type with the literal of wchar_t type doesn’t work.
I cannot input the literal of wchat_t type.

Is it possible to input the literal of wchat_t type in ChaiScript?

        "   if(s[1]=='b'){"
        "       print(\"2\");"
        "   }"

D:\TestWork\test_chaiscript>t5
terminate called after throwing an instance of 'chaiscript::exception::eval_error'
  what():  Error: "Error with numeric operator calling: =="

#2

Below is the sam contents in stackoverflow.
stackoverflow.com/questions/30838757/

Thanks for your reply.
But my problem is not cleared.

chai.add(chaiscript::fun<bool (wchar_t, wchar_t)>([](wchar_t lhs, wchar_t rhs) { return lhs == rhs; }), “==”);

The compile error occurred in above code. (mingw-w64 5.1.0, vc2013)

D:\TestWork\test_chaiscript>g++ t5.cpp -std=c++14 -O2 -Os -Wall -mthrea
ds -o t5.exe -DWIN32 -D_WIN32 -DUNICODE -D_UNICODE -Id:\myprj\chaiscript_git\include -static-libstdc++ -static-libgcc -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic
t5.cpp: In function 'int main()':
t5.cpp:17:103: error: no matching function for call to 'fun(main()::lambda(wchar_t, wchar_t)>)'
  chai.add(chaiscript::fun<bool (wchar_t, wchar_t)>([](wchar_t lhs, wchar_t rhs) { return lhs == rhs; }), "==");
                                                                                                       ^

Below is modified code by me but same runtime error occurred.

chai.add(chaiscript::fun<std::function<bool (wchar_t, wchar_t)> >([](wchar_t lhs, wchar_t rhs)->bool { return lhs == rhs; }), "==");
//chai.add(chaiscript::user_type<wchar_t>(), "wchar_t");

std::cout << chai.eval<std::function<int (std::wstring, std::wstring)> >(
    "    if(s[1]==t[1]){"
    "        print(\"2\");"
    "    }"
    "     return 3;"
    "}"
)(std::wstring(L"abcd"), std::wstring(L"abaa"));

D:\TestWork\test_chaiscript>t5.exe
terminate called after throwing an instance of 'chaiscript::exception::eval_error'
  what():  Error: "Error with numeric operator calling: =="

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.


std::cout << chai.eval<std::function<int (wchar_t a, wchar_t b)> >(
    "fun(a, b){"
    "    if(a==b){"
    "        print(\"2\");"
    "    }"
    "     return 3;"
    "}"
)(wchar_t(L'a'), wchar_t(L'a'));

D:\TestWork\test_chaiscript>t5.exe
terminate called after throwing an instance of 'chaiscript::exception::eval_error'
  what():  Error: "Error with numeric operator calling: =="

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

#3

I think that the native support wchar_t need in chaiscript.

"Error with numeric operator calling: " exception is generated in chaiscript_eval.hpp.

If the type of variable is arithmetic, Boxed_Number::do_oper() is called.

// chaiscript_eval.hpp, line 98
if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic())
{
  // If it's an arithmetic operation we want to short circuit dispatch
  try{
    return Boxed_Number::do_oper(t_oper, t_lhs, t_rhs);
  } catch (const chaiscript::exception::arithmetic_error &) {
    throw;
  } catch (...) {
    throw exception::eval_error("Error with numeric operator calling: " + t_oper_string);
  }
} else {

It seems to use std::is_arithmetic to determine whether arithmetic type or not.

// type_info.hpp, 133 line
struct Get_Type_Info
{
    typedef T type;

     static Type_Info get()
    {
      return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, std::is_reference<T>::value, std::is_pointer<T>::value, 
          std::is_void<T>::value,
          std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
          &typeid(T), 
          &typeid(typename Bare_Type<T>::type));
    }
};

wchat_t is the arithmetic type.

std::cout << std::is_arithmetic<wchar_t>::value << std::endl;
std::cout << std::is_arithmetic<std::string>::value << std::endl;

D:\TestWork\test_chaiscript>t5.exe
1
0

If the type is arithmetic, oper() method for Boxed_Value is called.
But, wchar_t type is not supported in oper() method.

// boxed_number.hpp, 295 line
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
{
  const Type_Info &inp_ = t_lhs.get_type_info();

  if (inp_ == typeid(int)) {
    return oper_rhs<int>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(double)) {
    return oper_rhs<double>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(long double)) {
    return oper_rhs<long double>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(float)) {
    return oper_rhs<float>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(char)) {
    return oper_rhs<char>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(unsigned int)) {
    return oper_rhs<unsigned int>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(long)) {
    return oper_rhs<long>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(unsigned long)) {
    return oper_rhs<unsigned long>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::int8_t)) {
    return oper_rhs<std::int8_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::int16_t)) {
    return oper_rhs<std::int16_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::int32_t)) {
    return oper_rhs<std::int32_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::int64_t)) {
    return oper_rhs<std::int64_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::uint8_t)) {
    return oper_rhs<std::uint8_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::uint16_t)) {
    return oper_rhs<std::uint16_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::uint32_t)) {
    return oper_rhs<std::uint32_t>(t_oper, t_lhs, t_rhs);
  } else if (inp_ == typeid(std::uint64_t)) {
    return oper_rhs<std::uint64_t>(t_oper, t_lhs, t_rhs);
  } else  {
    throw chaiscript::detail::exception::bad_any_cast();
  }
}

I add the code to support wchar_t type like below in typeid(char) used place.

} else if (inp_ == typeid(char)) {
    return go<LHS, char>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(wchar_t)) {
    return go<LHS, wchar_t>(t_oper, t_lhs, t_rhs);
} else if (inp_ == typeid(unsigned int)) {

My test code works well.

std::cout << chai.eval<std::function<int (wchar_t a, wchar_t b)> >(
    "fun(a, b){"
    "    if(a==b){"
    "        print(\"2\");"
    "    }"
    "     return 3;"
    "}"
)(wchar_t(L'a'), wchar_t(L'a'));

D:\prj\secu\TestWork\test_chaiscript>t5.exe
2
3

#4

Yes, you are correct. It’s because it’s being detected as an arithmetic type that the operator== support is failing to be executed.

I spent some time 2 days ago working on this when I saw your second post on stackoverflow (please remember to accept answer on stackoverflow that answer your questions). The problem that I have write now is that adding proper support more built in native support for char types is adding significantly to the compile time. I’ll need to spend some more time working on it.

At the moment the only thing I can suggest is to use utf8 instead of 16bit wide characters.

utf8 should be able to give you almost everything you need.

-Jason


#5

I just committed to the develop branch intrinsic support for the various wide character types. wchar_t char16_t and char32_t.

They should work as expected now. No need to add the == operator, but you will still need to add the string_type<std::wstring>() that you are already using.


#6

Thank you!!!
My test code works well.


#7

Great, I’m glad to hear it.

It will take some work to get ChaiScript to fully support unicode. It won’t be terribly difficult, but it will add to the compile-time overhead, so I don’t know when full built-in support will happen.

But I’m glad you are able to move forward with your project.