-
Notifications
You must be signed in to change notification settings - Fork 90
Assembly Architecture
This note describes the relationship between the three core DLR assemblies in src/core/:
Microsoft.ScriptingMicrosoft.DynamicMicrosoft.Scripting.Metadata
It is intended as a quick orientation guide for contributors working in the DLR subtree and for language implementations such as IronPython that build on top of it.
At the project level, the dependency direction is:
Microsoft.Scripting
Microsoft.Scripting.Metadata -> Microsoft.Scripting
Microsoft.Dynamic -> Microsoft.Scripting
Microsoft.Dynamic -> Microsoft.Scripting.Metadata (when FEATURE_METADATA_READER is enabled)
In practice, FEATURE_METADATA_READER is enabled by the DLR build for the current target frameworks, so Microsoft.Dynamic normally consumes Microsoft.Scripting.Metadata.
The assemblies form a simple stack:
graph TD
A[Language implementations, including IronPython] --> B[Microsoft.Dynamic]
B --> C[Microsoft.Scripting.Metadata]
B --> D[Microsoft.Scripting]
A --> D
C --> D
The intended separation is:
-
Microsoft.Scriptingprovides the base hosting and runtime contracts. -
Microsoft.Dynamicprovides the heavier execution, code generation, interpreter, and interop machinery used by dynamic languages. -
Microsoft.Scripting.Metadataprovides low-level PE and CLR metadata reading used for specific reflection-oriented fast paths.
Microsoft.Scripting is the foundational DLR assembly. It defines the public concepts that hosts and language runtimes use to communicate.
- Define the hosting API surface.
- Define source-code, compilation, scope, and runtime abstractions.
- Provide shared runtime services that language implementations extend.
- Provide general utility code used across the DLR.
Key areas in the project are:
-
Hosting/: host-facing APIs such asScriptRuntime,ScriptEngine,ScriptSource,ScriptScope,CompiledCode, and related setup/configuration types. -
Runtime/: core runtime abstractions such asLanguageContext,ScriptDomainManager,Scope,ScriptCode,DynamicOperations, and tokenizer/parser service hooks. - Root-level source unit and diagnostics types such as
SourceUnit,SourceSpan,SourceLocation,ErrorSink,SyntaxErrorException, and compiler option types. -
Utils/: shared utility helpers used across the DLR.
Code belongs in Microsoft.Scripting when it defines a cross-language abstraction or a host/runtime API surface that should exist independently of a specific execution strategy.
Typical examples:
- host configuration and runtime startup
- source text and error reporting
- scope and engine abstractions
- language service extension points
Microsoft.Dynamic sits above Microsoft.Scripting and contains much of the implementation machinery dynamic languages actually rely on at runtime.
Although the project name is Microsoft.Dynamic, many of its namespaces are still under Microsoft.Scripting.*. This is historical DLR structure rather than a layering violation.
- Implement execution infrastructure for dynamic languages.
- Provide code-generation and interpreter support.
- Extend expression tree support with DLR-specific nodes and helpers.
- Provide interop, debugging, and reflection helpers used by language implementations.
Key areas in the project are:
-
Ast/: DLR expression-tree extensions and builders. -
Interpreter/: the light interpreter, interpreted frames, instruction set, and light lambda support. -
Generation/: IL generation, dynamic assembly generation, snippets, delegate helpers, and related emit infrastructure. -
ComInterop/: COM binding and interop helpers. -
Debugging/: runtime debugging support. -
Runtime/: a smaller set of runtime-adjacent implementation helpers. -
Utils/: reflection and collection helpers, including metadata-assisted reflection fast paths. -
Xaml/: XAML-related support for dynamic objects.
Code belongs in Microsoft.Dynamic when it is lower-level implementation machinery rather than a base host/runtime contract.
Typical examples:
- interpreter execution engine
- dynamic IL or assembly emission
- expression rewriting or custom AST nodes
- COM interop support
- reflection helpers with performance-oriented implementation details
Microsoft.Scripting.Metadata is a focused support assembly for reading CLI metadata directly from PE files and loaded modules.
- Parse PE and CLR metadata structures directly.
- Expose metadata table readers and helpers.
- Support reflection-oriented optimizations without relying exclusively on higher-level reflection APIs.
Key areas in the project are:
- PE file structures and readers
- metadata table enumerators and table implementations
- memory-mapped and block-based readers
- helpers for converting metadata records into CLR-facing concepts such as
AssemblyName - services that expose targeted metadata queries, such as visible extension-method discovery
Code belongs in Microsoft.Scripting.Metadata when it is specifically about reading or interpreting CLI metadata. It should stay narrowly focused; general reflection helpers belong elsewhere.
The clearest current dependency is in reflection utilities. Microsoft.Dynamic uses Microsoft.Scripting.Metadata to provide a fast path for discovering visible extension methods in assemblies when metadata-reader support is available and trusted.
That keeps metadata parsing isolated in a dedicated assembly while allowing Microsoft.Dynamic to use it for performance-sensitive reflection tasks.
When deciding where to place new code:
- prefer
Microsoft.Scriptingfor stable, cross-language abstractions and host-facing APIs; - prefer
Microsoft.Dynamicfor implementation details, execution machinery, and performance-oriented helpers; - prefer
Microsoft.Scripting.Metadataonly for narrowly scoped metadata-reader functionality; - avoid pulling metadata-reading logic directly into
Microsoft.Dynamicunless it truly belongs in the dedicated metadata layer.
Keeping this layering intact makes the DLR easier to reason about and reduces accidental coupling between public hosting abstractions and low-level implementation details.