Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
LightCompiler.cs2053 linesDownload Raw Back to interpreter
1/* ****************************************************************************2 *3 * Copyright (c) Microsoft Corporation.4 *5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A6 * copy of the license can be found in the License.html file at the root of this distribution. If7 * you cannot locate the Apache License, Version 2.0, please send an email to8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound9 * by the terms of the Apache License, Version 2.0.10 *11 * You must not remove this notice, or any other, from this software.12 *13 *14 * ***************************************************************************/15 16#if !CLR217using System.Globalization;18using System.Linq;19using System.Linq.Expressions;20#endif21 22using System.Collections.Generic;23using System.Diagnostics;24using System.Reflection;25using AstUtils = System.Management.Automation.Interpreter.Utils;26using System.Runtime.CompilerServices;27 28namespace System.Management.Automation.Interpreter29{30    internal sealed class ExceptionHandler31    {32        public readonly Type ExceptionType;33        public readonly int StartIndex;34        public readonly int EndIndex;35        public readonly int LabelIndex;36        public readonly int HandlerStartIndex;37        public readonly int HandlerEndIndex;38 39        internal TryCatchFinallyHandler Parent = null;40 41        public bool IsFault { get { return ExceptionType == null; } }42 43        internal ExceptionHandler(int start, int end, int labelIndex, int handlerStartIndex, int handlerEndIndex, Type exceptionType)44        {45            StartIndex = start;46            EndIndex = end;47            LabelIndex = labelIndex;48            ExceptionType = exceptionType;49            HandlerStartIndex = handlerStartIndex;50            HandlerEndIndex = handlerEndIndex;51        }52 53        internal void SetParent(TryCatchFinallyHandler tryHandler)54        {55            Debug.Assert(Parent == null);56            Parent = tryHandler;57        }58 59        public bool Matches(Type exceptionType)60        {61            if (ExceptionType == null || ExceptionType.IsAssignableFrom(exceptionType))62            {63                return true;64            }65 66            return false;67        }68 69        public bool IsBetterThan(ExceptionHandler other)70        {71            if (other == null)72            {73                return true;74            }75 76            Debug.Assert(StartIndex == other.StartIndex && EndIndex == other.EndIndex, "we only need to compare handlers for the same try block");77            return HandlerStartIndex < other.HandlerStartIndex;78        }79 80        internal bool IsInsideTryBlock(int index)81        {82            return index >= StartIndex && index < EndIndex;83        }84 85        internal bool IsInsideCatchBlock(int index)86        {87            return index >= HandlerStartIndex && index < HandlerEndIndex;88        }89 90        internal bool IsInsideFinallyBlock(int index)91        {92            Debug.Assert(Parent != null);93            return Parent.IsFinallyBlockExist && index >= Parent.FinallyStartIndex && index < Parent.FinallyEndIndex;94        }95 96        public override string ToString()97        {98            return string.Format(99                CultureInfo.InvariantCulture,100                "{0} [{1}-{2}] [{3}->{4}]",101                IsFault ? "fault" : "catch(" + ExceptionType.Name + ")",102                StartIndex,103                EndIndex,104                HandlerStartIndex,105                HandlerEndIndex);106        }107    }108 109    internal sealed class TryCatchFinallyHandler110    {111        internal readonly int TryStartIndex = Instruction.UnknownInstrIndex;112        internal readonly int TryEndIndex = Instruction.UnknownInstrIndex;113        internal readonly int FinallyStartIndex = Instruction.UnknownInstrIndex;114        internal readonly int FinallyEndIndex = Instruction.UnknownInstrIndex;115        internal readonly int GotoEndTargetIndex = Instruction.UnknownInstrIndex;116 117        private readonly ExceptionHandler[] _handlers;118 119        internal bool IsFinallyBlockExist120        {121            get { return (FinallyStartIndex != Instruction.UnknownInstrIndex && FinallyEndIndex != Instruction.UnknownInstrIndex); }122        }123 124        internal bool IsCatchBlockExist125        {126            get { return (_handlers != null); }127        }128 129        /// <summary>130        /// No finally block.131        /// </summary>132        internal TryCatchFinallyHandler(int tryStart, int tryEnd, int gotoEndTargetIndex, ExceptionHandler[] handlers)133            : this(tryStart, tryEnd, gotoEndTargetIndex, Instruction.UnknownInstrIndex, Instruction.UnknownInstrIndex, handlers)134        {135            Debug.Assert(handlers != null, "catch blocks should exist");136        }137 138        /// <summary>139        /// No catch blocks.140        /// </summary>141        internal TryCatchFinallyHandler(int tryStart, int tryEnd, int gotoEndTargetIndex, int finallyStart, int finallyEnd)142            : this(tryStart, tryEnd, gotoEndTargetIndex, finallyStart, finallyEnd, null)143        {144            Debug.Assert(finallyStart != Instruction.UnknownInstrIndex && finallyEnd != Instruction.UnknownInstrIndex, "finally block should exist");145        }146 147        /// <summary>148        /// Generic constructor.149        /// </summary>150        internal TryCatchFinallyHandler(int tryStart, int tryEnd, int gotoEndLabelIndex, int finallyStart, int finallyEnd, ExceptionHandler[] handlers)151        {152            TryStartIndex = tryStart;153            TryEndIndex = tryEnd;154            FinallyStartIndex = finallyStart;155            FinallyEndIndex = finallyEnd;156            GotoEndTargetIndex = gotoEndLabelIndex;157 158            _handlers = handlers;159 160            if (_handlers != null)161            {162                for (int index = 0; index < _handlers.Length; index++)163                {164                    var handler = _handlers[index];165                    handler.SetParent(this);166                }167            }168        }169 170        /// <summary>171        /// Goto the index of the first instruction of the suitable catch block.172        /// </summary>173        internal int GotoHandler(InterpretedFrame frame, object exception, out ExceptionHandler handler)174        {175            Debug.Assert(_handlers != null, "we should have at least one handler if the method gets called");176            handler = Array.Find(_handlers, t => t.Matches(exception.GetType()));177            if (handler == null) { return 0; }178 179            return frame.Goto(handler.LabelIndex, exception, gotoExceptionHandler: true);180        }181    }182 183    /// <summary>184    /// The re-throw instruction will throw this exception.185    /// </summary>186    internal sealed class RethrowException : SystemException187    {188    }189 190    internal class DebugInfo191    {192        // TODO: readonly193 194        public int StartLine, EndLine;195        public int Index;196        public string FileName;197        public bool IsClear;198        private static readonly DebugInfoComparer s_debugComparer = new DebugInfoComparer();199 200        private sealed class DebugInfoComparer : IComparer<DebugInfo>201        {202            // We allow comparison between int and DebugInfo here203            int IComparer<DebugInfo>.Compare(DebugInfo d1, DebugInfo d2)204            {205                if (d1.Index > d2.Index) return 1;206                else if (d1.Index == d2.Index) return 0;207                else return -1;208            }209        }210 211        public static DebugInfo GetMatchingDebugInfo(DebugInfo[] debugInfos, int index)212        {213            // Create a faked DebugInfo to do the search214            DebugInfo d = new DebugInfo { Index = index };215 216            // to find the closest debug info before the current index217 218            int i = Array.BinarySearch<DebugInfo>(debugInfos, d, s_debugComparer);219            if (i < 0)220            {221                // ~i is the index for the first bigger element222                // if there is no bigger element, ~i is the length of the array223                i = ~i;224                if (i == 0)225                {226                    return null;227                }228                // return the last one that is smaller229                i -= 1;230            }231 232            return debugInfos[i];233        }234 235        public override string ToString()236        {237            if (IsClear)238            {239                return string.Format(CultureInfo.InvariantCulture, "{0}: clear", Index);240            }241            else242            {243                return string.Format(CultureInfo.InvariantCulture, "{0}: [{1}-{2}] '{3}'", Index, StartLine, EndLine, FileName);244            }245        }246    }247 248    // TODO:249    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")]250    internal readonly struct InterpretedFrameInfo251    {252        public readonly string MethodName;253 254        // TODO:255        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]256        public readonly DebugInfo DebugInfo;257 258        public InterpretedFrameInfo(string methodName, DebugInfo info)259        {260            MethodName = methodName;261            DebugInfo = info;262        }263 264        public override string ToString()265        {266            return MethodName + (DebugInfo != null ? ": " + DebugInfo : null);267        }268    }269 270    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling")]271    internal sealed class LightCompiler272    {273        internal const int DefaultCompilationThreshold = 32;274 275        // zero: sync compilation276        private readonly int _compilationThreshold;277 278        private readonly InstructionList _instructions;279        private readonly LocalVariables _locals = new LocalVariables();280 281        private readonly List<DebugInfo> _debugInfos = new List<DebugInfo>();282        private readonly HybridReferenceDictionary<LabelTarget, LabelInfo> _treeLabels = new HybridReferenceDictionary<LabelTarget, LabelInfo>();283        private LabelScopeInfo _labelBlock = new LabelScopeInfo(null, LabelScopeKind.Lambda);284 285        private readonly Stack<ParameterExpression> _exceptionForRethrowStack = new Stack<ParameterExpression>();286 287        // Set to true to force compilation of this lambda.288        // This disables the interpreter for this lambda. We still need to289        // walk it, however, to resolve variables closed over from the parent290        // lambdas (because they may be interpreted).291        private bool _forceCompile;292 293        private readonly LightCompiler _parent;294 295        private static readonly LocalDefinition[] s_emptyLocals = Array.Empty<LocalDefinition>();296 297        public LightCompiler(int compilationThreshold)298        {299            _instructions = new InstructionList();300            _compilationThreshold = compilationThreshold < 0 ? DefaultCompilationThreshold : compilationThreshold;301        }302 303        private LightCompiler(LightCompiler parent)304            : this(parent._compilationThreshold)305        {306            _parent = parent;307        }308 309        public InstructionList Instructions310        {311            get { return _instructions; }312        }313 314        public LocalVariables Locals315        {316            get { return _locals; }317        }318 319        internal static Expression Unbox(Expression strongBoxExpression)320        {321            return Expression.Field(strongBoxExpression, typeof(StrongBox<object>).GetField("Value"));322        }323 324        public LightDelegateCreator CompileTop(LambdaExpression node)325        {326            for (int index = 0; index < node.Parameters.Count; index++)327            {328                var p = node.Parameters[index];329                var local = _locals.DefineLocal(p, 0);330                _instructions.EmitInitializeParameter(local.Index);331            }332 333            Compile(node.Body);334 335            // pop the result of the last expression:336            if (node.Body.Type != typeof(void) && node.ReturnType == typeof(void))337            {338                _instructions.EmitPop();339            }340 341            Debug.Assert(_instructions.CurrentStackDepth == (node.ReturnType != typeof(void) ? 1 : 0));342 343            return new LightDelegateCreator(MakeInterpreter(node.Name), node);344        }345 346        // internal LightDelegateCreator CompileTop(LightLambdaExpression node) {347        //    foreach (var p in node.Parameters) {348        //        var local = _locals.DefineLocal(p, 0);349        //        _instructions.EmitInitializeParameter(local.Index);350        //    }351        //352        //    Compile(node.Body);353        //354        //    // pop the result of the last expression:355        //    if (node.Body.Type != typeof(void) && node.ReturnType == typeof(void)) {356        //        _instructions.EmitPop();357        //    }358        //359        //    Debug.Assert(_instructions.CurrentStackDepth == (node.ReturnType != typeof(void) ? 1 : 0));360        //361        //    return new LightDelegateCreator(MakeInterpreter(node.Name), node);362        // }363 364        private Interpreter MakeInterpreter(string lambdaName)365        {366            if (_forceCompile)367            {368                return null;369            }370 371            var debugInfos = _debugInfos.ToArray();372            return new Interpreter(lambdaName, _locals, GetBranchMapping(), _instructions.ToArray(), debugInfos, _compilationThreshold);373        }374 375        private void CompileConstantExpression(Expression expr)376        {377            var node = (ConstantExpression)expr;378            _instructions.EmitLoad(node.Value, node.Type);379        }380 381        private void CompileDefaultExpression(Expression expr)382        {383            CompileDefaultExpression(expr.Type);384        }385 386        private void CompileDefaultExpression(Type type)387        {388            if (type != typeof(void))389            {390                if (type.IsValueType)391                {392                    object value = ScriptingRuntimeHelpers.GetPrimitiveDefaultValue(type);393                    if (value != null)394                    {395                        _instructions.EmitLoad(value);396                    }397                    else398                    {399                        _instructions.EmitDefaultValue(type);400                    }401                }402                else403                {404                    _instructions.EmitLoad(null);405                }406            }407        }408 409        private LocalVariable EnsureAvailableForClosure(ParameterExpression expr)410        {411            LocalVariable local;412            if (_locals.TryGetLocalOrClosure(expr, out local))413            {414                if (!local.InClosure && !local.IsBoxed)415                {416                    _locals.Box(expr, _instructions);417                }418 419                return local;420            }421            else if (_parent != null)422            {423                _parent.EnsureAvailableForClosure(expr);424                return _locals.AddClosureVariable(expr);425            }426            else427            {428                throw new InvalidOperationException("unbound variable: " + expr);429            }430        }431 432        // private void EnsureVariable(ParameterExpression variable) {433        //    if (!_locals.ContainsVariable(variable)) {434        //        EnsureAvailableForClosure(variable);435        //    }436        // }437 438        private LocalVariable ResolveLocal(ParameterExpression variable)439        {440            LocalVariable local;441            if (!_locals.TryGetLocalOrClosure(variable, out local))442            {443                local = EnsureAvailableForClosure(variable);444            }445 446            return local;447        }448 449        public void CompileGetVariable(ParameterExpression variable)450        {451            LocalVariable local = ResolveLocal(variable);452 453            if (local.InClosure)454            {455                _instructions.EmitLoadLocalFromClosure(local.Index);456            }457            else if (local.IsBoxed)458            {459                _instructions.EmitLoadLocalBoxed(local.Index);460            }461            else462            {463                _instructions.EmitLoadLocal(local.Index);464            }465 466            _instructions.SetDebugCookie(variable.Name);467        }468 469        public void CompileGetBoxedVariable(ParameterExpression variable)470        {471            LocalVariable local = ResolveLocal(variable);472 473            if (local.InClosure)474            {475                _instructions.EmitLoadLocalFromClosureBoxed(local.Index);476            }477            else478            {479                Debug.Assert(local.IsBoxed);480                _instructions.EmitLoadLocal(local.Index);481            }482 483            _instructions.SetDebugCookie(variable.Name);484        }485 486        public void CompileSetVariable(ParameterExpression variable, bool isVoid)487        {488            LocalVariable local = ResolveLocal(variable);489 490            if (local.InClosure)491            {492                if (isVoid)493                {494                    _instructions.EmitStoreLocalToClosure(local.Index);495                }496                else497                {498                    _instructions.EmitAssignLocalToClosure(local.Index);499                }500            }501            else if (local.IsBoxed)502            {503                if (isVoid)504                {505                    _instructions.EmitStoreLocalBoxed(local.Index);506                }507                else508                {509                    _instructions.EmitAssignLocalBoxed(local.Index);510                }511            }512            else513            {514                if (isVoid)515                {516                    _instructions.EmitStoreLocal(local.Index);517                }518                else519                {520                    _instructions.EmitAssignLocal(local.Index);521                }522            }523 524            _instructions.SetDebugCookie(variable.Name);525        }526 527        public void CompileParameterExpression(Expression expr)528        {529            var node = (ParameterExpression)expr;530            CompileGetVariable(node);531        }532 533        private void CompileBlockExpression(Expression expr, bool asVoid)534        {535            var node = (BlockExpression)expr;536            var end = CompileBlockStart(node);537 538            var lastExpression = node.Expressions[node.Expressions.Count - 1];539            Compile(lastExpression, asVoid);540            CompileBlockEnd(end);541        }542 543        private LocalDefinition[] CompileBlockStart(BlockExpression node)544        {545            var start = _instructions.Count;546 547            LocalDefinition[] locals;548            var variables = node.Variables;549            if (variables.Count != 0)550            {551                // TODO: basic flow analysis so we don't have to initialize all552                // variables.553                locals = new LocalDefinition[variables.Count];554                int localCnt = 0;555                for (int index = 0; index < variables.Count; index++)556                {557                    var variable = variables[index];558                    var local = _locals.DefineLocal(variable, start);559                    locals[localCnt++] = local;560 561                    _instructions.EmitInitializeLocal(local.Index, variable.Type);562                    _instructions.SetDebugCookie(variable.Name);563                }564            }565            else566            {567                locals = s_emptyLocals;568            }569 570            for (int i = 0; i < node.Expressions.Count - 1; i++)571            {572                CompileAsVoid(node.Expressions[i]);573            }574 575            return locals;576        }577 578        private void CompileBlockEnd(LocalDefinition[] locals)579        {580            for (int index = 0; index < locals.Length; index++)581            {582                var local = locals[index];583                _locals.UndefineLocal(local, _instructions.Count);584            }585        }586 587        private void CompileIndexExpression(Expression expr)588        {589            var index = (IndexExpression)expr;590 591            // instance:592            if (index.Object != null)593            {594                Compile(index.Object);595            }596 597            // indexes, byref args not allowed.598            for (int i = 0; i < index.Arguments.Count; i++)599            {600                var arg = index.Arguments[i];601                Compile(arg);602            }603 604            if (index.Indexer != null)605            {606                _instructions.EmitCall(index.Indexer.GetMethod);607            }608            else if (index.Arguments.Count != 1)609            {610                _instructions.EmitCall(index.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance));611            }612            else613            {614                _instructions.EmitGetArrayItem(index.Object.Type);615            }616        }617 618        private void CompileIndexAssignment(BinaryExpression node, bool asVoid)619        {620            var index = (IndexExpression)node.Left;621 622            if (!asVoid)623            {624                throw new NotImplementedException();625            }626 627            // instance:628            if (index.Object != null)629            {630                Compile(index.Object);631            }632 633            // indexes, byref args not allowed.634            for (int i = 0; i < index.Arguments.Count; i++)635            {636                var arg = index.Arguments[i];637                Compile(arg);638            }639 640            // value:641            Compile(node.Right);642 643            if (index.Indexer != null)644            {645                _instructions.EmitCall(index.Indexer.SetMethod);646            }647            else if (index.Arguments.Count != 1)648            {649                _instructions.EmitCall(index.Object.Type.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance));650            }651            else652            {653                _instructions.EmitSetArrayItem(index.Object.Type);654            }655        }656 657        private void CompileMemberAssignment(BinaryExpression node, bool asVoid)658        {659            var member = (MemberExpression)node.Left;660 661            PropertyInfo pi = member.Member as PropertyInfo;662            if (pi != null)663            {664                var method = pi.SetMethod;665                if (member.Expression != null)666                {667                    Compile(member.Expression);668                }669 670                Compile(node.Right);671 672                int start = _instructions.Count;673                if (!asVoid)674                {675                    LocalDefinition local = _locals.DefineLocal(Expression.Parameter(node.Right.Type), start);676                    _instructions.EmitAssignLocal(local.Index);677                    _instructions.EmitCall(method);678                    _instructions.EmitLoadLocal(local.Index);679                    _locals.UndefineLocal(local, _instructions.Count);680                }681                else682                {683                    _instructions.EmitCall(method);684                }685 686                return;687            }688 689            FieldInfo fi = member.Member as FieldInfo;690            if (fi != null)691            {692                if (member.Expression != null)693                {694                    Compile(member.Expression);695                }696 697                Compile(node.Right);698 699                int start = _instructions.Count;700                if (!asVoid)701                {702                    LocalDefinition local = _locals.DefineLocal(Expression.Parameter(node.Right.Type), start);703                    _instructions.EmitAssignLocal(local.Index);704                    _instructions.EmitStoreField(fi);705                    _instructions.EmitLoadLocal(local.Index);706                    _locals.UndefineLocal(local, _instructions.Count);707                }708                else709                {710                    _instructions.EmitStoreField(fi);711                }712 713                return;714            }715 716            throw new NotImplementedException();717        }718 719        private void CompileVariableAssignment(BinaryExpression node, bool asVoid)720        {721            this.Compile(node.Right);722 723            var target = (ParameterExpression)node.Left;724            CompileSetVariable(target, asVoid);725        }726 727        private void CompileAssignBinaryExpression(Expression expr, bool asVoid)728        {729            var node = (BinaryExpression)expr;730 731            switch (node.Left.NodeType)732            {733                case ExpressionType.Index:734                    CompileIndexAssignment(node, asVoid);735                    break;736 737                case ExpressionType.MemberAccess:738                    CompileMemberAssignment(node, asVoid);739                    break;740 741                case ExpressionType.Parameter:742                case ExpressionType.Extension:743                    CompileVariableAssignment(node, asVoid);744                    break;745 746                default:747                    throw new InvalidOperationException("Invalid lvalue for assignment: " + node.Left.NodeType);748            }749        }750 751        private void CompileBinaryExpression(Expression expr)752        {753            var node = (BinaryExpression)expr;754 755            if (node.Method != null)756            {757                Compile(node.Left);758                Compile(node.Right);759                _instructions.EmitCall(node.Method);760            }761            else762            {763                switch (node.NodeType)764                {765                    case ExpressionType.ArrayIndex:766                        Debug.Assert(node.Right.Type == typeof(int));767                        Compile(node.Left);768                        Compile(node.Right);769                        _instructions.EmitGetArrayItem(node.Left.Type);770                        return;771 772                    case ExpressionType.Add:773                    case ExpressionType.AddChecked:774                    case ExpressionType.Subtract:775                    case ExpressionType.SubtractChecked:776                    case ExpressionType.Multiply:777                    case ExpressionType.MultiplyChecked:778                    case ExpressionType.Divide:779                        CompileArithmetic(node.NodeType, node.Left, node.Right);780                        return;781 782                    case ExpressionType.Equal:783                        CompileEqual(node.Left, node.Right);784                        return;785 786                    case ExpressionType.NotEqual:787                        CompileNotEqual(node.Left, node.Right);788                        return;789 790                    case ExpressionType.LessThan:791                    case ExpressionType.LessThanOrEqual:792                    case ExpressionType.GreaterThan:793                    case ExpressionType.GreaterThanOrEqual:794                        CompileComparison(node.NodeType, node.Left, node.Right);795                        return;796 797                    default:798                        throw new NotImplementedException(node.NodeType.ToString());799                }800            }801        }802 803        private void CompileEqual(Expression left, Expression right)804        {805            Debug.Assert(left.Type == right.Type ||806                         !left.Type.IsValueType && !right.Type.IsValueType);807            Compile(left);808            Compile(right);809            _instructions.EmitEqual(left.Type);810        }811 812        private void CompileNotEqual(Expression left, Expression right)813        {814            Debug.Assert(left.Type == right.Type ||815                         !left.Type.IsValueType && !right.Type.IsValueType);816            Compile(left);817            Compile(right);818            _instructions.EmitNotEqual(left.Type);819        }820 821        private void CompileComparison(ExpressionType nodeType, Expression left, Expression right)822        {823            Debug.Assert(left.Type == right.Type && TypeUtils.IsNumeric(left.Type));824 825            // TODO:826            // if (TypeUtils.IsNullableType(left.Type) && liftToNull) ...827 828            Compile(left);829            Compile(right);830 831            switch (nodeType)832            {833                case ExpressionType.LessThan: _instructions.EmitLessThan(left.Type); break;834                case ExpressionType.LessThanOrEqual: _instructions.EmitLessThanOrEqual(left.Type); break;835                case ExpressionType.GreaterThan: _instructions.EmitGreaterThan(left.Type); break;836                case ExpressionType.GreaterThanOrEqual: _instructions.EmitGreaterThanOrEqual(left.Type); break;837                default: throw Assert.Unreachable;838            }839        }840 841        private void CompileArithmetic(ExpressionType nodeType, Expression left, Expression right)842        {843            Debug.Assert(left.Type == right.Type && TypeUtils.IsArithmetic(left.Type));844            Compile(left);845            Compile(right);846            switch (nodeType)847            {848                case ExpressionType.Add: _instructions.EmitAdd(left.Type, false); break;849                case ExpressionType.AddChecked: _instructions.EmitAdd(left.Type, true); break;850                case ExpressionType.Subtract: _instructions.EmitSub(left.Type, false); break;851                case ExpressionType.SubtractChecked: _instructions.EmitSub(left.Type, true); break;852                case ExpressionType.Multiply: _instructions.EmitMul(left.Type, false); break;853                case ExpressionType.MultiplyChecked: _instructions.EmitMul(left.Type, true); break;854                case ExpressionType.Divide: _instructions.EmitDiv(left.Type); break;855                default: throw Assert.Unreachable;856            }857        }858 859        private void CompileConvertUnaryExpression(Expression expr)860        {861            var node = (UnaryExpression)expr;862            if (node.Method != null)863            {864                Compile(node.Operand);865 866                // We should be able to ignore Int32ToObject867                if (node.Method != ScriptingRuntimeHelpers.Int32ToObjectMethod)868                {869                    _instructions.EmitCall(node.Method);870                }871            }872            else if (node.Type == typeof(void))873            {874                CompileAsVoid(node.Operand);875            }876            else877            {878                Compile(node.Operand);879                CompileConvertToType(node.Operand.Type, node.Type, node.NodeType == ExpressionType.ConvertChecked);880            }881        }882 883        private void CompileConvertToType(Type typeFrom, Type typeTo, bool isChecked)884        {885            Debug.Assert(typeFrom != typeof(void) && typeTo != typeof(void));886 887            if (typeTo == typeFrom)888            {889                return;890            }891 892            TypeCode from = typeFrom.GetTypeCode();893            TypeCode to = typeTo.GetTypeCode();894            if (TypeUtils.IsNumeric(from) && TypeUtils.IsNumeric(to))895            {896                if (isChecked)897                {898                    _instructions.EmitNumericConvertChecked(from, to);899                }900                else901                {902                    _instructions.EmitNumericConvertUnchecked(from, to);903                }904 905                return;906            }907 908            // TODO: Conversions to a super-class or implemented interfaces are no-op.909            // A conversion to a non-implemented interface or an unrelated class, etc. should fail.910            return;911        }912 913        private void CompileNotExpression(UnaryExpression node)914        {915            if (node.Operand.Type == typeof(bool))916            {917                Compile(node.Operand);918                _instructions.EmitNot();919            }920            else921            {922                throw new NotImplementedException();923            }924        }925 926        private void CompileUnaryExpression(Expression expr)927        {928            var node = (UnaryExpression)expr;929 930            if (node.Method != null)931            {932                Compile(node.Operand);933                _instructions.EmitCall(node.Method);934            }935            else936            {937                switch (node.NodeType)938                {939                    case ExpressionType.Not:940                        CompileNotExpression(node);941                        return;942                    case ExpressionType.TypeAs:943                        CompileTypeAsExpression(node);944                        return;945                    default:946                        throw new NotImplementedException(node.NodeType.ToString());947                }948            }949        }950 951        private void CompileAndAlsoBinaryExpression(Expression expr)952        {953            CompileLogicalBinaryExpression(expr, true);954        }955 956        private void CompileOrElseBinaryExpression(Expression expr)957        {958            CompileLogicalBinaryExpression(expr, false);959        }960 961        private void CompileLogicalBinaryExpression(Expression expr, bool andAlso)962        {963            var node = (BinaryExpression)expr;964            if (node.Method != null)965            {966                throw new NotImplementedException();967            }968 969            Debug.Assert(node.Left.Type == node.Right.Type);970 971            if (node.Left.Type == typeof(bool))972            {973                var elseLabel = _instructions.MakeLabel();974                var endLabel = _instructions.MakeLabel();975                Compile(node.Left);976                if (andAlso)977                {978                    _instructions.EmitBranchFalse(elseLabel);979                }980                else981                {982                    _instructions.EmitBranchTrue(elseLabel);983                }984 985                Compile(node.Right);986                _instructions.EmitBranch(endLabel, false, true);987                _instructions.MarkLabel(elseLabel);988                _instructions.EmitLoad(!andAlso);989                _instructions.MarkLabel(endLabel);990                return;991            }992 993            Debug.Assert(node.Left.Type == typeof(bool?));994            throw new NotImplementedException();995        }996 997        private void CompileConditionalExpression(Expression expr, bool asVoid)998        {999            var node = (ConditionalExpression)expr;1000            Compile(node.Test);1001 1002            if (node.IfTrue == AstUtils.Empty())1003            {1004                var endOfFalse = _instructions.MakeLabel();1005                _instructions.EmitBranchTrue(endOfFalse);1006                Compile(node.IfFalse, asVoid);1007                _instructions.MarkLabel(endOfFalse);1008            }1009            else1010            {1011                var endOfTrue = _instructions.MakeLabel();1012                _instructions.EmitBranchFalse(endOfTrue);1013                Compile(node.IfTrue, asVoid);1014 1015                if (node.IfFalse != AstUtils.Empty())1016                {1017                    var endOfFalse = _instructions.MakeLabel();1018                    _instructions.EmitBranch(endOfFalse, false, !asVoid);1019                    _instructions.MarkLabel(endOfTrue);1020                    Compile(node.IfFalse, asVoid);1021                    _instructions.MarkLabel(endOfFalse);1022                }1023                else1024                {1025                    _instructions.MarkLabel(endOfTrue);1026                }1027            }1028        }1029 1030        #region Loops1031 1032        private static void CompileLoopExpression(Expression expr)1033        {1034            //    var node = (LoopExpression)expr;1035            //    var enterLoop = new EnterLoopInstruction(node, _locals, _compilationThreshold, _instructions.Count);1036            //1037            //    PushLabelBlock(LabelScopeKind.Statement);1038            //    LabelInfo breakLabel = DefineLabel(node.BreakLabel);1039            //    LabelInfo continueLabel = DefineLabel(node.ContinueLabel);1040            //1041            //    _instructions.MarkLabel(continueLabel.GetLabel(this));1042            //1043            //    // emit loop body:1044            //    _instructions.Emit(enterLoop);1045            //    CompileAsVoid(node.Body);1046            //1047            //    // emit loop branch:1048            //    _instructions.EmitBranch(continueLabel.GetLabel(this), expr.Type != typeof(void), false);1049            //1050            //    _instructions.MarkLabel(breakLabel.GetLabel(this));1051            //1052            //    PopLabelBlock(LabelScopeKind.Statement);1053            //1054            //    enterLoop.FinishLoop(_instructions.Count);1055        }1056 1057        #endregion1058 1059        private void CompileSwitchExpression(Expression expr)1060        {1061            var node = (SwitchExpression)expr;1062 1063            // Currently only supports int test values, with no method1064            if (node.SwitchValue.Type != typeof(int) || node.Comparison != null)1065            {1066                throw new NotImplementedException();1067            }1068 1069            // Test values must be constant1070            if (!node.Cases.All(static c => c.TestValues.All(t => t is ConstantExpression)))1071            {1072                throw new NotImplementedException();1073            }1074 1075            LabelInfo end = DefineLabel(null);1076            bool hasValue = node.Type != typeof(void);1077 1078            Compile(node.SwitchValue);1079            var caseDict = new Dictionary<int, int>();1080            int switchIndex = _instructions.Count;1081            _instructions.EmitSwitch(caseDict);1082 1083            if (node.DefaultBody != null)1084            {1085                Compile(node.DefaultBody);1086            }1087            else1088            {1089                Debug.Assert(!hasValue);1090            }1091 1092            _instructions.EmitBranch(end.GetLabel(this), false, hasValue);1093 1094            for (int i = 0; i < node.Cases.Count; i++)1095            {1096                var switchCase = node.Cases[i];1097 1098                int caseOffset = _instructions.Count - switchIndex;1099                for (int index = 0; index < switchCase.TestValues.Count; index++)1100                {1101                    var testValue = (ConstantExpression)switchCase.TestValues[index];1102                    caseDict[(int)testValue.Value] = caseOffset;1103                }1104 1105                Compile(switchCase.Body);1106 1107                if (i < node.Cases.Count - 1)1108                {1109                    _instructions.EmitBranch(end.GetLabel(this), false, hasValue);1110                }1111            }1112 1113            _instructions.MarkLabel(end.GetLabel(this));1114        }1115 1116        private void CompileLabelExpression(Expression expr)1117        {1118            var node = (LabelExpression)expr;1119 1120            // If we're an immediate child of a block, our label will already1121            // be defined. If not, we need to define our own block so this1122            // label isn't exposed except to its own child expression.1123            LabelInfo label = null;1124 1125            if (_labelBlock.Kind == LabelScopeKind.Block)1126            {1127                _labelBlock.TryGetLabelInfo(node.Target, out label);1128 1129                // We're in a block but didn't find our label, try switch1130                if (label == null && _labelBlock.Parent.Kind == LabelScopeKind.Switch)1131                {1132                    _labelBlock.Parent.TryGetLabelInfo(node.Target, out label);1133                }1134 1135                // if we're in a switch or block, we should've found the label1136                Debug.Assert(label != null);1137            }1138 1139            label ??= DefineLabel(node.Target);1140 1141            if (node.DefaultValue != null)1142            {1143                if (node.Target.Type == typeof(void))1144                {1145                    CompileAsVoid(node.DefaultValue);1146                }1147                else1148                {1149                    Compile(node.DefaultValue);1150                }1151            }1152 1153            _instructions.MarkLabel(label.GetLabel(this));1154        }1155 1156        private void CompileGotoExpression(Expression expr)1157        {1158            var node = (GotoExpression)expr;1159            var labelInfo = ReferenceLabel(node.Target);1160 1161            if (node.Value != null)1162            {1163                Compile(node.Value);1164            }1165 1166            _instructions.EmitGoto(labelInfo.GetLabel(this), node.Type != typeof(void), node.Value != null && node.Value.Type != typeof(void));1167        }1168 1169        public BranchLabel GetBranchLabel(LabelTarget target)1170        {1171            return ReferenceLabel(target).GetLabel(this);1172        }1173 1174        public void PushLabelBlock(LabelScopeKind type)1175        {1176            _labelBlock = new LabelScopeInfo(_labelBlock, type);1177        }1178 1179        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kind")]1180        public void PopLabelBlock(LabelScopeKind kind)1181        {1182            Debug.Assert(_labelBlock != null && _labelBlock.Kind == kind);1183            _labelBlock = _labelBlock.Parent;1184        }1185 1186        private LabelInfo EnsureLabel(LabelTarget node)1187        {1188            LabelInfo result;1189            if (!_treeLabels.TryGetValue(node, out result))1190            {1191                _treeLabels[node] = result = new LabelInfo(node);1192            }1193 1194            return result;1195        }1196 1197        private LabelInfo ReferenceLabel(LabelTarget node)1198        {1199            LabelInfo result = EnsureLabel(node);1200            result.Reference(_labelBlock);

Showing the first 1,200 of 2053 lines. Download the file for the rest.