public override void CheckSemantics(Scope scope, List <SemanticError> errors) { //-------------------------------------------------- // Hacer 'CheckSemantics' A Los Hijos. //-------------------------------------------------- this.IfNode.CheckSemantics(scope, errors); this.ThenNode.CheckSemantics(scope, errors); this.ElseNode.CheckSemantics(scope, errors); //-------------------------------------------------- // Poner El Valor De Retorno De La Expresión A 'Error' // Por Default. //-------------------------------------------------- this.ExpressionType = PredefinedTypes.ErrorType; //-------------------------------------------------- // Si Ha Ocurrido Un Error En Alguno De Los Hijos, // Parar De Reportar Errores. //-------------------------------------------------- if (this.IfNode.ExpressionType == PredefinedTypes.ErrorType || this.ThenNode.ExpressionType == PredefinedTypes.ErrorType || this.ElseNode.ExpressionType == PredefinedTypes.ErrorType) { return; } //-------------------------------------------------- // La Condición Debe Ser De Tipo <int>. //-------------------------------------------------- if (this.IfNode.ExpressionType != PredefinedTypes.IntType) { errors.Add(SemanticError.InvalidTypeConvertion(PredefinedTypes.IntType, this.IfNode.ExpressionType, this.IfNode)); } else { //-------------------------------------------------- // Debe Haber Conversión Entre El Tipo Del 'Then' Y // Del 'Else'. //-------------------------------------------------- if (SemanticError.CompatibleTypes(this.ThenNode.ExpressionType, this.ElseNode.ExpressionType)) { this.ExpressionType = this.ThenNode.ExpressionType; } else if (SemanticError.CompatibleTypes(this.ElseNode.ExpressionType, this.ThenNode.ExpressionType)) { this.ExpressionType = this.ElseNode.ExpressionType; } else { errors.Add(SemanticError.IncompatibleTypesInIfThenElse(this)); } } }
public override void CheckSemantics(Scope scope, List <SemanticError> errors) { //-------------------------------------------------- // Hacer 'CheckSemantics' A Los Hijos. //-------------------------------------------------- this.IfNode.CheckSemantics(scope, errors); this.ThenNode.CheckSemantics(scope, errors); //-------------------------------------------------- // Poner El Valor De Retorno De La Expresión A 'Error' // Por Default. //-------------------------------------------------- this.ExpressionType = PredefinedTypes.ErrorType; //-------------------------------------------------- // Si Ha Ocurrido Un Error En Alguno De Los Hijos, // Parar De Reportar Errores. //-------------------------------------------------- if (this.IfNode.ExpressionType == PredefinedTypes.ErrorType || this.ThenNode.ExpressionType == PredefinedTypes.ErrorType) { return; } //-------------------------------------------------- // La Condición Debe Ser De Tipo <int>. //-------------------------------------------------- if (this.IfNode.ExpressionType != PredefinedTypes.IntType) { errors.Add(SemanticError.InvalidTypeConvertion(PredefinedTypes.IntType, this.IfNode.ExpressionType, this.IfNode )); return; } //-------------------------------------------------- // El Cuerpo Del IfThen No Puede Devolver. //-------------------------------------------------- if (this.ThenNode.ExpressionType != PredefinedTypes.VoidType) { errors.Add(SemanticError.ExpectedType(PredefinedTypes.VoidType, this.ThenNode.ExpressionType, this.ThenNode )); } else { this.ExpressionType = PredefinedTypes.VoidType; } }
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; } }
public override void CheckSemantics(Scope scope, List <SemanticError> errors) { //-------------------------------------------------- // Buscar El FunctionInfo Correspondiente. //-------------------------------------------------- this.FunctionInfo = scope.FindFunctionInfo(ID.Name); //-------------------------------------------------- // Poner Por Defecto Que Hay Errores. //-------------------------------------------------- this.ExpressionType = PredefinedTypes.ErrorType; //-------------------------------------------------- // Si La Función No Existe, Reportar Error. //-------------------------------------------------- if (this.FunctionInfo == null) { errors.Add(SemanticError.FunctionDoesNotExist(this.ID.Name, this)); return; } //-------------------------------------------------- // Si La Cantidad De Argumentos Es Diferente A La // Cantidad De Parámetros, Reportar Error. //-------------------------------------------------- var parameters = this.FunctionInfo.Parameters; if (this.Arguments.Count() != parameters.Length) { errors.Add(SemanticError.WrongParameterNumber(this.ID.Name, parameters.Length, this.Arguments.Count(), this)); return; } //-------------------------------------------------- // Hacer 'CheckSemantics' A Cada Argumento. //-------------------------------------------------- bool IsOk = true; foreach (var argument in this.Arguments) { argument.CheckSemantics(scope, errors); if (argument.ExpressionType == PredefinedTypes.ErrorType) { IsOk = false; } } //-------------------------------------------------- // Si Hay Errores En Los Argumentos, Parar De // Reportar Errores. //-------------------------------------------------- if (!IsOk) { return; } //-------------------------------------------------- // Comprobar Que Los Tipos De Los Argumentos Son Iguales // A Los Tipos De Los Parámetros Correspondientes. //-------------------------------------------------- for (int i = 0; i < parameters.Length; i++) { var arg = this.Arguments.ElementAt(i); if (!SemanticError.CompatibleTypes(parameters[i].TypeNode, arg.ExpressionType)) { errors.Add(SemanticError.InvalidTypeConvertion(parameters[i].TypeNode, arg.ExpressionType, arg)); IsOk = false; } } if (IsOk) { this.ExpressionType = this.FunctionInfo.ReturnType; } }
public override void CheckSemantics(Scope scope, List <SemanticError> errors) { //-------------------------------------------------- // Por Default, El Nodo No Tiene Errores. //-------------------------------------------------- this.IsOk = true; //-------------------------------------------------- // Si Existe Una Función O Una Variable Con El Mismo // Nombre En El Scope Local, Reportar Error. //-------------------------------------------------- if (scope.FindLocalFunctionInfo(this.ID.Name) != null || scope.FindLocalVariableInfo(this.ID.Name) != null) { errors.Add(SemanticError.PreviousVariableOrFunctionDeclaration(this.ID.Name, this)); this.IsOk = false; } //-------------------------------------------------- // Hacer 'CheckSemantics' Al Valor De La Variable. //-------------------------------------------------- this.Expression.CheckSemantics(scope, errors); //-------------------------------------------------- // Si El Valor De La Expresión Tiene Algún Error, // Parar De Reportar Errores. //-------------------------------------------------- if (this.Expression.ExpressionType == PredefinedTypes.ErrorType) { this.IsOk = false; } if (!this.IsOk) { return; } if (this.ChildCount == 3) { //-------------------------------------------------- // Si La Variable Tiene El Tipo Explícitamente Entonces // Es De La Siguiente Forma: // // var id : type-id := expr //-------------------------------------------------- var typeID = this.Children[2] as IdNode; //-------------------------------------------------- // Si El Tipo No Existe, Entonces Reportar El Error. //-------------------------------------------------- var TI = scope.FindTypeInfo(typeID.Name); if (TI == null) { errors.Add(SemanticError.TypeDoesNotExist(typeID.Name, this)); this.IsOk = false; return; } if (this.Expression.ExpressionType == PredefinedTypes.NilType) { //-------------------------------------------------- // Si El Valor De La Expresión Es <nil>, Entonces El // Tipo De La Variable, Escrito Explícitamente; Puede // Ser Cualquiera, Excepto 'int'. // // var id : type-id := nil //-------------------------------------------------- if (TI.TypeNode == PredefinedTypes.IntType) { errors.Add(SemanticError.InvalidIntNilAssignation(this)); this.IsOk = false; return; } } else if (TI.TypeNode != this.Expression.ExpressionType) { //-------------------------------------------------- // Si Los Tipos Son Diferentes, Reportar Error. //-------------------------------------------------- this.IsOk = false; errors.Add(SemanticError.InvalidTypeConvertion(TI.TypeNode, this.Expression.ExpressionType, this)); return; } //-------------------------------------------------- // Crear 'VariableInfo'. //-------------------------------------------------- this.VariableInfo = new VariableInfo(this.ID.Name, TI.TypeNode); } else { //-------------------------------------------------- // En Este Caso Se Omite El Tipo De La Variable, Por // Tanto Se Debe Inferir De La Parte Derecha. Se Debe // Comprobar Que La Parte Derecha No Sea <nil> o <void>. // // var id := expr //-------------------------------------------------- if (this.Expression.ExpressionType == PredefinedTypes.NilType || this.Expression.ExpressionType == PredefinedTypes.VoidType) { errors.Add(SemanticError.InvalidTypeInference(this.Expression.ExpressionType, this)); this.IsOk = false; return; } //-------------------------------------------------- // Crear 'VariableInfo'. //-------------------------------------------------- this.VariableInfo = new VariableInfo(this.ID.Name, this.Expression.ExpressionType); } //-------------------------------------------------- // Actualizar 'Scope' Con La Variable Actual. //-------------------------------------------------- scope.Add(this.VariableInfo); }