Пример #1
0
        public List<ILNode> ConvertToAst(List<Instruction> body, IEnumerable<ExceptionHandler> ehs)
        {
            List<ILNode> ast = new List<ILNode>();

            while (ehs.Any()) {
                ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock();

                // Find the first and widest scope
                int tryStart = ehs.Min(eh => eh.TryStart.Offset);
                int tryEnd   = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset);
                var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList();

                // Cut all instructions up to the try block
                {
                    int tryStartIdx;
                    for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++);
                    ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx)));
                }

                // Cut the try block
                {
                    List<ExceptionHandler> nestedEHs = ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd)).ToList();
                    int tryEndIdx;
                    for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++);
                    tryCatchBlock.TryBlock = ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs);
                }

                // Cut all handlers
                tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>();
                foreach(ExceptionHandler eh in handlers) {
                    int start;
                    for (start = 0; body[start] != eh.HandlerStart; start++);
                    int end;
                    for (end = 0; body[end] != eh.HandlerEnd; end++);
                    int count = end - start;
                    List<ExceptionHandler> nestedEHs = ehs.Where(e => (start <= e.TryStart.Offset && e.TryEnd.Offset < end) || (start < e.TryStart.Offset && e.TryEnd.Offset <= end)).ToList();
                    List<ILNode> handlerAst = ConvertToAst(body.CutRange(start, count), nestedEHs);
                    if (eh.HandlerType == ExceptionHandlerType.Catch) {
                        tryCatchBlock.CatchBlocks.Add(new ILTryCatchBlock.CatchBlock() {
                            ExceptionType = eh.CatchType,
                            Body = handlerAst
                        });
                    } else if (eh.HandlerType == ExceptionHandlerType.Finally) {
                        tryCatchBlock.FinallyBlock = handlerAst;
                    } else {
                        // TODO
                    }
                }

                ehs = ehs.Where(eh => eh.TryStart.Offset > tryEnd).ToList();

                ast.Add(tryCatchBlock);
            }

            // Add whatever is left
            ast.AddRange(ConvertToAst(body));

            return ast;
        }
Пример #2
0
        List<ILNode> ConvertToAst(List<ByteCode> body, HashSet<ExceptionHandler> ehs)
        {
            List<ILNode> ast = new List<ILNode>();

            while (ehs.Any()) {
                ILTryCatchBlock tryCatchBlock = new ILTryCatchBlock();

                // Find the first and widest scope
                int tryStart = ehs.Min(eh => eh.TryStart.Offset);
                int tryEnd   = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset);
                var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList();

                // Cut all instructions up to the try block
                {
                    int tryStartIdx;
                    for (tryStartIdx = 0; body[tryStartIdx].Offset != tryStart; tryStartIdx++);
                    ast.AddRange(ConvertToAst(body.CutRange(0, tryStartIdx)));
                }

                // Cut the try block
                {
                    HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(eh => (tryStart <= eh.TryStart.Offset && eh.TryEnd.Offset < tryEnd) || (tryStart < eh.TryStart.Offset && eh.TryEnd.Offset <= tryEnd)));
                    ehs.ExceptWith(nestedEHs);
                    int tryEndIdx;
                    for (tryEndIdx = 0; tryEndIdx < body.Count && body[tryEndIdx].Offset != tryEnd; tryEndIdx++);
                    tryCatchBlock.TryBlock = new ILBlock(ConvertToAst(body.CutRange(0, tryEndIdx), nestedEHs));
                }

                // Cut all handlers
                tryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>();
                foreach(ExceptionHandler eh in handlers) {
                    int startIndex;
                    for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++);
                    int endInclusiveIndex;
                    // Note that the end(exclusiove) instruction may not necessarly be in our body
                    for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++);
                    int count = 1 + endInclusiveIndex - startIndex;
                    HashSet<ExceptionHandler> nestedEHs = new HashSet<ExceptionHandler>(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset)));
                    ehs.ExceptWith(nestedEHs);
                    List<ILNode> handlerAst = ConvertToAst(body.CutRange(startIndex, count), nestedEHs);
                    if (eh.HandlerType == ExceptionHandlerType.Catch) {
                        tryCatchBlock.CatchBlocks.Add(new ILTryCatchBlock.CatchBlock() {
                            ExceptionType = eh.CatchType,
                            Body = handlerAst
                        });
                    } else if (eh.HandlerType == ExceptionHandlerType.Finally) {
                        tryCatchBlock.FinallyBlock = new ILBlock(handlerAst);
                    } else {
                        // TODO
                    }
                }

                ehs.ExceptWith(handlers);

                ast.Add(tryCatchBlock);
            }

            // Add whatever is left
            ast.AddRange(ConvertToAst(body));

            return ast;
        }