| File: Microsoft\CSharp\RuntimeBinder\Semantics\EXPRExtensions.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.CSharp\src\Microsoft.CSharp.csproj (Microsoft.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal static class EXPRExtensions { public static Expr Map(this Expr expr, Func<Expr, Expr> f) { Debug.Assert(f != null); if (expr == null) { return f(null); } Expr result = null; Expr tail = null; foreach (Expr item in expr.ToEnumerable()) { Expr mappedItem = f(item); ExprFactory.AppendItemToList(mappedItem, ref result, ref tail); } return result; } public static IEnumerable<Expr> ToEnumerable(this Expr expr) { Expr exprCur = expr; while (exprCur != null) { if (exprCur is ExprList list) { yield return list.OptionalElement; exprCur = list.OptionalNextListNode; } else { yield return exprCur; yield break; } } } [Conditional("DEBUG")] public static void AssertIsBin(this Expr expr) { Debug.Assert(expr?.Kind >= ExpressionKind.TypeLimit && 0 != (expr.Flags & EXPRFLAG.EXF_BINOP)); } public static bool isLvalue(this Expr expr) { return (expr == null) ? false : 0 != (expr.Flags & EXPRFLAG.EXF_LVALUE); } public static bool isChecked(this Expr expr) { return (expr == null) ? false : 0 != (expr.Flags & EXPRFLAG.EXF_CHECKOVERFLOW); } public static bool isNull(this Expr expr) => expr is ExprConstant constant && expr.Type.FundamentalType == FUNDTYPE.FT_REF && constant.Val.IsNullRef; public static bool IsZero(this Expr expr) => expr is ExprConstant constant && constant.IsZero; private static Expr GetSeqVal(this Expr expr) { // Scan through EK_SEQUENCE and EK_SEQREV exprs to get the real value. if (expr == null) { return null; } Expr exprVal = expr; while (exprVal.Kind == ExpressionKind.Sequence) { exprVal = ((ExprBinOp)exprVal).OptionalRightChild; } return exprVal; } /*************************************************************************************************** Determine whether this expr has a constant value (EK_CONSTANT or EK_ZEROINIT), possibly with side effects (via EK_SEQUENCE or EK_SEQREV). Returns NULL if not, or the constant expr if so. The returned Expr will always be an EK_CONSTANT or EK_ZEROINIT. ***************************************************************************************************/ public static Expr GetConst(this Expr expr) { Expr exprVal = expr.GetSeqVal(); switch (exprVal?.Kind) { case ExpressionKind.Constant: case ExpressionKind.ZeroInit: return exprVal; } return null; } } }