Browse Source

initial port of the new interpreter

Jeff Hutchinson 4 years ago
parent
commit
35500a87c6
47 changed files with 3332 additions and 5360 deletions
  1. 10 3
      Engine/source/T3D/gameBase/gameConnection.cpp
  2. 2 2
      Engine/source/app/net/net.cpp
  3. 2 2
      Engine/source/app/net/tcpObject.cpp
  4. 1 1
      Engine/source/app/net/tcpObject.h
  5. 1 1
      Engine/source/console/SimXMLDocument.cpp
  6. 1 1
      Engine/source/console/SimXMLDocument.h
  7. 141 137
      Engine/source/console/ast.h
  8. 98 82
      Engine/source/console/astAlloc.cpp
  9. 306 423
      Engine/source/console/astNodes.cpp
  10. 597 674
      Engine/source/console/codeBlock.cpp
  11. 0 3018
      Engine/source/console/codeInterpreter.cpp
  12. 0 262
      Engine/source/console/codeInterpreter.h
  13. 1879 22
      Engine/source/console/compiledEval.cpp
  14. 9 15
      Engine/source/console/compiler.h
  15. 14 215
      Engine/source/console/console.cpp
  16. 9 156
      Engine/source/console/consoleInternal.cpp
  17. 57 26
      Engine/source/console/consoleInternal.h
  18. 4 4
      Engine/source/console/consoleLogger.cpp
  19. 1 1
      Engine/source/console/consoleLogger.h
  20. 121 0
      Engine/source/console/consoleValueStack.h
  21. 3 6
      Engine/source/console/sim.h
  22. 18 5
      Engine/source/console/simManager.cpp
  23. 9 3
      Engine/source/console/simSet.cpp
  24. 2 2
      Engine/source/console/simSet.h
  25. 0 225
      Engine/source/console/stringStack.cpp
  26. 0 44
      Engine/source/console/stringStack.h
  27. 2 0
      Engine/source/console/test/ScriptTest.cpp
  28. 3 0
      Engine/source/console/test/consoleTest.cpp
  29. 3 1
      Engine/source/console/test/engineAPITest.cpp
  30. 5 0
      Engine/source/core/strings/stringFunctions.h
  31. 1 1
      Engine/source/environment/waterObject.cpp
  32. 1 1
      Engine/source/environment/waterObject.h
  33. 1 1
      Engine/source/gui/core/guiControl.cpp
  34. 1 1
      Engine/source/gui/core/guiControl.h
  35. 3 3
      Engine/source/gui/worldEditor/worldEditor.cpp
  36. 1 1
      Engine/source/gui/worldEditor/worldEditor.h
  37. 12 7
      Engine/source/platformWin32/winMath.cpp
  38. 1 1
      Engine/source/sfx/sfxSource.cpp
  39. 1 1
      Engine/source/sfx/sfxSource.h
  40. 1 1
      Engine/source/sfx/sfxTrack.cpp
  41. 1 1
      Engine/source/sfx/sfxTrack.h
  42. 3 3
      Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp
  43. 1 1
      Engine/source/shaderGen/GLSL/customFeatureGLSL.h
  44. 3 3
      Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp
  45. 1 1
      Engine/source/shaderGen/HLSL/customFeatureHLSL.h
  46. 1 1
      Engine/source/shaderGen/customShaderFeature.cpp
  47. 1 1
      Engine/source/shaderGen/customShaderFeature.h

+ 10 - 3
Engine/source/T3D/gameBase/gameConnection.cpp

@@ -331,7 +331,7 @@ DefineEngineStringlyVariadicMethod(GameConnection, setConnectArgs, void, 3, 17,
    
    
    "@see GameConnection::onConnect()\n\n")
    "@see GameConnection::onConnect()\n\n")
 {
 {
-   StringStackWrapper args(argc - 2, argv + 2);
+   ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
    object->setConnectArgs(args.count(), args);
    object->setConnectArgs(args.count(), args);
 }
 }
 
 
@@ -494,11 +494,17 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
       *errorString = "CR_INVALID_ARGS";
       *errorString = "CR_INVALID_ARGS";
       return false;
       return false;
    }
    }
-   ConsoleValueRef connectArgv[MaxConnectArgs + 3];
+   ConsoleValue connectArgv[MaxConnectArgs + 3];
    ConsoleValue connectArgvValue[MaxConnectArgs + 3];
    ConsoleValue connectArgvValue[MaxConnectArgs + 3];
 
 
+   // TODO(JTH): Fix pls.
+   AssertISV(false, "TODO: FIX CONSOLE VALUE");
+   return false;
+
+   /*
    for(U32 i = 0; i < mConnectArgc+3; i++)
    for(U32 i = 0; i < mConnectArgc+3; i++)
    {
    {
+
       connectArgv[i].value = &connectArgvValue[i];
       connectArgv[i].value = &connectArgvValue[i];
       connectArgvValue[i].init();
       connectArgvValue[i].init();
    }
    }
@@ -524,6 +530,7 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
       return false;
       return false;
    }
    }
    return true;
    return true;
+   */
 }
 }
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
@@ -1088,7 +1095,7 @@ bool GameConnection::readDemoStartBlock(BitStream *stream)
 void GameConnection::demoPlaybackComplete()
 void GameConnection::demoPlaybackComplete()
 {
 {
    static const char* demoPlaybackArgv[1] = { "demoPlaybackComplete" };
    static const char* demoPlaybackArgv[1] = { "demoPlaybackComplete" };
-   static StringStackConsoleWrapper demoPlaybackCmd(1, demoPlaybackArgv);
+   static StringArrayToConsoleValueWrapper demoPlaybackCmd(1, demoPlaybackArgv);
 
 
    Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(demoPlaybackCmd.argc, demoPlaybackCmd.argv, false));
    Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(demoPlaybackCmd.argc, demoPlaybackCmd.argv, false));
    Parent::demoPlaybackComplete();
    Parent::demoPlaybackComplete();

+ 2 - 2
Engine/source/app/net/net.cpp

@@ -251,7 +251,7 @@ DefineEngineStringlyVariadicFunction( commandToServer, void, 2, RemoteCommandEve
    NetConnection *conn = NetConnection::getConnectionToServer();
    NetConnection *conn = NetConnection::getConnectionToServer();
    if(!conn)
    if(!conn)
       return;
       return;
-   StringStackWrapper args(argc - 1, argv + 1);
+   ConsoleValueToStringArrayWrapper args(argc - 1, argv + 1);
    RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
    RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
 }
 }
 
 
@@ -289,7 +289,7 @@ DefineEngineStringlyVariadicFunction( commandToClient, void, 3, RemoteCommandEve
    NetConnection *conn;
    NetConnection *conn;
    if(!Sim::findObject(argv[1], conn))
    if(!Sim::findObject(argv[1], conn))
       return;
       return;
-   StringStackWrapper args(argc - 2, argv + 2);
+   ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
    RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
    RemoteCommandEvent::sendRemoteCommand(conn, args.count(), args);
 }
 }
 
 

+ 2 - 2
Engine/source/app/net/tcpObject.cpp

@@ -236,13 +236,13 @@ TCPObject::~TCPObject()
    }
    }
 }
 }
 
 
-bool TCPObject::processArguments(S32 argc, ConsoleValueRef *argv)
+bool TCPObject::processArguments(S32 argc, ConsoleValue *argv)
 {
 {
    if(argc == 0)
    if(argc == 0)
       return true;
       return true;
    else if(argc == 1)
    else if(argc == 1)
    {
    {
-      addToTable(NetSocket::fromHandle(dAtoi(argv[0])));
+      addToTable(NetSocket::fromHandle(argv[0].getInt()));
       return true;
       return true;
    }
    }
    return false;
    return false;

+ 1 - 1
Engine/source/app/net/tcpObject.h

@@ -83,7 +83,7 @@ public:
    void disconnect();
    void disconnect();
    State getState() { return mState; }
    State getState() { return mState; }
 
 
-   bool processArguments(S32 argc, ConsoleValueRef *argv);
+   bool processArguments(S32 argc, ConsoleValue *argv);
    void send(const U8 *buffer, U32 bufferLen);
    void send(const U8 *buffer, U32 bufferLen);
 
 
    ///Send an entire file over tcp
    ///Send an entire file over tcp

+ 1 - 1
Engine/source/console/SimXMLDocument.cpp

@@ -158,7 +158,7 @@ SimXMLDocument::~SimXMLDocument()
 // -----------------------------------------------------------------------------
 // -----------------------------------------------------------------------------
 // Included for completeness.
 // Included for completeness.
 // -----------------------------------------------------------------------------
 // -----------------------------------------------------------------------------
-bool SimXMLDocument::processArguments(S32 argc, ConsoleValueRef *argv)
+bool SimXMLDocument::processArguments(S32 argc, ConsoleValue *argv)
 {
 {
    return argc == 0;
    return argc == 0;
 }
 }

+ 1 - 1
Engine/source/console/SimXMLDocument.h

@@ -57,7 +57,7 @@ class SimXMLDocument: public SimObject
       // tie in to the script language.  The .cc file has more in depth
       // tie in to the script language.  The .cc file has more in depth
       // comments on these.
       // comments on these.
       //-----------------------------------------------------------------------
       //-----------------------------------------------------------------------
-      bool processArguments(S32 argc, ConsoleValueRef *argv);
+      bool processArguments(S32 argc, ConsoleValue *argv);
       bool onAdd();
       bool onAdd();
       void onRemove();
       void onRemove();
       static void initPersistFields();
       static void initPersistFields();

+ 141 - 137
Engine/source/console/ast.h

@@ -39,8 +39,15 @@ enum TypeReq
    TypeReqNone,
    TypeReqNone,
    TypeReqUInt,
    TypeReqUInt,
    TypeReqFloat,
    TypeReqFloat,
-   TypeReqString,
-   TypeReqVar
+   TypeReqString
+};
+
+enum ExprNodeName
+{
+   NameExprNode,
+   NameFloatNode,
+   NameIntNode,
+   NameVarNode
 };
 };
 
 
 /// Representation of a node for the scripting language parser.
 /// Representation of a node for the scripting language parser.
@@ -52,7 +59,7 @@ enum TypeReq
 /// each representing a different language construct.
 /// each representing a different language construct.
 struct StmtNode
 struct StmtNode
 {
 {
-   StmtNode *mNext;   ///< Next entry in parse tree.
+   StmtNode* next;   ///< Next entry in parse tree.
 
 
    StmtNode();
    StmtNode();
    virtual ~StmtNode() {}
    virtual ~StmtNode() {}
@@ -61,8 +68,8 @@ struct StmtNode
    /// @{
    /// @{
 
 
    ///
    ///
-   void append(StmtNode *next);
-   StmtNode *getNext() const { return mNext; }
+   void append(StmtNode* next);
+   StmtNode* getNext() const { return next; }
 
 
    /// @}
    /// @}
 
 
@@ -79,93 +86,95 @@ struct StmtNode
    /// @name Breaking
    /// @name Breaking
    /// @{
    /// @{
 
 
-   void addBreakLine(CodeStream &codeStream);
+   void addBreakLine(CodeStream& codeStream);
    /// @}
    /// @}
 
 
    /// @name Compilation
    /// @name Compilation
    /// @{
    /// @{
 
 
-   virtual U32 compileStmt(CodeStream &codeStream, U32 ip) = 0;
+   virtual U32 compileStmt(CodeStream& codeStream, U32 ip) = 0;
    virtual void setPackage(StringTableEntry packageName);
    virtual void setPackage(StringTableEntry packageName);
    /// @}
    /// @}
 };
 };
 
 
 /// Helper macro
 /// Helper macro
 #ifndef DEBUG_AST_NODES
 #ifndef DEBUG_AST_NODES
-#  define DBG_STMT_TYPE(s) virtual String dbgStmtType() const { return String(#s); }
+#  define DBG_STMT_TYPE(s) virtual const char* dbgStmtType() const { return "#s"; }
 #else
 #else
 #  define DBG_STMT_TYPE(s) 
 #  define DBG_STMT_TYPE(s) 
 #endif
 #endif
 
 
 struct BreakStmtNode : StmtNode
 struct BreakStmtNode : StmtNode
 {
 {
-   static BreakStmtNode *alloc(S32 lineNumber);
+   static BreakStmtNode* alloc(S32 lineNumber);
 
 
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    DBG_STMT_TYPE(BreakStmtNode);
    DBG_STMT_TYPE(BreakStmtNode);
 };
 };
 
 
 struct ContinueStmtNode : StmtNode
 struct ContinueStmtNode : StmtNode
 {
 {
-   static ContinueStmtNode *alloc(S32 lineNumber);
+   static ContinueStmtNode* alloc(S32 lineNumber);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    DBG_STMT_TYPE(ContinueStmtNode);
    DBG_STMT_TYPE(ContinueStmtNode);
 };
 };
 
 
 /// A mathematical expression.
 /// A mathematical expression.
 struct ExprNode : StmtNode
 struct ExprNode : StmtNode
 {
 {
+   ExprNode* optimizedNode;
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
 
 
-   virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type) = 0;
+   virtual U32 compile(CodeStream& codeStream, U32 ip, TypeReq type) = 0;
    virtual TypeReq getPreferredType() = 0;
    virtual TypeReq getPreferredType() = 0;
+   virtual ExprNodeName getExprNodeNameEnum() const { return NameExprNode; }
 };
 };
 
 
 struct ReturnStmtNode : StmtNode
 struct ReturnStmtNode : StmtNode
 {
 {
-   ExprNode *expr;
+   ExprNode* expr;
 
 
-   static ReturnStmtNode *alloc(S32 lineNumber, ExprNode *expr);
+   static ReturnStmtNode* alloc(S32 lineNumber, ExprNode* expr);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    DBG_STMT_TYPE(ReturnStmtNode);
    DBG_STMT_TYPE(ReturnStmtNode);
 };
 };
 
 
 struct IfStmtNode : StmtNode
 struct IfStmtNode : StmtNode
 {
 {
-   ExprNode *testExpr;
-   StmtNode *ifBlock, *elseBlock;
+   ExprNode* testExpr;
+   StmtNode* ifBlock, * elseBlock;
    U32 endifOffset;
    U32 endifOffset;
    U32 elseOffset;
    U32 elseOffset;
    bool integer;
    bool integer;
    bool propagate;
    bool propagate;
 
 
-   static IfStmtNode *alloc(S32 lineNumber, ExprNode *testExpr, StmtNode *ifBlock, StmtNode *elseBlock, bool propagateThrough);
-   void propagateSwitchExpr(ExprNode *left, bool string);
-   ExprNode *getSwitchOR(ExprNode *left, ExprNode *list, bool string);
+   static IfStmtNode* alloc(S32 lineNumber, ExprNode* testExpr, StmtNode* ifBlock, StmtNode* elseBlock, bool propagateThrough);
+   void propagateSwitchExpr(ExprNode* left, bool string);
+   ExprNode* getSwitchOR(ExprNode* left, ExprNode* list, bool string);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    DBG_STMT_TYPE(IfStmtNode);
    DBG_STMT_TYPE(IfStmtNode);
 };
 };
 
 
 struct LoopStmtNode : StmtNode
 struct LoopStmtNode : StmtNode
 {
 {
-   ExprNode *testExpr;
-   ExprNode *initExpr;
-   ExprNode *endLoopExpr;
-   StmtNode *loopBlock;
+   ExprNode* testExpr;
+   ExprNode* initExpr;
+   ExprNode* endLoopExpr;
+   StmtNode* loopBlock;
    bool isDoLoop;
    bool isDoLoop;
    U32 breakOffset;
    U32 breakOffset;
    U32 continueOffset;
    U32 continueOffset;
    U32 loopBlockStartOffset;
    U32 loopBlockStartOffset;
    bool integer;
    bool integer;
 
 
-   static LoopStmtNode *alloc(S32 lineNumber, ExprNode *testExpr, ExprNode *initExpr, ExprNode *endLoopExpr, StmtNode *loopBlock, bool isDoLoop);
+   static LoopStmtNode* alloc(S32 lineNumber, ExprNode* testExpr, ExprNode* initExpr, ExprNode* endLoopExpr, StmtNode* loopBlock, bool isDoLoop);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    DBG_STMT_TYPE(LoopStmtNode);
    DBG_STMT_TYPE(LoopStmtNode);
 };
 };
 
 
@@ -189,35 +198,38 @@ struct IterStmtNode : StmtNode
 
 
    static IterStmtNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* containerExpr, StmtNode* body, bool isStringIter);
    static IterStmtNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* containerExpr, StmtNode* body, bool isStringIter);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
 };
 };
 
 
 /// A binary mathematical expression (ie, left op right).
 /// A binary mathematical expression (ie, left op right).
 struct BinaryExprNode : ExprNode
 struct BinaryExprNode : ExprNode
 {
 {
    S32 op;
    S32 op;
-   ExprNode *left;
-   ExprNode *right;
+   ExprNode* left;
+   ExprNode* right;
 };
 };
 
 
 struct FloatBinaryExprNode : BinaryExprNode
 struct FloatBinaryExprNode : BinaryExprNode
 {
 {
-   static FloatBinaryExprNode *alloc(S32 lineNumber, S32 op, ExprNode *left, ExprNode *right);
+   static FloatBinaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right);
+
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
+
+   bool optimize();
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FloatBinaryExprNode);
    DBG_STMT_TYPE(FloatBinaryExprNode);
 };
 };
 
 
 struct ConditionalExprNode : ExprNode
 struct ConditionalExprNode : ExprNode
 {
 {
-   ExprNode *testExpr;
-   ExprNode *trueExpr;
-   ExprNode *falseExpr;
+   ExprNode* testExpr;
+   ExprNode* trueExpr;
+   ExprNode* falseExpr;
    bool integer;
    bool integer;
-   static ConditionalExprNode *alloc(S32 lineNumber, ExprNode *testExpr, ExprNode *trueExpr, ExprNode *falseExpr);
+   static ConditionalExprNode* alloc(S32 lineNumber, ExprNode* testExpr, ExprNode* trueExpr, ExprNode* falseExpr);
 
 
-   virtual U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   virtual U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    virtual TypeReq getPreferredType();
    virtual TypeReq getPreferredType();
    DBG_STMT_TYPE(ConditionalExprNode);
    DBG_STMT_TYPE(ConditionalExprNode);
 };
 };
@@ -227,11 +239,13 @@ struct IntBinaryExprNode : BinaryExprNode
    TypeReq subType;
    TypeReq subType;
    U32 operand;
    U32 operand;
 
 
-   static IntBinaryExprNode *alloc(S32 lineNumber, S32 op, ExprNode *left, ExprNode *right);
+   static IntBinaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right);
 
 
    void getSubTypeOperand();
    void getSubTypeOperand();
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   bool optimize();
+
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(IntBinaryExprNode);
    DBG_STMT_TYPE(IntBinaryExprNode);
 };
 };
@@ -239,9 +253,9 @@ struct IntBinaryExprNode : BinaryExprNode
 struct StreqExprNode : BinaryExprNode
 struct StreqExprNode : BinaryExprNode
 {
 {
    bool eq;
    bool eq;
-   static StreqExprNode *alloc(S32 lineNumber, ExprNode *left, ExprNode *right, bool eq);
+   static StreqExprNode* alloc(S32 lineNumber, ExprNode* left, ExprNode* right, bool eq);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(StreqExprNode);
    DBG_STMT_TYPE(StreqExprNode);
 };
 };
@@ -249,19 +263,19 @@ struct StreqExprNode : BinaryExprNode
 struct StrcatExprNode : BinaryExprNode
 struct StrcatExprNode : BinaryExprNode
 {
 {
    S32 appendChar;
    S32 appendChar;
-   static StrcatExprNode *alloc(S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar);
+   static StrcatExprNode* alloc(S32 lineNumber, ExprNode* left, ExprNode* right, S32 appendChar);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(StrcatExprNode);
    DBG_STMT_TYPE(StrcatExprNode);
 };
 };
 
 
 struct CommaCatExprNode : BinaryExprNode
 struct CommaCatExprNode : BinaryExprNode
 {
 {
-   static CommaCatExprNode *alloc(S32 lineNumber, ExprNode *left, ExprNode *right);
+   static CommaCatExprNode* alloc(S32 lineNumber, ExprNode* left, ExprNode* right);
 
 
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(CommaCatExprNode);
    DBG_STMT_TYPE(CommaCatExprNode);
 };
 };
@@ -269,12 +283,12 @@ struct CommaCatExprNode : BinaryExprNode
 struct IntUnaryExprNode : ExprNode
 struct IntUnaryExprNode : ExprNode
 {
 {
    S32 op;
    S32 op;
-   ExprNode *expr;
+   ExprNode* expr;
    bool integer;
    bool integer;
 
 
-   static IntUnaryExprNode *alloc(S32 lineNumber, S32 op, ExprNode *expr);
+   static IntUnaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* expr);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(IntUnaryExprNode);
    DBG_STMT_TYPE(IntUnaryExprNode);
 };
 };
@@ -282,11 +296,11 @@ struct IntUnaryExprNode : ExprNode
 struct FloatUnaryExprNode : ExprNode
 struct FloatUnaryExprNode : ExprNode
 {
 {
    S32 op;
    S32 op;
-   ExprNode *expr;
+   ExprNode* expr;
 
 
-   static FloatUnaryExprNode *alloc(S32 lineNumber, S32 op, ExprNode *expr);
+   static FloatUnaryExprNode* alloc(S32 lineNumber, S32 op, ExprNode* expr);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FloatUnaryExprNode);
    DBG_STMT_TYPE(FloatUnaryExprNode);
 };
 };
@@ -294,12 +308,13 @@ struct FloatUnaryExprNode : ExprNode
 struct VarNode : ExprNode
 struct VarNode : ExprNode
 {
 {
    StringTableEntry varName;
    StringTableEntry varName;
-   ExprNode *arrayIndex;
+   ExprNode* arrayIndex;
 
 
-   static VarNode *alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex);
+   static VarNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
+   virtual ExprNodeName getExprNodeNameEnum() const { return NameVarNode; }
    DBG_STMT_TYPE(VarNode);
    DBG_STMT_TYPE(VarNode);
 };
 };
 
 
@@ -308,10 +323,11 @@ struct IntNode : ExprNode
    S32 value;
    S32 value;
    U32 index; // if it's converted to float/string
    U32 index; // if it's converted to float/string
 
 
-   static IntNode *alloc(S32 lineNumber, S32 value);
+   static IntNode* alloc(S32 lineNumber, S32 value);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
+   virtual ExprNodeName getExprNodeNameEnum() const { return NameIntNode; }
    DBG_STMT_TYPE(IntNode);
    DBG_STMT_TYPE(IntNode);
 };
 };
 
 
@@ -320,24 +336,25 @@ struct FloatNode : ExprNode
    F64 value;
    F64 value;
    U32 index;
    U32 index;
 
 
-   static FloatNode *alloc(S32 lineNumber, F64 value);
+   static FloatNode* alloc(S32 lineNumber, F64 value);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
+   virtual ExprNodeName getExprNodeNameEnum() const { return NameFloatNode; }
    DBG_STMT_TYPE(FloatNode);
    DBG_STMT_TYPE(FloatNode);
 };
 };
 
 
 struct StrConstNode : ExprNode
 struct StrConstNode : ExprNode
 {
 {
-   char *str;
+   char* str;
    F64 fVal;
    F64 fVal;
    U32 index;
    U32 index;
    bool tag;
    bool tag;
    bool doc; // Specifies that this string is a documentation block.
    bool doc; // Specifies that this string is a documentation block.
 
 
-   static StrConstNode *alloc(S32 lineNumber, char *str, bool tag, bool doc = false);
+   static StrConstNode* alloc(S32 lineNumber, char* str, bool tag, bool doc = false);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(StrConstNode);
    DBG_STMT_TYPE(StrConstNode);
 };
 };
@@ -348,9 +365,9 @@ struct ConstantNode : ExprNode
    F64 fVal;
    F64 fVal;
    U32 index;
    U32 index;
 
 
-   static ConstantNode *alloc(S32 lineNumber, StringTableEntry value);
+   static ConstantNode* alloc(S32 lineNumber, StringTableEntry value);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(ConstantNode);
    DBG_STMT_TYPE(ConstantNode);
 };
 };
@@ -358,13 +375,13 @@ struct ConstantNode : ExprNode
 struct AssignExprNode : ExprNode
 struct AssignExprNode : ExprNode
 {
 {
    StringTableEntry varName;
    StringTableEntry varName;
-   ExprNode *expr;
-   ExprNode *arrayIndex;
+   ExprNode* expr;
+   ExprNode* arrayIndex;
    TypeReq subType;
    TypeReq subType;
 
 
-   static AssignExprNode *alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr);
+   static AssignExprNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex, ExprNode* expr);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(AssignExprNode);
    DBG_STMT_TYPE(AssignExprNode);
 };
 };
@@ -373,22 +390,22 @@ struct AssignDecl
 {
 {
    S32 lineNumber;
    S32 lineNumber;
    S32 token;
    S32 token;
-   ExprNode *expr;
+   ExprNode* expr;
    bool integer;
    bool integer;
 };
 };
 
 
 struct AssignOpExprNode : ExprNode
 struct AssignOpExprNode : ExprNode
 {
 {
    StringTableEntry varName;
    StringTableEntry varName;
-   ExprNode *expr;
-   ExprNode *arrayIndex;
+   ExprNode* expr;
+   ExprNode* arrayIndex;
    S32 op;
    S32 op;
    U32 operand;
    U32 operand;
    TypeReq subType;
    TypeReq subType;
 
 
-   static AssignOpExprNode *alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr, S32 op);
+   static AssignOpExprNode* alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex, ExprNode* expr, S32 op);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(AssignOpExprNode);
    DBG_STMT_TYPE(AssignOpExprNode);
 };
 };
@@ -396,22 +413,22 @@ struct AssignOpExprNode : ExprNode
 struct TTagSetStmtNode : StmtNode
 struct TTagSetStmtNode : StmtNode
 {
 {
    StringTableEntry tag;
    StringTableEntry tag;
-   ExprNode *valueExpr;
-   ExprNode *stringExpr;
+   ExprNode* valueExpr;
+   ExprNode* stringExpr;
 
 
-   static TTagSetStmtNode *alloc(S32 lineNumber, StringTableEntry tag, ExprNode *valueExpr, ExprNode *stringExpr);
+   static TTagSetStmtNode* alloc(S32 lineNumber, StringTableEntry tag, ExprNode* valueExpr, ExprNode* stringExpr);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    DBG_STMT_TYPE(TTagSetStmtNode);
    DBG_STMT_TYPE(TTagSetStmtNode);
 };
 };
 
 
 struct TTagDerefNode : ExprNode
 struct TTagDerefNode : ExprNode
 {
 {
-   ExprNode *expr;
+   ExprNode* expr;
 
 
-   static TTagDerefNode *alloc(S32 lineNumber, ExprNode *expr);
+   static TTagDerefNode* alloc(S32 lineNumber, ExprNode* expr);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(TTagDerefNode);
    DBG_STMT_TYPE(TTagDerefNode);
 };
 };
@@ -420,9 +437,9 @@ struct TTagExprNode : ExprNode
 {
 {
    StringTableEntry tag;
    StringTableEntry tag;
 
 
-   static TTagExprNode *alloc(S32 lineNumber, StringTableEntry tag);
+   static TTagExprNode* alloc(S32 lineNumber, StringTableEntry tag);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(TTagExprNode);
    DBG_STMT_TYPE(TTagExprNode);
 };
 };
@@ -431,42 +448,31 @@ struct FuncCallExprNode : ExprNode
 {
 {
    StringTableEntry funcName;
    StringTableEntry funcName;
    StringTableEntry nameSpace;
    StringTableEntry nameSpace;
-   ExprNode *args;
+   ExprNode* args;
    U32 callType;
    U32 callType;
    enum {
    enum {
       FunctionCall,
       FunctionCall,
+      StaticCall,
       MethodCall,
       MethodCall,
       ParentCall
       ParentCall
    };
    };
 
 
-   static FuncCallExprNode *alloc(S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode *args, bool dot);
+   static FuncCallExprNode* alloc(S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode* args, bool dot);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(FuncCallExprNode);
    DBG_STMT_TYPE(FuncCallExprNode);
 };
 };
 
 
-struct FuncPointerCallExprNode : ExprNode
-{
-   ExprNode *funcPointer;
-   ExprNode *args;
-
-   static FuncPointerCallExprNode *alloc(S32 lineNumber, ExprNode *stmt, ExprNode *args);
-
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
-   TypeReq getPreferredType();
-   DBG_STMT_TYPE(FuncPointerCallExprNode);
-};
-
 struct AssertCallExprNode : ExprNode
 struct AssertCallExprNode : ExprNode
 {
 {
-   ExprNode *testExpr;
-   const char *message;
+   ExprNode* testExpr;
+   const char* message;
    U32 messageIndex;
    U32 messageIndex;
 
 
-   static AssertCallExprNode *alloc(S32 lineNumber, ExprNode *testExpr, const char *message);
+   static AssertCallExprNode* alloc(S32 lineNumber, ExprNode* testExpr, const char* message);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(AssertCallExprNode);
    DBG_STMT_TYPE(AssertCallExprNode);
 };
 };
@@ -474,19 +480,19 @@ struct AssertCallExprNode : ExprNode
 struct SlotDecl
 struct SlotDecl
 {
 {
    S32              lineNumber;
    S32              lineNumber;
-   ExprNode         *object;
+   ExprNode* object;
    StringTableEntry slotName;
    StringTableEntry slotName;
-   ExprNode         *array;
+   ExprNode* array;
 };
 };
 
 
 struct SlotAccessNode : ExprNode
 struct SlotAccessNode : ExprNode
 {
 {
-   ExprNode *objectExpr, *arrayExpr;
+   ExprNode* objectExpr, * arrayExpr;
    StringTableEntry slotName;
    StringTableEntry slotName;
 
 
-   static SlotAccessNode *alloc(S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName);
+   static SlotAccessNode* alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* arrayExpr, StringTableEntry slotName);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(SlotAccessNode);
    DBG_STMT_TYPE(SlotAccessNode);
 };
 };
@@ -494,101 +500,99 @@ struct SlotAccessNode : ExprNode
 struct InternalSlotDecl
 struct InternalSlotDecl
 {
 {
    S32              lineNumber;
    S32              lineNumber;
-   ExprNode         *object;
-   ExprNode         *slotExpr;
+   ExprNode* object;
+   ExprNode* slotExpr;
    bool             recurse;
    bool             recurse;
 };
 };
 
 
 struct InternalSlotAccessNode : ExprNode
 struct InternalSlotAccessNode : ExprNode
 {
 {
-   ExprNode *objectExpr, *slotExpr;
+   ExprNode* objectExpr, * slotExpr;
    bool recurse;
    bool recurse;
 
 
-   static InternalSlotAccessNode *alloc(S32 lineNumber, ExprNode *objectExpr, ExprNode *slotExpr, bool recurse);
+   static InternalSlotAccessNode* alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* slotExpr, bool recurse);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(InternalSlotAccessNode);
    DBG_STMT_TYPE(InternalSlotAccessNode);
 };
 };
 
 
 struct SlotAssignNode : ExprNode
 struct SlotAssignNode : ExprNode
 {
 {
-   ExprNode *objectExpr, *arrayExpr;
+   ExprNode* objectExpr, * arrayExpr;
    StringTableEntry slotName;
    StringTableEntry slotName;
-   ExprNode *valueExpr;
+   ExprNode* valueExpr;
    U32 typeID;
    U32 typeID;
 
 
-   static SlotAssignNode *alloc(S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName, ExprNode *valueExpr, U32 typeID = -1);
+   static SlotAssignNode* alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* arrayExpr, StringTableEntry slotName, ExprNode* valueExpr, U32 typeID = -1);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(SlotAssignNode);
    DBG_STMT_TYPE(SlotAssignNode);
 };
 };
 
 
 struct SlotAssignOpNode : ExprNode
 struct SlotAssignOpNode : ExprNode
 {
 {
-   ExprNode *objectExpr, *arrayExpr;
+   ExprNode* objectExpr, * arrayExpr;
    StringTableEntry slotName;
    StringTableEntry slotName;
    S32 op;
    S32 op;
-   ExprNode *valueExpr;
+   ExprNode* valueExpr;
    U32 operand;
    U32 operand;
    TypeReq subType;
    TypeReq subType;
 
 
-   static SlotAssignOpNode *alloc(S32 lineNumber, ExprNode *objectExpr, StringTableEntry slotName, ExprNode *arrayExpr, S32 op, ExprNode *valueExpr);
+   static SlotAssignOpNode* alloc(S32 lineNumber, ExprNode* objectExpr, StringTableEntry slotName, ExprNode* arrayExpr, S32 op, ExprNode* valueExpr);
 
 
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(SlotAssignOpNode);
    DBG_STMT_TYPE(SlotAssignOpNode);
 };
 };
 
 
 struct ObjectDeclNode : ExprNode
 struct ObjectDeclNode : ExprNode
 {
 {
-   ExprNode *classNameExpr;
+   ExprNode* classNameExpr;
    StringTableEntry parentObject;
    StringTableEntry parentObject;
-   ExprNode *objectNameExpr;
-   ExprNode *argList;
-   SlotAssignNode *slotDecls;
-   ObjectDeclNode *subObjects;
+   ExprNode* objectNameExpr;
+   ExprNode* argList;
+   SlotAssignNode* slotDecls;
+   ObjectDeclNode* subObjects;
    bool isDatablock;
    bool isDatablock;
    U32 failOffset;
    U32 failOffset;
    bool isClassNameInternal;
    bool isClassNameInternal;
    bool isSingleton;
    bool isSingleton;
 
 
-   static ObjectDeclNode *alloc(S32 lineNumber, ExprNode *classNameExpr, ExprNode *objectNameExpr, ExprNode *argList, StringTableEntry parentObject, SlotAssignNode *slotDecls, ObjectDeclNode *subObjects, bool isDatablock, bool classNameInternal, bool isSingleton);
+   static ObjectDeclNode* alloc(S32 lineNumber, ExprNode* classNameExpr, ExprNode* objectNameExpr, ExprNode* argList, StringTableEntry parentObject, SlotAssignNode* slotDecls, ObjectDeclNode* subObjects, bool isDatablock, bool classNameInternal, bool isSingleton);
 
 
    U32 precompileSubObject(bool);
    U32 precompileSubObject(bool);
-   U32 compile(CodeStream &codeStream, U32 ip, TypeReq type);
-   U32 compileSubObject(CodeStream &codeStream, U32 ip, bool);
+   U32 compile(CodeStream& codeStream, U32 ip, TypeReq type);
+   U32 compileSubObject(CodeStream& codeStream, U32 ip, bool);
    TypeReq getPreferredType();
    TypeReq getPreferredType();
    DBG_STMT_TYPE(ObjectDeclNode);
    DBG_STMT_TYPE(ObjectDeclNode);
 };
 };
 
 
 struct ObjectBlockDecl
 struct ObjectBlockDecl
 {
 {
-   SlotAssignNode *slots;
-   ObjectDeclNode *decls;
+   SlotAssignNode* slots;
+   ObjectDeclNode* decls;
 };
 };
 
 
 struct FunctionDeclStmtNode : StmtNode
 struct FunctionDeclStmtNode : StmtNode
 {
 {
    StringTableEntry fnName;
    StringTableEntry fnName;
-   VarNode *args;
-   StmtNode *stmts;
+   VarNode* args;
+   StmtNode* stmts;
    StringTableEntry nameSpace;
    StringTableEntry nameSpace;
    StringTableEntry package;
    StringTableEntry package;
    U32 endOffset;
    U32 endOffset;
    U32 argc;
    U32 argc;
 
 
-   static FunctionDeclStmtNode *alloc(S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode *args, StmtNode *stmts);
+   static FunctionDeclStmtNode* alloc(S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode* args, StmtNode* stmts);
 
 
-   U32 compileStmt(CodeStream &codeStream, U32 ip);
+   U32 compileStmt(CodeStream& codeStream, U32 ip);
    void setPackage(StringTableEntry packageName);
    void setPackage(StringTableEntry packageName);
    DBG_STMT_TYPE(FunctionDeclStmtNode);
    DBG_STMT_TYPE(FunctionDeclStmtNode);
 };
 };
 
 
-extern StmtNode *gStatementList;
-extern StmtNode *gAnonFunctionList;
-extern U32 gAnonFunctionID;
+extern StmtNode* gStatementList;
 extern ExprEvalState gEvalState;
 extern ExprEvalState gEvalState;
 
 
 #endif
 #endif

+ 98 - 82
Engine/source/console/astAlloc.cpp

@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
+// Copyright (c) 2013 GarageGames, LLC
 //
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to
 // of this software and associated documentation files (the "Software"), to
@@ -20,7 +20,6 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-#include "platform/platform.h"
 #include "console/console.h"
 #include "console/console.h"
 #include "console/compiler.h"
 #include "console/compiler.h"
 #include "console/consoleInternal.h"
 #include "console/consoleInternal.h"
@@ -38,25 +37,25 @@ using namespace Compiler;
 
 
 //------------------------------------------------------------
 //------------------------------------------------------------
 
 
-BreakStmtNode *BreakStmtNode::alloc(S32 lineNumber)
+BreakStmtNode* BreakStmtNode::alloc(S32 lineNumber)
 {
 {
-   BreakStmtNode *ret = (BreakStmtNode *)consoleAlloc(sizeof(BreakStmtNode));
+   BreakStmtNode* ret = (BreakStmtNode*)consoleAlloc(sizeof(BreakStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    return ret;
    return ret;
 }
 }
 
 
-ContinueStmtNode *ContinueStmtNode::alloc(S32 lineNumber)
+ContinueStmtNode* ContinueStmtNode::alloc(S32 lineNumber)
 {
 {
-   ContinueStmtNode *ret = (ContinueStmtNode *)consoleAlloc(sizeof(ContinueStmtNode));
+   ContinueStmtNode* ret = (ContinueStmtNode*)consoleAlloc(sizeof(ContinueStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    return ret;
    return ret;
 }
 }
 
 
-ReturnStmtNode *ReturnStmtNode::alloc(S32 lineNumber, ExprNode *expr)
+ReturnStmtNode* ReturnStmtNode::alloc(S32 lineNumber, ExprNode* expr)
 {
 {
-   ReturnStmtNode *ret = (ReturnStmtNode *)consoleAlloc(sizeof(ReturnStmtNode));
+   ReturnStmtNode* ret = (ReturnStmtNode*)consoleAlloc(sizeof(ReturnStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->expr = expr;
    ret->expr = expr;
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
@@ -64,9 +63,9 @@ ReturnStmtNode *ReturnStmtNode::alloc(S32 lineNumber, ExprNode *expr)
    return ret;
    return ret;
 }
 }
 
 
-IfStmtNode *IfStmtNode::alloc(S32 lineNumber, ExprNode *testExpr, StmtNode *ifBlock, StmtNode *elseBlock, bool propagate)
+IfStmtNode* IfStmtNode::alloc(S32 lineNumber, ExprNode* testExpr, StmtNode* ifBlock, StmtNode* elseBlock, bool propagate)
 {
 {
-   IfStmtNode *ret = (IfStmtNode *)consoleAlloc(sizeof(IfStmtNode));
+   IfStmtNode* ret = (IfStmtNode*)consoleAlloc(sizeof(IfStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
 
 
@@ -78,9 +77,9 @@ IfStmtNode *IfStmtNode::alloc(S32 lineNumber, ExprNode *testExpr, StmtNode *ifBl
    return ret;
    return ret;
 }
 }
 
 
-LoopStmtNode *LoopStmtNode::alloc(S32 lineNumber, ExprNode *initExpr, ExprNode *testExpr, ExprNode *endLoopExpr, StmtNode *loopBlock, bool isDoLoop)
+LoopStmtNode* LoopStmtNode::alloc(S32 lineNumber, ExprNode* initExpr, ExprNode* testExpr, ExprNode* endLoopExpr, StmtNode* loopBlock, bool isDoLoop)
 {
 {
-   LoopStmtNode *ret = (LoopStmtNode *)consoleAlloc(sizeof(LoopStmtNode));
+   LoopStmtNode* ret = (LoopStmtNode*)consoleAlloc(sizeof(LoopStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    ret->testExpr = testExpr;
    ret->testExpr = testExpr;
@@ -111,11 +110,12 @@ IterStmtNode* IterStmtNode::alloc(S32 lineNumber, StringTableEntry varName, Expr
    return ret;
    return ret;
 }
 }
 
 
-FloatBinaryExprNode *FloatBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *left, ExprNode *right)
+FloatBinaryExprNode* FloatBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right)
 {
 {
-   FloatBinaryExprNode *ret = (FloatBinaryExprNode *)consoleAlloc(sizeof(FloatBinaryExprNode));
+   FloatBinaryExprNode* ret = (FloatBinaryExprNode*)consoleAlloc(sizeof(FloatBinaryExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
 
 
    ret->op = op;
    ret->op = op;
    ret->left = left;
    ret->left = left;
@@ -124,11 +124,12 @@ FloatBinaryExprNode *FloatBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode
    return ret;
    return ret;
 }
 }
 
 
-IntBinaryExprNode *IntBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *left, ExprNode *right)
+IntBinaryExprNode* IntBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode* left, ExprNode* right)
 {
 {
-   IntBinaryExprNode *ret = (IntBinaryExprNode *)consoleAlloc(sizeof(IntBinaryExprNode));
+   IntBinaryExprNode* ret = (IntBinaryExprNode*)consoleAlloc(sizeof(IntBinaryExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
 
 
    ret->op = op;
    ret->op = op;
    ret->left = left;
    ret->left = left;
@@ -137,11 +138,12 @@ IntBinaryExprNode *IntBinaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *le
    return ret;
    return ret;
 }
 }
 
 
-StreqExprNode *StreqExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *right, bool eq)
+StreqExprNode* StreqExprNode::alloc(S32 lineNumber, ExprNode* left, ExprNode* right, bool eq)
 {
 {
-   StreqExprNode *ret = (StreqExprNode *)consoleAlloc(sizeof(StreqExprNode));
+   StreqExprNode* ret = (StreqExprNode*)consoleAlloc(sizeof(StreqExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->left = left;
    ret->left = left;
    ret->right = right;
    ret->right = right;
    ret->eq = eq;
    ret->eq = eq;
@@ -149,11 +151,12 @@ StreqExprNode *StreqExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *ri
    return ret;
    return ret;
 }
 }
 
 
-StrcatExprNode *StrcatExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *right, S32 appendChar)
+StrcatExprNode* StrcatExprNode::alloc(S32 lineNumber, ExprNode* left, ExprNode* right, int appendChar)
 {
 {
-   StrcatExprNode *ret = (StrcatExprNode *)consoleAlloc(sizeof(StrcatExprNode));
+   StrcatExprNode* ret = (StrcatExprNode*)consoleAlloc(sizeof(StrcatExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->left = left;
    ret->left = left;
    ret->right = right;
    ret->right = right;
    ret->appendChar = appendChar;
    ret->appendChar = appendChar;
@@ -161,61 +164,67 @@ StrcatExprNode *StrcatExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *
    return ret;
    return ret;
 }
 }
 
 
-CommaCatExprNode *CommaCatExprNode::alloc(S32 lineNumber, ExprNode *left, ExprNode *right)
+CommaCatExprNode* CommaCatExprNode::alloc(S32 lineNumber, ExprNode* left, ExprNode* right)
 {
 {
-   CommaCatExprNode *ret = (CommaCatExprNode *)consoleAlloc(sizeof(CommaCatExprNode));
+   CommaCatExprNode* ret = (CommaCatExprNode*)consoleAlloc(sizeof(CommaCatExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->left = left;
    ret->left = left;
    ret->right = right;
    ret->right = right;
 
 
    return ret;
    return ret;
 }
 }
 
 
-IntUnaryExprNode *IntUnaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *expr)
+IntUnaryExprNode* IntUnaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode* expr)
 {
 {
-   IntUnaryExprNode *ret = (IntUnaryExprNode *)consoleAlloc(sizeof(IntUnaryExprNode));
+   IntUnaryExprNode* ret = (IntUnaryExprNode*)consoleAlloc(sizeof(IntUnaryExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->op = op;
    ret->op = op;
    ret->expr = expr;
    ret->expr = expr;
    return ret;
    return ret;
 }
 }
 
 
-FloatUnaryExprNode *FloatUnaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode *expr)
+FloatUnaryExprNode* FloatUnaryExprNode::alloc(S32 lineNumber, S32 op, ExprNode* expr)
 {
 {
-   FloatUnaryExprNode *ret = (FloatUnaryExprNode *)consoleAlloc(sizeof(FloatUnaryExprNode));
+   FloatUnaryExprNode* ret = (FloatUnaryExprNode*)consoleAlloc(sizeof(FloatUnaryExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->op = op;
    ret->op = op;
    ret->expr = expr;
    ret->expr = expr;
    return ret;
    return ret;
 }
 }
 
 
-VarNode *VarNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex)
+VarNode* VarNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex)
 {
 {
-   VarNode *ret = (VarNode *)consoleAlloc(sizeof(VarNode));
+   VarNode* ret = (VarNode*)consoleAlloc(sizeof(VarNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->varName = varName;
    ret->varName = varName;
    ret->arrayIndex = arrayIndex;
    ret->arrayIndex = arrayIndex;
    return ret;
    return ret;
 }
 }
 
 
-IntNode *IntNode::alloc(S32 lineNumber, S32 value)
+IntNode* IntNode::alloc(S32 lineNumber, S32 value)
 {
 {
-   IntNode *ret = (IntNode *)consoleAlloc(sizeof(IntNode));
+   IntNode* ret = (IntNode*)consoleAlloc(sizeof(IntNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->value = value;
    ret->value = value;
    return ret;
    return ret;
 }
 }
 
 
-ConditionalExprNode *ConditionalExprNode::alloc(S32 lineNumber, ExprNode *testExpr, ExprNode *trueExpr, ExprNode *falseExpr)
+ConditionalExprNode* ConditionalExprNode::alloc(S32 lineNumber, ExprNode* testExpr, ExprNode* trueExpr, ExprNode* falseExpr)
 {
 {
-   ConditionalExprNode *ret = (ConditionalExprNode *)consoleAlloc(sizeof(ConditionalExprNode));
+   ConditionalExprNode* ret = (ConditionalExprNode*)consoleAlloc(sizeof(ConditionalExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->testExpr = testExpr;
    ret->testExpr = testExpr;
    ret->trueExpr = trueExpr;
    ret->trueExpr = trueExpr;
    ret->falseExpr = falseExpr;
    ret->falseExpr = falseExpr;
@@ -223,44 +232,50 @@ ConditionalExprNode *ConditionalExprNode::alloc(S32 lineNumber, ExprNode *testEx
    return ret;
    return ret;
 }
 }
 
 
-FloatNode *FloatNode::alloc(S32 lineNumber, F64 value)
+FloatNode* FloatNode::alloc(S32 lineNumber, F64 value)
 {
 {
-   FloatNode *ret = (FloatNode *)consoleAlloc(sizeof(FloatNode));
+   FloatNode* ret = (FloatNode*)consoleAlloc(sizeof(FloatNode));
    constructInPlace(ret);
    constructInPlace(ret);
 
 
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->value = value;
    ret->value = value;
    return ret;
    return ret;
 }
 }
 
 
-StrConstNode *StrConstNode::alloc(S32 lineNumber, char *str, bool tag, bool doc)
+StrConstNode* StrConstNode::alloc(S32 lineNumber, char* str, bool tag, bool doc)
 {
 {
-   StrConstNode *ret = (StrConstNode *)consoleAlloc(sizeof(StrConstNode));
+   StrConstNode* ret = (StrConstNode*)consoleAlloc(sizeof(StrConstNode));
    constructInPlace(ret);
    constructInPlace(ret);
+   S32 len = dStrlen(str);
+
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
-   dsize_t retStrLen = dStrlen(str) + 1;
-   ret->str = (char *)consoleAlloc(retStrLen);
+   ret->optimizedNode = NULL;
+   ret->str = (char*)consoleAlloc(len + 1);
    ret->tag = tag;
    ret->tag = tag;
    ret->doc = doc;
    ret->doc = doc;
-   dStrcpy(ret->str, str, retStrLen);
+   dStrcpy(ret->str, str, len);
+   ret->str[len] = '\0';
 
 
    return ret;
    return ret;
 }
 }
 
 
-ConstantNode *ConstantNode::alloc(S32 lineNumber, StringTableEntry value)
+ConstantNode* ConstantNode::alloc(S32 lineNumber, StringTableEntry value)
 {
 {
-   ConstantNode *ret = (ConstantNode *)consoleAlloc(sizeof(ConstantNode));
+   ConstantNode* ret = (ConstantNode*)consoleAlloc(sizeof(ConstantNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->value = value;
    ret->value = value;
    return ret;
    return ret;
 }
 }
 
 
-AssignExprNode *AssignExprNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr)
+AssignExprNode* AssignExprNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex, ExprNode* expr)
 {
 {
-   AssignExprNode *ret = (AssignExprNode *)consoleAlloc(sizeof(AssignExprNode));
+   AssignExprNode* ret = (AssignExprNode*)consoleAlloc(sizeof(AssignExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->varName = varName;
    ret->varName = varName;
    ret->expr = expr;
    ret->expr = expr;
    ret->arrayIndex = arrayIndex;
    ret->arrayIndex = arrayIndex;
@@ -268,11 +283,12 @@ AssignExprNode *AssignExprNode::alloc(S32 lineNumber, StringTableEntry varName,
    return ret;
    return ret;
 }
 }
 
 
-AssignOpExprNode *AssignOpExprNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode *arrayIndex, ExprNode *expr, S32 op)
+AssignOpExprNode* AssignOpExprNode::alloc(S32 lineNumber, StringTableEntry varName, ExprNode* arrayIndex, ExprNode* expr, S32 op)
 {
 {
-   AssignOpExprNode *ret = (AssignOpExprNode *)consoleAlloc(sizeof(AssignOpExprNode));
+   AssignOpExprNode* ret = (AssignOpExprNode*)consoleAlloc(sizeof(AssignOpExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->varName = varName;
    ret->varName = varName;
    ret->expr = expr;
    ret->expr = expr;
    ret->arrayIndex = arrayIndex;
    ret->arrayIndex = arrayIndex;
@@ -280,9 +296,9 @@ AssignOpExprNode *AssignOpExprNode::alloc(S32 lineNumber, StringTableEntry varNa
    return ret;
    return ret;
 }
 }
 
 
-TTagSetStmtNode *TTagSetStmtNode::alloc(S32 lineNumber, StringTableEntry tag, ExprNode *valueExpr, ExprNode *stringExpr)
+TTagSetStmtNode* TTagSetStmtNode::alloc(S32 lineNumber, StringTableEntry tag, ExprNode* valueExpr, ExprNode* stringExpr)
 {
 {
-   TTagSetStmtNode *ret = (TTagSetStmtNode *)consoleAlloc(sizeof(TTagSetStmtNode));
+   TTagSetStmtNode* ret = (TTagSetStmtNode*)consoleAlloc(sizeof(TTagSetStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    ret->tag = tag;
    ret->tag = tag;
@@ -291,59 +307,54 @@ TTagSetStmtNode *TTagSetStmtNode::alloc(S32 lineNumber, StringTableEntry tag, Ex
    return ret;
    return ret;
 }
 }
 
 
-TTagDerefNode *TTagDerefNode::alloc(S32 lineNumber, ExprNode *expr)
+TTagDerefNode* TTagDerefNode::alloc(S32 lineNumber, ExprNode* expr)
 {
 {
-   TTagDerefNode *ret = (TTagDerefNode *)consoleAlloc(sizeof(TTagDerefNode));
+   TTagDerefNode* ret = (TTagDerefNode*)consoleAlloc(sizeof(TTagDerefNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->expr = expr;
    ret->expr = expr;
    return ret;
    return ret;
 }
 }
 
 
-TTagExprNode *TTagExprNode::alloc(S32 lineNumber, StringTableEntry tag)
+TTagExprNode* TTagExprNode::alloc(S32 lineNumber, StringTableEntry tag)
 {
 {
-   TTagExprNode *ret = (TTagExprNode *)consoleAlloc(sizeof(TTagExprNode));
+   TTagExprNode* ret = (TTagExprNode*)consoleAlloc(sizeof(TTagExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->tag = tag;
    ret->tag = tag;
    return ret;
    return ret;
 }
 }
 
 
-FuncCallExprNode *FuncCallExprNode::alloc(S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode *args, bool dot)
+FuncCallExprNode* FuncCallExprNode::alloc(S32 lineNumber, StringTableEntry funcName, StringTableEntry nameSpace, ExprNode* args, bool dot)
 {
 {
-   FuncCallExprNode *ret = (FuncCallExprNode *)consoleAlloc(sizeof(FuncCallExprNode));
+   FuncCallExprNode* ret = (FuncCallExprNode*)consoleAlloc(sizeof(FuncCallExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->funcName = funcName;
    ret->funcName = funcName;
    ret->nameSpace = nameSpace;
    ret->nameSpace = nameSpace;
    ret->args = args;
    ret->args = args;
    if (dot)
    if (dot)
       ret->callType = MethodCall;
       ret->callType = MethodCall;
-   else
+   else if (nameSpace != NULL)
    {
    {
-      if (nameSpace && !dStricmp(nameSpace, "Parent"))
+      if (dStricmp(nameSpace, "Parent") == 0)
          ret->callType = ParentCall;
          ret->callType = ParentCall;
       else
       else
-         ret->callType = FunctionCall;
+         ret->callType = StaticCall;
    }
    }
+   else
+      ret->callType = FunctionCall;
    return ret;
    return ret;
 }
 }
 
 
-FuncPointerCallExprNode *FuncPointerCallExprNode::alloc(S32 lineNumber, ExprNode *funcPointer, ExprNode *args)
-{
-   FuncPointerCallExprNode *ret = (FuncPointerCallExprNode *)consoleAlloc(sizeof(FuncPointerCallExprNode));
-   constructInPlace(ret);
-   ret->dbgLineNumber = lineNumber;
-   ret->funcPointer = funcPointer;
-   ret->args = args;
-   return ret;
-}
-
-AssertCallExprNode *AssertCallExprNode::alloc(S32 lineNumber, ExprNode *testExpr, const char *message)
+AssertCallExprNode* AssertCallExprNode::alloc(S32 lineNumber, ExprNode* testExpr, const char* message)
 {
 {
-#ifdef TORQUE_ENABLE_SCRIPTASSERTS      
+#ifdef TORQUE_ENABLE_SCRIPTASSERTS
 
 
-   AssertCallExprNode *ret = (AssertCallExprNode *)consoleAlloc(sizeof(FuncCallExprNode));
+   AssertCallExprNode* ret = (AssertCallExprNode*)consoleAlloc(sizeof(FuncCallExprNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    ret->testExpr = testExpr;
    ret->testExpr = testExpr;
@@ -357,10 +368,11 @@ AssertCallExprNode *AssertCallExprNode::alloc(S32 lineNumber, ExprNode *testExpr
 #endif
 #endif
 }
 }
 
 
-SlotAccessNode *SlotAccessNode::alloc(S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName)
+SlotAccessNode* SlotAccessNode::alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* arrayExpr, StringTableEntry slotName)
 {
 {
-   SlotAccessNode *ret = (SlotAccessNode *)consoleAlloc(sizeof(SlotAccessNode));
+   SlotAccessNode* ret = (SlotAccessNode*)consoleAlloc(sizeof(SlotAccessNode));
    constructInPlace(ret);
    constructInPlace(ret);
+   ret->optimizedNode = NULL;
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    ret->objectExpr = objectExpr;
    ret->objectExpr = objectExpr;
    ret->arrayExpr = arrayExpr;
    ret->arrayExpr = arrayExpr;
@@ -368,22 +380,24 @@ SlotAccessNode *SlotAccessNode::alloc(S32 lineNumber, ExprNode *objectExpr, Expr
    return ret;
    return ret;
 }
 }
 
 
-InternalSlotAccessNode *InternalSlotAccessNode::alloc(S32 lineNumber, ExprNode *objectExpr, ExprNode *slotExpr, bool recurse)
+InternalSlotAccessNode* InternalSlotAccessNode::alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* slotExpr, bool recurse)
 {
 {
-   InternalSlotAccessNode *ret = (InternalSlotAccessNode *)consoleAlloc(sizeof(InternalSlotAccessNode));
+   InternalSlotAccessNode* ret = (InternalSlotAccessNode*)consoleAlloc(sizeof(InternalSlotAccessNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->objectExpr = objectExpr;
    ret->objectExpr = objectExpr;
    ret->slotExpr = slotExpr;
    ret->slotExpr = slotExpr;
    ret->recurse = recurse;
    ret->recurse = recurse;
    return ret;
    return ret;
 }
 }
 
 
-SlotAssignNode *SlotAssignNode::alloc(S32 lineNumber, ExprNode *objectExpr, ExprNode *arrayExpr, StringTableEntry slotName, ExprNode *valueExpr, U32 typeID /* = -1 */)
+SlotAssignNode* SlotAssignNode::alloc(S32 lineNumber, ExprNode* objectExpr, ExprNode* arrayExpr, StringTableEntry slotName, ExprNode* valueExpr, U32 typeID /* = -1 */)
 {
 {
-   SlotAssignNode *ret = (SlotAssignNode *)consoleAlloc(sizeof(SlotAssignNode));
+   SlotAssignNode* ret = (SlotAssignNode*)consoleAlloc(sizeof(SlotAssignNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->objectExpr = objectExpr;
    ret->objectExpr = objectExpr;
    ret->arrayExpr = arrayExpr;
    ret->arrayExpr = arrayExpr;
    ret->slotName = slotName;
    ret->slotName = slotName;
@@ -392,11 +406,12 @@ SlotAssignNode *SlotAssignNode::alloc(S32 lineNumber, ExprNode *objectExpr, Expr
    return ret;
    return ret;
 }
 }
 
 
-SlotAssignOpNode *SlotAssignOpNode::alloc(S32 lineNumber, ExprNode *objectExpr, StringTableEntry slotName, ExprNode *arrayExpr, S32 op, ExprNode *valueExpr)
+SlotAssignOpNode* SlotAssignOpNode::alloc(S32 lineNumber, ExprNode* objectExpr, StringTableEntry slotName, ExprNode* arrayExpr, S32 op, ExprNode* valueExpr)
 {
 {
-   SlotAssignOpNode *ret = (SlotAssignOpNode *)consoleAlloc(sizeof(SlotAssignOpNode));
+   SlotAssignOpNode* ret = (SlotAssignOpNode*)consoleAlloc(sizeof(SlotAssignOpNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->objectExpr = objectExpr;
    ret->objectExpr = objectExpr;
    ret->arrayExpr = arrayExpr;
    ret->arrayExpr = arrayExpr;
    ret->slotName = slotName;
    ret->slotName = slotName;
@@ -405,11 +420,12 @@ SlotAssignOpNode *SlotAssignOpNode::alloc(S32 lineNumber, ExprNode *objectExpr,
    return ret;
    return ret;
 }
 }
 
 
-ObjectDeclNode *ObjectDeclNode::alloc(S32 lineNumber, ExprNode *classNameExpr, ExprNode *objectNameExpr, ExprNode *argList, StringTableEntry parentObject, SlotAssignNode *slotDecls, ObjectDeclNode *subObjects, bool isDatablock, bool classNameInternal, bool isSingleton)
+ObjectDeclNode* ObjectDeclNode::alloc(S32 lineNumber, ExprNode* classNameExpr, ExprNode* objectNameExpr, ExprNode* argList, StringTableEntry parentObject, SlotAssignNode* slotDecls, ObjectDeclNode* subObjects, bool isDatablock, bool classNameInternal, bool isSingleton)
 {
 {
-   ObjectDeclNode *ret = (ObjectDeclNode *)consoleAlloc(sizeof(ObjectDeclNode));
+   ObjectDeclNode* ret = (ObjectDeclNode*)consoleAlloc(sizeof(ObjectDeclNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
+   ret->optimizedNode = NULL;
    ret->classNameExpr = classNameExpr;
    ret->classNameExpr = classNameExpr;
    ret->objectNameExpr = objectNameExpr;
    ret->objectNameExpr = objectNameExpr;
    ret->argList = argList;
    ret->argList = argList;
@@ -422,13 +438,13 @@ ObjectDeclNode *ObjectDeclNode::alloc(S32 lineNumber, ExprNode *classNameExpr, E
    if (parentObject)
    if (parentObject)
       ret->parentObject = parentObject;
       ret->parentObject = parentObject;
    else
    else
-      ret->parentObject = StringTable->EmptyString();
+      ret->parentObject = StringTable->insert("");
    return ret;
    return ret;
 }
 }
 
 
-FunctionDeclStmtNode *FunctionDeclStmtNode::alloc(S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode *args, StmtNode *stmts)
+FunctionDeclStmtNode* FunctionDeclStmtNode::alloc(S32 lineNumber, StringTableEntry fnName, StringTableEntry nameSpace, VarNode* args, StmtNode* stmts)
 {
 {
-   FunctionDeclStmtNode *ret = (FunctionDeclStmtNode *)consoleAlloc(sizeof(FunctionDeclStmtNode));
+   FunctionDeclStmtNode* ret = (FunctionDeclStmtNode*)consoleAlloc(sizeof(FunctionDeclStmtNode));
    constructInPlace(ret);
    constructInPlace(ret);
    ret->dbgLineNumber = lineNumber;
    ret->dbgLineNumber = lineNumber;
    ret->fnName = fnName;
    ret->fnName = fnName;

File diff suppressed because it is too large
+ 306 - 423
Engine/source/console/astNodes.cpp


+ 597 - 674
Engine/source/console/codeBlock.cpp

@@ -477,7 +477,6 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
    STEtoCode = compileSTEtoCode;
    STEtoCode = compileSTEtoCode;
 
 
    gStatementList = NULL;
    gStatementList = NULL;
-   gAnonFunctionList = NULL;
 
 
    // Set up the parser.
    // Set up the parser.
    smCurrentParser = getParserForFile(fileName);
    smCurrentParser = getParserForFile(fileName);
@@ -487,17 +486,6 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
    smCurrentParser->setScanBuffer(script, fileName);
    smCurrentParser->setScanBuffer(script, fileName);
    smCurrentParser->restart(NULL);
    smCurrentParser->restart(NULL);
    smCurrentParser->parse();
    smCurrentParser->parse();
-   if (gStatementList)
-   {
-      if (gAnonFunctionList)
-      {
-         // Prepend anonymous functions to statement list, so they're defined already when
-         // the statements run.
-         gAnonFunctionList->append(gStatementList);
-         gStatementList = gAnonFunctionList;
-      }
-   }
-
 
 
    if (gSyntaxError)
    if (gSyntaxError)
    {
    {
@@ -575,11 +563,9 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
    st.close();
    st.close();
 
 
    return true;
    return true;
-
-
 }
 }
 
 
-ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
+void CodeBlock::compileExec(StringTableEntry fileName, const char *inString, ConsoleValue &returnValue, bool noCalls, S32 setFrame)
 {
 {
    AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
    AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
 
 
@@ -620,7 +606,6 @@ ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *in
       addToCodeList();
       addToCodeList();
 
 
    gStatementList = NULL;
    gStatementList = NULL;
-   gAnonFunctionList = NULL;
 
 
    // Set up the parser.
    // Set up the parser.
    smCurrentParser = getParserForFile(fileName);
    smCurrentParser = getParserForFile(fileName);
@@ -630,21 +615,11 @@ ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *in
    smCurrentParser->setScanBuffer(string, fileName);
    smCurrentParser->setScanBuffer(string, fileName);
    smCurrentParser->restart(NULL);
    smCurrentParser->restart(NULL);
    smCurrentParser->parse();
    smCurrentParser->parse();
-   if (gStatementList)
-   {
-      if (gAnonFunctionList)
-      {
-         // Prepend anonymous functions to statement list, so they're defined already when
-         // the statements run.
-         gAnonFunctionList->append(gStatementList);
-         gStatementList = gAnonFunctionList;
-      }
-   }
 
 
    if (!gStatementList)
    if (!gStatementList)
    {
    {
       delete this;
       delete this;
-      return ConsoleValueRef();
+      return;
    }
    }
 
 
    resetTables();
    resetTables();
@@ -678,7 +653,7 @@ ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *in
    if (lastIp + 1 != codeSize)
    if (lastIp + 1 != codeSize)
       Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp);
       Con::warnf(ConsoleLogEntry::General, "precompile size mismatch, precompile: %d compile: %d", codeSize, lastIp);
 
 
-   return exec(0, fileName, NULL, 0, 0, noCalls, NULL, setFrame);
+   exec(0, fileName, NULL, 0, 0, noCalls, NULL, returnValue, setFrame);
 }
 }
 
 
 //-------------------------------------------------------------------------
 //-------------------------------------------------------------------------
@@ -739,775 +714,723 @@ void CodeBlock::dumpInstructions(U32 startIp, bool upToReturn)
       switch (code[ip++])
       switch (code[ip++])
       {
       {
 
 
-         case OP_FUNC_DECL:
-         {
-            StringTableEntry fnName = CodeToSTE(code, ip);
-            StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
-            StringTableEntry fnPackage = CodeToSTE(code, ip + 4);
-            bool hasBody = bool(code[ip + 6]);
-            U32 newIp = code[ip + 7];
-            U32 argc = code[ip + 8];
-            endFuncIp = newIp;
-
-            Con::printf("%i: OP_FUNC_DECL name=%s nspace=%s package=%s hasbody=%i newip=%i argc=%i",
-               ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc);
+      case OP_FUNC_DECL:
+      {
+         StringTableEntry fnName = CodeToSTE(code, ip);
+         StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
+         StringTableEntry fnPackage = CodeToSTE(code, ip + 4);
+         bool hasBody = bool(code[ip + 6]);
+         U32 newIp = code[ip + 7];
+         U32 argc = code[ip + 8];
+         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",
+            ip - 1, fnName, fnNamespace, fnPackage, hasBody, newIp, argc, regCount);
+
+         // Skip args.
+
+         ip += 10 + argc;
+         smInFunction = true;
+         break;
+      }
 
 
-            // Skip args.
+      case OP_CREATE_OBJECT:
+      {
+         StringTableEntry objParent = CodeToSTE(code, ip);
+         bool isDataBlock = code[ip + 2];
+         bool isInternal = code[ip + 3];
+         bool isSingleton = code[ip + 4];
+         U32  lineNumber = code[ip + 5];
+         U32 failJump = code[ip + 6];
 
 
-            ip += 9 + (argc * 2);
-            smInFunction = true;
-            break;
-         }
+         Con::printf("%i: OP_CREATE_OBJECT objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i",
+            ip - 1, objParent, isDataBlock, isInternal, isSingleton, lineNumber, failJump);
 
 
-         case OP_CREATE_OBJECT:
-         {
-            StringTableEntry objParent = CodeToSTE(code, ip);
-            bool isDataBlock = code[ip + 2];
-            bool isInternal = code[ip + 3];
-            bool isSingleton = code[ip + 4];
-            U32  lineNumber = code[ip + 5];
-            U32 failJump = code[ip + 6];
+         ip += 7;
+         break;
+      }
 
 
-            Con::printf("%i: OP_CREATE_OBJECT objParent=%s isDataBlock=%i isInternal=%i isSingleton=%i lineNumber=%i failJump=%i",
-               ip - 1, objParent, isDataBlock, isInternal, isSingleton, lineNumber, failJump);
+      case OP_ADD_OBJECT:
+      {
+         bool placeAtRoot = code[ip++];
+         Con::printf("%i: OP_ADD_OBJECT placeAtRoot=%i", ip - 1, placeAtRoot);
+         break;
+      }
 
 
-            ip += 7;
-            break;
-         }
+      case OP_END_OBJECT:
+      {
+         bool placeAtRoot = code[ip++];
+         Con::printf("%i: OP_END_OBJECT placeAtRoot=%i", ip - 1, placeAtRoot);
+         break;
+      }
 
 
-         case OP_ADD_OBJECT:
-         {
-            bool placeAtRoot = code[ip++];
-            Con::printf("%i: OP_ADD_OBJECT placeAtRoot=%i", ip - 1, placeAtRoot);
-            break;
-         }
+      case OP_FINISH_OBJECT:
+      {
+         Con::printf("%i: OP_FINISH_OBJECT", ip - 1);
+         break;
+      }
 
 
-         case OP_END_OBJECT:
-         {
-            bool placeAtRoot = code[ip++];
-            Con::printf("%i: OP_END_OBJECT placeAtRoot=%i", ip - 1, placeAtRoot);
-            break;
-         }
+      case OP_JMPIFFNOT:
+      {
+         Con::printf("%i: OP_JMPIFFNOT ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_FINISH_OBJECT:
-         {
-            Con::printf("%i: OP_FINISH_OBJECT", ip - 1);
-            break;
-         }
+      case OP_JMPIFNOT:
+      {
+         Con::printf("%i: OP_JMPIFNOT ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_JMPIFFNOT:
-         {
-            Con::printf("%i: OP_JMPIFFNOT ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+      case OP_JMPIFF:
+      {
+         Con::printf("%i: OP_JMPIFF ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_JMPIFNOT:
-         {
-            Con::printf("%i: OP_JMPIFNOT ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+      case OP_JMPIF:
+      {
+         Con::printf("%i: OP_JMPIF ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_JMPIFF:
-         {
-            Con::printf("%i: OP_JMPIFF ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+      case OP_JMPIFNOT_NP:
+      {
+         Con::printf("%i: OP_JMPIFNOT_NP ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_JMPIF:
-         {
-            Con::printf("%i: OP_JMPIF ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+      case OP_JMPIF_NP:
+      {
+         Con::printf("%i: OP_JMPIF_NP ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_JMPIFNOT_NP:
-         {
-            Con::printf("%i: OP_JMPIFNOT_NP ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+      case OP_JMP:
+      {
+         Con::printf("%i: OP_JMP ip=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_JMPIF_NP:
-         {
-            Con::printf("%i: OP_JMPIF_NP ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+      case OP_RETURN:
+      {
+         Con::printf("%i: OP_RETURN", ip - 1);
 
 
-         case OP_JMP:
-         {
-            Con::printf("%i: OP_JMP ip=%i", ip - 1, code[ip]);
-            ++ip;
-            break;
-         }
+         if (upToReturn)
+            return;
 
 
-         case OP_RETURN:
-         {
-            Con::printf("%i: OP_RETURN", ip - 1);
+         break;
+      }
 
 
-            if (upToReturn)
-               return;
+      case OP_RETURN_VOID:
+      {
+         Con::printf("%i: OP_RETURNVOID", ip - 1);
 
 
-            break;
-         }
+         if (upToReturn)
+            return;
 
 
-         case OP_RETURN_VOID:
-         {
-            Con::printf("%i: OP_RETURNVOID", ip - 1);
+         break;
+      }
 
 
-            if (upToReturn)
-               return;
+      case OP_RETURN_UINT:
+      {
+         Con::printf("%i: OP_RETURNUINT", ip - 1);
 
 
-            break;
-         }
+         if (upToReturn)
+            return;
 
 
-         case OP_RETURN_UINT:
-         {
-            Con::printf("%i: OP_RETURNUINT", ip - 1);
+         break;
+      }
 
 
-            if (upToReturn)
-               return;
+      case OP_RETURN_FLT:
+      {
+         Con::printf("%i: OP_RETURNFLT", ip - 1);
 
 
-            break;
-         }
+         if (upToReturn)
+            return;
 
 
-         case OP_RETURN_FLT:
-         {
-            Con::printf("%i: OP_RETURNFLT", ip - 1);
+         break;
+      }
 
 
-            if (upToReturn)
-               return;
+      case OP_CMPEQ:
+      {
+         Con::printf("%i: OP_CMPEQ", ip - 1);
+         break;
+      }
 
 
-            break;
-         }
+      case OP_CMPGR:
+      {
+         Con::printf("%i: OP_CMPGR", ip - 1);
+         break;
+      }
 
 
-         case OP_CMPEQ:
-         {
-            Con::printf("%i: OP_CMPEQ", ip - 1);
-            break;
-         }
+      case OP_CMPGE:
+      {
+         Con::printf("%i: OP_CMPGE", ip - 1);
+         break;
+      }
 
 
-         case OP_CMPGR:
-         {
-            Con::printf("%i: OP_CMPGR", ip - 1);
-            break;
-         }
+      case OP_CMPLT:
+      {
+         Con::printf("%i: OP_CMPLT", ip - 1);
+         break;
+      }
 
 
-         case OP_CMPGE:
-         {
-            Con::printf("%i: OP_CMPGE", ip - 1);
-            break;
-         }
+      case OP_CMPLE:
+      {
+         Con::printf("%i: OP_CMPLE", ip - 1);
+         break;
+      }
 
 
-         case OP_CMPLT:
-         {
-            Con::printf("%i: OP_CMPLT", ip - 1);
-            break;
-         }
+      case OP_CMPNE:
+      {
+         Con::printf("%i: OP_CMPNE", ip - 1);
+         break;
+      }
 
 
-         case OP_CMPLE:
-         {
-            Con::printf("%i: OP_CMPLE", ip - 1);
-            break;
-         }
+      case OP_XOR:
+      {
+         Con::printf("%i: OP_XOR", ip - 1);
+         break;
+      }
 
 
-         case OP_CMPNE:
-         {
-            Con::printf("%i: OP_CMPNE", ip - 1);
-            break;
-         }
+      case OP_MOD:
+      {
+         Con::printf("%i: OP_MOD", ip - 1);
+         break;
+      }
 
 
-         case OP_XOR:
-         {
-            Con::printf("%i: OP_XOR", ip - 1);
-            break;
-         }
+      case OP_BITAND:
+      {
+         Con::printf("%i: OP_BITAND", ip - 1);
+         break;
+      }
 
 
-         case OP_MOD:
-         {
-            Con::printf("%i: OP_MOD", ip - 1);
-            break;
-         }
+      case OP_BITOR:
+      {
+         Con::printf("%i: OP_BITOR", ip - 1);
+         break;
+      }
 
 
-         case OP_BITAND:
-         {
-            Con::printf("%i: OP_BITAND", ip - 1);
-            break;
-         }
+      case OP_NOT:
+      {
+         Con::printf("%i: OP_NOT", ip - 1);
+         break;
+      }
 
 
-         case OP_BITOR:
-         {
-            Con::printf("%i: OP_BITOR", ip - 1);
-            break;
-         }
+      case OP_NOTF:
+      {
+         Con::printf("%i: OP_NOTF", ip - 1);
+         break;
+      }
 
 
-         case OP_NOT:
-         {
-            Con::printf("%i: OP_NOT", ip - 1);
-            break;
-         }
+      case OP_ONESCOMPLEMENT:
+      {
+         Con::printf("%i: OP_ONESCOMPLEMENT", ip - 1);
+         break;
+      }
 
 
-         case OP_NOTF:
-         {
-            Con::printf("%i: OP_NOTF", ip - 1);
-            break;
-         }
+      case OP_SHR:
+      {
+         Con::printf("%i: OP_SHR", ip - 1);
+         break;
+      }
 
 
-         case OP_ONESCOMPLEMENT:
-         {
-            Con::printf("%i: OP_ONESCOMPLEMENT", ip - 1);
-            break;
-         }
+      case OP_SHL:
+      {
+         Con::printf("%i: OP_SHL", ip - 1);
+         break;
+      }
 
 
-         case OP_SHR:
-         {
-            Con::printf("%i: OP_SHR", ip - 1);
-            break;
-         }
+      case OP_AND:
+      {
+         Con::printf("%i: OP_AND", ip - 1);
+         break;
+      }
 
 
-         case OP_SHL:
-         {
-            Con::printf("%i: OP_SHL", ip - 1);
-            break;
-         }
+      case OP_OR:
+      {
+         Con::printf("%i: OP_OR", ip - 1);
+         break;
+      }
 
 
-         case OP_AND:
-         {
-            Con::printf("%i: OP_AND", ip - 1);
-            break;
-         }
+      case OP_ADD:
+      {
+         Con::printf("%i: OP_ADD", ip - 1);
+         break;
+      }
 
 
-         case OP_OR:
-         {
-            Con::printf("%i: OP_OR", ip - 1);
-            break;
-         }
+      case OP_SUB:
+      {
+         Con::printf("%i: OP_SUB", ip - 1);
+         break;
+      }
 
 
-         case OP_ADD:
-         {
-            Con::printf("%i: OP_ADD", ip - 1);
-            break;
-         }
+      case OP_MUL:
+      {
+         Con::printf("%i: OP_MUL", ip - 1);
+         break;
+      }
 
 
-         case OP_SUB:
-         {
-            Con::printf("%i: OP_SUB", ip - 1);
-            break;
-         }
+      case OP_DIV:
+      {
+         Con::printf("%i: OP_DIV", ip - 1);
+         break;
+      }
 
 
-         case OP_MUL:
-         {
-            Con::printf("%i: OP_MUL", ip - 1);
-            break;
-         }
+      case OP_NEG:
+      {
+         Con::printf("%i: OP_NEG", ip - 1);
+         break;
+      }
 
 
-         case OP_DIV:
-         {
-            Con::printf("%i: OP_DIV", ip - 1);
-            break;
-         }
+      case OP_INC:
+      {
+         Con::printf("%i: OP_INC reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_NEG:
-         {
-            Con::printf("%i: OP_NEG", ip - 1);
-            break;
-         }
+      case OP_SETCURVAR:
+      {
+         StringTableEntry var = CodeToSTE(code, ip);
 
 
-         case OP_INC:
-         {
-            Con::printf("%i: OP_INC varName=%s", ip - 1, CodeToSTE(code, ip));
-            ip += 2;
-            break;
-         }
+         Con::printf("%i: OP_SETCURVAR var=%s", ip - 1, var);
+         ip += 2;
+         break;
+      }
 
 
-         case OP_DEC:
-         {
-            Con::printf("%i: OP_DEC varName=%s", ip - 1, CodeToSTE(code, ip));
-            ip += 2;
-            break;
-         }
+      case OP_SETCURVAR_CREATE:
+      {
+         StringTableEntry var = CodeToSTE(code, ip);
 
 
-         case OP_SETCURVAR:
-         {
-            StringTableEntry var = CodeToSTE(code, ip);
-
-            Con::printf("%i: OP_SETCURVAR var=%s", ip - 1, var);
-            ip += 2;
-            break;
-         }
-
-         case OP_SETCURVAR_CREATE:
-         {
-            StringTableEntry var = CodeToSTE(code, ip);
-
-            Con::printf("%i: OP_SETCURVAR_CREATE var=%s", ip - 1, var);
-            ip += 2;
-            break;
-         }
-
-         case OP_SETCURVAR_ARRAY:
-         {
-            Con::printf("%i: OP_SETCURVAR_ARRAY", ip - 1);
-            break;
-         }
-
-         case OP_SETCURVAR_ARRAY_VARLOOKUP:
-         {
-            StringTableEntry arrayName = CodeToSTE(code, ip);
-            StringTableEntry arrayLookup = CodeToSTE(code, ip + 2);
-
-            Con::printf("%i: OP_SETCURVAR_ARRAY_VARLOOKUP arrayName=%s arrayLookup=%s", ip - 1, arrayName, arrayLookup);
-            ip += 4;
-            break;
-         }
-
-         case OP_SETCURVAR_ARRAY_CREATE:
-         {
-            Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE", ip - 1);
-            break;
-         }
-
-         case OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP:
-         {
-            StringTableEntry arrayName = CodeToSTE(code, ip);
-            StringTableEntry arrayLookup = CodeToSTE(code, ip + 2);
-
-            Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP arrayName=%s arrayLookup=%s", ip - 1, arrayName, arrayLookup);
-            ip += 4;
-            break;
-         }
-
-         case OP_LOADVAR_UINT:
-         {
-            Con::printf("%i: OP_LOADVAR_UINT", ip - 1);
-            break;
-         }
-
-         case OP_LOADVAR_FLT:
-         {
-            Con::printf("%i: OP_LOADVAR_FLT", ip - 1);
-            break;
-         }
-
-         case OP_LOADVAR_STR:
-         {
-            Con::printf("%i: OP_LOADVAR_STR", ip - 1);
-            break;
-         }
+         Con::printf("%i: OP_SETCURVAR_CREATE var=%s", ip - 1, var);
+         ip += 2;
+         break;
+      }
 
 
-         case OP_LOADVAR_VAR:
-         {
-            Con::printf("%i: OP_LOADVAR_VAR", ip - 1);
-            break;
-         }
+      case OP_SETCURVAR_ARRAY:
+      {
+         Con::printf("%i: OP_SETCURVAR_ARRAY", ip - 1);
+         break;
+      }
 
 
-         case OP_SAVEVAR_UINT:
-         {
-            Con::printf("%i: OP_SAVEVAR_UINT", ip - 1);
-            break;
-         }
+      case OP_SETCURVAR_ARRAY_CREATE:
+      {
+         Con::printf("%i: OP_SETCURVAR_ARRAY_CREATE", ip - 1);
+         break;
+      }
 
 
-         case OP_SAVEVAR_FLT:
-         {
-            Con::printf("%i: OP_SAVEVAR_FLT", ip - 1);
-            break;
-         }
+      case OP_LOADVAR_UINT:
+      {
+         Con::printf("%i: OP_LOADVAR_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_SAVEVAR_STR:
-         {
-            Con::printf("%i: OP_SAVEVAR_STR", ip - 1);
-            break;
-         }
+      case OP_LOADVAR_FLT:
+      {
+         Con::printf("%i: OP_LOADVAR_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_SAVEVAR_VAR:
-         {
-            Con::printf("%i: OP_SAVEVAR_VAR", ip - 1);
-            break;
-         }
+      case OP_LOADVAR_STR:
+      {
+         Con::printf("%i: OP_LOADVAR_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_SETCUROBJECT:
-         {
-            Con::printf("%i: OP_SETCUROBJECT", ip - 1);
-            break;
-         }
+      case OP_SAVEVAR_UINT:
+      {
+         Con::printf("%i: OP_SAVEVAR_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_SETCUROBJECT_NEW:
-         {
-            Con::printf("%i: OP_SETCUROBJECT_NEW", ip - 1);
-            break;
-         }
+      case OP_SAVEVAR_FLT:
+      {
+         Con::printf("%i: OP_SAVEVAR_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_SETCUROBJECT_INTERNAL:
-         {
-            Con::printf("%i: OP_SETCUROBJECT_INTERNAL", ip - 1);
-            ++ip;
-            break;
-         }
+      case OP_SAVEVAR_STR:
+      {
+         Con::printf("%i: OP_SAVEVAR_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_SETCURFIELD:
-         {
-            StringTableEntry curField = CodeToSTE(code, ip);
-            Con::printf("%i: OP_SETCURFIELD field=%s", ip - 1, curField);
-            ip += 2;
-            break;
-         }
+      case OP_LOAD_LOCAL_VAR_UINT:
+      {
+         Con::printf("%i: OP_LOAD_LOCAL_VAR_UINT reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_SETCURFIELD_ARRAY:
-         {
-            Con::printf("%i: OP_SETCURFIELD_ARRAY", ip - 1);
-            break;
-         }
+      case OP_LOAD_LOCAL_VAR_FLT:
+      {
+         Con::printf("%i: OP_LOAD_LOCAL_VAR_FLT reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_SETCURFIELD_ARRAY_VAR:
-         {
-            StringTableEntry var = CodeToSTE(code, ip);
-            Con::printf("%i: OP_SETCURFIELD_ARRAY_VAR var=%s", ip - 1, var);
-            ip += 2;
-            break;
-         }
+      case OP_LOAD_LOCAL_VAR_STR:
+      {
+         Con::printf("%i: OP_LOAD_LOCAL_VAR_STR reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_SETCURFIELD_THIS:
-         {
-            StringTableEntry curField = CodeToSTE(code, ip);
-            Con::printf("%i: OP_SETCURFIELD_THIS field=%s", ip - 1, curField);
-            ip += 2;
-            break;
-         }
+      case OP_SAVE_LOCAL_VAR_UINT:
+      {
+         Con::printf("%i: OP_SAVE_LOCAL_VAR_UINT reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_SETCURFIELD_TYPE:
-         {
-            U32 type = code[ip];
-            Con::printf("%i: OP_SETCURFIELD_TYPE type=%i", ip - 1, type);
-            ++ip;
-            break;
-         }
+      case OP_SAVE_LOCAL_VAR_FLT:
+      {
+         Con::printf("%i: OP_SAVE_LOCAL_VAR_FLT reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_LOADFIELD_UINT:
-         {
-            Con::printf("%i: OP_LOADFIELD_UINT", ip - 1);
-            break;
-         }
+      case OP_SAVE_LOCAL_VAR_STR:
+      {
+         Con::printf("%i: OP_SAVE_LOCAL_VAR_STR reg=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_LOADFIELD_FLT:
-         {
-            Con::printf("%i: OP_LOADFIELD_FLT", ip - 1);
-            break;
-         }
+      case OP_SETCUROBJECT:
+      {
+         Con::printf("%i: OP_SETCUROBJECT", ip - 1);
+         break;
+      }
 
 
-         case OP_LOADFIELD_STR:
-         {
-            Con::printf("%i: OP_LOADFIELD_STR", ip - 1);
-            break;
-         }
+      case OP_SETCUROBJECT_NEW:
+      {
+         Con::printf("%i: OP_SETCUROBJECT_NEW", ip - 1);
+         break;
+      }
 
 
-         case OP_SAVEFIELD_UINT:
-         {
-            Con::printf("%i: OP_SAVEFIELD_UINT", ip - 1);
-            break;
-         }
+      case OP_SETCUROBJECT_INTERNAL:
+      {
+         Con::printf("%i: OP_SETCUROBJECT_INTERNAL", ip - 1);
+         ++ip;
+         break;
+      }
 
 
-         case OP_SAVEFIELD_FLT:
-         {
-            Con::printf("%i: OP_SAVEFIELD_FLT", ip - 1);
-            break;
-         }
+      case OP_SETCURFIELD:
+      {
+         StringTableEntry curField = CodeToSTE(code, ip);
+         Con::printf("%i: OP_SETCURFIELD field=%s", ip - 1, curField);
+         ip += 2;
+         break;
+      }
 
 
-         case OP_SAVEFIELD_STR:
-         {
-            Con::printf("%i: OP_SAVEFIELD_STR", ip - 1);
-            break;
-         }
+      case OP_SETCURFIELD_ARRAY:
+      {
+         Con::printf("%i: OP_SETCURFIELD_ARRAY", ip - 1);
+         break;
+      }
 
 
-         case OP_STR_TO_UINT:
-         {
-            Con::printf("%i: OP_STR_TO_UINT", ip - 1);
-            break;
-         }
+      case OP_SETCURFIELD_TYPE:
+      {
+         U32 type = code[ip];
+         Con::printf("%i: OP_SETCURFIELD_TYPE type=%i", ip - 1, type);
+         ++ip;
+         break;
+      }
 
 
-         case OP_STR_TO_FLT:
-         {
-            Con::printf("%i: OP_STR_TO_FLT", ip - 1);
-            break;
-         }
+      case OP_LOADFIELD_UINT:
+      {
+         Con::printf("%i: OP_LOADFIELD_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_STR_TO_NONE:
-         {
-            Con::printf("%i: OP_STR_TO_NONE", ip - 1);
-            break;
-         }
+      case OP_LOADFIELD_FLT:
+      {
+         Con::printf("%i: OP_LOADFIELD_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_FLT_TO_UINT:
-         {
-            Con::printf("%i: OP_FLT_TO_UINT", ip - 1);
-            break;
-         }
+      case OP_LOADFIELD_STR:
+      {
+         Con::printf("%i: OP_LOADFIELD_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_FLT_TO_STR:
-         {
-            Con::printf("%i: OP_FLT_TO_STR", ip - 1);
-            break;
-         }
+      case OP_SAVEFIELD_UINT:
+      {
+         Con::printf("%i: OP_SAVEFIELD_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_FLT_TO_NONE:
-         {
-            Con::printf("%i: OP_FLT_TO_NONE", ip - 1);
-            break;
-         }
+      case OP_SAVEFIELD_FLT:
+      {
+         Con::printf("%i: OP_SAVEFIELD_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_UINT_TO_FLT:
-         {
-            Con::printf("%i: OP_SAVEFIELD_STR", ip - 1);
-            break;
-         }
+      case OP_SAVEFIELD_STR:
+      {
+         Con::printf("%i: OP_SAVEFIELD_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_UINT_TO_STR:
-         {
-            Con::printf("%i: OP_UINT_TO_STR", ip - 1);
-            break;
-         }
+      case OP_STR_TO_UINT:
+      {
+         Con::printf("%i: OP_STR_TO_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_UINT_TO_NONE:
-         {
-            Con::printf("%i: OP_UINT_TO_NONE", ip - 1);
-            break;
-         }
+      case OP_STR_TO_FLT:
+      {
+         Con::printf("%i: OP_STR_TO_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_COPYVAR_TO_NONE:
-         {
-            Con::printf("%i: OP_COPYVAR_TO_NONE", ip - 1);
-            break;
-         }
+      case OP_STR_TO_NONE:
+      {
+         Con::printf("%i: OP_STR_TO_NONE", ip - 1);
+         break;
+      }
 
 
-         case OP_LOADIMMED_UINT:
-         {
-            U32 val = code[ip];
-            Con::printf("%i: OP_LOADIMMED_UINT val=%i", ip - 1, val);
-            ++ip;
-            break;
-         }
+      case OP_FLT_TO_UINT:
+      {
+         Con::printf("%i: OP_FLT_TO_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_LOADIMMED_FLT:
-         {
-            F64 val = (smInFunction ? functionFloats : globalFloats)[code[ip]];
-            Con::printf("%i: OP_LOADIMMED_FLT val=%f", ip - 1, val);
-            ++ip;
-            break;
-         }
+      case OP_FLT_TO_STR:
+      {
+         Con::printf("%i: OP_FLT_TO_STR", ip - 1);
+         break;
+      }
 
 
-         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);
-            ++ip;
-            break;
-         }
+      case OP_FLT_TO_NONE:
+      {
+         Con::printf("%i: OP_FLT_TO_NONE", ip - 1);
+         break;
+      }
 
 
-         case OP_LOADIMMED_STR:
-         {
-            const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip];
-            Con::printf("%i: OP_LOADIMMED_STR str=%s", ip - 1, str);
-            ++ip;
-            break;
-         }
+      case OP_UINT_TO_FLT:
+      {
+         Con::printf("%i: OP_UINT_TO_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_DOCBLOCK_STR:
-         {
-            const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip];
-            Con::printf("%i: OP_DOCBLOCK_STR str=%s", ip - 1, str);
-            ++ip;
-            break;
-         }
+      case OP_UINT_TO_STR:
+      {
+         Con::printf("%i: OP_UINT_TO_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_LOADIMMED_IDENT:
-         {
-            StringTableEntry str = CodeToSTE(code, ip);
-            Con::printf("%i: OP_LOADIMMED_IDENT str=%s", ip - 1, str);
-            ip += 2;
-            break;
-         }
+      case OP_UINT_TO_NONE:
+      {
+         Con::printf("%i: OP_UINT_TO_NONE", ip - 1);
+         break;
+      }
 
 
-         case OP_CALLFUNC_RESOLVE:
-         {
-            StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
-            StringTableEntry fnName = CodeToSTE(code, ip);
-            U32 callType = code[ip + 2];
+      case OP_LOADIMMED_UINT:
+      {
+         U32 val = code[ip];
+         Con::printf("%i: OP_LOADIMMED_UINT val=%i", ip - 1, val);
+         ++ip;
+         break;
+      }
 
 
-            Con::printf("%i: OP_CALLFUNC_RESOLVE name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace,
-               callType == FuncCallExprNode::FunctionCall ? "FunctionCall"
-               : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall");
+      case OP_LOADIMMED_FLT:
+      {
+         F64 val = (smInFunction ? functionFloats : globalFloats)[code[ip]];
+         Con::printf("%i: OP_LOADIMMED_FLT val=%f", ip - 1, val);
+         ++ip;
+         break;
+      }
 
 
-            ip += 5;
-            break;
-         }
+      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);
+         ++ip;
+         break;
+      }
 
 
-         case OP_CALLFUNC:
-         {
-            StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
-            StringTableEntry fnName = CodeToSTE(code, ip);
-            U32 callType = code[ip + 4];
+      case OP_LOADIMMED_STR:
+      {
+         const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip];
+         Con::printf("%i: OP_LOADIMMED_STR str=%s", ip - 1, str);
+         ++ip;
+         break;
+      }
 
 
-            Con::printf("%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace,
-               callType == FuncCallExprNode::FunctionCall ? "FunctionCall"
-               : callType == FuncCallExprNode::MethodCall ? "MethodCall" : "ParentCall");
+      case OP_DOCBLOCK_STR:
+      {
+         const char* str = (smInFunction ? functionStrings : globalStrings) + code[ip];
+         Con::printf("%i: OP_DOCBLOCK_STR str=%s", ip - 1, str);
+         ++ip;
+         break;
+      }
 
 
-            ip += 5;
-            break;
-         }
+      case OP_LOADIMMED_IDENT:
+      {
+         StringTableEntry str = CodeToSTE(code, ip);
+         Con::printf("%i: OP_LOADIMMED_IDENT str=%s", ip - 1, str);
+         ip += 2;
+         break;
+      }
 
 
-         case OP_CALLFUNC_POINTER:
-         {
-            Con::printf("%i: OP_CALLFUNC_POINTER", ip - 1);
-            break;
-         }
+      case OP_CALLFUNC:
+      {
+         StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
+         StringTableEntry fnName = CodeToSTE(code, ip);
+         U32 callType = code[ip + 4];
 
 
-         case OP_CALLFUNC_THIS:
+         StringTableEntry callTypeName;
+         switch (callType)
          {
          {
-            StringTableEntry fnName = CodeToSTE(code, ip);
-            Con::printf("%i: OP_CALLFUNC_THIS name=%s ", ip - 1, fnName);
-
-            ip += 2;
-            break;
+         case FuncCallExprNode::FunctionCall: callTypeName = "FunctionCall"; break;
+         case FuncCallExprNode::MethodCall:   callTypeName = "MethodCall"; break;
+         case FuncCallExprNode::ParentCall:   callTypeName = "ParentCall"; break;
+         case FuncCallExprNode::StaticCall:   callTypeName = "StaticCall"; break;
          }
          }
 
 
-         case OP_ADVANCE_STR:
-         {
-            Con::printf("%i: OP_ADVANCE_STR", ip - 1);
-            break;
-         }
+         Con::printf("%i: OP_CALLFUNC name=%s nspace=%s callType=%s", ip - 1, fnName, fnNamespace, callTypeName);
 
 
-         case OP_ADVANCE_STR_APPENDCHAR:
-         {
-            char ch = code[ip];
-            Con::printf("%i: OP_ADVANCE_STR_APPENDCHAR char=%c", ip - 1, ch);
-            ++ip;
-            break;
-         }
+         ip += 5;
+         break;
+      }
 
 
-         case OP_ADVANCE_STR_COMMA:
-         {
-            Con::printf("%i: OP_ADVANCE_STR_COMMA", ip - 1);
-            break;
-         }
+      case OP_ADVANCE_STR:
+      {
+         Con::printf("%i: OP_ADVANCE_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_ADVANCE_STR_NUL:
-         {
-            Con::printf("%i: OP_ADVANCE_STR_NUL", ip - 1);
-            break;
-         }
+      case OP_ADVANCE_STR_APPENDCHAR:
+      {
+         char ch = code[ip];
+         Con::printf("%i: OP_ADVANCE_STR_APPENDCHAR char=%c", ip - 1, ch);
+         ++ip;
+         break;
+      }
 
 
-         case OP_REWIND_STR:
-         {
-            Con::printf("%i: OP_REWIND_STR", ip - 1);
-            break;
-         }
+      case OP_ADVANCE_STR_COMMA:
+      {
+         Con::printf("%i: OP_ADVANCE_STR_COMMA", ip - 1);
+         break;
+      }
 
 
-         case OP_TERMINATE_REWIND_STR:
-         {
-            Con::printf("%i: OP_TERMINATE_REWIND_STR", ip - 1);
-            break;
-         }
+      case OP_ADVANCE_STR_NUL:
+      {
+         Con::printf("%i: OP_ADVANCE_STR_NUL", ip - 1);
+         break;
+      }
 
 
-         case OP_COMPARE_STR:
-         {
-            Con::printf("%i: OP_COMPARE_STR", ip - 1);
-            break;
-         }
+      case OP_REWIND_STR:
+      {
+         Con::printf("%i: OP_REWIND_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_PUSH:
-         {
-            Con::printf("%i: OP_PUSH", ip - 1);
-            break;
-         }
+      case OP_TERMINATE_REWIND_STR:
+      {
+         Con::printf("%i: OP_TERMINATE_REWIND_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_PUSH_UINT:
-         {
-            Con::printf("%i: OP_PUSH_UINT", ip - 1);
-            break;
-         }
+      case OP_COMPARE_STR:
+      {
+         Con::printf("%i: OP_COMPARE_STR", ip - 1);
+         break;
+      }
 
 
-         case OP_PUSH_FLT:
-         {
-            Con::printf("%i: OP_PUSH_FLT", ip - 1);
-            break;
-         }
+      case OP_PUSH:
+      {
+         Con::printf("%i: OP_PUSH", ip - 1);
+         break;
+      }
 
 
-         case OP_PUSH_VAR:
-         {
-            Con::printf("%i: OP_PUSH_VAR", ip - 1);
-            break;
-         }
+      case OP_PUSH_UINT:
+      {
+         Con::printf("%i: OP_PUSH_UINT", ip - 1);
+         break;
+      }
 
 
-         case OP_PUSH_THIS:
-         {
-            Con::printf("%i: OP_PUSH_THIS varName=%s", ip - 1, CodeToSTE(code, ip));
-            ip += 2;
-            break;
-         }
+      case OP_PUSH_FLT:
+      {
+         Con::printf("%i: OP_PUSH_FLT", ip - 1);
+         break;
+      }
 
 
-         case OP_PUSH_FRAME:
-         {
-            Con::printf("%i: OP_PUSH_FRAME", ip - 1);
-            break;
-         }
+      case OP_PUSH_FRAME:
+      {
+         Con::printf("%i: OP_PUSH_FRAME count=%i", ip - 1, code[ip]);
+         ++ip;
+         break;
+      }
 
 
-         case OP_ASSERT:
-         {
-            const char* message = (smInFunction ? functionStrings : globalStrings) + code[ip];
-            Con::printf("%i: OP_ASSERT message=%s", ip - 1, message);
-            ++ip;
-            break;
-         }
+      case OP_ASSERT:
+      {
+         const char* message = (smInFunction ? functionStrings : globalStrings) + code[ip];
+         Con::printf("%i: OP_ASSERT message=%s", ip - 1, message);
+         ++ip;
+         break;
+      }
 
 
-         case OP_BREAK:
-         {
-            Con::printf("%i: OP_BREAK", ip - 1);
-            break;
-         }
+      case OP_BREAK:
+      {
+         Con::printf("%i: OP_BREAK", ip - 1);
+         break;
+      }
 
 
-         case OP_ITER_BEGIN:
-         {
-            StringTableEntry varName = CodeToSTE(code, ip);
-            U32 failIp = code[ip + 2];
+      case OP_ITER_BEGIN:
+      {
+         StringTableEntry varName = CodeToSTE(code, ip);
+         U32 failIp = code[ip + 2];
 
 
-            Con::printf("%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp);
+         Con::printf("%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp);
 
 
-            ip += 3;
-            break;
-         }
+         ip += 3;
+         break;
+      }
 
 
-         case OP_ITER_BEGIN_STR:
-         {
-            StringTableEntry varName = CodeToSTE(code, ip);
-            U32 failIp = code[ip + 2];
+      case OP_ITER_BEGIN_STR:
+      {
+         StringTableEntry varName = CodeToSTE(code, ip);
+         U32 failIp = code[ip + 2];
 
 
-            Con::printf("%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp);
+         Con::printf("%i: OP_ITER_BEGIN varName=%s failIp=%i", ip - 1, varName, failIp);
 
 
-            ip += 3;
-            break;
-         }
+         ip += 3;
+         break;
+      }
 
 
-         case OP_ITER:
-         {
-            U32 breakIp = code[ip];
+      case OP_ITER:
+      {
+         U32 breakIp = code[ip];
 
 
-            Con::printf("%i: OP_ITER breakIp=%i", ip - 1, breakIp);
+         Con::printf("%i: OP_ITER breakIp=%i", ip - 1, breakIp);
 
 
-            ++ip;
-            break;
-         }
+         ++ip;
+         break;
+      }
 
 
-         case OP_ITER_END:
-         {
-            Con::printf("%i: OP_ITER_END", ip - 1);
-            break;
-         }
+      case OP_ITER_END:
+      {
+         Con::printf("%i: OP_ITER_END", ip - 1);
+         break;
+      }
 
 
-         default:
-            Con::printf("%i: !!INVALID!!", ip - 1);
-            break;
+      default:
+         Con::printf("%i: !!INVALID!!", ip - 1);
+         break;
       }
       }
    }
    }
 
 

+ 0 - 3018
Engine/source/console/codeInterpreter.cpp

@@ -1,3018 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
-// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
-// Copyright (C) 2015 Faust Logic, Inc.
-//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
-
-#include "console/codeInterpreter.h"
-#include "console/compiler.h"
-#include "console/simBase.h"
-#include "console/telnetDebugger.h"
-#include "sim/netStringTable.h"
-#include "console/ICallMethod.h"
-#include "console/stringStack.h"
-#include "util/messaging/message.h"
-#include "core/strings/findMatch.h"
-#include "core/strings/stringUnit.h"
-#include "console/console.h"
-#include "console/consoleInternal.h"
-#include "cinterface/cinterface.h"
-
-//#define TORQUE_VALIDATE_STACK
-
-using namespace Compiler;
-
-enum EvalConstants
-{
-   MaxStackSize = 1024,
-   FieldBufferSizeString = 2048,
-   FieldBufferSizeNumeric = 128,
-   MethodOnComponent = -2
-};
-
-namespace Con
-{
-   // Current script file name and root, these are registered as
-   // console variables.
-   extern StringTableEntry gCurrentFile;
-   extern StringTableEntry gCurrentRoot;
-   extern S32 gObjectCopyFailures;
-}
-
-// Gets a component of an object's field value or a variable and returns it
-// in val.
-static void getFieldComponent(SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField, char val[])
-{
-   const char* prevVal = NULL;
-
-   // Grab value from object.
-   if (object && field)
-      prevVal = object->getDataField(field, array);
-
-   // 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();
-
-   // Make sure we got a value.
-   if (prevVal && *prevVal)
-   {
-      static const StringTableEntry xyzw[] =
-      {
-         StringTable->insert("x"),
-         StringTable->insert("y"),
-         StringTable->insert("z"),
-         StringTable->insert("w")
-      };
-
-      static const StringTableEntry rgba[] =
-      {
-         StringTable->insert("r"),
-         StringTable->insert("g"),
-         StringTable->insert("b"),
-         StringTable->insert("a")
-      };
-
-      // Translate xyzw and rgba into the indexed component 
-      // of the variable or field.
-      if (subField == xyzw[0] || subField == rgba[0])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n"), 128);
-
-      else if (subField == xyzw[1] || subField == rgba[1])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 1, " \t\n"), 128);
-
-      else if (subField == xyzw[2] || subField == rgba[2])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 2, " \t\n"), 128);
-
-      else if (subField == xyzw[3] || subField == rgba[3])
-         dStrcpy(val, StringUnit::getUnit(prevVal, 3, " \t\n"), 128);
-
-      else
-         val[0] = 0;
-   }
-   else
-      val[0] = 0;
-}
-
-// Sets a component of an object's field value based on the sub field. 'x' will
-// set the first field, 'y' the second, and 'z' the third.
-static void setFieldComponent(SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField)
-{
-   // Copy the current string value
-   char strValue[1024];
-   dStrncpy(strValue, STR.getStringValue(), 1024);
-
-   char val[1024] = "";
-   const char* prevVal = NULL;
-
-   // Set the value on an object field.
-   if (object && field)
-      prevVal = object->getDataField(field, array);
-
-   // Set the value on a variable.
-   else if (gEvalState.currentVariable)
-      prevVal = gEvalState.getStringVariable();
-
-   // Ensure that the variable has a value
-   if (!prevVal)
-      return;
-
-   static const StringTableEntry xyzw[] =
-   {
-      StringTable->insert("x"),
-      StringTable->insert("y"),
-      StringTable->insert("z"),
-      StringTable->insert("w")
-   };
-
-   static const StringTableEntry rgba[] =
-   {
-      StringTable->insert("r"),
-      StringTable->insert("g"),
-      StringTable->insert("b"),
-      StringTable->insert("a")
-   };
-
-   // Insert the value into the specified 
-   // component of the string.
-   if (subField == xyzw[0] || subField == rgba[0])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n"), 128);
-
-   else if (subField == xyzw[1] || subField == rgba[1])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 1, strValue, " \t\n"), 128);
-
-   else if (subField == xyzw[2] || subField == rgba[2])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 2, strValue, " \t\n"), 128);
-
-   else if (subField == xyzw[3] || subField == rgba[3])
-      dStrcpy(val, StringUnit::setUnit(prevVal, 3, strValue, " \t\n"), 128);
-
-   if (val[0] != 0)
-   {
-      // Update the field or variable.
-      if (object && field)
-         object->setDataField(field, 0, val);
-      else if (gEvalState.currentVariable)
-         gEvalState.setStringVariable(val);
-   }
-}
-extern ExprEvalState gEvalState;
-
-char sTraceBuffer[1024];
-
-StringStack STR;
-ConsoleValueStack CSTK;
-
-U32 _FLT = 0;     ///< Stack pointer for floatStack.
-U32 _UINT = 0;    ///< Stack pointer for intStack.
-U32 _ITER = 0;    ///< Stack pointer for iterStack.
-
-IterStackRecord iterStack[MaxStackSize];
-
-F64 floatStack[MaxStackSize];
-S64 intStack[MaxStackSize];
-
-char curFieldArray[256];
-char prevFieldArray[256];
-
-typedef OPCodeReturn(CodeInterpreter::*OpFn)(U32&);
-
-static OpFn gOpCodeArray[MAX_OP_CODELEN];
-
-CodeInterpreter::CodeInterpreter(CodeBlock *cb) :
-   mCodeBlock(cb),
-   mIterDepth(0),
-   mCurFloatTable(nullptr),
-   mCurStringTable(nullptr),
-   mThisFunctionName(nullptr),
-   mPopFrame(false),
-   mObjectCreationStackIndex(0),
-   mCurrentNewObject(nullptr),
-   mFailJump(0),
-   mPrevField(nullptr),
-   mCurField(nullptr),
-   mPrevObject(nullptr),
-   mCurObject(nullptr),
-   mSaveObject(nullptr),
-   mThisObject(nullptr),
-   mNSEntry(nullptr),
-   mCurFNDocBlock(nullptr),
-   mCurNSDocBlock(nullptr),
-   mCallArgc(0),
-   mCallArgv(nullptr),
-   mSaveCodeBlock(nullptr),
-   mCurrentInstruction(0)
-{
-   dMemset(&mExec, 0, sizeof(mExec));
-   dMemset(&mObjectCreationStack, 0, sizeof(mObjectCreationStack));
-   dMemset(&mNSDocBlockClass, 0, sizeof(mNSDocBlockClass));
-}
-
-CodeInterpreter::~CodeInterpreter()
-{
-}
-
-void CodeInterpreter::init()
-{
-   gOpCodeArray[OP_FUNC_DECL] = &CodeInterpreter::op_func_decl;
-   gOpCodeArray[OP_CREATE_OBJECT] = &CodeInterpreter::op_create_object;
-   gOpCodeArray[OP_ADD_OBJECT] = &CodeInterpreter::op_add_object;
-   gOpCodeArray[OP_END_OBJECT] = &CodeInterpreter::op_end_object;
-   gOpCodeArray[OP_FINISH_OBJECT] = &CodeInterpreter::op_finish_object;
-   gOpCodeArray[OP_JMPIFFNOT] = &CodeInterpreter::op_jmpiffnot;
-   gOpCodeArray[OP_JMPIFNOT] = &CodeInterpreter::op_jmpifnot;
-   gOpCodeArray[OP_JMPIFF] = &CodeInterpreter::op_jmpiff;
-   gOpCodeArray[OP_JMPIF] = &CodeInterpreter::op_jmpif;
-   gOpCodeArray[OP_JMPIFNOT_NP] = &CodeInterpreter::op_jmpifnot_np;
-   gOpCodeArray[OP_JMPIF_NP] = &CodeInterpreter::op_jmpif_np;
-   gOpCodeArray[OP_JMP] = &CodeInterpreter::op_jmp;
-   gOpCodeArray[OP_RETURN] = &CodeInterpreter::op_return;
-   gOpCodeArray[OP_RETURN_VOID] = &CodeInterpreter::op_return_void;
-   gOpCodeArray[OP_RETURN_FLT] = &CodeInterpreter::op_return_flt;
-   gOpCodeArray[OP_RETURN_UINT] = &CodeInterpreter::op_return_uint;
-   gOpCodeArray[OP_CMPEQ] = &CodeInterpreter::op_cmpeq;
-   gOpCodeArray[OP_CMPGR] = &CodeInterpreter::op_cmpgr;
-   gOpCodeArray[OP_CMPGE] = &CodeInterpreter::op_cmpge;
-   gOpCodeArray[OP_CMPLT] = &CodeInterpreter::op_cmplt;
-   gOpCodeArray[OP_CMPLE] = &CodeInterpreter::op_cmple;
-   gOpCodeArray[OP_CMPNE] = &CodeInterpreter::op_cmpne;
-   gOpCodeArray[OP_XOR] = &CodeInterpreter::op_xor;
-   gOpCodeArray[OP_MOD] = &CodeInterpreter::op_mod;
-   gOpCodeArray[OP_BITAND] = &CodeInterpreter::op_bitand;
-   gOpCodeArray[OP_BITOR] = &CodeInterpreter::op_bitor;
-   gOpCodeArray[OP_NOT] = &CodeInterpreter::op_not;
-   gOpCodeArray[OP_NOTF] = &CodeInterpreter::op_notf;
-   gOpCodeArray[OP_ONESCOMPLEMENT] = &CodeInterpreter::op_onescomplement;
-   gOpCodeArray[OP_SHR] = &CodeInterpreter::op_shr;
-   gOpCodeArray[OP_SHL] = &CodeInterpreter::op_shl;
-   gOpCodeArray[OP_AND] = &CodeInterpreter::op_and;
-   gOpCodeArray[OP_OR] = &CodeInterpreter::op_or;
-   gOpCodeArray[OP_ADD] = &CodeInterpreter::op_add;
-   gOpCodeArray[OP_SUB] = &CodeInterpreter::op_sub;
-   gOpCodeArray[OP_MUL] = &CodeInterpreter::op_mul;
-   gOpCodeArray[OP_DIV] = &CodeInterpreter::op_div;
-   gOpCodeArray[OP_NEG] = &CodeInterpreter::op_neg;
-   gOpCodeArray[OP_INC] = &CodeInterpreter::op_inc;
-   gOpCodeArray[OP_DEC] = &CodeInterpreter::op_dec;
-   gOpCodeArray[OP_SETCURVAR] = &CodeInterpreter::op_setcurvar;
-   gOpCodeArray[OP_SETCURVAR_CREATE] = &CodeInterpreter::op_setcurvar_create;
-   gOpCodeArray[OP_SETCURVAR_ARRAY] = &CodeInterpreter::op_setcurvar_array;
-   gOpCodeArray[OP_SETCURVAR_ARRAY_VARLOOKUP] = &CodeInterpreter::op_setcurvar_array_varlookup;
-   gOpCodeArray[OP_SETCURVAR_ARRAY_CREATE] = &CodeInterpreter::op_setcurvar_array_create;
-   gOpCodeArray[OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP] = &CodeInterpreter::op_setcurvar_array_create_varlookup;
-   gOpCodeArray[OP_LOADVAR_UINT] = &CodeInterpreter::op_loadvar_uint;
-   gOpCodeArray[OP_LOADVAR_FLT] = &CodeInterpreter::op_loadvar_flt;
-   gOpCodeArray[OP_LOADVAR_STR] = &CodeInterpreter::op_loadvar_str;
-   gOpCodeArray[OP_LOADVAR_VAR] = &CodeInterpreter::op_loadvar_var;
-   gOpCodeArray[OP_SAVEVAR_UINT] = &CodeInterpreter::op_savevar_uint;
-   gOpCodeArray[OP_SAVEVAR_FLT] = &CodeInterpreter::op_savevar_flt;
-   gOpCodeArray[OP_SAVEVAR_STR] = &CodeInterpreter::op_savevar_str;
-   gOpCodeArray[OP_SAVEVAR_VAR] = &CodeInterpreter::op_savevar_var;
-   gOpCodeArray[OP_SETCUROBJECT] = &CodeInterpreter::op_setcurobject;
-   gOpCodeArray[OP_SETCUROBJECT_INTERNAL] = &CodeInterpreter::op_setcurobject_internal;
-   gOpCodeArray[OP_SETCUROBJECT_NEW] = &CodeInterpreter::op_setcurobject_new;
-   gOpCodeArray[OP_SETCURFIELD] = &CodeInterpreter::op_setcurfield;
-   gOpCodeArray[OP_SETCURFIELD_ARRAY] = &CodeInterpreter::op_setcurfield_array;
-   gOpCodeArray[OP_SETCURFIELD_TYPE] = &CodeInterpreter::op_setcurfield_type;
-   gOpCodeArray[OP_SETCURFIELD_ARRAY_VAR] = &CodeInterpreter::op_setcurfield_array_var;
-   gOpCodeArray[OP_SETCURFIELD_THIS] = &CodeInterpreter::op_setcurfield_this;
-   gOpCodeArray[OP_LOADFIELD_UINT] = &CodeInterpreter::op_loadfield_uint;
-   gOpCodeArray[OP_LOADFIELD_FLT] = &CodeInterpreter::op_loadfield_flt;
-   gOpCodeArray[OP_LOADFIELD_STR] = &CodeInterpreter::op_loadfield_str;
-   gOpCodeArray[OP_SAVEFIELD_UINT] = &CodeInterpreter::op_savefield_uint;
-   gOpCodeArray[OP_SAVEFIELD_FLT] = &CodeInterpreter::op_savefield_flt;
-   gOpCodeArray[OP_SAVEFIELD_STR] = &CodeInterpreter::op_savefield_str;
-   gOpCodeArray[OP_STR_TO_UINT] = &CodeInterpreter::op_str_to_uint;
-   gOpCodeArray[OP_STR_TO_FLT] = &CodeInterpreter::op_str_to_flt;
-   gOpCodeArray[OP_STR_TO_NONE] = &CodeInterpreter::op_str_to_none;
-   gOpCodeArray[OP_FLT_TO_UINT] = &CodeInterpreter::op_flt_to_uint;
-   gOpCodeArray[OP_FLT_TO_STR] = &CodeInterpreter::op_flt_to_str;
-   gOpCodeArray[OP_FLT_TO_NONE] = &CodeInterpreter::op_flt_to_none;
-   gOpCodeArray[OP_UINT_TO_FLT] = &CodeInterpreter::op_uint_to_flt;
-   gOpCodeArray[OP_UINT_TO_STR] = &CodeInterpreter::op_uint_to_str;
-   gOpCodeArray[OP_UINT_TO_NONE] = &CodeInterpreter::op_uint_to_none;
-   gOpCodeArray[OP_COPYVAR_TO_NONE] = &CodeInterpreter::op_copyvar_to_none;
-   gOpCodeArray[OP_LOADIMMED_UINT] = &CodeInterpreter::op_loadimmed_uint;
-   gOpCodeArray[OP_LOADIMMED_FLT] = &CodeInterpreter::op_loadimmed_flt;
-   gOpCodeArray[OP_TAG_TO_STR] = &CodeInterpreter::op_tag_to_str;
-   gOpCodeArray[OP_LOADIMMED_STR] = &CodeInterpreter::op_loadimmed_str;
-   gOpCodeArray[OP_DOCBLOCK_STR] = &CodeInterpreter::op_docblock_str;
-   gOpCodeArray[OP_LOADIMMED_IDENT] = &CodeInterpreter::op_loadimmed_ident;
-   gOpCodeArray[OP_CALLFUNC_RESOLVE] = &CodeInterpreter::op_callfunc_resolve;
-   gOpCodeArray[OP_CALLFUNC] = &CodeInterpreter::op_callfunc;
-   gOpCodeArray[OP_CALLFUNC_POINTER] = &CodeInterpreter::op_callfunc_pointer;
-   gOpCodeArray[OP_CALLFUNC_THIS] = &CodeInterpreter::op_callfunc_this;
-   gOpCodeArray[OP_ADVANCE_STR] = &CodeInterpreter::op_advance_str;
-   gOpCodeArray[OP_ADVANCE_STR_APPENDCHAR] = &CodeInterpreter::op_advance_str_appendchar;
-   gOpCodeArray[OP_ADVANCE_STR_COMMA] = &CodeInterpreter::op_advance_str_comma;
-   gOpCodeArray[OP_ADVANCE_STR_NUL] = &CodeInterpreter::op_advance_str_nul;
-   gOpCodeArray[OP_REWIND_STR] = &CodeInterpreter::op_rewind_str;
-   gOpCodeArray[OP_TERMINATE_REWIND_STR] = &CodeInterpreter::op_terminate_rewind_str;
-   gOpCodeArray[OP_COMPARE_STR] = &CodeInterpreter::op_compare_str;
-   gOpCodeArray[OP_PUSH] = &CodeInterpreter::op_push;
-   gOpCodeArray[OP_PUSH_UINT] = &CodeInterpreter::op_push_uint;
-   gOpCodeArray[OP_PUSH_FLT] = &CodeInterpreter::op_push_flt;
-   gOpCodeArray[OP_PUSH_VAR] = &CodeInterpreter::op_push_var;
-   gOpCodeArray[OP_PUSH_THIS] = &CodeInterpreter::op_push_this;
-   gOpCodeArray[OP_PUSH_FRAME] = &CodeInterpreter::op_push_frame;
-   gOpCodeArray[OP_ASSERT] = &CodeInterpreter::op_assert;
-   gOpCodeArray[OP_BREAK] = &CodeInterpreter::op_break;
-   gOpCodeArray[OP_ITER_BEGIN_STR] = &CodeInterpreter::op_iter_begin_str;
-   gOpCodeArray[OP_ITER_BEGIN] = &CodeInterpreter::op_iter_begin;
-   gOpCodeArray[OP_ITER] = &CodeInterpreter::op_iter;
-   gOpCodeArray[OP_ITER_END] = &CodeInterpreter::op_iter_end;
-   gOpCodeArray[OP_INVALID] = &CodeInterpreter::op_invalid;
-}
-
-ConsoleValueRef CodeInterpreter::exec(U32 ip,
-                                      StringTableEntry functionName,
-                                      Namespace *thisNamespace,
-                                      U32 argc, 
-                                      ConsoleValueRef *argv,
-                                      bool noCalls,
-                                      StringTableEntry packageName,
-                                      S32 setFrame) 
-{
-   mExec.functionName = functionName;
-   mExec.thisNamespace = thisNamespace;
-   mExec.argc = argc;
-   mExec.argv = argv;
-   mExec.noCalls = noCalls;
-   mExec.packageName = packageName;
-   mExec.setFrame = setFrame;
-
-   mCodeBlock->incRefCount();
-
-   mPopFrame = false;
-
-#ifdef TORQUE_VALIDATE_STACK
-   U32 stackStart = STR.mStartStackSize;
-#endif
-
-   STR.clearFunctionOffset(); // ensures arg buffer offset is back to 0
-
-   // Lets load up our function arguments.
-   parseArgs(ip);
-
-   // Grab the state of the telenet debugger here once
-   // so that the push and pop frames are always balanced.
-   const bool telDebuggerOn = TelDebugger && TelDebugger->isConnected();
-   if (telDebuggerOn && setFrame < 0)
-      TelDebugger->pushStackFrame();
-
-   mSaveCodeBlock = CodeBlock::smCurrentCodeBlock;
-   CodeBlock::smCurrentCodeBlock = mCodeBlock;
-   if (mCodeBlock->name)
-   {
-      Con::gCurrentFile = mCodeBlock->name;
-      Con::gCurrentRoot = mCodeBlock->modPath;
-   }
-
-   U32 *code = mCodeBlock->code;
-
-   while (true)
-   {
-      mCurrentInstruction = code[ip++];
-      mNSEntry = nullptr;
-
-#ifdef TORQUE_VALIDATE_STACK
-      // OP Code check.
-      AssertFatal(mCurrentInstruction < MAX_OP_CODELEN, "Invalid OP code in script interpreter");
-#endif
-
-   breakContinueLabel:
-      OPCodeReturn ret = (this->*gOpCodeArray[mCurrentInstruction])(ip);
-      if (ret == OPCodeReturn::exitCode)
-         break;
-      else if (ret == OPCodeReturn::breakContinue)
-         goto breakContinueLabel;
-   }
-
-   if (telDebuggerOn && setFrame < 0)
-      TelDebugger->popStackFrame();
-
-   if (mPopFrame)
-      gEvalState.popFrame();
-
-   if (argv)
-   {
-      if (gEvalState.traceOn)
-      {
-         sTraceBuffer[0] = 0;
-         dStrcat(sTraceBuffer, "Leaving ", 1024);
-
-         if (packageName)
-         {
-            dStrcat(sTraceBuffer, "[", 1024);
-            dStrcat(sTraceBuffer, packageName, 1024);
-            dStrcat(sTraceBuffer, "]", 1024);
-         }
-         if (thisNamespace && thisNamespace->mName)
-         {
-            dSprintf(sTraceBuffer + dStrlen(sTraceBuffer), (U32)(sizeof(sTraceBuffer) - dStrlen(sTraceBuffer)),
-               "%s::%s() - return %s", thisNamespace->mName, mThisFunctionName, STR.getStringValue());
-         }
-         else
-         {
-            dSprintf(sTraceBuffer + dStrlen(sTraceBuffer), (U32)(sizeof(sTraceBuffer) - dStrlen(sTraceBuffer)),
-               "%s() - return %s", mThisFunctionName, STR.getStringValue());
-         }
-         Con::printf("%s", sTraceBuffer);
-      }
-   }
-
-   CodeBlock::smCurrentCodeBlock = mSaveCodeBlock;
-   if (mSaveCodeBlock && mSaveCodeBlock->name)
-   {
-      Con::gCurrentFile = mSaveCodeBlock->name;
-      Con::gCurrentRoot = mSaveCodeBlock->modPath;
-   }
-
-   mCodeBlock->decRefCount();
-
-#ifdef TORQUE_VALIDATE_STACK
-   AssertFatal(!(STR.mStartStackSize > stackStart), "String stack not popped enough in script exec");
-   AssertFatal(!(STR.mStartStackSize < stackStart), "String stack popped too much in script exec");
-#endif
-
-   return mReturnValue;
-}
-
-void CodeInterpreter::parseArgs(U32 &ip)
-{
-   U32 *code = mCodeBlock->code;
-
-   if (mExec.argv)
-   {
-      U32 fnArgc = code[ip + 2 + 6];
-      mThisFunctionName = Compiler::CodeToSTE(code, ip);
-      S32 wantedArgc = getMin(mExec.argc - 1, fnArgc); // argv[0] is func name
-      if (gEvalState.traceOn)
-      {
-         sTraceBuffer[0] = 0;
-         dStrcat(sTraceBuffer, "Entering ", 1024);
-
-         if (mExec.packageName)
-         {
-            dStrcat(sTraceBuffer, "[", 1024);
-            dStrcat(sTraceBuffer, mExec.packageName, 1024);
-            dStrcat(sTraceBuffer, "]", 1024);
-         }
-         if (mExec.thisNamespace && mExec.thisNamespace->mName)
-         {
-            dSprintf(sTraceBuffer + dStrlen(sTraceBuffer), (U32)(sizeof(sTraceBuffer) - dStrlen(sTraceBuffer)),
-               "%s::%s(", mExec.thisNamespace->mName, mThisFunctionName);
-         }
-         else
-         {
-            dSprintf(sTraceBuffer + dStrlen(sTraceBuffer), (U32)(sizeof(sTraceBuffer) - dStrlen(sTraceBuffer)),
-               "%s(", mThisFunctionName);
-         }
-         for (S32 i = 0; i < wantedArgc; i++)
-         {
-            dStrcat(sTraceBuffer, mExec.argv[i + 1], 1024);
-            if (i != wantedArgc - 1)
-               dStrcat(sTraceBuffer, ", ", 1024);
-         }
-         dStrcat(sTraceBuffer, ")", 1024);
-         Con::printf("%s", sTraceBuffer);
-      }
-
-      gEvalState.pushFrame(mThisFunctionName, mExec.thisNamespace);
-      mPopFrame = true;
-
-      StringTableEntry thisPointer = StringTable->insert("%this");
-
-      for (S32 i = 0; i < wantedArgc; i++)
-      {
-         StringTableEntry var = Compiler::CodeToSTE(code, ip + (2 + 6 + 1) + (i * 2));
-         gEvalState.setCurVarNameCreate(var);
-
-         ConsoleValueRef ref = mExec.argv[i + 1];
-
-         switch (ref.getType())
-         {
-         case ConsoleValue::TypeInternalInt:
-            gEvalState.setIntVariable(ref);
-            break;
-         case ConsoleValue::TypeInternalFloat:
-            gEvalState.setFloatVariable(ref);
-            break;
-         case ConsoleValue::TypeInternalStringStackPtr:
-            gEvalState.setStringStackPtrVariable(ref.getStringStackPtrValue());
-            break;
-         case ConsoleValue::TypeInternalStackString:
-         case ConsoleValue::TypeInternalString:
-         default:
-            gEvalState.setStringVariable(ref);
-            break;
-         }
-
-         if (var == thisPointer)
-         {
-            // %this gets optimized as it is flagged as a constant.
-            // Since it is guarenteed to be constant, we can then perform optimizations.
-            gEvalState.currentVariable->mIsConstant = true;
-
-            // Store a reference to the this pointer object.
-            mThisObject = Sim::findObject(gEvalState.getStringVariable());
-         }
-      }
-
-      ip = ip + (fnArgc * 2) + (2 + 6 + 1);
-      mCurFloatTable = mCodeBlock->functionFloats;
-      mCurStringTable = mCodeBlock->functionStrings;
-   }
-   else
-   {
-      mCurFloatTable = mCodeBlock->globalFloats;
-      mCurStringTable = mCodeBlock->globalStrings;
-
-      // If requested stack frame isn't available, request a new one
-      // (this prevents assert failures when creating local
-      //  variables without a stack frame)
-      if (gEvalState.getStackDepth() <= mExec.setFrame)
-         mExec.setFrame = -1;
-
-      // Do we want this code to execute using a new stack frame?
-      if (mExec.setFrame < 0)
-      {
-         gEvalState.pushFrame(NULL, NULL);
-         mPopFrame = true;
-      }
-      else
-      {
-         // We want to copy a reference to an existing stack frame
-         // on to the top of the stack.  Any change that occurs to 
-         // the locals during this new frame will also occur in the 
-         // original frame.
-         S32 stackIndex = gEvalState.getStackDepth() - mExec.setFrame - 1;
-         gEvalState.pushFrameRef(stackIndex);
-         mPopFrame = true;
-      }
-   }
-}
-
-OPCodeReturn CodeInterpreter::op_func_decl(U32 &ip)
-{
-   U32 *code = mCodeBlock->code;
-
-   if (!mExec.noCalls)
-   {
-      StringTableEntry fnName = CodeToSTE(code, ip);
-      StringTableEntry fnNamespace = CodeToSTE(code, ip + 2);
-      StringTableEntry fnPackage = CodeToSTE(code, ip + 4);
-      bool hasBody = (code[ip + 6] & 0x01) != 0;
-      U32 lineNumber = code[ip + 6] >> 1;
-
-      Namespace::unlinkPackages();
-      Namespace *ns = Namespace::find(fnNamespace, fnPackage);
-      ns->addFunction(fnName, mCodeBlock, hasBody ? ip : 0, mCurFNDocBlock ? dStrdup(mCurFNDocBlock) : NULL, lineNumber);// if no body, set the IP to 0
-      if (mCurNSDocBlock)
-      {
-         // If we have a docblock before we declare the function in the script file,
-         // this will attempt to set the doc block to the function.
-         // See OP_DOCBLOCK_STR
-         if (fnNamespace == StringTable->lookup(mNSDocBlockClass))
-         {
-            char *usageStr = dStrdup(mCurNSDocBlock);
-            usageStr[dStrlen(usageStr)] = '\0';
-            ns->mUsage = usageStr;
-            ns->mCleanUpUsage = true;
-            mCurNSDocBlock = NULL;
-         }
-      }
-      Namespace::relinkPackages();
-
-      // If we had a docblock, it's definitely not valid anymore, so clear it out.
-      mCurFNDocBlock = NULL;
-
-      //Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip);
-   }
-   ip = code[ip + 7];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_create_object(U32 &ip)
-{
-   U32 *code = mCodeBlock->code;
-
-   // Read some useful info.
-   StringTableEntry objParent = CodeToSTE(code, ip);
-   bool isDataBlock = code[ip + 2];
-   bool isInternal = code[ip + 3];
-   bool isSingleton = code[ip + 4];
-   U32  lineNumber = code[ip + 5];
-   mFailJump = code[ip + 6];
-
-   // If we don't allow calls, we certainly don't allow creating objects!
-   // Moved this to after failJump is set. Engine was crashing when
-   // noCalls = true and an object was being created at the beginning of
-   // a file. ADL.
-   if (mExec.noCalls)
-   {
-      ip = mFailJump;
-      return OPCodeReturn::success;
-   }
-
-   // Push the old info to the stack
-   //Assert( objectCreationStackIndex < objectCreationStackSize );
-   mObjectCreationStack[mObjectCreationStackIndex].newObject = mCurrentNewObject;
-   mObjectCreationStack[mObjectCreationStackIndex++].failJump = mFailJump;
-
-   // Get the constructor information off the stack.
-   CSTK.getArgcArgv(NULL, &mCallArgc, &mCallArgv);
-   const char *objectName = mCallArgv[2];
-
-   // Con::printf("Creating object...");
-
-   // objectName = argv[1]...
-   mCurrentNewObject = NULL;
-
-   // Are we creating a datablock? If so, deal with case where we override
-   // an old one.
-   if (isDataBlock)
-   {
-      // Con::printf("  - is a datablock");
-
-      // Find the old one if any.
-      SimObject *db = Sim::getDataBlockGroup()->findObject(objectName);
-
-      // Make sure we're not changing types on ourselves...
-      if (db && dStricmp(db->getClassName(), mCallArgv[1]))
-      {
-         Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare data block %s with a different class.", mCodeBlock->getFileLine(ip), objectName);
-         ip = mFailJump;
-         STR.popFrame();
-         CSTK.popFrame();
-         return OPCodeReturn::success;
-      }
-
-      // If there was one, set the currentNewObject and move on.
-      if (db)
-         mCurrentNewObject = db;
-   }
-   else if (!isInternal)
-   {
-      // IF we aren't looking at a local/internal object, then check if 
-      // this object already exists in the global space
-
-      AbstractClassRep* rep = AbstractClassRep::findClassRep(objectName);
-      if (rep != NULL) {
-         Con::errorf(ConsoleLogEntry::General, "%s: Cannot name object [%s] the same name as a script class.",
-            mCodeBlock->getFileLine(ip), objectName);
-         ip = mFailJump;
-         STR.popFrame();
-         CSTK.popFrame();
-         return OPCodeReturn::success;
-      }
-
-      SimObject *obj = Sim::findObject((const char*)objectName);
-      if (obj /*&& !obj->isLocalName()*/)
-      {
-         if (isSingleton)
-         {
-            // Make sure we're not trying to change types
-            if (dStricmp(obj->getClassName(), (const char*)mCallArgv[1]) != 0)
-            {
-               Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare object [%s] with a different class [%s] - was [%s].",
-                  mCodeBlock->getFileLine(ip), objectName, (const char*)mCallArgv[1], obj->getClassName());
-               ip = mFailJump;
-               STR.popFrame();
-               CSTK.popFrame();
-               return OPCodeReturn::success;
-            }
-
-            // We're creating a singleton, so use the found object
-            // instead of creating a new object.
-            mCurrentNewObject = obj;
-         }
-         else
-         {
-            const char* redefineBehavior = Con::getVariable("$Con::redefineBehavior");
-
-            if (dStricmp(redefineBehavior, "replaceExisting") == 0)
-            {
-               // Save our constructor args as the argv vector is stored on the
-               // string stack and may get stomped if deleteObject triggers
-               // script execution.
-
-               ConsoleValueRef savedArgv[StringStack::MaxArgs];
-               for (int i = 0; i< mCallArgc; i++) {
-                  savedArgv[i] = mCallArgv[i];
-               }
-               //dMemcpy( savedArgv, callArgv, sizeof( savedArgv[ 0 ] ) * callArgc );
-
-               // Prevent stack value corruption
-               CSTK.pushFrame();
-               STR.pushFrame();
-               // --
-
-               obj->deleteObject();
-               obj = NULL;
-
-               // Prevent stack value corruption
-               CSTK.popFrame();
-               STR.popFrame();
-               // --
-
-               //dMemcpy( callArgv, savedArgv, sizeof( callArgv[ 0 ] ) * callArgc );
-               for (int i = 0; i<mCallArgc; i++) {
-                  mCallArgv[i] = savedArgv[i];
-               }
-            }
-            else if (dStricmp(redefineBehavior, "renameNew") == 0)
-            {
-               for (U32 i = 1;; ++i)
-               {
-                  String newName = String::ToString("%s%i", objectName, i);
-                  if (!Sim::findObject(newName))
-                  {
-                     objectName = StringTable->insert(newName);
-                     break;
-                  }
-               }
-            }
-            else if (dStricmp(redefineBehavior, "unnameNew") == 0)
-            {
-               objectName = StringTable->insert("");
-            }
-            else if (dStricmp(redefineBehavior, "postfixNew") == 0)
-            {
-               const char* postfix = Con::getVariable("$Con::redefineBehaviorPostfix");
-               String newName = String::ToString("%s%s", objectName, postfix);
-
-               if (Sim::findObject(newName))
-               {
-                  Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare object with postfix [%s].",
-                     mCodeBlock->getFileLine(ip), newName.c_str());
-                  ip = mFailJump;
-                  STR.popFrame();
-                  CSTK.popFrame();
-                  return OPCodeReturn::success;
-               }
-               else
-                  objectName = StringTable->insert(newName);
-            }
-            else
-            {
-               Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare object [%s].",
-                  mCodeBlock->getFileLine(ip), objectName);
-               ip = mFailJump;
-               STR.popFrame();
-               CSTK.popFrame();
-               return OPCodeReturn::success;
-            }
-         }
-      }
-   }
-
-   STR.popFrame();
-   CSTK.popFrame();
-
-   if (!mCurrentNewObject)
-   {
-      // Well, looks like we have to create a new object.
-      ConsoleObject *object = ConsoleObject::create((const char*)mCallArgv[1]);
-
-      // Deal with failure!
-      if (!object)
-      {
-         Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-conobject class %s.", mCodeBlock->getFileLine(ip), (const char*)mCallArgv[1]);
-         ip = mFailJump;
-         return OPCodeReturn::success;
-      }
-
-      // Do special datablock init if appropros
-      if (isDataBlock)
-      {
-         SimDataBlock *dataBlock = dynamic_cast<SimDataBlock *>(object);
-         if (dataBlock)
-         {
-            dataBlock->assignId();
-         }
-         else
-         {
-            // They tried to make a non-datablock with a datablock keyword!
-            Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-datablock class %s.", mCodeBlock->getFileLine(ip), (const char*)mCallArgv[1]);
-            // Clean up...
-            delete object;
-            mCurrentNewObject = NULL;
-            ip = mFailJump;
-            return OPCodeReturn::success;
-         }
-      }
-
-      // Finally, set currentNewObject to point to the new one.
-      mCurrentNewObject = dynamic_cast<SimObject *>(object);
-
-      // Deal with the case of a non-SimObject.
-      if (!mCurrentNewObject)
-      {
-         Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-SimObject class %s.", mCodeBlock->getFileLine(ip), (const char*)mCallArgv[1]);
-         delete object;
-         mCurrentNewObject = NULL;
-         ip = mFailJump;
-         return OPCodeReturn::success;
-      }
-
-      // Set the declaration line
-      mCurrentNewObject->setDeclarationLine(lineNumber);
-
-      // Set the file that this object was created in
-      mCurrentNewObject->setFilename(mCodeBlock->name);
-
-      // Does it have a parent object? (ie, the copy constructor : syntax, not inheriance)
-      if (*objParent)
-      {
-         // Find it!
-         SimObject *parent;
-         if (Sim::findObject(objParent, parent))
-         {
-            // Con::printf(" - Parent object found: %s", parent->getClassName());
-
-            mCurrentNewObject->setCopySource(parent);
-            mCurrentNewObject->assignFieldsFrom(parent);
-
-            // copy any substitution statements
-            SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
-            if (parent_db)
-            {
-               SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(mCurrentNewObject);
-               if (currentNewObject_db)
-                  currentNewObject_db->copySubstitutionsFrom(parent_db);
-            }
-         }
-         else
-         {
-            if (Con::gObjectCopyFailures == -1)
-               Con::errorf(ConsoleLogEntry::General, "%s: Unable to find parent object %s for %s.", mCodeBlock->getFileLine(ip), objParent, (const char*)mCallArgv[1]);
-            else
-               ++Con::gObjectCopyFailures;
-
-            // Fail to create the object.
-            delete object;
-            mCurrentNewObject = NULL;
-            ip = mFailJump;
-            return OPCodeReturn::success;
-         }
-      }
-
-      // If a name was passed, assign it.
-      if (objectName[0])
-      {
-         if (!isInternal)
-            mCurrentNewObject->assignName(objectName);
-         else
-            mCurrentNewObject->setInternalName(objectName);
-
-         // Set the original name
-         mCurrentNewObject->setOriginalName(objectName);
-      }
-
-      // Prevent stack value corruption
-      CSTK.pushFrame();
-      STR.pushFrame();
-      // --
-
-      // Do the constructor parameters.
-      if (!mCurrentNewObject->processArguments(mCallArgc - 3, mCallArgv + 3))
-      {
-         delete mCurrentNewObject;
-         mCurrentNewObject = NULL;
-         ip = mFailJump;
-
-         // Prevent stack value corruption
-         CSTK.popFrame();
-         STR.popFrame();
-         // --
-         return OPCodeReturn::success;
-      }
-
-      // Prevent stack value corruption
-      CSTK.popFrame();
-      STR.popFrame();
-      // --
-
-      // If it's not a datablock, allow people to modify bits of it.
-      if (!isDataBlock)
-      {
-         mCurrentNewObject->setModStaticFields(true);
-         mCurrentNewObject->setModDynamicFields(true);
-      }
-   }
-   else
-   {
-      mCurrentNewObject->reloadReset(); // AFX (reload-reset)
-                                       // Does it have a parent object? (ie, the copy constructor : syntax, not inheriance)
-      if (*objParent)
-      {
-         // Find it!
-         SimObject *parent;
-         if (Sim::findObject(objParent, parent))
-         {
-            // Con::printf(" - Parent object found: %s", parent->getClassName());
-
-            // temporarily block name change
-            SimObject::preventNameChanging = true;
-            mCurrentNewObject->setCopySource(parent);
-            mCurrentNewObject->assignFieldsFrom(parent);
-            // restore name changing
-            SimObject::preventNameChanging = false;
-
-            // copy any substitution statements
-            SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
-            if (parent_db)
-            {
-               SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(mCurrentNewObject);
-               if (currentNewObject_db)
-                  currentNewObject_db->copySubstitutionsFrom(parent_db);
-            }
-         }
-         else
-            Con::errorf(ConsoleLogEntry::General, "%d: Unable to find parent object %s for %s.", lineNumber, objParent, (const char*)mCallArgv[1]);
-      }
-   }
-
-   // Advance the IP past the create info...
-   ip += 7;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_add_object(U32 &ip)
-{
-   // See OP_SETCURVAR for why we do this.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-
-   // Do we place this object at the root?
-   bool placeAtRoot = mCodeBlock->code[ip++];
-
-   // Con::printf("Adding object %s", currentNewObject->getName());
-
-   // Prevent stack value corruption
-   CSTK.pushFrame();
-   STR.pushFrame();
-   // --
-
-   // Make sure it wasn't already added, then add it.
-   if (mCurrentNewObject->isProperlyAdded() == false)
-   {
-      bool ret = false;
-
-      Message *msg = dynamic_cast<Message *>(mCurrentNewObject);
-      if (msg)
-      {
-         SimObjectId id = Message::getNextMessageID();
-         if (id != 0xffffffff)
-            ret = mCurrentNewObject->registerObject(id);
-         else
-            Con::errorf("%s: No more object IDs available for messages", mCodeBlock->getFileLine(ip));
-      }
-      else
-         ret = mCurrentNewObject->registerObject();
-
-      if (!ret)
-      {
-         // This error is usually caused by failing to call Parent::initPersistFields in the class' initPersistFields().
-         Con::warnf(ConsoleLogEntry::General, "%s: Register object failed for object %s of class %s.", mCodeBlock->getFileLine(ip), mCurrentNewObject->getName(), mCurrentNewObject->getClassName());
-         delete mCurrentNewObject;
-         mCurrentNewObject = NULL;
-         ip = mFailJump;
-         // Prevent stack value corruption
-         CSTK.popFrame();
-         STR.popFrame();
-         // --
-         return OPCodeReturn::success;
-      }
-   }
-
-   // Are we dealing with a datablock?
-   SimDataBlock *dataBlock = dynamic_cast<SimDataBlock *>(mCurrentNewObject);
-   static String errorStr;
-
-   // If so, preload it.
-   if (dataBlock && !dataBlock->preload(true, errorStr))
-   {
-      Con::errorf(ConsoleLogEntry::General, "%s: preload failed for %s: %s.", mCodeBlock->getFileLine(ip),
-         mCurrentNewObject->getName(), errorStr.c_str());
-      dataBlock->deleteObject();
-      mCurrentNewObject = NULL;
-      ip = mFailJump;
-
-      // Prevent stack value corruption
-      CSTK.popFrame();
-      STR.popFrame();
-      // --
-      return OPCodeReturn::success;
-   }
-
-   // What group will we be added to, if any?
-   U32 groupAddId = intStack[_UINT];
-   SimGroup *grp = NULL;
-   SimSet   *set = NULL;
-   bool isMessage = dynamic_cast<Message *>(mCurrentNewObject) != NULL;
-
-   if (!placeAtRoot || !mCurrentNewObject->getGroup())
-   {
-      if (!isMessage)
-      {
-         if (!placeAtRoot)
-         {
-            // Otherwise just add to the requested group or set.
-            if (!Sim::findObject(groupAddId, grp))
-               Sim::findObject(groupAddId, set);
-         }
-
-         if (placeAtRoot)
-         {
-            // Deal with the instantGroup if we're being put at the root or we're adding to a component.
-            if (Con::gInstantGroup.isEmpty()
-               || !Sim::findObject(Con::gInstantGroup, grp))
-               grp = Sim::getRootGroup();
-         }
-      }
-
-      // If we didn't get a group, then make sure we have a pointer to
-      // the rootgroup.
-      if (!grp)
-         grp = Sim::getRootGroup();
-
-      // add to the parent group
-      grp->addObject(mCurrentNewObject);
-
-      // If for some reason the add failed, add the object to the
-      // root group so it won't leak.
-      if (!mCurrentNewObject->getGroup())
-         Sim::getRootGroup()->addObject(mCurrentNewObject);
-
-      // add to any set we might be in
-      if (set)
-         set->addObject(mCurrentNewObject);
-   }
-
-   // store the new object's ID on the stack (overwriting the group/set
-   // id, if one was given, otherwise getting pushed)
-   if (placeAtRoot)
-      intStack[_UINT] = mCurrentNewObject->getId();
-   else
-      intStack[++_UINT] = mCurrentNewObject->getId();
-
-   // Prevent stack value corruption
-   CSTK.popFrame();
-   STR.popFrame();
-   // --
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_end_object(U32 &ip)
-{
-   // If we're not to be placed at the root, make sure we clean up
-   // our group reference.
-   bool placeAtRoot = mCodeBlock->code[ip++];
-   if (!placeAtRoot)
-      _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_finish_object(U32 &ip)
-{
-   if (mCurrentNewObject)
-      mCurrentNewObject->onPostAdd();
-
-   //Assert( objectCreationStackIndex >= 0 );
-   // Restore the object info from the stack [7/9/2007 Black]
-   mCurrentNewObject = mObjectCreationStack[--mObjectCreationStackIndex].newObject;
-   mFailJump = mObjectCreationStack[mObjectCreationStackIndex].failJump;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_jmpiffnot(U32 &ip)
-{
-   if (floatStack[_FLT--])
-   {
-      ip++;
-      return OPCodeReturn::success;
-   }
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-
-OPCodeReturn CodeInterpreter::op_jmpifnot(U32 &ip)
-{
-   if (intStack[_UINT--])
-   {
-      ip++;
-      return OPCodeReturn::success;
-   }
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_jmpiff(U32 &ip)
-{
-   if (!floatStack[_FLT--])
-   {
-      ip++;
-      return OPCodeReturn::success;
-   }
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_jmpif(U32 &ip)
-{
-   if (!intStack[_UINT--])
-   {
-      ip++;
-      return OPCodeReturn::success;
-   }
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_jmpifnot_np(U32 &ip)
-{
-   if (intStack[_UINT])
-   {
-      _UINT--;
-      ip++;
-      return OPCodeReturn::success;
-   }
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_jmpif_np(U32 &ip)
-{
-   if (!intStack[_UINT])
-   {
-      _UINT--;
-      ip++;
-      return OPCodeReturn::success;
-   }
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_jmp(U32 &ip)
-{
-   ip = mCodeBlock->code[ip];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_return_void(U32 &ip)
-{
-   STR.setStringValue("");
-   // We're falling thru here on purpose.
-
-   OPCodeReturn ret = op_return(ip);
-
-   return ret;
-}
-
-OPCodeReturn CodeInterpreter::op_return(U32 &ip)
-{
-   StringStackPtr retValue = STR.getStringValuePtr();
-
-   if (mIterDepth > 0)
-   {
-      // Clear iterator state.
-      while (mIterDepth > 0)
-      {
-         iterStack[--_ITER].mIsStringIter = false;
-         --mIterDepth;
-      }
-
-      STR.rewind();
-      STR.setStringValue(StringStackPtrRef(retValue).getPtr(&STR)); // Not nice but works.
-      retValue = STR.getStringValuePtr();
-   }
-
-   // Previously the return value was on the stack and would be returned using STR.getStringValue().
-   // Now though we need to wrap it in a ConsoleValueRef 
-   mReturnValue.value = CSTK.pushStringStackPtr(retValue);
-
-   return OPCodeReturn::exitCode;
-}
-
-OPCodeReturn CodeInterpreter::op_return_flt(U32 &ip)
-{
-   if (mIterDepth > 0)
-   {
-      // Clear iterator state.
-      while (mIterDepth > 0)
-      {
-         iterStack[--_ITER].mIsStringIter = false;
-         --mIterDepth;
-      }
-
-   }
-
-   mReturnValue.value = CSTK.pushFLT(floatStack[_FLT]);
-   _FLT--;
-
-   return OPCodeReturn::exitCode;
-}
-
-OPCodeReturn CodeInterpreter::op_return_uint(U32 &ip)
-{
-   if (mIterDepth > 0)
-   {
-      // Clear iterator state.
-      while (mIterDepth > 0)
-      {
-         iterStack[--_ITER].mIsStringIter = false;
-         --mIterDepth;
-      }
-   }
-
-   mReturnValue.value = CSTK.pushUINT(intStack[_UINT]);
-   _UINT--;
-
-   return OPCodeReturn::exitCode;
-}
-
-OPCodeReturn CodeInterpreter::op_cmpeq(U32 &ip)
-{
-   intStack[_UINT + 1] = bool(floatStack[_FLT] == floatStack[_FLT - 1]);
-   _UINT++;
-   _FLT -= 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_cmpgr(U32 &ip)
-{
-   intStack[_UINT + 1] = bool(floatStack[_FLT] > floatStack[_FLT - 1]);
-   _UINT++;
-   _FLT -= 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_cmpge(U32 &ip)
-{
-   intStack[_UINT + 1] = bool(floatStack[_FLT] >= floatStack[_FLT - 1]);
-   _UINT++;
-   _FLT -= 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_cmplt(U32 &ip)
-{
-   intStack[_UINT + 1] = bool(floatStack[_FLT] < floatStack[_FLT - 1]);
-   _UINT++;
-   _FLT -= 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_cmple(U32 &ip)
-{
-   intStack[_UINT + 1] = bool(floatStack[_FLT] <= floatStack[_FLT - 1]);
-   _UINT++;
-   _FLT -= 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_cmpne(U32 &ip)
-{
-   intStack[_UINT + 1] = bool(floatStack[_FLT] != floatStack[_FLT - 1]);
-   _UINT++;
-   _FLT -= 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_xor(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] ^ intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_mod(U32 &ip)
-{
-   if (intStack[_UINT - 1] != 0)
-      intStack[_UINT - 1] = intStack[_UINT] % intStack[_UINT - 1];
-   else
-      intStack[_UINT - 1] = 0;
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_bitand(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] & intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_bitor(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] | intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_not(U32 &ip)
-{
-   intStack[_UINT] = !intStack[_UINT];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_notf(U32 &ip)
-{
-   intStack[_UINT + 1] = !floatStack[_FLT];
-   _FLT--;
-   _UINT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_onescomplement(U32 &ip)
-{
-   intStack[_UINT] = ~intStack[_UINT];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_shr(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] >> intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_shl(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] << intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_and(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] && intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_or(U32 &ip)
-{
-   intStack[_UINT - 1] = intStack[_UINT] || intStack[_UINT - 1];
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_add(U32 &ip)
-{
-   floatStack[_FLT - 1] = floatStack[_FLT] + floatStack[_FLT - 1];
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_sub(U32 &ip)
-{
-   floatStack[_FLT - 1] = floatStack[_FLT] - floatStack[_FLT - 1];
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_mul(U32 &ip)
-{
-   floatStack[_FLT - 1] = floatStack[_FLT] * floatStack[_FLT - 1];
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_div(U32 &ip)
-{
-   floatStack[_FLT - 1] = floatStack[_FLT] / floatStack[_FLT - 1];
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_neg(U32 &ip)
-{
-   floatStack[_FLT] = -floatStack[_FLT];
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_inc(U32 &ip)
-{
-   StringTableEntry var = CodeToSTE(mCodeBlock->code, ip);
-   ip += 2;
-
-   // If a variable is set, then these must be NULL. It is necessary
-   // to set this here so that the vector parser can appropriately
-   // identify whether it's dealing with a vector.
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarNameCreate(var);
-
-   // In order to let docblocks work properly with variables, we have
-   // clear the current docblock when we do an assign. This way it 
-   // won't inappropriately carry forward to following function decls.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-
-   F64 val = gEvalState.getFloatVariable() + 1.0;
-   gEvalState.setFloatVariable(val);
-
-   // We gotta push val onto the stack. What if we have
-   // more expressions that have to use this.
-   // If we don't, we send out an op code to pop it.
-   floatStack[_FLT + 1] = val;
-   _FLT++;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_dec(U32 &ip)
-{
-   StringTableEntry var = CodeToSTE(mCodeBlock->code, ip);
-   ip += 2;
-
-   // If a variable is set, then these must be NULL. It is necessary
-   // to set this here so that the vector parser can appropriately
-   // identify whether it's dealing with a vector.
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarNameCreate(var);
-
-   // In order to let docblocks work properly with variables, we have
-   // clear the current docblock when we do an assign. This way it 
-   // won't inappropriately carry forward to following function decls.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-
-   F64 val = gEvalState.getFloatVariable() - 1.0;
-   gEvalState.setFloatVariable(val);
-
-   // We gotta push val onto the stack. What if we have
-   // more expressions that have to use this.
-   // If we don't, we send out an op code to pop it.
-   floatStack[_FLT + 1] = val;
-   _FLT++;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurvar(U32 &ip)
-{
-   StringTableEntry var = CodeToSTE(mCodeBlock->code, ip);
-   ip += 2;
-
-   // If a variable is set, then these must be NULL. It is necessary
-   // to set this here so that the vector parser can appropriately
-   // identify whether it's dealing with a vector.
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarName(var);
-
-   // In order to let docblocks work properly with variables, we have
-   // clear the current docblock when we do an assign. This way it 
-   // won't inappropriately carry forward to following function decls.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurvar_create(U32 &ip)
-{
-   StringTableEntry var = CodeToSTE(mCodeBlock->code, ip);
-   ip += 2;
-
-   // See OP_SETCURVAR
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarNameCreate(var);
-
-   // See OP_SETCURVAR for why we do this.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurvar_array(U32 &ip)
-{
-   StringTableEntry var = STR.getSTValue();
-
-   // See OP_SETCURVAR
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarName(var);
-
-   // See OP_SETCURVAR for why we do this.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurvar_array_varlookup(U32 &ip)
-{
-   StringTableEntry arrayName = CodeToSTE(mCodeBlock->code, ip);
-   StringTableEntry arrayLookup = CodeToSTE(mCodeBlock->code, ip + 2);
-   ip += 4;
-
-   STR.setStringValue(arrayName);
-   STR.advance();
-
-   // See OP_SETCURVAR
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   // resolve arrayLookup to get the 'value'
-   // Note: we have to setCurVarNameCreate in case the var doesn't exist.
-   // this won't cause much of a performance hit since vars are hashed.
-   gEvalState.setCurVarNameCreate(arrayLookup);
-   StringTableEntry hash = gEvalState.getStringVariable();
-
-   STR.setStringValue(hash);
-   STR.rewind();
-
-   // Generate new array name.
-   StringTableEntry var = STR.getSTValue();
-   gEvalState.setCurVarName(var);
-
-   // See OP_SETCURVAR for why we do this.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurvar_array_create(U32 &ip)
-{
-   StringTableEntry var = STR.getSTValue();
-
-   // See OP_SETCURVAR
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarNameCreate(var);
-
-   // See OP_SETCURVAR for why we do this.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurvar_array_create_varlookup(U32 &ip)
-{
-   StringTableEntry arrayName = CodeToSTE(mCodeBlock->code, ip);
-   StringTableEntry arrayLookup = CodeToSTE(mCodeBlock->code, ip + 2);
-   ip += 4;
-
-   // See OP_SETCURVAR
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   STR.setStringValue(arrayName);
-   STR.advance();
-
-   // resolve arrayLookup to get the 'value'
-   // Note: we have to setCurVarNameCreate in case the var doesn't exist.
-   // this won't cause much of a performance hit since vars are hashed.
-   gEvalState.setCurVarNameCreate(arrayLookup);
-   StringTableEntry hash = gEvalState.getStringVariable();
-
-   STR.setStringValue(hash);
-   STR.rewind();
-
-   // Generate new array name.
-   StringTableEntry var = STR.getSTValue();
-   gEvalState.setCurVarNameCreate(var);
-
-   // See OP_SETCURVAR for why we do this.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadvar_uint(U32 &ip)
-{
-   intStack[_UINT + 1] = gEvalState.getIntVariable();
-   _UINT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadvar_flt(U32 &ip)
-{
-   floatStack[_FLT + 1] = gEvalState.getFloatVariable();
-   _FLT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadvar_str(U32 &ip)
-{
-   StringTableEntry val = gEvalState.getStringVariable();
-   STR.setStringValue(val);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadvar_var(U32 &ip)
-{
-   // Sets current source of OP_SAVEVAR_VAR
-   gEvalState.copyVariable = gEvalState.currentVariable;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savevar_uint(U32 &ip)
-{
-   gEvalState.setIntVariable(intStack[_UINT]);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savevar_flt(U32 &ip)
-{
-   gEvalState.setFloatVariable(floatStack[_FLT]);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savevar_str(U32 &ip)
-{
-   gEvalState.setStringVariable(STR.getStringValue());
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savevar_var(U32 &ip)
-{
-   // this basically handles %var1 = %var2
-   gEvalState.setCopyVariable();
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurobject(U32 &ip)
-{
-   // Save the previous object for parsing vector fields.
-   mPrevObject = mCurObject;
-   StringTableEntry val = STR.getStringValue();
-
-   // Sim::findObject will sometimes find valid objects from
-   // multi-component strings. This makes sure that doesn't
-   // happen.
-   for (const char* check = val; *check; check++)
-   {
-      if (*check == ' ')
-      {
-         val = "";
-         break;
-      }
-   }
-   mCurObject = Sim::findObject(val);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurobject_internal(U32 &ip)
-{
-   ++ip; // To skip the recurse flag if the object wasn't found
-   if (mCurObject)
-   {
-      SimSet *set = dynamic_cast<SimSet *>(mCurObject);
-      if (set)
-      {
-         StringTableEntry intName = StringTable->insert(STR.getStringValue());
-         bool recurse = mCodeBlock->code[ip - 1];
-         SimObject *obj = set->findObjectByInternalName(intName, recurse);
-         intStack[_UINT + 1] = obj ? obj->getId() : 0;
-         _UINT++;
-      }
-      else
-      {
-         Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-set %s of class %s.", mCodeBlock->getFileLine(ip - 2), mCurObject->getName(), mCurObject->getClassName());
-         intStack[_UINT] = 0;
-      }
-   }
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurobject_new(U32 &ip)
-{
-   mCurObject = mCurrentNewObject;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurfield(U32 &ip)
-{
-   // Save the previous field for parsing vector fields.
-   mPrevField = mCurField;
-   dStrcpy(prevFieldArray, curFieldArray, 256);
-   mCurField = CodeToSTE(mCodeBlock->code, ip);
-   curFieldArray[0] = 0;
-   ip += 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurfield_array(U32 &ip)
-{
-   dStrcpy(curFieldArray, STR.getStringValue(), 256);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurfield_type(U32 &ip)
-{
-   if (mCurObject)
-      mCurObject->setDataFieldType(mCodeBlock->code[ip], mCurField, curFieldArray);
-   ip++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurfield_array_var(U32 &ip)
-{
-   StringTableEntry var = CodeToSTE(mCodeBlock->code, ip);
-   ip += 2;
-
-   // We set the current var name (create it as well in case if it doesn't exist,
-   // otherwise we will crash).
-   gEvalState.setCurVarNameCreate(var);
-
-   // Then load the var and copy the contents to the current field array
-   dStrncpy(curFieldArray, gEvalState.currentVariable->getStringValue(), sizeof(curFieldArray));
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_setcurfield_this(U32 &ip)
-{
-   // set the 'this pointer' as the current object.
-   mCurObject = mThisObject;
-
-   mPrevField = mCurField;
-   dStrcpy(prevFieldArray, curFieldArray, 256);
-   mCurField = CodeToSTE(mCodeBlock->code, ip);
-   curFieldArray[0] = 0;
-   ip += 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadfield_uint(U32 &ip)
-{
-   if (mCurObject)
-      intStack[_UINT + 1] = U32(dAtoi(mCurObject->getDataField(mCurField, curFieldArray)));
-   else
-   {
-      // The field is not being retrieved from an object. Maybe it's
-      // a special accessor?
-      char buff[FieldBufferSizeNumeric];
-      memset(buff, 0, sizeof(buff));
-      getFieldComponent(mPrevObject, mPrevField, prevFieldArray, mCurField, buff);
-      intStack[_UINT + 1] = dAtoi(buff);
-   }
-   _UINT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadfield_flt(U32 &ip)
-{
-   if (mCurObject)
-      floatStack[_FLT + 1] = dAtof(mCurObject->getDataField(mCurField, curFieldArray));
-   else
-   {
-      // The field is not being retrieved from an object. Maybe it's
-      // a special accessor?
-      char buff[FieldBufferSizeNumeric];
-      memset(buff, 0, sizeof(buff));
-      getFieldComponent(mPrevObject, mPrevField, prevFieldArray, mCurField, buff);
-      floatStack[_FLT + 1] = dAtof(buff);
-   }
-   _FLT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadfield_str(U32 &ip)
-{
-   if (mCurObject)
-   {
-      StringTableEntry val = mCurObject->getDataField(mCurField, curFieldArray);
-      STR.setStringValue(val);
-   }
-   else
-   {
-      // The field is not being retrieved from an object. Maybe it's
-      // a special accessor?
-      char buff[FieldBufferSizeString];
-      memset(buff, 0, sizeof(buff));
-      getFieldComponent(mPrevObject, mPrevField, prevFieldArray, mCurField, buff);
-      STR.setStringValue(buff);
-   }
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savefield_uint(U32 &ip)
-{
-   STR.setIntValue(intStack[_UINT]);
-   if (mCurObject)
-      mCurObject->setDataField(mCurField, curFieldArray, STR.getStringValue());
-   else
-   {
-      // The field is not being set on an object. Maybe it's
-      // a special accessor?
-      setFieldComponent(mPrevObject, mPrevField, prevFieldArray, mCurField);
-      mPrevObject = NULL;
-   }
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savefield_flt(U32 &ip)
-{
-   STR.setFloatValue(floatStack[_FLT]);
-   if (mCurObject)
-      mCurObject->setDataField(mCurField, curFieldArray, STR.getStringValue());
-   else
-   {
-      // The field is not being set on an object. Maybe it's
-      // a special accessor?
-      setFieldComponent(mPrevObject, mPrevField, prevFieldArray, mCurField);
-      mPrevObject = NULL;
-   }
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_savefield_str(U32 &ip)
-{
-   if (mCurObject)
-      mCurObject->setDataField(mCurField, curFieldArray, STR.getStringValue());
-   else
-   {
-      // The field is not being set on an object. Maybe it's
-      // a special accessor?
-      setFieldComponent(mPrevObject, mPrevField, prevFieldArray, mCurField);
-      mPrevObject = NULL;
-   }
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_str_to_uint(U32 &ip)
-{
-   intStack[_UINT + 1] = STR.getIntValue();
-   _UINT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_str_to_flt(U32 &ip)
-{
-   floatStack[_FLT + 1] = STR.getFloatValue();
-   _FLT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_str_to_none(U32 &ip)
-{
-   // This exists simply to deal with certain typecast situations.
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_flt_to_uint(U32 &ip)
-{
-   intStack[_UINT + 1] = (S64)floatStack[_FLT];
-   _FLT--;
-   _UINT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_flt_to_str(U32 &ip)
-{
-   STR.setFloatValue(floatStack[_FLT]);
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_flt_to_none(U32 &ip)
-{
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_uint_to_flt(U32 &ip)
-{
-   floatStack[_FLT + 1] = (F32)intStack[_UINT];
-   _UINT--;
-   _FLT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_uint_to_str(U32 &ip)
-{
-   STR.setIntValue(intStack[_UINT]);
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_uint_to_none(U32 &ip)
-{
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_copyvar_to_none(U32 &ip)
-{
-   gEvalState.copyVariable = NULL;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadimmed_uint(U32 &ip)
-{
-   intStack[_UINT + 1] = mCodeBlock->code[ip++];
-   _UINT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadimmed_flt(U32 &ip)
-{
-   floatStack[_FLT + 1] = mCurFloatTable[mCodeBlock->code[ip]];
-   ip++;
-   _FLT++;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_tag_to_str(U32 &ip)
-{
-   mCodeBlock->code[ip - 1] = OP_LOADIMMED_STR;
-   // it's possible the string has already been converted
-   if (U8(mCurStringTable[mCodeBlock->code[ip]]) != StringTagPrefixByte)
-   {
-      U32 id = GameAddTaggedString(mCurStringTable + mCodeBlock->code[ip]);
-      dSprintf(mCurStringTable + mCodeBlock->code[ip] + 1, 7, "%d", id);
-      *(mCurStringTable + mCodeBlock->code[ip]) = StringTagPrefixByte;
-   }
-
-   // Fallthrough
-   OPCodeReturn ret = op_loadimmed_str(ip);
-
-   return ret;
-}
-
-OPCodeReturn CodeInterpreter::op_loadimmed_str(U32 &ip)
-{
-   STR.setStringValue(mCurStringTable + mCodeBlock->code[ip++]);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_docblock_str(U32 &ip)
-{
-   // If the first word of the doc is '\class' or '@class', then this
-   // is a namespace doc block, otherwise it is a function doc block.
-   const char* docblock = mCurStringTable + mCodeBlock->code[ip++];
-
-   const char* sansClass = dStrstr(docblock, "@class");
-   if (!sansClass)
-      sansClass = dStrstr(docblock, "\\class");
-
-   if (sansClass)
-   {
-      // Don't save the class declaration. Scan past the 'class'
-      // keyword and up to the first whitespace.
-      sansClass += 7;
-      S32 index = 0;
-      while ((*sansClass != ' ') && (*sansClass != '\n') && *sansClass && (index < (nsDocLength - 1)))
-      {
-         mNSDocBlockClass[index++] = *sansClass;
-         sansClass++;
-      }
-      mNSDocBlockClass[index] = '\0';
-
-      mCurNSDocBlock = sansClass + 1;
-   }
-   else
-      mCurFNDocBlock = docblock;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_loadimmed_ident(U32 &ip)
-{
-   STR.setStringValue(CodeToSTE(mCodeBlock->code, ip));
-   ip += 2;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_callfunc_resolve(U32 &ip)
-{
-   // This deals with a function that is potentially living in a namespace.
-   StringTableEntry fnNamespace = CodeToSTE(mCodeBlock->code, ip + 2);
-   StringTableEntry fnName = CodeToSTE(mCodeBlock->code, ip);
-
-   // Try to look it up.
-   mNSEntry = Namespace::find(fnNamespace)->lookup(fnName);
-   if (!CInterface::GetCInterface().isMethod(fnNamespace, fnName) && !mNSEntry)
-   {
-      ip += 5;
-      Con::warnf(ConsoleLogEntry::General,
-         "%s: Unable to find function %s%s%s",
-         mCodeBlock->getFileLine(ip - 7), fnNamespace ? fnNamespace : "",
-         fnNamespace ? "::" : "", fnName);
-      STR.popFrame();
-      CSTK.popFrame();
-      return OPCodeReturn::success;
-   }
-
-   // Fallthrough to op_callfunc_resolve
-   OPCodeReturn ret = op_callfunc(ip);
-
-   return ret;
-}
-
-OPCodeReturn CodeInterpreter::op_callfunc(U32 &ip)
-{
-   // This routingId is set when we query the object as to whether
-   // it handles this method.  It is set to an enum from the table
-   // above indicating whether it handles it on a component it owns
-   // or just on the object.
-   S32 routingId = 0;
-
-   U32 *code = mCodeBlock->code;
-
-   StringTableEntry fnNamespace = CodeToSTE(mCodeBlock->code, ip + 2);
-   StringTableEntry fnName = CodeToSTE(code, ip);
-
-   //if this is called from inside a function, append the ip and codeptr
-   if (gEvalState.getStackDepth() > 0)
-   {
-      gEvalState.getCurrentFrame().code = mCodeBlock;
-      gEvalState.getCurrentFrame().ip = ip - 1;
-   }
-
-   U32 callType = code[ip + 4];
-
-   ip += 5;
-   CSTK.getArgcArgv(fnName, &mCallArgc, &mCallArgv);
-
-   const char *componentReturnValue = "";
-   Namespace *ns = NULL;
-
-   bool cFunctionRes = false;
-   const char* cRetRes = NULL;
-
-   if (callType == FuncCallExprNode::FunctionCall)
-   {
-      if (!mNSEntry)
-         mNSEntry = Namespace::global()->lookup(fnName);
-
-      StringStackWrapper args(mCallArgc, mCallArgv);
-      cRetRes = CInterface::CallFunction(fnNamespace, fnName, args.argv + 1, args.argc - 1, &cFunctionRes);
-   }
-   else if (callType == FuncCallExprNode::MethodCall)
-   {
-      mSaveObject = gEvalState.thisObject;
-      gEvalState.thisObject = Sim::findObject((const char*)mCallArgv[1]);
-      if (!gEvalState.thisObject)
-      {
-         // Go back to the previous saved object.
-         gEvalState.thisObject = mSaveObject;
-
-         Con::warnf(ConsoleLogEntry::General, "%s: Unable to find object: '%s' attempting to call function '%s'", mCodeBlock->getFileLine(ip - 4), (const char*)mCallArgv[1], fnName);
-         STR.popFrame();
-         CSTK.popFrame();
-         STR.setStringValue("");
-         return OPCodeReturn::success;
-      }
-
-      bool handlesMethod = gEvalState.thisObject->handlesConsoleMethod(fnName, &routingId);
-      if (handlesMethod && routingId == MethodOnComponent)
-      {
-         ICallMethod *pComponent = dynamic_cast<ICallMethod *>(gEvalState.thisObject);
-         if (pComponent)
-            componentReturnValue = pComponent->callMethodArgList(mCallArgc, mCallArgv, false);
-      }
-
-      ns = gEvalState.thisObject->getNamespace();
-      if (ns)
-         mNSEntry = ns->lookup(fnName);
-      else
-         mNSEntry = NULL;
-
-      StringStackWrapper args(mCallArgc, mCallArgv);
-      cRetRes = CInterface::CallMethod(gEvalState.thisObject, fnName, args.argv + 2, args.argc - 2, &cFunctionRes);
-   }
-   else // it's a ParentCall
-   {
-      if (mExec.thisNamespace)
-      {
-         ns = mExec.thisNamespace->mParent;
-         if (ns)
-            mNSEntry = ns->lookup(fnName);
-         else
-            mNSEntry = NULL;
-      }
-      else
-      {
-         ns = NULL;
-         mNSEntry = NULL;
-      }
-   }
-
-   Namespace::Entry::CallbackUnion * nsCb = NULL;
-   const char * nsUsage = NULL;
-   if (mNSEntry)
-   {
-      nsCb = &mNSEntry->cb;
-      nsUsage = mNSEntry->mUsage;
-      routingId = 0;
-   }
-   if (!cFunctionRes && (!mNSEntry || mExec.noCalls))
-   {
-      if (!mExec.noCalls && !(routingId == MethodOnComponent))
-      {
-         if (callType == FuncCallExprNode::MethodCall)
-         {
-            if (gEvalState.thisObject != NULL)
-            {
-               // Try to use the name instead of the id
-               StringTableEntry name = gEvalState.thisObject->getName() ? gEvalState.thisObject->getName() : gEvalState.thisObject->getIdString();
-               Con::warnf(ConsoleLogEntry::General, "%s: Unknown method %s.%s Namespace List: %s", mCodeBlock->getFileLine(ip - 6), name, fnName, Con::getNamespaceList(ns));
-            }
-            else
-            {
-               // NULL.
-               Con::warnf(ConsoleLogEntry::General, "%s: Unknown method NULL.%s", mCodeBlock->getFileLine(ip - 6), fnName);
-            }
-         }
-         else if (callType == FuncCallExprNode::ParentCall)
-         {
-            Con::warnf(ConsoleLogEntry::General, "%s: Unknown parent call %s.", mCodeBlock->getFileLine(ip - 6), fnName);
-         }
-         else 
-         {
-            Con::warnf(ConsoleLogEntry::General, "%s: Unknown function %s.", mCodeBlock->getFileLine(ip - 6), fnName);
-         }
-      }
-      STR.popFrame();
-      CSTK.popFrame();
-
-      if (routingId == MethodOnComponent)
-         STR.setStringValue(componentReturnValue);
-      else
-         STR.setStringValue("");
-      return OPCodeReturn::success;
-   }
-
-   // ConsoleFunctionType is for any function defined by script.
-   // Any 'callback' type is an engine function that is exposed to script.
-   if (cFunctionRes || mNSEntry->mType == Namespace::Entry::ConsoleFunctionType)
-   {
-      ConsoleValue retVal;
-      ConsoleValueRef ret;
-      if (cFunctionRes)
-      {
-         retVal.init();
-         ret.value = &retVal;
-         retVal.setStackStringValue(cRetRes);
-      }
-      else if (mNSEntry->mFunctionOffset)
-      {
-         ret = mNSEntry->mCode->exec(mNSEntry->mFunctionOffset, fnName, mNSEntry->mNamespace, mCallArgc, mCallArgv, false, mNSEntry->mPackage);
-      }
-
-      STR.popFrame();
-      // Functions are assumed to return strings, so look ahead to see if we can skip the conversion
-      if (code[ip] == OP_STR_TO_UINT)
-      {
-         ip++;
-         intStack[++_UINT] = (U32)((S32)ret);
-      }
-      else if (code[ip] == OP_STR_TO_FLT)
-      {
-         ip++;
-         floatStack[++_FLT] = (F32)ret;
-      }
-      else if (code[ip] == OP_STR_TO_NONE)
-      {
-         STR.setStringValue(ret.getStringValue());
-         ip++;
-      }
-      else
-         STR.setStringValue((const char*)ret);
-
-      // This will clear everything including returnValue
-      CSTK.popFrame();
-      //STR.clearFunctionOffset();
-   }
-   else
-   {
-      const char* nsName = ns ? ns->mName : "";
-#ifndef TORQUE_DEBUG
-      // [tom, 12/13/2006] This stops tools functions from working in the console,
-      // which is useful behavior when debugging so I'm ifdefing this out for debug builds.
-      if (mNSEntry->mToolOnly && !Con::isCurrentScriptToolScript())
-      {
-         Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", mCodeBlock->getFileLine(ip - 6), nsName, fnName);
-      }
-      else
-#endif
-      if ((mNSEntry->mMinArgs && S32(mCallArgc) < mNSEntry->mMinArgs) || (mNSEntry->mMaxArgs && S32(mCallArgc) > mNSEntry->mMaxArgs))
-      {
-         Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).",
-            mCodeBlock->getFileLine(ip - 6), nsName, fnName,
-            mCallArgc, mNSEntry->mMinArgs, mNSEntry->mMaxArgs);
-         Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", mCodeBlock->getFileLine(ip - 6), mNSEntry->mUsage);
-         STR.popFrame();
-         CSTK.popFrame();
-      }
-      else
-      {
-         switch (mNSEntry->mType)
-         {
-         case Namespace::Entry::StringCallbackType:
-         {
-            const char *ret = mNSEntry->cb.mStringCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-            STR.popFrame();
-            CSTK.popFrame();
-            if (ret != STR.getStringValue())
-               STR.setStringValue(ret);
-            //else
-            //   sSTR.setLen(dStrlen(ret));
-            break;
-         }
-         case Namespace::Entry::IntCallbackType:
-         {
-            S32 result = mNSEntry->cb.mIntCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-            STR.popFrame();
-            CSTK.popFrame();
-            if (code[ip] == OP_STR_TO_UINT)
-            {
-               ip++;
-               intStack[++_UINT] = result;
-               break;
-            }
-            else if (code[ip] == OP_STR_TO_FLT)
-            {
-               ip++;
-               floatStack[++_FLT] = result;
-               break;
-            }
-            else if (code[ip] == OP_STR_TO_NONE)
-               ip++;
-            else
-               STR.setIntValue(result);
-            break;
-         }
-         case Namespace::Entry::FloatCallbackType:
-         {
-            F64 result = mNSEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-            STR.popFrame();
-            CSTK.popFrame();
-            if (code[ip] == OP_STR_TO_UINT)
-            {
-               ip++;
-               intStack[++_UINT] = (S64)result;
-               break;
-            }
-            else if (code[ip] == OP_STR_TO_FLT)
-            {
-               ip++;
-               floatStack[++_FLT] = result;
-               break;
-            }
-            else if (code[ip] == OP_STR_TO_NONE)
-               ip++;
-            else
-               STR.setFloatValue(result);
-            break;
-         }
-         case Namespace::Entry::VoidCallbackType:
-            mNSEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-            if (code[ip] != OP_STR_TO_NONE && Con::getBoolVariable("$Con::warnVoidAssignment", true))
-               Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", mCodeBlock->getFileLine(ip - 6), fnName, mExec.functionName);
-
-            STR.popFrame();
-            CSTK.popFrame();
-            STR.setStringValue("");
-            break;
-         case Namespace::Entry::BoolCallbackType:
-         {
-            bool result = mNSEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-            STR.popFrame();
-            CSTK.popFrame();
-            if (code[ip] == OP_STR_TO_UINT)
-            {
-               ip++;
-               intStack[++_UINT] = result;
-               break;
-            }
-            else if (code[ip] == OP_STR_TO_FLT)
-            {
-               ip++;
-               floatStack[++_FLT] = result;
-               break;
-            }
-            else if (code[ip] == OP_STR_TO_NONE)
-               ip++;
-            else
-               STR.setIntValue(result);
-            break;
-         }
-         }
-      }
-   }
-
-   if (callType == FuncCallExprNode::MethodCall)
-      gEvalState.thisObject = mSaveObject;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_callfunc_pointer(U32 &ip)
-{
-   // get function name. This is the 'function pointer'.
-   StringTableEntry fnName = StringTable->insert(STR.getStringValue());
-
-   U32 *code = mCodeBlock->code;
-
-   mNSEntry = Namespace::global()->lookup(fnName);
-
-   //if this is called from inside a function, append the ip and codeptr
-   if (gEvalState.getStackDepth() > 0)
-   {
-      gEvalState.getCurrentFrame().code = mCodeBlock;
-      gEvalState.getCurrentFrame().ip = ip - 1;
-   }
-
-   CSTK.getArgcArgv(fnName, &mCallArgc, &mCallArgv);
-
-
-   if (!mNSEntry || mExec.noCalls)
-   {
-      if (!mExec.noCalls)
-      {
-         Con::warnf(ConsoleLogEntry::General, "%s: Unknown function %s.", mCodeBlock->getFileLine(ip - 6), fnName);
-      }
-      STR.popFrame();
-      CSTK.popFrame();
-
-      STR.setStringValue("");
-      return OPCodeReturn::success;
-   }
-
-   // ConsoleFunctionType is for any function defined by script.
-   // Any 'callback' type is an engine function that is exposed to script.
-   if (mNSEntry->mType == Namespace::Entry::ConsoleFunctionType)
-   {
-      ConsoleValueRef ret;
-      if (mNSEntry->mFunctionOffset)
-         ret = mNSEntry->mCode->exec(mNSEntry->mFunctionOffset, fnName, mNSEntry->mNamespace, mCallArgc, mCallArgv, false, mNSEntry->mPackage);
-
-      STR.popFrame();
-      // Functions are assumed to return strings, so look ahead to see if we can skip the conversion
-      if (code[ip] == OP_STR_TO_UINT)
-      {
-         ip++;
-         intStack[++_UINT] = (U32)((S32)ret);
-      }
-      else if (code[ip] == OP_STR_TO_FLT)
-      {
-         ip++;
-         floatStack[++_FLT] = (F32)ret;
-      }
-      else if (code[ip] == OP_STR_TO_NONE)
-      {
-         STR.setStringValue(ret.getStringValue());
-         ip++;
-      }
-      else
-         STR.setStringValue((const char*)ret);
-
-      // This will clear everything including returnValue
-      CSTK.popFrame();
-      //STR.clearFunctionOffset();
-   }
-   else
-   {
-      const char* nsName = "";
-
-#ifndef TORQUE_DEBUG
-      // [tom, 12/13/2006] This stops tools functions from working in the console,
-      // which is useful behavior when debugging so I'm ifdefing this out for debug builds.
-      if (mNSEntry->mToolOnly && !Con::isCurrentScriptToolScript())
-      {
-         Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", mCodeBlock->getFileLine(ip - 6), nsName, fnName);
-      }
-      else
-#endif
-         if ((mNSEntry->mMinArgs && S32(mCallArgc) < mNSEntry->mMinArgs) || (mNSEntry->mMaxArgs && S32(mCallArgc) > mNSEntry->mMaxArgs))
-         {
-            Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).",
-               mCodeBlock->getFileLine(ip - 6), nsName, fnName,
-               mCallArgc, mNSEntry->mMinArgs, mNSEntry->mMaxArgs);
-            Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", mCodeBlock->getFileLine(ip - 6), mNSEntry->mUsage);
-            STR.popFrame();
-            CSTK.popFrame();
-         }
-         else
-         {
-            switch (mNSEntry->mType)
-            {
-            case Namespace::Entry::StringCallbackType:
-            {
-               const char *ret = mNSEntry->cb.mStringCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (ret != STR.getStringValue())
-                  STR.setStringValue(ret);
-               //else
-               //   sSTR.setLen(dStrlen(ret));
-               break;
-            }
-            case Namespace::Entry::IntCallbackType:
-            {
-               S32 result = mNSEntry->cb.mIntCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (code[ip] == OP_STR_TO_UINT)
-               {
-                  ip++;
-                  intStack[++_UINT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_FLT)
-               {
-                  ip++;
-                  floatStack[++_FLT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_NONE)
-                  ip++;
-               else
-                  STR.setIntValue(result);
-               break;
-            }
-            case Namespace::Entry::FloatCallbackType:
-            {
-               F64 result = mNSEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (code[ip] == OP_STR_TO_UINT)
-               {
-                  ip++;
-                  intStack[++_UINT] = (S64)result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_FLT)
-               {
-                  ip++;
-                  floatStack[++_FLT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_NONE)
-                  ip++;
-               else
-                  STR.setFloatValue(result);
-               break;
-            }
-            case Namespace::Entry::VoidCallbackType:
-               mNSEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-               if (code[ip] != OP_STR_TO_NONE && Con::getBoolVariable("$Con::warnVoidAssignment", true))
-                  Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", mCodeBlock->getFileLine(ip - 6), fnName, mExec.functionName);
-
-               STR.popFrame();
-               CSTK.popFrame();
-               STR.setStringValue("");
-               break;
-            case Namespace::Entry::BoolCallbackType:
-            {
-               bool result = mNSEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (code[ip] == OP_STR_TO_UINT)
-               {
-                  ip++;
-                  intStack[++_UINT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_FLT)
-               {
-                  ip++;
-                  floatStack[++_FLT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_NONE)
-                  ip++;
-               else
-                  STR.setIntValue(result);
-               break;
-            }
-            }
-         }
-   }
-
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_callfunc_this(U32 &ip)
-{
-   U32 *code = mCodeBlock->code;
-
-   StringTableEntry fnName = CodeToSTE(code, ip);
-
-   //if this is called from inside a function, append the ip and codeptr
-   if (gEvalState.getStackDepth() > 0)
-   {
-      gEvalState.getCurrentFrame().code = mCodeBlock;
-      gEvalState.getCurrentFrame().ip = ip - 1;
-   }
-
-   ip += 2;
-   CSTK.getArgcArgv(fnName, &mCallArgc, &mCallArgv);
-
-   Namespace *ns = mThisObject ? mThisObject->getNamespace() : NULL;
-   if (ns)
-      mNSEntry = ns->lookup(fnName);
-   else
-      mNSEntry = NULL;
-
-   if (!mNSEntry || mExec.noCalls)
-   {
-      if (!mExec.noCalls)
-      {
-         if (mThisObject)
-         {
-            // Try to use the name instead of the id
-            StringTableEntry name = mThisObject->getName() ? mThisObject->getName() : mThisObject->getIdString();
-            Con::warnf(ConsoleLogEntry::General, "%s: Unknown method %s.%s Namespace List: %s", mCodeBlock->getFileLine(ip - 6), name, fnName, Con::getNamespaceList(ns));
-         }
-         else
-         {
-            // At least let the scripter know that they access the object.
-            Con::warnf(ConsoleLogEntry::General, "%s: Unknown method NULL.%s", mCodeBlock->getFileLine(ip - 6), fnName);
-         }
-      }
-      STR.popFrame();
-      CSTK.popFrame();
-
-      STR.setStringValue("");
-      return OPCodeReturn::success;
-   }
-
-   // ConsoleFunctionType is for any function defined by script.
-   // Any 'callback' type is an engine function that is exposed to script.
-   if (mNSEntry->mType == Namespace::Entry::ConsoleFunctionType)
-   {
-      ConsoleValueRef ret;
-      if (mNSEntry->mFunctionOffset)
-         ret = mNSEntry->mCode->exec(mNSEntry->mFunctionOffset, fnName, mNSEntry->mNamespace, mCallArgc, mCallArgv, false, mNSEntry->mPackage);
-
-      STR.popFrame();
-      // Functions are assumed to return strings, so look ahead to see if we can skip the conversion
-      if (code[ip] == OP_STR_TO_UINT)
-      {
-         ip++;
-         intStack[++_UINT] = (U32)((S32)ret);
-      }
-      else if (code[ip] == OP_STR_TO_FLT)
-      {
-         ip++;
-         floatStack[++_FLT] = (F32)ret;
-      }
-      else if (code[ip] == OP_STR_TO_NONE)
-      {
-         STR.setStringValue(ret.getStringValue());
-         ip++;
-      }
-      else
-         STR.setStringValue((const char*)ret);
-
-      // This will clear everything including returnValue
-      CSTK.popFrame();
-      //STR.clearFunctionOffset();
-   }
-   else
-   {
-      const char* nsName = ns ? ns->mName : "";
-#ifndef TORQUE_DEBUG
-      // [tom, 12/13/2006] This stops tools functions from working in the console,
-      // which is useful behavior when debugging so I'm ifdefing this out for debug builds.
-      if (mNSEntry->mToolOnly && !Con::isCurrentScriptToolScript())
-      {
-         Con::errorf(ConsoleLogEntry::Script, "%s: %s::%s - attempting to call tools only function from outside of tools.", mCodeBlock->getFileLine(ip - 6), nsName, fnName);
-      }
-      else
-#endif
-         if ((mNSEntry->mMinArgs && S32(mCallArgc) < mNSEntry->mMinArgs) || (mNSEntry->mMaxArgs && S32(mCallArgc) > mNSEntry->mMaxArgs))
-         {
-            Con::warnf(ConsoleLogEntry::Script, "%s: %s::%s - wrong number of arguments (got %i, expected min %i and max %i).",
-               mCodeBlock->getFileLine(ip - 6), nsName, fnName,
-               mCallArgc, mNSEntry->mMinArgs, mNSEntry->mMaxArgs);
-            Con::warnf(ConsoleLogEntry::Script, "%s: usage: %s", mCodeBlock->getFileLine(ip - 6), mNSEntry->mUsage);
-            STR.popFrame();
-            CSTK.popFrame();
-         }
-         else
-         {
-            switch (mNSEntry->mType)
-            {
-            case Namespace::Entry::StringCallbackType:
-            {
-               const char *ret = mNSEntry->cb.mStringCallbackFunc(mThisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (ret != STR.getStringValue())
-                  STR.setStringValue(ret);
-               //else
-               //   sSTR.setLen(dStrlen(ret));
-               break;
-            }
-            case Namespace::Entry::IntCallbackType:
-            {
-               S32 result = mNSEntry->cb.mIntCallbackFunc(mThisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (code[ip] == OP_STR_TO_UINT)
-               {
-                  ip++;
-                  intStack[++_UINT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_FLT)
-               {
-                  ip++;
-                  floatStack[++_FLT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_NONE)
-                  ip++;
-               else
-                  STR.setIntValue(result);
-               break;
-            }
-            case Namespace::Entry::FloatCallbackType:
-            {
-               F64 result = mNSEntry->cb.mFloatCallbackFunc(mThisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (code[ip] == OP_STR_TO_UINT)
-               {
-                  ip++;
-                  intStack[++_UINT] = (S64)result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_FLT)
-               {
-                  ip++;
-                  floatStack[++_FLT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_NONE)
-                  ip++;
-               else
-                  STR.setFloatValue(result);
-               break;
-            }
-            case Namespace::Entry::VoidCallbackType:
-               mNSEntry->cb.mVoidCallbackFunc(mThisObject, mCallArgc, mCallArgv);
-               if (code[ip] != OP_STR_TO_NONE && Con::getBoolVariable("$Con::warnVoidAssignment", true))
-                  Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", mCodeBlock->getFileLine(ip - 6), fnName, mExec.functionName);
-
-               STR.popFrame();
-               CSTK.popFrame();
-               STR.setStringValue("");
-               break;
-            case Namespace::Entry::BoolCallbackType:
-            {
-               bool result = mNSEntry->cb.mBoolCallbackFunc(mThisObject, mCallArgc, mCallArgv);
-               STR.popFrame();
-               CSTK.popFrame();
-               if (code[ip] == OP_STR_TO_UINT)
-               {
-                  ip++;
-                  intStack[++_UINT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_FLT)
-               {
-                  ip++;
-                  floatStack[++_FLT] = result;
-                  break;
-               }
-               else if (code[ip] == OP_STR_TO_NONE)
-                  ip++;
-               else
-                  STR.setIntValue(result);
-               break;
-            }
-            }
-         }
-   }
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_advance_str(U32 &ip)
-{
-   STR.advance();
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_advance_str_appendchar(U32 &ip)
-{
-   STR.advanceChar(mCodeBlock->code[ip++]);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_advance_str_comma(U32 &ip)
-{
-   STR.advanceChar('_');
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_advance_str_nul(U32 &ip)
-{
-   STR.advanceChar(0);
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_rewind_str(U32 &ip)
-{
-   STR.rewind();
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_terminate_rewind_str(U32 &ip)
-{
-   STR.rewindTerminate();
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_compare_str(U32 &ip)
-{
-   intStack[++_UINT] = STR.compare();
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_push(U32 &ip)
-{
-   STR.push();
-   CSTK.pushStringStackPtr(STR.getPreviousStringValuePtr());
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_push_uint(U32 &ip)
-{
-   CSTK.pushUINT(intStack[_UINT]);
-   _UINT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_push_flt(U32 &ip)
-{
-   CSTK.pushFLT(floatStack[_FLT]);
-   _FLT--;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_push_var(U32 &ip)
-{
-   if (gEvalState.currentVariable)
-      CSTK.pushValue(gEvalState.currentVariable->value);
-   else
-      CSTK.pushString("");
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_push_this(U32 &ip)
-{
-   StringTableEntry varName = CodeToSTE(mCodeBlock->code, ip);
-   ip += 2;
-
-   // shorthand OP_SETCURVAR
-
-   // If a variable is set, then these must be NULL. It is necessary
-   // to set this here so that the vector parser can appropriately
-   // identify whether it's dealing with a vector.
-   mPrevField = NULL;
-   mPrevObject = NULL;
-   mCurObject = NULL;
-
-   gEvalState.setCurVarName(varName);
-
-   // In order to let docblocks work properly with variables, we have
-   // clear the current docblock when we do an assign. This way it 
-   // won't inappropriately carry forward to following function decls.
-   mCurFNDocBlock = NULL;
-   mCurNSDocBlock = NULL;
-
-   // shorthand OP_LOADVAR_STR (since objs can be by name we can't assume uint)
-   STR.setStringValue(gEvalState.getStringVariable());
-
-   // shorthand OP_PUSH
-   STR.push();
-   CSTK.pushStringStackPtr(STR.getPreviousStringValuePtr());
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_push_frame(U32 &ip)
-{
-   STR.pushFrame();
-   CSTK.pushFrame();
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_assert(U32 &ip)
-{
-   if (!intStack[_UINT--])
-   {
-      const char *message = mCurStringTable + mCodeBlock->code[ip];
-
-      U32 breakLine, inst;
-      mCodeBlock->findBreakLine(ip - 1, breakLine, inst);
-
-      if (PlatformAssert::processAssert(PlatformAssert::Fatal,
-         mCodeBlock->name ? mCodeBlock->name : "eval",
-         breakLine,
-         message))
-      {
-         if (TelDebugger && TelDebugger->isConnected() && breakLine > 0)
-         {
-            TelDebugger->breakProcess();
-         }
-         else
-            Platform::debugBreak();
-      }
-   }
-
-   ip++;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_break(U32 &ip)
-{
-   //append the ip and codeptr before managing the breakpoint!
-   AssertFatal(gEvalState.getStackDepth() > 0, "Empty eval stack on break!");
-   gEvalState.getCurrentFrame().code = mCodeBlock;
-   gEvalState.getCurrentFrame().ip = ip - 1;
-
-   U32 breakLine;
-   mCodeBlock->findBreakLine(ip - 1, breakLine, mCurrentInstruction);
-   if (!breakLine)
-      return OPCodeReturn::breakContinue;
-   TelDebugger->executionStopped(mCodeBlock, breakLine);
-   return OPCodeReturn::breakContinue;
-}
-
-OPCodeReturn CodeInterpreter::op_iter_begin_str(U32 &ip)
-{
-   iterStack[_ITER].mIsStringIter = true;
-
-   // Emulate fallthrough:
-   OPCodeReturn fallthrough = op_iter_begin(ip);
-
-   return fallthrough;
-}
-
-OPCodeReturn CodeInterpreter::op_iter_begin(U32 &ip)
-{
-   StringTableEntry varName = CodeToSTE(mCodeBlock->code, ip);
-   U32 failIp = mCodeBlock->code[ip + 2];
-
-   IterStackRecord& iter = iterStack[_ITER];
-
-   if (varName[0] == '$')
-      iter.mVariable = gEvalState.globalVars.add(varName);
-   else
-      iter.mVariable = gEvalState.getCurrentFrame().add(varName);
-
-   if (iter.mIsStringIter)
-   {
-      iter.mData.mStr.mString = STR.getStringValuePtr();
-      iter.mData.mStr.mIndex = 0;
-   }
-   else
-   {
-      // Look up the object.
-
-      SimSet* set;
-      if (!Sim::findObject(STR.getStringValue(), set))
-      {
-         Con::errorf(ConsoleLogEntry::General, "No SimSet object '%s'", STR.getStringValue());
-         Con::errorf(ConsoleLogEntry::General, "Did you mean to use 'foreach$' instead of 'foreach'?");
-         ip = failIp;
-         return OPCodeReturn::success;
-      }
-
-      // Set up.
-
-      iter.mData.mObj.mSet = set;
-      iter.mData.mObj.mIndex = 0;
-   }
-
-   _ITER++;
-   mIterDepth++;
-
-   STR.push();
-
-   ip += 3;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_iter(U32 &ip)
-{
-   U32 breakIp = mCodeBlock->code[ip];
-   IterStackRecord& iter = iterStack[_ITER - 1];
-
-   if (iter.mIsStringIter)
-   {
-      const char* str = StringStackPtrRef(iter.mData.mStr.mString).getPtr(&STR);
-
-      U32 startIndex = iter.mData.mStr.mIndex;
-      U32 endIndex = startIndex;
-
-      // Break if at end.
-
-      if (!str[startIndex])
-      {
-         ip = breakIp;
-         return OPCodeReturn::success; // continue in old interpreter
-      }
-
-      // Find right end of current component.
-
-      if (!dIsspace(str[endIndex]))
-         do ++endIndex;
-      while (str[endIndex] && !dIsspace(str[endIndex]));
-
-      // Extract component.
-
-      if (endIndex != startIndex)
-      {
-         char savedChar = str[endIndex];
-         const_cast< char* >(str)[endIndex] = '\0'; // We are on the string stack so this is okay.
-         iter.mVariable->setStringValue(&str[startIndex]);
-         const_cast< char* >(str)[endIndex] = savedChar;
-      }
-      else
-         iter.mVariable->setStringValue("");
-
-      // Skip separator.
-      if (str[endIndex] != '\0')
-         ++endIndex;
-
-      iter.mData.mStr.mIndex = endIndex;
-   }
-   else
-   {
-      U32 index = iter.mData.mObj.mIndex;
-      SimSet* set = iter.mData.mObj.mSet;
-
-      if (index >= set->size())
-      {
-         ip = breakIp;
-         return OPCodeReturn::success; // continue in old interpreter
-      }
-
-      iter.mVariable->setIntValue(set->at(index)->getId());
-      iter.mData.mObj.mIndex = index + 1;
-   }
-
-   ++ip;
-
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_iter_end(U32 &ip)
-{
-   --_ITER;
-   --mIterDepth;
-   STR.rewind();
-   iterStack[_ITER].mIsStringIter = false;
-   return OPCodeReturn::success;
-}
-
-OPCodeReturn CodeInterpreter::op_invalid(U32 &ip)
-{
-   // Invalid does nothing.
-   return OPCodeReturn::exitCode;
-}

+ 0 - 262
Engine/source/console/codeInterpreter.h

@@ -1,262 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _CODEINTERPRETER_H_
-#define _CODEINTERPRETER_H_
-
-#include "console/codeBlock.h"
-#include "console/console.h"
-#include "console/consoleInternal.h"
-
-/// Frame data for a foreach/foreach$ loop.
-struct IterStackRecord
-{
-   /// If true, this is a foreach$ loop; if not, it's a foreach loop.
-   bool mIsStringIter;
-
-   /// The iterator variable.
-   Dictionary::Entry* mVariable;
-
-   /// Information for an object iterator loop.
-   struct ObjectPos
-   {
-      /// The set being iterated over.
-      SimSet* mSet;
-
-      /// Current index in the set.
-      U32 mIndex;
-   };
-
-   /// Information for a string iterator loop.
-   struct StringPos
-   {
-      /// The raw string data on the string stack.
-      StringStackPtr mString;
-
-      /// Current parsing position.
-      U32 mIndex;
-   };
-
-   union
-   {
-      ObjectPos mObj;
-      StringPos mStr;
-   } mData;
-};
-
-enum OPCodeReturn
-{
-   exitCode = -1,
-   success = 0,
-   breakContinue = 1
-};
-
-class CodeInterpreter
-{
-public:
-   CodeInterpreter(CodeBlock *cb);
-   ~CodeInterpreter();
-
-   ConsoleValueRef exec(U32 ip, 
-                        StringTableEntry functionName,
-                        Namespace *thisNamespace,
-                        U32 argc, 
-                        ConsoleValueRef *argv, 
-                        bool noCalls, 
-                        StringTableEntry packageName, 
-                        S32 setFrame);
-
-   static void init();
-
-   // Methods
-private:
-   void parseArgs(U32 &ip);
-
-   /// Group op codes
-   /// @{
-
-   OPCodeReturn op_func_decl(U32 &ip);
-   OPCodeReturn op_create_object(U32 &ip);
-   OPCodeReturn op_add_object(U32 &ip);
-   OPCodeReturn op_end_object(U32 &ip);
-   OPCodeReturn op_finish_object(U32 &ip);
-   OPCodeReturn op_jmpiffnot(U32 &ip);
-   OPCodeReturn op_jmpifnot(U32 &ip);
-   OPCodeReturn op_jmpiff(U32 &ip);
-   OPCodeReturn op_jmpif(U32 &ip);
-   OPCodeReturn op_jmpifnot_np(U32 &ip);
-   OPCodeReturn op_jmpif_np(U32 &ip);
-   OPCodeReturn op_jmp(U32 &ip);
-   OPCodeReturn op_return_void(U32 &ip);
-   OPCodeReturn op_return(U32 &ip);
-   OPCodeReturn op_return_flt(U32 &ip);
-   OPCodeReturn op_return_uint(U32 &ip);
-   OPCodeReturn op_cmpeq(U32 &ip);
-   OPCodeReturn op_cmpgr(U32 &ip);
-   OPCodeReturn op_cmpge(U32 &ip);
-   OPCodeReturn op_cmplt(U32 &ip);
-   OPCodeReturn op_cmple(U32 &ip);
-   OPCodeReturn op_cmpne(U32 &ip);
-   OPCodeReturn op_xor(U32 &ip);
-   OPCodeReturn op_mod(U32 &ip);
-   OPCodeReturn op_bitand(U32 &ip);
-   OPCodeReturn op_bitor(U32 &ip);
-   OPCodeReturn op_not(U32 &ip);
-   OPCodeReturn op_notf(U32 &ip);
-   OPCodeReturn op_onescomplement(U32 &ip);
-   OPCodeReturn op_shr(U32 &ip);
-   OPCodeReturn op_shl(U32 &ip);
-   OPCodeReturn op_and(U32 &ip);
-   OPCodeReturn op_or(U32 &ip);
-   OPCodeReturn op_add(U32 &ip);
-   OPCodeReturn op_sub(U32 &ip);
-   OPCodeReturn op_mul(U32 &ip);
-   OPCodeReturn op_div(U32 &ip);
-   OPCodeReturn op_neg(U32 &ip);
-   OPCodeReturn op_inc(U32 &ip);
-   OPCodeReturn op_dec(U32 &ip);
-   OPCodeReturn op_setcurvar(U32 &ip);
-   OPCodeReturn op_setcurvar_create(U32 &ip);
-   OPCodeReturn op_setcurvar_array(U32 &ip);
-   OPCodeReturn op_setcurvar_array_varlookup(U32 &ip);
-   OPCodeReturn op_setcurvar_array_create(U32 &ip);
-   OPCodeReturn op_setcurvar_array_create_varlookup(U32 &ip);
-   OPCodeReturn op_loadvar_uint(U32 &ip);
-   OPCodeReturn op_loadvar_flt(U32 &ip);
-   OPCodeReturn op_loadvar_str(U32 &ip);
-   OPCodeReturn op_loadvar_var(U32 &ip);
-   OPCodeReturn op_savevar_uint(U32 &ip);
-   OPCodeReturn op_savevar_flt(U32 &ip);
-   OPCodeReturn op_savevar_str(U32 &ip);
-   OPCodeReturn op_savevar_var(U32 &ip);
-   OPCodeReturn op_setcurobject(U32 &ip);
-   OPCodeReturn op_setcurobject_internal(U32 &ip);
-   OPCodeReturn op_setcurobject_new(U32 &ip);
-   OPCodeReturn op_setcurfield(U32 &ip);
-   OPCodeReturn op_setcurfield_array(U32 &ip);
-   OPCodeReturn op_setcurfield_type(U32 &ip);
-   OPCodeReturn op_setcurfield_this(U32 &ip);
-   OPCodeReturn op_setcurfield_array_var(U32 &ip);
-   OPCodeReturn op_loadfield_uint(U32 &ip);
-   OPCodeReturn op_loadfield_flt(U32 &ip);
-   OPCodeReturn op_loadfield_str(U32 &ip);
-   OPCodeReturn op_savefield_uint(U32 &ip);
-   OPCodeReturn op_savefield_flt(U32 &ip);
-   OPCodeReturn op_savefield_str(U32 &ip);
-   OPCodeReturn op_str_to_uint(U32 &ip);
-   OPCodeReturn op_str_to_flt(U32 &ip);
-   OPCodeReturn op_str_to_none(U32 &ip);
-   OPCodeReturn op_flt_to_uint(U32 &ip);
-   OPCodeReturn op_flt_to_str(U32 &ip);
-   OPCodeReturn op_flt_to_none(U32 &ip);
-   OPCodeReturn op_uint_to_flt(U32 &ip);
-   OPCodeReturn op_uint_to_str(U32 &ip);
-   OPCodeReturn op_uint_to_none(U32 &ip);
-   OPCodeReturn op_copyvar_to_none(U32 &ip);
-   OPCodeReturn op_loadimmed_uint(U32 &ip);
-   OPCodeReturn op_loadimmed_flt(U32 &ip);
-   OPCodeReturn op_tag_to_str(U32 &ip);
-   OPCodeReturn op_loadimmed_str(U32 &ip);
-   OPCodeReturn op_docblock_str(U32 &ip);
-   OPCodeReturn op_loadimmed_ident(U32 &ip);
-   OPCodeReturn op_callfunc_resolve(U32 &ip);
-   OPCodeReturn op_callfunc(U32 &ip);
-   OPCodeReturn op_callfunc_pointer(U32 &ip);
-   OPCodeReturn op_callfunc_this(U32 &ip);
-   OPCodeReturn op_advance_str(U32 &ip);
-   OPCodeReturn op_advance_str_appendchar(U32 &ip);
-   OPCodeReturn op_advance_str_comma(U32 &ip);
-   OPCodeReturn op_advance_str_nul(U32 &ip);
-   OPCodeReturn op_rewind_str(U32 &ip);
-   OPCodeReturn op_terminate_rewind_str(U32 &ip);
-   OPCodeReturn op_compare_str(U32 &ip);
-   OPCodeReturn op_push(U32 &ip);
-   OPCodeReturn op_push_uint(U32 &ip);
-   OPCodeReturn op_push_flt(U32 &ip);
-   OPCodeReturn op_push_var(U32 &ip);
-   OPCodeReturn op_push_this(U32 &ip);
-   OPCodeReturn op_push_frame(U32 &ip);
-   OPCodeReturn op_assert(U32 &ip);
-   OPCodeReturn op_break(U32 &ip);
-   OPCodeReturn op_iter_begin_str(U32 &ip);
-   OPCodeReturn op_iter_begin(U32 &ip);
-   OPCodeReturn op_iter(U32 &ip);
-   OPCodeReturn op_iter_end(U32 &ip);
-   OPCodeReturn op_invalid(U32 &ip);
-
-   /// @}
-
-private:
-   CodeBlock *mCodeBlock;
-
-   /// Group exec arguments.
-   struct
-   {
-      StringTableEntry functionName;
-      Namespace *thisNamespace;
-      U32 argc;
-      ConsoleValueRef *argv;
-      bool noCalls;
-      StringTableEntry packageName;
-      S32 setFrame;
-   } mExec;
-
-   U32 mIterDepth;
-   F64 *mCurFloatTable;
-   char *mCurStringTable;
-   StringTableEntry mThisFunctionName;
-   bool mPopFrame;
-
-   // Add local object creation stack [7/9/2007 Black]
-   static const U32 objectCreationStackSize = 32;
-   U32 mObjectCreationStackIndex;
-   struct 
-   {
-      SimObject *newObject;
-      U32 failJump;
-   } mObjectCreationStack[objectCreationStackSize];
-
-   SimObject *mCurrentNewObject;
-   U32 mFailJump;
-   StringTableEntry mPrevField;
-   StringTableEntry mCurField;
-   SimObject *mPrevObject;
-   SimObject *mCurObject;
-   SimObject *mSaveObject;
-   SimObject *mThisObject;
-   Namespace::Entry *mNSEntry;
-   StringTableEntry mCurFNDocBlock;
-   StringTableEntry mCurNSDocBlock;
-   U32 mCallArgc;
-   ConsoleValueRef *mCallArgv;
-   CodeBlock *mSaveCodeBlock;
-
-   // note: anything returned is pushed to CSTK and will be invalidated on the next exec()
-   ConsoleValueRef mReturnValue;
-
-   U32 mCurrentInstruction;
-
-   static const S32 nsDocLength = 128;
-   char mNSDocBlockClass[nsDocLength];
-};
-
-#endif

+ 1879 - 22
Engine/source/console/compiledEval.cpp

@@ -1,5 +1,7 @@
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
+// Copyright (c) 2013 GarageGames, LLC
+// Copyright (c) 2015 Faust Logic, Inc.
+// Copyright (c) 2021 TGEMIT Authors & Contributors
 //
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to
 // of this software and associated documentation files (the "Software"), to
@@ -40,8 +42,8 @@
 #include "util/messaging/message.h"
 #include "util/messaging/message.h"
 #include "core/frameAllocator.h"
 #include "core/frameAllocator.h"
 
 
-#include "console/codeInterpreter.h"
 #include "console/returnBuffer.h"
 #include "console/returnBuffer.h"
+#include "console/consoleValueStack.h"
 
 
 #ifndef TORQUE_TGB_ONLY
 #ifndef TORQUE_TGB_ONLY
 #include "materials/materialDefinition.h"
 #include "materials/materialDefinition.h"
@@ -50,13 +52,71 @@
 
 
 using namespace Compiler;
 using namespace Compiler;
 
 
+enum EvalConstants
+{
+   MaxStackSize = 1024,
+   FieldBufferSizeString = 2048,
+   FieldBufferSizeNumeric = 128,
+   MethodOnComponent = -2
+};
+
+/// Frame data for a foreach/foreach$ loop.
+struct IterStackRecord
+{
+   /// If true, this is a foreach$ loop; if not, it's a foreach loop.
+   bool mIsStringIter;
+
+   /// The iterator variable.
+   Dictionary::Entry* mVariable;
+
+   /// Information for an object iterator loop.
+   struct ObjectPos
+   {
+      /// The set being iterated over.
+      SimSet* mSet;
+
+      /// Current index in the set.
+      U32 mIndex;
+   };
+
+   /// Information for a string iterator loop.
+   struct StringPos
+   {
+      /// The raw string data on the string stack.
+      const char* mString;
+
+      /// Current parsing position.
+      U32 mIndex;
+   };
+   union
+   {
+      ObjectPos mObj;
+      StringPos mStr;
+   } mData;
+};
+
+ConsoleValueStack<4096> gCallStack;
+
+StringStack STR;
+
+U32 _FLT = 0;     ///< Stack pointer for floatStack.
+U32 _UINT = 0;    ///< Stack pointer for intStack.
+U32 _ITER = 0;    ///< Stack pointer for iterStack.
+
+IterStackRecord iterStack[MaxStackSize];
+
+F64 floatStack[MaxStackSize];
+S64 intStack[MaxStackSize];
+
+char curFieldArray[256];
+char prevFieldArray[256];
+
 namespace Con
 namespace Con
 {
 {
    // Current script file name and root, these are registered as
    // Current script file name and root, these are registered as
    // console variables.
    // console variables.
    extern StringTableEntry gCurrentFile;
    extern StringTableEntry gCurrentFile;
    extern StringTableEntry gCurrentRoot;
    extern StringTableEntry gCurrentRoot;
-   extern S32 gObjectCopyFailures;
 }
 }
 
 
 namespace Con
 namespace Con
@@ -79,6 +139,124 @@ namespace Con
    }
    }
 }
 }
 
 
+// Gets a component of an object's field value or a variable and returns it
+// in val.
+static void getFieldComponent(SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField, char val[])
+{
+   const char* prevVal = NULL;
+
+   // Grab value from object.
+   if (object && field)
+      prevVal = object->getDataField(field, array);
+
+   // 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();
+
+   // Make sure we got a value.
+   if (prevVal && *prevVal)
+   {
+      static const StringTableEntry xyzw[] =
+      {
+         StringTable->insert("x"),
+         StringTable->insert("y"),
+         StringTable->insert("z"),
+         StringTable->insert("w")
+      };
+
+      static const StringTableEntry rgba[] =
+      {
+         StringTable->insert("r"),
+         StringTable->insert("g"),
+         StringTable->insert("b"),
+         StringTable->insert("a")
+      };
+
+      // Translate xyzw and rgba into the indexed component 
+      // of the variable or field.
+      if (subField == xyzw[0] || subField == rgba[0])
+         dStrcpy(val, StringUnit::getUnit(prevVal, 0, " \t\n"), 128);
+
+      else if (subField == xyzw[1] || subField == rgba[1])
+         dStrcpy(val, StringUnit::getUnit(prevVal, 1, " \t\n"), 128);
+
+      else if (subField == xyzw[2] || subField == rgba[2])
+         dStrcpy(val, StringUnit::getUnit(prevVal, 2, " \t\n"), 128);
+
+      else if (subField == xyzw[3] || subField == rgba[3])
+         dStrcpy(val, StringUnit::getUnit(prevVal, 3, " \t\n"), 128);
+
+      else
+         val[0] = 0;
+   }
+   else
+      val[0] = 0;
+}
+
+// Sets a component of an object's field value based on the sub field. 'x' will
+// set the first field, 'y' the second, and 'z' the third.
+static void setFieldComponent(SimObject* object, StringTableEntry field, const char* array, StringTableEntry subField)
+{
+   // Copy the current string value
+   char strValue[1024];
+   dStrncpy(strValue, STR.getStringValue(), 1024);
+
+   char val[1024] = "";
+   const char* prevVal = NULL;
+
+   // Set the value on an object field.
+   if (object && field)
+      prevVal = object->getDataField(field, array);
+
+   // Set the value on a variable.
+   else if (gEvalState.currentVariable)
+      prevVal = gEvalState.getStringVariable();
+
+   // Ensure that the variable has a value
+   if (!prevVal)
+      return;
+
+   static const StringTableEntry xyzw[] =
+   {
+      StringTable->insert("x"),
+      StringTable->insert("y"),
+      StringTable->insert("z"),
+      StringTable->insert("w")
+   };
+
+   static const StringTableEntry rgba[] =
+   {
+      StringTable->insert("r"),
+      StringTable->insert("g"),
+      StringTable->insert("b"),
+      StringTable->insert("a")
+   };
+
+   // Insert the value into the specified 
+   // component of the string.
+   if (subField == xyzw[0] || subField == rgba[0])
+      dStrcpy(val, StringUnit::setUnit(prevVal, 0, strValue, " \t\n"), 128);
+
+   else if (subField == xyzw[1] || subField == rgba[1])
+      dStrcpy(val, StringUnit::setUnit(prevVal, 1, strValue, " \t\n"), 128);
+
+   else if (subField == xyzw[2] || subField == rgba[2])
+      dStrcpy(val, StringUnit::setUnit(prevVal, 2, strValue, " \t\n"), 128);
+
+   else if (subField == xyzw[3] || subField == rgba[3])
+      dStrcpy(val, StringUnit::setUnit(prevVal, 3, strValue, " \t\n"), 128);
+
+   if (val[0] != 0)
+   {
+      // Update the field or variable.
+      if (object && field)
+         object->setDataField(field, 0, val);
+      else if (gEvalState.currentVariable)
+         gEvalState.setStringVariable(val);
+   }
+}
+
 //------------------------------------------------------------
 //------------------------------------------------------------
 
 
 F64 consoleStringToNumber(const char *str, StringTableEntry file, U32 line)
 F64 consoleStringToNumber(const char *str, StringTableEntry file, U32 line)
@@ -239,38 +417,1717 @@ void ExprEvalState::setStringVariable(const char *val)
    currentVariable->setStringValue(val);
    currentVariable->setStringValue(val);
 }
 }
 
 
-void ExprEvalState::setStringStackPtrVariable(StringStackPtr str)
-{
-   AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!");
-   currentVariable->setStringStackPtrValue(str);
-}
+//-----------------------------------------------------------------------------
 
 
-void ExprEvalState::setCopyVariable()
+U32 gExecCount = 0;
+void CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNamespace, U32 argc, ConsoleValue* argv, bool noCalls, StringTableEntry packageName, ConsoleValue& returnValue, S32 setFrame)
 {
 {
-   if (copyVariable)
+#ifdef TORQUE_DEBUG
+   U32 stackStart = STR.mStartStackSize;
+   gExecCount++;
+#endif
+
+   const dsize_t TRACE_BUFFER_SIZE = 1024;
+   static char traceBuffer[TRACE_BUFFER_SIZE];
+   U32 i;
+
+   U32 iterDepth = 0;
+
+   incRefCount();
+   F64* curFloatTable;
+   char* curStringTable;
+   S32 curStringTableLen = 0; //clint to ensure we dont overwrite it
+   STR.clearFunctionOffset();
+   StringTableEntry thisFunctionName = NULL;
+   bool popFrame = false;
+   if (argv)
    {
    {
-      switch (copyVariable->value.type)
+      // assume this points into a function decl:
+      U32 fnArgc = code[ip + 2 + 6];
+      U32 regCount = code[ip + 2 + 7];
+      thisFunctionName = CodeToSTE(code, ip);
+      S32 wantedArgc = getMin(argc - 1, fnArgc); // argv[0] is func name
+      if (gEvalState.traceOn)
+      {
+         traceBuffer[0] = 0;
+         dStrcat(traceBuffer, "Entering ", TRACE_BUFFER_SIZE);
+         if (packageName)
+         {
+            dStrcat(traceBuffer, "[", TRACE_BUFFER_SIZE);
+            dStrcat(traceBuffer, packageName, TRACE_BUFFER_SIZE);
+            dStrcat(traceBuffer, "]", TRACE_BUFFER_SIZE);
+         }
+         if (thisNamespace && thisNamespace->mName)
+         {
+            dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
+               "%s::%s(", thisNamespace->mName, thisFunctionName);
+         }
+         else
+         {
+            dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
+               "%s(", thisFunctionName);
+         }
+         for (i = 0; i < wantedArgc; i++)
+         {
+            dStrcat(traceBuffer, argv[i + 1].getString(), TRACE_BUFFER_SIZE);
+            if (i != wantedArgc - 1)
+               dStrcat(traceBuffer, ", ", TRACE_BUFFER_SIZE);
+         }
+         dStrcat(traceBuffer, ")", TRACE_BUFFER_SIZE);
+         Con::printf("%s", traceBuffer);
+      }
+      gEvalState.pushFrame(thisFunctionName, thisNamespace, regCount);
+      popFrame = true;
+      for (i = 0; i < wantedArgc; i++)
       {
       {
-         case ConsoleValue::TypeInternalInt:
-            currentVariable->setIntValue(copyVariable->getIntValue());
+         S32 reg = code[ip + (2 + 6 + 1 + 1) + i];
+         ConsoleValue& value = argv[i + 1];
+         switch (value.getType())
+         {
+         case ConsoleValueType::cvString:
+            gEvalState.setLocalStringVariable(reg, value.getString(), dStrlen(value.getString()));
+            break;
+         case ConsoleValueType::cvInteger:
+            gEvalState.setLocalIntVariable(reg, value.getInt());
+            break;
+         case ConsoleValueType::cvFloat:
+            gEvalState.setLocalFloatVariable(reg, value.getFloat());
             break;
             break;
-         case ConsoleValue::TypeInternalFloat:
-            currentVariable->setFloatValue(copyVariable->getFloatValue());
+         case ConsoleValueType::cvSTEntry:
+            gEvalState.setLocalStringTableEntryVariable(reg, value.getString());
             break;
             break;
          default:
          default:
-            currentVariable->setStringValue(copyVariable->getStringValue());
+            AssertFatal(false, avar("Invalid local variable type. Type was: %i", value.getType()));
+         }
+      }
+      ip = ip + fnArgc + (2 + 6 + 1 + 1);
+      curFloatTable = functionFloats;
+      curStringTable = functionStrings;
+      curStringTableLen = functionStringsMaxLen;
+   }
+   else
+   {
+      curFloatTable = globalFloats;
+      curStringTable = globalStrings;
+      curStringTableLen = globalStringsMaxLen;
+
+      // Do we want this code to execute using a new stack frame?
+      if (setFrame < 0)
+      {
+         gEvalState.pushFrame(NULL, NULL, 0);
+         gCallStack.pushFrame(0);
+         popFrame = true;
+      }
+      else if (!gEvalState.stack.empty())
+      {
+         // We want to copy a reference to an existing stack frame
+         // on to the top of the stack.  Any change that occurs to
+         // the locals during this new frame will also occur in the
+         // original frame.
+         S32 stackIndex = gEvalState.stack.size() - setFrame - 1;
+         gEvalState.pushFrameRef(stackIndex);
+         popFrame = true;
+      }
+   }
+
+   // Grab the state of the telenet debugger here once
+   // so that the push and pop frames are always balanced.
+   const bool telDebuggerOn = TelDebugger && TelDebugger->isConnected();
+   if (telDebuggerOn && setFrame < 0)
+      TelDebugger->pushStackFrame();
+
+   StringTableEntry var, objParent;
+   U32 failJump;
+   StringTableEntry fnName;
+   StringTableEntry fnNamespace, fnPackage;
+
+   static const U32 objectCreationStackSize = 32;
+   U32 objectCreationStackIndex = 0;
+   struct {
+      SimObject* newObject;
+      U32 failJump;
+   } objectCreationStack[objectCreationStackSize];
+
+   SimObject* currentNewObject = 0;
+   StringTableEntry prevField = NULL;
+   StringTableEntry curField = NULL;
+   SimObject* prevObject = NULL;
+   SimObject* curObject = NULL;
+   SimObject* saveObject = NULL;
+   Namespace::Entry* nsEntry;
+   Namespace* ns;
+   const char* curFNDocBlock = NULL;
+   const char* curNSDocBlock = NULL;
+   const S32 nsDocLength = 128;
+   char nsDocBlockClass[nsDocLength];
+
+   S32 callArgc;
+   ConsoleValue* callArgv;
+
+   static char curFieldArray[256];
+   static char prevFieldArray[256];
+
+   CodeBlock* saveCodeBlock = smCurrentCodeBlock;
+   smCurrentCodeBlock = this;
+   if (this->name)
+   {
+      Con::gCurrentFile = this->name;
+      Con::gCurrentRoot = this->modPath;
+   }
+   const char* val;
+   S32 reg;
+
+   // The frame temp is used by the variable accessor ops (OP_SAVEFIELD_* and
+   // OP_LOADFIELD_*) to store temporary values for the fields.
+   static S32 VAL_BUFFER_SIZE = 1024;
+   FrameTemp<char> valBuffer(VAL_BUFFER_SIZE);
+
+   for (;;)
+   {
+      U32 instruction = code[ip++];
+   breakContinue:
+      switch (instruction)
+      {
+      case OP_FUNC_DECL:
+         if (!noCalls)
+         {
+            fnName = CodeToSTE(code, ip);
+            fnNamespace = CodeToSTE(code, ip + 2);
+            fnPackage = CodeToSTE(code, ip + 4);
+            bool hasBody = (code[ip + 6] & 0x01) != 0;
+            U32 lineNumber = code[ip + 6] >> 1;
+
+            Namespace::unlinkPackages();
+            if (fnNamespace == NULL && fnPackage == NULL)
+               ns = Namespace::global();
+            else
+               ns = Namespace::find(fnNamespace, fnPackage);
+            ns->addFunction(fnName, this, hasBody ? ip : 0);// if no body, set the IP to 0
+            if (curNSDocBlock)
+            {
+               if (fnNamespace == StringTable->lookup(nsDocBlockClass))
+               {
+                  char* usageStr = dStrdup(curNSDocBlock);
+                  usageStr[dStrlen(usageStr)] = '\0';
+                  ns->mUsage = usageStr;
+                  ns->mCleanUpUsage = true;
+                  curNSDocBlock = NULL;
+               }
+            }
+            Namespace::relinkPackages();
+
+            // If we had a docblock, it's definitely not valid anymore, so clear it out.
+            curFNDocBlock = NULL;
+
+            //Con::printf("Adding function %s::%s (%d)", fnNamespace, fnName, ip);
+         }
+         ip = code[ip + 7];
+         break;
+
+      case OP_CREATE_OBJECT:
+      {
+         // Read some useful info.
+         objParent = CodeToSTE(code, ip);
+         bool isDataBlock = code[ip + 2];
+         bool isInternal = code[ip + 3];
+         bool isSingleton = code[ip + 4];
+         U32  lineNumber = code[ip + 5];
+         failJump = code[ip + 6];
+
+         // If we don't allow calls, we certainly don't allow creating objects!
+         // Moved this to after failJump is set. Engine was crashing when
+         // noCalls = true and an object was being created at the beginning of
+         // a file. ADL.
+         if (noCalls)
+         {
+            ip = failJump;
+            break;
+         }
+
+         // Push the old info to the stack
+         //Assert( objectCreationStackIndex < objectCreationStackSize );
+         objectCreationStack[objectCreationStackIndex].newObject = currentNewObject;
+         objectCreationStack[objectCreationStackIndex++].failJump = failJump;
+
+         // Get the constructor information off the stack.
+         gCallStack.argvc(NULL, callArgc, &callArgv);
+         AssertFatal(callArgc - 3 >= 0, avar("Call Arg needs at least 3, only has %d", callArgc));
+         const char* objectName = callArgv[2].getString();
+
+         // Con::printf("Creating object...");
+
+         // objectName = argv[1]...
+         currentNewObject = NULL;
+
+         // Are we creating a datablock? If so, deal with case where we override
+         // an old one.
+         if (isDataBlock)
+         {
+            // Con::printf("  - is a datablock");
+
+            // Find the old one if any.
+            SimObject* db = Sim::getDataBlockGroup()->findObject(objectName);
+
+            // Make sure we're not changing types on ourselves...
+            if (db && dStricmp(db->getClassName(), callArgv[1].getString()))
+            {
+               Con::errorf(ConsoleLogEntry::General, "Cannot re-declare data block %s with a different class.", objectName);
+               ip = failJump;
+               gCallStack.popFrame();
+               break;
+            }
+
+            // If there was one, set the currentNewObject and move on.
+            if (db)
+               currentNewObject = db;
+         }
+         else if (!isInternal)
+         {
+            AbstractClassRep* rep = AbstractClassRep::findClassRep(objectName);
+            if (rep != NULL)
+            {
+               Con::errorf(ConsoleLogEntry::General, "%s: Cannot name object [%s] the same name as a script class.",
+                  getFileLine(ip), objectName);
+               ip = failJump;
+               gCallStack.popFrame();
+               break;
+            }
+
+            SimObject* obj = Sim::findObject((const char*)objectName);
+            if (obj)
+            {
+               if (isSingleton)
+               {
+                  // Make sure we're not trying to change types
+                  if (dStricmp(obj->getClassName(), callArgv[1].getString()) != 0)
+                  {
+                     Con::errorf(ConsoleLogEntry::General, "%s: Cannot re-declare object [%s] with a different class [%s] - was [%s].",
+                        getFileLine(ip), objectName, callArgv[1].getString(), obj->getClassName());
+                     ip = failJump;
+                     gCallStack.popFrame();
+                     break;
+                  }
+
+                  // We're creating a singleton, so use the found object instead of creating a new object.
+                  currentNewObject = obj;
+                  Con::warnf("%s: Singleton Object was already created with name %s. Using existing object.",
+                     getFileLine(ip), objectName);
+               }
+            }
+         }
+
+         gCallStack.popFrame();
+
+         if (!currentNewObject)
+         {
+            // Well, looks like we have to create a new object.
+            ConsoleObject* object = ConsoleObject::create(callArgv[1].getString());
+
+            // Deal with failure!
+            if (!object)
+            {
+               Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-conobject class %s.", getFileLine(ip - 1), callArgv[1].getString());
+               ip = failJump;
+               break;
+            }
+
+            // Do special datablock init if appropros
+            if (isDataBlock)
+            {
+               SimDataBlock* dataBlock = dynamic_cast<SimDataBlock*>(object);
+               if (dataBlock)
+               {
+                  dataBlock->assignId();
+               }
+               else
+               {
+                  // They tried to make a non-datablock with a datablock keyword!
+                  Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-datablock class %s.", getFileLine(ip - 1), callArgv[1].getString());
+
+                  // Clean up...
+                  delete object;
+                  ip = failJump;
+                  break;
+               }
+            }
+
+            // Finally, set currentNewObject to point to the new one.
+            currentNewObject = dynamic_cast<SimObject*>(object);
+
+            // Deal with the case of a non-SimObject.
+            if (!currentNewObject)
+            {
+               Con::errorf(ConsoleLogEntry::General, "%s: Unable to instantiate non-SimObject class %s.", getFileLine(ip - 1), callArgv[1].getString());
+               delete object;
+               ip = failJump;
+               break;
+            }
+
+            // Set the declaration line
+            currentNewObject->setDeclarationLine(lineNumber);
+
+            // Set the file that this object was created in
+            currentNewObject->setFilename(this->name);
+
+            // Does it have a parent object? (ie, the copy constructor : syntax, not inheriance)
+            if (*objParent)
+            {
+               // Find it!
+               SimObject* parent;
+               if (Sim::findObject(objParent, parent))
+               {
+                  // Con::printf(" - Parent object found: %s", parent->getClassName());
+
+                  currentNewObject->setCopySource(parent);
+                  currentNewObject->assignFieldsFrom(parent);
+
+                  // copy any substitution statements
+                  SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
+                  if (parent_db)
+                  {
+                     SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(currentNewObject);
+                     if (currentNewObject_db)
+                        currentNewObject_db->copySubstitutionsFrom(parent_db);
+                  }
+               }
+               else
+               {
+                  Con::errorf(ConsoleLogEntry::General, "%s: Unable to find parent object %s for %s.", getFileLine(ip - 1), objParent, callArgv[1].getString());
+                  delete object;
+                  currentNewObject = NULL;
+                  ip = failJump;
+                  break;
+               }
+            }
+
+            // If a name was passed, assign it.
+            if (objectName[0])
+            {
+               if (!isInternal)
+                  currentNewObject->assignName(objectName);
+               else
+                  currentNewObject->setInternalName(objectName);
+
+               // Set the original name
+               currentNewObject->setOriginalName( objectName );
+            }
+
+            // Do the constructor parameters.
+            if (!currentNewObject->processArguments(callArgc - 3, callArgv + 3))
+            {
+               delete currentNewObject;
+               currentNewObject = NULL;
+               ip = failJump;
+               break;
+            }
+
+            // If it's not a datablock, allow people to modify bits of it.
+            if (!isDataBlock)
+            {
+               currentNewObject->setModStaticFields(true);
+               currentNewObject->setModDynamicFields(true);
+            }
+         }
+         else
+         {
+            currentNewObject->reloadReset(); // AFX (reload-reset)
+
+            // Does it have a parent object? (ie, the copy constructor : syntax, not inheriance)
+            if (*objParent)
+            {
+               // Find it!
+               SimObject* parent;
+               if (Sim::findObject(objParent, parent))
+               {
+                  // Con::printf(" - Parent object found: %s", parent->getClassName());
+
+                  // temporarily block name change
+                  SimObject::preventNameChanging = true;
+                  currentNewObject->setCopySource(parent);
+                  currentNewObject->assignFieldsFrom(parent);
+                  // restore name changing
+                  SimObject::preventNameChanging = false;
+
+                  // copy any substitution statements
+                  SimDataBlock* parent_db = dynamic_cast<SimDataBlock*>(parent);
+                  if (parent_db)
+                  {
+                     SimDataBlock* currentNewObject_db = dynamic_cast<SimDataBlock*>(currentNewObject);
+                     if (currentNewObject_db)
+                        currentNewObject_db->copySubstitutionsFrom(parent_db);
+                  }
+               }
+               else
+               {
+                  Con::errorf(ConsoleLogEntry::General, "%d: Unable to find parent object %s for %s.", lineNumber, objParent, callArgv[1].getString());
+               }
+            }
+         }
+
+         // Advance the IP past the create info...
+         ip += 7;
+         break;
+      }
+
+      case OP_ADD_OBJECT:
+      {
+         // See OP_SETCURVAR for why we do this.
+         curFNDocBlock = NULL;
+         curNSDocBlock = NULL;
+
+         // Do we place this object at the root?
+         bool placeAtRoot = code[ip++];
+
+         // Con::printf("Adding object %s", currentNewObject->getName());
+
+         // Make sure it wasn't already added, then add it.
+         if (currentNewObject == NULL)
+         {
+            break;
+         }
+
+         bool isMessage = dynamic_cast<Message*>(currentNewObject) != NULL;
+
+         if (currentNewObject->isProperlyAdded() == false)
+         {
+            bool ret = false;
+            if (isMessage)
+            {
+               SimObjectId id = Message::getNextMessageID();
+               if (id != 0xffffffff)
+                  ret = currentNewObject->registerObject(id);
+               else
+                  Con::errorf("%s: No more object IDs available for messages", getFileLine(ip));
+            }
+            else
+               ret = currentNewObject->registerObject();
+
+            if (!ret)
+            {
+               // This error is usually caused by failing to call Parent::initPersistFields in the class' initPersistFields().
+               Con::warnf(ConsoleLogEntry::General, "%s: Register object failed for object %s of class %s.", getFileLine(ip - 2), currentNewObject->getName(), currentNewObject->getClassName());
+               delete currentNewObject;
+               ip = failJump;
+               break;
+            }
+         }
+
+         // Are we dealing with a datablock?
+         SimDataBlock* dataBlock = dynamic_cast<SimDataBlock*>(currentNewObject);
+         String errorStr;
+
+         // If so, preload it.
+         if (dataBlock && !dataBlock->preload(true, errorStr))
+         {
+            Con::errorf(ConsoleLogEntry::General, "%s: preload failed for %s: %s.", getFileLine(ip - 2),
+               currentNewObject->getName(), errorStr.c_str());
+            dataBlock->deleteObject();
+            ip = failJump;
+            break;
+         }
+
+         // What group will we be added to, if any?
+         U32 groupAddId = (U32)intStack[_UINT];
+         SimGroup* grp = NULL;
+         SimSet* set = NULL;
+
+         if (!placeAtRoot || !currentNewObject->getGroup())
+         {
+            if (!isMessage)
+            {
+               if (!placeAtRoot)
+               {
+                  // Otherwise just add to the requested group or set.
+                  if (!Sim::findObject(groupAddId, grp))
+                     Sim::findObject(groupAddId, set);
+               }
+
+               if (placeAtRoot)
+               {
+                  // Deal with the instantGroup if we're being put at the root or we're adding to a component.
+                  if (Con::gInstantGroup.isEmpty() || !Sim::findObject(Con::gInstantGroup, grp))
+                     grp = Sim::getRootGroup();
+               }
+            }
+
+            // If we didn't get a group, then make sure we have a pointer to
+            // the rootgroup.
+            if (!grp)
+               grp = Sim::getRootGroup();
+
+            // add to the parent group
+            grp->addObject(currentNewObject);
+
+            // If for some reason the add failed, add the object to the
+            // root group so it won't leak.
+            if (currentNewObject->getGroup() == NULL)
+               Sim::getRootGroup()->addObject(currentNewObject);
+
+            // add to any set we might be in
+            if (set)
+               set->addObject(currentNewObject);
+         }
+
+         // store the new object's ID on the stack (overwriting the group/set
+         // id, if one was given, otherwise getting pushed)
+         S32 id = currentNewObject->getId();
+         if (placeAtRoot)
+            intStack[_UINT] = id;
+         else
+            intStack[++_UINT] = id;
+
+         break;
+      }
+
+      case OP_END_OBJECT:
+      {
+         // If we're not to be placed at the root, make sure we clean up
+         // our group reference.
+         bool placeAtRoot = code[ip++];
+         if (!placeAtRoot)
+            _UINT--;
+         break;
+      }
+
+      case OP_FINISH_OBJECT:
+      {
+         if (currentNewObject)
+            currentNewObject->onPostAdd();
+
+         //Assert( objectCreationStackIndex >= 0 );
+         // Restore the object info from the stack [7/9/2007 Black]
+         currentNewObject = objectCreationStack[--objectCreationStackIndex].newObject;
+         failJump = objectCreationStack[objectCreationStackIndex].failJump;
+         break;
+      }
+
+      case OP_JMPIFFNOT:
+         if (floatStack[_FLT--])
+         {
+            ip++;
+            break;
+         }
+         ip = code[ip];
+         break;
+      case OP_JMPIFNOT:
+         if (intStack[_UINT--])
+         {
+            ip++;
+            break;
+         }
+         ip = code[ip];
+         break;
+      case OP_JMPIFF:
+         if (!floatStack[_FLT--])
+         {
+            ip++;
+            break;
+         }
+         ip = code[ip];
+         break;
+      case OP_JMPIF:
+         if (!intStack[_UINT--])
+         {
+            ip++;
+            break;
+         }
+         ip = code[ip];
+         break;
+      case OP_JMPIFNOT_NP:
+         if (intStack[_UINT])
+         {
+            _UINT--;
+            ip++;
+            break;
+         }
+         ip = code[ip];
+         break;
+      case OP_JMPIF_NP:
+         if (!intStack[_UINT])
+         {
+            _UINT--;
+            ip++;
+            break;
+         }
+         ip = code[ip];
+         break;
+      case OP_JMP:
+         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.
+
+      case OP_RETURN:
+
+         if (iterDepth > 0)
+         {
+            // Clear iterator state.
+            while (iterDepth > 0)
+            {
+               iterStack[--_ITER].mIsStringIter = false;
+               --iterDepth;
+            }
+
+            const char* retVal = STR.getStringValue();
+            STR.rewind();
+
+            returnValue.setString(retVal, STR.mLen);
+            //STR.setStringValue(returnValue); // Not nice but works.
+         }
+
+         goto execFinished;
+
+      case OP_RETURN_FLT:
+
+         if (iterDepth > 0)
+         {
+            // Clear iterator state.
+            while (iterDepth > 0)
+            {
+               iterStack[--_ITER].mIsStringIter = false;
+               --iterDepth;
+            }
+
+         }
+
+         returnValue.setFloat(floatStack[_FLT]);
+         _FLT--;
+
+         goto execFinished;
+
+      case OP_RETURN_UINT:
+
+         if (iterDepth > 0)
+         {
+            // Clear iterator state.
+            while (iterDepth > 0)
+            {
+               iterStack[--_ITER].mIsStringIter = false;
+               --iterDepth;
+            }
+         }
+
+         returnValue.setInt(intStack[_UINT]);
+         _UINT--;
+
+         goto execFinished;
+
+      case OP_CMPEQ:
+         intStack[_UINT + 1] = bool(floatStack[_FLT] == floatStack[_FLT - 1]);
+         _UINT++;
+         _FLT -= 2;
+         break;
+
+      case OP_CMPGR:
+         intStack[_UINT + 1] = bool(floatStack[_FLT] > floatStack[_FLT - 1]);
+         _UINT++;
+         _FLT -= 2;
+         break;
+
+      case OP_CMPGE:
+         intStack[_UINT + 1] = bool(floatStack[_FLT] >= floatStack[_FLT - 1]);
+         _UINT++;
+         _FLT -= 2;
+         break;
+
+      case OP_CMPLT:
+         intStack[_UINT + 1] = bool(floatStack[_FLT] < floatStack[_FLT - 1]);
+         _UINT++;
+         _FLT -= 2;
+         break;
+
+      case OP_CMPLE:
+         intStack[_UINT + 1] = bool(floatStack[_FLT] <= floatStack[_FLT - 1]);
+         _UINT++;
+         _FLT -= 2;
+         break;
+
+      case OP_CMPNE:
+         intStack[_UINT + 1] = bool(floatStack[_FLT] != floatStack[_FLT - 1]);
+         _UINT++;
+         _FLT -= 2;
+         break;
+
+      case OP_XOR:
+         intStack[_UINT - 1] = intStack[_UINT] ^ intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_MOD:
+         if (intStack[_UINT - 1] != 0)
+            intStack[_UINT - 1] = intStack[_UINT] % intStack[_UINT - 1];
+         else
+            intStack[_UINT - 1] = 0;
+         _UINT--;
+         break;
+
+      case OP_BITAND:
+         intStack[_UINT - 1] = intStack[_UINT] & intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_BITOR:
+         intStack[_UINT - 1] = intStack[_UINT] | intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_NOT:
+         intStack[_UINT] = !intStack[_UINT];
+         break;
+
+      case OP_NOTF:
+         intStack[_UINT + 1] = !floatStack[_FLT];
+         _FLT--;
+         _UINT++;
+         break;
+
+      case OP_ONESCOMPLEMENT:
+         intStack[_UINT] = ~intStack[_UINT];
+         break;
+
+      case OP_SHR:
+         intStack[_UINT - 1] = intStack[_UINT] >> intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_SHL:
+         intStack[_UINT - 1] = intStack[_UINT] << intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_AND:
+         intStack[_UINT - 1] = intStack[_UINT] && intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_OR:
+         intStack[_UINT - 1] = intStack[_UINT] || intStack[_UINT - 1];
+         _UINT--;
+         break;
+
+      case OP_ADD:
+         floatStack[_FLT - 1] = floatStack[_FLT] + floatStack[_FLT - 1];
+         _FLT--;
+         break;
+
+      case OP_SUB:
+         floatStack[_FLT - 1] = floatStack[_FLT] - floatStack[_FLT - 1];
+         _FLT--;
+         break;
+
+      case OP_MUL:
+         floatStack[_FLT - 1] = floatStack[_FLT] * floatStack[_FLT - 1];
+         _FLT--;
+         break;
+      case OP_DIV:
+         floatStack[_FLT - 1] = floatStack[_FLT] / floatStack[_FLT - 1];
+         _FLT--;
+         break;
+      case OP_NEG:
+         floatStack[_FLT] = -floatStack[_FLT];
+         break;
+
+      case OP_INC:
+         reg = code[ip++];
+         gEvalState.setLocalFloatVariable(reg, gEvalState.getLocalFloatVariable(reg) + 1.0);
+         break;
+
+      case OP_SETCURVAR:
+         var = CodeToSTE(code, ip);
+         ip += 2;
+
+         // If a variable is set, then these must be NULL. It is necessary
+         // to set this here so that the vector parser can appropriately
+         // identify whether it's dealing with a vector.
+         prevField = NULL;
+         prevObject = NULL;
+         curObject = NULL;
+
+         gEvalState.setCurVarName(var);
+
+         // In order to let docblocks work properly with variables, we have
+         // clear the current docblock when we do an assign. This way it
+         // won't inappropriately carry forward to following function decls.
+         curFNDocBlock = NULL;
+         curNSDocBlock = NULL;
+         break;
+
+      case OP_SETCURVAR_CREATE:
+         var = CodeToSTE(code, ip);
+         ip += 2;
+
+         // See OP_SETCURVAR
+         prevField = NULL;
+         prevObject = NULL;
+         curObject = NULL;
+
+         gEvalState.setCurVarNameCreate(var);
+
+         // See OP_SETCURVAR for why we do this.
+         curFNDocBlock = NULL;
+         curNSDocBlock = NULL;
+         break;
+
+      case OP_SETCURVAR_ARRAY:
+         var = STR.getSTValue();
+
+         // See OP_SETCURVAR
+         prevField = NULL;
+         prevObject = NULL;
+         curObject = NULL;
+
+         gEvalState.setCurVarName(var);
+
+         // See OP_SETCURVAR for why we do this.
+         curFNDocBlock = NULL;
+         curNSDocBlock = NULL;
+         break;
+
+      case OP_SETCURVAR_ARRAY_CREATE:
+         var = STR.getSTValue();
+
+         // See OP_SETCURVAR
+         prevField = NULL;
+         prevObject = NULL;
+         curObject = NULL;
+
+         gEvalState.setCurVarNameCreate(var);
+
+         // See OP_SETCURVAR for why we do this.
+         curFNDocBlock = NULL;
+         curNSDocBlock = NULL;
+         break;
+
+      case OP_LOADVAR_UINT:
+         intStack[_UINT + 1] = gEvalState.getIntVariable();
+         _UINT++;
+         break;
+
+      case OP_LOADVAR_FLT:
+         floatStack[_FLT + 1] = gEvalState.getFloatVariable();
+         _FLT++;
+         break;
+
+      case OP_LOADVAR_STR:
+         val = gEvalState.getStringVariable();
+         STR.setStringValue(val);
+         break;
+
+      case OP_SAVEVAR_UINT:
+         gEvalState.setIntVariable((S32)intStack[_UINT]);
+         break;
+
+      case OP_SAVEVAR_FLT:
+         gEvalState.setFloatVariable(floatStack[_FLT]);
+         break;
+
+      case OP_SAVEVAR_STR:
+         gEvalState.setStringVariable(STR.getStringValue());
+         break;
+
+      case OP_LOAD_LOCAL_VAR_UINT:
+         reg = code[ip++];
+         intStack[_UINT + 1] = gEvalState.getLocalIntVariable(reg);
+         _UINT++;
+         break;
+
+      case OP_LOAD_LOCAL_VAR_FLT:
+         reg = code[ip++];
+         floatStack[_FLT + 1] = gEvalState.getLocalFloatVariable(reg);
+         _FLT++;
+         break;
+
+      case OP_LOAD_LOCAL_VAR_STR:
+         reg = code[ip++];
+         val = gEvalState.getLocalStringVariable(reg);
+         STR.setStringValue(val);
+         break;
+
+      case OP_SAVE_LOCAL_VAR_UINT:
+         reg = code[ip++];
+         gEvalState.setLocalIntVariable(reg, (S32)intStack[_UINT]);
+         break;
+
+      case OP_SAVE_LOCAL_VAR_FLT:
+         reg = code[ip++];
+         gEvalState.setLocalFloatVariable(reg, floatStack[_FLT]);
+         break;
+
+      case OP_SAVE_LOCAL_VAR_STR:
+         reg = code[ip++];
+         gEvalState.setLocalStringVariable(reg, STR.getStringValue(), (S32)STR.mLen);
+         break;
+
+      case OP_SETCUROBJECT:
+         // Save the previous object for parsing vector fields.
+         prevObject = curObject;
+         val = STR.getStringValue();
+
+         // Sim::findObject will sometimes find valid objects from
+         // multi-component strings. This makes sure that doesn't
+         // happen.
+         for (const char* check = val; *check; check++)
+         {
+            if (*check == ' ')
+            {
+               val = "";
+               break;
+            }
+         }
+         curObject = Sim::findObject(val);
+         break;
+
+      case OP_SETCUROBJECT_INTERNAL:
+         ++ip; // To skip the recurse flag if the object wasnt found
+         if (curObject)
+         {
+            SimGroup* group = dynamic_cast<SimGroup*>(curObject);
+            if (group)
+            {
+               StringTableEntry intName = StringTable->insert(STR.getStringValue());
+               bool recurse = code[ip - 1];
+               SimObject* obj = group->findObjectByInternalName(intName, recurse);
+               intStack[_UINT + 1] = obj ? obj->getId() : 0;
+               _UINT++;
+            }
+            else
+            {
+               Con::errorf(ConsoleLogEntry::Script, "%s: Attempt to use -> on non-group %s of class %s.", getFileLine(ip - 2), curObject->getName(), curObject->getClassName());
+               intStack[_UINT] = 0;
+            }
+         }
+         break;
+
+      case OP_SETCUROBJECT_NEW:
+         curObject = currentNewObject;
+         break;
+
+      case OP_SETCURFIELD:
+         // Save the previous field for parsing vector fields.
+         prevField = curField;
+         dStrcpy(prevFieldArray, curFieldArray, 256);
+         curField = CodeToSTE(code, ip);
+         curFieldArray[0] = 0;
+         ip += 2;
+         break;
+
+      case OP_SETCURFIELD_ARRAY:
+         dStrcpy(curFieldArray, STR.getStringValue(), 256);
+         break;
+
+      case OP_SETCURFIELD_TYPE:
+         if(curObject)
+            curObject->setDataFieldType(code[ip], curField, curFieldArray);
+         ip++;
+         break;
+
+      case OP_LOADFIELD_UINT:
+         if (curObject)
+            intStack[_UINT + 1] = U32(dAtoi(curObject->getDataField(curField, curFieldArray)));
+         else
+         {
+            // The field is not being retrieved from an object. Maybe it's
+            // a special accessor?
+            char buff[FieldBufferSizeNumeric];
+            memset(buff, 0, sizeof(buff));
+            getFieldComponent(prevObject, prevField, prevFieldArray, curField, buff);
+            intStack[_UINT + 1] = dAtoi(buff);
+         }
+         _UINT++;
+         break;
+
+      case OP_LOADFIELD_FLT:
+         if (curObject)
+            floatStack[_FLT + 1] = dAtof(curObject->getDataField(curField, curFieldArray));
+         else
+         {
+            // The field is not being retrieved from an object. Maybe it's
+            // a special accessor?
+            char buff[FieldBufferSizeNumeric];
+            memset(buff, 0, sizeof(buff));
+            getFieldComponent(prevObject, prevField, prevFieldArray, curField, buff);
+            floatStack[_FLT + 1] = dAtof(buff);
+         }
+         _FLT++;
+         break;
+
+      case OP_LOADFIELD_STR:
+         if (curObject)
+         {
+            val = curObject->getDataField(curField, curFieldArray);
+            STR.setStringValue(val);
+         }
+         else
+         {
+            // The field is not being retrieved from an object. Maybe it's
+            // a special accessor?
+            char buff[FieldBufferSizeString];
+            memset(buff, 0, sizeof(buff));
+            getFieldComponent(prevObject, prevField, prevFieldArray, curField, buff);
+            STR.setStringValue(buff);
+         }
+
+         break;
+
+      case OP_SAVEFIELD_UINT:
+         STR.setIntValue((U32)intStack[_UINT]);
+         if (curObject)
+            curObject->setDataField(curField, curFieldArray, STR.getStringValue());
+         else
+         {
+            // The field is not being set on an object. Maybe it's
+            // a special accessor?
+            setFieldComponent( prevObject, prevField, prevFieldArray, curField );
+            prevObject = NULL;
+         }
+         break;
+
+      case OP_SAVEFIELD_FLT:
+         STR.setFloatValue(floatStack[_FLT]);
+         if (curObject)
+            curObject->setDataField(curField, curFieldArray, STR.getStringValue());
+         else
+         {
+            // The field is not being set on an object. Maybe it's
+            // a special accessor?
+            setFieldComponent( prevObject, prevField, prevFieldArray, curField );
+            prevObject = NULL;
+         }
+         break;
+
+      case OP_SAVEFIELD_STR:
+         if (curObject)
+            curObject->setDataField(curField, curFieldArray, STR.getStringValue());
+         else
+         {
+            // The field is not being set on an object. Maybe it's
+            // a special accessor?
+            setFieldComponent( prevObject, prevField, prevFieldArray, curField );
+            prevObject = NULL;
+         }
+         break;
+
+      case OP_STR_TO_UINT:
+         intStack[_UINT + 1] = STR.getIntValue();
+         _UINT++;
+         break;
+
+      case OP_STR_TO_FLT:
+         floatStack[_FLT + 1] = STR.getFloatValue();
+         _FLT++;
+         break;
+
+      case OP_STR_TO_NONE:
+         // This exists simply to deal with certain typecast situations.
+         break;
+
+      case OP_FLT_TO_UINT:
+         intStack[_UINT + 1] = (S64)floatStack[_FLT];
+         _FLT--;
+         _UINT++;
+         break;
+
+      case OP_FLT_TO_STR:
+         STR.setFloatValue(floatStack[_FLT]);
+         _FLT--;
+         break;
+
+      case OP_FLT_TO_NONE:
+         _FLT--;
+         break;
+
+      case OP_UINT_TO_FLT:
+         floatStack[_FLT + 1] = (F64)intStack[_UINT];
+         _UINT--;
+         _FLT++;
+         break;
+
+      case OP_UINT_TO_STR:
+         STR.setIntValue((U32)intStack[_UINT]);
+         _UINT--;
+         break;
+
+      case OP_UINT_TO_NONE:
+         _UINT--;
+         break;
+
+      case OP_LOADIMMED_UINT:
+         intStack[_UINT + 1] = code[ip++];
+         _UINT++;
+         break;
+
+      case OP_LOADIMMED_FLT:
+         floatStack[_FLT + 1] = curFloatTable[code[ip]];
+         ip++;
+         _FLT++;
+         break;
+      case OP_TAG_TO_STR:
+         code[ip - 1] = OP_LOADIMMED_STR;
+         // it's possible the string has already been converted
+         if (U8(curStringTable[code[ip]]) != StringTagPrefixByte)
+         {
+            U32 id = GameAddTaggedString(curStringTable + code[ip]);
+            dSprintf(curStringTable + code[ip] + 1, 7, "%d", id);
+            *(curStringTable + code[ip]) = StringTagPrefixByte;
+         }
+      case OP_LOADIMMED_STR:
+         STR.setStringValue(curStringTable + code[ip++]);
+         break;
+
+      case OP_DOCBLOCK_STR:
+      {
+         // If the first word of the doc is '\class' or '@class', then this
+         // is a namespace doc block, otherwise it is a function doc block.
+         const char* docblock = curStringTable + code[ip++];
+
+         const char* sansClass = dStrstr(docblock, "@class");
+         if (!sansClass)
+            sansClass = dStrstr(docblock, "\\class");
+
+         if (sansClass)
+         {
+            // Don't save the class declaration. Scan past the 'class'
+            // keyword and up to the first whitespace.
+            sansClass += 7;
+            S32 index = 0;
+            while ((*sansClass != ' ') && (*sansClass != '\n') && *sansClass && (index < (nsDocLength - 1)))
+            {
+               nsDocBlockClass[index++] = *sansClass;
+               sansClass++;
+            }
+            nsDocBlockClass[index] = '\0';
+
+            curNSDocBlock = sansClass + 1;
+         }
+         else
+            curFNDocBlock = docblock;
+      }
+
+      break;
+
+      case OP_LOADIMMED_IDENT:
+         STR.setStringValue(CodeToSTE(code, ip));
+         ip += 2;
+         break;
+
+      case OP_CALLFUNC:
+      {
+         // This routingId is set when we query the object as to whether
+         // it handles this method.  It is set to an enum from the table
+         // above indicating whether it handles it on a component it owns
+         // or just on the object.
+         S32 routingId = 0;
+
+         fnName = CodeToSTE(code, ip);
+         fnNamespace = CodeToSTE(code, ip + 2);
+         U32 callType = code[ip + 4];
+
+         //if this is called from inside a function, append the ip and codeptr
+         if (!gEvalState.stack.empty())
+         {
+            gEvalState.stack.last()->code = this;
+            gEvalState.stack.last()->ip = ip - 1;
+         }
+
+         ip += 5;
+         gCallStack.argvc(fnName, callArgc, &callArgv);
+
+         if (callType == FuncCallExprNode::FunctionCall)
+         {
+            // Note: This works even if the function was in a package. Reason being is when
+            // activatePackage() is called, it swaps the namespaceEntry into the global namespace
+            // (and reverts it when deactivatePackage is called). Method or Static related ones work
+            // as expected, as the namespace is resolved on the fly.
+            nsEntry = Namespace::global()->lookup(fnName);
+            if (!nsEntry)
+            {
+               Con::warnf(ConsoleLogEntry::General,
+                  "%s: Unable to find function %s",
+                  getFileLine(ip - 4), fnName);
+               //STR.popFrame();
+               gCallStack.popFrame();
+               break;
+            }
+         }
+         else if (callType == FuncCallExprNode::StaticCall)
+         {
+            // Try to look it up.
+            ns = Namespace::find(fnNamespace);
+            nsEntry = ns->lookup(fnName);
+            if (!nsEntry)
+            {
+               Con::warnf(ConsoleLogEntry::General,
+                  "%s: Unable to find function %s%s%s",
+                  getFileLine(ip - 4), fnNamespace ? fnNamespace : "",
+                  fnNamespace ? "::" : "", fnName);
+               //STR.popFrame();
+               gCallStack.popFrame();
+               break;
+            }
+         }
+         else if (callType == FuncCallExprNode::MethodCall)
+         {
+            saveObject = gEvalState.thisObject;
+
+            // Optimization: If we're an integer, we can lookup the value by SimObjectId
+            const ConsoleValue& simObjectLookupValue = callArgv[1];
+            if (simObjectLookupValue.getType() == ConsoleValueType::cvInteger)
+               gEvalState.thisObject = Sim::findObject(static_cast<SimObjectId>(simObjectLookupValue.getInt()));
+            else
+               gEvalState.thisObject = Sim::findObject(simObjectLookupValue.getString());
+
+            if (gEvalState.thisObject == NULL)
+            {
+               Con::warnf(
+                  ConsoleLogEntry::General,
+                  "%s: Unable to find object: '%s' attempting to call function '%s'",
+                  getFileLine(ip - 6),
+                  simObjectLookupValue.getString(),
+                  fnName
+               );
+               //STR.popFrame();
+               gCallStack.popFrame();
+               STR.setStringValue("");
+               break;
+            }
+
+            ns = gEvalState.thisObject->getNamespace();
+            if (ns)
+               nsEntry = ns->lookup(fnName);
+            else
+               nsEntry = NULL;
+         }
+         else // it's a ParentCall
+         {
+            if (thisNamespace)
+            {
+               ns = thisNamespace->mParent;
+               if (ns)
+                  nsEntry = ns->lookup(fnName);
+               else
+                  nsEntry = NULL;
+            }
+            else
+            {
+               ns = NULL;
+               nsEntry = NULL;
+            }
+         }
+
+         if (!nsEntry || noCalls)
+         {
+            if (!noCalls)
+            {
+               Con::warnf(ConsoleLogEntry::General, "%s: Unknown command %s.", getFileLine(ip - 4), fnName);
+               if (callType == FuncCallExprNode::MethodCall)
+               {
+                  Con::warnf(ConsoleLogEntry::General, "  Object %s(%d) %s",
+                     gEvalState.thisObject->getName() ? gEvalState.thisObject->getName() : "",
+                     gEvalState.thisObject->getId(), Con::getNamespaceList(ns));
+               }
+            }
+            gCallStack.popFrame();
+            STR.setStringValue("");
+            STR.setStringValue("");
             break;
             break;
+         }
+         if (nsEntry->mType == Namespace::Entry::ConsoleFunctionType)
+         {
+            if (nsEntry->mFunctionOffset)
+            {
+               ConsoleValue ret;
+               nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage, ret);
+               STR.setStringValue(ret.getString());
+            }
+            else // no body
+               STR.setStringValue("");
+
+            gCallStack.popFrame();
+         }
+         else
+         {
+            if ((nsEntry->mMinArgs && S32(callArgc) < nsEntry->mMinArgs) || (nsEntry->mMaxArgs && S32(callArgc) > nsEntry->mMaxArgs))
+            {
+               const char* nsName = ns ? ns->mName : "";
+               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("");
+            }
+            else
+            {
+               switch (nsEntry->mType)
+               {
+               case Namespace::Entry::StringCallbackType:
+               {
+                  const char* ret = nsEntry->cb.mStringCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  gCallStack.popFrame();
+                  if (ret != STR.getStringValue())
+                     STR.setStringValue(ret);
+                  else
+                     STR.setLen(dStrlen(ret));
+                  break;
+               }
+               case Namespace::Entry::IntCallbackType:
+               {
+                  S32 result = nsEntry->cb.mIntCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  gCallStack.popFrame();
+                  if (code[ip] == OP_STR_TO_UINT)
+                  {
+                     ip++;
+                     intStack[++_UINT] = result;
+                     break;
+                  }
+                  else if (code[ip] == OP_STR_TO_FLT)
+                  {
+                     ip++;
+                     floatStack[++_FLT] = result;
+                     break;
+                  }
+                  else if (code[ip] == OP_STR_TO_NONE)
+                     ip++;
+                  else
+                     STR.setIntValue(result);
+                  break;
+               }
+               case Namespace::Entry::FloatCallbackType:
+               {
+                  F64 result = nsEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  gCallStack.popFrame();
+                  if (code[ip] == OP_STR_TO_UINT)
+                  {
+                     ip++;
+                     intStack[++_UINT] = (S64)result;
+                     break;
+                  }
+                  else if (code[ip] == OP_STR_TO_FLT)
+                  {
+                     ip++;
+                     floatStack[++_FLT] = result;
+                     break;
+                  }
+                  else if (code[ip] == OP_STR_TO_NONE)
+                     ip++;
+                  else
+                     STR.setFloatValue(result);
+                  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("");
+                  break;
+               }
+               case Namespace::Entry::BoolCallbackType:
+               {
+                  bool result = nsEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  gCallStack.popFrame();
+                  if (code[ip] == OP_STR_TO_UINT)
+                  {
+                     ip++;
+                     intStack[++_UINT] = result;
+                     break;
+                  }
+                  else if (code[ip] == OP_STR_TO_FLT)
+                  {
+                     ip++;
+                     floatStack[++_FLT] = result;
+                     break;
+                  }
+                  else if (code[ip] == OP_STR_TO_NONE)
+                     ip++;
+                  else
+                     STR.setIntValue(result);
+                  break;
+               }
+               }
+            }
+         }
+
+         if (callType == FuncCallExprNode::MethodCall)
+            gEvalState.thisObject = saveObject;
+         break;
+      }
+      case OP_ADVANCE_STR:
+         STR.advance();
+         break;
+      case OP_ADVANCE_STR_APPENDCHAR:
+         STR.advanceChar(code[ip++]);
+         break;
+
+      case OP_ADVANCE_STR_COMMA:
+         STR.advanceChar('_');
+         break;
+
+      case OP_ADVANCE_STR_NUL:
+         STR.advanceChar(0);
+         break;
+
+      case OP_REWIND_STR:
+         STR.rewind();
+         break;
+
+      case OP_TERMINATE_REWIND_STR:
+         STR.rewindTerminate();
+         break;
+
+      case OP_COMPARE_STR:
+         intStack[++_UINT] = STR.compare();
+         break;
+
+      case OP_PUSH:
+         gCallStack.pushString(STR.getStringValue(), STR.mLen);
+         break;
+
+      case OP_PUSH_UINT:
+         gCallStack.pushInt((U32)intStack[_UINT--]);
+         break;
+
+      case OP_PUSH_FLT:
+         gCallStack.pushFloat(floatStack[_FLT--]);
+         break;
+
+      case OP_PUSH_FRAME:
+         gCallStack.pushFrame(code[ip++]);
+         break;
+
+      case OP_ASSERT:
+      {
+         if (!intStack[_UINT--])
+         {
+            const char* message = curStringTable + code[ip];
+
+            U32 breakLine, inst;
+            findBreakLine(ip - 1, breakLine, inst);
+
+            if (PlatformAssert::processAssert(PlatformAssert::Fatal,
+               name ? name : "eval",
+               breakLine,
+               message))
+            {
+               if (TelDebugger && TelDebugger->isConnected() && breakLine > 0)
+               {
+                  TelDebugger->breakProcess();
+               }
+               else
+                  Platform::debugBreak();
+            }
+         }
+
+         ip++;
+         break;
+      }
+
+      case OP_BREAK:
+      {
+         //append the ip and codeptr before managing the breakpoint!
+         AssertFatal(!gEvalState.stack.empty(), "Empty eval stack on break!");
+         gEvalState.stack.last()->code = this;
+         gEvalState.stack.last()->ip = ip - 1;
+
+         U32 breakLine;
+         findBreakLine(ip - 1, breakLine, instruction);
+         if (!breakLine)
+            goto breakContinue;
+         TelDebugger->executionStopped(this, breakLine);
+
+         goto breakContinue;
+      }
+
+      case OP_ITER_BEGIN_STR:
+      {
+         iterStack[_ITER].mIsStringIter = true;
+         /* fallthrough */
+      }
+
+      case OP_ITER_BEGIN:
+      {
+         StringTableEntry varName = CodeToSTE(code, ip);
+         U32 failIp = code[ip + 2];
+
+         IterStackRecord& iter = iterStack[_ITER];
+
+         iter.mVariable = gEvalState.getCurrentFrame().add(varName);
+
+         if (iter.mIsStringIter)
+         {
+            iter.mData.mStr.mString = STR.getStringValue();
+            iter.mData.mStr.mIndex = 0;
+         }
+         else
+         {
+            // Look up the object.
+
+            SimSet* set;
+            if (!Sim::findObject(STR.getStringValue(), set))
+            {
+               Con::errorf(ConsoleLogEntry::General, "No SimSet object '%s'", STR.getStringValue());
+               Con::errorf(ConsoleLogEntry::General, "Did you mean to use 'foreach$' instead of 'foreach'?");
+               ip = failIp;
+               continue;
+            }
+
+            // Set up.
+
+            iter.mData.mObj.mSet = set;
+            iter.mData.mObj.mIndex = 0;
+         }
+
+         _ITER++;
+         iterDepth++;
+
+         STR.push();
+
+         ip += 3;
+         break;
+      }
+
+      case OP_ITER:
+      {
+         U32 breakIp = code[ip];
+         IterStackRecord& iter = iterStack[_ITER - 1];
+
+         if (iter.mIsStringIter)
+         {
+            const char* str = iter.mData.mStr.mString;
+
+            U32 startIndex = iter.mData.mStr.mIndex;
+            U32 endIndex = startIndex;
+
+            // Break if at end.
+
+            if (!str[startIndex])
+            {
+               ip = breakIp;
+               continue;
+            }
+
+            // Find right end of current component.
+
+            if (!dIsspace(str[endIndex]))
+               do ++endIndex;
+            while (str[endIndex] && !dIsspace(str[endIndex]));
+
+            // Extract component.
+
+            if (endIndex != startIndex)
+            {
+               char savedChar = str[endIndex];
+               const_cast<char*>(str)[endIndex] = '\0'; // We are on the string stack so this is okay.
+               iter.mVariable->setStringValue(&str[startIndex]);
+               const_cast<char*>(str)[endIndex] = savedChar;
+            }
+            else
+               iter.mVariable->setStringValue("");
+
+            // Skip separator.
+            if (str[endIndex] != '\0')
+               ++endIndex;
+
+            iter.mData.mStr.mIndex = endIndex;
+         }
+         else
+         {
+            U32 index = iter.mData.mObj.mIndex;
+            SimSet* set = iter.mData.mObj.mSet;
+
+            if (index >= set->size())
+            {
+               ip = breakIp;
+               continue;
+            }
+
+            iter.mVariable->setIntValue(set->at(index)->getId());
+            iter.mData.mObj.mIndex = index + 1;
+         }
+
+         ++ip;
+         break;
+      }
+
+      case OP_ITER_END:
+      {
+         --_ITER;
+         --iterDepth;
+
+         STR.rewind();
+
+         iterStack[_ITER].mIsStringIter = false;
+         break;
+      }
+
+      case OP_INVALID:
+
+      default:
+         // error!
+         goto execFinished;
       }
       }
    }
    }
-}
+execFinished:
+#ifdef TORQUE_DEBUG
+   AssertFatal(returnValue.getType() == ConsoleValueType::cvNone, "returnValue was never set during script exec");
+#endif
 
 
-//------------------------------------------------------------
+   if (telDebuggerOn && setFrame < 0)
+      TelDebugger->popStackFrame();
 
 
+   if (popFrame)
+   {
+      gEvalState.popFrame();
+   }
 
 
-ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thisNamespace, U32 argc, ConsoleValueRef *argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
-{
-   CodeInterpreter interpreter(this);
-   return interpreter.exec(ip, functionName, thisNamespace, argc, argv, noCalls, packageName, setFrame);
+   if (argv)
+   {
+      if (gEvalState.traceOn)
+      {
+         traceBuffer[0] = 0;
+         dStrcat(traceBuffer, "Leaving ", TRACE_BUFFER_SIZE);
+
+         if (packageName)
+         {
+            dStrcat(traceBuffer, "[", TRACE_BUFFER_SIZE);
+            dStrcat(traceBuffer, packageName, TRACE_BUFFER_SIZE);
+            dStrcat(traceBuffer, "]", TRACE_BUFFER_SIZE);
+         }
+         if (thisNamespace && thisNamespace->mName)
+         {
+            dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
+               "%s::%s() - return %s", thisNamespace->mName, thisFunctionName, returnValue.getString());
+         }
+         else
+         {
+            dSprintf(traceBuffer + dStrlen(traceBuffer), sizeof(traceBuffer) - dStrlen(traceBuffer),
+               "%s() - return %s", thisFunctionName, returnValue.getString());
+         }
+         Con::printf("%s", traceBuffer);
+      }
+   }
+   else
+   {
+      delete[] const_cast<char*>(globalStrings);
+      delete[] globalFloats;
+      globalStrings = NULL;
+      globalFloats = NULL;
+   }
+   smCurrentCodeBlock = saveCodeBlock;
+   if (saveCodeBlock && saveCodeBlock->name)
+   {
+      Con::gCurrentFile = saveCodeBlock->name;
+      Con::gCurrentRoot = saveCodeBlock->modPath;
+   }
+
+   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");
+#endif
 }
 }
 
 
 //------------------------------------------------------------
 //------------------------------------------------------------

+ 9 - 15
Engine/source/console/compiler.h

@@ -93,26 +93,28 @@ namespace Compiler
       OP_MUL,
       OP_MUL,
       OP_DIV,
       OP_DIV,
       OP_NEG,
       OP_NEG,
-
       OP_INC,
       OP_INC,
-      OP_DEC,
 
 
       OP_SETCURVAR,
       OP_SETCURVAR,
       OP_SETCURVAR_CREATE,
       OP_SETCURVAR_CREATE,
       OP_SETCURVAR_ARRAY,
       OP_SETCURVAR_ARRAY,
-      OP_SETCURVAR_ARRAY_VARLOOKUP,
       OP_SETCURVAR_ARRAY_CREATE,
       OP_SETCURVAR_ARRAY_CREATE,
-      OP_SETCURVAR_ARRAY_CREATE_VARLOOKUP,
 
 
       OP_LOADVAR_UINT,// 40
       OP_LOADVAR_UINT,// 40
       OP_LOADVAR_FLT,
       OP_LOADVAR_FLT,
       OP_LOADVAR_STR,
       OP_LOADVAR_STR,
-      OP_LOADVAR_VAR,
 
 
       OP_SAVEVAR_UINT,
       OP_SAVEVAR_UINT,
       OP_SAVEVAR_FLT,
       OP_SAVEVAR_FLT,
       OP_SAVEVAR_STR,
       OP_SAVEVAR_STR,
-      OP_SAVEVAR_VAR,
+
+      OP_LOAD_LOCAL_VAR_UINT,
+      OP_LOAD_LOCAL_VAR_FLT,
+      OP_LOAD_LOCAL_VAR_STR,
+
+      OP_SAVE_LOCAL_VAR_UINT,
+      OP_SAVE_LOCAL_VAR_FLT,
+      OP_SAVE_LOCAL_VAR_STR,
 
 
       OP_SETCUROBJECT,
       OP_SETCUROBJECT,
       OP_SETCUROBJECT_NEW,
       OP_SETCUROBJECT_NEW,
@@ -121,8 +123,6 @@ namespace Compiler
       OP_SETCURFIELD,
       OP_SETCURFIELD,
       OP_SETCURFIELD_ARRAY, // 50
       OP_SETCURFIELD_ARRAY, // 50
       OP_SETCURFIELD_TYPE,
       OP_SETCURFIELD_TYPE,
-      OP_SETCURFIELD_ARRAY_VAR,
-      OP_SETCURFIELD_THIS,
 
 
       OP_LOADFIELD_UINT,
       OP_LOADFIELD_UINT,
       OP_LOADFIELD_FLT,
       OP_LOADFIELD_FLT,
@@ -141,19 +141,15 @@ namespace Compiler
       OP_UINT_TO_FLT,
       OP_UINT_TO_FLT,
       OP_UINT_TO_STR,
       OP_UINT_TO_STR,
       OP_UINT_TO_NONE,
       OP_UINT_TO_NONE,
-      OP_COPYVAR_TO_NONE,
 
 
       OP_LOADIMMED_UINT,
       OP_LOADIMMED_UINT,
       OP_LOADIMMED_FLT,
       OP_LOADIMMED_FLT,
       OP_TAG_TO_STR,
       OP_TAG_TO_STR,
       OP_LOADIMMED_STR, // 70
       OP_LOADIMMED_STR, // 70
-      OP_DOCBLOCK_STR,
+      OP_DOCBLOCK_STR,  // 76
       OP_LOADIMMED_IDENT,
       OP_LOADIMMED_IDENT,
 
 
-      OP_CALLFUNC_RESOLVE,
       OP_CALLFUNC,
       OP_CALLFUNC,
-      OP_CALLFUNC_POINTER,
-      OP_CALLFUNC_THIS,
 
 
       OP_ADVANCE_STR,
       OP_ADVANCE_STR,
       OP_ADVANCE_STR_APPENDCHAR,
       OP_ADVANCE_STR_APPENDCHAR,
@@ -166,8 +162,6 @@ namespace Compiler
       OP_PUSH,          // String
       OP_PUSH,          // String
       OP_PUSH_UINT,     // Integer
       OP_PUSH_UINT,     // Integer
       OP_PUSH_FLT,      // Float
       OP_PUSH_FLT,      // Float
-      OP_PUSH_VAR,      // Variable
-      OP_PUSH_THIS,     // This pointer
       OP_PUSH_FRAME,    // Frame
       OP_PUSH_FRAME,    // Frame
 
 
       OP_ASSERT,
       OP_ASSERT,

+ 14 - 215
Engine/source/console/console.cpp

@@ -271,8 +271,6 @@ StringTableEntry gCurrentFile;
 StringTableEntry gCurrentRoot;
 StringTableEntry gCurrentRoot;
 /// @}
 /// @}
 
 
-S32 gObjectCopyFailures = -1;
-
 bool alwaysUseDebugOutput = true;
 bool alwaysUseDebugOutput = true;
 bool useTimestamp = false;
 bool useTimestamp = false;
 bool useRealTimestamp = false;
 bool useRealTimestamp = false;
@@ -327,6 +325,7 @@ void init()
 
 
    // Setup the console types.
    // Setup the console types.
    ConsoleBaseType::initialize();
    ConsoleBaseType::initialize();
+   ConsoleValue::init();
 
 
    // And finally, the ACR...
    // And finally, the ACR...
    AbstractClassRep::initialize();
    AbstractClassRep::initialize();
@@ -344,10 +343,6 @@ void init()
    addVariable( "instantGroup", TypeRealString, &gInstantGroup, "The group that objects will be added to when they are created.\n"
    addVariable( "instantGroup", TypeRealString, &gInstantGroup, "The group that objects will be added to when they are created.\n"
       "@ingroup Console\n");
       "@ingroup Console\n");
 
 
-   addVariable("Con::objectCopyFailures", TypeS32, &gObjectCopyFailures, "If greater than zero then it counts the number of object creation "
-      "failures based on a missing copy object and does not report an error..\n"
-      "@ingroup Console\n");   
-
    // Current script file name and root
    // Current script file name and root
    addVariable( "Con::File", TypeString, &gCurrentFile, "The currently executing script file.\n"
    addVariable( "Con::File", TypeString, &gCurrentFile, "The currently executing script file.\n"
       "@ingroup FileSystem\n");
       "@ingroup FileSystem\n");
@@ -1590,11 +1585,9 @@ ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef ar
       ICallMethod *com = dynamic_cast<ICallMethod *>(object);
       ICallMethod *com = dynamic_cast<ICallMethod *>(object);
       if(com)
       if(com)
       {
       {
-         STR.pushFrame();
-         CSTK.pushFrame();
+         gCallStack.pushFrame(0);
          com->callMethodArgList(argc, argv, false);
          com->callMethodArgList(argc, argv, false);
-         STR.popFrame();
-         CSTK.popFrame();
+         gCallStack.popFrame();
       }
       }
    }
    }
 
 
@@ -2523,70 +2516,20 @@ DefineEngineFunction( logWarning, void, ( const char* message ),,
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 
 
-extern ConsoleValueStack CSTK;
-
-ConsoleValueRef::ConsoleValueRef(const ConsoleValueRef &ref)
-{
-   value = ref.value;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(const ConsoleValueRef &newValue)
-{
-   value = newValue.value;
-   return *this;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(const char *newValue)
-{
-   AssertFatal(value, "value should not be NULL");
-   value->setStringValue(newValue);
-   return *this;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(S32 newValue)
-{
-   AssertFatal(value, "value should not be NULL");
-   value->setIntValue(newValue);
-   return *this;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(U32 newValue)
-{
-   AssertFatal(value, "value should not be NULL");
-   value->setIntValue(newValue);
-   return *this;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(F32 newValue)
-{
-   AssertFatal(value, "value should not be NULL");
-   value->setFloatValue(newValue);
-   return *this;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(F64 newValue)
-{
-   AssertFatal(value, "value should not be NULL");
-   value->setFloatValue(newValue);
-   return *this;
-}
-
-//------------------------------------------------------------------------------
-
-StringStackWrapper::StringStackWrapper(int targc, ConsoleValueRef targv[])
+ConsoleValueToStringArrayWrapper::ConsoleValueToStringArrayWrapper(int targc, ConsoleValue *targv)
 {
 {
    argv = new const char*[targc];
    argv = new const char*[targc];
    argc = targc;
    argc = targc;
 
 
-   for (int i=0; i<targc; i++)
+   for (S32 i = 0; i < targc; i++)
    {
    {
-      argv[i] = dStrdup(targv[i]);
+      argv[i] = dStrdup(targv[i].getString());
    }
    }
 }
 }
 
 
-StringStackWrapper::~StringStackWrapper()
+ConsoleValueToStringArrayWrapper::~ConsoleValueToStringArrayWrapper()
 {
 {
-   for (int i=0; i<argc; i++)
+   for (S32 i = 0; i< argc; i++)
    {
    {
       dFree(argv[i]);
       dFree(argv[i]);
    }
    }
@@ -2594,164 +2537,20 @@ StringStackWrapper::~StringStackWrapper()
 }
 }
 
 
 
 
-StringStackConsoleWrapper::StringStackConsoleWrapper(int targc, const char** targ)
+StringArrayToConsoleValueWrapper::StringArrayToConsoleValueWrapper(int targc, const char** targv)
 {
 {
-   argv = new ConsoleValueRef[targc];
-   argvValue = new ConsoleValue[targc];
+   argv = new ConsoleValue[targc];
    argc = targc;
    argc = targc;
 
 
-   for (int i=0; i<targc; i++) {
-      argvValue[i].init();
-      argv[i].value = &argvValue[i];
-      argvValue[i].setStackStringValue(targ[i]);
-   }
-}
-
-StringStackConsoleWrapper::~StringStackConsoleWrapper()
-{
-   for (int i=0; i<argc; i++)
-   {
-      argv[i] = 0;
-   }
-   delete[] argv;
-   delete[] argvValue;
-}
-
-//------------------------------------------------------------------------------
-
-S32 ConsoleValue::getSignedIntValue()
-{
-   if(type <= TypeInternalString)
-      return (S32)fval;
-   else
-      return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
-}
-
-U32 ConsoleValue::getIntValue()
-{
-   if(type <= TypeInternalString)
-      return ival;
-   else
-      return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
-}
-
-F32 ConsoleValue::getFloatValue()
-{
-   if(type <= TypeInternalString)
-      return fval;
-   else
-      return dAtof(Con::getData(type, dataPtr, 0, enumTable));
-}
-
-const char *ConsoleValue::getStringValue()
-{
-   if(type == TypeInternalString || type == TypeInternalStackString)
-      return sval;
-   else if (type == TypeInternalStringStackPtr)
-      return STR.mBuffer + (uintptr_t)sval;
-   else
-   {
-      // We need a string representation, so lets create one
-      const char *internalValue = NULL;
-
-      if(type == TypeInternalFloat)
-         internalValue = Con::getData(TypeF32, &fval, 0);
-      else if(type == TypeInternalInt)
-         internalValue = Con::getData(TypeS32, &ival, 0);
-      else
-         return Con::getData(type, dataPtr, 0, enumTable); // We can't save sval here since it is the same as dataPtr
-
-      if (!internalValue)
-         return "";
-
-      U32 stringLen = dStrlen(internalValue);
-      U32 newLen = ((stringLen + 1) + 15) & ~15; // pad upto next cache line
-      
-      if (bufferLen == 0)
-         sval = (char *) dMalloc(newLen);
-      else if(newLen > bufferLen)
-         sval = (char *) dRealloc(sval, newLen);
-
-      dStrcpy(sval, internalValue, newLen);
-      bufferLen = newLen;
-
-      return sval;
-   }
-}
-
-StringStackPtr ConsoleValue::getStringStackPtr()
-{
-   if (type == TypeInternalStringStackPtr)
-      return (uintptr_t)sval;
-   else
-      return (uintptr_t)-1;
-}
-
-bool ConsoleValue::getBoolValue()
-{
-   if(type == TypeInternalString || type == TypeInternalStackString || type == TypeInternalStringStackPtr)
-      return dAtob(getStringValue());
-   if(type == TypeInternalFloat)
-      return fval > 0;
-   else if(type == TypeInternalInt)
-      return ival > 0;
-   else {
-      const char *value = Con::getData(type, dataPtr, 0, enumTable);
-      return dAtob(value);
-   }
-}
-
-void ConsoleValue::setIntValue(S32 val)
-{
-   setFloatValue(val);
-}
-
-void ConsoleValue::setIntValue(U32 val)
-{
-   if(type <= TypeInternalString)
-   {
-      fval = (F32)val;
-      ival = val;
-      if(bufferLen > 0)
-      {
-         dFree(sval);
-         bufferLen = 0;
-      }
-
-      sval = typeValueEmpty;
-      type = TypeInternalInt;
-   }
-   else
+   for (int i=0; i<targc; i++)
    {
    {
-      const char *dptr = Con::getData(TypeS32, &val, 0);
-      Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
+      argv[i].setString(targv[i], dStrlen(targv[i]));
    }
    }
 }
 }
 
 
-void ConsoleValue::setBoolValue(bool val)
+StringArrayToConsoleValueWrapper::~StringArrayToConsoleValueWrapper()
 {
 {
-   return setIntValue(val ? 1 : 0);
-}
-
-void ConsoleValue::setFloatValue(F32 val)
-{
-   if(type <= TypeInternalString)
-   {
-      fval = val;
-      ival = static_cast<U32>(val);
-      if(bufferLen > 0)
-      {
-         dFree(sval);
-         bufferLen = 0;
-      }
-      sval = typeValueEmpty;
-      type = TypeInternalFloat;
-   }
-   else
-   {
-      const char *dptr = Con::getData(TypeF32, &val, 0);
-      Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
-   }
+   delete[] argv;
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------

+ 9 - 156
Engine/source/console/consoleInternal.cpp

@@ -183,13 +183,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)->value.type)
+      switch ((*s)->value.getType())
       {
       {
-         case ConsoleValue::TypeInternalInt:
-            dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->value.ival, cat);
+         case ConsoleValueType::cvInteger:
+            dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->value.getInt(), cat);
             break;
             break;
-         case ConsoleValue::TypeInternalFloat:
-            dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->value.fval, cat);
+         case ConsoleValueType::cvFloat:
+            dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->value.getFloat(), cat);
             break;
             break;
          default:
          default:
             expandEscape(expandBuffer, (*s)->getStringValue());
             expandEscape(expandBuffer, (*s)->getStringValue());
@@ -243,13 +243,11 @@ void Dictionary::exportVariables(const char *varString, Vector<String> *names, V
 
 
       if (values)
       if (values)
       {
       {
-         switch ((*s)->value.type)
+         switch ((*s)->value.getType())
          {
          {
-            case ConsoleValue::TypeInternalInt:
-               values->push_back(String::ToString((*s)->value.ival));
-               break;
-            case ConsoleValue::TypeInternalFloat:
-               values->push_back(String::ToString((*s)->value.fval));
+            case ConsoleValueType::cvInteger:
+            case ConsoleValueType::cvFloat:
+               values->push_back(String((*s)->value.getString()));
                break;
                break;
             default:
             default:
                expandEscape(expandBuffer, (*s)->getStringValue());
                expandEscape(expandBuffer, (*s)->getStringValue());
@@ -470,7 +468,6 @@ char *typeValueEmpty = "";
 Dictionary::Entry::Entry(StringTableEntry in_name)
 Dictionary::Entry::Entry(StringTableEntry in_name)
 {
 {
    name = in_name;
    name = in_name;
-   value.type = ConsoleValue::TypeInternalString;
    notify = NULL;
    notify = NULL;
    nextEntry = NULL;
    nextEntry = NULL;
    mUsage = NULL;
    mUsage = NULL;
@@ -508,150 +505,6 @@ const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
    return "";
    return "";
 }
 }
 
 
-void ConsoleValue::setStringValue(const char * value)
-{
-   if (value == NULL) value = typeValueEmpty;
-
-   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
-      // 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;
-      }
-      */
-      if (value == typeValueEmpty)
-      {
-         if (bufferLen > 0)
-         {
-            dFree(sval);
-            bufferLen = 0;
-         }
-
-         sval = typeValueEmpty;
-         fval = 0.f;
-         ival = 0;
-         type = TypeInternalString;
-         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;
-      }
-
-      // may as well pad to the next cache line
-      U32 newLen = ((stringLen + 1) + 15) & ~15;
-
-      if (bufferLen == 0)
-         sval = (char *)dMalloc(newLen);
-      else if (newLen > bufferLen)
-         sval = (char *)dRealloc(sval, newLen);
-
-      type = TypeInternalString;
-
-      bufferLen = newLen;
-      dStrcpy(sval, value, newLen);
-   }
-   else
-      Con::setData(type, dataPtr, 0, 1, &value, enumTable);
-}
-
-
-void ConsoleValue::setStackStringValue(const char *value)
-{
-   if (value == NULL) value = typeValueEmpty;
-
-   if (type <= ConsoleValue::TypeInternalString)
-   {
-      // sval might still be temporarily present so we need to check and free it
-      if (bufferLen > 0)
-      {
-         dFree(sval);
-         bufferLen = 0;
-      }
-
-      if (value == typeValueEmpty)
-      {
-         sval = typeValueEmpty;
-         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 = 0;
-   }
-   else
-      Con::setData(type, dataPtr, 0, 1, &value, enumTable);
-}
-
-void ConsoleValue::setStringStackPtrValue(StringStackPtr ptrValue)
-{
-   if (type <= ConsoleValue::TypeInternalString)
-   {
-      const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
-      if (bufferLen > 0)
-      {
-         dFree(sval);
-         bufferLen = 0;
-      }
-
-      U32 stringLen = dStrlen(value);
-      if (stringLen < 256)
-      {
-         fval = dAtof(value);
-         ival = dAtoi(value);
-      }
-      else
-      {
-         fval = 0.f;
-         ival = 0;
-      }
-
-      type = TypeInternalStringStackPtr;
-      sval = (char*)(value - STR.mBuffer);
-      bufferLen = 0;
-   }
-   else
-   {
-      const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
-      Con::setData(type, dataPtr, 0, 1, &value, enumTable);
-   }
-}
-
 S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid)
 S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid)
 {
 {
    Entry *ent = lookup(name);
    Entry *ent = lookup(name);

+ 57 - 26
Engine/source/console/consoleInternal.h

@@ -324,17 +324,17 @@ public:
 
 
       inline U32 getIntValue()
       inline U32 getIntValue()
       {
       {
-         return value.getIntValue();
+         return value.getInt();
       }
       }
 
 
       inline F32 getFloatValue()
       inline F32 getFloatValue()
       {
       {
-         return value.getFloatValue();
+         return value.getFloat();
       }
       }
 
 
       inline const char *getStringValue()
       inline const char *getStringValue()
       {
       {
-         return value.getStringValue();
+         return value.getString();
       }
       }
 
 
       void setIntValue(U32 val)
       void setIntValue(U32 val)
@@ -345,7 +345,7 @@ public:
             return;
             return;
          }
          }
 
 
-         value.setIntValue(val);
+         value.setInt(val);
 
 
          // Fire off the notification if we have one.
          // Fire off the notification if we have one.
          if (notify)
          if (notify)
@@ -360,23 +360,7 @@ public:
             return;
             return;
          }
          }
 
 
-         value.setFloatValue(val);
-
-         // Fire off the notification if we have one.
-         if (notify)
-            notify->trigger();
-      }
-
-      void setStringStackPtrValue(StringStackPtr newValue)
-      {
-         if (mIsConstant)
-         {
-            Con::errorf("Cannot assign value to constant '%s'.", name);
-            return;
-         }
-
-         value.setStringStackPtrValue(newValue);
-
+         value.setFloat(val);
 
 
          // Fire off the notification if we have one.
          // Fire off the notification if we have one.
          if (notify)
          if (notify)
@@ -391,8 +375,7 @@ public:
             return;
             return;
          }
          }
 
 
-         value.setStringValue(newValue);
-
+         value.setString(newValue, dStrlen(newValue));
 
 
          // Fire off the notification if we have one.
          // Fire off the notification if we have one.
          if (notify)
          if (notify)
@@ -471,6 +454,18 @@ public:
    void validate();
    void validate();
 };
 };
 
 
+struct ConsoleValueFrame
+{
+   ConsoleValue* values;
+   bool isReference;
+
+   ConsoleValueFrame(ConsoleValue* vals, bool isRef)
+   {
+      values = vals;
+      isReference = isRef;
+   }
+};
+
 class ExprEvalState
 class ExprEvalState
 {
 {
 public:
 public:
@@ -499,6 +494,9 @@ public:
    /// an interior pointer that will become invalid when the object changes address.
    /// an interior pointer that will become invalid when the object changes address.
    Vector< Dictionary* > stack;
    Vector< Dictionary* > stack;
 
 
+   Vector< ConsoleValueFrame > localStack;
+   ConsoleValueFrame* currentRegisterArray; // contains array at to top of localStack
+
    ///
    ///
    Dictionary globalVars;
    Dictionary globalVars;
 
 
@@ -511,10 +509,43 @@ public:
    void setIntVariable(S32 val);
    void setIntVariable(S32 val);
    void setFloatVariable(F64 val);
    void setFloatVariable(F64 val);
    void setStringVariable(const char *str);
    void setStringVariable(const char *str);
-   void setStringStackPtrVariable(StringStackPtr str);
-   void setCopyVariable();
 
 
-   void pushFrame(StringTableEntry frameName, Namespace *ns);
+   TORQUE_FORCEINLINE S32 getLocalIntVariable(S32 reg)
+   {
+      return currentRegisterArray->values[reg].getInt();
+   }
+
+   TORQUE_FORCEINLINE F64 getLocalFloatVariable(S32 reg)
+   {
+      return currentRegisterArray->values[reg].getFloat();
+   }
+
+   TORQUE_FORCEINLINE const char* getLocalStringVariable(S32 reg)
+   {
+      return currentRegisterArray->values[reg].getString();
+   }
+
+   TORQUE_FORCEINLINE void setLocalIntVariable(S32 reg, S64 val)
+   {
+      currentRegisterArray->values[reg].setInt(val);
+   }
+
+   TORQUE_FORCEINLINE void setLocalFloatVariable(S32 reg, F64 val)
+   {
+      currentRegisterArray->values[reg].setFloat(val);
+   }
+
+   TORQUE_FORCEINLINE void setLocalStringVariable(S32 reg, const char* val, S32 len)
+   {
+      currentRegisterArray->values[reg].setString(val, len);
+   }
+
+   TORQUE_FORCEINLINE void setLocalStringTableEntryVariable(S32 reg, StringTableEntry val)
+   {
+      currentRegisterArray->values[reg].setStringTableEntry(val);
+   }
+
+   void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount);
    void popFrame();
    void popFrame();
 
 
    /// Puts a reference to an existing stack frame
    /// Puts a reference to an existing stack frame

+ 4 - 4
Engine/source/console/consoleLogger.cpp

@@ -79,18 +79,18 @@ void ConsoleLogger::initPersistFields()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool ConsoleLogger::processArguments( S32 argc, ConsoleValueRef *argv )
+bool ConsoleLogger::processArguments( S32 argc, ConsoleValue *argv )
 {
 {
    if( argc == 0 )
    if( argc == 0 )
       return false;
       return false;
 
 
    bool append = false;
    bool append = false;
 
 
-   if( argc == 2 )
-      append = dAtob( argv[1] );
+   if (argc == 2)
+      append = argv[1].getBool();
 
 
    mAppend = append;
    mAppend = append;
-   mFilename = StringTable->insert( argv[0] );
+   mFilename = StringTable->insert( argv[0].getString() );
 
 
    if( init() )
    if( init() )
    {
    {

+ 1 - 1
Engine/source/console/consoleLogger.h

@@ -81,7 +81,7 @@ class ConsoleLogger : public SimObject
       /// // Example script constructor usage.
       /// // Example script constructor usage.
       /// %obj = new ConsoleLogger( objName, logFileName, [append = false] );
       /// %obj = new ConsoleLogger( objName, logFileName, [append = false] );
       /// @endcode
       /// @endcode
-      bool processArguments( S32 argc, ConsoleValueRef *argv );
+      bool processArguments( S32 argc, ConsoleValue *argv );
 
 
       /// Default constructor, make sure to initalize
       /// Default constructor, make sure to initalize
       ConsoleLogger();
       ConsoleLogger();

+ 121 - 0
Engine/source/console/consoleValueStack.h

@@ -0,0 +1,121 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+// Copyright (c) 2021 TGEMIT Authors & Contributors
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _CONSOLE_CONSOLE_VALUE_STACK_H_
+#define _CONSOLE_CONSOLE_VALUE_STACK_H_
+
+template<S32 StackSize>
+class ConsoleValueStack
+{
+   constexpr static S32 allocatorSize = sizeof(ConsoleValue) * StackSize;
+
+   struct Frame
+   {
+      ConsoleValue* values;
+      S32 count;
+      S32 internalCounter;
+   };
+
+   Vector<Frame> stack;
+   char* memory;
+   S32 sp;
+
+   TORQUE_FORCEINLINE Frame alloc(S32 count)
+   {
+      AssertFatal(sp + count * sizeof(ConsoleValue) < allocatorSize, "ConsoleValueStack overflow");
+
+      ConsoleValue* ret = reinterpret_cast<ConsoleValue*>(memory + sp);
+      sp += count * sizeof(ConsoleValue);
+
+      return { ret, count, 1 };
+   }
+
+   TORQUE_FORCEINLINE void deAlloc(S32 count)
+   {
+      sp -= count * sizeof(ConsoleValue);
+      AssertFatal(sp >= 0, "Popped ConsoleValueStack too far, underflow");
+   }
+
+public:
+   ConsoleValueStack()
+   {
+      memory = (char*)dMalloc(allocatorSize);
+      for (S32 i = 0; i < allocatorSize; i += sizeof(ConsoleValue))
+      {
+         constructInPlace<ConsoleValue>(reinterpret_cast<ConsoleValue*>(memory + i));
+      }
+      sp = 0;
+   }
+
+   ~ConsoleValueStack()
+   {
+      dFree(memory);
+   }
+
+   TORQUE_FORCEINLINE void pushFrame(S32 count)
+   {
+      AssertISV(count >= 0, "Must be >= 0 when pushing stack frame");
+
+      // +1 for function name in argv[0]
+      const Frame& frame = alloc(count + 1);
+      stack.push_back(frame);
+   }
+
+   TORQUE_FORCEINLINE void popFrame()
+   {
+      AssertISV(stack.size() > 0, "Stack Underflow");
+
+      deAlloc(stack.last().count);
+      stack.pop_back();
+   }
+
+   TORQUE_FORCEINLINE void pushInt(S64 value)
+   {
+      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);
+   }
+
+   TORQUE_FORCEINLINE void argvc(StringTableEntry fn, S32& argc, ConsoleValue** argv)
+   {
+      Frame& frame = stack.last();
+      argc = frame.count;
+
+      // First param is always function name
+      frame.values[0].setStringTableEntry(fn);
+      *argv = frame.values;
+   }
+};
+
+#endif

+ 3 - 6
Engine/source/console/sim.h

@@ -125,15 +125,12 @@ namespace Sim
    SimDataBlockGroup *getDataBlockGroup();
    SimDataBlockGroup *getDataBlockGroup();
    SimGroup* getRootGroup();
    SimGroup* getRootGroup();
 
 
-   SimObject* findObject(ConsoleValueRef&);
    SimObject* findObject(SimObjectId);
    SimObject* findObject(SimObjectId);
+   SimObject* findObject(const ConsoleValue&);
+   SimObject* findObject(ConsoleValue*);
    SimObject* findObject(const char* name);
    SimObject* findObject(const char* name);
    SimObject* findObject(const char* fileName, S32 declarationLine);
    SimObject* findObject(const char* fileName, S32 declarationLine);
-   template<class T> inline bool findObject(ConsoleValueRef &ref,T*&t)
-   {
-      t = dynamic_cast<T*>(findObject(ref));
-      return t != NULL;
-   }
+
    template<class T> inline bool findObject(SimObjectId iD,T*&t)
    template<class T> inline bool findObject(SimObjectId iD,T*&t)
    {
    {
       t = dynamic_cast<T*>(findObject(iD));
       t = dynamic_cast<T*>(findObject(iD));

+ 18 - 5
Engine/source/console/simManager.cpp

@@ -328,11 +328,6 @@ SimObject* findObject(const char* fileName, S32 declarationLine)
    return gRootGroup->findObjectByLineNumber(fileName, declarationLine, true);
    return gRootGroup->findObjectByLineNumber(fileName, declarationLine, true);
 }
 }
 
 
-SimObject* findObject(ConsoleValueRef &ref)
-{
-   return findObject((const char*)ref);
-}
-
 SimObject* findObject(const char* name)
 SimObject* findObject(const char* name)
 {
 {
    PROFILE_SCOPE(SimFindObject);
    PROFILE_SCOPE(SimFindObject);
@@ -391,6 +386,24 @@ SimObject* findObject(const char* name)
    return obj->findObject(name + len + 1);
    return obj->findObject(name + len + 1);
 }
 }
 
 
+SimObject* findObject(const ConsoleValue &val)
+{
+   if (val.getType() == ConsoleValueType::cvNone)
+      return NULL;
+   if (val.getType() == ConsoleValueType::cvInteger)
+      return findObject((SimObjectId)val.getInt());
+   return findObject(val.getString());
+}
+
+SimObject* findObject(ConsoleValue* val)
+{
+   if (val->getType() == ConsoleValueType::cvNone)
+      return NULL;
+   if (val->getType() == ConsoleValueType::cvInteger)
+      return findObject((SimObjectId)val->getInt());
+   return findObject(val->getString());
+}
+
 SimObject* findObject(SimObjectId id)
 SimObject* findObject(SimObjectId id)
 {
 {
    return gIdDictionary->find(id);
    return gIdDictionary->find(id);

+ 9 - 3
Engine/source/console/simSet.cpp

@@ -229,11 +229,16 @@ void SimSet::scriptSort( const String &scriptCallbackFn )
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValueRef argv[], bool executeOnChildGroups )
+void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValue argv[], bool executeOnChildGroups )
 {
 {
+   // TODO(JTH): Implement
+   AssertISV(false, "TODO Implement");
+   return;
+
+   /*
    // Prep the arguments for the console exec...
    // Prep the arguments for the console exec...
    // Make sure and leave args[1] empty.
    // Make sure and leave args[1] empty.
-   ConsoleValueRef args[21] = { };
+   ConsoleValue args[21] = { };
    ConsoleValue name_method;
    ConsoleValue name_method;
    name_method.setStackStringValue(method.c_str());
    name_method.setStackStringValue(method.c_str());
    args[0] = ConsoleValueRef::fromValue(&name_method);
    args[0] = ConsoleValueRef::fromValue(&name_method);
@@ -255,6 +260,7 @@ void SimSet::callOnChildren( const String &method, S32 argc, ConsoleValueRef arg
             childSet->callOnChildren( method, argc, argv, executeOnChildGroups );
             childSet->callOnChildren( method, argc, argv, executeOnChildGroups );
       }
       }
    }
    }
+   */
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -838,7 +844,7 @@ SimGroup* SimGroup::deepClone()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool SimGroup::processArguments(S32, ConsoleValueRef *argv)
+bool SimGroup::processArguments(S32, ConsoleValue *argv)
 {
 {
    return true;
    return true;
 }
 }

+ 2 - 2
Engine/source/console/simSet.h

@@ -218,7 +218,7 @@ class SimSet : public SimObject, public TamlChildren
       
       
       /// @}
       /// @}
 
 
-      void callOnChildren( const String &method, S32 argc, ConsoleValueRef argv[], bool executeOnChildGroups = true );
+      void callOnChildren( const String &method, S32 argc, ConsoleValue argv[], bool executeOnChildGroups = true );
 
 
       /// Return the number of objects in this set as well as all sets that are contained
       /// Return the number of objects in this set as well as all sets that are contained
       /// in this set and its children.
       /// in this set and its children.
@@ -464,7 +464,7 @@ class SimGroup: public SimSet
       virtual SimObject* findObject(const char* name);
       virtual SimObject* findObject(const char* name);
       virtual void onRemove();
       virtual void onRemove();
 
 
-      virtual bool processArguments( S32 argc, ConsoleValueRef *argv );
+      virtual bool processArguments( S32 argc, ConsoleValue *argv );
 
 
       virtual SimObject* getObject(const S32& index);
       virtual SimObject* getObject(const S32& index);
 
 

+ 0 - 225
Engine/source/console/stringStack.cpp

@@ -207,228 +207,3 @@ void StringStack::clearFrames()
    mStartStackSize = 0;
    mStartStackSize = 0;
    mFunctionOffset = 0;
    mFunctionOffset = 0;
 }
 }
-
-
-void ConsoleValueStack::getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame /* = false */)
-{
-   U32 startStack = mStackFrames[mFrame-1];
-   U32 argCount   = getMin(mStackPos - startStack, (U32)MaxArgs - 1);
-
-   *in_argv = mArgv;
-   mArgv[0].value = CSTK.pushStackString(name);
-   
-   for(U32 i = 0; i < argCount; i++) {
-      ConsoleValueRef *ref = &mArgv[i+1];
-      ref->value = &mStack[startStack + i];
-   }
-   argCount++;
-   
-   *argc = argCount;
-
-   if(popStackFrame)
-      popFrame();
-}
-
-ConsoleValueStack::ConsoleValueStack() : 
-mFrame(0),
-mStackPos(0)
-{
-   for (int i=0; i<ConsoleValueStack::MaxStackDepth; i++) {
-      mStack[i].init();
-      mStack[i].type = ConsoleValue::TypeInternalString;
-   }
-   dMemset(mStackFrames, 0, sizeof(mStackFrames));
-}
-
-ConsoleValueStack::~ConsoleValueStack()
-{
-}
-
-void ConsoleValueStack::pushVar(ConsoleValue *variable)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return;
-   }
-
-   switch (variable->type)
-   {
-   case ConsoleValue::TypeInternalInt:
-      mStack[mStackPos++].setIntValue((S32)variable->getIntValue());
-   case ConsoleValue::TypeInternalFloat:
-      mStack[mStackPos++].setFloatValue((F32)variable->getFloatValue());
-   default:
-      mStack[mStackPos++].setStackStringValue(variable->getStringValue());
-   }
-}
-
-void ConsoleValueStack::pushValue(ConsoleValue &variable)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return;
-   }
-
-   switch (variable.type)
-   {
-   case ConsoleValue::TypeInternalInt:
-      mStack[mStackPos++].setIntValue((S32)variable.getIntValue());
-   case ConsoleValue::TypeInternalFloat:
-      mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue());
-   case ConsoleValue::TypeInternalStringStackPtr:
-      mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr());
-   default:
-      mStack[mStackPos++].setStringValue(variable.getStringValue());
-   }
-}
-
-ConsoleValue* ConsoleValueStack::reserveValues(U32 count)
-{
-   U32 startPos = mStackPos;
-   if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return NULL;
-   }
-
-   //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
-   mStackPos += count;
-   return &mStack[startPos];
-}
-
-bool ConsoleValueStack::reserveValues(U32 count, ConsoleValueRef *outValues)
-{
-   U32 startPos = mStackPos;
-   if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return false;
-   }
-
-   //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
-   for (U32 i=0; i<count; i++)
-   {
-      outValues[i].value = &mStack[mStackPos+i];
-   }
-   mStackPos += count;
-   return true;
-}
-
-ConsoleValue *ConsoleValueStack::pushString(const char *value)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return NULL;
-   }
-
-   //Con::printf("[%i]CSTK pushString %s", mStackPos, value);
-
-   mStack[mStackPos++].setStringValue(value);
-   return &mStack[mStackPos-1];
-}
-
-ConsoleValue *ConsoleValueStack::pushStackString(const char *value)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return NULL;
-   }
-
-   //Con::printf("[%i]CSTK pushString %s", mStackPos, value);
-
-   mStack[mStackPos++].setStackStringValue(value);
-   return &mStack[mStackPos-1];
-}
-
-ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return NULL;
-   }
-
-   //Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR));
-
-   mStack[mStackPos++].setStringStackPtrValue(value);
-   return &mStack[mStackPos-1];
-}
-
-ConsoleValue *ConsoleValueStack::pushUINT(U32 value)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return NULL;
-   }
-
-   //Con::printf("[%i]CSTK pushUINT %i", mStackPos, value);
-
-   mStack[mStackPos++].setIntValue(value);
-   return &mStack[mStackPos-1];
-}
-
-ConsoleValue *ConsoleValueStack::pushFLT(float value)
-{
-   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return NULL;
-   }
-
-   //Con::printf("[%i]CSTK pushFLT %f", mStackPos, value);
-
-   mStack[mStackPos++].setFloatValue(value);
-   return &mStack[mStackPos-1];
-}
-
-static ConsoleValue gNothing;
-
-ConsoleValue* ConsoleValueStack::pop()
-{
-   if (mStackPos == 0) {
-      AssertFatal(false, "Console Value Stack is empty");
-      return &gNothing;
-   }
-
-   return &mStack[--mStackPos];
-}
-
-void ConsoleValueStack::pushFrame()
-{
-   //Con::printf("CSTK pushFrame[%i] (%i)", mFrame, mStackPos);
-   mStackFrames[mFrame++] = mStackPos;
-}
-
-void ConsoleValueStack::resetFrame()
-{
-   if (mFrame == 0) {
-      mStackPos = 0;
-      return;
-   }
-
-   U32 start = mStackFrames[mFrame-1];
-   //for (U32 i=start; i<mStackPos; i++) {
-      //mStack[i].clear();
-   //}
-   mStackPos = start;
-   //Con::printf("CSTK resetFrame to %i", mStackPos);
-}
-
-void ConsoleValueStack::clearFrames()
-{
-   mStackPos = 0;
-   mFrame = 0;
-}
-
-void ConsoleValueStack::popFrame()
-{
-   //Con::printf("CSTK popFrame");
-   if (mFrame == 0) {
-      // Go back to start
-      mStackPos = 0;
-      return;
-   }
-
-   U32 start = mStackFrames[mFrame-1];
-   //for (U32 i=start; i<mStackPos; i++) {
-      //mStack[i].clear();
-   //}
-   mStackPos = start;
-   mFrame--;
-}

+ 0 - 44
Engine/source/console/stringStack.h

@@ -189,51 +189,7 @@ struct StringStack
    void getArgcArgv(StringTableEntry name, U32 *argc, const char ***in_argv, bool popStackFrame = false);
    void getArgcArgv(StringTableEntry name, U32 *argc, const char ***in_argv, bool popStackFrame = false);
 };
 };
 
 
-
-// New console value stack
-class ConsoleValueStack
-{
-   enum {
-      MaxStackDepth = 1024,
-      MaxArgs = 20,
-      ReturnBufferSpace = 512
-   };
-
-public:
-   ConsoleValueStack();
-   ~ConsoleValueStack();
-
-   void pushVar(ConsoleValue *variable);
-   void pushValue(ConsoleValue &value);
-   ConsoleValue* reserveValues(U32 numValues);
-   bool reserveValues(U32 numValues, ConsoleValueRef *values);
-   ConsoleValue* pop();
-
-   ConsoleValue *pushString(const char *value);
-   ConsoleValue *pushStackString(const char *value);
-   ConsoleValue *pushStringStackPtr(StringStackPtr ptr);
-   ConsoleValue *pushUINT(U32 value);
-   ConsoleValue *pushFLT(float value);
-
-   void pushFrame();
-   void popFrame();
-
-   void resetFrame();
-   void clearFrames();
-
-   void getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame = false);
-
-   ConsoleValue mStack[MaxStackDepth];
-   U32 mStackFrames[MaxStackDepth];
-
-   U32 mFrame;
-   U32 mStackPos;
-
-   ConsoleValueRef mArgv[MaxArgs];
-};
-
 extern StringStack STR;
 extern StringStack STR;
-extern ConsoleValueStack CSTK;
 
 
 inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; }
 inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; }
 
 

+ 2 - 0
Engine/source/console/test/ScriptTest.cpp

@@ -20,6 +20,7 @@
 // IN THE SOFTWARE.
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+#ifdef 0
 #ifdef TORQUE_TESTS_ENABLED
 #ifdef TORQUE_TESTS_ENABLED
 #include "testing/unitTesting.h"
 #include "testing/unitTesting.h"
 #include "platform/platform.h"
 #include "platform/platform.h"
@@ -393,3 +394,4 @@ TEST(Script, Basic_Package)
 }
 }
 
 
 #endif
 #endif
+#endif

+ 3 - 0
Engine/source/console/test/consoleTest.cpp

@@ -1,3 +1,5 @@
+#ifdef 0
+
 #ifdef TORQUE_TESTS_ENABLED
 #ifdef TORQUE_TESTS_ENABLED
 #include "testing/unitTesting.h"
 #include "testing/unitTesting.h"
 #include "platform/platform.h"
 #include "platform/platform.h"
@@ -253,3 +255,4 @@ TEST(Con, execute)
 }
 }
 
 
 #endif
 #endif
+#endif

+ 3 - 1
Engine/source/console/test/engineAPITest.cpp

@@ -1,3 +1,4 @@
+#if 0
 #ifdef TORQUE_TESTS_ENABLED
 #ifdef TORQUE_TESTS_ENABLED
 #include "testing/unitTesting.h"
 #include "testing/unitTesting.h"
 #include "platform/platform.h"
 #include "platform/platform.h"
@@ -147,4 +148,5 @@ TEST(EngineAPI, _EngineConsoleExecCallbackHelper)
 		"All values should be printed in the correct order";
 		"All values should be printed in the correct order";
 }
 }
 
 
-#endif
+#endif
+#endif

+ 5 - 0
Engine/source/core/strings/stringFunctions.h

@@ -200,6 +200,11 @@ inline F64 dAtod(const char *str)
    return strtod(str, NULL);
    return strtod(str, NULL);
 }
 }
 
 
+inline S64 dAtol(const char* str)
+{
+   return strtol(str, NULL, 10);
+}
+
 inline char dToupper(const char c)
 inline char dToupper(const char c)
 {
 {
    return toupper( c );
    return toupper( c );

+ 1 - 1
Engine/source/environment/waterObject.cpp

@@ -411,7 +411,7 @@ void WaterObject::inspectPostApply()
    setMaskBits( UpdateMask | WaveMask | TextureMask | SoundMask );
    setMaskBits( UpdateMask | WaveMask | TextureMask | SoundMask );
 }
 }
 
 
-bool WaterObject::processArguments( S32 argc, ConsoleValueRef *argv )
+bool WaterObject::processArguments( S32 argc, ConsoleValue *argv )
 {
 {
    if( typeid( *this ) == typeid( WaterObject ) )
    if( typeid( *this ) == typeid( WaterObject ) )
    {
    {

+ 1 - 1
Engine/source/environment/waterObject.h

@@ -156,7 +156,7 @@ public:
    virtual bool onAdd();
    virtual bool onAdd();
    virtual void onRemove();
    virtual void onRemove();
    virtual void inspectPostApply();
    virtual void inspectPostApply();
-   virtual bool processArguments(S32 argc, ConsoleValueRef *argv);
+   virtual bool processArguments(S32 argc, ConsoleValue *argv);
 
 
    // NetObject
    // NetObject
    virtual U32  packUpdate( NetConnection * conn, U32 mask, BitStream *stream );
    virtual U32  packUpdate( NetConnection * conn, U32 mask, BitStream *stream );

+ 1 - 1
Engine/source/gui/core/guiControl.cpp

@@ -319,7 +319,7 @@ void GuiControl::initPersistFields()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool GuiControl::processArguments(S32 argc, ConsoleValueRef *argv)
+bool GuiControl::processArguments(S32 argc, ConsoleValue *argv)
 {
 {
    // argv[0] - The GuiGroup to add this control to when it's created.  
    // argv[0] - The GuiGroup to add this control to when it's created.  
    //           this is an optional parameter that may be specified at
    //           this is an optional parameter that may be specified at

+ 1 - 1
Engine/source/gui/core/guiControl.h

@@ -341,7 +341,7 @@ class GuiControl : public SimGroup
       
       
       GuiControl();
       GuiControl();
       virtual ~GuiControl();
       virtual ~GuiControl();
-      virtual bool processArguments(S32 argc, ConsoleValueRef *argv);
+      virtual bool processArguments(S32 argc, ConsoleValue *argv);
       
       
       static void initPersistFields();
       static void initPersistFields();
       static void consoleInit();
       static void consoleInit();

+ 3 - 3
Engine/source/gui/worldEditor/worldEditor.cpp

@@ -2858,17 +2858,17 @@ void WorldEditor::initPersistFields()
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 // These methods are needed for the console interfaces.
 // These methods are needed for the console interfaces.
 
 
-void WorldEditor::ignoreObjClass( U32 argc, ConsoleValueRef *argv )
+void WorldEditor::ignoreObjClass( U32 argc, ConsoleValue *argv )
 {
 {
    for(S32 i = 2; i < argc; i++)
    for(S32 i = 2; i < argc; i++)
    {
    {
-      ClassInfo::Entry * entry = getClassEntry(argv[i]);
+      ClassInfo::Entry * entry = getClassEntry(argv[i].getString());
       if(entry)
       if(entry)
          entry->mIgnoreCollision = true;
          entry->mIgnoreCollision = true;
       else
       else
       {
       {
          entry = new ClassInfo::Entry;
          entry = new ClassInfo::Entry;
-         entry->mName = StringTable->insert(argv[i]);
+         entry->mName = StringTable->insert(argv[i].getString());
          entry->mIgnoreCollision = true;
          entry->mIgnoreCollision = true;
          if(!addClassEntry(entry))
          if(!addClassEntry(entry))
             delete entry;
             delete entry;

+ 1 - 1
Engine/source/gui/worldEditor/worldEditor.h

@@ -76,7 +76,7 @@ class WorldEditor : public EditTSCtrl
          Point3F p2;
          Point3F p2;
       };
       };
 
 
-      void ignoreObjClass(U32 argc, ConsoleValueRef* argv);
+      void ignoreObjClass(U32 argc, ConsoleValue* argv);
       void clearIgnoreList();
       void clearIgnoreList();
 
 
       static bool setObjectsUseBoxCenter( void *object, const char *index, const char *data ) { static_cast<WorldEditor*>(object)->setObjectsUseBoxCenter( dAtob( data ) ); return false; };
       static bool setObjectsUseBoxCenter( void *object, const char *index, const char *data ) { static_cast<WorldEditor*>(object)->setObjectsUseBoxCenter( dAtob( data ) ); return false; };

+ 12 - 7
Engine/source/platformWin32/winMath.cpp

@@ -55,31 +55,36 @@ DefineEngineStringlyVariadicFunction( mathInit, void, 1, 10, "( ... )"
    }
    }
    for (argc--, argv++; argc; argc--, argv++)
    for (argc--, argv++; argc; argc--, argv++)
    {
    {
-      if (dStricmp(*argv, "DETECT") == 0) {
+      const char* str = (*argv).getString();
+      if (dStricmp(str, "DETECT") == 0) {
          Math::init(0);
          Math::init(0);
          return;
          return;
       }
       }
-      if (dStricmp(*argv, "C") == 0) {
+      if (dStricmp(str, "C") == 0) {
          properties |= CPU_PROP_C;
          properties |= CPU_PROP_C;
          continue;
          continue;
       }
       }
-      if (dStricmp(*argv, "FPU") == 0) {
+      if (dStricmp(str, "FPU") == 0) {
          properties |= CPU_PROP_FPU;
          properties |= CPU_PROP_FPU;
          continue;
          continue;
       }
       }
-      if (dStricmp(*argv, "MMX") == 0) {
+      if (dStricmp(str, "MMX") == 0) {
          properties |= CPU_PROP_MMX;
          properties |= CPU_PROP_MMX;
          continue;
          continue;
       }
       }
-      if (dStricmp(*argv, "3DNOW") == 0) {
+      if (dStricmp(str, "3DNOW") == 0) {
          properties |= CPU_PROP_3DNOW;
          properties |= CPU_PROP_3DNOW;
          continue;
          continue;
       }
       }
-      if (dStricmp(*argv, "SSE") == 0) {
+      if (dStricmp(str, "SSE") == 0) {
          properties |= CPU_PROP_SSE;
          properties |= CPU_PROP_SSE;
          continue;
          continue;
       }
       }
-      Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", argv->getStringValue());
+      if (dStricmp(str, "SSE2") == 0) {
+         properties |= CPU_PROP_SSE2;
+         continue;
+      }
+      Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", str);
    }
    }
    Math::init(properties);
    Math::init(properties);
 }
 }

+ 1 - 1
Engine/source/sfx/sfxSource.cpp

@@ -316,7 +316,7 @@ void SFXSource::initPersistFields()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool SFXSource::processArguments( S32 argc, ConsoleValueRef *argv )
+bool SFXSource::processArguments( S32 argc, ConsoleValue *argv )
 {
 {
    // Don't allow subclasses of this to be created via script.  Force
    // Don't allow subclasses of this to be created via script.  Force
    // usage of the SFXSystem functions.
    // usage of the SFXSystem functions.

+ 1 - 1
Engine/source/sfx/sfxSource.h

@@ -382,7 +382,7 @@ class SFXSource : public SimGroup
 
 
       /// We overload this to disable creation of 
       /// We overload this to disable creation of 
       /// a source via script 'new'.
       /// a source via script 'new'.
-      virtual bool processArguments( S32 argc, ConsoleValueRef *argv );
+      virtual bool processArguments( S32 argc, ConsoleValue *argv );
       
       
       // Console getters/setters.
       // Console getters/setters.
       static bool _setDescription( void *obj, const char *index, const char *data );
       static bool _setDescription( void *obj, const char *index, const char *data );

+ 1 - 1
Engine/source/sfx/sfxTrack.cpp

@@ -95,7 +95,7 @@ void SFXTrack::initPersistFields()
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
-bool SFXTrack::processArguments( S32 argc, ConsoleValueRef *argv )
+bool SFXTrack::processArguments( S32 argc, ConsoleValue *argv )
 {
 {
    if( typeid( *this ) == typeid( SFXTrack ) )
    if( typeid( *this ) == typeid( SFXTrack ) )
    {
    {

+ 1 - 1
Engine/source/sfx/sfxTrack.h

@@ -61,7 +61,7 @@ class SFXTrack : public SimDataBlock
       StringTableEntry mParameters[ MaxNumParameters ];
       StringTableEntry mParameters[ MaxNumParameters ];
    
    
       /// Overload this to disable direct instantiation of this class via script 'new'.
       /// Overload this to disable direct instantiation of this class via script 'new'.
-      virtual bool processArguments( S32 argc, ConsoleValueRef *argv );
+      virtual bool processArguments( S32 argc, ConsoleValue *argv );
 
 
    public:
    public:
          
          

+ 3 - 3
Engine/source/shaderGen/GLSL/customFeatureGLSL.cpp

@@ -238,7 +238,7 @@ void CustomFeatureGLSL::addVertTexCoord(String name)
    mVars.push_back(newVarHolder);
    mVars.push_back(newVarHolder);
 }
 }
 
 
-void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValueRef * argv)
+void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValue * argv)
 {
 {
    //do the var/arg fetching here
    //do the var/arg fetching here
    Vector<Var*> varList;
    Vector<Var*> varList;
@@ -246,7 +246,7 @@ void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
 
 
    for (U32 i = 0; i < argc; i++)
    for (U32 i = 0; i < argc; i++)
    {
    {
-      String varName = argv[i].getStringValue();
+      String varName = argv[i].getString();
       Var* newVar = (Var*)LangElement::find(varName.c_str());
       Var* newVar = (Var*)LangElement::find(varName.c_str());
       if (!newVar)
       if (!newVar)
       {
       {
@@ -304,7 +304,7 @@ void CustomFeatureGLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
          if (!newVar)
          if (!newVar)
          {
          {
             //couldn't find that variable, bail out
             //couldn't find that variable, bail out
-            Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getStringValue());
+            Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getString());
             return;
             return;
          }
          }
       }
       }

+ 1 - 1
Engine/source/shaderGen/GLSL/customFeatureGLSL.h

@@ -128,5 +128,5 @@ public:
    void addTexture(String name, String type, String samplerState, U32 arraySize);
    void addTexture(String name, String type, String samplerState, U32 arraySize);
    void addConnector(String name, String type, String elementName);
    void addConnector(String name, String type, String elementName);
    void addVertTexCoord(String name);
    void addVertTexCoord(String name);
-   void writeLine(String format, S32 argc, ConsoleValueRef* argv);
+   void writeLine(String format, S32 argc, ConsoleValue* argv);
 };
 };

+ 3 - 3
Engine/source/shaderGen/HLSL/customFeatureHLSL.cpp

@@ -385,7 +385,7 @@ void CustomFeatureHLSL::addVertTexCoord(String name)
    mVars.push_back(newVarHolder);
    mVars.push_back(newVarHolder);
 }
 }
 
 
-void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef * argv)
+void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValue *argv)
 {
 {
    //do the var/arg fetching here
    //do the var/arg fetching here
    Vector<Var*> varList;
    Vector<Var*> varList;
@@ -393,7 +393,7 @@ void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
 
 
    for (U32 i = 0; i < argc; i++)
    for (U32 i = 0; i < argc; i++)
    {
    {
-      String varName = argv[i].getStringValue();
+      String varName = argv[i].getString();
       Var* newVar = (Var*)LangElement::find(varName.c_str());
       Var* newVar = (Var*)LangElement::find(varName.c_str());
       if (!newVar)
       if (!newVar)
       {
       {
@@ -451,7 +451,7 @@ void CustomFeatureHLSL::writeLine(String format, S32 argc, ConsoleValueRef * arg
          if (!newVar)
          if (!newVar)
          {
          {
             //couldn't find that variable, bail out
             //couldn't find that variable, bail out
-            Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getStringValue());
+            Con::errorf("CustomShaderFeature::writeLine: unable to find variable %s, meaning it was not declared before being used!", argv[i].getString());
             return;
             return;
          }
          }
       }
       }

+ 1 - 1
Engine/source/shaderGen/HLSL/customFeatureHLSL.h

@@ -128,5 +128,5 @@ public:
    void addTexture(String name, String type, String samplerState, U32 arraySize);
    void addTexture(String name, String type, String samplerState, U32 arraySize);
    void addConnector(String name, String type, String elementName);
    void addConnector(String name, String type, String elementName);
    void addVertTexCoord(String name);
    void addVertTexCoord(String name);
-   void writeLine(String format, S32 argc, ConsoleValueRef* argv);
+   void writeLine(String format, S32 argc, ConsoleValue* argv);
 };
 };

+ 1 - 1
Engine/source/shaderGen/customShaderFeature.cpp

@@ -189,7 +189,7 @@ bool CustomShaderFeatureData::hasFeature(String name)
    return false;
    return false;
 }
 }
 
 
-void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValueRef* argv)
+void CustomShaderFeatureData::writeLine(String format, S32 argc, ConsoleValue* argv)
 {
 {
 #ifdef TORQUE_D3D11
 #ifdef TORQUE_D3D11
    if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)
    if (GFX->getAdapterType() == GFXAdapterType::Direct3D11)

+ 1 - 1
Engine/source/shaderGen/customShaderFeature.h

@@ -77,7 +77,7 @@ public:
    void addVertTexCoord(String name);
    void addVertTexCoord(String name);
 	bool hasFeature(String name);
 	bool hasFeature(String name);
 
 
-	void writeLine(String format, S32 argc, ConsoleValueRef *argv);
+	void writeLine(String format, S32 argc, ConsoleValue *argv);
 };
 };
 
 
 #endif
 #endif

Some files were not shown because too many files changed in this diff