diff --git a/Engine/source/console/ast.h b/Engine/source/console/ast.h index 71cfbeec0..f6e81de4c 100644 --- a/Engine/source/console/ast.h +++ b/Engine/source/console/ast.h @@ -38,7 +38,8 @@ enum TypeReq TypeReqNone, TypeReqUInt, TypeReqFloat, - TypeReqString + TypeReqString, + TypeReqVar }; /// Representation of a node for the scripting language parser. diff --git a/Engine/source/console/astNodes.cpp b/Engine/source/console/astNodes.cpp index 31b337c35..ae09abbd2 100644 --- a/Engine/source/console/astNodes.cpp +++ b/Engine/source/console/astNodes.cpp @@ -134,6 +134,8 @@ static U32 conversionOp(TypeReq src, TypeReq dst) return OP_STR_TO_FLT; case TypeReqNone: return OP_STR_TO_NONE; + case TypeReqVar: + return OP_SAVEVAR_STR; default: break; } @@ -148,6 +150,8 @@ static U32 conversionOp(TypeReq src, TypeReq dst) return OP_FLT_TO_STR; case TypeReqNone: return OP_FLT_TO_NONE; + case TypeReqVar: + return OP_SAVEVAR_FLT; default: break; } @@ -162,6 +166,24 @@ static U32 conversionOp(TypeReq src, TypeReq dst) return OP_UINT_TO_STR; case TypeReqNone: return OP_UINT_TO_NONE; + case TypeReqVar: + return OP_SAVEVAR_UINT; + default: + break; + } + } + else if(src == TypeReqVar) + { + switch(dst) + { + case TypeReqUInt: + return OP_LOADVAR_UINT; + case TypeReqFloat: + return OP_LOADVAR_FLT; + case TypeReqString: + return OP_LOADVAR_STR; + case TypeReqNone: + return OP_COPYVAR_TO_NONE; default: break; } @@ -872,6 +894,7 @@ U32 VarNode::precompile(TypeReq type) return (arrayIndex ? arrayIndex->precompile(TypeReqString) + 6 : 3); } +// Puts value of VarNode onto StringStack/intStack/fltStack U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type) { if(type == TypeReqNone) @@ -882,10 +905,11 @@ U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type) ip++; if(arrayIndex) { + // NOTE: in this case we have the start value loaded into STR codeStream[ip++] = OP_ADVANCE_STR; - ip = arrayIndex->compile(codeStream, ip, TypeReqString); - codeStream[ip++] = OP_REWIND_STR; - codeStream[ip++] = OP_SETCURVAR_ARRAY; + ip = arrayIndex->compile(codeStream, ip, TypeReqString); // Add on extra bits + codeStream[ip++] = OP_REWIND_STR; // Go back to start + codeStream[ip++] = OP_SETCURVAR_ARRAY; // Set variable name } switch(type) { @@ -898,8 +922,13 @@ U32 VarNode::compile(U32 *codeStream, U32 ip, TypeReq type) case TypeReqString: codeStream[ip++] = OP_LOADVAR_STR; break; + case TypeReqVar: + codeStream[ip++] = OP_LOADVAR_VAR; + break; case TypeReqNone: break; + default: + break; } return ip; } @@ -1105,8 +1134,15 @@ U32 AssignExprNode::precompile(TypeReq type) subType = expr->getPreferredType(); if(subType == TypeReqNone) subType = type; - if(subType == TypeReqNone) - subType = TypeReqString; + if(subType == TypeReqNone) { + // jamesu - what we need to do in this case is turn it into a VarNode reference + if (dynamic_cast(expr) != NULL) { + // Sanity check passed + subType = TypeReqVar; + } else { + subType = TypeReqString; + } + } // if it's an array expr, the formula is: // eval expr // (push and pop if it's TypeReqString) OP_ADVANCE_STR @@ -1139,7 +1175,7 @@ U32 AssignExprNode::precompile(TypeReq type) U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) { - ip = expr->compile(codeStream, ip, subType); + ip = expr->compile(codeStream, ip, subType); // this is the value of VarNode if(arrayIndex) { if(subType == TypeReqString) @@ -1172,6 +1208,9 @@ U32 AssignExprNode::compile(U32 *codeStream, U32 ip, TypeReq type) case TypeReqFloat: codeStream[ip++] = OP_SAVEVAR_FLT; break; + case TypeReqVar: + codeStream[ip++] = OP_SAVEVAR_VAR; + break; case TypeReqNone: break; } diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index ca9e730fb..612ddad12 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -285,6 +285,24 @@ inline void ExprEvalState::setStringVariable(const char *val) currentVariable->setStringValue(val); } +inline void ExprEvalState::setCopyVariable() +{ + if (copyVariable) { + switch (copyVariable->value.type) + { + case ConsoleValue::TypeInternalInt: + currentVariable->setIntValue(copyVariable->getIntValue()); + break; + case ConsoleValue::TypeInternalFloat: + currentVariable->setFloatValue(copyVariable->getFloatValue()); + break; + default: + currentVariable->setStringValue(copyVariable->getStringValue()); + break; + } + } +} + //------------------------------------------------------------ // Gets a component of an object's field value or a variable and returns it @@ -1362,6 +1380,11 @@ breakContinue: STR.setStringValue(val); break; + case OP_LOADVAR_VAR: + // Sets current source of OP_SAVEVAR_VAR + gEvalState.copyVariable = gEvalState.currentVariable; + break; + case OP_SAVEVAR_UINT: gEvalState.setIntVariable(intStack[_UINT]); break; @@ -1373,6 +1396,11 @@ breakContinue: case OP_SAVEVAR_STR: gEvalState.setStringVariable(STR.getStringValue()); break; + + case OP_SAVEVAR_VAR: + // this basically handles %var1 = %var2 + gEvalState.setCopyVariable(); + break; case OP_SETCUROBJECT: // Save the previous object for parsing vector fields. @@ -1560,6 +1588,11 @@ breakContinue: _UINT--; break; + case OP_COPYVAR_TO_NONE: + // nop + gEvalState.copyVariable = NULL; + break; + case OP_LOADIMMED_UINT: intStack[_UINT+1] = code[ip++]; _UINT++; @@ -1940,6 +1973,13 @@ breakContinue: CSTK.pushFLT(floatStack[_FLT]); _FLT--; break; + case OP_PUSH_VAR: + //Con::printf("Pushing variable: %s",gEvalState.getCurrentVariable()]); + if (gEvalState.currentVariable) + CSTK.pushValue(gEvalState.currentVariable->value); + else + CSTK.pushString(""); + break; case OP_PUSH_FRAME: STR.pushFrame(); diff --git a/Engine/source/console/compiler.h b/Engine/source/console/compiler.h index 5354ee029..150b92b2e 100644 --- a/Engine/source/console/compiler.h +++ b/Engine/source/console/compiler.h @@ -90,10 +90,12 @@ namespace Compiler OP_LOADVAR_UINT, OP_LOADVAR_FLT, OP_LOADVAR_STR, + OP_LOADVAR_VAR, OP_SAVEVAR_UINT, OP_SAVEVAR_FLT, OP_SAVEVAR_STR, + OP_SAVEVAR_VAR, OP_SETCUROBJECT, OP_SETCUROBJECT_NEW, @@ -120,6 +122,7 @@ namespace Compiler OP_UINT_TO_FLT, OP_UINT_TO_STR, OP_UINT_TO_NONE, + OP_COPYVAR_TO_NONE, OP_LOADIMMED_UINT, OP_LOADIMMED_FLT, @@ -140,8 +143,9 @@ namespace Compiler OP_COMPARE_STR, OP_PUSH, // String - OP_PUSH_UINT, // Integer - OP_PUSH_FLT, // Float + OP_PUSH_UINT, // Integer + OP_PUSH_FLT, // Float + OP_PUSH_VAR, // Variable OP_PUSH_FRAME, // Frame OP_ASSERT, diff --git a/Engine/source/console/consoleInternal.h b/Engine/source/console/consoleInternal.h index 7893e6384..da465d74f 100644 --- a/Engine/source/console/consoleInternal.h +++ b/Engine/source/console/consoleInternal.h @@ -464,6 +464,7 @@ public: /// SimObject *thisObject; Dictionary::Entry *currentVariable; + Dictionary::Entry *copyVariable; bool traceOn; U32 mStackDepth; @@ -485,12 +486,14 @@ public: void setCurVarName(StringTableEntry name); void setCurVarNameCreate(StringTableEntry name); + S32 getIntVariable(); F64 getFloatVariable(); const char *getStringVariable(); void setIntVariable(S32 val); void setFloatVariable(F64 val); void setStringVariable(const char *str); + void setCopyVariable(); void pushFrame(StringTableEntry frameName, Namespace *ns); void popFrame();