A .NET 8/.NET 10 library for building, manipulating, serialising, and converting an object-oriented intermediate representation (IR). Think LLVM IR, but designed from the ground up for OO languages — classes, interfaces, structs, generics, virtual dispatch, and all.
History. This library merges two codebases that were the same IR split in two:
- ObjectIR.Core — the rich AST, TextIR parser, JSON/BSON/FOB serialisation, fluent builder, and module composition.
- ObjectRT.Reader / ObjectRT.Abstractions — the index-based wire model (
ORBTModule, string pool,ushort-indexed records) and the ObjectIL / ORBT binary parsers used by the ObjectRT VM.ORBT, FOB/IR, and ObjectIL/TextIR are the same format family under different names — ORBT is the binary format, the old FOB/IR v3 payload wrapper has been removed. ObjektRT.Core keeps both representations in one library and provides a bidirectional conversion layer between them, so tooling (compilers, analysers, the ObjectRT VM, the finite compiler collection) can move between them freely.
The obsolete legacy
IRmodel has been removed (it was marked end-of-life in the old README and is preserved in git history).
- Build an AST with a fluent
IRBuilderor parse it from TextIR / ObjectIL source - Parse ObjectIL text into the index-based wire model (
ObjectILParser) - Read / write the ORBT binary format (
ORBTReader,ORBTWriter,OrbtFileReader) - Convert between the AST and the wire model in both directions (
Conversion/) - Serialize to JSON or BSON (
Serialization/), or to the ORBT binary format (ORBTReader/ORBTWriter) - Compose multiple modules (
Composition/) - Execute (in the ObjectRT VM) or analyse (in compilers)
ObjektRT.Core/
├── Model/ wire model — ORBTModule, StringPool, records, typed operands, wire opcodes
├── AST/ rich AST — ModuleNode, statements, instructions, AST opcodes
├── Parsing/ ObjectIL tokenizer+parser → wire model; TextIR parser → AST
├── Serialization/ ORBT binary reader/writer, BinaryStream, JSON/BSON serializers, ModuleLoader
├── Conversion/ AstToModelConverter + ModelToAstConverter (bidirectional)
├── Builder/ fluent IRBuilder
├── Composition/ module composition and dependency resolution
├── Attributes/ module metadata attributes
└── Core/ Value<T> container, ObjectNode placeholder
dotnet add package ObjektRT.CoreParse ObjectIL straight into the wire model, then up into an AST:
using ObjektRT.Core.Parsing;
using ObjektRT.Core.Conversion;
var model = new ObjectILParser(source).ParseModule(); // wire model
var ast = new ModelToAstConverter().Convert(model); // rich AST
var back = new AstToModelConverter().Convert(ast); // wire model againBuild an AST directly and lower it to a runnable wire module:
using ObjektRT.Core.Conversion;
using ObjektRT.Core.AST;
var ast = new ModuleNode("MyApp") { Version = "1.0.0" };
ast.AddClass("Animal");
var model = new AstToModelConverter().Convert(ast);- AST → Model: structured
if/whileare lowered to flatbrfalse/br/dupbytecode with labels (identical to the ObjectIL parser); locals are hoisted to the method local table; call targets become name + parameter count (the wire call encoding). AST opcodes with no wire encoding (Shl,Beq,Box,For,Switch, …) throwNotSupportedException— checkAstToModelConverter.TryGetWireOpcodefirst. - Model → AST: canonical
if/whileshapes are reconstructed back into structured statements; anything else stays flatSimpleInstructions (semantics preserved, structure flat). Field access modifiers do not exist in the wire format (fields come backpublic); wireEnumtypes map toClassNode(the AST has no enum node).try/catchhas no AST representation yet.
Opcode mappings are exposed as AstToModelConverter.TryGetWireOpcode / ModelToAstConverter.TryGetAstOpcode for front-ends.
dotnet build ObjektRT.Core.slnx
dotnet run --project tests/ObjektRT.Core.Tests # round-trip smoke tests- PackageId:
ObjektRT.Core - Version: 1.0.0 (breaking rename from
ObjectIR.Core0.1.3 — old package stays published for legacy consumers)
MIT — see LICENSE.