public IHolderCil Visit(CondExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            var condValue = Visit(parserRule.ifExpr, cilTree, contextCil);

            condValue = GetValue(condValue, cilTree, CilAst.Bool);
            var labelElse = cilTree.CreateLabel("else");

            cilTree.ThreeDirInses.Add(new IfGoto(condValue, labelElse));
            //genero el codigo de elseValue
            var elseValue = Visit(parserRule.elseExpr, cilTree, contextCil);
            var labelEnd  = cilTree.CreateLabel("end");

            //El resultado lo almaceno en value
            cilTree.ThreeDirInses.Add(new AssigCil(value, elseValue));
            //Voy pa la etiquta end
            cilTree.ThreeDirInses.Add(new GotoCil(labelEnd));
            //Pongo la etiqueta de else
            cilTree.ThreeDirInses.Add(new Label(labelElse));
            //genero el codigo de thenValue
            var thenValue = Visit(parserRule.thenExpr, cilTree, contextCil);

            //Asigno el valor a esle value
            cilTree.ThreeDirInses.Add(new AssigCil(value, thenValue));
            //Pongo la etiqueta end
            cilTree.ThreeDirInses.Add(new Label(labelEnd));
            //retorno el valor
            return(value);
        }
        public void VisitString(DispatchContext parserRule, IFunctionCil cilTree, List <IHolderCil> Params)
        {
            var value  = GetValue(Params[0], cilTree, CilAst.String);
            var Length = new LocalCil($"_length{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(Length);

            var isParam1NotInRange = new LocalCil($"_isParam1InRange{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(isParam1NotInRange);

            cilTree.ThreeDirInses.Add(new LenghtCil(Length, value));
            //tomamos los valores de los argumentos
            var param1 = GetValue(Params[1], cilTree, CilAst.Int);
            var param2 = GetValue(Params[2], cilTree, CilAst.Int);

            //
            cilTree.ThreeDirInses.Add(new MinorCil(isParam1NotInRange, param1, Length));
            Visit_Runtime_Error_whit_Cond(isParam1NotInRange, cilTree, $"\"({parserRule.id.Line},{parserRule.id.Column+1}) - Rutime Error : Substring out of range\"");
            var lastIndex = new LocalCil($"_lastIndex{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(lastIndex);
            cilTree.ThreeDirInses.Add(new SumCil(lastIndex, param1, param2));
            var isParam2NotInRange = new LocalCil($"_isParam2InRange{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(isParam2NotInRange);
            cilTree.ThreeDirInses.Add(new Minor_EqualCil(isParam2NotInRange, lastIndex, Length));
            Visit_Runtime_Error_whit_Cond(isParam2NotInRange, cilTree, $"\"({parserRule.id.Line},{parserRule.id.Column + 1}) - Rutime Error : Substring out of range\"");
        }
        public virtual IHolderCil Visit(SelfDispatchContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var Params = new List <IHolderCil>();

            foreach (var expr in parserRule._expresions)
            {
                //genera el codigo de cada parametro que le paso a los metodos
                var param = Visit(expr, cilTree, contextCil);
                Params.Add(param);
            }
            //Averiguo el tipo dinamico de self es decir( el de la clase que esta usando la funcion en ese momento)
            var varType = new LocalCil($"_Type{cilTree.ThreeDirInses.Count}");

            cilTree.LocalCils.Add(varType);
            var self = cilTree.self;

            cilTree.ThreeDirInses.Add(new TypeOf(varType, self));
            //cada parametro los anado al metodo puede que tenga sentido pasarlos al revez
            cilTree.ThreeDirInses.Add(new ArgExprCil(self));
            foreach (var param in Params)
            {
                cilTree.ThreeDirInses.Add(new ArgExprCil(param));
            }
            //ITypeCil typeCil;
            ////resuelve el metodo en cil de ese tipo estatico
            var functionCil = typeCil.GetFunctionCilsByCoolName(parserRule.id.Text);
            ////nueva variable donde se almacena el valor que retorna el metodo
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            cilTree.ThreeDirInses.Add(new VCallCil(value, varType, functionCil));
            return(value);
        }
        public IHolderCil Visit(CaseExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            var expr0 = Visit(parserRule.expresion, cilTree, contextCil);
            //is void
            var TypeValue   = new LocalCil($"_TypeValue{cilTree.LocalCils.Count}");
            var not_is_void = new LocalCil($"not_is_void{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(TypeValue);
            cilTree.LocalCils.Add(not_is_void);
            cilTree.ThreeDirInses.Add(new TypeOf(TypeValue, expr0));
            cilTree.ThreeDirInses.Add(new NotEqualCil(not_is_void, TypeValue, CilAst.GetTypeCilByName("void")));

            //lanzamos el error

            Visit_Runtime_Error_whit_Cond(not_is_void, cilTree, $"\"({parserRule.Start.Line},{parserRule.Start.Column + 1}) -  Rutime Error: A case on void\"");

            //ejecucion del case
            var closestAncestor = new LocalCil($"_closestAncestor{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(closestAncestor);

            //Inicializo el valor de numberType en 0 y closestAncestor con object
            var isNotConform = new LocalCil($"_isNotConform{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(isNotConform);

            var branches = parserRule._branches.Concat(new List <BranchContext>()
            {
                parserRule.firstBranch
            }).OrderBy(t => - (CilAst.GetTypeCilByName(t.typeText).IndexOfPrecedence)).ToArray();
            //El tipo de la primera rama
            var End = cilTree.CreateLabel("End_");

            for (int i = 0; i < branches.Length; i++)
            {
                var branch    = branches[i];
                var nextLabel = cilTree.CreateLabel("Case_");
                //tipo de la rama
                var typeBranch = CilAst.GetTypeCilByName(branch.typeText, typeCil);
                cilTree.ThreeDirInses.Add(new IsNotConformCil(isNotConform, TypeValue, typeBranch));
                cilTree.ThreeDirInses.Add(new IfGoto(isNotConform, nextLabel));
                var valueBranch = new LocalCil(branch.idText);//preguntarle as zahuis
                cilTree.LocalCils.Add(valueBranch);
                cilTree.ThreeDirInses.Add(new AssigCil(valueBranch, expr0));
                var newContextCil = contextCil.CreateAChild();
                newContextCil.Define(branch.idText);
                var valueExpr = Visit(branch.expression, cilTree, newContextCil);
                cilTree.ThreeDirInses.Add(new AssigCil(value, valueExpr));
                cilTree.ThreeDirInses.Add(new GotoCil(End));
                cilTree.ThreeDirInses.Add(new Label(nextLabel));
            }
            Visit_Runtime_Error(cilTree, $"\"linea {parserRule.Start.Line} y columna {parserRule.Start.Column + 1} Execution of a case statement without a matching branch\"");
            cilTree.ThreeDirInses.Add(new Label(End));


            return(value);
        }
        public void Visit(DeclarationContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            contextCil.Define(parserRule.idText);
            var Id = new LocalCil(contextCil.variables[parserRule.idText].Name);

            cilTree.LocalCils.Add(Id);
            IHolderCil value;

            if (parserRule.expression != null)
            {
                value = Visit(parserRule.expression, cilTree, contextCil);
            }
            else if (parserRule.type.Text == "Int")
            {
                value = CreateABasicType(cilTree, CilAst.Int);
            }
            else if (parserRule.type.Text == "String")
            {
                value = CreateABasicType(cilTree, CilAst.String);
            }
            else if (parserRule.type.Text == "Bool")
            {
                value = CreateABasicType(cilTree, CilAst.Bool);
            }
            else
            {
                value = Visit_void(cilTree);
            }
            cilTree.ThreeDirInses.Add(new AssigCil(Id, value));
        }
        public IHolderCil Visit_void(IFunctionCil cilTree)
        {
            var valueV = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(valueV);
            cilTree.ThreeDirInses.Add(new CallCil(valueV, CilAst.void_init));
            return(valueV);
        }
        public IVarCil GetValue(IHolderCil obj, IFunctionCil cilTree, ITypeCil typeCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            cilTree.ThreeDirInses.Add(new GetAttrCil(value, obj, typeCil.GetAttributeCilsByCoolName("x")));
            return(value);
        }
        public IVarCil CreateABasicType(IFunctionCil cilTree, ITypeCil typeCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            cilTree.ThreeDirInses.Add(new Allocate(value, typeCil));
            return(value);
        }
        public IHolderCil Visit(NegExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            var valueExpr = Visit(parserRule.expresion, cilTree, contextCil);

            valueExpr = GetValue(valueExpr, cilTree, CilAst.Int);
            cilTree.ThreeDirInses.Add(new NegCil(value, valueExpr));
            return(CreateABasicTypeWhitVal(cilTree, CilAst.Int, value));
        }
        public IHolderCil Visit(NotExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var _valueNum = new LocalCil($"_valueNum{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(_valueNum);
            var valueExpr = Visit(parserRule.expresion, cilTree, contextCil);
            var BoolCil   = CilAst.Bool;

            valueExpr = GetValue(valueExpr, cilTree, BoolCil);
            cilTree.ThreeDirInses.Add(new RestCil(_valueNum, new HolderCil("1"), valueExpr));
            return(CreateABasicTypeWhitVal(cilTree, BoolCil, _valueNum));
        }
        public IHolderCil Visit(StringExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            var stringCool    = parserRule.STRING().GetText();
            var varDataString = new VarCil($"s{CilAst.dataStringCils.Count}");

            CilAst.dataStringCils.Add(new DataStringCil(varDataString, new StringCil(stringCool)));
            cilTree.ThreeDirInses.Add(new LoadCil(value, varDataString));
            return(CreateABasicTypeWhitVal(cilTree, CilAst.String, value));
        }
        public void Visit_Runtime_Error(IFunctionCil cilTree, string sms)
        {
            var varStr = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(varStr);
            var varDataString = new VarCil($"s{CilAst.dataStringCils.Count}");

            CilAst.dataStringCils.Add(new DataStringCil(varDataString, new StringCil(sms)));
            cilTree.ThreeDirInses.Add(new LoadCil(varStr, varDataString));
            cilTree.ThreeDirInses.Add(new Out_strCil(varStr));
            cilTree.ThreeDirInses.Add(new Halt());
        }
        public IHolderCil Visit(IsvoidExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            var valueExpr = Visit(parserRule.expresion, cilTree, contextCil);
            var TypeValue = new LocalCil($"_TypeValue{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(TypeValue);
            cilTree.ThreeDirInses.Add(new TypeOf(TypeValue, valueExpr));
            cilTree.ThreeDirInses.Add(new EqualCil(value, TypeValue, CilAst.GetTypeCilByName("void")));
            return(CreateABasicTypeWhitVal(cilTree, CilAst.Bool, value));
        }
        public IHolderCil Visit(IdExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            //Si no es una variable declarada dentro del metodo entonces es un atributo de la clase (self)

            if (!contextCil.variables.ContainsKey(parserRule.id.Text))
            {
                var value = new LocalCil($"_value{cilTree.LocalCils.Count}");
                cilTree.LocalCils.Add(value);
                cilTree.ThreeDirInses.Add(new GetAttrCil(value, cilTree.self, typeCil.GetAttributeCilsByCoolName(parserRule.id.Text)));
                return(value);
            }

            return(contextCil.variables[parserRule.id.Text]);
        }
        public IHolderCil Visit(CompaExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            var valueLeft  = Visit(parserRule.left, cilTree, contextCil);
            var valueRight = Visit(parserRule.right, cilTree, contextCil);

            if (parserRule.left.computedType == GlobalContext.Int)
            {
                valueLeft  = GetValue(valueLeft, cilTree, CilAst.Int);
                valueRight = GetValue(valueRight, cilTree, CilAst.Int);
            }
            else if (parserRule.left.computedType == GlobalContext.Bool)
            {
                valueLeft  = GetValue(valueLeft, cilTree, CilAst.Bool);
                valueRight = GetValue(valueRight, cilTree, CilAst.Bool);
            }
            else if (parserRule.left.computedType == GlobalContext.String)
            {
                valueLeft  = GetValue(valueLeft, cilTree, CilAst.String);
                valueRight = GetValue(valueRight, cilTree, CilAst.String);
            }
            switch (parserRule.op.Text)
            {
            case "<":
                cilTree.ThreeDirInses.Add(new MinorCil(value, valueLeft, valueRight));
                break;

            case "<=":
                cilTree.ThreeDirInses.Add(new Minor_EqualCil(value, valueLeft, valueRight));
                break;

            case "=":
                if (parserRule.left.computedType == GlobalContext.String)
                {
                    cilTree.ThreeDirInses.Add(new EqualStringCil(value, valueLeft, valueRight));
                }
                else
                {
                    cilTree.ThreeDirInses.Add(new EqualCil(value, valueLeft, valueRight));
                }
                break;

            default:
                break;
            }
            return(CreateABasicTypeWhitVal(cilTree, CilAst.Bool, value));
        }
        public void Visit_Runtime_Error_whit_Cond(IHolderCil valueCond, IFunctionCil cilTree, string sms)
        {
            var Continue = cilTree.CreateLabel($"Continue_");

            cilTree.ThreeDirInses.Add(new IfGoto(valueCond, Continue));
            var varStr = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(varStr);
            var varDataString = new VarCil($"s{CilAst.dataStringCils.Count}");

            CilAst.dataStringCils.Add(new DataStringCil(varDataString, new StringCil(sms)));
            cilTree.ThreeDirInses.Add(new LoadCil(varStr, varDataString));
            cilTree.ThreeDirInses.Add(new Out_strCil(varStr));
            cilTree.ThreeDirInses.Add(new Halt());
            cilTree.ThreeDirInses.Add(new Label(Continue));
        }
        public IHolderCil Visit(NewTypeExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);
            if (parserRule.type.Text == "SELF_TYPE")
            {
                var varType = new LocalCil($"_Type{cilTree.ThreeDirInses.Count}");
                cilTree.LocalCils.Add(varType);
                cilTree.ThreeDirInses.Add(new TypeOf(varType, new ValuelCil("self")));
                cilTree.ThreeDirInses.Add(new VCallCil(value, varType, new ValuelCil("Init")));
            }
            else
            {
                var varType = CilAst.GetTypeCilByName(parserRule.type.Text, typeCil);
                cilTree.ThreeDirInses.Add(new CallCil(value, varType.Init.Function));
            }
            return(value);
        }
        public IHolderCil Visit(AssignExprContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var valueExpr = Visit(parserRule.expresion, cilTree, contextCil);

            if (!contextCil.variables.ContainsKey(parserRule.id.Text))
            {
                var value = new LocalCil($"_value{cilTree.LocalCils.Count}");
                cilTree.LocalCils.Add(value);
                cilTree.ThreeDirInses.Add(new SetAttrCil(cilTree.self, typeCil.GetAttributeCilsByCoolName(parserRule.id.Text), valueExpr));
                cilTree.ThreeDirInses.Add(new GetAttrCil(value, cilTree.self, typeCil.GetAttributeCilsByCoolName(parserRule.id.Text)));
                return(value);
            }
            else
            {
                var value = contextCil.variables[parserRule.id.Text];
                cilTree.ThreeDirInses.Add(new AssigCil(value, valueExpr));
                return(value);
            }
        }
        public IHolderCil Visit(ArithContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var valueNum = new LocalCil($"_valueNum{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(valueNum);
            var valueLeft  = Visit(parserRule.left, cilTree, contextCil);
            var valueRight = Visit(parserRule.right, cilTree, contextCil);
            var valLeft    = GetValue(valueLeft, cilTree, CilAst.Int);
            var valRigth   = GetValue(valueRight, cilTree, CilAst.Int);

            switch (parserRule.op.Text)
            {
            case "/":
                var isZero = new LocalCil($"_isZero{cilTree.LocalCils.Count}");
                cilTree.LocalCils.Add(isZero);
                cilTree.ThreeDirInses.Add(new NotEqualCil(isZero, valRigth, new HolderCil("0")));
                Visit_Runtime_Error_whit_Cond(isZero, cilTree, $"\"({parserRule.Start.Line},{parserRule.Start.Column+1}) -  Rutime Error: Division by zero\"");
                cilTree.ThreeDirInses.Add(new DivCil(valueNum, valLeft, valRigth));
                break;

            case "*":
                cilTree.ThreeDirInses.Add(new MultCil(valueNum, valLeft, valRigth));
                break;

            case "+":
                cilTree.ThreeDirInses.Add(new SumCil(valueNum, valLeft, valRigth));
                break;

            case "-":
                cilTree.ThreeDirInses.Add(new RestCil(valueNum, valLeft, valRigth));
                break;

            default:
                break;
            }

            return(CreateABasicTypeWhitVal(cilTree, CilAst.Int, valueNum));
        }
        public IHolderCil Visit(IFunctionCil cilTree)
        {
            switch (cilTree.Name)
            {
            case "String_lenght":
                var value = new LocalCil("value");
                cilTree.LocalCils.Add(value);
                cilTree.ThreeDirInses.Add(new LenghtCil(value, GetValue(cilTree.self, cilTree, CilAst.GetTypeCilByName("String"))));
                return(CreateABasicTypeWhitVal(cilTree, CilAst.GetTypeCilByName("Int"), value));

            case "String_concat":
                value = new LocalCil("value");
                cilTree.LocalCils.Add(value);
                cilTree.ThreeDirInses.Add(new ConcatCil(value, GetValue(cilTree.self, cilTree, CilAst.GetTypeCilByName("String")), GetValue(cilTree.ArgCils.SingleOrDefault(t => t.Name != "self"), cilTree, CilAst.GetTypeCilByName("String"))));
                return(CreateABasicTypeWhitVal(cilTree, CilAst.GetTypeCilByName("String"), value));

            case "String_substr":
                value = new LocalCil("value");
                cilTree.LocalCils.Add(value);
                var self = GetValue(cilTree.self, cilTree, CilAst.GetTypeCilByName("String"));
                //tomamos los valores de los argumentos
                var param1 = GetValue(cilTree.ArgCils.ElementAt(1), cilTree, CilAst.Int);
                var param2 = GetValue(cilTree.ArgCils.ElementAt(2), cilTree, CilAst.Int);
                cilTree.ThreeDirInses.Add(new SubStringCil(value, self, param1, param2));
                return(CreateABasicTypeWhitVal(cilTree, CilAst.String, value));

            case "Object_abort":
                cilTree.ThreeDirInses.Add(new Halt());
                return(null);

            case "Object_type_name":
                var x_type_name = new LocalCil("x");
                cilTree.LocalCils.Add(x_type_name);
                cilTree.ThreeDirInses.Add(new Type_Name(x_type_name, cilTree.self));
                return(CreateABasicTypeWhitVal(cilTree, CilAst.GetTypeCilByName("String"), x_type_name));

            case "Object_copy":
                var x_Object_copy = new LocalCil("x");
                cilTree.LocalCils.Add(x_Object_copy);
                cilTree.ThreeDirInses.Add(new Copy(x_Object_copy, cilTree.self));
                return(x_Object_copy);

            case "IO_out_string":
                cilTree.ThreeDirInses.Add(new Out_strCil(GetValue(cilTree.ArgCils.SingleOrDefault(t => t.Name != "self"), cilTree, CilAst.GetTypeCilByName("String"))));
                return(cilTree.self);

            case "IO_out_int":
                cilTree.ThreeDirInses.Add(new Out_intCil(GetValue(cilTree.ArgCils.SingleOrDefault(t => t.Name != "self"), cilTree, CilAst.GetTypeCilByName("Int"))));
                return(cilTree.self);

            case "IO_in_string":
                var x_in_string = new LocalCil("x");
                cilTree.LocalCils.Add(x_in_string);
                cilTree.ThreeDirInses.Add(new In_strCil(x_in_string));
                return(CreateABasicTypeWhitVal(cilTree, CilAst.GetTypeCilByName("String"), x_in_string));

            case "IO_in_int":
                var x_in_int = new LocalCil("x");
                cilTree.LocalCils.Add(x_in_int);
                cilTree.ThreeDirInses.Add(new In_intCil(x_in_int));
                return(CreateABasicTypeWhitVal(cilTree, CilAst.GetTypeCilByName("Int"), x_in_int));

            default:
                return(null);
            }
        }
        public void Visit()
        {
            IFunctionCil init  = typeCil.Init.Function;
            var          value = new LocalCil("self");

            init.LocalCils.Add(value);
            var typeCilNew = CilAst.GetTypeCilByName(typeCil.Name, typeCil);

            init.ThreeDirInses.Add(new Allocate(value, typeCilNew));
            var typeCool   = GlobalContext.GetType(typeCil.Name);
            var contextCil = new ContextCil();

            contextCil.Define("self");
            foreach (var typeTemp in typeCool.Hierachty)
            {
                foreach (var attributeTemp in typeTemp.Attributes)
                {
                    //Inicializamos los atributos
                    if (attributeTemp.initializacion != null)
                    {
                        var valueAttribute = Visit(attributeTemp.initializacion, init, contextCil);
                        //No siempre los tipos de Cil estan para eso eso habria que hacer 2 pasadas al AST
                        init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), valueAttribute));
                    }
                    else
                    {
                        if (typeTemp == GlobalContext.Int || typeTemp == GlobalContext.Bool)
                        {
                            init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), new ValuelCil("0")));
                        }
                        else if (typeTemp == GlobalContext.String)
                        {
                            var valueS = new LocalCil($"_value{init.LocalCils.Count}");
                            init.LocalCils.Add(valueS);

                            var stringCool    = "";
                            var varDataString = new VarCil($"s{CilAst.dataStringCils.Count}");
                            CilAst.dataStringCils.Add(new DataStringCil(varDataString, new StringCil(stringCool)));
                            init.ThreeDirInses.Add(new LoadCil(valueS, varDataString));
                            init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), valueS));
                        }
                        else if (attributeTemp.Type == GlobalContext.String)
                        {
                            init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), CreateABasicType(init, CilAst.String)));
                        }
                        else if (attributeTemp.Type == GlobalContext.Int)
                        {
                            init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), CreateABasicType(init, CilAst.Int)));
                        }
                        else if (attributeTemp.Type == GlobalContext.Bool)
                        {
                            init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), CreateABasicType(init, CilAst.Bool)));
                        }
                        else
                        {
                            init.ThreeDirInses.Add(new SetAttrCil(value, typeCilNew.GetAttributeCilsByCoolName(attributeTemp.ID), Visit_void(init)));
                        }
                    }
                }
            }
            init.ThreeDirInses.Add(new ReturnCil(value));
        }
        public virtual IHolderCil Visit(DispatchContext parserRule, IFunctionCil cilTree, IContextCil contextCil)
        {
            var Params = new List <IHolderCil>();
            var expr0  = Visit(parserRule.expresion, cilTree, contextCil);

            foreach (var expr in parserRule._expresions)
            {
                //genera el codigo de cada parametro que le paso a los metodos
                var param = Visit(expr, cilTree, contextCil);
                Params.Add(param);
            }
            //Averiguo el tipo dinamico de self es decir( el de la clase que esta usando la funcion en ese momento)
            var varType = new LocalCil($"_Type{cilTree.ThreeDirInses.Count}");

            cilTree.LocalCils.Add(varType);
            cilTree.ThreeDirInses.Add(new TypeOf(varType, expr0));
            //Verifico si el tipo del objeto que le voy hacer el dispatch es void
            if (parserRule.id.Text == "substr")
            {
                VisitString(parserRule, cilTree, new List <IHolderCil>()
                {
                    expr0
                }.Concat(Params).ToList());
            }
            if (cilTree.Name != "entry")
            {
                var isVoid = new LocalCil($"_isVoid{cilTree.ThreeDirInses.Count}");
                cilTree.LocalCils.Add(isVoid);
                cilTree.ThreeDirInses.Add(new NotEqualCil(isVoid, varType, CilAst.GetTypeCilByName("void")));
                Visit_Runtime_Error_whit_Cond(isVoid, cilTree, $"\"({parserRule.id.Line},{parserRule.id.Column+1}) -  Rutime Error: A dispatch on void\"");
                cilTree.ThreeDirInses.Add(new ArgExprCil(expr0));
            }
            //cada parametro los anado al metodo puede que tenga sentido pasarlos al revez


            foreach (var param in Params)
            {
                cilTree.ThreeDirInses.Add(new ArgExprCil(param));
            }
            ////nueva variable donde se almacena el valor que retorna el metodo
            var value = new LocalCil($"_value{cilTree.LocalCils.Count}");

            cilTree.LocalCils.Add(value);

            if (parserRule.type == null)
            {
                //Se resuleve el tipo de la expr0 a partir de su tipo estatico calculado por el checkeo semantico
                var typeExpr0 = CilAst.GetTypeCilByName(parserRule.expresion.computedType.Name, typeCil);
                ////resuelve el metodo en cil de ese tipo estatico
                var functionCil = typeExpr0.GetFunctionCilsByCoolName(parserRule.id.Text);
                //como ningun tipo puede redefinir a string entonces llamo directamente al metodo
                if (parserRule.expresion.computedType == GlobalContext.String)
                {
                    cilTree.ThreeDirInses.Add(new CallCil(value, functionCil.Function));
                }
                else
                {
                    cilTree.ThreeDirInses.Add(new VCallCil(value, varType, functionCil));
                }
            }
            else
            {
                //Se resuelve el tipo de la type
                var typeT       = CilAst.GetTypeCilByName(parserRule.type.Text, typeCil);
                var functionCil = typeT.GetFunctionCilsByCoolName(parserRule.id.Text).Function;
                cilTree.ThreeDirInses.Add(new CallCil(value, functionCil));
            }
            return(value);
        }