From 964fde8f091a254286797e1ed57a8218a160bfab Mon Sep 17 00:00:00 2001 From: Jeff Hutchinson Date: Mon, 26 Apr 2021 22:52:58 -0400 Subject: [PATCH] Goodbye String Stack! --- Engine/source/console/astNodes.cpp | 185 +++------- Engine/source/console/codeBlock.cpp | 268 ++++++-------- Engine/source/console/compiledEval.cpp | 408 ++++++++++------------ Engine/source/console/compiler.h | 22 +- Engine/source/console/console.h | 27 +- Engine/source/console/consoleValueStack.h | 16 +- Engine/source/console/test/ScriptTest.cpp | 139 ++++++++ 7 files changed, 507 insertions(+), 558 deletions(-) diff --git a/Engine/source/console/astNodes.cpp b/Engine/source/console/astNodes.cpp index 4d58d91d4..1f8fea367 100644 --- a/Engine/source/console/astNodes.cpp +++ b/Engine/source/console/astNodes.cpp @@ -47,7 +47,9 @@ namespace Compiler U32 compileBlock(StmtNode* block, CodeStream& codeStream, U32 ip) { for (StmtNode* walk = block; walk; walk = walk->getNext()) + { ip = walk->compileStmt(codeStream, ip); + } return codeStream.tell(); } } @@ -146,55 +148,6 @@ void FunctionDeclStmtNode::setPackage(StringTableEntry packageName) // //------------------------------------------------------------ -static U32 conversionOp(TypeReq src, TypeReq dst) -{ - if (src == TypeReqString) - { - switch (dst) - { - case TypeReqUInt: - return OP_STR_TO_UINT; - case TypeReqFloat: - return OP_STR_TO_FLT; - case TypeReqNone: - return OP_STR_TO_NONE; - default: - break; - } - } - else if (src == TypeReqFloat) - { - switch (dst) - { - case TypeReqUInt: - return OP_FLT_TO_UINT; - case TypeReqString: - return OP_FLT_TO_STR; - case TypeReqNone: - return OP_NUM_TO_NONE; - default: - break; - } - } - else if (src == TypeReqUInt) - { - switch (dst) - { - case TypeReqFloat: - return OP_UINT_TO_FLT; - case TypeReqString: - return OP_UINT_TO_STR; - case TypeReqNone: - return OP_NUM_TO_NONE; - default: - break; - } - } - return OP_INVALID; -} - -//------------------------------------------------------------ - U32 BreakStmtNode::compileStmt(CodeStream& codeStream, U32 ip) { if (codeStream.inLoop()) @@ -517,8 +470,6 @@ U32 FloatBinaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) break; } codeStream.emit(operand); - if (type != TypeReqFloat) - codeStream.emit(conversionOp(TypeReqFloat, type)); return codeStream.tell(); } @@ -608,8 +559,6 @@ U32 IntBinaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) ip = left->compile(codeStream, ip, subType); codeStream.emit(operand); } - if (type != TypeReqUInt) - codeStream.emit(conversionOp(TypeReqUInt, type)); return codeStream.tell(); } @@ -629,13 +578,10 @@ U32 StreqExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) // optional conversion ip = left->compile(codeStream, ip, TypeReqString); - codeStream.emit(OP_ADVANCE_STR_NUL); ip = right->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_COMPARE_STR); if (!eq) codeStream.emit(OP_NOT); - if (type != TypeReqUInt) - codeStream.emit(conversionOp(TypeReqUInt, type)); return codeStream.tell(); } @@ -649,19 +595,13 @@ TypeReq StreqExprNode::getPreferredType() U32 StrcatExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) { ip = left->compile(codeStream, ip, TypeReqString); - if (!appendChar) - codeStream.emit(OP_ADVANCE_STR); - else + if (appendChar) { codeStream.emit(OP_ADVANCE_STR_APPENDCHAR); codeStream.emit(appendChar); } ip = right->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_REWIND_STR); - if (type == TypeReqUInt) - codeStream.emit(OP_STR_TO_UINT); - else if (type == TypeReqFloat) - codeStream.emit(OP_STR_TO_FLT); return codeStream.tell(); } @@ -675,7 +615,8 @@ TypeReq StrcatExprNode::getPreferredType() U32 CommaCatExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) { ip = left->compile(codeStream, ip, TypeReqString); - codeStream.emit(OP_ADVANCE_STR_COMMA); + codeStream.emit(OP_ADVANCE_STR_APPENDCHAR); + codeStream.emit('_'); ip = right->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_REWIND_STR); @@ -684,10 +625,7 @@ U32 CommaCatExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) // But we're paranoid, so accept (but whine) if we get an oddity... if (type == TypeReqUInt || type == TypeReqFloat) Con::warnf(ConsoleLogEntry::General, "%s (%d): converting comma string to a number... probably wrong.", dbgFileName, dbgLineNumber); - if (type == TypeReqUInt) - codeStream.emit(OP_STR_TO_UINT); - else if (type == TypeReqFloat) - codeStream.emit(OP_STR_TO_FLT); + return codeStream.tell(); } @@ -710,8 +648,7 @@ U32 IntUnaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emit(integer ? OP_NOT : OP_NOTF); else if (op == '~') codeStream.emit(OP_ONESCOMPLEMENT); - if (type != TypeReqUInt) - codeStream.emit(conversionOp(TypeReqUInt, type)); + return codeStream.tell(); } @@ -726,8 +663,7 @@ U32 FloatUnaryExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) { ip = expr->compile(codeStream, ip, TypeReqFloat); codeStream.emit(OP_NEG); - if (type != TypeReqFloat) - codeStream.emit(conversionOp(TypeReqFloat, type)); + return codeStream.tell(); } @@ -768,10 +704,11 @@ U32 VarNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) if (arrayIndex) { - codeStream.emit(OP_ADVANCE_STR); + //codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_REWIND_STR); codeStream.emit(OP_SETCURVAR_ARRAY); + codeStream.emit(OP_POP_STK); } switch (type) { @@ -1013,18 +950,18 @@ U32 AssignExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) { if (arrayIndex) { - if (subType == TypeReqString) - codeStream.emit(OP_ADVANCE_STR); + //if (subType == TypeReqString) + // codeStream.emit(OP_ADVANCE_STR); codeStream.emit(OP_LOADIMMED_IDENT); codeStream.emitSTE(varName); - codeStream.emit(OP_ADVANCE_STR); + //codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_REWIND_STR); codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); - if (subType == TypeReqString) - codeStream.emit(OP_TERMINATE_REWIND_STR); + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); } else { @@ -1049,11 +986,8 @@ U32 AssignExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emit(getFuncVars()->assign(varName, subType == TypeReqNone ? TypeReqString : subType)); } - if (type != subType) - { - U32 conOp = conversionOp(subType, type); - codeStream.emit(conOp); - } + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); return ip; } @@ -1068,11 +1002,14 @@ static void getAssignOpTypeOp(S32 op, TypeReq& type, U32& operand) { switch (op) { - case '+': case opPLUSPLUS: + TORQUE_CASE_FALLTHROUGH; + case '+': type = TypeReqFloat; operand = OP_ADD; break; + case opMINUSMINUS: + TORQUE_CASE_FALLTHROUGH; case '-': type = TypeReqFloat; operand = OP_SUB; @@ -1109,6 +1046,8 @@ static void getAssignOpTypeOp(S32 op, TypeReq& type, U32& operand) type = TypeReqUInt; operand = OP_SHR; break; + default: + AssertFatal(false, "Invalid opcode on operation expression"); } } @@ -1163,10 +1102,12 @@ U32 AssignOpExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emit(OP_LOADIMMED_IDENT); codeStream.emitSTE(varName); - codeStream.emit(OP_ADVANCE_STR); + //codeStream.emit(OP_ADVANCE_STR); ip = arrayIndex->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_REWIND_STR); codeStream.emit(OP_SETCURVAR_ARRAY_CREATE); + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); } codeStream.emit((subType == TypeReqFloat) ? OP_LOADVAR_FLT : OP_LOADVAR_UINT); codeStream.emit(operand); @@ -1184,10 +1125,8 @@ U32 AssignOpExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emit(varIdx); } - if (subType != type) - { - codeStream.emit(conversionOp(subType, type)); - } + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); } return codeStream.tell(); } @@ -1259,18 +1198,7 @@ U32 FuncCallExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) walkType = TypeReqString; ip = walk->compile(codeStream, ip, walkType); - switch (walk->getPreferredType()) - { - case TypeReqFloat: - codeStream.emit(OP_PUSH_FLT); - break; - case TypeReqUInt: - codeStream.emit(OP_PUSH_UINT); - break; - default: - codeStream.emit(OP_PUSH); - break; - } + codeStream.emit(OP_PUSH); } codeStream.emit(OP_CALLFUNC); @@ -1278,8 +1206,9 @@ U32 FuncCallExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emitSTE(nameSpace); codeStream.emit(callType); - if (type != TypeReqString) - codeStream.emit(conversionOp(TypeReqString, type)); + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); + return codeStream.tell(); } @@ -1288,7 +1217,6 @@ TypeReq FuncCallExprNode::getPreferredType() return TypeReqString; } - //------------------------------------------------------------ U32 AssertCallExprNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) @@ -1322,15 +1250,7 @@ U32 SlotAccessNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) if (arrayExpr) { - // eval array - // OP_ADVANCE_STR - // evaluate object expression sub (OP_SETCURFIELD) - // OP_TERMINATE_REWIND_STR - // OP_SETCURFIELDARRAY - // total add of 4 + array precomp - ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream.emit(OP_ADVANCE_STR); } ip = objectExpr->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_SETCUROBJECT); @@ -1341,8 +1261,8 @@ U32 SlotAccessNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) if (arrayExpr) { - codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_SETCURFIELD_ARRAY); + codeStream.emit(OP_POP_STK); } switch (type) @@ -1381,8 +1301,6 @@ U32 InternalSlotAccessNode::compile(CodeStream& codeStream, U32 ip, TypeReq type codeStream.emit(OP_SETCUROBJECT_INTERNAL); codeStream.emit(recurse); - if (type != TypeReqUInt) - codeStream.emit(conversionOp(TypeReqUInt, type)); return codeStream.tell(); } @@ -1426,11 +1344,9 @@ U32 SlotAssignNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) precompileIdent(slotName); ip = valueExpr->compile(codeStream, ip, TypeReqString); - codeStream.emit(OP_ADVANCE_STR); if (arrayExpr) { ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream.emit(OP_ADVANCE_STR); } if (objectExpr) { @@ -1444,11 +1360,10 @@ U32 SlotAssignNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) if (arrayExpr) { - codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_SETCURFIELD_ARRAY); + codeStream.emit(OP_POP_STK); } - codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_SAVEFIELD_STR); if (typeID != -1) @@ -1457,8 +1372,9 @@ U32 SlotAssignNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emit(typeID); } - if (type != TypeReqString) - codeStream.emit(conversionOp(TypeReqString, type)); + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); + return codeStream.tell(); } @@ -1501,7 +1417,6 @@ U32 SlotAssignOpNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) if (arrayExpr) { ip = arrayExpr->compile(codeStream, ip, TypeReqString); - codeStream.emit(OP_ADVANCE_STR); } ip = objectExpr->compile(codeStream, ip, TypeReqString); codeStream.emit(OP_SETCUROBJECT); @@ -1510,14 +1425,15 @@ U32 SlotAssignOpNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) if (arrayExpr) { - codeStream.emit(OP_TERMINATE_REWIND_STR); codeStream.emit(OP_SETCURFIELD_ARRAY); + if (subType == TypeReqNone) + codeStream.emit(OP_POP_STK); } codeStream.emit((subType == TypeReqFloat) ? OP_LOADFIELD_FLT : OP_LOADFIELD_UINT); codeStream.emit(operand); codeStream.emit((subType == TypeReqFloat) ? OP_SAVEFIELD_FLT : OP_SAVEFIELD_UINT); - if (subType != type) - codeStream.emit(conversionOp(subType, type)); + if (subType == TypeReqNone) + codeStream.emit(OP_POP_STK); return codeStream.tell(); } @@ -1572,18 +1488,7 @@ U32 ObjectDeclNode::compileSubObject(CodeStream& codeStream, U32 ip, bool root) TypeReq walkType = exprWalk->getPreferredType(); if (walkType == TypeReqNone) walkType = TypeReqString; ip = exprWalk->compile(codeStream, ip, walkType); - switch (exprWalk->getPreferredType()) - { - case TypeReqFloat: - codeStream.emit(OP_PUSH_FLT); - break; - case TypeReqUInt: - codeStream.emit(OP_PUSH_UINT); - break; - default: - codeStream.emit(OP_PUSH); - break; - } + codeStream.emit(OP_PUSH); } codeStream.emit(OP_CREATE_OBJECT); codeStream.emitSTE(parentObject); @@ -1621,8 +1526,10 @@ U32 ObjectDeclNode::compile(CodeStream& codeStream, U32 ip, TypeReq type) codeStream.emit(OP_LOADIMMED_UINT); codeStream.emit(0); ip = compileSubObject(codeStream, ip, true); - if (type != TypeReqUInt) - codeStream.emit(conversionOp(TypeReqUInt, type)); + + if (type == TypeReqNone) + codeStream.emit(OP_POP_STK); + return codeStream.tell(); } diff --git a/Engine/source/console/codeBlock.cpp b/Engine/source/console/codeBlock.cpp index 47345aae1..9c1ddda17 100644 --- a/Engine/source/console/codeBlock.cpp +++ b/Engine/source/console/codeBlock.cpp @@ -520,7 +520,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con lastIp = 0; } - codeStream.emit(OP_RETURN); + codeStream.emit(OP_RETURN_VOID); codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); lineBreakPairCount = codeStream.getNumLineBreaks(); @@ -640,11 +640,11 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr globalFloats = getGlobalFloatTable().build(); functionFloats = getFunctionFloatTable().build(); - codeStream.emit(OP_RETURN); + codeStream.emit(OP_RETURN_VOID); codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs); - if (Con::getBoolVariable("dump")) - dumpInstructions(0, false); + //if (Con::getBoolVariable("dump")) + //dumpInstructions(0, false); consoleAllocReset(); @@ -726,7 +726,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) U32 regCount = code[ip + 9]; endFuncIp = newIp; - Con::printf("%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i regCount=%i", + Con::printf("%i: OP_FUNC_DECL stk=+0 name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i regCount=%i", ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc, regCount); // Skip args. @@ -745,7 +745,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) U32 lineNumber = code[ip + 5]; U32 failJump = code[ip + 6]; - Con::printf("%i: OP_CREATE_OBJECT objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i", + Con::printf("%i: OP_CREATE_OBJECT stk=+0 objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i", ip - 1, objParent, isDataBlock, isInternal, isSingleton, lineNumber, failJump); ip += 7; @@ -755,14 +755,16 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_ADD_OBJECT: { bool placeAtRoot = code[ip++]; - Con::printf("%i: OP_ADD_OBJECT placeAtRoot=%i", ip - 1, placeAtRoot); + const char* stk = placeAtRoot ? "+1" : "0"; + Con::printf("%i: OP_ADD_OBJECT stk=%s placeAtRoot=%i", ip - 1, stk, placeAtRoot); break; } case OP_END_OBJECT: { bool placeAtRoot = code[ip++]; - Con::printf("%i: OP_END_OBJECT placeAtRoot=%i", ip - 1, placeAtRoot); + const char* stk = placeAtRoot ? "-1" : "0"; + Con::printf("%i: OP_END_OBJECT stk=%s placeAtRoot=%i", ip - 1, stk, placeAtRoot); break; } @@ -774,56 +776,56 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_JMPIFFNOT: { - Con::printf("%i: OP_JMPIFFNOT ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMPIFFNOT stk=-1 ip=%i", ip - 1, code[ip]); ++ip; break; } case OP_JMPIFNOT: { - Con::printf("%i: OP_JMPIFNOT ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMPIFNOT stk=-1 ip=%i", ip - 1, code[ip]); ++ip; break; } case OP_JMPIFF: { - Con::printf("%i: OP_JMPIFF ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMPIFF stk=-1 ip=%i", ip - 1, code[ip]); ++ip; break; } case OP_JMPIF: { - Con::printf("%i: OP_JMPIF ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMPIF stk=-1 ip=%i", ip - 1, code[ip]); ++ip; break; } case OP_JMPIFNOT_NP: { - Con::printf("%i: OP_JMPIFNOT_NP ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMPIFNOT_NP stk=-1 or 0 ip=%i", ip - 1, code[ip]); ++ip; break; } case OP_JMPIF_NP: { - Con::printf("%i: OP_JMPIF_NP ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMPIF_NP stk=-1 or 0 ip=%i", ip - 1, code[ip]); ++ip; break; } case OP_JMP: { - Con::printf("%i: OP_JMP ip=%i", ip - 1, code[ip]); + Con::printf("%i: OP_JMP stk=0 ip=%i", ip - 1, code[ip]); ++ip; break; } - case OP_RETURN: + case OP_RETURN_VOID: { - Con::printf("%i: OP_RETURN", ip - 1); + Con::printf("%i: OP_RETURN_VOID stk=0", ip - 1); if (upToReturn) return; @@ -831,9 +833,9 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) break; } - case OP_RETURN_VOID: + case OP_RETURN: { - Con::printf("%i: OP_RETURNVOID", ip - 1); + Con::printf("%i: OP_RETURN stk=-1", ip - 1); if (upToReturn) return; @@ -843,7 +845,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_RETURN_UINT: { - Con::printf("%i: OP_RETURNUINT", ip - 1); + Con::printf("%i: OP_RETURNUINT stk=-1", ip - 1); if (upToReturn) return; @@ -853,7 +855,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_RETURN_FLT: { - Con::printf("%i: OP_RETURNFLT", ip - 1); + Con::printf("%i: OP_RETURNFLT stk=-1", ip - 1); if (upToReturn) return; @@ -863,139 +865,139 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_CMPEQ: { - Con::printf("%i: OP_CMPEQ", ip - 1); + Con::printf("%i: OP_CMPEQ stk=-1", ip - 1); break; } case OP_CMPGR: { - Con::printf("%i: OP_CMPGR", ip - 1); + Con::printf("%i: OP_CMPGR stk=-1", ip - 1); break; } case OP_CMPGE: { - Con::printf("%i: OP_CMPGE", ip - 1); + Con::printf("%i: OP_CMPGE stk=-1", ip - 1); break; } case OP_CMPLT: { - Con::printf("%i: OP_CMPLT", ip - 1); + Con::printf("%i: OP_CMPLT stk=-1", ip - 1); break; } case OP_CMPLE: { - Con::printf("%i: OP_CMPLE", ip - 1); + Con::printf("%i: OP_CMPLE stk=-1", ip - 1); break; } case OP_CMPNE: { - Con::printf("%i: OP_CMPNE", ip - 1); + Con::printf("%i: OP_CMPNE stk=-1", ip - 1); break; } case OP_XOR: { - Con::printf("%i: OP_XOR", ip - 1); + Con::printf("%i: OP_XOR stk=-1", ip - 1); break; } case OP_MOD: { - Con::printf("%i: OP_MOD", ip - 1); + Con::printf("%i: OP_MOD stk=-1", ip - 1); break; } case OP_BITAND: { - Con::printf("%i: OP_BITAND", ip - 1); + Con::printf("%i: OP_BITAND stk=-1", ip - 1); break; } case OP_BITOR: { - Con::printf("%i: OP_BITOR", ip - 1); + Con::printf("%i: OP_BITOR stk=-1", ip - 1); break; } case OP_NOT: { - Con::printf("%i: OP_NOT", ip - 1); + Con::printf("%i: OP_NOT stk=0", ip - 1); break; } case OP_NOTF: { - Con::printf("%i: OP_NOTF", ip - 1); + Con::printf("%i: OP_NOTF stk=0", ip - 1); break; } case OP_ONESCOMPLEMENT: { - Con::printf("%i: OP_ONESCOMPLEMENT", ip - 1); + Con::printf("%i: OP_ONESCOMPLEMENT stk=0", ip - 1); break; } case OP_SHR: { - Con::printf("%i: OP_SHR", ip - 1); + Con::printf("%i: OP_SHR stk=-1", ip - 1); break; } case OP_SHL: { - Con::printf("%i: OP_SHL", ip - 1); + Con::printf("%i: OP_SHL stk=-1", ip - 1); break; } case OP_AND: { - Con::printf("%i: OP_AND", ip - 1); + Con::printf("%i: OP_AND stk=-1", ip - 1); break; } case OP_OR: { - Con::printf("%i: OP_OR", ip - 1); + Con::printf("%i: OP_OR stk=-1", ip - 1); break; } case OP_ADD: { - Con::printf("%i: OP_ADD", ip - 1); + Con::printf("%i: OP_ADD stk=-1", ip - 1); break; } case OP_SUB: { - Con::printf("%i: OP_SUB", ip - 1); + Con::printf("%i: OP_SUB stk=-1", ip - 1); break; } case OP_MUL: { - Con::printf("%i: OP_MUL", ip - 1); + Con::printf("%i: OP_MUL stk=-1", ip - 1); break; } case OP_DIV: { - Con::printf("%i: OP_DIV", ip - 1); + Con::printf("%i: OP_DIV stk=-1", ip - 1); break; } case OP_NEG: { - Con::printf("%i: OP_NEG", ip - 1); + Con::printf("%i: OP_NEG stk=0", ip - 1); break; } case OP_INC: { - Con::printf("%i: OP_INC reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_INC stk=0 reg=%i", ip - 1, code[ip]); ++ip; break; } @@ -1004,7 +1006,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) { StringTableEntry var = CodeToSTE(code, ip); - Con::printf("%i: OP_SETCURVAR var=%s", ip - 1, var); + Con::printf("%i: OP_SETCURVAR stk=0 var=%s", ip - 1, var); ip += 2; break; } @@ -1013,116 +1015,116 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) { StringTableEntry var = CodeToSTE(code, ip); - Con::printf("%i: OP_SETCURVAR_CREATE var=%s", ip - 1, var); + Con::printf("%i: OP_SETCURVAR_CREATE stk=0 var=%s", ip - 1, var); ip += 2; break; } case OP_SETCURVAR_ARRAY: { - Con::printf("%i: OP_SETCURVAR_ARRAY", ip - 1); + Con::printf("%i: OP_SETCURVAR_ARRAY stk=0", ip - 1); break; } case OP_SETCURVAR_ARRAY_CREATE: { - Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE", ip - 1); + Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE stk=0", ip - 1); break; } case OP_LOADVAR_UINT: { - Con::printf("%i: OP_LOADVAR_UINT", ip - 1); + Con::printf("%i: OP_LOADVAR_UINT stk=+1", ip - 1); break; } case OP_LOADVAR_FLT: { - Con::printf("%i: OP_LOADVAR_FLT", ip - 1); + Con::printf("%i: OP_LOADVAR_FLT stk=+1", ip - 1); break; } case OP_LOADVAR_STR: { - Con::printf("%i: OP_LOADVAR_STR", ip - 1); + Con::printf("%i: OP_LOADVAR_STR stk=+1", ip - 1); break; } case OP_SAVEVAR_UINT: { - Con::printf("%i: OP_SAVEVAR_UINT", ip - 1); + Con::printf("%i: OP_SAVEVAR_UINT stk=0", ip - 1); break; } case OP_SAVEVAR_FLT: { - Con::printf("%i: OP_SAVEVAR_FLT", ip - 1); + Con::printf("%i: OP_SAVEVAR_FLT stk=0", ip - 1); break; } case OP_SAVEVAR_STR: { - Con::printf("%i: OP_SAVEVAR_STR", ip - 1); + Con::printf("%i: OP_SAVEVAR_STR stk=0", ip - 1); break; } case OP_LOAD_LOCAL_VAR_UINT: { - Con::printf("%i: OP_LOAD_LOCAL_VAR_UINT reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_LOAD_LOCAL_VAR_UINT stk=+1 reg=%i", ip - 1, code[ip]); ++ip; break; } case OP_LOAD_LOCAL_VAR_FLT: { - Con::printf("%i: OP_LOAD_LOCAL_VAR_FLT reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_LOAD_LOCAL_VAR_FLT stk=+1 reg=%i", ip - 1, code[ip]); ++ip; break; } case OP_LOAD_LOCAL_VAR_STR: { - Con::printf("%i: OP_LOAD_LOCAL_VAR_STR reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_LOAD_LOCAL_VAR_STR stk=+1 reg=%i", ip - 1, code[ip]); ++ip; break; } case OP_SAVE_LOCAL_VAR_UINT: { - Con::printf("%i: OP_SAVE_LOCAL_VAR_UINT reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_SAVE_LOCAL_VAR_UINT stk=0 reg=%i", ip - 1, code[ip]); ++ip; break; } case OP_SAVE_LOCAL_VAR_FLT: { - Con::printf("%i: OP_SAVE_LOCAL_VAR_FLT reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_SAVE_LOCAL_VAR_FLT stk=0 reg=%i", ip - 1, code[ip]); ++ip; break; } case OP_SAVE_LOCAL_VAR_STR: { - Con::printf("%i: OP_SAVE_LOCAL_VAR_STR reg=%i", ip - 1, code[ip]); + Con::printf("%i: OP_SAVE_LOCAL_VAR_STR stk=0 reg=%i", ip - 1, code[ip]); ++ip; break; } case OP_SETCUROBJECT: { - Con::printf("%i: OP_SETCUROBJECT", ip - 1); + Con::printf("%i: OP_SETCUROBJECT stk=-1", ip - 1); break; } case OP_SETCUROBJECT_NEW: { - Con::printf("%i: OP_SETCUROBJECT_NEW", ip - 1); + Con::printf("%i: OP_SETCUROBJECT_NEW stk=0", ip - 1); break; } case OP_SETCUROBJECT_INTERNAL: { - Con::printf("%i: OP_SETCUROBJECT_INTERNAL", ip - 1); + Con::printf("%i: OP_SETCUROBJECT_INTERNAL stk=0", ip - 1); ++ip; break; } @@ -1130,113 +1132,71 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_SETCURFIELD: { StringTableEntry curField = CodeToSTE(code, ip); - Con::printf("%i: OP_SETCURFIELD field=%s", ip - 1, curField); + Con::printf("%i: OP_SETCURFIELD stk=0 field=%s", ip - 1, curField); ip += 2; break; } case OP_SETCURFIELD_ARRAY: { - Con::printf("%i: OP_SETCURFIELD_ARRAY", ip - 1); + Con::printf("%i: OP_SETCURFIELD_ARRAY stk=0", ip - 1); break; } case OP_SETCURFIELD_TYPE: { U32 type = code[ip]; - Con::printf("%i: OP_SETCURFIELD_TYPE type=%i", ip - 1, type); + Con::printf("%i: OP_SETCURFIELD_TYPE stk=0 type=%i", ip - 1, type); ++ip; break; } case OP_LOADFIELD_UINT: { - Con::printf("%i: OP_LOADFIELD_UINT", ip - 1); + Con::printf("%i: OP_LOADFIELD_UINT stk=+1", ip - 1); break; } case OP_LOADFIELD_FLT: { - Con::printf("%i: OP_LOADFIELD_FLT", ip - 1); + Con::printf("%i: OP_LOADFIELD_FLT stk=+1", ip - 1); break; } case OP_LOADFIELD_STR: { - Con::printf("%i: OP_LOADFIELD_STR", ip - 1); + Con::printf("%i: OP_LOADFIELD_STR stk=+1", ip - 1); break; } case OP_SAVEFIELD_UINT: { - Con::printf("%i: OP_SAVEFIELD_UINT", ip - 1); + Con::printf("%i: OP_SAVEFIELD_UINT stk=0", ip - 1); break; } case OP_SAVEFIELD_FLT: { - Con::printf("%i: OP_SAVEFIELD_FLT", ip - 1); + Con::printf("%i: OP_SAVEFIELD_FLT stk=0", ip - 1); break; } case OP_SAVEFIELD_STR: { - Con::printf("%i: OP_SAVEFIELD_STR", ip - 1); + Con::printf("%i: OP_SAVEFIELD_STR stk=0", ip - 1); break; } - case OP_STR_TO_UINT: + case OP_POP_STK: { - Con::printf("%i: OP_STR_TO_UINT", ip - 1); - break; - } - - case OP_STR_TO_FLT: - { - Con::printf("%i: OP_STR_TO_FLT", ip - 1); - break; - } - - case OP_STR_TO_NONE: - { - Con::printf("%i: OP_STR_TO_NONE", ip - 1); - break; - } - - case OP_FLT_TO_UINT: - { - Con::printf("%i: OP_FLT_TO_UINT", ip - 1); - break; - } - - case OP_FLT_TO_STR: - { - Con::printf("%i: OP_FLT_TO_STR", ip - 1); - break; - } - - case OP_UINT_TO_FLT: - { - Con::printf("%i: OP_UINT_TO_FLT", ip - 1); - break; - } - - case OP_UINT_TO_STR: - { - Con::printf("%i: OP_UINT_TO_STR", ip - 1); - break; - } - - case OP_NUM_TO_NONE: - { - Con::printf("%i: OP_NUM_TO_NONE", ip - 1); + Con::printf("%i: OP_POP_STK stk=-1", ip - 1); break; } case OP_LOADIMMED_UINT: { U32 val = code[ip]; - Con::printf("%i: OP_LOADIMMED_UINT val=%i", ip - 1, val); + Con::printf("%i: OP_LOADIMMED_UINT stk=+1 val=%i", ip - 1, val); ++ip; break; } @@ -1244,7 +1204,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_LOADIMMED_FLT: { F64 val = (smInFunction ? functionFloats : globalFloats)[code[ip]]; - Con::printf("%i: OP_LOADIMMED_FLT val=%f", ip - 1, val); + Con::printf("%i: OP_LOADIMMED_FLT stk=+1 val=%f", ip - 1, val); ++ip; break; } @@ -1252,7 +1212,8 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_TAG_TO_STR: { const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip]; - Con::printf("%i: OP_TAG_TO_STR str=%s", ip - 1, str); + Con::printf("%i: OP_TAG_TO_STR stk=0 str=%s", ip - 1, str); + Con::printf(" OP_LOADIMMED_STR stk=+1 (fallthrough)"); ++ip; break; } @@ -1260,7 +1221,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_LOADIMMED_STR: { const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip]; - Con::printf("%i: OP_LOADIMMED_STR str=%s", ip - 1, str); + Con::printf("%i: OP_LOADIMMED_STR stk=+1 str=%s", ip - 1, str); ++ip; break; } @@ -1268,7 +1229,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_DOCBLOCK_STR: { const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip]; - Con::printf("%i: OP_DOCBLOCK_STR str=%s", ip - 1, str); + Con::printf("%i: OP_DOCBLOCK_STR stk=0 str=%s", ip - 1, str); ++ip; break; } @@ -1276,7 +1237,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_LOADIMMED_IDENT: { StringTableEntry str = CodeToSTE(code, ip); - Con::printf("%i: OP_LOADIMMED_IDENT str=%s", ip - 1, str); + Con::printf("%i: OP_LOADIMMED_IDENT stk=+1 str=%s", ip - 1, str); ip += 2; break; } @@ -1296,77 +1257,48 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case FuncCallExprNode::StaticCall: callTypeName = "StaticCall"; break; } - Con::printf("%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callTypeName); + Con::printf("%i: OP_CALLFUNC stk=+1 name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callTypeName); ip += 5; break; } - case OP_ADVANCE_STR: - { - Con::printf("%i: OP_ADVANCE_STR", ip - 1); - break; - } - case OP_ADVANCE_STR_APPENDCHAR: { char ch = code[ip]; - Con::printf("%i: OP_ADVANCE_STR_APPENDCHAR char=%c", ip - 1, ch); + Con::printf("%i: OP_ADVANCE_STR_APPENDCHAR stk=0 char=%c", ip - 1, ch); ++ip; break; } - case OP_ADVANCE_STR_COMMA: - { - Con::printf("%i: OP_ADVANCE_STR_COMMA", ip - 1); - break; - } - - case OP_ADVANCE_STR_NUL: - { - Con::printf("%i: OP_ADVANCE_STR_NUL", ip - 1); - break; - } - case OP_REWIND_STR: { - Con::printf("%i: OP_REWIND_STR", ip - 1); + Con::printf("%i: OP_REWIND_STR stk=0", ip - 1); + Con::printf(" OP_TERMINATE_REWIND_STR stk=-1 (fallthrough)"); break; } case OP_TERMINATE_REWIND_STR: { - Con::printf("%i: OP_TERMINATE_REWIND_STR", ip - 1); + Con::printf("%i: OP_TERMINATE_REWIND_STR stk=-1", ip - 1); break; } case OP_COMPARE_STR: { - Con::printf("%i: OP_COMPARE_STR", ip - 1); + Con::printf("%i: OP_COMPARE_STR stk=-1", ip - 1); break; } case OP_PUSH: { - Con::printf("%i: OP_PUSH", ip - 1); - break; - } - - case OP_PUSH_UINT: - { - Con::printf("%i: OP_PUSH_UINT", ip - 1); - break; - } - - case OP_PUSH_FLT: - { - Con::printf("%i: OP_PUSH_FLT", ip - 1); + Con::printf("%i: OP_PUSH stk=-1", ip - 1); break; } case OP_PUSH_FRAME: { - Con::printf("%i: OP_PUSH_FRAME count=%i", ip - 1, code[ip]); + Con::printf("%i: OP_PUSH_FRAME stk=0 count=%i", ip - 1, code[ip]); ++ip; break; } @@ -1374,14 +1306,14 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_ASSERT: { const char* message = (smInFunction ? functionStrings : globalStrings) + code[ip]; - Con::printf("%i: OP_ASSERT message=%s", ip - 1, message); + Con::printf("%i: OP_ASSERT stk=-1 message=%s", ip - 1, message); ++ip; break; } case OP_BREAK: { - Con::printf("%i: OP_BREAK", ip - 1); + Con::printf("%i: OP_BREAK stk=0", ip - 1); break; } @@ -1393,7 +1325,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) StringTableEntry varName = CodeToSTE(code, ip + 1); U32 failIp = code[ip + 3]; - Con::printf("%i: OP_ITER_BEGIN varName=%s failIp=%i isGlobal=%s", ip - 1, varName, failIp, "true"); + Con::printf("%i: OP_ITER_BEGIN stk=0 varName=%s failIp=%i isGlobal=%s", ip - 1, varName, failIp, "true"); ip += 4; } @@ -1402,7 +1334,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) S32 reg = code[ip + 1]; U32 failIp = code[ip + 2]; - Con::printf("%i: OP_ITER_BEGIN varRegister=%d failIp=%i isGlobal=%s", ip - 1, reg, failIp, "false"); + Con::printf("%i: OP_ITER_BEGIN stk=0 varRegister=%d failIp=%i isGlobal=%s", ip - 1, reg, failIp, "false"); ip += 3; } @@ -1417,7 +1349,8 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) StringTableEntry varName = CodeToSTE(code, ip + 1); U32 failIp = code[ip + 3]; - Con::printf("%i: OP_ITER_BEGIN_STR varName=%s failIp=%i isGlobal=%s", ip - 1, varName, failIp, "true"); + Con::printf("%i: OP_ITER_BEGIN_STR stk=0 varName=%s failIp=%i isGlobal=%s", ip - 1, varName, failIp, "true"); + Con::printf(" OP_ITER_BEGIN stk=0 (fallthrough)"); ip += 4; } @@ -1426,7 +1359,8 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) S32 reg = code[ip + 1]; U32 failIp = code[ip + 2]; - Con::printf("%i: OP_ITER_BEGIN_STR varRegister=%d failIp=%i isGlobal=%s", ip - 1, reg, failIp, "false"); + Con::printf("%i: OP_ITER_BEGIN_STR stk=0 varRegister=%d failIp=%i isGlobal=%s", ip - 1, reg, failIp, "false"); + Con::printf(" OP_ITER_BEGIN stk=0 (fallthrough)"); ip += 3; } @@ -1438,7 +1372,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) { U32 breakIp = code[ip]; - Con::printf("%i: OP_ITER breakIp=%i", ip - 1, breakIp); + Con::printf("%i: OP_ITER stk=0 breakIp=%i", ip - 1, breakIp); ++ip; break; @@ -1446,7 +1380,7 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn) case OP_ITER_END: { - Con::printf("%i: OP_ITER_END", ip - 1); + Con::printf("%i: OP_ITER_END stk=-1", ip - 1); break; } diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index 5a6785ed2..228dc85f3 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -109,18 +109,11 @@ ConsoleValueStack<4096> gCallStack; StringStack STR; +IterStackRecord iterStack[MaxStackSize]; U32 _ITER = 0; ///< Stack pointer for iterStack. -IterStackRecord iterStack[MaxStackSize]; - -union StackValue -{ - F64 f; - S64 i; -}; - -StackValue numStack[MaxStackSize]; -U32 _STK = 0; +ConsoleValue stack[MaxStackSize]; +S32 _STK = 0; char curFieldArray[256]; char prevFieldArray[256]; @@ -166,7 +159,7 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c // Otherwise, grab from the string stack. The value coming in will always // be a string because that is how multicomponent variables are handled. else - prevVal = STR.getStringValue(); + prevVal = stack[_STK].getString(); // Make sure we got a value. if (prevVal && *prevVal) @@ -214,7 +207,7 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c { // Copy the current string value char strValue[1024]; - dStrncpy(strValue, STR.getStringValue(), 1024); + dStrncpy(strValue, stack[_STK].getString(), 1024); char val[1024] = ""; const char* prevVal = NULL; @@ -437,7 +430,7 @@ U32 gExecCount = 0; ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNamespace, U32 argc, ConsoleValue* argv, bool noCalls, StringTableEntry packageName, S32 setFrame) { #ifdef TORQUE_DEBUG - U32 stackStart = STR.mStartStackSize; + U32 stackStart = _STK; gExecCount++; #endif @@ -452,7 +445,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa F64* curFloatTable; char* curStringTable; S32 curStringTableLen = 0; //clint to ensure we dont overwrite it - STR.clearFunctionOffset(); + StringTableEntry thisFunctionName = NULL; bool popFrame = false; if (argv) @@ -949,7 +942,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa } // What group will we be added to, if any? - U32 groupAddId = (U32)numStack[_STK].i; + U32 groupAddId = (U32)stack[_STK].getInt(); SimGroup* grp = NULL; SimSet* set = NULL; @@ -994,9 +987,9 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa // id, if one was given, otherwise getting pushed) S32 id = currentNewObject->getId(); if (placeAtRoot) - numStack[_STK].i = id; + stack[_STK].setInt(id); else - numStack[++_STK].i = id; + stack[++_STK].setInt(id); break; } @@ -1024,7 +1017,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa } case OP_JMPIFFNOT: - if (numStack[_STK--].f) + if (stack[_STK--].getFloat()) { ip++; break; @@ -1032,7 +1025,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa ip = code[ip]; break; case OP_JMPIFNOT: - if (numStack[_STK--].i) + if (stack[_STK--].getInt()) { ip++; break; @@ -1040,7 +1033,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa ip = code[ip]; break; case OP_JMPIFF: - if (!numStack[_STK--].f) + if (!stack[_STK--].getFloat()) { ip++; break; @@ -1048,7 +1041,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa ip = code[ip]; break; case OP_JMPIF: - if (!numStack[_STK--].i) + if (!stack[_STK--].getFloat()) { ip++; break; @@ -1056,7 +1049,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa ip = code[ip]; break; case OP_JMPIFNOT_NP: - if (numStack[_STK].i) + if (stack[_STK].getInt()) { _STK--; ip++; @@ -1065,7 +1058,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa ip = code[ip]; break; case OP_JMPIF_NP: - if (!numStack[_STK].i) + if (!stack[_STK].getInt()) { _STK--; ip++; @@ -1077,10 +1070,24 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa ip = code[ip]; break; - // This fixes a bug when not explicitly returning a value. case OP_RETURN_VOID: - STR.setStringValue(""); - // We're falling thru here on purpose. + { + if (iterDepth > 0) + { + // Clear iterator state. + while (iterDepth > 0) + { + iterStack[--_ITER].mIsStringIter = false; + --iterDepth; + } + + _STK--; // this is a pop from foreach() + } + + returnValue.setEmptyString(); + + goto execFinished; + } case OP_RETURN: { @@ -1093,12 +1100,16 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa --iterDepth; } - const char* retVal = STR.getStringValue(); - STR.rewind(); - STR.setStringValue(retVal); // Not nice but works. + + const char* retVal = stack[_STK].getString(); + _STK--; + _STK--; + stack[_STK + 1].setString(retVal); + _STK++; // Not nice but works. } - returnValue.setString(STR.getStringValue(), STR.mLen); + returnValue.setString(stack[_STK].getString()); + _STK--; goto execFinished; } @@ -1115,7 +1126,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa } - returnValue.setFloat(numStack[_STK].f); + returnValue.setFloat(stack[_STK].getFloat()); _STK--; goto execFinished; @@ -1132,116 +1143,118 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa } } - returnValue.setInt(numStack[_STK].i); + returnValue.setInt(stack[_STK].getInt()); _STK--; goto execFinished; case OP_CMPEQ: - numStack[_STK - 1].i = bool(numStack[_STK].f == numStack[_STK - 1].f); + stack[_STK - 1].setInt(stack[_STK].getFloat() == stack[_STK - 1].getFloat()); _STK--; break; case OP_CMPGR: - numStack[_STK - 1].i = bool(numStack[_STK].f > numStack[_STK - 1].f); + stack[_STK - 1].setInt(stack[_STK].getFloat() > stack[_STK - 1].getFloat()); _STK--; break; case OP_CMPGE: - numStack[_STK - 1].i = bool(numStack[_STK].f >= numStack[_STK - 1].f); + stack[_STK - 1].setInt(stack[_STK].getFloat() >= stack[_STK - 1].getFloat()); _STK--; break; case OP_CMPLT: - numStack[_STK - 1].i = bool(numStack[_STK].f < numStack[_STK - 1].f); + stack[_STK - 1].setInt(stack[_STK].getFloat() < stack[_STK - 1].getFloat()); _STK--; break; case OP_CMPLE: - numStack[_STK - 1].i = bool(numStack[_STK].f <= numStack[_STK - 1].f); + stack[_STK - 1].setInt(stack[_STK].getFloat() <= stack[_STK - 1].getFloat()); _STK--; break; case OP_CMPNE: - numStack[_STK - 1].i = bool(numStack[_STK].f != numStack[_STK - 1].f); + stack[_STK - 1].setInt(stack[_STK].getFloat() != stack[_STK - 1].getFloat()); _STK--; break; case OP_XOR: - numStack[_STK - 1].i = numStack[_STK].i ^ numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() ^ stack[_STK - 1].getInt()); _STK--; break; case OP_MOD: - if (numStack[_STK - 1].i != 0) - numStack[_STK - 1].i = numStack[_STK].i % numStack[_STK - 1].i; + if (stack[_STK - 1].getInt() != 0) + stack[_STK - 1].setInt(stack[_STK].getInt() % stack[_STK - 1].getInt()); else - numStack[_STK - 1].i = 0; + stack[_STK - 1].setInt(0); _STK--; break; case OP_BITAND: - numStack[_STK - 1].i = numStack[_STK].i & numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() & stack[_STK - 1].getInt()); _STK--; break; case OP_BITOR: - numStack[_STK - 1].i = numStack[_STK].i | numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() | stack[_STK - 1].getInt()); _STK--; break; case OP_NOT: - numStack[_STK].i = !numStack[_STK].i; + stack[_STK].setInt(!stack[_STK].getInt()); break; case OP_NOTF: - numStack[_STK].i = !numStack[_STK].f; + stack[_STK].setInt(!stack[_STK].getFloat()); break; case OP_ONESCOMPLEMENT: - numStack[_STK].i = ~numStack[_STK].i; + stack[_STK].setInt(~stack[_STK].getInt()); break; case OP_SHR: - numStack[_STK - 1].i = numStack[_STK].i >> numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() >> stack[_STK - 1].getInt()); _STK--; break; case OP_SHL: - numStack[_STK - 1].i = numStack[_STK].i << numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() << stack[_STK - 1].getInt()); _STK--; break; case OP_AND: - numStack[_STK - 1].i = numStack[_STK].i && numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() && stack[_STK - 1].getInt()); _STK--; break; case OP_OR: - numStack[_STK - 1].i = numStack[_STK].i || numStack[_STK - 1].i; + stack[_STK - 1].setInt(stack[_STK].getInt() || stack[_STK - 1].getInt()); _STK--; break; case OP_ADD: - numStack[_STK - 1].f = numStack[_STK].f + numStack[_STK - 1].f; + stack[_STK - 1].setFloat(stack[_STK].getFloat() + stack[_STK - 1].getFloat()); _STK--; break; case OP_SUB: - numStack[_STK - 1].f = numStack[_STK].f - numStack[_STK - 1].f; + stack[_STK - 1].setFloat(stack[_STK].getFloat() - stack[_STK - 1].getFloat()); _STK--; break; case OP_MUL: - numStack[_STK - 1].f = numStack[_STK].f * numStack[_STK - 1].f; + stack[_STK - 1].setFloat(stack[_STK].getFloat() * stack[_STK - 1].getFloat()); _STK--; break; + case OP_DIV: - numStack[_STK - 1].f = numStack[_STK].f / numStack[_STK - 1].f; + stack[_STK - 1].setFloat(stack[_STK].getFloat() / stack[_STK - 1].getFloat()); _STK--; break; + case OP_NEG: - numStack[_STK].f = -numStack[_STK].f; + stack[_STK].setFloat(-stack[_STK].getFloat()); break; case OP_INC: @@ -1286,7 +1299,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa break; case OP_SETCURVAR_ARRAY: - var = STR.getSTValue(); + var = StringTable->insert(stack[_STK].getString()); // See OP_SETCURVAR prevField = NULL; @@ -1301,7 +1314,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa break; case OP_SETCURVAR_ARRAY_CREATE: - var = STR.getSTValue(); + var = StringTable->insert(stack[_STK].getString()); // See OP_SETCURVAR prevField = NULL; @@ -1316,69 +1329,72 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa break; case OP_LOADVAR_UINT: - numStack[_STK + 1].i = gEvalState.getIntVariable(); + stack[_STK + 1].setInt(gEvalState.getIntVariable()); _STK++; break; case OP_LOADVAR_FLT: - numStack[_STK + 1].f = gEvalState.getFloatVariable(); + stack[_STK + 1].setFloat(gEvalState.getFloatVariable()); _STK++; break; case OP_LOADVAR_STR: - val = gEvalState.getStringVariable(); - STR.setStringValue(val); + stack[_STK + 1].setString(gEvalState.getStringVariable()); + _STK++; break; case OP_SAVEVAR_UINT: - gEvalState.setIntVariable(numStack[_STK].i); + gEvalState.setIntVariable(stack[_STK].getInt()); break; case OP_SAVEVAR_FLT: - gEvalState.setFloatVariable(numStack[_STK].f); + gEvalState.setFloatVariable(stack[_STK].getFloat()); break; case OP_SAVEVAR_STR: - gEvalState.setStringVariable(STR.getStringValue()); + gEvalState.setStringVariable(stack[_STK].getString()); break; case OP_LOAD_LOCAL_VAR_UINT: reg = code[ip++]; - numStack[_STK + 1].i = gEvalState.getLocalIntVariable(reg); + stack[_STK + 1].setInt(gEvalState.getLocalIntVariable(reg)); _STK++; break; case OP_LOAD_LOCAL_VAR_FLT: reg = code[ip++]; - numStack[_STK + 1].f = gEvalState.getLocalFloatVariable(reg); + stack[_STK + 1].setFloat(gEvalState.getLocalFloatVariable(reg)); _STK++; break; case OP_LOAD_LOCAL_VAR_STR: reg = code[ip++]; val = gEvalState.getLocalStringVariable(reg); - STR.setStringValue(val); + stack[_STK + 1].setString(val); + _STK++; break; case OP_SAVE_LOCAL_VAR_UINT: reg = code[ip++]; - gEvalState.setLocalIntVariable(reg, numStack[_STK].i); + gEvalState.setLocalIntVariable(reg, stack[_STK].getInt()); break; case OP_SAVE_LOCAL_VAR_FLT: reg = code[ip++]; - gEvalState.setLocalFloatVariable(reg, numStack[_STK].f); + gEvalState.setLocalFloatVariable(reg, stack[_STK].getFloat()); break; case OP_SAVE_LOCAL_VAR_STR: reg = code[ip++]; - gEvalState.setLocalStringVariable(reg, STR.getStringValue(), (S32)STR.mLen); + val = stack[_STK].getString(); + gEvalState.setLocalStringVariable(reg, val, (S32)dStrlen(val)); break; case OP_SETCUROBJECT: // Save the previous object for parsing vector fields. prevObject = curObject; - val = STR.getStringValue(); + val = stack[_STK].getString(); + _STK--; // Sim::findObject will sometimes find valid objects from // multi-component strings. This makes sure that doesn't @@ -1401,16 +1417,15 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa SimGroup* group = dynamic_cast(curObject); if (group) { - StringTableEntry intName = StringTable->insert(STR.getStringValue()); + StringTableEntry intName = StringTable->insert(stack[_STK].getString()); bool recurse = code[ip - 1]; SimObject* obj = group->findObjectByInternalName(intName, recurse); - numStack[_STK + 1].i = obj ? obj->getId() : 0; - _STK++; + stack[_STK].setInt(obj ? obj->getId() : 0); } else { Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-group %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName()); - numStack[_STK].i = 0; + stack[_STK].setInt(0); } } break; @@ -1429,7 +1444,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa break; case OP_SETCURFIELD_ARRAY: - dStrcpy(curFieldArray, STR.getStringValue(), 256); + dStrcpy(curFieldArray, stack[_STK].getString(), 256); break; case OP_SETCURFIELD_TYPE: @@ -1440,7 +1455,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa case OP_LOADFIELD_UINT: if (curObject) - numStack[_STK + 1].i = dAtol(curObject->getDataField(curField, curFieldArray)); + stack[_STK + 1].setInt(dAtol(curObject->getDataField(curField, curFieldArray))); else { // The field is not being retrieved from an object. Maybe it's @@ -1448,14 +1463,14 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa char buff[FieldBufferSizeNumeric]; memset(buff, 0, sizeof(buff)); getFieldComponent(prevObject, prevField, prevFieldArray, curField, buff); - numStack[_STK + 1].i = dAtol(buff); + stack[_STK + 1].setInt(dAtol(buff)); } _STK++; break; case OP_LOADFIELD_FLT: if (curObject) - numStack[_STK + 1].f = dAtod(curObject->getDataField(curField, curFieldArray)); + stack[_STK + 1].setFloat(dAtod(curObject->getDataField(curField, curFieldArray))); else { // The field is not being retrieved from an object. Maybe it's @@ -1463,7 +1478,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa char buff[FieldBufferSizeNumeric]; memset(buff, 0, sizeof(buff)); getFieldComponent(prevObject, prevField, prevFieldArray, curField, buff); - numStack[_STK + 1].f = dAtod(buff); + stack[_STK + 1].setFloat(dAtod(buff)); } _STK++; break; @@ -1472,7 +1487,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa if (curObject) { val = curObject->getDataField(curField, curFieldArray); - STR.setStringValue(val); + stack[_STK + 1].setString(val); } else { @@ -1481,15 +1496,14 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa char buff[FieldBufferSizeString]; memset(buff, 0, sizeof(buff)); getFieldComponent(prevObject, prevField, prevFieldArray, curField, buff); - STR.setStringValue(buff); + stack[_STK + 1].setString(buff); } - + _STK++; break; case OP_SAVEFIELD_UINT: - STR.setIntValue(numStack[_STK].i); if (curObject) - curObject->setDataField(curField, curFieldArray, STR.getStringValue()); + curObject->setDataField(curField, curFieldArray, stack[_STK].getString()); else { // The field is not being set on an object. Maybe it's @@ -1500,9 +1514,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa break; case OP_SAVEFIELD_FLT: - STR.setFloatValue(numStack[_STK].f); if (curObject) - curObject->setDataField(curField, curFieldArray, STR.getStringValue()); + curObject->setDataField(curField, curFieldArray, stack[_STK].getString()); else { // The field is not being set on an object. Maybe it's @@ -1514,7 +1527,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa case OP_SAVEFIELD_STR: if (curObject) - curObject->setDataField(curField, curFieldArray, STR.getStringValue()); + curObject->setDataField(curField, curFieldArray, stack[_STK].getString()); else { // The field is not being set on an object. Maybe it's @@ -1524,51 +1537,20 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa } break; - case OP_STR_TO_UINT: - numStack[_STK + 1].i = STR.getIntValue(); - _STK++; - break; - - case OP_STR_TO_FLT: - numStack[_STK + 1].f = STR.getFloatValue(); - _STK++; - break; - - case OP_STR_TO_NONE: - // This exists simply to deal with certain typecast situations. - break; - - case OP_FLT_TO_UINT: - numStack[_STK].i = (S64)numStack[_STK].f; - break; - - case OP_FLT_TO_STR: - STR.setFloatValue(numStack[_STK].f); - _STK--; - break; - - case OP_UINT_TO_FLT: - numStack[_STK].f = (F64)numStack[_STK].i; - break; - - case OP_UINT_TO_STR: - STR.setIntValue(numStack[_STK].i); - _STK--; - break; - - case OP_NUM_TO_NONE: + case OP_POP_STK: _STK--; break; case OP_LOADIMMED_UINT: - numStack[_STK + 1].i = code[ip++]; + stack[_STK + 1].setInt(code[ip++]); _STK++; break; case OP_LOADIMMED_FLT: - numStack[_STK + 1].f = curFloatTable[code[ip++]]; + stack[_STK + 1].setFloat(curFloatTable[code[ip++]]); _STK++; break; + case OP_TAG_TO_STR: code[ip - 1] = OP_LOADIMMED_STR; // it's possible the string has already been converted @@ -1578,8 +1560,11 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa dSprintf(curStringTable + code[ip] + 1, 7, "%d", id); *(curStringTable + code[ip]) = StringTagPrefixByte; } + TORQUE_CASE_FALLTHROUGH; + case OP_LOADIMMED_STR: - STR.setStringValue(curStringTable + code[ip++]); + stack[_STK + 1].setString(curStringTable + code[ip++]); + _STK ++; break; case OP_DOCBLOCK_STR: @@ -1614,7 +1599,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa break; case OP_LOADIMMED_IDENT: - STR.setStringValue(CodeToSTE(code, ip)); + stack[_STK + 1].setString(CodeToSTE(code, ip)); + _STK++; ip += 2; break; @@ -1652,8 +1638,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa Con::warnf(ConsoleLogEntry::General, "%s: Unable to find function %s", getFileLine(ip - 4), fnName); - //STR.popFrame(); + gCallStack.popFrame(); + stack[_STK + 1].setEmptyString(); + _STK++; break; } } @@ -1668,8 +1656,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa "%s: Unable to find function %s%s%s", getFileLine(ip - 4), fnNamespace ? fnNamespace : "", fnNamespace ? "::" : "", fnName); - //STR.popFrame(); + gCallStack.popFrame(); + stack[_STK + 1].setEmptyString(); + _STK++; break; } } @@ -1702,9 +1692,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa simObjectLookupValue.getString(), fnName ); - //STR.popFrame(); + gCallStack.popFrame(); - STR.setStringValue(""); + stack[_STK + 1].setEmptyString(); + _STK++; break; } @@ -1744,8 +1735,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa } } gCallStack.popFrame(); - STR.setStringValue(""); - STR.setStringValue(""); + stack[_STK + 1].setEmptyString(); + _STK++; break; } if (nsEntry->mType == Namespace::Entry::ConsoleFunctionType) @@ -1754,10 +1745,11 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa { // TODO: not make this strings only for returns. ConsoleValue returnFromFn = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage); - STR.setStringValue(returnFromFn.getString()); + stack[_STK + 1] = std::move(returnFromFn); } else // no body - STR.setStringValue(""); + stack[_STK + 1].setEmptyString(); + _STK++; gCallStack.popFrame(); } @@ -1769,7 +1761,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments.", getFileLine(ip - 4), nsName, fnName); Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", getFileLine(ip - 4), nsEntry->mUsage); gCallStack.popFrame(); - STR.setStringValue(""); + stack[_STK + 1].setEmptyString(); + _STK++; } else { @@ -1777,87 +1770,73 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa { case Namespace::Entry::StringCallbackType: { - const char* ret = nsEntry->cb.mStringCallbackFunc(gEvalState.thisObject, callArgc, callArgv); + const char* result = nsEntry->cb.mStringCallbackFunc(gEvalState.thisObject, callArgc, callArgv); gCallStack.popFrame(); - if (ret != STR.getStringValue()) - STR.setStringValue(ret); - else - STR.setLen(dStrlen(ret)); + stack[_STK + 1].setString(result); + _STK++; break; } case Namespace::Entry::IntCallbackType: { S64 result = nsEntry->cb.mIntCallbackFunc(gEvalState.thisObject, callArgc, callArgv); gCallStack.popFrame(); - if (code[ip] == OP_STR_TO_UINT) + + if (code[ip] == OP_POP_STK) { ip++; - numStack[++_STK].i = result; break; } - else if (code[ip] == OP_STR_TO_FLT) - { - ip++; - numStack[++_STK].f = result; - break; - } - else if (code[ip] == OP_STR_TO_NONE) - ip++; - else - STR.setIntValue(result); + + stack[_STK + 1].setInt(result); + _STK++; break; } case Namespace::Entry::FloatCallbackType: { F64 result = nsEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, callArgc, callArgv); gCallStack.popFrame(); - if (code[ip] == OP_STR_TO_UINT) + + if (code[ip] == OP_POP_STK) { ip++; - numStack[++_STK].i = (S64)result; break; } - else if (code[ip] == OP_STR_TO_FLT) - { - ip++; - numStack[++_STK].f = result; - break; - } - else if (code[ip] == OP_STR_TO_NONE) - ip++; - else - STR.setFloatValue(result); + + stack[_STK + 1].setInt(result); + _STK++; break; } case Namespace::Entry::VoidCallbackType: { nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv); - if (code[ip] != OP_STR_TO_NONE) - Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip - 4), fnName, functionName); gCallStack.popFrame(); - STR.setStringValue(""); + + if (code[ip] == OP_POP_STK) + { + ip++; + break; + } + + Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip - 4), fnName, functionName); + stack[_STK + 1].setEmptyString(); + _STK++; + break; } case Namespace::Entry::BoolCallbackType: { bool result = nsEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, callArgc, callArgv); gCallStack.popFrame(); - if (code[ip] == OP_STR_TO_UINT) + + if (code[ip] == OP_POP_STK) { ip++; - numStack[++_STK].i = result; break; } - else if (code[ip] == OP_STR_TO_FLT) - { - ip++; - numStack[++_STK].f = result; - break; - } - else if (code[ip] == OP_STR_TO_NONE) - ip++; - else - STR.setIntValue(result); + + stack[_STK + 1].setBool(result); + _STK++; + break; } } @@ -1868,43 +1847,45 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa gEvalState.thisObject = saveObject; break; } - case OP_ADVANCE_STR: - STR.advance(); - break; + case OP_ADVANCE_STR_APPENDCHAR: - STR.advanceChar(code[ip++]); - break; + { + // TODO: Create a better way to handle string concatination without + // heap allocating every time. - case OP_ADVANCE_STR_COMMA: - STR.advanceChar('_'); - break; + val = stack[_STK].getString(); + dsize_t len = dStrlen(val) + 2; + + char buff[2]; + buff[0] = (char)code[ip++]; + buff[1] = '\0'; + + char* concat = new char[len]; + dMemset(concat, 0, len); + dStrcat(concat, val, len); + dStrcat(concat, buff, len); + + stack[_STK].setString(concat); + + delete[] concat; - case OP_ADVANCE_STR_NUL: - STR.advanceChar(0); break; + } case OP_REWIND_STR: - STR.rewind(); - break; - + TORQUE_CASE_FALLTHROUGH; case OP_TERMINATE_REWIND_STR: - STR.rewindTerminate(); + stack[_STK - 1].setString((String(stack[_STK - 1] + String(stack[_STK])))); + _STK--; break; case OP_COMPARE_STR: - numStack[++_STK].i = STR.compare(); + stack[_STK - 1].setBool(!dStricmp(stack[_STK].getString(), stack[_STK - 1].getString())); + _STK--; break; case OP_PUSH: - gCallStack.pushString(STR.getStringValue(), STR.mLen); - break; - - case OP_PUSH_UINT: - gCallStack.pushInt((U32)numStack[_STK--].i); - break; - - case OP_PUSH_FLT: - gCallStack.pushFloat(numStack[_STK--].f); + gCallStack.push(std::move(stack[_STK--])); break; case OP_PUSH_FRAME: @@ -1913,7 +1894,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa case OP_ASSERT: { - if (!numStack[_STK--].i) + if (!stack[_STK--].getBool()) { const char* message = curStringTable + code[ip]; @@ -1957,7 +1938,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa case OP_ITER_BEGIN_STR: { iterStack[_ITER].mIsStringIter = true; - /* fallthrough */ + TORQUE_CASE_FALLTHROUGH; } case OP_ITER_BEGIN: @@ -1981,7 +1962,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa if (iter.mIsStringIter) { - iter.mData.mStr.mString = STR.getStringValue(); + iter.mData.mStr.mString = stack[_STK].getString(); iter.mData.mStr.mIndex = 0; } else @@ -1989,9 +1970,9 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa // Look up the object. SimSet* set; - if (!Sim::findObject(STR.getStringValue(), set)) + if (!Sim::findObject(stack[_STK].getString(), set)) { - Con::errorf(ConsoleLogEntry::General, "No SimSet object '%s'", STR.getStringValue()); + Con::errorf(ConsoleLogEntry::General, "No SimSet object '%s'", stack[_STK].getString()); Con::errorf(ConsoleLogEntry::General, "Did you mean to use 'foreach$' instead of 'foreach'?"); ip = failIp; continue; @@ -2006,8 +1987,6 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa _ITER++; iterDepth++; - STR.push(); - ip += isGlobal ? 4 : 3; break; } @@ -2096,16 +2075,17 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa --_ITER; --iterDepth; - STR.rewind(); + _STK--; iterStack[_ITER].mIsStringIter = false; break; } case OP_INVALID: - + TORQUE_CASE_FALLTHROUGH; default: // error! + AssertISV(false, "Invalid OPCode Processed!"); goto execFinished; } } @@ -2162,8 +2142,8 @@ execFinished: decRefCount(); #ifdef TORQUE_DEBUG - AssertFatal(!(STR.mStartStackSize > stackStart), "String stack not popped enough in script exec"); - AssertFatal(!(STR.mStartStackSize < stackStart), "String stack popped too much in script exec"); + AssertFatal(!(_STK > stackStart), "String stack not popped enough in script exec"); + AssertFatal(!(_STK < stackStart), "String stack popped too much in script exec"); #endif return std::move(returnValue); diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index f0633deab..128088827 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -69,6 +69,7 @@ namespace Compiler OP_RETURN_FLT, OP_RETURN_UINT, + OP_CMPEQ, OP_CMPGR, OP_CMPGE, @@ -132,14 +133,7 @@ namespace Compiler OP_SAVEFIELD_FLT, OP_SAVEFIELD_STR, - OP_STR_TO_UINT, - OP_STR_TO_FLT, - OP_STR_TO_NONE, // 60 - OP_FLT_TO_UINT, - OP_FLT_TO_STR, - OP_UINT_TO_FLT, - OP_UINT_TO_STR, - OP_NUM_TO_NONE, + OP_POP_STK, OP_LOADIMMED_UINT, OP_LOADIMMED_FLT, @@ -150,18 +144,14 @@ namespace Compiler OP_CALLFUNC, - OP_ADVANCE_STR, OP_ADVANCE_STR_APPENDCHAR, - OP_ADVANCE_STR_COMMA, - OP_ADVANCE_STR_NUL, OP_REWIND_STR, - OP_TERMINATE_REWIND_STR, // 80 + OP_TERMINATE_REWIND_STR, + OP_COMPARE_STR, - OP_PUSH, // String - OP_PUSH_UINT, // Integer - OP_PUSH_FLT, // Float - OP_PUSH_FRAME, // Frame + OP_PUSH, + OP_PUSH_FRAME, OP_ASSERT, OP_BREAK, diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index d42c202a7..b36a7c233 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -174,14 +174,7 @@ class ConsoleValue } } -public: - explicit ConsoleValue() - { - type = ConsoleValueType::cvSTEntry; - s = const_cast(StringTable->EmptyString()); - } - - ConsoleValue(ConsoleValue&& ref) noexcept + TORQUE_FORCEINLINE void _move(ConsoleValue&& ref) noexcept { type = ref.type; @@ -207,6 +200,24 @@ public: ref.setEmptyString(); } +public: + ConsoleValue() + { + type = ConsoleValueType::cvSTEntry; + s = const_cast(StringTable->EmptyString()); + } + + ConsoleValue(ConsoleValue&& ref) noexcept + { + _move(std::move(ref)); + } + + TORQUE_FORCEINLINE ConsoleValue& operator=(ConsoleValue&& ref) noexcept + { + _move(std::move(ref)); + return *this; + } + ConsoleValue(const ConsoleValue&) = delete; ConsoleValue& operator=(const ConsoleValue&) = delete; diff --git a/Engine/source/console/consoleValueStack.h b/Engine/source/console/consoleValueStack.h index b88804dd5..8b44a652c 100644 --- a/Engine/source/console/consoleValueStack.h +++ b/Engine/source/console/consoleValueStack.h @@ -89,22 +89,10 @@ public: stack.pop_back(); } - TORQUE_FORCEINLINE void pushInt(S64 value) + TORQUE_FORCEINLINE void push(ConsoleValue&& val) { Frame& frame = stack.last(); - frame.values[frame.internalCounter++].setInt(value); - } - - TORQUE_FORCEINLINE void pushFloat(F64 value) - { - Frame& frame = stack.last(); - frame.values[frame.internalCounter++].setFloat(value); - } - - TORQUE_FORCEINLINE void pushString(const char* value, S32 len) - { - Frame& frame = stack.last(); - frame.values[frame.internalCounter++].setString(value, len); + frame.values[frame.internalCounter++] = std::move(val); } TORQUE_FORCEINLINE void argvc(StringTableEntry fn, S32& argc, ConsoleValue** argv) diff --git a/Engine/source/console/test/ScriptTest.cpp b/Engine/source/console/test/ScriptTest.cpp index ecf3ae3f9..ecc974d2f 100644 --- a/Engine/source/console/test/ScriptTest.cpp +++ b/Engine/source/console/test/ScriptTest.cpp @@ -60,6 +60,60 @@ TEST(Script, Basic_Arithmetic) )"); ASSERT_EQ(div.getInt(), 5); + + ConsoleValue mod = RunScript(R"( + return 4 % 5; + )"); + + ASSERT_EQ(mod.getInt(), 4); + + ConsoleValue add2 = RunScript(R"( + $a = 0; + $a += 2; + return $a; + )"); + + ASSERT_EQ(add2.getInt(), 2); + + ConsoleValue sub2 = RunScript(R"( + $a = 0; + $a -= 2; + return $a; + )"); + + ASSERT_EQ(sub2.getInt(), -2); + + ConsoleValue mult2 = RunScript(R"( + $a = 2; + $a *= 3; + return $a; + )"); + + ASSERT_EQ(mult2.getInt(), 6); + + ConsoleValue div2 = RunScript(R"( + $a = 10; + $a /= 2; + return $a; + )"); + + ASSERT_EQ(div2.getInt(), 5); + + ConsoleValue pp = RunScript(R"( + $a = 0; + $a++; + return $a; + )"); + + ASSERT_EQ(pp.getInt(), 1); + + ConsoleValue mm = RunScript(R"( + $a = 2; + $a--; + return $a; + )"); + + ASSERT_EQ(mm.getInt(), 1); } TEST(Script, Complex_Arithmetic) @@ -240,6 +294,20 @@ TEST(Script, Basic_Loop_Statements) ASSERT_STREQ(forValue.getString(), "aaa"); + ConsoleValue forReverseLoop = RunScript(R"( + function t(%times) + { + %result = ""; + for (%i = %times - 1; %i >= 0; %i--) + %result = %result @ "b"; + return %result; + } + + return t(3); + )"); + + ASSERT_STREQ(forReverseLoop.getString(), "bbb"); + ConsoleValue forIfValue = RunScript(R"( function t() { @@ -402,6 +470,77 @@ TEST(Script, Basic_SimObject) )"); ASSERT_STREQ(parentFn.getString(), "FooBar"); + + ConsoleValue grp = RunScript(R"( + new SimGroup(FudgeCollectorGroup) + { + theName = "fudge"; + + new SimObject(ChocolateFudge) + { + type = "Chocolate"; + }; + new SimObject(PeanutButterFudge) + { + type = "Peanut Butter"; + + field["a"] = "Yes"; + }; + }; + + return FudgeCollectorGroup.getId(); + )"); + + SimGroup* simGroup = dynamic_cast(Sim::findObject(grp)); + ASSERT_NE(simGroup, (SimGroup*)NULL); + ASSERT_EQ(simGroup->size(), 2); + + simGroup->deleteObject(); + + ConsoleValue fieldTest = RunScript(R"( + function a() + { + %obj = new SimObject(); + %obj.field = "A"; + %obj.val[%obj.field] = "B"; + + %value = %obj.val["A"]; + %obj.delete(); + return %value; + } + return a(); + )"); + + ASSERT_STREQ(fieldTest.getString(), "B"); +} + +TEST(Script, Internal_Name) +{ + ConsoleValue value = RunScript(R"( + function SimObject::_internalCall(%this) + { + return 5; + } + + function a() + { + %grp = new SimGroup(); + %obj = new SimObject() + { + internalName = "Yay"; + }; + %grp.add(%obj); + + %val = %grp->Yay._internalCall(); + + %grp.delete(); + + return %val; + } + return a(); + )"); + + ASSERT_EQ(value.getInt(), 5); } TEST(Script, Basic_Package)