Esempio n. 1
0
        public override void CheckSemantics(Scope scope, List <SemanticError> errors)
        {
            //--------------------------------------------------
            // Por Default, El Nodo No Tiene Errores.
            //--------------------------------------------------
            this.IsOk = true;

            //--------------------------------------------------
            // Hacer  'CheckSemantics'  A  Cada  Función.
            //--------------------------------------------------
            foreach (var declaration in this.Declarations)
            {
                declaration.CheckSemantics(scope, errors);
                this.IsOk &= declaration.IsOk;
            }

            if (!this.IsOk)
            {
                return;
            }

            //--------------------------------------------------
            // Hacer 'CheckSemantics' Al Cuerpo De Las Funciones.
            // Esto Es Una Segunda Pasada.
            //--------------------------------------------------
            foreach (var declaration in this.Declarations)
            {
                Scope InnerScope = scope.CreateChildScope();
                foreach (var parameter in declaration.FunctionInfo.Parameters)
                {
                    InnerScope.Add(parameter);
                }

                //--------------------------------------------------
                // Mantener La Referencia Del Scope Definido En
                // El Function Info.
                //--------------------------------------------------
                declaration.FunctionInfo.Scope = InnerScope;

                declaration.Body.CheckSemantics(InnerScope, errors);

                //--------------------------------------------------
                // Parar De Reportar Errores Si El Cuerpo De La Función
                // Tiene Error.
                //--------------------------------------------------
                if (declaration.Body.ExpressionType == PredefinedTypes.ErrorType)
                {
                    declaration.IsOk = false;
                }

                this.IsOk &= declaration.IsOk;

                if (!declaration.IsOk)
                {
                    continue;
                }

                //--------------------------------------------------
                // Comprobar  Que  El  Tipo  De  Retorno De La Función
                // Sea Igual Al Del Cuerpo De La Misma. Comprobar Tres
                // Casos:
                // 1 - La Función No Devuelve & El Cuerpo Devuelve
                // 2 - La Función Devuelve & El Cuerpo No Devuelve
                // 3 - La Función Y El Cuerpo Devuelven Pero Tipos Incompatibles.
                //   - Tener En Cuenta El Caso <object_type> = <nil>
                //--------------------------------------------------
                if (declaration.FunctionInfo.ReturnType == PredefinedTypes.VoidType)
                {
                    //--------------------------------------------------
                    // La Función Es Un Procedimiento ( No Devuelve )...
                    //--------------------------------------------------
                    if (declaration.Body.ExpressionType != PredefinedTypes.VoidType)
                    {
                        errors.Add(SemanticError.ProcedureCannotReturn(declaration.ID.Name, declaration));
                        declaration.IsOk = false;
                    }
                }
                else
                {
                    //--------------------------------------------------
                    // La Función Devuelve ...
                    //--------------------------------------------------
                    if (declaration.Body.ExpressionType == PredefinedTypes.VoidType)
                    {
                        errors.Add(SemanticError.FunctionMustReturn(declaration.ID.Name, declaration));
                        declaration.IsOk = false;
                    }
                    else
                    {
                        if (declaration.Body.ExpressionType == PredefinedTypes.NilType)
                        {
                            if (declaration.FunctionInfo.ReturnType == PredefinedTypes.IntType)
                            {
                                errors.Add(SemanticError.InvalidIntNilAssignation(declaration));
                                declaration.IsOk = false;
                            }
                        }
                        else if (declaration.Body.ExpressionType != declaration.FunctionInfo.ReturnType)
                        {
                            errors.Add(SemanticError.InvalidTypeConvertion(declaration.FunctionInfo.ReturnType, declaration.Body.ExpressionType, declaration));
                            declaration.IsOk = false;
                        }
                    }
                }

                this.IsOk &= declaration.IsOk;
            }
        }