Author Topic: Sqrat  (Read 16452 times)

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Sqrat
« on: June 27, 2012, 02:33:21 pm »
Playing with Sqrat for a while, I've found out that it is not alltogether as nice as easy as it looked at first sight, at least not for us (or maybe I'm really just too stupid).

First, it is not trivial to bind enum values, of which we have quite a number bound. You need to add each enum name with its proper value to the constant table. Not all values are contiguous either, and not all are in our own headers.

Basically, as far as enum values go, we are left with the following choices:
  • maintain the enum and its script binding separately
  • use X-Macros

The first solution is error prone and a maintenance nightmare, the second solution is moderately ugly and doesn't look like C++. Also it won't work for the wxWidgets enums that we bind (will have to do these by hand either way).

Also, giving X-Macros a try (which kind of worked, too), I suddenly realized that Code::Blocks uses Unicode strings, so when a script is called, its identifiers should obviously be provided as wchar_t.

Adding a L wrapper generated "note:   no known conversion for argument 1 from 'const wchar_t [4]' to 'const SQChar* {aka const char*}'".
Oh oh, looks like I forgot compiling with -DSQUNICODE.

Now,  compiling with -DSQUNICODE, it turns out that neither Squirrel nor Sqrat work properly in Unicode mode... Squirrel has a special codepath for MSVC to behave properly, and typedefs wchar_t on every other compiler (no, I'm not joking, look at lines 116-125 in squirrel.h), and Sqrat calls sq_throwerror with ordinary C character strings, regardless of ANSI/Unicode mode (with -DSQUNICODE, the function expects  const wchar_t*). Both issues break the build.

Ideas? Seriously, I must be making a mistake here, this cannot be  ;D
« Last Edit: June 27, 2012, 02:36:37 pm by thomas »
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Sqrat
« Reply #1 on: June 27, 2012, 02:48:26 pm »
Note:
There seems to be a similar issue with constants in SQPlus. At least that is how I interprete the obscure macros used all over the place, which bind constants not as constants, but rather as macro-generated getter callback functions which return a constant at runtime.

This might be a third solution for the binding issue in Sqrat, though it kind of shares the worst of both worlds. It's ugly and obscure, and it has runtime overhead.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9723
Re: Sqrat
« Reply #2 on: June 27, 2012, 03:27:07 pm »
Well looking at how we did things in the Squirrel we use I see in squirrel.h:

1.)
Code
// C::B patch: Comment out Unicode stuff
//#ifdef _UNICODE
//#define SQUNICODE
//#endif

...and 2.)
Code
// C::B patch: Comment out typedef
//typedef unsigned short wchar_t;

What happens if you do the same in Squirrel 3.x.x?

(We also don't compile with SQUNICODE btw...)
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9723
Re: Sqrat
« Reply #3 on: June 27, 2012, 03:53:02 pm »
Well I just tried with your example, and if I exchange lines 109-122 with:

Code
// C::B patch: Unicode stuff only if not omitted
#if !defined(SQUNICODE) && defined(_UNICODE) && !defined(NO_SQUNICODE)
  #define SQUNICODE
#endif

#ifdef SQUNICODE
#if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8
  #if !defined(_NATIVE_WCHAR_T_DEFINED) // this is if the compiler considers wchar_t as native type
    #define wchar_t unsigned short
  #endif
// C::B patch: typedef only for non-GCC
#elif !defined(__GNUC__) // wchar_t is already defined in GCC
  typedef unsigned short wchar_t;
#endif

...and then within your sqtest sample:

Code
static void printfunc(HSQUIRRELVM v,const SQChar *s,...)
{
va_list vl;
va_start(vl, s);
#ifdef SQUNICODE
vwprintf(s, vl);
#else
vprintf(s, vl);
#endif
va_end(vl);
}

...and all references in sqRat to sq_throwerror with something like:
Code
        if(SQ_FAILED(sq_get(vm, 1))) { // Lookup the proper overload
            return sq_throwerror(vm, _SC("No overload matching this argument list found"));// How to best appropriately error?
        }
...it works fine here, when compiling with SQUNICODE enabled.

It seems sqrat was never tried with unicode, too - but these simple changes should do it.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Sqrat
« Reply #4 on: June 27, 2012, 04:14:19 pm »
Quote
Code
// C::B patch: Comment out typedef
//typedef unsigned short wchar_t;
Well, sure enough, this is what I did, and this certainly works... it's just bleh. "Vendors Are Bad For Security" as Ben Laurie put it (though I'm sure this patch is kind of harmless).

Quote
(We also don't compile with SQUNICODE btw...)
Hum... how does a script work with non-ANSI characters then? Without this, Squirrel strings (and scripts) are, according to the docs "plain 8-bits ASCII characters".  The script loading functions in sqstdlib, too, only support UTF-8 and UTF-16 with SQUNICODE. This would mean that our scripted wizards and debugger scripts only work "by accident" because they're not localized :S

Well I just tried with your example, and if I exchange ...
Yes, yes, did all that too...

Quote
with something like:
return sq_throwerror(vm, _SC("No overload matching this argument list found"));
That is exactly the problem. There are two occurrences that do not have the _SC.
Of course if I patch them in manually, it works. But again... bleh.

Let me maybe reword the Unicode question: Do we want Unicode? (Apparently so far we don't need it at all?)
Do we want to locally patch both packages so they work, or rather ... something else?

And about the enum issue... how dirty do we want to get, really... I'm not sure.
« Last Edit: June 27, 2012, 04:18:54 pm by thomas »
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Sqrat
« Reply #5 on: June 27, 2012, 04:22:06 pm »
Interesting... I'm just now browsing the Sqrat SVN repo, and it turns out that the missing _SCs that I complain about are in HEAD. So apparently just my local copy is screwed up, or outdated, or whatever.

So that's that. Guess we can live with commenting out one line in Squirrel.h.

Remains to be decided what to do with enum.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: Sqrat
« Reply #6 on: June 27, 2012, 04:41:51 pm »
One question: Will swtiching from SqPlus to Scrat break scripts? I was looking at it and it looked like so.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9723
Re: Sqrat
« Reply #7 on: June 27, 2012, 04:45:12 pm »
So that's that. Guess we can live with commenting out one line in Squirrel.h.
OK - that's nice. :-)

Remains to be decided what to do with enum.
Can you provide a test case of all three solutions? For the enums: What do we do currently with SQPlus (I cannot have a look atm...)?
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Sqrat
« Reply #8 on: June 27, 2012, 07:24:32 pm »
One question: Will swtiching from SqPlus to Scrat break scripts? I was looking at it and it looked like so.
I wouldn't know why it should break any script. They both register classes or functions that scripts can call. If we do the registering 1:1, then all should work the same.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: Sqrat
« Reply #9 on: June 27, 2012, 07:37:51 pm »
I'm not really sure, the demo code showed was different, but my understanding of squirrel is pretty weak.

There was difference in how the code looked and there was the instancing operator used '<-' and I think when using scrat it is mandatory.
But I may be wrong, of course.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: Sqrat
« Reply #10 on: June 27, 2012, 07:41:41 pm »
Can you provide a test case of all three solutions? For the enums: What do we do currently with SQPlus (I cannot have a look atm...)?
What we currently do with SQPlus is a macro (one invocation per enum type) that expands to code like this:
Code
namespace SqPlus \
{ \
    inline void Push(HSQUIRRELVM v,T value) { sq_pushinteger(v,value); } \
    inline bool Match(TypeWrapper<T>, HSQUIRRELVM v, int idx) { return sq_gettype(v,idx) == OT_INTEGER; } \
    inline T Get(TypeWrapper<T>,HSQUIRRELVM v,int idx) { SQInteger i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return (T)i; } \
}
Which, if I understand correctly, provides a kind of "getter function" for the compile-time constant, which I guess is evaluated at runtime by the SQPlus layer... though I don't quite get how it matches enum names...

The "maintain separately " solution would look something like this:
Code
// File printing_types.h
enum PrintColourMode
{
    pcmBlackAndWhite,
    pcmColourOnWhite,
    pcmInvertColours,
    pcmAsIs
};


// File bindings/sc_base_types.h
Sqrat::ConstTable().Enum(_SC("PrintColourMode"), Sqrat::Enumeration() .Const(_SC("pcmBlackAndWhite"), pcmBlackAndWhite)
Sqrat::ConstTable().Enum(_SC("PrintColourMode"), Sqrat::Enumeration() .Const(_SC("pcmColourOnWhite"), pcmColourOnWhite)
Sqrat::ConstTable().Enum(_SC("PrintColourMode"), Sqrat::Enumeration() .Const(_SC("pcmInvertColours"), pcmInvertColours)
Sqrat::ConstTable().Enum(_SC("PrintColourMode"), Sqrat::Enumeration() .Const(_SC("pcmAsIs"), pcmAsIs)
If someone adds an enumeration on one end and forgets the other, it all crashes and burns. Also, you have to do this once for every single enum value in every single enum type.


... and the X-Macro solution would look something like this:
Code
// File print_colour_mode.h
X(pcmBlackAndWhite, = 5)
X(pcmColourOnWhite, )
X(pcmInvertColours, )
X(pcmAsIs,          )


// File printing_types.h
#define END        END2(__LINE__, __COUNTER__) /* need this to get rid of the last comma */
#define END2(a,b)  END3(a,b)
#define END3(a,b)  _##a##b##_

#define X(a, b) a b,
enum PrintColourMode
{
#include "print_colour_mode.h"
END
};
#undef X


// File sc_base_types.h
#define X(a, b) .Const(_SC(#a), a)
void bind_enums()
{
Sqrat::ConstTable().Enum
(
_SC("PrintColourMode"), Sqrat::Enumeration()
#include "print_colour_mode.h"
);
}
#undef X
This is not really C++ any more, but surprisingly it works...

The code would be somewhat less ugly if enums always started at zero and were contiguous ... but alas, life is not fair...
« Last Edit: June 27, 2012, 07:46:36 pm by thomas »
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9723
Re: Sqrat
« Reply #11 on: June 29, 2012, 10:56:08 am »
[...] all the options [...]
Well to me all look acceptable to me. ::)
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: https://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: https://wiki.codeblocks.org/index.php?title=FAQ