From 110fb3f790caf810087e1f1586b812ea2c782795 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 5 May 2026 11:55:56 +0000
Subject: [PATCH 1/3] Initial plan
From 8df91dc6932da7a13639341a91176e4e5dfbcc84 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 5 May 2026 12:03:19 +0000
Subject: [PATCH 2/3] Clean up FlatExpression naming and index storage
Agent-Logs-Url: https://github.com/dadhi/FastExpressionCompiler/sessions/1746b8bc-0db6-44b9-8a60-8e4068db9213
Co-authored-by: dadhi <39516+dadhi@users.noreply.github.com>
---
.../FlatExpression.cs | 544 ++++++++----------
.../LightExpressionPropertyTests.cs | 2 +-
.../LightExpressionTests.cs | 68 ++-
3 files changed, 296 insertions(+), 318 deletions(-)
diff --git a/src/FastExpressionCompiler.LightExpression/FlatExpression.cs b/src/FastExpressionCompiler.LightExpression/FlatExpression.cs
index cd9023a6..ad07b3fe 100644
--- a/src/FastExpressionCompiler.LightExpression/FlatExpression.cs
+++ b/src/FastExpressionCompiler.LightExpression/FlatExpression.cs
@@ -45,7 +45,7 @@ public enum ExprNodeKind : byte
UInt16Pair,
}
-/// Stores one flat expression node plus its intrusive child-link metadata in 24 bytes on 64-bit runtimes.
+/// Stores one flat expression node and its child-link metadata in 24 bytes on 64-bit runtimes.
///
/// Layout (64-bit): Type(8) | Obj(8) | _meta(4) | _data(4) = 24 bytes.
/// _meta bits: NodeType(8)|Tag(8)|NextIdx(16).
@@ -80,7 +80,7 @@ public struct ExprNode
[FieldOffset(16)]
private uint _meta;
- /// ChildCount(16b) | ChildIdx(16b) —OR— raw 32-bit inline constant value.
+ /// ChildCount(16b) | ChildIdx(16b) or raw 32-bit inline constant value.
[FieldOffset(20)]
private uint _data;
@@ -92,13 +92,13 @@ public struct ExprNode
internal byte Flags => (byte)((_meta >> (MetaTagShift + FlagsShift)) & 0xFu);
- /// Gets the next sibling node index in the intrusive child chain.
+ /// Gets the next sibling node idx.
public int NextIdx => (int)(_meta & 0xFFFFu);
/// Gets the number of direct children linked from this node.
public int ChildCount => (int)(_data >> DataCountShift);
- /// Gets the first child index or an auxiliary payload index.
+ /// Gets the first child idx or an auxiliary payload idx.
public int ChildIdx => (int)(_data & DataIdxMask);
/// Gets the raw 32-bit value for inline primitive constants. Only valid when == .
@@ -109,8 +109,8 @@ internal ExprNode(Type type, object obj, ExpressionType nodeType, ExprNodeKind k
Type = type;
Obj = obj;
var tag = (byte)((flags << FlagsShift) | (byte)kind);
- _meta = ((uint)(byte)nodeType << MetaNodeTypeShift) | ((uint)tag << MetaTagShift) | (ushort)nextIdx;
- _data = ((uint)(ushort)childCount << DataCountShift) | (ushort)childIdx;
+ _meta = ((uint)(byte)nodeType << MetaNodeTypeShift) | ((uint)tag << MetaTagShift) | checked((ushort)nextIdx);
+ _data = ((uint)checked((ushort)childCount) << DataCountShift) | checked((ushort)childIdx);
}
/// Constructs an inline primitive constant node; is set to .
@@ -124,11 +124,11 @@ internal ExprNode(Type type, uint inlineValue)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SetNextIdx(int nextIdx) =>
- _meta = (_meta & MetaKeepWithoutNext) | (ushort)nextIdx;
+ _meta = (_meta & MetaKeepWithoutNext) | checked((ushort)nextIdx);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SetChildInfo(int childIdx, int childCount) =>
- _data = ((uint)(ushort)childCount << DataCountShift) | (ushort)childIdx;
+ _data = ((uint)checked((ushort)childCount) << DataCountShift) | checked((ushort)childIdx);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool Is(ExprNodeKind kind) => Kind == kind;
@@ -146,16 +146,16 @@ internal bool ShouldCloneWhenLinked() =>
Kind == ExprNodeKind.ObjectReference || ChildCount == 0;
}
-/// Maps a lambda node to a captured outer parameter/variable identity used for closure creation.
-/// Uses the same 16-bit index range already used by flat-expression node links and identities.
+/// Maps a lambda node to a captured outer parameter or variable.
+/// Uses the same 16-bit storage range as the flat node links and identities.
[StructLayout(LayoutKind.Explicit, Size = 6)]
public struct LambdaClosureParameterUsage
{
- /// The lambda node index in the flat-expression node array.
+ /// The lambda node idx in the flat-expression node array.
[FieldOffset(0)]
public ushort LambdaIdx;
- /// The parameter-usage expression node index in the flat-expression node array.
+ /// The parameter-usage expression node idx in the flat-expression node array.
[FieldOffset(2)]
public ushort ParameterIdx;
@@ -172,7 +172,7 @@ public LambdaClosureParameterUsage(ushort lambdaIdx, ushort parameterIdx, ushort
}
}
-/// Stores an expression tree as a flat node array plus out-of-line closure constants.
+/// Stores an expression tree as flat nodes plus separate closure constants.
public struct ExprTree
{
private static readonly object ClosureConstantMarker = new();
@@ -184,8 +184,8 @@ public struct ExprTree
private const byte CatchHasFilterFlag = 2;
private const byte TryFaultFlag = 1;
- /// Gets or sets the root node index.
- public int RootIndex;
+ /// Gets or sets the root node idx.
+ public int RootIdx;
/// Gets or sets the flat node storage.
public SmallList, NoArrayPool> Nodes;
@@ -193,59 +193,44 @@ public struct ExprTree
/// Gets or sets closure constants that are referenced from constant nodes.
public SmallList