Skip to content

Switch to Roslyn instead of IL emitting #67

@snakex64

Description

@snakex64

To enable modern debugging and future proffing we must switch the entire code generation from IL emitting (with expression trees) to using the Roslyin SDK. We must generate a SyntaxTree (not raw C#) as this will prevent many mitakes that can occur with raw string generation.

The code currently doesn't work due to an upgrade to .net 10, it doesn't work in the IL code generation so the switch to Roslyin will fix it. We can completely remove the expression tree stuff, FastCompiler library and all.

Here is a complete description of work requirement :

Objective:

Refactor an existing Visual Programming Language (VPL) runtime. The current implementation uses System.Linq.Expressions to generate code. You must replace this with Roslyn SyntaxTree generation to enable "native" debugging (breakpoints, stepping, inspection) for in-memory compiled assemblies.

Architectural Pattern: Polymorphic Generation

Do not use a central giant converter/visitor class. You must implement a Distributed/Polymorphic pattern where each Node class is responsible for generating its own Roslyn syntax.

  1. The GenerationContext Class (New Requirement)
    Since SyntaxNode objects do not automatically handle data flow like Expression trees, you must implement a GenerationContext class to pass between nodes. Validate if such class already exists and reuse/adapt it if so. Otherwise create a new one and pass it down during generation.

Responsibility:

Symbol Table: A dictionary mapping ConnectionID to string (Generated C# Variable Name).

Name Generator: A method to create unique variable names (e.g., GetUniqueName("node_1_out") -> node_1_out_x92).

Statement Buffer: A collection to hold auxiliary statements. (e.g., if a Node needs to emit 3 lines of setup code but return 1 variable name, it adds the setup lines here).

  1. The Abstract Node Update
    Refactor the base node class/interfaces as required.

Remove: the previous expression generation

Add: public abstract SyntaxNode GenerateRoslynSyntax(GenerationContext ctx); (and any additionally required parameters)

Behavior:

Nodes must look up input variable names from the ctx.

Nodes must register their output variable names into the ctx.

Nodes return a StatementSyntax (for execution flow) or an ExpressionSyntax (for data calculation).

  1. The Compilation Service
    Modify the existing compilation service

Input: The root CompilationUnitSyntax generated by the graph.

Source Embedding:

Convert the tree to a string: tree.GetRoot().NormalizeWhitespace().ToFullString().

Use EmbeddedText.FromSource(...) to embed this string into the PDB. This allows the debugger to show the code even though it exists only in RAM.

Emission:

Create CSharpCompilation with OptimizationLevel.Debug.

Emit to MemoryStream using DebugInformationFormat.PortablePdb.

Load using Assembly.Load(peBytes, pdbBytes).

  1. Constraints & Pitfalls to Avoid
    Type Safety: Do not try to resolve complex types manually. Use var (Implicit Type) in generated C# variable declarations wherever possible.

Whitespace: You must call .NormalizeWhitespace() on the final root node before compilation. Without this, #line directives may collapse onto a single line, breaking the debugger mapping.

Scope: Be careful with variable scoping. If a variable is generated inside an if block (e.g., inside a Conditional Node), ensure it is declared outside the block if it is needed by subsequent nodes (Variable Hoisting).

Limit: limit the amount of code modified to minimum. Make sure you read how it is done before modifying any code

Test: Add as much testing as possible

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions