public override void OutASimpleInvokeExp(ASimpleInvokeExp node)
        {
            if (data.SimpleMethodLinks.ContainsKey(node))
                return;

            List<AMethodDecl> candidates = new List<AMethodDecl>();
            List<AMethodDecl> implicitCandidates = new List<AMethodDecl>();
            List<AMethodDecl> matchingNames = new List<AMethodDecl>();

            List<PType> argTypes = new List<PType>();
            foreach (PExp exp in node.GetArgs())
            {
                argTypes.Add(data.ExpTypes[exp]);
            }
            PExp baseExp;
            bool matchResize;
            GetTargets(node.GetName().Text, node.GetName(), null, null, argTypes, candidates, out matchResize, implicitCandidates, matchingNames, out baseExp, null, data, errors);

            if (baseExp != null)
            {
                ANonstaticInvokeExp replacer = new ANonstaticInvokeExp(baseExp, new ADotDotType(new TDot(".")), node.GetName(), new ArrayList());
                while (node.GetArgs().Count > 0)
                {
                    replacer.GetArgs().Add(node.GetArgs()[0]);
                }
                node.ReplaceBy(replacer);
                baseExp.Apply(this);
                OutANonstaticInvokeExp(replacer);
                return;
            }

            AMethodDecl decl;
            if (candidates.Count == 0 && implicitCandidates.Count == 1)
            {
                //Do the implicit casts
                for (int i = 0; i < node.GetArgs().Count; i++)
                {
                    PType argType = data.ExpTypes[(PExp)node.GetArgs()[i]];
                    AALocalDecl formal = (AALocalDecl)implicitCandidates[0].GetFormals()[i];
                    PType formalType = formal.GetType();
                    if (formal.GetOut() != null && !Assignable(formalType, argType)
                        || formal.GetRef() != null && !(Assignable(argType, formalType) && Assignable(formalType, argType))
                        || formal.GetOut() == null && formal.GetRef() == null && !Assignable(argType, formalType))
                    {
                        PExp exp = (PExp)node.GetArgs()[i];
                        ACastExp cast = new ACastExp(new TLParen("("), Util.MakeClone(formalType, data), null);
                        exp.ReplaceBy(cast);
                        cast.SetExp(exp);
                        OutACastExp(cast);
                    }
                }
                decl = implicitCandidates[0];
            }
            else
                decl = candidates[0];

            data.SimpleMethodLinks.Add(node, decl);
            data.ExpTypes.Add(node, decl.GetReturnType());

            CheckInvoke(node, decl);

            base.OutASimpleInvokeExp(node);
        }
        private void MakeInvoke(InvokeStm node)
        {
            //Find target method
            List<AMethodDecl> candidates = new List<AMethodDecl>();
            List<AMethodDecl> implicitCandidates = new List<AMethodDecl>();
            List<AMethodDecl> matchingNames = new List<AMethodDecl>();

            List<PType> argTypes = new List<PType>();
            foreach (PExp exp in node.Args)
            {
                argTypes.Add(data.ExpTypes[exp]);
            }
            PExp baseExp;
            bool needsVisit = node.Base == null || node.Base is AAName;
            bool matchResize;

            if (node.Base != null)
            {

            }

            GetTargets(node.Name.Text, node.Token, node.Base, null, argTypes, candidates, out matchResize, implicitCandidates, matchingNames, out baseExp, null, data, errors);

            if (needsVisit && baseExp != null)
            {
                //Add as an arg, visit it, then remove it
                node.Args.Add(baseExp);
                baseExp.Apply(this);
                node.Args.Remove(baseExp);
            }

            AMethodDecl candidate = candidates.Count == 1 ? candidates[0] : implicitCandidates[0];
            bool isImplicitCandidate = candidates.Count != 1;

            if (baseExp != null && baseExp is ALvalueExp && ((ALvalueExp)baseExp).GetLvalue() is APointerLvalue && Util.HasAncestor<AStructDecl>(candidate))
            {
                baseExp = ((APointerLvalue) ((ALvalueExp) baseExp).GetLvalue()).GetBase();
            }
            node.BaseExp = baseExp;

            if (isImplicitCandidate)
            {
                //Do the implicit casts
                for (int i = 0; i < node.Args.Count; i++)
                {
                    PType argType = argTypes[i];
                    AALocalDecl formal = (AALocalDecl) candidate.GetFormals()[i];
                    PType formalType = formal.GetType();
                    if (formal.GetOut() != null && !Assignable(formalType, argType)
                        ||
                        formal.GetRef() != null && !(Assignable(argType, formalType) && Assignable(formalType, argType))
                        || formal.GetOut() == null && formal.GetRef() == null && !Assignable(argType, formalType))
                    {
                        PExp exp = (PExp) node.Args[i];
                        ACastExp cast = new ACastExp(new TLParen("("), Util.MakeClone(formalType, data), null);
                        exp.ReplaceBy(cast);
                        cast.SetExp(exp);
                        OutACastExp(cast);
                    }
                }
            }

            if (!data.Invokes.ContainsKey(candidate))
                data.Invokes.Add(candidate, new List<InvokeStm>());
            data.Invokes[candidate].Add(node);
            if (!node.IsAsync)
                data.ExpTypes.Add(node.SyncNode, candidate.GetReturnType());

            //For each formal marked as ref or out, the argument must be a variable
            for (int i = 0; i < node.Args.Count; i++)
            {
                AALocalDecl formal = (AALocalDecl)candidate.GetFormals()[i];
                if (formal.GetRef() != null || formal.GetOut() != null)
                {
                    PExp exp = (PExp)node.Args[i];
                    while (true)
                    {
                        PLvalue lvalue;
                        if (exp is ALvalueExp)
                        {
                            lvalue = ((ALvalueExp)exp).GetLvalue();
                        }
                        else if (exp is AAssignmentExp)
                        {
                            lvalue = ((AAssignmentExp)exp).GetLvalue();
                        }
                        else
                        {
                            errors.Add(new ErrorCollection.Error(node.Token, currentSourceFile, LocRM.GetString("ErrorText129") + (i + 1) + LocRM.GetString("ErrorText130")));
                            break;
                        }
                        if (lvalue is ALocalLvalue ||
                            lvalue is AFieldLvalue ||
                            lvalue is AStructFieldLvalue)
                            break;
                        if (lvalue is AStructLvalue)
                        {
                            exp = ((AStructLvalue)lvalue).GetReceiver();
                            continue;
                        }
                        if (lvalue is AArrayLvalue)
                        {
                            exp = ((AArrayLvalue)lvalue).GetBase();
                            continue;
                        }
                        throw new Exception("Unexpected lvalue");
                    }
                }
            }
        }
        public override void OutANonstaticInvokeExp(ANonstaticInvokeExp node)
        {
            List<AMethodDecl> candidates = new List<AMethodDecl>();
            List<AMethodDecl> implicitCandidates = new List<AMethodDecl>();
            List<AMethodDecl> matchingNames = new List<AMethodDecl>();
            List<AMethodDecl> delegateCandidates = new List<AMethodDecl>();

            List<PType> argTypes = new List<PType>();
            foreach (PExp exp in node.GetArgs())
            {
                argTypes.Add(data.ExpTypes[exp]);
            }
            PExp baseExp;
            bool needsVistit = false;
            Node reciever = node.GetReceiver();
            bool visitBaseExp = false;
            if (node.GetReceiver() is ALvalueExp && ((ALvalueExp)node.GetReceiver()).GetLvalue() is AAmbiguousNameLvalue)
            {
                visitBaseExp = true;
                reciever = ((AAmbiguousNameLvalue) ((ALvalueExp) node.GetReceiver()).GetLvalue()).GetAmbiguous();
            }
            bool matchResize;
            GetTargets(node.GetName().Text, node.GetName(), reciever, null, argTypes, candidates, out matchResize, implicitCandidates, matchingNames, out baseExp, delegateCandidates, data, errors);

            if (visitBaseExp && baseExp != null)
            {
                node.GetArgs().Add(baseExp);
                baseExp.Apply(this);
                node.GetArgs().Remove(baseExp);
            }

            if (matchResize)
            {
                AArrayResizeExp replacer = new AArrayResizeExp(node.GetName(), baseExp, (PExp) node.GetArgs()[0]);
                node.ReplaceBy(replacer);
                data.ExpTypes[replacer] = new ANamedType(new TIdentifier("void"), null);
                return;
            }

            if (implicitCandidates.Count > 0)
            {
                //Do the implicit casts
                for (int i = 0; i < node.GetArgs().Count; i++)
                {
                    PType argType = data.ExpTypes[(PExp)node.GetArgs()[i]];
                    AALocalDecl formal = (AALocalDecl)implicitCandidates[0].GetFormals()[i];
                    PType formalType = formal.GetType();
                    if (formal.GetOut() != null && !Assignable(formalType, argType)
                        || formal.GetRef() != null && !(Assignable(argType, formalType) && Assignable(formalType, argType))
                        || formal.GetOut() == null && formal.GetRef() == null && !Assignable(argType, formalType))
                    {
                        PExp exp = (PExp)node.GetArgs()[i];
                        ACastExp cast = new ACastExp(new TLParen("("), Util.MakeClone(formalType, data), null);
                        exp.ReplaceBy(cast);
                        cast.SetExp(exp);
                        OutACastExp(cast);
                    }
                }
            }

            if (delegateCandidates.Count > 0)
            {//Target is a delegate invoke
                ADelegateInvokeExp replacer = new ADelegateInvokeExp(node.GetName(), baseExp, new ArrayList());
                while (node.GetArgs().Count > 0)
                {
                    replacer.GetArgs().Add(node.GetArgs()[0]);
                }
                data.ExpTypes[replacer] = delegateCandidates[0].GetReturnType();
                node.ReplaceBy(replacer);
                return;
            }
            AMethodDecl candidate = candidates.Count == 1 ? candidates[0] : implicitCandidates[0];

            if (baseExp == null)
            {
                //Replace with a simple invoke to it.
                ASimpleInvokeExp replacementInvoke = new ASimpleInvokeExp(node.GetName(), new ArrayList());
                while (node.GetArgs().Count > 0)
                {
                    replacementInvoke.GetArgs().Add(node.GetArgs()[0]);
                }
                data.SimpleMethodLinks[replacementInvoke] = candidate;
                data.ExpTypes[replacementInvoke] = candidate.GetReturnType();
                node.ReplaceBy(replacementInvoke);
                CheckInvoke(replacementInvoke, candidate);
                return;
            }
            node.SetReceiver(baseExp);

            data.StructMethodLinks[node] = candidate;
            data.ExpTypes[node] = candidate.GetReturnType();

            if (candidate.GetInline() != null)
            {
                AMethodDecl pMethod = Util.GetAncestor<AMethodDecl>(node);
                AConstructorDecl pConstructor = Util.GetAncestor<AConstructorDecl>(node);
                APropertyDecl pProperty = Util.GetAncestor<APropertyDecl>(node);
                if (pMethod == null && pConstructor == null && pProperty == null && !Util.HasAncestor<ADeconstructorDecl>(node))
                {
                    errors.Add(new ErrorCollection.Error(node.GetName(), currentSourceFile, LocRM.GetString("ErrorText133")));
                }
                else if (pMethod != null && !InlineMethodCalls[pMethod].Contains(candidate))
                    InlineMethodCalls[pMethod].Add(candidate);
            }

            base.OutANonstaticInvokeExp(node);
        }