Click here to Skip to main content
15,885,123 members
Articles / Containers / Virtual Machine

Hacking the Mono C# Compiler.

Rate me:
Please Sign up or sign in to vote.
5.00/5 (12 votes)
9 Oct 2010CPOL7 min read 56.2K   1.5K   41  
Describes how to dump information from the C# parse tree
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;

namespace Mono.CSharp {


    public interface IVisitable
    {
        IEnumerable<IVisitable> GetChildren(object context);
        string GetName();
    }

    public class Child : IVisitable
    {
        public string name;
        
        public Child(string name){
            this.name = name;
        }

        public string Name
        {
            get
            {
                return name;
            }
        }

        public virtual IEnumerable<IVisitable> GetChildren(object context)
        {
            throw new NotImplementedException("subclasses of Child should implement IVisitable interface");
        }

        public virtual string GetName()
        {
            return Name;
        }


    }

    public class Single: Child
    {
        public IVisitable value;
        
        public IVisitable Value{
            get{
                return value;
            }
        } 
       
        public Single(string name, IVisitable value): base(name)
        {
            this.value = value;
        }

        public override IEnumerable<IVisitable> GetChildren(object context)
        {
            yield return value;
        }

        public override int GetHashCode()
        {
            return value.GetHashCode();
        }

        public override bool Equals(Object o)
        {
            if (o is Single)
            {
                return (value == (o as Single).value);
            }
            return false;
        }

    }

    public class StringValue : Child
    {
        public string value;

        public string Value
        {
            get
            {
                return value;
            }
        }

        public StringValue(string name, string value)
            : base(name)
        {
            this.value = value;
        }

        public override IEnumerable<IVisitable> GetChildren(object context)
        {
            return Enumerable.Empty<IVisitable>();
        }

        public override int GetHashCode()
        {
            return value.GetHashCode();
        }

        public override bool Equals(Object o)
        {
            if (o is StringValue)
            {
                return (((value == null && (o as StringValue).value == null))
                        |
                       (value == (o as StringValue).value));
            }
            return false;
        }

    }

    public class NullValue : Child
    {

        public NullValue(string name)
            : base(name)
        {
        }

        public override IEnumerable<IVisitable> GetChildren(object context)
        {
            return Enumerable.Empty<IVisitable>();
        }
    }

    public class Many: Child
    {
        public IVisitable[] values;
        
        public IVisitable[] Values{
            get{
                return values;
            }
        }

        public Many(string name, IVisitable[] values)
            : base(name)
        {
            this.values = values;
        }

        public override IEnumerable<IVisitable> GetChildren(object context)
        {
            return values;
        }


    }

    public class Container: IEnumerable<IVisitable>
    {
        private List<IVisitable> children;

        public Container(){
            children = new List<IVisitable>();
        }

        public void Add(IVisitable v)
        {
            children.Add(v);
        }

        public Container Single(string name, IVisitable value)
        {
            if (value != null)
                children.Add(new Single(name, value));
            else
                children.Add(new NullValue(name));
            return this;
        }

        public Container String(string name, string value)
        {
            children.Add(new StringValue(name, value));
            return this;
        }

        public Container Many(string name, IVisitable[] values)
        {
            if (values != null)
            {
                children.Add(new Many(name, values));
            }
            else
            {
                children.Add(new NullValue(name));
            }
            return this;
        }

        public Container ManyUntyped(string name, System.Collections.IEnumerable values)
        {
            if (values != null)
            {
                List<IVisitable> tmp = new List<IVisitable>();

                foreach (object value in values)
                {
                    if (value is IVisitable)
                        tmp.Add(value as IVisitable);
                    else
                        throw new NotSupportedException("Expected IVisitable");
                }
                children.Add(new Many(name, tmp.ToArray()));
            }
            else
            {
                children.Add(new NullValue(name));
            }
            return this;
        }

        public Container Base(IEnumerable<IVisitable> children)
        {
            foreach (var child in children)
                this.children.Add(child);
            return this;
        }

        public IEnumerator<IVisitable> GetEnumerator(){
            return children.GetEnumerator();
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return children.GetEnumerator();
        }
        //public System.Collections.IEnumerator GetEnumerator()
        //{
        //    return children.GetEnumerator();
        //}

    }

    

    public class Visitable{
        public static Container Container(){
            return new Container();
        }
        

        public static IVisitable [] HashTableToArray(System.Collections.Hashtable table){
            List<IVisitable> tmp = new List<IVisitable>();
            foreach(var k in table.Keys){
                var name = k as string;
                var value = table[k];
                if (!(value is IVisitable) || name == null)
                    throw new NotImplementedException("Expected IVisitable");
                tmp.Add(new Single(name, value as IVisitable));
            }
            return tmp.ToArray();
        }

        public static IVisitable[] ListDictionaryToArray(System.Collections.Specialized.ListDictionary table)
        {
            List<IVisitable> tmp = new List<IVisitable>();
            List<object> values = new List<object>();
            foreach (var v in table.Values)
            {
                values.Add(v);
            }
            var valuesArr = values.ToArray();
            int i = 0;
            foreach (var k in table.Keys)
            {
                var name = k as string;
                var value = valuesArr[i++];
                if (!(value is IVisitable) || name == null)
                    throw new NotImplementedException("Expected IVisitable");
                tmp.Add(new Single(name, value as IVisitable));
            }
            return tmp.ToArray();
        }
    }

    public class ReflectedObject: IVisitable
    {
        object value;
        public ReflectedObject(object o){
            value = o;
        }

		public override int GetHashCode ()
		{
			return value.GetHashCode ();
		}

        public override bool Equals(Object o)
        {
            if (o is ReflectedObject)
            {
                return (value == (o as ReflectedObject).value);
            }
            return false;
        }



        public virtual string GetName()
        {
            return "class: " + value.GetType().ToString().Replace("Mono.CSharp.", "");
        }

        public virtual IEnumerable<IVisitable> GetChildren(object context)
        {
            var c = Visitable.Container();
            Type typeInfo1 = value.GetType();

            List<Type> nestedL = new List<Type>();
            while(typeInfo1 != null && !(typeInfo1.ToString().StartsWith("System."))){
                nestedL.Add(typeInfo1);
                typeInfo1 = typeInfo1.BaseType;
            }


            Dictionary<string, bool> shown = new Dictionary<string, bool>();
            foreach (var typeInfo in nestedL)
            {
                foreach (System.Reflection.FieldInfo fi in typeInfo.GetFields(System.Reflection.BindingFlags.Instance
                                                                              | System.Reflection.BindingFlags.Public
                                                                              //| System.Reflection.BindingFlags.FlattenHierarchy
                                                                              | System.Reflection.BindingFlags.Static
                                                                              | System.Reflection.BindingFlags.NonPublic))
                {
                    if (shown.ContainsKey(fi.Name))
                        continue;
                    shown[fi.Name] = true;

                    var fieldValue = fi.GetValue(value);


                    if (fieldValue != null)
                    {
                        var t = fieldValue.GetType();
                        if (t == typeof(Mono.CSharp.CompilerContext)) //skip this type
                        {
                            continue;
                        }

                        if (t.ToString().StartsWith("Mono.CSharp") && t.IsClass &&
                            (!(fieldValue is System.Collections.ArrayList)) &&
                            (!(fieldValue is System.Collections.Hashtable))
                            )
                        {
                            c.Single("field: " + fi.Name, new ReflectedObject(fieldValue));
                        }
                        else if (fieldValue is System.Collections.ArrayList)
                        {
                            var c1 = Visitable.Container();
                            foreach (var o in (fieldValue as System.Collections.ArrayList))
                            {
                                c1.Add(new ReflectedObject(o));
                            }
                            c.Many("field: " + fi.Name, c1.ToArray());
                        }
                        else if (fieldValue is System.Collections.Hashtable)
                        {
                            var c1 = Visitable.Container();
                            var table = (fieldValue as System.Collections.Hashtable);
                            foreach (var o in table.Keys)
                            {
                                var key = o as string;
                                var v = table[key];
                                c1.Add(new Single("key: " + key, new ReflectedObject(v)));
                            }
                            c.Many("field: " + fi.Name, c1.ToArray());
                        }
                        else
                            c.String("field: " + fi.Name, "value: " + fieldValue.ToString());
                    }
                }
            }
            return c;
            
        }
    }

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions