public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { TypeReturn typeOfAsign = Asign.CheckSemantics(scope_list, errors); //hago el chequeo semantico de la asignacion if (typeOfAsign is ReturnNotValue) //verifico que devuelva algun valor { errors.Add(new Error(line, column, "La parte derecha de la asignacion debe devolver algun valor")); } TypeReturn typeOfLvalue = LValue.CheckSemantics(scope_list, errors); //hago el chequeo semantico del Lvalue if (LValue is VariableNode && Utils.NoAsignVar(scope_list, ((VariableNode)LValue).Name)) { errors.Add(new Error(line, column, "No se le puede asignar ningún valor a la variable '" + ((VariableNode)LValue).Name + "'")); } if (typeOfAsign is ReturnNil) //pregunto si la parte derecha es nil { if (typeOfLvalue is ReturnInt) //un entero no permite nil (todos los demas tipos si) { errors.Add(new Error(line, column, "No se le puede asignar un '" + typeOfAsign + "' a un '" + typeOfLvalue + "'")); } } else if (typeOfLvalue != null && typeOfAsign != null && //pregunto si no hubo problema con el chequeo de las variables !typeOfLvalue.ToString().Equals(typeOfAsign.ToString())) //chequeo que los tipos sean iguales { errors.Add(new Error(line, column, "No se le puede asignar un '" + typeOfAsign + "' a un '" + typeOfLvalue + "'")); } return(new ReturnNotValue()); //la asignacion no devuelve valor }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { TypeReturn t = Left.CheckSemantics(scope_list, errors); if (!(t is ReturnInt || t is ReturnString || t is ReturnNil))//Mira si la parte izquierda es valida(solo pueden ser entera o string) { errors.Add(new Error(line, column, "La expresión izquierda de la operación relacional debe ser 'int' o 'string'")); } TypeReturn t1 = Right.CheckSemantics(scope_list, errors); if (!(t1 is ReturnInt || t1 is ReturnString || t1 is ReturnNil))//Mira si la parte derecha es valida(solo pueden ser entera o string) { errors.Add(new Error(line, column, "La expresión derecha de la operación relacional debe ser 'int' o 'string'")); } if (t1 == null || t == null || t1.ToString() != t.ToString()) { if ((t is ReturnInt && t1 is ReturnNil) || (t is ReturnNil && t1 is ReturnInt) || (t is ReturnNil && t1 is ReturnNil)) { errors.Add(new Error(line, column, "Las expresiones comparadas son invalidas")); } else if (!(t is ReturnNil) && !(t1 is ReturnNil)) { errors.Add(new Error(line, column, "Ambas expresiones deben ser de tipo 'int' o de tipo 'string'")); } } return(new ReturnInt()); }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { Scope s = new Scope(); foreach (var p in types) { s.Vars.Add(p.Item1, p.Item2); } scope_list.Add(s); TypeReturn r = Body.CheckSemantics(scope_list, errors); if (r != null && r is ReturnNil)//ver si el valor de retorno es distinto a lo que deberia devolver { if (Retu == "int") { errors.Add(new Error(line, column, "No coincide el tipo de retorno con el que debería retornar")); } } else if (r != null && r.ToString() != Retu) { errors.Add(new Error(line, column, "No coincide el tipo de retorno con el que debería retornar")); } scope_list.RemoveAt(scope_list.Count - 1); return(new ReturnNotValue()); }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { Scope s = new Scope(); foreach (var p in types) { s.Vars.Add(p.Item1, p.Item2); } scope_list.Add(s); TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors); if (typeOfBody == null) //pregunto si hubo problemas con el body del procedimiento { return(null); } if (typeOfBody.ToString() != "No valor")//ver que no retorna valor { errors.Add(new Error(line, column, "El procedimiento '" + Name + "' no debe retornar valor")); } scope_list.RemoveAt(scope_list.Count - 1); return(new ReturnNotValue()); }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { //chequeamos si el tipo del array ya se definio anteriormente TypeReturn typeOfArray = Utils.FindType(scope_list, Name); if (typeOfArray == null) { errors.Add(new Error(line, column, "El tipo " + this.Name + "no se ha delcarado todavia")); } //verificamos que la expresion de inicializacion devuelva algun valor(puede ser nil) TypeReturn typeOfInitial = Initial.CheckSemantics(scope_list, errors); if (typeOfInitial is ReturnNotValue || typeOfInitial == null) //pregunto por null porque si hubo un error devuelvo null { errors.Add(new Error(line, column, "La expresion de la inicializacion del array debe devolver algun valor")); } if (!(typeOfArray is ReturnArray)) //el tipo no es un array { errors.Add(new Error(line, column, "El tipo " + "'" + this.Name + "'" + " no es de tipo array")); } else { if (typeOfInitial is ReturnNil) //si es nil no pueden ser int los valores del array { if ((typeOfArray as ReturnArray).Type_Of_Elements is ReturnInt) { errors.Add(new Error(line, column, "El array no permite 'nil' porque los valores del array son 'int'")); } } else if (((ReturnArray)typeOfArray).Type_Of_Elements.ToString() != typeOfInitial.ToString()) { errors.Add(new Error(line, column, "Los elementos del array son de tipo '" + ((ReturnArray)typeOfArray).Type_Of_Elements.ToString() + "' y no de tipo '" + typeOfInitial.ToString() + "'")); } } //verificamos que el size es un entero TypeReturn typeOfSize = Size.CheckSemantics(scope_list, errors); if (!(typeOfSize is ReturnInt)) { errors.Add(new Error(line, column, "La expresion del tamaño del array no devuelve un entero")); } Array = typeOfArray as ReturnArray; //para usarlo en la generacion de codigo return((typeOfArray != null) ? typeOfArray : new ReturnArray(this.Name, typeOfInitial)); //retorno el array }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { TypeReturn typeOfFun = Utils.FindFunction(scope_list, Name, out fun, ref NumLevelUp); //chequear que la funcion este definida en el scope if (typeOfFun == null) { errors.Add(new Error(line, column, "La funcion '" + Name + "' no esta declarada en este ambito")); return(null); //no se encontro la funcion en el scope } //para no irme de rango en el for y no tener que estar preguntando cual es menor o mayor int min = Math.Min(Param.Count, fun.Param.Count); //me quedo con el minimo de la cantidad de parametros entre la functioncall y la declarada //voy comparando los parametros y viendo que devuelvan lo mismo for (int i = 0; i < min; i++) { TypeReturn type = Param[i].CheckSemantics(scope_list, errors); //le hago el chequeo semantico a cada parametro (tienen que devolver algun valor) if (type == null) { continue; } if (type is ReturnNil) { if (fun.Param[i].Item2 is ReturnInt) { errors.Add(new Error(line, column, "No se le puede asignar un '" + type + "' a un '" + fun.Param[i].Item2 + "'")); //añado el error } } else if (!type.ToString().Equals(fun.Param[i].Item2.ToString())) //pregunto si el parametro i-esimo de la functioncall es del mismo tipo que del declarado { errors.Add(new Error(line, column, "El parametro '" + fun.Param[i].Item1 + "' no es de tipo '" + fun.Param[i].Item2 + "'")); } if (type is ReturnNotValue) //pregunto si el i-esimo parametro devuelve algun valor (tienen que hacerlo) { errors.Add(new Error(line, column, "La expresion del parametro " + i + "-esimo no devuelve valor")); } } if (fun.Param.Count != Param.Count) //para saber si tienen la misma cantidad de parametros la funcioncall que la declarada { errors.Add(new Error(line, column, "La funcion '" + Name + "' no tiene " + Param.Count + " parametros")); } return(typeOfFun); //es null si la funcion no se encontro en el Scope }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { this.CheckCondition(scope_list, errors); //chequea que la expresion de la condicion sea un entero //hago el chequeo semantico del then y del else TypeReturn typeOfBody = Body.CheckSemantics(scope_list, errors); TypeReturn typeOfBodyElse = Body_else.CheckSemantics(scope_list, errors); if (typeOfBody == null || typeOfBodyElse == null) //pregunto si hubo problemas en el then y en el else { return(null); } //chequeamos que los tipos devueltos por el then y el else sean iguales (puede ser nil uno de las exp mientras la otra no sea int) if (typeOfBody is ReturnNil) { if (typeOfBodyElse is ReturnInt) { errors.Add(new Error(line, column, "Los tipos retornados por las expresiones del then y del else tienen que ser iguales")); } else { return(typeOfBodyElse); } } else { if (typeOfBodyElse is ReturnNil) { if (typeOfBody is ReturnInt) { errors.Add(new Error(line, column, "Los tipos retornados por las expresiones del then y del else tienen que ser iguales")); } else { return(typeOfBody); } } else if (!typeOfBody.ToString().Equals(typeOfBodyElse.ToString())) //el tipo del then y el del else tienen que ser iguales { errors.Add(new Error(line, column, "Los tipos retornados por las expresiones del then y del else tienen que ser iguales")); } } //tanto la exp del then como la del else retornan el mismo tipo => retorno el tipo de cualquiera de las dos return(typeOfBody); //VER AQUI CUANDO LOS TIPOS SEAN != SI DEVUELVO NULL }
protected TypeReturn CheckSemanticsForEqualAndDistinct(List <Scope> scope_list, List <Error> errors) { TypeReturn tLeft = Left.CheckSemantics(scope_list, errors); TypeReturn tRight = Right.CheckSemantics(scope_list, errors); if (tLeft == null || tRight == null) //si alguna de las dos variables tuvo problemas no se hace la comparacion { return(new ReturnInt()); } if (tLeft is ReturnNotValue || tRight is ReturnNotValue) { errors.Add(new Error(line, column, "De las expresiones comparadas hay al menos una que no tiene valor")); } if (tLeft is ReturnInt && !(tRight is ReturnInt)) { errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo 'int' con una del tipo '" + tRight.ToString() + "'")); } if (tLeft is ReturnString && !(tRight is ReturnString || tRight is ReturnNil)) { errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo 'string' con una del tipo '" + tRight.ToString() + "'")); } if (tLeft is ReturnArray && !(tRight is ReturnNil || tLeft.Equals(tRight))) { errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo '" + tLeft.ToString() + "' con una del tipo '" + tRight.ToString() + "'")); } if (tLeft is ReturnRecord && !(tRight is ReturnNil || tLeft.Equals(tRight))) { errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo '" + tLeft.ToString() + "' con una del tipo '" + tRight.ToString() + "'")); } if (tLeft is ReturnNil && ((tRight is ReturnInt) || (tRight is ReturnNil))) { errors.Add(new Error(line, column, "Las expresiones comparadas no son del mismo tipo,no se puede comparar una expresion del Tipo Nil con una del tipo " + tRight.ToString() + "'")); } return(new ReturnInt()); }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { ReturnRecord recordDeclared = null; //chequear si el tipo del record ya existe en el scope KeyValuePair <string, TypeReturn> pair = default(KeyValuePair <string, TypeReturn>); for (int i = 0; i < scope_list.Count; i++) { Scope scope = scope_list[i]; pair = scope.Types.FirstOrDefault(s => s.Key.Equals(this.Name)); //busco el tipo (nombre) del record en el scope if (!pair.Equals(default(KeyValuePair <string, TypeReturn>))) //pregunto si existe el nombre del tipo en este ambito { //chequeo si el tipo es un record if (pair.Value is ReturnRecord) { recordDeclared = pair.Value as ReturnRecord; } else { errors.Add(new Error(line, column, "El tipo '" + Name + "' no es de tipo record")); } break; } } if (pair.Equals(default(KeyValuePair <string, TypeReturn>))) //pregunto si se encontro el el tipo del record en el scope { errors.Add(new Error(line, column, "El tipo '" + Name + "' no existe en este ambito")); return(null); //el record no esta declarado en este scope } //el menor de la cantidad de campos entre el instanciado y el declarado para no irme de rango en el for int min = Math.Min(recordDeclared.Fields.Count, Dict.Count); //chequear que concuerden los nombres de los campos y sus tipos de retorno (entre el record declarado y el instanciado) for (int i = 0; i < min; i++) //por cada campo { //chequeo que los nombres sean los mismos string keyRecordInstanced = Dict.ElementAt(i).Item1; //cojo el nombre del campo i-esimo del record instanciado string keyRecordDeclared = recordDeclared.Fields.ElementAt(i).Item1; //el nombre del campo i-esimo del record declarado if (!keyRecordInstanced.Equals(keyRecordDeclared)) //pregunto si los nombres de los campos son distintos { errors.Add(new Error(line, column, "El " + i + "-esimo campo no se llama " + keyRecordDeclared + " sino " + keyRecordInstanced)); } //chequeo que los tipos de los campos sean los mismos TypeReturn typeOfParameterDeclared = recordDeclared.Fields.ElementAt(i).Item2; //el tipo del campo i-esimo del record declarado if (typeOfParameterDeclared == null) //si es null es porque no se encontro el tipo en este ambito { errors.Add(new Error(line, column, "El tipo '" + recordDeclared.Fields.ElementAt(i).Item2 + "' no se encuentra declarado en este ambito")); } TypeReturn typeOfParameterInstanced = Dict.ElementAt(i).Item2.CheckSemantics(scope_list, errors); //el tipo del campo i-esimo cuando se instancio el record if (typeOfParameterInstanced is ReturnNil) //chequeo si el campo del record instanciado es nil { //hay que chequear que el tipo del parametro no sea ni int ni string if (typeOfParameterDeclared is ReturnInt) { errors.Add(new Error(line, column, "Solo se puede asignar nil a un tipo record, array o string")); } } //pregunto si los TypeReturn de los campos son != de null para que no me de NullException al pedirle el GetType() else if (typeOfParameterDeclared != null && typeOfParameterInstanced != null && !typeOfParameterDeclared.GetType().Equals(typeOfParameterInstanced.GetType())) //pregunto si los tipos de retorno son iguales { errors.Add(new Error(line, column, "El record '" + recordDeclared.Record_name + "'. El tipo del campo '" + keyRecordDeclared + "' es '" + typeOfParameterDeclared.ToString() + "' y no '" + typeOfParameterInstanced.ToString() + "'")); } } if (Dict.Count != recordDeclared.Fields.Count) //para saber si los records tienen la misma cantidad de campos { errors.Add(new Error(line, column, "El record '" + Name + "' no tiene " + Dict.Count + " campos")); } record = recordDeclared; return(recordDeclared); //retorno el mismo record que estaba en el scope }
public override TypeReturn CheckSemantics(List <Scope> scope_list, List <Error> errors) { int cant = errors.Count;//me da la cant de errores que hay hasta el momento TypeReturn typeOfAsign = Asig.CheckSemantics(scope_list, errors); TypeReturn typeVar; if (typeOfAsign == null) //cuando no existe la asignación { return(new ReturnNotValue()); } if (VarType == null) //no tiene tipo la variable { if ((typeOfAsign is ReturnNil) || (typeOfAsign is ReturnNotValue)) //si es nil o no retorna valor no se puede inferir el tipo { errors.Add(new Error(line, column, "No se puede inferir el tipo")); return(new ReturnNotValue()); } //Var_type = typeOfAsign.ToString(); //se infiere el tipo typeVar = typeOfAsign; } //tiene tipo la variable (VarType!=null) else { typeVar = Utils.FindType(scope_list, VarType); //busco el tipo de la variable if (typeVar == null) { errors.Add(new Error(line, column, "El tipo de la variable '" + Name + "' no existe")); //añado el error return(null); } // el tipo de la variable existe if (typeOfAsign is ReturnNil) //pregunto si la asignacion es nil y el Lvalue permite nil { if (typeVar is ReturnInt) { errors.Add(new Error(line, column, "No se le puede asignar un '" + typeOfAsign.ToString() + "' a un '" + typeVar + "'")); //añado el error } } else if (!typeVar.Equals(typeOfAsign)) { errors.Add(new Error(line, column, "No se le puede asignar un '" + typeOfAsign.ToString() + "' a un '" + typeVar + "'")); //añado el error } } if (scope_list[scope_list.Count - 1].Vars.ContainsKey(Name) || scope_list[scope_list.Count - 1].Funcs.ContainsKey(Name)) //ver si hay una funcion o una variable con ese nombre { errors.Add(new Error(line, column, "El nombre de la variable '" + Name + "' ya esta en uso")); //añado el error } if (cant == errors.Count) //si no hubo errores { v = new Var_Scope(Name, typeVar); scope_list[scope_list.Count - 1].Vars.Add(Name, v); //añado la variable al scope } return(new ReturnNotValue()); }