mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 23:24:41 +00:00
Improvements based on experience from implementing Python runtime
This commit is contained in:
parent
e28e24a802
commit
83ea6cd0df
6 changed files with 67 additions and 188 deletions
|
|
@ -365,6 +365,18 @@ public:
|
||||||
return type >= ConsoleValueType::cvConsoleValueType;
|
return type >= ConsoleValueType::cvConsoleValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORQUE_FORCEINLINE ConsoleValueConsoleType* getConsoleType() const
|
||||||
|
{
|
||||||
|
if(type >= ConsoleValueType::cvConsoleValueType)
|
||||||
|
{
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TORQUE_FORCEINLINE void setFastFloat(F64 flt)
|
TORQUE_FORCEINLINE void setFastFloat(F64 flt)
|
||||||
{
|
{
|
||||||
type = ConsoleValueType::cvFloat;
|
type = ConsoleValueType::cvFloat;
|
||||||
|
|
|
||||||
|
|
@ -181,13 +181,13 @@ void Dictionary::exportVariables(const char *varString, const char *fileName, bo
|
||||||
|
|
||||||
for (s = sortList.begin(); s != sortList.end(); s++)
|
for (s = sortList.begin(); s != sortList.end(); s++)
|
||||||
{
|
{
|
||||||
switch ((*s)->type)
|
switch ((*s)->value.getType())
|
||||||
{
|
{
|
||||||
case Entry::TypeInternalInt:
|
case ConsoleValueType::cvInteger:
|
||||||
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->ival, cat);
|
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->getIntValue(), cat);
|
||||||
break;
|
break;
|
||||||
case Entry::TypeInternalFloat:
|
case ConsoleValueType::cvFloat:
|
||||||
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->fval, cat);
|
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->getFloatValue(), cat);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
expandEscape(expandBuffer, (*s)->getStringValue());
|
expandEscape(expandBuffer, (*s)->getStringValue());
|
||||||
|
|
@ -241,7 +241,7 @@ void Dictionary::exportVariables(const char *varString, Vector<String> *names, V
|
||||||
|
|
||||||
if (values)
|
if (values)
|
||||||
{
|
{
|
||||||
switch ((*s)->type)
|
switch ((*s)->value.getType())
|
||||||
{
|
{
|
||||||
case ConsoleValueType::cvInteger:
|
case ConsoleValueType::cvInteger:
|
||||||
case ConsoleValueType::cvFloat:
|
case ConsoleValueType::cvFloat:
|
||||||
|
|
@ -461,19 +461,11 @@ const char *Dictionary::tabComplete(const char *prevText, S32 baseLen, bool fFor
|
||||||
Dictionary::Entry::Entry(StringTableEntry in_name)
|
Dictionary::Entry::Entry(StringTableEntry in_name)
|
||||||
{
|
{
|
||||||
name = in_name;
|
name = in_name;
|
||||||
type = TypeInternalString;
|
|
||||||
notify = NULL;
|
notify = NULL;
|
||||||
nextEntry = NULL;
|
nextEntry = NULL;
|
||||||
mUsage = NULL;
|
mUsage = NULL;
|
||||||
mIsConstant = false;
|
mIsConstant = false;
|
||||||
mNext = NULL;
|
mNext = NULL;
|
||||||
|
|
||||||
ival = 0;
|
|
||||||
fval = 0;
|
|
||||||
sval = NULL;
|
|
||||||
bufferLen = 0;
|
|
||||||
dataPtr = NULL;
|
|
||||||
enumTable = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::Entry::~Entry()
|
Dictionary::Entry::~Entry()
|
||||||
|
|
@ -484,73 +476,11 @@ Dictionary::Entry::~Entry()
|
||||||
void Dictionary::Entry::reset()
|
void Dictionary::Entry::reset()
|
||||||
{
|
{
|
||||||
name = NULL;
|
name = NULL;
|
||||||
if (type <= TypeInternalString && sval != NULL)
|
value.reset();
|
||||||
dFree(sval);
|
|
||||||
if (notify)
|
if (notify)
|
||||||
delete notify;
|
delete notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dictionary::Entry::setStringValue(const char* value)
|
|
||||||
{
|
|
||||||
if (mIsConstant)
|
|
||||||
{
|
|
||||||
Con::errorf("Cannot assign value to constant '%s'.", name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type <= TypeInternalString)
|
|
||||||
{
|
|
||||||
// Let's not remove empty-string-valued global vars from the dict.
|
|
||||||
// If we remove them, then they won't be exported, and sometimes
|
|
||||||
// it could be necessary to export such a global. There are very
|
|
||||||
// few empty-string global vars so there's no performance-related
|
|
||||||
// need to remove them from the dict.
|
|
||||||
/*
|
|
||||||
if(!value[0] && name[0] == '$')
|
|
||||||
{
|
|
||||||
gEvalState.globalVars.remove(this);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
U32 stringLen = dStrlen(value);
|
|
||||||
|
|
||||||
// If it's longer than 256 bytes, it's certainly not a number.
|
|
||||||
//
|
|
||||||
// (This decision may come back to haunt you. Shame on you if it
|
|
||||||
// does.)
|
|
||||||
if (stringLen < 256)
|
|
||||||
{
|
|
||||||
fval = dAtof(value);
|
|
||||||
ival = dAtoi(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fval = 0.f;
|
|
||||||
ival = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = TypeInternalString;
|
|
||||||
|
|
||||||
// may as well pad to the next cache line
|
|
||||||
U32 newLen = ((stringLen + 1) + 15) & ~15;
|
|
||||||
|
|
||||||
if (sval == NULL)
|
|
||||||
sval = (char*)dMalloc(newLen);
|
|
||||||
else if (newLen > bufferLen)
|
|
||||||
sval = (char*)dRealloc(sval, newLen);
|
|
||||||
|
|
||||||
bufferLen = newLen;
|
|
||||||
dStrcpy(sval, value, newLen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
|
|
||||||
|
|
||||||
// Fire off the notification if we have one.
|
|
||||||
if (notify)
|
|
||||||
notify->trigger();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
|
const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
|
||||||
{
|
{
|
||||||
Entry *ent = lookup(name);
|
Entry *ent = lookup(name);
|
||||||
|
|
@ -626,17 +556,12 @@ Dictionary::Entry* Dictionary::addVariable(const char *name,
|
||||||
|
|
||||||
Entry *ent = add(StringTable->insert(name));
|
Entry *ent = add(StringTable->insert(name));
|
||||||
|
|
||||||
if (ent->type <= Entry::TypeInternalString && ent->sval != NULL)
|
|
||||||
dFree(ent->sval);
|
|
||||||
|
|
||||||
ent->mUsage = usage;
|
ent->mUsage = usage;
|
||||||
ent->type = type;
|
|
||||||
ent->dataPtr = dataPtr;
|
|
||||||
|
|
||||||
// Fetch enum table, if any.
|
// Fetch enum table, if any.
|
||||||
ConsoleBaseType* conType = ConsoleBaseType::getType(type);
|
ConsoleBaseType* conType = ConsoleBaseType::getType(type);
|
||||||
AssertFatal(conType, "Dictionary::addVariable - invalid console type");
|
AssertFatal(conType, "Dictionary::addVariable - invalid console type");
|
||||||
ent->enumTable = conType->getEnumTable();
|
ent->value.setConsoleData(type, dataPtr, conType->getEnumTable());
|
||||||
|
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -286,16 +286,8 @@ public:
|
||||||
{
|
{
|
||||||
friend class Dictionary;
|
friend class Dictionary;
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
TypeInternalInt = -3,
|
|
||||||
TypeInternalFloat = -2,
|
|
||||||
TypeInternalString = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
StringTableEntry name;
|
StringTableEntry name;
|
||||||
Entry *nextEntry;
|
Entry *nextEntry;
|
||||||
S32 type;
|
|
||||||
|
|
||||||
typedef Signal<void()> NotifySignal;
|
typedef Signal<void()> NotifySignal;
|
||||||
|
|
||||||
|
|
@ -309,58 +301,17 @@ public:
|
||||||
/// Whether this is a constant that cannot be assigned to.
|
/// Whether this is a constant that cannot be assigned to.
|
||||||
bool mIsConstant;
|
bool mIsConstant;
|
||||||
|
|
||||||
protected:
|
ConsoleValue value;
|
||||||
|
|
||||||
// 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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma warning( pop ) // C4201
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Entry() {
|
Entry() {
|
||||||
name = NULL;
|
name = NULL;
|
||||||
type = TypeInternalString;
|
|
||||||
notify = NULL;
|
notify = NULL;
|
||||||
nextEntry = NULL;
|
nextEntry = NULL;
|
||||||
mUsage = NULL;
|
mUsage = NULL;
|
||||||
mIsConstant = false;
|
mIsConstant = false;
|
||||||
mNext = NULL;
|
mNext = NULL;
|
||||||
|
|
||||||
ival = 0;
|
|
||||||
fval = 0;
|
|
||||||
sval = NULL;
|
|
||||||
bufferLen = 0;
|
|
||||||
dataPtr = NULL;
|
|
||||||
enumTable = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry(StringTableEntry name);
|
Entry(StringTableEntry name);
|
||||||
|
|
@ -370,32 +321,21 @@ public:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
inline ConsoleValue getValue() { return std::move(value); }
|
||||||
|
|
||||||
inline U32 getIntValue()
|
inline U32 getIntValue()
|
||||||
{
|
{
|
||||||
if (type <= TypeInternalString)
|
return value.getInt();
|
||||||
return ival;
|
|
||||||
else
|
|
||||||
return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline F32 getFloatValue()
|
inline F32 getFloatValue()
|
||||||
{
|
{
|
||||||
if (type <= TypeInternalString)
|
return value.getFloat();
|
||||||
return fval;
|
|
||||||
else
|
|
||||||
return dAtof(Con::getData(type, dataPtr, 0, enumTable));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *getStringValue()
|
inline const char *getStringValue()
|
||||||
{
|
{
|
||||||
if (type == TypeInternalString)
|
return value.getString();
|
||||||
return sval;
|
|
||||||
if (type == TypeInternalFloat)
|
|
||||||
return Con::getData(TypeF32, &fval, 0);
|
|
||||||
else if (type == TypeInternalInt)
|
|
||||||
return Con::getData(TypeS32, &ival, 0);
|
|
||||||
else
|
|
||||||
return Con::getData(type, dataPtr, 0, enumTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIntValue(U32 val)
|
void setIntValue(U32 val)
|
||||||
|
|
@ -406,21 +346,15 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type <= TypeInternalString)
|
if (value.isConsoleType())
|
||||||
{
|
{
|
||||||
fval = (F32)val;
|
const char* dptr = Con::getData(TypeS32, &val, 0);
|
||||||
ival = val;
|
ConsoleValueConsoleType* cvt = value.getConsoleType();
|
||||||
if (sval != NULL)
|
Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
|
||||||
{
|
|
||||||
dFree(sval);
|
|
||||||
sval = NULL;
|
|
||||||
}
|
|
||||||
type = TypeInternalInt;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* dptr = Con::getData(TypeS32, &val, 0);
|
value.setInt(val);
|
||||||
Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire off the notification if we have one.
|
// Fire off the notification if we have one.
|
||||||
|
|
@ -436,21 +370,15 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type <= TypeInternalString)
|
if (value.isConsoleType())
|
||||||
{
|
{
|
||||||
fval = val;
|
const char* dptr = Con::getData(TypeF32, &val, 0);
|
||||||
ival = static_cast<U32>(val);
|
ConsoleValueConsoleType* cvt = value.getConsoleType();
|
||||||
if (sval != NULL)
|
Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
|
||||||
{
|
|
||||||
dFree(sval);
|
|
||||||
sval = NULL;
|
|
||||||
}
|
|
||||||
type = TypeInternalFloat;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* dptr = Con::getData(TypeF32, &val, 0);
|
value.setFloat(val);
|
||||||
Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire off the notification if we have one.
|
// Fire off the notification if we have one.
|
||||||
|
|
@ -458,7 +386,29 @@ public:
|
||||||
notify->trigger();
|
notify->trigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStringValue(const char* value);
|
|
||||||
|
void setStringValue(const char* val)
|
||||||
|
{
|
||||||
|
if (mIsConstant)
|
||||||
|
{
|
||||||
|
Con::errorf("Cannot assign value to constant '%s'.", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.isConsoleType())
|
||||||
|
{
|
||||||
|
ConsoleValueConsoleType* cvt = value.getConsoleType();
|
||||||
|
Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &val, cvt->enumTable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.setString(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire off the notification if we have one.
|
||||||
|
if (notify)
|
||||||
|
notify->trigger();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HashTableData
|
struct HashTableData
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ static void dumpVariable( Stream& stream,
|
||||||
{
|
{
|
||||||
// Skip variables defined in script.
|
// Skip variables defined in script.
|
||||||
|
|
||||||
if( entry->type <= Dictionary::Entry::TypeInternalString )
|
if( entry->value.getType() <= ConsoleValueType::cvString )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Skip internals... don't export them.
|
// Skip internals... don't export them.
|
||||||
|
|
@ -148,7 +148,7 @@ static void dumpVariable( Stream& stream,
|
||||||
|
|
||||||
// Skip variables for which we can't decipher their type.
|
// Skip variables for which we can't decipher their type.
|
||||||
|
|
||||||
ConsoleBaseType* type = ConsoleBaseType::getType( entry->type );
|
ConsoleBaseType* type = ConsoleBaseType::getType( entry->value.getConsoleType()->consoleType );
|
||||||
if( !type )
|
if( !type )
|
||||||
{
|
{
|
||||||
Con::errorf( "Can't find type for variable '%s'", entry->name );
|
Con::errorf( "Can't find type for variable '%s'", entry->name );
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "core/stream/stream.h"
|
#include "core/stream/stream.h"
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "core/util/tDictionary.h"
|
||||||
|
|
||||||
namespace Con
|
namespace Con
|
||||||
{
|
{
|
||||||
|
|
@ -24,15 +25,10 @@ namespace Con
|
||||||
|
|
||||||
Module* getCurrentModule();
|
Module* getCurrentModule();
|
||||||
|
|
||||||
inline Vector<Runtime*> gRuntimes(32);
|
inline HashMap<S32, Runtime*> gRuntimes;
|
||||||
inline Runtime* getRuntime(S32 pRuntimeId = 0) { return gRuntimes[pRuntimeId]; }
|
inline Runtime* getRuntime(S32 pRuntimeId = 0) { return gRuntimes[pRuntimeId]; }
|
||||||
inline void registerRuntime(S32 pRuntimeId, Runtime* pRuntime)
|
inline void registerRuntime(S32 pRuntimeId, Runtime* pRuntime)
|
||||||
{
|
{
|
||||||
if (gRuntimes.size() == 0)
|
|
||||||
{
|
|
||||||
gRuntimes.setSize(pRuntimeId + 1);
|
|
||||||
gRuntimes.fill(NULL);
|
|
||||||
}
|
|
||||||
AssertFatal(gRuntimes[pRuntimeId] == NULL, "A runtime with that ID already exists");
|
AssertFatal(gRuntimes[pRuntimeId] == NULL, "A runtime with that ID already exists");
|
||||||
gRuntimes[pRuntimeId] = pRuntime;
|
gRuntimes[pRuntimeId] = pRuntime;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,16 +95,12 @@ namespace TorqueScript
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
Con::EvalResult TorqueScriptRuntime::evaluatef(const char* string, ...)
|
Con::EvalResult TorqueScriptRuntime::evaluatef(const char* string, ...)
|
||||||
{
|
{
|
||||||
ConsoleStackFrameSaver stackSaver;
|
|
||||||
stackSaver.save();
|
|
||||||
|
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, string);
|
va_start(args, string);
|
||||||
dVsprintf(buffer, sizeof(buffer), string, args);
|
dVsprintf(buffer, sizeof(buffer), string, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
CodeBlock* newCodeBlock = new CodeBlock();
|
return evaluate(buffer);
|
||||||
return newCodeBlock->compileExec(NULL, buffer, false, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TorqueScriptRuntime::executeFile(const char* fileName, bool noCalls, bool journalScript)
|
bool TorqueScriptRuntime::executeFile(const char* fileName, bool noCalls, bool journalScript)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue