public virtual void InACastExp(ACastExp node)
 {
     DefaultIn(node);
 }
 public virtual void OutACastExp(ACastExp node)
 {
     DefaultOut(node);
 }
 public override void CaseACastExp(ACastExp node)
 {
     InACastExp(node);
     if (node.GetExp() != null)
     {
         node.GetExp().Apply(this);
     }
     if (node.GetType() != null)
     {
         node.GetType().Apply(this);
     }
     if (node.GetToken() != null)
     {
         node.GetToken().Apply(this);
     }
     OutACastExp(node);
 }
 public virtual void CaseACastExp(ACastExp node)
 {
     DefaultCase(node);
 }
 public override void CaseACastExp(ACastExp node)
 {
     IsConst = false;
 }
 public override void CaseATempCastExp(ATempCastExp node)
 {
     //The cast type must be a single identifier
     if (node.GetType() is ALvalueExp)
     {
         ALvalueExp lvalueExp = (ALvalueExp)node.GetType();
         if (lvalueExp.GetLvalue() is AAmbiguousNameLvalue)
         {
             AAmbiguousNameLvalue ambiguousLvalue = (AAmbiguousNameLvalue) lvalueExp.GetLvalue();
             if (ambiguousLvalue.GetAmbiguous() is AAName)
             {
                 AAName simpleName = (AAName) ambiguousLvalue.GetAmbiguous();
                 if (simpleName.GetIdentifier().Count == 1)
                 {
                     ACastExp castExp = new ACastExp(node.GetToken(), new ANamedType(simpleName), node.GetExp());
                     node.ReplaceBy(castExp);
                     castExp.Apply(this);
                     return;
                 }
             }
         }
     }
     errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile, LocRM.GetString("ErrorText202")));
 }
        public override void OutAValueReturnStm(AValueReturnStm node)
        {
            AMethodDecl method = Util.GetAncestor<AMethodDecl>(node);
            AConstructorDecl constructor = Util.GetAncestor<AConstructorDecl>(node);
            APropertyDecl property = Util.GetAncestor<APropertyDecl>(node);
            AABlock lastBlock = Util.GetLastAncestor<AABlock>(node);

            //WTF is this? constructors can only return void
            if (constructor == null)
            {
                PType from = data.ExpTypes[node.GetExp()];
                PType to;

                if (property != null)
                {
                    if (lastBlock == property.GetSetter())
                    {
                        errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile,
                                                             LocRM.GetString("ErrorText151") + Util.TypeToString(from) +
                                                             LocRM.GetString("ErrorText159")));
                        return;
                    }
                }

                if (method != null)
                    to = method.GetReturnType();
                else
                    to = property.GetType();
                if (!Assignable(from, to))
                {
                    if (ImplicitAssignable(from, to))
                    {
                        ANamedType namedTo = (ANamedType) to;
                        ACastExp cast = new ACastExp(new TLParen("("),
                                                     new ANamedType(new TIdentifier(((AAName)namedTo.GetName()).AsString()), null),
                                                     node.GetExp());
                        node.SetExp(cast);
                        OutACastExp(cast);
                    }
                    else
                        errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile,
                                                             LocRM.GetString("ErrorText151") + Util.TypeToString(from) +
                                                             LocRM.GetString("ErrorText152") + Util.TypeToString(to)));
                }
            }
            if (property == null)
                CheckAssignedOutParameters(
                    method != null ? method.GetFormals().Cast<AALocalDecl>() : constructor.GetFormals().Cast<AALocalDecl>(),
                    node.GetToken());
            base.OutAValueReturnStm(node);

            /*if (property != null)
            {
                AABlock lastBlock = Util.GetLastAncestor<AABlock>(node);
                if (lastBlock == property.GetGetter())
                    errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile,
                                                         "The getter must return something of type " +
                                                         Util.TypeToString(property.GetType())));
            }
            else*/
        }
        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);
        }
        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);
        }
        public override void OutACastExp(ACastExp node)
        {
            string toType = ((AAName)((ANamedType) node.GetType()).GetName()).AsString();
            string fromType;
            PType fromPType = data.ExpTypes[node.GetExp()];
            AStructDecl toEnum = null;
            AStructDecl fromEnum = null;

            if (data.StructTypeLinks.ContainsKey((ANamedType)node.GetType()))
            {
                AStructDecl str = data.StructTypeLinks[(ANamedType)node.GetType()];
                if (data.Enums.ContainsKey(str))
                    toEnum = str;
            }
            if (fromPType is ANamedType)
            {
                fromType = ((AAName)((ANamedType)fromPType).GetName()).AsString();
                //Namespace ignored
                if (data.StructTypeLinks.ContainsKey((ANamedType) fromPType))
                {
                    AStructDecl str = data.StructTypeLinks[(ANamedType) fromPType];
                    if (data.Enums.ContainsKey(str))
                        fromEnum = str;
                }
            }
            else
            {
                errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile, LocRM.GetString("ErrorText121")));
                throw new ParserException(node.GetToken(), "Invalid cast");
            }

            if (toEnum != null && (fromType == "int" || fromType == "byte"))
            {
                ANamedType type = new ANamedType(new TIdentifier(toEnum.GetName().Text), null);
                data.StructTypeLinks[type] = toEnum;
                data.ExpTypes[node.GetExp()] = type;
                node.ReplaceBy(node.GetExp());
                return;
            }

            if (fromEnum != null && (toType == "int" || toType == "byte"))
            {
                int enumDefinitions = 0;
                foreach (PLocalDecl local in fromEnum.GetLocals())
                {
                    if (local is AALocalDecl)
                        enumDefinitions++;
                }
                string typeName = enumDefinitions > 255 ? "int" : "byte";
                ANamedType type = new ANamedType(new TIdentifier(typeName), null);
                data.ExpTypes[node.GetExp()] = new ANamedType(new TIdentifier(typeName), null);
                node.ReplaceBy(node.GetExp());
                return;
            }

            if (fromEnum != null && toType == "string")
            {
                AMethodDecl targetMethod = data.StructMethods[fromEnum][0];
                ASimpleInvokeExp invokeExp = new ASimpleInvokeExp(new TIdentifier("toString"), new ArrayList(){node.GetExp()});
                data.SimpleMethodLinks[invokeExp] = targetMethod;
                data.ExpTypes[invokeExp] = targetMethod.GetReturnType();
                node.ReplaceBy(invokeExp);
                return;
            }

            ASimpleInvokeExp replacementMethod = null;
            switch (toType)
            {
                case "string":
                    switch (fromType)
                    {
                        case "wave":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("AIWaveToString"), new ArrayList{node.GetExp()});
                            break;
                        case "fixed"://Implicit
                            AFieldLvalue precisionArg = new AFieldLvalue(new TIdentifier("c_fixedPrecisionAny"));
                            ALvalueExp exp = new ALvalueExp(precisionArg);
                            data.FieldLinks[precisionArg] =
                                data.Libraries.Fields.First(field => field.GetName().Text == precisionArg.GetName().Text);
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("FixedToString"), new ArrayList { node.GetExp(), exp});
                            break;
                        case "int"://Implicit
                        case "byte"://Implicit
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("IntToString"), new ArrayList { node.GetExp()});
                            break;
                        case "bool"://Implicit
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("libNtve_gf_ConvertBooleanToString"), new ArrayList { node.GetExp() });
                            break;
                        case "color"://Implicit
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("libNtve_gf_ConvertColorToString"), new ArrayList { node.GetExp() });
                            break;
                    }
                    break;
                case "text":
                    switch (fromType)
                    {
                        case "wave":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("AIWaveToText"), new ArrayList { node.GetExp() });
                            break;
                        case "fixed"://Implicit
                            AFieldLvalue precisionArg = new AFieldLvalue(new TIdentifier("c_fixedPrecisionAny"));
                            ALvalueExp exp = new ALvalueExp(precisionArg);
                            data.FieldLinks[precisionArg] =
                                data.Libraries.Fields.First(field => field.GetName().Text == precisionArg.GetName().Text);
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("FixedToText"), new ArrayList { node.GetExp(), exp });
                            break;
                        case "int"://Implicit
                        case "byte":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("IntToText"), new ArrayList { node.GetExp() });
                            break;
                        case "bool"://Implicit
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("libNtve_gf_ConvertBooleanToText"), new ArrayList { node.GetExp() });
                            break;
                        case "string"://Implicit
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("StringToText"), new ArrayList { node.GetExp() });
                            break;
                    }
                    break;
                case "int":
                    switch (fromType)
                    {
                        case "bool":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("BoolToInt"), new ArrayList {node.GetExp()});
                            break;
                        case "fixed":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("FixedToInt"), new ArrayList { node.GetExp() });
                            break;
                        case "string":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("StringToInt"), new ArrayList { node.GetExp() });
                            break;
                    }
                    break;
                case "fixed":
                    switch (fromType)
                    {
                        case "int"://Already implicit
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("IntToFixed"), new ArrayList { node.GetExp() });
                            break;
                        case "string":
                            replacementMethod = new ASimpleInvokeExp(new TIdentifier("StringToFixed"), new ArrayList { node.GetExp() });
                            break;
                    }
                    break;
                case "bool":
                    switch (fromType)
                    {
                        case "int":
                        case "byte":
                        case "fixed":
                            //Replace by
                            //exp != 0
                            AIntConstExp zero = new AIntConstExp(new TIntegerLiteral("0"));
                            ABinopExp binop = new ABinopExp(node.GetExp(), new ANeBinop(new TNeq("!=")), zero);
                            node.ReplaceBy(binop);

                            binop.Apply(this);
                            return;
                    }
                    break;
            }

            if (replacementMethod == null)
            {
                errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile, LocRM.GetString("ErrorText122") + fromType + LocRM.GetString("ErrorText123") + toType));
                throw new ParserException(node.GetToken(), LocRM.GetString("ErrorText121"));
            }

            data.SimpleMethodLinks[replacementMethod] =
                data.Libraries.Methods.First(method => method.GetName().Text == replacementMethod.GetName().Text);
            data.ExpTypes[replacementMethod] = data.SimpleMethodLinks[replacementMethod].GetReturnType();
            node.ReplaceBy(replacementMethod);
            for (int i = 1; i < replacementMethod.GetArgs().Count; i++)
            {
                ((Node)replacementMethod.GetArgs()[i]).Apply(this);
            }
        }
        public override void OutABinopExp(ABinopExp node)
        {
            PBinop binop = node.GetBinop();
            PExp left = node.GetLeft();
            PType leftType = data.ExpTypes[left];
            string leftTypeString = Util.TypeToString(leftType);
            PExp right = node.GetRight();
            PType rightType = data.ExpTypes[right];
            string rightTypeString = Util.TypeToString(rightType);

            bool wasDefined = false;
            Token token = null;
            while (true)
            {
                if (binop is APlusBinop)
                {
                    token = ((APlusBinop) binop).GetToken();
                    //Check that types are okay for +
                    if (!new[] {"int", "fixed", "string", "text", "byte", "point"}.Any(c => c == leftTypeString))
                    {
                        errors.Add(new ErrorCollection.Error(token, currentSourceFile,
                                                             LocRM.GetString("ErrorText103") + leftTypeString));
                        throw new ParserException(null, null);
                    }
                    if (!new[] {"int", "fixed", "string", "text", "byte", "point"}.Any(c => c == rightTypeString))
                    {
                        errors.Add(new ErrorCollection.Error(token, currentSourceFile,
                                                             LocRM.GetString("ErrorText103") + rightTypeString));
                        throw new ParserException(null, null);
                    }
                    //If you are using string or text, both sides must be same type
                    if ((leftTypeString == "string" && rightTypeString != "string") ||
                        (leftTypeString == "text" && rightTypeString != "text") ||
                        (leftTypeString == "point" && rightTypeString != "point") ||
                        (rightTypeString == "string" && leftTypeString != "string") ||
                        (rightTypeString == "text" && leftTypeString != "text") ||
                        (rightTypeString == "point" && leftTypeString != "point"))
                    {
                        if (ImplicitAssignable(leftType, rightType))
                        {
                            ANamedType namedTo = (ANamedType) rightType;
                            ACastExp cast = new ACastExp(new TLParen("("),
                                                         new ANamedType(
                                                             new TIdentifier(((AAName) namedTo.GetName()).AsString()),
                                                             null), node.GetLeft());
                            node.SetLeft(cast);
                            OutACastExp(cast);
                            leftType = rightType;
                        }
                        else if (ImplicitAssignable(rightType, leftType))
                        {
                            ANamedType namedTo = (ANamedType) leftType;
                            ACastExp cast = new ACastExp(new TLParen("("),
                                                         new ANamedType(
                                                             new TIdentifier(((AAName) namedTo.GetName()).AsString()),
                                                             null), node.GetRight());
                            node.SetRight(cast);
                            OutACastExp(cast);
                            rightType = leftType;
                        }
                        else
                        {
                            //Not valid
                            break;
                        }
                    }
                    wasDefined = true;
                    PType type = leftType;
                    if (rightTypeString == "fixed")
                        type = rightType;
                    data.ExpTypes[node] = type;
                }
                else if (binop is AMinusBinop || binop is ATimesBinop || binop is ADivideBinop || binop is AModuloBinop)
                {
                    token = null;
                    if (binop is AMinusBinop) token = ((AMinusBinop) binop).GetToken();
                    else if (binop is ATimesBinop) token = ((ATimesBinop) binop).GetToken();
                    else if (binop is ADivideBinop) token = ((ADivideBinop) binop).GetToken();
                    else if (binop is AModuloBinop) token = ((AModuloBinop) binop).GetToken();

                    //Check that types are okay for whatever
                    if (!new[] {"int", "fixed", "byte", "point"}.Any(c => c == leftTypeString))
                    {
                        //Not valid
                        break;
                    }
                    if (!new[] {"int", "fixed", "byte", "point"}.Any(c => c == rightTypeString))
                    {
                        //Not valid
                        break;
                    }
                    if ((leftTypeString == "point" || rightTypeString == "point") &&
                        !(leftTypeString == "point" && rightTypeString == "point" && binop is AMinusBinop))
                    {
                        //Not valid
                        break;
                    }
                    wasDefined = true;
                    PType type = leftType;
                    if (rightTypeString == "fixed")
                        type = rightType;
                    if (rightTypeString == "int" && leftTypeString == "byte")
                        type = rightType;
                    data.ExpTypes[node] = type;
                }
                else if (binop is AEqBinop || binop is ANeBinop || binop is ALtBinop || binop is ALeBinop ||
                         binop is AGtBinop || binop is AGeBinop)
                {
                    token = null;
                    if (binop is AEqBinop) token = ((AEqBinop) binop).GetToken();
                    else if (binop is ANeBinop) token = ((ANeBinop) binop).GetToken();
                    else if (binop is ALtBinop) token = ((ALtBinop) binop).GetToken();
                    else if (binop is ALeBinop) token = ((ALeBinop) binop).GetToken();
                    else if (binop is AGtBinop) token = ((AGtBinop) binop).GetToken();
                    else if (binop is AGeBinop) token = ((AGeBinop) binop).GetToken();

                    //Unless types are int and fixed, they must be the same type, or null and a nullable type
                    if (leftTypeString == "void" || rightTypeString == "void" ||
                        !(
                             GalaxyKeywords.NullablePrimitives.words.Any(s => s == leftTypeString) &&
                             rightTypeString == "null" ||
                             leftTypeString == "null" &&
                             GalaxyKeywords.NullablePrimitives.words.Any(s => s == rightTypeString) ||
                             (leftTypeString == "int" || leftTypeString == "fixed" || leftTypeString == "byte") &&
                             (rightTypeString == "int" || rightTypeString == "fixed" || rightTypeString == "byte") ||
                             leftTypeString == rightTypeString && !(IsDynamic(leftType) || IsDynamic(rightType)) ||
                             (binop is AEqBinop || binop is ANeBinop) &&
                             (
                                 leftTypeString == rightTypeString ||
                                 leftTypeString == "null" && IsDynamic(rightType) ||
                                 IsDynamic(leftType) && rightTypeString == "null" ||
                                 Util.TypesEqual(leftType, rightType, data)
                             ) ||
                             leftType is ANamedType && data.DelegateTypeLinks.ContainsKey((ANamedType) leftType) &&
                             (rightTypeString == "null" ||
                              rightType is ANamedType && data.DelegateTypeLinks.ContainsKey((ANamedType) rightType)) ||
                             rightType is ANamedType && data.DelegateTypeLinks.ContainsKey((ANamedType) rightType) &&
                             leftTypeString == "null"
                         )
                        )
                    {

                        //Not valid
                        break;

                    }
                    wasDefined = true;
                    data.ExpTypes[node] = new ANamedType(new TIdentifier("bool"), null);
                }
                else if (binop is AAndBinop || binop is AOrBinop || binop is AXorBinop || binop is ALBitShiftBinop ||
                         binop is ARBitShiftBinop)
                {
                    token = null;
                    if (binop is AAndBinop) token = ((AAndBinop) binop).GetToken();
                    else if (binop is AOrBinop) token = ((AOrBinop) binop).GetToken();
                    else if (binop is AXorBinop) token = ((AXorBinop) binop).GetToken();
                    else if (binop is ALBitShiftBinop) token = ((ALBitShiftBinop) binop).GetToken();
                    else if (binop is ARBitShiftBinop) token = ((ARBitShiftBinop) binop).GetToken();

                    if (
                        !((leftTypeString == "int" || leftTypeString == "byte") &&
                          (rightTypeString == "int" || rightTypeString == "byte") &&
                          (binop is ALBitShiftBinop || binop is ARBitShiftBinop ||
                           leftTypeString == rightTypeString)))
                    {
                        if (rightTypeString == "int" && leftTypeString == "byte" && left is AIntConstExp)
                        {
                            data.ExpTypes[left] =
                                leftType = new ANamedType(new TIdentifier("int"), null);
                            leftTypeString = "int";
                        }
                        else if (leftTypeString == "int" && rightTypeString == "byte" && right is AIntConstExp)
                        {
                            data.ExpTypes[right] =
                                rightType = new ANamedType(new TIdentifier("int"), null);
                            rightTypeString = "int";
                        }
                        else
                        {
                            //Not valid
                            break;
                        }
                    }
                    wasDefined = true;
                    data.ExpTypes[node] = leftType;
                    if (rightTypeString == "int")
                        data.ExpTypes[node] = rightType;
                }
                else if (binop is ALazyAndBinop || binop is ALazyOrBinop)
                {
                    token = null;
                    if (binop is ALazyAndBinop) token = ((ALazyAndBinop) binop).GetToken();
                    else if (binop is ALazyOrBinop) token = ((ALazyOrBinop) binop).GetToken();

                    if (leftTypeString != "bool" || rightTypeString != "bool")
                    {

                        errors.Add(new ErrorCollection.Error(token, currentSourceFile,
                                                             token.Text + LocRM.GetString("ErrorText104") +
                                                             token.Text +
                                                             " bool). Got (" +
                                                             leftTypeString + " " + token.Text + " " +
                                                             rightTypeString + ")"));
                        throw new ParserException(null, null);
                    }
                    wasDefined = true;
                    data.ExpTypes[node] = leftType;
                }
                else
                    throw new Exception("Unexpected binop (This should never happen)");
                break;
            }

            List<AMethodDecl> possibleOperators = new List<AMethodDecl>();
            List<IList> visibleDecls = Util.GetVisibleDecls(node, true);
            List<string> currentNamespace = Util.GetFullNamespace(node);
            AASourceFile currentFile = Util.GetAncestor<AASourceFile>(node);
            foreach (IList declList in visibleDecls)
            {
                bool sameNS = false;
                bool sameFile = false;
                if (declList.Count > 0)
                {
                    sameNS = Util.NamespacesEquals(currentNamespace, Util.GetFullNamespace((PDecl) declList[0]));
                    sameFile = currentFile == Util.GetAncestor<AASourceFile>((PDecl) declList[0]);
                }
                foreach (PDecl decl in declList)
                {
                    if (decl is AMethodDecl)
                    {
                        AMethodDecl method = (AMethodDecl) decl;
                        if (method.GetName().Text == token.Text)
                        {
                            if (method.GetVisibilityModifier() is APrivateVisibilityModifier && !sameNS)
                                continue;
                            if (method.GetStatic() != null && !sameFile)
                                continue;
                            //Check that parameters are assignable
                            bool add = true;
                            bool matchImplicit = false;
                            List<PType> argTypes = new List<PType>(){leftType, rightType};
                            for (int i = 0; i < argTypes.Count; i++)
                            {
                                PType argType = argTypes[i];
                                AALocalDecl formal = (AALocalDecl)method.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))
                                {
                                    add = false;
                                    if (formal.GetOut() == null && formal.GetRef() == null &&
                                        ImplicitAssignable(argType, formalType))
                                    {
                                        matchImplicit = true;
                                    }
                                    else
                                    {
                                        matchImplicit = false;
                                        break;
                                    }
                                }
                            }
                            if (!add && !matchImplicit)
                                continue;
                            if (add)
                                possibleOperators.Add(method);
                        }
                    }
                }
            }

            if (possibleOperators.Count == 0 && !wasDefined)
            {
                errors.Add(new ErrorCollection.Error(token, LocRM.GetString("ErrorText105") + leftTypeString + " " + token.Text + " " + rightTypeString + ")"));
                throw new ParserException(token, "TypeChecking.OutABinopExp");
            }

            if (possibleOperators.Count + (wasDefined ? 1 : 0) > 1)
            {
                List<ErrorCollection.Error> subErrors = new List<ErrorCollection.Error>();
                foreach (AMethodDecl method in possibleOperators)
                {
                    subErrors.Add(new ErrorCollection.Error(method.GetName(), LocRM.GetString("ErrorText106")));
                }
                if (wasDefined)
                    subErrors.Add(new ErrorCollection.Error(token, LocRM.GetString("ErrorText107") + token.Text));
                errors.Add(new ErrorCollection.Error(token, LocRM.GetString("ErrorText108") + leftTypeString + " " + token.Text + " " + rightTypeString + LocRM.GetString("ErrorText109"), false, subErrors.ToArray()));
                throw new ParserException(token, "TypeChecking.OutABinopExp");
            }

            if (wasDefined)
                return;

            AMethodDecl op = possibleOperators[0];
            ASimpleInvokeExp replacer = new ASimpleInvokeExp(new TIdentifier(op.GetName().Text), new ArrayList(){node.GetLeft(), node.GetRight()});
            node.ReplaceBy(replacer);
            data.SimpleMethodLinks[replacer] = op;
            data.ExpTypes[replacer] = op.GetReturnType();

            //base.OutABinopExp(node);
        }
        public override void OutAAssignmentExp(AAssignmentExp node)
        {
            PType from = data.ExpTypes[node.GetExp()];
            PType to = data.LvalueTypes[node.GetLvalue()];
            if (!Assignable(from, to))
            {
                if (ImplicitAssignable(from, to))
                {
                    ANamedType namedTo = (ANamedType) to;
                    ACastExp cast = new ACastExp(new TLParen("("), new ANamedType(new TIdentifier(((AAName)namedTo.GetName()).AsString()), null), node.GetExp());
                    node.SetExp(cast);
                    OutACastExp(cast);
                    //to = from;
                }
                else
                    errors.Add(new ErrorCollection.Error(node.GetToken(), currentSourceFile,
                                                         LocRM.GetString("ErrorText151") + Util.TypeToString(from) +
                                                         LocRM.GetString("ErrorText152") + Util.TypeToString(to)));
            }
            data.ExpTypes[node] = to;

            if (node.GetLvalue() is ALocalLvalue)
            {
                assignedToOutParams.Add(data.LocalLinks[(ALocalLvalue) node.GetLvalue()]);
            }

            if (node.GetLvalue() is AStructLvalue && data.StructFieldLinks.ContainsKey((AStructLvalue) node.GetLvalue()))
            {
                AALocalDecl decl = data.StructFieldLinks[(AStructLvalue) node.GetLvalue()];
                if (decl.GetConst() != null)
                    errors.Add(new ErrorCollection.Error(node.GetToken(), LocRM.GetString("ErrorText153")));
            }

            if (node.GetLvalue() is AStructFieldLvalue && data.StructMethodFieldLinks.ContainsKey((AStructFieldLvalue)node.GetLvalue()))
            {
                AALocalDecl decl = data.StructMethodFieldLinks[(AStructFieldLvalue)node.GetLvalue()];
                if (decl.GetConst() != null)
                    errors.Add(new ErrorCollection.Error(node.GetToken(), LocRM.GetString("ErrorText153")));
            }

            base.OutAAssignmentExp(node);
        }
        public override void OutAALocalDecl(AALocalDecl node)
        {
            if (node.GetInit() != null)
            {
                PType from = data.ExpTypes[node.GetInit()];
                PType to = node.GetType();
                if (!Assignable(from, to))
                {
                    if (ImplicitAssignable(from, to))
                    {
                        ANamedType namedTo = (ANamedType)to;
                        ACastExp cast = new ACastExp(new TLParen("("), new ANamedType(new TIdentifier(((AAName)namedTo.GetName()).AsString()), null), node.GetInit());
                        node.SetInit(cast);
                        OutACastExp(cast);
                        to = from;
                    }
                    else
                        errors.Add(new ErrorCollection.Error(node.GetName(), currentSourceFile,
                                                             LocRM.GetString("ErrorText151") + Util.TypeToString(from) +
                                                             LocRM.GetString("ErrorText152") + Util.TypeToString(to)));
                }
            }

            //If the return type or the type of any formals is a private struct, and the method is a public context, give an error
            if (node.Parent() is AStructDecl)
            {
                AStructDecl pStruct = Util.GetAncestor<AStructDecl>(node);
                //Is public context
                if ( pStruct.GetVisibilityModifier() is APublicVisibilityModifier && !(node.GetVisibilityModifier() is APrivateVisibilityModifier))
                {
                    PType type = node.GetType();
                    int i = 0;
                    FindPrivateTypes finder = new FindPrivateTypes(data);
                    type.Apply(finder);

                    if (finder.PrivateTypes.Count > 0)
                    {
                        List<ErrorCollection.Error> subErrors = new List<ErrorCollection.Error>();
                        List<PDecl> usedDecls = new List<PDecl>();
                        foreach (ANamedType namedType in finder.PrivateTypes)
                        {
                            if (data.StructTypeLinks.ContainsKey(namedType))
                            {
                                AStructDecl decl = data.StructTypeLinks[namedType];
                                if (usedDecls.Contains(decl))
                                    continue;
                                usedDecls.Add(decl);
                                subErrors.Add(new ErrorCollection.Error(decl.GetName(), LocRM.GetString("ErrorText64")));
                            }
                            else if (data.DelegateTypeLinks.ContainsKey(namedType))
                            {
                                AMethodDecl decl = data.DelegateTypeLinks[namedType];
                                if (usedDecls.Contains(decl))
                                    continue;
                                usedDecls.Add(decl);
                                subErrors.Add(new ErrorCollection.Error(decl.GetName(), LocRM.GetString("ErrorText154")));
                            }
                        }

                        errors.Add(new ErrorCollection.Error(node.GetName(), LocRM.GetString("ErrorText155"), false, subErrors.ToArray()));
                    }
                }
            }
            base.OutAALocalDecl(node);
        }
        public override void CaseATempCastExp(ATempCastExp node)
        {
            //The cast type must be a single identifier
            if (node.GetType() is ALvalueExp)
            {
                ALvalueExp lvalueExp = (ALvalueExp)node.GetType();
                if (lvalueExp.GetLvalue() is AAmbiguousNameLvalue)
                {
                    AAmbiguousNameLvalue ambiguousLvalue = (AAmbiguousNameLvalue)lvalueExp.GetLvalue();
                    if (ambiguousLvalue.GetAmbiguous() is AAName)
                    {
                        AAName simpleName = (AAName)ambiguousLvalue.GetAmbiguous();
                        if (simpleName.GetIdentifier().Count == 1)
                        {
                            ACastExp castExp = new ACastExp(node.GetToken(), new ANamedType(simpleName), node.GetExp());
                            node.ReplaceBy(castExp);
                            castExp.Apply(this);
                            return;
                        }

                    }
                }
            }
            PExp exp = node.GetExp();
            node.ReplaceBy(exp);
            exp.Apply(this);
        }