Beginnings of the "pass everything using a native type wrapper" console code.

- ConsoleValue class is now the base value class.
- ConsoleValueRef is now used to supply function parameters. Values are disposable.
- Script functions return values instead of just strings where possible.
- Variables can be disposable strings
- Bytecode changed

Fix the issues with console method parameters and fields which prevented missions from loading.
This commit is contained in:
James Urquhart 2012-09-23 09:59:48 +01:00
parent 394d87cd54
commit 38c8e52c1d
68 changed files with 1511 additions and 529 deletions

View file

@ -29,15 +29,18 @@
#ifndef _BITSET_H_
#include "core/bitSet.h"
#endif
#ifndef _REFBASE_H_
#include "core/util/refBase.h"
#endif
#include <stdarg.h>
#include "core/util/str.h"
#include "core/util/journal/journaledSignal.h"
class SimObject;
class Namespace;
struct ConsoleFunctionHeader;
class EngineEnumTable;
typedef EngineEnumTable EnumTable;
@ -110,6 +113,163 @@ struct ConsoleLogEntry
};
typedef const char *StringTableEntry;
extern char *typeValueEmpty;
class ConsoleValue
{
public:
enum
{
TypeInternalInt = -4,
TypeInternalFloat = -3,
TypeInternalStackString = -2,
TypeInternalString = -1,
};
S32 type;
public:
// NOTE: This is protected to ensure no one outside
// of this structure is messing with it.
#pragma warning( push )
#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union
// An variable is either a real dynamic type or
// its one exposed from C++ using a data pointer.
//
// We use this nameless union and struct setup
// to optimize the memory usage.
union
{
struct
{
char *sval;
U32 ival; // doubles as strlen when type is TypeInternalString
F32 fval;
U32 bufferLen;
};
struct
{
/// The real data pointer.
void *dataPtr;
/// The enum lookup table for enumerated types.
const EnumTable *enumTable;
};
};
U32 getIntValue();
F32 getFloatValue();
const char *getStringValue();
void setIntValue(U32 val);
void setFloatValue(F32 val);
void setStringValue(const char *value);
void setStackStringValue(const char *value);
void init()
{
ival = 0;
fval = 0;
sval = typeValueEmpty;
bufferLen = 0;
}
void cleanup()
{
if (type <= TypeInternalString &&
sval != typeValueEmpty && type != TypeInternalStackString )
dFree(sval);
sval = typeValueEmpty;
type = ConsoleValue::TypeInternalString;
ival = 0;
fval = 0;
bufferLen = 0;
}
};
// Proxy class for console variables
// Can point to existing console variables
// or act like a free floating value
class ConsoleValueRef {
public:
ConsoleValue *value;
const char *stringStackValue;
ConsoleValueRef() : value(0), stringStackValue(0) { ; }
~ConsoleValueRef() { ; }
ConsoleValueRef(const ConsoleValueRef &ref);
ConsoleValueRef(const char *value);
ConsoleValueRef(const String &ref);
ConsoleValueRef(S32 value);
ConsoleValueRef(F32 value);
ConsoleValueRef(F64 value);
const char *getStringValue() { return value ? value->getStringValue() : ""; }
const char *getStringArgValue();
inline S32 getIntValue() { return value ? value->getIntValue() : 0; }
inline F32 getFloatValue() { return value ? value->getFloatValue() : 0.0f; }
//inline F64 getDoubleValue() { return value ? value->getDoubleValue() : 0.0; }
inline operator const char*() { return getStringValue(); }
inline operator String() { return String(getStringValue()); }
inline operator S32() { return getIntValue(); }
inline operator F32() { return getFloatValue(); }
//inline operator F64() { return getDoubleValue(); }
inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStackString : true; }
inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; }
inline bool isFloat() { return value ? value->type == ConsoleValue::TypeInternalFloat : false; }
// Note: operators replace value
ConsoleValueRef& operator=(const ConsoleValueRef &other);
ConsoleValueRef& operator=(const char *newValue);
ConsoleValueRef& operator=(S32 newValue);
ConsoleValueRef& operator=(F32 newValue);
ConsoleValueRef& operator=(F64 newValue);
};
// Transparently converts ConsoleValue[] to const char**
class StringStackWrapper
{
public:
const char **argv;
int argc;
StringStackWrapper(int targc, ConsoleValueRef targv[]);
~StringStackWrapper();
const char* operator[](int idx) { return argv[idx]; }
operator const char**() { return argv; }
int count() { return argc; }
};
// Transparently converts const char** to ConsoleValue
class StringStackConsoleWrapper
{
public:
ConsoleValueRef *argv;
int argc;
StringStackConsoleWrapper(int targc, const char **targv);
~StringStackConsoleWrapper();
ConsoleValueRef& operator[](int idx) { return argv[idx]; }
operator ConsoleValueRef*() { return argv; }
int count() { return argc; }
};
/// @defgroup console_callbacks Scripting Engine Callbacks
///
@ -129,11 +289,11 @@ typedef const char *StringTableEntry;
/// @{
///
typedef const char * (*StringCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef S32 (*IntCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef F32 (*FloatCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef void (*VoidCallback)(SimObject *obj, S32 argc, const char *argv[]); // We have it return a value so things don't break..
typedef bool (*BoolCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef const char * (*StringCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
typedef S32 (*IntCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
typedef F32 (*FloatCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
typedef void (*VoidCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); // We have it return a value so things don't break..
typedef bool (*BoolCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]);
typedef void (*ConsumerCallback)(U32 level, const char *consoleLine);
/// @}
@ -182,7 +342,7 @@ namespace Con
/// 09/12/07 - CAF - 43->44 remove newmsg operator
/// 09/27/07 - RDB - 44->45 Patch from Andreas Kirsch: Added opcode to support correct void return
/// 01/13/09 - TMS - 45->46 Added script assert
DSOVersion = 46,
DSOVersion = 47,
MaxLineLength = 512, ///< Maximum length of a line of console input.
MaxDataTypes = 256 ///< Maximum number of registered data types.
@ -415,6 +575,11 @@ namespace Con
/// @return The string value of the variable or "" if the variable does not exist.
const char* getVariable(const char* name);
/// Retrieve the string value of an object field
/// @param name "object.field" string to query
/// @return The string value of the variable or NULL if no object is specified
const char* getObjectField(const char* name);
/// Same as setVariable(), but for bools.
void setBoolVariable (const char* name,bool var);
@ -565,9 +730,11 @@ namespace Con
/// char* result = execute(2, argv);
/// @endcode
const char *execute(S32 argc, const char* argv[]);
const char *execute(S32 argc, ConsoleValueRef argv[]);
/// @see execute(S32 argc, const char* argv[])
#define ARG const char*
// Note: this can't be ConsoleValueRef& since the compiler will confuse it with SimObject*
#define ARG ConsoleValueRef
const char *executef( ARG);
const char *executef( ARG, ARG);
const char *executef( ARG, ARG, ARG);
@ -580,7 +747,6 @@ namespace Con
const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
#undef ARG
/// Call a Torque Script member function of a SimObject from C/C++ code.
/// @param object Object on which to execute the method call.
/// @param argc Number of elements in the argv parameter (must be >2, see argv)
@ -594,9 +760,10 @@ namespace Con
/// char* result = execute(mysimobject, 3, argv);
/// @endcode
const char *execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly = false);
const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
/// @see execute(SimObject *, S32 argc, const char *argv[])
#define ARG const char*
/// @see execute(SimObject *, S32 argc, ConsoleValueRef argv[])
#define ARG ConsoleValueRef
const char *executef(SimObject *, ARG);
const char *executef(SimObject *, ARG, ARG);
const char *executef(SimObject *, ARG, ARG, ARG);
@ -646,6 +813,8 @@ namespace Con
char* getStringArg( const String& arg );
/// @}
void resetStackFrame();
/// @name Namespaces
/// @{
@ -941,14 +1110,14 @@ struct ConsoleDocFragment
static ConsoleConstructor cfg_ConsoleFunctionGroup_##groupName##_GroupBegin(NULL,#groupName,usage)
# define ConsoleFunction(name,returnType,minArgs,maxArgs,usage1) \
returnType cf_##name(SimObject *, S32, const char **argv); \
returnType cf_##name(SimObject *, S32, ConsoleValueRef *argv); \
ConsoleConstructor cc_##name##_obj(NULL,#name,cf_##name,usage1,minArgs,maxArgs); \
returnType cf_##name(SimObject *, S32 argc, const char **argv)
returnType cf_##name(SimObject *, S32 argc, ConsoleValueRef *argv)
# define ConsoleToolFunction(name,returnType,minArgs,maxArgs,usage1) \
returnType ctf_##name(SimObject *, S32, const char **argv); \
returnType ctf_##name(SimObject *, S32, ConsoleValueRef *argv); \
ConsoleConstructor cc_##name##_obj(NULL,#name,ctf_##name,usage1,minArgs,maxArgs, true); \
returnType ctf_##name(SimObject *, S32 argc, const char **argv)
returnType ctf_##name(SimObject *, S32 argc, ConsoleValueRef *argv)
# define ConsoleFunctionGroupEnd(groupName) \
static ConsoleConstructor cfg_##groupName##_GroupEnd(NULL,#groupName,NULL)
@ -961,22 +1130,22 @@ struct ConsoleDocFragment
static ConsoleConstructor cc_##className##_##groupName##_GroupBegin(#className,#groupName,usage)
# define ConsoleMethod(className,name,returnType,minArgs,maxArgs,usage1) \
inline returnType cm_##className##_##name(className *, S32, const char **argv); \
returnType cm_##className##_##name##_caster(SimObject *object, S32 argc, const char **argv) { \
inline returnType cm_##className##_##name(className *, S32, ConsoleValueRef *argv); \
returnType cm_##className##_##name##_caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \
AssertFatal( dynamic_cast<className*>( object ), "Object passed to " #name " is not a " #className "!" ); \
conmethod_return_##returnType ) cm_##className##_##name(static_cast<className*>(object),argc,argv); \
}; \
ConsoleConstructor cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage1,minArgs,maxArgs); \
inline returnType cm_##className##_##name(className *object, S32 argc, const char **argv)
inline returnType cm_##className##_##name(className *object, S32 argc, ConsoleValueRef *argv)
# define ConsoleStaticMethod(className,name,returnType,minArgs,maxArgs,usage1) \
inline returnType cm_##className##_##name(S32, const char **); \
returnType cm_##className##_##name##_caster(SimObject *object, S32 argc, const char **argv) { \
inline returnType cm_##className##_##name(S32, ConsoleValueRef *); \
returnType cm_##className##_##name##_caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \
conmethod_return_##returnType ) cm_##className##_##name(argc,argv); \
}; \
ConsoleConstructor \
cc_##className##_##name##_obj(#className,#name,cm_##className##_##name##_caster,usage1,minArgs,maxArgs); \
inline returnType cm_##className##_##name(S32 argc, const char **argv)
inline returnType cm_##className##_##name(S32 argc, ConsoleValueRef *argv)
# define ConsoleMethodGroupEnd(className, groupName) \
static ConsoleConstructor cc_##className##_##groupName##_GroupEnd(#className,#groupName,NULL)
@ -999,32 +1168,32 @@ struct ConsoleDocFragment
// These are identical to what's above, we just want to null out the usage strings.
# define ConsoleFunction(name,returnType,minArgs,maxArgs,usage1) \
static returnType c##name(SimObject *, S32, const char **); \
static returnType c##name(SimObject *, S32, ConsoleValueRef*); \
static ConsoleConstructor g##name##obj(NULL,#name,c##name,"",minArgs,maxArgs);\
static returnType c##name(SimObject *, S32 argc, const char **argv)
static returnType c##name(SimObject *, S32 argc, ConsoleValueRef *argv)
# define ConsoleToolFunction(name,returnType,minArgs,maxArgs,usage1) \
static returnType c##name(SimObject *, S32, const char **); \
static returnType c##name(SimObject *, S32, ConsoleValueRef*); \
static ConsoleConstructor g##name##obj(NULL,#name,c##name,"",minArgs,maxArgs, true);\
static returnType c##name(SimObject *, S32 argc, const char **argv)
static returnType c##name(SimObject *, S32 argc, ConsoleValueRef *argv)
# define ConsoleMethod(className,name,returnType,minArgs,maxArgs,usage1) \
static inline returnType c##className##name(className *, S32, const char **argv); \
static returnType c##className##name##caster(SimObject *object, S32 argc, const char **argv) { \
static inline returnType c##className##name(className *, S32, ConsoleValueRef *argv); \
static returnType c##className##name##caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \
conmethod_return_##returnType ) c##className##name(static_cast<className*>(object),argc,argv); \
}; \
static ConsoleConstructor \
className##name##obj(#className,#name,c##className##name##caster,"",minArgs,maxArgs); \
static inline returnType c##className##name(className *object, S32 argc, const char **argv)
static inline returnType c##className##name(className *object, S32 argc, ConsoleValueRef *argv)
# define ConsoleStaticMethod(className,name,returnType,minArgs,maxArgs,usage1) \
static inline returnType c##className##name(S32, const char **); \
static returnType c##className##name##caster(SimObject *object, S32 argc, const char **argv) { \
static inline returnType c##className##name(S32, ConsoleValueRef*); \
static returnType c##className##name##caster(SimObject *object, S32 argc, ConsoleValueRef *argv) { \
conmethod_return_##returnType ) c##className##name(argc,argv); \
}; \
static ConsoleConstructor \
className##name##obj(#className,#name,c##className##name##caster,"",minArgs,maxArgs); \
static inline returnType c##className##name(S32 argc, const char **argv)
static inline returnType c##className##name(S32 argc, ConsoleValueRef *argv)
#define ConsoleDoc( text )