示例#1
0
        public string ToString(string programName, int start, int end)
        {
            IList rewrites = (IList)programs[programName];

            if (rewrites == null)
            {
                return(null);                // invalid program
            }
            StringBuilder buf = new StringBuilder();

            // Index of first rewrite we have not done
            int rewriteOpIndex = 0;

            int tokenCursor = start;

            while ((tokenCursor >= MIN_TOKEN_INDEX) &&
                   (tokenCursor <= end) &&
                   (tokenCursor < tokens.Count))
            {
                if (rewriteOpIndex < rewrites.Count)
                {
                    RewriteOperation op = (RewriteOperation)rewrites[rewriteOpIndex];
                    while ((tokenCursor == op.index) && (rewriteOpIndex < rewrites.Count))
                    {
                        /*
                         * Console.Out.WriteLine("execute op "+rewriteOpIndex+
                         *                                      " (type "+op.GetType().FullName+")"
                         +" at index "+op.index);
                         */
                        tokenCursor = op.execute(buf);
                        rewriteOpIndex++;
                        if (rewriteOpIndex < rewrites.Count)
                        {
                            op = (RewriteOperation)rewrites[rewriteOpIndex];
                        }
                    }
                }
                if (tokenCursor < end)
                {
                    buf.Append(getToken(tokenCursor).getText());
                    tokenCursor++;
                }
            }
            // now see if there are operations (append) beyond last token index
            for (int opi = rewriteOpIndex; opi < rewrites.Count; opi++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[opi];
                op.execute(buf);                 // must be insertions if after last token
            }

            return(buf.ToString());
        }
示例#2
0
            public virtual int Compare(object o1, object o2)
            {
                RewriteOperation rop1 = (RewriteOperation)o1;
                RewriteOperation rop2 = (RewriteOperation)o2;

                if (rop1.index < rop2.index)
                {
                    return(-1);
                }
                if (rop1.index > rop2.index)
                {
                    return(1);
                }
                return(0);
            }
        /** <summary>Get all operations before an index of a particular kind</summary> */
        protected virtual IList <RewriteOperation> GetKindOfOps(IList <RewriteOperation> rewrites, Type kind, int before)
        {
            IList <RewriteOperation> ops = new List <RewriteOperation>();

            for (int i = 0; i < before && i < rewrites.Count; i++)
            {
                RewriteOperation op = rewrites[i];
                if (op == null)
                {
                    continue; // ignore deleted
                }
                if (op.GetType() == kind)
                {
                    ops.Add(op);
                }
            }
            return(ops);
        }
        /// <summary>
        /// Get all operations before an index of a particular kind
        /// </summary>
        protected IList GetKindOfOps(IList rewrites, Type kind, int before)
        {
            IList ops = new ArrayList();

            for (int i = 0; i < before && i < rewrites.Count; i++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[i];
                if (op == null)
                {
                    continue;                             // ignore deleted
                }
                if (op.GetType() == kind)
                {
                    ops.Add(op);
                }
            }
            return(ops);
        }
示例#5
0
        protected void addToSortedRewriteList(string programName, RewriteOperation op)
        {
            ArrayList rewrites = (ArrayList)getProgram(programName);

            // if at or beyond last op's index, just append
            if (op.index >= getLastRewriteTokenIndex(programName))
            {
                rewrites.Add(op);                 // append to list of operations
                // record the index of this operation for next time through
                setLastRewriteTokenIndex(programName, op.index);
                return;
            }
            // not after the last one, so must insert to ordered list
            int pos = rewrites.BinarySearch(op, RewriteOperationComparer.Default);

            if (pos < 0)
            {
                rewrites.Insert(-pos - 1, op);
            }
        }
示例#6
0
        public static void AssertRewrite(Action <RewriteContext> preAssertions, Action <RewriteContext> postAssertions)
        {
            var context = RewriteContext.For(
                "Test.Target.dll",
                DebugSymbolFormat.None,
                "Test.Support.dll",
                string.Empty,
                new string[] { Path.GetDirectoryName(typeof(object).Assembly.Location) },
                string.Empty,
                new string[] {},
                string.Empty,
                new string[0],
                new string[0],
                new Dictionary <string, IList <string> >(),
                new Dictionary <string, IList <string> >());

            var operation = RewriteOperation.Create(ns => ns.StartsWith("System") ? "Test.Support" + ns.Substring("System".Length) : ns);

            preAssertions(context);
            operation.Execute(context);
            postAssertions(context);
        }
        /** We need to combine operations and report invalid operations (like
         *  overlapping replaces that are not completed nested).  Inserts to
         *  same index need to be combined etc...   Here are the cases:
         *
         *  I.i.u I.j.v								leave alone, nonoverlapping
         *  I.i.u I.i.v								combine: Iivu
         *
         *  R.i-j.u R.x-y.v	| i-j in x-y			delete first R
         *  R.i-j.u R.i-j.v							delete first R
         *  R.i-j.u R.x-y.v	| x-y in i-j			ERROR
         *  R.i-j.u R.x-y.v	| boundaries overlap	ERROR
         *
         *  Delete special case of replace (text==null):
         *  D.i-j.u D.x-y.v	| boundaries overlap	combine to max(min)..max(right)
         *
         *  I.i.u R.x-y.v | i in (x+1)-y			delete I (since insert before
         *											we're not deleting i)
         *  I.i.u R.x-y.v | i not in (x+1)-y		leave alone, nonoverlapping
         *  R.x-y.v I.i.u | i in x-y				ERROR
         *  R.x-y.v I.x.u                           R.x-y.uv (combine, delete I)
         *  R.x-y.v I.i.u | i not in x-y			leave alone, nonoverlapping
         *
         *  I.i.u = insert u before op @ index i
         *  R.x-y.u = replace x-y indexed tokens with u
         *
         *  First we need to examine replaces.  For any replace op:
         *
         *      1. wipe out any insertions before op within that range.
         *		2. Drop any replace op before that is contained completely within
         *         that range.
         *		3. Throw exception upon boundary overlap with any previous replace.
         *
         *  Then we can deal with inserts:
         *
         *      1. for any inserts to same index, combine even if not adjacent.
         *      2. for any prior replace with same left boundary, combine this
         *         insert with replace and delete this replace.
         *      3. throw exception if index in same range as previous replace
         *
         *  Don't actually delete; make op null in list. Easier to walk list.
         *  Later we can throw as we add to index -> op map.
         *
         *  Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
         *  inserted stuff would be before the replace range.  But, if you
         *  add tokens in front of a method body '{' and then delete the method
         *  body, I think the stuff before the '{' you added should disappear too.
         *
         *  Return a map from token index to operation.
         */
        protected virtual IDictionary <int, RewriteOperation> ReduceToSingleOperationPerIndex(IList <RewriteOperation> rewrites)
        {
            //System.out.println("rewrites="+rewrites);

            // WALK REPLACES
            for (int i = 0; i < rewrites.Count; i++)
            {
                RewriteOperation op = rewrites[i];
                if (op == null)
                {
                    continue;
                }
                if (!(op is ReplaceOp))
                {
                    continue;
                }
                ReplaceOp rop = (ReplaceOp)rewrites[i];
                // Wipe prior inserts within range
                var inserts = GetKindOfOps(rewrites, typeof(InsertBeforeOp), i);
                for (int j = 0; j < inserts.Count; j++)
                {
                    InsertBeforeOp iop = (InsertBeforeOp)inserts[j];
                    if (iop.index == rop.index)
                    {
                        // E.g., insert before 2, delete 2..2; update replace
                        // text to include insert before, kill insert
                        rewrites[iop.instructionIndex] = null;
                        rop.text = iop.text.ToString() + (rop.text != null ? rop.text.ToString() : string.Empty);
                    }
                    else if (iop.index > rop.index && iop.index <= rop.lastIndex)
                    {
                        // delete insert as it's a no-op.
                        rewrites[iop.instructionIndex] = null;
                    }
                }
                // Drop any prior replaces contained within
                var prevReplaces = GetKindOfOps(rewrites, typeof(ReplaceOp), i);
                for (int j = 0; j < prevReplaces.Count; j++)
                {
                    ReplaceOp prevRop = (ReplaceOp)prevReplaces[j];
                    if (prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex)
                    {
                        // delete replace as it's a no-op.
                        rewrites[prevRop.instructionIndex] = null;
                        continue;
                    }
                    // throw exception unless disjoint or identical
                    bool disjoint =
                        prevRop.lastIndex <rop.index || prevRop.index> rop.lastIndex;
                    bool same =
                        prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex;
                    // Delete special case of replace (text==null):
                    // D.i-j.u D.x-y.v	| boundaries overlap	combine to max(min)..max(right)
                    if (prevRop.text == null && rop.text == null && !disjoint)
                    {
                        //System.out.println("overlapping deletes: "+prevRop+", "+rop);
                        rewrites[prevRop.instructionIndex] = null; // kill first delete
                        rop.index     = Math.Min(prevRop.index, rop.index);
                        rop.lastIndex = Math.Max(prevRop.lastIndex, rop.lastIndex);
#if !PORTABLE
                        Console.WriteLine("new rop " + rop);
#endif
                    }
                    else if (!disjoint && !same)
                    {
                        throw new ArgumentException("replace op boundaries of " + rop +
                                                    " overlap with previous " + prevRop);
                    }
                }
            }

            // WALK INSERTS
            for (int i = 0; i < rewrites.Count; i++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[i];
                if (op == null)
                {
                    continue;
                }
                if (!(op is InsertBeforeOp))
                {
                    continue;
                }
                InsertBeforeOp iop = (InsertBeforeOp)rewrites[i];
                // combine current insert with prior if any at same index
                var prevInserts = GetKindOfOps(rewrites, typeof(InsertBeforeOp), i);
                for (int j = 0; j < prevInserts.Count; j++)
                {
                    InsertBeforeOp prevIop = (InsertBeforeOp)prevInserts[j];
                    if (prevIop.index == iop.index)
                    { // combine objects
                        // convert to strings...we're in process of toString'ing
                        // whole token buffer so no lazy eval issue with any templates
                        iop.text = CatOpText(iop.text, prevIop.text);
                        // delete redundant prior insert
                        rewrites[prevIop.instructionIndex] = null;
                    }
                }
                // look for replaces where iop.index is in range; error
                var prevReplaces = GetKindOfOps(rewrites, typeof(ReplaceOp), i);
                for (int j = 0; j < prevReplaces.Count; j++)
                {
                    ReplaceOp rop = (ReplaceOp)prevReplaces[j];
                    if (iop.index == rop.index)
                    {
                        rop.text    = CatOpText(iop.text, rop.text);
                        rewrites[i] = null;  // delete current insert
                        continue;
                    }
                    if (iop.index >= rop.index && iop.index <= rop.lastIndex)
                    {
                        throw new ArgumentException("insert op " + iop +
                                                    " within boundaries of previous " + rop);
                    }
                }
            }
            // System.out.println("rewrites after="+rewrites);
            IDictionary <int, RewriteOperation> m = new Dictionary <int, RewriteOperation>();
            for (int i = 0; i < rewrites.Count; i++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[i];
                if (op == null)
                {
                    continue; // ignore deleted ops
                }
                RewriteOperation existing;
                if (m.TryGetValue(op.index, out existing) && existing != null)
                {
                    throw new Exception("should only be one op per index");
                }
                m[op.index] = op;
            }
            //System.out.println("index to op: "+m);
            return(m);
        }
 protected void addToSortedRewriteList(string programName, RewriteOperation op)
 {
     var rewrites = (ArrayList) getProgram(programName);
     // if at or beyond last op's index, just append
     if ( op.index >= getLastRewriteTokenIndex(programName) )
     {
         rewrites.Add(op); // append to list of operations
         // record the index of this operation for next time through
         setLastRewriteTokenIndex(programName, op.index);
         return;
     }
     // not after the last one, so must insert to ordered list
     var pos = rewrites.BinarySearch(op, RewriteOperationComparer.Default);
     if (pos < 0)
     {
         rewrites.Insert(-pos-1, op);
     }
 }
 /// <summary>
 /// If op.index > lastRewriteTokenIndexes, just add to the end.
 /// Otherwise, do linear
 /// </summary>
 /// <param name="op"></param>
 protected void addToSortedRewriteList(RewriteOperation op)
 {
     addToSortedRewriteList(DEFAULT_PROGRAM_NAME, op);
 }
示例#10
0
 /// <summary>
 /// If op.index > lastRewriteTokenIndexes, just add to the end.
 /// Otherwise, do linear
 /// </summary>
 /// <param name="op"></param>
 protected void addToSortedRewriteList(RewriteOperation op)
 {
     addToSortedRewriteList(DEFAULT_PROGRAM_NAME, op);
 }
示例#11
0
        /// <summary>
        /// Return a map from token index to operation.
        /// </summary>
        /// <remarks>We need to combine operations and report invalid operations (like
        /// overlapping replaces that are not completed nested).  Inserts to
        /// same index need to be combined etc...   Here are the cases:
        ///
        /// I.i.u I.j.v								leave alone, nonoverlapping
        /// I.i.u I.i.v								combine: Iivu
        ///
        /// R.i-j.u R.x-y.v	| i-j in x-y			delete first R
        /// R.i-j.u R.i-j.v							delete first R
        /// R.i-j.u R.x-y.v	| x-y in i-j			ERROR
        /// R.i-j.u R.x-y.v	| boundaries overlap	ERROR
        ///
        /// I.i.u R.x-y.v | i in x-y				delete I
        /// I.i.u R.x-y.v | i not in x-y			leave alone, nonoverlapping
        /// R.x-y.v I.i.u | i in x-y				ERROR
        /// R.x-y.v I.x.u                           R.x-y.uv (combine, delete I)
        /// R.x-y.v I.i.u | i not in x-y			leave alone, nonoverlapping
        ///
        /// I.i.u = insert u before op @ index i
        /// R.x-y.u = replace x-y indexed tokens with u
        ///
        /// First we need to examine replaces.  For any replace op:
        ///
        ///		1. wipe out any insertions before op within that range.
        ///		2. Drop any replace op before that is contained completely within
        ///        that range.
        ///		3. Throw exception upon boundary overlap with any previous replace.
        ///
        /// Then we can deal with inserts:
        ///
        ///		1. for any inserts to same index, combine even if not adjacent.
        ///		2. for any prior replace with same left boundary, combine this
        ///        insert with replace and delete this replace.
        ///		3. throw exception if index in same range as previous replace
        ///
        /// Don't actually delete; make op null in list. Easier to walk list.
        /// Later we can throw as we add to index -> op map.
        ///
        /// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
        /// inserted stuff would be before the replace range.  But, if you
        /// add tokens in front of a method body '{' and then delete the method
        /// body, I think the stuff before the '{' you added should disappear too.
        /// </remarks>
        protected IDictionary ReduceToSingleOperationPerIndex(IList rewrites)
        {
            // WALK REPLACES
            for (int i = 0; i < rewrites.Count; i++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[i];
                if (op == null)
                {
                    continue;
                }
                if (!(op is ReplaceOp))
                {
                    continue;
                }
                ReplaceOp rop = (ReplaceOp)rewrites[i];
                // Wipe prior inserts within range
                IList inserts = GetKindOfOps(rewrites, typeof(InsertBeforeOp), i);
                for (int j = 0; j < inserts.Count; j++)
                {
                    InsertBeforeOp iop = (InsertBeforeOp)inserts[j];
                    if (iop.index >= rop.index && iop.index <= rop.lastIndex)
                    {
                        // delete insert as it's a no-op.
                        rewrites[iop.instructionIndex] = null;
                    }
                }
                // Drop any prior replaces contained within
                IList prevReplaces = GetKindOfOps(rewrites, typeof(ReplaceOp), i);
                for (int j = 0; j < prevReplaces.Count; j++)
                {
                    ReplaceOp prevRop = (ReplaceOp)prevReplaces[j];
                    if (prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex)
                    {
                        // delete replace as it's a no-op.
                        rewrites[prevRop.instructionIndex] = null;
                        continue;
                    }
                    // throw exception unless disjoint or identical
                    bool disjoint =
                        prevRop.lastIndex <rop.index || prevRop.index> rop.lastIndex;
                    bool same =
                        prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex;
                    if (!disjoint && !same)
                    {
                        throw new ArgumentOutOfRangeException("replace op boundaries of " + rop +
                                                              " overlap with previous " + prevRop);
                    }
                }
            }

            // WALK INSERTS
            for (int i = 0; i < rewrites.Count; i++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[i];
                if (op == null)
                {
                    continue;
                }
                if (!(op is InsertBeforeOp))
                {
                    continue;
                }
                InsertBeforeOp iop = (InsertBeforeOp)rewrites[i];
                // combine current insert with prior if any at same index
                IList prevInserts = GetKindOfOps(rewrites, typeof(InsertBeforeOp), i);
                for (int j = 0; j < prevInserts.Count; j++)
                {
                    InsertBeforeOp prevIop = (InsertBeforeOp)prevInserts[j];
                    if (prevIop.index == iop.index)                         // combine objects
                    // convert to strings...we're in process of toString'ing
                    // whole token buffer so no lazy eval issue with any templates
                    {
                        iop.text = CatOpText(iop.text, prevIop.text);
                        // delete redundant prior insert
                        rewrites[prevIop.instructionIndex] = null;
                    }
                }
                // look for replaces where iop.index is in range; error
                IList prevReplaces = GetKindOfOps(rewrites, typeof(ReplaceOp), i);
                for (int j = 0; j < prevReplaces.Count; j++)
                {
                    ReplaceOp rop = (ReplaceOp)prevReplaces[j];
                    if (iop.index == rop.index)
                    {
                        rop.text    = CatOpText(iop.text, rop.text);
                        rewrites[i] = null;                          // delete current insert
                        continue;
                    }
                    if (iop.index >= rop.index && iop.index <= rop.lastIndex)
                    {
                        throw new ArgumentOutOfRangeException("insert op " + iop +
                                                              " within boundaries of previous " + rop);
                    }
                }
            }
            // System.out.println("rewrites after="+rewrites);
            IDictionary m = new Hashtable();

            for (int i = 0; i < rewrites.Count; i++)
            {
                RewriteOperation op = (RewriteOperation)rewrites[i];
                if (op == null)
                {
                    continue;                             // ignore deleted ops
                }
                if (m[op.index] != null)
                {
                    throw new Exception("should only be one op per index");
                }
                m[op.index] = op;
            }
            //System.out.println("index to op: "+m);
            return(m);
        }
示例#12
0
        public virtual string ToString(string programName, int start, int end)
        {
            IList rewrites = (IList)programs[programName];

            // ensure start/end are in range
            if (end > tokens.Count - 1)
            {
                end = tokens.Count - 1;
            }
            if (start < 0)
            {
                start = 0;
            }

            if ((rewrites == null) || (rewrites.Count == 0))
            {
                return(ToOriginalString(start, end));                // no instructions to execute
            }
            StringBuilder buf = new StringBuilder();

            // First, optimize instruction stream
            IDictionary indexToOp = ReduceToSingleOperationPerIndex(rewrites);

            // Walk buffer, executing instructions and emitting tokens
            int i = start;

            while (i <= end && i < tokens.Count)
            {
                RewriteOperation op = (RewriteOperation)indexToOp[i];
                indexToOp.Remove(i);                 // remove so any left have index size-1
                IToken t = (IToken)tokens[i];
                if (op == null)
                {
                    // no operation at that index, just dump token
                    buf.Append(t.Text);
                    i++;                     // move to next token
                }
                else
                {
                    i = op.Execute(buf);                     // execute operation and skip
                }
            }

            // include stuff after end if it's last index in buffer
            // So, if they did an insertAfter(lastValidIndex, "foo"), include
            // foo if end==lastValidIndex.
            if (end == tokens.Count - 1)
            {
                // Scan any remaining operations after last token
                // should be included (they will be inserts).
                IEnumerator iter = indexToOp.Values.GetEnumerator();
                while (iter.MoveNext())
                {
                    InsertBeforeOp iop = (InsertBeforeOp)iter.Current;
                    if (iop.index >= tokens.Count - 1)
                    {
                        buf.Append(iop.text);
                    }
                }
            }
            return(buf.ToString());
        }