ソースを参照

Merge pull request #1004 from lukaspj/console-refactor

Console Refactor
Brian Roberts 2 年 前
コミット
ec8a8290b4
89 ファイル変更1937 行追加1727 行削除
  1. 14 13
      Engine/source/CMakeLists.txt
  2. 3 2
      Engine/source/T3D/assets/CubemapAsset.cpp
  3. 5 4
      Engine/source/T3D/assets/GUIAsset.cpp
  4. 3 2
      Engine/source/T3D/assets/GameObjectAsset.cpp
  5. 3 2
      Engine/source/T3D/assets/MaterialAsset.cpp
  6. 3 2
      Engine/source/T3D/assets/PostEffectAsset.cpp
  7. 4 3
      Engine/source/T3D/assets/ScriptAsset.cpp
  8. 3 2
      Engine/source/T3D/assets/TerrainMaterialAsset.cpp
  9. 2 1
      Engine/source/T3D/prefab.cpp
  10. 1 0
      Engine/source/T3D/trigger.cpp
  11. 2 1
      Engine/source/Verve/Core/VDataTable.cpp
  12. 1 0
      Engine/source/Verve/Extension/Script/VScriptEvent.cpp
  13. 4 5
      Engine/source/afx/afxChoreographer.cpp
  14. 3 2
      Engine/source/afx/arcaneFX.cpp
  15. 3 6
      Engine/source/afx/ea/afxEA_PhraseEffect.cpp
  16. 1 0
      Engine/source/app/mainLoop.cpp
  17. 2 1
      Engine/source/app/net/serverQuery.cpp
  18. 3 2
      Engine/source/cinterface/c_controlInterface.cpp
  19. 0 1
      Engine/source/cinterface/cinterface.cpp
  20. 114 397
      Engine/source/console/console.cpp
  21. 16 26
      Engine/source/console/console.h
  22. 1 3
      Engine/source/console/consoleDoc.cpp
  23. 15 71
      Engine/source/console/consoleFunctions.cpp
  24. 50 272
      Engine/source/console/consoleInternal.cpp
  25. 66 208
      Engine/source/console/consoleInternal.h
  26. 7 8
      Engine/source/console/engineDoc.cpp
  27. 1 3
      Engine/source/console/fileSystemFunctions.cpp
  28. 45 0
      Engine/source/console/module.h
  29. 0 2
      Engine/source/console/propertyParsing.cpp
  30. 112 0
      Engine/source/console/runtime.h
  31. 71 0
      Engine/source/console/script.h
  32. 5 4
      Engine/source/console/scriptFilename.cpp
  33. 4 7
      Engine/source/console/simDatablock.cpp
  34. 1 4
      Engine/source/console/simEvents.cpp
  35. 3 4
      Engine/source/console/simManager.cpp
  36. 4 5
      Engine/source/console/simObject.cpp
  37. 2 1
      Engine/source/console/simObjectMemento.cpp
  38. 72 117
      Engine/source/console/telnetDebugger.cpp
  39. 6 7
      Engine/source/console/telnetDebugger.h
  40. 0 0
      Engine/source/console/torquescript/CMDgram.y
  41. 125 126
      Engine/source/console/torquescript/CMDscan.cpp
  42. 0 0
      Engine/source/console/torquescript/CMDscan.l
  43. 13 5
      Engine/source/console/torquescript/ast.h
  44. 1 1
      Engine/source/console/torquescript/astAlloc.cpp
  45. 3 8
      Engine/source/console/torquescript/astNodes.cpp
  46. 0 0
      Engine/source/console/torquescript/bison.bat
  47. 0 0
      Engine/source/console/torquescript/bison.simple
  48. 2 4
      Engine/source/console/torquescript/cmdgram.cpp
  49. 5 0
      Engine/source/console/torquescript/cmdgram.h
  50. 19 61
      Engine/source/console/torquescript/codeBlock.cpp
  51. 34 39
      Engine/source/console/torquescript/codeBlock.h
  52. 117 171
      Engine/source/console/torquescript/compiledEval.cpp
  53. 6 15
      Engine/source/console/torquescript/compiler.cpp
  54. 6 4
      Engine/source/console/torquescript/compiler.h
  55. 157 0
      Engine/source/console/torquescript/evalState.cpp
  56. 119 0
      Engine/source/console/torquescript/evalState.h
  57. 2 3
      Engine/source/console/torquescript/optimizer.cpp
  58. 0 0
      Engine/source/console/torquescript/parser.cpp
  59. 49 0
      Engine/source/console/torquescript/parser.h
  60. 486 0
      Engine/source/console/torquescript/runtime.cpp
  61. 27 0
      Engine/source/console/torquescript/runtime.h
  62. 0 12
      Engine/source/core/volume.cpp
  63. 0 1
      Engine/source/core/volume.h
  64. 1 0
      Engine/source/gfx/gfxCardProfile.cpp
  65. 1 0
      Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp
  66. 1 0
      Engine/source/gui/controls/guiConsoleTextCtrl.cpp
  67. 1 0
      Engine/source/gui/controls/guiGameListMenuCtrl.cpp
  68. 1 0
      Engine/source/gui/controls/guiGameSettingsCtrl.cpp
  69. 39 38
      Engine/source/gui/controls/guiListBoxCtrl.cpp
  70. 1 0
      Engine/source/gui/controls/guiMLTextEditCtrl.cpp
  71. 2 2
      Engine/source/gui/core/guiControl.cpp
  72. 1 0
      Engine/source/gui/editor/guiEditCtrl.cpp
  73. 1 0
      Engine/source/gui/editor/inspector/dynamicGroup.cpp
  74. 4 2
      Engine/source/gui/editor/inspector/field.cpp
  75. 2 0
      Engine/source/gui/editor/inspector/group.cpp
  76. 2 3
      Engine/source/gui/editor/inspector/variableGroup.cpp
  77. 1 0
      Engine/source/gui/shiny/guiAudioCtrl.cpp
  78. 22 24
      Engine/source/i18n/lang.cpp
  79. 2 0
      Engine/source/postFx/postEffectVis.cpp
  80. 3 1
      Engine/source/sfx/sfxDescription.cpp
  81. 1 0
      Engine/source/sim/actionMap.cpp
  82. 2 1
      Engine/source/testing/ScriptTest.cpp
  83. 7 9
      Engine/source/testing/consoleTest.cpp
  84. 1 0
      Engine/source/testing/engineAPITest.cpp
  85. 1 0
      Engine/source/testing/runtimeClassRepTest.cpp
  86. 8 6
      Engine/source/testing/unitTesting.cpp
  87. 3 2
      Engine/source/ts/tsShape.cpp
  88. 1 1
      Engine/source/windowManager/sdl/sdlWindow.cpp
  89. 2 0
      Engine/source/windowManager/windowInputGenerator.cpp

+ 14 - 13
Engine/source/CMakeLists.txt

@@ -33,12 +33,12 @@ endif (APPLE)
 
 # When on Windows, we need to link against winsock and windows codecs
 if (WIN32)
-	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_WIN_SOURCES})	
+	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_WIN_SOURCES})
 endif (WIN32)
 
 # Linux requires X11 & freetype
 if (UNIX AND NOT APPLE)
-	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_X11_SOURCES})  
+	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_X11_SOURCES})
 	find_package(Freetype REQUIRED)
 	set(TORQUE_INCLUDE_DIRECTORIES ${TORQUE_INCLUDE_DIRECTORIES} ${FREETYPE_INCLUDE_DIRS})
 endif (UNIX AND NOT APPLE)
@@ -50,11 +50,12 @@ torqueAddSourceDirectories("app" "app/net")
 
 # Handle console
 torqueAddSourceDirectories("console")
+torqueAddSourceDirectories("console/torquescript")
 
 # Handle Platform
 torqueAddSourceDirectories("platform" "platform/threads" "platform/async"
                                   "platform/input" "platform/output")
-								  
+
 torqueAddSourceDirectories("platform/nativeDialogs")
 
 # Handle T3D
@@ -291,7 +292,7 @@ endforeach()
 # Prepare Windows RC file
 if (WIN32)
 	set(APPLICATION_ICON_PATH "${CMAKE_SOURCE_DIR}/Tools/CMake/torque.ico")
-	
+
 	configure_file("${CMAKE_SOURCE_DIR}/Tools/CMake/torque-win.rc.in" "${CMAKE_BINARY_DIR}/temp/torque.rc")
 	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} "${CMAKE_BINARY_DIR}/temp/torque.rc")
 endif (WIN32)
@@ -300,7 +301,7 @@ endif (WIN32)
 if (APPLE)
 	set(TORQUE_SOURCE_FILES ${TORQUE_SOURCE_FILES} ${TORQUE_PLATFORM_MAC_SOURCES} "${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns")
 	set_source_files_properties("${CMAKE_SOURCE_DIR}/Tools/CMake/torque.icns" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
-	
+
 	set(EXECUTABLE_NAME "${TORQUE_APP_NAME}")
 	configure_file("${CMAKE_SOURCE_DIR}/Tools/CMake/Info.plist.in" "${CMAKE_BINARY_DIR}/temp/Info.plist" COPYONLY)
 endif (APPLE)
@@ -348,25 +349,25 @@ if (APPLE)
 	set(CMAKE_XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks")
 elseif (WIN32)
 	add_executable(${TORQUE_APP_NAME} WIN32 ${TORQUE_SOURCE_FILES})
-    
+
     set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS /MP /Ob2 /Oi /Ot /Oy /GT /Zi /W4 /nologo /GF /EHsc /GS- /Gy- /Qpar- /fp:precise /fp:except- /GR /Zc:wchar_t-" )
     if( TORQUE_CPU_X32 )
        set(TORQUE_CXX_FLAGS_COMMON_DEFAULT "${TORQUE_CXX_FLAGS_COMMON_DEFAULT} /arch:SSE2")
     endif()
     set(TORQUE_CXX_FLAGS_COMMON ${TORQUE_CXX_FLAGS_COMMON_DEFAULT} CACHE STRING "")
     mark_as_advanced(TORQUE_CXX_FLAGS_COMMON)
-	
+
     set(TORQUE_CXX_FLAGS_EXECUTABLES "/wd4018 /wd4100 /wd4121 /wd4127 /wd4130 /wd4244 /wd4245 /wd4389 /wd4511 /wd4512 /wd4800 /wd4995" CACHE STRING "")
     mark_as_advanced(TORQUE_CXX_FLAGS_EXECUTABLES)
-    
+
     set(TORQUE_CXX_FLAGS "${TORQUE_CXX_FLAGS_COMMON_DEFAULT} ${TORQUE_CXX_FLAGS_EXECUTABLES}" CACHE STRING "")
     mark_as_advanced(TORQUE_CXX_FLAGS)
-    
+
 	# NOTE: On Windows, /Zc:wchar_t- is necessary otherwise you get unicode errors
 	set_target_properties(${TORQUE_APP_NAME} PROPERTIES COMPILE_FLAGS "${TORQUE_CXX_FLAGS}")
 else()
 	add_executable(${TORQUE_APP_NAME} ${TORQUE_SOURCE_FILES})
-	
+
 	# NOTE: On Linux, we set the rpath to ./ so that shared objects next to the executable are used
 	set_target_properties(${TORQUE_APP_NAME} PROPERTIES LINK_FLAGS "-Wl,-rpath,./")
 endif()
@@ -423,9 +424,9 @@ if (UNIX)
 	  # For eg. OSX some links are not valid targets - for example frameworks provided by OS
 	  if (TARGET ${GAME_LINK_LIBRARY})
 		  get_target_property(LINK_LIBRARY_TYPE ${GAME_LINK_LIBRARY} TYPE)
-			
+
 		  # Only pay attention to shared libraries and make them output to the app resources
-		  if ("${LINK_LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")	 
+		  if ("${LINK_LIBRARY_TYPE}" STREQUAL "SHARED_LIBRARY")
         if (APPLE)
           set_target_properties(${GAME_LINK_LIBRARY} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${TORQUE_APP_GAME_DIRECTORY}/${TORQUE_APP_NAME}.app/Contents/Frameworks")
         else()
@@ -434,4 +435,4 @@ if (UNIX)
 		  endif()
 	  endif()
 	endforeach()
-endif (UNIX)
+endif (UNIX)

+ 3 - 2
Engine/source/T3D/assets/CubemapAsset.cpp

@@ -41,6 +41,7 @@
 #endif
 
 // Debug Profiling.
+#include "console/script.h"
 #include "platform/profiler.h"
 
 //-----------------------------------------------------------------------------
@@ -140,7 +141,7 @@ void CubemapAsset::initializeAsset()
 
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 }
 
@@ -148,7 +149,7 @@ void CubemapAsset::onAssetRefresh()
 {
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 }
 

+ 5 - 4
Engine/source/T3D/assets/GUIAsset.cpp

@@ -41,6 +41,7 @@
 #endif
 
 // Debug Profiling.
+#include "console/script.h"
 #include "platform/profiler.h"
 
 //-----------------------------------------------------------------------------
@@ -118,12 +119,12 @@ void GUIAsset::initializeAsset()
 {
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 
    mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
 
-   if (Torque::FS::IsScriptFile(mGUIPath))
+   if (Con::isScriptFile(mGUIPath))
       Con::executeFile(mGUIPath, false, false);
 }
 
@@ -131,12 +132,12 @@ void GUIAsset::onAssetRefresh()
 {
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 
    mGUIPath = getOwned() ? expandAssetFilePath(mGUIFile) : mGUIPath;
 
-   if (Torque::FS::IsScriptFile(mGUIPath))
+   if (Con::isScriptFile(mGUIPath))
       Con::executeFile(mGUIPath, false, false);
 }
 

+ 3 - 2
Engine/source/T3D/assets/GameObjectAsset.cpp

@@ -41,6 +41,7 @@
 #endif
 
 // Debug Profiling.
+#include "console/script.h"
 #include "platform/profiler.h"
 
 //-----------------------------------------------------------------------------
@@ -134,7 +135,7 @@ void GameObjectAsset::initializeAsset()
    //Ensure we have an expanded filepath
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 
    mTAMLPath = getOwned() ? expandAssetFilePath(mTAMLFile) : mTAMLPath;
@@ -145,7 +146,7 @@ void GameObjectAsset::onAssetRefresh()
    //Ensure we have an expanded filepath
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 
    mTAMLPath = getOwned() ? expandAssetFilePath(mTAMLFile) : mTAMLPath;

+ 3 - 2
Engine/source/T3D/assets/MaterialAsset.cpp

@@ -40,6 +40,7 @@
 #include "assets/assetPtr.h"
 #endif
 
+#include "console/script.h"
 #include "T3D/assets/assetImporter.h"
 
 StringTableEntry MaterialAsset::smNoMaterialAssetFallback = NULL;
@@ -179,7 +180,7 @@ void MaterialAsset::initializeAsset()
    {
       mLoadedState = EmbeddedDefinition;
    }
-   else if (Torque::FS::IsScriptFile(mScriptPath))
+   else if (Con::isScriptFile(mScriptPath))
    {
       if (!Sim::findObject(mMatDefinitionName))
       {
@@ -211,7 +212,7 @@ void MaterialAsset::onAssetRefresh()
       return;
    }
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
    {
       //Since we're refreshing, we can assume that the file we're executing WILL have an existing definition.
       //But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior

+ 3 - 2
Engine/source/T3D/assets/PostEffectAsset.cpp

@@ -41,6 +41,7 @@
 #endif
 
 // Debug Profiling.
+#include "console/script.h"
 #include "platform/profiler.h"
 
 //-----------------------------------------------------------------------------
@@ -137,7 +138,7 @@ void PostEffectAsset::initializeAsset()
    mHLSLShaderPath = getOwned() ? expandAssetFilePath(mHLSLShaderFile) : mHLSLShaderPath;
    mGLSLShaderPath = getOwned() ? expandAssetFilePath(mGLSLShaderFile) : mGLSLShaderPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 }
 
@@ -147,7 +148,7 @@ void PostEffectAsset::onAssetRefresh()
    mHLSLShaderPath = getOwned() ? expandAssetFilePath(mHLSLShaderFile) : mHLSLShaderPath;
    mGLSLShaderPath = getOwned() ? expandAssetFilePath(mGLSLShaderFile) : mGLSLShaderPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
       Con::executeFile(mScriptPath, false, false);
 }
 

+ 4 - 3
Engine/source/T3D/assets/ScriptAsset.cpp

@@ -40,6 +40,7 @@
 #endif
 
 // Debug Profiling.
+#include "console/script.h"
 #include "platform/profiler.h"
 
 //-----------------------------------------------------------------------------
@@ -140,7 +141,7 @@ void ScriptAsset::initializeAsset()
 
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
    {
       //We're initialized properly, so we'll go ahead and kick along any dependencies we may have as well
       AssetManager::typeAssetDependsOnHash::Iterator assetDependenciesItr = mpOwningAssetManager->getDependedOnAssets()->find(mpAssetDefinition->mAssetId);
@@ -170,7 +171,7 @@ void ScriptAsset::onAssetRefresh()
 {
    mScriptPath = getOwned() ? expandAssetFilePath(mScriptFile) : mScriptPath;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
    {
       //Refresh any dependencies we may have
       for (U32 i = 0; i < mScriptAssetDependencies.size(); i++)
@@ -215,7 +216,7 @@ bool ScriptAsset::execScript()
    if (handle)
       return true;
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
    {
       return Con::executeFile(mScriptPath, false, false);
    }

+ 3 - 2
Engine/source/T3D/assets/TerrainMaterialAsset.cpp

@@ -40,6 +40,7 @@
 #include "assets/assetPtr.h"
 #endif
 
+#include "console/script.h"
 #include "T3D/assets/assetImporter.h"
 
 StringTableEntry TerrainMaterialAsset::smNoTerrainMaterialAssetFallback = NULL;
@@ -182,7 +183,7 @@ void TerrainMaterialAsset::initializeAsset()
    {
       mLoadedState = EmbeddedDefinition;
    }
-   else if (Torque::FS::IsScriptFile(mScriptPath))
+   else if (Con::isScriptFile(mScriptPath))
    {
       if (!Sim::findObject(mMatDefinitionName))
       {
@@ -214,7 +215,7 @@ void TerrainMaterialAsset::onAssetRefresh()
          return;
       }
 
-   if (Torque::FS::IsScriptFile(mScriptPath))
+   if (Con::isScriptFile(mScriptPath))
    {
       //Since we're refreshing, we can assume that the file we're executing WILL have an existing definition.
       //But that definition, whatever it is, is the 'correct' one, so we enable the Replace Existing behavior

+ 2 - 1
Engine/source/T3D/prefab.cpp

@@ -31,6 +31,7 @@
 #include "console/consoleTypes.h"
 #include "core/volume.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "T3D/physics/physicsShape.h"
 #include "core/util/path.h"
 
@@ -344,7 +345,7 @@ void Prefab::_loadFile( bool addFileNotify )
    if ( mFilename == StringTable->EmptyString())
       return;
 
-   if ( !Torque::FS::IsScriptFile( mFilename ) )
+   if ( !Con::isScriptFile( mFilename ) )
    {
       Con::errorf( "Prefab::_loadFile() - file %s was not found.", mFilename );
       return;

+ 1 - 0
Engine/source/T3D/trigger.cpp

@@ -27,6 +27,7 @@
 #include "console/consoleTypes.h"
 #include "console/engineAPI.h"
 #include "collision/boxConvex.h"
+#include "console/script.h"
 
 #include "core/stream/bitStream.h"
 #include "math/mathIO.h"

+ 2 - 1
Engine/source/Verve/Core/VDataTable.cpp

@@ -22,6 +22,7 @@
 //-----------------------------------------------------------------------------
 #include "Verve/Core/VDataTable.h"
 
+#include "console/script.h"
 #include "console/simObject.h"
 
 //-----------------------------------------------------------------------------
@@ -228,7 +229,7 @@ bool VDataTable::getValue( SimObject *pObject, const String &pFieldName, String
         case VDataTable::k_TypeExpression :
             {
                 // Evaluate.
-                pValue = Con::evaluate( fieldValue, false ).getString();
+                pValue = Con::evaluate( fieldValue, false ).value.getString();
 
             } break;
 

+ 1 - 0
Engine/source/Verve/Extension/Script/VScriptEvent.cpp

@@ -26,6 +26,7 @@
 #include "Verve/Extension/Script/VScriptEvent.h"
 
 #include "console/consoleTypes.h"
+#include "console/script.h"
 
 //-----------------------------------------------------------------------------
 IMPLEMENT_CONOBJECT( VScriptEvent );

+ 4 - 5
Engine/source/afx/afxChoreographer.cpp

@@ -26,9 +26,9 @@
 #include "afx/arcaneFX.h"
 
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "T3D/gameBase/gameConnection.h"
 #include "math/mathIO.h"
-#include "console/compiler.h"
 
 #include "afx/afxConstraint.h"
 #include "afx/afxChoreographer.h"
@@ -108,12 +108,11 @@ bool afxChoreographerData::preload(bool server, String &errorStr)
 
   if (!server && client_script_file != ST_NULLSTRING)
   {
-    Compiler::gSyntaxError = false;
-    Con::evaluate(avar("exec(\"%s\");", client_script_file), false, 0);
-    if (Compiler::gSyntaxError)
+     Con::EvalResult result = Con::evaluate(avar("exec(\"%s\");", client_script_file), false, 0);
+
+    if (!result.valid)
     {
       Con::errorf("afxChoreographerData: failed to exec clientScriptFile \"%s\" -- syntax error", client_script_file);
-      Compiler::gSyntaxError = false;
     }
   }
 

+ 3 - 2
Engine/source/afx/arcaneFX.cpp

@@ -31,8 +31,9 @@
 #include "T3D/gameBase/gameProcess.h"
 #include "T3D/player.h"
 #include "math/mathUtils.h"
-#include "console/compiler.h"
+
 #include "console/engineAPI.h"
+#include "console/script.h"
 
 #include "afx/afxChoreographer.h"
 #include "afx/afxSelectron.h"
@@ -672,7 +673,7 @@ DefineEngineFunction(wasSyntaxError, bool, (),,
                      "for detecting syntax errors after reloading a script.\n\n"
                      "@ingroup AFX")
 {
-  return Compiler::gSyntaxError;
+   return Con::getLastEvalResult().valid == false;
 }
 
 //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//

+ 3 - 6
Engine/source/afx/ea/afxEA_PhraseEffect.cpp

@@ -26,8 +26,8 @@
 #include <typeinfo>
 #include "afx/arcaneFX.h"
 
-#include "console/compiler.h"
 #include "T3D/player.h"
+#include "console/script.h"
 
 #include "afx/afxEffectDefs.h"
 #include "afx/afxPhrase.h"
@@ -314,13 +314,10 @@ void afxEA_PhraseEffect::trigger_new_phrase()
     }
     b[0] = '\0';
 
-    Compiler::gSyntaxError = false;
-    //Con::errorf("EVAL [%s]", avar("%s;", buffer));
-    Con::evaluate(avar("%s;", buffer), false, 0);
-    if (Compiler::gSyntaxError)
+    Con::EvalResult result = Con::evaluate(avar("%s;", buffer), false, 0);
+    if (!result.valid)
     {
       Con::errorf("onTriggerCommand \"%s\" -- syntax error", phrase_fx_data->on_trig_cmd);
-      Compiler::gSyntaxError = false;
     }
   }
 

+ 1 - 0
Engine/source/app/mainLoop.cpp

@@ -61,6 +61,7 @@
 // For the TickMs define... fix this for T2D...
 #include "T3D/gameBase/processList.h"
 #include "cinterface/cinterface.h"
+#include "console/script.h"
 
 #ifdef TORQUE_ENABLE_VFS
 #include "platform/platformVFS.h"

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

@@ -107,6 +107,7 @@
 #include "sim/netInterface.h"
 
 // cafTODO: breaks T2D
+#include "console/script.h"
 #include "T3D/gameBase/gameConnection.h"
 
 // This is basically the server query protocol version now:
@@ -2020,7 +2021,7 @@ static void handleGameInfoRequest( const NetAddress* address, U32 key, U8 flags
          out->writeString( Con::getVariable( "pref::Server::Info" ) );
       else
          writeCString( out, Con::getVariable( "pref::Server::Info" ) );
-      writeLongCString( out, Con::evaluate( "onServerInfoQuery();" ) );
+      writeLongCString( out, Con::executef( "onServerInfoQuery" ) );
 
       BitStream::sendPacketStream(address);
    }

+ 3 - 2
Engine/source/cinterface/c_controlInterface.cpp

@@ -23,6 +23,7 @@
 #include "c_controlInterface.h"
 
 #include "console/consoleInternal.h"
+#include "console/engineAPI.h"
 #include "console/simSet.h"
 #include "app/mainLoop.h"
 #include "windowManager/platformWindow.h"
@@ -50,7 +51,7 @@ extern "C" {
    // reset the engine, unloading any current level and returning to the main menu
    void torque_reset()
    {
-      Con::evaluate("disconnect();");
+      Con::executef("disconnect");
    }
 
    // initialize Torque 3D including argument handling
@@ -119,7 +120,7 @@ extern "C" {
    // signal an engine shutdown (as with the quit(); console command)
    void torque_enginesignalshutdown()
    {
-      Con::evaluate("quit();");
+      Con::executef("quit");
    }
 
    // shutdown the engine

+ 0 - 1
Engine/source/cinterface/cinterface.cpp

@@ -21,7 +21,6 @@
 //-----------------------------------------------------------------------------
 #include "cinterface.h"
 
-#include "console/compiler.h"
 #include "windowManager/platformWindow.h"
 
 CInterface& CInterface::GetCInterface()

+ 114 - 397
Engine/source/console/console.cpp

@@ -28,16 +28,16 @@
 #include "console/consoleObject.h"
 #include "console/consoleParser.h"
 #include "core/stream/fileStream.h"
-#include "console/ast.h"
 #include "core/tAlgorithm.h"
 #include "console/consoleTypes.h"
 #include "console/telnetDebugger.h"
 #include "console/simBase.h"
-#include "console/compiler.h"
 #include "console/stringStack.h"
 #include "console/ICallMethod.h"
 #include "console/engineAPI.h"
 #include <stdarg.h>
+
+#include "returnBuffer.h"
 #include "platform/threads/mutex.h"
 #include "core/util/journal/journal.h"
 #include "cinterface/cinterface.h"
@@ -72,13 +72,10 @@ char* ConsoleValue::convertToBuffer() const
 
 const char* ConsoleValue::getConsoleData() const
 {
-   return Con::getData(type, ct->dataPtr, 0, ct->enumTable);
+   return Con::getData(ct->consoleType, ct->dataPtr, 0, ct->enumTable);
 }
 
 ConsoleDocFragment* ConsoleDocFragment::smFirst;
-ExprEvalState gEvalState;
-StmtNode *gStatementList;
-StmtNode *gAnonFunctionList;
 U32 gAnonFunctionID = 0;
 ConsoleConstructor *ConsoleConstructor::mFirst = NULL;
 bool gWarnUndefinedScriptVariables;
@@ -565,7 +562,7 @@ U32 tabComplete(char* inputBuffer, U32 cursorPos, U32 maxResultLength, bool forw
       // In the global namespace, we can complete on global vars as well as functions.
       if (inputBuffer[completionBaseStart] == '$')
       {
-         newText = gEvalState.globalVars.tabComplete(inputBuffer + completionBaseStart, completionBaseLen, forwardTab);
+         newText = gGlobalVars.tabComplete(inputBuffer + completionBaseStart, completionBaseLen, forwardTab);
       }
       else 
       {
@@ -665,9 +662,9 @@ static void _printf(ConsoleLogEntry::Level level, ConsoleLogEntry::Type type, co
 
    char buffer[8192] = {};
    U32 offset = 0;
-   if( gEvalState.traceOn && gEvalState.getStackDepth() > 0 )
+   if( gTraceOn && !getFrameStack().empty())
    {
-      offset = gEvalState.getStackDepth() * 3;
+      offset = getFrameStack().size() * 3;
       for(U32 i = 0; i < offset; i++)
          buffer[i] = ' ';
    }
@@ -831,41 +828,25 @@ bool getVariableObjectField(const char *name, SimObject **object, const char **f
    return false;
 }
 
-Dictionary::Entry *getLocalVariableEntry(const char *name)
-{
-   name = prependPercent(name);
-   return gEvalState.getCurrentFrame().lookup(StringTable->insert(name));
-}
-
 Dictionary::Entry *getVariableEntry(const char *name)
 {
    name = prependDollar(name);
-   return gEvalState.globalVars.lookup(StringTable->insert(name));
+   return gGlobalVars.lookup(StringTable->insert(name));
 }
 
 Dictionary::Entry *addVariableEntry(const char *name)
 {
    name = prependDollar(name);
-   return gEvalState.globalVars.add(StringTable->insert(name));
+   return gGlobalVars.add(StringTable->insert(name));
 }
 
 Dictionary::Entry *getAddVariableEntry(const char *name)
 {
    name = prependDollar(name);
    StringTableEntry stName = StringTable->insert(name);
-   Dictionary::Entry *entry = gEvalState.globalVars.lookup(stName);
+   Dictionary::Entry *entry = gGlobalVars.lookup(stName);
    if (!entry)
-      entry = gEvalState.globalVars.add(stName);
-   return entry;
-}
-
-Dictionary::Entry *getAddLocalVariableEntry(const char *name)
-{
-   name = prependPercent(name);
-   StringTableEntry stName = StringTable->insert(name);
-   Dictionary::Entry *entry = gEvalState.getCurrentFrame().lookup(stName);
-   if (!entry)
-      entry = gEvalState.getCurrentFrame().add(stName);
+      entry = gGlobalVars.add(stName);
    return entry;
 }
 
@@ -881,7 +862,7 @@ void setVariable(const char *name, const char *value)
    else 
    {
       name = prependDollar(name);
-      gEvalState.globalVars.setVariable(StringTable->insert(name), value);
+      gGlobalVars.setVariable(StringTable->insert(name), value);
    }
 }
 
@@ -988,7 +969,7 @@ void stripColorChars(char* line)
    }
 }
 
-// 
+//
 const char *getObjectTokenField(const char *name)
 {
    const char *dot = dStrchr(name, '.');
@@ -1046,7 +1027,7 @@ const char *getLocalVariable(const char *name)
 {
    name = prependPercent(name);
 
-   return gEvalState.getCurrentFrame().getVariable(StringTable->insert(name));
+   return Con::getCurrentStackFrame()->getVariable(StringTable->insert(name));
 }
 
 bool getBoolVariable(const char *varName, bool def)
@@ -1099,7 +1080,7 @@ void addVariable(    const char *name,
                      void *dptr, 
                      const char* usage )
 {
-   gEvalState.globalVars.addVariable( name, type, dptr, usage );
+   gGlobalVars.addVariable( name, type, dptr, usage );
 }
 
 void addConstant(    const char *name, 
@@ -1107,24 +1088,24 @@ void addConstant(    const char *name,
                      const void *dptr, 
                      const char* usage )
 {
-   Dictionary::Entry* entry = gEvalState.globalVars.addVariable( name, type, const_cast< void* >( dptr ), usage );
+   Dictionary::Entry* entry = gGlobalVars.addVariable( name, type, const_cast< void* >( dptr ), usage );
    entry->mIsConstant = true;
 }
 
 bool removeVariable(const char *name)
 {
    name = StringTable->lookup(prependDollar(name));
-   return name!=0 && gEvalState.globalVars.removeVariable(name);
+   return name!=0 && gGlobalVars.removeVariable(name);
 }
 
 void addVariableNotify( const char *name, const NotifyDelegate &callback )
 {
-   gEvalState.globalVars.addVariableNotify( name, callback );
+   gGlobalVars.addVariableNotify( name, callback );
 }
 
 void removeVariableNotify( const char *name, const NotifyDelegate &callback )
 {
-   gEvalState.globalVars.removeVariableNotify( name, callback );
+   gGlobalVars.removeVariableNotify( name, callback );
 }
 
 //---------------------------------------------------------------------------
@@ -1206,359 +1187,6 @@ void addCommand( const char *name,BoolCallback cb,const char *usage, S32 minArgs
    Namespace::global()->addCommand( StringTable->insert(name), cb, usage, minArgs, maxArgs, isToolOnly, header );
 }
 
-bool executeFile(const char* fileName, bool noCalls, bool journalScript)
-{
-   bool journal = false;
-
-   char scriptFilenameBuffer[1024];
-   U32 execDepth = 0;
-   U32 journalDepth = 1;
-
-   execDepth++;
-   if (journalDepth >= execDepth)
-      journalDepth = execDepth + 1;
-   else
-      journal = true;
-
-   bool ret = false;
-
-   if (journalScript && !journal)
-   {
-      journal = true;
-      journalDepth = execDepth;
-   }
-
-   // Determine the filename we actually want...
-   Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), fileName);
-
-   // since this function expects a script file reference, if it's a .dso
-   // lets terminate the string before the dso so it will act like a .tscript
-   if (dStrEndsWith(scriptFilenameBuffer, ".dso"))
-   {
-      scriptFilenameBuffer[dStrlen(scriptFilenameBuffer) - dStrlen(".dso")] = '\0';
-   }
-
-   // Figure out where to put DSOs
-   StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
-
-   const char *ext = dStrrchr(scriptFilenameBuffer, '.');
-
-   if (!ext)
-   {
-      // Try appending the default script extension and see if that succeeds
-
-      if (executeFile(fileName + String("." TORQUE_SCRIPT_EXTENSION), noCalls, journalScript))
-      {
-         return true;
-      }
-
-      // We need an extension!
-      Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file name %s.", scriptFilenameBuffer);
-      execDepth--;
-      return false;
-   }
-
-   // Check Editor Extensions
-   bool isEditorScript = false;
-
-   // If the script file extension is '.ed.tscript' then compile it to a different compiled extension
-   if (dStricmp(ext, "." TORQUE_SCRIPT_EXTENSION) == 0)
-   {
-      const char* ext2 = ext - 3;
-      if (dStricmp(ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0)
-         isEditorScript = true;
-   }
-   else if (dStricmp(ext, ".gui") == 0)
-   {
-      const char* ext2 = ext - 3;
-      if (dStricmp(ext2, ".ed.gui") == 0)
-         isEditorScript = true;
-   }
-
-   StringTableEntry scriptFileName = StringTable->insert(scriptFilenameBuffer);
-
-   // Is this a file we should compile? (anything in the prefs path should not be compiled)
-   StringTableEntry prefsPath = Platform::getPrefsPath();
-   bool compiled = dStricmp(ext, ".mis") && !journal && !Con::getBoolVariable("Scripts::ignoreDSOs");
-
-   // [tom, 12/5/2006] stripBasePath() fucks up if the filename is not in the exe
-   // path, current directory or prefs path. Thus, getDSOFilename() will also screw
-   // up and so this allows the scripts to still load but without a DSO.
-   if (Platform::isFullPath(Platform::stripBasePath(scriptFilenameBuffer)))
-      compiled = false;
-
-   // [tom, 11/17/2006] It seems to make sense to not compile scripts that are in the
-   // prefs directory. However, getDSOPath() can handle this situation and will put
-   // the dso along with the script to avoid name clashes with tools/game dsos.
-   if ((dsoPath && *dsoPath == 0) || (prefsPath && prefsPath[0] && dStrnicmp(scriptFileName, prefsPath, dStrlen(prefsPath)) == 0))
-      compiled = false;
-
-   // If we're in a journaling mode, then we will read the script
-   // from the journal file.
-   if (journal && Journal::IsPlaying())
-   {
-      char fileNameBuf[256];
-      bool fileRead = false;
-      U32 fileSize;
-
-      Journal::ReadString(fileNameBuf);
-      Journal::Read(&fileRead);
-
-      if (!fileRead)
-      {
-         Con::errorf(ConsoleLogEntry::Script, "Journal script read (failed) for %s", fileNameBuf);
-         execDepth--;
-         return false;
-      }
-      Journal::Read(&fileSize);
-      char *script = new char[fileSize + 1];
-      Journal::Read(fileSize, script);
-      script[fileSize] = 0;
-      Con::printf("Executing (journal-read) %s.", scriptFileName);
-      CodeBlock *newCodeBlock = new CodeBlock();
-      newCodeBlock->compileExec(scriptFileName, script, noCalls, 0);
-      delete[] script;
-      delete newCodeBlock;
-      
-      execDepth--;
-      return true;
-   }
-
-   // Ok, we let's try to load and compile the script.
-   Torque::FS::FileNodeRef scriptFile = Torque::FS::GetFileNode(scriptFileName);
-   Torque::FS::FileNodeRef dsoFile;
-
-   //    ResourceObject *rScr = gResourceManager->find(scriptFileName);
-   //    ResourceObject *rCom = NULL;
-
-   char nameBuffer[512];
-   char* script = NULL;
-   U32 version;
-
-   Stream *compiledStream = NULL;
-   Torque::Time scriptModifiedTime, dsoModifiedTime;
-
-   // Check here for .edso
-   bool edso = false;
-   if (dStricmp(ext, ".edso") == 0 && scriptFile != NULL)
-   {
-      edso = true;
-      dsoFile = scriptFile;
-      scriptFile = NULL;
-
-      dsoModifiedTime = dsoFile->getModifiedTime();
-      dStrcpy(nameBuffer, scriptFileName, 512);
-   }
-
-   // If we're supposed to be compiling this file, check to see if there's a DSO
-   if (compiled && !edso)
-   {
-      const char *filenameOnly = dStrrchr(scriptFileName, '/');
-      if (filenameOnly)
-         ++filenameOnly;
-      else
-         filenameOnly = scriptFileName;
-
-      char pathAndFilename[1024];
-      Platform::makeFullPathName(filenameOnly, pathAndFilename, sizeof(pathAndFilename), dsoPath);
-
-      if (isEditorScript)
-         dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".edso", NULL);
-      else
-         dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".dso", NULL);
-
-      dsoFile = Torque::FS::GetFileNode(nameBuffer);
-
-      if (scriptFile != NULL)
-         scriptModifiedTime = scriptFile->getModifiedTime();
-
-      if (dsoFile != NULL)
-         dsoModifiedTime = dsoFile->getModifiedTime();
-   }
-
-   // Let's do a sanity check to complain about DSOs in the future.
-   //
-   // MM:   This doesn't seem to be working correctly for now so let's just not issue
-   //    the warning until someone knows how to resolve it.
-   //
-   //if(compiled && rCom && rScr && Platform::compareFileTimes(comModifyTime, scrModifyTime) < 0)
-   //{
-   //Con::warnf("exec: Warning! Found a DSO from the future! (%s)", nameBuffer);
-   //}
-
-   // If we had a DSO, let's check to see if we should be reading from it.
-   //MGT: fixed bug with dsos not getting recompiled correctly
-   //Note: Using Nathan Martin's version from the forums since its easier to read and understand
-   if (compiled && dsoFile != NULL && (scriptFile == NULL || (dsoModifiedTime >= scriptModifiedTime)))
-   { //MGT: end
-      compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
-      if (compiledStream)
-      {
-         // Check the version!
-         compiledStream->read(&version);
-         if (version != Con::DSOVersion)
-         {
-            Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, Con::DSOVersion);
-            delete compiledStream;
-            compiledStream = NULL;
-         }
-      }
-   }
-
-   // If we're journalling, let's write some info out.
-   if (journal && Journal::IsRecording())
-      Journal::WriteString(scriptFileName);
-
-   if (scriptFile != NULL && !compiledStream)
-   {
-      // If we have source but no compiled version, then we need to compile
-      // (and journal as we do so, if that's required).
-
-      void *data;
-      U32 dataSize = 0;
-      Torque::FS::ReadFile(scriptFileName, data, dataSize, true);
-
-      if (journal && Journal::IsRecording())
-         Journal::Write(bool(data != NULL));
-
-      if (data == NULL)
-      {
-         Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file %s.", scriptFileName);
-         execDepth--;
-         return false;
-      }
-      else
-      {
-         if (!dataSize)
-         {
-            execDepth--;
-            return false;
-         }
-
-         script = (char *)data;
-
-         if (journal && Journal::IsRecording())
-         {
-            Journal::Write(dataSize);
-            Journal::Write(dataSize, data);
-         }
-      }
-
-#ifndef TORQUE_NO_DSO_GENERATION
-      if (compiled)
-      {
-         // compile this baddie.
-#ifdef TORQUE_DEBUG
-         Con::printf("Compiling %s...", scriptFileName);
-#endif   
-
-         CodeBlock *code = new CodeBlock();
-         code->compile(nameBuffer, scriptFileName, script);
-         delete code;
-         code = NULL;
-
-         compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
-         if (compiledStream)
-         {
-            compiledStream->read(&version);
-         }
-         else
-         {
-            // We have to exit out here, as otherwise we get double error reports.
-            delete[] script;
-            execDepth--;
-            return false;
-         }
-      }
-#endif
-   }
-   else
-   {
-      if (journal && Journal::IsRecording())
-         Journal::Write(bool(false));
-   }
-
-   if (compiledStream)
-   {
-      // Delete the script object first to limit memory used
-      // during recursive execs.
-      delete[] script;
-      script = 0;
-
-      // We're all compiled, so let's run it.
-#ifdef TORQUE_DEBUG
-      Con::printf("Loading compiled script %s.", scriptFileName);
-#endif   
-      CodeBlock *code = new CodeBlock;
-      code->read(scriptFileName, *compiledStream);
-      delete compiledStream;
-      code->exec(0, scriptFileName, NULL, 0, NULL, noCalls, NULL, 0);
-      delete code;
-      ret = true;
-   }
-   else
-      if (scriptFile)
-      {
-         // No compiled script,  let's just try executing it
-         // directly... this is either a mission file, or maybe
-         // we're on a readonly volume.
-#ifdef TORQUE_DEBUG
-         Con::printf("Executing %s.", scriptFileName);
-#endif   
-
-         CodeBlock *newCodeBlock = new CodeBlock();
-         StringTableEntry name = StringTable->insert(scriptFileName);
-
-         newCodeBlock->compileExec(name, script, noCalls, 0);
-         ret = true;
-      }
-      else
-      {
-         // Don't have anything.
-         Con::warnf(ConsoleLogEntry::Script, "Missing file: %s!", scriptFileName);
-         ret = false;
-      }
-
-   delete[] script;
-   execDepth--;
-   return ret;
-}
-
-ConsoleValue evaluate(const char* string, bool echo, const char *fileName)
-{
-   ConsoleStackFrameSaver stackSaver;
-   stackSaver.save();
-
-   if (echo)
-   {
-      if (string[0] == '%')
-         Con::printf("%s", string);
-      else
-         Con::printf("%s%s", getVariable( "$Con::Prompt" ), string);
-   }
-
-   if(fileName)
-      fileName = StringTable->insert(fileName);
-
-   CodeBlock *newCodeBlock = new CodeBlock();
-   return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0));
-}
-
-//------------------------------------------------------------------------------
-ConsoleValue evaluatef(const char* string, ...)
-{
-   ConsoleStackFrameSaver stackSaver;
-   stackSaver.save();
-
-   char buffer[4096];
-   va_list args;
-   va_start(args, string);
-   dVsprintf(buffer, sizeof(buffer), string, args);
-   va_end(args);
-   CodeBlock *newCodeBlock = new CodeBlock();
-   return newCodeBlock->compileExec(NULL, buffer, false, 0);
-}
-
 //------------------------------------------------------------------------------
 
 // Internal execute for global function which does not save the stack
@@ -1598,7 +1226,7 @@ ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[])
       return std::move(ConsoleValue());
    }
 
-   return std::move(ent->execute(argc, argv, &gEvalState));
+   return std::move(ent->execute(argc, argv, NULL));
 }
 
 ConsoleValue execute(S32 argc, ConsoleValue argv[])
@@ -1701,10 +1329,7 @@ static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue a
       // Twiddle %this argument
       argv[1].setInt(ident);
 
-      SimObject *save = gEvalState.thisObject;
-      gEvalState.thisObject = object;
-      ConsoleValue ret = std::move(ent->execute(argc, argv, &gEvalState));
-      gEvalState.thisObject = save;
+      ConsoleValue ret = std::move(ent->execute(argc, argv, object));
 
       // Twiddle it back
       argv[1].setString(oldIdent);
@@ -1810,6 +1435,84 @@ void setLogMode(S32 newMode)
    }
 }
 
+//------------------------------------------------------------------------------
+
+ReturnBuffer retBuffer;
+
+char* getReturnBuffer(U32 bufferSize)
+{
+   return retBuffer.getBuffer(bufferSize);
+}
+
+char* getReturnBuffer(const char* stringToCopy)
+{
+   U32 len = dStrlen(stringToCopy) + 1;
+   char* ret = retBuffer.getBuffer(len);
+   dMemcpy(ret, stringToCopy, len);
+   return ret;
+}
+
+char* getReturnBuffer(const String& str)
+{
+   const U32 size = str.size();
+   char* ret = retBuffer.getBuffer(size);
+   dMemcpy(ret, str.c_str(), size);
+   return ret;
+}
+
+char* getReturnBuffer(const StringBuilder& str)
+{
+   char* buffer = Con::getReturnBuffer(str.length() + 1);
+   str.copy(buffer);
+   buffer[str.length()] = '\0';
+
+   return buffer;
+}
+
+char* getArgBuffer(U32 bufferSize)
+{
+   return STR.getArgBuffer(bufferSize);
+}
+
+char* getFloatArg(F64 arg)
+{
+   char* ret = STR.getArgBuffer(32);
+   dSprintf(ret, 32, "%g", arg);
+   return ret;
+}
+
+char* getIntArg(S32 arg)
+{
+   char* ret = STR.getArgBuffer(32);
+   dSprintf(ret, 32, "%d", arg);
+   return ret;
+}
+
+char* getBoolArg(bool arg)
+{
+   char* ret = STR.getArgBuffer(32);
+   dSprintf(ret, 32, "%d", arg);
+   return ret;
+}
+
+char* getStringArg(const char* arg)
+{
+   U32 len = dStrlen(arg) + 1;
+   char* ret = STR.getArgBuffer(len);
+   dMemcpy(ret, arg, len);
+   return ret;
+}
+
+char* getStringArg(const String& arg)
+{
+   const U32 size = arg.size();
+   char* ret = STR.getArgBuffer(size);
+   dMemcpy(ret, arg.c_str(), size);
+   return ret;
+}
+
+//------------------------------------------------------------------------------
+
 Namespace *lookupNamespace(const char *ns)
 {
    if(!ns)
@@ -1911,7 +1614,7 @@ bool isCurrentScriptToolScript()
 #ifndef TORQUE_TOOLS
    return false;
 #else
-   const StringTableEntry cbFullPath = CodeBlock::getCurrentCodeBlockFullPath();
+   const StringTableEntry cbFullPath = getCurrentScriptModulePath();
    if(cbFullPath == NULL)
       return false;
    const StringTableEntry exePath = Platform::getMainDotCsDir();
@@ -1922,6 +1625,20 @@ bool isCurrentScriptToolScript()
 
 //------------------------------------------------------------------------------
 
+bool isScriptFile(const char* pFilePath)
+{
+   return (Torque::FS::IsFile(pFilePath)
+      || Torque::FS::IsFile(pFilePath + String(".dso"))
+      || Torque::FS::IsFile(pFilePath + String(".mis"))
+      || Torque::FS::IsFile(pFilePath + String(".mis.dso"))
+      || Torque::FS::IsFile(pFilePath + String(".gui"))
+      || Torque::FS::IsFile(pFilePath + String(".gui.dso"))
+      || Torque::FS::IsFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION))
+      || Torque::FS::IsFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION) + String(".dso")));
+}
+
+//------------------------------------------------------------------------------
+
 StringTableEntry getModNameFromPath(const char *path)
 {
    if(path == NULL || *path == 0)
@@ -2248,7 +1965,7 @@ bool expandPath(char* pDstPath, U32 size, const char* pSrcPath, const char* pWor
    if (leadingToken == '.')
    {
       // Fetch the code-block file-path.
-      const StringTableEntry codeblockFullPath = CodeBlock::getCurrentCodeBlockFullPath();
+      const StringTableEntry codeblockFullPath = getCurrentScriptModulePath();
 
       // Do we have a code block full path?
       if (codeblockFullPath == NULL)

+ 16 - 26
Engine/source/console/console.h

@@ -128,6 +128,7 @@ enum ConsoleValueType
 
 struct ConsoleValueConsoleType
 {
+   S32 consoleType;
    void* dataPtr;
    EnumTable* enumTable;
 };
@@ -340,8 +341,8 @@ public:
    TORQUE_FORCEINLINE void setConsoleData(S32 consoleType, void* dataPtr, const EnumTable* enumTable)
    {
       cleanupData();
-      type = ConsoleValueType::cvSTEntry;
-      ct = new ConsoleValueConsoleType{ dataPtr, const_cast<EnumTable*>(enumTable) };
+      type = ConsoleValueType::cvConsoleValueType;
+      ct = new ConsoleValueConsoleType{ consoleType, dataPtr, const_cast<EnumTable*>(enumTable) };
    }
 
    TORQUE_FORCEINLINE S32 getType() const
@@ -364,6 +365,18 @@ public:
       return type >= ConsoleValueType::cvConsoleValueType;
    }
 
+   TORQUE_FORCEINLINE ConsoleValueConsoleType* getConsoleType() const
+   {
+      if(type >= ConsoleValueType::cvConsoleValueType)
+      {
+         return ct;
+      }
+      else
+      {
+         return NULL;
+      }
+   }
+
    TORQUE_FORCEINLINE void setFastFloat(F64 flt)
    {
       type = ConsoleValueType::cvFloat;
@@ -626,6 +639,7 @@ namespace Con
    StringTableEntry getPathExpandoValue(U32 expandoIndex);
 
    bool isCurrentScriptToolScript();
+   bool isScriptFile(const char* path);
 
    StringTableEntry getModNameFromPath(const char *path);
 
@@ -918,30 +932,6 @@ namespace Con
    ConsoleValue execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
    ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly = false);
 
-   /// Executes a script file and compiles it for use in script.
-   ///
-   /// @param  string   File name that is the script to be executed and compiled.
-   /// @param fileName Path to the file to execute
-   /// @param noCalls Deprecated
-   /// @param journalScript Deprecated
-   ///
-   /// @return True if the script was successfully executed, false if not.
-   bool executeFile(const char* fileName, bool noCalls, bool journalScript);
-
-   /// Evaluate an arbitrary chunk of code.
-   ///
-   /// @param  string   Buffer containing code to execute.
-   /// @param  echo     Should we echo the string to the console?
-   /// @param  fileName Indicate what file this code is coming from; used in error reporting and such.
-   /// NOTE: This function restores the console stack on return.
-   ConsoleValue evaluate(const char* string, bool echo = false, const char *fileName = NULL);
-
-   /// Evaluate an arbitrary line of script.
-   ///
-   /// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
-   /// NOTE: This function restores the console stack on return.
-   ConsoleValue evaluatef(const char* string, ...);
-
    /// @}
 
    /// @name Console Function Implementation Helpers

+ 1 - 3
Engine/source/console/consoleDoc.cpp

@@ -23,14 +23,12 @@
 #include "platform/platform.h"
 #include "console/console.h"
 
-#include "console/ast.h"
 #include "core/tAlgorithm.h"
 
 #include "core/strings/findMatch.h"
 #include "console/consoleInternal.h"
 #include "console/consoleObject.h"
 #include "core/stream/fileStream.h"
-#include "console/compiler.h"
 #include "core/frameAllocator.h"
 #include "console/engineAPI.h"
 
@@ -272,7 +270,7 @@ void Namespace::printNamespaceEntries(Namespace * g, bool dumpScript, bool dumpE
       }
       else if(ewalk->mFunctionOffset)                 // If it's a builtin function...
       {
-         String args = ewalk->mCode->getFunctionArgs(ewalk->mFunctionOffset);
+         String args = ewalk->mModule->getFunctionArgs(ewalk->mFunctionName, ewalk->mFunctionOffset);
          printClassMethod(false, typeNames[ewalk->mType], ewalk->mFunctionName, args, "");
       }
       else

+ 15 - 71
Engine/source/console/consoleFunctions.cpp

@@ -24,18 +24,17 @@
 #include "console/console.h"
 #include "console/consoleInternal.h"
 #include "console/engineAPI.h"
-#include "console/ast.h"
 
 #ifndef _CONSOLFUNCTIONS_H_
 #include "console/consoleFunctions.h"
 #endif
 
+#include "script.h"
 #include "cinterface/cinterface.h"
 #include "core/strings/findMatch.h"
 #include "core/strings/stringUnit.h"
 #include "core/strings/unicode.h"
 #include "core/stream/fileStream.h"
-#include "console/compiler.h"
 #include "platform/platformInput.h"
 #include "core/util/journal/journal.h"
 #include "gfx/gfxEnums.h"
@@ -43,6 +42,7 @@
 #include "core/color.h"
 #include "math/mPoint3.h"
 #include "math/mathTypes.h"
+#include "torquescript/runtime.h"
 
 // This is a temporary hack to get tools using the library to
 // link in this module which contains no other references.
@@ -2330,63 +2330,7 @@ DefineEngineFunction( compile, bool, ( const char* fileName, bool overrideNoDSO
    "@see exec\n"
    "@ingroup Scripting" )
 {
-   Con::expandScriptFilename( scriptFilenameBuffer, sizeof( scriptFilenameBuffer ), fileName );
-
-   // Figure out where to put DSOs
-   StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
-   if(dsoPath && *dsoPath == 0)
-      return false;
-
-   // If the script file extention is '.ed.tscript' then compile it to a different compiled extention
-   bool isEditorScript = false;
-   const char *ext = dStrrchr( scriptFilenameBuffer, '.' );
-   if( ext && ( dStricmp( ext, "." TORQUE_SCRIPT_EXTENSION) == 0 ) )
-   {
-      const char* ext2 = ext - 3;
-      if( dStricmp( ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0 )
-         isEditorScript = true;
-   }
-   else if( ext && ( dStricmp( ext, ".gui" ) == 0 ) )
-   {
-      const char* ext2 = ext - 3;
-      if( dStricmp( ext2, ".ed.gui" ) == 0 )
-         isEditorScript = true;
-   }
-
-   const char *filenameOnly = dStrrchr(scriptFilenameBuffer, '/');
-   if(filenameOnly)
-      ++filenameOnly;
-   else
-      filenameOnly = scriptFilenameBuffer;
- 
-   char nameBuffer[512];
-
-   if( isEditorScript )
-      dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".edso", NULL);
-   else
-      dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".dso", NULL);
-   
-   void *data = NULL;
-   U32 dataSize = 0;
-   Torque::FS::ReadFile(scriptFilenameBuffer, data, dataSize, true);
-   if(data == NULL)
-   {
-      Con::errorf(ConsoleLogEntry::Script, "compile: invalid script file %s.", scriptFilenameBuffer);
-      return false;
-   }
-
-   const char *script = static_cast<const char *>(data);
-
-#ifdef TORQUE_DEBUG
-   Con::printf("Compiling %s...", scriptFilenameBuffer);
-#endif 
-
-   CodeBlock *code = new CodeBlock();
-   code->compile(nameBuffer, scriptFilenameBuffer, script, overrideNoDSO);
-   delete code;
-   delete[] script;
-
-   return true;
+   return TorqueScript::getRuntime()->compile(fileName, overrideNoDSO);
 }
 
 //-----------------------------------------------------------------------------
@@ -2410,12 +2354,12 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou
 
 DefineEngineFunction( eval, const char*, ( const char* consoleString ), , "eval(consoleString)" )
 {
-   ConsoleValue returnValue = Con::evaluate(consoleString, false, NULL);
+   Con::EvalResult returnValue = Con::evaluate(consoleString, false, NULL);
 
-   return Con::getReturnBuffer(returnValue.getString());
+   return Con::getReturnBuffer(returnValue.value.getString());
 }
 
-DefineEngineFunction( getVariable, const char*, ( const char* varName ), , "(string varName)\n" 
+DefineEngineFunction( getVariable, const char*, ( const char* varName ), , "(string varName)\n"
    "@brief Returns the value of the named variable or an empty string if not found.\n\n"
    "@varName Name of the variable to search for\n"
    "@return Value contained by varName, \"\" if the variable does not exist\n"
@@ -2589,15 +2533,15 @@ DefineEngineFunction( isDefined, bool, ( const char* varName, const char* varVal
    else if (name[0] == '%')
    {
       // Look up a local variable
-      if( gEvalState.getStackDepth() > 0 )
+      if( Con::getFrameStack().size() > 0 )
       {
-         Dictionary::Entry* ent = gEvalState.getCurrentFrame().lookup(name);
+         Dictionary::Entry* ent = Con::getCurrentStackFrame()->lookup(name);
 
          if (ent)
             return true;
          else if (!String::isEmpty(varValue))
          {
-            gEvalState.getCurrentFrame().setVariable(name, varValue);
+            Con::getCurrentStackFrame()->setVariable(name, varValue);
          }
       }
       else
@@ -2606,13 +2550,13 @@ DefineEngineFunction( isDefined, bool, ( const char* varName, const char* varVal
    else if (name[0] == '$')
    {
       // Look up a global value
-      Dictionary::Entry* ent = gEvalState.globalVars.lookup(name);
+      Dictionary::Entry* ent = Con::gGlobalVars.lookup(name);
 
       if (ent)
          return true;
       else if (!String::isEmpty(varValue))
       {
-         gEvalState.globalVars.setVariable(name, varValue);
+         Con::gGlobalVars.setVariable(name, varValue);
       }
    }
    else
@@ -2739,7 +2683,7 @@ DefineEngineFunction( export, void, ( const char* pattern, const char* filename,
    else
       filename = NULL;
 
-   gEvalState.globalVars.exportVariables( pattern, filename, append );
+   Con::gGlobalVars.exportVariables( pattern, filename, append );
 }
 
 //-----------------------------------------------------------------------------
@@ -2756,7 +2700,7 @@ DefineEngineFunction( deleteVariables, void, ( const char* pattern ),,
    "@see strIsMatchExpr\n"
    "@ingroup Scripting" )
 {
-   gEvalState.globalVars.deleteVariables( pattern );
+   Con::gGlobalVars.deleteVariables( pattern );
 }
 
 //-----------------------------------------------------------------------------
@@ -2769,8 +2713,8 @@ DefineEngineFunction( trace, void, ( bool enable ), ( true ),
    "@param enable New setting for script trace execution, on by default.\n"
    "@ingroup Debugging" )
 {
-   gEvalState.traceOn = enable;
-   Con::printf( "Console trace %s", gEvalState.traceOn ? "enabled." : "disabled." );
+   Con::gTraceOn = enable;
+   Con::printf( "Console trace %s", Con::gTraceOn ? "enabled." : "disabled." );
 }
 
 //-----------------------------------------------------------------------------

+ 50 - 272
Engine/source/console/consoleInternal.cpp

@@ -25,13 +25,11 @@
 #include "platform/platform.h"
 #include "console/console.h"
 
-#include "console/ast.h"
 #include "core/tAlgorithm.h"
 
 #include "core/strings/findMatch.h"
 #include "console/consoleInternal.h"
 #include "core/stream/fileStream.h"
-#include "console/compiler.h"
 #include "console/engineAPI.h"
 
 //#define DEBUG_SPEW
@@ -183,13 +181,13 @@ void Dictionary::exportVariables(const char *varString, const char *fileName, bo
 
    for (s = sortList.begin(); s != sortList.end(); s++)
    {
-      switch ((*s)->type)
+      switch ((*s)->value.getType())
       {
-         case Entry::TypeInternalInt:
-            dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->ival, cat);
+         case ConsoleValueType::cvInteger:
+            dSprintf(buffer, sizeof(buffer), "%s = %d;%s", (*s)->name, (*s)->getIntValue(), cat);
             break;
-         case Entry::TypeInternalFloat:
-            dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->fval, cat);
+         case ConsoleValueType::cvFloat:
+            dSprintf(buffer, sizeof(buffer), "%s = %g;%s", (*s)->name, (*s)->getFloatValue(), cat);
             break;
          default:
             expandEscape(expandBuffer, (*s)->getStringValue());
@@ -243,7 +241,7 @@ void Dictionary::exportVariables(const char *varString, Vector<String> *names, V
 
       if (values)
       {
-         switch ((*s)->type)
+         switch ((*s)->value.getType())
          {
             case ConsoleValueType::cvInteger:
             case ConsoleValueType::cvFloat:
@@ -375,18 +373,16 @@ Dictionary::Dictionary()
 #pragma warning( disable : 4355 )
    ownHashTable(this), // Warning with VC++ but this is safe.
 #pragma warning( default : 4355 )
-   exprState(NULL),
    scopeName(NULL),
    scopeNamespace(NULL),
-   code(NULL),
+   module(NULL),
    ip(0)
 {
+   setState(NULL);
 }
 
-void Dictionary::setState(ExprEvalState *state, Dictionary* ref)
+void Dictionary::setState(Dictionary* ref)
 {
-   exprState = state;
-
    if (ref)
    {
       hashTable = ref->hashTable;
@@ -439,7 +435,7 @@ void Dictionary::reset()
 
    scopeName = NULL;
    scopeNamespace = NULL;
-   code = NULL;
+   module = NULL;
    ip = 0;
 }
 
@@ -465,19 +461,11 @@ const char *Dictionary::tabComplete(const char *prevText, S32 baseLen, bool fFor
 Dictionary::Entry::Entry(StringTableEntry in_name)
 {
    name = in_name;
-   type = TypeInternalString;
    notify = NULL;
    nextEntry = NULL;
    mUsage = NULL;
    mIsConstant = false;
    mNext = NULL;
-
-   ival = 0;
-   fval = 0;
-   sval = NULL;
-   bufferLen = 0;
-   dataPtr = NULL;
-   enumTable = NULL;
 }
 
 Dictionary::Entry::~Entry()
@@ -488,73 +476,11 @@ Dictionary::Entry::~Entry()
 void Dictionary::Entry::reset()
 {
    name = NULL;
-   if (type <= TypeInternalString && sval != NULL)
-      dFree(sval);
+   value.reset();
    if (notify)
       delete notify;
 }
 
-void Dictionary::Entry::setStringValue(const char* value)
-{
-   if (mIsConstant)
-   {
-      Con::errorf("Cannot assign value to constant '%s'.", name);
-      return;
-   }
-
-   if (type <= TypeInternalString)
-   {
-      // Let's not remove empty-string-valued global vars from the dict.
-      // If we remove them, then they won't be exported, and sometimes
-      // it could be necessary to export such a global.  There are very
-      // few empty-string global vars so there's no performance-related
-      // need to remove them from the dict.
-      /*
-       if(!value[0] && name[0] == '$')
-       {
-       gEvalState.globalVars.remove(this);
-       return;
-       }
-       */
-
-      U32 stringLen = dStrlen(value);
-
-      // If it's longer than 256 bytes, it's certainly not a number.
-      //
-      // (This decision may come back to haunt you. Shame on you if it
-      // does.)
-      if (stringLen < 256)
-      {
-         fval = dAtof(value);
-         ival = dAtoi(value);
-      }
-      else
-      {
-         fval = 0.f;
-         ival = 0;
-      }
-
-      type = TypeInternalString;
-
-      // may as well pad to the next cache line
-      U32 newLen = ((stringLen + 1) + 15) & ~15;
-
-      if (sval == NULL)
-         sval = (char*)dMalloc(newLen);
-      else if (newLen > bufferLen)
-         sval = (char*)dRealloc(sval, newLen);
-
-      bufferLen = newLen;
-      dStrcpy(sval, value, newLen);
-   }
-   else
-      Con::setData(type, dataPtr, 0, 1, &value, enumTable);
-
-   // Fire off the notification if we have one.
-   if (notify)
-      notify->trigger();
-}
-
 const char *Dictionary::getVariable(StringTableEntry name, bool *entValid)
 {
    Entry *ent = lookup(name);
@@ -630,17 +556,12 @@ Dictionary::Entry* Dictionary::addVariable(const char *name,
 
    Entry *ent = add(StringTable->insert(name));
 
-   if (ent->type <= Entry::TypeInternalString && ent->sval != NULL)
-      dFree(ent->sval);
-
    ent->mUsage = usage;
-   ent->type = type;
-   ent->dataPtr = dataPtr;
 
    // Fetch enum table, if any.
    ConsoleBaseType* conType = ConsoleBaseType::getType(type);
    AssertFatal(conType, "Dictionary::addVariable - invalid console type");
-   ent->enumTable = conType->getEnumTable();
+   ent->value.setConsoleData(type, dataPtr, conType->getEnumTable());
 
    return ent;
 }
@@ -680,158 +601,15 @@ void Dictionary::validate()
       "Dictionary::validate() - Dictionary not owner of own hashtable!");
 }
 
-void ExprEvalState::pushFrame(StringTableEntry frameName, Namespace *ns, S32 registerCount)
-{
-#ifdef DEBUG_SPEW
-   validate();
-
-   Platform::outputDebugString("[ConsoleInternal] Pushing new frame for '%s' at %i",
-      frameName, mStackDepth);
-#endif
-
-   if (mStackDepth + 1 > stack.size())
-   {
-#ifdef DEBUG_SPEW
-      Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
-#endif
-
-      stack.push_back(new Dictionary);
-   }
-
-   Dictionary& newFrame = *(stack[mStackDepth]);
-   newFrame.setState(this);
-
-   newFrame.scopeName = frameName;
-   newFrame.scopeNamespace = ns;
-
-   mStackDepth++;
-   currentVariable = NULL;
-
-   AssertFatal(!newFrame.getCount(), "ExprEvalState::pushFrame - Dictionary not empty!");
-
-   ConsoleValue* consoleValArray = new ConsoleValue[registerCount]();
-   localStack.push_back(ConsoleValueFrame(consoleValArray, false));
-   currentRegisterArray = &localStack.last();
-
-   AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
-
-#ifdef DEBUG_SPEW
-   validate();
-#endif
-}
-
-void ExprEvalState::popFrame()
-{
-   AssertFatal(mStackDepth > 0, "ExprEvalState::popFrame - Stack Underflow!");
-
-#ifdef DEBUG_SPEW
-   validate();
-
-   Platform::outputDebugString("[ConsoleInternal] Popping %sframe at %i",
-      getCurrentFrame().isOwner() ? "" : "shared ", mStackDepth - 1);
-#endif
-
-   mStackDepth--;
-   stack[mStackDepth]->reset();
-   currentVariable = NULL;
-
-   const ConsoleValueFrame& frame = localStack.last();
-   localStack.pop_back();
-   if (!frame.isReference)
-      delete[] frame.values;
-
-   currentRegisterArray = localStack.size() ? &localStack.last() : NULL;
-
-   AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
-
-#ifdef DEBUG_SPEW
-   validate();
-#endif
-}
-
-void ExprEvalState::pushFrameRef(S32 stackIndex)
-{
-   AssertFatal(stackIndex >= 0 && stackIndex < mStackDepth, "You must be asking for a valid frame!");
-
-#ifdef DEBUG_SPEW
-   validate();
-
-   Platform::outputDebugString("[ConsoleInternal] Cloning frame from %i to %i",
-      stackIndex, mStackDepth);
-#endif
-
-   if (mStackDepth + 1 > stack.size())
-   {
-#ifdef DEBUG_SPEW
-      Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
-#endif
-
-      stack.push_back(new Dictionary);
-   }
-
-   Dictionary& newFrame = *(stack[mStackDepth]);
-   newFrame.setState(this, stack[stackIndex]);
-
-   mStackDepth++;
-   currentVariable = NULL;
-
-   ConsoleValue* values = localStack[stackIndex].values;
-   localStack.push_back(ConsoleValueFrame(values, true));
-   currentRegisterArray = &localStack.last();
-
-   AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
-
-#ifdef DEBUG_SPEW
-   validate();
-#endif
-}
-
-void ExprEvalState::pushDebugFrame(S32 stackIndex)
-{
-   pushFrameRef(stackIndex);
-
-   Dictionary& newFrame = *(stack[mStackDepth - 1]);
-
-   // debugger needs to know this info...
-   newFrame.scopeName = stack[stackIndex]->scopeName;
-   newFrame.scopeNamespace = stack[stackIndex]->scopeNamespace;
-   newFrame.code = stack[stackIndex]->code;
-   newFrame.ip = stack[stackIndex]->ip;
-}
-
-ExprEvalState::ExprEvalState()
-{
-   VECTOR_SET_ASSOCIATION(stack);
-   globalVars.setState(this);
-   thisObject = NULL;
-   traceOn = false;
-   currentVariable = NULL;
-   mStackDepth = 0;
-   stack.reserve(64);
-   mShouldReset = false;
-   mResetLocked = false;
-   copyVariable = NULL;
-   currentRegisterArray = NULL;
-}
-
-ExprEvalState::~ExprEvalState()
+Con::Module* Con::findScriptModuleForFile(const char* fileName)
 {
-   // Delete callframes.
-
-   while (!stack.empty())
+   for (Con::Module* module : gScriptModules)
    {
-      delete stack.last();
-      stack.decrement();
+      if (module->getName() == fileName) {
+         return module;
+      }
    }
-}
-
-void ExprEvalState::validate()
-{
-   AssertFatal(mStackDepth <= stack.size(),
-      "ExprEvalState::validate() - Stack depth pointing beyond last stack frame!");
-
-   for (U32 i = 0; i < stack.size(); ++i)
-      stack[i]->validate();
+   return NULL;
 }
 
 DefineEngineFunction(backtrace, void, (), ,
@@ -842,35 +620,37 @@ DefineEngineFunction(backtrace, void, (), ,
 {
    U32 totalSize = 1;
 
-   for (U32 i = 0; i < gEvalState.getStackDepth(); i++)
+   for (U32 i = 0; i < Con::getFrameStack().size(); i++)
    {
-      if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage)
-         totalSize += dStrlen(gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage) + 2;
-      if (gEvalState.stack[i]->scopeName)
-         totalSize += dStrlen(gEvalState.stack[i]->scopeName) + 3;
-      if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
-         totalSize += dStrlen(gEvalState.stack[i]->scopeNamespace->mName) + 2;
+      const Con::ConsoleFrame* frame = Con::getStackFrame(i);
+      if (frame->scopeNamespace && frame->scopeNamespace->mEntryList->mPackage)
+         totalSize += dStrlen(frame->scopeNamespace->mEntryList->mPackage) + 2;
+      if (frame->scopeName)
+         totalSize += dStrlen(frame->scopeName) + 3;
+      if (frame->scopeNamespace && frame->scopeNamespace->mName)
+         totalSize += dStrlen(frame->scopeNamespace->mName) + 2;
    }
 
    char *buf = Con::getReturnBuffer(totalSize);
    buf[0] = 0;
-   for (U32 i = 0; i < gEvalState.getStackDepth(); i++)
+   for (U32 i = 0; i < Con::getFrameStack().size(); i++)
    {
+      const Con::ConsoleFrame* frame = Con::getStackFrame(i);
       dStrcat(buf, "->", totalSize);
 
-      if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage)
+      if (frame->scopeNamespace && frame->scopeNamespace->mEntryList->mPackage)
       {
          dStrcat(buf, "[", totalSize);
-         dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mEntryList->mPackage, totalSize);
+         dStrcat(buf, frame->scopeNamespace->mEntryList->mPackage, totalSize);
          dStrcat(buf, "]", totalSize);
       }
-      if (gEvalState.stack[i]->scopeNamespace && gEvalState.stack[i]->scopeNamespace->mName)
+      if (frame->scopeNamespace && frame->scopeNamespace->mName)
       {
-         dStrcat(buf, gEvalState.stack[i]->scopeNamespace->mName, totalSize);
+         dStrcat(buf, frame->scopeNamespace->mName, totalSize);
          dStrcat(buf, "::", totalSize);
       }
-      if (gEvalState.stack[i]->scopeName)
-         dStrcat(buf, gEvalState.stack[i]->scopeName, totalSize);
+      if (frame->scopeName)
+         dStrcat(buf, frame->scopeName, totalSize);
    }
 
    Con::printf("BackTrace: %s", buf);
@@ -878,7 +658,7 @@ DefineEngineFunction(backtrace, void, (), ,
 
 Namespace::Entry::Entry()
 {
-   mCode = NULL;
+   mModule = NULL;
    mType = InvalidFunctionType;
    mUsage = NULL;
    mHeader = NULL;
@@ -896,10 +676,10 @@ Namespace::Entry::Entry()
 
 void Namespace::Entry::clear()
 {
-   if (mCode)
+   if (mModule)
    {
-      mCode->decRefCount();
-      mCode = NULL;
+      mModule->decRefCount();
+      mModule = NULL;
    }
 
    // Clean up usage strings generated for script functions.
@@ -1233,15 +1013,15 @@ Namespace::Entry *Namespace::createLocalEntry(StringTableEntry name)
    return ent;
 }
 
-void Namespace::addFunction(StringTableEntry name, CodeBlock *cb, U32 functionOffset, const char* usage, U32 lineNumber)
+void Namespace::addFunction(StringTableEntry name, Con::Module *cb, U32 functionOffset, const char* usage, U32 lineNumber)
 {
    Entry *ent = createLocalEntry(name);
    trashCache();
 
    ent->mUsage = usage;
-   ent->mCode = cb;
+   ent->mModule = cb;
    ent->mFunctionOffset = functionOffset;
-   ent->mCode->incRefCount();
+   ent->mModule->incRefCount();
    ent->mType = Entry::ConsoleFunctionType;
    ent->mFunctionLineNumber = lineNumber;
 }
@@ -1366,9 +1146,7 @@ void Namespace::markGroup(const char* name, const char* usage)
    ent->cb.mGroupName = name;
 }
 
-extern S32 executeBlock(StmtNode *block, ExprEvalState *state);
-
-ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, ExprEvalState *state)
+ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, SimObject *thisObj)
 {
    STR.clearFunctionOffset();
 
@@ -1376,7 +1154,7 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, ExprEvalSta
    {
       if (mFunctionOffset)
       {
-         return std::move(mCode->exec(mFunctionOffset, argv[0].getString(), mNamespace, argc, argv, false, mPackage));
+         return std::move(mModule->exec(mFunctionOffset, argv[0].getString(), mNamespace, argc, argv, false, mPackage).value);
       }
       else
       {
@@ -1406,21 +1184,21 @@ ConsoleValue Namespace::Entry::execute(S32 argc, ConsoleValue *argv, ExprEvalSta
    {
       case StringCallbackType:
       {
-         const char* str = cb.mStringCallbackFunc(state->thisObject, argc, argv);
+         const char* str = cb.mStringCallbackFunc(thisObj, argc, argv);
          result.setString(str);
          break;
       }
       case IntCallbackType:
-         result.setInt(cb.mIntCallbackFunc(state->thisObject, argc, argv));
+         result.setInt(cb.mIntCallbackFunc(thisObj, argc, argv));
          break;
       case FloatCallbackType:
-         result.setFloat(cb.mFloatCallbackFunc(state->thisObject, argc, argv));
+         result.setFloat(cb.mFloatCallbackFunc(thisObj, argc, argv));
          break;
       case VoidCallbackType:
-         cb.mVoidCallbackFunc(state->thisObject, argc, argv);
+         cb.mVoidCallbackFunc(thisObj, argc, argv);
          break;
       case BoolCallbackType:
-         result.setBool(cb.mBoolCallbackFunc(state->thisObject, argc, argv));
+         result.setBool(cb.mBoolCallbackFunc(thisObj, argc, argv));
          break;
    }
 
@@ -1704,7 +1482,7 @@ String Namespace::Entry::getArgumentsString() const
 
       if (sFindArgumentListSubstring(mUsage, argListStart, argListEnd))
          str.append(argListStart, argListEnd - argListStart);
-      else if (mType == ConsoleFunctionType && mCode)
+      else if (mType == ConsoleFunctionType && mModule)
       {
          // This isn't correct but the nonsense console stuff is set up such that all
          // functions that have no function bodies are keyed to offset 0 to indicate "no code."
@@ -1716,7 +1494,7 @@ String Namespace::Entry::getArgumentsString() const
          if (!mFunctionOffset)
             return "()";
 
-         String args = mCode->getFunctionArgs(mFunctionOffset);
+         String args = mModule->getFunctionArgs(mFunctionName, mFunctionOffset);
          if (args.isEmpty())
             return "()";
 

+ 66 - 208
Engine/source/console/consoleInternal.h

@@ -38,12 +38,12 @@
 #ifndef _DATACHUNKER_H_
 #include "core/dataChunker.h"
 #endif
+#include "module.h"
 
 /// @ingroup console_system Console System
 /// @{
 
 
-class ExprEvalState;
 struct FunctionDecl;
 class CodeBlock;
 class AbstractClassRep;
@@ -125,7 +125,7 @@ public:
       ConsoleFunctionHeader* mHeader;
 
       /// The compiled script code if this is a script function.
-      CodeBlock* mCode;
+      Con::Module* mModule;
 
       /// The offset in the compiled script code at which this function begins.
       U32 mFunctionOffset;
@@ -150,7 +150,7 @@ public:
       void clear();
 
       ///
-      ConsoleValue execute(S32 argc, ConsoleValue* argv, ExprEvalState* state);
+      ConsoleValue execute(S32 argc, ConsoleValue* argv, SimObject* thisObj);
 
       /// Return a one-line documentation text string for the function.
       String getBriefDescription(String* outRemainingDocText = NULL) const;
@@ -181,7 +181,7 @@ public:
    Namespace();
    ~Namespace();
 
-   void addFunction(StringTableEntry name, CodeBlock* cb, U32 functionOffset, const char* usage = NULL, U32 lineNumber = 0);
+   void addFunction(StringTableEntry name, Con::Module* cb, U32 functionOffset, const char* usage = NULL, U32 lineNumber = 0);
    void addCommand(StringTableEntry name, StringCallback, const char *usage, S32 minArgs, S32 maxArgs, bool toolOnly = false, ConsoleFunctionHeader* header = NULL);
    void addCommand(StringTableEntry name, IntCallback, const char *usage, S32 minArgs, S32 maxArgs, bool toolOnly = false, ConsoleFunctionHeader* header = NULL);
    void addCommand(StringTableEntry name, FloatCallback, const char *usage, S32 minArgs, S32 maxArgs, bool toolOnly = false, ConsoleFunctionHeader* header = NULL);
@@ -286,16 +286,8 @@ public:
    {
       friend class Dictionary;
 
-      enum
-      {
-         TypeInternalInt = -3,
-         TypeInternalFloat = -2,
-         TypeInternalString = -1,
-      };
-
       StringTableEntry name;
       Entry *nextEntry;
-      S32 type;
 
       typedef Signal<void()> NotifySignal;
 
@@ -309,58 +301,17 @@ public:
       /// Whether this is a constant that cannot be assigned to.
       bool mIsConstant;
 
-   protected:
-
-      // NOTE: This is protected to ensure no one outside
-      // of this structure is messing with it.
-
-#pragma warning( push )
-#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union
-
-      // An variable is either a real dynamic type or
-      // its one exposed from C++ using a data pointer.
-      //
-      // We use this nameless union and struct setup
-      // to optimize the memory usage.
-      union
-      {
-         struct
-         {
-            char* sval;
-            U32 ival;  // doubles as strlen when type is TypeInternalString
-            F32 fval;
-            U32 bufferLen;
-         };
-
-         struct
-         {
-            /// The real data pointer.
-            void* dataPtr;
-
-            /// The enum lookup table for enumerated types.
-            const EnumTable* enumTable;
-         };
-      };
-
-#pragma warning( pop ) // C4201
+      ConsoleValue value;
 
    public:
 
       Entry() {
          name = NULL;
-         type = TypeInternalString;
          notify = NULL;
          nextEntry = NULL;
          mUsage = NULL;
          mIsConstant = false;
          mNext = NULL;
-
-         ival = 0;
-         fval = 0;
-         sval = NULL;
-         bufferLen = 0;
-         dataPtr = NULL;
-         enumTable = NULL;
       }
 
       Entry(StringTableEntry name);
@@ -370,32 +321,21 @@ public:
 
       void reset();
 
+      inline ConsoleValue getValue() { return std::move(value); }
+
       inline U32 getIntValue()
       {
-         if (type <= TypeInternalString)
-            return ival;
-         else
-            return dAtoi(Con::getData(type, dataPtr, 0, enumTable));
+         return value.getInt();
       }
 
       inline F32 getFloatValue()
       {
-         if (type <= TypeInternalString)
-            return fval;
-         else
-            return dAtof(Con::getData(type, dataPtr, 0, enumTable));
+         return value.getFloat();
       }
 
       inline const char *getStringValue()
       {
-         if (type == TypeInternalString)
-            return sval;
-         if (type == TypeInternalFloat)
-            return Con::getData(TypeF32, &fval, 0);
-         else if (type == TypeInternalInt)
-            return Con::getData(TypeS32, &ival, 0);
-         else
-            return Con::getData(type, dataPtr, 0, enumTable);
+         return value.getString();
       }
 
       void setIntValue(U32 val)
@@ -406,21 +346,15 @@ public:
             return;
          }
 
-         if (type <= TypeInternalString)
+         if (value.isConsoleType())
          {
-            fval = (F32)val;
-            ival = val;
-            if (sval != NULL)
-            {
-               dFree(sval);
-               sval = NULL;
-            }
-            type = TypeInternalInt;
+            const char* dptr = Con::getData(TypeS32, &val, 0);
+            ConsoleValueConsoleType* cvt = value.getConsoleType();
+            Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
          }
          else
          {
-            const char* dptr = Con::getData(TypeS32, &val, 0);
-            Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
+            value.setInt(val);
          }
 
          // Fire off the notification if we have one.
@@ -436,21 +370,15 @@ public:
             return;
          }
 
-         if (type <= TypeInternalString)
+         if (value.isConsoleType())
          {
-            fval = val;
-            ival = static_cast<U32>(val);
-            if (sval != NULL)
-            {
-               dFree(sval);
-               sval = NULL;
-            }
-            type = TypeInternalFloat;
+            const char* dptr = Con::getData(TypeF32, &val, 0);
+            ConsoleValueConsoleType* cvt = value.getConsoleType();
+            Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &dptr, cvt->enumTable);
          }
          else
          {
-            const char* dptr = Con::getData(TypeF32, &val, 0);
-            Con::setData(type, dataPtr, 0, 1, &dptr, enumTable);
+            value.setFloat(val);
          }
 
          // Fire off the notification if we have one.
@@ -458,7 +386,29 @@ public:
             notify->trigger();
       }
 
-      void setStringValue(const char* value);
+
+      void setStringValue(const char* val)
+      {
+         if (mIsConstant)
+         {
+            Con::errorf("Cannot assign value to constant '%s'.", name);
+            return;
+         }
+
+         if (value.isConsoleType())
+         {
+            ConsoleValueConsoleType* cvt = value.getConsoleType();
+            Con::setData(cvt->consoleType, cvt->dataPtr, 0, 1, &val, cvt->enumTable);
+         }
+         else
+         {
+            value.setString(val);
+         }
+
+         // Fire off the notification if we have one.
+         if (notify)
+            notify->trigger();
+      }
    };
 
    struct HashTableData
@@ -475,11 +425,10 @@ public:
 
    HashTableData* hashTable;
    HashTableData ownHashTable;
-   ExprEvalState *exprState;
 
    StringTableEntry scopeName;
    Namespace *scopeNamespace;
-   CodeBlock *code;
+   Con::Module *module;
    U32 ip;
 
    Dictionary();
@@ -487,7 +436,7 @@ public:
 
    Entry *lookup(StringTableEntry name);
    Entry *add(StringTableEntry name);
-   void setState(ExprEvalState *state, Dictionary* ref = NULL);
+   void setState(Dictionary* ref = NULL);
    void remove(Entry *);
    void reset();
 
@@ -547,126 +496,35 @@ struct ConsoleValueFrame
    }
 };
 
-class ExprEvalState
+namespace Con
 {
-public:
-   /// @name Expression Evaluation
-   /// @{
-
-   ///
-   SimObject *thisObject;
-   Dictionary::Entry *currentVariable;
-   Dictionary::Entry *copyVariable;
-   bool traceOn;
-
-   U32 mStackDepth;
-   bool mShouldReset; ///< Designates if the value stack should be reset
-   bool mResetLocked; ///< mShouldReset will be set at the end
-
-   ExprEvalState();
-   ~ExprEvalState();
-
-   /// @}
-
-   /// @name Stack Management
-   /// @{
-
-   /// The stack of callframes.  The extra redirection is necessary since Dictionary holds
-   /// an interior pointer that will become invalid when the object changes address.
-   Vector< Dictionary* > stack;
-
-   S32 getTopOfStack() { return (S32)mStackDepth; }
-
-   Vector< ConsoleValueFrame > localStack;
-   ConsoleValueFrame* currentRegisterArray; // contains array at to top of localStack
-
-   ///
-   Dictionary globalVars;
-
-   void setCurVarName(StringTableEntry name);
-   void setCurVarNameCreate(StringTableEntry name);
-
-   S32 getIntVariable();
-   F64 getFloatVariable();
-   const char *getStringVariable();
-   void setIntVariable(S32 val);
-   void setFloatVariable(F64 val);
-   void setStringVariable(const char *str);
-
-   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);
-   }
+   /// The current $instantGroup setting.
+   extern String gInstantGroup;
 
-   TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue val)
-   {
-      currentRegisterArray->values[reg] = std::move(val);
-   }
+   /// Global variable storage
+   inline Dictionary gGlobalVars;
 
-   void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount);
-   void popFrame();
+   typedef Dictionary ConsoleFrame;
+   typedef Vector<ConsoleFrame*> ConsoleStack;
 
-   /// Puts a reference to an existing stack frame
-   /// on the top of the stack.
-   void pushFrameRef(S32 stackIndex);
+   inline ConsoleStack gFrameStack;
 
-   void pushDebugFrame(S32 stackIndex);
+   inline ConsoleStack getFrameStack() { return gFrameStack; }
+   inline void pushStackFrame(ConsoleFrame* frame) { gFrameStack.push_back(frame); }
+   inline ConsoleFrame* popStackFrame() { ConsoleFrame* last = gFrameStack.last(); gFrameStack.pop_back(); return last; }
+   inline ConsoleFrame* getCurrentStackFrame() { return getFrameStack().empty() ? NULL : gFrameStack.last(); }
+   inline ConsoleFrame* getStackFrame(S32 idx) { return gFrameStack[idx]; }
 
-   U32 getStackDepth() const
-   {
-      return mStackDepth;
-   }
+   inline Vector<Con::Module*> gScriptModules;
 
-   Dictionary& getCurrentFrame()
-   {
-      return *(stack[mStackDepth - 1]);
-   }
+   inline Vector<Con::Module*> getAllScriptModules() { return gScriptModules; }
+   Con::Module* findScriptModuleForFile(const char* fileName);
+   // Convenience functions for getting the execution context
+   inline const char* getCurrentScriptModulePath() { return getCurrentStackFrame() && getCurrentStackFrame()->module ? getCurrentStackFrame()->module->getPath() : NULL; }
+   inline const char* getCurrentScriptModuleName() { return getCurrentStackFrame() && getCurrentStackFrame()->module ? getCurrentStackFrame()->module->getName() : NULL; }
+   inline Con::Module* getCurrentScriptModule() { return getCurrentStackFrame() ? getCurrentStackFrame()->module : NULL; }
 
-   Dictionary& getFrameAt(S32 depth)
-   {
-      return *(stack[depth]);
-   }
-
-   /// @}
-
-   /// Run integrity checks for debugging.
-   void validate();
-};
-
-namespace Con
-{
-   /// The current $instantGroup setting.
-   extern String gInstantGroup;
+   inline bool gTraceOn;
 }
 
 /// @}

+ 7 - 8
Engine/source/console/engineDoc.cpp

@@ -26,7 +26,6 @@
 #include "console/engineAPI.h"
 #include "core/stream/fileStream.h"
 #include "console/consoleInternal.h"
-#include "console/compiler.h"
 
 #define USE_UNDOCUMENTED_GROUP
 
@@ -113,10 +112,10 @@ static void dumpVariable(  Stream& stream,
                            const char* inClass = NULL )
 {
    // Skip variables defined in script.
-   
-   if( entry->type <= Dictionary::Entry::TypeInternalString )
+
+   if( entry->value.getType() <= ConsoleValueType::cvString )
       return;
-         
+
    // Skip internals... don't export them.
    if (  entry->mUsage &&
          ( dStrstr( entry->mUsage, "@hide" ) || dStrstr( entry->mUsage, "@internal" ) ) )
@@ -146,10 +145,10 @@ static void dumpVariable(  Stream& stream,
       if( nameComponents.size() > 1 && Con::lookupNamespace( nameComponents.first().c_str() + 1 )->mClassRep )
          return;
    }
-            
+
    // Skip variables for which we can't decipher their type.
 
-   ConsoleBaseType* type = ConsoleBaseType::getType( entry->type );
+   ConsoleBaseType* type = ConsoleBaseType::getType( entry->value.getConsoleType()->consoleType );
    if( !type )
    {
       Con::errorf( "Can't find type for variable '%s'", entry->name );
@@ -204,9 +203,9 @@ static void dumpVariable(  Stream& stream,
 
 static void dumpVariables( Stream& stream, const char* inClass = NULL )
 {
-   const U32 hashTableSize = gEvalState.globalVars.hashTable->size;
+   const U32 hashTableSize = Con::gGlobalVars.hashTable->size;
    for( U32 i = 0; i < hashTableSize; ++ i )
-      for( Dictionary::Entry* entry = gEvalState.globalVars.hashTable->data[ i ]; entry != NULL; entry = entry->nextEntry )
+      for( Dictionary::Entry* entry = Con::gGlobalVars.hashTable->data[ i ]; entry != NULL; entry = entry->nextEntry )
          dumpVariable( stream, entry, inClass );
 }
 

+ 1 - 3
Engine/source/console/fileSystemFunctions.cpp

@@ -24,9 +24,7 @@
 #include "console/console.h"
 #include "console/consoleInternal.h"
 #include "console/engineAPI.h"
-#include "console/ast.h"
 #include "core/stream/fileStream.h"
-#include "console/compiler.h"
 #include "platform/platformInput.h"
 #include "torqueConfig.h"
 #include "core/frameAllocator.h"
@@ -420,7 +418,7 @@ DefineEngineFunction(isScriptFile, bool, (const char* fileName), ,
 
    "@ingroup FileSystem")
 {
-   return Torque::FS::IsScriptFile(fileName);
+   return Con::isScriptFile(fileName);
 }
 
 DefineEngineFunction( IsDirectory, bool, ( const char* directory ),,

+ 45 - 0
Engine/source/console/module.h

@@ -0,0 +1,45 @@
+#ifndef _SCRIPT_MODULE_H_
+#define _SCRIPT_MODULE_H_
+#include "runtime.h"
+#include "console/console.h"
+#include "platform/types.h"
+
+namespace Con
+{
+   class Module
+   {
+   private:
+      S32 mRefCount = 0;
+   public:
+      Module() = default;
+      virtual ~Module() = default;
+
+      void incRefCount() { mRefCount++; }
+      void decRefCount() { mRefCount--; if (!mRefCount) delete this; }
+      virtual const char* getFunctionArgs(StringTableEntry functionName, U32 functionOffset) = 0;
+      virtual const char* getPath() = 0;
+      virtual const char* getName() = 0;
+
+      virtual EvalResult exec(U32 offset, const char* fnName, Namespace* ns, U32 argc,
+                              ConsoleValue* argv, bool noCalls, StringTableEntry packageName,
+                              S32 setFrame = -1) = 0;
+      virtual void findBreakLine(U32 ip, U32& line, U32& instruction) = 0;
+      virtual const char *getFileLine(U32 ip) = 0;
+
+      /// Returns the first breakable line or 0 if none was found.
+      /// @param lineNumber The one based line number.
+      virtual U32 findFirstBreakLine(U32 lineNumber) = 0;
+
+      /// Set a OP_BREAK instruction on a line. If a break
+      /// is not possible on that line it returns false.
+      /// @param lineNumber The one based line number.
+      virtual bool setBreakpoint(U32 lineNumber) = 0;
+
+      virtual void setAllBreaks() = 0;
+      virtual void clearAllBreaks() = 0;
+      virtual void clearBreakpoint(U32 lineNumber) = 0;
+      virtual Vector<U32> getBreakableLines() = 0;
+   };
+}
+
+#endif

+ 0 - 2
Engine/source/console/propertyParsing.cpp

@@ -35,8 +35,6 @@
 // Property system includes:
 #include "console/propertyParsing.h"
 
-extern ExprEvalState gEvalState;
-
 namespace PropertyInfo
 {
    //-----------------------------------------------------------------------------

+ 112 - 0
Engine/source/console/runtime.h

@@ -0,0 +1,112 @@
+#ifndef _RUNTIME_H_
+#define _RUNTIME_H_
+
+#include "console/console.h"
+
+namespace Con
+{
+   struct EvalResult
+   {
+      bool valid;
+      ConsoleValue value;
+      String error;
+
+   public:
+      EvalResult() {}
+
+      EvalResult(ConsoleValue&& pValue)
+      {
+         valid = true;
+         value = (ConsoleValue&&)pValue;
+      }
+
+      EvalResult(String errorMessage)
+      {
+         valid = false;
+         error = errorMessage;
+      }
+   };
+
+   struct Error
+   {
+      const char* message;
+   };
+
+   struct SyntaxError : Error {};
+
+   class Stack
+   {
+      class Frame
+      {
+      public:
+         ConsoleValue* lookup(const char*);
+      };
+
+   public:
+      S32 getDepth();
+      Frame getFrame(S32 idx);
+   };
+
+   class Runtime
+   {
+   private:
+      Stack mStack;
+   public:
+      virtual ~Runtime() = default;
+      virtual Stack getStack() { return mStack; }
+
+      /// Convert from a relative script path to an absolute script path.
+      ///
+      /// This is used in (among other places) the exec() script function, which
+      /// takes a parameter indicating a script file and executes it. Script paths
+      /// can be one of:
+      ///      - <b>Absolute:</b> <i>fps/foo/bar.tscript</i> Paths of this sort are passed
+      ///        through.
+      ///      - <b>Mod-relative:</b> <i>~/foo/bar.tscript</i> Paths of this sort have their
+      ///        replaced with the name of the current mod.
+      ///      - <b>File-relative:</b> <i>./baz/blip.tscript</i> Paths of this sort are
+      ///        calculated relative to the path of the current scripting file.
+      ///
+      /// @note This function determines paths relative to the currently executing
+      ///       CodeBlock. Calling it outside of script execution will result in
+      ///       it directly copying src to filename, since it won't know to what the
+      ///       path is relative!
+      ///
+      /// @param  filename    Pointer to string buffer to fill with absolute path.
+      /// @param  size        Size of buffer pointed to by filename.
+      /// @param  src         Original, possibly relative script path.
+      bool expandScriptFilename(char *filename, U32 size, const char *src);
+      bool expandToolScriptFilename(char *filename, U32 size, const char *src);
+      bool collapseScriptFilename(char *filename, U32 size, const char *src);
+
+      virtual void expandEscapedCharacters(char* dest, const char* src) = 0;
+      virtual bool collapseEscapedCharacters(char* buf) = 0;
+
+      /// Evaluate an arbitrary chunk of code.
+      ///
+      /// @param  string   Buffer containing code to execute.
+      /// @param  echo     Should we echo the string to the console?
+      /// @param  fileName Indicate what file this code is coming from; used in error reporting and such.
+      /// NOTE: This function restores the console stack on return.
+      virtual EvalResult evaluate(const char* string, bool echo = false, const char *fileName = NULL) = 0;
+
+      virtual EvalResult evaluate(const char* string, S32 frame, bool echo = false, const char *fileName = NULL) = 0;
+
+      /// Evaluate an arbitrary line of script.
+      ///
+      /// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
+      /// NOTE: This function restores the console stack on return.
+      virtual EvalResult evaluatef(const char* string, ...) = 0;
+
+      /// Executes a script file and compiles it for use in script.
+      ///
+      /// @param  fileName File name that is the script to be executed and compiled.
+      /// @param noCalls Deprecated
+      /// @param journalScript Deprecated
+      ///
+      /// @return True if the script was successfully executed, false if not.
+      virtual bool executeFile(const char* fileName, bool noCalls, bool journalScript) = 0;
+   };
+}
+
+#endif

+ 71 - 0
Engine/source/console/script.h

@@ -0,0 +1,71 @@
+#ifndef _SCRIPT_H_
+#define _SCRIPT_H_
+
+#include "runtime.h"
+#include "core/stream/stream.h"
+#include "module.h"
+#include "core/util/tDictionary.h"
+
+namespace Con
+{
+   inline EvalResult gLastEvalResult;
+   inline EvalResult setLastEvalResult(EvalResult pLastEvalResult)
+   {
+      gLastEvalResult.valid = pLastEvalResult.valid;
+      gLastEvalResult.error = pLastEvalResult.error;
+      gLastEvalResult.value.setString(pLastEvalResult.value.getString());
+      return std::move(pLastEvalResult);
+   }
+   inline EvalResult getLastEvalResult() { return setLastEvalResult(std::move(gLastEvalResult)); };
+
+   bool runStream(Stream* byteCode, const char* fileName);
+
+   bool isCurrentScriptToolScript();
+
+
+   Module* getCurrentModule();
+
+   inline HashMap<S32, Runtime*> gRuntimes;
+   inline Runtime* getRuntime(S32 pRuntimeId = 0) { return gRuntimes[pRuntimeId]; }
+   inline void registerRuntime(S32 pRuntimeId, Runtime* pRuntime)
+   {
+      AssertFatal(gRuntimes[pRuntimeId] == NULL, "A runtime with that ID already exists");
+      gRuntimes[pRuntimeId] = pRuntime;
+   }
+
+
+   /// Evaluate an arbitrary chunk of code.
+   ///
+   /// @param  script   Buffer containing code to execute.
+   /// @param  echo     Should we echo the string to the console?
+   /// @param  fileName Indicate what file this code is coming from; used in error reporting and such.
+   /// NOTE: This function restores the console stack on return.
+   inline EvalResult evaluate(const char* script, bool echo = false, const char *fileName = NULL) { return setLastEvalResult(getRuntime()->evaluate(script, echo, fileName)); };
+
+   inline EvalResult evaluate(const char* script, S32 frame, bool echo = false, const char *fileName = NULL) { return setLastEvalResult(getRuntime()->evaluate(script, frame, echo, fileName)); };
+
+   /// Evaluate an arbitrary line of script.
+   ///
+   /// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
+   /// NOTE: This function restores the console stack on return.
+   inline EvalResult evaluatef(const char* string, ...)
+   {
+      va_list args;
+      va_start(args, string);
+      EvalResult result = setLastEvalResult(getRuntime()->evaluatef(string, args));
+      va_end(args);
+      return result;
+   };
+
+   /// Executes a script file and compiles it for use in script.
+   ///
+   /// @param  string   File name that is the script to be executed and compiled.
+   /// @param fileName Path to the file to execute
+   /// @param noCalls Deprecated
+   /// @param journalScript Deprecated
+   ///
+   /// @return True if the script was successfully executed, false if not.
+   inline bool executeFile(const char* fileName, bool noCalls, bool journalScript) { return getRuntime()->executeFile(fileName, noCalls, journalScript); };
+}
+
+#endif

+ 5 - 4
Engine/source/console/scriptFilename.cpp

@@ -23,12 +23,12 @@
 #include "platform/platform.h"
 #include "console/scriptFilename.h"
 
+#include "consoleInternal.h"
 #include "core/frameAllocator.h"
 #include "core/tSimpleHashTable.h"
 #include "core/strings/stringFunctions.h"
 #include "core/stringTable.h"
 #include "console/engineAPI.h"
-#include "console/compiler.h"
 
 
 namespace Con
@@ -88,8 +88,8 @@ bool expandToolScriptFilename(char *filename, U32 size, const char *src)
    // same way the old code did as it is now possible that something could
    // be expanded if the name or mod is NULL. This was previously not the case.
 
-   const StringTableEntry cbMod = CodeBlock::getCurrentCodeBlockModName();
-   const StringTableEntry cbFullPath = CodeBlock::getCurrentCodeBlockFullPath();
+   const StringTableEntry cbMod = Con::getCurrentScriptModuleName();
+   const StringTableEntry cbFullPath = Con::getCurrentScriptModulePath();
 
    char varBuf[1024], modBuf[1024];
    const char *ptr = src;
@@ -216,7 +216,8 @@ bool expandToolScriptFilename(char *filename, U32 size, const char *src)
 
 bool expandOldScriptFilename(char *filename, U32 size, const char *src)
 {
-   const StringTableEntry cbName = CodeBlock::getCurrentCodeBlockName();
+   const StringTableEntry cbName = Con::getCurrentScriptModuleName();
+
    if (!cbName)
    {
       dStrcpy(filename, src, size);

+ 4 - 7
Engine/source/console/simDatablock.cpp

@@ -27,6 +27,7 @@
 #include "platform/platform.h"
 #include "console/simDatablock.h"
 
+#include "script.h"
 #include "console/console.h"
 #include "console/consoleInternal.h"
 #include "console/engineAPI.h"
@@ -34,7 +35,6 @@
 #include "T3D/gameBase/gameConnection.h"
 
 #include "core/stream/bitStream.h"
-#include "console/compiler.h"
 
 IMPLEMENT_CO_DATABLOCK_V1(SimDataBlock);
 SimObjectId SimDataBlock::sNextObjectId = DataBlockObjectIdFirst;
@@ -252,17 +252,14 @@ void SimDataBlock::performSubstitutions(SimDataBlock* dblock, const SimObject* o
 
          b[0] = '\0';
 
-         // perform the statement evaluation
-         Compiler::gSyntaxError = false;
-         //Con::errorf("EVAL [%s]", avar("return %s;", buffer));
-         const char *result = Con::evaluate(avar("return %s;", buffer), false, 0);
-         if (Compiler::gSyntaxError)
+         Con::EvalResult evalResult = Con::evaluate(avar("return %s;", buffer), false, 0);
+         if (evalResult.valid)
          {
             Con::errorf("Field Substitution Failed: field=\"%s\" substitution=\"%s\" -- syntax error", 
                substitutions[i]->mSlot, substitutions[i]->mValue);
-            Compiler::gSyntaxError = false;
             return;
          }
+         const char* result = evalResult.value;
 
          // output a runtime console error when a substitution produces and empty result.
          if (result == 0 || result[0] == '\0')

+ 1 - 4
Engine/source/console/simEvents.cpp

@@ -25,9 +25,6 @@
 #include "platform/threads/semaphore.h"
 #include "console/simEvents.h"
 
-// Stupid globals not declared in a header
-extern ExprEvalState gEvalState;
-
 SimConsoleEvent::SimConsoleEvent(S32 argc, ConsoleValue *argv, bool onObject)
 {
    mOnObject = onObject;
@@ -79,7 +76,7 @@ void SimConsoleEvent::process(SimObject* object)
             Namespace::Entry* nse = ns->lookup( StringTable->insert( func ) );
             if( nse )
                // Execute.
-               nse->execute( mArgc, mArgv, &gEvalState );
+               nse->execute( mArgc, mArgv, object );
          }
       }
 

+ 3 - 4
Engine/source/console/simManager.cpp

@@ -20,6 +20,7 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#include "script.h"
 #include "platform/platform.h"
 #include "platform/threads/mutex.h"
 #include "console/simBase.h"
@@ -36,8 +37,6 @@
 #include "platform/profiler.h"
 #include "math/mMathFn.h"
 
-extern ExprEvalState gEvalState;
-
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 
@@ -341,9 +340,9 @@ SimObject* findObject(const char* name)
 
    if (c == '%')
    {
-      if (gEvalState.getStackDepth())
+      if (!Con::getFrameStack().empty())
       {
-         Dictionary::Entry* ent = gEvalState.getCurrentFrame().lookup(StringTable->insert(name));
+         Dictionary::Entry* ent = Con::getCurrentStackFrame()->lookup(StringTable->insert(name));
 
          if (ent)
             return Sim::findObject(ent->getIntValue());

+ 4 - 5
Engine/source/console/simObject.cpp

@@ -35,7 +35,6 @@
 #include "console/simPersistID.h"
 #include "console/typeValidators.h"
 #include "console/arrayObject.h"
-#include "console/codeBlock.h"
 #include "core/frameAllocator.h"
 #include "core/stream/fileStream.h"
 #include "core/fileObject.h"
@@ -2479,7 +2478,7 @@ static void sEnumCallback( EngineObject* object )
    if( !simObject )
       return;
       
-   Con::evaluatef( "%s( %i );", sEnumCallbackFunction, simObject->getId() );
+   Con::executef(sEnumCallbackFunction, simObject->getId());
 }
 
 DefineEngineFunction( debugEnumInstances, void, ( const char* className, const char* functionName ),,
@@ -2645,10 +2644,10 @@ DefineEngineMethod( SimObject, dumpMethods, ArrayObject*, (),,
       str.append( e->getPrototypeString() );
 
       str.append( '\n' );
-      if( e->mCode && e->mCode->fullPath )
-         str.append( e->mCode->fullPath );
+      if( e->mModule && e->mModule->getPath() )
+         str.append( e->mModule->getPath() );
       str.append( '\n' );
-      if( e->mCode )
+      if( e->mModule )
          str.append( String::ToString( e->mFunctionLineNumber ) );
 
       str.append( '\n' );

+ 2 - 1
Engine/source/console/simObjectMemento.cpp

@@ -23,6 +23,7 @@
 #include "platform/platform.h"
 #include "console/simObjectMemento.h"
 
+#include "script.h"
 #include "console/simObject.h"
 #include "console/simDatablock.h"
 #include "core/stream/memStream.h"
@@ -95,7 +96,7 @@ SimObject *SimObjectMemento::restore() const
 
       // Read the object.
 
-      const UTF8* result = Con::evaluate( mState );
+      const UTF8* result = Con::evaluate( mState ).value;
 
       // Restore the redefine behavior.
 

+ 72 - 117
Engine/source/console/telnetDebugger.cpp

@@ -28,10 +28,9 @@
 #include "console/engineAPI.h"
 #include "core/stringTable.h"
 #include "console/consoleInternal.h"
-#include "console/ast.h"
-#include "console/compiler.h"
 #include "core/util/journal/process.h"
 #include "core/module.h"
+#include "script.h"
 
 
 MODULE_BEGIN( TelnetDebugger )
@@ -169,7 +168,7 @@ TelnetDebugger::TelnetDebugger()
    // Add the version number in a global so that
    // scripts can detect the presence of the
    // "enhanced" debugger features.
-   Con::evaluatef( "$dbgVersion = %d;", Version );
+   Con::setIntVariable("dbgVersion", Version);
 }
 
 TelnetDebugger::Breakpoint **TelnetDebugger::findBreakpoint(StringTableEntry fileName, S32 lineNumber)
@@ -380,7 +379,7 @@ void TelnetDebugger::checkDebugRecv()
    }
 }
 
-void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
+void TelnetDebugger::executionStopped(Con::Module *module, U32 lineNumber)
 {
    if(mProgramPaused)
       return;
@@ -392,13 +391,13 @@ void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
       return;
    }
 
-   Breakpoint **bp = findBreakpoint(code->name, lineNumber);
+   Breakpoint **bp = findBreakpoint(module->getName(), lineNumber);
    if(!bp)
       return;
    
    Breakpoint *brk = *bp;
    mProgramPaused = true;
-   Con::evaluatef("$Debug::result = %s;", brk->testExpression);
+   Con::setVariable("$Debug::result", brk->testExpression);
    if(Con::getBoolVariable("$Debug::result"))
    {
       brk->curCount++;
@@ -406,7 +405,7 @@ void TelnetDebugger::executionStopped(CodeBlock *code, U32 lineNumber)
       {
          brk->curCount = 0;
          if(brk->clearOnHit)
-            removeBreakpoint(code->name, lineNumber);
+            removeBreakpoint(module->getName(), lineNumber);
          breakProcess();
       }
    }
@@ -418,8 +417,8 @@ void TelnetDebugger::pushStackFrame()
    if(mState == NotConnected)
       return;
 
-   if(mBreakOnNextStatement && mStackPopBreakIndex > -1 && 
-      gEvalState.getStackDepth() > mStackPopBreakIndex)
+   if(mBreakOnNextStatement && mStackPopBreakIndex > -1 &&
+      Con::getFrameStack().size() > mStackPopBreakIndex)
       setBreakOnNextStatement( false );
 }
 
@@ -428,7 +427,7 @@ void TelnetDebugger::popStackFrame()
    if(mState == NotConnected)
       return;
 
-   if(mStackPopBreakIndex > -1 && gEvalState.getStackDepth()-1 <= mStackPopBreakIndex)
+   if(mStackPopBreakIndex > -1 && Con::getFrameStack().size()-1 <= mStackPopBreakIndex)
       setBreakOnNextStatement( true );
 }
 
@@ -461,14 +460,14 @@ void TelnetDebugger::sendBreak()
 
    S32 last = 0;
 
-   for(S32 i = (S32) gEvalState.getStackDepth() - 1; i >= last; i--)
+   for(S32 i = (S32) Con::getFrameStack().size() - 1; i >= last; i--)
    {
-      CodeBlock *code = gEvalState.stack[i]->code;
+      Con::Module *module = Con::getStackFrame(i)->module;
       const char *file = "<none>";
-      if (code && code->name && code->name[0])
-         file = code->name;
+      if (module && module->getName() && module->getName()[0])
+         file = module->getName();
 
-      Namespace *ns = gEvalState.stack[i]->scopeNamespace;
+      Namespace *ns = Con::getStackFrame(i)->scopeNamespace;
       scope[0] = 0;
       if ( ns ) {
 
@@ -482,15 +481,15 @@ void TelnetDebugger::sendBreak()
          }
       }
 
-      const char *function = gEvalState.stack[i]->scopeName;
+      const char *function = Con::getStackFrame(i)->scopeName;
       if ((!function) || (!function[0]))
          function = "<none>";
       dStrcat( scope, function, MaxCommandSize );
 
       U32 line=0, inst;
-      U32 ip = gEvalState.stack[i]->ip;
-      if (code)
-         code->findBreakLine(ip, line, inst);
+      U32 ip = Con::getStackFrame(i)->ip;
+      if (module)
+         module->findBreakLine(ip, line, inst);
       dSprintf(buffer, MaxCommandSize, " %s %d %s", file, line, scope);
       send(buffer);
    }
@@ -579,7 +578,7 @@ void TelnetDebugger::removeVariableBreakpoint(const char*)
    send("removeVariableBreakpoint\r\n");
 }
 
-void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
+void TelnetDebugger::addAllBreakpoints(Con::Module *module)
 {
    if(mState == NotConnected)
       return;
@@ -590,14 +589,14 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
    {
       // TODO: This assumes that the OS file names are case 
       // insensitive... Torque needs a dFilenameCmp() function.
-      if( dStricmp( cur->fileName, code->name ) == 0 )
+      if( dStricmp( cur->fileName, module->getName() ) == 0 )
       {
-         cur->code = code;
+         cur->module = module;
 
          // Find the fist breakline starting from and
          // including the requested breakline.
-         S32 newLine = code->findFirstBreakLine(cur->lineNumber);
-         if (newLine <= 0) 
+         S32 newLine = module->findFirstBreakLine(cur->lineNumber);
+         if (newLine <= 0)
          {
             char buffer[MaxCommandSize];
             dSprintf(buffer, MaxCommandSize, "BRKCLR %s %d\r\n", cur->fileName, cur->lineNumber);
@@ -638,7 +637,7 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
             cur->lineNumber = newLine;
          }
 
-         code->setBreakpoint(cur->lineNumber);
+         module->setBreakpoint(cur->lineNumber);
       }
 
       cur = cur->next;
@@ -646,7 +645,7 @@ void TelnetDebugger::addAllBreakpoints(CodeBlock *code)
 
    // Enable all breaks if a break next was set.
    if (mBreakOnNextStatement)
-       code->setAllBreaks();
+       module->setAllBreaks();
 }
 
 void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S32 passCount, const char *evalString)
@@ -668,12 +667,12 @@ void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S
    {
       // Note that if the code block is not already 
       // loaded it is handled by addAllBreakpoints.
-      CodeBlock* code = CodeBlock::find(fileName);
-      if (code)
+      Con::Module* module = Con::findScriptModuleForFile(fileName);
+      if (module)
       {
          // Find the fist breakline starting from and
          // including the requested breakline.
-         S32 newLine = code->findFirstBreakLine(line);
+         S32 newLine = module->findFirstBreakLine(line);
          if (newLine <= 0) 
          {
             char buffer[MaxCommandSize];
@@ -703,11 +702,11 @@ void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S
             line = newLine;
          }
 
-         code->setBreakpoint(line);
+         module->setBreakpoint(line);
       }
 
       Breakpoint *brk = new Breakpoint;
-      brk->code = code;
+      brk->module = module;
       brk->fileName = fileName;
       brk->lineNumber = line;
       brk->passCount = passCount;
@@ -719,13 +718,13 @@ void TelnetDebugger::addBreakpoint(const char *fileName, S32 line, bool clear, S
    }
 }
 
-void TelnetDebugger::removeBreakpointsFromCode(CodeBlock *code)
+void TelnetDebugger::removeBreakpointsFromCode(Con::Module *code)
 {
    Breakpoint **walk = &mBreakpoints;
    Breakpoint *cur;
    while((cur = *walk) != NULL)
    {
-      if(cur->code == code)
+      if(cur->module == code)
       {
          dFree(cur->testExpression);
          *walk = cur->next;
@@ -744,8 +743,8 @@ void TelnetDebugger::removeBreakpoint(const char *fileName, S32 line)
    {
       Breakpoint *brk = *bp;
       *bp = brk->next;
-     if ( brk->code )
-          brk->code->clearBreakpoint(brk->lineNumber);
+     if ( brk->module )
+          brk->module->clearBreakpoint(brk->lineNumber);
       dFree(brk->testExpression);
       delete brk;
    }
@@ -757,8 +756,8 @@ void TelnetDebugger::removeAllBreakpoints()
    while(walk)
    {
       Breakpoint *temp = walk->next;
-     if ( walk->code )
-          walk->code->clearBreakpoint(walk->lineNumber);
+     if ( walk->module )
+          walk->module->clearBreakpoint(walk->lineNumber);
       dFree(walk->testExpression);
       delete walk;
       walk = temp;
@@ -781,23 +780,24 @@ void TelnetDebugger::debugContinue()
 
 void TelnetDebugger::setBreakOnNextStatement( bool enabled )
 {
+   Vector<Con::Module*> modules = Con::getAllScriptModules();
    if ( enabled )
    {
       // Apply breaks on all the code blocks.
-      for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
-         walk->setAllBreaks();
+      for(Con::Module** walk = modules.begin(); walk != modules.end(); walk++)
+         (*walk)->setAllBreaks();
       mBreakOnNextStatement = true;
    } 
    else if ( !enabled )
    {
       // Clear all the breaks on the codeblocks 
       // then go reapply the breakpoints.
-      for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
-         walk->clearAllBreaks();
+      for(Con::Module** walk = modules.begin(); walk != modules.end(); walk++)
+         (*walk)->clearAllBreaks();
       for(Breakpoint *w = mBreakpoints; w; w = w->next)
      {
-        if ( w->code )
-              w->code->setBreakpoint(w->lineNumber);
+        if ( w->module )
+              w->module->setBreakpoint(w->lineNumber);
      }
       mBreakOnNextStatement = false;
    }
@@ -838,7 +838,7 @@ void TelnetDebugger::debugStepOver()
       return;
 
    setBreakOnNextStatement( true );
-   mStackPopBreakIndex = gEvalState.getStackDepth();
+   mStackPopBreakIndex = Con::getFrameStack().size();
    mProgramPaused = false;
    send("RUNNING\r\n");
 }
@@ -849,7 +849,7 @@ void TelnetDebugger::debugStepOut()
       return;
 
    setBreakOnNextStatement( false );
-   mStackPopBreakIndex = gEvalState.getStackDepth() - 1;
+   mStackPopBreakIndex = Con::getFrameStack().size() - 1;
    if ( mStackPopBreakIndex == 0 )
       mStackPopBreakIndex = -1;
    mProgramPaused = false;
@@ -858,84 +858,39 @@ void TelnetDebugger::debugStepOut()
 
 void TelnetDebugger::evaluateExpression(const char *tag, S32 frame, const char *evalBuffer)
 {
-   // Make sure we're passing a valid frame to the eval.
-   if ( frame > gEvalState.getStackDepth() )
-      frame = gEvalState.getStackDepth() - 1;
-   if ( frame < 0 )
-      frame = 0;
-
-   // Local variables use their own memory management and can't be queried by just executing
-   // TorqueScript, we have to go digging into the interpreter.
-   S32 evalBufferLen = dStrlen(evalBuffer);
-   bool isEvaluatingLocalVariable = evalBufferLen > 0 && evalBuffer[0] == '%';
-   if (isEvaluatingLocalVariable)
-   {
-      // See calculation of current frame in pushing a reference frame for console exec, we need access
-      // to the proper scope.
-      //frame = gEvalState.getTopOfStack() - frame - 1;
-      S32 stackIndex = gEvalState.getTopOfStack() - frame - 1;
-
-      const char* format = "EVALOUT %s %s\r\n";
-
-      gEvalState.pushDebugFrame(stackIndex);
-
-      Dictionary& stackFrame = gEvalState.getCurrentFrame();
-      StringTableEntry functionName = stackFrame.scopeName;
-      StringTableEntry namespaceName = stackFrame.scopeNamespace->mName;
-      StringTableEntry varToLookup = StringTable->insert(evalBuffer);
-
-      S32 registerId = stackFrame.code->variableRegisterTable.lookup(namespaceName, functionName, varToLookup);
-
-      if (registerId == -1)
-      {
-         // ERROR, can't read the variable!
-         send("EVALOUT \"\" \"\"");
-         return;
-      }
-
-      const char* varResult = gEvalState.getLocalStringVariable(registerId);
-
-      gEvalState.popFrame();
-
-      S32 len = dStrlen(format) + dStrlen(tag) + dStrlen(varResult);
-      char* buffer = new char[len];
-      dSprintf(buffer, len, format, tag, varResult[0] ? varResult : "\"\"");
-
-      send(buffer);
-      delete[] buffer;
-
-      return;
-   }
-
    // Build a buffer just big enough for this eval.
    const char* format = "return %s;";
-   dsize_t len = dStrlen( format ) + dStrlen( evalBuffer );
+   S32 len = dStrlen( format ) + dStrlen( evalBuffer );
    char* buffer = new char[ len ];
    dSprintf( buffer, len, format, evalBuffer );
+   Con::EvalResult evalResult = Con::evaluate(buffer, frame);
+   delete buffer;
+
+   if (!evalResult.valid)
+   {
+      // ERROR, can't read the variable!
+      send("EVALOUT \"\" \"\"");
+      return;
+   }
 
-   // Execute the eval.
-   CodeBlock *newCodeBlock = new CodeBlock();
-   ConsoleValue result = newCodeBlock->compileExec( NULL, buffer, false, frame );
-   delete [] buffer;
-   
-   // Create a new buffer that fits the result.
    format = "EVALOUT %s %s\r\n";
-   len = dStrlen( format ) + dStrlen( tag ) + dStrlen( result.getString() );
-   buffer = new char[ len ];
-   dSprintf( buffer, len, format, tag, result.getString()[0] ? result.getString() : "\"\"" );
 
-   send( buffer );
-   delete newCodeBlock;
-   delete [] buffer;
+   len = dStrlen(format) + dStrlen(tag) + dStrlen(evalResult.value);
+   buffer = new char[len];
+   dSprintf(buffer, len, format, tag, evalResult.value[0] ? evalResult.value : "\"\"");
+
+   send(buffer);
+   delete[] buffer;
 }
 
 void TelnetDebugger::dumpFileList()
 {
    send("FILELISTOUT ");
-   for(CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
+   Vector<Con::Module*> modules = Con::getAllScriptModules();
+   for(Con::Module** walk = modules.begin(); walk != modules.end(); walk++)
    {
-      send(walk->name);
-      if(walk->nextFile)
+      send((*walk)->getName());
+      if((walk + 1) != modules.end())
          send(" ");
    }
    send("\r\n");
@@ -944,15 +899,15 @@ void TelnetDebugger::dumpFileList()
 void TelnetDebugger::dumpBreakableList(const char *fileName)
 {
    fileName = StringTable->insert(fileName);
-   CodeBlock *file = CodeBlock::find(fileName);
+   Con::Module *file = Con::findScriptModuleForFile(fileName);
    char buffer[MaxCommandSize];
    if(file)
    {
-      dSprintf(buffer, MaxCommandSize, "BREAKLISTOUT %s %d", fileName, file->breakListSize >> 1);
+      dSprintf(buffer, MaxCommandSize, "BREAKLISTOUT %s %d", fileName, file->getBreakableLines().size() >> 1);
       send(buffer);
-      for(U32 i = 0; i < file->breakListSize; i += 2)
+      for(U32 i = 0; i < file->getBreakableLines().size(); i += 2)
       {
-         dSprintf(buffer, MaxCommandSize, " %d %d", file->breakList[i], file->breakList[i+1]);
+         dSprintf(buffer, MaxCommandSize, " %d %d", file->getBreakableLines()[i], file->getBreakableLines()[i+1]);
          send(buffer);
       }
       send("\r\n");
@@ -962,14 +917,14 @@ void TelnetDebugger::dumpBreakableList(const char *fileName)
 }
 
 
-void TelnetDebugger::clearCodeBlockPointers(CodeBlock *code)
+void TelnetDebugger::clearCodeBlockPointers(Con::Module *code)
 {
    Breakpoint **walk = &mBreakpoints;
    Breakpoint *cur;
    while((cur = *walk) != NULL)
    {
-      if(cur->code == code)
-         cur->code = NULL;
+      if(cur->module == code)
+         cur->module = NULL;
 
       walk = &cur->next;
    }

+ 6 - 7
Engine/source/console/telnetDebugger.h

@@ -26,8 +26,7 @@
 #ifndef _PLATFORM_PLATFORMNET_H_
 #include "platform/platformNet.h"
 #endif
-
-class CodeBlock;
+#include "module.h"
 
 /// Telnet debug service implementation.
 ///
@@ -75,7 +74,7 @@ class TelnetDebugger
    struct Breakpoint
    {
       StringTableEntry fileName;
-      CodeBlock *code;
+      Con::Module *module;
       U32 lineNumber;
       S32 passCount;
       S32 curCount;
@@ -105,7 +104,7 @@ class TelnetDebugger
    void evaluateExpression(const char *tag, S32 frame, const char *evalBuffer);
    void dumpFileList();
    void dumpBreakableList(const char *fileName);
-   void removeBreakpointsFromCode(CodeBlock *code);
+   void removeBreakpointsFromCode(Con::Module *code);
 
    void checkDebugRecv();
    void processLineBuffer(S32);
@@ -121,13 +120,13 @@ public:
    void process();
    void popStackFrame();
    void pushStackFrame();
-   void addAllBreakpoints(CodeBlock *code);
+   void addAllBreakpoints(Con::Module *module);
 
-   void clearCodeBlockPointers(CodeBlock *code);
+   void clearCodeBlockPointers(Con::Module *code);
 
    void breakProcess();
 
-   void executionStopped(CodeBlock *code, U32 lineNumber);
+   void executionStopped(Con::Module *module, U32 lineNumber);
    void send(const char *s);
    void setDebugParameters(S32 port, const char *password, bool waitForClient);
    void processConsoleLine(const char *consoleLine);

+ 0 - 0
Engine/source/console/CMDgram.y → Engine/source/console/torquescript/CMDgram.y


+ 125 - 126
Engine/source/console/CMDscan.cpp → Engine/source/console/torquescript/CMDscan.cpp

@@ -29,6 +29,10 @@
 
 #include <stdio.h>
 
+#include "compiler.h"
+#include "runtime.h"
+#include "console/script.h"
+
 
 /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
 #ifdef c_plusplus
@@ -551,11 +555,9 @@ char *yytext;
 #define YYLMAX 4096
 #define YY_NO_UNISTD_H
 
-#include <stdio.h>
 #include "platform/platform.h"
 #include "core/stringTable.h"
 #include "console/console.h"
-#include "console/compiler.h"
 #include "console/dynamicTypes.h"
 #include "core/strings/stringFunctions.h"
 
@@ -576,10 +578,7 @@ inline Token< T > MakeToken( T value, U32 lineNumber )
    return result;
 }
 
-#include "console/cmdgram.h"
-
-// HACK: C++17 and beyond can't use register keyword
-#define register
+#include "cmdgram.h"
 
 using namespace Compiler;
 
@@ -634,7 +633,7 @@ void CMDerror(const char * s, ...);
 // Reset the parser.
 void CMDrestart(FILE *in);
 
-#line 638 "CMDscan.cpp"
+#line 635 "CMDscan.cpp"
 
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
@@ -777,14 +776,14 @@ YY_MALLOC_DECL
 
 YY_DECL
 	{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
+    yy_state_type yy_current_state;
+    char *yy_cp, *yy_bp;
+    int yy_act;
 
-#line 108 "CMDscan.l"
+#line 105 "CMDscan.l"
 
          ;
-#line 788 "CMDscan.cpp"
+#line 785 "CMDscan.cpp"
 
 	if ( yy_init )
 		{
@@ -826,7 +825,7 @@ YY_DECL
 yy_match:
 		do
 			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+		    YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
 			if ( yy_accept[yy_current_state] )
 				{
 				yy_last_accepting_state = yy_current_state;
@@ -869,187 +868,187 @@ do_action:	/* This label is used only to access EOF actions. */
 
 case 1:
 YY_RULE_SETUP
-#line 110 "CMDscan.l"
+#line 107 "CMDscan.l"
 { }
 	YY_BREAK
 case 2:
 YY_RULE_SETUP
-#line 111 "CMDscan.l"
+#line 108 "CMDscan.l"
 { return(Sc_ScanDocBlock()); }
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 112 "CMDscan.l"
+#line 109 "CMDscan.l"
 ;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 113 "CMDscan.l"
+#line 110 "CMDscan.l"
 ;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 114 "CMDscan.l"
+#line 111 "CMDscan.l"
 {lineIndex++;}
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
-#line 115 "CMDscan.l"
+#line 112 "CMDscan.l"
 { return(Sc_ScanString(STRATOM)); }
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 116 "CMDscan.l"
+#line 113 "CMDscan.l"
 { return(Sc_ScanString(TAGATOM)); }
 	YY_BREAK
 case 8:
 YY_RULE_SETUP
-#line 117 "CMDscan.l"
+#line 114 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opEQ, lineIndex ); return opEQ; }
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 118 "CMDscan.l"
+#line 115 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opNE, lineIndex ); return opNE; }
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 119 "CMDscan.l"
+#line 116 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opGE, lineIndex ); return opGE; }
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 120 "CMDscan.l"
+#line 117 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opLE, lineIndex ); return opLE; }
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 121 "CMDscan.l"
+#line 118 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opAND, lineIndex ); return opAND; }
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 122 "CMDscan.l"
+#line 119 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opOR, lineIndex ); return opOR; }
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 123 "CMDscan.l"
+#line 120 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opCOLONCOLON, lineIndex ); return opCOLONCOLON; }
 	YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 124 "CMDscan.l"
+#line 121 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opMINUSMINUS, lineIndex ); return opMINUSMINUS; }
 	YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 125 "CMDscan.l"
+#line 122 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opPLUSPLUS, lineIndex ); return opPLUSPLUS; }
 	YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 126 "CMDscan.l"
+#line 123 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opSTREQ, lineIndex ); return opSTREQ; }
 	YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 127 "CMDscan.l"
+#line 124 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opSTRNE, lineIndex ); return opSTRNE; }
 	YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 128 "CMDscan.l"
+#line 125 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opSHL, lineIndex ); return opSHL; }
 	YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 129 "CMDscan.l"
+#line 126 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opSHR, lineIndex ); return opSHR; }
 	YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 130 "CMDscan.l"
+#line 127 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opPLASN, lineIndex ); return opPLASN; }
 	YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 131 "CMDscan.l"
+#line 128 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opMIASN, lineIndex ); return opMIASN; }
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 132 "CMDscan.l"
+#line 129 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opMLASN, lineIndex ); return opMLASN; }
 	YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 133 "CMDscan.l"
+#line 130 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opDVASN, lineIndex ); return opDVASN; }
 	YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 134 "CMDscan.l"
+#line 131 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opMODASN, lineIndex ); return opMODASN; }
 	YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 135 "CMDscan.l"
+#line 132 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opANDASN, lineIndex ); return opANDASN; }
 	YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 136 "CMDscan.l"
+#line 133 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opXORASN, lineIndex ); return opXORASN; }
 	YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 137 "CMDscan.l"
+#line 134 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opORASN, lineIndex ); return opORASN; }
 	YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 138 "CMDscan.l"
+#line 135 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opSLASN, lineIndex ); return opSLASN; }
 	YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 139 "CMDscan.l"
+#line 136 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opSRASN, lineIndex ); return opSRASN; }
 	YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 140 "CMDscan.l"
+#line 137 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opINTNAME, lineIndex ); return opINTNAME; }
 	YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 141 "CMDscan.l"
+#line 138 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( opINTNAMER, lineIndex ); return opINTNAMER; }
 	YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 142 "CMDscan.l"
+#line 139 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( '\n', lineIndex ); return '@'; }
 	YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 143 "CMDscan.l"
+#line 140 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( '\t', lineIndex ); return '@'; }
 	YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 144 "CMDscan.l"
+#line 141 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( ' ', lineIndex ); return '@'; }
 	YY_BREAK
 case 36:
 YY_RULE_SETUP
-#line 145 "CMDscan.l"
+#line 142 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( 0, lineIndex ); return '@'; }
 	YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 146 "CMDscan.l"
+#line 143 "CMDscan.l"
 { /* this comment stops syntax highlighting from getting messed up when editing the lexer in TextPad */
          int c = 0, l;
          for ( ; ; )
@@ -1075,222 +1074,222 @@ YY_RULE_SETUP
       }
 	YY_BREAK
 case 38:
-#line 170 "CMDscan.l"
+#line 167 "CMDscan.l"
 case 39:
-#line 171 "CMDscan.l"
+#line 168 "CMDscan.l"
 case 40:
-#line 172 "CMDscan.l"
+#line 169 "CMDscan.l"
 case 41:
-#line 173 "CMDscan.l"
+#line 170 "CMDscan.l"
 case 42:
-#line 174 "CMDscan.l"
+#line 171 "CMDscan.l"
 case 43:
-#line 175 "CMDscan.l"
+#line 172 "CMDscan.l"
 case 44:
-#line 176 "CMDscan.l"
+#line 173 "CMDscan.l"
 case 45:
-#line 177 "CMDscan.l"
+#line 174 "CMDscan.l"
 case 46:
-#line 178 "CMDscan.l"
+#line 175 "CMDscan.l"
 case 47:
-#line 179 "CMDscan.l"
+#line 176 "CMDscan.l"
 case 48:
-#line 180 "CMDscan.l"
+#line 177 "CMDscan.l"
 case 49:
-#line 181 "CMDscan.l"
+#line 178 "CMDscan.l"
 case 50:
-#line 182 "CMDscan.l"
+#line 179 "CMDscan.l"
 case 51:
-#line 183 "CMDscan.l"
+#line 180 "CMDscan.l"
 case 52:
-#line 184 "CMDscan.l"
+#line 181 "CMDscan.l"
 case 53:
-#line 185 "CMDscan.l"
+#line 182 "CMDscan.l"
 case 54:
-#line 186 "CMDscan.l"
+#line 183 "CMDscan.l"
 case 55:
-#line 187 "CMDscan.l"
+#line 184 "CMDscan.l"
 case 56:
-#line 188 "CMDscan.l"
+#line 185 "CMDscan.l"
 case 57:
-#line 189 "CMDscan.l"
+#line 186 "CMDscan.l"
 case 58:
-#line 190 "CMDscan.l"
+#line 187 "CMDscan.l"
 case 59:
-#line 191 "CMDscan.l"
+#line 188 "CMDscan.l"
 case 60:
-#line 192 "CMDscan.l"
+#line 189 "CMDscan.l"
 case 61:
 YY_RULE_SETUP
-#line 192 "CMDscan.l"
+#line 189 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( CMDtext[ 0 ], lineIndex ); return CMDtext[ 0 ]; }
 	YY_BREAK
 case 62:
 YY_RULE_SETUP
-#line 193 "CMDscan.l"
+#line 190 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwIN, lineIndex ); return(rwIN); }
 	YY_BREAK
 case 63:
 YY_RULE_SETUP
-#line 194 "CMDscan.l"
+#line 191 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwCASEOR, lineIndex ); return(rwCASEOR); }
 	YY_BREAK
 case 64:
 YY_RULE_SETUP
-#line 195 "CMDscan.l"
+#line 192 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwBREAK, lineIndex ); return(rwBREAK); }
 	YY_BREAK
 case 65:
 YY_RULE_SETUP
-#line 196 "CMDscan.l"
+#line 193 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwRETURN, lineIndex ); return(rwRETURN); }
 	YY_BREAK
 case 66:
 YY_RULE_SETUP
-#line 197 "CMDscan.l"
+#line 194 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwELSE, lineIndex ); return(rwELSE); }
 	YY_BREAK
 case 67:
 YY_RULE_SETUP
-#line 198 "CMDscan.l"
+#line 195 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwASSERT, lineIndex ); return(rwASSERT); }
 	YY_BREAK
 case 68:
 YY_RULE_SETUP
-#line 199 "CMDscan.l"
+#line 196 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwWHILE, lineIndex ); return(rwWHILE); }
 	YY_BREAK
 case 69:
 YY_RULE_SETUP
-#line 200 "CMDscan.l"
+#line 197 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwDO, lineIndex ); return(rwDO); }
 	YY_BREAK
 case 70:
 YY_RULE_SETUP
-#line 201 "CMDscan.l"
+#line 198 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwIF, lineIndex ); return(rwIF); }
 	YY_BREAK
 case 71:
 YY_RULE_SETUP
-#line 202 "CMDscan.l"
+#line 199 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwFOREACHSTR, lineIndex ); return(rwFOREACHSTR); }
 	YY_BREAK
 case 72:
 YY_RULE_SETUP
-#line 203 "CMDscan.l"
+#line 200 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwFOREACH, lineIndex ); return(rwFOREACH); }
 	YY_BREAK
 case 73:
 YY_RULE_SETUP
-#line 204 "CMDscan.l"
+#line 201 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwFOR, lineIndex ); return(rwFOR); }
 	YY_BREAK
 case 74:
 YY_RULE_SETUP
-#line 205 "CMDscan.l"
+#line 202 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwCONTINUE, lineIndex ); return(rwCONTINUE); }
 	YY_BREAK
 case 75:
 YY_RULE_SETUP
-#line 206 "CMDscan.l"
+#line 203 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwDEFINE, lineIndex ); return(rwDEFINE); }
 	YY_BREAK
 case 76:
 YY_RULE_SETUP
-#line 207 "CMDscan.l"
+#line 204 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwDECLARE, lineIndex ); return(rwDECLARE); }
 	YY_BREAK
 case 77:
 YY_RULE_SETUP
-#line 208 "CMDscan.l"
+#line 205 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwDECLARESINGLETON, lineIndex ); return(rwDECLARESINGLETON); }
 	YY_BREAK
 case 78:
 YY_RULE_SETUP
-#line 209 "CMDscan.l"
+#line 206 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwDATABLOCK, lineIndex ); return(rwDATABLOCK); }
 	YY_BREAK
 case 79:
 YY_RULE_SETUP
-#line 210 "CMDscan.l"
+#line 207 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwCASE, lineIndex ); return(rwCASE); }
 	YY_BREAK
 case 80:
 YY_RULE_SETUP
-#line 211 "CMDscan.l"
+#line 208 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwSWITCHSTR, lineIndex ); return(rwSWITCHSTR); }
 	YY_BREAK
 case 81:
 YY_RULE_SETUP
-#line 212 "CMDscan.l"
+#line 209 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwSWITCH, lineIndex ); return(rwSWITCH); }
 	YY_BREAK
 case 82:
 YY_RULE_SETUP
-#line 213 "CMDscan.l"
+#line 210 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwDEFAULT, lineIndex ); return(rwDEFAULT); }
 	YY_BREAK
 case 83:
 YY_RULE_SETUP
-#line 214 "CMDscan.l"
+#line 211 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwPACKAGE, lineIndex ); return(rwPACKAGE); }
 	YY_BREAK
 case 84:
 YY_RULE_SETUP
-#line 215 "CMDscan.l"
+#line 212 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( rwNAMESPACE, lineIndex ); return(rwNAMESPACE); }
 	YY_BREAK
 case 85:
 YY_RULE_SETUP
-#line 216 "CMDscan.l"
+#line 213 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( 1, lineIndex ); return INTCONST; }
 	YY_BREAK
 case 86:
 YY_RULE_SETUP
-#line 217 "CMDscan.l"
+#line 214 "CMDscan.l"
 { CMDlval.i = MakeToken< int >( 0, lineIndex ); return INTCONST; }
 	YY_BREAK
 case 87:
 YY_RULE_SETUP
-#line 218 "CMDscan.l"
+#line 215 "CMDscan.l"
 { return(Sc_ScanVar()); }
 	YY_BREAK
 case 88:
 YY_RULE_SETUP
-#line 220 "CMDscan.l"
+#line 216 "CMDscan.l"
 { return Sc_ScanIdent(); }
 	YY_BREAK
 case 89:
 YY_RULE_SETUP
-#line 221 "CMDscan.l"
+#line 217 "CMDscan.l"
 return(Sc_ScanHex());
 	YY_BREAK
 case 90:
 YY_RULE_SETUP
-#line 222 "CMDscan.l"
+#line 218 "CMDscan.l"
 { CMDtext[CMDleng] = 0; CMDlval.i = MakeToken< int >( dAtoi(CMDtext), lineIndex ); return INTCONST; }
 	YY_BREAK
 case 91:
 YY_RULE_SETUP
-#line 223 "CMDscan.l"
+#line 219 "CMDscan.l"
 return Sc_ScanNum();
 	YY_BREAK
 case 92:
 YY_RULE_SETUP
-#line 224 "CMDscan.l"
+#line 220 "CMDscan.l"
 return(ILLEGAL_TOKEN);
 	YY_BREAK
 case 93:
 YY_RULE_SETUP
-#line 225 "CMDscan.l"
+#line 221 "CMDscan.l"
 return(ILLEGAL_TOKEN);
 	YY_BREAK
 case 94:
 YY_RULE_SETUP
-#line 226 "CMDscan.l"
+#line 222 "CMDscan.l"
 ECHO;
 	YY_BREAK
-#line 1294 "CMDscan.cpp"
+#line 1291 "CMDscan.cpp"
 case YY_STATE_EOF(INITIAL):
 	yyterminate();
 
@@ -1433,9 +1432,9 @@ case YY_STATE_EOF(INITIAL):
 
 static int yy_get_next_buffer()
 	{
-	register char *dest = yy_current_buffer->yy_ch_buf;
-	register char *source = yytext_ptr;
-	register int number_to_move, i;
+    char *dest = yy_current_buffer->yy_ch_buf;
+    char *source = yytext_ptr;
+    int number_to_move, i;
 	int ret_val;
 
 	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
@@ -1563,14 +1562,14 @@ static int yy_get_next_buffer()
 
 static yy_state_type yy_get_previous_state()
 	{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
+    yy_state_type yy_current_state;
+    char *yy_cp;
 
 	yy_current_state = yy_start;
 
 	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
 		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+	    YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
 		if ( yy_accept[yy_current_state] )
 			{
 			yy_last_accepting_state = yy_current_state;
@@ -1602,10 +1601,10 @@ static yy_state_type yy_try_NUL_trans( yy_current_state )
 yy_state_type yy_current_state;
 #endif
 	{
-	register int yy_is_jam;
-	register char *yy_cp = yy_c_buf_p;
+    int yy_is_jam;
+    char *yy_cp = yy_c_buf_p;
 
-	register YY_CHAR yy_c = 1;
+    YY_CHAR yy_c = 1;
 	if ( yy_accept[yy_current_state] )
 		{
 		yy_last_accepting_state = yy_current_state;
@@ -1626,14 +1625,14 @@ yy_state_type yy_current_state;
 
 #ifndef YY_NO_UNPUT
 #ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
+static void yyunput( int c, char *yy_bp )
 #else
 static void yyunput( c, yy_bp )
 int c;
-register char *yy_bp;
+char *yy_bp;
 #endif
 	{
-	register char *yy_cp = yy_c_buf_p;
+    char *yy_cp = yy_c_buf_p;
 
 	/* undo effects of setting up yytext */
 	*yy_cp = yy_hold_char;
@@ -1641,10 +1640,10 @@ register char *yy_bp;
 	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
 		{ /* need to shift things up to make room */
 		/* +2 for EOB chars. */
-		register int number_to_move = yy_n_chars + 2;
-		register char *dest = &yy_current_buffer->yy_ch_buf[
+		int number_to_move = yy_n_chars + 2;
+		char *dest = &yy_current_buffer->yy_ch_buf[
 					yy_current_buffer->yy_buf_size + 2];
-		register char *source =
+		char *source =
 				&yy_current_buffer->yy_ch_buf[number_to_move];
 
 		while ( source > yy_current_buffer->yy_ch_buf )
@@ -2098,7 +2097,7 @@ yyconst char *s2;
 int n;
 #endif
 	{
-	register int i;
+    int i;
 	for ( i = 0; i < n; ++i )
 		s1[i] = s2[i];
 	}
@@ -2150,7 +2149,7 @@ int main()
 	return 0;
 	}
 #endif
-#line 226 "CMDscan.l"
+#line 222 "CMDscan.l"
 
 
 static const char *scanBuffer;
@@ -2341,7 +2340,7 @@ static int Sc_ScanDocBlock()
 static int Sc_ScanString(int ret)
 {
    CMDtext[CMDleng - 1] = 0;
-   if(!collapseEscape(CMDtext+1))
+   if(!TorqueScript::getRuntime()->collapseEscapedCharacters(CMDtext+1))
       return -1;
 
    dsize_t bufferLen = dStrlen( CMDtext );

+ 0 - 0
Engine/source/console/CMDscan.l → Engine/source/console/torquescript/CMDscan.l


+ 13 - 5
Engine/source/console/ast.h → Engine/source/console/torquescript/ast.h

@@ -23,8 +23,9 @@
 #ifndef _AST_H_
 #define _AST_H_
 
-class ExprEvalState;
-class Namespace;
+#include "evalState.h"
+#include "platform/types.h"
+
 class SimObject;
 class SimGroup;
 class CodeStream;
@@ -101,7 +102,7 @@ struct StmtNode
 #ifndef DEBUG_AST_NODES
 #  define DBG_STMT_TYPE(s) virtual const char* dbgStmtType() const { return "#s"; }
 #else
-#  define DBG_STMT_TYPE(s) 
+#  define DBG_STMT_TYPE(s)
 #endif
 
 struct BreakStmtNode : StmtNode
@@ -592,7 +593,14 @@ struct FunctionDeclStmtNode : StmtNode
    DBG_STMT_TYPE(FunctionDeclStmtNode);
 };
 
-extern StmtNode* gStatementList;
-extern ExprEvalState gEvalState;
+namespace Script
+{
+   inline ExprEvalState gEvalState;
+
+   inline StmtNode *gStatementList;
+   inline StmtNode *gAnonFunctionList;
+   inline U32 gAnonFunctionID = 0;
+}
+
 
 #endif

+ 1 - 1
Engine/source/console/astAlloc.cpp → Engine/source/console/torquescript/astAlloc.cpp

@@ -21,7 +21,7 @@
 //-----------------------------------------------------------------------------
 
 #include "console/console.h"
-#include "console/compiler.h"
+#include "compiler.h"
 #include "console/consoleInternal.h"
 
 using namespace Compiler;

+ 3 - 8
Engine/source/console/astNodes.cpp → Engine/source/console/torquescript/astNodes.cpp

@@ -22,15 +22,10 @@
 
 #include "platform/platform.h"
 #include "console/console.h"
-#include "console/telnetDebugger.h"
 
-#include "console/ast.h"
-#include "core/tAlgorithm.h"
+#include "ast.h"
 
-#include "core/strings/findMatch.h"
-#include "console/consoleInternal.h"
-#include "core/stream/fileStream.h"
-#include "console/compiler.h"
+#include "compiler.h"
 
 #include "console/simBase.h"
 
@@ -40,7 +35,7 @@ struct Token
    T value;
    S32 lineNumber;
 };
-#include "console/cmdgram.h"
+#include "cmdgram.h"
 
 namespace Compiler
 {

+ 0 - 0
Engine/source/console/bison.bat → Engine/source/console/torquescript/bison.bat


+ 0 - 0
Engine/source/console/bison.simple → Engine/source/console/torquescript/bison.simple


+ 2 - 4
Engine/source/console/cmdgram.cpp → Engine/source/console/torquescript/cmdgram.cpp

@@ -95,7 +95,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include "console/console.h"
-#include "console/compiler.h"
+#include "compiler.h"
 #include "console/consoleInternal.h"
 #include "core/strings/stringFunctions.h"
 
@@ -1581,7 +1581,7 @@ case 2:
     break;}
 case 3:
 #line 169 "cmdgram.y"
-{ if(!gStatementList) { gStatementList = yyvsp[0].stmt; } else { gStatementList->append(yyvsp[0].stmt); } ;
+{ if(!Script::gStatementList) { Script::gStatementList = yyvsp[0].stmt; } else { Script::gStatementList->append(yyvsp[0].stmt); } ;
     break;}
 case 4:
 #line 174 "cmdgram.y"
@@ -2390,5 +2390,3 @@ yyerrhandle:
   goto yynewstate;
 }
 #line 617 "cmdgram.y"
-
-

+ 5 - 0
Engine/source/console/cmdgram.h → Engine/source/console/torquescript/cmdgram.h

@@ -1,3 +1,6 @@
+#ifndef _CMDGRAM_H_
+#define _CMDGRAM_H_
+
 typedef union {
    Token< char >           c;
    Token< int >            i;
@@ -90,3 +93,5 @@ typedef union {
 
 
 extern YYSTYPE CMDlval;
+
+#endif

+ 19 - 61
Engine/source/console/codeBlock.cpp → Engine/source/console/torquescript/codeBlock.cpp

@@ -21,10 +21,11 @@
 //-----------------------------------------------------------------------------
 
 #include "console/console.h"
-#include "console/compiler.h"
-#include "console/codeBlock.h"
+#include "compiler.h"
+#include "codeBlock.h"
+#include "ast.h"
+
 #include "console/telnetDebugger.h"
-#include "console/ast.h"
 #include "core/strings/unicode.h"
 #include "core/strings/stringFunctions.h"
 #include "core/stringTable.h"
@@ -34,8 +35,7 @@ using namespace Compiler;
 
 bool           CodeBlock::smInFunction = false;
 CodeBlock *    CodeBlock::smCodeBlockList = NULL;
-CodeBlock *    CodeBlock::smCurrentCodeBlock = NULL;
-ConsoleParser *CodeBlock::smCurrentParser = NULL;
+TorqueScriptParser *CodeBlock::smCurrentParser = NULL;
 
 extern FuncVars gEvalFuncVars;
 extern FuncVars gGlobalScopeFuncVars;
@@ -52,8 +52,6 @@ CodeBlock::CodeBlock()
    globalFloats = NULL;
    functionFloats = NULL;
    lineBreakPairs = NULL;
-   breakList = NULL;
-   breakListSize = 0;
 
    refCount = 0;
    code = NULL;
@@ -68,7 +66,7 @@ CodeBlock::CodeBlock()
 CodeBlock::~CodeBlock()
 {
    // Make sure we aren't lingering in the current code block...
-   AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!");
+   AssertFatal(Con::getCurrentScriptModule() != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!");
 
    if (name)
       removeFromCodeList();
@@ -81,35 +79,10 @@ CodeBlock::~CodeBlock()
    delete[] globalFloats;
    delete[] functionFloats;
    delete[] code;
-   delete[] breakList;
 }
 
 //-------------------------------------------------------------------------
 
-StringTableEntry CodeBlock::getCurrentCodeBlockName()
-{
-   if (CodeBlock::getCurrentBlock())
-      return CodeBlock::getCurrentBlock()->name;
-   else
-      return NULL;
-}
-
-StringTableEntry CodeBlock::getCurrentCodeBlockFullPath()
-{
-   if (CodeBlock::getCurrentBlock())
-      return CodeBlock::getCurrentBlock()->fullPath;
-   else
-      return NULL;
-}
-
-StringTableEntry CodeBlock::getCurrentCodeBlockModName()
-{
-   if (CodeBlock::getCurrentBlock())
-      return CodeBlock::getCurrentBlock()->modPath;
-   else
-      return NULL;
-}
-
 CodeBlock *CodeBlock::find(StringTableEntry name)
 {
    for (CodeBlock *walk = CodeBlock::getCodeBlockList(); walk; walk = walk->nextFile)
@@ -309,8 +282,7 @@ void CodeBlock::calcBreakList()
    if (seqCount)
       size++;
 
-   breakList = new U32[size+3]; //lineBreakPairs plus pad
-   breakListSize = size;
+   breakList.setSize(size+3); //lineBreakPairs plus pad
    line = -1;
    seqCount = 0;
    size = 0;
@@ -502,10 +474,10 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
 
    STEtoCode = compileSTEtoCode;
 
-   gStatementList = NULL;
+   Script::gStatementList = NULL;
 
    // Set up the parser.
-   smCurrentParser = getParserForFile(fileName);
+   smCurrentParser = new TorqueScriptParser();
    AssertISV(smCurrentParser, avar("CodeBlock::compile - no parser available for '%s'!", fileName));
 
    // Now do some parsing.
@@ -536,9 +508,9 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
 
    CodeStream codeStream;
    U32 lastIp;
-   if (gStatementList)
+   if (Script::gStatementList)
    {
-      lastIp = compileBlock(gStatementList, codeStream, 0) + 1;
+      lastIp = compileBlock(Script::gStatementList, codeStream, 0) + 1;
    }
    else
    {
@@ -594,7 +566,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
    return true;
 }
 
-ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
+Con::EvalResult CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
 {
    AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
 
@@ -634,14 +606,14 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
    if (name)
       addToCodeList();
 
-   gStatementList = NULL;
-   
+   Script::gStatementList = NULL;
+
    // we are an eval compile if we don't have a file name associated (no exec)
    gIsEvalCompile = fileName == NULL;
    gFuncVars = gIsEvalCompile ? &gEvalFuncVars : &gGlobalScopeFuncVars;
 
    // Set up the parser.
-   smCurrentParser = getParserForFile(fileName);
+   smCurrentParser = new TorqueScriptParser();
    AssertISV(smCurrentParser, avar("CodeBlock::compile - no parser available for '%s'!", fileName));
 
    // Now do some parsing.
@@ -649,10 +621,10 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
    smCurrentParser->restart(NULL);
    smCurrentParser->parse();
 
-   if (!gStatementList)
+   if (!Script::gStatementList)
    {
       delete this;
-      return std::move(ConsoleValue());
+      return Con::EvalResult(Con::getVariable("$ScriptError"));
    }
 
    resetTables();
@@ -660,7 +632,7 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
    smInFunction = false;
 
    CodeStream codeStream;
-   U32 lastIp = compileBlock(gStatementList, codeStream, 0);
+   U32 lastIp = compileBlock(Script::gStatementList, codeStream, 0);
 
    lineBreakPairCount = codeStream.getNumLineBreaks();
 
@@ -677,7 +649,7 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
 
    codeStream.emit(OP_RETURN_VOID);
    codeStream.emitCodeStream(&codeSize, &code, &lineBreakPairs);
-   
+
    S32 localRegisterCount = gIsEvalCompile ? gEvalFuncVars.count() : gGlobalScopeFuncVars.count();
 
    consoleAllocReset();
@@ -701,20 +673,6 @@ ConsoleValue CodeBlock::compileExec(StringTableEntry fileName, const char *inStr
 
 //-------------------------------------------------------------------------
 
-void CodeBlock::incRefCount()
-{
-   refCount++;
-}
-
-void CodeBlock::decRefCount()
-{
-   refCount--;
-   if (!refCount)
-      delete this;
-}
-
-//-------------------------------------------------------------------------
-
 String CodeBlock::getFunctionArgs(U32 ip)
 {
    StringBuilder str;

+ 34 - 39
Engine/source/console/codeBlock.h → Engine/source/console/torquescript/codeBlock.h

@@ -26,6 +26,9 @@
 #include <vector>
 #include <unordered_map>
 
+#include "parser.h"
+#include "console/runtime.h"
+
 struct CompilerLocalVariableToRegisterMappingTable
 {
    struct RemappingTable
@@ -42,8 +45,7 @@ struct CompilerLocalVariableToRegisterMappingTable
    void write(Stream& stream);
 };
 
-#include "console/compiler.h"
-#include "console/consoleParser.h"
+#include "compiler.h"
 
 class Stream;
 class ConsoleValue;
@@ -51,33 +53,24 @@ class ConsoleValue;
 /// Core TorqueScript code management class.
 ///
 /// This class represents a block of code, usually mapped directly to a file.
-class CodeBlock
+class CodeBlock : Con::Module
 {
 private:
    static CodeBlock* smCodeBlockList;
-   static CodeBlock* smCurrentCodeBlock;
 
 public:
    static bool                      smInFunction;
-   static Compiler::ConsoleParser * smCurrentParser;
-
-   static CodeBlock* getCurrentBlock()
-   {
-      return smCurrentCodeBlock;
-   }
+   static TorqueScriptParser * smCurrentParser;
 
    static CodeBlock *getCodeBlockList()
    {
       return smCodeBlockList;
    }
 
-   static StringTableEntry getCurrentCodeBlockName();
-   static StringTableEntry getCurrentCodeBlockFullPath();
-   static StringTableEntry getCurrentCodeBlockModName();
    static CodeBlock *find(StringTableEntry);
 
    CodeBlock();
-   ~CodeBlock();
+   ~CodeBlock() override;
 
    StringTableEntry name;
    StringTableEntry fullPath;
@@ -100,59 +93,55 @@ public:
    U32 refCount;
    U32 lineBreakPairCount;
    U32 *lineBreakPairs;
-   U32 breakListSize;
-   U32 *breakList;
+   Vector<U32> breakList;
    CodeBlock *nextFile;
 
    void addToCodeList();
    void removeFromCodeList();
    void calcBreakList();
-   void clearAllBreaks();
-   void setAllBreaks();
+   void clearAllBreaks() override;
+   void setAllBreaks() override;
    void dumpInstructions(U32 startIp = 0, bool upToReturn = false);
 
    /// Returns the first breakable line or 0 if none was found.
    /// @param lineNumber The one based line number.
-   U32 findFirstBreakLine(U32 lineNumber);
+   U32 findFirstBreakLine(U32 lineNumber) override;
 
-   void clearBreakpoint(U32 lineNumber);
+   void clearBreakpoint(U32 lineNumber) override;
 
-   /// Set a OP_BREAK instruction on a line. If a break 
+   /// Set a OP_BREAK instruction on a line. If a break
    /// is not possible on that line it returns false.
    /// @param lineNumber The one based line number.
-   bool setBreakpoint(U32 lineNumber);
+   bool setBreakpoint(U32 lineNumber) override;
 
-   void findBreakLine(U32 ip, U32 &line, U32 &instruction);
-   const char *getFileLine(U32 ip);
+   void findBreakLine(U32 ip, U32 &line, U32 &instruction) override;
+   const char *getFileLine(U32 ip) override;
 
-   /// 
+   ///
    String getFunctionArgs(U32 offset);
 
    bool read(StringTableEntry fileName, Stream &st);
    bool compile(const char *dsoName, StringTableEntry fileName, const char *script, bool overrideNoDso = false);
 
-   void incRefCount();
-   void decRefCount();
-
    /// Compiles and executes a block of script storing the compiled code in this
-   /// CodeBlock. If there is no filename breakpoints will not be generated and 
-   /// the CodeBlock will not be added to the linked list of loaded CodeBlocks. 
+   /// CodeBlock. If there is no filename breakpoints will not be generated and
+   /// the CodeBlock will not be added to the linked list of loaded CodeBlocks.
    /// Note that if the script contains no executable statements the CodeBlock
-   /// will delete itself on return an empty string. The return string is any 
+   /// will delete itself on return an empty string. The return string is any
    /// result of the code executed, if any, or an empty string.
    ///
-   /// @param fileName The file name, including path and extension, for the 
+   /// @param fileName The file name, including path and extension, for the
    /// block of code or an empty string.
    /// @param script The script code to compile and execute.
    /// @param noCalls Skips calling functions from the script.
-   /// @param setFrame A zero based index of the stack frame to execute the code 
+   /// @param setFrame A zero based index of the stack frame to execute the code
    /// with, zero being the top of the stack. If the the index is
    /// -1 a new frame is created. If the index is out of range the
    /// top stack frame is used.
-   ConsoleValue compileExec(StringTableEntry fileName, const char *script,
+   Con::EvalResult compileExec(StringTableEntry fileName, const char *script,
       bool noCalls, S32 setFrame = -1);
 
-   /// Executes the existing code in the CodeBlock. The return string is any 
+   /// Executes the existing code in the CodeBlock. The return string is any
    /// result of the code executed, if any, or an empty string.
    ///
    /// @param offset The instruction offset to start executing from.
@@ -162,14 +151,20 @@ public:
    /// zero to execute code outside of a function.
    /// @param argv The function parameter list.
    /// @param noCalls Skips calling functions from the script.
-   /// @param setFrame A zero based index of the stack frame to execute the code 
+   /// @param setFrame A zero based index of the stack frame to execute the code
    /// with, zero being the top of the stack. If the the index is
    /// -1 a new frame is created. If the index is out of range the
    /// top stack frame is used.
    /// @param packageName The code package name or null.
-   ConsoleValue exec(U32 offset, const char *fnName, Namespace *ns, U32 argc,
-      ConsoleValue *argv, bool noCalls, StringTableEntry packageName,
-      S32 setFrame = -1);
+   Con::EvalResult exec(U32 offset, const char* fnName, Namespace* ns, U32 argc,
+                           ConsoleValue* argv, bool noCalls, StringTableEntry packageName,
+                           S32 setFrame = -1) override;
+
+   const char* getFunctionArgs(StringTableEntry functionName, U32 functionOffset) override { return getFunctionArgs(functionOffset); }
+   const char* getPath() override { return fullPath; }
+   const char* getName() override { return name; }
+   Vector<U32> getBreakableLines() override { return breakList; }
+
 };
 
 #endif

+ 117 - 171
Engine/source/console/compiledEval.cpp → Engine/source/console/torquescript/compiledEval.cpp

@@ -23,31 +23,25 @@
 //-----------------------------------------------------------------------------
 
 #include "platform/platform.h"
-#include "console/console.h"
 
-#include "console/ast.h"
-#include "core/tAlgorithm.h"
+#include "ast.h"
+#include "compiler.h"
 
-#include "core/strings/findMatch.h"
 #include "core/strings/stringUnit.h"
 #include "console/consoleInternal.h"
-#include "core/stream/fileStream.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/frameAllocator.h"
 
 #include "console/returnBuffer.h"
 #include "console/consoleValueStack.h"
+#include "console/telnetDebugger.h"
 
 #ifndef TORQUE_TGB_ONLY
 #include "materials/materialDefinition.h"
-#include "materials/materialManager.h"
 #endif
 
 using namespace Compiler;
@@ -116,6 +110,13 @@ U32 _ITER = 0;    ///< Stack pointer for iterStack.
 ConsoleValue stack[MaxStackSize];
 S32 _STK = 0;
 
+ReturnBuffer retBuffer;
+
+char *getReturnBuffer(U32 bufferSize)
+{
+   return retBuffer.getBuffer(bufferSize);
+}
+
 const char* tsconcat(const char* strA, const char* strB, S32& outputLen)
 {
    S32 lenA = dStrlen(strA);
@@ -150,7 +151,7 @@ namespace Con
       Namespace * walk;
       for (walk = ns; walk; walk = walk->mParent)
          size += dStrlen(walk->mName) + 4;
-      char *ret = Con::getReturnBuffer(size);
+      char *ret = getReturnBuffer(size);
       ret[0] = 0;
       for (walk = ns; walk; walk = walk->mParent)
       {
@@ -169,9 +170,9 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c
    if (object && field)
       prevVal = object->getDataField(field, array);
    else if (currentLocalRegister != -1)
-      prevVal = gEvalState.getLocalStringVariable(currentLocalRegister);
-   else if (gEvalState.currentVariable)
-      prevVal = gEvalState.getStringVariable();
+      prevVal = Script::gEvalState.getLocalStringVariable(currentLocalRegister);
+   else if (Script::gEvalState.currentVariable)
+      prevVal = Script::gEvalState.getStringVariable();
 
    // Make sure we got a value.
    if (prevVal && *prevVal)
@@ -192,7 +193,7 @@ static void getFieldComponent(SimObject* object, StringTableEntry field, const c
          StringTable->insert("a")
       };
 
-      // Translate xyzw and rgba into the indexed component 
+      // 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);
@@ -225,10 +226,10 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
    if (object && field)
       prevVal = object->getDataField(field, array);
    else if (currentLocalRegister != -1)
-      prevVal = gEvalState.getLocalStringVariable(currentLocalRegister);
+      prevVal = Script::gEvalState.getLocalStringVariable(currentLocalRegister);
    // Set the value on a variable.
-   else if (gEvalState.currentVariable)
-      prevVal = gEvalState.getStringVariable();
+   else if (Script::gEvalState.currentVariable)
+      prevVal = Script::gEvalState.getStringVariable();
 
    // Ensure that the variable has a value
    if (!prevVal)
@@ -250,7 +251,7 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
       StringTable->insert("a")
    };
 
-   // Insert the value into the specified 
+   // 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);
@@ -270,9 +271,9 @@ static void setFieldComponent(SimObject* object, StringTableEntry field, const c
       if (object && field)
          object->setDataField(field, 0, val);
       else if (currentLocalRegister != -1)
-         gEvalState.setLocalStringVariable(currentLocalRegister, val, dStrlen(val));
-      else if (gEvalState.currentVariable)
-         gEvalState.setStringVariable(val);
+         Script::gEvalState.setLocalStringVariable(currentLocalRegister, val, dStrlen(val));
+      else if (Script::gEvalState.currentVariable)
+         Script::gEvalState.setStringVariable(val);
    }
 }
 
@@ -295,83 +296,26 @@ F64 consoleStringToNumber(const char *str, StringTableEntry file, U32 line)
    return 0;
 }
 
-//------------------------------------------------------------
-
-namespace Con
+SimObject* getThisObject(ConsoleValue& simObjectLookupValue)
 {
-   ReturnBuffer retBuffer;
+   SimObject* thisObject = NULL;
 
-   char *getReturnBuffer(U32 bufferSize)
-   {
-      return retBuffer.getBuffer(bufferSize);
-   }
-
-   char *getReturnBuffer(const char *stringToCopy)
-   {
-      U32 len = dStrlen(stringToCopy) + 1;
-      char *ret = retBuffer.getBuffer(len);
-      dMemcpy(ret, stringToCopy, len);
-      return ret;
-   }
-
-   char* getReturnBuffer(const String& str)
-   {
-      const U32 size = str.size();
-      char* ret = retBuffer.getBuffer(size);
-      dMemcpy(ret, str.c_str(), size);
-      return ret;
-   }
-
-   char* getReturnBuffer(const StringBuilder& str)
-   {
-      char* buffer = Con::getReturnBuffer(str.length() + 1);
-      str.copy(buffer);
-      buffer[str.length()] = '\0';
-
-      return buffer;
-   }
-
-   char *getArgBuffer(U32 bufferSize)
-   {
-      return STR.getArgBuffer(bufferSize);
-   }
-
-   char *getFloatArg(F64 arg)
-   {
-      char *ret = STR.getArgBuffer(32);
-      dSprintf(ret, 32, "%g", arg);
-      return ret;
-   }
-
-   char *getIntArg(S32 arg)
+   // Optimization: If we're an integer, we can lookup the value by SimObjectId
+   if (simObjectLookupValue.getType() == ConsoleValueType::cvInteger)
+      thisObject = Sim::findObject(static_cast<SimObjectId>(simObjectLookupValue.getFastInt()));
+   else
    {
-      char *ret = STR.getArgBuffer(32);
-      dSprintf(ret, 32, "%d", arg);
-      return ret;
-   }
+      SimObject *foundObject = Sim::findObject(simObjectLookupValue.getString());
 
-   char* getBoolArg(bool arg)
-   {
-      char *ret = STR.getArgBuffer(32);
-      dSprintf(ret, 32, "%d", arg);
-      return ret;
-   }
+      // Optimization: If we're not an integer, let's make it so that the fast path exists
+      // on the first argument of the method call (speeds up future usage of %this, for example)
+      if (foundObject != NULL)
+         simObjectLookupValue.setInt(static_cast<S64>(foundObject->getId()));
 
-   char *getStringArg(const char *arg)
-   {
-      U32 len = dStrlen(arg) + 1;
-      char *ret = STR.getArgBuffer(len);
-      dMemcpy(ret, arg, len);
-      return ret;
+      thisObject = foundObject;
    }
 
-   char* getStringArg(const String& arg)
-   {
-      const U32 size = arg.size();
-      char* ret = STR.getArgBuffer(size);
-      dMemcpy(ret, arg.c_str(), size);
-      return ret;
-   }
+   return thisObject;
 }
 
 //------------------------------------------------------------
@@ -379,7 +323,7 @@ namespace Con
 void ExprEvalState::setCurVarName(StringTableEntry name)
 {
    if (name[0] == '$')
-      currentVariable = globalVars.lookup(name);
+      currentVariable = Con::gGlobalVars.lookup(name);
    else if (getStackDepth() > 0)
       currentVariable = getCurrentFrame().lookup(name);
    if (!currentVariable && gWarnUndefinedScriptVariables)
@@ -389,7 +333,7 @@ void ExprEvalState::setCurVarName(StringTableEntry name)
 void ExprEvalState::setCurVarNameCreate(StringTableEntry name)
 {
    if (name[0] == '$')
-      currentVariable = globalVars.add(name);
+      currentVariable = Con::gGlobalVars.add(name);
    else if (getStackDepth() > 0)
       currentVariable = getCurrentFrame().add(name);
    else
@@ -605,7 +549,7 @@ TORQUE_FORCEINLINE void doIntOperation()
 //-----------------------------------------------------------------------------
 
 U32 gExecCount = 0;
-ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNamespace, U32 argc, ConsoleValue* argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
+Con::EvalResult CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNamespace, U32 argc, ConsoleValue* argv, bool noCalls, StringTableEntry packageName, S32 setFrame)
 {
 #ifdef TORQUE_DEBUG
    U32 stackStart = _STK;
@@ -633,7 +577,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
       U32 regCount = code[ip + 2 + 7];
       thisFunctionName = CodeToSTE(code, ip);
       S32 wantedArgc = getMin(argc - 1, fnArgc); // argv[0] is func name
-      if (gEvalState.traceOn)
+      if (Con::gTraceOn)
       {
          traceBuffer[0] = 0;
          dStrcat(traceBuffer, "Entering ", TRACE_BUFFER_SIZE);
@@ -662,13 +606,13 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          dStrcat(traceBuffer, ")", TRACE_BUFFER_SIZE);
          Con::printf("%s", traceBuffer);
       }
-      gEvalState.pushFrame(thisFunctionName, thisNamespace, regCount);
+      Script::gEvalState.pushFrame(thisFunctionName, thisNamespace, regCount);
       popFrame = true;
       for (i = 0; i < wantedArgc; i++)
       {
          S32 reg = code[ip + (2 + 6 + 1 + 1) + i];
          ConsoleValue& value = argv[i + 1];
-         gEvalState.moveConsoleValue(reg, std::move(value));
+         Script::gEvalState.moveConsoleValue(reg, std::move(value));
       }
       ip = ip + fnArgc + (2 + 6 + 1 + 1);
       curFloatTable = functionFloats;
@@ -684,7 +628,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
       // 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() <= setFrame)
+      if (Script::gEvalState.getStackDepth() <= setFrame)
          setFrame = -1;
 
       // Do we want this code to execute using a new stack frame?
@@ -692,8 +636,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
       if (setFrame <= 0)
       {
          // argc is the local count for eval
-         gEvalState.pushFrame(NULL, NULL, argc);
-         popFrame = true;
+         Script::gEvalState.pushFrame(NULL, NULL, argc);
       }
       else
       {
@@ -701,12 +644,16 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          // 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.getTopOfStack() - setFrame - 1;
-         gEvalState.pushFrameRef(stackIndex);
-         popFrame = true;
+         S32 stackIndex = Script::gEvalState.getTopOfStack() - setFrame - 1;
+         Script::gEvalState.pushFrameRef(stackIndex);
       }
+
+      popFrame = true;
    }
 
+   Script::gEvalState.getCurrentFrame().module = this;
+   Script::gEvalState.getCurrentFrame().ip = 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();
@@ -730,7 +677,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
    StringTableEntry curField = NULL;
    SimObject* prevObject = NULL;
    SimObject* curObject = NULL;
-   SimObject* saveObject = NULL;
+   SimObject* thisObject = NULL;
    Namespace::Entry* nsEntry;
    Namespace* ns = NULL;
    const char* curFNDocBlock = NULL;
@@ -744,8 +691,6 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
    static char curFieldArray[256];
    static char prevFieldArray[256];
 
-   CodeBlock* saveCodeBlock = smCurrentCodeBlock;
-   smCurrentCodeBlock = this;
    if (this->name)
    {
       Con::gCurrentFile = this->name;
@@ -1402,7 +1347,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
       case OP_INC:
          reg = code[ip++];
          currentRegister = reg;
-         gEvalState.setLocalFloatVariable(reg, gEvalState.getLocalFloatVariable(reg) + 1.0);
+         Script::gEvalState.setLocalFloatVariable(reg, Script::gEvalState.getLocalFloatVariable(reg) + 1.0);
          break;
 
       case OP_SETCURVAR:
@@ -1420,7 +1365,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          // set a global, we aren't active
          currentRegister = -1;
 
-         gEvalState.setCurVarName(var);
+         Script::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
@@ -1442,7 +1387,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          // set a global, we aren't active
          currentRegister = -1;
 
-         gEvalState.setCurVarNameCreate(var);
+         Script::gEvalState.setCurVarNameCreate(var);
 
          // See OP_SETCURVAR for why we do this.
          curFNDocBlock = NULL;
@@ -1461,7 +1406,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          // set a global, we aren't active
          currentRegister = -1;
 
-         gEvalState.setCurVarName(var);
+         Script::gEvalState.setCurVarName(var);
 
          // See OP_SETCURVAR for why we do this.
          curFNDocBlock = NULL;
@@ -1480,7 +1425,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          // set a global, we aren't active
          currentRegister = -1;
 
-         gEvalState.setCurVarNameCreate(var);
+         Script::gEvalState.setCurVarNameCreate(var);
 
          // See OP_SETCURVAR for why we do this.
          curFNDocBlock = NULL;
@@ -1489,32 +1434,32 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
 
       case OP_LOADVAR_UINT:
          currentRegister = -1;
-         stack[_STK + 1].setInt(gEvalState.getIntVariable());
+         stack[_STK + 1].setInt(Script::gEvalState.getIntVariable());
          _STK++;
          break;
 
       case OP_LOADVAR_FLT:
          currentRegister = -1;
-         stack[_STK + 1].setFloat(gEvalState.getFloatVariable());
+         stack[_STK + 1].setFloat(Script::gEvalState.getFloatVariable());
          _STK++;
          break;
 
       case OP_LOADVAR_STR:
          currentRegister = -1;
-         stack[_STK + 1].setString(gEvalState.getStringVariable());
+         stack[_STK + 1].setString(Script::gEvalState.getStringVariable());
          _STK++;
          break;
 
       case OP_SAVEVAR_UINT:
-         gEvalState.setIntVariable(stack[_STK].getInt());
+         Script::gEvalState.setIntVariable(stack[_STK].getInt());
          break;
 
       case OP_SAVEVAR_FLT:
-         gEvalState.setFloatVariable(stack[_STK].getFloat());
+         Script::gEvalState.setFloatVariable(stack[_STK].getFloat());
          break;
 
       case OP_SAVEVAR_STR:
-         gEvalState.setStringVariable(stack[_STK].getString());
+         Script::gEvalState.setStringVariable(stack[_STK].getString());
          break;
 
       case OP_LOAD_LOCAL_VAR_UINT:
@@ -1526,7 +1471,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          prevObject = NULL;
          curObject = NULL;
 
-         stack[_STK + 1].setInt(gEvalState.getLocalIntVariable(reg));
+         stack[_STK + 1].setInt(Script::gEvalState.getLocalIntVariable(reg));
          _STK++;
          break;
 
@@ -1539,7 +1484,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          prevObject = NULL;
          curObject = NULL;
 
-         stack[_STK + 1].setFloat(gEvalState.getLocalFloatVariable(reg));
+         stack[_STK + 1].setFloat(Script::gEvalState.getLocalFloatVariable(reg));
          _STK++;
          break;
 
@@ -1552,7 +1497,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          prevObject = NULL;
          curObject = NULL;
 
-         val = gEvalState.getLocalStringVariable(reg);
+         val = Script::gEvalState.getLocalStringVariable(reg);
          stack[_STK + 1].setString(val);
          _STK++;
          break;
@@ -1566,7 +1511,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          prevObject = NULL;
          curObject = NULL;
 
-         gEvalState.setLocalIntVariable(reg, stack[_STK].getInt());
+         Script::gEvalState.setLocalIntVariable(reg, stack[_STK].getInt());
          break;
 
       case OP_SAVE_LOCAL_VAR_FLT:
@@ -1578,7 +1523,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          prevObject = NULL;
          curObject = NULL;
 
-         gEvalState.setLocalFloatVariable(reg, stack[_STK].getFloat());
+         Script::gEvalState.setLocalFloatVariable(reg, stack[_STK].getFloat());
          break;
 
       case OP_SAVE_LOCAL_VAR_STR:
@@ -1591,7 +1536,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          prevObject = NULL;
          curObject = NULL;
 
-         gEvalState.setLocalStringVariable(reg, val, (S32)dStrlen(val));
+         Script::gEvalState.setLocalStringVariable(reg, val, (S32)dStrlen(val));
          break;
 
       case OP_SETCUROBJECT:
@@ -1820,10 +1765,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          U32 callType = code[ip + 4];
 
          //if this is called from inside a function, append the ip and codeptr
-         if (!gEvalState.stack.empty())
+         if (!Script::gEvalState.stack.empty())
          {
-            gEvalState.getCurrentFrame().code = this;
-            gEvalState.getCurrentFrame().ip = ip - 1;
+            Script::gEvalState.getCurrentFrame().module = this;
+            Script::gEvalState.getCurrentFrame().ip = ip - 1;
          }
 
          ip += 5;
@@ -1868,25 +1813,10 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          }
          else if (callType == FuncCallExprNode::MethodCall)
          {
-            saveObject = gEvalState.thisObject;
+            ConsoleValue& simObjectLookupValue = callArgv[1];
+            thisObject = getThisObject(simObjectLookupValue);
 
-            // 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.getFastInt()));
-            else
-            {
-               SimObject *foundObject = Sim::findObject(simObjectLookupValue.getString());
-
-               // Optimization: If we're not an integer, let's make it so that the fast path exists
-               // on the first argument of the method call (speeds up future usage of %this, for example)
-               if (foundObject != NULL)
-                  callArgv[1].setInt(static_cast<S64>(foundObject->getId()));
-
-               gEvalState.thisObject = foundObject;
-            }
-
-            if (gEvalState.thisObject == NULL)
+            if (thisObject == NULL)
             {
                Con::warnf(
                   ConsoleLogEntry::General,
@@ -1902,7 +1832,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                break;
             }
 
-            ns = gEvalState.thisObject->getNamespace();
+            ns = thisObject->getNamespace();
             if (ns)
                nsEntry = ns->lookup(fnName);
             else
@@ -1910,6 +1840,25 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          }
          else // it's a ParentCall
          {
+            ConsoleValue& simObjectLookupValue = callArgv[1];
+            thisObject = getThisObject(simObjectLookupValue);
+
+            if (thisObject == NULL)
+            {
+               Con::warnf(
+                  ConsoleLogEntry::General,
+                  "%s: Unable to find object: '%s' attempting to call function '%s'",
+                  getFileLine(ip - 6),
+                  simObjectLookupValue.getString(),
+                  fnName
+               );
+
+               gCallStack.popFrame();
+               stack[_STK + 1].setEmptyString();
+               _STK++;
+               break;
+            }
+
             if (thisNamespace)
             {
                ns = thisNamespace->mParent;
@@ -1933,8 +1882,8 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                if (callType == FuncCallExprNode::MethodCall)
                {
                   Con::warnf(ConsoleLogEntry::General, "  Object %s(%d) %s",
-                     gEvalState.thisObject->getName() ? gEvalState.thisObject->getName() : "",
-                     gEvalState.thisObject->getId(), Con::getNamespaceList(ns));
+                     thisObject->getName() ? thisObject->getName() : "",
+                     thisObject->getId(), Con::getNamespaceList(ns));
                }
             }
             gCallStack.popFrame();
@@ -1946,7 +1895,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          {
             if (nsEntry->mFunctionOffset)
             {
-               ConsoleValue returnFromFn = nsEntry->mCode->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage);
+               ConsoleValue returnFromFn = nsEntry->mModule->exec(nsEntry->mFunctionOffset, fnName, nsEntry->mNamespace, callArgc, callArgv, false, nsEntry->mPackage).value;
                stack[_STK + 1] = std::move(returnFromFn);
             }
             else // no body
@@ -1972,7 +1921,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                {
                case Namespace::Entry::StringCallbackType:
                {
-                  const char* result = nsEntry->cb.mStringCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  const char* result = nsEntry->cb.mStringCallbackFunc(thisObject, callArgc, callArgv);
                   gCallStack.popFrame();
                   stack[_STK + 1].setString(result);
                   _STK++;
@@ -1980,7 +1929,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                }
                case Namespace::Entry::IntCallbackType:
                {
-                  S64 result = nsEntry->cb.mIntCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  S64 result = nsEntry->cb.mIntCallbackFunc(thisObject, callArgc, callArgv);
                   gCallStack.popFrame();
 
                   if (code[ip] == OP_POP_STK)
@@ -1995,7 +1944,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                }
                case Namespace::Entry::FloatCallbackType:
                {
-                  F64 result = nsEntry->cb.mFloatCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  F64 result = nsEntry->cb.mFloatCallbackFunc(thisObject, callArgc, callArgv);
                   gCallStack.popFrame();
 
                   if (code[ip] == OP_POP_STK)
@@ -2010,7 +1959,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                }
                case Namespace::Entry::VoidCallbackType:
                {
-                  nsEntry->cb.mVoidCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  nsEntry->cb.mVoidCallbackFunc(thisObject, callArgc, callArgv);
                   gCallStack.popFrame();
 
                   if (code[ip] == OP_POP_STK)
@@ -2023,7 +1972,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                   {
                      Con::warnf(ConsoleLogEntry::General, "%s: Call to %s in %s uses result of void function call.", getFileLine(ip - 4), fnName, functionName);
                   }
-                  
+
                   stack[_STK + 1].setEmptyString();
                   _STK++;
 
@@ -2031,7 +1980,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                }
                case Namespace::Entry::BoolCallbackType:
                {
-                  bool result = nsEntry->cb.mBoolCallbackFunc(gEvalState.thisObject, callArgc, callArgv);
+                  bool result = nsEntry->cb.mBoolCallbackFunc(thisObject, callArgc, callArgv);
                   gCallStack.popFrame();
 
                   if (code[ip] == OP_POP_STK)
@@ -2048,9 +1997,6 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                }
             }
          }
-
-         if (callType == FuncCallExprNode::MethodCall)
-            gEvalState.thisObject = saveObject;
          break;
       }
 
@@ -2122,9 +2068,9 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
       case OP_BREAK:
       {
          //append the ip and codeptr before managing the breakpoint!
-         AssertFatal(!gEvalState.stack.empty(), "Empty eval stack on break!");
-         gEvalState.getCurrentFrame().code = this;
-         gEvalState.getCurrentFrame().ip = ip - 1;
+         AssertFatal(!Script::gEvalState.stack.empty(), "Empty eval stack on break!");
+         Script::gEvalState.getCurrentFrame().module = this;
+         Script::gEvalState.getCurrentFrame().ip = ip - 1;
 
          U32 breakLine;
          findBreakLine(ip - 1, breakLine, instruction);
@@ -2153,7 +2099,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
          if (isGlobal)
          {
             StringTableEntry varName = CodeToSTE(code, ip + 1);
-            iter.mVar.mVariable = gEvalState.globalVars.add(varName);
+            iter.mVar.mVariable = Con::gGlobalVars.add(varName);
          }
          else
          {
@@ -2227,7 +2173,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                if (iter.mIsGlobalVariable)
                   iter.mVar.mVariable->setStringValue(&str[startIndex]);
                else
-                  gEvalState.setLocalStringVariable(iter.mVar.mRegister, &str[startIndex], endIndex - startIndex);
+                  Script::gEvalState.setLocalStringVariable(iter.mVar.mRegister, &str[startIndex], endIndex - startIndex);
 
                const_cast<char*>(str)[endIndex] = savedChar;
             }
@@ -2236,7 +2182,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
                if (iter.mIsGlobalVariable)
                   iter.mVar.mVariable->setStringValue("");
                else
-                  gEvalState.setLocalStringVariable(iter.mVar.mRegister, "", 0);
+                  Script::gEvalState.setLocalStringVariable(iter.mVar.mRegister, "", 0);
             }
 
             // Skip separator.
@@ -2261,7 +2207,7 @@ ConsoleValue CodeBlock::exec(U32 ip, const char* functionName, Namespace* thisNa
             if (iter.mIsGlobalVariable)
                iter.mVar.mVariable->setIntValue(id);
             else
-               gEvalState.setLocalIntVariable(iter.mVar.mRegister, id);
+               Script::gEvalState.setLocalIntVariable(iter.mVar.mRegister, id);
 
             iter.mData.mObj.mIndex = index + 1;
          }
@@ -2296,12 +2242,12 @@ execFinished:
 
    if (popFrame)
    {
-      gEvalState.popFrame();
+      Script::gEvalState.popFrame();
    }
 
    if (argv)
    {
-      if (gEvalState.traceOn)
+      if (Con::gTraceOn)
       {
          traceBuffer[0] = 0;
          dStrcat(traceBuffer, "Leaving ", TRACE_BUFFER_SIZE);
@@ -2332,11 +2278,11 @@ execFinished:
       globalStrings = NULL;
       globalFloats = NULL;
    }
-   smCurrentCodeBlock = saveCodeBlock;
-   if (saveCodeBlock && saveCodeBlock->name)
+
+   if (Con::getCurrentScriptModuleName())
    {
-      Con::gCurrentFile = saveCodeBlock->name;
-      Con::gCurrentRoot = saveCodeBlock->modPath;
+      Con::gCurrentFile = Con::getCurrentScriptModuleName();
+      Con::gCurrentRoot = Con::getModNameFromPath(Con::getCurrentScriptModulePath());
    }
 
    decRefCount();
@@ -2346,7 +2292,7 @@ execFinished:
    AssertFatal(!(_STK < stackStart), "String stack popped too much in script exec");
 #endif
 
-   return returnValue;
+   return Con::EvalResult(std::move(returnValue));
 }
 
 //------------------------------------------------------------

+ 6 - 15
Engine/source/console/compiler.cpp → Engine/source/console/torquescript/compiler.cpp

@@ -22,16 +22,8 @@
 
 #include "platform/platform.h"
 #include "console/console.h"
-#include "console/telnetDebugger.h"
-
-#include "console/ast.h"
-#include "core/tAlgorithm.h"
-
-#include "core/strings/findMatch.h"
-#include "console/consoleInternal.h"
-#include "core/stream/fileStream.h"
-#include "console/compiler.h"
 
+#include "compiler.h"
 #include "console/simBase.h"
 
 extern FuncVars gEvalFuncVars;
@@ -178,15 +170,15 @@ S32 FuncVars::assign(StringTableEntry var, TypeReq currentType, S32 lineNumber,
 S32 FuncVars::lookup(StringTableEntry var, S32 lineNumber)
 {
    std::unordered_map<StringTableEntry, Var>::iterator found = vars.find(var);
-   
+
    if (found == vars.end())
    {
       const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber);
       scriptErrorHandler(str);
-      
+
       return assign(var, TypeReqString, lineNumber, false);
    }
-   
+
    return found->second.reg;
 }
 
@@ -198,11 +190,11 @@ TypeReq FuncVars::lookupType(StringTableEntry var, S32 lineNumber)
    {
       const char* str = avar("Script Warning: Variable %s referenced before used when compiling script. File: %s Line: %d", var, CodeBlock::smCurrentParser->getCurrentFile(), lineNumber);
       scriptErrorHandler(str);
-      
+
       assign(var, TypeReqString, lineNumber, false);
       return vars.find(var)->second.currentType;
    }
-   
+
    return found->second.currentType;
 }
 
@@ -561,4 +553,3 @@ void CodeStream::reset()
       mCodeHead = mCode;
    }
 }
-

+ 6 - 4
Engine/source/console/compiler.h → Engine/source/console/torquescript/compiler.h

@@ -33,12 +33,14 @@
 #include <string>
 #include <unordered_map>
 
+class CodeStream;
+struct StmtNode;
 class Stream;
 class DataChunker;
 
 #include "platform/platform.h"
-#include "console/ast.h"
-#include "console/codeBlock.h"
+#include "ast.h"
+#include "codeBlock.h"
 
 #ifndef _TVECTOR_H_
 #include "core/util/tVector.h"
@@ -297,13 +299,13 @@ public:
    S32 lookup(StringTableEntry var, S32 lineNumber);
 
    TypeReq lookupType(StringTableEntry var, S32 lineNumber);
-   
+
    inline S32 count() { return counter; }
 
    std::unordered_map<S32, StringTableEntry> variableNameMap;
 
    void clear();
-   
+
 private:
    std::unordered_map<StringTableEntry, Var> vars;
    S32 counter = 0;

+ 157 - 0
Engine/source/console/torquescript/evalState.cpp

@@ -0,0 +1,157 @@
+
+#include "evalState.h"
+
+void ExprEvalState::pushFrame(StringTableEntry frameName, Namespace *ns, S32 registerCount)
+{
+#ifdef DEBUG_SPEW
+   validate();
+
+   Platform::outputDebugString("[ConsoleInternal] Pushing new frame for '%s' at %i",
+      frameName, mStackDepth);
+#endif
+
+   if (mStackDepth + 1 > stack.size())
+   {
+#ifdef DEBUG_SPEW
+      Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
+#endif
+
+      stack.push_back(new Dictionary);
+   }
+
+   Dictionary& newFrame = *(stack[mStackDepth]);
+   newFrame.setState();
+
+   newFrame.scopeName = frameName;
+   newFrame.scopeNamespace = ns;
+
+   Con::pushStackFrame(stack[mStackDepth]);
+   mStackDepth++;
+   currentVariable = NULL;
+
+   AssertFatal(!newFrame.getCount(), "ExprEvalState::pushFrame - Dictionary not empty!");
+
+   ConsoleValue* consoleValArray = new ConsoleValue[registerCount]();
+   localStack.push_back(ConsoleValueFrame(consoleValArray, false));
+   currentRegisterArray = &localStack.last();
+
+   AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
+
+#ifdef DEBUG_SPEW
+   validate();
+#endif
+}
+
+void ExprEvalState::popFrame()
+{
+   AssertFatal(mStackDepth > 0, "ExprEvalState::popFrame - Stack Underflow!");
+
+#ifdef DEBUG_SPEW
+   validate();
+
+   Platform::outputDebugString("[ConsoleInternal] Popping %sframe at %i",
+      getCurrentFrame().isOwner() ? "" : "shared ", mStackDepth - 1);
+#endif
+
+   Con::popStackFrame();
+   mStackDepth--;
+   stack[mStackDepth]->reset();
+   currentVariable = NULL;
+
+   const ConsoleValueFrame& frame = localStack.last();
+   localStack.pop_back();
+   if (!frame.isReference)
+      delete[] frame.values;
+
+   currentRegisterArray = localStack.size() ? &localStack.last() : NULL;
+
+   AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
+
+#ifdef DEBUG_SPEW
+   validate();
+#endif
+}
+
+void ExprEvalState::pushFrameRef(S32 stackIndex)
+{
+   AssertFatal(stackIndex >= 0 && stackIndex < mStackDepth, "You must be asking for a valid frame!");
+
+#ifdef DEBUG_SPEW
+   validate();
+
+   Platform::outputDebugString("[ConsoleInternal] Cloning frame from %i to %i",
+      stackIndex, mStackDepth);
+#endif
+
+   if (mStackDepth + 1 > stack.size())
+   {
+#ifdef DEBUG_SPEW
+      Platform::outputDebugString("[ConsoleInternal] Growing stack by one frame");
+#endif
+
+      stack.push_back(new Dictionary);
+   }
+
+   Dictionary& newFrame = *(stack[mStackDepth]);
+   newFrame.setState(stack[stackIndex]);
+
+   Con::pushStackFrame(stack[mStackDepth]);
+
+   mStackDepth++;
+   currentVariable = NULL;
+
+   ConsoleValue* values = localStack[stackIndex].values;
+   localStack.push_back(ConsoleValueFrame(values, true));
+   currentRegisterArray = &localStack.last();
+
+   AssertFatal(mStackDepth == localStack.size(), avar("Stack sizes do not match. mStackDepth = %d, localStack = %d", mStackDepth, localStack.size()));
+
+#ifdef DEBUG_SPEW
+   validate();
+#endif
+}
+
+void ExprEvalState::pushDebugFrame(S32 stackIndex)
+{
+   pushFrameRef(stackIndex);
+
+   Dictionary& newFrame = *(stack[mStackDepth - 1]);
+
+   // debugger needs to know this info...
+   newFrame.scopeName = stack[stackIndex]->scopeName;
+   newFrame.scopeNamespace = stack[stackIndex]->scopeNamespace;
+   newFrame.module = stack[stackIndex]->module;
+   newFrame.ip = stack[stackIndex]->ip;
+}
+
+ExprEvalState::ExprEvalState()
+{
+   VECTOR_SET_ASSOCIATION(stack);
+   currentVariable = NULL;
+   mStackDepth = 0;
+   stack.reserve(64);
+   mShouldReset = false;
+   mResetLocked = false;
+   copyVariable = NULL;
+   currentRegisterArray = NULL;
+}
+
+ExprEvalState::~ExprEvalState()
+{
+   // Delete callframes.
+
+   while (!stack.empty())
+   {
+      delete stack.last();
+      stack.decrement();
+   }
+}
+
+void ExprEvalState::validate()
+{
+   AssertFatal(mStackDepth <= stack.size(),
+      "ExprEvalState::validate() - Stack depth pointing beyond last stack frame!");
+
+   for (U32 i = 0; i < stack.size(); ++i)
+      stack[i]->validate();
+}

+ 119 - 0
Engine/source/console/torquescript/evalState.h

@@ -0,0 +1,119 @@
+#ifndef _EVALSTATE_H
+#define _EVALSTATE_H
+#include "console/consoleInternal.h"
+
+class ExprEvalState
+{
+public:
+   /// @name Expression Evaluation
+   /// @{
+
+   ///
+
+   Dictionary::Entry *currentVariable;
+   Dictionary::Entry *copyVariable;
+
+   U32 mStackDepth;
+   bool mShouldReset; ///< Designates if the value stack should be reset
+   bool mResetLocked; ///< mShouldReset will be set at the end
+
+   ExprEvalState();
+   ~ExprEvalState();
+
+   /// @}
+
+   /// @name Stack Management
+   /// @{
+
+   /// The stack of callframes.  The extra redirection is necessary since Dictionary holds
+   /// an interior pointer that will become invalid when the object changes address.
+   Vector< Dictionary* > stack;
+
+   S32 getTopOfStack() { return (S32)mStackDepth; }
+
+   Vector< ConsoleValueFrame > localStack;
+   ConsoleValueFrame* currentRegisterArray; // contains array at to top of localStack
+
+   ///
+
+   void setCurVarName(StringTableEntry name);
+   void setCurVarNameCreate(StringTableEntry name);
+
+   S32 getIntVariable();
+   F64 getFloatVariable();
+   const char *getStringVariable();
+   void setIntVariable(S32 val);
+   void setFloatVariable(F64 val);
+   void setStringVariable(const char *str);
+
+   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);
+   }
+
+   TORQUE_FORCEINLINE void moveConsoleValue(S32 reg, ConsoleValue val)
+   {
+      currentRegisterArray->values[reg] = std::move(val);
+   }
+
+   void pushFrame(StringTableEntry frameName, Namespace *ns, S32 regCount);
+   void popFrame();
+
+   /// Puts a reference to an existing stack frame
+   /// on the top of the stack.
+   void pushFrameRef(S32 stackIndex);
+
+   void pushDebugFrame(S32 stackIndex);
+
+   U32 getStackDepth() const
+   {
+      return mStackDepth;
+   }
+
+   Dictionary& getCurrentFrame()
+   {
+      return *(stack[mStackDepth - 1]);
+   }
+
+   Dictionary& getFrameAt(S32 depth)
+   {
+      return *(stack[depth]);
+   }
+
+   /// @}
+
+   /// Run integrity checks for debugging.
+   void validate();
+};
+
+#endif

+ 2 - 3
Engine/source/console/optimizer.cpp → Engine/source/console/torquescript/optimizer.cpp

@@ -21,8 +21,7 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
-#include "console/console.h"
-#include "console/codeBlock.h"
+#include "codeBlock.h"
 
 static bool isLiteralNumber(ExprNode* node)
 {
@@ -85,7 +84,7 @@ bool IntBinaryExprNode::optimize()
       S32 val = getIntValue(right);
       switch (val)
       {
-      case 2: 
+      case 2:
          op = '&';
          optimizedNode = IntNode::alloc(dbgLineNumber, 1);
          return true;

+ 0 - 0
Engine/source/console/torquescript/parser.cpp


+ 49 - 0
Engine/source/console/torquescript/parser.h

@@ -0,0 +1,49 @@
+#ifndef _TORQUESCRIPT_PARSER_H_
+#define _TORQUESCRIPT_PARSER_H_
+#include <cstdio>
+
+#include "platform/types.h"
+
+const char* CMDGetCurrentFile();
+S32 CMDGetCurrentLine();
+S32 CMDparse();
+void CMDrestart(FILE* in);
+void CMDSetScanBuffer(const char *sb, const char *fn);
+
+extern void expandEscape(char *dest, const char *src);
+extern bool collapseEscape(char *buf);
+
+class TorqueScriptParser
+{
+public:
+   TorqueScriptParser() = default;
+
+   const char* mExtension;
+
+   //-----------------------------------------------------------------------------
+   /// \brief Function for GetCurrentFile from the lexer
+   //-----------------------------------------------------------------------------
+   const char* getCurrentFile() { return CMDGetCurrentFile(); }
+
+   //-----------------------------------------------------------------------------
+   /// \brief Function for GetCurrentLine from the lexer
+   //-----------------------------------------------------------------------------
+   S32 getCurrentLine() { return CMDGetCurrentLine(); }
+
+   //-----------------------------------------------------------------------------
+   /// \brief Function for Parse from the lexer
+   //-----------------------------------------------------------------------------
+   S32 parse() { return CMDparse(); }
+
+   //-----------------------------------------------------------------------------
+   /// \brief Function for Restart from the lexer
+   //-----------------------------------------------------------------------------
+   void restart(FILE *pInputFile) { CMDrestart(pInputFile); }
+
+   //-----------------------------------------------------------------------------
+   /// \brief Function for SetScanBuffer from the lexer
+   //-----------------------------------------------------------------------------
+   void setScanBuffer(const char* sb, const char* fn) { CMDSetScanBuffer(sb, fn); }
+};
+
+#endif

+ 486 - 0
Engine/source/console/torquescript/runtime.cpp

@@ -0,0 +1,486 @@
+#include "runtime.h"
+
+#include "codeBlock.h"
+#include "console/script.h"
+#include "console/runtime.h"
+#include "core/volume.h"
+#include "core/stream/fileStream.h"
+#include "core/util/timeClass.h"
+
+
+namespace TorqueScript
+{
+   // Buffer for expanding script filenames.
+   static char scriptFilenameBuffer[1024];
+
+   TorqueScriptRuntime::TorqueScriptRuntime()
+   {
+      Con::registerRuntime(0, this);
+   }
+
+   TorqueScriptRuntime::~TorqueScriptRuntime()
+   {
+   }
+
+   Con::EvalResult TorqueScriptRuntime::evaluate(const char* string, bool echo, const char* fileName)
+   {
+      ConsoleStackFrameSaver stackSaver;
+      stackSaver.save();
+
+      if (echo)
+      {
+         if (string[0] == '%')
+            Con::printf("%s", string);
+         else
+            Con::printf("%s%s", Con::getVariable("$Con::Prompt"), string);
+      }
+
+      if (fileName)
+         fileName = StringTable->insert(fileName);
+
+      CodeBlock* newCodeBlock = new CodeBlock();
+      return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0));
+   }
+
+   Con::EvalResult TorqueScriptRuntime::evaluate(const char* script, S32 frame, bool echo, const char* fileName)
+   {
+      // Make sure we're passing a valid frame to the eval.
+      if (frame > Script::gEvalState.getStackDepth())
+         frame = Script::gEvalState.getStackDepth() - 1;
+      if (frame < 0)
+         frame = 0;
+
+      // Local variables use their own memory management and can't be queried by just executing
+      // TorqueScript, we have to go digging into the interpreter.
+      S32 evalBufferLen = dStrlen(script);
+      bool isEvaluatingLocalVariable = evalBufferLen > 0 && script[0] == '%';
+      if (isEvaluatingLocalVariable)
+      {
+         // See calculation of current frame in pushing a reference frame for console exec, we need access
+         // to the proper scope.
+         //frame = gEvalState.getTopOfStack() - frame - 1;
+         S32 stackIndex = Script::gEvalState.getStackDepth() - frame - 1;
+
+         Script::gEvalState.pushDebugFrame(stackIndex);
+
+         Dictionary& stackFrame = Script::gEvalState.getCurrentFrame();
+         StringTableEntry functionName = stackFrame.scopeName;
+         StringTableEntry namespaceName = stackFrame.scopeNamespace->mName;
+         StringTableEntry varToLookup = StringTable->insert(script);
+
+         S32 registerId = ((CodeBlock*)stackFrame.module)->variableRegisterTable.lookup(namespaceName, functionName, varToLookup);
+
+         if (registerId == -1)
+         {
+            // ERROR, can't read the variable!
+            return Con::EvalResult("variable not found");
+         }
+
+         const char* varResult = Script::gEvalState.getLocalStringVariable(registerId);
+
+         Script::gEvalState.popFrame();
+
+         ConsoleValue val;
+         val.setString(varResult);
+
+         return Con::EvalResult("variable not found");
+      }
+
+      // Execute the eval.
+      CodeBlock* newCodeBlock = new CodeBlock();
+      Con::EvalResult result = newCodeBlock->compileExec(NULL, script, false, frame);
+      return result;
+   }
+
+   //------------------------------------------------------------------------------
+   Con::EvalResult TorqueScriptRuntime::evaluatef(const char* string, ...)
+   {
+      char buffer[4096];
+      va_list args;
+      va_start(args, string);
+      dVsprintf(buffer, sizeof(buffer), string, args);
+      va_end(args);
+      return evaluate(buffer);
+   }
+
+   bool TorqueScriptRuntime::executeFile(const char* fileName, bool noCalls, bool journalScript)
+   {
+      bool journal = false;
+
+      U32 execDepth = 0;
+      U32 journalDepth = 1;
+
+      execDepth++;
+      if (journalDepth >= execDepth)
+         journalDepth = execDepth + 1;
+      else
+         journal = true;
+
+      bool ret = false;
+
+      if (journalScript && !journal)
+      {
+         journal = true;
+         journalDepth = execDepth;
+      }
+
+      // Determine the filename we actually want...
+      Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), fileName);
+
+      // since this function expects a script file reference, if it's a .dso
+      // lets terminate the string before the dso so it will act like a .tscript
+      if (dStrEndsWith(scriptFilenameBuffer, ".dso"))
+      {
+         scriptFilenameBuffer[dStrlen(scriptFilenameBuffer) - dStrlen(".dso")] = '\0';
+      }
+
+      // Figure out where to put DSOs
+      StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
+
+      const char* ext = dStrrchr(scriptFilenameBuffer, '.');
+
+      if (!ext)
+      {
+         // Try appending the default script extension and see if that succeeds
+
+         if (executeFile(fileName + String("." TORQUE_SCRIPT_EXTENSION), noCalls, journalScript))
+         {
+            return true;
+         }
+
+         // We need an extension!
+         Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file name %s.", scriptFilenameBuffer);
+         execDepth--;
+         return false;
+      }
+
+      // Check Editor Extensions
+      bool isEditorScript = false;
+
+      // If the script file extension is '.ed.tscript' then compile it to a different compiled extension
+      if (dStricmp(ext, "." TORQUE_SCRIPT_EXTENSION) == 0)
+      {
+         const char* ext2 = ext - 3;
+         if (dStricmp(ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0)
+            isEditorScript = true;
+      }
+      else if (dStricmp(ext, ".gui") == 0)
+      {
+         const char* ext2 = ext - 3;
+         if (dStricmp(ext2, ".ed.gui") == 0)
+            isEditorScript = true;
+      }
+
+      StringTableEntry scriptFileName = StringTable->insert(scriptFilenameBuffer);
+
+      // Is this a file we should compile? (anything in the prefs path should not be compiled)
+      StringTableEntry prefsPath = Platform::getPrefsPath();
+      bool compiled = dStricmp(ext, ".mis") && !journal && !Con::getBoolVariable("Scripts::ignoreDSOs");
+
+      // [tom, 12/5/2006] stripBasePath() fucks up if the filename is not in the exe
+      // path, current directory or prefs path. Thus, getDSOFilename() will also screw
+      // up and so this allows the scripts to still load but without a DSO.
+      if (Platform::isFullPath(Platform::stripBasePath(scriptFilenameBuffer)))
+         compiled = false;
+
+      // [tom, 11/17/2006] It seems to make sense to not compile scripts that are in the
+      // prefs directory. However, getDSOPath() can handle this situation and will put
+      // the dso along with the script to avoid name clashes with tools/game dsos.
+      if ((dsoPath && *dsoPath == 0) || (prefsPath && prefsPath[0] && dStrnicmp(
+         scriptFileName, prefsPath, dStrlen(prefsPath)) == 0))
+         compiled = false;
+
+      // If we're in a journaling mode, then we will read the script
+      // from the journal file.
+      if (journal && Journal::IsPlaying())
+      {
+         char fileNameBuf[256];
+         bool fileRead = false;
+         U32 fileSize;
+
+         Journal::ReadString(fileNameBuf);
+         Journal::Read(&fileRead);
+
+         if (!fileRead)
+         {
+            Con::errorf(ConsoleLogEntry::Script, "Journal script read (failed) for %s", fileNameBuf);
+            execDepth--;
+            return false;
+         }
+         Journal::Read(&fileSize);
+         char* script = new char[fileSize + 1];
+         Journal::Read(fileSize, script);
+         script[fileSize] = 0;
+         Con::printf("Executing (journal-read) %s.", scriptFileName);
+
+         CodeBlock *newCodeBlock = new CodeBlock();
+         newCodeBlock->compileExec(scriptFileName, script, noCalls, 0);
+         delete newCodeBlock;
+         delete[] script;
+
+         execDepth--;
+         return true;
+      }
+
+      // Ok, we let's try to load and compile the script.
+      Torque::FS::FileNodeRef scriptFile = Torque::FS::GetFileNode(scriptFileName);
+      Torque::FS::FileNodeRef dsoFile;
+
+      //    ResourceObject *rScr = gResourceManager->find(scriptFileName);
+      //    ResourceObject *rCom = NULL;
+
+      char nameBuffer[512];
+      char* script = NULL;
+      U32 version;
+
+      Stream* compiledStream = NULL;
+      Torque::Time scriptModifiedTime, dsoModifiedTime;
+
+      // Check here for .edso
+      bool edso = false;
+      if (dStricmp(ext, ".edso") == 0 && scriptFile != NULL)
+      {
+         edso = true;
+         dsoFile = scriptFile;
+         scriptFile = NULL;
+
+         dsoModifiedTime = dsoFile->getModifiedTime();
+         dStrcpy(nameBuffer, scriptFileName, 512);
+      }
+
+      // If we're supposed to be compiling this file, check to see if there's a DSO
+      if (compiled && !edso)
+      {
+         const char* filenameOnly = dStrrchr(scriptFileName, '/');
+         if (filenameOnly)
+            ++filenameOnly;
+         else
+            filenameOnly = scriptFileName;
+
+         char pathAndFilename[1024];
+         Platform::makeFullPathName(filenameOnly, pathAndFilename, sizeof(pathAndFilename), dsoPath);
+
+         if (isEditorScript)
+            dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".edso", NULL);
+         else
+            dStrcpyl(nameBuffer, sizeof(nameBuffer), pathAndFilename, ".dso", NULL);
+
+         dsoFile = Torque::FS::GetFileNode(nameBuffer);
+
+         if (scriptFile != NULL)
+            scriptModifiedTime = scriptFile->getModifiedTime();
+
+         if (dsoFile != NULL)
+            dsoModifiedTime = dsoFile->getModifiedTime();
+      }
+
+      // Let's do a sanity check to complain about DSOs in the future.
+      //
+      // MM:   This doesn't seem to be working correctly for now so let's just not issue
+      //    the warning until someone knows how to resolve it.
+      //
+      //if(compiled && rCom && rScr && Platform::compareFileTimes(comModifyTime, scrModifyTime) < 0)
+      //{
+      //Con::warnf("exec: Warning! Found a DSO from the future! (%s)", nameBuffer);
+      //}
+
+      // If we had a DSO, let's check to see if we should be reading from it.
+      //MGT: fixed bug with dsos not getting recompiled correctly
+      //Note: Using Nathan Martin's version from the forums since its easier to read and understand
+      if (compiled && dsoFile != NULL && (scriptFile == NULL || (dsoModifiedTime >= scriptModifiedTime)))
+      {
+         //MGT: end
+         compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
+         if (compiledStream)
+         {
+            // Check the version!
+            compiledStream->read(&version);
+            if (version != Con::DSOVersion)
+            {
+               Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, Con::DSOVersion);
+               delete compiledStream;
+               compiledStream = NULL;
+            }
+         }
+      }
+
+      // If we're journalling, let's write some info out.
+      if (journal && Journal::IsRecording())
+         Journal::WriteString(scriptFileName);
+
+      if (scriptFile != NULL && !compiledStream)
+      {
+         // If we have source but no compiled version, then we need to compile
+         // (and journal as we do so, if that's required).
+
+         void* data;
+         U32 dataSize = 0;
+         Torque::FS::ReadFile(scriptFileName, data, dataSize, true);
+
+         if (journal && Journal::IsRecording())
+            Journal::Write(bool(data != NULL));
+
+         if (data == NULL)
+         {
+            Con::errorf(ConsoleLogEntry::Script, "exec: invalid script file %s.", scriptFileName);
+            execDepth--;
+            return false;
+         }
+         else
+         {
+            if (!dataSize)
+            {
+               execDepth--;
+               return false;
+            }
+
+            script = (char*)data;
+
+            if (journal && Journal::IsRecording())
+            {
+               Journal::Write(dataSize);
+               Journal::Write(dataSize, data);
+            }
+         }
+
+#ifndef TORQUE_NO_DSO_GENERATION
+      if (compiled)
+      {
+         // compile this baddie.
+#ifdef TORQUE_DEBUG
+         Con::printf("Compiling %s...", scriptFileName);
+#endif
+
+         CodeBlock *code = new CodeBlock();
+         code->compile(nameBuffer, scriptFileName, script);
+         delete code;
+         code = NULL;
+
+         compiledStream = FileStream::createAndOpen(nameBuffer, Torque::FS::File::Read);
+         if (compiledStream)
+         {
+            compiledStream->read(&version);
+         }
+         else
+         {
+            // We have to exit out here, as otherwise we get double error reports.
+            delete[] script;
+            execDepth--;
+            return false;
+         }
+      }
+#endif
+      }
+      else
+      {
+         if (journal && Journal::IsRecording())
+            Journal::Write(bool(false));
+      }
+
+      if (compiledStream)
+      {
+         // Delete the script object first to limit memory used
+         // during recursive execs.
+         delete[] script;
+         script = 0;
+
+         // We're all compiled, so let's run it.
+#ifdef TORQUE_DEBUG
+         Con::printf("Loading compiled script %s.", scriptFileName);
+#endif
+         CodeBlock* code = new CodeBlock;
+         code->read(scriptFileName, *compiledStream);
+         delete compiledStream;
+         code->exec(0, scriptFileName, NULL, 0, NULL, noCalls, NULL, 0);
+         delete code;
+         ret = true;
+      }
+      else if (scriptFile)
+      {
+         // No compiled script,  let's just try executing it
+         // directly... this is either a mission file, or maybe
+         // we're on a readonly volume.
+#ifdef TORQUE_DEBUG
+         Con::printf("Executing %s.", scriptFileName);
+#endif
+
+         CodeBlock *newCodeBlock = new CodeBlock();
+         StringTableEntry name = StringTable->insert(scriptFileName);
+
+         newCodeBlock->compileExec(name, script, noCalls, 0);
+         ret = true;
+      }
+      else
+      {
+         // Don't have anything.
+         Con::warnf(ConsoleLogEntry::Script, "Missing file: %s!", scriptFileName);
+         ret = false;
+      }
+
+      delete[] script;
+      execDepth--;
+      return ret;
+   }
+
+   bool TorqueScriptRuntime::compile(const char* fileName, bool overrideNoDso)
+   {
+      Con::expandScriptFilename( scriptFilenameBuffer, sizeof( scriptFilenameBuffer ), fileName );
+
+      // Figure out where to put DSOs
+      StringTableEntry dsoPath = Con::getDSOPath(scriptFilenameBuffer);
+      if(dsoPath && *dsoPath == 0)
+         return false;
+
+      // If the script file extention is '.ed.tscript' then compile it to a different compiled extention
+      bool isEditorScript = false;
+      const char *ext = dStrrchr( scriptFilenameBuffer, '.' );
+      if( ext && ( dStricmp( ext, "." TORQUE_SCRIPT_EXTENSION) == 0 ) )
+      {
+         const char* ext2 = ext - 3;
+         if( dStricmp( ext2, ".ed." TORQUE_SCRIPT_EXTENSION) == 0 )
+            isEditorScript = true;
+      }
+      else if( ext && ( dStricmp( ext, ".gui" ) == 0 ) )
+      {
+         const char* ext2 = ext - 3;
+         if( dStricmp( ext2, ".ed.gui" ) == 0 )
+            isEditorScript = true;
+      }
+
+      const char *filenameOnly = dStrrchr(scriptFilenameBuffer, '/');
+      if(filenameOnly)
+         ++filenameOnly;
+      else
+         filenameOnly = scriptFilenameBuffer;
+
+      char nameBuffer[512];
+
+      if( isEditorScript )
+         dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".edso", NULL);
+      else
+         dStrcpyl(nameBuffer, sizeof(nameBuffer), dsoPath, "/", filenameOnly, ".dso", NULL);
+
+      void *data = NULL;
+      U32 dataSize = 0;
+      Torque::FS::ReadFile(scriptFilenameBuffer, data, dataSize, true);
+      if(data == NULL)
+      {
+         Con::errorf(ConsoleLogEntry::Script, "compile: invalid script file %s.", scriptFilenameBuffer);
+         return false;
+      }
+
+      const char *script = static_cast<const char *>(data);
+
+#ifdef TORQUE_DEBUG
+      Con::printf("Compiling %s...", scriptFilenameBuffer);
+#endif
+
+      CodeBlock *code = new CodeBlock();
+      code->compile(nameBuffer, scriptFilenameBuffer, script, overrideNoDso);
+      delete code;
+      delete[] script;
+
+      return true;
+   }
+
+}

+ 27 - 0
Engine/source/console/torquescript/runtime.h

@@ -0,0 +1,27 @@
+#ifndef _TORQUESCRIPT_RUNTIME_H_
+#define _TORQUESCRIPT_RUNTIME_H_
+#include "ast.h"
+#include "console/runtime.h"
+
+namespace TorqueScript
+{
+   class TorqueScriptRuntime : public Con::Runtime
+   {
+   public:
+      TorqueScriptRuntime();
+      ~TorqueScriptRuntime() override;
+
+      void expandEscapedCharacters(char* dest, const char* src) override { expandEscape(dest, src); }
+      bool collapseEscapedCharacters(char* buf) override { return collapseEscape(buf); }
+      Con::EvalResult evaluate(const char* string, bool echo = false, const char* fileName = NULL) override;
+      Con::EvalResult evaluate(const char* script, S32 frame, bool echo = false, const char *fileName = NULL) override;
+      Con::EvalResult evaluatef(const char* string, ...) override;
+      bool executeFile(const char* fileName, bool noCalls, bool journalScript) override;
+      bool compile(const char* fileName, bool overrideNoDso);
+   };
+
+   inline TorqueScriptRuntime* gRuntime = new TorqueScriptRuntime();
+   inline TorqueScriptRuntime* getRuntime() { return gRuntime; }
+}
+
+#endif

+ 0 - 12
Engine/source/core/volume.cpp

@@ -1234,18 +1234,6 @@ bool IsFile(const Path &path)
    return sgMountSystem.isFile(path);
 }
 
-bool IsScriptFile(const char* pFilePath)
-{
-   return (sgMountSystem.isFile(pFilePath)
-      || sgMountSystem.isFile(pFilePath + String(".dso"))
-      || sgMountSystem.isFile(pFilePath + String(".mis"))
-      || sgMountSystem.isFile(pFilePath + String(".mis.dso"))
-      || sgMountSystem.isFile(pFilePath + String(".gui"))
-      || sgMountSystem.isFile(pFilePath + String(".gui.dso"))
-      || sgMountSystem.isFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION))
-      || sgMountSystem.isFile(pFilePath + String("." TORQUE_SCRIPT_EXTENSION) + String(".dso")));
-}
-
 bool IsDirectory(const Path &path)
 {
    return sgMountSystem.isDirectory(path);

+ 0 - 1
Engine/source/core/volume.h

@@ -567,7 +567,6 @@ bool CreatePath(const Path &path);
 bool IsReadOnly(const Path &path);
 bool IsDirectory(const Path &path);
 bool IsFile(const Path &path);
-bool IsScriptFile(const char* pFilePath);
 bool VerifyWriteAccess(const Path &path);
 
 /// This returns a unique file path from the components 

+ 1 - 0
Engine/source/gfx/gfxCardProfile.cpp

@@ -25,6 +25,7 @@
 
 #include "console/console.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "core/volume.h"
 
 // NOTE: The script class docs are in 

+ 1 - 0
Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp

@@ -1,5 +1,6 @@
 #include "gui/core/guiCanvas.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "gfx/gfxDebugEvent.h"
 
 #include "gfx/gl/gfxGLDevice.h"

+ 1 - 0
Engine/source/gui/controls/guiConsoleTextCtrl.cpp

@@ -25,6 +25,7 @@
 
 #include "console/consoleTypes.h"
 #include "console/console.h"
+#include "console/script.h"
 #include "core/color.h"
 #include "gfx/gfxDrawUtil.h"
 #include "gui/core/guiDefaultControlRender.h"

+ 1 - 0
Engine/source/gui/controls/guiGameListMenuCtrl.cpp

@@ -24,6 +24,7 @@
 
 #include "console/consoleTypes.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "gfx/gfxDrawUtil.h"
 #include "gui/containers/guiScrollCtrl.h"
 #include "sim/actionMap.h"

+ 1 - 0
Engine/source/gui/controls/guiGameSettingsCtrl.cpp

@@ -24,6 +24,7 @@
 
 #include "console/consoleTypes.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "gfx/gfxDrawUtil.h"
 #include "gui/containers/guiScrollCtrl.h"
 #include "core/strings/stringUnit.h"

+ 39 - 38
Engine/source/gui/controls/guiListBoxCtrl.cpp

@@ -22,6 +22,7 @@
 #include "gui/controls/guiListBoxCtrl.h"
 #include "gfx/gfxDrawUtil.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 
 IMPLEMENT_CONOBJECT(GuiListBoxCtrl);
 
@@ -165,7 +166,7 @@ GuiListBoxCtrl::GuiListBoxCtrl()
    mColorBullet = true;
    mItemSize = Point2I(10,20);
    mLastClickItem = NULL;
-   
+
    mRenderTooltipDelegate.bind( this, &GuiListBoxCtrl::renderTooltip );
 }
 
@@ -469,11 +470,11 @@ void GuiListBoxCtrl::getSelectedItems( Vector<S32> &Items )
 {
    // Clear our return vector
    Items.clear();
-   
+
    // If there are no selected items, return an empty vector
    if( mSelectedItems.empty() )
       return;
-   
+
    for( S32 i = 0; i < mItems.size(); i++ )
       if( mItems[i]->isSelected )
          Items.push_back( i );
@@ -882,8 +883,8 @@ StringTableEntry GuiListBoxCtrl::getItemText( S32 index )
       Con::warnf( "GuiListBoxCtrl::getItemText - index out of range!" );
       return StringTable->lookup("");
    }
-   
-   return mItems[ index ]->itemText;   
+
+   return mItems[ index ]->itemText;
 }
 
 DefineEngineMethod( GuiListBoxCtrl, getItemObject,  const char*, (S32 index),,
@@ -917,7 +918,7 @@ SimObject* GuiListBoxCtrl::getItemObject( S32 index )
    SimObject *outObj;
    Sim::findObject( (SimObjectId)(uintptr_t)(mItems[ index ]->itemData), outObj );
 
-   return outObj;   
+   return outObj;
 }
 
 DefineEngineMethod( GuiListBoxCtrl, setItemText, void, (S32 index, const char* newtext),,
@@ -974,7 +975,7 @@ DefineEngineMethod( GuiListBoxCtrl, setItemTooltip, void, (S32 index, const char
       Con::errorf( "GuiListBoxCtrl::setItemTooltip - index '%i' out of range", index );
       return;
    }
-   
+
    object->mItems[ index ]->itemTooltip = text;
 }
 
@@ -1104,7 +1105,7 @@ bool GuiListBoxCtrl::renderTooltip( const Point2I &hoverPos, const Point2I& curs
    S32 hitItemIndex;
    if( hitTest( hoverPos, hitItemIndex ) )
       tipText = mItems[ hitItemIndex ]->itemTooltip;
-      
+
    return defaultTooltipRender( hoverPos, cursorPos, tipText );
 }
 
@@ -1115,7 +1116,7 @@ bool GuiListBoxCtrl::renderTooltip( const Point2I &hoverPos, const Point2I& curs
 bool GuiListBoxCtrl::hitTest( const Point2I& point, S32& outItem )
 {
    Point2I localPoint = globalToLocalCoord( point );
-   
+
    S32 itemHit = ( localPoint.y < 0 ) ? -1 : (S32)mFloor( (F32)localPoint.y / (F32)mItemSize.y );
    if ( itemHit >= mItems.size() || itemHit == -1 )
       return false;
@@ -1123,7 +1124,7 @@ bool GuiListBoxCtrl::hitTest( const Point2I& point, S32& outItem )
    LBItem *hitItem = mItems[ itemHit ];
    if ( hitItem == NULL )
       return false;
-      
+
    outItem = itemHit;
    return true;
 }
@@ -1144,7 +1145,7 @@ void GuiListBoxCtrl::onMouseDown( const GuiEvent &event )
    S32 itemHit;
    if( !hitTest( event.mousePoint, itemHit ) )
       return;
-      
+
    LBItem* hitItem = mItems[ itemHit ];
 
    // If we're not a multiple selection listbox, we simply select/unselect an item
@@ -1172,7 +1173,7 @@ void GuiListBoxCtrl::onMouseDown( const GuiEvent &event )
       return;
 
    }
-   
+
    // Deal with multiple selections
    if( event.modifier & SI_MULTISELECT)
    {
@@ -1219,7 +1220,7 @@ void GuiListBoxCtrl::onMouseUp( const GuiEvent& event )
 
    // Execute console command
    execConsoleCallback();
-   
+
    Parent::onMouseUp( event );
 }
 
@@ -1268,7 +1269,7 @@ U32 GuiListBoxCtrl::getStringElementCount( const char* inString )
                 // Yes...
                 search = 0;
                 break;
-            }   
+            }
         }
 
         // Found a seperator?
@@ -1300,7 +1301,7 @@ U32 GuiListBoxCtrl::getStringElementCount( const char* inString )
                     // Yes...
                     search = 0;
                     break;
-                }   
+                }
             }
 
             // Found Seperator?
@@ -1357,7 +1358,7 @@ const char* GuiListBoxCtrl::getStringElement( const char* inString, const U32 in
                     // Yes...
                     search = 0;
                     break;
-                }   
+                }
             }
 
             // Found a seperator?
@@ -1396,7 +1397,7 @@ const char* GuiListBoxCtrl::getStringElement( const char* inString, const U32 in
                         // Yes...
                         search = 0;
                         break;
-                    }   
+                    }
                 }
 
                 // Found Seperator?
@@ -1446,19 +1447,19 @@ void GuiListBoxCtrl::_mirror()
 
    // Allow script to filter out objects if desired.
 
-   Vector<SimObjectId> workingSet;   
+   Vector<SimObjectId> workingSet;
 
    // If the method is not defined we assume user wants us to add
    // all objects.
    bool isObjMirroredDefined = isMethod( "isObjectMirrored" );
-   
+
    for ( S32 i = 0; i < mirrorSet->size(); i++ )
    {
       bool addObj = true;
-        
+
       if ( isObjMirroredDefined )
-         addObj = isObjectMirrored_callback(mirrorSet->at(i)->getIdString()); 
-        
+         addObj = isObjectMirrored_callback(mirrorSet->at(i)->getIdString());
+
       if ( addObj )
          workingSet.push_back( mirrorSet->at(i)->getId() );
    }
@@ -1481,8 +1482,8 @@ void GuiListBoxCtrl::_mirror()
       if ( curObj )
       {
          if ( workingSet.contains( curId ) )
-         {         
-            mItems[i]->itemText = _makeMirrorItemName( curObj );            
+         {
+            mItems[i]->itemText = _makeMirrorItemName( curObj );
             keep = true;
          }
       }
@@ -1492,7 +1493,7 @@ void GuiListBoxCtrl::_mirror()
          deleteItem( i );
          i--;
       }
-   }   
+   }
 
 
    // Add items that are in the SimSet but not yet in the list.
@@ -1512,7 +1513,7 @@ void GuiListBoxCtrl::_mirror()
             break;
          }
       }
-      
+
       for ( U32 j = 0; j < mFilteredItems.size(); j++ )
       {
          if ( (SimObjectId)(uintptr_t)(mFilteredItems[j]->itemData) == curId )
@@ -1523,8 +1524,8 @@ void GuiListBoxCtrl::_mirror()
       }
 
       if ( !found )
-      {                  
-         addItem( _makeMirrorItemName( curObj ), (void*)(uintptr_t)curId );         
+      {
+         addItem( _makeMirrorItemName( curObj ), (void*)(uintptr_t)curId );
       }
    }
 }
@@ -1537,12 +1538,12 @@ StringTableEntry GuiListBoxCtrl::_makeMirrorItemName( SimObject *inObj )
    {
       Con::setIntVariable( "$ThisControl", getId() );
       Con::setIntVariable( "$ThisObject", inObj->getId() );
-      
-      outName = StringTable->insert( Con::evaluate( mMakeNameCallback ), true );      
+
+      outName = StringTable->insert( Con::evaluate( mMakeNameCallback ).value, true );
    }
    else if ( inObj->getName() )
       outName = StringTable->insert( inObj->getName() );
-   
+
    if ( !outName || !outName[0] )
       outName = StringTable->insert( "(no name)" );
 
@@ -1582,22 +1583,22 @@ DefineEngineMethod( GuiListBoxCtrl, addFilteredItem, void, (const char* newItem)
 void GuiListBoxCtrl::addFilteredItem( String item )
 {
    // Delete from selected items list
-   for ( S32 i = 0; i < mSelectedItems.size(); i++ ) 
+   for ( S32 i = 0; i < mSelectedItems.size(); i++ )
    {
       String itemText = mSelectedItems[i]->itemText;
-      if ( String::compare( itemText.c_str(), item.c_str() ) == 0 ) 
+      if ( String::compare( itemText.c_str(), item.c_str() ) == 0 )
       {
          mSelectedItems.erase_fast( i );
          break;
       }
    }
 
-   for ( S32 i = 0; i < mItems.size(); i++ ) 
+   for ( S32 i = 0; i < mItems.size(); i++ )
    {
       String itemText = mItems[i]->itemText;
       if( String::compare( itemText.c_str(), item.c_str() ) == 0 )
-      {  
-         mItems[i]->isSelected = false;      
+      {
+         mItems[i]->isSelected = false;
          mFilteredItems.push_front( mItems[i] );
          mItems.erase( &mItems[i] );
          break;
@@ -1625,11 +1626,11 @@ DefineEngineMethod( GuiListBoxCtrl, removeFilteredItem, void, ( const char* item
 
 void GuiListBoxCtrl::removeFilteredItem( String item )
 {
-   for ( S32 i = 0; i < mFilteredItems.size(); i++ ) 
+   for ( S32 i = 0; i < mFilteredItems.size(); i++ )
    {
       String itemText = mFilteredItems[i]->itemText;
       if( String::compare( itemText.c_str(), item.c_str() ) == 0 )
-      {        
+      {
          mItems.push_front( mFilteredItems[i] );
          mFilteredItems.erase( &mFilteredItems[i] );
          break;

+ 1 - 0
Engine/source/gui/controls/guiMLTextEditCtrl.cpp

@@ -28,6 +28,7 @@
 #include "core/stringBuffer.h"
 #include "gfx/gfxDrawUtil.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 
 IMPLEMENT_CONOBJECT(GuiMLTextEditCtrl);
 

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

@@ -32,7 +32,7 @@
 #include "console/console.h"
 #include "console/consoleInternal.h"
 #include "console/engineAPI.h"
-#include "console/codeBlock.h"
+#include "console/script.h"
 #include "gfx/bitmap/gBitmap.h"
 #include "sim/actionMap.h"
 #include "gui/core/guiCanvas.h"
@@ -2489,7 +2489,7 @@ void GuiControl::getCursor(GuiCursor *&cursor, bool &showCursor, const GuiEvent
 const char* GuiControl::evaluate( const char* str )
 {
    smThisControl = this;
-   const char* result = Con::evaluate(str, false);
+   const char* result = Con::evaluate(str, false).value;
    smThisControl = NULL;
 
    return result;

+ 1 - 0
Engine/source/gui/editor/guiEditCtrl.cpp

@@ -31,6 +31,7 @@
 #include "gui/containers/guiScrollCtrl.h"
 #include "core/strings/stringUnit.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 
 
 IMPLEMENT_CONOBJECT( GuiEditCtrl );

+ 1 - 0
Engine/source/gui/editor/inspector/dynamicGroup.cpp

@@ -25,6 +25,7 @@
 #include "gui/editor/inspector/dynamicGroup.h"
 #include "gui/editor/inspector/dynamicField.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 
 IMPLEMENT_CONOBJECT(GuiInspectorDynamicGroup);
 

+ 4 - 2
Engine/source/gui/editor/inspector/field.cpp

@@ -23,6 +23,8 @@
 #include "console/engineAPI.h"
 #include "platform/platform.h"
 #include "gui/editor/inspector/field.h"
+
+#include "console/script.h"
 #include "gui/buttons/guiIconButtonCtrl.h"
 #include "gui/editor/guiInspector.h"
 #include "core/util/safeDelete.h"
@@ -321,7 +323,7 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
          {
             char buffer[ 2048 ];
             expandEscape( buffer, newValue );
-            evaluationResult = Con::evaluatef("$f = \"%s\"; return ( %s );", oldValue.c_str(), buffer);
+            evaluationResult = Con::evaluatef("$f = \"%s\"; return ( %s );", oldValue.c_str(), buffer).value;
             newValue = evaluationResult.getString();
             Con::evaluatef("$f=0;");
          }
@@ -359,7 +361,7 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
                expandEscape( buffer, newComponentExpr );
 
                evaluationResult = Con::evaluatef("$f = \"%s\"; $v = \"%s\"; return ( %s );",
-                  oldComponentVal, oldValue.c_str(), buffer);
+                  oldComponentVal, oldValue.c_str(), buffer).value;
                Con::evaluatef("$f=0;$v=0;");
 
                if( !isFirst )

+ 2 - 0
Engine/source/gui/editor/inspector/group.cpp

@@ -22,6 +22,8 @@
 
 #include "gui/editor/guiInspector.h"
 #include "gui/editor/inspector/group.h"
+
+#include "console/script.h"
 #include "gui/editor/inspector/dynamicField.h"
 #include "gui/editor/inspector/datablockField.h"
 #include "gui/buttons/guiIconButtonCtrl.h"

+ 2 - 3
Engine/source/gui/editor/inspector/variableGroup.cpp

@@ -25,8 +25,7 @@
 #include "gui/editor/guiInspector.h"
 #include "gui/buttons/guiIconButtonCtrl.h"
 #include "console/consoleInternal.h"
-
-extern ExprEvalState gEvalState;
+#include "console/script.h"
 
 //-----------------------------------------------------------------------------
 // GuiInspectorVariableGroup
@@ -65,7 +64,7 @@ bool GuiInspectorVariableGroup::inspectGroup()
    {
       Vector<String> names;
 
-      gEvalState.globalVars.exportVariables(mSearchString, &names, NULL);
+      Con::gGlobalVars.exportVariables(mSearchString, &names, NULL);
 
       for (U32 i = 0; i < names.size(); i++)
       {

+ 1 - 0
Engine/source/gui/shiny/guiAudioCtrl.cpp

@@ -21,6 +21,7 @@
 //-----------------------------------------------------------------------------
 #include "gui/shiny/guiAudioCtrl.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "sfx/sfxSystem.h"
 #include "sfx/sfxTrack.h"
 #include "sfx/sfxSource.h"

+ 22 - 24
Engine/source/i18n/lang.cpp

@@ -25,8 +25,6 @@
 #include "core/stream/fileStream.h"
 #include "console/console.h"
 #include "console/consoleInternal.h"
-#include "console/ast.h"
-#include "console/compiler.h"
 #include "core/util/safeDelete.h"
 #include "console/engineAPI.h"
 
@@ -102,7 +100,7 @@ bool LangFile::load(Stream *s)
 bool LangFile::save(const UTF8 *filename)
 {
 	FileStream *fs;
-	
+
 	if(!isLoaded())
 		return false;
 
@@ -168,7 +166,7 @@ void LangFile::setLangName(const UTF8 *newName)
 {
 	if(mLangName)
 		delete [] mLangName;
-	
+
 	dsize_t langNameLen = dStrlen(newName) + 1;
 	mLangName = new UTF8 [langNameLen];
 	dStrcpy(mLangName, newName, langNameLen);
@@ -178,7 +176,7 @@ void LangFile::setLangFile(const UTF8 *langFile)
 {
 	if(mLangFile)
 		delete [] mLangFile;
-	
+
 	dsize_t langFileLen = dStrlen(langFile) + 1;
 	mLangFile = new UTF8 [langFileLen];
 	dStrcpy(mLangFile, langFile, langFileLen);
@@ -211,7 +209,7 @@ IMPLEMENT_CONOBJECT(LangTable);
 ConsoleDocClass( LangTable,
    "@brief Provides the code necessary to handle the low level management "
    "of the string tables for localization\n\n"
-   
+
    "One LangTable is created for each mod, as well as one for the C++ code. "
    "LangTable is responsible for obtaining the correct strings from each "
    "and relaying it to the appropriate controls.\n\n"
@@ -260,7 +258,7 @@ S32 LangTable::addLanguage(const UTF8 *filename, const UTF8 *name /* = NULL */)
    if(Torque::FS::IsFile(filename))
 	{
 		lang->setLangFile(filename);
-			
+
       S32 ret = addLanguage(lang);
 		if(ret >= 0)
 			return ret;
@@ -287,7 +285,7 @@ const U32 LangTable::getStringLength(const U32 id) const
 	const UTF8 *s = getString(id);
 	if(s)
 		return dStrlen(s);
-	
+
 	return 0;
 }
 
@@ -299,7 +297,7 @@ void LangTable::setDefaultLanguage(S32 langid)
 		{
 			if(mDefaultLang >= 0)
 				mLangTable[mDefaultLang]->deactivateLanguage();
-			
+
 			mDefaultLang = langid;
 		}
 	}
@@ -329,7 +327,7 @@ void LangTable::setCurrentLanguage(S32 langid)
 
 
 
-DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languageName), ("", ""), 
+DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languageName), ("", ""),
 			  "(string filename, [string languageName])"
 			  "@brief Adds a language to the table\n\n"
 			  "@param filename Name and path to the language file\n"
@@ -338,12 +336,12 @@ DefineEngineMethod(LangTable, addLanguage, S32, (String filename, String languag
 			  )
 {
 	UTF8 scriptFilenameBuffer[1024];
-	
+
 	Con::expandScriptFilename((char*)scriptFilenameBuffer, sizeof(scriptFilenameBuffer), filename);
 	return object->addLanguage(scriptFilenameBuffer, (const UTF8*)languageName);
 }
 
-DefineEngineMethod(LangTable, getString, const char *, (U32 id), , 
+DefineEngineMethod(LangTable, getString, const char *, (U32 id), ,
 			  "(string filename)"
 			  "@brief Grabs a string from the specified table\n\n"
 			  "If an invalid is passed, the function will attempt to "
@@ -359,7 +357,7 @@ DefineEngineMethod(LangTable, getString, const char *, (U32 id), ,
 		dStrcpy(ret, str, retLen);
 		return ret;
 	}
-	
+
 	return "";
 }
 
@@ -370,7 +368,7 @@ DefineEngineMethod(LangTable, setDefaultLanguage, void, (S32 langId), , "(int la
 	object->setDefaultLanguage(langId);
 }
 
-DefineEngineMethod(LangTable, setCurrentLanguage, void, (S32 langId), , 
+DefineEngineMethod(LangTable, setCurrentLanguage, void, (S32 langId), ,
 			  "(int language)"
 			  "@brief Sets the current language table for grabbing text\n\n"
 			  "@param language ID of the table\n")
@@ -398,7 +396,7 @@ DefineEngineMethod(LangTable, getLangName, const char *, (S32 langId), , "(int l
 		dStrcpy(ret, str, retLen);
 		return ret;
 	}
-	
+
 	return "";
 }
 
@@ -420,9 +418,9 @@ UTF8 *sanitiseVarName(const UTF8 *varName, UTF8 *buffer, U32 bufsize)
 		*buffer = 0;
 		return NULL;
 	}
-	
+
 	dStrcpy(buffer, (const UTF8*)"I18N::", bufsize);
-	
+
 	UTF8 *dptr = buffer + 6;
 	const UTF8 *sptr = varName;
 	while(*sptr)
@@ -435,27 +433,27 @@ UTF8 *sanitiseVarName(const UTF8 *varName, UTF8 *buffer, U32 bufsize)
 				*dptr++ = '_';
 			sptr++;
 		}
-		
+
 		if((dptr - buffer) >= (bufsize - 1))
 			break;
 	}
 	*dptr = 0;
-	
+
 	return buffer;
 }
 
 UTF8 *getCurrentModVarName(UTF8 *buffer, U32 bufsize)
 {
 	char varName[256];
-	StringTableEntry cbName = CodeBlock::getCurrentCodeBlockName();
-	
+	StringTableEntry cbName = Con::getCurrentScriptModuleName();
+
 	const UTF8 *slash = (const UTF8*)dStrchr(cbName, '/');
 	if (slash == NULL)
 	{
 		Con::errorf("Illegal CodeBlock path detected in sanitiseVarName() (no mod directory): %s", cbName);
 		return NULL;
 	}
-	
+
 	dStrncpy(varName, cbName, slash - (const UTF8*)cbName);
 	varName[slash - (const UTF8*)cbName] = 0;
 
@@ -465,7 +463,7 @@ UTF8 *getCurrentModVarName(UTF8 *buffer, U32 bufsize)
 const LangTable *getCurrentModLangTable()
 {
 	UTF8 saneVarName[256];
-	
+
 	if(getCurrentModVarName(saneVarName, sizeof(saneVarName)))
 	{
 		const LangTable *lt = dynamic_cast<LangTable *>(Sim::findObject(Con::getIntVariable((const char*)saneVarName)));
@@ -508,7 +506,7 @@ bool compiledFileNeedsUpdate(UTF8* filename)
    return false;
 }
 
-DefineEngineFunction(CompileLanguage, void, (const char* inputFile, bool createMap), (false), 
+DefineEngineFunction(CompileLanguage, void, (const char* inputFile, bool createMap), (false),
    "@brief Compiles a LSO language file."
    " if createIndex is true, will also create languageMap." TORQUE_SCRIPT_EXTENSION " with"
    " the global variables for each string index."

+ 2 - 0
Engine/source/postFx/postEffectVis.cpp

@@ -22,6 +22,8 @@
 
 #include "platform/platform.h"
 #include "postFx/postEffectVis.h"
+
+#include "console/script.h"
 #include "gui/containers/guiWindowCtrl.h"
 #include "gui/controls/guiBitmapCtrl.h"
 #include "gui/core/guiCanvas.h"

+ 3 - 1
Engine/source/sfx/sfxDescription.cpp

@@ -37,6 +37,8 @@
 #include "core/module.h"
 #include "math/mathIO.h"
 #include "math/mathTypes.h"
+#include "console/simBase.h"
+#include "console/engineAPI.h"
 
 
 IMPLEMENT_CO_DATABLOCK_V1( SFXDescription );
@@ -455,7 +457,7 @@ bool SFXDescription::onAdd()
    const char* channelValue = getDataField( sChannel, NULL );
    if( channelValue && channelValue[ 0 ] )
    {
-      ConsoleValue result = Con::evaluatef( "return sfxOldChannelToGroup( %s );", channelValue );
+      ConsoleValue result = Con::executef("sfxOldChannelToGroup", channelValue);
       const char* group = result.getString();
       if( !Sim::findObject( group, mSourceGroup ) )
          Con::errorf( "SFXDescription::onAdd - could not resolve channel '%s' to SFXSource", channelValue );

+ 1 - 0
Engine/source/sim/actionMap.cpp

@@ -28,6 +28,7 @@
 #include "core/stream/fileStream.h"
 #include "math/mMathFn.h"
 #include "console/engineAPI.h"
+#include "console/script.h"
 #include "math/mQuat.h"
 #include "math/mAngAxis.h"
 

+ 2 - 1
Engine/source/testing/ScriptTest.cpp

@@ -26,12 +26,13 @@
 #include "console/simBase.h"
 #include "console/engineAPI.h"
 #include "math/mMath.h"
+#include "console/script.h"
 #include "console/stringStack.h"
 #include "gui/buttons/guiIconButtonCtrl.h"
 
 inline ConsoleValue RunScript(const char* str)
 {
-   return std::move(Con::evaluate(str, false, NULL));
+   return std::move(Con::evaluate(str, false, NULL).value);
 }
 
 using ::testing::Matcher;

+ 7 - 9
Engine/source/testing/consoleTest.cpp

@@ -7,12 +7,10 @@
 #include "console/simBase.h"
 #include "console/engineAPI.h"
 #include "math/mMath.h"
+#include "console/script.h"
 #include "console/stringStack.h"
 #include "console/consoleInternal.h"
 
-// Stupid globals not declared in a header
-extern ExprEvalState gEvalState;
-
 using ::testing::Matcher;
 using ::testing::TypedEq;
 
@@ -25,10 +23,10 @@ protected:
 
    void SetUp() override
    {
-      
+
    }
-   
-   
+
+
 };
 
 TEST_F(ConsoleTest, executef)
@@ -176,7 +174,7 @@ TEST_F(ConsoleTest, execute)
 {
 	Con::evaluate("function testScriptExecuteFunction(%a,%b) {return %a SPC %b;}\nfunction testScriptExecuteFunction(%a,%b,%this) {return %a SPC %b;}\r\n", false, "testExecute");
 
-	U32 startStackPos = gEvalState.getStackDepth();
+	U32 startStackPos = Con::getFrameStack().size();
 	U32 startStringStackPos = STR.mStart;
 
 	// const char* versions of execute should maintain stack
@@ -187,7 +185,7 @@ TEST_F(ConsoleTest, execute)
 	EXPECT_STREQ(returnValue, "1 2") <<
 		"execute should return 1 2";
 
-	EXPECT_EQ(gEvalState.getStackDepth(), startStackPos) <<
+	EXPECT_EQ(Con::getFrameStack().size(), startStackPos) <<
 		"execute should restore stack";
 
 	returnValue = Con::execute(4, argvObject);
@@ -195,6 +193,6 @@ TEST_F(ConsoleTest, execute)
 	EXPECT_STREQ(returnValue, "1 2") <<
 		"execute should return 1 2";
 
-	EXPECT_EQ(gEvalState.getStackDepth(), startStackPos) <<
+	EXPECT_EQ(Con::getFrameStack().size(), startStackPos) <<
 		"execute should restore stack";
 }

+ 1 - 0
Engine/source/testing/engineAPITest.cpp

@@ -7,6 +7,7 @@
 #include "console/simBase.h"
 #include "console/engineAPI.h"
 #include "math/mMath.h"
+#include "console/script.h"
 
 using ::testing::Matcher;
 using ::testing::TypedEq;

+ 1 - 0
Engine/source/testing/runtimeClassRepTest.cpp

@@ -25,6 +25,7 @@
 #include "console/simBase.h"
 #include "console/consoleTypes.h"
 #include "console/runtimeClassRep.h"
+#include "console/script.h"
 
 class RuntimeRegisteredSimObject : public SimObject
 {

+ 8 - 6
Engine/source/testing/unitTesting.cpp

@@ -23,7 +23,7 @@
 
 #include "app/mainLoop.h"
 #include "console/console.h"
-#include "console/codeBlock.h"
+#include "console/script.h"
 #include "console/engineAPI.h"
 #include "console/consoleInternal.h"
 #include "gfx/gfxInit.h"
@@ -32,6 +32,8 @@
 #define _CRTDBG_MAP_ALLOC
 #include <crtdbg.h>
 #endif
+
+
 //-----------------------------------------------------------------------------
 
 class TorqueUnitTestListener : public ::testing::EmptyTestEventListener
@@ -195,9 +197,9 @@ DefineEngineFunction(addUnitTest, void, (const char* function), ,
    U32 ln = __LINE__;
    if (entry != NULL)
    {
-      file = entry->mCode->name;
+      file = entry->mModule->getName();
       U32 inst;
-      entry->mCode->findBreakLine(entry->mFunctionOffset, ln, inst);
+      entry->mModule->findBreakLine(entry->mFunctionOffset, ln, inst);
    }
    else
    {
@@ -210,9 +212,9 @@ DefineEngineFunction(addUnitTest, void, (const char* function), ,
 
 String scriptFileMessage(const char* message)
 {
-   Dictionary* frame = &gEvalState.getCurrentFrame();
-   CodeBlock* code = frame->code;
-   const char* scriptLine = code->getFileLine(frame->ip);
+   Dictionary* frame = Con::getCurrentStackFrame();
+   Con::Module* module = frame->module;
+   const char* scriptLine = module->getFileLine(frame->ip);
    return  String::ToString("at %s: %s", scriptLine, message);
 }
 

+ 3 - 2
Engine/source/ts/tsShape.cpp

@@ -29,12 +29,13 @@
 #include "console/console.h"
 #include "ts/tsShapeInstance.h"
 #include "collision/convex.h"
+#include "console/consoleInternal.h"
+#include "console/script.h"
 #include "materials/matInstance.h"
 #include "materials/materialManager.h"
 #include "math/mathIO.h"
 #include "core/util/endian.h"
 #include "core/stream/fileStream.h"
-#include "console/compiler.h"
 #include "core/fileObject.h"
 
 #ifdef TORQUE_COLLADA
@@ -2144,7 +2145,7 @@ template<> void *Resource<TSShape>::create(const Torque::Path &path)
    scriptPath.setExtension(TORQUE_SCRIPT_EXTENSION);
 
    // Don't execute the script if we're already doing so!
-   StringTableEntry currentScript = Platform::stripBasePath(CodeBlock::getCurrentCodeBlockFullPath());
+   StringTableEntry currentScript = Platform::stripBasePath(Con::getCurrentScriptModulePath());
    if (!scriptPath.getFullPath().equal(currentScript))
    {
       Torque::Path scriptPathDSO(scriptPath);

+ 1 - 1
Engine/source/windowManager/sdl/sdlWindow.cpp

@@ -650,7 +650,7 @@ void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
                _updateMonitorFromMove(evt);
                // If display device has changed, make sure window params are compatible with the new device.
                if (oldDisplay != Con::getIntVariable("pref::Video::deviceId", 0))
-                  Con::evaluate("configureCanvas();");
+                  Con::executef("configureCanvas");
                break;
             }
             case SDL_WINDOWEVENT_RESIZED:

+ 2 - 0
Engine/source/windowManager/windowInputGenerator.cpp

@@ -21,6 +21,8 @@
 //-----------------------------------------------------------------------------
 
 #include "windowManager/windowInputGenerator.h"
+
+#include "console/script.h"
 #include "windowManager/platformWindow.h"
 #include "sim/actionMap.h"
 #include "platform/input/IProcessInput.h"