There are various forms of dynamic compilations of scripts. In the following subtopics I try to explain the theory of them and give some information on how they can be implemented.
The most common form of dynamic compilations is building new modules on demand, i.e. as they are needed. When using this the application or game engine is typically designed to have separate scripts to perform different tasks, e.g. menu handling, different types of AI controllers, player controller, etc. If these separate scripts have an abstraction layer through the application to interact with each other it is very easy to build the scripts on demand.
To build a new script on demand, simply get a new module, add the needed script sections to it and build it just as you would when building the first script. As each module is independent the previously existing module will be unaffected.
Each module can be configured to see a different application interface, so there is no need to create different engine instances.
Though modules are independent, they can still interact with each other if the application provides the interface for that. To make the communication between modules easier one can chose to use shared script entities. Shared script entities will be compiled only once by the first module that includes the code. Any subsequent module that also include the code for the shared entity will reuse what was built by the first module, i.e. will share the internal type and bytecode.
Another option is to import global functions from a previously compiled module. In this case the application must make sure the function that exports the functions is compiled first, then after building the module that imports the function the application must call the asIScriptModule::BindAllImportedFunctions so conclude the imports.
Besides the ordinary compilation of scripts and subsequent executions, AngelScript also support dynamically compiling additional functions and global variables to incrementally add to the scope of a module. These functions and variables will become part of the scope, just as if they had been included in the initial script compilation which means that subsequent executions or incremental compilations can use them.
It is also possible to dynamically remove functions and variables. Doing so doesn't immediately discard the functions or variables, so other functions that still refer to them will not fail when executing them. They will however no longer be visible for new compilations or when searching for functions or variables in the module.
This kind of dynamic compilations is most useful when dealing with user interaction, e.g. an ingame console, or perhaps event handlers, e.g. a trigger on a GUI button click.
Hot reloading is most often used when quick change & test cycles are wanted. It is quite common for game engines to have a debug mode that continuously monitors the script files to detect any updates that are made, and when detected automatically reloads the scripts without restarting the game. This allows the developers, for example, to quickly change the behaviour of the AI and immediately see the result without having to play through the entire level over and over again.
Hot reloading without preserving the state of existing objects is quite trivial. Simply discard everything, reload the scripts, and create new objects. On the other hand, hot reloading scripts while preserving the state of existing objects can be quite tricky, but is also the most rewarding when implemented successfully.
The first part to reloading while preserving the state is keeping track of the object instances so the application knows which objects needs to be serialized when a module is hot reloaded. It is entirely up to the application to build and maintain this mapping.
The second part is knowing which script files that will trigger a reload when changed. When building the module the application needs to store the list of the files that were added to it. If you use the standard script builder add-on, then it provides methods to enumerate the included sections or files.
The third part is the hardest, and that is to implement the actual serialization. Serializing object members of value types is normally quite trivial, simply enumerate the object properties and store a name-value pair for each. Serializing object members of reference types needs some consideration, as depending on the object that is referred to, either you will be able to store the actual pointer, or you will need to store some kind of descriptor as the referred to object will also be recreated during the reload.
Once all the objects that will need to be recreated after the reload have been serialized for backup, the module can be rebuilt using the normal procedure for compiling a script. Afterwards the serialized objects needs to be recreated. Once created you'll enumerate the members and set their values or references according to the backed up data.