Esempio n. 1
0
        /// <summary>
        /// Returns the target variable or signal, or null
        /// </summary>
        /// <returns>The target variable or signal.</returns>
        /// <param name="self">The item to examine.</param>
        public static DataElement GetTarget(this ASTItem self)
        {
            if (self == null)
            {
                return(null);
            }
            if (self is DataElement)
            {
                return((DataElement)self);
            }
            if (self is IdentifierExpression)
            {
                return(((IdentifierExpression)self).Target);
            }
            if (self is MemberReferenceExpression)
            {
                return(((MemberReferenceExpression)self).Target);
            }
            if (self is WrappingExpression)
            {
                return(GetTarget(((WrappingExpression)self).Expression));
            }
            if (self is CustomExpression)
            {
                return(((CustomExpression)self).GetTarget());
            }

            return(null);
        }
Esempio n. 2
0
        /// <summary>
        /// Returns all the leaves in the sequence originating in the given item
        /// </summary>
        /// <returns>The leaves.</returns>
        /// <param name="self">The items to enumerate.</param>
        /// <param name="visitor">The visitor method. Return <c>false</c> to prevent entering this node.</param>
        public static IEnumerable <ASTItem> LeavesOnly(this ASTItem self, Func <ASTItem, VisitorState, bool> visitor = null)
        {
            visitor = visitor ?? ((a, b) => true);
            var     work = new List <ASTItem>();
            ASTItem last = null;

            foreach (var n in All(self, (el, state) =>
            {
                if (state == VisitorState.Enter)
                {
                    last = el;
                }
                if (state == VisitorState.Leave)
                {
                    if (el == last)
                    {
                        work.Add(el);
                    }
                    last = null;
                }
                return(visitor(el, state));
            }))
            {
                foreach (var el in work)
                {
                    yield return(el);
                }

                work.Clear();
            }
            foreach (var el in work)
            {
                yield return(el);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Visits all elements in depth-first-search, using post-order vistits
        /// </summary>
        /// <returns>The sequence of elements in depth-first post-order.</returns>
        /// <param name="self">The item to enumerate.</param>
        /// <param name="visitor">The visitor method. Return <c>false</c> to prevent entering this node.</param>
        public static IEnumerable <ASTItem> DepthFirstPostOrder(this ASTItem self, Func <ASTItem, VisitorState, bool> visitor = null)
        {
            visitor = visitor ?? ((a, b) => true);
            var work = new List <ASTItem>();

            foreach (var n in All(self, (el, state) => {
                if (state == VisitorState.Leave)
                {
                    work.Add(el);
                }
                return(visitor(el, state));
            }))
            {
                foreach (var el in work)
                {
                    yield return(el);
                }

                work.Clear();
            }

            foreach (var el in work)
            {
                yield return(el);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Enumerates all elements in the item, and optionally applies the visitor function
        /// </summary>
        /// <param name="self">The item to traverse.</param>
        /// <param name="visitor">The visitor method. Return <c>false</c> to prevent entering this node.</param>
        public static IEnumerable <ASTItem> All(this ASTItem self, Func <ASTItem, VisitorState, bool> visitor = null)
        {
            if (self is Network)
            {
                return(All((Network)self, visitor));
            }
            if (self is Process)
            {
                return(All((Process)self, visitor));
            }
            if (self is Bus)
            {
                return(All((Bus)self, visitor));
            }
            if (self is Method)
            {
                return(All((Method)self, visitor));
            }
            if (self is Statement)
            {
                return(All((Statement)self, visitor));
            }
            if (self is Expression)
            {
                return(All((Expression)self, visitor));
            }

            throw new Exception($"Unable to visit expression of type {self.GetType().FullName}");
        }
Esempio n. 5
0
            /// <summary>
            /// Starts a new local scope
            /// </summary>
            /// <param name="scope">The item starting the scope.</param>
            public void StartScope(ASTItem scope)
            {
                if (scope == null)
                {
                    throw new ArgumentNullException(nameof(scope));
                }

                Scopes.Add(new KeyValuePair <ASTItem, Dictionary <string, Variable> >(scope, new Dictionary <string, Variable>()));
            }
Esempio n. 6
0
        /// <summary>
        /// Reverse walks the tree to find the next parent of the given type or null
        /// </summary>
        /// <returns>The nearest parent or null.</returns>
        /// <param name="self">The item ot get the parent for.</param>
        /// <param name="parentType">The data type to look for.</param>
        public static ASTItem GetNearestParent(this ASTItem self, Type parentType)
        {
            if (self == null)
            {
                return(null);
            }
            var p = self.Parent;

            while (p != null && !parentType.IsAssignableFrom(p.GetType()))
            {
                p = p.Parent;
            }

            return(p);
        }
Esempio n. 7
0
            /// <summary>
            /// Closes the current local scope
            /// </summary>
            /// <param name="scope">The scope to close.</param>
            public void FinishScope(ASTItem scope)
            {
                if (scope == null)
                {
                    throw new ArgumentNullException(nameof(scope));
                }

                if (Scopes.Last().Key != scope)
                {
                    throw new Exception("PopScope had incorrect scope");
                }

                if (scope is BlockStatement)
                {
                    ((BlockStatement)scope).Variables = Scopes.Last().Value.Values.ToArray();
                }

                Scopes.RemoveAt(Scopes.Count - 1);
            }
Esempio n. 8
0
 /// <summary>
 /// Sets the target value
 /// </summary>
 /// <returns>The target variable or signal.</returns>
 /// <param name="self">The item to set the element on.</param>
 /// <param name="target">The value to set</param>
 public static void SetTarget(this ASTItem self, DataElement target)
 {
     if (self is IdentifierExpression)
     {
         ((IdentifierExpression)self).Target = target;
     }
     else if (self is MemberReferenceExpression)
     {
         ((MemberReferenceExpression)self).Target = target;
     }
     else if (self is WrappingExpression)
     {
         SetTarget(((WrappingExpression)self).Expression, target);
     }
     else if (self is Expression && self != ((Expression)self).GetUnwrapped())
     {
         SetTarget(((Expression)self).GetUnwrapped(), target);
     }
     else
     {
         throw new Exception($"Unable to set target on item of type {self.GetType().FullName}");
     }
 }
Esempio n. 9
0
 /// <summary>
 /// Reverse walks the tree to find the next parent of the given type or null
 /// </summary>
 /// <returns>The nearest parent or null.</returns>
 /// <param name="self">The item ot get the parent for.</param>
 /// <typeparam name="T">The data type to look for.</typeparam>
 public static T GetNearestParent <T>(this ASTItem self)
     where T : ASTItem
 {
     return((T)GetNearestParent(self, typeof(T)));
 }
Esempio n. 10
0
        /// <summary>
        /// Locates the target for an expression.
        /// </summary>
        /// <returns>The data element.</returns>
        /// <param name="network">The top-level network.</param>
        /// <param name="proc">The process where the method is located.</param>
        /// <param name="method">The method where the statement is found.</param>
        /// <param name="statement">The statement where the expression is found.</param>
        /// <param name="expression">The expression to examine.</param>
        protected ASTItem TryLocateElement(NetworkState network, ProcessState proc, MethodState method, Statement statement, ICSharpCode.Decompiler.CSharp.Syntax.Expression expression)
        {
            if (expression is ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression)
            {
                var e      = expression as ICSharpCode.Decompiler.CSharp.Syntax.InvocationExpression;
                var target = e.Target;
                return(LocateDataElement(network, proc, method, statement, target));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression)
            {
                var e      = expression as ICSharpCode.Decompiler.CSharp.Syntax.IndexerExpression;
                var target = e.Target;
                return(LocateDataElement(network, proc, method, statement, target));
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)
            {
                var e    = expression as ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression;
                var name = e.Identifier;

                Variable variable;
                if (method != null && method.TryGetVariable(name, out variable))
                {
                    return(variable);
                }

                if (method != null)
                {
                    var p = method.Parameters.FirstOrDefault(x => x.Name == name);
                    if (p != null)
                    {
                        return(p);
                    }
                }

                if (proc.Variables.TryGetValue(name, out variable))
                {
                    return(variable);
                }

                Signal signal;
                if (proc != null && proc.Signals.TryGetValue(name, out signal))
                {
                    return(signal);
                }

                return(null);
            }
            else if (expression is ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)
            {
                var e = expression as ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression;

                ASTItem current = null;

                var parts = new List <string>();
                ICSharpCode.Decompiler.CSharp.Syntax.Expression ec = e;
                while (ec != null)
                {
                    if (ec is ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)
                    {
                        parts.Add(((ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)ec).MemberName);
                        ec = ((ICSharpCode.Decompiler.CSharp.Syntax.MemberReferenceExpression)ec).Target;
                    }
                    else if (ec is ICSharpCode.Decompiler.CSharp.Syntax.ThisReferenceExpression)
                    {
                        //parts.Add("this");
                        ec = null;
                        break;
                    }
                    else if (ec is ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)
                    {
                        parts.Add(((ICSharpCode.Decompiler.CSharp.Syntax.IdentifierExpression)ec).Identifier);
                        ec = null;
                        break;
                    }
                    else if (ec is ICSharpCode.Decompiler.CSharp.Syntax.TypeReferenceExpression)
                    {
                        TypeDefinition dc = null;
                        if (method != null)
                        {
                            dc = method.SourceMethod.DeclaringType;
                        }
                        else if (proc != null)
                        {
                            dc = proc.CecilType.Resolve();
                        }

                        var ecs = ec.ToString();

                        if (dc != null)
                        {
                            if (ecs == dc.FullName || ecs == dc.Name)
                            {
                                ec = null;
                                //parts.Add("this");
                                break;
                            }

                            var targetproc = network.Processes.FirstOrDefault(x => x.CecilType.Name == ecs || x.CecilType.FullName == ecs);
                            if (targetproc != null)
                            {
                                // This is a static reference
                                current = null;                                 //targetproc;
                                break;
                            }

                            var bt = LoadTypeByName(ecs, dc.Module);
                            if (bt == null)
                            {
                                bt = LoadTypeByName(dc.FullName + "." + ecs, method.SourceMethod.Module);
                            }
                            if (bt == null)
                            {
                                bt = LoadTypeByName(dc.Namespace + "." + ecs, method.SourceMethod.Module);
                            }
                            // In some cases dc.Namespace is empty ...
                            if (bt == null && proc != null && proc.SourceType != null)
                            {
                                bt = LoadTypeByName(proc.SourceType.Namespace + "." + ecs, method.SourceMethod.Module);
                            }

                            if (bt != null && parts.Count == 1)
                            {
                                var br = bt.Resolve();
                                var px = br.Fields.FirstOrDefault(x => x.Name == parts[0]);

                                // Enum flags are encoded as constants
                                if (br.IsEnum)
                                {
                                    if (px == null)
                                    {
                                        throw new Exception($"Unable to find enum value {parts[0]} in {br.FullName}");
                                    }

                                    return(new Constant()
                                    {
                                        CecilType = bt,
                                        DefaultValue = px,
                                        Source = expression
                                    });
                                }
                                else
                                {
                                    // This is a constant of sorts
                                    var pe = network.ConstantLookup.Keys.FirstOrDefault(x => x.Name == parts[0]);
                                    if (pe != null)
                                    {
                                        return(network.ConstantLookup[pe]);
                                    }

                                    return(network.ConstantLookup[px] = new Constant()
                                    {
                                        CecilType = px.FieldType,
                                        Name = parts[0],
                                        Source = px,
                                        Parent = network
                                    });
                                }

                                //parts.AddRange(bt.FullName.Split('.').Reverse());
                            }


                            break;
                        }

                        // Likely a static reference, which is stored as a global constant
                        ec = null;
                    }
                    else
                    {
                        throw new Exception($"Unexpected element in reference chain: {ec.GetType().FullName}");
                    }
                }

                parts.Reverse();
                var fullname = string.Join(".", parts);


                if (parts.First() == "this")
                {
                    parts.RemoveAt(0);
                    if (proc == null)
                    {
                        throw new Exception("Attempting to do a resolve of \this\" but no process context is provided");
                    }
                    current = proc;
                }

                var first = true;
                foreach (var el in parts)
                {
                    var isIsFirst = first;
                    first = false;

                    if (current == null)
                    {
                        var pe = network.ConstantLookup.Keys.FirstOrDefault(x => x.Name == el);
                        if (pe != null)
                        {
                            current = network.ConstantLookup[pe];
                            continue;
                        }
                    }

                    if (current is MethodState || (isIsFirst && current == null))
                    {
                        //if (method.LocalRenames.ContainsKey(el))
                        //	el = method.LocalRenames[el];

                        var mt = current as MethodState ?? method;
                        if (mt != null)
                        {
                            Variable temp;
                            if (mt.TryGetVariable(el, out temp))
                            {
                                current = temp;
                                continue;
                            }

                            var p = mt.Parameters.FirstOrDefault(x => x.Name == el);
                            if (p != null)
                            {
                                current = p;
                                continue;
                            }

                            if (mt.ReturnVariable != null && !string.IsNullOrWhiteSpace(mt.ReturnVariable.Name) && el == mt.ReturnVariable.Name)
                            {
                                current = mt.ReturnVariable;
                                continue;
                            }
                        }
                    }

                    if (current is ProcessState || (isIsFirst && current == null))
                    {
                        var pr = current as ProcessState ?? proc;

                        if (pr != null)
                        {
                            if (pr.BusInstances.ContainsKey(el))
                            {
                                current = pr.BusInstances[el];
                                continue;
                            }

                            if (pr.Signals.ContainsKey(el))
                            {
                                current = pr.Signals[el];
                                continue;
                            }

                            if (pr.Variables.ContainsKey(el))
                            {
                                current = pr.Variables[el];
                                continue;
                            }

                            if (pr.Methods != null)
                            {
                                var p = pr.Methods.FirstOrDefault(x => x.Name == el);
                                if (p != null)
                                {
                                    current = p;
                                    continue;
                                }
                            }
                        }
                    }

                    if (current is Bus)
                    {
                        current = ((Bus)current).Signals.FirstOrDefault(x => x.Name == el);
                        if (current != null)
                        {
                            continue;
                        }
                    }

                    if (current is Variable)
                    {
                        var fi = ((Variable)current).CecilType.Resolve().Fields.FirstOrDefault(x => x.Name == el);
                        if (fi != null)
                        {
                            current = new Variable()
                            {
                                Name         = el,
                                Parent       = current,
                                Source       = fi,
                                CecilType    = fi.FieldType,
                                DefaultValue = null
                            };

                            continue;
                        }

                        var pi = ((Variable)current).CecilType.Resolve().Properties.FirstOrDefault(x => x.Name == el);
                        if (pi != null)
                        {
                            current = new Variable()
                            {
                                Name         = el,
                                Parent       = current,
                                Source       = fi,
                                CecilType    = fi.FieldType,
                                DefaultValue = null
                            };

                            continue;
                        }
                    }

                    if (el == "Length" && (current is DataElement) && ((DataElement)current).CecilType.IsArrayType())
                    {
                        return(new Constant()
                        {
                            ArrayLengthSource = current as DataElement,
                            CecilType = LoadType(typeof(int)),
                            DefaultValue = null,
                            Source = (current as DataElement).Source
                        });
                    }

                    throw new Exception($"Failed lookup at {el} in {fullname}");
                }

                if (current == null)
                {
                    throw new Exception($"Failed to fully resolve {fullname}");
                }

                return(current);
            }
            else
            {
                throw new Exception($"Unable to find a data element for an expression of type {expression.GetType().FullName}");
            }
        }