We have already mentioned the support of PHP’s
eval () function a long time ago, but there have been some interesting updates on how the code being passed to
eval () is processed!
eval is a well-known function of dynamic languages allowing you to execute code at runtime. The dynamic language is usually interpreted and the runtime contains the parser and interpreter already, so implementing such a feature is no rocket science. Still…
result=compilation.Emit (peStream, pdbStream, emitOptions, embeddedTexts);
Roslyn’s compilation has a neat API method
Emit , which according to our options performs the compilation – in-memory. It writes the content of the assembly and debug information into
System.IO.Stream s –
pdbStream . All the diagnostics are populated into the
object for further inspection; we might for example forbid the execution of code containing any warning or just a specific warning.
assembly=System.Runtime.Loader.AssemblyLoadContext .Default .LoadFromStream (peStream, pdbStream)
We keep things in memory only and load our resulting assembly from the stream. Assuming you have a debugger attached, it will load the PDB and process it. Using reflection, we find the script entry point from the loaded
assembly (in case of PHP scripts it’s a static method
(xxx. (Context, PhpArray, object, RuntimeTypeHandle) . It takes all the parameters it needs to properly execute within PHP code – runtime
$ this object and the current type context.
The method is then invoked! The rest is handled by the CoreCLR debugger. If you press
F in your favorite IDE, the debugger will jump over the compilation stuff and steps right inside the invoked method. The debugger will start looking for the source code, which is annotated to be in our virtual file path. It finds it within the loaded debug information and displays it to you!
Visual Studio, for instance, will create a temporary file, copies the content of Embedded Source document into it and opens it in the editor. Also, it remembers the mapping between the original virtual file path and allows you to put breakpoints in there.
Visual Studio Code will open a virtual document for this purpose allowing you to do the same.
A small touch is to make the virtual Embedded Source text colorized when opened by the debugger in your IDE. Fortunately, this is not that hard. First, the virtual file path has to have the right file extension, in our case
. Php . (The other option would be to implement a custom language service for the IDE as an extension).
Next, since the code passed to
eval () in PHP omits the opening code tags (
php ), the editor syntax highlighter would treat the code as text or HTML. So before compiling the code, we prefix it with the commented opening tag:
# Php . The hash is treated as a line comment, but the editor views it as HTML text, and
Php as the opening tag. The rest of the code is nicely colorized. (the other editor features then work as well – tooltips, structure guidelines, outlining, etc.)
I don’t think Embedded Source and Roslyn’s compilation were designed for dynamic languages in the first place, but it seems like a perfect use case for those features. This greatly improves the debugging experience of compiled dynamic languages - out of the box.
Just a side note – this works for a few other dynamic documents in PHP that cause other IDEs headaches –
create_function () ,
eval () and debugging inside the PHAR archives, which are embedded into PDB as well, at compile-time already.
Posted on February 823, , in category (Information , tags: (dynamic ,
- (Read More)