mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-13 11:43:49 +00:00
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:
parent
394d87cd54
commit
38c8e52c1d
68 changed files with 1511 additions and 529 deletions
|
|
@ -35,6 +35,44 @@
|
|||
//#define DEBUG_SPEW
|
||||
|
||||
|
||||
Dictionary::Entry smLocalDictionaryEntryStack[4096*4];
|
||||
Dictionary::Entry *smLocalDictionaryEntryStackHead = NULL;
|
||||
|
||||
void setupDictionaryStack()
|
||||
{
|
||||
smLocalDictionaryEntryStackHead = &smLocalDictionaryEntryStack[0];
|
||||
|
||||
for (int i=0; i<4096*4; i++) {
|
||||
(smLocalDictionaryEntryStackHead + i)->mNext = i == (4096*4)-1 ? NULL : smLocalDictionaryEntryStackHead + (i+1);
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary::Entry * getDictionaryStackEntry()
|
||||
{
|
||||
Dictionary::Entry *entry = smLocalDictionaryEntryStackHead;
|
||||
AssertFatal(entry, "No more local variables");
|
||||
|
||||
entry->reset();
|
||||
|
||||
Dictionary::Entry *next = entry->mNext;
|
||||
|
||||
smLocalDictionaryEntryStackHead = next;
|
||||
|
||||
entry->mNext = NULL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void disposeDictionaryStackEntry(Dictionary::Entry *entry)
|
||||
{
|
||||
Dictionary::Entry *prevHead = smLocalDictionaryEntryStackHead;
|
||||
smLocalDictionaryEntryStackHead = entry;
|
||||
|
||||
smLocalDictionaryEntryStackHead->mNext = prevHead;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define ST_INIT_SIZE 15
|
||||
|
||||
static char scratchBuffer[1024];
|
||||
|
|
@ -168,13 +206,13 @@ void Dictionary::exportVariables(const char *varString, const char *fileName, bo
|
|||
|
||||
for(s = sortList.begin(); s != sortList.end(); s++)
|
||||
{
|
||||
switch((*s)->type)
|
||||
switch((*s)->value.type)
|
||||
{
|
||||
case Entry::TypeInternalInt:
|
||||
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->ival, cat);
|
||||
case ConsoleValue::TypeInternalInt:
|
||||
dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->value.ival, cat);
|
||||
break;
|
||||
case Entry::TypeInternalFloat:
|
||||
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->fval, cat);
|
||||
case ConsoleValue::TypeInternalFloat:
|
||||
dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->value.fval, cat);
|
||||
break;
|
||||
default:
|
||||
expandEscape(expandBuffer, (*s)->getStringValue());
|
||||
|
|
@ -228,13 +266,13 @@ void Dictionary::exportVariables( const char *varString, Vector<String> *names,
|
|||
|
||||
if ( values )
|
||||
{
|
||||
switch ( (*s)->type )
|
||||
switch ( (*s)->value.type )
|
||||
{
|
||||
case Entry::TypeInternalInt:
|
||||
values->push_back( String::ToString( (*s)->ival ) );
|
||||
case ConsoleValue::TypeInternalInt:
|
||||
values->push_back( String::ToString( (*s)->value.ival ) );
|
||||
break;
|
||||
case Entry::TypeInternalFloat:
|
||||
values->push_back( String::ToString( (*s)->fval ) );
|
||||
case ConsoleValue::TypeInternalFloat:
|
||||
values->push_back( String::ToString( (*s)->value.fval ) );
|
||||
break;
|
||||
default:
|
||||
expandEscape( expandBuffer, (*s)->getStringValue() );
|
||||
|
|
@ -284,10 +322,13 @@ Dictionary::Entry *Dictionary::lookup(StringTableEntry name)
|
|||
Dictionary::Entry *Dictionary::add(StringTableEntry name)
|
||||
{
|
||||
// Try to find an existing match.
|
||||
//printf("Add Variable %s\n", name);
|
||||
|
||||
Entry* ret = lookup( name );
|
||||
if( ret )
|
||||
if( ret ) {
|
||||
//printf("Found Variable %s (named %s)\n", name, ret->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Rehash if the table get's too crowded. Be aware that this might
|
||||
// modify a table that we don't own.
|
||||
|
|
@ -296,6 +337,7 @@ Dictionary::Entry *Dictionary::add(StringTableEntry name)
|
|||
if( hashTable->count > hashTable->size * 2 )
|
||||
{
|
||||
// Allocate a new table.
|
||||
printf("Re-hashing dictionary...\n");
|
||||
|
||||
const U32 newTableSize = hashTable->size * 4 - 1;
|
||||
Entry** newTableData = new Entry*[ newTableSize ];
|
||||
|
|
@ -307,7 +349,10 @@ Dictionary::Entry *Dictionary::add(StringTableEntry name)
|
|||
for( Entry* entry = hashTable->data[ i ]; entry != NULL; )
|
||||
{
|
||||
Entry* next = entry->nextEntry;
|
||||
S32 index = HashPointer( entry->name ) % newTableSize;
|
||||
U32 index = HashPointer( entry->name ) % newTableSize;
|
||||
|
||||
|
||||
//printf(" Variable(%s) in bucket %i moved to bucket %i\n", entry->name, i, index);
|
||||
|
||||
entry->nextEntry = newTableData[ index ];
|
||||
newTableData[ index ] = entry;
|
||||
|
|
@ -328,9 +373,10 @@ Dictionary::Entry *Dictionary::add(StringTableEntry name)
|
|||
|
||||
// Add the new entry.
|
||||
|
||||
ret = hashTable->mChunker.alloc();
|
||||
constructInPlace( ret, name );
|
||||
S32 idx = HashPointer(name) % hashTable->size;
|
||||
ret = getDictionaryStackEntry();//hashTable->mChunker.alloc();
|
||||
ret->name = name;
|
||||
//constructInPlace( ret, name );
|
||||
U32 idx = HashPointer(name) % hashTable->size;
|
||||
ret->nextEntry = hashTable->data[idx];
|
||||
hashTable->data[idx] = ret;
|
||||
|
||||
|
|
@ -350,8 +396,8 @@ void Dictionary::remove(Dictionary::Entry *ent)
|
|||
|
||||
*walk = (ent->nextEntry);
|
||||
|
||||
destructInPlace( ent );
|
||||
hashTable->mChunker.free( ent );
|
||||
disposeDictionaryStackEntry( ent );
|
||||
//hashTable->mChunker.free( ent );
|
||||
|
||||
hashTable->count--;
|
||||
}
|
||||
|
|
@ -412,13 +458,13 @@ void Dictionary::reset()
|
|||
while( walk )
|
||||
{
|
||||
Entry* temp = walk->nextEntry;
|
||||
destructInPlace( walk );
|
||||
disposeDictionaryStackEntry( walk );
|
||||
walk = temp;
|
||||
}
|
||||
}
|
||||
|
||||
dMemset( ownHashTable.data, 0, ownHashTable.size * sizeof( Entry* ) );
|
||||
ownHashTable.mChunker.freeBlocks( true );
|
||||
//ownHashTable.mChunker.freeBlocks( true );
|
||||
|
||||
ownHashTable.count = 0;
|
||||
hashTable = NULL;
|
||||
|
|
@ -454,7 +500,7 @@ char *typeValueEmpty = "";
|
|||
Dictionary::Entry::Entry(StringTableEntry in_name)
|
||||
{
|
||||
name = in_name;
|
||||
type = TypeInternalString;
|
||||
value.type = ConsoleValue::TypeInternalString;
|
||||
notify = NULL;
|
||||
nextEntry = NULL;
|
||||
mUsage = NULL;
|
||||
|
|
@ -462,17 +508,12 @@ Dictionary::Entry::Entry(StringTableEntry in_name)
|
|||
|
||||
// NOTE: This is data inside a nameless
|
||||
// union, so we don't need to init the rest.
|
||||
ival = 0;
|
||||
fval = 0;
|
||||
sval = typeValueEmpty;
|
||||
bufferLen = 0;
|
||||
value.init();
|
||||
}
|
||||
|
||||
Dictionary::Entry::~Entry()
|
||||
{
|
||||
if ( type <= TypeInternalString &&
|
||||
sval != typeValueEmpty )
|
||||
dFree(sval);
|
||||
value.cleanup();
|
||||
|
||||
if ( notify )
|
||||
delete notify;
|
||||
|
|
@ -497,15 +538,11 @@ const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
|
|||
return "";
|
||||
}
|
||||
|
||||
void Dictionary::Entry::setStringValue(const char * value)
|
||||
void ConsoleValue::setStringValue(const char * value)
|
||||
{
|
||||
if( mIsConstant )
|
||||
{
|
||||
Con::errorf( "Cannot assign value to constant '%s'.", name );
|
||||
return;
|
||||
}
|
||||
if (value == NULL) value = typeValueEmpty;
|
||||
|
||||
if(type <= TypeInternalString)
|
||||
if(type <= ConsoleValue::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
|
||||
|
|
@ -519,6 +556,15 @@ void Dictionary::Entry::setStringValue(const char * value)
|
|||
return;
|
||||
}
|
||||
*/
|
||||
if (value == typeValueEmpty) {
|
||||
if (sval && sval != typeValueEmpty && type != TypeInternalStackString) dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
bufferLen = 0;
|
||||
fval = 0.f;
|
||||
ival = 0;
|
||||
type = TypeInternalString;
|
||||
return;
|
||||
}
|
||||
|
||||
U32 stringLen = dStrlen(value);
|
||||
|
||||
|
|
@ -537,25 +583,89 @@ void Dictionary::Entry::setStringValue(const char * value)
|
|||
ival = 0;
|
||||
}
|
||||
|
||||
type = TypeInternalString;
|
||||
|
||||
// may as well pad to the next cache line
|
||||
U32 newLen = ((stringLen + 1) + 15) & ~15;
|
||||
|
||||
if(sval == typeValueEmpty)
|
||||
|
||||
if(sval == typeValueEmpty || type == TypeInternalStackString)
|
||||
sval = (char *) dMalloc(newLen);
|
||||
else if(newLen > bufferLen)
|
||||
sval = (char *) dRealloc(sval, newLen);
|
||||
|
||||
type = TypeInternalString;
|
||||
|
||||
bufferLen = newLen;
|
||||
dStrcpy(sval, value);
|
||||
}
|
||||
else
|
||||
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
|
||||
}
|
||||
|
||||
// Fire off the notification if we have one.
|
||||
if ( notify )
|
||||
notify->trigger();
|
||||
|
||||
void ConsoleValue::setStackStringValue(const char * value)
|
||||
{
|
||||
if (value == NULL) value = typeValueEmpty;
|
||||
|
||||
if(type <= ConsoleValue::TypeInternalString)
|
||||
{
|
||||
if (value == typeValueEmpty) {
|
||||
if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString) dFree(sval);
|
||||
sval = typeValueEmpty;
|
||||
bufferLen = 0;
|
||||
fval = 0.f;
|
||||
ival = 0;
|
||||
type = TypeInternalString;
|
||||
return;
|
||||
}
|
||||
|
||||
U32 stringLen = dStrlen(value);
|
||||
if(stringLen < 256)
|
||||
{
|
||||
fval = dAtof(value);
|
||||
ival = dAtoi(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
fval = 0.f;
|
||||
ival = 0;
|
||||
}
|
||||
|
||||
type = TypeInternalStackString;
|
||||
sval = (char*)value;
|
||||
bufferLen = stringLen;
|
||||
}
|
||||
else
|
||||
Con::setData(type, dataPtr, 0, 1, &value, enumTable);
|
||||
}
|
||||
|
||||
|
||||
S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid)
|
||||
{
|
||||
Entry *ent = lookup(name);
|
||||
if(ent)
|
||||
{
|
||||
if(entValid)
|
||||
*entValid = true;
|
||||
return ent->getIntValue();
|
||||
}
|
||||
if(entValid)
|
||||
*entValid = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
F32 Dictionary::getFloatVariable(StringTableEntry name, bool *entValid)
|
||||
{
|
||||
Entry *ent = lookup(name);
|
||||
if(ent)
|
||||
{
|
||||
if(entValid)
|
||||
*entValid = true;
|
||||
return ent->getFloatValue();
|
||||
}
|
||||
if(entValid)
|
||||
*entValid = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Dictionary::setVariable(StringTableEntry name, const char *value)
|
||||
|
|
@ -582,19 +692,19 @@ Dictionary::Entry* Dictionary::addVariable( const char *name,
|
|||
|
||||
Entry *ent = add(StringTable->insert(name));
|
||||
|
||||
if ( ent->type <= Entry::TypeInternalString &&
|
||||
ent->sval != typeValueEmpty )
|
||||
dFree(ent->sval);
|
||||
if ( ent->value.type <= ConsoleValue::TypeInternalString &&
|
||||
ent->value.sval != typeValueEmpty && ent->value.type != ConsoleValue::TypeInternalStackString )
|
||||
dFree(ent->value.sval);
|
||||
|
||||
ent->type = type;
|
||||
ent->dataPtr = dataPtr;
|
||||
ent->value.type = type;
|
||||
ent->value.dataPtr = dataPtr;
|
||||
ent->mUsage = usage;
|
||||
|
||||
// Fetch enum table, if any.
|
||||
|
||||
ConsoleBaseType* conType = ConsoleBaseType::getType( type );
|
||||
AssertFatal( conType, "Dictionary::addVariable - invalid console type" );
|
||||
ent->enumTable = conType->getEnumTable();
|
||||
ent->value.enumTable = conType->getEnumTable();
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
|
@ -1031,6 +1141,8 @@ void Namespace::init()
|
|||
mGlobalNamespace->mName = NULL;
|
||||
mGlobalNamespace->mNext = NULL;
|
||||
mNamespaceList = mGlobalNamespace;
|
||||
|
||||
setupDictionaryStack();
|
||||
}
|
||||
|
||||
Namespace *Namespace::global()
|
||||
|
|
@ -1268,7 +1380,7 @@ void Namespace::markGroup(const char* name, const char* usage)
|
|||
|
||||
extern S32 executeBlock(StmtNode *block, ExprEvalState *state);
|
||||
|
||||
const char *Namespace::Entry::execute(S32 argc, const char **argv, ExprEvalState *state)
|
||||
const char *Namespace::Entry::execute(S32 argc, ConsoleValueRef *argv, ExprEvalState *state)
|
||||
{
|
||||
if(mType == ConsoleFunctionType)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue