public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     InitialExp.CheckSemantic(scope.Parent, errors);
     if (!InitialExp.ReturnType.MatchWith(IntType.IntInstance))
     {
         errors.Add(new Error(InitialExp, "En una expresión 'for' la expresión de inicialización debe ser de tipo 'int' y se encontró una expresión de tipo '{0}'",InitialExp.ReturnType));
         HasError = true;
     }
     RelatedType = IntType.IntInstance;
     scope.AddFunVar(VariableName, this);
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     DeclarationNode funDeclaration = scope.GetFunVar(VariableName, false);
     //El tipo del parametro se determino en el chequeo de semantica de la secuencia de declaraciones de funciones
     if (funDeclaration != null)
     {
         errors.Add(new Error(this, "Se han definido dos o más parámetros con el nombre '{0}' dentro de la función", VariableName));
         HasError = true;
     }
     else
         scope.AddFunVar(VariableName, this);
 }
 public override void CheckSemantic(Scope scope, List<Error> errors)
 {
     InitialExp.CheckSemantic(scope, errors);
     //se pone por defecto con error y de tipo indefinido para factorizar
     HasError = true;
     RelatedType = UndefinedType.UndefinedInstance;
     if (TypeName != null) //se conoce el tipo de la variable
     {
         TigerType formalType = scope.GetType(TypeName);
         if (formalType == null) //el tipo formal no esta definido
             errors.Add(new Error(GetChild(2),"El tipo '{0}' no ha sido definido en el ámbito actual", TypeName));
         else
             if (!InitialExp.ReturnType.MatchWith(formalType)) //el tipo real no coincide con el formal
             {
                 errors.Add(new Error(InitialExp, "En una declaración el tipo de variable debe coincidir con el tipo de la expresión de inicialización y se encontró el tipo '{0}' y una expresión de tipo '{1}'", formalType, InitialExp.ReturnType));
                 RelatedType = formalType; // En C# si se declara 'string a = 5' se asume que 'a' es de tipo 'string' aunque no machee
             }
             else //si entra aqui es que no hay error
             {
                 HasError = false;
                 RelatedType = formalType;
             }
     }
     else //se debe inferir el tipo de la variable
     {
         if (InitialExp.ReturnType == NillType.NillInstance)
             errors.Add(new Error(InitialExp,"No es posible inferir el tipo de la variable '{0}' debido a que la expresión de inicialización es de tipo 'nil'",VariableName));
         else if (InitialExp.ReturnType.MatchWith(VoidType.VoidInstance))
             errors.Add(new Error(InitialExp,"No es posible inferir el tipo de la variable debido a que la expresión de inicialización es de tipo 'void'"));
         else //si entra aqui es que no hay error
         {
             HasError = false;
             RelatedType = InitialExp.ReturnType;
         }
     }
     DeclarationNode varDeclaretions = scope.GetFunVar(VariableName, false);
     if (varDeclaretions != null)
     {
         if (varDeclaretions is VariableDecNode)
             errors.Add(new Error(GetChild(0),"No es posible definir una variable con el nombre '{0}' debido a que existe otra variable con igual nombre dentro del mismo 'let'",VariableName));
         else
             errors.Add(new Error(GetChild(0),"No es posible definir una variable con el nombre '{0}' debido a que existe una función con igual nombre dentro del mismo 'let'", VariableName));
         HasError = true;
     }
     else
         scope.AddFunVar(VariableName, this);
 }
        public override void CheckSemantic(Scope scope, List<Error> errors)
        {
            foreach (FunctionDecNode funcDec in Declarations)
            {
                #region determinar el tipo de retorno
                if (funcDec.ReturnTypeName == null) // es un procedure
                    funcDec.RelatedType = VoidType.VoidInstance;
                else // es una function
                {
                    TigerType funType = scope.GetType(funcDec.ReturnTypeName);
                    if (funType == null)
                    {
                        errors.Add(
                            new Error(funcDec.GetChild(0),
                                "El tipo '{0}' no está definido en el ámbito actual", funcDec.ReturnTypeName));
                        HasError = true;
                        funcDec.RelatedType = UndefinedType.UndefinedInstance;
                    }
                    else
                        funcDec.RelatedType = funType;
                }

                #endregion

                #region determinar el tipo de cada parametro
                foreach (FunctionVariableDecNode paramDecl in funcDec.Arguments)
                {
                    TigerType paramType = scope.GetType(paramDecl.TypeName);
                    if (paramType == null)
                    {
                        paramDecl.RelatedType = UndefinedType.UndefinedInstance;
                        HasError = true;
                        errors.Add(new Error(paramDecl.GetChild(0),"El tipo '{0}' no está definido en el ámbito actual", paramDecl.TypeName));
                    }
                    else
                        paramDecl.RelatedType = paramType;
                }
                #endregion

                #region añadir la funcion al scope si no esta repetida

                DeclarationNode funDeclarations = scope.GetFunVar(funcDec.Name, false);
                if (funDeclarations != null)
                {
                    if (funDeclarations is FunctionDecNode)
                        errors.Add(new Error(funcDec.GetChild(0),"No es posible definir una función con el nombre '{0}' debido a que existe otra función con igual nombre dentro de un mismo 'let'", funcDec.Name));
                    else
                        errors.Add(new Error(funcDec.GetChild(0), "No es posible definir una función con el nombre '{0}' debido a que existe una variable con igual nombre dentro de un mismo 'let'", funcDec.Name));
                    HasError = true;
                }
                else if (BuiltInFunctions.Functions.Contains(funcDec.Name))
                {
                    errors.Add(new Error(funcDec.GetChild(0),"La función '{0}' está definida en la Biblioteca Estándar de Tiger y no puede ser redefinida", funcDec.Name));
                    HasError = true;
                }
                else
                    scope.AddFunVar(funcDec.Name, funcDec);
                #endregion
            }
            foreach (FunctionDecNode funcDecl in Declarations)
                funcDecl.CheckSemantic(scope, errors);
        }
        public static void DefineBuiltinFunctions(Scope scope, out FunctionDecNode printFunct, out FunctionDecNode printiFunct, out FunctionDecNode printlineFunct, out FunctionDecNode getCharFunct, out FunctionDecNode getlineFunct, out FunctionDecNode chrFunct, out FunctionDecNode sizeFunct, out FunctionDecNode substringFunct, out FunctionDecNode concatFunct, out FunctionDecNode notFunct, out FunctionDecNode exitFunct, out FunctionDecNode flushFunct, out FunctionDecNode ordFunct)
        {
            // print() Function
            printFunct = new FunctionDecNode();
            printFunct.Name = "print";
            printFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "text" } };
            printFunct.RelatedType = VoidType.VoidInstance;
            scope.AddFunVar("print", printFunct);

            // printline() Function
            printlineFunct = new FunctionDecNode();
            printlineFunct.Name = "printline";
            printlineFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "text" } };
            printlineFunct.RelatedType = VoidType.VoidInstance;
            scope.AddFunVar("printline", printlineFunct);

            // printi() Function
            printiFunct = new FunctionDecNode();
            printiFunct.Name = "printi";
            printiFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = IntType.IntInstance, VariableName = "number" } };
            printiFunct.RelatedType = VoidType.VoidInstance;
            scope.AddFunVar("printi", printiFunct);

            //getchar():string  Function
            getCharFunct = new FunctionDecNode();
            getCharFunct.Name = "getchar";
            getCharFunct.Arguments = new List<FunctionVariableDecNode>();
            getCharFunct.RelatedType = StringType.StringInstance;
            scope.AddFunVar("getchar", getCharFunct);

            //getcharln():string  Function
            getlineFunct = new FunctionDecNode();
            getlineFunct.Name = "getline";
            getlineFunct.Arguments = new List<FunctionVariableDecNode>();
            getlineFunct.RelatedType = StringType.StringInstance;
            scope.AddFunVar("getline", getlineFunct);

            //chr(i:int):string  Function
            chrFunct = new FunctionDecNode();
            chrFunct.Name = "chr";
            chrFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = IntType.IntInstance, VariableName = "number" } };
            chrFunct.RelatedType = StringType.StringInstance;
            scope.AddFunVar("chr", chrFunct);

            //size(s:string): int  Function
            sizeFunct = new FunctionDecNode();
            sizeFunct.Name = "size";
            sizeFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "strg" } };
            sizeFunct.RelatedType = IntType.IntInstance;
            scope.AddFunVar("size", sizeFunct);

            //substring(s:string , first:int, n:int): int  Function
            substringFunct = new FunctionDecNode();
            substringFunct.Name = "substring";
            substringFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "s" }, new FunctionVariableDecNode() { RelatedType = IntType.IntInstance, VariableName = "first" }, new FunctionVariableDecNode() { RelatedType = IntType.IntInstance, VariableName = "n" } };
            substringFunct.RelatedType = StringType.StringInstance;
            scope.AddFunVar("substring", substringFunct);

            //concat(s1:string ,s1:string ):string  Function
            concatFunct = new FunctionDecNode();
            concatFunct.Name = "concat";
            concatFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "s1" }, new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "s2" } };
            concatFunct.RelatedType = StringType.StringInstance;
            scope.AddFunVar("concat", concatFunct);

            //not(i:int ):int  Function
            notFunct = new FunctionDecNode();
            notFunct.Name = "not";
            notFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = IntType.IntInstance, VariableName = "i" } };
            notFunct.RelatedType = IntType.IntInstance;
            scope.AddFunVar("not", notFunct);

            //exit(i:int ):int  Function
            exitFunct = new FunctionDecNode();
            exitFunct.Name = "exit";
            exitFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = IntType.IntInstance, VariableName = "exitcode" } };
            exitFunct.RelatedType = VoidType.VoidInstance;
            scope.AddFunVar("exit", exitFunct);

            //flush ()  Function
            flushFunct = new FunctionDecNode();
            flushFunct.Name = "flush";
            flushFunct.Arguments = new List<FunctionVariableDecNode>();
            flushFunct.RelatedType = VoidType.VoidInstance;
            scope.AddFunVar("flush", flushFunct);

            //ord(s:string): int  Function
            ordFunct = new FunctionDecNode();
            ordFunct.Name = "ord";
            ordFunct.Arguments = new List<FunctionVariableDecNode>() { new FunctionVariableDecNode() { RelatedType = StringType.StringInstance, VariableName = "str" } };
            ordFunct.RelatedType = IntType.IntInstance;
            scope.AddFunVar("ord", ordFunct);
        }